mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-02 11:59:58 +00:00
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:
parent
31e6b31cd0
commit
ddaacd2f7b
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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:
|
||||
|
139
src/app/file/palette_file.cpp
Normal file
139
src/app/file/palette_file.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
37
src/app/file/palette_file.h
Normal file
37
src/app/file/palette_file.h
Normal 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
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user