تمرين من المصدر الأصلي · تطبيق عملي

هذا الإصدار من التصفية

استخدم الشرح العربي للفهم، واعتمد صفحة CS50 الأصلية مرجعًا نهائيًا للمواصفات والتسليم.

جلسة دراسة مقترحة: حتى 60 دقيقةالجهد الكلي التقريبي: 120 دقيقة · أكمل من حيث توقفت لاحقًا.Week 4
محاور هذه الخطوة
  • المؤشرات
  • العناوين
  • malloc
  • الملفات

ترجمة آلية تحت المراجعة

هذا الإصدار من التصفية

المصدر الأصلي

قائمة تنفيذ التمرين

تُحفظ علامات هذه القائمة على هذا الجهاز والمتصفح فقط. أنشئ حسابًا مفعّلًا لحفظ إنجاز التمرين في مسارك.

التصفية

Harvard Yard in grayscale

مشكلة بحاجة إلى حل

ربما تكون أبسط طريقة لتمثيل الصورة هي باستخدام شبكة من وحدات البكسل (i.e.، نقاط)، يمكن أن يكون كل منها بلون مختلف. بالنسبة للصور بالأبيض والأسود، نحتاج إلى 1 بت لكل بكسل، حيث يمكن أن يمثل 0 اللون الأسود و1 يمكن أن يمثل اللون الأبيض، كما هو موضح أدناه.

a simple bitmap

وبهذا المعنى، فإن الصورة هي مجرد صورة نقطية (i.e.، خريطة من البتات). للحصول على المزيد من الصور الملونة، تحتاج ببساطة إلى عدد أكبر من البتات لكل بكسل. تنسيق الملف (مثل بي إم بي, JPEG، أو PNG) الذي يدعم "لون 24 بت" يستخدم 24 بت لكل بكسل. (يدعم BMP في الواقع الألوان 1 و4 و8 و16 و24 و32 بت.)

يستخدم BMP ذو 24 بت 8 بتات للإشارة إلى مقدار اللون الأحمر في لون البكسل، و8 بتات للإشارة إلى مقدار اللون الأخضر في لون البكسل، و8 بتات للإشارة إلى مقدار اللون الأزرق في لون البكسل. إذا كنت قد سمعت من قبل عن ألوان RGB، حسنًا، لقد حصلت عليها: الأحمر، الأخضر، الأزرق.

إذا كانت قيم R وG وB لبعض وحدات البكسل في BMP هي، على سبيل المثال، 0xff, 0x00و 0x00 بالنظام الست عشري، يكون هذا البكسل باللون الأحمر النقي، مثل 0xff (المعروف أيضًا باسم 255 بالنظام العشري) تشير إلى "الكثير من اللون الأحمر"، بينما 0x00 و 0x00 تشير ضمنًا إلى "لا يوجد اللون الأخضر" و"لا يوجد اللون الأزرق" على التوالي. في هذه المشكلة، ستتعامل مع قيم R وG وB لوحدات البكسل الفردية، مما يؤدي في النهاية إلى إنشاء مرشحات الصور الخاصة بك.

في ملف يسمى helpers.c في مجلد يسمى filter-less، اكتب برنامجًا لتطبيق المرشحات على BMPs.

تجريبي

رمز التوزيع

بالنسبة لهذه المشكلة، ستقوم بتوسيع وظيفة الشيفرة المقدمة لك من قبل موظفي CS50.

قم بتنزيل كود التوزيع

قم بتسجيل الدخول cs50.dev، انقر على نافذتك الطرفية، وقم بالتنفيذ cd بمفرده. يجب أن تجد أن مطالبة النافذة الطرفية الخاصة بك تشبه ما يلي:

$

التنفيذ التالي

wget https://cdn.cs50.net/2026/x/psets/4/filter-less.zip

من أجل تنزيل ملف ZIP يسمى filter-less.zip في مساحة الشيفرة الخاصة بك.

ثم نفذ

unzip filter-less.zip

لإنشاء مجلد يسمى filter-less. لم تعد بحاجة إلى ملف ZIP، حتى تتمكن من التنفيذ

rm filter-less.zip

