2

ユーザーが画像の領域を定義し、その領域をファイルに保存できるアプリケーションがあります。解決できない問題にぶつかりました。選択した領域をペイントするために作成したビットマップは、「MemoryBmp」の ImageFormat でスタックしています。これは、ファイルが読み込まれていないビットマップに設定されている ImageFormat のようです。問題は、ビットマップがメモリ内に作成され、それを CCITT4 モノクロ TIFF として保存したいのですが、「GDI+ で一般的なエラーが発生しました」という例外が発生することです。これは、Image.RawFormat プロパティがその恐ろしい MemoryBmp であるという事実によるものであると確信しています。

Image.Save() には ImageFormat パラメータを受け取るオーバーロードがあり、渡す ImageFormat.Tiff を使用すると問題なく保存されますが、エンコーダ パラメータを指定する機会がありません。

私が考えることができる唯一の回避策は、Image.Save(Image, ImageFormat) を使用してディスクに保存し、それをリロードし (RawFormat は ImageFormat.Tif に正しく設定されます)、エンコーダー設定を渡して再度保存することです。それはばかげていますが、もっと良い方法があるはずです。

これは、以前の説明が十分に明確でない場合に備えて、私が何をしているのかを示すコードの一部です (これは単なるテスト用です)。

SizeF dpiScale = GetScreenToImageDPIRatio(loadedImage);
using (Bitmap image = new Bitmap(loadedImage,
    (int)(_cropBox.Width * dpiScale.Width),
    (int)(_cropBox.Height * dpiScale.Height)))
{
    image.SetResolution(loadedImage.HorizontalResolution, 
        loadedImage.VerticalResolution);

    using (Graphics g = Graphics.FromImage(image))
    {
        g.DrawImage(loadedImage, 0, 0, new Rectangle(
            (int)(_cropBox.Location.X * dpiScale.Width),
            (int)(_cropBox.Location.Y * dpiScale.Height),
            (int)(_cropBox.Width * dpiScale.Width),
            (int)(_cropBox.Height * dpiScale.Height)),
            GraphicsUnit.Pixel);
    }

    //  It's stuck as a MemoryBmp so none of these checks will work
    if (true || image.RawFormat.Equals(ImageFormat.Tiff))
    {
        ImageCodecInfo tiffCodecInfo = ImageUtils.GetEncoderInfo("image/tiff");
        EncoderParameters myEncoderParameters = new EncoderParameters(2);

        myEncoderParameters.Param[0] = new
            EncoderParameter(System.Drawing.Imaging.Encoder.Compression,
                (long)EncoderValue.CompressionCCITT4);
        myEncoderParameters.Param[1] = new
            EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 1L);

        image.Save(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".tif"),
            tiffCodecInfo, myEncoderParameters);

        //  The file is a "MemoryBmp" and it's screwing things up
        //image.Save(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".tif"),
        //    ImageFormat.Tiff);
    }
    else
    {
        //  other format saving support, blah blah blah
    }
}

ああ、「loadedIimage」は確かに tiff 画像であることに言及する必要があります。

4

1 に答える 1

5

CCITT4 には 2 階調の画像が必要であることがわかりました。そこで私はグーグルをやめ、 CodeProject の記事に出くわし、ソースを調べました。著者は、32bppARGB を 1bpp 2 階調に変換するためのかなりまともな方法を提供しました。私はそれを試してみましたが、それは高速で (単一のページで約 34 ミリ秒のテストを示しています)、うまくいきました!

私は自分の質問に答えています。これが、少なくともこの問題に遭遇した他の誰かに役立つことを願っています。

于 2010-11-06T05:19:07.130 に答える