write images in IDX2RLE format.

This commit is contained in:
Martin Preuss
2026-01-16 16:43:14 +01:00
parent 283374b5cd
commit 0d0b1d2fc6

View File

@@ -69,6 +69,12 @@ static int AQH_Tool_ExportBmpFile(const char *fname);
static int _exportBmp_1bpp(const BMP_FILE *bf); static int _exportBmp_1bpp(const BMP_FILE *bf);
static int _exportBmp_gray8bpp(const BMP_FILE *bf); static int _exportBmp_gray8bpp(const BMP_FILE *bf);
static GWEN_BUFFER *_extractPixels_gray8bpp(const uint8_t *ptrPixels, int imageWidth, int imageHeight);
static void _printBytes_ASM(const char *sName, const uint8_t *ptrPixels, int lenPixels, int imageWidth, int imageHeight);
static GWEN_BUFFER *_rleEncode(const uint8_t *ptrPixels, int lenPixels);
static int _countRepeats(const uint8_t *ptrPixels, int lenPixels);
static BMP_FILEHEADER *_fileHeader_new(); static BMP_FILEHEADER *_fileHeader_new();
static void _fileHeader_free(BMP_FILEHEADER *fh); static void _fileHeader_free(BMP_FILEHEADER *fh);
@@ -185,7 +191,6 @@ int AQH_Tool_ExportBmpFile(const char *fname)
int _exportBmp_1bpp(const BMP_FILE *bf) int _exportBmp_1bpp(const BMP_FILE *bf)
{ {
const uint8_t *ptrBuffer; const uint8_t *ptrBuffer;
uint32_t lenBuffer;
uint32_t offsPixels; uint32_t offsPixels;
const uint8_t *ptrPixels; const uint8_t *ptrPixels;
int imageWidth; int imageWidth;
@@ -195,7 +200,6 @@ int _exportBmp_1bpp(const BMP_FILE *bf)
int y; int y;
ptrBuffer=(const uint8_t *) GWEN_Buffer_GetStart(bf->buffer); ptrBuffer=(const uint8_t *) GWEN_Buffer_GetStart(bf->buffer);
lenBuffer=GWEN_Buffer_GetUsedBytes(bf->buffer);
offsPixels=bf->fileHeader->offsPixels; offsPixels=bf->fileHeader->offsPixels;
ptrPixels=ptrBuffer+offsPixels; ptrPixels=ptrBuffer+offsPixels;
imageWidth=bf->imageHeader->imgWidth; imageWidth=bf->imageHeader->imgWidth;
@@ -226,34 +230,51 @@ int _exportBmp_1bpp(const BMP_FILE *bf)
int _exportBmp_gray8bpp(const BMP_FILE *bf) int _exportBmp_gray8bpp(const BMP_FILE *bf)
{ {
const uint8_t *ptrBuffer; const uint8_t *ptrBuffer;
uint32_t lenBuffer;
uint32_t offsPixels; uint32_t offsPixels;
const uint8_t *ptrPixels; const uint8_t *ptrPixels;
int imageWidth; int imageWidth;
int imageHeight; int imageHeight;
int rowWidthInBytes; GWEN_BUFFER *pixelBuf;
int columns; GWEN_BUFFER *asmBuf;
int y;
ptrBuffer=(const uint8_t *) GWEN_Buffer_GetStart(bf->buffer); ptrBuffer=(const uint8_t *) GWEN_Buffer_GetStart(bf->buffer);
lenBuffer=GWEN_Buffer_GetUsedBytes(bf->buffer);
offsPixels=bf->fileHeader->offsPixels; offsPixels=bf->fileHeader->offsPixels;
ptrPixels=ptrBuffer+offsPixels; ptrPixels=ptrBuffer+offsPixels;
imageWidth=bf->imageHeader->imgWidth; imageWidth=bf->imageHeader->imgWidth;
imageHeight=bf->imageHeader->imgHeight; imageHeight=bf->imageHeader->imgHeight;
pixelBuf=_extractPixels_gray8bpp(ptrPixels, imageWidth, imageHeight);
asmBuf=_rleEncode((const uint8_t*) GWEN_Buffer_GetStart(pixelBuf), GWEN_Buffer_GetUsedBytes(pixelBuf));
_printBytes_ASM("imageData",
(const uint8_t*) GWEN_Buffer_GetStart(asmBuf), GWEN_Buffer_GetUsedBytes(asmBuf),
imageWidth, imageHeight);
fprintf(stderr, "Compression: %d -> %d bytes\n", GWEN_Buffer_GetUsedBytes(pixelBuf), GWEN_Buffer_GetUsedBytes(asmBuf));
GWEN_Buffer_free(asmBuf);
GWEN_Buffer_free(pixelBuf);
return 0;
}
GWEN_BUFFER *_extractPixels_gray8bpp(const uint8_t *ptrPixels, int imageWidth, int imageHeight)
{
int rowWidthInBytes;
int columns;
int y;
GWEN_BUFFER *destBuf;
destBuf=GWEN_Buffer_new(0, 256, 0, 1);
columns=imageWidth; columns=imageWidth;
rowWidthInBytes=4*((columns+3)/4); /* BMPs have multiple of 4 bytes per row! */ rowWidthInBytes=4*((columns+3)/4); /* BMPs have multiple of 4 bytes per row! */
fprintf(stdout, "imgData: \n");
fprintf(stdout, " .dw %d, %d\n", imageWidth, imageHeight);
for (y=imageHeight-1; y>=0; y--) { for (y=imageHeight-1; y>=0; y--) {
const uint8_t *rowPtr; const uint8_t *rowPtr;
int x; int x;
uint8_t currentByte=0; uint8_t currentByte=0;
int writtenBytes=0;
int packedPixels=0; int packedPixels=0;
fprintf(stdout, " .db ");
rowPtr=ptrPixels+(y*rowWidthInBytes); rowPtr=ptrPixels+(y*rowWidthInBytes);
for (x=0; x<columns; x++) { for (x=0; x<columns; x++) {
uint8_t pixel; uint8_t pixel;
@@ -271,15 +292,122 @@ int _exportBmp_gray8bpp(const BMP_FILE *bf)
currentByte|=newPix; currentByte|=newPix;
packedPixels++; packedPixels++;
if (packedPixels==4) { if (packedPixels==4) {
if (writtenBytes) GWEN_Buffer_AppendByte(destBuf, currentByte);
fprintf(stdout, ", "); packedPixels=0;
fprintf(stdout, "0x%02x", currentByte); currentByte=0;
writtenBytes++;
packedPixels=0;
currentByte=0;
} }
} }
fprintf(stdout, "\n"); }
if (GWEN_Buffer_GetUsedBytes(destBuf)==0) {
GWEN_Buffer_free(destBuf);
return NULL;
}
return destBuf;
}
void _printBytes_ASM(const char *sName, const uint8_t *ptrPixels, int lenPixels, int imageWidth, int imageHeight)
{
int i;
fprintf(stdout, "%s: \n", sName);
fprintf(stdout, " .dw %d, %d ; width, height\n", imageWidth, imageHeight);
for (i=0; i<lenPixels; i++) {
uint8_t currentByte;
currentByte=ptrPixels[i];
if ((i & 15)==0) {
if (i)
fprintf(stdout, "\n");
fprintf(stdout, " .db 0x%02x", currentByte);
}
else {
fprintf(stdout, ", 0x%02x", currentByte);
}
}
fprintf(stdout, "\n");
}
GWEN_BUFFER *_rleEncode(const uint8_t *ptrPixels, int lenPixels)
{
GWEN_BUFFER *resultBuf;
GWEN_BUFFER *currentBuf;
int numCurrentBuf;
resultBuf=GWEN_Buffer_new(0, 256, 0, 1);
currentBuf=GWEN_Buffer_new(0, 128, 0, 1);
while(ptrPixels && lenPixels>0) {
int countRepeats;
countRepeats=_countRepeats(ptrPixels, lenPixels);
if (countRepeats<4) {
GWEN_Buffer_AppendByte(currentBuf, *ptrPixels);
numCurrentBuf=GWEN_Buffer_GetUsedBytes(currentBuf);
if (numCurrentBuf==127) {
GWEN_Buffer_AppendByte(resultBuf, numCurrentBuf); /* bit 7 =0 */
GWEN_Buffer_AppendBytes(resultBuf, GWEN_Buffer_GetStart(currentBuf), numCurrentBuf);
GWEN_Buffer_Reset(currentBuf);
}
ptrPixels++;
lenPixels--;
}
else {
numCurrentBuf=GWEN_Buffer_GetUsedBytes(currentBuf);
if (numCurrentBuf>0) {
GWEN_Buffer_AppendByte(resultBuf, numCurrentBuf); /* bit 7 =0 */
GWEN_Buffer_AppendBytes(resultBuf, GWEN_Buffer_GetStart(currentBuf), numCurrentBuf);
GWEN_Buffer_Reset(currentBuf);
}
GWEN_Buffer_AppendByte(resultBuf, countRepeats | 128);
GWEN_Buffer_AppendByte(resultBuf, *ptrPixels);
ptrPixels+=countRepeats;
lenPixels-=countRepeats;
}
}
numCurrentBuf=GWEN_Buffer_GetUsedBytes(currentBuf);
if (numCurrentBuf>0) {
GWEN_Buffer_AppendByte(resultBuf, numCurrentBuf); /* bit 7 =0 */
GWEN_Buffer_AppendBytes(resultBuf, GWEN_Buffer_GetStart(currentBuf), numCurrentBuf);
}
GWEN_Buffer_free(currentBuf);
if (GWEN_Buffer_GetUsedBytes(resultBuf)==0) {
GWEN_Buffer_free(resultBuf);
return NULL;
}
return resultBuf;
}
int _countRepeats(const uint8_t *ptrPixels, int lenPixels)
{
if (ptrPixels && lenPixels) {
int currentByte;
int count=1;
currentByte=*(ptrPixels++);
lenPixels--;
while(ptrPixels && lenPixels) {
if (*ptrPixels==currentByte) {
count++;
if (count==127)
return count;
}
else
return count;
ptrPixels++;
lenPixels--;
}
return count;
} }
return 0; return 0;
} }
@@ -288,6 +416,7 @@ int _exportBmp_gray8bpp(const BMP_FILE *bf)
BMP_FILE *BMP_File_new(const char *fname) BMP_FILE *BMP_File_new(const char *fname)
{ {
BMP_FILE *bf; BMP_FILE *bf;