corona  1.0.2
Corona.cpp
Go to the documentation of this file.
00001 #ifdef _MSC_VER
00002 #pragma warning(disable : 4786)
00003 #endif
00004 
00005 
00006 #include <memory>
00007 #include <string>
00008 #include <vector>
00009 #include <string.h>
00010 #include <ctype.h>
00011 #include "corona.h"
00012 #include "MemoryFile.h"
00013 #include "Open.h"
00014 #include "Save.h"
00015 #include "SimpleImage.h"
00016 
00017 
00018 namespace corona {
00019   namespace hidden {
00020 
00022 
00023     COR_EXPORT(const char*) CorGetVersion() {
00024       return "1.0.2";
00025     }
00026 
00028 
00029     class FFDImpl : public FileFormatDesc {
00030     public:
00031       FFDImpl(FileFormat format, const char* description, const char* exts) {
00032         m_format = format;
00033         m_description = description;
00034 
00035         const char* ext = exts;
00036         while (*ext) {
00037           m_extensions.push_back(ext);
00038           ext += strlen(ext) + 1;
00039         }
00040       }
00041 
00042       FileFormat getFormat()             { return m_format;                }
00043       const char* getDescription()       { return m_description.c_str();   }
00044       size_t getExtensionCount()         { return m_extensions.size();     }
00045       const char* getExtension(size_t i) { return m_extensions[i].c_str(); }
00046 
00047     private:
00048       FileFormat m_format;
00049       std::string m_description;
00050       std::vector<std::string> m_extensions;
00051     };
00052 
00053     FFDImpl ffPNG (FF_PNG,  "PNG Files",  "png\0");
00054     FFDImpl ffJPEG(FF_JPEG, "JPEG Files", "jpeg\0jpg\0");
00055     FFDImpl ffPCX (FF_PCX,  "PCX Files",  "pcx\0");
00056     FFDImpl ffBMP (FF_BMP,  "BMP Files",  "bmp\0");
00057     FFDImpl ffTGA (FF_TGA,  "TGA Files",  "tga\0");
00058     FFDImpl ffGIF (FF_GIF,  "GIF Files",  "gif\0");
00059 
00060     const int MAX_FORMAT_COUNT = 64;
00061     FileFormatDesc** g_read_formats  = 0;
00062     FileFormatDesc** g_write_formats = 0;
00063     FileFormatDesc* g_read_array[MAX_FORMAT_COUNT + 1]  = {0};
00064     FileFormatDesc* g_write_array[MAX_FORMAT_COUNT + 1] = {0};
00065 
00066 
00067     COR_EXPORT(FileFormatDesc**) CorGetSupportedReadFormats() {
00068       if (!g_read_formats) {
00069         g_read_formats = g_read_array;
00070         FileFormatDesc** f = g_read_formats;
00071 #ifndef NO_PNG
00072         *f++ = &ffPNG;
00073 #endif
00074 #ifndef NO_JPEG
00075         *f++ = &ffJPEG;
00076 #endif
00077         *f++ = &ffPCX;
00078         *f++ = &ffBMP;
00079         *f++ = &ffTGA;
00080         *f++ = &ffGIF;
00081       }
00082       return g_read_formats;
00083     }
00084 
00085 
00086     COR_EXPORT(FileFormatDesc**) CorGetSupportedWriteFormats() {
00087       if (!g_write_formats) {
00088         g_write_formats = g_write_array;
00089         FileFormatDesc** f = g_write_formats;
00090 #ifndef NO_PNG
00091         *f++ = &ffPNG;
00092 #endif
00093 #ifndef NO_JPEG
00094         *f++ = &ffJPEG;
00095 #endif
00096         *f++ = &ffTGA;
00097       }
00098       return g_write_formats;
00099     }
00100 
00102 
00103     COR_EXPORT(Image*) CorCreateImage(
00104       int width,
00105       int height,
00106       PixelFormat format)
00107     {
00108       return CreateImage(width, height, format, 0);
00109     }
00110 
00112 
00113     COR_EXPORT(Image*) CorCreateImageWithPixels(
00114       int width,
00115       int height,
00116       PixelFormat format,
00117       void* pixels)
00118     {
00119       // this function only supports creation of non-palettized images
00120       if (!IsDirect(format)) {
00121         return 0;
00122       }
00123 
00124       int size = width * height * GetPixelSize(format);
00125       byte* p = new byte[size];
00126       if (pixels) {
00127         memcpy(p, pixels, size);
00128       } else {
00129         memset(p, 0, size);
00130       }
00131       return new SimpleImage(width, height, format, p);
00132     }
00133 
00135 
00136     COR_EXPORT(Image*) CorCreatePalettizedImage(
00137       int width,
00138       int height,
00139       PixelFormat format,
00140       int palette_size,
00141       PixelFormat palette_format)
00142     {
00143       // only support creation of palettized images
00144       if (!IsPalettized(format) || !IsDirect(palette_format)) {
00145         return 0;
00146       }
00147 
00148       // make sure the palette is the right size
00149       if (palette_size != GetPaletteSize(format)) {
00150         return 0;
00151       }
00152 
00153       int size = width * height * GetPixelSize(format);
00154       byte* pixels = new byte[size];
00155       memset(pixels, 0, size);
00156 
00157       int palette_bytes = palette_size * GetPixelSize(palette_format);
00158       byte* palette = new byte[palette_bytes];
00159       memset(palette, 0, palette_bytes);
00160 
00161       return new SimpleImage(width, height, format, pixels,
00162                              palette, palette_size, palette_format);      
00163     }
00164 
00166 
00167     COR_EXPORT(Image*) CorCloneImage(
00168       Image* source,
00169       PixelFormat format)
00170     {
00171       if (!source) {
00172         // we need an image to clone :)
00173         return 0;
00174       }
00175 
00176       const int width = source->getWidth();
00177       const int height = source->getHeight();
00178       const PixelFormat source_format = source->getFormat();
00179 
00180       const int source_pixel_size = GetPixelSize(source_format);
00181       if (source_pixel_size == 0) {
00182         // unknown pixel size?
00183         return 0;
00184       }
00185 
00186       // duplicate the image
00187       int image_size = width * height * source_pixel_size;
00188       byte* pixels = new byte[image_size];
00189       memcpy(pixels, source->getPixels(), image_size);
00190       
00191       if (IsPalettized(source_format)) {
00192         // clone palette
00193         int palette_size = source->getPaletteSize();
00194         PixelFormat palette_format = source->getPaletteFormat();
00195         int palette_bytes = palette_size * GetPixelSize(palette_format);
00196         byte* palette = new byte[palette_bytes];
00197         memcpy(palette, source->getPalette(), palette_bytes);
00198         Image* image = new SimpleImage(width, height, source_format, pixels,
00199                                        palette, palette_size, palette_format);
00200         return ConvertImage(image, format);
00201       }
00202 
00203       Image* image = new SimpleImage(width, height, source_format, pixels);
00204       return ConvertImage(image, format);
00205     }
00206 
00208 
00209     COR_EXPORT(Image*) CorOpenImage(
00210       const char* filename,
00211       FileFormat file_format)
00212     {
00213       if (!filename) {
00214         return 0;
00215       }
00216 
00217       std::auto_ptr<File> file(OpenFile(filename, false));
00218       return CorOpenImageFromFile(file.get(), file_format);
00219     }
00220 
00222 
00223     COR_EXPORT(Image*) CorOpenImageFromFile(
00224       File* file,
00225       FileFormat file_format)
00226     {
00227       if (!file) {
00228         return 0;
00229       }
00230 
00231 #define TRY_TYPE(type)                                 \
00232   {                                                    \
00233     Image* image = CorOpenImageFromFile(file, (type)); \
00234     if (image) { return image; }                       \
00235   }
00236 
00237       file->seek(0, File::BEGIN);
00238       switch (file_format) {
00239         case FF_AUTODETECT: {
00240 #ifndef NO_PNG
00241           TRY_TYPE(FF_PNG);
00242 #endif
00243 #ifndef NO_JPEG
00244           TRY_TYPE(FF_JPEG);
00245 #endif
00246           TRY_TYPE(FF_PCX);
00247           TRY_TYPE(FF_BMP);
00248           TRY_TYPE(FF_TGA);
00249           TRY_TYPE(FF_GIF);
00250           return 0;
00251         }
00252         
00253 #ifndef NO_PNG
00254         case FF_PNG:  return OpenPNG(file);
00255 #endif
00256 #ifndef NO_JPEG
00257         case FF_JPEG: return OpenJPEG(file);
00258 #endif
00259         case FF_PCX:  return OpenPCX(file);
00260         case FF_BMP:  return OpenBMP(file);
00261         case FF_TGA:  return OpenTGA(file);
00262         case FF_GIF:  return OpenGIF(file);
00263         default:      return 0;
00264       }
00265     }
00266 
00268 
00269     int strcmp_ci(const char* a, const char* b) {
00270       while (*a && *b) {
00271         const int diff = tolower(*a) - tolower(*b);
00272         if (diff != 0) {
00273           return diff;
00274         }
00275         ++a;
00276         ++b;
00277       }
00278       return tolower(*a) - tolower(*b);
00279     }
00280 
00281     bool ends_with(const char* str, const char* ext) {
00282       const int str_len = strlen(str);
00283       const int ext_len = strlen(ext);
00284       return (str_len >= ext_len &&
00285               strcmp_ci(str + str_len - ext_len, ext) == 0);
00286     }
00287 
00288     COR_EXPORT(bool) CorSaveImage(
00289       const char* filename,
00290       FileFormat file_format,
00291       Image* image)
00292     {
00293       if (!filename) {
00294         return false;
00295       }
00296 
00297       if (file_format == FF_AUTODETECT) {
00298         if (ends_with(filename, ".png")) {
00299           file_format = FF_PNG;
00300         } else if (ends_with(filename, ".tga")) {
00301           file_format = FF_TGA;
00302         } else if (ends_with(filename, ".jpg") || ends_with(filename, ".jpeg")) {
00303           file_format = FF_JPEG;
00304         } else {
00305           return false;
00306         }
00307       }
00308 
00309       std::auto_ptr<File> file(OpenFile(filename, true));
00310       return CorSaveImageToFile(file.get(), file_format, image);
00311     }
00312 
00314 
00315     COR_EXPORT(bool) CorSaveImageToFile(
00316       File* file,
00317       FileFormat file_format,
00318       Image* image)
00319     {
00320       if (!file || !image) {
00321         return false;
00322       }
00323 
00324       switch (file_format) {
00325 #ifndef NO_PNG
00326         case FF_PNG:  return SavePNG(file, image);
00327 #endif
00328 #ifndef NO_JPEG
00329         case FF_JPEG: return SaveJPEG(file, image);
00330 #endif
00331         case FF_PCX:  return false;
00332         case FF_BMP:  return false;
00333         case FF_TGA:  return SaveTGA(file, image);
00334         case FF_GIF:  return false;
00335         default:      return false;
00336       }
00337     }
00338 
00340 
00341     COR_EXPORT(int) CorGetPixelSize(PixelFormat format) {
00342       switch (format) {
00343         case PF_R8G8B8A8: return 4;
00344         case PF_R8G8B8:   return 3;
00345         case PF_B8G8R8A8: return 4;
00346         case PF_B8G8R8:   return 3;
00347         case PF_I8:       return 1;
00348         default:          return 0;
00349       }
00350     }
00351 
00353 
00354   }
00355 }