What is the largest size of a 640x480 JPEG?
I'm creating a data storage device that takes a certain number of pictures of the night sky over a couple of hours, and the pictures will be downloaded right after they are all taken. The memory card must be able to store all of the pictures at once.
The JPEGs that will be taken are 640x480 pixels, and it is essential that there is enough room on the memory card for all 100 of them. So what is the largest size of a 640x480 JPEG?
I have taken some test pictures to figure this out:
- The file size of the "stackoverflow" image is 73,774 bytes.
- The file size of the white image is only 36,607 bytes.
- But the file size for the checkered photo clocks in at 149,339 bytes.
I am assuming that the file size increases with complexity.
How can I build enough room on the memory card to fit 100 640x480 JPEGS, without knowing how complicated and what size they will be? I don't want to waste extra space as I may be making many of these capture devices.
Here I suggest an upper bound for JPEG file sizes. See Ilmari Karonen's answer for a discussion of more typical jpeg sizes.
The pixel storage space for a 640X480 32-bit bitmap image can be calculated like so (based on this answer, but corrected based on Ignacio Vazquez-Abrams' comment and this answer):
Assuming that no compression has been applied to the file, there are 307,200 pixels, which is a 0.3MP. Handy look up table
If each pixel contains 32 bits of information, then
- 307,200 * 32 = 9,830,400 bits of information
- Divide by the 8 bits to become a byte value
- 9,830,400 / 8 = 1228800 bytes (Or 1.17 Mb)
This is the size of an uncompressed bitmap, and as such should be an upper bound for jpeg file size (In reality, because the JPEG format uses compression, your images should be much smaller, especially given that you're taking pictures of the night sky, which I imagine contains a lot of black. Note that the largest example image in your question is only 0.14 MB).
With regard to your specific issue however, even using that upper bound, 100 images is only 117 MB, and it's been a long time since I've seen a memory card as small as 128 MB. I suspect any currently available memory card will have enough capacity to meet your needs.
Apparently the issue of maximum jpeg file size is subject to some debate. This Stack Overflow answer suggests a theoretical maximum size of 20.25 bytes per pixel, or 5.9 MB in your case, but producing an image of that size requires deliberate misuse of the jpeg format's compression scheme, so it's extremely unlikely that you'd ever see such a thing produced by a camera.
Just to check, let me test ForeverWintr's analysis experimentally.
The worst kind of input image for JPEG compression (or any compression, really) is uniformly random RGB noise, which is theoretically incompressible. So let me generate some using the netpbm tools:
$ rawtoppm < /dev/urandom 640 480 > rnd.ppm
$ pnmtopng < rnd.ppm > rnd.png
$ du -b rnd.*
923772 rnd.png
921615 rnd.ppm
(Uniformly random RGB noise, lossless PNG format, 903 kb)
Note (March 2017): I'm fairly sure the image above was in PNG format when I first wrote this answer and uploaded it back in 2013. (There's even a comment about color management below that strongly implies this.) Unfortunately, it would seem that it has been silently converted into JPEG at some point, making the visual comparison here useless.
I've tried to reupload a new PNG test image, but apparently it hits some kind of an arbitrary PNG file size limit at imgur and gets auto-converted to JPEG. I'm not sure if there's any way around this issue, but at least if you have access to a Linux box, you can always re-run the given commands to generate your own test images. In any case, other than preventing direct visual comparison of the compression quality, this does not invalidate the analysis below in any way.
OK, so the uncompressed PPM file is 640 × 480 × 3 = 921,600 bytes long, plus 15 bytes for the minimal PPM header, just as expected. Trying to losslessly compress it using the PNG format just ends up increasing the size by 2157 bytes, presumably taken up by PNG headers and metadata and possibly some slight inefficiency in the compression algorithm trying to compress incompressible data.
(Yes, that's 3 bytes per pixel, not 4; even the PPM format, which is about as simple as a graphics file format can get, isn't dumb enough to store a useless fourth byte per pixel on disk. There may be some advantage to doing so in memory for alignment reasons, especially if you also need to store an alpha channel, but those reasons don't apply when writing the image to a file.)
OK, so what about JPEG? Let's try to minimize the compression losses first (quality = 100, no chroma subsampling, floating-point DCT). Unfortunately, the pnmtojpeg
manual doesn't clearly explain how to set all the relevant options (specifically, the -sample
option is listed in the "Options for wizards" section, which just references a file in the libjpeg documentation), so I'll convert it in the GIMP instead. The resulting file looks like this:
897249 rnd.jpg
(JPEG compressed RGB noise, quality = 100, no chroma subsampling, 876 kb)
What, how can it be smaller? Didn't I just say pure noise was incompressible? Well, the thing is, even at maximum quality, normal JPEG compression isn't quite lossless. Reopening the image in GIMP and comparing it with the original, one can see that some pixels have had their color values shifted by one or two steps (out of 256). Those are the pixels where the JPEG compression algorithm "cheated" and threw away a bit here, another there, where it estimated that the change wouldn't be noticeable. Indeed, to the unaided human eye the result is quite indistinguishable from the original, but those discarded bits do add up to a measurable decrease in file size, even after accounting for header and encoding overhead.
So that was maximum quality; what about more typical settings, like the pnmtojpeg
defaults (quality = 75, subsampling enabled)? Let's try it:
$ pnmtojpeg < rnd.ppm > rnd2.jpg
$ du -b rnd2.jpg
185128 rnd2.jpg
(JPEG compressed RGB noise, quality = 75, chroma subsampling, 184 kb)
Wow, from 901 down to 184 kb! That's pretty aggressive compression, though, and you can definitely tell the difference when comparing the images closely. Most of it's because of the chroma subsampling, which basically just throws away 75% of the color (hue / saturation) data. Trying it in the GIMP with subsampling disabled gives a 350,618 byte file that still looks (to the human eye, at least) pretty close to the original even when magnified.
Anyway, the point of all this is to demonstrate that, no matter how noisy your night sky photos might be, and no matter how high a quality you might select, there's just no way a 640 × 480 JPEG file can get significantly larger than 900 kb. (Well, unless your camera attached a multi-megabyte Exif color profile to it or something equally stupid, that is.) And if you're using more typical JPEG compression settings, the maximum plausible file size goes down to about 200 kb or so.