suresh
suresh

Reputation: 177

How to duplicate image using BitmapData

I had a situation to duplicate an image with the help of bitmap data, below is the code i used to do the same, am I wrong anywhere, please help me.. Try drawing this image https://i.sstatic.net/VCSoQ.png in the bmp format

private void button1_Click(object sender, EventArgs e)
{
Bitmap mask = Image.FromFile("../../Data/mask.bmp") as Bitmap;
BitmapData data = mask.LockBits(new Rectangle(0, 0, mask.Width, mask.Height), ImageLockMode.ReadWrite, mask.PixelFormat);
int bytes = Math.Abs(data.Stride) * mask.Height;
byte[] outPut = new byte[bytes];
Marshal.Copy(data.Scan0, outPut, 0, bytes);

Bitmap test = new Bitmap(mask.Width, mask.Height, mask.PixelFormat);
BitmapData testData = test.LockBits(new Rectangle(0, 0, test.Width, test.Height),
ImageLockMode.ReadWrite, test.PixelFormat);
Marshal.Copy(outPut, 0, testData.Scan0, bytes);
test.UnlockBits(testData);
test.Save("test.jpg");
}

Thanks, Suresh

Upvotes: 1

Views: 7208

Answers (3)

Luke Dupin
Luke Dupin

Reputation: 2305

If you're willing to use P/Invoke, this can be done with a single copy.

class MyClass
{
  [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
  public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);

  Bitmap _frame = null;
  BitmapData _dest = null;

  void Reinit( int width, int height, PixelFormat format )
  {
    if ( _frame != null )
    {
      _frame.Unlock(_dest);
      _frame.Dispose();
    }

    _frame = new Bitmap( width, height, format );
    _dest = _frame.LockBits( new Rectangle( 0, 0, _frame.Width, _frame.Height ), ImageLockMode.ReadWrite, _frame.PixelFormat );
  }

  void CloneBitmapData( BitmapData src )
  {
    if ( _dest == null || _dest.Width != src.Width || _dest.Height != src.Height )
      Reinit( src.Width, src.Height, src.PixelFormat );

    CopyMemory( _dest.Scan0, src.Scan0, (uint)(src.Stride * src.Height) );
  }

Upvotes: 0

suresh
suresh

Reputation: 177

There is problem in getting the color palette of the image through BitmapData, on replacing the color palette of the new image with the old, we could get the same image.

Bitmap mask = Image.FromFile("../../Data/mask.bmp") as Bitmap;
        BitmapData data = mask.LockBits(new Rectangle(0, 0, (int)mask.PhysicalDimension.Width, (int)mask.PhysicalDimension.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
        int bytes = Math.Abs(data.Stride) * mask.Height;            
        byte[] outPut = new byte[bytes];
        Marshal.Copy(data.Scan0, outPut, 0, bytes);
        Marshal.Copy(outPut, 0, data.Scan0, bytes);
        mask.UnlockBits(data);

        Bitmap test = new Bitmap(mask.Width, mask.Height, PixelFormat.Format8bppIndexed);
        test.Palette = mask.Palette;
        BitmapData testData = test.LockBits(new Rectangle(0, 0, mask.Width, mask.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
        Marshal.Copy(outPut, 0, testData.Scan0, bytes);
        test.UnlockBits(data);
        test.Save("test.jpg");

Upvotes: 2

user1027167
user1027167

Reputation: 4458

with the example on http://msdn.microsoft.com/de-de/library/5ey6h79d.aspx you should get it.

    private void CopyImage()
    {

        // Create a new bitmap.
        Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");

        // Lock the bitmap's bits.  
        Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        System.Drawing.Imaging.BitmapData bmpData =
            bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
            bmp.PixelFormat);

        // Get the address of the first line.
        IntPtr ptr = bmpData.Scan0;

        // Declare an array to hold the bytes of the bitmap.
        int bytes  = Math.Abs(bmpData.Stride) * bmp.Height;
        byte[] rgbValues = new byte[bytes];

        // Copy the RGB values into the array.
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

        // Set every third value to 255. A 24bpp bitmap will look red.  
        //for (int counter = 2; counter < rgbValues.Length; counter += 3)
        //    rgbValues[counter] = 255;

        // Copy the RGB values back to the bitmap
        System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);

        // Unlock the bits.
        bmp.UnlockBits(bmpData);

        // Draw the modified image.
        //e.Graphics.DrawImage(bmp, 0, 150);

        bmp.Save("c:\\fakePhotoCopy.jpg");

    }

Upvotes: 1

Related Questions