Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi!
I´m trying to edit 16 bit image data but I can´t access the full 16 bit of each pixel.
The following code is working flawlessly with 8 bit images.

private void ImageEditing()
{            
    //opening a 8 bit per pixel jpg image
    Bitmap bmp = new Bitmap("Image.jpg");

    int Width = bmp.Width;
    int Height = bmp.Height;

    //creating the bitmapdata and lock bits
    System.Drawing.Rectangle rec = new System.Drawing.Rectangle(0, 0, Width, Height);
    BitmapData bmd = bmp.LockBits(rec, ImageLockMode.ReadOnly, bmp.PixelFormat);

    unsafe
    {
        //iterating through all the pixels in y direction
        for (int y = 0; y < Height; y++)
        {
            //getting the pixels of current row
            byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride);

            //iterating through all the pixels in x direction
            for (int x = 0; x < Width; x++)
            {
                //getting index of current pixel (3 because of the 3 * 8bits per pixel)
                int index = x * 3;

                //getting R, G and B values
                byte R = row[index + 2];
                byte G = row[index + 1];
                byte B = row[index];
            }
        }
    }

    //unlocking bits and disposing image
    bmp.UnlockBits(bmd);
    bmp.Dispose();
}


If I want to adapt it to 16 bit and replace bytes with ushorts(unsigned 16 bit integer) and also open a 16 bit image it compiles but I get an AccesViolationException somewhere in the middle of the picture.

Any ideas what I did wrong or are there any different approches?

I couldn´t find anything here or with google except some article on how to display Raw image data which doesn´t help me in this case as I don´t have that.

I hope you guys can help
Johannes
Posted
Updated 15-Oct-12 23:22pm
v2

The code is basically correct, but it cannot universally work, just because all your shifts will depends on pixel format, which you never use. You only transparently pass bmp.PixelFormat as a parameter to a new bitmap. The code cannot work correctly unless you analyze the value of System.Drawing.PixelFormat (you might need to use if or switch) and shift your pointer arithmetic accordingly. Please see:
http://msdn.microsoft.com/en-us/library/system.drawing.image.pixelformat.aspx[^],
http://msdn.microsoft.com/en-us/library/system.drawing.imaging.pixelformat.aspx[^].

—SA
 
Share this answer
 
Comments
Johannes Bildstein 16-Oct-12 4:15am    
Hi Sergey, thanks for your help!
I am aware of the Pixelformat and in my universal code I do use it.
But in this case, if I change from byte to ushort I still have a pixelsize of 3 if I´m not wrong.
Sergey Alexandrovich Kryukov 16-Oct-12 12:22pm    
You see, absolutely regardless of concrete calculations: if you have some bitmap calculations for one Bits-Per-Pixel format, and try to use the same code to different amount of pixels, that code would not do the same thing, unless it has "switch" or "if" branches with shifting bits by different step per pixel, depending on the value of this enumerator, not matter what else you do. Isn't that logical?
--SA
Johannes Bildstein 16-Oct-12 16:53pm    
Hi Sergey,
as I said, in my universal code I do switch between the various pixelformats.
This is just a simplified version only for 8bit images without alpha channel.
I also have found the solution by now and posted it here.
if I change the code from byte to ushort and then only take one row with BitmapData.Stride/2 it works. because this stride value is calculated in bytes and I use ushorts it´s only half the length.
And that´s where the AccessViolation happened, I simply used a too long row.
Sergey Alexandrovich Kryukov 16-Oct-12 16:59pm    
Well, then I don't know what's the problem. If you are showing a simplified version, but the essence of the problem is in full version... what sense it should make?
What you say now sounds like a correct solution.
--SA
Johannes Bildstein 16-Oct-12 17:03pm    
the problem also occurred in the simplified version otherwise it wouldn´t have made much sense...
and the solution is correct as I successfully tested it
I finally found the solution!
Because I changed the row from byte to ushort the row has only half the length.

so for a 16 bit image the code would look like this:

private void ImageEditing()
{            
    //opening a 16 bit per pixel tif image
    Bitmap bmp = new Bitmap("Image.tif");
 
    int Width = bmp.Width;
    int Height = bmp.Height;
 
    //creating the bitmapdata and lock bits
    System.Drawing.Rectangle rec = new System.Drawing.Rectangle(0, 0, Width, Height);
    BitmapData bmd = bmp.LockBits(rec, ImageLockMode.ReadOnly, bmp.PixelFormat);
 
    unsafe
    {
        //iterating through all the pixels in y direction
        for (int y = 0; y < Height; y++)
        {
            //getting the pixels of current row
            ushort* row = (ushort*)bmd.Scan0 + (y * bmd.Stride / 2);
 
            //iterating through all the pixels in x direction
            for (int x = 0; x < Width; x++)
            {
                //getting index of current pixel (3 because of the 3 * 16bits per pixel)
                int index = x * 3;
 
                //getting R, G and B values
                ushort R = row[index + 2];
                ushort G = row[index + 1];
                ushort B = row[index];
            }
        }
    }
 
    //unlocking bits and disposing image
    bmp.UnlockBits(bmd);
    bmp.Dispose();
}
 
Share this answer
 
Comments
Nitesh Thakur 2-Jun-18 3:37am    
How we can write data without unsafe with ushort for creating bitmap

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900