System.Drawing.Imageからファイルシステムに新しいイメージを作成しますか?
-
22-07-2019 - |
質問
OK、すみません、これはおそらく初心者の質問ですが、ちょっと行き詰まっています。
(asp.netアプリケーションで)私がやっていることは、ファイルシステムから画像をロードすることです。
System.Drawing.Image tempImage;
tempImage = System.Drawing.Image.FromFile(HttpContext.Server.MapPath(originalPath));
その後、サイズ変更を行います:
tempImage = my awesomeResizingFunction(tempImage, newSize);
そしてこれを使用して別の場所のファイルシステムに保存するつもりです:
string newPath = "/myAwesomePath/newImageName.jpg";
tempImage.Save(newPath);
そして私が得るのはこのエラーです:
"A generic error occurred in GDI+."
画像が「OK」であることは知っています。ブラウザに書き出してサイズ変更された画像を表示できるため、保存しようとするとエラーが発生するだけです。私はちょっと新しくて立ち往生していますが、これはまったく間違っていますか? (まあ、それは明らかだと思いますが、あなたは私が何を意味するか知っています...)
解決
plzこのコードを試してください...画像のサイズ変更と保存に同じコードを使用しました。問題が発生した場合は、plzまでお知らせください。
System.Drawing.Bitmap bmpOut = new System.Drawing.Bitmap(NewWidth, NewHeight);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmpOut);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle(System.Drawing.Brushes.White, 0, 0, NewWidth, NewHeight);
g.DrawImage(new System.Drawing.Bitmap(fupProduct.PostedFile.InputStream), 0, 0, NewWidth, NewHeight);
MemoryStream stream = new MemoryStream();
switch (fupProduct.FileName.Substring(fupProduct.FileName.IndexOf('.') + 1).ToLower())
{
case "jpg":
bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
break;
case "jpeg":
bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
break;
case "tiff":
bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Tiff);
break;
case "png":
bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
break;
case "gif":
bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Gif);
break;
}
String saveImagePath = Server.MapPath("../") + "Images/Thumbnail/" + fupProduct.FileName.Substring(fupProduct.FileName.IndexOf('.'));
bmpOut.Save(saveImagePath);
fupProductはfileuploadコントロールIDです
他のヒント
originalPathとnewPathが異なるファイルを指していることを確認しますか? Image.FromFileを使用する場合、イメージでDisposeを呼び出すまでファイルはロックされたままになり、前述の例外が発生する可能性があります。代わりにそのような画像をロードできます:
Image tempImage = null;
using (FileStream fs = new FileStream(originalPath, FileMode.Open, FileAccess.Read))
{
tempImage = Image.FromStream(fs);
}
...
このアプローチは、usingブロックの最後でファイルが閉じられることを保証します
元の画像を支える元のストリームが閉じられた可能性はありますか?ビットマップの背後のストリームが閉じられている場合、GDI +エラーが発生し始めます。私たちがウェブサイトに画像処理を追加したとき、私はこれに何度も遭遇しました。
Visual Studioデバッガーでビットマップオブジェクトを開くと、プロパティの値ではなく例外が表示されますか?その場合、保存操作に問題はありませんが、GDI +レイヤーはオブジェクト、期間を処理する機能を失っています。
私が見つけたのは、ビットマップに属するMemoryStreamを追跡し、それらをすべてまとめる必要があるということです。画像のサイズを変更すると、新しいビットマップ画像を含む新しいMemoryStreamが生成されました。
この単純なクラスを作成することになりました(ここでは不要ないくつかの追加プロパティをトリミングしました):
public class UploadedImage : IDisposable
{
private Bitmap _img = null;
private Stream _baseStream = null;
/// <summary>
/// The image object. This must always belong to BaseStream, or weird things can happen.
/// </summary>
public Bitmap Img
{
[DebuggerStepThrough]
get { return _img; }
[DebuggerStepThrough]
set { _img = value; }
}
/// <summary>
/// The stream that stores the image. This must ALWAYS belong to Img, or weird things can happen.
/// </summary>
public Stream BaseStream
{
[DebuggerStepThrough]
get { return _baseStream; }
[DebuggerStepThrough]
set { _baseStream = value; }
}
[DebuggerStepThrough]
public void Dispose()
{
if (Img != null)
Img.Dispose();
if (BaseStream != null)
BaseStream.Close();
_attached = false;
}
}
今、私はウェブサイトにアップロードされた画像を扱っていましたが、Asp.Netがリクエストに添付されたストリームをリサイクルすると、突然の画像操作がすべて反転し始めたことがわかりました。したがって、これが最善の方法であるかどうかにかかわらず、私のソリューションは、アップロードストリームからデータを自分のMemoryStreamにコピーし、そこから画像をロードし、両方をこのコンテナーに固定することでした。そして、古いイメージから新しいイメージを作成するたびに、常にストリームとイメージを一緒に保ちました。
これが役立つことを願っています。
編集:画像のサイズ変更をどのように行っているかを見るのにも興味があります。これは私がやった方法の断片です:
temp = new Bitmap(newWidth, newHeight, PIXEL_FORMAT);
temp.SetResolution(newHorizontalRes, newVerticalRes);
gr = Graphics.FromImage(temp);
//
// This copies the active frame from 'img' to the new 'temp' bitmap.
// Also resizes it and makes it super shiny. Sparkle on, mr image dude.
//
Rectangle rect = new Rectangle(0, 0, newWidth, newHeight);
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.SmoothingMode = SmoothingMode.HighSpeed;
gr.PageUnit = GraphicsUnit.Pixel;
gr.DrawImage(img, rect);
//
// Image copied onto the new bitmap. Save the bitmap to a fresh memory stream.
//
retval = new UploadedImage();
retval.BaseStream = (Stream)(new MemoryStream());
temp.Save(retval.BaseStream, ImageFormat.Jpeg);
retval.Img = temp;