4
\$\begingroup\$

I would like to prepare a photo to display it on a webpage. I would like to compress this image such that most of the image is compressed to lower quality, to reduce download size, but a few small areas are compressed in high quality.

The photo is an outdoor scene most of which shows foilage, but there are eight people visible walking in the foreground. If I compress the photo with JPEG set to lower quality, most of the image doesn't lose important details. However, the heads of the people visible on the image are an important focus of the image, and most of them have important details in the facial features that are lost at low quality JPEG compression. All the heads together take less than 1/200 the are of the image.

I do not believe that it is possible to solve this optimally with a single JPEG image. This is because the entire JPEG image must use the same quantizing matrix, which has to be high quality enough to be able to represent the high quality details, and also has to use the same Huffman code, so even if I encode most of the image in a special way, such as zeroing many of the cosine transform coefficients in most of the blocks, the large areas will be compressed suboptimally.

Given this, what is the best way to represent the image on a webpage? Can you give examples of webpages doing something similar? Can you point me to instructions or software that helps solve some of this task?

I was thinking of maybe using a low quality JPEG image that covers all the picture, and then overlaying a few other images (JPEG or PNG). I could use CSS rules to place the additional images. Alternately, I could split the image to rectangular subimages, and assemble them using a table.

To clarify, I don't need help for choosing the areas that have to be represented in high quality. I can choose those myself easily, by observing which parts of the image lose detail in a lower quality compression.

\$\endgroup\$
3
  • \$\begingroup\$ It actually is possible to compress each macro block of a JPEG with different quantization factors. I once worked on a tool that allowed you to paint the areas of the image you wanted to be high quality with one brush and the areas of low quality with a different brush. However, it never actually shipped. But I did see it working! \$\endgroup\$ Dec 15, 2015 at 4:58
  • \$\begingroup\$ In a gallery I've programmed I used three resolutions, one for the thumbnails and two for the big view to optimize for different viewport dimensions. In the single view, initally the thumbnail image was show (scaled up of cause) before the big image finished loading. The scaled image looks blocky, but the viewer gets an impression of the image. I saw other galeries providing a blurry, highly compressed (but full resolution) image while loading the final, high quality "piece of work". (This might be an alternative approach.) \$\endgroup\$
    – eogavy
    Dec 15, 2015 at 16:51
  • 1
    \$\begingroup\$ This question is not about photography, is about web design/web development. \$\endgroup\$
    – Dragos
    Dec 15, 2015 at 19:31

6 Answers 6

6
\$\begingroup\$

You can do this with an experimental version of the jpegtran utility with the "drop" option. Get it from http://jpegclub.org/jpegtran/. Here's an example (using a sample image from http://www.rawsamples.ch/). I've uploaded all samples here as PNG files to avoid any extra recompression from the hosting service.

First, the image in high quality JPEG:

High-quality JPG

This is 1715K — over a megabyte.

Now, dropped to terrible-quality (10% in Gimp, with 4:2:0 subsampling):

Low-quality JPEG

Whooo, down to 52K. JPEG is amazing.

So, next, I tried the suggestion from StephenG; I took the low-quality version and put it on top of the uncompressed original, then erased the section I want to look best — the trumpet-vine cloth in the top row. That yields:

Low-Q with original blended in, then saved as high q

But, unfortunately, this is now back up to 667K, which kind of defeats the purpose. Even when I go to 4:2:0 subsampling, it's still 378K — and this is a more fair comparison, as you'll see in a bit.

So, I tried the jpegtran -drop approach — I cut out an overlay of the part I want high quality:

overlay

which is 38K, by the way, and used

jpegtran -drop +592+62 overlay.jpg -outfile dropped.jpg lowq.jpg

to paste it in. I discovered that the subsampling has to match, so I couldn't use the ultimate high quality, but that's probably okay.

dropped in

for a final 221K image. This is a significantly better size result than resaving as high-quality, even with subsampling. However, it's arguably a worse visual result, as you can't blend — it needs to be in straight lines, and everything snaps to 8×8 chunks. You could get around this by carefully doing the edge chunks individually, with intermediate levels of compression so the transition isn't obvious, but that seems... tedious.

So, if you need one file, you could do this. And, if the square crop and block alignment issue works with your image, it might even be the best way.

However, since you're presenting on a web page, I'd take a different approach: use CSS, and put your high-quality area in a PNG file with transparency, and put that right on top of the low-quality JPEG. And in your case, where the high-quality area is small (0.5% of the image!), it's probably the best.

Of course, this only works if your high-quality area is small enough for that to be a compression win. If it's large enough, you're back to trying some of the above.

\$\endgroup\$
3
\$\begingroup\$

Compose the compressed images in a SVG file

SVG images are well-supported in modern browsers. You can either embed the bitmap images in the SVG file, or have the SVG link to them. Note that embedding uses base-64 encoding which adds one third to the file size.

Below is a how-to for Inkscape. Note that you can choose whether to embed or link each image when you open/import it.

  1. File > Open the large low-quality image. This creates a new SVG image with the same dimensions as the opened image.
  2. File > Import the smaller high-quality images. These images are added on top of the low-quality image from step 1.
  3. Place the smaller images. Note that the Inkscape coordinate system has (0, 0) in the bottom left corner.
  4. File > Save As... and choose "Plain SVG".

