I would like to confirm my interpretation of the PNG file format description is correct with color type 0x02 and with tRNS chunk present. It says on PNG website that:
For colour types 0 or 2, two bytes per sample are used regardless of the image bit depth (see 7.1: Integers and byte order). Pixels of the specified grey sample value or RGB sample values are treated as transparent (equivalent to alpha value 0); all other pixels are to be treated as fully opaque (alpha value 2bitdepth-1). If the image bit depth is less than 16, the least significant bits are used and the others are 0.
Give this same tRNS Chunk:
Length: 6
Type: tRNS
Data: 00 ff 00 ff 00 ff
CRC: 37581b7d
Does this mean for RRGGGBBB: 0xFFFFFF or the white color is treated as transparent and all other colors are as is? If so, for the general case, I need to construct an array of such color (say array of int) and during the decoding of the IDAT chunk, I need to look up if the color is one of the transparent color, if so, it is treated as (RRGGBBAA) 0xRRGGBB00, or fully transparent? What would be a good LUT for such case?
Thanks!
Your interpretation is correct.
I need to look up if the color is one of the transparent color,
Actually not "one of" but the transparent colour: in the truecolor+TRNS scenario all colors are opaque except one.
What would be a good LUT for such case?
I don't think that scenario has to do with LUTs. Think of this format as an efficient way to store a true color image with "hard" (yes/no) transparency. The decoder will typically either decode the image adding an alpha channel (and then the colour would be factually ignored), (for example you can see lineToARGB32 method here) or either by ignoring the TRNS.
Notice that this truecolour+TRNS case is not very usual, there are not many PNG images with that format, and many readers just ignore the TRNS in that case.
Related
As can be seen in this example, each channel (R, G, B) in a BMP file takes an input. A 24-bit BMP image has 8 bit for-R , 8-bit for G, and 8 bit for B. I saved an image in MS-paint as monochrome(black and white). Its property says the image's depth is 1-bit. The question is who gets this 1 bit: R , G or B? Is it not mandatory that all the three channels must get certain value? I am not able to understand how MS-Paint has drawn this BMP image using 1 bit.
Thanks in advance for your replies.
There's multiple ways to store a bitmap. In this case, the important distinction is RGB versus indexed.
In an RGB bitmap, every pixel is associated with three separate values, one for red, another for green, and another for blue. Depending on the "bitness" (bit depth) and the specific pixel format, the different colour channels can have different amount of bits allocated for them - the simplest case is the typical true-color with 8 bits for each of the channels, and another 8 bits (optional) for the alpha channel. However, some pixel formats allocate a bit differently - the idea is that the human eye has different sensitivity to each of those channels, and you can save up on space and improve visual quality by allocating the bits in a smarter way. For example, one of the more popular pixel formats is BGR-565 - that is, 16 bits total, 5 bits for blue, 6 bits for green and 5 bits for red.
In an indexed bitmap, the value stored with each of the pixels is an index (hence "indexed bitmap") into a palette (a colour table). The palette is usually a simple table of colours, using RGB "pixel" formats to assign each index with some specific colour. For example, index 0 might mean black, 1 might mean turqouise etc.
In this case, the bit-depth doesn't exactly map into colour quality - you're not trying to map the whole colour space, you're focusing on some subset of the possible colours instead. For example, if you have 256 shades of grey (say, from black to white), a true-colour bitmap would need at least three bytes per pixel (and each of those three bytes would have the same value), while you could use an indexed bitmap with a pallete of all the grey colours, requiring only one byte per pixel (plus the cost of the pallete - 256 * 3 bytes). There's a lot of benefits to using indexed bitmaps, and a lot of tricks to improve the visual quality further without using more bits-per-pixel, but that would be way beyond the scope of this question.
This also means that you only need as many possible values as you want to show. If you only need 16 different colours, you only need four bits per pixel. If you only need a monochromatic bitmap (that is, either a pixel is "on", or it's "off"), you only need one bit per pixel - and that's exactly your case. If you have the amount of distinct colours you need, you can easily get the required bit depth by taking a base-2 logarithm (e.g. log 256 = 8).
So let's say you have an image that only uses two colours - black and white. You'll build a pallete with two colours, black and white. And for each of the pixels in the bitmap, you either save 0 if it's black, or 1 if it's white.
Now, when you want to draw a bitmap like this, you simply read the palette (0 -> RGB(0, 0, 0), 1 -> RGB(1, 1, 1) in this case), and then you read one pixel after another. If the bit is zero, paint a black pixel. If it's one, paint a white pixel. Done :)
No, it depends on the type of data you chose to save as. Because you chose to save as monochrome, the RGB mapping is not used here, and the used mapping would go as a one byte per pixel, ranging from white to black.
Each type has its own mapping ways, saving as 24-bit will give you RGB mapping, saving as 256 will map a byte for each pixel, each value represents a color( you can find the table on the internet), as for monochrome, you'll have the same as a 256 bitmap, but the color table will only have white and black colors.
Sorry for the mistake, the way I explained for monochrome is actually used by Gray Scale, the monochrome uses one bit to indicate if the pixel is black or white, depending on the value of each bit, no mapping table is used.
I'd like to convert a VGA color (256 colors; 8 bit) to a RGB color on iOS.
Is it possible to compute this or do I have to use color tables (using CGColorSpaceCreateIndexed).
UIColor does not support 256 Colors.
Thanks :)
Somewhere, the title you're porting should have set the palette. On the VGA, the 256 colours are mapped through a table that the programmer has previously set to convert them into 18 bit RGB colour (at a uniform 6 bits per channel). If you're running the original title through emulation then watch for writes to ports 0x3c6, 0x3c8 and 0x3c9 or calls to the BIOS via int 10h, with ax = 0x1010 (to set a single colour) or 0x1012 (to set a range). If you have the original code, obviously look for the source of the palette table.
In drawing terms, you can keep the palette yourself, for example as a C-style array of 256 CGColorRefs, or use CGColorSpaceCreateIndexed as you suggest (ignore Apple's slight documentation error; the colour table can contain up to 256 entries, not up to 255) probably with a bitmap context to just pass your buffer off to CoreGraphics and forget about it.
I expect the remapping will be performed on the CPU, so if that gets a bit too costly then consider using GL ES 2.x and writing a suitable pixel shader — you'd upload your actual image as, say, a luminance (ie, single channel) texture, plus a 256x1 texture where the colour at each spot is a palette entry, then write a shader that reads from the first texture for the current texture coordinates and uses that value to index the second.
24 bits are available per pixel.
Assuming
1. eyes are sensitive to brightness than color.
2. eyes are sensitive to red & green than blue.
What kind of encoding can I choose?
I thought about it,but didn't get an idea. Y'CbCr with 4:2:0 encoding works for the brightness part, but what about the color?
That's already accounted for. YUV420 meens that the color components are subsampled. I'm not sure if it was horizontally or vertically though. That means that your image will contain half the color information compared to luminence. Also, the quantization tables are different for the color components so that will also increase the compression rate.
In Fireworks, when you export a PNG8 file with alpha transparency, the resulting file will be something like this:
png8-fireworks.png: PNG image data, 500 x 500, 8-bit colormap, non-interlaced
If you convert a 32bit PNG using other tools (PNGOUT, Smush.it) the result looks like this:
png24-smushit.png: PNG image data, 500 x 500, 8-bit/color RGBA, non-interlaced
png8-pngout.png: PNG image data, 500 x 500, 8-bit/color RGBA, non-interlaced
What exactly is the difference? They both have alpha transparency, but the Fireworks file is 8KB while the others are 20KB. Now the Fireworks file in noticeably lower quality (namely with banding on gradients).
For some images the PNG8+alpha from Fireworks works great and has a super small file size comparatively. I just haven't been able to figure out what Fireworks is doing and how it is different than the other methods.
The PNG8 file is a very efficient format. It finds the unique colors in the image and only saves those in a small palette. The cool part is that it also saves alpha transparency in the palette with each color. (If you have three pure reds (#FF0000) in your image, but each has a different alpha value, let's say 255, 128, 65, it will save three entries in the palette.
You can also in Fireworks choose to limit the palette size to a power of 2, so you can reduce colors used for more savings. Often a 256 color image will look fine at 64 colors and save a lot of weight.
from sites of both tools:
PNGOUT:
It won't convert an image to a color type or bit depth that cannot losslessly store the image.
It won't reduce the number of colors being used in an image, or convert the colors to grayscale unless all the colors correspond to PNG grayscale values already.
Smush.it:
It is a "lossless" tool […]
Neither gives you a 256 paletted png: it's the diff between "colormap" (= palette) and "rgba" (truecolor = R of 2^8 x G of 2^8 x B of 2^8 x Alpha of 2^8, with 2^8 = 256).
Fireworks does.
PNG-8 means 8 bits per pixel, which means it can only display 256 different colours (from a pallet).
24 and 32 bits per pixel allow you to use far more colours (and hence get nice smooth gradients) but come at the cost of filesize.
CGBitmapContextCreate takes an parameter that's not very obvious to me:
For example, for a 32-bit pixel format
and an RGB color space, you would
specify a value of 8 bits per
component.
I have created 24-bit PNG files with alphatransparency, and added them to Xcode. At compile time, Xcode optimizes those PNG tiles with pngcrunch.
So, when trying to make an graphics context out of such an image file on iPhone-OS, I need to specify the bits per component.
In this case, I would say they're 4 bits per component, although I dont know if alpha counts as an component.
It's 8 bits per component:
Red:8;
Green:8;
Blue:8;
Alpha:8;
That adds up to 32 bits per pixel. Your 24-bit png with transparency is 24-bits for RGB, plus 8 bits for transparency (the 'alpha channel').