剛考完期中考,閒來無事,想到之前有看到別人用C語言來讀取bmp檔,想說自己也來寫一個XD之後過了3、4天才弄出來,看來還需多加磨練XD

程式介面如圖:

     
  

而利用C語言讀bmp檔,要先了解C語言中的struct和熟悉bmp的檔案格式,而struct的用法可以在C語言相關的書中找到這邊就不多加敘述,bmp相關的架構可以參考bmp格式

接著另外一個重點就是GLUT,GLUT的簡介如下,更詳細的內容可以參考GLUT介紹

GLUT(英文全寫:OpenGL Utility Toolkit)是一個處理OpenGL程式的工具庫,負責處理和底層作業系統的呼叫以及I/O,並包括了以下常見的功能:
    1.定義以及控制視窗
    2.偵測並處理鍵盤及滑鼠的事件
    3.以一個函數呼叫繪製某些常用的立體圖形,例如長方體、球、以及猶他茶壺(實心或只有骨架,如glutWireTeapot())
    4.提供了簡單選單列的實現

在這邊我用的IDE是DEV C++,可以到工具->檢查更新版本那去找OpenGLUT的相關更新。安裝好之後,在開新專案時,可以找到MultiMedia的頁籤中,找到OpenGLUT,接著打好名稱,按確定,就可以踏入GLUT的世界啦!

而這邊回到重點,我這邊寫的程式的主要是先用C語言中的檔案函數,透過讀二進制的方法,並配合bmp的檔案架構,寫好幾個struct,在將檔案標頭部份讀進struct,而其中代表圖像的像素陣列則是用二維陣列儲存。

這邊要注意的是,bmp檔中像素的是用BGR,所以COLOR那我的宣告是依序是B、G、R這樣就不會有問題了。

而在繪圖時,是將圖片一點一點描繪出來,使用了glColor3f函數和glVertex2i函數,設定顏色和描點。這邊也要注意一點glColor3f函數中的RGB值是照比例來算,所以前面讀出像素陣列的RGB值都要除上255。

而這邊在繪圖部分,則是提供三種功能顯示原圖、灰階圖像、負片,由使用者輸入代碼而定。至於檔案名稱是透過命令列參數讀入。

下面就是程式碼的部分啦!

#include <GL/openglut.h>
#include <stdarg.h>
#include<stdio.h>
#include<stdlib.h>
typedef struct BmpHeader

