corona
1.0.2
|
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 }