/* Copyright (C) 2014 Jerome Revaud This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see */ #include "std.h" #include #include #include #include #include "io.h" void output_correspondences( const char* out_filename, const corres_t* corres, int nb, float fx, float fy ) { assert(0x0,fy*r->y0,fx*r->x1,fy*r->y1,r->maxima,r->score); else std_printf("%g %g %g %g %g %g\n",fx*r->x0,fy*r->y0,fx*r->x1,fy*r->y1,r->maxima,r->score); } if(out_filename) fclose(f); } /* IMAGE */ // PPM typedef struct { int magic; int width; int height; int pixmax; } ppm_hdr_t; static void get_magic(FILE *fp, ppm_hdr_t *ppm_hdr) { char str[1024]; fgets(str, 1024, fp); if(str[0] == 'P' && (str[1] <= '6' || str[1] >= '1')) { ppm_hdr->magic = str[1] - '0'; } } static int skip_comment(FILE *fp) { char c; do { c = (char) fgetc(fp); } while (c == ' ' || c == '\t' || c == '\n'); if(c == '#') { do { c = (char) fgetc(fp); } while(c != 0x0A); return 1; } else { ungetc(c, fp); } return 0; } /*----------------------------------------------------------------------------*/ static void skip_comments(FILE *fp) { while(skip_comment(fp)); } /*----------------------------------------------------------------------------*/ static int get_image_size(FILE *fp, ppm_hdr_t *ppm_hdr) { skip_comments(fp); if(fscanf(fp, "%d %d", &ppm_hdr->width, &ppm_hdr->height) != 2) { err_printf( "Warning: PGM --> File currupted\n"); return 0; } return 1; } /*----------------------------------------------------------------------------*/ static int get_pixmax(FILE *fp, ppm_hdr_t *ppm_hdr) { skip_comments(fp); ppm_hdr->pixmax = 1; if(ppm_hdr->magic == 2 || ppm_hdr->magic == 3 || ppm_hdr->magic == 5 || ppm_hdr->magic == 6) { if(fscanf(fp, "%d", &ppm_hdr->pixmax) != 1) { err_printf( "Warning: PGM --> pixmax not valid\n"); return 0; } } fgetc(fp); return 1; } /*----------------------------------------------------------------------------*/ static int get_ppm_hdr(FILE *fp, ppm_hdr_t *ppm_hdr) { get_magic(fp, ppm_hdr); if(!get_image_size(fp, ppm_hdr)) { return 0; } if(!get_pixmax(fp, ppm_hdr)) { return 0; } return 1; } static void raw_read_color(FILE *fp, color_image_t *image) { int i, size=image->height*image->width; for(i=0;ic1[i]=(float) fgetc(fp); image->c2[i]=(float) fgetc(fp); image->c3[i]=(float) fgetc(fp); } } color_image_t *color_image_pnm_load(FILE *fp) { color_image_t *image = NULL; ppm_hdr_t ppm_hdr; if(!get_ppm_hdr(fp, &ppm_hdr)) { return NULL; } switch(ppm_hdr.magic) { case 1: /* PBM ASCII */ case 2: /* PGM ASCII */ case 3: /* PPM ASCII */ case 4: /* PBM RAW */ case 5: /* PGM RAW */ err_printf( "color_image_pnm_load: only PPM raw with maxval 255 supported\n"); break; case 6: /* PPM RAW */ image = color_image_new(ppm_hdr.width, ppm_hdr.height); raw_read_color(fp, image); break; } return image; } // JPG color_image_t *color_image_jpeg_load(FILE *fp) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPARRAY buffer; int row_stride; int index = 0; color_image_t *image = NULL; float *r_p, *g_p, *b_p; JSAMPROW buffer_p; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, fp); jpeg_read_header(&cinfo, TRUE); cinfo.out_color_space = JCS_RGB; cinfo.quantize_colors = FALSE; image = color_image_new(cinfo.image_width, cinfo.image_height); if(image == NULL) { return NULL; } jpeg_start_decompress(&cinfo); row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); r_p = image->c1; g_p = image->c2; b_p = image->c3; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, buffer, 1); buffer_p = buffer[0]; index = cinfo.output_width; while(index--) { *r_p++ = (float) *buffer_p++; *g_p++ = (float) *buffer_p++; *b_p++ = (float) *buffer_p++; } } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); return image; } color_image_t * color_image_png_load( FILE* fp, const char* file_name ) { // read the header png_byte header[8]; fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { err_printf( "error: %s is not a PNG.\n", file_name); fclose(fp); return 0; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { err_printf( "error: png_create_read_struct returned 0.\n"); fclose(fp); return 0; } // create png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { err_printf( "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(fp); return 0; } // create png info struct png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { err_printf( "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); fclose(fp); return 0; } // the code in this if statement gets called if libpng encounters an error if (setjmp(png_jmpbuf(png_ptr))) { err_printf( "error from libpng\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return 0; } // init png reading png_init_io(png_ptr, fp); // let libpng know you already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read all the info up to the image data png_read_info(png_ptr, info_ptr); // variables to pass to get info int bit_depth, color_type; png_uint_32 temp_width, temp_height; // get info about png png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, NULL, NULL, NULL); // Update the png info struct. png_read_update_info(png_ptr, info_ptr); // Row size in bytes. int rowbytes = png_get_rowbytes(png_ptr, info_ptr); // Allocate the image_data as a big block, to be given to opengl png_byte * image_data; image_data = NEWA(png_byte, rowbytes * temp_height); assert(image_data!=NULL); // row_pointers is for pointing to image_data for reading the png with libpng png_bytep * row_pointers = NEWA(png_bytep, temp_height); assert(row_pointers!=NULL); // set the individual row_pointers to point at the correct offsets of image_data unsigned int i; for (i = 0; i c1[i] = image->c2[i] = image->c3[i] = image_data[i]; } else if( color_type == 2 ) { assert((unsigned)rowbytes == 3*temp_width || !"error: not a proper color png image"); for(i=0; ic1[i] = image_data[3*i+0]; image->c2[i] = image_data[3*i+1]; image->c3[i] = image_data[3*i+2]; } } else assert(!"error: unknown PNG color type" ); // clean up png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(row_pointers); free(image_data); return image; } // GENERAL LOAD /* load a color image from a file */ color_image_t *color_image_load(const char *fname) { FILE *fp; char magic[2]; unsigned short *magic_short = (unsigned short *) magic; color_image_t *image = NULL; if((fp = fopen(fname, "rb")) == NULL) { err_printf( "Warning: color_image_load() - can not open file `%s' !\n", fname); return NULL; } fread(magic, sizeof(char), 2, fp); rewind(fp); if(magic_short[0] == 0xd8ff) { image = color_image_jpeg_load(fp); } else if(magic[0]=='P' && (magic[1]=='6' || magic[1]=='5')) { /* PPM raw */ image = color_image_pnm_load(fp); } else if( magic[0]==-119 && magic[1]=='P' ) { image = color_image_png_load( fp, fname ); } else { err_printf( "Warning: color_image_load(%s) - image format not recognized\n",fname); } fclose(fp); return image; }