ثم قم بالرد بـ "y" متبوعًا بـ Enter عند المطالبة لإزالة ملف ZIP الذي قمت بتنزيله.

الآن اكتب

cd filter-less

متبوعًا بـ Enter للانتقال إلى (i.e.، open) هذا الدليل. يجب أن تشبه مطالبتك الآن ما يلي.

filter-less/ $

تنفيذ ls بمفرده، ويجب أن تشاهد بعض الملفات: bmp.h, filter.c, helpers.h, helpers.cو Makefile. يجب أن تشاهد أيضًا مجلدًا، images/، بأربعة ملفات BMP. إذا واجهت أي مشكلة، فاتبع نفس الخطوات مرة أخرى لترى ما إذا كان بإمكانك تحديد الخطأ الذي ارتكبته!

الخلفية

قليلا(خريطة) أكثر تقنية

تذكر أن الملف هو مجرد سلسلة من البتات، مرتبة بطريقة ما. إذن، فإن ملف BMP ذو 24 بت هو في الأساس مجرد سلسلة من البتات، (تقريبًا) كل 24 منها تمثل لونًا معينًا للبكسل. لكن ملف BMP يحتوي أيضًا على بعض "البيانات الوصفية"، وهي معلومات مثل ارتفاع الصورة وعرضها. يتم تخزين هذه البيانات الوصفية في بداية الملف في شكل بنيتين للبيانات يُشار إليهما عمومًا باسم "الرؤوس"، ويجب عدم الخلط بينها وبين ملفات رأس لغة C. (بالمناسبة، تطورت هذه الترويسات بمرور الوقت. وتستخدم هذه المشكلة أحدث إصدار من تنسيق BMP من Microsoft، 4.0، والذي ظهر لأول مرة مع نظام التشغيل Windows 95.)

تم استدعاء أول هذه الرؤوس BITMAPFILEHEADER، يبلغ طوله 14 بايت. (تذكر أن البايت الواحد يساوي 8 بتات.) يسمى الثاني من هذه الرؤوس BITMAPINFOHEADER، يبلغ طوله 40 بايت. مباشرة بعد هذه الرؤوس توجد الصورة النقطية الفعلية: مجموعة من البايتات، ثلاثة أضعافها تمثل لون البكسل. ومع ذلك، يقوم BMP بتخزين هذه الثلاثيات بشكل عكسي (i.e.، مثل BGR)، مع 8 بتات للون الأزرق، تليها 8 بتات للأخضر، تليها 8 بتات للون الأحمر. (تقوم بعض برامج BMP أيضًا بتخزين الصورة النقطية بأكملها بشكل عكسي، مع وجود الصف العلوي للصورة في نهاية ملف BMP. ولكننا قمنا بتخزين BMPs لمجموعة المشكلات هذه كما هو موضح هنا، مع الصف العلوي لكل صورة نقطية في الأول والصف السفلي في النهاية.) بمعنى آخر، إذا قمنا بتحويل الوجه المبتسم ذو 1 بت أعلاه إلى وجه مبتسم 24 بت، مع استبدال اللون الأحمر بالأسود، فإن BMP ذو 24 بت سيخزن هذه الصورة النقطية على النحو التالي، حيث 0000ff يعني اللون الأحمر و ffffff يعني اللون الأبيض؛ لقد أبرزنا باللون الأحمر جميع حالات 0000ff.

red smile

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

للتوضيح، تذكر أن الرقم السداسي العشري يمثل 4 بتات. وبناء على ذلك، ffffff بالنظام الست عشري يشير في الواقع 111111111111111111111111 في الثنائي.

لاحظ أنه يمكنك تمثيل الصورة النقطية كمصفوفة ثنائية الأبعاد من وحدات البكسل: حيث تكون الصورة عبارة عن مصفوفة من الصفوف، وكل صف عبارة عن مصفوفة من وحدات البكسل. في الواقع، هذه هي الطريقة التي اخترنا بها تمثيل الصور النقطية في هذه المشكلة.

تصفية الصور

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

المواصفات

