::: 강좌/소스/문서 :::

강좌/소스/문서 성격에 맞지 않는 광고,비방,질문의 글은 즉시 삭제하며
내용을 복사하여 사용할 경우 반드시 이곳(http://www.howto.pe.kr)을 출처로 명시하여 주세요


Category

  김영대(2003-03-18 22:36:40, Hit : 7510, Vote : 1326
 [소스] Windows RLE(BMP) Encoder

// 제  목: 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);
}    





13   [컴퓨터 전공] [소스] 이진 트리(Binary Tree)  김영대 2004/06/18 9784 1823
12   [컴퓨터 전공] [소스] MASM 간단한 계산기 어셈블리 프로그램 소스  김영대 2003/07/11 9634 1505
11   [컴퓨터 전공] [소스] Top-down parsing by Recursive-Descent 을 이용한 계산기 MASM 어셈블리 생성기  김영대 2003/07/11 7481 1603
10   [컴퓨터 전공] [소스] Huffman Code Encoder  김영대 2003/03/18 7818 1503
  [컴퓨터 전공] [소스] Windows RLE(BMP) Encoder  김영대 2003/03/18 7510 1326
8   [컴퓨터 전공] [소스] CompuServe RLE Encoder  김영대 2003/03/18 6172 1438
7   [컴퓨터 전공] [소스] 계산기를 위한 Lex & Yacc  김영대 2003/03/15 9806 1599
6   [컴퓨터 전공] [소스] ANSI-C 파서를 위한 Lex & Yacc  김영대 2003/03/13 8644 1931
5   [컴퓨터 전공] [소스] PL/0 Compiler 구현  김영대 2003/03/13 7435 1693
4   [컴퓨터 전공] [소스] Recursive-Descent 파싱을 이용한 계산기 구현  김영대 2003/03/13 10276 1613
3   [컴퓨터 전공] [소스] POSIX thread를 사용한 행렬계산  김영대 2003/03/13 7356 1510
2   [컴퓨터 전공] [소스] 0/1 배낭 문제(Knapsack Problem)  김영대 2003/03/13 9027 1601
1   [컴퓨터 전공] [소스] SIC/XE 어셈블러 구현  김영대 2003/03/13 18545 1858

1
 

Copyright 1999-2017 Zeroboard / skin by zero