[ create a new paste ] login | about

Link: http://codepad.org/i6XH6wiR    [ raw code | output | fork ]

C, pasted on Jul 27:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct {
  unsigned char bfType1;
  unsigned char bfType2;
  unsigned long bfSize;
  unsigned short bfReserved1;
  unsigned short bfReserved2;
  unsigned long bfOffBits;
} BitmapFileHeader;

int bmHeaderCheck(FILE *fp, BitmapFileHeader *bh) {
  assert(sizeof(unsigned short) == 2);
  assert(sizeof(unsigned long) == 4);
  if (fread(&(bh->bfType1), sizeof(unsigned char), 1, fp) != 1)
    goto error_NotRead;
  if (fread(&(bh->bfType2), sizeof(unsigned char), 1, fp) != 1)
    goto error_NotRead;
  if (fread(&(bh->bfSize), sizeof(unsigned long), 1, fp) != 1)
    goto error_NotRead;
  if (fread(&(bh->bfReserved1), sizeof(unsigned short), 1, fp) != 1)
    goto error_NotRead;
  if (fread(&(bh->bfReserved2), sizeof(unsigned short), 1, fp) != 1)
    goto error_NotRead;
  if (fread(&(bh->bfOffBits), sizeof(unsigned long), 1, fp) != 1)
    goto error_NotRead;
  if (bh->bfType1 != 'B' || bh->bfType2 != 'M')
    goto error_NotBitmap;
  if (bh->bfReserved1 != 0 || bh->bfReserved2 != 0)
    goto error_NotBitmap;
  printf("bfType1: %c\n", bh->bfType1);
  printf("bfType2: %c\n", bh->bfType2);
  printf("bfSize: %lu\n", bh->bfSize);
  printf("bfReserved1: %u\n", bh->bfReserved1);
  printf("bfReserved2: %u\n", bh->bfReserved2);
  printf("bfOffBits: %lu\n", bh->bfOffBits);
  putchar('\n');
  return 1;

error_NotBitmap:
  fprintf(stderr, "cannot find bmp header\n");
  return 0;
error_NotRead:
  fprintf(stderr, "cannot read bmp header\n");
  return 0;
}

typedef struct {
  unsigned long biSize;
  long biWidth;
  long biHeight;
  unsigned short biPlanes;
  unsigned short biBitCount;
  unsigned long biCompression;
  unsigned long biSizeImage;
  long biXPixPerMeter;
  long biYPixPerMeter;
  unsigned long biClrUsed;
  unsigned long biClrImportant;
} BitmapInfoHeader;

