Что делает LockBits / UnlockBits в c#? - PullRequest
0 голосов
/ 21 января 2020

У меня есть метод в c#, который использует только LockBits, а затем UnlockBits, и изображения (вход / выход, преобразованные в байтовые массивы) различны. Один из выходных данных имеет менее 100 с чем-то байтов, чем один из входных данных. Это происходит только с файлами .jpg. И, проверяя файлы в HxD, я понял, что он удаляет часть заголовка, точнее, подпись exif. Но я не знаю, как и почему.

Кто-то знает, что это делает?

Вот код:

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;
}

Ответы [ 2 ]

3 голосов
/ 21 января 2020

Вызов Bitmap.LockBits() с последующим Bitmap.UnlockBits() ничего не делает .

Наблюдаемое вами поведение связано с загрузкой изображения JPEG и последующим его сохранением. JPEG использует алгоритм с потерями. Итак, что происходит:

  1. Вы загружаете JPEG с диска
  2. Данные JPEG декодируются в отдельные пиксели с информацией о цвете, т.е. с битовой картой
  3. Вы сохраняете битовую карту снова в формате JPEG, в результате чего файл будет отличаться от # 1

При этом вы также можете потерять метаданные, которые присутствовали в файле JPEG. Так что да, файл отличается и, вероятно, меньше, потому что каждый раз, когда вы делаете это, вы теряете некоторые данные или метаданные пикселей.

Блокировки / Разблокировки используются, чтобы позволить программе манипулировать данными изображения в памяти. Ни больше ни меньше. См. Также документацию для этих методов .

0 голосов
/ 21 января 2020

Используйте метод LockBits, чтобы заблокировать существующее растровое изображение в системной памяти, чтобы его можно было изменить программно. Вы можете изменить цвет изображения с помощью метода SetPixel, хотя метод LockBits обеспечивает лучшую производительность для крупномасштабных изменений. Структура Rectangle, указывающая часть растрового изображения для блокировки.

Пример: 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);

}    
...