سؤال

هل لدى أي شخص الصيغة السرية لتغيير حجم الصور الشفافة (بشكل أساسي صور GIF) بدون أي خسارة في الجودة - ماذا يحدث على الإطلاق؟

لقد جربت مجموعة من الأشياء، وأقرب ما حصلت عليه ليس جيدًا بما فيه الكفاية.

ألق نظرة على صورتي الرئيسية:

http://www.thewallcompany.dk/test/main.gif

ثم الصورة المقاسة:

http://www.thewallcompany.dk/test/ScaledImage.gif

//Internal resize for indexed colored images
void IndexedRezise(int xSize, int ySize)
{
  BitmapData sourceData;
  BitmapData targetData;

  AdjustSizes(ref xSize, ref ySize);

  scaledBitmap = new Bitmap(xSize, ySize, bitmap.PixelFormat);
  scaledBitmap.Palette = bitmap.Palette;
  sourceData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
    ImageLockMode.ReadOnly, bitmap.PixelFormat);
  try
  {
    targetData = scaledBitmap.LockBits(new Rectangle(0, 0, xSize, ySize),
      ImageLockMode.WriteOnly, scaledBitmap.PixelFormat);
    try
    {
      xFactor = (Double)bitmap.Width / (Double)scaledBitmap.Width;
      yFactor = (Double)bitmap.Height / (Double)scaledBitmap.Height;
      sourceStride = sourceData.Stride;
      sourceScan0 = sourceData.Scan0;
      int targetStride = targetData.Stride;
      System.IntPtr targetScan0 = targetData.Scan0;
      unsafe
      {
        byte* p = (byte*)(void*)targetScan0;
        int nOffset = targetStride - scaledBitmap.Width;
        int nWidth = scaledBitmap.Width;
        for (int y = 0; y < scaledBitmap.Height; ++y)
        {
          for (int x = 0; x < nWidth; ++x)
          {
            p[0] = GetSourceByteAt(x, y);
            ++p;
          }
          p += nOffset;
        }
      }
    }
    finally
    {
      scaledBitmap.UnlockBits(targetData);
    }
  }
  finally
  {
    bitmap.UnlockBits(sourceData);
  }
}

أنا أستخدم الكود أعلاه لإجراء تغيير الحجم المفهرس.

هل لدى أي شخص أفكار التحسين؟

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

المحلول

إذا لم يكن هناك شرط للحفاظ على نوع الملف بعد القياس، فإنني أوصي بالأسلوب التالي.

using (Image src = Image.FromFile("main.gif"))
using (Bitmap dst = new Bitmap(100, 129))
using (Graphics g = Graphics.FromImage(dst))
{
   g.SmoothingMode = SmoothingMode.AntiAlias;
   g.InterpolationMode = InterpolationMode.HighQualityBicubic;
   g.DrawImage(src, 0, 0, dst.Width, dst.Height);
   dst.Save("scale.png", ImageFormat.Png);
}

ستكون النتيجة حوافًا لطيفة مضادة للتعرجات

  • تمت إزالة صورة الكوخ التي تم استبدالها بإعلان

إذا كان يجب عليك تصدير الصورة بصيغة GIF فأنت في رحلة؛GDI+ لا يعمل بشكل جيد مع GIF.يرى هذا بلوق وظيفة عنها لمزيد من المعلومات

يحرر: لقد نسيت التخلص من الصور النقطية في المثال؛لقد تم تصحيحه

نصائح أخرى

هذه هي وظيفة تغيير الحجم الأساسية التي استخدمتها لعدد قليل من تطبيقاتي التي تستفيد من GDI+

