تحويل الألوان إلى الأبيض والأسود

This article is available in English too, check it out here.

نظرة خاطفة

درسنا في هذا اليوم يتكلم عن كيفية تحويل الألوان إلى الدرجات من الأبيض إلى الأسود، وكيفية معاينة المحتوى قبل طباعته كما لو كان على طابعة لا تدعم الألوان. يتكلم الدرس أيضا عن كيفية معرفة وضع الطباعة (معاينة/طباعة) وكيفية معرفة نظام الطباعة (ألوان/أبيض وأسود فقط) في MFC.

مقدمة

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

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

الألوان إلى درجات الرمادي

حقيقة، هي ليست أبيض وأسود! هي درجات من الأبيض إلى الأسود أو درجات الرمادي Gray Shades (يسمى نظام الألوان هذا Grayscale).

لتحويل اللون إلى قيمته في درجات الرمادي، يمكنك تطبيق هذه العملية على اللون:

R/G/B = (red * 0.30) + (green * 0.59) + (blue * 0.11)

فمثلا، الأحمر الأرجواني Magenta (0xFF, 0x00, 0xFF) يمكنك تحويله إلى قيمته في الطيف الرمادي بالطريقة التالية:

-> 255 * 0.30 = 76
-> 0 * 0.59 = 0
-> 255 * 0.11 = 28
-> 76 + 0 + 28 = 104
-> R/G/B = 104 = 0x68

ففي هذا المثال، كل من القيم الأحمر، الأخضر، والأزرق أخذت القيمة 0x68. إذا فالـ Magenta له قيم الـ RGB التالية: 0x68, 0x68, 0x68.

وهذه دالة تقوم بهذه العملية:

COLORREF GetGrayscale(COLORREF cr)
{
    BYTE byColor;

    byColor =
        ( GetRValue(cr) * 0.30 ) +
        ( GetGValue(cr) * 0.59 ) +
        ( GetBValue(cr) * 0.11 );

    return
        RGB( byColor, byColor, byColor );
}

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

R/G/B = (red * 0.2125) + (green * 0.7154) + (blue * 0.0721)

إذا فعملية تحويل اللون الـ Magenta تكون كالتالي:

-> 255 * 0.2125 = 54.1875
-> 0 * 0.7154 = 0
-> 255 * 0.0721 = 18.3855
-> 54.1875 + 0 + 18.3855 = 72.573
-> R/G/B ≈ 73 = 0x49

إذا، فالصحيح أن يكون اللون الأحمر الأرجواني Magenta عند تمثيله بدرجة من درجات الرمادي أن يكون له القيم التالية 0x49، 0x49، 0x49.

وهذه هي نفس الدالة السابقة معدلة:

COLORREF GetGrayscale(COLORREF cr)
{
	BYTE byColor;

	byColor =
		( GetRValue(cr) * 0.2125) +
		( GetGValue(cr) * 0.7154) +
		( GetBValue(cr) * 0.0721);

	return
		RGB( byColor, byColor, byColor );
}

معرفة وضعية معاينة الطباعة الطباعة

في MFC، هل أنت الآن تقوم بالطباعة أو بالمعاينة قبل الطباعة؟ كيف يتم اكتشاف هذا برمجيا؟

إذا كان لديك عنصر من نوع CPrintInfo فيمكنك اكتشاف وضعية معاينة الطباعة ببساطة عن طريق استخدام العضو m_bPreview الموجود داخل هذا العنصر. أما إذا لم يكن لديك عنصر من نوع CPrintInfo (وهذا هو الحال في كود OnDraw) فيمكنك معرفة هل تقوم بمعاينة الطباعة أم لا عن طريق مقارنة العضوين m_hDC و m_hAttribDC وهما مقبضان لوسائط إخراج DC. كيف يفيدنا هذا؟

يقوم MFC باستخدام m_hDC لعملية الإخراج Output. أما m_hAttribDC فيستخدم للحصول على معلومات من الجهاز الذي نستخدمه في هذه العملية. مرة أخرى، كيف يفيد هذا؟

ببساطة، أثناء عملية الرسم على الشاشة أو الطباعة فإن m_hDC و m_hAttribDC يرمزان لنفس المقبض وهو المقبض المستخدم في عملية الرسم سواء على الشاشة أو على الورق. من الناحية الأخرى، ففي حالة عملية معاينة الطباعة، فإن المقبض m_hDC هو مقبض للشاشة التي تتم عليها عملية الرسم، أما مقبض m_hAttribDC فيكون مقبض للطابعة الأساسية. وبهذا، يمكنك الطباعة على الشاشة وفي نفس الوقت الحصول على معلومات الطابعة الرئيسية حتى يتسنى لك التنفيذ على أساس إمكانياتها أو مواصفاتها.

إذا فكود بسيط مثل هذا يساعدنا على معرفة هل هذه عملية معاينة قبل الطباعة أم لا:

BOOL bPreview = (pDC->m_hDC != pDC->m_hAttribDC);

معرفة إمكانيات الطابعة

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

بالطبع أول ما يخطر على بالك هو استخدام دالة GetDeviceCaps() والتي تستطيع من خلالها معرفة جميع البيانات عن الجهاز Device المطلوب.

يمكنك استخدام الدالة GetDeviceCaps() مع تحديد الثابت MUMCOLORS لتحديد عدد الألوان التي تدعمها الطابعة (والذي يكون 2 في حالة كون الطابعة لا تدعم الألوان.) لاحظ أن هذه الطريقة تستخدم مع الطابعات التي تدعم دقة ألوان 8bpx أو أقل. لهذا فإنك تستطيع استخدامها فقط في حالتنا هذه (على الأغلب.)

الكود التالي يقوم بتحديد هل هذه الطابعة تدعم الألوان الأبيض والأسود فقط أم أكثر من ذلك:

BOOL bGrayscale = (pDC->GetDeviceCaps(NUMCOLORS) == 2);

ربط الأفكار

إذا، فيمكنك في أكواد مثل OnPaint() و OnDraw() استخدام كود مثل التالي والذي يقوم بمعرفة هل تدعم الطابعة الأبيض والأسود فقط أم الألوان جميعا، ويتصرف على أساس هذا.

BOOL bGrayscale =
    (pDC->GetDeviceCaps (NUMCOLORS) == 2) &&
    (pDC->m_hDC != pDC->m_hAttribDC);

CBrush brush    (bGrayscale ?
    GetGrayscale(RGB (255, 0, 255)) :
    RGB (255, 0, 255));

رأيان حول “تحويل الألوان إلى الأبيض والأسود

اترك تعليقا