비트 맵을 바이트 배열로 변환


233

C #을 사용하면 임시 파일로 저장하고 ?를 사용하여 결과를 읽는 것보다 Windows Bitmap를 변환하는 더 좋은 방법 byte[]FileStream있습니까?

답변:


418

몇 가지 방법이 있습니다.

ImageConverter

public static byte[] ImageToByte(Image img)
{
    ImageConverter converter = new ImageConverter();
    return (byte[])converter.ConvertTo(img, typeof(byte[]));
}

많은 코드가 필요하지 않기 때문에 편리합니다.

메모리 스트림

public static byte[] ImageToByte2(Image img)
{
    using (var stream = new MemoryStream())
    {
        img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
        return stream.ToArray();
    }
}

이것은 파일이 디스크 대신 메모리에 저장된다는 점을 제외하고는 현재 수행중인 작업과 동일합니다. 더 많은 코드가 있지만 ImageFormat 옵션이 있으며 메모리 또는 디스크에 저장하는 사이에 쉽게 수정할 수 있습니다.

출처 : http://www.vcskicks.com/image-to-byte.php


2
또한 중간
메모리

4
ImageConverter방법을 사용하면 이미지가 Png로 저장되어 거대한 파일이 생성됩니다.
skolima

8
'using'을 사용할 때 스트림을 닫을 필요가 없습니다
LastTribunal

2
아무도이 배열의 구조에 대해 조금 더 많은 정보를 줄 수 있습니까? x = 0으로 시작하고 모든 y를 순환 한 다음 x를 증분합니까? 그런 다음 [0,0,1,1,1,1,0,0,1,1]?
Raymond Timmermans

1
ImageConverter.net 표준이 아님MemoryStream
Alexandre

95

MemoryStream을은 이 도움이 될 수 있습니다. 확장 방법으로 넣을 수 있습니다.

public static class ImageExtensions
{
    public static byte[] ToByteArray(this Image image, ImageFormat format)
    {
        using(MemoryStream ms = new MemoryStream())
        {
            image.Save(ms, format);
            return ms.ToArray();
        }
    }
}

다음과 같이 사용할 수 있습니다.

var image = new Bitmap(10, 10);
// Draw your image
byte[] arr = image.ToByteArray(ImageFormat.Bmp);

ImageConverter와 관련하여 prestomanifto의 답변에 부분적으로 동의하지 않습니다. ImageConverter를 사용하지 마십시오. 기술적으로 잘못된 것은 없지만 객체에서 boxing / unboxing을 사용한다는 사실은 .NET 프레임 워크의 오래된 어두운 곳에서 가져온 코드이며 이미지 처리에 사용하기에는 이상적이지 않다는 것을 나타냅니다 (바이트로 변환하기에는 너무 과도합니다) [] 적어도), 특히 다음을 고려할 때.

ImageConverter.Net 프레임 워크에서 사용 하는 코드를 살펴 보았으며 내부적으로 위에서 제공 한 코드와 거의 동일한 코드를 사용합니다. 새로운을 생성하고 제공했을 때의 형식으로 MemoryStream저장 Bitmap하고 배열을 반환합니다. 다음 ImageConverter을 사용하여 클래스 를 만드는 추가 오버 헤드를 건너 뜁니다.MemoryStream


아름다운. 그거야! 그래도 MemoryStream을 처분하고 싶을 것입니다.
Jeremy McGee

선택한 답변에서 알 수 있듯이 ImageConverter를 사용하지 않는 이유와 폐기 추가에 대한 토론으로 답변을 업데이트했습니다.
Christopher Currens

확장 방법을 잘 사용하면 마음에 들어요!
Dude Pascalou

3
ImageConverter를 조사하고 연구 결과를보고 한 +1 그러나 나는 당신이 발견 한 것이 "ImageConverter를 사용하지 마십시오"라는 진술을 보증한다고 생각하지 않습니다. 예를 들어 이미지 해상도 (dpi) 설정과 같이 바이트 배열에서 이미지까지 다른 방식으로 유용한 서비스를 제공합니다. "ImageConverter 클래스를 만드는 데 드는 추가 오버 헤드"는 무시할만한 수준이며 사용 횟수에 관계없이 한 번만 수행하면됩니다.
RenniePet

1
ImageConverter가 이미지의 유형을 자동으로 결정할 수 있다는 점에서 ImageConverter도 유용하다는 것을 알았습니다. 예를 들어 이미지의 바이트 배열이 있지만 형식을 모르는 경우 헤더를 읽고 힌트를 얻을 수는 있지만, 글쎄 ... ... (Image img = (Image) myImgConverter.ConvertFrom (byteImage))를 사용하고 img.PixelFormat 등을 확인하는 것이 훨씬 쉽습니다.-물론 원하는 작업에 따라
hello_earth

45

비트 맵 데이터를 복사 할 수도 있습니다. 중간 메모리 스트림 등이 없으며 빠른 메모리 사본. 24 비트 및 32 비트 비트 맵 모두에서 작동합니다.

public static byte[] BitmapToByteArray(Bitmap bitmap)
{

    BitmapData bmpdata = null;

    try
    {
        bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
        int numbytes = bmpdata.Stride * bitmap.Height;
        byte[] bytedata = new byte[numbytes];
        IntPtr ptr = bmpdata.Scan0;

        Marshal.Copy(ptr, bytedata, 0, numbytes);

        return bytedata;
    }
    finally
    {
        if (bmpdata != null)
            bitmap.UnlockBits(bmpdata);
    }

}

