// // File: image.cc // // (C) 2000-2006 Helmut Cantzler // // Licensed under the terms of the Lesser General Public License. // #include "image.h" extern "C" { #include } Image::Image() { image_data=new_data=NULL; image_height = image_width = image_pixel_size = 0; } Image::~Image() { delete image_data; } // JPEG error handling // #include typedef struct error_mgr { struct jpeg_error_mgr pub; jmp_buf setjmp_buffer; } *error_ptr; void new_error_exit(j_common_ptr cinfo) { error_ptr err = (error_ptr) cinfo->err; longjmp(err->setjmp_buffer, 1); } int Image::read(const char *filename) { struct jpeg_decompress_struct cinfo; struct error_mgr jerr; JSAMPARRAY buffer; int row_size, x, y, z, b; FILE *f; if ((f=fopen(filename, "rb")) == NULL) { //fprintf(stderr, "can't open %s\n", filename); return 1; } // Init error handling cinfo.err=jpeg_std_error(&jerr.pub); // Replace the standard jpeg error function jerr.pub.error_exit = new_error_exit; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); fclose(f); return 2; } // Init & Read header jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo,f); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); image_pixel_size=cinfo.output_components; image_height=cinfo.output_height; image_width=cinfo.output_width; //printf("Bytes per pixel: %d\n", image_pixel_size); // Check if we have a RGB or gray scale image if (image_pixel_size != 1 && image_pixel_size != 3) { jpeg_destroy_decompress(&cinfo); return 2; } // Create the data structures delete image_data; image_data= new Array3D(image_width, image_height, image_pixel_size); row_size=image_width * image_pixel_size; buffer=(*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_size, 1); // Read JPEG image line per line for (y=image_height-1; cinfo.output_scanline < cinfo.output_height; y--) { jpeg_read_scanlines(&cinfo, buffer, 1); for (b=x=0; x < image_width; x++) for (z=0; z < image_pixel_size; z++) image_data->set(x, y, z, buffer[0][b++]); } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(f); return 0; } void Image::grey_to_rgb(void) { if (image_pixel_size != 1) return; int x, y, z; new_data = new Array3D(image_width, image_height, 3); for (y=0; y < image_height; y++) for (x=0; x < image_width; x++) for (z=0; z < 3; z++) new_data->set(x, y, z, image_data->get(x, y, 1)); delete image_data; image_data=new_data; image_pixel_size=3; } void Image::scale(int height, int width) { float h, w; int y, x, z; // Ratio between old and new size h=(float)image_height/(float)height; w=(float)image_width/(float)width; // Create the data structures new_data = new Array3D(width, height, image_pixel_size); for (y=0; y < height; y++) for (x=0; x < width; x++) for (z=0; z < image_pixel_size; z++) new_data->set(x, y, z, image_data->get((int)(x*w+0.5), (int)(y*h+0.5), z)); delete image_data; image_data=new_data; image_height=height; image_width=width; } int Image::height(void) const { return image_height; } int Image::width(void) const { return image_width; } int Image::pixel_size(void) const { return image_pixel_size; } const unsigned char* Image::data(void) { return image_data->get_data(); }