2016-07-31 2 views
-1

다음 두 가지 루틴을 고려하십시오.int [,] 변환의 비트 맵

//Tested 
    ///Working fine. 
    public static Bitmap ToBitmap(int [,] image) 
    { 
     int Width = image.GetLength(0); 
     int Height = image.GetLength(1); 
     int i, j; 
     Bitmap bitmap = new Bitmap(Width, Height); 
     BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), 
           ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 
     unsafe 
     { 
      byte* address = (byte*)bitmapData.Scan0; 

      for (i = 0; i < bitmapData.Height; i++) 
      { 
       for (j = 0; j < bitmapData.Width; j++) 
       { 
        // write the logic implementation here 
        address[0] = (byte)image[j, i]; 
        address[1] = (byte)image[j, i]; 
        address[2] = (byte)image[j, i]; 
        address[3] = (byte)255; 
        //4 bytes per pixel 
        address += 4; 
       }//end for j 

       //4 bytes per pixel 
       address += (bitmapData.Stride - (bitmapData.Width * 4)); 
      }//end for i 
     }//end unsafe 
     bitmap.UnlockBits(bitmapData); 
     return bitmap;// col; 
    } 

    //Tested 
    ///Working fine. 
    public static int[,] ToInteger(Bitmap bitmap) 
    { 
     int[,] array2D = new int[bitmap.Width, bitmap.Height]; 

     BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), 
               ImageLockMode.ReadWrite, 
               PixelFormat.Format32bppRgb); 

     unsafe 
     { 
      byte* address = (byte*)bitmapData.Scan0; 

      int paddingOffset = bitmapData.Stride - (bitmap.Width * 4);//4 bytes per pixel 

      for (int i = 0; i < bitmap.Width; i++) 
      { 
       for (int j = 0; j < bitmap.Height; j++) 
       { 
        byte[] temp = new byte[4]; 
        temp[0] = address[0]; 
        temp[1] = address[1]; 
        temp[2] = address[2]; 
        temp[3] = address[3]; 

        array2D[j, i] = BitConverter.ToInt32(temp, 0); 

        //4-bytes per pixel 
        address += 4;//4-channels 
       } 
       address += paddingOffset; 
      } 
     } 
     bitmap.UnlockBits(bitmapData); 

     return array2D; 
    } 

이 두 루틴은 32bpp 이미지에 잘 작동합니다. 이러한 루틴은 픽셀 형식이 PixelFormat.Format32bpp으로 설정된 경우에만 작동합니다. PixelFormat.Format8bppIndexed을 사용하면 예외가 발생합니다. 나는 32 비트 Bitmap이하는 것을 그레이 스케일에게 int[,]가 다시 변환 될 때마다 변환해야합니다 (또한, 내가 byte 때문에 주소 계산 문제의 int 사이의 원활한 전환을 달성 할 수있다) 그 예외를 방지하기 위해

Bitmap에 이 문제를 해결하고 싶습니다.

 Bitmap grayscale = Grayscale.ToGrayscale(InputImage); 

     //Here, the Bitmap is treated as a 32bit image 
     //to avoid the exception eventhough it is already 
     //an 8bpp grayscale image. 
     int[,] i1 = ImageDataConverter.ToInteger(grayscale); 

     Complex[,] comp = ImageDataConverter.ToComplex(i1); 

     int[,] i2 = ImageDataConverter.ToInteger(comp); 

     Bitmap b2 = ImageDataConverter.ToBitmap(i2); 

     //It is already a Grayscale image. 
     //But, the problem is, b2.PixelFormat is set to 
     //PixelFormat.Formap32bpp because of those routines. 
     //Hence the unnecessay conversion. 
     b2 = Grayscale.ToGrayscale(b2); 

8bpp 색인화 된 (회색 음영) 이미지에서만 작동하도록 수정해야합니다.

어떻게하면됩니까?

+0

무슨 작업을 원하는가 : 이미지를 저장하면 반대 논리를 수행해야합니다? 'int [,]'대신'byte [,]'를 전달할 수 있기를 원하십니까? 그렇지 않다면, int [,]는 어떻게 해석 될 것인가? 각 32 비트 값은 0에서 255 사이의 값을 저장하나요? 당신이 글을 쓸 때 색인이 실제로 만들어 집니까? 그렇다면 어떤 팔레트를 사용해야합니까? 아니면 그들이 정말로 회색 음영입니까? 각 32 비트 값에 4 개의 픽셀이 압축됩니까? 어느 쪽이든, 8 비트 값은 어떻게 해석 될까요? 32bpp 이미지를 출력 하시겠습니까, 아니면 출력도 8bpp이어야합니까? 사양의 모든 중요한 부분을 거의 생략했습니다. –

답변

