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