سؤال

بعد عدة أيام من تتبع أخطاء Bizarre GDI +، تعثرت عبر هذه الأحجار الكريمة الصغيرة MSDN.:

لا يتم دعم الفصول الموجودة داخل مساحة الاسم. قد تنتج محاولة استخدام هذه الفئات من خلال أحد أنواع التطبيقات هذه مشكلات غير متوقعة، مثل أداء الخدمة المتناقص واستثناءات وقت التشغيل.

لا أعرف ما إذا كانت "خدمة ASP.NET" تعني "تطبيق الويب" في هذا السياق، ولكن يبدو أن "أداء الخدمة المتناقص" بالتأكيد يغطي التشكيلة العشوائية "حدث خطأ عام في GDI +" و "خارج الذاكرة" أخطاء أن التطبيق الخاص بي هو رمي - أخطاء متقطعة وغير قابلة للتخويم القراءة والكتابة صور JPEG التي كانت - في كثير من الحالات - تم إنشاؤها بالفعل بواسطة System.Drawing.Inging في المقام الأول.

لذلك - إذا لم يتمكن GDI + قراءة وكتابة ملفات JPEG بشكل موثوق في تطبيق ويب، فماذا يجب أن أستخدم بدلا من ذلك؟

أريد أن يكون المستخدمون قادرين على تحميل الصور (JPEG مطلوب أو تنسيقات أخرى لطيفة)، وإعادة تكوينها بثقة, وعرض رسائل خطأ مفيدة إذا حدث خطأ ما. أيه أفكار؟ هي Names.Media Namespaces من WPF يستحق النظر؟

تعديل: نعم، أعرف GDI + يعمل "معظم الوقت". هذا ليس جيدا بما فيه الكفاية، لأنه عندما يفشل، فإنه يفعل ذلك بطريقة مستحيلة عزل أو التعافي من بأمان. أنا غير مهتم بأمثلة على رمز GDI + الذي يعمل من أجلك: أنا أبحث عن المكتبات البديلة لاستخدامها لمعالجة الصور.

هل كانت مفيدة؟

المحلول

هناك وظيفة مدونة ممتاز بما في ذلك C # رمز حول استخدام مكتبة الرسومات ImageMagick من خلال interop في توبتن برامج بلوق. وبعد صفق هذا المنشور خصيصا مع تشغيل ASP.NET على Linux تحت أحادي؛ ومع ذلك، يجب أن يكون رمز C # في نسخ معجون تماما، والشيء الوحيد الذي ستحتاج إلى تغييره هو سمات Interop إذا كنت تعمل تحت Windows الرجوع إلى نافذة ثنائية (DLL).

ImageMagick® هو مجموعة برامج لإنشاء أو تحرير أو إنشاء أو تحويل صور النقطية. يمكن قراءة الصور وكتابة الصور في مجموعة متنوعة من التنسيقات (أكثر من 100) بما في ذلك DPX و Exr و GIF و JPEG و JPEG-2000 و PDF و Photocd و PNG و PostScript و SVG و TIFF. استخدم ImageMagick لتغيير حجم، فليب، مرآة، تدوير، تشويه، قص وصخر وتحويل الصور، وضبط ألوان الصورة، وتطبيق المؤثرات الخاصة المختلفة، أو رسم نصوص، خطوط، مضلعات، حدائق منفائز Bézier.

هناك أيضا ImageMagick. برنامج تطوير المشروع على codeplex الذي يلف كل شيء بالنسبة لك. لكنه لا يظهر تطور نشط منذ عام 2009، لذلك قد يتخلف وراء إصدار مكتبة ImageMagick الحالية. للحصول على روتين صغير لتغيير حجمه، من المحتمل أن أشعل مع Interop. تحتاج فقط إلى مشاهدة تنفيذك بعناية بالنسبة لتسريب الذاكرة الخاصة بك أو موارد غير مرئية (المكتبة نفسها تم اختبارها جيدا وتوجهها من قبل المجتمع).

