I have read severel posts like this one claiming that the size of a JPG texture can be calculated as
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)
which totally makes sense since each pixel is represented by a color value. Here comes the weird part:
I have these two JPG files
First JPG
which has the dimensions 242x198 and uses 24-bit color values.
Second JPG
which has the dimensions 3840x2400 and uses 24-bit color values.
Then I tried to calculate the sizes using the technique above and concluded that
The first JPG must have the size 242*198*24 = 1149984 bits = 1149984/8/1000 = 143.7 kb - now the actual file size is 47,6 kb?? So the calculation apparently gives a number above the actual size, why?
The second JPG must have the size 3840*2400*24 = 221184000 = 221184000/8/10000 = 27.6 mb - now the actual file size is 7.33 mb. So the calculation apparently gives a number above the actual size, why?
I have myself managed to draw the first JPG and made sure to export it without compression (JPG 100).
The whole point of JPEGs is that they are compressed to take up less space. If you resave your file as a BMP you'll get the sizes you expect (plus a bit extra for headers and alignment).
Related
This is all of the information I was provided in the practice question. I am trying to figure out how to calculate it when prompted to do so on an exam...
How to determine the number of bytes necessary to store an uncompressed grayscale image of size 8000 × 3400 pixels?
I am also curious how the calculation changes if the image is a compressed binary image.
"I am trying to figure out how to calculate it when prompted to do so on an exam."
There are 8 bits to make 1 byte, so once you know how many bits-per-pixel (bpp) you have, this is a very simple calculation.
For 8 bits per pixel greyscale, just multiply the width by the height.
8000 * 3400 = 27200000 bytes.
For 1 bit per pixel black&white, multiply the width by the height and then divide by 8.
(8000 * 3400) / 8 = 3400000 bytes.
It's critical that the image is uncompressed, and that there's no padding at the end of each raster line. Otherwise the count will be off.
The first thing to work out is how many pixels you have. That is easy, it is just the width of the image multiplied by the height:
N = w * h
So, in your case:
N = 8000 * 3400 = 27200000 pixels
Next, in general you need to work out how many samples (S) you have at each of those 27200000 pixel locations in the image. That depends on the type of the image:
if the image is greyscale, you will have a single grey value at each location, so S=1
if the image is greyscale and has transparency as well, you will have a grey value plus a transparency (alpha) value at each location, so S=2
if the image is colour, you will have three samples for each pixel - one Red sample, one Green sample and one Blue sample, so S=3
if the image is colour and has transparency as well, you will get the 3 RGB values plus a transparency (alpha) value for each pixel, so S=4
there are others, but let's not get too complicated
The final piece of the jigsaw is how big each sample is, or how much storage it takes, i.e. the bytes per sample (B).
8-bit data takes 1 byte per sample, so B=1
16-bit data takes 2 bytes per sample, so B=2
32-bit floating point or integer data take 4 bytes per sample, so B=4
there are others, but let's not get too complicated
So, the actual answer for an uncompressed greyscale image is:
storage required = w * h * S * B
and in your specific case:
storage required = 8000 * 3400 * 1 * 1 = 27200000 bytes
If the image were compressed, the only thing you should hope and expect is that it takes less storage. The actual amount required will depend on:
how repetitive/predictable the image is - the more predictable the image is, in general, the better it will compress
how many colours the image contains - fewer colours generally means better compression
which image file format you require (PNG, JPEG, TIFF, GIF)
which compression algorithm you use (RLE, LZW, DCT)
how long you are prepared to wait for compression and decompression - the longer you can wait, the better you can compress in general
what losses/inaccuracies you are prepared to tolerate to save space - if you are prepared to accept a lower quality version of your image, you can get a smaller file
Typically, the most common RGB format seems to be 24-bit RGB (8-bits for each channel). However, historically, RGB has been represented in many other formats, including 3-bit RGB (1-bit per channel), 6-bit RGB (2-bits per channel), 9-bit RGB (3-bits per channel), etc.
When an N-bit RGB file has a value of N that is not a multiple of 8, how are these bitmaps typically represented in memory? For example, if we have 6-bit RGB, it means each pixel is 6 bits, and thus each pixel is not directly addressable by a modern computer without using bitwise operations.
So, is it common practice to simply covert N-bit RGB files into bitmaps where each pixel is of an addressable size (e.g. convert 6-bit to 8-bit)? Or is it more common to simply use bitwise operations to manipulate bitmaps where the pixel size is not addressable?
And what about disk storage? How is, say, a 6-bit RGB file stored on disk, when the last byte of the bitmap may not even contain a full pixel?
Images are often heavy and bandwidth is critical when transferring them. So a 6 bit per channel image is a reasonable choice if some loss in chrominance is acceptable (usually unnoticeable with textures and photos)
How is, say, a 6-bit RGB file stored on disk, when the last byte of
the bitmap may not even contain a full pixel?
If the smallest unit of storage is a Byte then yes you need to add some padding to be 8 bit aligned. This is fine because the space saving compared to an 8 bit per channel image can be considerable.
A power of 2 value that is divisible by 6 is very large. Better numbers are 5 bits for the red and blue channels and 6 bits for the green channel and the total is 16 bits per pixel. R5G6B5 is a very common pixel format.
Apologies for the archeological dig, but I just couldn't resist, as there's no good answer imho.
In the old days memory was the most expensive part of a computer. These days memory is dirt-cheap, so the most sensible way to handle N-bit channel images in modern hardware is to blow up every channel to the number of bits that fits your API or hardware (usually 8 bits).
For files, you could do the same, as disk space is also cheap these days. (and you can use one of the many compressed file formats out there.)
That said, the way it worked in the old days when these formats were common, is this:
The total number of bits per pixel was not a multiple of 8, but the number of pixels per scan line always was a multiple of 8. In this case you can store your scan lines "a bit at a time" and not waste any memory space when storing it in bytes.
So if your pixels were 9 bits per pixel, and a scan line was 320 pixels, you would have 320/8 = 40 bytes containing bit #0 of each pixel, followed by 40 bytes containing all bit #1's etc. up to and including bit #8. Hence all pixel info for your scan line would be exactly 360 bytes.
The video chips would have a different hardware wiring to the memory, so rendering such scan lines was fast. In fact, this is the easiest way to implement a variable amount of bits/pixel hardware support: by pulling bits from N adresses at once.
Note that this method does not change the amount of 'bitshifting' required to find the bits for pixel number X in a scanline, based on the total number of bits you use. You just read less addresses ahead at once.
I created a monochrome bitmap image and stored it in secondary memory. The dimension of the image is 484 * 114. In monochrome each pixel of the image is represented by 1 bit so the size of the image should be 6.7 kb . But when I check the size by right on file in OS , it is 7.18 KB , I need the explanation why the size is different and not exact as I calculated?
Because of overhead of headers for example; your bitmap won't only store the bits representing your image but also (meta)information containing information such as width, height, bits per plane etc. The actual bitmap data is just a bunch of bytes, without this (meta)information your image might as well be 114 x 484 instead of 484 x 114. Take a look at, for example, the BMP fileformat.
Also, OS'es tend to round filesizes to particular block sizes (like 4Kib). Unless you state the exact filesize in bytes, OS and filetype all we can do is guess.
I've done a bit of fiddling around with PNGs over the last couple days and I am upset with my findings. I'm concluding that the majority of my results deal with compression. So this weekend I'm going to dive into advanced compression articles. I wanted to share my findings so far. To see if anyone has any advice on achieving my goal and to maybe point me in the right direction.
I am currently working on a project where I need to obtain the smallest possible file size within a window of less than 15 seconds.
The majority of the images I am working with are PNG-8bpp with a full 256 color palette. Most of these images I could represent accurately with 5bpp (32 colors).
PNG indexed however only supports 1,2,4, and 8bpp. So my idea was to strip the PNG format to the minimal information I needed and write an encoder/decoder to support IDAT sections with 3,5,6, or 7bpp.
Test 1:
Original File: 61.5KB, 750 * 500, 8pp Palette, 256 colors, No tRNS
After Optimizations (Reductions to 4bpp, Strip Anx Chunks, & PNGOUT): 49.2KB 4bpp, 16 Colors
Human Interpretation: I can see 6 distinguishable colors.
Since I only need six colors to represent the image I decide to encode the IDAT using 3bpp to give me a max palette of 8 colors. First I uncompressed the IDAT which results in a new file size of 368KB. After applying a 3bpp to IDAT my new uncompressed file size is 274KB. I was off to what seemed to be a good start... Next I applied deflate to my new IDAT section. Result... 59KB.
10KB larger than using 4bpp.
Test 2:
Original File: 102KB, 1000 * 750, 8bpp, 256 Colors, tRNS 1 fully transparent color
After Optimization: 79KB, 8bpp, 193 colors, tRNS 1 full transparent color
Human Interpretation: I need about 24 colors to represent this picture.
24 colors can be represented in 5bpp at 32 colors. Using the same technique above I was able to achieve much better results over uncompressed but again I lost at compression. Final size compressed... 84KB. Then I tried at 6,7bpp... same result poorer compression that at 8bpp.
Just to be sure I saved all the uncompressed images and tried several other compression algorithms... LZMA, BZIP2, PAQ8... same result smaller compression size at 8bpp than at 5,6, or 7bpp AND smaller size at 4bpp than at 3bpp.
Why is this occuring? Can I tweak/modify a compression algorithm to target a PNG like format that uses a 5,6, or 7bpp format that beast 8bpp compression? Is it worth the time... and yes saving another 10KB would be worth it.
What you're seeing is that by using odd pixel sizes, your effective compression decreases because of the way PNG compression works. The advantage of PNG compression over just using straight FLATE/ZIP compression is the filtering. PNG compression tries to exploit horizontal and vertical symmetry with a small assortment of pre-processing filters. These filters work on byte boundaries and are effective with pixel sizes of 4/8/16/24/32/48/64 bits. When you move to an odd size pixel (3/5/6/7 bits) you are defeating the filtering because identically colored pixels won't "cancel each other out" horizontally when filtered on 8-bit boundaries.
Even if the filtering weren't an issue, the way that FLATE compression works, reducing the pixel size from 8 to 7 or 6 bits won't have much effect either because it also assumes a symbol size of 8-bits.
In conclusion...the only benefit you can achieve by using odd sizes of pixels is that the uncompressed data will be smaller. By breaking the pixels' byte boundary symmetry, you defeat much of the benefit of PNG compression.
GIF compression supports all pixel sizes from 1 to 8 bits. It defines the symbol size as the pixel size and doesn't use any pre-filtering. An 8-bit GIF image, if compressed as 7-bit pixels, wouldn't suffer less compression, but also wouldn't benefit because the compression depends more on the repetition of the pixels than the symbol size.
DEFLATE compression used by PNG has two main techniques:
finds repeating byte sequences and encodes them as backreferences
encodes bytes using Huffman coding
By changing pixel length from 8-bit you're out of sync with byte boundaries and DEFLATE won't be able to encode repeating pixel runs as repeated bytes.
And thanks to Huffman coding it doesn't matter that 8-bit pixels have unused bits, because the coding will encode bytes with variable-width codes assigning shortest ones to most frequently occurring values.
What's the maximum size an uncompressed 48x48 image can have? I'd like to set up a reference image for debugging.
48 * 48 = 2304
So, (2304 * number of channels * bytes per channel) bytes
W * H * BitsPerPixel
If BitsPerPixel is 32 (Millions of colors), then it would be 73,728 bits. divide that by 8 to get bytes (9,216). The actual size would vary between the uncompressed formats a bit, especially depending on their color capabilities.
For Bitmaps, this Wikipedia page mentiones some of the color options: http://en.wikipedia.org/wiki/Bitmap
Recently I wrote a primitive PNG writer. You have to put one byte infront of every line and add PNG as well as ZLIB headers and checksums. I'm not sure but I think you can have RGBA images with 16bit per channel. The raw data would be 48*49*2*4=9.4kB. So I would make sure that you can handle 16kB or so.
As you are talking about compression, I assume that you mean an image file.
The maximum size would depend on the file format and bit depth that you allow.
A 96 bpp TIFF image for example would be 46 kB.
A more reasonable format could be a 24 bbp BMP file, which is 7 kB.