2010-06-15 3 views
6

BitmapSource 개체를 이미지 파일에 저장하는 작은 유틸리티 클래스를 작성했습니다. 이미지 파일은 bmp, jpeg 또는 png 일 수 있습니다. 여기 코드는 다음과 같습니다 BitmapSource를 WPF의 bmp, jpeg 및 png로 저장할 때 완전히 다른 결과가 나타나는 이유

public class BitmapProcessor 
{ 
    public void SaveAsBmp(BitmapSource bitmapSource, string path) 
    { 
     Save(bitmapSource, path, new BmpBitmapEncoder()); 
    } 

    public void SaveAsJpg(BitmapSource bitmapSource, string path) 
    { 
     Save(bitmapSource, path, new JpegBitmapEncoder()); 
    } 

    public void SaveAsPng(BitmapSource bitmapSource, string path) 
    { 
     Save(bitmapSource, path, new PngBitmapEncoder()); 
    } 

    private void Save(BitmapSource bitmapSource, string path, BitmapEncoder encoder) 
    { 
     using (var stream = new FileStream(path, FileMode.Create)) 
     { 
      encoder.Frames.Add(BitmapFrame.Create(bitmapSource)); 
      encoder.Save(stream); 
     } 
    } 
} 

Save 방법의 각

작동,하지만 난 BMP와 JPEG와 예상치 못한 결과를 얻을 수 있습니다. PNG는 WPF Image 컨트롤을 사용하여 화면에 BitmapSource을 표시하면 내가 본 것의 정확한 재현을 생성하는 유일한 형식입니다. 여기

결과이다 :


BMP-너무 어두운


too dark http://img822.imageshack.us/img822/7403/terrainbmp.png

JPEG
- 너무 포화

too saturated http://img816.imageshack.us/img816/8127/terrainjpeg.jpg


PNG - 다른 파일 형식의 올바른

correct http://img810.imageshack.us/img810/6243/terrainpng.png


하는 이유는 무엇입니까 완전히 다른 결과?

필자의 예제에서 BitmapSource은 0.1의 알파 값을 사용한다는 점에 유의해야하지만 (결과적으로 매우 흐릿한 것으로 나타남) 결과 색상을 모든 이미지 형식으로 표시 할 수 있어야합니다. 나는 HyperSnap과 같은 것을 사용하여 화면 캡처를하면, 내가 저장하는 파일 유형에 상관없이 올바르게 보일 것입니다.

correct http://img815.imageshack.us/img815/9966/terrainbmphypersnap.png

당신이 볼 수 있듯이, 이것은 문제가되지 않습니다, 그래서 WPF의 이미지 인코더에 대한 이상한 일이 분명히있다 :


는 여기 BMP로 저장된 HyperSnap 화면 캡처입니다.

설정이 잘못 되었습니까? 내가 놓친 게 있니?

+0

이러한 이미지를 메모리에 저장 한 다음 저장하고 있습니까? 또는 디스크 로딩 된 이미지에서 가져온 것입니까? –

+0

@Adam이 이미지는'RenderTargetBitmap.Render (UIElement)'를 사용하여 메모리 내 (화면 상)'Viewport3D'에서 캡처됩니다. – devuxer

답변

7

나는 당신이보고있는 것을보기에는 너무 놀랍다고 개인적으로 생각하지 않습니다. BMP 및 JPG는 불투명도 및 PNG를 지원하지 않습니다.

이미지에 부분적으로 투명한 파란색 사각형을 만드는이 코드를 예로 들어 보겠습니다.

WriteableBitmap bm = new WriteableBitmap(100, 100, 96, 96, PixelFormats.Pbgra32, null); 
bm.Lock(); 

Bitmap bmp = new Bitmap(bm.PixelWidth, bm.PixelHeight, bm.BackBufferStride, System.Drawing.Imaging.PixelFormat.Format32bppArgb, bm.BackBuffer); 
using(Graphics g = Graphics.FromImage(bmp)) { 
    var color = System.Drawing.Color.FromArgb(20, System.Drawing.Color.Blue); 
    g.FillRectangle(
     new System.Drawing.SolidBrush(color), 
     new RectangleF(0, 0, bmp.Width, bmp.Height)); 
} 

bmp.Save(@".\000_foo.bmp", System.Drawing.Imaging.ImageFormat.Bmp); 
bmp.Save(@".\000_foo.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); 
bmp.Save(@".\000_foo.png", System.Drawing.Imaging.ImageFormat.Png); 

bmp.Dispose(); 

bm.AddDirtyRect(new Int32Rect(0, 0, bm.PixelWidth, bm.PixelHeight)); 
bm.Unlock(); 

new BitmapProcessor().SaveAsBmp(bm, @".\foo.bmp"); 
new BitmapProcessor().SaveAsJpg(bm, @".\foo.jpg"); 
new BitmapProcessor().SaveAsPng(bm, @".\foo.png"); 

System.Drawing이든 WPF 인코더이든 항상 PNG 형식이 작동합니다. JPG 및 BMP 인코더는 작동하지 않습니다. 그들은 단색의 파란색 직사각형을 보여줍니다.

여기에서 중요한 것은 이미지에 배경색을 지정하지 못했습니다. 배경색이 없으면 알파 채널 (BMP/JPG)을 지원하지 않는 형식으로 이미지가 올바르게 렌더링되지 않습니다. 하나 개의 코드 추가 라인 :

g.Clear(System.Drawing.Color.White); 
g.FillRectangle(
    new System.Drawing.SolidBrush(color), 
    new RectangleF(0, 0, bmp.Width, bmp.Height)); 

내 이미지는 배경 색상이 있으므로 알파 채널을 지원하지 않는 인코더는 출력 색상 픽셀 당되어야 하는지를 결정할 수 있습니다. 이제 모든 이미지가 올바르게 보입니다.

경우에 따라 배경색을 지정한 컨트롤을 RenderTargetBitmap으로 지정하거나 이미지를 렌더링 할 때 배경색을 페인트해야합니다.

그리고 제 3 자 인쇄 화면이 작동하는 이유는 궁극적으로 투명한 색이 배경색을 가진 창에있는 그 시점에서 배경색을가집니다. 하지만 WPF 내부에서는 하나의 집합이없는 요소를 다루고 있습니다. 요소에서 RTB를 사용하면 배경색과 같은 다양한 상위 요소의 속성이 상속되지 않습니다.

+0

+1. 고마워요, Adam! 배경이없는 것이 물건을 엉망으로 만든다는 것은 많은 의미가 있습니다. 흥미롭게도, HyperSnap에서 저장 한 bmp를 보면 매우 밝은 파란색 배경입니다. PNG는 완전히 투명합니다. – devuxer

+0

밝은 파란색 배경 또는 부분적으로 투명한 파란색 배경입니까? 배경이 RTB중인 요소 (또는 하위)에 있는지 확인하십시오. 레벨이 1 단계 높으면 계산되지 않습니다. –

관련 문제