Create and write paletted RGBA PNG using NSImage - cocoa

I'm trying to create paletted PNG image (8-bit per pixel) that uses RGBA palette (32-bit per palette entry) using Cocoa framework*.
I've tried few combinations for [NSBitmapImageRep initWithBitmapDataPlanes:…] method. It seems to create appropriate bitmap for bitsPerSample:2 bitsPerPixel:8.
However, when I try to write such bitmap with [NSBitmapImageRep representationUsingType:NSPNGFileType…] I get:
libpng error: Invalid bit depth for RGBA image
If I try other bit depths, then I get 32-bit per pixel (non-paletted) image.
*) I know I could just use libpng, but that's not an answer I'm looking for.

2 bits per sample, 8 per pixel will not get you an indexed PNG--it will, in theory, create an RGBA PNG file with 2 bits per sample, just as it suggests. Now, such an image has 256 possible colour values per pixel (including alpha channel) but it's not indexed in the sense of having a colour lookup table.
To my knowledge, there is no way to specify a colour palette when using NSBitmapImageRep. You will probably have to use libpng directly to get the effect you want. (By the way, it doesn't matter if you aren't looking for this answer. It's still the correct answer to this particular problem and saying "no!" isn't going to change the universe around you.)
However, before you do that, if you tell us why you think/know you need an indexed PNG, we may be able to point you toward a better or simpler solution.

Related

keep original values when saving matrix to image in Matlab

Let me explain.
My program takes an x-ray in a format of the x-ray detector ".his" which goes from 0 to 65535, and from those values it can tell you how much of a certain material is in each pixel "4 cm of aluminum" for example.
It does that for every pixel and you end up with a matrix that tells you how much of a given material is there, and you can visualize that matrix and see only fat tissue in an image without the bones blocking your view, it's very cool I know.
What I want to do now is to save that matrix as an image so that I can analyse and modify that image with programs like Image J, but I also want that if I see the pixel value I see the original value, I want to see "4" and know that pixel shows 4 cm of lungs or whatever material I'm working on.
Is that possible?, my professor seems to think that it is but he's not sure how to do it, and figure that out is my job anyway.
It should be possible since with Image J I can open the ".his" format and I can do just that, I can see the values from 0 to 65535, provided I say Image J that the image is 16 bit unsigned and other properties of that kind of files, but I wouldn't know how to do that for a Matlab variable.
Thanks a lot.
So if I understand correctly, you want to save an image that also contains arbitrary metadata on every pixel (in this case an integer).
If you use an image format like PNG you could encode that extra data into the alpha channel (which would be nearly imperceptible with a value like 4/255 away from fully opaque), but you'd have to be careful when editing the image that you don't change the alpha channel by mistake.
However, this is rather finnicky and would be cumbersome to implement in Matlab.
Instead I would suggest simply saving a standard image and a text file (or binary file) alongside it with the data you want.

Reading voxel values from binary file into matlab

