// Based on example program from // http://stackoverflow.com/q/1821806/101258 #include "write-png.h" /* Attempts to save PNG to file; returns 0 on success, non-zero on error. */ int bitmap_save_to_png(RGBBitmap *bitmap, const char *path) { FILE *fp = fopen(path, "wb"); png_structp png_ptr = NULL; png_infop info_ptr = NULL; size_t x, y; png_uint_32 bytes_per_row; png_byte **row_pointers = NULL; if (fp == NULL) return -1; /* Initialize the write struct. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); return -1; } /* Initialize the info struct. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct(&png_ptr, NULL); fclose(fp); return -1; } /* Set up error handling. */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return -1; } /* Set image attributes. */ png_set_IHDR(png_ptr, info_ptr, bitmap->width, bitmap->height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Initialize rows of PNG. */ bytes_per_row = bitmap->width * bitmap->bytes_per_pixel; row_pointers = png_malloc(png_ptr, bitmap->height * sizeof(png_byte *)); for (y = 0; y < bitmap->height; ++y) { uint8_t *row = png_malloc(png_ptr, sizeof(uint8_t) * bytes_per_row); row_pointers[y] = (png_byte *)row; for (x = 0; x < bitmap->width; ++x) { RGBPixel color = RGBPixelAtPoint(bitmap, x, y); *row++ = color.red; *row++ = color.green; *row++ = color.blue; } } /* Actually write the image data. */ png_init_io(png_ptr, fp); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); /* Cleanup. */ for (y = 0; y < bitmap->height; y++) { png_free(png_ptr, row_pointers[y]); } png_free(png_ptr, row_pointers); /* Finish writing. */ png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return 0; } int bitmap_init(RGBBitmap *img, int width, int height) { img->width = width; img->height = height; img->bytes_per_pixel = 3; img->pixels = calloc(1, sizeof(RGBPixel) * img->width * img->height); return 0; } int bitmap_set(RGBBitmap *img, int x, int y, int r, int g, int b) { RGBPixel *pixel = RGBBufferAtPoint(img, x, y); pixel->red = r; pixel->green = g; pixel->blue = b; return 0; } void bitmap_fill(RGBBitmap *img, int r, int g, int b) { int x, y; // TODO: could use pointers directly or even memcpy // to make this faster for (y = 0; y < img->height; y++) { for (x = 0; x < img->width; x++) { bitmap_set(img, x, y, r, g, b); } } } //int main() //{ // const char path[] = "test.png"; // int status = 0, x, y; // RGBBitmap img; // // bitmap_init(&img, 100, 100); // for (y = 0; y < img.height; y++) { // for (x = 0; x < img.height; x++) { // bitmap_set(&img, x, y, 255, 255, 255); // } // } // bitmap_set(&img, 50, 50, 0, 0, 255); // bitmap_set(&img, 0, 0, 0, 0, 255); // bitmap_set(&img, 99, 0, 0, 0, 255); // bitmap_set(&img, 0, 99, 0, 0, 255); // bitmap_set(&img, 99, 99, 0, 0, 255); // // status = bitmap_save_to_png(&img, path); // if (!status){ // printf("Successfully saved %s\n", path); // } else { // printf("Unable to save %s\n", path); // } // return status; //}