Resizing and Recompressing via HTML5/Flash Uploader

Supported technologies: Adobe FlashHTML 5

About Converters

Let's imagine that a user adds all necessary photos to the upload list and hits the Upload button. What's next?

Each website has its own scenario. Someone wants just the original files to be sent. Others want to upload only resized copies. Someone else wants uploading multiple resized copies per each file (e.g. a thumbnail and a hi-res copy).

To combine a flexibility and simplicity of configuration, a concept of ConverterConverter (ASP.NET)Converter (PHP)converter (JavaScript) is used in HTML5/Flash Uploader. You specify one or more converters in the upload settings. Each converter takes a file from the upload list, "converts" it (e.g. to a thumbnail or just returns an unchanged file) and adds it to the upload queue.

This topic examines resizing and recompressing settings and describes how to handle the situation when a thumbnail cannot be created.

Defining a Thumbnail Converter

First of all, let's agree that we will call any resized copy of an image a thumbnail, even if it is 5000x5000 image. It will make it easier to understand the API names and avoid misunderstanding.

To upload thumbnails you need to create a Converter and set its ModeMode (ASP.NET)Mode (PHP)mode (JavaScript) property to Thumbnail. Then you should use its ThumbnailXXX properties as explained below. A code example can be found below as well.

Thumbnail Size

To specify a desired thumbnail dimensions you should use the ThumbnailWidthThumbnailWidth (ASP.NET)ThumbnailWidth (PHP)thumbnailWidth (JavaScript) and ThumbnailHeightThumbnailHeight (ASP.NET)ThumbnailHeight (PHP)thumbnailHeight (JavaScript) properties. However the problem is that you don't know the aspect ratio of the original image beforehand. That's why you cannot expect that the resulting image will have exactly these dimensions.

To address this issue, there is a ThumbnailFitModeThumbnailFitMode (ASP.NET)ThumbnailFitMode (PHP)thumbnailFitMode (JavaScript) property which defines the strategy of the image resizing. There are the following values are supported:

  • Fit means that the original image should be resized to fit the rectangle specified with the ThumbnailHeight and ThumbnailWidth properties. Note that the proportions of the original image will be kept.
  • Crop means that before the resizing, the image is cropped according to the resulting image aspect ratio (crop frame is centered). It means that the output image always has width and height that you specify, although a part of the image is lost.
  • Width means that the original image should be resized to be no wider than the ThumbnailWidth value. Image is resized proportionally, so the ThumbnailHeight property is ignored in this mode.
  • Height means that the original image should be resized to be no higher than the ThumbnailHeight value. Image is resized proportionally, so the ThumbnailWidth property is ignored in this mode.
  • ActualSize means that ThumbnailWidth and ThumbnailHeight are ignored and dimensions of the original image should be kept; however, it can be rotated or recompressed if necessary.

If you know target image DPI and size (in inches), you can calculate thumbnail width and height by multiplying target values. For example, you want to get 4x6 inch image with 72 DPI, then you should set ThumbnailWidth to 432 (432 pixels = 6 inches x 72 DPI) and ThumbnailHeight to 288 (288 pixels = 4 inches x 72 DPI).

Important to remember that the image is always downsized. If you specify a thumbnail size larger than the image, the original size is kept. The only exception is the Crop fit mode - in this case the uploader adds fields around the image to guaranty the image dimensions.

Note

HTML5/Flash Uploader Express and Professional restrict a size (width x height) of each created thumbnail to 3 and 5 megapixels respectively. For example, the size of 1500x1500 thumbnail is 2.25 megapixels (1500 pixels x 1500 pixels = 2.25 megapixels), thus, such a thumbnail can be uploaded with HTML5/Flash Uploader Express. See the Upload Suite Editions topic for details.

Let's see how a thumbnail converter may look like.

ASP.NET
<aur:ImageUploaderFlash ID="Uploader1" runat="server">
    <Converters>
        <aur:Converter Mode="*.*=Thumbnail" 
           ThumbnailHeight="200" 
           ThumbnailWidth="200" 
           ThumbnailFitMode="Fit" />
    </Converters>
</aur:ImageUploaderFlash>
PHP
$uploader = new ImageUploaderFlash("Uploader1");
$converters = &$uploader->getConverters();
$converter = new Converter();
$converter->setMode("*.*=Thumbnail");
$converter->setThumbnailWidth(200);
$converter->setThumbnailHeight(200);
$converter->setThumbnailFitMode("Fit");
$converters[] = $converter;
JavaScript
var fu = $au.imageUploaderFlash({
    id: 'Uploader1',
    converters: [{mode: '*.*=Thumbnail', 
        thumbnailWidth: 200, 
        thumbnailHeight: 200, 
        thumbnailFitMode: 'Fit'}]
});

Output file type

