For an extreme example, I have the following image that was a JPEG before stackexchange converted it to a PNG:-


Before you perform all sorts of funky image processing tricks on it, it's just a black square. This is what happens with my web cam when there is insufficient light. It just gets low pass filtered out and a black square results. The interesting thing is that when I pull up 100 consecutive images from the camera, they're all exactly 6616 bytes long. There must be an internal light level threshold.

My question is, why was this square's original file size fixed at 6616 bytes? That seems like a lot of overhead to store just a single repeated value of "0", and given that extremely low frequency images should compress greatly. Also, given the random (quantum) nature of the various noise sources impacting the sensor, I would expect some natural variation in size.

For reference, the original image is available here, and it came from this:-


  • 1
    $\begingroup$ Could you share the original JPEG somehow? I kinda doubt an actual JPEG image could be all black in practice $\endgroup$ – Laurent Duval May 1 '18 at 13:41
  • $\begingroup$ @LaurentDuval On your command... $\endgroup$ – Paul Uszak May 1 '18 at 15:20

The picture you've posted most certainly didn't come directly from the image sensor – it was processed by the camera hardware, and software; it's pure dark grey.

Anyway; JPEG (to be more specific: JFIF as the JPEG-carrying file format) is not zero overhead, and you can expect a couple kB for this kind of image to work.

There's a couple bytes of headers (it's really negligible), but then things get a bit more complicated:

  • For a monochrome image, the actual JPEG quality setting won't do anything to the file size; it just sets a quantization mask, and you're always hitting the DC bin with a value of nonzero for anything. No matter how that turns out, Run-Length Encoding for the rest of the bins in each 8x8 pixel block will reduce the rest to the same number of bytes, regardless of quantization.
  • What does matter is the subsampling mask for the channels. Stanley's answer is a tiny bit wrong w.r.t. to the three channels: JPEG does support 4:2:0 subsampling, meaning that you actually omit one channel every row. But that's a story for a different day. Anyways, since your image doesn't change spatially at all, that saves space
  • Entropy encoding (I think it's a Huffmann method) is applied to the rest. Since the picture is built from identical 8x8 blocks, these should be reduced to very little data at all.
  • There's the special JPEG/JFIF feature of interleaving the info in a way that allows the lower frequency parts of the image to be transferred first (e.g. for slow connections; if you grew up in the 90s, you'll remember pictures that got sharper gradually while you hoped for your dialup modem to take less costly time). While these practically make little difference for "typical" photos, for your monochrome picture, they'll make matters worse and increase the file size by some 20 to 25%, maybe.

So, 6 kB is actually pretty OK, and you should probably look into whatever gave you that picture – it's definitely heavily smoothing the image, to a degree that the data you're presented has nothing to do with what the sensor sees. The sensor sees noise.

| improve this answer | |

JPEG standard will not care about how an image was generated; rather it looks for their block based statistical properties reflected in their quantized DCT coefficients. Under the same compression settings and the same image information, the same output will be produced.

As Marcus has stated, the size is pretty ok even for such a whole zero image. Consider the number of 8 x 8 blocks in your 640 x 480 image: there will be 4800 blocks. As far as I remember, every JPEG block must have at least a single code indicating its end of block (EOB) information which is 1010 in binary.

Then assuming that all your 4800 blocks have an at least one EOB symbol code, and further that they have also to indicate their DC coefficient of quantized DCT transforms (AC coefficents all seem to be zero for this particular case), then that amounts to a few kilobytes depending on how that single DC value was encoded by the standard Huffman entropy table(s) (or a custom entropy table which is allowed and located in a JPEG header).

The header may also contain AC and DC quantization tables for monochrome and RGB images and Huffman tables for both channels if a nondefault compression is employed. Quantization tables (masks) are 8 x 8 matrices and would not add much.

After all your image would take about 1 MB if it were stored as an RGB BMP and now in its RGB JPEG mode it takes only about 6 kB which is pretty good isn't it?

Try encoding in grayscale mode if possible... It reduced to 1.4 kB now.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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