المكتبة مجانية ومصدر مفتوح. يبدو أن ترخيص Apache 2 متوافقا مع الأغراض الشخصية والتجارية. يرى ImageMagick رخصة الصفحة.

تعبر المكتبة تماما عن منصة وتنفذ العديد من إجراءات معالجة الصور والتحويل قوية غير موجودة في GDI + (أو غير مطبقة تحت أحادي) ولديها سمعة طيبة كبديل لمعالجة الصور 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 هنا: تغيير حجم الصور من الخادم باستخدام WPF / WIC بدلا من GDI + يقترح استخدام WPF بدلا من GDI +. الأمر أكثر نشاطا على الإصدار المصغر ولكنه بشكل عام نفس القضايا.

على أي حال، في النهاية تنص على هذا:

اتصلت بفريق WPF للحصول على الكلمة الأخيرة حول ما إذا كان هذا مدعوم. لسوء الحظ، ليس الأمر كذلك، ويتم تحديث الوثائق وفقا لذلك. أعتذر عن أي ارتباك قد تسبب هذا. نحن نبحث عن طرق لجعل هذه القصة أكثر مقبولة في المستقبل.

حتى WPF غير مدعوم أيضا في تطبيقات الويب وما زالت أعتقد: -

imagesharp.

imagesharp. هو مكتبة رسومات 2D مفتوحة منصة مفتوحة المصدر. يتم كتابته في C # أعلى معيار .NET الجديد، مع عدم وجود اعتماد على أي API الخاص ب OS.

لا يزال حاليا في إصدار ما قبل الإصدار في MyGet (عليك إضافة مصدر الحزمة في خيارات VS أو ملف Nuget.config)، لكننا نستخدمه بالفعل مع بعض النتائج الإيجابية للغاية.

معظم القضايا التي قرأت عنها تتعلق بالموارد التي لا يتم التخلص منها بشكل صحيح.

لقد استخدمت متغيرات من الوقت والوقت مرة أخرى مع عدم وجود مشاكل من تطبيقات الويب:

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. لم أختبرها ولكنها تبدو واعدة.

لقد كان لدي سلوك جيد من مكتبة القاهرة (http://www.ciraphographics.org) في بيئة ASP.NET WebServer. لقد انتقلت بالفعل إلى القاهرة من WPF بسبب ضعف نموذج استخدام الذاكرة في WPF للأشياء المستندة إلى الويب.

يميل WPF فعليا إلى تشغيل عملية العمال الخاصة بك من الذاكرة. لا يتم تنفيذ أي من كائنات WPF IDisposable, ، والكثير منهم يشيرون إلى الذاكرة غير المدارة التي يتم تحريرها فقط عبر النهائي. الاستخدام المكثف من WPF (خاصة إذا كان الخادم الخاص بك هو فرض ضرائب على وحدة المعالجة المركزية بشكل كبير) في النهاية خارج الذاكرة لأن قائمة انتظار نهضتك تشبع. عندما كنت تقوم بتنطيب تطبيقي، على سبيل المثال، كان لدى قائمة انتظار الانتهاء من أعلى 50000 كائنات على ذلك، العديد منهم يحملون إشارات إلى الذاكرة غير المدارة. لقد تصرفت القاهرة أفضل بكثير بالنسبة لي، وكان نمط استخدام الذاكرة أكثر قابلية للتنبؤ بكثير من WPF.

إذا كنت مهتما باستخدام القاهرة، فاستطع Libs من موقع GTK +. لديهم X86 بالإضافة إلى مجموعة X64 من الثنائيات.

الجانب السلبي الوحيد هو أن القاهرة لا تستطيع قراءة / كتابة JPG أصلا؛ ومع ذلك، يمكنك بسهولة تكييف الأشياء WPF لقراءة / كتابة JPG والقيام بإعادة البناء / التحجيم / الرسم / أي شيء آخر باستخدام القاهرة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top