.


1
안녕하세요,이 방법을 사용했지만이 바이트 배열을 이미지로 다시 변환 할 수 없습니다. 비트 맵 비트 맵 1 = 새로운 비트 맵 (new MemoryStream (array)); 유효하지 않은 매개 변수의 예외가 발생합니다. 실수가 있습니까?
Howard

1
안녕하세요, 댓글 섹션이 너무 작아서 완전한 코드를 게시 할 수 없습니다. 가장 간단한 방법은 배열을 고정하는 것입니다. GCHandle handle = GCHandle.Alloc (bufferarray, GCHandleType.Pinned); 배열에 대한 포인터를 가져옵니다. IntPtr iptr = Marshal.UnsafeAddrOfPinnedArrayElement (bufferarray, 0); 그런 다음 IntPtr을 사용하여 새 비트 맵을 만듭니다. bitmap = new Bitmap (width, height, (width * 4), PixelFormat.Format32bppArgb, iptr); 그러나 비트 맵 형식에 적절한 비트 맵 생성 매개 변수를 사용해야합니다. 반드시 정리하십시오 : iptr = IntPtr.Zero; handle.Free ();
deegee

3
버그는 무엇입니까? 저를 포함한 많은 프로그래머들이이 코드 스타일을 사용하고 있으며 잘 작동합니다.
deegee

4
@ mini-me-비트 맵 보폭 대 비트 맵 폭을 찾는 것이 좋습니다. 이것은 내 코드의 버그가 아니며 Windows가 비트 맵을 처리하는 방법입니다. Stride는 각 줄 끝을 갖도록 메모리 정렬 및 성능을 위해 32 비트 경계에서 시작하기 위해 각 줄 끝 (폭)에 추가 데이터를 포함 할 수 있습니다.
deegee

3
버그가 아닙니다. msdn.microsoft.com/ko-kr/library/…
deegee

16

Image를 MemoryStream에 저장 한 다음 바이트 배열을 가져옵니다.

http://msdn.microsoft.com/en-us/library/ms142148.aspx

  Byte[] data;

  using (var memoryStream = new MemoryStream())
  {
    image.Save(memoryStream, ImageFormat.Bmp);

    data = memoryStream.ToArray();
  }

이미지에 저장 방법이 없습니다.
Prescott Chartier

@PrescottChartier 위의 예는 다음 형식에서 파생 된 것으로 가정합니다 System.Drawing.Image ( docs.microsoft.com/en-us/dotnet/api/… 참조 )
Chris Baxter

System.Drawing.Image does not exist. 그래서 .. 아니, 작동하지 않습니다 :(
Prescott Chartier

내가 여기서 뭘 하려는지 알 수 있습니다 : stackoverflow.com/questions/55084620/…
Prescott Chartier

10

다음과 같이를 MemoryStream대신 사용하십시오 FileStream.

MemoryStream ms = new MemoryStream();
bmp.Save (ms, ImageFormat.Jpeg);
byte[] bmpBytes = ms.ToArray();

아마 당신은 원하지 ToArray않을 것 GetBuffer입니다.
vcsjones

GetBuffer는 부호없는 바이트의 배열을 반환합니다 (바이트 배열)
Jeff Reddy

4
이미지의 일부가 아닌 필러 데이터를 가질 수 있습니다. 문서에서 : Note that the buffer contains allocated bytes which might be unused. For example, if the string "test" is written into the MemoryStream object, the length of the buffer returned from GetBuffer is 256, not 4, with 252 bytes unused. To obtain only the data in the buffer, use the ToArray method.이제 바이트 배열에서 GetBuffer이미지와 사용하지 않은 바이트를 반환하여 이미지가 손상 될 수 있습니다.
vcsjones

1
알아 둘만 한. 의견 vcs에 감사드립니다!
Jeff Reddy

이 방법은 기본 압축 설정을 사용하여 이미지를 jpeg로 저장하므로 이미지가 눈에 띄게 저하 될 수있는 압축 아티팩트가 발생합니다.
Richard Ev

8

다음을 시도하십시오 :

MemoryStream stream = new MemoryStream();
Bitmap bitmap = new Bitmap();
bitmap.Save(stream, ImageFormat.Jpeg);

byte[] byteArray = stream.GetBuffer();

다음을 사용 중인지 확인하십시오.

System.Drawing & using System.Drawing.Imaging;

1
이 방법은 기본 압축 설정을 사용하여 이미지를 jpeg로 저장하므로 이미지가 눈에 띄게 저하 될 수있는 압축 아티팩트가 발생합니다.
Richard Ev

다시 비트 맵에 저장 메소드가 없습니다.
Prescott Chartier 12

7

나는 당신이 단순히 할 수 있다고 믿습니다.

ImageConverter converter = new ImageConverter();
var bytes = (byte[])converter.ConvertTo(img, typeof(byte[]));

6
MemoryStream ms = new MemoryStream();
yourBitmap.Save(ms, ImageFormat.Bmp);
byte[] bitmapData = ms.ToArray();

5

더 단순하게:

return (byte[])System.ComponentModel.TypeDescriptor.GetConverter(pImagen).ConvertTo(pImagen, typeof(byte[]))

-3

한 줄로만 사용하면 매우 간단합니다.

byte[] imgdata = File.ReadAllBytes(@"C:\download.png");

op는이 옵션에 관심이 없다고 말했다
Mauro Sampietro
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.