RGBAImagePtr LoadTGABuff(const byte* buffer) { PointerInputStream istream(buffer); TargaHeader targa_header; targa_header_read_istream(targa_header, istream); if (targa_header.image_type != 2 && targa_header.image_type != 10 && targa_header.image_type != 3) { globalErrorStream() << "LoadTGA: TGA type " << targa_header.image_type << " not supported\n"; globalErrorStream() << "LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n"; return RGBAImagePtr(); } if (targa_header.colormap_type != 0) { globalErrorStream() << "LoadTGA: colormaps not supported\n"; return RGBAImagePtr(); } if ((targa_header.pixel_size != 32 && targa_header.pixel_size != 24) && targa_header.image_type != 3) { globalErrorStream() << "LoadTGA: Only 32 or 24 bit images supported\n"; return RGBAImagePtr(); } if ((targa_header.attributes & (TGA_FLIP_HORIZONTAL|TGA_FLIP_VERTICAL)) == 0) { return Targa_decodeImageData(targa_header, istream, Flip00()); } if((targa_header.attributes & TGA_FLIP_HORIZONTAL) == 0 && (targa_header.attributes & TGA_FLIP_VERTICAL) != 0) { return Targa_decodeImageData(targa_header, istream, Flip01()); } if ((targa_header.attributes & TGA_FLIP_HORIZONTAL) != 0 && (targa_header.attributes & TGA_FLIP_VERTICAL) == 0) { return Targa_decodeImageData(targa_header, istream, Flip10()); } if ((targa_header.attributes & TGA_FLIP_HORIZONTAL) != 0 && (targa_header.attributes & TGA_FLIP_VERTICAL) != 0) { return Targa_decodeImageData(targa_header, istream, Flip11()); } // unreachable return RGBAImagePtr(); }
/* ============== LoadPCX32 ============== */ RGBAImagePtr LoadPCX32Buff(byte* buffer, std::size_t length) { byte *palette; byte *pic8; int i, c, p, width, height; byte *pic32; LoadPCXBuff(buffer, length, &pic8, &palette, &width, &height); if (!pic8) { return RGBAImagePtr(); } RGBAImagePtr image (new RGBAImage(width, height)); c = (width) * (height); pic32 = image->getMipMapPixels(0); for (i = 0; i < c; i++) { p = pic8[i]; pic32[0] = palette[p * 3]; pic32[1] = palette[p * 3 + 1]; pic32[2] = palette[p * 3 + 2]; pic32[3] = 255; pic32 += 4; } free (pic8); free (palette); return image; }
RGBAImagePtr Targa_decodeImageData(const TargaHeader& targa_header, PointerInputStream& istream, const Flip& flip) { RGBAImagePtr image (new RGBAImage(targa_header.width, targa_header.height)); if (targa_header.image_type == 2 || targa_header.image_type == 3) { switch (targa_header.pixel_size) { case 8: targa_decode_grayscale(istream, *image, flip); break; case 24: targa_decode_rgb(istream, *image, flip); break; case 32: targa_decode_rgba(istream, *image, flip); break; default: globalErrorStream() << "LoadTGA: illegal pixel_size '" << targa_header.pixel_size << "'\n"; return RGBAImagePtr(); } } else if (targa_header.image_type == 10) { switch (targa_header.pixel_size) { case 24: targa_decode_rle_rgb(istream, *image, flip); break; case 32: targa_decode_rle_rgba(istream, *image, flip); break; default: globalErrorStream() << "LoadTGA: illegal pixel_size '" << targa_header.pixel_size << "'\n"; return RGBAImagePtr(); } } return image; }
static RGBAImagePtr LoadJPGBuff_(const void *src_buffer, int src_size) { struct jpeg_decompress_struct cinfo; struct my_jpeg_error_mgr jerr; cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = my_jpeg_error_exit; if (setjmp (jerr.setjmp_buffer)) //< TODO: use c++ exceptions instead of setjmp/longjmp to handle errors { rError() << "WARNING: JPEG library error: " << errormsg << "\n"; jpeg_destroy_decompress (&cinfo); return RGBAImagePtr(); } jpeg_create_decompress (&cinfo); jpeg_buffer_src (&cinfo, const_cast<void*>(src_buffer), src_size); jpeg_read_header (&cinfo, TRUE); jpeg_start_decompress (&cinfo); int row_stride = cinfo.output_width * cinfo.output_components; RGBAImagePtr image (new RGBAImage(cinfo.output_width, cinfo.output_height)); JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines (&cinfo, buffer, 1); if (cinfo.out_color_components == 4) j_putRGBAScanline (buffer[0], cinfo.output_width, image->getMipMapPixels(0), cinfo.output_scanline-1); else if (cinfo.out_color_components == 3) j_putRGBScanline (buffer[0], cinfo.output_width, image->getMipMapPixels(0), cinfo.output_scanline-1); else if (cinfo.out_color_components == 1) j_putGrayScanlineToRGB (buffer[0], cinfo.output_width, image->getMipMapPixels(0), cinfo.output_scanline-1); } jpeg_finish_decompress (&cinfo); jpeg_destroy_decompress (&cinfo); return image; }
static RGBAImagePtr LoadPNGBuff (unsigned char* fbuffer) { png_byte** row_pointers; png_bytep p_fbuffer; p_fbuffer = fbuffer; // the reading glue // http://www.libpng.org/pub/png/libpng-manual.html png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, user_error_fn, user_warning_fn); if (!png_ptr) { rError() << "libpng error: png_create_read_struct\n"; return RGBAImagePtr(); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); rError() << "libpng error: png_create_info_struct (info_ptr)" << std::endl; return RGBAImagePtr(); } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); rError() << "libpng error: png_create_info_struct (end_info)" << std::endl; return RGBAImagePtr(); } // configure the read function png_set_read_fn(png_ptr, (png_voidp)&p_fbuffer, (png_rw_ptr)&user_read_data); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return RGBAImagePtr(); } png_read_info(png_ptr, info_ptr); int bit_depth = png_get_bit_depth(png_ptr, info_ptr); int color_type = png_get_color_type(png_ptr, info_ptr); // we want to treat all images the same way // The following code transforms grayscale images of less than 8 to 8 bits, // changes paletted images to RGB, and adds a full alpha channel if there is // transparency information in a tRNS chunk. if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { #if PNG_LIBPNG_VER < 10400 png_set_gray_1_2_4_to_8(png_ptr); #else png_set_expand_gray_1_2_4_to_8(png_ptr); #endif } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); } if (!(color_type & PNG_COLOR_MASK_ALPHA)) { // Set the background color to draw transparent and alpha images over. png_color_16 my_background, *image_background; if (png_get_bKGD(png_ptr, info_ptr, &image_background)) { png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); } else { png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } // Add alpha byte after each RGB triplet png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); } // read the sucker in one chunk png_read_update_info(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); int width = png_get_image_width(png_ptr, info_ptr); int height = png_get_image_height(png_ptr, info_ptr); // allocate the pixel buffer, and the row pointers RGBAImagePtr image(new RGBAImage(width, height)); row_pointers = (png_byte**) malloc((height) * sizeof(png_byte*)); for (int i = 0; i < height; i++) { row_pointers[i] = (png_byte*)(image->getMipMapPixels(0)) + i * 4 * (width); } // actual read png_read_image(png_ptr, row_pointers); /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); /* free up the memory structure */ png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); free(row_pointers); return image; }