C++/C# Header of bgr32 bitmap - c#

To my understanding, the srgb32 is only a 24-bit color depth image with 8 bits of padding at the end.
ie, a blue pixel in little endian:
byte1_b = 255
byte2_g = 00
byte3_r = 00
byte4 = 00 //padding
What has got me confused is how should my headers look like to indicate this padded encoding. If I am not mistaken, simply setting the color depth to 32 won't work because that enables alpha channels. How should I encode this?
Edit. This is a project that is done both in C++ and C#. I am using WritableBitmap class to render a fractal image. But the actual image is drawn through the backend api in C++ using P/Invoke. Hence the title is C#/C++ to emphasize that I am working in these two environments.

I found the answer to my question albeit raising more questions. This Microsoft link describes that the high byte is ignored by default. I tested it out and the image seems unchanged regardless of the padded byte.

Related

Why is bmp loading faster than png

I have a sample wpf app here and wondering, why BMP is loading faster than PNG. Here is the exact setup:
- Windows 7
- Visual Studio 2013
- landscape.png, 1920x1080, 2.4mb
- landscape.bmp, 1920x1080, 5.6mb
- wpf-app, class MainWindow.xaml.cs constructor, no other code before
Code:
var sw = Stopwatch.StartNew();
var Bitmap1 = new Bitmap("landscape.bmp");
long t1 = sw.ElapsedMilliseconds;
sw.Restart();
var Bitmap2 = new Bitmap("landscape.png");
long t2 = sw.ElapsedMilliseconds;
So the BMP loads with around 6ms, the PNG needs 40ms.
Why is that so?
First, we need to understand how digital images are stored and shown, a digital image is represented as a matrix where each element of the matrix is the color of the pixel, if you have a grayscale image then each element is a uint8 (unsigned 8-bit integer) number between 0 and 255 and in some cases, it's an int8 (signed 8-bit integer) number between -128 and 127. if the element is 0 (or -128 in int8 version) the color is solid black and if the element is 255 (or 127 in int8 version) the color is solid white.
For RGB images each element of the said matrix takes 24 bit or 3 Byte to store (one Byte for each color), a very common resolution for digital cameras and smartphones is 3264 x 2448 for an 8-megapixel camera, now imagine we want to save a 3264 row matrix where each row has 2448 element and each element is 3 Byte, we need about 24 MegaByte to store that image which is not very efficient for posting on the internet or transferring or most of the other purposes. That is why we should compress the image, we can go for JPEG which is a lossy compression method and that means we do lose some quality or we can choose a lossless compression method like PNG which will give us less compression ratio but instead we are not gonna lose quality.
Whether we chose to compress the image or not, when we want to see the image, we can only show the uncompressed version of the image, if the image is not compressed at all, there is no problem, we show exactly what it is, but if it's compressed, we have to decode it first (uncompress it).
With all that being said, let's answer the question. BMP is a format for somewhat raw images, there is either no compression at all or much fewer compression techniques are used than PNG or JPEG but the file size is bigger. When you want to show a BMP image, because it's bigger, there is more data to read into memory, but when it is read, you can show it very faster because there is either no need for decoding or much less decoding is required, on the other hand when you want to show a PNG image, the image will be read into memory much faster but compared to BMP the decoding is going take more time.
If you have a very slow storage, BMP images will be shown slow.
If you have a very slow CPU or your decoding software is not efficient PNG images will be shown slow.

Kinect Infrared gray Pixelformat converting to 8bpp

