Octave 4.0 `imwrite` png: `BitDepth` 4? - image

Matlab's imwrite allows me to specify paired arguments 'BitDepth',4 when writing a 2D uint16 array to a file '*.png'. My Octave's imwrite doesn't accept the paired arguments 'BitDepth',4. I can exercise some limited control of bit depth, however, if I scale the data for uint8 and save it to a 2D uint8 array; the '*.png' from imwrite is then just over half the size the file for a uint16 array. I got the idea to do this by looking at imread, for which the bit depth of the source image file determines the uint type of the destination variable. Assuming that the uint type of the source 2D image array similarly determines the bit depth of the imwrite destination file, uint8 yields a bit depth of 8. I found, however, that a bit depth of 2 is often enough for 100 dpi grayscale scans of hand notes. Is there an easy way to have such arbitrary bit depth control for imwrite?
Aside: Regarding the reference to uint16 above, I didn't just make that up. It's the default from a conversion from colour RGB. From a web search, I found a conversion method for my old Octave 4.0 (no rgb2gray):
im=imread('rgb.jpeg');
[imInd,Ind]=rgb2ind(im);
imGray16=ind2gray(imInd,Ind); imwrite(imGray16,'gray16b.png');
imGray8=uint8(imGray16/256); imwrite(imGray8,'gray8b.png');
I am using the Octave installation that is part of Cygwin. However, the laptop I use has limited user rights, and upgrading Octave requires phenomenal amounts of time.

Answering your question, you can't set BitDepth when calling imwrite. The function will write an image with the data type of the variable (provided that the image file type supports it).
If you really need arbitrary bit depth control when writing the file, you would need to interact with libpng directly, that is, write your own oct function.
However, there's a few things about your comments:
the issue of converting from uint16 -> uint8 and getting more than half the size, I'm guessing is because the image is compressed.
rgb2ind does nor convert to uint16 by default. It will convert to uint8 or uint16 depending on the number of unique colours in your image.
the function rgb2gray is part of the image package. Load that package if you want that function.

Related

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.

Scan an image for certain colors, convert to an integer array

So I recently obtained an 8x8 bi-color LED array for my arduino kit, and I want to be able to read an image file for certain RGB values at certain coordinates, to create a 2d int array, with the ints corresponding to certain RGB values. for instance, since my array can display 3 different colors, i could define three different RGB values to read from the image in the code. then i'd have it read the image, make a 2d int array by the dimensions of the image, store ints 1-3 in the array where the corresponding RGB values were found.
i was going to try and find a C library for it but I think that arduino is a separate language, I'm not sure.
I did similar stuff for my Blinkenlight Experiments. Especially for the POV experiments. You might want to have a look at my Python code for converting images to Arduino Programms here: http://blog.blinkenlight.net/experiments/basic-effects/pov-generator/.
Another easy way to convert images to C code is to use "The Gimp". The Gimp supports "save as C source code" and "save as C header".
Just for completeness: Arduino is not a separate language. Arduino is C++ with some IDE preprocessing that tries to hide the fact that you actually code C++.

Create and write paletted RGBA PNG using NSImage

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.

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 does the d3dx library save textures to files?

When using the function: D3DXSaveTextureToFile and passing in D3DXIFF_BMP to create a bmp I've noticed that the values seem to be estimated rather than given specifically.
Correct me if I'm wrong but a floating point texture can store any float in any given texel which would put it outside the range of a BMP which is stuck between rgb(255,255,255,255), so what it seems that the function is doing is simply taking the upper most and lowermost value of the texture and normalizing it between that range.
So my question is: Is it possible to grab the values exactly as they are in memory? including when the colours are outside of the spectruc of the computer monitor?
Don't use BMP. Use a format that supports the data type you want. For DX textures, it seems the D3DXIFF_PFM format is what you need. It's described like so:
Portable float map format. A raw
floating point image format, without
any compression. The file header
specifies image width, height,
monochrome or color, and machine word
order. Pixel data is stored as 32-bit
floating point values, with 3 values
per pixel for color, and one value per
pixel for monochrome.
Note that images will be large, though. A 256x256 texture in this format should weigh in at around 768 KB.
Updates: You should be able to use Image Magick's display command to view images in this format. Also HDRView supports the PFM format. A third choice might be fv.

Resources