質問

奇妙なGDI+エラーを数日間追跡した後、私はこの小さな宝石に出くわしました MSDN:

System.Drawing NameSpace内のクラスは、WindowsまたはASP.NETサービス内で使用するためにサポートされていません。これらのアプリケーションタイプのいずれかからこれらのクラスを使用しようとすると、サービスパフォーマンスの低下やランタイムの例外など、予期しない問題が発生する場合があります。

「ASP.NETサービス」がこのコンテキストで「Webアプリケーション」を意味するかどうかはわかりませんが、「サービスパフォーマンスの低下」は、「GDI+」と「Out of Memory」エラーの「一般的なエラーが発生した」というランダムな品揃えを確実にカバーしているようです。私のアプリがスローしていること - 多くの場合、System.draw.imagingによって実際に作成されたJPEG画像の読み取りと書き込みの断続的なエラーの読み取りエラー。

したがって、GDI+がWebアプリでJPEGファイルを確実に読み書きできない場合、代わりに何を使用する必要がありますか?

ユーザーに画像をアップロードできるようにしたい(JPEGが必要、その他の形式がいい)、それらをリセンプすることを望んでいます 確実に, 、そして何か問題が発生した場合に有用なエラーメッセージを表示します。何か案は? WPFのSystem.Mediaの名前空間は検討する価値がありますか?

編集: ええ、私はGDI+が「ほとんどの時間」で動作することを知っています。それは十分ではありません。なぜなら、それが失敗したとき、それは優雅に隔離または回復することが不可能な方法でそうするからです。私はあなたのために働くGDI+コードの例には興味がありません:私は探しています 画像処理に使用する代替ライブラリ。

役に立ちましたか?

解決

の使用に関するC#コードを含む優れたブログ投稿があります ImageMagickグラフィックライブラリ ATを介して Toptenソフトウェアブログ. 。この投稿では、モノの下でLinuxでASP.NETを実行していることを特に扱っています。ただし、C#コードは完全にコピー可能である必要があります。変更する必要があるのは、ウィンドウバイナリ(DLL)を参照するWindowsで実行されている場合の互換的な属性だけです。

ImageMagick®は、ビットマップ画像を作成、編集、作成、または変換するソフトウェアスイートです。 DPX、EXR、GIF、JPEG、JPEG-2000、PDF、PHOTOCD、PNG、PostScript、SVG、TIFFなど、さまざまな形式(100を超える100)で画像を読み書きできます。 ImageMagickを使用して、サイズ変更、フリップ、ミラー、回転、歪み、歪み、歪み、画像の変換、画像の色の調整、さまざまな特殊効果を適用するか、テキスト、ライン、ポリゴン、楕円、ベジエ曲線を描きます。

またあります ImageMagick .NET開発プロジェクト CodePlexであなたのためにすべてを包みます。しかし、2009年以降は積極的な開発は表示されないため、現在のImageMagick Libraryバージョンに遅れをとっている可能性があります。小さな些細なサイズのルーチンのために、私はおそらく相互作用に固執するでしょう。自分のメモリリークまたは未発表のリソースについて、実装を注意深く視聴する必要があります(ライブラリ自体は、コミュニティによって十分にテストされ、審査されます)。

ライブラリは無料でオープンソースです。 Apache 2ライセンスは、個人および商業目的の両方と互換性があるようです。見る ImageMagickライセンスページ.

ライブラリは完全にクロスプラットフォームであり、GDI+(またはMonoの下で実装されていない)には見られない多くの強力な画像処理と変換ルーチンを実装し、ASP.NET画像処理の代替として高い評価を得ています。

更新:.NETラッパーの更新バージョンがここにあるようです: http://magick.codeplex.com/

他のヒント

はい、WPFを使用します System.Windows.Media クラス。完全に管理されていると、GDIの問題と同じ問題はありません。

これは、勾配をレンダリングするために使用するいくつかのMVCコードからの抜粋です。WPFから取得する方法を教えてください Visual PNGへ:

using System;
using System.IO;
using System.Web.Mvc;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace MyMvcWebApp.Controllers
{
    public class ImageGenController : Controller
    {
        // GET: ~/ImageGen/Gradient?color1=red&color2=pink
        [OutputCache(CacheProfile = "Image")]
        public ActionResult Gradient(Color color1, Color color2, int width = 1, int height = 30, double angle = 90)
        {
            var visual = new DrawingVisual();
            using (DrawingContext dc = visual.RenderOpen())
            {
                Brush brush = new LinearGradientBrush(color1, color2, angle);
                dc.DrawRectangle(brush, null, new Rect(0, 0, width, height));
            }

            return new FileStreamResult(renderPng(visual, width, height), "image/png");
        }

        static Stream renderPng(Visual visual, int width, int height)
        {
            var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default);
            rtb.Render(visual);

            var frame = BitmapFrame.Create(rtb);
            var encoder = new PngBitmapEncoder();
            encoder.Frames.Add(frame);

            var stream = new MemoryStream();
            encoder.Save(stream);
            stream.Position = 0;

            return stream;
        }
    }
}

