#include <stdio.h> #include <stdlib.h> extern "C" __stdcall lzma_set_dict_size(unsigned logdictsize); extern "C" __stdcall lzma_compress( const void* source, void* destination, unsigned length, void* workmem); typedef struct { short int sizeX; short int sizeY; int compressedSize; int physicalOffset; int uncompressedSize; } SCompBmpHeader; int main(int argc, char* argv[]) { if (argc < 3) { printf("Usage: bmp2src <destination> <src1> <src2> ...\n"); return 1; } FILE* fo = fopen(argv[1], "wb"); if (!fo) { printf("Cannot create destination file\n"); return 2; } int n=0; SCompBmpHeader* hea = (SCompBmpHeader*)malloc((argc-2)*sizeof(SCompBmpHeader)); void** ptrs = (void**)malloc((argc-2)*4); lzma_set_dict_size(20); void* workmem = (void*)malloc(0x509000 + (1<<20)*19/2); for (int i=2;i<argc;i++) { FILE* fi = fopen(argv[i], "rb"); if (!fi) { printf("Cannot open input file %s\n",argv[i]); continue; } unsigned char buf[0x36]; fread(buf,1,0x36,fi); if (buf[0] != 'B' || buf[1] != 'M') { if (buf[0] != 0xFF || buf[1] != 0xD8) { printf("%s: unrecognized type\n",argv[i]); fclose(fi); continue; } // JPEG printf("Processing %s ...",argv[i]); fseek(fi,0,SEEK_END); unsigned insize = ftell(fi); void* output = malloc(insize); unsigned char* ptr = (unsigned char*)output; *ptr++ = 0xFF; *ptr++ = 0xD8; // Now load JPEG file, skipping all APPx markers fseek(fi,2,SEEK_SET); bool bOk = false; for (;;) { if (fread(buf,1,4,fi) != 4 || buf[0] != 0xFF) { printf("%s: invalid JPEG file\n",argv[i]); bOk = false; break; } // ignore APPx markers if (buf[1] >= 0xE0 && buf[1] <= 0xEF) { fseek(fi,buf[2]*256 + buf[3] - 2,SEEK_CUR); continue; } unsigned len = buf[2]*256 + buf[3] + 2; fseek(fi,-4,SEEK_CUR); fread(ptr,1,len,fi); if (buf[1]>=0xC0 && buf[1]<=0xCF && buf[1]!=0xC4 && buf[1]!=0xC8 && buf[1]!=0xCC) { // found SOFn marker hea[i-2].sizeX = (unsigned char)ptr[4+3]*256 + (unsigned char)ptr[4+4]; hea[i-2].sizeY = (unsigned char)ptr[4+1]*256 + (unsigned char)ptr[4+2]; bOk = true; } ptr += len; if (buf[1] == 0xDA) { // SOS marker len = insize - ftell(fi); fread(ptr,1,len,fi); ptr += len; break; } } if (!bOk) {printf(" invalid\n");free(ptr);continue;} hea[i-2].compressedSize = ptr - (unsigned char*)output; hea[i-2].uncompressedSize = hea[i-2].compressedSize - 1; hea[i-2].physicalOffset = (i==2) ? 0 : hea[i-3].physicalOffset+hea[i-3].compressedSize; ptrs[i-2] = output; ++n; printf(" OK\n"); continue; } if (buf[0x1C] != 24) { printf("Input file %s is not 24-bit BMP\n",argv[i]); fclose(fi); continue; } int width = *(int*)(buf+0x12); int linesize = (width*3+3)&~3; int height = *(int*)(buf+0x16); void* input = malloc(width*height*3); void* packed = malloc(9*width*height*3/8 + 0x80); for (int p=0;p<height;p++) { fseek(fi,(height-p-1)*linesize+0x36,SEEK_SET); fread((char*)input+p*width*3, 1, width*3, fi); } fclose(fi); hea[i-2].sizeX = (short)width; hea[i-2].sizeY = (short)height; unsigned uncompressedSize = width*height*3; hea[i-2].uncompressedSize = uncompressedSize; hea[i-2].physicalOffset = (i==2) ? 0 : hea[i-3].physicalOffset+hea[i-3].compressedSize; printf("Compressing %s ...",argv[i]); unsigned compressedSize = lzma_compress(input,packed, uncompressedSize,workmem); if (compressedSize >= uncompressedSize) { compressedSize = uncompressedSize; free(packed); ptrs[i-2] = input; } else { ptrs[i-2] = packed; free(input); } printf(" %d -> %d\n",uncompressedSize, compressedSize); hea[i-2].compressedSize = compressedSize; ++n; } for (i=0;i<n;i++) hea[i].physicalOffset += 4+n*sizeof(SCompBmpHeader); fwrite(&n,4,1,fo); fwrite(hea,sizeof(SCompBmpHeader),n,fo); for (i=0;i<n;i++) { fwrite(ptrs[i],1,hea[i].compressedSize,fo); free(ptrs[i]); } fclose(fo); free(hea); free(workmem); free(ptrs); return 0; }