By default, the output file format is JPEG. This image format has an ability to balance between file size and image quality.

If you would like to override this behavior, you can use the ThumbnailTypeThumbnailType (ASP.NET)ThumbnailType (PHP)thumbnailType (JavaScript) property. It supports the following values:

  • image/jpeg - always create a JPEG file. Default value.
  • image/png - always create a PNG file.
  • original - if the input image is JPEG, it creates a JPEG, if it is PNG, it creates PNG. For other image formats, the JPEG is used.
  • auto - tries to select the best file format for these settings. See below for details.

Thumbnail Quality

You can specify JPEG quality of a thumbnail via the ThumbnailJpegQualityThumbnailJpegQuality (ASP.NET)ThumbnailJpegQuality (PHP)thumbnailJpegQuality (JavaScript) property which accepts a number in the range [0, 100]. If you specify 0, the file will be extremely small, but the quality will be very low (almost always unacceptable). Alternatively, if you specify 100, the file will be quite large, but JPEG artifacts will be almost invisible. Usually, small images have rather low quality (to be loaded quickly), whereas screen-size images have higher quality. The default ThumbnailJpegQuality value is 80 which is the most balanced and common JPEG quality.

Note

If you set the JPEG quality to a large value, and upload a JPEG file that has poor quality initially, the file size may increase (although the quality will not become better). It is not guaranteed that the output JPEG will have the same or less size than the original file. This effect is caused by specificity of JPEG compression algorithm.

That is why if you expect that users will upload poor-quality JPEG files, it makes sense to set the quality to a low value.

There is also the ThumbnailResizeQualityThumbnailResizeQuality (ASP.NET)ThumbnailResizeQuality (PHP)thumbnailResizeQuality (JavaScript) property which is related to the thumbnail quality. This property specifies whether to use fast algorithm but receive not-so-good result or prefer the best possible quality sacrificing the performance. The resize quality should not be confused with the JPEG quality: the latter specifies the quality of recompression, not the resize algoritm. As for now, you may choose between the following quality values: Low, Medium, and High. The default is Low, which means that it uses standard HTML5 image resizing utilities. Consider using High quality if the performance is not so critical.

Picking image format and/or JPEG quality automatically

In some scenarios, instead of configuring a specific JPEG quality, you may rather prefer to specify some max file size for an image. In this case you don't care what the JPEG quality is as long as it is not too poor.

To implement this scenario, you should use the ThumbnailSizeLimitThumbnailSizeLimit (ASP.NET)ThumbnailSizeLimit (PHP)thumbnailSizeLimit (JavaScript) property. It specifies the max size of the output file you expect to have. The uploader will try to create the JPEG with the best quality. If it is too large, it will reduce the quality and try again, and repeats until the file size meets the specified restriction. The ThumbnailJpegQuality is used as a min boundary of the JPEG quality range. Note, if the size limit is too strict, the image is compressed with the value specified by the ThumbnailJpegQuality.

You can also combine this technique with an ability to generate PNG thumbnails. Just set ThumbnailType to auto and the uploader will try to create a PNG file first. If PNG file meets the limit specified by ThumbnailSizeLimit, it will return the PNG image. Otherwise, it will try to create JPEG with automatic quality selection as explained above.

Detect when the image is really optimized

Most likely if you resizing images before the upload, you expect that the result file will be smaller than the original one. However, it is not always the case. For example, the original image has the same dimensions as the resized one and its JPEG compression is lower than you specify with ThumbnailJpegQuality. If your goal is to optimize the bandwidth, you would like to upload the original file instead of the resized image in this case.

You can do it with a help of the ThumbnailCompressOversizedOnlyThumbnailCompressOversizedOnly (ASP.NET)ThumbnailCompressOversizedOnly (PHP)thumbnailCompressOversizedOnly (JavaScript) property. Set it to true, and it will upload the resized copies of images only when they are smaller than the source file.

Preserving Image Transparency

If you upload PNG files with transparent regions and a converter is configured to generate JPEG files, you may find it annoying that the transparent pixels are converted to black pixels. How to handle this?

There are two ways: (1) force PNG and GIF files to be uploaded as PNG or (2) flatten background with a specific color (e.g. white).

Set different convertor for non-JPEG files

The idea is simple: configure two different convertors for different file types, like this:

ASP.NET
<aur:ImageUploaderFlash ID="Uploader1" runat="server">
    <Converters>
        <aur:Converter Mode="*.jpg=Thumbnail"
           ThumbnailType="image/jpeg"
           ThumbnailHeight="600" 
           ThumbnailWidth="800" 
           ThumbnailJpegQuality="75"
           ThumbnailFitMode="Fit" />
        <aur:Converter Mode="*.png,*.gif=Thumbnail"
           ThumbnailType="image/png"
           ThumbnailHeight="600" 
           ThumbnailWidth="800" 
           ThumbnailFitMode="Fit" />           
    </Converters>
