Blame simple/imgfilters/img.ldr.tga.inc.c

608c44
608c44
608c44
#pragma pack(push,1)
608c44
typedef struct {
608c44
  unsigned char  idLength;
608c44
  unsigned char  colormapType;
608c44
  unsigned char  imageType;
608c44
  unsigned char  colormapIndex[2];
608c44
  unsigned char  colormapLength[2];
608c44
  unsigned char  colormapSize;
608c44
  unsigned char  xOrigin[2];
608c44
  unsigned char  yOrigin[2];
608c44
  unsigned char  width[2];
608c44
  unsigned char  height[2];
608c44
  unsigned char  pixelSize;
608c44
  unsigned char  attributes;
608c44
} TgaHeader;
608c44
#pragma pack(pop)
608c44
608c44
608c44
unsigned short getLEU16(unsigned char *c)
608c44
    { return c[0] | ((unsigned short)c[1] << 8); }
608c44
void setLEU16(unsigned char *c, unsigned short i)
608c44
    { c[0] = i; c[1] = i >> 8; }
608c44
608c44
608c44
int imageLoadTga(const char *path, int *outWidth, int *outHeight, unsigned char **pixels) {
608c44
  *outWidth = *outHeight = 0; *pixels = NULL;
608c44
608c44
  FILE *f = fopen(path, "rb");
608c44
    if (!f) {
608c44
    fprintf(stderr, "Cannot open for read: %s\n", path);
608c44
    fflush(stderr);
608c44
    return FALSE;
608c44
  }
608c44
608c44
  TgaHeader header = {};
608c44
  fread(&header, sizeof(header), 1, f); // todo: endianess
608c44
608c44
  //printf("%d %d %d %d %d\n", header.imageType, header.width, header.height, header.colormapType, header.pixelSize);
608c44
608c44
  if ( header.imageType != 2
608c44
    || !header.width
608c44
    || !header.height
608c44
    || header.colormapType
608c44
    || (header.pixelSize != 24 && header.pixelSize != 32)
608c44
  ) {
608c44
    fprintf(stderr, "Unsupported format. Only uncompressed 24 or 32 bits TGA are supported: %s\n", path);
608c44
    fflush(stderr);
608c44
    return FALSE;
608c44
  }
608c44
608c44
  fseek(f, header.idLength, SEEK_CUR);
608c44
608c44
  int w = *outWidth = getLEU16(header.width);
608c44
  int h = *outHeight = getLEU16(header.height);
608c44
  int rowSize = w*4;
608c44
  int size = h*rowSize;
608c44
  *pixels = (unsigned char*)calloc(1, size);
608c44
  unsigned char *row = *pixels + size;
608c44
  for(unsigned short r = h; r; --r, row -= rowSize) {
608c44
    for(unsigned char *c = row - rowSize; c < row; c += 4) {
608c44
      c[2] = fgetc(f);
608c44
      c[1] = fgetc(f);
608c44
      c[0] = fgetc(f);
608c44
      c[3] = header.pixelSize == 32 ? fgetc(f) : 255;
608c44
    }
608c44
  }
608c44
  fclose(f);
608c44
608c44
  return TRUE;
608c44
}
608c44
608c44
608c44
int imageSaveTga(const char *path, int width, int height, const unsigned char *pixels) {
608c44
  if (width <= 0 || height <= 0 || width > 0xffff || height > 0xffff || !pixels) return FALSE;
608c44
608c44
  FILE *f = fopen(path, "wb");
608c44
  if (!f) {
608c44
    fprintf(stderr, "Cannot open file for write: %s\n", path);
608c44
    fflush(stderr);
608c44
    return FALSE;
608c44
  }
608c44
608c44
  TgaHeader header = {};
608c44
  header.imageType = 2;
608c44
  setLEU16(header.width, width);
608c44
  setLEU16(header.height, height);
608c44
  header.pixelSize = 32;
608c44
  fwrite(&header, sizeof(header), 1, f); // todo: endianess
608c44
608c44
  int rowSize = width*4;
608c44
  int size = height*rowSize;
608c44
  const unsigned char *row = pixels + size;
608c44
  for(unsigned short r = height; r; --r, row -= rowSize) {
608c44
    for(const unsigned char *c = row - rowSize; c < row; c += 4) {
608c44
      fputc(c[2], f);
608c44
      fputc(c[1], f);
608c44
      fputc(c[0], f);
608c44
      fputc(c[3], f);
608c44
    }
608c44
  }
608c44
  fclose(f);
608c44
608c44
  return TRUE;
608c44
}
608c44