تنفيذ الوظائف في helpers.c بحيث يمكن للمستخدم تطبيق مرشحات التدرج الرمادي أو البني الداكن أو الانعكاس أو التمويه على صوره.

  • الوظيفة يجب على grayscale التقاط صورة وتحويلها إلى نسخة بالأبيض والأسود لنفس الصورة.
  • الوظيفة sepia التقاط صورة وتحويلها إلى نسخة بني داكن من نفس الصورة. يجب أن تلتقط وظيفة
  • ال يتم استخدام الدالة reflect الصورة وتعكسها أفقيًا.
  • أخيرًا، يجب أن تقوم وظيفة blur بالتقاط صورة وتحويلها إلى نسخة مربعة غير واضحة من نفس الصورة.

لا يجوز لك تعديل أي من توقيعات الوظائف، كما لا يجوز لك تعديل أي ملفات أخرى بخلاف helpers.c.

تلميحات

فهم رمز التوزيع

دعنا الآن نلقي نظرة على بعض الملفات المقدمة لك كرمز توزيع لفهم ما بداخلها.

bmp.h

افتح bmp.h (مثل النقر المزدوج عليه في متصفح الملفات) وإلقاء نظرة.

ستشاهد تعريفات الرؤوس التي ذكرناها (BITMAPINFOHEADER و BITMAPFILEHEADER). وبالإضافة إلى ذلك، يحدد هذا الملف BYTE, DWORD, LONGو WORD، أنواع البيانات الموجودة عادة في عالم برمجة Windows. لاحظ كيف أنها مجرد أسماء مستعارة للأوليات التي (نأمل) أن تكون على دراية بها بالفعل. يبدو أن BITMAPFILEHEADER و BITMAPINFOHEADER الاستفادة من هذه الأنواع.

ولعل الأهم بالنسبة لك هو أن هذا الملف يعرّف أيضًا ملف struct RGBTRIPLE الذي، بكل بساطة، "يحتوي" على ثلاث بايتات: واحدة زرقاء، وواحدة خضراء، وواحدة حمراء (الترتيب، كما نتذكر، الذي نتوقع فيه العثور على ثلاثيات RGB فعليًا على القرص).

لماذا هذه structمفيد؟ حسنًا، تذكر أن الملف هو مجرد سلسلة من البايتات (أو في النهاية البتات) الموجودة على القرص. ولكن يتم ترتيب هذه البايتات بشكل عام بحيث تمثل البايتات القليلة الأولى شيئًا ما، وتمثل البايتات القليلة التالية شيئًا آخر، وهكذا. توجد "تنسيقات الملفات" لأن العالم قام بتوحيد ما تعنيه وحدات البايت. الآن، يمكننا فقط قراءة ملف من القرص إلى ذاكرة الوصول العشوائي (RAM) كمصفوفة واحدة كبيرة من البايتات. ويمكننا أن نتذكر فقط أن البايت عند array[i] يمثل شيئًا واحدًا، بينما البايت عند array[j] يمثل آخر. ولكن لماذا لا نذكر أسماء بعض تلك البايتات حتى نتمكن من استرجاعها من الذاكرة بسهولة أكبر؟ هذا هو بالضبط ما الهياكل فيه bmp.h اسمح لنا بذلك. بدلاً من التفكير في بعض الملفات على أنها تسلسل طويل من البايتات، يمكننا بدلاً من ذلك التفكير فيها على أنها تسلسل من structق.

filter.c

الآن، دعونا ننفتح filter.c. لقد تم كتابة هذا الملف لك بالفعل، ولكن هناك بعض النقاط المهمة الجديرة بالملاحظة هنا.

أولاً، لاحظ تعريف filters في السطر 10. تخبر هذه السلسلة البرنامج ما هي وسائط سطر الأوامر المسموح بها للبرنامج: b, g, rو s. يحدد كل واحد منهم مرشحًا مختلفًا قد نطبقه على صورنا: التمويه، والتدرج الرمادي، والانعكاس، والبني الداكن.

تفتح الأسطر العديدة التالية ملف صورة، وتتأكد من أنه ملف BMP بالفعل، وتقرأ جميع معلومات البكسل في مصفوفة ثنائية الأبعاد تسمى image.

