jlnc
jlnc

Reputation: 41

What does LockBits/UnlockBits do in c#?

I have a method in c# that the only thing it does its LockBits, and then UnlockBits, and the images(input/output, transformed to byte arrays) are different. The one from output has less 100 and something bytes than the one from the input. This happens only with .jpg files. And checking the files in HxD I came to the understanding that it´s removing a part of the header, the exif signature to be exact. But I don't know how and why.

Does someone know what this is doing?

Here's the code:

public Image Validate (image){
  BitmapData original = null;
  Bitmap originalBMP = null;
  try{
     originalBMP = image as Bitmap;
     original = originalBMP.LockBits(new Rectangle(0, 0, 
        originalBMP.Width, originalBMP.Height),
        ImageLockMode.ReadWrite,
        originalBMP.PixelFormat);
     originalBMP.UnlockBits(original);
  }catch{}

  return image;
}

Upvotes: 2

Views: 3673

Answers (2)

Syed Munawar Hussain
Syed Munawar Hussain

Reputation: 39

Use the LockBits method to lock an existing bitmap in system memory so that it can be changed programmatically. You can change the color of an image with the SetPixel method, although the LockBits method offers better performance for large-scale changes. A Rectangle structure that specifies the portion of the Bitmap to lock.

Example: private void LockUnlockBitsExample(PaintEventArgs e) {

    // 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);

}    

Upvotes: 0

CodeCaster
CodeCaster

Reputation: 151664

Calling Bitmap.LockBits() followed by Bitmap.UnlockBits() does nothing.

The behavior you observe is because of loading a JPEG image, and then saving it again. JPEG uses a lossy algorithm. So what happens:

  1. You load the JPEG from disk
  2. The JPEG data gets decoded into individual pixels with color information, i.e. a bitmap
  3. You save the bitmap again in the JPEG format, resulting in a different file than #1

You also potentially lose metadata that was present in the JPEG file in doing so. So yes, the file is different and probably smaller, because every time you do this, you lose some pixel data or metadata.

Lockbits/Unlockbits are used to allow the program to manipulate the image data in memory. Nothing more, nothing less. See also the documentation for those methods.

Upvotes: 3

Related Questions