سؤال

لدي مؤشر إلى مخزن مؤقت لـ 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

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