c bmp 파일 읽 기

18622 단어 문건
출처: http://hi.baidu.com/prince_hyai/item/d328959f62360bc7b72531d3 
이 코드 에서 파일 헤드 를 직접 읽 는 것 은 잘못된 것 입 니 다. struct 구조 체 메모리 정렬 은 구조 체 끝 에 공간 을 늘 리 는 것 이 아니 라 변수 뒤에 바이트 공간 을 늘 리 는 것 입 니 다.
예 를 들 면:
typedef struct { uint16_t bfType;  // 비트 맵 파일 의 형식 은 BM (1 - 2 바이트) uint 32 t bfSize 여야 합 니 다.   // 비트 맵 파일 의 크기 는 바이트 단위 (3 - 6 바이트) uint 16 t bfReserved 1; / 비트 맵 파일 보존 자, 0 (7 - 8 바이트) uint 16 t bfReserved 2; / / 비트 맵 파일 보존 자, 0 (9 - 10 바이트) uint 32 t bfOffBits 여야 합 니 다.    // 비트 맵 데이터 의 시작 위 치 는 비트 맵 (11 - 14 바이트)} 에 비해 BMPFILEHEADER 입 니 다. 이 구조 체 는 마지막 변수 bfOffBits 가 아 닌 bfType 변수 뒤에 있 습 니 다.
따라서 파일 을 차례로 읽 어야 정확 한 결 과 를 얻 을 수 있다.
 
#ifndef _BMPLOAD_H_ 
#define _BMPLOAD_H_ 
#include <stdio.h> 
#include <stdint.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

//        
typedef struct { 
	int width; //      
	int height; //      
	int components; //           ,3:24  ,4: alpha   24   
	unsigned char *data; //      
	unsigned int unpack_size; //       
} TEXTUREIMAGE; 

// BMP   (14  )
typedef struct { 
	uint16_t bfType;  //        ,   BM(1-2  )
	uint32_t bfSize;   //        ,      (3-6  )
	uint16_t bfReserved1; //        ,   0(7-8  )
	uint16_t bfReserved2; //        ,   0(9-10  )
	uint32_t bfOffBits;    //          ,      (11-14  )
} BMPFILEHEADER; 

// BMP   (40  )
typedef struct { 
	uint32_t biSize; //          (15-18  )
	uint32_t biWidth;  //      ,      (19-22  )
	uint32_t biHeight; //      ,      (23-26  )
	uint16_t biPlanes; //         ,   1(27-28  )
	uint16_t biBitCount; //          ,   1(  ),4(16 ),8(256 ) 24(   )  (29-30  )
	uint32_t biCompression; //       ,    0(   ),1(BI_RLE8    ) 2(BI_RLE4    )  (31-34  )
	uint32_t biSizeImage;   //      ,      (35-38  )
	uint32_t biXPelsPerMeter;//        ,     (39-42  )
	uint32_t biYPelsPerMeter;//        ,     (43-46  )
	uint32_t biClrUsed; //                (47-50  )
	uint32_t biClrImportant; //              (51-54  )
} BMPINFOHEADER; 
#endif

//   BMP       
int LoadBmp(char *filename, TEXTUREIMAGE *textureImg) { 
	int i, j; 
	FILE *file; 
	BMPFILEHEADER bmpFile; 
	BMPINFOHEADER bmpInfo; 
	int pixel_size; 
	unsigned int unpack_size;
	struct stat finfo;

	memset(&bmpFile, 0, sizeof bmpFile);
	memset(&bmpInfo, 0, sizeof bmpInfo);
	memset(textureImg, 0, sizeof (TEXTUREIMAGE));

	if (-1 == stat(filename, &finfo)) {
		perror("Error to stat");
		return -1;
	}
	//      
	file = fopen(filename, "rb "); 
	if (file == NULL) { 
		perror("Open file error"); 
		return -1; 
	} 
	//       
	fread(&bmpFile.bfType, 2, 1, file); 
	fread(&bmpFile.bfSize, 4, 1, file); 
	//        
	if (finfo.st_size != bmpFile.bfSize) {
		printf("file size:%d bmp info size: %d, file not complete!
"); return -1; } fread(&bmpFile.bfReserved1, 2, 1, file); fread(&bmpFile.bfReserved2, 2, 1, file); fread(&bmpFile.bfOffBits, 4, 1, file); //printf("bmpFile.bfType:%X
bmpFile.bfSize:%u
bmpFile.bfReserved1:%d
bmpFile.bfReserved2:%d
bmpFile.bfOffBits:%d
", bmpFile.bfType, bmpFile.bfSize, bmpFile.bfReserved1, bmpFile.bfReserved2, bmpFile.bfOffBits); fread(&bmpInfo, 40, 1, file); /* printf("bmpInfo.biSize:%d
", bmpInfo.biSize); printf("bmpInfo.biWidth:%d
", bmpInfo.biWidth); printf("bmpInfo.biHeight:%d
", bmpInfo.biHeight); printf("bmpInfo.biPlanes:%d
", bmpInfo.biPlanes); printf("bmpInfo.biBitCount:%d
", bmpInfo.biBitCount); printf("bmpInfo.biCompression:%d
", bmpInfo.biCompression); printf("bmpInfo.biSizeImage:%d
", bmpInfo.biSizeImage); printf("bmpInfo.biXPelsPerMeter:%d
", bmpInfo.biXPelsPerMeter); printf("bmpInfo.biYPelsPerMeter:%d
", bmpInfo.biYPelsPerMeter); printf("bmpInfo.biClrUsed:%d
", bmpInfo.biClrUsed); printf("bmpInfo.biClrImportant:%d
", bmpInfo.biClrImportant); */ // if (bmpFile.bfType != 0x4D42) { printf("File Type Error
"); fclose(file); return -1; } if (bmpInfo.biCompression != 0) { printf("file compressed!
"); return -1; } if (bmpInfo.biBitCount != 24) { printf("only support 24 bit map
"); fclose(file); return -1; } // pixel_size = bmpInfo.biBitCount >> 3; // unpack_size = bmpInfo.biWidth * bmpInfo.biHeight * pixel_size; textureImg->data = (unsigned char*) malloc(unpack_size); if (textureImg->data == NULL) { fclose(file); return -1; } int bytes_add = bmpInfo.biWidth * pixel_size % 4; // for (i = 0; i < bmpInfo.biHeight; i++) { for (j = 0; j < bmpInfo.biWidth; j++) { // fread( textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 2, sizeof(unsigned char), 1, file); // fread( textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 1, sizeof(unsigned char), 1, file); // fread(textureImg->data + (i * bmpInfo.biWidth + j) * pixel_size + 0, sizeof(unsigned char), 1, file); // Alpha if (pixel_size == 4) { fread(textureImg-> data + (i * bmpInfo.biWidth + j) * pixel_size + 3, sizeof(unsigned char), 1, file); } } if (bytes_add > 0) { // if pixel_size == 4 then bytes_add == 0 fseek(file, bytes_add, SEEK_CUR); } } // textureImg->width = bmpInfo.biWidth; textureImg->height = bmpInfo.biHeight; textureImg->components = pixel_size; textureImg->unpack_size = unpack_size; fclose(file); return 0; } /** * @brief * @param[in] jpg_data JPG , unsigned * @param[in] unpack_size * @param[in] width JPG * @param[in] height JPG * @param[in] components * @param[in] max_color * @return max_color 0, , 2, */ static int scan_jpg_color(unsigned char *jpg_data, size_t unpack_size, int width, int height, int components, int max_color) { if (NULL == jpg_data) return 0; register int i, j, pixel, colors = 0; char *bitHash = (char *) malloc(2 * 1024 * 1024 * sizeof (char)); if (NULL == bitHash) { perror("malloc error"); return 0; } memset(bitHash, 0, 2 * 1024 * 1024 * sizeof (char)); // for (i=0; i<unpack_size; i+=components) { pixel = 0; for (j=0; j<components; j++) { pixel = (pixel << 8) | jpg_data[i+j]; } bitHash[pixel / 8] |= 1 << (pixel % 8); } for (i=0; i<2*1024*1024*8; i++) { if (bitHash[i / 8] & (1 << (i % 8))) { colors++; if (colors > max_color) { printf("colors more than %d!
", max_color); free(bitHash); return 0; } } } free(bitHash); printf("color's count:%d
", colors); return 2; } /** * @brief , samp * @param[in] jpg_data JPG , unsigned * @param[in] width JPG * @param[in] height JPG * @param[in] components * @param[out] samp * @param[in] pos * @param[in] num , * @return */ static int init_pixel_array(unsigned char *jpg_data, int width, int height, int components, int samp[], int pos[][2], int num) { int pixel, i, j, k = 0; size_t pos_num; for (i=0; i<num; i++) { if (width < pos[i][0] || height < pos[i][1]) continue; // , pos_num = pos[i][1] * width * components + pos[i][0] * components; pixel = 0; for (j=0; j<components; j++) { // RGB pixel = (pixel << 8) | jpg_data[pos_num+j]; } samp[k] = pixel; if (k > 0) { if (samp[k-1] == samp[k]) { k--; } } k++; } return k; } #define JPG_SAMP_PIXELS 5 static int scan_jpg_samps(unsigned char *jpg_data, size_t unpack_size, int width, int height, int components, float max_rate) { if (NULL == jpg_data) return 0; register int i, j, k = 0, m; register unsigned int pixel; register unsigned int max_num = max_rate * (unpack_size / 3); // int samp[JPG_SAMP_PIXELS] = {-1, -1, -1, -1, -1}; int pos[JPG_SAMP_PIXELS][2] = {{0, 0}, {25, 25}, {50, 50}, {(width-1), 0}, {width/2, height/2}}; unsigned int count[JPG_SAMP_PIXELS] = {0}; //size_t pos_num; //printf("max same pixel:%u
", max_num); k = init_pixel_array(jpg_data, width, height, components, samp, pos, JPG_SAMP_PIXELS); //printf("k=%d samp[0] = %X samp[1] = %X samp[2]=%X samp[3] = %X samp[4] = %X
", k, samp[0], samp[1], samp[2], samp[3], samp[4]); // for (i=0; i<unpack_size; i+=components) { pixel = 0; for (j=0; j<components; j++) { pixel = (pixel << 8) | jpg_data[i+j]; } for (m=0; m<k; m++) { if (pixel == samp[m]) { count[m]++; if (count[m] > max_num) { printf("Spam JPG: [%d] same color's pixel max than %u!
", m, max_num); return 1; } break; // , } } } int pixel_num = unpack_size / 3; for (m=0; m<k; m++) { printf("Ham JPG: same pixel count[%d] = %u (%f).
", m, count[m], count[m] / (float)pixel_num); } return 0; } /** * @brief * @param[in] jpg_data JPG , * @param[in] unpack_size * @param[in] width JPG * @param[in] height JPG * @param[in] components * @param[in] max_rate * @param[in] max_color * @return 0: max_color ; 1: ; 2: */ static int scan_jpg_samp_color(unsigned char *jpg_data, size_t unpack_size, int width, int height, int components, float max_rate, int max_color) { if (NULL == jpg_data) return 0; register int i, j; register int samp = -1; register unsigned int pixel; register unsigned int count = 0; register int colors = 0; register unsigned int max_num = max_rate * (unpack_size / 3); // int pos_x = width-1, pos_y = 0; size_t pos_num; //printf("max same pixel:%u
", max_num); if (components > 3) { //printf("components=%d return 0!
", components); return 0; } pos_num = pos_y * width * components + pos_x * components; pixel = 0; for (j=0; j<components; j++) { // RGB pixel = (pixel << 8) | jpg_data[pos_num+j]; } samp = pixel; // 24 ,2 24 , , 2^24/8=2MB char *bitHash = (char *) malloc(2 * 1024 * 1024 * sizeof (char)); if (NULL == bitHash) { perror("malloc error"); return 0; } memset(bitHash, 0, 2 * 1024 * 1024 * sizeof (char)); // //register size_t mid_pos = unpack_size / 3 / 2 * 3; //register int k; for (i=0; i<unpack_size; i+=components) { pixel = 0; for (j=0; j<components; j++) { pixel = (pixel << 8) | jpg_data[i+j]; } if (pixel == samp) { count++; if (count > max_num) { printf("same color's pixel max than %u, Spam JPG!
", max_num); free(bitHash); return 1; } } // bitHash[pixel / 8] |= (1 << (pixel % 8)); /* , , 6%=(1.282-1.202)/1.282 , , 40% * , 。 if (i == mid_pos) { colors = 0; for (k=0; k<2*1024*1024*8; k++) { if (bitHash[k / 8] & (1 << (k % 8))) colors++; if (colors > max_color) { printf("Ham JPG: colors more than %d!
", max_color); free(bitHash); return 0; } } } */ } int pixel_num = unpack_size / 3; printf("same pixel count = %u(%f)
", count, count / (float)pixel_num); colors = 0; for (i=0; i<2*1024*1024*8; i++) { if (bitHash[i / 8] & (1 << (i % 8))) { colors++; if (colors > max_color) { printf("Ham JPG: colors more than %d!
", max_color); free(bitHash); return 0; } } } free(bitHash); printf("Spam JPG: color's count:%d
", colors); return 2; } /** * @brief * @param[in] jpg_data JPG , * @param[in] unpack_size * @param[in] width JPG * @param[in] height JPG * @param[in] components * @param[in] max_rate * @param[in] max_color * @return 0: max_color ; 1: ; 2: */ static int scan_jpg_samps_color(unsigned char *jpg_data, size_t unpack_size, int width, int height, int components, float max_rate, int max_color) { if (NULL == jpg_data) return 0; register int i, j, k = 0, m; register unsigned int pixel; register int colors = 0; register unsigned int max_num = max_rate * (unpack_size / 3); // int samp[JPG_SAMP_PIXELS] = {-1, -1, -1, -1, -1}; int pos[JPG_SAMP_PIXELS][2] = {{0, 0}, {25, 25}, {50, 50}, {(width-1), 0}, {width/2, height/2}}; unsigned int count[JPG_SAMP_PIXELS] = {0}; //printf("max same pixel:%u
", max_num); k = init_pixel_array(jpg_data, width, height, components, samp, pos, JPG_SAMP_PIXELS); //printf("k=%d samp[0] = %X samp[1] = %X samp[2]=%X samp[3] = %X samp[4] = %X
", k, samp[0], samp[1], samp[2], samp[3], samp[4]); // 24 ,2 24 , , 2^24/8=2MB char *bitHash = (char *) malloc(2 * 1024 * 1024 * sizeof (char)); if (NULL == bitHash) { perror("malloc error"); return 0; } memset(bitHash, 0, 2 * 1024 * 1024 * sizeof (char)); // //register size_t mid_pos = unpack_size / 3 / 2 * 3; //register int k; for (i=0; i<unpack_size; i+=components) { pixel = 0; for (j=0; j<components; j++) { pixel = (pixel << 8) | jpg_data[i+j]; } for (m=0; m<k; m++) { if (pixel == samp[m]) { count[m]++; if (count[m] > max_num) { printf("same color's pixel max than %u, Spam JPG!
", max_num); free(bitHash); return 1; } } } // bitHash[pixel / 8] |= (1 << (pixel % 8)); /* , , 6%=(1.282-1.202)/1.282 , , 40% * , 。 if (i == mid_pos) { colors = 0; for (k=0; k<2*1024*1024*8; k++) { if (bitHash[k / 8] & (1 << (k % 8))) colors++; if (colors > max_color) { printf("Ham JPG: colors more than %d!
", max_color); free(bitHash); return 0; } } } */ } int pixel_num = unpack_size / 3; for (m=0; m<k; m++) printf("same pixel count = %u(%f)
", count[m], count[m] / (float)pixel_num); colors = 0; for (i=0; i<2*1024*1024*8; i++) { if (bitHash[i / 8] & (1 << (i % 8))) { colors++; if (colors > max_color) { printf("Ham JPG: colors more than %d!
", max_color); free(bitHash); return 0; } } } free(bitHash); printf("Spam JPG: color's count:%d
", colors); return 2; } int main(int argc, char **argv) { TEXTUREIMAGE image; if (0 == LoadBmp( "test.bmp", &image)) { printf("
"); printf("==============================================
"); scan_jpg_color(image.data, image.unpack_size, image.width, image.height, image.components, 40000); printf("==============================================
"); scan_jpg_samps(image.data, image.unpack_size, image.width, image.height, image.components, 0.1); printf("==============================================
"); scan_jpg_samp_color(image.data, image.unpack_size, image.width, image.height, image.components, 0.1, 40000); printf("==============================================
"); scan_jpg_samps_color(image.data, image.unpack_size, image.width, image.height, image.components, 0.1, 40000); printf("==============================================
"); free(image.data); } else { printf("
"); } return 0; }

좋은 웹페이지 즐겨찾기