SDL2 - difference between RGB888 and RGB24 - sdl-2

As best I understand, both the RGB888 and RGB24 formats put their red components first, followed by green and then blue, and both formats take a total of 24 bits per pixel (because 8+8+8 = 24). Given this information both identifiers appear to describe the exact same format but I can verify that some of my code works with one of the two formats but not the other. What's the difference between the two that makes them incompatible?

They are different. If you look at SDL2/SDL_pixels.h you'll find:
SDL_PIXELFORMAT_RGB24 =
SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_RGB, 0,
24, 3)
SDL_PIXELFORMAT_RGB888 =
SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB,
SDL_PACKEDLAYOUT_8888, 24, 4)
SDL_PIXELFORMAT_RGBX8888 =
SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBX,
SDL_PACKEDLAYOUT_8888, 24, 4)
So RGB24 is a tightly packed three byte format (RRGGBB), while RGB888 is a four byte format with the first byte going ignored (XXRRGGBB). So the format is just confusingly named and XRGB8888 would be a more appropriate name.
Don't know why they called it RGB888 instead of XRGB8888, but they leave the leading X away on other formats as well.

From my understanding RGB24 formats it's data in bit triplets, whereas RGB888 simply concatenates the respective byte for each channel.
RGB24:
RGBRGBRG BRGBRGBR GBRGBRGB
RGB888:
RRRRRRRR GGGGGGGG BBBBBBBB
I highly doubt RGB24 serves a functional or technical benefit, as it would be easier to just load the byte into memory like you would do with RGB888. But I'm not sure.

Related

How can an Interlaced .png file's size be smaller than the original file?

