Blob Blame Raw


int imageLoadPng(const char *path, int *outWidth, int *outHeight, unsigned char **pixels) {
  png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  png_infop info = png ? png_create_info_struct(png) : NULL;
  if (!png) {
    fprintf(stderr, "Cannot initialize PNG library\n");
    fflush(stderr);
    return FALSE;
  }

  FILE *f = fopen(path, "rb");
  if (!f) {
    fprintf(stderr, "Cannot open for read: %s\n", path);
    fflush(stderr);
    return FALSE;
  }

  unsigned char header[8];
  fread(header, sizeof(header), 1, f);
  if (png_sig_cmp(header, 0, sizeof(header))) {
    fclose(f);
    fprintf(stderr, "Seems it is not PNG image: %s\n", path);
    fflush(stderr);
    return FALSE;
  }

  png_init_io(png, f);
  png_set_sig_bytes(png, sizeof(header));
  png_read_info(png, info);

  unsigned int width, height;
  int bitdepth, colortype;
  png_get_IHDR(png,info, &width, &height, &bitdepth, &colortype, 0, 0, 0);
  if (colortype == PNG_COLOR_TYPE_PALETTE)
    png_set_palette_to_rgb(png);
  if (colortype == PNG_COLOR_TYPE_GRAY && bitdepth < 8)
    png_set_expand_gray_1_2_4_to_8(png);
  if (colortype == PNG_COLOR_TYPE_GRAY || colortype == PNG_COLOR_TYPE_GRAY_ALPHA)
    png_set_gray_to_rgb(png);
  if (png_get_valid(png, info, PNG_INFO_tRNS))
    png_set_tRNS_to_alpha(png);
  if (colortype == PNG_COLOR_TYPE_RGB)
    png_set_filler(png, 0xff, PNG_FILLER_AFTER);
  if (bitdepth == 16)
    png_set_strip_16(png);
  if (bitdepth < 8)
    png_set_packing(png);

  png_read_update_info(png, info);
  png_get_IHDR(png, info, &width, &height, 0, 0, 0, 0, 0);

  unsigned char *data = (unsigned char*)calloc(1, 4*width*height);
  png_bytep *rows = (png_bytep*)malloc(height*sizeof(png_bytep));
  for(unsigned int i = 0; i < height; i++)
    rows[i] = data + i*4*width;
  png_read_image(png, rows);
  png_read_end(png, 0);
  free(rows);

  png_destroy_read_struct(&png, &info, 0);
  fclose(f);

  *outWidth = (int)width;
  *outHeight = (int)height;
  *pixels = data;
  return TRUE;
}


int imageSavePng(const char *path, int width, int height, const unsigned char *pixels) {
  png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  png_infop info = png ? png_create_info_struct(png) : NULL;
  if (!png) {
    fprintf(stderr, "Cannot initialize PNG library\n");
    fflush(stderr);
    return FALSE;
  }

  FILE *f = fopen(path, "wb");
  if (!f) {
    fprintf(stderr, "Cannot open for write: %s\n", path);
    fflush(stderr);
    return FALSE;
  }

  png_init_io(png, f);
  png_set_IHDR( png, info, width, height, 8, PNG_COLOR_TYPE_RGBA,
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE );
  png_write_info(png, info);
  png_set_packing(png);

  png_bytep *rows = (png_bytep*)malloc(height*sizeof(png_bytep));
  for(int i = 0; i < height; i++)
    rows[i] = (png_bytep)(pixels + i*4*width);
  png_write_image(png, rows);
  png_write_end(png, info);
  free(rows);

  png_destroy_write_struct(&png, &info);

  fclose(f);
  return TRUE;
}