c2fbdf929c
git-svn-id: svn://kolibrios.org@1805 a494cfbc-eb01-0410-851d-a64ba20cac60
167 lines
4.2 KiB
C++
167 lines
4.2 KiB
C++
#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;
|
|
}
|