قم بالتمرير لأسفل إلى عبارة switch التي تبدأ بالسطر 101. لاحظ ذلك، اعتمادًا على ماذا filter الذي اخترناه، يتم استدعاء وظيفة مختلفة: إذا اختار المستخدم عامل التصفية b، يستدعي البرنامج وظيفة blur ؛ إذا تم استدعاء gإذن يجب طباعة grayscale ؛ إذا تم استدعاء rإذن يجب طباعة reflect ؛ وإذا تم استدعاء sإذن يجب طباعة sepia . لاحظ أيضًا أن كل واحدة من هذه الوظائف تأخذ ارتفاع الصورة وعرضها ومصفوفة البكسلات ثنائية الأبعاد كمتغيرات.

هذه هي الوظائف التي ستنفذها (قريبًا!). كما قد تتخيل، فإن الهدف هو أن تقوم كل وظيفة من هذه الوظائف بتحرير مصفوفة ثنائية الأبعاد من وحدات البكسل بطريقة يتم فيها تطبيق المرشح المطلوب على الصورة.

تأخذ الأسطر المتبقية من البرنامج الناتج image واكتبها في ملف صورة جديد.

helpers.h

بعد ذلك، ألقِ نظرة على helpers.h. هذا الملف قصير جدًا، ويوفر فقط النماذج الأولية للوظائف التي رأيتها سابقًا.

هنا، لاحظ حقيقة أن كل وظيفة تأخذ مصفوفة ثنائية الأبعاد تسمى image كوسيطة، حيث image عبارة عن مصفوفة من height العديد من الصفوف، وكل صف هو في حد ذاته مصفوفة أخرى width كثيرة RGBTRIPLEق. فإذا image يمثل الصورة بأكملها إذن image[0] يمثل الصف الأول، و يمثل image[0][0] البكسل الموجود في الزاوية العلوية اليسرى من الصورة.

helpers.c

الآن، افتح helpers.c. هنا يتم تنفيذ الوظائف المعلنة فيها helpers.h ينتمون. لكن لاحظ أن التطبيقات مفقودة الآن! هذا الجزء متروك لك.

Makefile

أخيرًا، دعونا ننظر Makefile. يحدد هذا الملف ما يجب أن يحدث عندما نقوم بتشغيل أمر طرفي مثل make filter. في حين أن البرامج التي ربما تكون قد كتبتها من قبل كانت مقتصرة على ملف واحد فقط، يبدو أن filter يستخدم ملفات متعددة: filter.c و helpers.c. لذلك علينا أن نقول make كيفية تجميع هذا الملف.

حاول التجميع filter بنفسك عن طريق الذهاب إلى جهازك الطرفي والتشغيل

$ make filter

ثم يمكنك تشغيل البرنامج عن طريق تشغيل:

$ ./filter -g images/yard.bmp out.bmp

الذي يأخذ الصورة في images/yard.bmp، ويقوم بإنشاء صورة جديدة تسمى out.bmp بعد تشغيل وحدات البكسل من خلال grayscale . grayscale لم يفعل أي شيء حتى الآن، لذا يجب أن تبدو الصورة الناتجة مثل الفناء الأصلي.

التنفيذ grayscale

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

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

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

void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
    // Loop over all pixels

        // Take average of red, green, and blue

        // Update pixel values
}

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

void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
    // Loop over all pixels
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            // Take average of red, green, and blue

            // Update pixel values
        }
    }
}

الآن، يمكنك استخدام image[i][j] للوصول إلى أي بكسل فردي للصورة. ولكن كيف يمكن الحصول على متوسط ​​العناصر الحمراء والخضراء والزرقاء؟ أذكر كل عنصر من image هو RGBTRIPLE، وهو struct محددة في bmp.h لتمثيل البكسل. بناء الجملة المعتاد للوصول إلى أعضاء أ struct ينطبق، حيث image[i][j].rgbtRed سوف يتيح لك الوصول إلى RGBTRIPLEالقيمة الحمراء، سيمنحك image[i][j].rgbtGreen إمكانية الوصول إلى قيمته الخضراء، وما إلى ذلك.