Our goal is to make a movie from the Infrared images coming from the Kinect. We are using the AForge videowriter, we already have working code to work with a normal RGB stream. (RgbResolution640x480Fps30)
Looking at the documentation ( http://msdn.microsoft.com/en-us/library/microsoft.kinect.colorimageformat.aspx ) the image are in a 16 bits format, but only the first 10 are used? So do we have a 10 bits format image or how does this work?
Looking at the Aforge documentation only the following formats are accepted : 24 or 32 bpp image or grayscale 8 bpp (indexed) image. (http://www.aforgenet.com/framework/docs/html/84a560df-bfd5-e0d6-2812-f810b56a254d.htm)
Why are only 8 bpp indexed images accepted?
Is it possible to transform the 16 (10??) bit images from the Kinect to a 8 bpp indexed image
Or maybe allow AForge to accept 16 bit images as well
Thanks!
Kinect is supposed to produce depth or z with 11 bits of resolution packed in 16bit samples. To work around this problem you can divide the samples by 2^3=8, which would produce blunt results, or use a tone mapping technique like those used in HDR photography. This last one makes sense given the fact that Kinect doesn't have the same resolution for close by objects as for distant ones (see this StackOverflow question) so a non linear mapping can be used between the 11b samples and the 8b reduced resolution as explained in the OpenKinect Wiki.
On the Aforge, I'd say it'd be common to support 8bit gray, 24bit RGB (8bit per plane) and 32bit RGBA (8bit per plane).
AForge can convert to an 8 bit image for you:
Bitmap grayImage8bit = AForge.Imaging.Filters.Grayscale.CommonAlgorithms.BT709.Apply(original_bitmap);
I've been using this to convert 32 bit rgba bitmaps.

Convert 24 Bit BMP to Monochrome Bit in C#

How would I go about taking a BMP which is 24 bits and converting it to a Monochrome Bitmap? I am not concerned about losing colors, etc. and I do not want to use another file format.
There are basically two methods. You can use Interop methods to read the raw BMP data and write raw BMP data for a monchrome bitmap. There are googlable functions which will do this.
Or, better, you can use ImageMagickObject to convert the image using a stoichastic dither.
Do the second one.
If you do the first one, you should still use a stocichastic dither, but you will have to implement it by hand.
Edit: You asked "what do the following RGB values become"... the answer is they become what you want them to become. YOU DECIDE.
The obvious choices are to either use a strict threshold, where anything less than X becomes black, anything more becomes white, or you can use a stoichastic dither. Select two thresholds, black Threshold bt and white threshold wt, such that 0 < bt < wt < 255. Then for each point choose a random number q between 0.0. and 1.0. Compare the pixel brightness ((r+g+b)/3) to (q*(wt-bt)+bt). If it is greater or equal, it is white, if less, black. This will give you a nice dithered greyscale. For most purposes 31 and 224 are good values for bt and wt, but for photographic images 0 and 255 might be better.

24 bit data type array to hold 24 bit bitmap file

I am attempting to read a bitmap manually. So I read the bitmap file using a filestream. There wasn't a problem until I had to deal with 24 bit bitmap files. Is there a method to actually read a 24 bitmap image into a 24 bit array ?
I hold a 8 bit bitmap image in a byte array like this
byte[] fileBufferArray = new byte[fileLength];
A few options:
If you're not too worried about memory (you don't have a large number or very large bitmaps open), you can store it as 32-bit numbers instead. Often the fourth byte is then interpreted as "alpha" (a blending specifier when rendering the image on a background.) Most modern image manipulation libraries treat color images in this way now.
You can pack the colors into a byte array and access them individually. RGB and BGR are the two most common packing orders. Usually you also end up putting padding bytes at the end of each row so that the width in bytes lines up with DWORD (4-byte) boundaries.
You can split the image into three separate byte array 'planes', which are basically 8-bit images for Red, Green and Blue respectively. This is another common format when doing image processing, as often your filtering steps operate on channels independently.

XNA: Getting a struct as a texture to the GPU

I use XNA as a nice easy basis for some graphics processing I'm doing on the CPU, because it already provides a lot of the things I need. Currently, my "rendertarget" is an array of a custom Color struct I've written that consists of three floating point fields: R, G, B.
When I want to render this on screen, I manually convert this array to the Color struct that XNA provides (only 8 bits of precision per channel) by simply clamping the result within the byte range of 0-255. I then set this new array as the data of a Texture2D (it has a SurfaceFormat of SurfaceFormat.Color) and render the texture with a SpriteBatch.
What I'm looking for is a way to get rid of this translation process on the CPU and simply send my backbuffer directly to the GPU as some sort of texture, where I want to do some basic post-processing. And I really need a bit more precision than 8 bits there (not necessarily 32-bits, but since what I'm doing isn't GPU intensive, it can't hurt I guess).
How would I go about doing this?
I figured that if I gave Color an explicit size of 32 bytes (so 8 bytes padding, because my three channels only fill 24 bits) through StructLayout and set the SurfaceFormat of the texture that is rendered with the SpriteBatch to SurfaceFormat.Vector4 (32 bytes large) and filled the texture with SetData<Color> that it would maybe work. But I get this exception:
The type you are using for T in this method is an invalid size for this resource.
Is it possible to use any arbitrarily made up struct and interpret it as texture data in the GPU like you can with vertices through VertexDeclaration by specifying how it's laid out?
I think I have what I want by dumping the Color struct I made and using Vector4 for my color information. This works if the SurfaceFormat of the texture is also set to Vector4.

Categories

Resources