memory.save()on memorybmpでencoderparamsを使用してtiff-どのように?
-
29-09-2019 - |
質問
ユーザーが画像の領域を定義し、その領域を保存することを可能にするアプリケーションがあります。私は整理できないひっかきりと駆け抜けました。選択した領域をペイントするために作成したビットマップは、「MemoryBMP」の画像形式に貼り付けられています。これは、ファイル以外のロードされたビットマップに設定されているImageFormatであると思われます。問題は、私のビットマップがメモリで作成されており、CCITT4ビットナルチフとして保存したいのですが、「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画像であることに言及する必要があります。Bitmap.ctor()へのLoadeDimageへの参照を渡して、それが対処しているものにそれを手がかりにするかどうかを確認しましたが、違いはありませんでした。
解決
CCITT4にはバイトーナル画像が必要であることがわかりました。それで私はグーグルで出かけ、出会いました CodeProjectの記事 ソースでスヌープしました。著者は、32BPPARGBを1BPPのBi-Tonalに変換するかなりまともな方法を提供しました。私はそれを試してみました、そしてそれは速いです(テストは1ページで約34ミリ秒を示しています)、それはトリックをしました!
私は自分の質問に答えています。これが少なくともこの問題に出くわす他の誰かに役立つことを願っています。