diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 14b04a951..8016fd8a9 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -120,6 +120,7 @@ add_library(app-lib file/gif_format.cpp file/ico_format.cpp file/jpeg_format.cpp + file/palette_file.cpp file/pcx_format.cpp file/png_format.cpp file/tga_format.cpp diff --git a/src/app/app.cpp b/src/app/app.cpp index 90caa59f6..8bf19dea7 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -33,6 +33,7 @@ #include "app/document_location.h" #include "app/file/file.h" #include "app/file/file_formats_manager.h" +#include "app/file/palette_file.h" #include "app/file_system.h" #include "app/find_widget.h" #include "app/gui_xml.h" @@ -139,7 +140,7 @@ App::App(int argc, const char* argv[]) } // Register well-known image file types. - FileFormatsManager::instance().registerAllFormats(); + FileFormatsManager::instance()->registerAllFormats(); // init editor cursor Editor::editor_cursor_init(); @@ -165,7 +166,7 @@ App::App(int argc, const char* argv[]) if (!palFile.empty()) { PRINTF("Loading custom palette file: %s\n", palFile.c_str()); - base::UniquePtr pal(Palette::load(palFile.c_str())); + base::UniquePtr pal(load_palette(palFile.c_str())); if (pal.get() != NULL) { set_default_palette(pal.get()); } diff --git a/src/app/commands/cmd_load_palette.cpp b/src/app/commands/cmd_load_palette.cpp index 7dcebf88c..51997dab1 100644 --- a/src/app/commands/cmd_load_palette.cpp +++ b/src/app/commands/cmd_load_palette.cpp @@ -24,6 +24,7 @@ #include "app/commands/command.h" #include "app/commands/commands.h" #include "app/context.h" +#include "app/file/palette_file.h" #include "app/file_selector.h" #include "base/unique_ptr.h" #include "raster/palette.h" @@ -51,9 +52,12 @@ LoadPaletteCommand::LoadPaletteCommand() void LoadPaletteCommand::onExecute(Context* context) { - std::string filename = app::show_file_selector("Load Palette", "", "png,pcx,bmp,tga,lbm,col,gpl"); + char exts[4096]; + get_readable_palette_extensions(exts, sizeof(exts)); + + std::string filename = app::show_file_selector("Load Palette", "", exts); if (!filename.empty()) { - base::UniquePtr palette(raster::Palette::load(filename.c_str())); + base::UniquePtr palette(load_palette(filename.c_str())); if (!palette) { Alert::show("Error<save(filename.c_str())) { + if (!save_palette(filename.c_str(), palette)) { Alert::show("Error<begin(); + FileFormatsList::iterator end = FileFormatsManager::instance()->end(); /* clear the string */ ustrncpy(buf, empty_string, size); @@ -74,8 +72,8 @@ void get_readable_extensions(char* buf, int size) void get_writable_extensions(char* buf, int size) { - FileFormatsList::iterator it = FileFormatsManager::instance().begin(); - FileFormatsList::iterator end = FileFormatsManager::instance().end(); + FileFormatsList::iterator it = FileFormatsManager::instance()->begin(); + FileFormatsList::iterator end = FileFormatsManager::instance()->end(); /* clear the string */ ustrncpy(buf, empty_string, size); @@ -162,8 +160,10 @@ FileOp* fop_to_load_document(Context* context, const char* filename, int flags) goto done; } - /* get the format through the extension of the filename */ - fop->format = get_fileformat(extension.c_str()); + // Get the format through the extension of the filename + fop->format = FileFormatsManager::instance() + ->getFileFormatByExtension(extension.c_str()); + if (!fop->format || !fop->format->support(FILE_SUPPORT_LOAD)) { fop_error(fop, "ASEPRITE can't load \"%s\" files\n", extension.c_str()); @@ -252,8 +252,10 @@ FileOp* fop_to_save_document(Context* context, Document* document) PRINTF("Saving document \"%s\" (%s)\n", fop->document->filename().c_str(), extension.c_str()); - /* get the format through the extension of the filename */ - fop->format = get_fileformat(extension.c_str()); + // Get the format through the extension of the filename + fop->format = FileFormatsManager::instance() + ->getFileFormatByExtension(extension.c_str()); + if (!fop->format || !fop->format->support(FILE_SUPPORT_SAVE)) { fop_error(fop, "ASEPRITE can't save \"%s\" files\n", extension.c_str()); @@ -848,25 +850,6 @@ static void fop_prepare_for_sequence(FileOp* fop) fop->seq.format_options.reset(); } -static FileFormat* get_fileformat(const char* extension) -{ - FileFormatsList::iterator it = FileFormatsManager::instance().begin(); - FileFormatsList::iterator end = FileFormatsManager::instance().end(); - char buf[512], *tok; - - for (; it != end; ++it) { - ustrcpy(buf, (*it)->extensions()); - - for (tok=ustrtok(buf, ","); tok; - tok=ustrtok(NULL, ",")) { - if (ustricmp(extension, tok) == 0) - return (*it); - } - } - - return NULL; -} - // Splits a file-name like "my_ani0000.pcx" to "my_ani" and ".pcx", // returning the number of the center; returns "-1" if the function // can't split anything diff --git a/src/app/file/file_formats_manager.cpp b/src/app/file/file_formats_manager.cpp index a95e579d0..62a532710 100644 --- a/src/app/file/file_formats_manager.cpp +++ b/src/app/file/file_formats_manager.cpp @@ -41,11 +41,11 @@ extern FileFormat* CreateTgaFormat(); static FileFormatsManager* singleton = NULL; // static -FileFormatsManager& FileFormatsManager::instance() +FileFormatsManager* FileFormatsManager::instance() { if (!singleton) singleton = new FileFormatsManager(); - return *singleton; + return singleton; } // static @@ -91,4 +91,21 @@ FileFormatsList::iterator FileFormatsManager::end() return m_formats.end(); } +FileFormat* FileFormatsManager::getFileFormatByExtension(const char* extension) const +{ + char buf[512], *tok; + + for (FileFormat* ff : m_formats) { + strcpy(buf, ff->extensions()); + + for (tok=strtok(buf, ","); tok; + tok=strtok(NULL, ",")) { + if (stricmp(extension, tok) == 0) + return ff; + } + } + + return NULL; +} + } // namespace app diff --git a/src/app/file/file_formats_manager.h b/src/app/file/file_formats_manager.h index c3bf37553..61a53d1f0 100644 --- a/src/app/file/file_formats_manager.h +++ b/src/app/file/file_formats_manager.h @@ -35,7 +35,7 @@ namespace app { class FileFormatsManager { public: // Returns a singleton of this class. - static FileFormatsManager& instance(); + static FileFormatsManager* instance(); static void destroyInstance(); virtual ~FileFormatsManager(); @@ -46,6 +46,8 @@ namespace app { FileFormatsList::iterator begin(); FileFormatsList::iterator end(); + FileFormat* getFileFormatByExtension(const char* extension) const; + private: // Register one format. void registerFormat(FileFormat* fileFormat); diff --git a/src/app/file/file_tests.cpp b/src/app/file/file_tests.cpp index 48fd484e8..160234701 100644 --- a/src/app/file/file_tests.cpp +++ b/src/app/file/file_tests.cpp @@ -36,7 +36,7 @@ TEST(File, SeveralSizes) { she::ScopedHandle system(she::create_system()); // Register all possible image formats. - FileFormatsManager::instance().registerAllFormats(); + FileFormatsManager::instance()->registerAllFormats(); std::vector fn(256); app::Context ctx; diff --git a/src/app/file/gif_tests.cpp b/src/app/file/gif_tests.cpp index 2ba7085aa..ee33b1f51 100644 --- a/src/app/file/gif_tests.cpp +++ b/src/app/file/gif_tests.cpp @@ -33,7 +33,7 @@ using namespace app; class GifFormat : public ::testing::Test { public: GifFormat() : m_system(she::create_system()) { - FileFormatsManager::instance().registerAllFormats(); + FileFormatsManager::instance()->registerAllFormats(); } protected: diff --git a/src/app/file/palette_file.cpp b/src/app/file/palette_file.cpp new file mode 100644 index 000000000..97a8361e7 --- /dev/null +++ b/src/app/file/palette_file.cpp @@ -0,0 +1,139 @@ +/* Aseprite + * Copyright (C) 2001-2014 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "app/context.h" +#include "app/document.h" +#include "app/file/file.h" +#include "app/file/file_format.h" +#include "app/file/file_formats_manager.h" +#include "base/path.h" +#include "base/string.h" +#include "raster/cel.h" +#include "raster/file/col_file.h" +#include "raster/file/gpl_file.h" +#include "raster/image.h" +#include "raster/layer.h" +#include "raster/palette.h" +#include "raster/sprite.h" + +namespace app { + +using namespace raster; + +void get_readable_palette_extensions(char* buf, int size) +{ + get_readable_extensions(buf, size); + strcat(buf, ",col,gpl"); +} + +void get_writable_palette_extensions(char* buf, int size) +{ + get_writable_extensions(buf, size); + strcat(buf, ",col,gpl"); +} + +Palette* load_palette(const char *filename) +{ + std::string ext = base::string_to_lower(base::get_file_extension(filename)); + Palette* pal = NULL; + + if (ext == "col") { + pal = raster::file::load_col_file(filename); + } + else if (ext == "gpl") { + pal = raster::file::load_gpl_file(filename); + } + else { + FileFormat* ff = FileFormatsManager::instance()->getFileFormatByExtension(ext.c_str()); + if (ff->support(FILE_SUPPORT_LOAD)) { + FileOp* fop = fop_to_load_document(NULL, filename, + FILE_LOAD_SEQUENCE_NONE | + FILE_LOAD_ONE_FRAME); + if (fop && !fop->has_error()) { + fop_operate(fop, NULL); + fop_post_load(fop); + + if (fop->document && + fop->document->sprite() && + fop->document->sprite()->getPalette(FrameNumber(0))) { + pal = new Palette( + *fop->document->sprite()->getPalette(FrameNumber(0))); + + // TODO remove this line when support for palettes with less + // than 256 colors is added. + pal->resize(Palette::MaxColors); + } + + delete fop->document; + fop_done(fop); + } + } + } + + if (pal) + pal->setFilename(filename); + + return pal; +} + +bool save_palette(const char *filename, Palette* pal) +{ + std::string ext = base::string_to_lower(base::get_file_extension(filename)); + bool success = false; + + if (ext == "col") { + success = raster::file::save_col_file(pal, filename); + } + else if (ext == "gpl") { + success = raster::file::save_gpl_file(pal, filename); + } + else { + FileFormat* ff = FileFormatsManager::instance()->getFileFormatByExtension(ext.c_str()); + if (ff->support(FILE_SUPPORT_SAVE)) { + app::Context tmpContext; + doc::Document* doc = tmpContext.documents().add( + 16, 16, doc::ColorMode::INDEXED, + Palette::MaxColors); + + Sprite* sprite = doc->sprite(); + doc->sprite()->setPalette(pal, false); + + LayerImage* layer = dynamic_cast(sprite->folder()->getFirstLayer()); + Image* image = layer->getCel(FrameNumber(0))->image(); + + int x, y, c; + for (y=c=0; y<16; y++) + for (x=0; x<16; x++) + image->putPixel(x, y, c++); + + doc->setFilename(filename); + success = (save_document(&tmpContext, doc) == 0); + + doc->close(); + delete doc; + } + } + + return success; +} + +} diff --git a/src/app/file/palette_file.h b/src/app/file/palette_file.h new file mode 100644 index 000000000..39579ef44 --- /dev/null +++ b/src/app/file/palette_file.h @@ -0,0 +1,37 @@ +/* Aseprite + * Copyright (C) 2001-2014 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef APP_FILE_PALETTE_FILE_H_INCLUDED +#define APP_FILE_PALETTE_FILE_H_INCLUDED +#pragma once + +namespace raster { + class Palette; +} + +namespace app { + + void get_readable_palette_extensions(char* buf, int size); + void get_writable_palette_extensions(char* buf, int size); + + raster::Palette* load_palette(const char *filename); + bool save_palette(const char *filename, raster::Palette* pal); + +} // namespace app + +#endif diff --git a/src/app/res/palettes_loader_delegate.cpp b/src/app/res/palettes_loader_delegate.cpp index 43657bd37..79309da75 100644 --- a/src/app/res/palettes_loader_delegate.cpp +++ b/src/app/res/palettes_loader_delegate.cpp @@ -22,6 +22,7 @@ #include "app/res/palettes_loader_delegate.h" +#include "app/file/palette_file.h" #include "app/file_system.h" #include "app/res/palette_resource.h" #include "app/resource_finder.h" @@ -49,7 +50,7 @@ std::string PalettesLoaderDelegate::resourcesLocation() const Resource* PalettesLoaderDelegate::loadResource(const std::string& filename) { - raster::Palette* palette = raster::Palette::load(filename.c_str()); + raster::Palette* palette = load_palette(filename.c_str()); if (!palette) return NULL; diff --git a/src/raster/palette.cpp b/src/raster/palette.cpp index c2ac687a7..691ca6e57 100644 --- a/src/raster/palette.cpp +++ b/src/raster/palette.cpp @@ -22,19 +22,13 @@ #include "raster/palette.h" -#include "base/path.h" -#include "base/string.h" #include "gfx/hsv.h" #include "gfx/rgb.h" #include "raster/conversion_alleg.h" -#include "raster/file/col_file.h" -#include "raster/file/gpl_file.h" #include "raster/image.h" #include -#include // TODO Remove this dependency - namespace raster { using namespace gfx; @@ -405,73 +399,6 @@ void Palette::sort(int from, int to, SortPalette* sort_palette, std::vector // End of Sort stuff ////////////////////////////////////////////////////////////////////// -Palette* Palette::load(const char *filename) -{ - std::string ext = base::string_to_lower(base::get_file_extension(filename)); - Palette* pal = NULL; - - if (ext == "png" || - ext == "pcx" || - ext == "bmp" || - ext == "tga" || - ext == "lbm") { - PALETTE rgbpal; - BITMAP* bmp; - - bmp = load_bitmap(filename, rgbpal); - if (bmp) { - destroy_bitmap(bmp); - - pal = new Palette(FrameNumber(0), MaxColors); - convert_palette_from_allegro(rgbpal, pal); - } - } - else if (ext == "col") { - pal = raster::file::load_col_file(filename); - } - else if (ext == "gpl") { - pal = raster::file::load_gpl_file(filename); - } - - if (pal) - pal->setFilename(filename); - - return pal; -} - -bool Palette::save(const char *filename) const -{ - std::string ext = base::string_to_lower(base::get_file_extension(filename)); - bool success = false; - - if (ext == "png" || - ext == "pcx" || - ext == "bmp" || - ext == "tga") { - PALETTE rgbpal; - BITMAP* bmp; - int c, x, y; - - bmp = create_bitmap_ex(8, 16, 16); - for (y=c=0; y<16; y++) - for (x=0; x<16; x++) - putpixel(bmp, x, y, c++); - - convert_palette_to_allegro(this, rgbpal); - - success = (save_bitmap(filename, bmp, rgbpal) == 0); - destroy_bitmap(bmp); - } - else if (ext == "col") { - success = raster::file::save_col_file(this, filename); - } - else if (ext == "gpl") { - success = raster::file::save_gpl_file(this, filename); - } - - return success; -} - int Palette::findExactMatch(int r, int g, int b) const { for (int i=0; i<(int)m_colors.size(); ++i) diff --git a/src/raster/palette.h b/src/raster/palette.h index 916c619db..3ccf2725e 100644 --- a/src/raster/palette.h +++ b/src/raster/palette.h @@ -98,9 +98,6 @@ namespace raster { void makeRectRamp(int from, int to, int columns); void sort(int from, int to, SortPalette* sort_palette, std::vector& mapping); - static Palette* load(const char *filename); - bool save(const char *filename) const; - int findExactMatch(int r, int g, int b) const; int findBestfit(int r, int g, int b, int mask_index = 0) const;