Microsoftの従業員から非常に良い記事をここで見つけることができます: GDI+の代わりにWPF/WICを使用してサーバーから画像を変更する これは、GDI+の代わりにWPFを使用することを提案しています。それはサムネーリングに関するものですが、全体的に同じ問題です。

とにかく、最後にこれはこれを述べています:

WPFチームに連絡して、これがサポートされているかどうかについての最後の言葉を持っています。残念ながら、そうではなく、ドキュメントはそれに応じて更新されています。これが引き起こした可能性のある混乱についてお詫び申し上げます。私たちは、その物語を将来より受け入れやすくする方法を検討しています。

したがって、WPFはWebアプリにもサポートされていませんが、それでも私は信じています:-S

Imagesharp

Imagesharp オープンソースのクロスプラットフォーム2Dグラフィックライブラリです。これは、OS固有のAPIに依存することなく、新しい.NET標準の上にC#で書かれています。

現在、MyGetでプレリリースしています(VSオプションまたはnuget.configファイルにパッケージソースを追加する必要があります)が、すでにいくつかの非常に肯定的な結果を使用して使用しています。

私が読んだ問題のほとんどは、適切に処分されていないリソースに関係しています。

私はこのコードのバリエーションを何度も使用しており、Webアプリケーションに問題はありません。

public void GenerateThumbNail(HttpPostedFile fil, string sPhysicalPath, 
                              string sOrgFileName,string sThumbNailFileName,
                              System.Drawing.Imaging.ImageFormat oFormat, int rez)
{

    try
    {

        System.Drawing.Image oImg = System.Drawing.Image.FromStream(fil.InputStream);

        decimal pixtosubstract = 0;
        decimal percentage;

        //default
        Size ThumbNailSizeToUse = new Size();
        if (ThumbNailSize.Width < oImg.Size.Width || ThumbNailSize.Height < oImg.Size.Height)
        {
            if (oImg.Size.Width > oImg.Size.Height)
            {
                percentage = (((decimal)oImg.Size.Width - (decimal)ThumbNailSize.Width) / (decimal)oImg.Size.Width);
                pixtosubstract = percentage * oImg.Size.Height;
                ThumbNailSizeToUse.Width = ThumbNailSize.Width;
                ThumbNailSizeToUse.Height = oImg.Size.Height - (int)pixtosubstract;
            }
            else
            {
                percentage = (((decimal)oImg.Size.Height - (decimal)ThumbNailSize.Height) / (decimal)oImg.Size.Height);
                pixtosubstract = percentage * (decimal)oImg.Size.Width;
                ThumbNailSizeToUse.Height = ThumbNailSize.Height;
                ThumbNailSizeToUse.Width = oImg.Size.Width - (int)pixtosubstract;
            }

        }
        else
        {
            ThumbNailSizeToUse.Width = oImg.Size.Width;
            ThumbNailSizeToUse.Height = oImg.Size.Height;
        }

        Bitmap bmp = new Bitmap(ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);
        bmp.SetResolution(rez, rez);
        System.Drawing.Image oThumbNail = bmp;

        bmp = null;

        Graphics oGraphic = Graphics.FromImage(oThumbNail);

        oGraphic.CompositingQuality = CompositingQuality.HighQuality;

        oGraphic.SmoothingMode = SmoothingMode.HighQuality;

        oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;

        Rectangle oRectangle = new Rectangle(0, 0, ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);

        oGraphic.DrawImage(oImg, oRectangle);

        oThumbNail.Save(sPhysicalPath  + sThumbNailFileName, oFormat);

        oImg.Dispose();

    }
    catch (Exception ex)
    {
        Response.Write(ex.Message);
    }

}

あなたは見ているかもしれません http://gd-sharp.sourceforge.net/ これはGDライブラリのラッパーです。私はそれをテストしていませんが、それは有望なようです。

ASP.NET Webサーバー環境で、カイロ図書館(http://www.cairographics.org)から良い振る舞いがありました。 WPFのWebベースのものに対するメモリ使用モデルが不十分であるため、私は実際にWPFからCairoに移りました。

WPFは実際には、ワーカープロセスをメモリから実行する傾向があります。 WPFオブジェクトはどれも実装していません IDisposable, 、そしてそれらの多くは、ファイナルライザーによってのみ解放された未成年のメモリを参照しています。 WPFの大量使用(特にサーバーが大幅にCPU税がかかっている場合)は、最終的なキューが飽和状態になるため、最終的にメモリから外れます。たとえば、アプリをプロファイリングしていたとき、ファイナライゼーションキューには50,000以上のオブジェクトがあり、その多くは管理されていないメモリへの参照を保持していました。カイロは私にとってはるかに優れた振る舞いをしており、その記憶使用パターンはWPFよりもはるかに予測可能でした。

Cairoの使用に興味がある場合は、GTK+のWebサイトからLibsを入手してください。 X86とX64セットのバイナリがあります。

唯一の欠点は、カイロがJPGをネイティブに読み書きできないことです。ただし、JPGの読み取り/書き込みにWPFのものを簡単に適応させ、Cairoを使用してリサンプリング/スケーリング/描画/その他は何でも実行できます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top