ImageLoaders.cpp

Go to the documentation of this file.
00001 #include "ImageLoaders.h"
00002 #include "MercuryTextureManager.h"
00003 #include "MercuryFiles.h"
00004 #include "MercuryLog.h"
00005 
00006 //for PNG Loading
00007 #if defined(WIN32)
00008 #  include <png.h>
00009 #  if defined(_MSC_VER)
00010 #    pragma comment(lib, "libpng.lib")
00011 #  endif
00012 #  pragma warning(disable: 4611) /* interaction between '_setjmp' and C++ object destruction is non-portable */
00013 #else
00014 #  include <png.h>
00015 #endif
00016 
00017 #define abort_( x ) { LOG.Warn(x); return NULL; }
00018 
00019 void PNGRead( png_struct *png, png_byte *p, png_size_t size )
00020 {
00021     MercuryFile* f = (MercuryFile*)png->io_ptr;
00022 
00023     int got = f->Read( p, size );
00024 
00025     if( got == -1 )
00026         png_error( png, "Error reading from file");
00027 //  else if( got != size )
00028 //      png_error( png, "Unexpected EOF" );
00029 }
00030 
00031 
00032 RawImageData* LoadPNG( MercuryFile * fp )
00033 {
00034     png_structp png_ptr;
00035     png_infop info_ptr;
00036     int number_of_passes;
00037     png_bytep* row_pointers;
00038     png_byte color_type;
00039     png_byte bit_depth;
00040     RawImageData* image;
00041     unsigned char header[8];    // 8 is the maximum size that can be checked
00042 
00043     //open file and test for it being a png 
00044     if (!fp)
00045         abort_("[read_png_file] File %s could not be opened for reading");
00046     fp->Read(header, 8 );
00047     if (png_sig_cmp(header, 0, 8))
00048         abort_("[read_png_file] File %s is not recognized as a PNG file");
00049 
00050 
00051     //initialize stuff 
00052     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00053 
00054     if (!png_ptr)
00055         abort_("[read_png_file] png_create_read_struct failed");
00056 
00057     info_ptr = png_create_info_struct(png_ptr);
00058     if (!info_ptr)
00059         abort_("[read_png_file] png_create_info_struct failed");
00060 
00061     if (setjmp(png_jmpbuf(png_ptr)))
00062         abort_("[read_png_file] Error during init_io");
00063 
00064     png_set_sig_bytes(png_ptr, 8);
00065     png_set_read_fn( png_ptr, fp, PNGRead );
00066 
00067     png_read_info(png_ptr, info_ptr);
00068 
00069     image = new RawImageData;
00070 
00071     image->attrs.m_width = info_ptr->width;
00072     image->attrs.m_height = info_ptr->height;
00073     color_type = info_ptr->color_type;
00074     bit_depth = info_ptr->bit_depth;
00075 
00076 //  if ( color_type & PNG_COLOR_MASK_PALETTE )
00077 //  {
00078 //      SAFE_DELETE(image);
00079 //      abort_("Cannot open paletted PNG files.");
00080 //  }
00081     if (color_type == PNG_COLOR_TYPE_PALETTE)
00082         png_set_palette_to_rgb(png_ptr);
00083 
00084     number_of_passes = png_set_interlace_handling(png_ptr);
00085     png_read_update_info(png_ptr, info_ptr);
00086 
00087     // read file 
00088     if (setjmp(png_jmpbuf(png_ptr)))
00089     {
00090         SAFE_DELETE(image);
00091         abort_("[read_png_file] Error during read_image");
00092     }
00093 
00094     row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * image->attrs.m_height);
00095     unsigned int y;
00096     for ( y=0; y < (unsigned)image->attrs.m_height; y++)
00097         row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes);
00098 
00099     png_read_image(png_ptr, row_pointers);
00100 
00101     png_read_end( png_ptr, info_ptr );
00102     png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
00103 
00104     png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
00105 
00106     if (color_type & PNG_COLOR_MASK_ALPHA)
00107         image->attrs.m_ColorByteType = RGBA;    
00108     else
00109         image->attrs.m_ColorByteType = RGB; 
00110 
00111 //  SAFE_DELETE(texture->m_data);
00112     
00113     image->data = new unsigned char[sizeof(unsigned char) * image->attrs.m_height * image->attrs.m_width *  4];
00114 
00115     switch (image->attrs.m_ColorByteType)
00116     {
00117     case RGBA:
00118         for ( y=0; y < (unsigned)image->attrs.m_height; ++y) {
00119             png_byte* row = row_pointers[y];
00120             for (int x = 0; x < image->attrs.m_width; ++x) {
00121                 png_byte* ptr = &(row[x*4]);
00122                 image->data[(x + y * image->attrs.m_width) * 4] = ptr[0];
00123                 image->data[(x + y * image->attrs.m_width) * 4 + 1] = ptr[1];
00124                 image->data[(x + y * image->attrs.m_width) * 4 + 2] = ptr[2];
00125                 image->data[(x + y * image->attrs.m_width) * 4 + 3] = ptr[3];
00126             }   
00127         }
00128         break;
00129     case RGB:
00130         for ( y=0; y < (unsigned)image->attrs.m_height; y++) {
00131             png_byte* row = row_pointers[y];
00132             for (int x=0; x<image->attrs.m_width; x++) {
00133                 png_byte* ptr = &(row[x * 3]);
00134                 image->data[(x + y * image->attrs.m_width) * 3] = ptr[0];
00135                 image->data[(x + y * image->attrs.m_width) * 3 + 1] = ptr[1];
00136                 image->data[(x + y * image->attrs.m_width) * 3 + 2] = ptr[2];
00137             }   
00138         }
00139         break;
00140     default:
00141         LOG.Warn("Invalid color byte type for PNG.");
00142     }
00143 
00144     for ( y=0; y < (unsigned)image->attrs.m_height; y++)
00145         SAFE_DELETE(row_pointers[y]);
00146     SAFE_DELETE(row_pointers);
00147 
00148 //  texture->CorrectSize();
00149 //  texture->CreateCache(); 
00150 
00151     return image;
00152 }
00153 
00154 RawImageData* LoadBMP( MercuryFile * file )
00155 {
00156     int offset;
00157     char* tmp = new char[sizeof(int)];
00158     int compression = 0;
00159     int length;
00160     int rawlength = 0;
00161     int bitsapix = 0;
00162     unsigned char b[3];
00163     unsigned int res_x, res_y;
00164 
00165     LOG.Info( "BMP Load Start" );
00166     if (file==NULL)
00167     {
00168         LOG.Warn("Could not open BMP (null file pointer)");
00169         SAFE_DELETE(tmp);
00170         return NULL;
00171     }
00172 
00173     //Get the type of file and test
00174     memset(tmp, 0, 4);
00175     file->Read(tmp, sizeof(char) * 2);
00176     MString type(tmp);
00177 
00178     if (type != "BM")
00179     {
00180         LOG.Warn("\"" + file->GetName() + "\" not a valid BMP");
00181         SAFE_DELETE(tmp);
00182         return NULL;
00183     }
00184     //Offset of bitmap data.
00185     file->Seek(10);
00186     file->Read(tmp, 4);
00187     memcpy(&offset, tmp, 4);
00188     TO_ENDIAN( offset );
00189 
00190     RawImageData* image = new RawImageData;
00191 
00192     //width & width
00193     file->Seek(18);
00194     file->Read(tmp, sizeof(int));
00195     memcpy(&image->attrs.m_width, tmp, sizeof(int));
00196     TO_ENDIAN( image->attrs.m_width );
00197     file->Read(tmp, sizeof(int));
00198     memcpy(&image->attrs.m_height, tmp, sizeof(int));
00199     TO_ENDIAN( image->attrs.m_height );
00200 
00201     //bits per pixel
00202     memset(tmp, 0, sizeof(int));
00203     file->Seek(28);
00204     file->Read(tmp, sizeof(int));
00205     memcpy(&bitsapix, tmp, sizeof(int));
00206     TO_ENDIAN( bitsapix );
00207 
00208     if (bitsapix != 24)
00209     {
00210         LOG.Warn("\"" + file->GetName() + "\" is not 24b/pix");
00211         SAFE_DELETE(tmp);
00212         SAFE_DELETE(image);
00213         return NULL;
00214     }
00215 
00216     //compression
00217     file->Seek(30);
00218     file->Read(tmp, sizeof(int));
00219     memcpy(&compression, tmp, sizeof(int));
00220     TO_ENDIAN(compression);
00221 
00222     if (compression != 0)
00223     {
00224         LOG.Warn("\"" + file->GetName() + "\" uses compression (not supported)");
00225         SAFE_DELETE(tmp);
00226         SAFE_DELETE(image);
00227         return NULL;
00228     }
00229 
00230     //pix/m X
00231     memset(tmp, 0, sizeof(int));
00232     file->Seek(38);
00233     file->Read(tmp, sizeof(int));
00234     memcpy(&res_x, tmp, sizeof(int));
00235     TO_ENDIAN(res_x);
00236 
00237     //pix/m Y
00238     memset(tmp, 0, sizeof(int));
00239     file->Seek(42);
00240     file->Read(tmp, sizeof(int));
00241     memcpy(&res_y, tmp, sizeof(int));
00242     TO_ENDIAN(res_y);
00243 
00244     if (res_x > 0)
00245     {
00246         image->attrs.m_dpi_x = M2DPI(res_x);
00247     }
00248 
00249     if (res_y > 0)
00250     {
00251         image->attrs.m_dpi_y = M2DPI(res_y);
00252     }
00253 
00254     //Get the file length
00255     length = file->Length();
00256     rawlength = (length) - (offset-1); //Remember to subtract 1 from the offset.
00257 
00258     //Allocate space
00259     SAFE_DELETE(image->data);
00260     image->data = new unsigned char[rawlength];
00261     memset(image->data, 0, rawlength);
00262 
00263     //Get raw data and convert BGR->RGB
00264     file->Seek(offset);
00265     for (unsigned int x = 0; !file->Eof(); x += 3)
00266     {
00267         memset(b, 0, sizeof(unsigned char) * 3);
00268         file->Read((char*)&b, sizeof(unsigned char) * 3);
00269 
00270         image->data[x] = b[2];
00271         image->data[x+1] = b[1];
00272         image->data[x+2] = b[0];
00273     }
00274     image->attrs.m_ColorByteType = RGB;
00275     SAFE_DELETE(tmp);
00276     LOG.Info( "BMP Load End" );
00277     return image;
00278 }
00279 
00280 RUN_STATEMENT_AT_BOOT( include_png, IMAGEREADERREGISTER.AddDecoder( LoadPNG, "‰PN" ); )
00281 RUN_STATEMENT_AT_BOOT( include_bmp, IMAGEREADERREGISTER.AddDecoder( LoadBMP, "BM8" ); )
00282 
00283 
00284 /* 
00285  * Copyright (c) 2004 Glenn Maynard
00286  * (c) 2006 Joshua Allen
00287  * All rights reserved.
00288  *
00289  * Redistribution and use in source and binary forms, with or
00290  * without modification, are permitted provided that the following
00291  * conditions are met:
00292  *  -   Redistributions of source code must retain the above
00293  *      copyright notice, this list of conditions and the following disclaimer.
00294  *  -   Redistributions in binary form must reproduce the above copyright
00295  *      notice, this list of conditions and the following disclaimer in
00296  *      the documentation and/or other materials provided with the distribution.
00297  *  -   Neither the name of the Mercury Engine nor the names of its
00298  *      contributors may be used to endorse or promote products derived from
00299  *      this software without specific prior written permission.
00300  *
00301  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00302  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00303  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00304  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00305  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00306  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00307  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00308  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00309  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00310  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00311  */

Hosted by SourceForge.net Logo