{
          unsigned char HEADER_NAME[2];

          unsigned char SIZE[4];

          unsigned int UNUSE1;

          unsigned int UNUSE2;

          unsigned long PIXEL_ARRAY_BEGIN;     

}BMP_HEADER;
 typedef struct DIBHeader

 {
         unsigned long DIB_HEADER_SIZE;

         unsigned long IMAGE_WIDTH;

         unsigned long IMAGE_HEIGHT;

         unsigned int PLANE_AMOUNT;

         unsigned int BITS_PER_PIXEL;

         unsigned long COMPRESSION_USED;

         unsigned long PIXEL_ARRAY_SIZE;

         unsigned long H_RESOLUTION;

         unsigned long V_RESOLUTION;

         unsigned long PALETTLE_COLOR;

         unsigned long IMPORTANT_COLOR ;  

}DIB_HEADER;
typedef struct Color{

        unsigned char B;

        unsigned char G;

        unsigned char R;
}COLOR;
typedef struct image{

        BMP_HEADER ImageBMP_HEADER;

        DIB_HEADER ImageDIB_HEADER;
   
}IMAGE;
int LoadFile(FILE*,int,char * [],IMAGE*);
void display();
int Height;
int Width;
IMAGE ReadImage;
COLOR ImageData[600][800];
int OperatorNumber;
int main(int argc,char *argv[])
{
    int i,j;

    FILE*fptr;

    if (LoadFile(fptr,argc,argv,&ReadImage)==-1)
    {
       system("PAUSE");
       return 0;
    }
    printf("Image information:\n");
    printf("Image size:%dKB\n",(54+ReadImage.ImageDIB_HEADER.IMAGE_HEIGHT*ReadImage.ImageDIB_HEADER.IMAGE_WIDTH*24/8)/1024);
    printf("Image height:%d\n",ReadImage.ImageDIB_HEADER.IMAGE_HEIGHT);
    printf("Image width:%d\n\n",ReadImage.ImageDIB_HEADER.IMAGE_WIDTH);
    printf("Input operator number:\n");
    printf("0)Show initial image\n1)Change to gray image\n2)Change to negative image\n");
    scanf("%d",&OperatorNumber);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowSize(640,640);
    glutCreateWindow("Read BMP");
    glutDisplayFunc(display);
    glPointSize(4.0);            
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 640.0, 0.0,480.0);
    glutMainLoop();
    return 0;
}
int LoadFile(FILE* fptrSet,int main_argc,char *main_argv[],IMAGE *image)
{
     int i;
     if (main_argc<2)
     {
       printf("File name cann't be finded!\n");
       return -1;
     }
     else if (main_argc==2)
     {  
       fptrSet=fopen(main_argv[1],"rb");
     }else
     {
        printf("Too many arguments!\n");
        return -1;
     }  
     if (fptrSet!=NULL)
     {   
       fread(&(image->ImageBMP_HEADER),sizeof(image->ImageBMP_HEADER),1,fptrSet);
       fseek(fptrSet,0x000E,SEEK_SET);
       fread(&(image->ImageDIB_HEADER),sizeof(image->ImageDIB_HEADER),1,fptrSet);
       Width=image->ImageDIB_HEADER.IMAGE_WIDTH;
       Height=image->ImageDIB_HEADER.IMAGE_HEIGHT;
       fseek(fptrSet,0x0036,SEEK_SET);
       for(int i=0;i<Height;i++)
       {
               fread(ImageData[i],sizeof(COLOR),Width,fptrSet);
       }
       if (image->ImageBMP_HEADER.HEADER_NAME[0]=='B'&&image->ImageBMP_HEADER.HEADER_NAME[1]=='M')
       {
          printf("The image was loaded!\n");
          return 0;
       }else
       {
          printf("The image is not bmp!\n");
          return -1; 
       }
    }
       fclose(fptrSet);
 }
void display()
{
     float gray;
     glClear(GL_COLOR_BUFFER_BIT);
     switch (OperatorNumber)
     {
           case 0:
                for (int i=0;i<Height;i++)
                {
                    for (int j=0;j<Width;j++)
                    {
                        glBegin(GL_POINTS);
                        glColor3f((float)ImageData[i][j].R/255,(float)ImageData[i][j].G/255,(float)ImageData[i][j].B/255);
                        glVertex2i(j,i);
                        glEnd();
                    }
                }
                break;
           case 1:
                for (int i=0;i<Height;i++)
                {
                    for (int j=0;j<Width;j++)
                    {
                        glBegin(GL_POINTS);
                        gray=((float)ImageData[i][j].R/255+(float)ImageData[i][j].G/255+(float)ImageData[i][j].B/255)/3;
                        glColor3f(gray,gray,gray);
                        glVertex2i(j,i);
                        glEnd();
                    }
                }
                break;
           case 2:
                for (int i=0;i<Height;i++)
                {
                    for (int j=0;j<Width;j++)
                    {
                        glBegin(GL_POINTS);
                        glColor3f((float)(ImageData[i][j].R^255)/255,(float)(ImageData[i][j].G^255)/255,(float)(ImageData[i][j].B^255)/255);
                        glVertex2i(j,i);
                        glEnd();
                    }
                }
                break;
}
    glFlush();
}

需要程式檔及原始碼的朋友請按這裡。接下來就是繼續奮鬥,索貝爾運算子!

 

文章標籤
全站熱搜
創作者介紹
創作者 jeff810123 的頭像
jeff810123

在我心中有一個夢

jeff810123 發表在 痞客邦 留言(0) 人氣(1,713)