Fix #11 - now we support all formats to load/save palettes

Also we've removed dependency with Allegro code to load/save palette files.
This commit is contained in:
David Capello 2014-08-21 23:39:20 -03:00
parent 31e6b31cd0
commit ddaacd2f7b
15 changed files with 231 additions and 118 deletions

View File

@ -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

View File

@ -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<Palette> pal(Palette::load(palFile.c_str()));
base::UniquePtr<Palette> pal(load_palette(palFile.c_str()));
if (pal.get() != NULL) {
set_default_palette(pal.get());
}

View File

@ -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<raster::Palette> palette(raster::Palette::load(filename.c_str()));
base::UniquePtr<raster::Palette> palette(load_palette(filename.c_str()));
if (!palette) {
Alert::show("Error<<Loading palette file||&Close");
}

View File

@ -21,6 +21,7 @@
#endif
#include "app/commands/command.h"
#include "app/file/palette_file.h"
#include "app/file_selector.h"
#include "app/modules/palettes.h"
#include "base/fs.h"
@ -50,11 +51,14 @@ SavePaletteCommand::SavePaletteCommand()
void SavePaletteCommand::onExecute(Context* context)
{
char exts[4096];
get_writable_palette_extensions(exts, sizeof(exts));
std::string filename;
int ret;
again:
filename = app::show_file_selector("Save Palette", "", "png,pcx,bmp,tga,col,gpl");
filename = app::show_file_selector("Save Palette", "", exts);
if (!filename.empty()) {
if (base::is_file(filename)) {
ret = Alert::show("Warning<<File exists, overwrite it?<<%s||&Yes||&No||&Cancel",
@ -67,7 +71,7 @@ again:
}
raster::Palette* palette = get_current_palette();
if (!palette->save(filename.c_str())) {
if (!save_palette(filename.c_str(), palette)) {
Alert::show("Error<<Saving palette file||&Close");
}
}

View File

@ -20,6 +20,7 @@
#define APP_DOCUMENT_H_INCLUDED
#pragma once
#include "app/file/format_options.h"
#include "base/disable_copying.h"
#include "base/observable.h"
#include "base/shared_ptr.h"
@ -54,7 +55,6 @@ namespace undo {
namespace app {
class DocumentApi;
class DocumentUndo;
class FormatOptions;
struct BoundSeg;
using namespace raster;

View File

@ -50,14 +50,12 @@ using namespace base;
static FileOp* fop_new(FileOpType type, Context* context);
static void fop_prepare_for_sequence(FileOp* fop);
static FileFormat* get_fileformat(const char* extension);
static int split_filename(const char* filename, char* left, char* right, int* width);
void get_readable_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);
@ -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

View File

@ -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

View File

@ -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);

View File

@ -36,7 +36,7 @@ TEST(File, SeveralSizes)
{
she::ScopedHandle<she::System> system(she::create_system());
// Register all possible image formats.
FileFormatsManager::instance().registerAllFormats();
FileFormatsManager::instance()->registerAllFormats();
std::vector<char> fn(256);
app::Context ctx;

View File

@ -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:

View File

@ -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<LayerImage*>(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;
}
}

View File

@ -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

View File

@ -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;

View File

@ -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 <algorithm>
#include <allegro.h> // 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<int>
// 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)

View File

@ -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<int>& 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;