/** * A miminal use of libpng for UIUC's CS418 class. * * See uselibpng.c for implementation notes */ #ifdef __cplusplus extern "C" { #endif #include /** * RGBA pixel with several ways of looking at it: * * pixel.p[0] is the first (red) channel of the pixel * pixel.red is the red (first) channel of the pixel * pixel.r is the red (first) channel of the pixel */ typedef union { uint8_t p[4]; struct { uint8_t r, g, b, a; }; struct { uint8_t red, green, blue, alpha; }; } pixel_t; /** * A minimal struct for storing PNG data. C/C++ has poor support for 2D arrays, * so use the provided image_xy macro (C) or the Image wrapper class (C++) for access. */ typedef struct { uint32_t height, width; pixel_t *rgba; } image_t; /** * Load a PNG from the given file. * * ~~~~ * image_t *img = load_image("existing_image.png"); * if (img == NULL) { fprintf(stderr, "%s was not a PNG file", "existing_image.png"); } * for(int y = 0; y < img->height; y += 1) { * for(int x = 0; x < img->width; x += 1) { * pixel_t pixel = pixel_xy(img, x, y); * } * } * ~~~~ */ image_t *load_image(const char *filename); /** * Save a PNG to the given file. * * ~~~~ * image_t *img = ... * save_image(img, "new_image.png") * ~~~~ */ void save_image(image_t *img, const char *filename); /** * Allocate an image with the given width and height. * * ~~~~ * image_t *img = new_image(1280, 720); * for(int y = 0; y < img->height; y += 1) { * for(int x = 0; x < img->width; x += 1) { * pixel_xy(img, x, y).red = x & 0xFF; * pixel_xy(img, x, y).g = y & 0xFF; * pixel_xy(img, x, y).p[2] = ((x+y)>>8) & 0xFF; * pixel_xy(img, x, y).alpha = (x^y)&1 ? 0xFF : 0x00; * } * } * save_image(img, "demo_image.png"); * ~~~~ */ image_t *new_image(uint32_t width, uint32_t height); /** * Deallocate memory used to store the image */ void free_image(image_t *img); #ifdef __cplusplus } // end extern "C" #endif #ifdef __cplusplus /** * A class wrapper around the image_t structure and its functions * * ~~~~ * Image img = Image("image_to_read.png"); * * for(uint32_t y=0; yrgba[data->width * y]); } /// store the image in a PNG file void save(const char *filename) const { save_image(data, filename); } /// get the width of the image uint32_t width() const { return data->width; } /// get the height of the image uint32_t height() const { return data->height; } private: image_t* data; }; #else /** * A helper macro for accessing the image. * pixel_xy(img, x, y).red = 255; * opacity = pixel_xy(img, x, y).alpha; */ #define pixel_xy(img,x,y) (img)->rgba[(x) + (y)*(img)->width] #endif