#include #include #include #include #include #include "corona.h" #include "MemoryFile.h" #include "Open.h" #include "Save.h" #include "SimpleImage.h" namespace corona { namespace hidden { /////////////////////////////////////////////////////////////////////////// COR_EXPORT(const char*) CorGetVersion() { return "1.0.2"; } /////////////////////////////////////////////////////////////////////////// class FFDImpl : public FileFormatDesc { public: FFDImpl(FileFormat format, const char* description, const char* exts) { m_format = format; m_description = description; const char* ext = exts; while (*ext) { m_extensions.push_back(ext); ext += strlen(ext) + 1; } } FileFormat getFormat() { return m_format; } const char* getDescription() { return m_description.c_str(); } size_t getExtensionCount() { return m_extensions.size(); } const char* getExtension(size_t i) { return m_extensions[i].c_str(); } private: FileFormat m_format; std::string m_description; std::vector m_extensions; }; FFDImpl ffPNG (FF_PNG, "PNG Files", "png\0"); FFDImpl ffJPEG(FF_JPEG, "JPEG Files", "jpeg\0jpg\0"); FFDImpl ffPCX (FF_PCX, "PCX Files", "pcx\0"); FFDImpl ffBMP (FF_BMP, "BMP Files", "bmp\0"); FFDImpl ffTGA (FF_TGA, "TGA Files", "tga\0"); FFDImpl ffGIF (FF_GIF, "GIF Files", "gif\0"); const int MAX_FORMAT_COUNT = 64; FileFormatDesc** g_read_formats = 0; FileFormatDesc** g_write_formats = 0; FileFormatDesc* g_read_array[MAX_FORMAT_COUNT + 1] = {0}; FileFormatDesc* g_write_array[MAX_FORMAT_COUNT + 1] = {0}; COR_EXPORT(FileFormatDesc**) CorGetSupportedReadFormats() { if (!g_read_formats) { g_read_formats = g_read_array; FileFormatDesc** f = g_read_formats; *f++ = &ffPNG; *f++ = &ffPCX; *f++ = &ffBMP; *f++ = &ffTGA; } return g_read_formats; } COR_EXPORT(FileFormatDesc**) CorGetSupportedWriteFormats() { if (!g_write_formats) { g_write_formats = g_write_array; FileFormatDesc** f = g_write_formats; *f++ = &ffPNG; *f++ = &ffTGA; } return g_write_formats; } /////////////////////////////////////////////////////////////////////////// COR_EXPORT(Image*) CorCreateImage( int width, int height, PixelFormat format) { return CreateImage(width, height, format, 0); } /////////////////////////////////////////////////////////////////////////// COR_EXPORT(Image*) CorCreateImageWithPixels( int width, int height, PixelFormat format, void* pixels) { // this function only supports creation of non-palettized images if (!IsDirect(format)) { return 0; } int size = width * height * GetPixelSize(format); byte* p = new byte[size]; if (pixels) { memcpy(p, pixels, size); } else { memset(p, 0, size); } return new SimpleImage(width, height, format, p); } /////////////////////////////////////////////////////////////////////////// COR_EXPORT(Image*) CorCreatePalettizedImage( int width, int height, PixelFormat format, int palette_size, PixelFormat palette_format) { // only support creation of palettized images if (!IsPalettized(format) || !IsDirect(palette_format)) { return 0; } // make sure the palette is the right size if (palette_size != GetPaletteSize(format)) { return 0; } int size = width * height * GetPixelSize(format); byte* pixels = new byte[size]; memset(pixels, 0, size); int palette_bytes = palette_size * GetPixelSize(palette_format); byte* palette = new byte[palette_bytes]; memset(palette, 0, palette_bytes); return new SimpleImage(width, height, format, pixels, palette, palette_size, palette_format); } /////////////////////////////////////////////////////////////////////////// COR_EXPORT(Image*) CorCloneImage( Image* source, PixelFormat format) { if (!source) { // we need an image to clone :) return 0; } const int width = source->getWidth(); const int height = source->getHeight(); const PixelFormat source_format = source->getFormat(); const int source_pixel_size = GetPixelSize(source_format); if (source_pixel_size == 0) { // unknown pixel size? return 0; } // duplicate the image int image_size = width * height * source_pixel_size; byte* pixels = new byte[image_size]; memcpy(pixels, source->getPixels(), image_size); if (IsPalettized(source_format)) { // clone palette int palette_size = source->getPaletteSize(); PixelFormat palette_format = source->getPaletteFormat(); int palette_bytes = palette_size * GetPixelSize(palette_format); byte* palette = new byte[palette_bytes]; memcpy(palette, source->getPalette(), palette_bytes); Image* image = new SimpleImage(width, height, source_format, pixels, palette, palette_size, palette_format); return ConvertImage(image, format); } Image* image = new SimpleImage(width, height, source_format, pixels); return ConvertImage(image, format); } /////////////////////////////////////////////////////////////////////////// COR_EXPORT(Image*) CorOpenImage( const char* filename, FileFormat file_format) { if (!filename) { return 0; } std::auto_ptr file(OpenFile(filename, false)); return CorOpenImageFromFile(file.get(), file_format); } /////////////////////////////////////////////////////////////////////////// COR_EXPORT(Image*) CorOpenImageFromFile( File* file, FileFormat file_format) { if (!file) { return 0; } #define TRY_TYPE(type) \ { \ Image* image = CorOpenImageFromFile(file, (type)); \ if (image) { return image; } \ } file->seek(0, File::BEGIN); switch (file_format) { case FF_AUTODETECT: { TRY_TYPE(FF_PNG); TRY_TYPE(FF_PCX); TRY_TYPE(FF_BMP); TRY_TYPE(FF_TGA); return 0; } case FF_PNG: return OpenPNG(file); case FF_PCX: return OpenPCX(file); case FF_BMP: return OpenBMP(file); case FF_TGA: return OpenTGA(file); default: return 0; } } /////////////////////////////////////////////////////////////////////////// int strcmp_ci(const char* a, const char* b) { while (*a && *b) { const int diff = tolower(*a) - tolower(*b); if (diff != 0) { return diff; } ++a; ++b; } return tolower(*a) - tolower(*b); } bool ends_with(const char* str, const char* ext) { const int str_len = strlen(str); const int ext_len = strlen(ext); return (str_len >= ext_len && strcmp_ci(str + str_len - ext_len, ext) == 0); } COR_EXPORT(bool) CorSaveImage( const char* filename, FileFormat file_format, Image* image) { if (!filename) { return false; } if (file_format == FF_AUTODETECT) { if (ends_with(filename, ".png")) { file_format = FF_PNG; } else if (ends_with(filename, ".tga")) { file_format = FF_TGA; } else { return false; } } std::auto_ptr file(OpenFile(filename, true)); return CorSaveImageToFile(file.get(), file_format, image); } /////////////////////////////////////////////////////////////////////////// COR_EXPORT(bool) CorSaveImageToFile( File* file, FileFormat file_format, Image* image) { if (!file || !image) { return false; } switch (file_format) { case FF_PNG: return SavePNG(file, image); case FF_JPEG: return false; case FF_PCX: return false; case FF_BMP: return false; case FF_TGA: return SaveTGA(file, image); case FF_GIF: return false; default: return false; } } /////////////////////////////////////////////////////////////////////////// COR_EXPORT(int) CorGetPixelSize(PixelFormat format) { switch (format) { case PF_R8G8B8A8: return 4; case PF_R8G8B8: return 3; case PF_B8G8R8A8: return 4; case PF_B8G8R8: return 3; case PF_I8: return 1; default: return 0; } } /////////////////////////////////////////////////////////////////////////// } }