2010-08-02 1 views
7

C#에서이 작업을 수행하는 방법은 무엇입니까?파일을 비트 맵에로드하지만 원래 파일은 그대로 두십시오.

Bitmap.FromFile()을 사용하면 원본 파일이 잠겨 있습니다.

Bitmap.FromStream()을 사용하는 경우 원본 파일이 잠겨 있지 않지만 설명서에 "이미지를 사용하는 동안 스트림을 열어 두어야합니다."라는 메시지가 표시됩니다. 이는 파일이 여전히 이미지 객체에 연결되어 있음을 의미합니다 (예 : 파일이 객체를 변경하거나 객체를 변경 한 경우).

내가 그냥 비트 맵을 읽고 객체에 저장되고 싶지하고 파일 및 이미지 객체 사이의 어떠한 링크가 없다는 것을 후

답변

25

이 동작에 대한 배경 정보 : 비트 맵은 메모리 매핑 파일을 사용하여 비트 맵의 ​​픽셀에 액세스합니다. 이것은 Windows API의 매우 기본적인 기능이며 파일 데이터에 대한 메모리의 효율적인 매핑을 가능하게합니다. 프로그램이 메모리를 읽을 때만 파일에서 데이터를 읽습니다. 가상 메모리 페이지는 Windows 페이징 파일에서 공간을 차지하지 않습니다.

정확하게 동일한 메커니즘이 .NET 어셈블리를로드하는 데 사용됩니다. 파일에 잠금을 설정하는 것은 메모리 매핑입니다. 기본적으로 어셈블리가 .NET 프로그램에서 사용될 때 잠기는 이유는 기본적으로 있습니다. Image.Dispose() 메서드는 잠금을 해제합니다. 잠금을 해제하면 비트 맵을 삭제하는 것을 잊어 버리는 경우가 종종 있습니다. 매우 중요합니다. Dispose()를 호출하는 것을 잊어 버리면 너무 많은 (관리되지 않는) 메모리가 필요할 수 있으므로 Bitmap을 제외하고 .NET 클래스에서는 종종 문제를 일으키지 않습니다.

예, FromStream()은 클래스가이 최적화를 수행하지 못하도록합니다. 비용은 중요합니다. 비트 맵이로드 될 때 메모리를 두 배로 늘려야합니다. 이 문제는 비트 맵이 크기 때문에 프로그램이 잠시 (주소 공간 조각화) 실행 중이며 64 비트 운영 체제에서 실행되고 있지 않을 때 OOM을 건너 뛸 때 문제가됩니다. 확실히 비트 맵의 ​​너비 x 높이 x 4> = 45MB,주고 받으면이 작업을 피하십시오.

일부 코드, 당신은 CopyStream 후프 통해 점프 필요가 없습니다 : 당신은 MemoryStream을 처분하지 않으려는

public static Image LoadImageNoLock(string path) { 
     var ms = new MemoryStream(File.ReadAllBytes(path)); // Don't use using!! 
     return Image.FromStream(ms); 
    } 

주, 당신은 하드는 "일반 오류"를 진단하는거야 당신이 비트 맵을 사용하게되면. 스트림을 게으른 읽기로 Image 클래스에서 발생합니다.

+0

비트 맵을 얻으려면이 기능이 필요합니다. 비트 맵 비트 맵 = 새 비트 맵 (LoadImageNoLock (path)); – Harris

+2

MemoryStream은 일회용으로 누가이 솔루션을 폐기 처분합니까? – kwesolowski

4

FileStream에서 복사하여 메모리에 파일을 읽기 MemoryStream. (스택 오버플로에서 CopyStream을 검색하면 안전하게 수행하는 방법에 대한 예제가 많이 있습니다. 기본적으로 반복하면서 루프를 반복하여 읽을 데이터가 없어 질 때까지 각 청크를 메모리 스트림에 씁니다.) MemoryStream (세트 Position = 0) 및 그 다음 Bitmap.FromStream으로 전달하십시오.

4

파일을 잠그지 않고 이미지를 만들려면 이미지의 FileStream 복사본을 만들어야합니다. 스트림을 복사하는 방법은이 페이지의 Best way to copy between two Stream instances - C#을 확인하십시오.

복사 한 스트림에서 이미지를 생성하면 바로 사용할 수 있습니다.

+0

Jon이 우리가해야한다고 제안한 검색에 대한 +1은 ... 매우 좋은 게시물을 발견했습니다. – awe

0

이 기술을 MemoryStream에 복사 한 다음 MemoryStream을 Bitmap.FromStream에 많은 시간을 보내고 있습니다. 그러나이 기술에는 하나의 잡아 당김이 있습니다.

나중에로드 된 이미지에서 Bitmap.Save 메서드 중 하나를 사용하려는 경우 스트림을 활성 상태로 유지해야합니다 (예 :, 이미지가로드 된 후에 처리하지 않음) 그렇지 않으면 두려운 "일반 GDI + 오류가 발생했습니다"예외가 발생합니다!