#include "mypng.h" #include #define STRINGIFY(number) #number #define TO_STRING(number) STRINGIFY(number) #define AT __FILE__ "/" TO_STRING(__LINE__) #define MYPNG_ERR(reason) AT " " #reason /* * Amplifying each component of every pixel by a given coefficient. * * 'coeff' must be divided by 256 to get the real amplification * coefficient. */ void png_amplify(struct pngdata *pp, unsigned int coeff) { unsigned int x, y; for (x = 0; x < pp->height; x++) for (y = 0; y < pp->width * PNG_COMPONENTS; y++) { unsigned long new_color; png_byte *bp = pp->rows[x] + y; new_color = (*bp) + ((*bp) * coeff >> 8); *bp = new_color < 255 ? new_color : 255; } } int png_write(const char *filename, struct pngdata *data) { int retval = 1; FILE *fp = NULL; png_structp png_p = NULL; png_infop info_p = NULL; fp = fopen(filename, "wb"); if (fp == NULL) goto _bailout; png_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_p == NULL) goto _bailout; info_p = png_create_info_struct(png_p); if (!info_p) goto _bailout; png_init_io(png_p, fp); png_set_IHDR(png_p, info_p, data->width, data->height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_p, info_p); png_write_image(png_p, data->rows); png_write_end(png_p, NULL); retval = 0; _bailout: if (png_p) png_destroy_write_struct(&png_p, &info_p); if (fp) fclose(fp); return retval; } const char * png_read_8bit_rgb(const char *filename, struct pngdata *data) { int ok = 0; const char *retval = NULL; FILE *fp = NULL; png_image img; png_structp png_p = NULL; png_infop info_p = NULL; png_uint_32 w, h; int color_type, bit_depth; assert(filename != NULL); assert(data != NULL); bzero((void *)&img, sizeof(img)); bzero(data, sizeof(*data)); fp = fopen(filename, "rb"); if (fp == NULL) { retval = MYPNG_ERR("failed to open input file"); goto _bailout; } png_p = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_p == NULL) { retval = MYPNG_ERR("PNG read struct creation failed"); goto _bailout; } info_p = png_create_info_struct(png_p); if (!info_p) { retval = MYPNG_ERR("PNG info struct creation failed"); goto _bailout; } png_init_io(png_p, fp); png_read_info(png_p, info_p); if (png_get_IHDR(png_p, info_p, &w, &h, &bit_depth, &color_type, NULL, NULL, NULL) == 0) { retval = MYPNG_ERR("failed to get data from PNG header"); goto _bailout; } if ((color_type & PNG_FORMAT_FLAG_COLOR) == 0) { retval = MYPNG_ERR("not a (non-transparent) RGB PNG"); goto _bailout; } if (bit_depth != 8) { retval = MYPNG_ERR("not a 8-bit (Dendy?) PNG"); goto _bailout; } data->width = w; data->height = h; png_allocate(data); png_read_image(png_p, data->rows); png_read_end(png_p, NULL); ok = 1; _bailout: if (!ok && data->width != 0 && data->height != 0) png_destroy(data); if (png_p) png_destroy_read_struct(&png_p, &info_p, NULL); if (fp) fclose(fp); return (retval); } void png_destroy(struct pngdata *p_pd) { assert(p_pd->width > 0); assert(p_pd->height > 0); if (p_pd->rows) { int i; for (i = 0; i < p_pd->height; i++) { if (p_pd->rows[i]) { free(p_pd->rows[i]); p_pd->rows[i] = NULL; } } free(p_pd->rows); } return; } void png_allocate(struct pngdata *p_pd) { size_t row_bytes = p_pd->height * sizeof(p_pd->rows[0]); size_t col_bytes = PNG_WIDTH * p_pd->width * sizeof(*(p_pd->rows[0])); unsigned int i; assert(p_pd->width > 0); assert(p_pd->height > 0); p_pd->rows = NULL; p_pd->rows = (png_bytep *)malloc(row_bytes); if (p_pd->rows == NULL) { printf("Not enough memory for row data.\n"); exit(1); } bzero((void *)p_pd->rows, row_bytes); for (i = 0; i < p_pd->height; i++) { p_pd->rows[i] = (png_byte *)malloc(col_bytes); if (p_pd->rows == NULL) { #if 0 int j; for (j = 0; j < i; j++) free(p_pd->rows[j]); free(p_pd->rows); #else png_destroy(p_pd); #endif printf("Not enough memory for column %d.\n", i); exit(1); } } } void png_copy(struct pngdata *src, struct pngdata *dest) { unsigned int x; size_t col_bytes = PNG_WIDTH * src->width * sizeof(*(src->rows[0])); assert(src->width > 0); assert(src->height > 0); assert(src->width == dest->width); assert(src->height == dest->height); for (x = 0; x < src->height; x++) bcopy(src->rows[x], dest->rows[x], col_bytes); }