이미지를 바이트 배열로 변환하는 가장 빠른 방법


106

데스크톱 이미지를 캡처하여 압축하여 수신자에게 보내는 원격 데스크톱 공유 애플리케이션을 만들고 있습니다. 이미지를 압축하려면 byte []로 변환해야합니다.

현재 나는 이것을 사용하고 있습니다 :

public byte[] imageToByteArray(System.Drawing.Image imageIn)
{
    MemoryStream ms = new MemoryStream();
    imageIn.Save(ms,System.Drawing.Imaging.ImageFormat.Gif);
    return  ms.ToArray();
}

public Image byteArrayToImage(byte[] byteArrayIn)
{
     MemoryStream ms = new MemoryStream(byteArrayIn);
     Image returnImage = Image.FromStream(ms);
     return returnImage;
}

하지만 ImageFormat으로 저장해야하고 리소스를 소모하고 (Slow Down) 다른 압축 결과를 생성 할 수 있기 때문에 마음에 들지 않습니다. 그들을 이해하십시오.

그렇다면이 목표를 달성하는 다른 방법이 있습니까?


MemoryStream과 Image에는 모두 dispose 메서드가 있으므로 MemoryLeaks가 발생할 수 있으므로 Disposing인지 확인하십시오.
abc123

3
@ abc123 : 당신은 처분 할 필요가 없습니다 MemoryStream; 원격에서 사용하지 않는 한 완전히 관리되는 리소스입니다. 이 두 경우 모두 자원을 폐기하는 것은 부적절합니다.
Jon Skeet

1
@JonSkeet 흥미 롭군요, 당신은 그것에 대한 벤치 마크를 했습니까? .net이 개체를 해제하는 속도를 확인하려면? DataTable에 대한 비슷한 주장이 있지만 GarbageCollector가 처리를 사용할 때 할당 된 메모리를 수집하는 속도에는 눈에 띄는 차이가 있습니다.
abc123

@ abc123 : 나는 정말로 거기에 기대하지 않을 것입니다-스트림을 폐기해도 배열에 아무 일도하지 않으며 MemoryStream에는 종료자가 없습니다 (MarshalByValueComponent에서 상속하는 DataTable과 달리).
Jon Skeet

2
전체 소스 코드가 포함 된 최종 솔루션이 있습니까?
Kiquenet 2013

답변:


39

그렇다면이 목표를 달성하는 다른 방법이 있습니까?

당신이 바이트 배열로 이미지를 변환하기 위해 번호 당신이 바이트 배열로 텍스트를 변환 할 때 인코딩을 지정해야하는 것처럼 - 이미지 포맷을 지정할 수 있습니다.

압축 아티팩트가 걱정된다면 무손실 형식을 선택하세요. CPU 리소스가 걱정된다면 압축을 방해하지 않는 형식을 선택하세요. 예를 들어 원시 ARGB 픽셀 만 있습니다. 그러나 물론 그것은 더 큰 바이트 배열로 이어질 것입니다.

참고는 형식 선택하면 것을 않는 압축을 포함을하고 나중에 바이트 배열을 압축 아무 소용이 없다 -는 더 유익한 효과가없는 것은 거의 확실합니다.


12
'무손실 형식 선택'대신 imageIn.RawFormat추가로 인코딩하지 않고 원시 이미지 바이트를 저장하려는 시도를 선택할 수 있습니다 .
Chris F Carroll

52

이미지의 파일 형식을 반환하는 Image 매개 변수의 RawFormat 속성이 있습니다. 다음을 시도 할 수 있습니다.

// extension method
public static byte[] imageToByteArray(this System.Drawing.Image image)
{
    using(var ms = new MemoryStream())
    {
        image.Save(ms, image.RawFormat);
        return ms.ToArray();
    }
}

9
나도 MemoryStream을 폐기 또는 사용 () {} 문에이 방법의 몸을 감싸는 것을 권 해드립니다
Neil.Allen

@ Neil.Allen 내가 여기 새로 왔는데 이유를 말씀해 주시겠습니까?
Khalil Khalaf

3
@FirstStep 스스로 청소하기 때문에 :)
Sinaesthetic

@Sinaesthetic 내가 본다. 그리고 루틴은 내가 실행하려는 함수를 using () {}에 넣는 것입니다.
Khalil Khalaf

2
@FirstStep 정답이 아닙니다. 더 정확하게 : IDisposable을 구현 한 개체를 사용하는 경우 작업이 완료되면 Dispose ()를 호출하여 연결된 모든 리소스를 정리해야합니다. using () {} 문은 객체가 해당 문의 범위를 벗어날 때이를 호출합니다. 그래서 당신은 할 수 myObject.Dispose()있거나 using(myObject){}-둘 다 같은 일을 할 수 있지만 using 문은 기본적으로 당신을 위해 정리할 범위를 만듭니다.
Sinaesthetic

14

Jon Skeet이 지적한 이유로 큰 이득을 얻을 수 있을지 모르겠습니다. 그러나 TypeConvert.ConvertTo 메서드를 시도하고 벤치마킹하고 현재 메서드를 사용하는 것과 비교해 볼 수 있습니다.

ImageConverter converter = new ImageConverter();
byte[] imgArray = (byte[])converter.ConvertTo(imageIn, typeof(byte[]));

'System.Byte []'유형의 개체를 'System.Drawing.Image'유형으로 캐스팅 할 수 없습니다.
user123

14
public static byte[] ReadImageFile(string imageLocation)
    {
        byte[] imageData = null;
        FileInfo fileInfo = new FileInfo(imageLocation);
        long imageFileLength = fileInfo.Length;
        FileStream fs = new FileStream(imageLocation, FileMode.Open, FileAccess.Read);
        BinaryReader br = new BinaryReader(fs);
        imageData = br.ReadBytes((int)imageFileLength);
        return imageData;
    }

5
stackoverflow.com에 오신 것을 환영합니다. 위의 코드 샘플이 도움이되는 이유를 설명하는 세부 정보를 추가해 주시겠습니까? 완전히 이해하지 못하는 다른 SO 사용자를위한 것입니다 ... stackoverflow.com/help/how-to-answer
Mack

이것은 파일을 바이트로 변환하는 것이지만 OP는 그리기 객체를 바이트로 변환하기를 원했습니다. 그리기 개체는 반드시 파일 시스템이 아닌 데이터베이스에 바이트 배열로 저장 될 수 있으므로 앞뒤로 변환해야하지만 파일 스트림에서 바이트로 변환 할 파일이 아닙니다. 초기 업로드.
vapcguy

이것은 파일로 이것을하려고 할 때 도움이되었습니다. 관련으로 가지고 있으면 좋습니다.
Justin

5
public static class HelperExtensions
{
    //Convert Image to byte[] array:
    public static byte[] ToByteArray(this Image imageIn)
    {
        var ms = new MemoryStream();
        imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        return ms.ToArray();
    }

    //Convert byte[] array to Image:
    public static Image ToImage(this byte[] byteArrayIn)
    {
        var ms = new MemoryStream(byteArrayIn);
        var returnImage = Image.FromStream(ms);
        return returnImage;
    }
}

2

내가 알아낼 수있는 가장 빠른 방법은 다음과 같습니다.

var myArray = (byte[]) new ImageConverter().ConvertTo(InputImg, typeof(byte[]));

유용 할 수 있기를 바랍니다.


특히 System.Windows.Controls.Image개체 가있는 WPF를 사용하는 경우주의해야 합니다. 그중 하나를 바이트로 변환하고이 줄에으로 전달하면 InputImg작동하지 않습니다. System.Drawing.Image객체를 기대 합니다.
vapcguy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.