I have a 16bit voxel data set from which I need to extract the integer values for each voxel. The data set can be downloaded from here, it is the 'Head Aneuyrism 16Bits' data set (You need to click on the blood vessels image to download the 16bit version). Its size is 512x512x512, but I don't know whether it is greyscale or color, nor if that matters. Looking at the image on the website I'd guess that it is color, but I am not sure whether the image should be taken literally.
A related question on SO is the following: How can I read in a RAW image in MATLAB?
and the following on mathworks: http://www.mathworks.com/matlabcentral/answers/63311-how-to-read-an-n-dimensioned-matrix-from-a-binary-file
Thanks to the information in the answers to these questions I managed to extract some information from the file with matlab as follows:
fileID=fopen('vertebra16.raw','r');
A=fread(fileID,512*512*512,'int16');
B=reshape(A,[512 512 512]);
I don't need to visualise the image, I only need to have the integer values for each voxel, but I am not sure whether I am reading the information in the correct way with my script.
The only way I found to try and check whether I have the correct voxel values is to visualise B using the following:
implay(B)
Now, with the code above, and then using implay(B) I get a black and white movie with a white disc in the center and black background and some black pixels moving in the disc (I tried to upload a frame of the movie, but it didn't work). Looking at the image on the website from which I downloaded the file, the movie frames I get seem quite different from that image, so I'd conclude that I do not have the correct voxel values.
Here are some questions related to my problem:
Do I need to know whether the image is in grey scale or color to read the voxel values correctly?
On the data set website there is only written that the data set is in 16bit format, so how do I know whether I am dealing with signed or unsigned integers?
In the SO question linked to above they use 'uint8=>uint8'. I could not find this in the matlab manual, so I wonder whether 'uint8=>uint8' is an obsolete matlab notation for 'uint8' or if it does something different. I suspect that it does something different since if I use 'int16=>int16' instead of 'int16' in my code above I get a completely black movie with implay.
It looks like you read the data correctly.
The problem when displaying it is the scale of the values. implay seems to assume the values to be in [0,1] and therefore clamps all values to be in that range, where are your data range is [0,3000].
Simply doing
B = B / max(B(:))
will rescale your data to [0,1] and looking at the data again with
implay(B)
shows you something much more sensible.

How can I find out if a `QPixmap` has transparency?

I have some QGraphicsPixmapItem that will contain images... of any kind.
I will have to perform certain processing, that is very simple if the image contained in the item is fully opaque, but more complicated if there is transparency. So I want to separate these 2 situations.
How can I find out if a QGraphicsPixmapItem or a QPixmap has transparency ?
(the only thing I found so far is QPixmap::mask():
Extracts a bitmap mask from the pixmap's alpha channel.
Warning: This is potentially an expensive operation. The mask of the pixmap is extracted dynamically from the pixeldata.
not sure what i do with it...
or I can iterate myself through pixel data till I find a pixel with some transparency... either version seems ineffective)
Update:
After implementing it myself, I found an older similar question:
Checking if a QImage has an alpha channel
(seems nobody else found an alternative to iterating through all pixel data)

Ideal image format for color image that is really greyscale

I have a matrix of m x n float data values that I want to apply a rainbow colormap to and then store as a color image.
The data values are almost random.
What would be the ideal image format for storing such an image?
I want the resulting image file to be as small as possible withouth loosing visual information.
Depends on what the images is getting used for. WebP has amazing lossless capabilities but the support is not great. IOS and most browsers does not support it although late android and Chrome does. For a generic lossless format you should use PNG. JPEG at a high quality setting is also fine depending on what you mean by loosing info. If you need exact pixel accurate color values you need to go lossless and cant use JPG.
To make the image as small as possible you can use a lower bit depth. By default most PNG files are 32 bit which is 24 bit of color and 8 bit of transparency (alpha channel). If you do not need transparency you can dump the alpha channel and go 24 bit. If you do not need as many colors use a lower bit depth. 16 bit will get you most colors you need for most purposes. You can take an image that is more than 16 bit and map it to 16 bit and for most purposes you can not tell. It depends on how many colors appear in the image even though they are random. At 8 bit and below PNG files uses a color lookup table so the colors can be random but if there are fewer than 256 or if you can live with some remapping go 8 bit PNG. Take this furthure, if there are fewer than 128 colors go 7 bit all the way down to 1 bit.
Also you can save tiny amount of size by stripping the metadata and other info. There are a bunch of open source tools to do so.

which format of png should I use?

Which format of PNG should I use PNG 8 or PNG 24? Which one is better for a website. I am confused about these. What is main different between PNG 8 and PNG 2?
Png-24. Png-24 has alpha transparency (where Png-8 only has on/off transparency).
Png-8 is indexed. Png-24 is loss-less.
Png-24 is better in almost every way.
http://www.elated.com/articles/understanding-image-formats/
PNG has several modes which can be used. It may contain:
Greyscale
Indexed colour, usually meant by PNG-8
Greayscale with alpha
Truecolour (RGB)
Truecolour with alpha (RGBA), usually meant by PNG-24
Indexed colour is different from the others that it is a palette of maximum 256 colours, from which indexes are used to denote the colour of specific pixels. It can contain transparency via an auxillary chunk. So every pixel is denoted by a byte-wide value or even less if palette isn't that big. If you use truecolour, there will be more data per pixel, depending on whether you use an alpha-channel.
So in a large image indexed colour will save you a lot of data per each pixel. However, if you use more than 256 colours, some colour data will be lost, which is also more probable in a large image. I would advise to save your image in both formats and see if the loss is worth the gain in smaller file size. Though if you are designing your image for normal web site, not for mobile phones, you should better use PNG-24 anyway, since no one will notice the difference in the size.
I would say that it depends on the image you want to store as PNG*, but in case you've doubts, PNG-24 is better: "true color" (8bits per channel), so that the image must not be dithered and don't "loose" "exact" color match, and optionally PNG-32 if with the alpha channel (transparency) too. PNG-8 images are limited (256 colors chosen from a 24bit palette) and allow only for a mask, you can use it e.g. if you convert from a GIF image; if you convert from other "true color" formats, you "loose" "exact" color match as said (the program try to reduce the real number of used colors into only 256 colors, and other tricks to give resemblance with the original). Some style of icons do not need "true colors", they are "described" well by 256 "fixed" colors or less, and so PNG-8 is ok; as said, if you have GIF images as source, go for PNG-8... if you convert from JPG, go for PNG-24; if you create you image by yourself directly "in" PNG, you know if you can "crunch" the result in PNG-8 or not, but if you are not able to evaluate or use tools to evaluate, PNG-24/32 is ok in any case.
I've written article about it: PNG that works, which outlines all major variants of PNG and their trade-offs/compatibility.
In short, use PNG8 (paletted) whenever you can, as it has much smaller file size. You can have full alpha transparency in PNG8 if you use good tools (Photoshop is not good for PNG).

Resources