(原創) 如何使用Standard Library作影像處理? (C/C++) (Image Processing)

在昨天的Blog,我們使用了Standard Library讀寫bmp圖檔,其中的unsigned char *,雖然是一個一維陣列,但骨子是一個二維陣列,該如何實際的做影像處理呢?

先示範一個最簡單的影像處理,產生一個紅色的圖形。

 1/* 
 2(C) OOMusou 2007 http://oomusou.cnblogs.com
 3
 4Filename    : BmpPixelByPixel.cpp
 5Compiler    : Visual C++ 8.0 / ANSI C / ISO C++
 6Description : Demo the how to process image pixel by pixel
 7Release     : 02/19/2007 1.0
 8*/

 9
10#include "stdio.h"
11#include "stdlib.h"
12
13int bmp_read(unsigned char *image, intintchar *);
14int bmp_write(unsigned char *image, intintchar *);
15
16int main() {
17    unsigned char *image;
18    int xsize = 512;
19    int ysize = 512;
20
21    image = (unsigned char *)malloc((size_t)xsize * ysize * 3);
22    if (image == NULL) 
23      return -1;
24      
25    for(int y = 0; y != ysize; ++y) {
26      for(int x = 0; x != xsize; ++x) {
27        // set (R,G,B) = (255,0,0)
28        // R
29        *(image + 3 * (y * xsize + x) + 2= 255;
30        // G
31        *(image + 3 * (y * xsize + x) + 1= 0;
32        // B
33        *(image + 3 * (y * xsize + x) + 0= 0;
34      }

35    }

36    
37    bmp_write(image, xsize, ysize, "onlyRed");
38    
39    free(image);
40}

41
42int bmp_read(unsigned char *image, int xsize, int ysize, char *filename) {
43    char fname_bmp[128];
44    sprintf(fname_bmp, "%s.bmp", filename);
45    
46    FILE *fp;
47    if (!(fp = fopen(fname_bmp, "rb"))) 
48      return -1;
49      
50    unsigned char header[54];
51    fread(header, sizeof(unsigned char), 54, fp);
52    fread(image, sizeof(unsigned char), (size_t)(long)xsize * ysize * 3, fp);
53    
54    fclose(fp);
55    return 0;
56}

57
58int bmp_write(unsigned char *image, int xsize, int ysize, char *filename) {
59    unsigned char header[54= {
60      0x420x4d00000000,
61        54000400000000000010240
62        00000000000000000000
63        0000
64    }
;
65    
66    long file_size = (long)xsize * (long)ysize * 3 + 54;
67    header[2= (unsigned char)(file_size &0x000000ff);
68    header[3= (file_size >> 8& 0x000000ff;
69    header[4= (file_size >> 16& 0x000000ff;
70    header[5= (file_size >> 24& 0x000000ff;
71    
72    long width = xsize;
73    header[18= width & 0x000000ff;
74    header[19= (width >> 8&0x000000ff;
75    header[20= (width >> 16&0x000000ff;
76    header[21= (width >> 24&0x000000ff;
77    
78    long height = ysize;
79    header[22= height &0x000000ff;
80    header[23= (height >> 8&0x000000ff;
81    header[24= (height >> 16&0x000000ff;
82    header[25= (height >> 24&0x000000ff;
83
84    char fname_bmp[128];
85    sprintf(fname_bmp, "%s.bmp", filename);
86    
87    FILE *fp;
88    if (!(fp = fopen(fname_bmp, "wb"))) 
89      return -1;
90      
91    fwrite(header, sizeof(unsigned char), 54, fp);
92    fwrite(image, sizeof(unsigned char), (size_t)(long)xsize * ysize * 3, fp);
93    
94    fclose(fp);
95    return 0;
96}


本範例試著用此一維陣列作一個最簡單的影像處理,將圖片由右向左作mirror。

  1/* 
  2(C) OOMusou 2007 http://oomusou.cnblogs.com
  3
  4Filename    : BmpRightSideLeft.cpp
  5Compiler    : Visual C++ 8.0 / ANSI C / ISO C++
  6Description : Demo the how to right side to left by standard library
  7Release     : 02/04/2007 1.0
  8*/

  9
 10#include "stdio.h"
 11#include "stdlib.h"
 12
 13int bmp_read(unsigned char *int , int , char *);
 14int bmp_write(unsigned char *int , int , char *);
 15int bmp_rightsideleft(unsigned char *, unsigned char *int , int);
 16
 17int main() {
 18    unsigned char *ori, *tar;
 19    int xsize = 512;
 20    int ysize = 512;
 21
 22    ori = (unsigned char *)malloc((size_t)xsize * ysize * 3);
 23    tar = (unsigned char *)malloc((size_t)xsize * ysize * 3);
 24    
 25    bmp_read(ori, xsize, ysize, "clena");
 26    bmp_rightsideleft(ori, tar, xsize, ysize);
 27    bmp_write(tar, xsize, ysize, "clena_rightsideleft");
 28}

 29
 30
 31int bmp_read(unsigned char *image, int xsize, int ysize, char *filename) {
 32    char fname_bmp[128];
 33    sprintf(fname_bmp, "%s.bmp", filename);
 34    
 35    FILE *fp;
 36    if (!(fp = fopen(fname_bmp, "rb"))) 
 37      return -1;
 38      
 39    unsigned char header[54];
 40    fread(header, sizeof(unsigned char), 54, fp);
 41    fread(image, sizeof(unsigned char), (size_t)(long)xsize * ysize * 3, fp);
 42    
 43    fclose(fp);
 44    return 0;
 45}

 46
 47int bmp_write(unsigned char *image, int xsize, int ysize, char *filename) {
 48    unsigned char header[54= {
 49      0x420x4d00000000,
 50        54000400000000000010240
 51        00000000000000000000
 52        0000
 53    }
;
 54    
 55    long file_size = (long)xsize * (long)ysize * 3 + 54;
 56    header[2= (unsigned char)(file_size &0x000000ff);
 57    header[3= (file_size >> 8& 0x000000ff;
 58    header[4= (file_size >> 16& 0x000000ff;
 59    header[5= (file_size >> 24& 0x000000ff;
 60    
 61    long width = xsize;
 62    header[18= width & 0x000000ff;
 63    header[19= (width >> 8&0x000000ff;
 64    header[20= (width >> 16&0x000000ff;
 65    header[21= (width >> 24&0x000000ff;
 66    
 67    long height = ysize;
 68    header[22= height &0x000000ff;
 69    header[23= (height >> 8&0x000000ff;
 70    header[24= (height >> 16&0x000000ff;
 71    header[25= (height >> 24&0x000000ff;
 72
 73    char fname_bmp[128];
 74    sprintf(fname_bmp, "%s.bmp", filename);
 75    
 76    FILE *fp;
 77    if (!(fp = fopen(fname_bmp, "wb"))) 
 78      return -1;
 79      
 80    fwrite(header, sizeof(unsigned char), 54, fp);
 81    fwrite(image, sizeof(unsigned char), (size_t)(long)xsize * ysize * 3, fp);
 82    
 83    fclose(fp);
 84    return 0;
 85}

 86
 87int bmp_rightsideleft(unsigned char *ori, unsigned char *tar, int xsize, int ysize) {
 88  // x-------
 89  // y
 90  // |
 91  // |
 92  // |
 93  
 94  int avgX = (0 + xsize) / 2;
 95  for(int y = 0; y != ysize; ++y) {
 96    for(int x = 0; x != xsize; ++x) {
 97      int tarX = 2 * avgX - x;
 98      // R
 99      *(tar + 3 * (y * xsize + tarX) + 2= *(ori + 3 * (y * xsize + x) + 2);
100      // G
101      *(tar + 3 * (y * xsize + tarX) + 1= *(ori + 3 * (y * xsize + x) + 1);
102      // B
103      *(tar + 3 * (y * xsize + tarX) + 0= *(ori + 3 * (y * xsize + x) + 0);
104    }

105  }

106  
107  return 0;
108}

125行到135行為實際的一個pixel一個pixel作影像處理。

原圖


執行結果


Remark
在撰寫處理陣列的迴圈時,應該先從z,再y,最後才是x,為什麼呢?因為當宣告陣列時,是int ia[sizey][sizex],所以是先y,然後才x。

See Also
(原創) 如何使用ANSI C/ISO C++讀寫bmp圖檔? (C/C++)

posted on 2007-02-04 20:07  真 OO无双  阅读(17825)  评论(8编辑  收藏  举报

导航