int bmInfoHeaderCheck(FILE *fp, BitmapInfoHeader *bi)
{
  assert(sizeof(unsigned short) == 2);
  assert(sizeof(unsigned long) == 4);
  assert(sizeof(long) == 4);
  if (fread(&(bi->biSize), sizeof(unsigned long), 1, fp) != 1)
    goto error_NotRead;
  if (bi->biSize == 12) {
    bi->biWidth = 0;
    if (fread(&(bi->biWidth), sizeof(short), 1, fp) != 1)
      goto error_NotRead;
    bi->biHeight = 0;
    if (fread(&(bi->biHeight), sizeof(short), 1, fp) != 1)
      goto error_NotRead;
    if (fread(&(bi->biPlanes), sizeof(unsigned short), 1, fp) != 1)
      goto error_NotRead;
    if (fread(&(bi->biBitCount), sizeof(unsigned short), 1, fp) != 1)
      goto error_NotRead;
    if (bi->biWidth > 32768)
      bi->biWidth = -bi->biWidth;
    if (bi->biHeight > 32768)
      bi->biWidth = -bi->biHeight;
  } else if (bi->biSize == 40) {
    if (fread(&(bi->biWidth), sizeof(long), 1, fp) != 1)
      goto error_NotRead;
    if (fread(&(bi->biHeight), sizeof(long), 1, fp) != 1)
      goto error_NotRead;
    if (fread(&(bi->biPlanes), sizeof(unsigned short), 1, fp) != 1)
      goto error_NotRead;
    if (fread(&(bi->biBitCount), sizeof(unsigned short), 1, fp) != 1)
      goto error_NotRead;
    if (fread(&(bi->biCompression), sizeof(unsigned long), 1, fp) != 1)
      goto error_NotRead;
    if (fread(&(bi->biSizeImage), sizeof(unsigned long), 1, fp) != 1)
      goto error_NotRead;
    if (fread(&(bi->biXPixPerMeter), sizeof(long), 1, fp) != 1)
      goto error_NotRead;
    if (fread(&(bi->biYPixPerMeter), sizeof(long), 1, fp) != 1)
      goto error_NotRead;
    if (fread(&(bi->biClrUsed), sizeof(unsigned long), 1, fp) != 1)
      goto error_NotRead;
    if (fread(&(bi->biClrImportant), sizeof(unsigned long), 1, fp) != 1)
      goto error_NotRead;
  } else
    goto error_NotSupported1;
  printf("biSize: %lu\n", bi->biSize);
  printf("biWidth: %ld\n", bi->biWidth);
  printf("biHeight: %ld\n", bi->biHeight);
  printf("biPlanes: %u\n", bi->biPlanes);
  printf("biBitcount: %u\n", bi->biBitCount);
  if (bi->biSize == 40) {
    printf("biCompression: %lu\n", bi->biCompression);
    printf("biSizeImage: %lu\n", bi->biSizeImage);
    printf("biXPixPerMeter %ld\n", bi->biXPixPerMeter);
    printf("biYPixPerMeter %ld\n", bi->biYPixPerMeter);
    printf("biClrUsed: %lu\n", bi->biClrUsed);
    printf("biClrImporant: %lu\n", bi->biClrImportant);
  }
  putchar('\n');
  if (bi->biSize != 40)
    goto error_NotSupported1;
  if (bi->biPlanes != 1)
    goto error_NotSupported2;
  if (bi->biBitCount != 24 && bi->biBitCount != 8)
    goto error_NotSupported3;
  if (bi->biCompression != 0)
    goto error_NotSupported4;
  return 1;

error_NotSupported1:
  fprintf(stderr, "info header size: this format is not supported\n");
  return 0;
error_NotSupported2:
  fprintf(stderr, "biPlanes: this format is not supported\n");
  return 0;
error_NotSupported3:
  fprintf(stderr, "biBitCount: this format is not supported\n");
  return 0;
error_NotSupported4:
  fprintf(stderr, "biCompression: this format is not supported\n");
  return 0;
error_NotRead:
  fprintf(stderr, "cannot read bmp info header\n");
  return 0;
}

int isFtellGood(FILE *fp, unsigned long pos) {
  return (unsigned long)ftell(fp) == pos;
}

long iabs(long n) {
  return (n > 0) ? n : -n;
}

void task_read24(FILE *fp, BitmapFileHeader *bheader, BitmapInfoHeader *binfo,
               unsigned char **dataR, unsigned char **dataG,
               unsigned char **dataB)
{
  long x, y;
  unsigned char dummy;
  int c;
  if (!isFtellGood(fp, bheader->bfOffBits)) {
    fprintf(stderr, "Header or Image Data is corrupted.\n");
    return;
  }
  *dataR = malloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight));
  *dataG = malloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight));
  *dataB = malloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight));  
  if (*dataR == NULL || *dataG == NULL || *dataB == NULL) {
    fprintf(stderr, "cannot alloc. enough memory.\n");
    return;
  }
  for (y = 0; y < iabs(binfo->biHeight); y++) {
    c = 0;
    for (x = 0; x < iabs(binfo->biWidth); x++) {
      fread((*dataB + y * iabs(binfo->biWidth) + x), 1, 1, fp);
      fread((*dataG + y * iabs(binfo->biWidth) + x), 1, 1, fp);
      fread((*dataR + y * iabs(binfo->biWidth) + x), 1, 1, fp);
      c += 3;
    }
    while (c % 4 != 0) {
      fread(&dummy, 1, 1, fp);
      c++;
    }
  }
  return;
}

