سؤال

أقوم حاليًا بتجربة استخدام PixelShaders المقدم مع .net 3.5 sp1 لتحسين أداء معالجة الصور.كل شيء أصبح أسرع بكثير، ولكن حتى الآن تم تطبيق التأثيرات على بعض العناصر في نماذج wpf الخاصة بي، والتي أريد تجنبها بالفعل.

لدينا مجموعة من وظائف معالجة الصور وأرغب في استبدال بعض الأشياء قطعة قطعة بتظليل البكسل للحصول على بعض الأداء.هل هناك طريقة لتطبيق تظليل البكسل هذا على ImageSource دون الحاجة إلى عرضه؟

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

المحلول

لمن لا يزال بحاجة إلى هذا:لقد قمت للتو بإنشاء هذه المقالة هنا والتي توضح كيفية القيام بذلك في WPF.http://www.codeproject.com/Articles/642151/Pixel-shaders-in-a-background-thread-in-WPF

تم نسخ الكود ذي الصلة أدناه.إنه من فئة تحتوي على بعض المتغيرات المخزنة

  • مصدر:مصدر الصورة
  • دي بي آي إكس، دي بي آي:الزوجي الذي يحتوي على Dpi من المصدر
  • إم جي:التحكم بالصورة WPF
  • مربع العرض:التحكم في WPF ViewBox
  • WPF_DPI_X، WPF_DPI_Y:const يتضاعف بقيمة 96.0

1. الصورة مضمنة في Viewbox (خارج الشاشة أيضًا)

//prepare images
img = new Image();
img.Stretch = Stretch.None;
viewbox = new Viewbox();
viewbox.Stretch = Stretch.None;
viewbox.Child = img; //control to render

2.img وviewbox يتم ضبط حجمهما بالنسب الصحيحة، كما يتم استدعاء بعض وظائف التخطيط في viewbox.يؤدي هذا إلى عرض عناصر التحكم مع تطبيق التظليل.

/// <summary>
/// Loads the image and viewbox for off-screen rendering.
/// </summary>
public void LoadImage(double width, double height)
{
    img.BeginInit();
    img.Width = width;
    img.Height = height;
    img.Source = Source;
    img.EndInit();

    viewbox.Measure(new Size(img.Width, img.Height));
    viewbox.Arrange(new Rect(0, 0, img.Width, img.Height));
    viewbox.UpdateLayout();
} 

3. وللحصول على محتويات الصورة، قم بعمل "لقطة شاشة" إذا صح التعبير:

void SaveUsingEncoder(BitmapEncoder encoder, Stream stream)
{
    RenderTargetBitmap bitmap = new RenderTargetBitmap((int)(img.Width * DpiX / WPF_DPI_X), (int)(img.Height * DpiY / WPF_DPI_Y), DpiX, DpiY, PixelFormats.Pbgra32);
    bitmap.Render(viewbox);

    BitmapFrame frame = BitmapFrame.Create(bitmap);
    encoder.Frames.Add(frame);
    encoder.Save(stream);
} 

أيضًا، إذا كنت تريد تشغيل هذا في موضوع منفصل، فستحتاج إلى إنشاء موضوع به

thread.SetApartmentState(ApartmentState.STA);

لمزيد من المعلومات والمشروع التجريبي، راجع المقال.

نصائح أخرى

نظرًا لأنك لم تحصل على أي إجابة حتى الآن من خبراء C#، سأحاول التعامل مع هذا من منظور مطور C++ DirectX، على أمل أنه إذا لم تكن إجابتي مفيدة، على الأقل ستوجهك في الاتجاه الصحيح.لا أعرف سوى القليل عن لغة C# ولا أعرف شيئًا عن كيفية دعم PixelShaders، لذا فإن الصدفة خاطئة تمامًا وما أكتبه هنا لا ينطبق على الإطلاق.في مثل هذه الحالة لا تتردد في التعليق أو التصويت ضد حسب الحاجة

ما يتم فعله بشكل عام في C++/DirectX لتحقيق ذلك هو:

التحضير (يتم مرة واحدة)

  • قم بإنشاء هدف العرض باستخدام CreateRenderTarget
  • قم بإنشاء سطح خارج الشاشة باستخدام CreateOffscreenPlainSurface
  • قم بتعيين السطح المستهدف للعرض باستخدام SetRenderTarget
  • قم بإنشاء أي موارد إدخال أخرى مطلوبة (الأنسجة، المخازن المؤقتة Vertex ...)

العرض (يتم تنفيذه عدة مرات)

  • قم بتحديث موارد الإدخال (الأنسجة والمخازن المؤقتة) حسب الحاجة
  • يجعل
  • انسخ محتويات هدف العرض إلى السطح الموجود خارج الشاشة عبر GetRenderTarget
  • قم بقفل السطح الموجود خارج الشاشة وقراءة محتواه على وحدة المعالجة المركزية
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top