/// <summary>
///    Resize image with GDI+ so that image is nice and clear with required size.
/// </summary>
/// <param name="SourceImage">Image to resize</param>
/// <param name="NewHeight">New height to resize to.</param>
/// <param name="NewWidth">New width to resize to.</param>
/// <returns>Image object resized to new dimensions.</returns>
/// <remarks></remarks>
public static Image ImageResize(Image SourceImage, Int32 NewHeight, Int32 NewWidth)
{
   System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(NewWidth, NewHeight, SourceImage.PixelFormat);

   if (bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format1bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format4bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format8bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Undefined | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.DontCare | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format16bppArgb1555 | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format16bppGrayScale) 
   {
      throw new NotSupportedException("Pixel format of the image is not supported.");
   }

   System.Drawing.Graphics graphicsImage = System.Drawing.Graphics.FromImage(bitmap);

   graphicsImage.SmoothingMode = Drawing.Drawing2D.SmoothingMode.HighQuality;
   graphicsImage.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
   graphicsImage.DrawImage(SourceImage, 0, 0, bitmap.Width, bitmap.Height);
   graphicsImage.Dispose();
   return bitmap; 
}

لا أتذكر من أعلى رأسي ما إذا كان سيعمل مع صور GIF، ولكن يمكنك تجربتها.

ملحوظة:لا أستطيع الحصول على الفضل الكامل لهذه الوظيفة.لقد قمت بتجميع بعض الأشياء معًا من بعض العينات الأخرى عبر الإنترنت وجعلتها تلبي احتياجاتي 8^D

أعتقد أن المشكلة تكمن في أنك تقوم بتغيير الحجم استنادًا إلى خط المسح، الأمر الذي سيؤدي إلى عدم وضوح الصورة بغض النظر عن مدى صعوبة تعديلها.تتطلب جودة تغيير حجم الصورة الجيدة منك القيام بمزيد من العمل لمعرفة متوسط ​​لون وحدات البكسل التي تم تغيير حجمها مسبقًا والتي يغطيها البكسل الذي تم تغيير حجمه.

الرجل الذي يدير هذا الموقع لديه تدوينة تناقش بعض خوارزميات تغيير حجم الصور.ربما تريد خوارزمية تحجيم الصورة المكعبة.

تغيير حجم الصورة بشكل أفضل

لأي شخص قد يحاول استخدام حل Markus Olsson لتغيير حجم الصور ديناميكيًا وكتابتها في تدفق الاستجابة.

هذا لن يعمل:

Response.ContentType = "image/png";
dst.Save( Response.OutputStream, ImageFormat.Png );

ولكن هذا سوف:

Response.ContentType = "image/png";
using (MemoryStream stream = new MemoryStream())
{
    dst.Save( stream, ImageFormat.Png );

    stream.WriteTo( Response.OutputStream );
}

على الرغم من أن PNG أفضل بالتأكيد من GIF، إلا أنه في بعض الأحيان تكون هناك حالة استخدام للحاجة إلى البقاء بتنسيق GIF.

باستخدام GIF أو PNG 8 بت، عليك معالجة مشكلة التكميم.

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

بالنسبة لتغييرات طفيفة في الحجم، مثل 10-30%، قد يكون من المقبول الحفاظ على لوحة الألوان الأصلية.

ومع ذلك، في معظم الحالات، ستحتاج إلى إعادة تحديد الكمية.

الخوارزميتان الأساسيتان للاختيار من بينهما هما Octree وnQuant.Octree سريع جدًا ويقوم بعمل جيد جدًا، خاصة إذا كان بإمكانك تراكب خوارزمية ثبات ذكية.يتطلب nQuant ما لا يقل عن 80 ميجابايت من ذاكرة الوصول العشوائي (RAM) لتنفيذ التشفير (ينشئ رسمًا بيانيًا كاملاً)، وعادةً ما يكون أبطأ بمقدار 20 إلى 30 مرة (من 1 إلى 5 ثوانٍ لكل تشفير على صورة متوسطة).ومع ذلك، فإنه ينتج أحيانًا جودة صورة أعلى من Octree لأنه لا يقوم بتقريب القيم للحفاظ على أداء ثابت.

عند تنفيذ دعم GIF الشفاف وملفات GIF المتحركة في ملف imageresizing.net المشروع، اخترت Octree.دعم الشفافية ليس بالأمر الصعب بمجرد التحكم في لوحة الصور.

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