How to export an image with specified filesize

We can export an image and check its size with Mathematica:

Export["test.png"(*or JPEG*), Plot[Sin[x], {x, 0, 6 Pi}]];
FileByteCount[%]/1024^2 // N


0.00997734

As we see, its size is about $0.01 Mb$. As I know, filesizes obtained with different ImageSize and ImageResolution can't be predicted with certain formula.

ImageSize

PNGsize = {Sequence @@ #,
N[FileByteCount[
Export["test.png", Plot[Sin[x], {x, 0, 6 Pi}],
ImageSize -> #]]/1024^2]} & /@ RandomInteger[300, {40, 2}];
Show[ListPlot3D[PNGsize, Mesh -> None],
ListPointPlot3D[PNGsize,
PlotStyle -> Directive[Blue, PointSize[0.02]]]]


ImageResolution

PNGsizeR = {#,
N[FileByteCount[
Export["test.png", Plot[Sin[x], {x, 0, 6 Pi}],
ImageResolution -> #]]/1024^2]} & /@ Range[20, 300, 20];
ListLinePlot[PNGsizeR, Epilog -> Point[PNGsizeR]]


So how to export the image with filesize exactly $1.2 Mb$?

• The png, jpg and other compressed formats does not allow the size prediction due to namely compression of the bitmap. You should use something like bmp format which is much more predictable for bitmaps with fixed size and color depth. Apr 18, 2017 at 4:33
• @Rom38 But I need a png format,and as I know the png isn't a compressed format?
– yode
Apr 18, 2017 at 4:41
• Mathematica doesn't allow to specify the compression level for PNG format, but third-party tools allow this and you can turn off the compression in order to get predictable filesize... But why do you need this? Apr 18, 2017 at 5:32
• @AlexeyPopkov Hard to say,I need it very long time,because some sites will resquest the size of image.And do you mean hard or impossible?
– yode
Apr 18, 2017 at 5:45
• @yode Web-sites probably need the actual size of a produced image, you can get it with FileSize. They do not require that the image must have explicit size in bytes (only maximum size may be specified). Apr 18, 2017 at 6:03

The site will limit the maximun size, but I want to produce a as big as possible image to ensure its quality. So I want to further control its size.

When I faced the problem of limited allowed image file size on image-hosing websites I always had to adjust the ImageSize manually and then use a third-party tool for achieving minimal possible filesize (Mathematica's built-in compression is far from the best), this process was always iterative. For GIF I recommend commercial GIF Movie Gear (and I haven't found anything better). For PNG there is free PNGOUT (included in free IrfanView as a plugin), also a commercial version is available. For JPG there is commercial JPEG Compressor which makes a pretty good job.

And as I see, the algorithm of compressed is certain,why we cannot predict it exactly?

As Rom38 correctly notes in the comments,

the result of compression depends on namely content which will be compressed. Therefore, each image, in general, will be compressed to a bit different sizes.

In the other words, only without compression the filesize may be completely predictable if we know only ImageDimensions.

So how to export the image with filesize exactly 1.2 Mb?

In the general case for lossless formats like PNG it isn't possible to produce a file with arbitrary small FileByteCount because we have no option to drop some information from the image. But as Gregory correctly notes, lossless format like PNG may give smaller filesize than lossy depending on the structure of image. Also it is worth to know that starting from upcoming version 11.2 there is "CompressionLevel" option supported for PNG export.

For lossy image formats it is possible to fit the filesize, and JPEG Compressor seemingly has an option to restrict maximum target file size. With Mathematica only something similar (but very crude as compared to what JPEG Compressor does) can be achieved using the "CompressionLevel" option (the following code just shows the idea):

FindRoot[ByteCount[
ExportString[Plot[Sin[x], {x, 0, 6 Pi}], "JPEG", "CompressionLevel" -> x]] ==
10000, {x, 0, 1}, PrecisionGoal -> 0, AccuracyGoal -> 1, Evaluated -> False]


FindRoot::brmp: The root has been bracketed as closely as possible with machine precision but the function value exceeds the absolute tolerance 0.1.

{x -> 0.51}


Some potentially useful ideas can be found also in this WC thread.

• Funny,I don't know the FindRoot can solve such equation before this.And just a query still haunt me around,why the lossless formats is unpredictable?I think since all the image data is valid,the result should be clear..
– yode
Apr 18, 2017 at 17:18
• @yode Both lossy and lossless formats give unpredictable filesizes if you use a compression. It is because the result of compression depends on the actual ImageData, not just on the ImageDimensions. Apr 18, 2017 at 17:24
• I know what you want to express,but I mean,since the compression algorithm is determinate,then we can know which digital in ImageData will left or be other value.Then we can calculate it.Let a lossless formats alone,since all digitals in ImageData will reserve,why it will be unpredictable?Hard to understand it..(also @Rom38)
– yode
Apr 18, 2017 at 17:28
• Don't forget to take into consideration, that the image size when saved at maximum quality and full resolution could still be under the desired size. Check for that first. In fact, the way PNG compresses similar pixels, you will get a smaller-sized PNG image with LOSSLESS compression from desktop graphics with lots of black/white/solid color pixels than a comparable JPG. Save both to ensure one isn't the image that you need before proceeding to "optimize". Apr 20, 2017 at 2:41
• Note the verion 11.2 coming up is support "CompressionLevel"` feature as its documentation here
– yode
Sep 8, 2017 at 16:10