0

hereSystem.Windowsのチュートリアルに従って、System.Windows.Media.Imaging(はい、GDI +ではなく)使用して、プログラムで簡単な透かしを描画している一連の画像があります。

ほとんどの画像は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ですか?

編集

1.これは私がに変換BitmapFrameする方法Streamです。次に、それを使用しStreamて画像を A​​mazonS3 に保存します

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.これは私がBitmapFrameから取得する方法ですStream

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

3.これは、ローカルディレクトリからファイルを読み取る方法です

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;
    }
}
4

2 に答える 2