عند حساب المتوسط، ضع في اعتبارك قيم البكسل مكونات rgbtRed, rgbtGreenو rgbtBlue كلها أعداد صحيحة. لذا تأكد من ذلك الجولة أي أرقام الفاصلة العائمة إلى أقرب عدد صحيح عند تخصيصها لقيمة البكسل! ولماذا قد ترغب في تقسيم مجموع هذه الأعداد الصحيحة على 3.0 وليس 3؟

بمجرد حساب متوسط ​​قيم البكسل الحمراء والخضراء والزرقاء إلى لون تدرج رمادي ناتج، تابع وقم بتحديث قيم البكسل الحمراء والخضراء والزرقاء. الآن، أنت على دراية ببناء جملة المهمة!

التنفيذ sepia

تدعم معظم برامج تحرير الصور مرشح "البني الداكن"، الذي يمنح الصور مظهرًا قديمًا من خلال جعل الصورة بأكملها تبدو ذات لون بني محمر قليلاً.

  • يمكن تحويل الصورة إلى اللون البني الداكن عن طريق أخذ كل بكسل، وحساب قيم جديدة باللون الأحمر والأخضر والأزرق بناءً على القيم الأصلية للثلاثة.
  • هناك عدد من الخوارزميات لتحويل الصورة إلى اللون البني الداكن، ولكن بالنسبة لهذه المشكلة، سنطلب منك استخدام الخوارزمية التالية. لكل بكسل، يجب حساب قيم اللون البني الداكن بناءً على قيم اللون الأصلية الموضحة أدناه.
    sepiaRed = .393 * originalRed + .769 * originalGreen + .189 * originalBlue
    sepiaGreen = .349 * originalRed + .686 * originalGreen + .168 * originalBlue
    sepiaBlue = .272 * originalRed + .534 * originalGreen + .131 * originalBlue
    
  • بالطبع، قد لا تكون نتيجة كل من هذه الصيغ عددًا صحيحًا، ولكن يمكن تقريب كل قيمة إلى أقرب عدد صحيح. من الممكن أيضًا أن تكون نتيجة الصيغة رقمًا أكبر من 255، وهو الحد الأقصى لقيمة اللون 8 بت. في هذه الحالة، يجب أن تكون قيم الأحمر والأخضر والأزرق محددة بـ 255. ونتيجة لذلك، يمكننا ضمان أن قيم الأحمر والأخضر والأزرق الناتجة ستكون أرقامًا صحيحة بين 0 و255، ضمنًا.

اكتب بعض الشيفرة الزائفة لمساعدتك في حل هذه المشكلة وتذكر استخدام المتداخلة for يتكرر لزيارة كل بكسل.

void sepia(int height, int width, RGBTRIPLE image[height][width])
{
    // Loop over all pixels
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            // Compute sepia values

            // Update pixel with sepia values
        }
    }
}

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

  • قم بتقريب نتيجة كل عملية حسابية إلى أقرب عدد صحيح
  • تأكد من أن القيمة الناتجة ليست أكبر من 255

كيف يمكن أن تكون الدالة التي تُرجع العدد الأصغر من عددين صحيحين مفيدة أثناء التنفيذ sepia، خاصة عندما تحتاج إلى التأكد من أن قيمة اللون لا تزيد عن 255؟ نرحب بك، ولكن ليس مطلوبًا منك، كتابة وظيفة مساعدة خاصة بك للقيام بذلك!

التنفيذ reflect

قد تقوم بعض المرشحات أيضًا بتحريك وحدات البكسل. إن عكس الصورة، على سبيل المثال، هو عبارة عن مرشح حيث تكون الصورة الناتجة هي ما ستحصل عليه عن طريق وضع الصورة الأصلية أمام المرآة.

  • أي بكسل على الجانب الأيسر من الصورة يجب أن ينتهي على الجانب الأيمن، والعكس صحيح.
  • لاحظ أن جميع وحدات البكسل الأصلية للصورة الأصلية ستظل موجودة في الصورة المنعكسة، لكن ربما تم إعادة ترتيب تلك البكسلات لتكون في مكان مختلف في الصورة.

في وظيفة reflect ، فستحتاج إلى تبديل قيم وحدات البكسل على الجوانب المقابلة للصف. اكتب بعض الشيفرة الزائفة لمساعدتك على البدء:

