一个简单的bmp格式压缩代码,可以将bmp文件的数据段用zlib来压缩。里面有验证程序,可以将压缩后的数据重新恢复成bmp格式。写得比较乱,如果需要解释可以直接mail我。 #include<stdio.h> #include<stdlib.h> #include <string.h> #include"./include/zlib.h" #include"./include/zconf.h" #define DEBUG_OUT printf int bmp2new(char *bmpname, char *newname); int new2bmp(char *bmpname, char *newname); int main(int argc, char * argv[]) { int i, len; char temp[50]; if(argc < 2) { printf("Error Usage!/n"); } #if 1 for(i = 1; i<argc; ++i) { printf("==============================================/n"); len = strlen(argv[i]); strcpy(temp, argv[i]); temp[len -3] = 's'; temp[len -2] = '2'; temp[len -1] = '4'; bmp2new(argv[i], temp); } #else for(i = 1; i<argc; ++i) { printf("==============================================/n"); len = strlen(argv[i]); strcpy(temp, argv[i]); temp[len -4] = '1'; temp[len -3] = '.'; temp[len -2] = 'b'; temp[len -1] = 'm'; temp[len -0] = 'p'; temp[len +1] = 0; new2bmp(temp, argv[i]); } #endif printf("==============================================/n"); return 0; } typedef struct _bmp_info { int size; int width; int height; int nouse[7]; }bmp_info; int byteperpixel = 3; int memcpyEx(unsigned char *dst, unsigned char *src, int size, int bSwitch, int bpp) { int i = 0; if((bpp!=3)&&(bSwitch == 1)) { printf("This bpp != 3 is not support to switch pixel/n"); return -1; } while((i + 2) < size) { dst[i] = src[i+2]; dst[i+1] = src[i+1]; dst[i+2] = src[i]; i+=3; } if( i == (size -1)) { dst[i] = src[i]; } else if( i == (size -2)) { dst[i] = src[i]; dst[i+1] = src[i+1]; } return 0; } int putbmpdata(FILE *fp, unsigned char * pBuffer, int width, int height) { int pitchbmp, pitchnew, left = height, size = 0; unsigned char *pBufPitch; // if(width & 0x03) // { // pitchbmp = ((width+3)&(~0x00000003))*byteperpixel; // } // else // { // pitchbmp =width * byteperpixel; // } pitchnew = width*byteperpixel; if(pitchnew & 0x03) { pitchnew = (pitchnew +3)&(-4); } pitchbmp = pitchnew; DEBUG_OUT("pitchnew = %d, pitchbmp = %d/n", pitchnew, pitchbmp); pBufPitch = (unsigned char *)malloc(pitchbmp); while(left>0) { if(byteperpixel == 3) { memcpyEx(pBufPitch, pBuffer + (left-1)*pitchnew, pitchnew, 1, byteperpixel); } else { memcpy(pBufPitch, pBuffer + (left-1)*pitchnew, pitchnew); } fwrite(pBufPitch, 1,pitchbmp, fp); --left; // pBuffer += pitchnew; size += pitchnew; } free(pBufPitch); return size; } int new2bmp(char *bmpname, char *newname) { FILE *fBmp; FILE *fnew; char header[14]; unsigned char *pBmpHead,*pDataBuffer, *pDataUnCompressed; int dataoffset, datasize, tempwidth, err; uLongf uncompressedLen, compressedLen; bmp_info info; fBmp = fopen(bmpname, "wb"); fnew = fopen(newname, "rb"); fread(&header, 1, 14, fnew); if(header[0]!='B' || header[1] != 'M') { printf("%s: is not bmp file format/n", newname); fclose(fBmp); gzclose(fnew); return -1; } dataoffset = *(int *)(header+10); fread(&info, 1, sizeof(bmp_info), fnew); if(info.width & 0x03) { tempwidth = (info.width+3)&(~0x00000003); } else { tempwidth = info.width; } datasize = tempwidth*byteperpixel*info.height; pBmpHead = (unsigned char *)malloc(dataoffset); if(pBmpHead == NULL) { printf("malloc pBmpHead failed/n"); fclose(fBmp); fclose(fnew); return -1; } pDataBuffer = (unsigned char *)malloc(datasize); if(pDataBuffer == NULL) { printf("malloc pBmpHead failed/n"); fclose(fBmp); fclose(fnew); return -1; } pDataUnCompressed = (unsigned char *)malloc(datasize); if(pDataUnCompressed == NULL) { printf("malloc pBmpHead failed/n"); fclose(fBmp); fclose(fnew); return -1; } fseek(fnew, 0, SEEK_SET); fread(pBmpHead, 1, dataoffset, fnew); fwrite(pBmpHead, 1, dataoffset, fBmp); fread(&compressedLen, 1, 4, fnew); DEBUG_OUT("compressed data size: %d/n", (int)compressedLen); DEBUG_OUT("tempwidth = %d, height = %d, datasize = %d/n", tempwidth, info.height, datasize); fread(pDataBuffer, 1, compressedLen, fnew); uncompressedLen = datasize; err = uncompress(pDataUnCompressed, &uncompressedLen, (const unsigned char *)pDataBuffer, compressedLen); if(err != Z_OK) { printf("uncompress error!, err = %d, uncompressedLen = %d/n", err, (int)uncompressedLen); fclose(fBmp); fclose(fnew); return -1; } DEBUG_OUT("uncompressed data size is = %d/n", (int)uncompressedLen); // fwrite(pDataUnCompressed, 1,uncompressedLen, fBmp); putbmpdata(fBmp, pDataUnCompressed, info.width, info.height); fclose(fBmp); fclose(fnew); } int getbmpdata(FILE *fp, unsigned char *pBuffer, int width, int height) { int pitchbmp, pitchnew, left = height, size = 0, readoffset; unsigned char *pBufPitch; // if(width & 0x03) // { // pitchbmp = ((width+3)&(~0x00000003))*byteperpixel; // } // else // { // pitchbmp =width * byteperpixel; // } pitchnew = width*byteperpixel; if(pitchnew & 0x03) { pitchnew = (pitchnew +3)&(-4); } pitchbmp = pitchnew; DEBUG_OUT("pitchnew = %d, pitchbmp = %d/n", pitchnew, pitchbmp); pBufPitch = (unsigned char *)malloc(pitchnew); if(pBufPitch == NULL) { printf("malloc error/n"); return 0; } readoffset = ftell(fp); while(left>0) { fseek(fp, readoffset + (left -1)*pitchbmp, SEEK_SET); fread(pBufPitch, 1, pitchbmp, fp); if(byteperpixel == 3) { memcpyEx(pBuffer, pBufPitch, pitchnew, 1, byteperpixel); } else { memcpy(pBuffer, pBufPitch, pitchnew); } --left; pBuffer += pitchnew; size += pitchnew; } printf("size:%d/n", size); free(pBufPitch); return size; } int bmp2new(char *bmpname, char *newname) { FILE *fBmp; FILE *fnew; int dataoffset, datasize, tempwidth, err, size; uLongf compressedLen; char header[14]; unsigned char *pBmpHead,*pDataBuffer, *pDataCompressed; bmp_info info; fBmp = fopen(bmpname, "rb"); fnew = fopen(newname, "wb"); if(fBmp == NULL) { printf("can't open the file %s/n", bmpname); fclose(fBmp); fclose(fnew); return -1; } if(fnew == NULL) { printf("can't open the file %s/n", newname); } fread(&header, 1, 14, fBmp); if(header[0]!='B' || header[1] != 'M') { printf("%s: is not bmp file format/n", bmpname); fclose(fBmp); fclose(fnew); return -1; } dataoffset = *(int *)(header+10); DEBUG_OUT("file filesz:%d/n", *(int *)(header+2)); DEBUG_OUT("data bmp_offset:%x/n", dataoffset); fread(&info, 1, sizeof(bmp_info), fBmp); if(info.width & 0x03) { tempwidth = (info.width+3)&(~0x00000003); } else { tempwidth = info.width; } datasize = tempwidth*byteperpixel*info.height; DEBUG_OUT("%s tempwidth = %d, height = %d, datasize = %d/n", bmpname, tempwidth, info.height, datasize); pBmpHead = (unsigned char *)malloc(dataoffset); if(pBmpHead == NULL) { printf("malloc pBmpHead failed/n"); fclose(fBmp); fclose(fnew); return -1; } fseek(fBmp, 0, SEEK_SET); fread(pBmpHead, 1, dataoffset, fBmp); fwrite(pBmpHead, 1, dataoffset, fnew); if(0) { DEBUG_OUT("%2X %2X/n", pBmpHead[0], pBmpHead[1]); fclose(fBmp); fclose(fnew); return 0; } pDataBuffer = (unsigned char *)malloc(datasize); if(pDataBuffer == NULL) { printf("malloc pBmpHead failed/n"); fclose(fBmp); fclose(fnew); return -1; } pDataCompressed = (unsigned char *)malloc(datasize); if(pDataCompressed == NULL) { printf("malloc pBmpHead failed/n"); fclose(fBmp); fclose(fnew); return -1; } // fread(pDataBuffer, 1, datasize, fBmp); size = getbmpdata(fBmp,pDataBuffer, info.width, info.height); compressedLen = datasize; err = compress(pDataCompressed, &compressedLen, (const unsigned char *)pDataBuffer, size); if(err != Z_OK) { printf("compress error!, err = %d, compressedlen = %d/n", err, (int)compressedLen); fclose(fBmp); fclose(fnew); return -1; } DEBUG_OUT("compressed data size is = %d/n", (int)compressedLen); fwrite(&compressedLen, 1, 4, fnew); fwrite(pDataCompressed, 1, compressedLen, fnew); fclose(fBmp); fclose(fnew); free(pBmpHead); free(pDataBuffer); return 0; }