// Apple's annoying non-standard GL include location
#if defined(__APPLE__) || defined(MACOSX)
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif

#include <png.h>

#include <stdio.h>
#include <string>
#include <memory>

void loadIMG(std::string filename, int texUnit)
{
    // open file
    FILE *fp = fopen(filename.c_str(), "rb");
    if (!fp) {
	perror(filename.c_str());
	return;
    }

    // get info
    png_structp imgp = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
    png_infop infop = png_create_info_struct(imgp);
    png_init_io(imgp, fp);
    png_read_info(imgp, infop);
    int w = png_get_image_width(imgp,infop);
    int h = png_get_image_height(imgp,infop);

    // figure out number of channels (or transform into something we
    // can handle
    int ctype = png_get_color_type(imgp,infop);
    if (ctype==PNG_COLOR_TYPE_PALETTE)
	png_set_palette_to_rgb(imgp);
    int c = png_get_channels(imgp, infop);

    // allocate single image block and row pointers into it
    // row pointers include flip from PNG bottom origin to GL top origin
    std::auto_ptr<png_byte> imdata(new png_byte[w*h*c]);
    std::auto_ptr<png_byte*> imrow(new png_byte*[h]);
    for(int i=0; i<h; ++i)
	imrow.get()[i] = imdata.get()+(h-1-i)*w*c;

    // read image and close
    png_read_image(imgp, imrow.get());
    png_read_end(imgp, 0);
    fclose(fp);

    // load into texture
    GLenum formats[] = {0,GL_LUMINANCE,GL_LUMINANCE_ALPHA,GL_RGB,GL_RGBA};
    glActiveTexture(GL_TEXTURE0 + texUnit);
    glBindTexture(GL_TEXTURE_2D,texUnit+1);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    gluBuild2DMipmaps(GL_TEXTURE_2D,c,w,h,formats[c],
		      GL_UNSIGNED_BYTE, imdata.get());
    glEnable(GL_TEXTURE_2D);
}


void dumpIMG(std::string filename, int x, int y, int w, int h)
{
    // get data
    std::auto_ptr<png_byte> imdata(new png_byte[w*h*4]);
    std::auto_ptr<png_byte*> imrow(new png_byte*[h]);
    for(int i=0; i<h; ++i)
	imrow.get()[i] = imdata.get()+(h-1-i)*w*4;
    glPixelStorei(GL_PACK_ALIGNMENT,1);
    glReadPixels(x,y,w,h,GL_RGBA,GL_UNSIGNED_BYTE,imdata.get());

    // create file
    FILE *fp = fopen(filename.c_str(), "wb");
    if (!fp) {
	perror(filename.c_str());
	return;
    }

    // initialize stuff
    png_structp imgp = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
    png_infop infop = png_create_info_struct(imgp);
    png_init_io(imgp, fp);
    png_set_IHDR(imgp, infop, w, h,
		 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
		 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

    // write file
    png_write_info(imgp, infop);
    png_write_image(imgp, imrow.get());
    png_write_end(imgp, NULL);
    fclose(fp);
}