Ok, so I tried to use the imagemagick command:
"convert picA.png -interlace line picB.png"
to make an interlace version of my .png images. Most of the time, I got the resulting image is larger than the original one, which is kinda normal. However, on certain image, the resulting image size is smaller.
So I just wonder why does that happen? I really don't want my new image to lose any quality because of the command.
Also, is there any compatibility problem with interlaced .png image?
EDIT: I guess my problem is that the original image was not compressed as best as it could be.
The following only applies to the cases where the pixel size is >= 8 bits. I didn't investigate for other cases but I expect similar outcomes.
A content-identical interlaced PNG image file will almost always be greater because of the additional data for filter type descriptions required to handle the passes scanlines. This is what I explained in details in this web page based on the PNG RFC RFC2083.
In short, this is because the sum of the below number of bytes for interlaced filter types description per interlacing pass is almost always greater than the image height (which is the number of filter types for non-interlaced images):
nb_pass1_lines = CEIL(height/8)
nb_pass2_lines = (width>4?CEIL(height/8):0)
nb_pass3_lines = CEIL((height-4)/8)
nb_pass4_lines = (width>2?CEIL(height/4):0)
nb_pass5_lines = CEIL((height-2)/4)
nb_pass6_lines = (width>1?CEIL(height/2):0)
nb_pass7_lines = FLOOR(height/2)
Though, theoretically, it can be that the data entropy/complexity accidentally gets lowered enough by the Adam7 interlacing so that, with the help of filtering, the usually additional space needed for filter types with interlacing may be compensated through the deflate compression used for the PNG format. This would be a particular case to be proven as the entropy/complexity is more likely to increase with interlacing because the image data is made less consistent through the interlacing deconstruction.
I used the word "accidentally" because reducing the data entropy/complexity is not the purpose of the Adam7 interlacing. Its purpose is to allow the progressive loading and display of the image through a passes mechanism. While, reducing the entropy/complexity is the purpose of the filtering for PNG.
I used the word "usually" because, as shown in the explanation web page, for example, a 1 pixel image will be described through the same length of uncompressed data whether interlaced or not. So, in this case, no additional space should be needed.
When it comes to the PNG file size, a lower size for interlaced can be due to:
Different non-pixel encoding related content embedded in the file such as palette (in the case of color type =! 3) and non-critical chunks such as chromaticities, gamma, number of significant bits, default background color, histogram, transparency, physical pixel dimensions, time, text, compressed text. Note that some of those non-pixel encoding related content can lead to different display of the image depending on the software used and the situation.
Different pixel encoding related content (which can change the image quality) such as bit depth, color type (and thus the use of palette or not with color type = 3), image size,... .
Different compression related content such as better filtering choices, accidental lower data entropy/complexity due to interlacing as explained above (theoretical particular case), higher compression level (as you mentioned)
If I had to check whether 2 PNG image files are equivalent pixel wise, I would use the following command in a bash prompt:
diff <( convert non-interlaced.png rgba:- ) <( convert interlaced.png rgba:- )
It should return no difference.
For the compatibility question, if the PNG encoder and PNG decoder implement the mandatory aspects of the PNG RFC, I see no reason for the interlacing to lead to a compatibility issue.
Edit 2018 11 13:
Some experiments based on auto evolved distributed genetic algorithms with niche mechanism (hosted on https://en.oga.jod.li ) are explained here:
https://jod.li/2018/11/13/can-an-interlaced-png-image-be-smaller-than-the-equivalent-non-interlaced-image/
Those experiments show that it is possible for equivalent PNG images to have a smaller size interlaced than non-interlaced. The best images for this are tall, they have a one pixel width and have pixel content that appear random. Though, the shape is not the only important aspect for the interlaced image to be smaller than the non-interlaced image as random cases with the same shape lead to different size differences.
So, yes, some PNG images can be identical pixel wise and for non-pixel related content but have a smaller size interlaced than non-interlaced.
So I just wonder why does that happen?
From section Interlacing and pass extraction of the PNG spec.
Scanlines that do not completely fill an integral number of bytes are padded as defined in 7.2: Scanlines.
NOTE If the reference image contains fewer than five columns or fewer than five rows, some passes will be empty.
I would assume the behavior your experiencing is the result of the Adam7 method requiring additional padding.

Get width and height from jpeg without 0xFF 0xC0

I'm trying to get the file dimensions (width and height) from a jpeg (in this case an Instagram picture)
https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/11264864_1701024620182742_1335691074_n.jpg
As I understand if, the width and height are defined after the 0xFF 0xC0 marker, however I cannot find this marker in this picture. Has it been stripped or is there an alternative marker I should check for?
The JPEG Start-Of-Frame (SOF) marker has 4 possible values:
FFC0 (baseline) - This is the usual mode chosen for photos and encodes fully specified DCT blocks in groupings depending on the color/subsample options chosen
FFC1 (extended) - This is similar to baseline, but has more than 8-bits
per color stimulus
FFC2 (progressive) - This mode is often found on web pages to allow the image to load progressively as the data is
received. Each "scan" of the image progressively defines more coefficients of the DCT blocks until they're fully defined. This effectively provides more and more detail as more scans are decoded
FFC3 (lossless) - This mode uses a simple Huffman encoding
to losslessly encode the image. The only place I've seen this used is
on 16-bit grayscale DICOM medical images
If you're scanning through the bytes looking for an FFCx pattern, be aware that you may encounter one in the embedded thumbnail image (inside an FFE1 Exif marker). To properly find the SOFx of the main image, you'll need to walk the chain of JPEG markers. The 2-byte length (big-endian) follows the 2-byte marker. One last pitfall to avoid is that some JPEG encoders stick extra FF values in between the valid markers. If you encounter a FFFF where a marker should be, just increment the pointer by 1 byte and try again until you hit a valid marker.
You can get it pretty simply at the command-line with ImageMagick which is installed on most Linux distros and is available for OSX and Windows.
identify -ping https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/11264864_1701024620182742_1335691074_n.jpg
Output
https://scontent.cdninstagram.com/t51....1074_n.jpg JPEG 640x640 640x640+0+0 8-bit sRGB 162KB 0.000u 0:00.000

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.

How is HDR data stored?

I am wondering what the data structure is behind storing images with HDR data. I understand how regular images (rgba) and cubemaps are stored. I doubt its as simple as storing multiple images at different exposures inside the same file.
You've probably moved on long ago, but I thought it worth posting references for anyone else who happened upon this question.
Here is an old reference for the Radiance .pic (now .hdr) file format. The useful info starts at the bottom of page 29.
http://radsite.lbl.gov/radiance/refer/filefmts.pdf
excerpt:
The basic idea is to store a 1-byte mantissa for each of three
primaries, and a common 1-byte exponent. The accuracy of these values
will be on the order of 1% (+/-1 in 200) over a dynamic range from
10^-38 to 10^38.
And here is a more recent reference for JPEG HDR format: http://www.anyhere.com/gward/papers/cic05.pdf
It's generally a matter of increasing the range of values (in an HSV sense) representable, so you can use e.g. RGB[A] where each element is a 16-bit int, 32-bit int, float, double etc. instead of a JPEG-type-quality 8-bit int. There's a trade-off between increasing the range represented, retaining fine gradations within that range, and whether some particular intensity levels are given priority via some non-linearity in the mapping (e.g. storing a log of the value).
The raw file from the camera normally stores the 12-14bit values from the Bayer mask - so effectively a greeyscale. These are sometimes compressed losslessly (in Canon or Nikon) or as 16bit values (Olympus). The header also contains the white balance and gain calibrations for the red,green,blue masked pixels so you can generate a color image.
Once you have a color image you can store it however you want, normally 16bit RGB is the easiest.
Here is some information on the Radiance file format, used for HDR images. It uses 32-bit floating-point numbers.
First, I am not sure if there is a public format for storing multiple images at different exposures inside cause the usage is rare. Those multiple images are used as one sort of HDR sources, but they are not HDR, they are just normal LDR (L for low) or SDR (S for standard?) images encoded like JPEG from digital cameras.
It is more common to store resulting in HDR format and the point is just like everyone mentioned, in floating point.
There are some HDR formats:
OpenEXR
TIF
Radiance
...
You can get more info from wiki

How can you hide information inside a jpg or gif photo?

How can I write some information inside a photo file like jpg or gif without destroying the image? and of course without showing it on the photo since the whole idea is to send information in the file of photo undetected by anyone (to provide security/privacy to some extent)!
You can concatenate a gif and a zip (the information you want to hide) into one file. Gifs are read from the start of the file, while zips are read from the end of the file.
To create such a file in linux:
$ cat file1.gif >> outfile.gif
$ cat file2.zip >> outfile.gif
The resulting file should have the size of file1.gif and file2.zip together and should be openable by any gif viewer and zip file handler.
I'm sure there are many ways. Here's one:
In a photograph, minor variations in color would often be unnoticable to the naked eye, or even if noticed, might easily be mistaken for flaws in the quality of the picture.
So to take a simple example, suppose you had a gray-scale GIF image where the pallette is arranged in order from white to black with a smooth range of grays in between. I'm not sure how much you know about graphic file formats, but in GIF you have one byte per pixel, with each possible byte value mapping to some specific color. So in this case we could say pallette #0=RGB(0,0,0), pallette #1=RGB(1,1,1), ... palette #255=RGB(255,255,255).
Then you take an ordinary, real photograph. Break your secret message into individual bits. Set the last bit of each pallette index number to successive bits of your message.
For example, suppose the first eight pixels of the original photo are, say, 01 00 C9 FF FF C8 42 43. Your message begins with the letter "C", ascii code 0110 0111. So you change the last bit of the first byte to 0, changing the byte from 01 to 00. You change the last bit of the second byte to 1, changing the byte from 00 to 01. You change the last bit of the third byte to 1. It's already 1, so that makes no difference. Etc. You end up with the coded 8 bytes being 00 01 C9 FE FF C9 43 43.
The changes to the colors would be so subtle that it's unlikely that anyone looking at the picture would notice. Even if they did notice, unless they had a reason to be suspicious, they would likely just conclude that the picture was of less-than-perfect quality.
Of course nothing says you have to use 1 bit per byte for the secret message. Depending on how much degradation in quality you think you can get away with, you could use 2 bits per byte, or just change 1 bit in every other byte, etc.
Of course the same technique can be used with color photos: change the last bit in each of the RGB components to encode 3 bits per pixel, etc.
Hey that method is called as Steganography. With that we can hide messages in not just images but also in audio,vedeo and other formats.
Here is an opensouce Steganography software called steganotool This project is an open source steganography tool that can be used to hide and extract text to/ from Bitmap images.
About Steganography Mediums
Steganography in images
This type of steganography is very effective against discovery and can serve a variety of purposes. These purposes can include authentication, concealing of messages, and transmission of encryption keys. The most effective method for this type of steganography is normally the least significant bit method. This simply means that the hidden message will alter the last bit of a byte in a picture. By altering that last bit, there will be relatively no change to the color of that pixel within the carrier image. This keeps the message from being easily detected. The best type of image file to hide information inside of is a 24 bit Bitmap. This is due the large file size and high quality.
Steganography in Audio
In audio files, the most prominent method for concealing information is the low bit encoding method. The low bit encoding method is somewhat similar to the least significant bit method used in image files. The secret information is attached to the end of the file. One of the issues with low bit encoding is that it can be noticeable to the human ear. If someone is trying to hide information, this could be risky, since it is so easily detectable. The spread spectrum method is another method that has been used in the concealment of information in audio files. What this method does, is it adds random noise to the audio broadcast. This method enables for the information to be spread accross the frequency spectrum and remain hiddden under the random noise. The last method seen in audio steganography is echo hiding data. This method seeks to hide information by using the echos that occur naturally within sound files. Then, extra sound can be added to these echos, extra sound being the concealed message. This is a sufficient way to hide information, expecially since it even improves the sound of the original audio file in some cases.
Steganography In Video
Steganography in Videos is basically hiding of information in each frame of video. Only a small amount of information is hidden inside of video it generally isn’t noticeable at all, however the more information that is hidden the more noticeable it will become. This method is effective as well, but must be done right or else reveal more information instead of hiding.
Steganography In Documents
This is basically adding white space and tabs to the ends of the lines of a document. This type of
Steganography is extremely effective, because the use white space and tabs is not visible to the human eye in most text/document editors.
You can also refer to this open source project
This article can be very useful.
You can store some information in image metadata. In fact that's how man digital cameras 'tag' the photos their making (camera model, date and time, GPS coords etc.).
This data format is called EXIF (Exchangeable Image File Format). There are a lot of examples how to use it in programming languages. Here's the example in Java.
If you want to prevent users from reading this data you can encrypt them somehow, but they will always be able to remove it from your picture (by opening in Photoshop and using Save As for example).
If you want to hide data (text, another image, whatever) in a jpeg file, you can simply append it to the end of the file. When the image is viewed, you'll only see the original image and your added data will be ignored.
While not a super-duper way of hiding data, this is a good way of hiding another jpeg, as if anyone opens the file in notepad or a hex editor, they will probably not notice that there are two jpegs and not one because the end of the second image will just look like the first anyway.
In windows you can use simple command to hide archive in image : copy /b cat.jpg + Documents.rar cat_new.jpg.
And then use for example winrar to extract data ftom image as from archive.
But better way is to use Steganography.
simple program for it for linux and windows : http://linux01.gwdg.de/~alatham/stego.html
using this program you will use pass phrase, without it nobody even will know, that you hided some data in picture ))
compressed data in gif files is in variable sized chunks. each chunk starts with a length byte. Usually these chunks are 255 bytes of data (and the length byte says 255) except for the last two chunks (the last one is 0)
But you could re-code the gif with chunks whose size spells out the message
eg using characters for ASCII text or bytes 1 2 3 4 representing 00 01 10 11 binary data,
byte-frequency analysis on the gif would reveal fewer than expected 255 bytes.
and the size would be larger than the original, but the image would look exactly the same.
You don't need any type of advanced tool to hide a file in an image –– you just you need to know some basic DOS commands… just follow the link below, to see how to do this (it’s a short description of image steganography):
https://www.youtube.com/watch?v=ox9ArqXtaWw&list=PLqEKOAKK4IbSTfDJZE_lH-DiOjOzZUczx&index=2

Resources