#include #include #include #include // eww, I know, but oh well. #include #define PNG_DEBUG 3 #include typedef uint8_t (*color_func)(int, int); int write_png(char *filename, int width, int height, color_func r, color_func g, color_func b) { FILE *fp; int code = 0; png_structp png_ptr; png_infop info_ptr; png_bytep row; fp = fopen(filename, "wb"); if (!fp) { fprintf(stderr, "Could not open file %s for writing.\n", filename); return 1; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fprintf(stderr, "Could not allocate write struct.\n"); code = 1; goto finalize; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "Could not allocate info struct.\n"); code = 1; goto finalize; } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "Error during png creation.\n"); code = 1; goto finalize; } png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); /* * You made it! After roughly 200 years of setup, we're at the * interesting part, the writing. * A row is 3 bytes * the width of the image * Let's set the RGB values for each pixel in the row and * write the row! * * After this, we're basically done. */ row = (png_bytep) malloc(3 * width); int x, y; for (y = 0; y < height; ++y) { for (x = 0; x < width; ++x) { png_bytep pixel = &row[x*3]; pixel[0] = r(x, y); pixel[1] = g(x, y); pixel[2] = b(x, y); } png_write_row(png_ptr, row); } png_write_end(png_ptr, NULL); finalize: if (fp != NULL) fclose(fp); if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); if (row != NULL) free(row); return code; } uint8_t r(int x, int y) { return x ^ y; } uint8_t g(int x, int y) { return x | y; } uint8_t b(int x, int y) { return x * y; } int main(int argc, char *argv[]) { char *filename = argv[1]; write_png(filename, 1920, 1080, r, g, b); }