Bitmap storage / memory representation for N-bit RGB bitmaps - image

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.

Related

Masking out the upper or lower 4 bits results in the same image

I am processing a 12-bit image which is unfortunately store as a 16-bit tiff. However, I do not know which 4 of the 16 bits are useless. So I tried three methods: mask each pixel with 0xFFF0, 0x0FFF, or 0x0FF0. It appears to me the resulting image of these three methods look just the same, but their md5 values are different. Why does this happen? Are there any differences if I use any of these three images for other purposes later?
Computer monitors can only display 256 distinct brightness levels. A 12-bit image consequently has its lower 4 bits ignored. So you see no difference when you zero out those bits or not.
When a 12-bit image is stored in a 16-bit integer, the upper 4 bits are usually left at zero, so there is no difference when you zero them or not. [Sometimes the pixel value is scaled to occupy the full 16 bit range, but this is not usually the case.]
So, don’t mask out any bits is my recommendation. Zeroing our the lower 4 bits just reduced the precision of the values in the image, making it equivalent to an 8-bit image. Masking the upper 4 bits is pointless because they already are zero.

Is Jericho Comms TRNG reliable?

I'm looking for a method to generate true random bits/numbers on smartphones.
Create a custom TRNG seems to be tricky and a lot of people suggest to trust in already existing ones, widely tested and approved.
But I've found Jericho Comms, that uses a custom TRNG from the pictures as input.
How secure, strong and reliable is this? Could it be a valid method to generate truly random numbers/bits?
I know that smartphone cameras are not perfect for this purpose because of the JPEG compression and low quality... but omitting this, how correct is the algorithm proposed?
I paste the documentation:
This process describes the full algorithm:
Load the user's photograph into memory and store it in a sequential array of RGB values.
Get the red, green and blue (RGB) integer values for each pixel. This will return a number between 0 and 255 for each colour.
Remove sequentially repeating black (0, 0, 0) pixels, white (255, 255, 255) pixels and pixel colours that are exactly the same. This removes sections of the photograph with underexposed pixels, overexposed pixels and those that have have little entropy. Generally it is very unusual to have adjacent pixels that are exactly the same colour unless there is a hardware failure, or the section of the photo is under/overexposed. Usually in a good quality photograph there are at least very slight colour variations in adjact pixels. This step removes these low entropy areas.
Estimate 1 bit of input entropy per set of RGB values (1 bit per 24 bit pixel). This is a very conservative estimate. Users can increase this in the TRNG settings to 3 bits per pixel which would account for the entropy in the least significant bit of each colour.
Gather 512 RGB values to get an estimated entropy input of 512 bits.
Convert the 512 RGB values to their hexadecimal representation and input them into a cryptographic hash with a 512 bit output. The user can choose which hash to use and the program allows either Skein or Keccak [c=2d]. Both are very strong finalist algorithms from the NIST hash function competition. Store this hash output of 512 bits as the temporary seed into the next hash.
Start a loop:
- Check there is enough new input entropy for the new hash, or break out of the loop.
- Get the temporary seed from earlier.
- Get a new set of 512 RGB values (512 bits) as the new input entropy.
- Concatenate the seed and input entropy together and hash them using: Hash( seed || input entropy ).
- Append the first 256 bits of the hash output to the output random data.
- Update the temporary seed to be the last 256 bits of the hash output.
- Return to start of the loop.
It is important to note that the program does not use this collected entropy to seed a psuedo-random number generator to give an unlimited amount of random data. The program aims to be a true random number generator so only quality randomness is wanted and each uniformly random bit must be used solely to encrypt one bit of the plaintext. It's assumed that most pseudo-random number generators or even CSPRNGs that stretch out the entropy could produce a subtle bias in the output and allow the NSA or other governments to decrypt part or all of a message. With this program the aim is to avoid stretching the available entropy over more bits.

Extra data within image (PPM/PAM/PNM)

Is it possible to store extra data in pixels of a binary PNM file in such a way that it can still be read as an image (hopefully by any decoder, but specifically by ffmpeg)?
I have a simulation that saves its data as PPM currently and I'd like a way to record more than three values per pixel in the file, and yet still be able to use it as an image (obviously only the first three/four values will actually affect the image).
In particle I think the TUPLTYPE of PAM should allow me to do this, but I don't know how make something that's also a readable image from that.
There are two tricks which together can get up to 5 additional bytes per pixel in PAM file.
First trick:
You can try store additional byte of information in alpha channel and then choose to ignore that information in decoder. Enabling alpha channel in PAM is done by adding _APLHA to TUPLTYPE argument, so instead TUPLTYPE RGB you have TUPLTYPE RGB_ALPHA.
Second trick:
You can set MAXVAL in PAM (or equivalent field in PPM and others) to 65535 instead of 255, which means that every pixel will be described by three 16-bit values instead of three 8-bit ones. Now, for these 16-bit values the 8 least significant bits can be used to store information as they do not affect visual properties of image when shown on typical computer screen.
First + second trick:
This gives you additional 3 x 8 = 24 bits for RGB planes and 16 bits in alpha channel. Which means: 5 bytes.
I've not used PNM file format, but I've done this trick with a .bmp file.
Hijack the least significant bit of the image data and stuff it with whatever binary data you want. Nobody will see the difference between a pixel value of a 0 or 1 (00000000 or 00000001), or the the difference between a 254 or 255 (1111110 or 11111111). For every 8 bytes of image data a byte of extra data can be embedded (6 bytes if you use a limited character set). The file viewing software won't know any difference. Any software which could open the file before the encoding, would be able to read it after.
If you want the data to be more covert/hidden, the bits can be stuffed into the image data with a shuffle routine, where the first bit might be location 50, the second in 123, the third in 32... and after locations 0-255 (first 256 bytes if image data) are used (first 32 bytes of extra data), start the shuffle again.

Custom Image Format: How to Target Compression Algorithms

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.

Compressing/packing "don't care" bits into 3 states

At the moment I am working on an on screen display project with black, white and transparent pixels. (This is an open source project: http://code.google.com/p/super-osd; that shows the 256x192 pixel set/clear OSD in development but I'm migrating to a white/black/clear OSD.)
Since each pixel is black, white or transparent I can use a simple 2 bit/4 state encoding where I store the black/white selection and the transparent selection. So I would have a truth table like this (x = don't care):
B/W T
x 0 pixel is transparent
0 1 pixel is black
1 1 pixel is white
However as can be clearly seen this wastes one bit when the pixel is transparent. I'm designing for a memory constrained microcontroller, so whenever I can save memory it is good.
So I'm trying to think of a way to pack these 3 states into some larger unit (say, a byte.) I am open to using lookup tables to decode and encode the data, so a complex algorithm can be used, but it cannot depend on the states of the pixels before or after the current unit/byte (this rules out any proper data compression algorithm) and the size must be consistent; that is, a scene with all transparent pixels must be the same as a scene with random noise. I was imagining something on the level of densely packed decimal which packs 3 x 4-bit (0-9) BCD numbers in only 10 bits with something like 24 states remaining out of the 1024, which is great. So does anyone have any ideas?
Any suggestions? Thanks!
In a byte (256 possible values) you can store 5 of your three-bit values. One way to look at it: three to the fifth power is 243, slightly less than 256. The fact that it's slightly less also shows that you're not wasting much of a fraction of a bit (hardly any, either).
For encoding five of your 3-bit "digits" into a byte, think of taking a number in base 3 made from your five "digits" in succession -- the resulting value is guaranteed to be less than 243 and therefore directly storable in a byte. Similarly, for decoding, do the base-3 conversion of a byte's value.

Resources