nuclear@0: #include nuclear@6: nuclear@6: #ifndef _MSC_VER nuclear@6: #include nuclear@6: #else nuclear@6: #include nuclear@6: #endif nuclear@6: nuclear@0: #include "imago2.h" nuclear@0: #include "image.h" nuclear@0: #include "logger.h" nuclear@0: nuclear@15: using namespace goatgfx; nuclear@0: nuclear@0: static int pixel_elements(Image::Format fmt); nuclear@0: static int elem_size(Image::Format fmt); nuclear@0: static int pixel_size(Image::Format fmt); nuclear@0: nuclear@0: Image::Image() nuclear@0: { nuclear@0: fmt = FMT_RGBA; nuclear@0: width = height = 0; nuclear@0: pixels = 0; nuclear@0: } nuclear@0: nuclear@0: Image::~Image() nuclear@0: { nuclear@0: delete [] (char*)pixels; nuclear@0: } nuclear@0: nuclear@0: int Image::get_width() const nuclear@0: { nuclear@0: return width; nuclear@0: } nuclear@0: nuclear@0: int Image::get_height() const nuclear@0: { nuclear@0: return height; nuclear@0: } nuclear@0: nuclear@0: Image::Format Image::get_format() const nuclear@0: { nuclear@0: return fmt; nuclear@0: } nuclear@0: nuclear@0: bool Image::create(int x, int y, Format fmt) nuclear@0: { nuclear@0: width = x; nuclear@0: height = y; nuclear@0: this->fmt = fmt; nuclear@0: nuclear@0: try { nuclear@0: pixels = new char[x * y * pixel_size(fmt)]; nuclear@0: } nuclear@0: catch(...) { nuclear@0: return false; nuclear@0: } nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@6: bool Image::set_pixels(int xsz, int ysz, void *pixels, Format fmt) nuclear@0: { nuclear@6: if(!create(xsz, ysz, fmt)) { nuclear@0: return false; nuclear@0: } nuclear@6: memcpy(this->pixels, pixels, xsz * ysz * pixel_size(fmt)); nuclear@6: return true; nuclear@6: } nuclear@6: nuclear@6: bool Image::set_pixels(int xsz, int ysz, void *pixels, int scan_width, Format fmt) nuclear@6: { nuclear@6: return set_pixels(xsz, ysz, pixels, 0, 0, scan_width, fmt); nuclear@6: } nuclear@6: nuclear@6: bool Image::set_pixels(int xsz, int ysz, void *pixels, int x, int y, int scan_width, Format fmt) nuclear@6: { nuclear@6: if(scan_width <= 0) { nuclear@6: scan_width = xsz; nuclear@6: } nuclear@6: nuclear@6: if(!create(xsz, ysz, fmt)) { nuclear@6: return false; nuclear@6: } nuclear@6: nuclear@6: int pixsz = pixel_size(fmt); nuclear@6: nuclear@6: unsigned char *dest = (unsigned char*)this->pixels; nuclear@6: unsigned char *src = (unsigned char*)pixels + (y * scan_width + x) * pixsz; nuclear@6: for(int i=0; i dest) { nuclear@6: memcpy(tmppix, src, pixsz); nuclear@6: memcpy(src, dest, pixsz); nuclear@6: memcpy(dest, tmppix, pixsz); nuclear@6: dest += pixsz; nuclear@6: src -= pixsz; nuclear@6: } nuclear@6: nuclear@6: scan += width * pixsz; nuclear@6: } nuclear@6: } nuclear@6: nuclear@6: void Image::flip_vertical() nuclear@6: { nuclear@6: int pixsz = pixel_size(fmt); nuclear@6: nuclear@6: unsigned char *tmpscan = (unsigned char*)alloca(width * pixsz); nuclear@6: nuclear@6: unsigned char *dest = (unsigned char*)pixels; nuclear@6: unsigned char *src = (unsigned char*)pixels + (height - 1) * width * pixsz; nuclear@6: nuclear@6: while(src > dest) { nuclear@6: memcpy(tmpscan, src, width * pixsz); nuclear@6: memcpy(src, dest, width * pixsz); nuclear@6: memcpy(dest, tmpscan, width * pixsz); nuclear@6: dest += width * pixsz; nuclear@6: src -= width * pixsz; nuclear@6: } nuclear@6: } nuclear@6: nuclear@6: void Image::rotate_180() nuclear@6: { nuclear@6: flip_vertical(); nuclear@6: flip_horizontal(); nuclear@6: } nuclear@6: nuclear@0: bool Image::load(const char *fname) nuclear@0: { nuclear@0: struct img_pixmap pixmap; nuclear@0: nuclear@0: img_init(&pixmap); nuclear@0: if(img_load(&pixmap, fname) == -1) { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: Format fmt; nuclear@0: switch(pixmap.fmt) { nuclear@0: case IMG_FMT_GREY8: nuclear@0: fmt = FMT_GREY; nuclear@0: break; nuclear@0: case IMG_FMT_RGB24: nuclear@0: fmt = FMT_RGB; nuclear@0: break; nuclear@0: case IMG_FMT_RGBA32: nuclear@0: fmt = FMT_RGBA; nuclear@0: break; nuclear@0: case IMG_FMT_GREYF: nuclear@0: fmt = FMT_GREY_FLOAT; nuclear@0: break; nuclear@0: case IMG_FMT_RGBF: nuclear@0: fmt = FMT_RGB_FLOAT; nuclear@0: break; nuclear@0: case IMG_FMT_RGBAF: nuclear@0: fmt = FMT_RGBA_FLOAT; nuclear@0: break; nuclear@0: default: nuclear@0: img_destroy(&pixmap); nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: if(!set_pixels(pixmap.width, pixmap.height, pixmap.pixels, fmt)) { nuclear@0: img_destroy(&pixmap); nuclear@0: return false; nuclear@0: } nuclear@0: img_destroy(&pixmap); nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: bool Image::save(const char *fname) const nuclear@0: { nuclear@0: struct img_pixmap pixmap; nuclear@0: nuclear@0: img_init(&pixmap); nuclear@0: nuclear@0: switch(fmt) { nuclear@0: case FMT_GREY: nuclear@0: pixmap.fmt = IMG_FMT_GREY8; nuclear@0: break; nuclear@0: case FMT_GREY_FLOAT: nuclear@0: pixmap.fmt = IMG_FMT_GREYF; nuclear@0: break; nuclear@0: case FMT_RGB: nuclear@0: pixmap.fmt = IMG_FMT_RGB24; nuclear@0: break; nuclear@0: case FMT_RGB_FLOAT: nuclear@0: pixmap.fmt = IMG_FMT_RGBF; nuclear@0: break; nuclear@0: case FMT_RGBA: nuclear@0: pixmap.fmt = IMG_FMT_RGBA32; nuclear@0: break; nuclear@0: case FMT_RGBA_FLOAT: nuclear@0: pixmap.fmt = IMG_FMT_RGBAF; nuclear@0: break; nuclear@0: default: nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: pixmap.width = width; nuclear@0: pixmap.height = height; nuclear@0: pixmap.pixels = pixels; nuclear@0: pixmap.pixelsz = pixel_size(fmt); nuclear@0: nuclear@0: if(img_save(&pixmap, fname) == -1) { nuclear@0: return false; nuclear@0: } nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: static int pixel_elements(Image::Format fmt) nuclear@0: { nuclear@0: switch(fmt) { nuclear@0: case Image::FMT_GREY: nuclear@0: case Image::FMT_GREY_FLOAT: nuclear@0: return 1; nuclear@0: nuclear@0: case Image::FMT_RGB: nuclear@0: case Image::FMT_RGB_FLOAT: nuclear@0: return 3; nuclear@0: nuclear@0: case Image::FMT_RGBA: nuclear@0: case Image::FMT_RGBA_FLOAT: nuclear@0: return 4; nuclear@0: nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: static int elem_size(Image::Format fmt) nuclear@0: { nuclear@0: switch(fmt) { nuclear@0: case Image::FMT_GREY: nuclear@0: case Image::FMT_RGB: nuclear@0: case Image::FMT_RGBA: nuclear@0: return 1; nuclear@0: nuclear@0: case Image::FMT_GREY_FLOAT: nuclear@0: case Image::FMT_RGB_FLOAT: nuclear@0: case Image::FMT_RGBA_FLOAT: nuclear@0: return sizeof(float); nuclear@0: nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: static int pixel_size(Image::Format fmt) nuclear@0: { nuclear@0: return elem_size(fmt) * pixel_elements(fmt); nuclear@0: }