2014-02-22 48 views
0

我有一組圖像,我使用System.WindowsSystem.Windows.Media.Imaging(是的,不是在GDI +中)按照here中的教程以編程方式在它們上繪製簡單水印。應用簡單水印後圖像大小急劇增加

大多數圖像不超過500Kb,但在應用簡單的水印後,這是一個帶有透明背景的文本,圖像大小急劇增加。

例如,440KB圖像與下面方法施加水印後成爲8.33MB,並且被電我。

private static BitmapFrame ApplyWatermark(BitmapFrame image, string waterMarkText) { 
    const int x = 5; 
    var y = image.Height - 20; 
    var targetVisual = new DrawingVisual(); 
    var targetContext = targetVisual.RenderOpen(); 
    var brush = (SolidColorBrush)(new BrushConverter().ConvertFrom("#FFFFFF")); 
    brush.Opacity = 0.5; 
    targetContext.DrawImage(image, new Rect(0, 0, image.Width, image.Height)); 
    targetContext.DrawRectangle(brush, new Pen(), new Rect(0, y, image.Width, 20)); 
    targetContext.DrawText(new FormattedText(waterMarkText, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, 
          new Typeface("Batang"), 13, Brushes.Black), new Point(x, y)); 
    targetContext.Close(); 
    var target = new RenderTargetBitmap((int)image.Width, (int)image.Height, 96, 96, PixelFormats.Default); 
    target.Render(targetVisual); 
    var targetFrame = BitmapFrame.Create(target); 
    return targetFrame; 
} 

我注意到圖像質量比原始圖像有所提高。圖像更平滑,顏色更淺。但是,你知道我不是很想要這個。我希望圖像保持原樣,但包含水印。沒有質量增加,當然圖像尺寸沒有劇烈變化。

是否有任何設置,我在這裏錯過告訴我的程序保持與源圖像一樣的質量?在我的ApplyWatermark方法發生變化後,如何防止圖像大小發生顯着變化?

編輯

這是我如何轉換BitmapFrameStream。然後我用Stream保存圖像AmazonS3

private Stream EncodeBitmap(BitmapFrame image) { 
    BitmapEncoder enc = new BmpBitmapEncoder(); 
    enc.Frames.Add(BitmapFrame.Create(image)); 
    var memoryStream = new MemoryStream(); 
    enc.Save(memoryStream); 
    return memoryStream; 
} 

2.這是我如何得到BitmapFrameStream

private static BitmapFrame ReadBitmapFrame(Stream stream) { 
    var photoDecoder = BitmapDecoder.Create(
     stream, 
     BitmapCreateOptions.PreservePixelFormat, 
     BitmapCacheOption.None); 
    return photoDecoder.Frames[0]; 
} 

這是我從讀文件本地目錄

public Stream FindFileInLocalImageDir() { 
    try { 
     var path = @"D:\Some\Path\Image.png"; 
     return !File.Exists(path) ? null : File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read); 
     } catch (Exception) { 
      return null; 
    } 
} 
+0

什麼是你開始的圖像格式?是否還有其他代碼在添加水印後實際上將圖像保存到磁盤? –

+0

圖片格式爲.png,圖片也會保存爲.png。處理完成後,圖像將被寫入AmazonS3。有一種將'BitmapFrame'轉換爲'Stream'的不同方法,然後使用.net的AmazonS3 API將流保存到Amazon。 – user3332579

+0

可以將'BitmapFrame'轉換爲'Stream'轉換器嗎?我是否也應該發佈該代碼? – user3332579

回答

0

我之前在評論中問我問題的原因是因爲我注意到有幾種不同的編碼器可用。由於存儲的圖像信息量大,因此位圖通常具有顯着更大的文件大小。

我自己沒有測試過這個,但是你試過了不同的編碼器嗎?

var pngEncoder = new PngBitmapEncoder(); 
pngEncoder.Frames.Add(ApplyWatermark(null, null)); 

MemoryStream stm = File.Create(image); 
pngEncoder.Save(stm); 
return stm; 
+0

我試過'PngBitmapEncoder'並得到'編解碼器不能使用提供的流類型錯誤。 – user3332579

+0

上面的錯誤不再是問題,解決了。但似乎我在某處犯了一些錯誤,所以在應用水印後圖像大小正在改變。例如'960x1280'圖像在水印後變成'1280x1706'。你知道我的錯誤在哪裏嗎? – user3332579

+0

源圖像的DPI在'x'和'y'中都是'72'。但正如您所看到的,我在構建輸出圖像時將dpi設置爲「96」。也增加了33%。那更可能是原因?當我將輸出圖像的DPI設置爲72(與源相同)時,圖像正在原始尺寸上繪製,但奇怪的是,圖像從右側和底側都有一些可用空間(33%)。 [示例在這裏](http://screencast.com/t/BE5QzBUd) – user3332579

1

問題是當你編輯圖像時,壓縮消失了。一張730x1108 JPG,帶有32bit的433kB光盤大小(你提到透明度,如此ARGB),光盤上至少需要730 * 1108 * 4 = 3,09MB。當然,你可以再次壓縮它(對於光盤,還有其他網絡流)。

這就是爲什麼圖像軟件在處理壓縮數據時總是需要大量內存的原因。

結論:您將需要可用內存來處理圖像。完全不可能擁有它。

+0

謝謝,但我不確定是否我正確理解了你。 「可用內存與圖像一起工作」是什麼意思?我沒有'內存不足例外'。我沒有任何例外,但圖像尺寸真的很大。那麼,我需要在處理之後和保存之前壓縮圖像嗎? – user3332579

+0

我只是說要修改圖像,它必須是未壓縮的。巨大的尺寸是沒有壓縮的「真實」尺寸。您可以在更改後重新壓縮(jpg,png等) – ZoolWay

+0

他所說的是大多數圖像格式JPEG,PNG,GIF都採用圖像壓縮來減小文件大小,這就是編碼器和解碼器所做的,所以您打開一個壓縮的圖像,將其解壓縮爲全尺寸,然後再次將其保存,然後再對其應用壓縮。你需要選擇一個編碼器,如JPEG或PNG,使用文件壓縮 – MikeT