ارسم على DeviceContext من ColorRef [
-
01-10-2019 - |
سؤال
لدي مؤشر إلى مخزن مؤقت لـ ColorRef ، شيء مثل: COLORREF* buf = new COLORREF[x*y];
روتين فرعي يملأ هذا المخزن المؤقت مع معلومات الألوان. كل ColorRef يمثل بكسل واحد.
الآن أريد رسم هذا المخزن المؤقت إلى سياق الجهاز. يعمل نهائي الحالي ، لكنه بطيء جدًا (== ~ 200ms لكل رسم ، اعتمادًا على حجم الصورة):
for (size_t i = 0; i < pixelpos; ++i)
{
// Get X and Y coordinates from 1-dimensional buffer.
size_t y = i / wnd_size.cx;
size_t x = i % wnd_size.cx;
::SetPixelV(hDC, x, y, buf[i]);
}
هل هناك طريقة للقيام بذلك بشكل أسرع ؛ في وقت واحد ، لا بكسل واحد تلو الآخر؟
أنا لست على دراية بـ GDI. سمعت عن الكثير من واجهات برمجة التطبيقات مثل createiBitMap () ، bitblt () ، hbitmap ، cimage وكل تلك الأشياء ، ولكن ليس لدي أي فكرة عن كيفية تطبيقها. يبدو كل شيء معقد جدا ...
MFC موضع ترحيب أيضا.
أيه أفكار؟
شكرا مقدما.
(الخلفية: الروتين الفرعي الذي ذكرته أعلاه هو kernel opencl - يحسب وحدة معالجة الرسومات صورة Mandelbrot وتؤيدها في المخزن المؤقت ColorRef.)
تعديل:
شكرا لكم جميعا على اقتراحاتك. أعطتني الإجابات (والروابط) بعض البصيرة في برمجة الرسومات Windows. أصبح الأداء مقبولًا الآن (يسير في سيارتي في عمل ماندلبروت :)
انتهى بي الأمر مع الحل التالي (MFC):
...
CDC dcMemory;
dcMemory.CreateCompatibleDC(pDC);
CBitmap mandelbrotBmp;
mandelbrotBmp.CreateBitmap(clientRect.Width(), clientRect.Height(), 1, 32, buf);
CBitmap* oldBmp = dcMemory.SelectObject(&mandelbrotBmp);
pDC->BitBlt(0, 0, clientRect.Width(), clientRect.Height(), &dcMemory, 0, 0, SRCCOPY);
dcMemory.SelectObject(oldBmp);
mandelbrotBmp.DeleteObject();
لذا ، فإن cbitmap :: createbitmap () أنقذني من استخدام واجهة برمجة التطبيقات الأولية (التي ما زلت لا أفهمها تمامًا). المثال في توثيق CDC :: CreateCompatibledc كان مفيدًا أيضًا.
Mandelbrot الخاص بي هو الآن أزرق - باستخدام setPixelv () كان أحمر. لكنني أعتقد أن هذا له علاقة بـ CBITMAP :: CreateBitMap () تفسير المخزن المؤقت الخاص بي ، وليس مهمًا حقًا.
قد أجرب اقتراح OpenGL لأنه كان سيكون الخيار الأكثر منطقية وأردت تجربة OpenCl تحت Linux على أي حال.
المحلول
في ظل هذه الظروف ، ربما أستخدم قسم DIB (الذي تنشئه معه CreateDIBSection
). قسم DIB عبارة عن صورة نقطية تتيح لك الوصول إلى المحتويات مباشرة كصفيف ، ولكن لا يزال يستخدمه مع جميع وظائف GDI المعتادة.
أعتقد أن هذا سيعطيك أفضل أداء لأي شيء يعتمد على GDI. إذا كنت بحاجة إلى أفضل ، فإن @Kornel صحي أو OpenGL - على الرغم من IMO ، فإن OpenGL هو خيار أفضل بكثير للوظيفة من DirectX).
بالنظر إلى أنك تقوم حاليًا بالحساب في OpenCL وترسب الإخراج في مخزن مؤقت للألوان ، سيكون OpenGL هو حقًا خيار واضح. على وجه الخصوص ، يمكنك إيداع OpenCl الإخراج في نسيج OpenGL ، ثم يمكنك رسم رباعية باستخدام هذا الملمس. بدلاً من ذلك ، نظرًا لأنك فقط تضع الإخراج على الشاشة على أي حال ، يمكنك فقط إجراء الحساب في ظل شظايا OpenGL (أو بالطبع تظليل DirectX Pixel) ، لذلك لن تضع الإخراج في الذاكرة خارج الشاشة فقط حتى تتمكن من نسخ النتيجة على الشاشة. إذا كانت الذاكرة تخدم ، فإن Book Orange يحتوي على Mandelbrot Shader كأحد أمثلةه.
نصائح أخرى
نعم ، بالتأكيد ، هذا بطيء. أنت تقوم بعمل رحلة ذهابًا وإيابًا عبر برنامج تشغيل جهاز kernel وجهاز الفيديو لكل بكسل فردي. يمكنك جعلها سريعة من خلال الرسم إلى الذاكرة أولاً ، ثم قم بتحديث الشاشة في ضربة واحدة. يتطلب ذلك ، على سبيل المثال ، CreatedIbitMap ، CreateCompatibledc () و bitblt ().
هذا ليس وقتًا جيدًا ومكانًا لبرمجة شاملة حول برمجة الرسومات. يتم تغطيته جيدًا بواسطة أي نص تمهيدي على برمجة GDI و/أو Windows API. كل ما ستحتاج إلى معرفته يمكنك العثور عليه في نوافذ البرمجة الخاصة بـ Petzold.
نظرًا لأن لديك بالفعل مجموعة من وحدات البكسل ، يمكنك استخدام Bitblt مباشرة لنقلها إلى العاصمة للنافذة. انظر هذا الرابط للحصول على مثال جزئي:http://msdn.microsoft.com/en-us/library/aa928058.aspx