void reflect(int height, int width, RGBTRIPLE image[height][width])
{
    // Loop over all pixels
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            // Swap pixels
        }
    }
}

تذكر من المحاضرة كيف قمنا بتبديل قيمتين بمتغير مؤقت. لا حاجة لاستخدام وظيفة منفصلة للتبديل إلا إذا كنت ترغب في ذلك!

والآن هو الوقت المناسب للتفكير في العناصر المتداخلة for حلقات. الخارجي تتكرر حلقة for على كل صف، بينما الجزء الداخلي تتكرر حلقة for على كل بكسل في هذا الصف. ومع ذلك، لكي تعكس صفًا بنجاح، هل تحتاج إلى التكرار على كل بكسل فيه؟

التنفيذ blur

هناك عدد من الطرق لإنشاء تأثير تمويه الصورة أو تنعيمها. بالنسبة لهذه المشكلة، سنستخدم "التعتيم المربع"، الذي يعمل عن طريق أخذ كل بكسل، وإعطائه قيمة جديدة لكل قيمة لون عن طريق حساب متوسط ​​قيم الألوان لوحدات البكسل المجاورة.

  • خذ بعين الاعتبار شبكة البكسلات التالية، حيث قمنا بترقيم كل بكسل.

    a grid of pixels

  • ستكون القيمة الجديدة لكل بكسل هي متوسط ​​قيم جميع وحدات البكسل الموجودة ضمن صف وعمود واحد من البكسل الأصلي (مشكلاً مربعًا 3x3). على سبيل المثال، سيتم الحصول على كل قيمة من قيم الألوان للبكسل 6 عن طريق حساب متوسط ​​قيم الألوان الأصلية للبكسلات 1 و2 و3 و5 و6 و7 و9 و10 و11 (لاحظ أن البكسل 6 نفسه مضمن في المتوسط). وبالمثل، سيتم الحصول على قيم الألوان للبكسل 11 عن طريق حساب متوسط قيم الألوان للبكسلات 6 و7 و8 و10 و11 و12 و14 و15 و16.
  • بالنسبة إلى البكسل الموجود على طول الحافة أو الزاوية، مثل البكسل 15، سنظل نبحث عن جميع البكسلات الموجودة في صف وعمود واحد: في هذه الحالة، البكسلات 10 و11 و12 و14 و15 و16.

عند تنفيذ وظيفة blur ، قد تجد أن تشويش بكسل واحد يؤدي في النهاية إلى التأثير على تشويش بكسل آخر. قد يكون من الأفضل إنشاء نسخة منه image من خلال الإعلان عن مصفوفة جديدة ثنائية الأبعاد برمز مثل RGBTRIPLE copy[height][width];. ثم انسخ image إلى copy، بكسل ببكسل، مع تداخل for ، كالتالي:

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    // Create a copy of image
    RGBTRIPLE copy[height][width];
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            copy[i][j] = image[i][j];
        }
    }
}

الآن، يمكنك قراءة ألوان البكسل منها copy ولكن اكتب (i.e.، قم بتغيير) ألوان البكسل في image!

الإرشادات التفصيلية

يرجى ملاحظة أن هناك 5 مقاطع فيديو في قائمة التشغيل هذه. مفتوح على YouTube.

محتوى خارجي من YouTube

لن نتصل بهذه الخدمة قبل موافقتك. يمكنك فتح المصدر في نافذة مستقلة بدل تحميله هنا.

فتح المصدر

كيفية الاختبار

تأكد من اختبار كافة المرشحات الخاصة بك على نماذج ملفات الصور النقطية المتوفرة!

صحة

check50 cs50/problems/2026/x/filter/less

النمط

style50 helpers.c

كيفية الإرسال

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

submit50 cs50/problems/2026/x/filter/less

أنهيت التطبيق؟

راجع عناصر التنفيذ أعلاه، ثم احفظ إنجازك وانتقل إلى التمرين التالي.

حفظ إنجاز التمرين

يمكنك قراءة الدورة كاملة دون حساب. يصبح حفظ التقدم متاحًا بعد تفعيل الحساب، ويبقى محفوظًا بعد انتهاء العضوية.

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