void task_read_palette(FILE *fp, BitmapFileHeader *bh, BitmapInfoHeader *bi,
                       unsigned char **dataPalette)
{
  int i, max;
  unsigned char dummy;
  if ((max = bi->biClrUsed) == 0)
    max = 256;
  *dataPalette = malloc(sizeof(char) * 3 * max);
  if (*dataPalette == NULL) {
    fprintf(stderr, "cannot alloc. enough memory.\n");
    return;
  }
  for (i = 0; i < max; i++) {
    fread((*dataPalette + 3 * i + 0), 1, 1, fp);
    fread((*dataPalette + 3 * i + 1), 1, 1, fp);
    fread((*dataPalette + 3 * i + 2), 1, 1, fp);
    fread(&dummy, 1, 1, fp);    
  }
}

void task_read8(FILE *fp, BitmapFileHeader *bheader, BitmapInfoHeader *binfo,
               unsigned char **dataR, unsigned char **dataG,
               unsigned char **dataB, unsigned char *dataPalette)
{
  long x, y;
  unsigned char data;
  int c;

  if (!isFtellGood(fp, bheader->bfOffBits)) {
    fprintf(stderr, "Header or Image Data is corrupted.\n");
    return;
  }
  *dataR = malloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight));
  *dataG = malloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight));
  *dataB = malloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight));  
  if (*dataR == NULL || *dataG == NULL || *dataB == NULL) {
    fprintf(stderr, "cannot alloc. enough memory.\n");
    return;
  }
  for (y = 0; y < iabs(binfo->biHeight); y++) {
    c = 0;
    for (x = 0; x < iabs(binfo->biWidth); x++) {
      fread(&data, 1, 1, fp);
      *(*dataB + y * iabs(binfo->biWidth) + x) = dataPalette[3 * data + 0];
      *(*dataG + y * iabs(binfo->biWidth) + x) = dataPalette[3 * data + 1];
      *(*dataR + y * iabs(binfo->biWidth) + x) = dataPalette[3 * data + 2];
      c++;
    }
    while (c % 4 != 0) {
      fread(&data, 1, 1, fp);
      c++;
    }
  }
}

void task_write_header(FILE *fp, BitmapFileHeader *bh) {
  assert(sizeof(unsigned short) == 2);
  assert(sizeof(unsigned long) == 4);
  fwrite(&(bh->bfType1), sizeof(unsigned char), 1, fp);
  fwrite(&(bh->bfType2), sizeof(unsigned char), 1, fp);
  fwrite(&(bh->bfSize), sizeof(unsigned long), 1, fp);
  fwrite(&(bh->bfReserved1), sizeof(unsigned short), 1, fp);
  fwrite(&(bh->bfReserved2), sizeof(unsigned short), 1, fp);
  fwrite(&(bh->bfOffBits), sizeof(unsigned long), 1, fp);
}

void task_write_info(FILE *fp, BitmapInfoHeader *bi) {
  assert(sizeof(unsigned short) == 2);
  assert(sizeof(unsigned long) == 4);
  assert(sizeof(long) == 4);
  fwrite(&(bi->biSize), sizeof(unsigned long), 1, fp);
  fwrite(&(bi->biWidth), sizeof(long), 1, fp);
  fwrite(&(bi->biHeight), sizeof(long), 1, fp);
  fwrite(&(bi->biPlanes), sizeof(unsigned short), 1, fp);
  fwrite(&(bi->biBitCount), sizeof(unsigned short), 1, fp);
  fwrite(&(bi->biCompression), sizeof(unsigned long), 1, fp);
  fwrite(&(bi->biSizeImage), sizeof(unsigned long), 1, fp);
  fwrite(&(bi->biXPixPerMeter), sizeof(long), 1, fp);
  fwrite(&(bi->biYPixPerMeter), sizeof(long), 1, fp);
  fwrite(&(bi->biClrUsed), sizeof(unsigned long), 1, fp);
  fwrite(&(bi->biClrImportant), sizeof(unsigned long), 1, fp);
}

