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


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.