0
public static int[,] ToInteger(Bitmap bitmap) 
{ 
    int[,] array2D = new int[bitmap.Width, bitmap.Height]; 

    BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), 
              ImageLockMode.ReadWrite, 
              PixelFormat.Format8bppIndexed); 
    int bytesPerPixel = sizeof(byte); 

    unsafe 
    { 
     byte* address = (byte*)bitmapData.Scan0; 

     int paddingOffset = bitmapData.Stride - (bitmap.Width * bytesPerPixel); 

     for (int i = 0; i < bitmap.Width; i++) 
     { 
      for (int j = 0; j < bitmap.Height; j++) 
      { 
       byte[] temp = new byte[bytesPerPixel]; 

       for (int k = 0; k < bytesPerPixel; k++) 
       { 
        temp[k] = address[k]; 
       } 

       int iii = 0; 

       if (bytesPerPixel >= sizeof(int)) 
       { 
        iii = BitConverter.ToInt32(temp, 0); 
       } 
       else 
       { 
        iii = (int)temp[0]; 
       } 

       array2D[j, i] = iii; 

       address += bytesPerPixel; 
      } 
      address += paddingOffset; 
     } 
    } 
    bitmap.UnlockBits(bitmapData); 

    return array2D; 
} 

public static Bitmap ToBitmap(int[,] image) 
{ 
    int Width = image.GetLength(0); 
    int Height = image.GetLength(1); 
    int i, j; 

    Bitmap bitmap = new Bitmap(Width, Height, PixelFormat.Format8bppIndexed); 

    BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), 
          ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); 

    int bytesPerPixel = sizeof(byte); 

    unsafe 
    { 
     byte* address = (byte*)bitmapData.Scan0; 

     for (i = 0; i < bitmapData.Height; i++) 
     { 
      for (j = 0; j < bitmapData.Width; j++) 
      { 
       byte[] bytes = BitConverter.GetBytes(image[j, i]); 

       for (int k = 0; k < bytesPerPixel; k++) 
       { 
        address[k] = bytes[k]; 
       } 

       address += bytesPerPixel; 
      } 

      address += (bitmapData.Stride - (bitmapData.Width * bytesPerPixel)); 
     } 
    } 
    bitmap.UnlockBits(bitmapData); 

    Grayscale.SetGrayscalePalette(bitmap); 

    return bitmap; 
} 
+0

설명이 약간 유용 할 것입니다. – TheLethalCoder

1

인덱싱 된 비트 맵을 처리하려면 이미지의 각 바이트를 읽고 팔레트에서 색상을 찾아야합니다.

public static Bitmap ToBitmap(int[,] image) 
{ 
    int width = image.GetLength(0); 
    int height = image.GetLength(1); 
    Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed); 
    BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), 
           ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); 
    int stride = bitmapData.Stride; 

    // A dictionary of colors to their index values 
    Dictionary<int, int> palette = new Dictionary<int, int>(); 
    // A flat list of colors 
    List<Color> paletteList = new List<Color>(); 

    unsafe 
    { 
     byte* address = (byte*)bitmapData.Scan0; 

     for (int x = 0; x < width; x++) 
     { 
      for (int y = 0; y < height; y++) 
      { 
       // Get the color from the Bitmap 
       int color = image[x, y]; 
       if (!palette.ContainsKey(color)) 
       { 
        // This color isn't in the palette, go ahead and add it 
        palette.Add(color, palette.Count); 
        paletteList.Add(Color.FromArgb(color)); 
        if (palette.Count >= 256) 
        { 
         // The palette is too big. Ideally this function would 
         // dither some pixels so it could handle this condition 
         // but that would make this example overly complicated 
         throw new InvalidOperationException("Too many colors in image"); 
        } 
       } 

       // And lookup the index of the color in the palette and 
       // add it to the BitmapData's memory 
       address[stride * y + x] = (byte)palette[color]; 
      } 
     } 
    } 

    bitmap.UnlockBits(bitmapData); 

    // Each time you call Bitmap.Palette it actually returns 
    // a Clone of the object, so we need to ask for a cloned 
    // copy here. 
    var newPalette = bitmap.Palette; 

    // For each one of our colors, add it to the palette object 
    for (int i = 0; i < paletteList.Count; i++) 
    { 
     newPalette.Entries[i] = paletteList[i]; 
    } 

    // And since this is a clone, assign it back to the bitmap 
    // so it'll take effect. 
    bitmap.Palette = newPalette; 

    return bitmap; 
} 

public static int[,] ToInteger(Bitmap bitmap) 
{ 
    if (bitmap.Palette.Entries.Length == 0) 
    { 
     // This doesn't appear to have a palette, so this operation doesn't 
     // make sense 
     throw new InvalidOperationException("bitmap is not an indexed bitmap"); 
    } 

    int width = bitmap.Width; 
    int height = bitmap.Height; 
    int[,] array2D = new int[width, height]; 

    BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), 
               ImageLockMode.ReadOnly, 
               PixelFormat.Format8bppIndexed); 

    unsafe 
    { 
     // Pull out the stride to prevent asking for it many times 
     int stride = bitmapData.Stride; 
     byte* address = (byte*)bitmapData.Scan0; 

     for (int x = 0; x < width; x++) 
     { 
      for (int y = 0; y < height; y++) 
      { 
       // Lookup the color based off the pixel, and set it's value 
       // to the return array 
       array2D[x, y] = bitmap.Palette.Entries[address[stride * y + x]].ToArgb(); 
      } 
     } 
    } 

    bitmap.UnlockBits(bitmapData); 

    return array2D; 
} 
+0

매우 느립니다! 실행하는 데 오랜 시간이 걸립니다. – anonymous

+1

예. 나는 당신의 쟁점에 대한 과정과 해결책을 보여 주려고 노력했지만, 가능한 가장 좋은 해결책을 제시하지는 못했습니다. –