3
votes

It is my first question to post. So please be kind to me, however comments on how to improve my questioning to improve readability are more than welcome.

I try to rotate an array of shorts using graphics.

I read an array of shorts to an image, rotate it using graphics and then store it back in an array of shorts. However I encountered that the graphics handler was not working as expected so i stripped my code to and it looked like this:

It first copies for example a simple array of shorts (source48) to the src Bitmap using Marshal.Copy().

   short[] source48= new short[]{255,255,255,2,2,2,5,5,5];
   int srcCols=3,int srcRows=1;
   Drawing.Bitmap srcImage = new Drawing.Bitmap(srcCols,srcRows, System.Drawing.Imaging.PixelFormat.Format48bppRgb);   
   System.Drawing.Imaging.BitmapData data = srcImage.LockBits(
                new Drawing.Rectangle(0, 0, srcCols, srcRows),
                System.Drawing.Imaging.ImageLockMode.WriteOnly,
                System.Drawing.Imaging.PixelFormat.Format48bppRgb);
   // Copy the source buffer to the bitmap
   Marshal.Copy(source48, 0, data.Scan0, source48.Length);
   // Unlock the bitmap of the input image again.
   srcImage.UnlockBits(data);
   data = null;             

than it creates a new bitmap "rotatedImage" and fills the "rotatedImage" with the "srcImage" using graphics (I skip the actual rotation for now)

  Drawing.Bitmap rotatedImage = new drawing.Bitmap(srcCols,srcRows,System.Drawing.Imaging.PixelFormat.Format48bppRgb);
  rotatedImage.SetResolution(srcImage.HorizontalResolution, srcImage.VerticalResolution);
  using (Drawing.Graphics g = Drawing.Graphics.FromImage(rotatedImage))
  {
        g.Clear(Drawing.Color.Black);
        g.DrawImage(srcImage, 0, 0);
  }

Then I read from the "rotated"Image the rawData.

 data = rotatedImage.LockBits(
                new Drawing.Rectangle(0, 0, srcCols, srcRows),
                System.Drawing.Imaging.ImageLockMode.ReadOnly,
                System.Drawing.Imaging.PixelFormat.Format48bppRgb);
 // Copy the bulk from the output image bitmap to a 48bppRGB buffer
 short[] destination48 = new short[9];
 Marshal.Copy(data.Scan0, destination48, 0, destination48.Length);

Unfortunately i find that destination48 is filled with {252,252,252,2,2,2,5,5,5]; instead of the expected:[255,255,255,2,2,2,5,5,5].

I have tried to fill the background, draw an rectangle etc. I really have no clue what could be the reason that the data in the destination bitmap does not contain the data from the source image. Is the accuracy of the graphics compromised?

1
What if you save the Bitmap first and inspect the image? - Jeroen van Langen
also, Format48bppRgb * srcCols * srcRows != sizeof(short) * srcCols * srcRows - Jeroen van Langen
Marshall.copy requires size in bytes. Try destination.lengrh * sizeof (short) - Jeroen van Langen
@JeroenvanLangen If I try that I get an out of range exception. Still finding some undefined behaviour. If I change the array of short to: [1,0,0,2,0,0,3,0,0,4,0,0,5,0,0,6,0,0] and srcRows=3 & src columns=2. The result is [0 0 0 2 0 0 2 0 0 0 0 0 5 0 0 5 0 0]. I am confused right now. - Deltadaniel

1 Answers

0
votes

On the MSDN, there is a comment stating that:

PixelFormat48bppRGB, PixelFormat64bppARGB, and PixelFormat64bppPARGB use 16 bits per color component (channel). GDI+ version 1.0 and 1.1 can read 16-bits-per-channel images, but such images are converted to an 8-bits-per-channel format for processing, displaying, and saving. Each 16-bit color channel can hold a value in the range 0 through 2^13.

I bet this is what's causing the loss of accuracy here.

Perhaps you could choose Format24bppRgb and use two pixels per short; it seems to return the correct results for your example, when also setting srcCols to double its value.