If you chose to link the images, you will need to distribute them together with the SVG file. If you need to adjust where the links point to, you can open the SVG file in a text editor and change it there.

\$\endgroup\$
2
\$\begingroup\$

The approach of making a single merged image (@StephenG) will create an image with some areas at low quality and some at high, BUT it's not going to drastically reduce the download size.

The final image needs saving at 'high quality' to preserve the detail areas (faces) but this will increase the file size of the low-quality areas too. I took a high-quality JPEG (450Kb), saved it as low quality (100Kb), reloaded and then resaved as high quality. The final file size was 300Kb. Some saving, yes, but the artefacts introduced by this process were unpleasant as well.

Personally, I'd have the low quality image as one asset, and each high quality section as another one. Use the HTML/CSS layout to position the high-quality sections directly overt the low quality ones.

An advantage is that on low bandwidth or low-resolution devices, you could simply skip the load of the hi-res sections.

\$\endgroup\$
1
\$\begingroup\$

Using PHP and Imagick

Imagick crop : http://php.net/manual/en/imagick.cropimage.php

Imagick Compress:

http://php.net/manual/en/imagick.setcompressionquality.php http://php.net/manual/en/imagick.setimagecompression.php

Imagick overlaying(merge): http://www.imagemagick.org/Usage/layers/ (or you can use css to set image point)

\$\endgroup\$
1
\$\begingroup\$

You can:

  • crop out the interesting part of the image
  • compress savagely the full image
  • compress lightly the much smaller image
  • make a bit of HTML that shows the small image over the large image

Technically, the HTML looks like this:

<div style="position:relative; ">
<img src=LoQ-full.jpg style="position:absolute; top: 0; left: 0 ; " >
<img src=HiQ-part.jpg style="position:absolute; top: 250; left: 615 ; " >
</div>
  • The relative position of the <div> makes it "positioned"
  • ... so that the absolute positions of the pictures are actually relative to the <div>

Using this picture (resized):

Whole Hi-Q (90) picture is 360K, Lo-Q (10) complete plus Hi-Q part is 51+5K, result (screenshot) is like this:

enter image description here

\$\endgroup\$
0
\$\begingroup\$

Save the image once as high and once as low quality. Use these as working copies for the operations below, but keep the original version separate.

Merge the parts of the high quality image you want into the low quality image. You'd use an editor like GIMP or Photoshop and a layer mask for this.

Save the resulting image to another high quality ( or moderate quality ) image.

That final composite image will have what you want and can be distributed as you like ( assuming you have the rights to the original image ).

\$\endgroup\$
5
  • \$\begingroup\$ How would this compare to degrading the low-quality portion of the image another way (say, gaussian blur)? \$\endgroup\$
    – mattdm
    Dec 15, 2015 at 15:14
  • \$\begingroup\$ I would use a not dissimilar approach to gaussian blur ( save original, work on duplicate, two layers, blur top layer, mask to control what blurred bits are used, merge layers and save new version ). Simpler that using two files instead of one file as a source.. But the OP seems to specifically want to use the low and high quality JPEG compression, not blurring, hence my outline of that procedure. Gaussian blur will obscure detail, but not really produce the same effect as different compression ratios. \$\endgroup\$ Dec 15, 2015 at 15:58
  • 1
    \$\begingroup\$ I assume you talk about JPEG. I further assume you do not reduce the image information with any filter because it's not mentioned in your answer. -- I don't think that this approach really helps. It might reduce the overall image size a bit, but probably only because of reduced information in the parts that were previously stronger compressed. What you proprose is actually "destroying" one image due to strong compression, then improrting, decompressing that image and recompressing this part of the overall image (with all its compression artifacts) again with higher compression. \$\endgroup\$
    – eogavy
    Dec 15, 2015 at 16:44
  • 1
    \$\begingroup\$ I honestly see no practical purpose in this exercise. Simply using the approach suggested by @mattdm is far more practical in my view. JPEG compression ought to adaptively produce high compression on low information parts of an image anyway. It is very hard to see the practical purpose of the OP's task. It complicates presentation and seems to produce no tangible benefits. Multiple files ( for web deployment ) result in not only multiple loads, but a more complex operation for the browser, and it's hardly mobile friendly to require two files and javascript to display just one image. \$\endgroup\$ Dec 15, 2015 at 17:15
  • 1
    \$\begingroup\$ I just tried it, and the save-as-low-jpeg/add-masked-higher-quality/save-as-higher-quality approach gives surprisingly good results visually compared to blurring at the same size. However, it's ridiculously inefficient; in my sample, the total high-quality image is 1.7M, the very degraded low-quality version is 52k; the high-quality portion as a crop saved separately is 75k, but the low-quality + original high-quality portion saved as high q is ugh, 667k. Much better to use a CSS overlay approach since this is meant to be a web page. \$\endgroup\$
    – mattdm
    Dec 15, 2015 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.