// Á¦ ¸ñ: Windows RLE(BMP) Encoder
// ÀÛ¼ºÀÚ: ±è¿µ´ë ( http://www.howto.pe.kr )
#include <stdio.h>
#include <fcntl.h>
#include <math.h>
#define BI_RGB 0
#define BI_RLE8 1
#define BI_RLE4 2
#define BI_bitfield 3
typedef struct tag_BITMAP_FILE_HEADER {
unsigned char bfType[2]; // ASCII "BM"
unsigned char bfSize[4]; // Àüü ÆÄÀÏÅ©±â
unsigned char bfReserved[4];
unsigned char bfOffBits[4]; // ½ÇÁ¦ raster pixel data°¡ ½ÃÀÛÇÏ´Â À§Ä¡
} BITMAP_FILE_HEADER;
typedef struct tag_BITMAP_INFO_HEADER {
unsigned char biSize[4]; // size of BITMAP_INFO_HEADER(40 bytes)
unsigned char biWidth[4];
unsigned char biHeight[4];
unsigned char biPlanes[2]; // Ç×»ó 1
unsigned char biBitCount[2]; // bits per pixel 1=mono,4=16,8=256,16=65536 High,24=2^24 True color
unsigned char biCompression[4]; // 0=no, 1=8bitRLE, 2=4bitRLE
unsigned char biSizeImage[4]; // ½ÇÁ¦ pixel dataÀÇ Å©±â=bfSize-bfOffBits
unsigned char biXPelsPerMeter[4]; // ¼öÆò resolution
unsigned char biYPelsPerMeter[4]; // ¼öÁ÷ resolution
unsigned char biClrUsed[4]; // Color Table(Palette)ÀÇ entry °¹¼ö(0 À̸é all used:2^BitCount °³)
unsigned char biClrImportant[4]; // biClrUsed¿Í °°´Ù
} BITMAP_INFO_HEADER;
typedef struct tag_COLOR_TABLE {
unsigned char bBlue; // Color Table(palette) Àº RGB°¡ ¾Æ´Ñ BGR formatÀ¸·Î ÀúÀåµÇ¾î ÀÖÀ½
unsigned char bGreen;
unsigned char bRed;
unsigned char bReserved; // padding
} COLOR_TABLE;
void pack_bytes(unsigned char dst[], long src, int bytes) {
int i;
for (i = 0; i < bytes; i++)
dst[i] = (src >> (8*i)) & 255;
}
long unpack_bytes(unsigned char src[], int bytes) {
int i;
long dst = 0;
for (i=bytes-1; i >= 0; i--)
dst += src[i] << (8*i);
return dst;
}
void print_header(BITMAP_FILE_HEADER *bmp_file, BITMAP_INFO_HEADER *bmp_info, COLOR_TABLE *color_table, int cu) {
int i;
printf("Bitmap File Header(14 bytes)n");
printf(" bfType(2 bytes): %c%c(%.2X%.2X)n",
bmp_file->bfType[0], bmp_file->bfType[1],
bmp_file->bfType[0], bmp_file->bfType[1]);
printf(" bfSize(4 bytes): %u(%.8X)n",
unpack_bytes(bmp_file->bfSize, sizeof(bmp_file->bfSize)),
unpack_bytes(bmp_file->bfSize, sizeof(bmp_file->bfSize)));
printf(" bfReserved(4 bytes): %u(%.8X)n",
unpack_bytes(bmp_file->bfReserved, sizeof(bmp_file->bfReserved)),
unpack_bytes(bmp_file->bfReserved, sizeof(bmp_file->bfReserved)));
printf(" bfOffBits(4 bytes): %u(%.8X)n",
unpack_bytes(bmp_file->bfOffBits, sizeof(bmp_file->bfOffBits)),
unpack_bytes(bmp_file->bfOffBits, sizeof(bmp_file->bfOffBits)));
printf("Bitmap Info Header(40 bytes)n");
printf(" biSize(4 bytes): %u(%.8X)n",
unpack_bytes(bmp_info->biSize, sizeof(bmp_info->biSize)),
unpack_bytes(bmp_info->biSize, sizeof(bmp_info->biSize)));
printf(" biWidth(4 bytes): %u(%.8X)n",
unpack_bytes(bmp_info->biWidth, sizeof(bmp_info->biWidth)),
unpack_bytes(bmp_info->biWidth, sizeof(bmp_info->biWidth)));
printf(" biHeight(4 bytes): %u(%.8X)n",
unpack_bytes(bmp_info->biHeight, sizeof(bmp_info->biHeight)),
unpack_bytes(bmp_info->biHeight, sizeof(bmp_info->biHeight)));
printf(" biPlanes(2 bytes): %u(%.4X)n",
unpack_bytes(bmp_info->biPlanes, sizeof(bmp_info->biPlanes)),
unpack_bytes(bmp_info->biPlanes, sizeof(bmp_info->biPlanes)));
printf(" biBitCount(2 bytes): %u(%.4X)n",
unpack_bytes(bmp_info->biBitCount, sizeof(bmp_info->biBitCount)),
unpack_bytes(bmp_info->biBitCount, sizeof(bmp_info->biBitCount)));
printf(" biCompression(4 bytes): %u(%.8X)n",
unpack_bytes(bmp_info->biCompression, sizeof(bmp_info->biCompression)),
unpack_bytes(bmp_info->biCompression, sizeof(bmp_info->biCompression)));
printf(" biSizeImage(4 bytes): %u(%.8X)n",
unpack_bytes(bmp_info->biSizeImage, sizeof(bmp_info->biSizeImage)),
unpack_bytes(bmp_info->biSizeImage, sizeof(bmp_info->biSizeImage)));
printf(" biXPelsPerMeter(4 bytes): %u(%.8X)n",
unpack_bytes(bmp_info->biXPelsPerMeter, sizeof(bmp_info->biXPelsPerMeter)),
unpack_bytes(bmp_info->biXPelsPerMeter, sizeof(bmp_info->biXPelsPerMeter)));
printf(" biYPelsPerMeter(4 bytes): %u(%.8X)n",
unpack_bytes(bmp_info->biYPelsPerMeter, sizeof(bmp_info->biYPelsPerMeter)),
unpack_bytes(bmp_info->biYPelsPerMeter, sizeof(bmp_info->biYPelsPerMeter)));
printf(" biClrUsed(4 bytes): %u(%.8X)n",
unpack_bytes(bmp_info->biClrUsed, sizeof(bmp_info->biClrUsed)),
unpack_bytes(bmp_info->biClrUsed, sizeof(bmp_info->biClrUsed)));
printf(" biClrImportant(4 bytes): %u(%.8X)n",
unpack_bytes(bmp_info->biClrImportant, sizeof(bmp_info->biClrImportant)),
unpack_bytes(bmp_info->biClrImportant, sizeof(bmp_info->biClrImportant)));
if (cu > 0) {
printf("ColorTable(4 * %d = %d bytes)n", cu, cu*4);
for (i=0; i < cu; i++) {
printf("%3d: ", i);
printf("R(%.2X) G(%.2X) B(%.2X) Padding(%.2X)n",
color_table[i].bRed,
color_table[i].bGreen,
color_table[i].bBlue,
color_table[i].bReserved);
}
}
}
main(int argc, char **argv) {
int ifd, ofd;
int bfSize, biHeight, biWidth, biBitCount, biClrUsed, biSizeImage;
int retbiSizeImage, retbiCompression;
int i, j, k, bnd, startWidth, endWidth;
BITMAP_FILE_HEADER bmp_file;
BITMAP_INFO_HEADER bmp_info;
COLOR_TABLE *color_table;
unsigned char *src_data, *tar_data;
if (argc != 3) {
fprintf(stderr, "»ç¿ë¹ý: %s sourceÆÄÀϸí targetÆÄÀϸín", argv[0]);
exit(1);
}
if ((ifd = open(argv[1], O_RDONLY)) < 0) {
fprintf(stderr, "%s ÆÄÀÏÀ» ÀÐÀ» ¼ö ¾ø½À´Ï´Ùn", argv[1]);
exit(1);
}
// sourceÆÄÀÏ¿¡¼ BITMAP_FILE_HEADER ¸¦ Àд´Ù
if (read(ifd, &bmp_file, sizeof(BITMAP_FILE_HEADER)) < sizeof(BITMAP_FILE_HEADER))
exit(1);
// sourceÆÄÀÏ¿¡¼ BITMAP_INFO_HEADER ¸¦ Àд´Ù
if (read(ifd, &bmp_info, sizeof(BITMAP_INFO_HEADER)) < sizeof(BITMAP_INFO_HEADER))
exit(1);
// BMP ÆÄÀÏÀÇ Çì´õ´Â "BM" À¸·Î ½ÃÀÛÇÑ´Ù
if (bmp_file.bfType[0] != 'B' ||
bmp_file.bfType[1] != 'M') {
fprintf(stderr, "%s ÆÄÀÏÀº BMP ÆÄÀÏÀÌ ¾Æ´Õ´Ï´Ùn", argv[1]);
close(ifd);
exit(1);
}
// ÀÌ¹Ì ¾ÐÃàµÇ¾î ÀÖ´Ù¸é ÁøÇàÀ» ÁßÁöÇÑ´Ù
if ((i=unpack_bytes(bmp_info.biCompression, sizeof(bmp_info.biCompression))) > BI_RGB) {
switch (i) {
case BI_RLE8:
fprintf(stderr, "%s ÆÄÀÏÀº ÀÌ¹Ì RLE-8 ·Î ¾ÐÃàµÇ¾î ÀÖ½À´Ï´Ùn", argv[1]);
break;
case BI_RLE4:
fprintf(stderr, "%s ÆÄÀÏÀº ÀÌ¹Ì RLE-4 ·Î ¾ÐÃàµÇ¾î ÀÖ½À´Ï´Ùn", argv[1]);
break;
case BI_bitfield:
fprintf(stderr, "%s ÆÄÀÏÀº ÀÌ¹Ì bit-field ·Î ¾ÐÃàµÇ¾î ÀÖ½À´Ï´Ùn", argv[1]);
break;
default:
fprintf(stderr, "%s ÆÄÀÏÀº ÀÌ¹Ì ¾Ë ¼ö ¾ø´Â formatÀ¸·Î ¾ÐÃàµÇ¾î ÀÖ½À´Ï´Ùn", argv[1]);
}
close(ifd);
exit(1);
}
if ((ofd = creat(argv[2], 0644)) < 0) {
fprintf(stderr, "%s ÆÄÀÏÀ» ¸¸µé ¼ö ¾ø½À´Ï´Ùn", argv[2]);
exit(1);
}
bfSize = unpack_bytes(bmp_file.bfSize, sizeof(bmp_file.bfSize));
biWidth = unpack_bytes(bmp_info.biWidth, sizeof(bmp_info.biWidth));
biHeight = unpack_bytes(bmp_info.biHeight, sizeof(bmp_info.biHeight));
biBitCount = unpack_bytes(bmp_info.biBitCount, sizeof(bmp_info.biBitCount));
biClrUsed = unpack_bytes(bmp_info.biClrUsed, sizeof(bmp_info.biClrUsed));
// sourceÆÄÀÏ¿¡¼ Color Table(Palette) À» Àд´Ù
color_table = NULL;
if (biBitCount > 0 && biBitCount <= 8) {
// Color Table ÀÇ entry °¹¼ö´Â 2^BitCount °³ ÀÌÁö¸¸ À̹ÌÁö¿¡¼ ½ÇÁ¦ »ç¿ëµÈ color ¸¸ ÀúÀåÇϱâ À§ÇØ
// biClrUsed °³ÀÇ entry¸¸ Color Table¿¡ »ç¿ëÇÑ´Ù
// ÇÏÁö¸¸ biClrUsed == 0 À̸é 2^BitCountÀ¸·Î ó¸®ÇؾßÇÑ´Ù
if (biClrUsed == 0)
biClrUsed = (int)pow(2, biBitCount); // 2 << (biBitCount-1)
color_table = (COLOR_TABLE *)malloc(biClrUsed * sizeof(COLOR_TABLE));
for (i=0; i < biClrUsed; i++)
if (read(ifd, &color_table[i], sizeof(COLOR_TABLE)) < sizeof(COLOR_TABLE))
exit(0);
}
// biSizeImage°¡ 0ÀÏ ¼ö ÀÖÀ¸¹Ç·Î biSizeImage°¡¸¦ Á÷Á¢ ±¸ÇÑ´Ù
biSizeImage = bfSize - (14+40+(biClrUsed*4));
// source/target Raster Data ¸¦ ÀúÀåÇÒ ¹öÆÛ
src_data = (char *)malloc(biSizeImage);
tar_data = (char *)malloc(biSizeImage * 2);
// sourceÆÄÀÏ¿¡¼ Raster Data ¸¦ Àд´Ù
if (read(ifd, src_data, biSizeImage) < biSizeImage)
exit(1);
// print_header(&bmp_file, &bmp_info, color_table, biClrUsed);
// target Raster DataÀÇ Å©±â´Â °è»êÇÏ¸é¼ Áõ°¡µÊ
retbiSizeImage = 0;
if (biBitCount == 1) { // 8 bit RLE encoding ÇÑ´Ù
retbiCompression = BI_RLE8;
for (i=0; i < biHeight; i++) {
if (biWidth%8 == 0) {
startWidth = i*(biWidth/8); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ data À§Ä¡
// 4 bytes bound °¡ raster data ¿¡ ÀÖÀ¸¹Ç·Î ½ÇÁ¦ rowÀÇ dataÀÇ À§Ä¡¸¦ º¸Á¤ ÇÑ´Ù
if ((biWidth/8) % 4 != 0)
startWidth += (i*(4-(biWidth/8)%4)); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ index À§Ä¡+padding bytes
endWidth = startWidth + (biWidth/8);
} else {
startWidth = i*(biWidth/8+1); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ data À§Ä¡
// 4 bytes bound °¡ raster data ¿¡ ÀÖÀ¸¹Ç·Î ½ÇÁ¦ rowÀÇ dataÀÇ À§Ä¡¸¦ º¸Á¤ ÇÑ´Ù
if ((biWidth/8+1) % 4 != 0)
startWidth += i*(4-(biWidth/8+1)%4); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ index À§Ä¡+padding bytes
endWidth = startWidth + (biWidth/8+1); // nibbleÀ» byte·Î ȯ»êÇÑ rowÀÇ ³¡ À§Ä¡(¸¶Áö¸· byteÀÇ nibbleÀº °è»ê¾ÈÇÔ)
}
j = startWidth;
while (1) {
// °°Àº ¼ýÀÚ°¡ ¹Ýº¹µÇ´Â length ¸¦ ã´Â´Ù
// example: 47 53 1E 0A 0A 0A 0A 05 05 3D 4C 01 01 || 01 B2 ...
k = j;
while ( (src_data[k] == src_data[k+1]) && ((k+1) < endWidth) && // 8bit°¡ 2°³ ÀÌ»ó ¹Ýº¹
((unsigned int)(k-j+1) <= 254) )
k++;
if ((k-j) > 0) {
tar_data[retbiSizeImage] = k-j+1; // Run Length
retbiSizeImage++;
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
j = k+1; // ´ÙÀ½ °Ë»çÇÒ À§Ä¡
if (tar_data[retbiSizeImage-2] >= 255)
continue;
}
if (j >= endWidth) // ÇÑ ÇàÀÇ °è»êÀÌ ³¡³²
break;
// °°Àº ¼ýÀÚ°¡ ¹Ýº¹µÇÁö ¾Ê´Â length ¸¦ ã´Â´Ù
k = j;
while ( (src_data[k] != src_data[k+1]) && (src_data[k+1] != src_data[k+2]) &&
((k+2) < endWidth) &&
((unsigned int)(k-j+1) <= 253) )
k += 2;
if ((k-j) > 0) { // example: 47 53 1E 0A 0A
tar_data[retbiSizeImage] = 0; // 0 = absolute mode
retbiSizeImage++;
tar_data[retbiSizeImage] = k-j+1; // directly drawn >= 3
retbiSizeImage++;
for (bnd=0; j <= k; j++, bnd++) {
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
}
if (bnd%2 == 1) { // Ȧ¼ö°³¿´´Ù¸é 16 bit boundary ½ÃŲ´Ù(2 byte ¾¿ ¦À» ÀÌ·ç¾î¾ß ÇÑ´Ù)
tar_data[retbiSizeImage] = 0;
retbiSizeImage++;
}
} else { // ¾Æ¹«°Íµµ °è»êµÇÁö ¾ÊÀ½
if (endWidth - j <= 2) { // °è»êÇÒ°ÍÀÌ 2°³ ÀÌÇÏ·Î ³²À¸¸é ±×³É Ãâ·Â
for (; j < endWidth; j++) {
tar_data[retbiSizeImage] = 1; // Run Length
retbiSizeImage++;
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
}
} else { // example: 1E 0A 0A ...
tar_data[retbiSizeImage] = 1; // Run Length
retbiSizeImage++;
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
j++; // ´ÙÀ½ °Ë»çÇÒ À§Ä¡
}
}
if (j >= endWidth) // ÇÑ ÇàÀÇ °è»êÀÌ ³¡³²
break;
}
tar_data[retbiSizeImage] = 0; // 0 = absolute mode
retbiSizeImage++;
tar_data[retbiSizeImage] = 0; // escape value: EOL(end of line)
retbiSizeImage++;
}
tar_data[retbiSizeImage] = 0; // 0 = absolute mode
retbiSizeImage++;
tar_data[retbiSizeImage] = 1; // escape value: EOB(end of bitmap)
retbiSizeImage++;
/*
retbiCompression = BI_RLE4;
for (i=0; i < biHeight; i++) {
if (biWidth%8 == 0) {
startWidth = i*(biWidth/8); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ data À§Ä¡
// 4 bytes bound °¡ raster data ¿¡ ÀÖÀ¸¹Ç·Î ½ÇÁ¦ rowÀÇ dataÀÇ À§Ä¡¸¦ º¸Á¤ ÇÑ´Ù
if ((biWidth/8) % 4 != 0)
startWidth += (i*(4-(biWidth/8)%4)); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ index À§Ä¡+padding bytes
endWidth = startWidth + (biWidth/8);
} else {
startWidth = i*(biWidth/8+1); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ data À§Ä¡
// 4 bytes bound °¡ raster data ¿¡ ÀÖÀ¸¹Ç·Î ½ÇÁ¦ rowÀÇ dataÀÇ À§Ä¡¸¦ º¸Á¤ ÇÑ´Ù
if ((biWidth/8+1) % 4 != 0)
startWidth += i*(4-(biWidth/8+1)%4); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ index À§Ä¡+padding bytes
endWidth = startWidth + (biWidth/8+1); // nibbleÀ» byte·Î ȯ»êÇÑ rowÀÇ ³¡ À§Ä¡(¸¶Áö¸· byteÀÇ nibbleÀº °è»ê¾ÈÇÔ)
}
j = startWidth;
while (1) {
// °°Àº ¼ýÀÚ°¡ ¹Ýº¹µÇ´Â length ¸¦ ã´Â´Ù
// ¿ø·¡´Â nibble´ÜÀ§·Î °è»êµÇ¾î¾ß Çϳª byte ´ÜÀ§·Î °è»êÇÔ
// example: 47 53 1E 0A 0A 0A 0A 05 05 3D 4C 01 01 || 01 B2 ...
k = j;
while ( (src_data[k] == src_data[k+1]) && ((k+1) < endWidth) && // 8bit°¡ 2°³ ÀÌ»ó ¹Ýº¹
((unsigned int)(2*(k-j+1)) <= 252) )
k++;
if ((k-j) > 0) {
tar_data[retbiSizeImage] = 2*(k-j+1); // Run Length
retbiSizeImage++;
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
j = k+1; // ´ÙÀ½ °Ë»çÇÒ À§Ä¡
if (tar_data[retbiSizeImage-2] >= 254)
continue;
}
if (j >= endWidth) // ÇÑ ÇàÀÇ °è»êÀÌ ³¡³²
break;
// °°Àº ¼ýÀÚ°¡ ¹Ýº¹µÇÁö ¾Ê´Â length ¸¦ ã´Â´Ù
k = j;
while ( (src_data[k] != src_data[k+1]) && ((k+1) < endWidth) &&
((unsigned int)(2*(k-j+1)) <= 252) )
k++;
if ((k-j) > 0) { // example: 47 53 1E 0A 0A
tar_data[retbiSizeImage] = 0; // 0 = absolute mode
retbiSizeImage++;
tar_data[retbiSizeImage] = 2*(k-j+1); // directly drawn >= 4
retbiSizeImage++;
for (bnd=0; j <= k; j++, bnd++) {
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
}
if (bnd%2 == 1) { // Ȧ¼ö°³¿´´Ù¸é 16 bit boundary ½ÃŲ´Ù(2 byte ¾¿ ¦À» ÀÌ·ç¾î¾ß ÇÑ´Ù)
tar_data[retbiSizeImage] = 0;
retbiSizeImage++;
}
} else { // ¾Æ¹«°Íµµ °è»êµÇÁö ¾ÊÀ½
if (endWidth - j <= 1) { // °è»êÇÒ°ÍÀÌ 1°³ ÀÌÇÏ·Î ³²À¸¸é ±×³É Ãâ·Â
for (; j < endWidth; j++) {
tar_data[retbiSizeImage] = (biWidth%8>4)?2:1; // Run Length(Ȧ¼ö widthÀÇ ¸¶Áö¸· byteÀÇ nibbleÀº 1)
retbiSizeImage++;
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
}
}
}
if (j >= endWidth) // ÇÑ ÇàÀÇ °è»êÀÌ ³¡³²
break;
}
tar_data[retbiSizeImage] = 0; // 0 = absolute mode
retbiSizeImage++;
tar_data[retbiSizeImage] = 0; // escape value: EOL(end of line)
retbiSizeImage++;
}
tar_data[retbiSizeImage] = 0; // 0 = absolute mode
retbiSizeImage++;
tar_data[retbiSizeImage] = 1; // escape value: EOB(end of bitmap)
retbiSizeImage++;
*/
}
else if (biBitCount == 4) { // 4 bit RLE encoding ÇÑ´Ù(ÀüºÎ nibbleÀ» byte·Î ȯ»êÇÏ¿© °è»êµÊ)
retbiCompression = BI_RLE4;
for (i=0; i < biHeight; i++) {
if (biWidth%2 == 0) {
startWidth = i*(biWidth/2); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ data À§Ä¡
// 4 bytes bound °¡ raster data ¿¡ ÀÖÀ¸¹Ç·Î ½ÇÁ¦ rowÀÇ dataÀÇ À§Ä¡¸¦ º¸Á¤ ÇÑ´Ù
if ((biWidth/2) % 4 != 0)
startWidth += (i*(4-(biWidth/2)%4)); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ index À§Ä¡+padding bytes
endWidth = startWidth + (biWidth/2);
} else {
startWidth = i*(biWidth/2+1); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ data À§Ä¡
// 4 bytes bound °¡ raster data ¿¡ ÀÖÀ¸¹Ç·Î ½ÇÁ¦ rowÀÇ dataÀÇ À§Ä¡¸¦ º¸Á¤ ÇÑ´Ù
if ((biWidth/2+1) % 4 != 0)
startWidth += i*(4-(biWidth/2+1)%4); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ index À§Ä¡+padding bytes
endWidth = startWidth + (biWidth/2+1); // nibbleÀ» byte·Î ȯ»êÇÑ rowÀÇ ³¡ À§Ä¡(¸¶Áö¸· byteÀÇ nibbleÀº °è»ê¾ÈÇÔ)
}
j = startWidth;
while (1) {
// °°Àº ¼ýÀÚ°¡ ¹Ýº¹µÇ´Â length ¸¦ ã´Â´Ù
// ¿ø·¡´Â nibble´ÜÀ§·Î °è»êµÇ¾î¾ß Çϳª byte ´ÜÀ§·Î °è»êÇÔ
// example: 47 53 1E 0A 0A 0A 0A 05 05 3D 4C 01 01 || 01 B2 ...
k = j;
while ( (src_data[k] == src_data[k+1]) && ((k+1) < endWidth) && // 8bit°¡ 2°³ ÀÌ»ó ¹Ýº¹
((unsigned int)(2*(k-j+1)) <= 252) )
k++;
if ((k-j) > 0) {
tar_data[retbiSizeImage] = 2*(k-j+1); // Run Length
retbiSizeImage++;
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
j = k+1; // ´ÙÀ½ °Ë»çÇÒ À§Ä¡
if (tar_data[retbiSizeImage-2] >= 254)
continue;
}
if (j >= endWidth) // ÇÑ ÇàÀÇ °è»êÀÌ ³¡³²
break;
// °°Àº ¼ýÀÚ°¡ ¹Ýº¹µÇÁö ¾Ê´Â length ¸¦ ã´Â´Ù
k = j;
while ( (src_data[k] != src_data[k+1]) && ((k+1) < endWidth) &&
((unsigned int)(2*(k-j+1)) <= 252) )
k++;
if ((k-j) > 0) { // example: 47 53 1E 0A 0A
tar_data[retbiSizeImage] = 0; // 0 = absolute mode
retbiSizeImage++;
tar_data[retbiSizeImage] = 2*(k-j+1); // directly drawn >= 4
retbiSizeImage++;
for (bnd=0; j <= k; j++, bnd++) {
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
}
if (bnd%2 == 1) { // Ȧ¼ö°³¿´´Ù¸é 16 bit boundary ½ÃŲ´Ù(2 byte ¾¿ ¦À» ÀÌ·ç¾î¾ß ÇÑ´Ù)
tar_data[retbiSizeImage] = 0;
retbiSizeImage++;
}
} else { // ¾Æ¹«°Íµµ °è»êµÇÁö ¾ÊÀ½
if (endWidth - j <= 1) { // °è»êÇÒ°ÍÀÌ 1°³ ÀÌÇÏ·Î ³²À¸¸é ±×³É Ãâ·Â
for (; j < endWidth; j++) {
tar_data[retbiSizeImage] = (biWidth%2)?1:2; // Run Length(Ȧ¼ö widthÀÇ ¸¶Áö¸· byteÀÇ nibbleÀº 1)
retbiSizeImage++;
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
}
}
}
if (j >= endWidth) // ÇÑ ÇàÀÇ °è»êÀÌ ³¡³²
break;
}
tar_data[retbiSizeImage] = 0; // 0 = absolute mode
retbiSizeImage++;
tar_data[retbiSizeImage] = 0; // escape value: EOL(end of line)
retbiSizeImage++;
}
tar_data[retbiSizeImage] = 0; // 0 = absolute mode
retbiSizeImage++;
tar_data[retbiSizeImage] = 1; // escape value: EOB(end of bitmap)
retbiSizeImage++;
}
else if (biBitCount == 8) { // 8 bit RLE encoding ÇÑ´Ù
retbiCompression = BI_RLE8;
for (i=0; i < biHeight; i++) {
startWidth = i*biWidth; // °Ë»çÇÒ rowÀÇ ½ÃÀÛ data À§Ä¡
// 4 bytes bound °¡ raster data ¿¡ ÀÖÀ¸¹Ç·Î ½ÇÁ¦ rowÀÇ dataÀÇ À§Ä¡¸¦ º¸Á¤ ÇÑ´Ù
if (biWidth % 4 != 0)
startWidth += i*(4-biWidth%4); // °Ë»çÇÒ rowÀÇ ½ÃÀÛ index À§Ä¡+padding bytes
endWidth = startWidth + biWidth;
j = startWidth;
while (1) {
// °°Àº ¼ýÀÚ°¡ ¹Ýº¹µÇ´Â length ¸¦ ã´Â´Ù
// example: 47 53 1E 0A 0A 0A 0A 05 05 3D 4C 01 01 || 01 B2 ...
k = j;
while ( (src_data[k] == src_data[k+1]) && ((k+1) < endWidth) && // 8bit°¡ 2°³ ÀÌ»ó ¹Ýº¹
((unsigned int)(k-j+1) <= 254) )
k++;
if ((k-j) > 0) {
tar_data[retbiSizeImage] = k-j+1; // Run Length
retbiSizeImage++;
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
j = k+1; // ´ÙÀ½ °Ë»çÇÒ À§Ä¡
if (tar_data[retbiSizeImage-2] >= 255)
continue;
}
if (j >= endWidth) // ÇÑ ÇàÀÇ °è»êÀÌ ³¡³²
break;
// °°Àº ¼ýÀÚ°¡ ¹Ýº¹µÇÁö ¾Ê´Â length ¸¦ ã´Â´Ù
k = j;
while ( (src_data[k] != src_data[k+1]) && (src_data[k+1] != src_data[k+2]) &&
((k+2) < endWidth) &&
((unsigned int)(k-j+1) <= 253) )
k += 2;
if ((k-j) > 0) { // example: 47 53 1E 0A 0A
tar_data[retbiSizeImage] = 0; // 0 = absolute mode
retbiSizeImage++;
tar_data[retbiSizeImage] = k-j+1; // directly drawn >= 3
retbiSizeImage++;
for (bnd=0; j <= k; j++, bnd++) {
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
}
if (bnd%2 == 1) { // Ȧ¼ö°³¿´´Ù¸é 16 bit boundary ½ÃŲ´Ù(2 byte ¾¿ ¦À» ÀÌ·ç¾î¾ß ÇÑ´Ù)
tar_data[retbiSizeImage] = 0;
retbiSizeImage++;
}
} else { // ¾Æ¹«°Íµµ °è»êµÇÁö ¾ÊÀ½
if (endWidth - j <= 2) { // °è»êÇÒ°ÍÀÌ 2°³ ÀÌÇÏ·Î ³²À¸¸é ±×³É Ãâ·Â
for (; j < endWidth; j++) {
tar_data[retbiSizeImage] = 1; // Run Length
retbiSizeImage++;
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
}
} else { // example: 1E 0A 0A ...
tar_data[retbiSizeImage] = 1; // Run Length
retbiSizeImage++;
tar_data[retbiSizeImage] = src_data[j]; // Raster Pixel index
retbiSizeImage++;
j++; // ´ÙÀ½ °Ë»çÇÒ À§Ä¡
}
}
if (j >= endWidth) // ÇÑ ÇàÀÇ °è»êÀÌ ³¡³²
break;
}
tar_data[retbiSizeImage] = 0; // 0 = absolute mode
retbiSizeImage++;
tar_data[retbiSizeImage] = 0; // escape value: EOL(end of line)
retbiSizeImage++;
}
tar_data[retbiSizeImage] = 0; // 0 = absolute mode
retbiSizeImage++;
tar_data[retbiSizeImage] = 1; // escape value: EOB(end of bitmap)
retbiSizeImage++;
}
else if (biBitCount == 16) {
}
else if (biBitCount == 24) {
}
// BITMAP_FILE_HEADER.bfSize
pack_bytes(bmp_file.bfSize,
14+40+ (biClrUsed*4) + retbiSizeImage,
sizeof(bmp_file.bfSize));
// BITMAP_INFO_HEADER.biCompression
pack_bytes(bmp_info.biCompression,
retbiCompression, // RLE encoding
sizeof(bmp_info.biCompression));
// BITMAP_INFO_HEADER.biSizeImage
pack_bytes(bmp_info.biSizeImage,
retbiSizeImage,
sizeof(bmp_info.biSizeImage));
// print_header(&bmp_file, &bmp_info, color_table, biClrUsed);
// targetÆÄÀÏ¿¡ BITMAP_FILE_HEADER ¸¦ ¾´´Ù
write(ofd, &bmp_file, sizeof(BITMAP_FILE_HEADER));
// targetÆÄÀÏ¿¡ BITMAP_INFO_HEADER ¸¦ ¾´´Ù
write(ofd, &bmp_info, sizeof(BITMAP_INFO_HEADER));
// targetÆÄÀÏ¿¡ Color Table ¸¦ ¾´´Ù
if (color_table != NULL)
for (i=0; i < biClrUsed; i++)
write(ofd, &color_table[i], sizeof(COLOR_TABLE));
// targetÆÄÀÏ¿¡ RLE encoded Raster Data¸¦ ¾´´Ù
write(ofd, tar_data, retbiSizeImage);
free(color_table);
free(src_data);
free(tar_data);
close(ifd);
close(ofd);
} |
|