|
| 1 | +#include <stdio.h> |
| 2 | +#include <stdlib.h> /* malloc() 함수와 free() 함수를 위해서 사용한다. */ |
| 3 | +#include <string.h> /* memcpy() 함수를 위해서 사용한다. */ |
| 4 | +#include <fcntl.h> /* O_RDWR 상수를 위해서 사용한다. */ |
| 5 | +#include <limits.h> /* USHRT_MAX 상수를 위해서 사용한다. */ |
| 6 | +#include <unistd.h> |
| 7 | +#include <sys/mman.h> |
| 8 | +#include <sys/ioctl.h> |
| 9 | +#include <linux/fb.h> |
| 10 | + |
| 11 | +#include "bmpHeader.h" |
| 12 | + |
| 13 | +#define FBDEVFILE "/dev/fb0" |
| 14 | + |
| 15 | +/* 이미지 데이터의 경계 검사를 위한 매크로 */ |
| 16 | +#define LIMIT_UBYTE(n) (n>UCHAR_MAX)?UCHAR_MAX:(n<0)?0:n |
| 17 | + |
| 18 | +typedef unsigned char ubyte; |
| 19 | + |
| 20 | +/* BMP 파일의 헤더를 분석해서 원하는 정보를 얻기 위한 함수 */ |
| 21 | +extern int readBmp(char *filename, ubyte **pData, int *cols, int *rows, int *color); |
| 22 | + |
| 23 | +void cvtBGR2Sepia(ubyte *dest, ubyte *src, int n) |
| 24 | +{ |
| 25 | + for(int i = 0; i < n; i++) { |
| 26 | + int b = *src++; /* blue */ |
| 27 | + int g = *src++; /* green */ |
| 28 | + int r = *src++; /* red */ |
| 29 | + |
| 30 | + /* 세피아 효과 계산 */ |
| 31 | + ubyte or = (r * 100 + g * 197 + b * 48) >> 8; |
| 32 | + ubyte og = (r * 89 + g * 175 + b * 43) >> 8; |
| 33 | + ubyte ob = (r * 70 + g * 136 + b * 33) >> 8; |
| 34 | + |
| 35 | + /* 결과값 경계 검사 */ |
| 36 | + *dest++ = LIMIT_UBYTE(ob); |
| 37 | + *dest++ = LIMIT_UBYTE(og); |
| 38 | + *dest++ = LIMIT_UBYTE(or); |
| 39 | + } |
| 40 | +} |
| 41 | + |
| 42 | +int main(int argc, char **argv) |
| 43 | +{ |
| 44 | + int cols, rows, color = 24; /* 프레임 버퍼의 가로 ×ばつ 세로의 크기 */ |
| 45 | + ubyte r, g, b, a = 255; |
| 46 | + ubyte *pData, *pBmpData, *pImageData, *pFbMap; |
| 47 | + struct fb_var_screeninfo vinfo; |
| 48 | + int fbfd; |
| 49 | + |
| 50 | + if(argc != 2) { |
| 51 | + printf("Usage: ./%s xxx.bmp\n", argv[0]); |
| 52 | + return 0; |
| 53 | + } |
| 54 | + |
| 55 | + /* 프레임 버퍼를 연다. */ |
| 56 | + fbfd = open(FBDEVFILE, O_RDWR); |
| 57 | + if(fbfd < 0) { |
| 58 | + perror("open()"); |
| 59 | + return -1; |
| 60 | + } |
| 61 | + |
| 62 | + /* 현재 프레임 버퍼에 대한 화면 정보를 얻어온다. */ |
| 63 | + if(ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) < 0) { |
| 64 | + perror("ioctl() : FBIOGET_VSCREENINFO"); |
| 65 | + return -1; |
| 66 | + } |
| 67 | + |
| 68 | + /* BMP 출력을 위한 변수의 메모리 할당 */ |
| 69 | + pBmpData = (ubyte *)malloc(vinfo.xres * vinfo.yres * sizeof(ubyte) * vinfo.bits_per_pixel/8); |
| 70 | + pData = (ubyte*)malloc(vinfo.xres * vinfo.yres * sizeof(ubyte) * color/8); |
| 71 | + pImageData = (ubyte *)malloc(vinfo.xres * vinfo.yres * sizeof(ubyte) * color/8); |
| 72 | + |
| 73 | + /* 프레임 버퍼에 대한 메모리 맵을 수행한다. */ |
| 74 | + pFbMap = (ubyte *)mmap(0, vinfo.xres * vinfo.yres * vinfo.bits_per_pixel/8, PROT_READ|PROT_WRITE, MAP_SHARED, fbfd, 0); |
| 75 | + if((unsigned)pFbMap == (unsigned)-1) { |
| 76 | + perror("mmap()"); |
| 77 | + return -1; |
| 78 | + } |
| 79 | + |
| 80 | + /* BMP 파일에서 헤더 정보를 가져온다. */ |
| 81 | + if(readBmp(argv[1], &pImageData, &cols, &rows, &color) < 0) { |
| 82 | + perror("readBmp()"); |
| 83 | + return -1; |
| 84 | + } |
| 85 | + |
| 86 | + cvtBGR2Sepia(pData, pImageData, vinfo.xres*vinfo.yres); |
| 87 | + |
| 88 | + /* BMP 이미지 데이터를 프레임 버퍼 데이터로 변경 */ |
| 89 | + for(int y = 0, k, total_y; y < rows; y++) { |
| 90 | + k = (rows-y-1)*cols*color/8; |
| 91 | + total_y = y*vinfo.xres*vinfo.bits_per_pixel/8; |
| 92 | + for(int x = 0; x < cols; x++) { |
| 93 | + /* BMP 이미지는 뒤집혀 있기 때문에 BGR 형태로 가져온다. */ |
| 94 | + b = LIMIT_UBYTE(pData[k+x*color/8+0]); |
| 95 | + g = LIMIT_UBYTE(pData[k+x*color/8+1]); |
| 96 | + r = LIMIT_UBYTE(pData[k+x*color/8+2]); |
| 97 | + *(pBmpData + x*vinfo.bits_per_pixel/8 + total_y + 0) = b; |
| 98 | + *(pBmpData + x*vinfo.bits_per_pixel/8 + total_y + 1) = g; |
| 99 | + *(pBmpData + x*vinfo.bits_per_pixel/8 + total_y + 2) = r; |
| 100 | + *(pBmpData + x*vinfo.bits_per_pixel/8 + total_y + 3) = a; |
| 101 | + } |
| 102 | + } |
| 103 | + |
| 104 | + /* 앞에서 생성한 BMP 데이터를 프레임 버퍼의 메모리 공간으로 복사 */ |
| 105 | + memcpy(pFbMap, pBmpData, vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8); |
| 106 | + |
| 107 | + /* 프레임 버퍼 파일을 닫고 이미지 데이터를 위해서 사용한 메모리를 해제 */ |
| 108 | + munmap(pFbMap, vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8); |
| 109 | + |
| 110 | + free(pBmpData); |
| 111 | + free(pImageData); |
| 112 | + free(pData); |
| 113 | + |
| 114 | + close(fbfd); /* 프레임 버퍼를 위한 디바이스 파일 닫기 */ |
| 115 | + |
| 116 | + return 0; |
| 117 | +} |
0 commit comments