static Surface *TryPNG(FILE *inFile,const uint8 *inData, int inDataLen) { png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. REQUIRED */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, user_error_fn, user_warning_fn); if (png_ptr == NULL) return (0); /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return (0); } /* Set error handling if you are using the setjmp/longjmp method (this is * the normal method of doing things with libpng). REQUIRED unless you * set up your own error handlers in the png_create_read_struct() earlier. */ Surface *result = 0; RenderTarget target; if (setjmp(png_jmpbuf(png_ptr))) { if (result) { result->EndRender(); result->DecRef(); } /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); /* If we get here, we had a problem reading the file */ return (0); } ReadBuf buffer(inData,inDataLen); if (inFile) { png_init_io(png_ptr, inFile); } else { png_set_read_fn(png_ptr,(void *)&buffer, user_read_data_fn); } png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); bool has_alpha = color_type== PNG_COLOR_TYPE_GRAY_ALPHA || color_type==PNG_COLOR_TYPE_RGB_ALPHA || png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS); /* Add filler (or alpha) byte (before/after each RGB triplet) */ png_set_expand(png_ptr); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); //png_set_gray_1_2_4_to_8(png_ptr); png_set_palette_to_rgb(png_ptr); png_set_gray_to_rgb(png_ptr); // Stripping 16 bits per channel to 8 bits per channel. if (bit_depth == 16) png_set_strip_16(png_ptr); png_set_bgr(png_ptr); result = new SimpleSurface(width,height, (has_alpha) ? pfARGB : pfXRGB); result->IncRef(); target = result->BeginRender(Rect(width,height)); /* if the image is interlaced, run multiple passes */ int number_of_passes = png_set_interlace_handling(png_ptr); for (int pass = 0; pass < number_of_passes; pass++) { for (int i = 0; i < height; i++) { png_bytep anAddr = (png_bytep) target.Row(i); png_read_rows(png_ptr, (png_bytepp) &anAddr, NULL, 1); } } result->EndRender(); /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); /* clean up after the read, and free any memory allocated - REQUIRED */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); /* that's it */ return result; }
static Surface *TryJPEG(FILE *inFile,const uint8 *inData, int inDataLen) { struct jpeg_decompress_struct cinfo; // Don't exit on error! struct ErrorData jpegError; cinfo.err = jpeg_std_error(&jpegError.base); jpegError.base.error_exit = OnError; jpegError.base.output_message = OnOutput; Surface *result = 0; uint8 *row_buf = 0; // Establish the setjmp return context for ErrorFunction to use if (setjmp(jpegError.on_error)) { if (row_buf) free(row_buf); if (result) result->DecRef(); jpeg_destroy_decompress(&cinfo); return 0; } // Initialize the JPEG decompression object. jpeg_create_decompress(&cinfo); // Specify data source (ie, a file, or buffer) MySrcManager manager(inData,inDataLen); if (inFile) jpeg_stdio_src(&cinfo, inFile); else { cinfo.src = &manager.pub; } // Read file parameters with jpeg_read_header(). if (jpeg_read_header(&cinfo, TRUE)!=JPEG_HEADER_OK) return 0; cinfo.out_color_space = JCS_RGB; // Start decompressor. jpeg_start_decompress(&cinfo); result = new SimpleSurface(cinfo.output_width, cinfo.output_height, pfXRGB); result->IncRef(); RenderTarget target = result->BeginRender(Rect(cinfo.output_width, cinfo.output_height)); row_buf = (uint8 *)malloc(cinfo.output_width * 3); while (cinfo.output_scanline < cinfo.output_height) { uint8 * src = row_buf; uint8 * dest = target.Row(cinfo.output_scanline); jpeg_read_scanlines(&cinfo, &row_buf, 1); uint8 *end = dest + cinfo.output_width*4; while (dest<end) { dest[0] = src[2]; dest[1] = src[1]; dest[2] = src[0]; dest[3] = 0xff; dest+=4; src+=3; } } result->EndRender(); free(row_buf); // Finish decompression. jpeg_finish_decompress(&cinfo); // Release JPEG decompression object jpeg_destroy_decompress(&cinfo); return result; }