void task_write24(FILE *fp, BitmapFileHeader *bh, BitmapInfoHeader *bi,
                unsigned char *dataR, unsigned char *dataG, unsigned char *dataB)
{
  int x, y;
  int c;
  unsigned char dummy = '\0';
  task_write_header(fp, bh);
  task_write_info(fp, bi);
  for (y = 0; y < iabs(bi->biHeight); y++) {
    c = 0;
    for (x = 0; x < iabs(bi->biWidth); x++) {
      fwrite(&dataB[y * iabs(bi->biWidth) + x], 1, 1, fp);
      fwrite(&dataG[y * iabs(bi->biWidth) + x], 1, 1, fp);
      fwrite(&dataR[y * iabs(bi->biWidth) + x], 1, 1, fp);
      c += 3;
    }
    while (c % 4 != 0) {
      fwrite(&dummy, 1, 1, fp);
      c++;
    }
  }
}

#define LOW 100
#define HIGH 150
int isBetween2(unsigned char c) {
  if (c >= LOW && c <= HIGH)
    return 1;
  else
    return 0;
}

int isBetween(unsigned char r, unsigned char g, unsigned char b) {
  return isBetween2(r) && isBetween2(g) && isBetween2(b);
}

void task_convert(BitmapFileHeader *bh, BitmapInfoHeader *bi,
                     unsigned char *dataR, unsigned char *dataG, unsigned char *dataB)
{
  unsigned long x, y, idx;
    for (y = 0; y < iabs(bi->biHeight); y++)
      for (x = 0; x < iabs(bi->biWidth); x++) {
        idx = y * bi->biWidth + x;
        if (isBetween(dataR[idx], dataG[idx], dataB[idx]))
          dataR[idx] = dataG[idx] = dataB[idx] = 255;
        else
          dataR[idx] = dataG[idx] = dataB[idx] = 0;
      }
}

int main(int argc, char *argv[]) {
  FILE *fp;
  BitmapFileHeader bheader;
  BitmapInfoHeader binfo;
  unsigned char *dataR, *dataG, *dataB, *dataPalette;

  if ((fp = fopen(argv[1], "rb")) == NULL) {
    fprintf(stderr, "cannot open the file \"%s\".\n", argv[1]);
    return -1;
  }
  if(!bmHeaderCheck(fp, &bheader)) {
    fprintf(stderr, "cannot handle the file \"%s\".\n", argv[1]);
    return -1;
  }
  if (!bmInfoHeaderCheck(fp, &binfo)) {
    fprintf(stderr, "cannot handle the file \"%s\".\n", argv[1]);
    return -1;
  }
  dataR = dataG = dataB = dataPalette = NULL;
  if (binfo.biBitCount == 24) {
    int n;
    task_read24(fp, &bheader, &binfo, &dataR, &dataG, &dataB);
    n = iabs(binfo.biWidth) * 3;
    if (n % 4 > 0)
      n += 4 - (n % 4);
    binfo.biSizeImage = n * iabs(binfo.biHeight);
    bheader.bfSize = binfo.biSizeImage + binfo.biSize + 14;
  } else if (binfo.biBitCount == 8) {
    int n;
    task_read_palette(fp, &bheader, &binfo, &dataPalette);
    task_read8(fp, &bheader, &binfo, &dataR, &dataG, &dataB, dataPalette);
    free(dataPalette);
    n = iabs(binfo.biWidth) * 3;
    if (n % 4 > 0)
      n += 4 - (n % 4);
    binfo.biSizeImage = n * iabs(binfo.biHeight);
    bheader.bfSize = binfo.biSizeImage + binfo.biSize + 14;
    bheader.bfOffBits = 54;
    binfo.biBitCount = 24;
    binfo.biClrUsed = 0;
    binfo.biClrImportant = 0;
  }
  fclose(fp);
  if (dataR && dataG && dataB) {
    task_convert(&bheader, &binfo, dataR, dataG, dataB);
    if ((fp = fopen(argv[2], "wb")) == NULL) {
      fprintf(stderr, "cannot open the file \"%s\".\n", argv[2]);
      return -1;
    }
    task_write24(fp, &bheader, &binfo, dataR, dataG, dataB);
    fclose(fp);
  }
  free(dataR);
  free(dataG);
  free(dataB);
  return 0;
}
/* end */


Output:
1
2
3
cannot open the file "(null)".

Exited: ExitFailure 255


Create a new paste based on this one


Comments: