לדלג לתוכן

תכנות וזיהוי/טיפול בתמונות מפת סיביות

מתוך ויקיספר, אוסף הספרים והמדריכים החופשי

טעינה ושמירה של קבצי תמונות[עריכה]

כדי לזהות עצם (או אות) ראוי להשוות אותו לתמונות מבסיס נתונים. בתוכנית יש בסיס נתונים של תמונות מפת סיביות.

בתוכנית, הבסיס נתונים הוא קובץ תמונה אחת המכילה הרבה תמונות בצורה של טבלה (בשם SaveBMP.bmp). כדי לעבוד עם בסיס הנתונים, התוכנית מאפשרת :

  1. לפתוח (לטעון מתיקיית הקבצים) קובץ מפת סיביות .
  2. לשמור בתיקיית הקבצים קובץ מפת סיביות
  3. להוסיף לקובץ בסיס הנתונים תמונה
  4. להחליף בקובץ בסיס הנתונים תמונה, בתמונה אחרת.

כך טוענים ושומרים קובץ מפת סיביות :

פונקציית הטוענת את קובץ מפת הסיביות SaveBMP.bmp מתיקיית קבצים[עריכה]

הפונקציה משתמשת בפונקציית הספרייה LoadImage שטוענת קובץ תמונה מתיקיית הקבצים,

אם משתמשים באפשרות LR_LOADFROMFILE שפירושה לטעון את התמונה מקובץ בתיקייה.

הפונקציה מחזירה כפלט משתנה Myhbmp מסוג מצביע לתמונת מפת סיביות HBITMAP .

#include <windows.h>
HBITMAP MyLoadBMP()
{
Myhbmp HBITMAP ;
Myhbmp=(HBITMAP)LoadImage(NULL,"SaveBMP.bmp",
           IMAGE_BITMAP,0,0,
           LR_DEFAULTCOLOR|
          LR_LOADFROMFILE
           );          
return Myhbmp;
}

אבל יש בעיה בפונקציה הזו כי היא טוענת את התמונה הפוכה בהיפוך מראָה,

לכן בתוך התוכנה יש פונקציה ההופכת חזרה את התמונה.

שמירת תמונת סיביות בזיכרון[עריכה]

כפי הידוע איין פונקציית ספרייה בשם SaveImage

לשמירת תמונה בתיקיית הקבצים . משום כך צריך לכתוב אותה לבד.

בכמה מקומות באינטרנט כתוב קוד לפונקציה כזאת :

  • האתר Runicsoft (התוכנה של רוניק) מוקדש לכתיבת פונקציה כזאת לשמירת תמונת מפת סיביות ( BITMAP) .
  • גם באתר videotutorialsrock (לימוד וידאו) במדריך שלו ל - OpenGL בשיעור ה- 6 "Puting It All Together" ,

יש קטע בו שומרים תמונת מפת סיביות שהיא דופן של קובייה. הטבלה הבאה משווה בין שמירת התמונות בשני האתרים :

הבדל אצל רוניק אצל לימוד וידאו
סוג מפת סיביות 24 סיביות - תמונות לא חדות שקל לעבדן 48 סיביות - תמונות חדות מאד
מתאים לגרסת חלונות כמעט כולן חלונות XP ומעלה
צורת התמונה שנשמרת מלבן ריבוע
כתוב בשפת C CPP
כדי להתאים את התוכנה אלינו חייבים לתרגם ל -CPP, על ידי התמרת משתנים צריך לתרגם מבנה נתונים בשם BEG בדבר מוכר למהדר כמו מערך בגודל 1
הסברים הסברים מפורטים גם על מבנה קובץ התמונה אין הסברים
ארכיטקטורת התכנות תכנות פונקציונאלי תכנות מונחה עצמים

כדי לא לצאת בלא כלום אלא לפחות להבין את העיקרון של שמירת קובץ מפת סיביות, בהמשך כתובות שתי פונקציות :

  1. פונקציה לתפיסת צבע תמונת החלון לתוך מערך של נקודות .
  2. פונקציה לשמירת התמונה בתיקיית הקבצים בתור קובץ PGM .

קובץ PGM[עריכה]

הקובץ הזה הוא אחד מסוגי תמונת מפת הסיביות של סדרת Netpbm .

שמו הוא ראשי תיבות של Portable Gray Map

כלומר מפת הזיכרון של תמונה עם גווני אפור שונים היכולה לשמש בהרבה סביבות עבודה .

חשוב לדעת איך שומרים קובץ כזה, משתי סיבות :

  • קובץ ה - BITMAP של מיקרוסופט דומה לפיתוח של קבצי Netpbm .
  • התוכנית בהמשך משתמשת בתוכנית קוד פתוח GOCR לשם זיהוי אותיות באנגלית, ו - GOCR מפענחת תמונות PGM ולא BITMAP .

שמירת חלון כקובץ PGM[עריכה]

/*PGM שמירת חלון כקובץ */
bool MakePgmInG(HWND TheWin)
{FILE *P5; /* PGM מצביע לקובץ תמונת */
int X,Y;
int ImageW,ImageL;/* גודל התמונה */
/* משתנים לשמירת הנתונים  */
char TheColor;
BYTE* RGBDataScreen = 0;
RECT r;
 
// מציאת גובה ורוחב של החלון
 GetWindowRect(TheWin,&r);
 ImageL =r.bottom - r.top;
 ImageW =r.right - r.left;

 if (!ImageW)
  { MessageBox(NULL,
            "החלון סגור",
            "אזהרה",0);
   return false;
  }
// image.pgm  פתח קובץ     
// wb לשם שמירה דחוסה (בינארית)  של נתונים 
// P5 את התוצאה שמור  במצביע לקובץ בשם  
 P5=fopen("image.pgm","wb");
// PGM כתוב את השורה הראשונה בקובץ בה הוא מאופיין כקובץ
//  בשורה כתוב סוג קובץ P5  מסדרת NETPBM (שהוא  PGM)
// המשתנים הבאים הם הגובה והרוחב של התמונה
 //  בשורה הבאה כתוב 255 כלומר שיש 256 דרגות הצבע בין 0 ל - 255  
 fprintf(P5,"P5\n%d %d\n255\n",ImageW,ImageL);
// תפוס את צבעי החלון בתוך מערך בעזרת הפונקציה בסעיף הבא
 RGBDataScreen = ScreenRGBCapInG(TheWin);
 // שומרים את הבהירות של צבע התמונה בקובץ
// בערך 8 ערכים של בהירות
  // output = (rColor+gColor+bColor) / 96;

 for(Y=0;Y<ImageL;Y++)
   for(X=0;X<ImageW;X++)
   {TheColor = char(
 //אדום
    (RGBDataScreen[4*((Y*ImageW)+X)]+
//ירוק
     RGBDataScreen[4*((Y*ImageW)+X)+1]+
//כחול
     RGBDataScreen[4*((Y*ImageW)+X)+2])/96) ;
    fprintf(P5,"%c",TheColor);
   }
 fclose(P5);
 return true;
}

שמירה מהירה של צבעי החלון במערך[עריכה]

// תפוס את כל צבעי המסך במערך
//GetPixel המהירות נוצרת כי לא משתמשים ב -
// יש דוגמה דומה לזו באינטרנט
//stackoverflow.com
//c++ getting RGB from hbitmap

BYTE * ScreenRGBCapInG(HWND TheWin)
{ //  הגדרת מערך של מספרים שלמים טבעיים בין 0 עד 256 
 BYTE* ScreenRGBData = 0;
int TheDefaultSize = 0;
// הגדרת מלבן בו נטענים הגובה והרוחב של המסך
RECT r;
//  הגדרת משתנה למבנה של תמונת מפת הסיביות
BITMAPINFOHEADER bmi ;
int ImageW,ImageL;/* מהגדרת משתנים לרוחב וגובה החלון */

   // תפוס את שולחן העבודה
    // יחד עם החלונות האחרים
    HDC hScreen = GetDCEx(
      TheWin,NULL,
      DCX_PARENTCLIP|
      DCX_EXCLUDERGN);
 
// מציאת גובה ורוחב של החלון
 GetWindowRect(TheWin,&r);
 ImageL =r.bottom - r.top;
 ImageW =r.right - r.left;

    HDC hdcMem = CreateCompatibleDC (hScreen);
    HBITMAP hBitmap = CreateCompatibleBitmap(
                      hScreen, ImageW, ImageL);
    HBITMAP hbmPrevius = SelectObject(hdcMem, hBitmap);
    BitBlt(hdcMem, 0, 0,
           ImageW, ImageL, hScreen, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmPrevius);    
 
/* אפס את מבנה הנתונים של תמונת מפת הסיביות */
 memset(&bmi,0,sizeof(BITMAPINFOHEADER));
 /* מצא כמה גודל תופס מבנה הנתונים של תמונת מפת הסיביות בזיכרון */  
    bmi.biSize = sizeof(BITMAPINFOHEADER);
/* אין לנו פלטות כדי להציב עליהן את התמונה  לכן יש רק משטח אחד */
    bmi.biPlanes = 1;
    bmi.biBitCount = 32; // כשמגדירים תמונת סיביות של 24 סיביות מציבים את הערך עשרים וארבע
 // אבל כאן אנו עובדים עם קובץ מסוג
// DIB

// גובה ורוחב התמונה
    bmi.biWidth =  ImageW;
    bmi.biHeight = - ImageL;
// שיטת דחיסת הצבעים
    bmi.biCompression = BI_RGB;
    bmi.biSizeImage = TheDefaultSize; // ערך בררת מחדל לגודל התמונה, 
                          //בסוף גודל התמונה יהיה בערך 3 * ScreenX * ScreenY

    if(ScreenRGBData)
        delete[]  ScreenRGBData;
    ScreenRGBData =
       new BYTE[ 4 *  ImageW *  ImageL];

    GetDIBits(hdcMem, hBitmap, 0,
      ImageL, ScreenRGBData,
       (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
  
 ReleaseDC(TheWin,hScreen);   
 DeleteDC(hdcMem);
 return ScreenRGBData;
}