</aur:ImageUploaderFlash>
PHP
$uploader = new ImageUploaderFlash("Uploader1");

$converter1 = new Converter();
$converter1->setMode("*.jpg=Thumbnail");
$converter1->setThumbnailType("image/jpeg");
$converter1->setThumbnailWidth(600);
$converter1->setThumbnailHeight(800);
$converter1->setThumbnailJpegQuality(75);
$converter1->setThumbnailFitMode("Fit");

$converter2 = new Converter();
$converter2->setMode("*.png,*.gif=Thumbnail");
$converter2->setThumbnailType("image/png");
$converter2->setThumbnailWidth(600);
$converter2->setThumbnailHeight(800);
$converter2->setThumbnailFitMode("Fit");

$uploader->setConverters(array($converter1, $converter2));
JavaScript
var fu = $au.imageUploaderFlash({
    id: 'Uploader1',
    converters: [
        {
            mode: '*.jpg=Thumbnail',
            thumbnailType: 'image/jpeg', 
            thumbnailWidth: 600, 
            thumbnailHeight: 800,
            thumbnailJpegQuality: 75, 
            thumbnailFitMode: 'Fit'
        },
        {
            mode: '*.png,*.gif=Thumbnail',
            thumbnailType: 'image/png', 
            thumbnailWidth: 600, 
            thumbnailHeight: 800,
            thumbnailFitMode: 'Fit'
        }        
        ]
});

Now imagine that you upload file1.jpg. Here the uploader applies the first converter and send a resized file as File0_0 POST variable. The second converter will be ignored (as a file name does not match the *.png,*.gif file mask) and nothing is sent as File1_0. In the similar way, if you upload file2.gif or file3.png, the first convertor will be skipped (and nothing is uploaded), while the second converter will produce a PNG file.

Set background color

You can follow this way if for any reasons JPEG is the only option. JPEG format does not support transparency. That does not mean that you will be unable to create thumbnails for transparent images. The thumbnails will simply be created on a background of some color. You can set this color using the ThumbnailBgColorThumbnailBgColor (ASP.NET)ThumbnailBgColor (PHP)thumbnailBgColor (JavaScript) property. To specify desired background color use a hex representation of the RGB triad in HTML-style syntax (#rrggbb). Default background color is white (#FFFFFF). The same color is used for the Crop fit mode if it needs to draw fields around the image.

If Thumbnail Cannot be Created

It is possible that some specific thumbnail will fail to be created, for example, when the original file is corrupted or it is non-image. To handle this situation specify one more conversion mode (e.g. SourceFile or Icon) after the Thumbnail one. In this case, if applying of the first mode has failed, HTML5/Flash Uploader will try to use the next one.

The following example illustrates the idea.

ASP.NET
<aur:ImageUploaderFlash ID="Uploader1" runat="server">
    <Converters>
        <%-- Send the source file if the thumbnail cannot be created --%>
        <aur:Converter Mode="*.*=Thumbnail;*.*=SourceFile" />
        <%-- Send an icon if the thumbnail cannot be created --%>
        <aur:Converter Mode="*.*=Thumbnail;*.*=Icon" />
    </Converters>
</aur:ImageUploaderFlash>
PHP
$uploader = new ImageUploaderFlash("Uploader1");
$converters = &$uploader->getConverters();
$converter = new Converter();
//Send the source file if the thumbnail cannot be created
$converter->setMode("*.*=Thumbnail;*.*=SourceFile");
$converters[] = $converter;
$converter = new Converter();
//Send an icon if the thumbnail cannot be created
$converter->setMode("*.*=Thumbnail;*.*=Icon");
$converters[] = $converter;
JavaScript
var fu = $au.imageUploaderFlash({
    id: 'Uploader1',
    converters: [
        //Send the original file if the thumbnail cannot be created
        {mode: '*.*=Thumbnail;*.*=SourceFile'}, 
        //Send an icon if the thumbnail cannot be created
        {mode: '*.*=Thumbnail;*.*=Icon'}
    ]
});

Another scenario where you may want to use the fallback option is the situation when the browser is not able to create a resized copy of specified dimensions because of the memory issues. It is especially actual on iOS browsers and may be applicable to Firefox and IE with very large sizes (when you want to receive a resized copy larger than 32 Mpix). Use the AutoReduceDimensionsAutoReduceDimensions (ASP.NET)AutoReduceDimensions (PHP)autoReduceDimensions (JavaScript) property to select between two options - either automatically reduce the output dimensions (e.g. instead of 9300x5000 you will get 7773x4181) or fail, as if it is a non-image. In the latter case, you can use the technique described above to send the original file instead of a resized copy.

See Also

Reference

Manual