New docio-lib to detect file format by content (fix #776)

This commit is contained in:
David Capello 2016-10-26 19:37:42 -03:00
parent 02e82289dc
commit 693a68844c
29 changed files with 326 additions and 86 deletions

View File

@ -109,6 +109,7 @@ add_subdirectory(gen)
add_subdirectory(gfx) add_subdirectory(gfx)
add_subdirectory(net) add_subdirectory(net)
add_subdirectory(render) add_subdirectory(render)
add_subdirectory(docio)
add_subdirectory(script) add_subdirectory(script)
add_subdirectory(she) add_subdirectory(she)
add_subdirectory(ui) add_subdirectory(ui)

View File

@ -47,11 +47,11 @@ because they don't depend on any other component.
## Level 4 ## Level 4
* [iff](iff/) (base, doc, render): Image File Formats library (load/save documents). * [docio](docio/) (base, flic): Load/save documents.
## Level 5 ## Level 5
* [app](app/) (allegro, base, doc, filters, fixmath, gfx, iff, pen, render, scripting, she, ui, undo, updater, webserver) * [app](app/) (allegro, base, doc, docio, filters, fixmath, flic, gfx, pen, render, scripting, she, ui, undo, updater, webserver)
## Level 6 ## Level 6

View File

@ -451,6 +451,7 @@ target_link_libraries(app-lib
clip clip
css-lib css-lib
doc-lib doc-lib
docio-lib
filters-lib filters-lib
fixmath-lib fixmath-lib
flic-lib flic-lib

View File

@ -145,6 +145,7 @@ private:
class AseFormat : public FileFormat { class AseFormat : public FileFormat {
const char* onGetName() const override { return "ase"; } const char* onGetName() const override { return "ase"; }
const char* onGetExtensions() const override { return "ase,aseprite"; } const char* onGetExtensions() const override { return "ase,aseprite"; }
docio::FileFormat onGetDocioFormat() const override { return docio::FileFormat::ASE_ANIMATION; }
int onGetFlags() const override { int onGetFlags() const override {
return return
FILE_SUPPORT_LOAD | FILE_SUPPORT_LOAD |

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -45,6 +45,7 @@ class BmpFormat : public FileFormat {
const char* onGetName() const override { return "bmp"; } const char* onGetName() const override { return "bmp"; }
const char* onGetExtensions() const override { return "bmp"; } const char* onGetExtensions() const override { return "bmp"; }
docio::FileFormat onGetDocioFormat() const override { return docio::FileFormat::BMP_IMAGE; }
int onGetFlags() const override { int onGetFlags() const override {
return return
FILE_SUPPORT_LOAD | FILE_SUPPORT_LOAD |

View File

@ -28,6 +28,7 @@
#include "base/shared_ptr.h" #include "base/shared_ptr.h"
#include "base/string.h" #include "base/string.h"
#include "doc/doc.h" #include "doc/doc.h"
#include "docio/detect_format.h"
#include "render/quantization.h" #include "render/quantization.h"
#include "render/render.h" #include "render/render.h"
#include "ui/alert.h" #include "ui/alert.h"
@ -127,10 +128,7 @@ FileOp* FileOp::createLoadDocumentOperation(Context* context, const char* filena
if (!fop) if (!fop)
return nullptr; return nullptr;
// Get the extension of the filename (in lower case) LOG("Loading file \"%s\"\n", filename);
std::string extension = base::string_to_lower(base::get_file_extension(filename));
LOG("Loading file \"%s\" (%s)\n", filename, extension.c_str());
// Does file exist? // Does file exist?
if (!base::is_file(filename)) { if (!base::is_file(filename)) {
@ -139,12 +137,12 @@ FileOp* FileOp::createLoadDocumentOperation(Context* context, const char* filena
} }
// Get the format through the extension of the filename // Get the format through the extension of the filename
fop->m_format = FileFormatsManager::instance() fop->m_format = FileFormatsManager::instance()->getFileFormat(
->getFileFormatByExtension(extension.c_str()); docio::detect_format(filename));
if (!fop->m_format || if (!fop->m_format ||
!fop->m_format->support(FILE_SUPPORT_LOAD)) { !fop->m_format->support(FILE_SUPPORT_LOAD)) {
fop->setError("%s can't load \"%s\" files\n", PACKAGE, extension.c_str()); fop->setError("%s can't load \"%s\" file (\"%s\")\n", PACKAGE,
filename, base::get_file_extension(filename).c_str());
goto done; goto done;
} }
@ -228,17 +226,15 @@ FileOp* FileOp::createSaveDocumentOperation(const Context* context,
fop->m_document = const_cast<Document*>(document); fop->m_document = const_cast<Document*>(document);
// Get the extension of the filename (in lower case) // Get the extension of the filename (in lower case)
std::string extension = base::string_to_lower(base::get_file_extension(filename)); LOG("Saving document \"%s\"\n", filename);
LOG("Saving document \"%s\" (%s)\n", filename, extension.c_str());
// Get the format through the extension of the filename // Get the format through the extension of the filename
fop->m_format = FileFormatsManager::instance() fop->m_format = FileFormatsManager::instance()->getFileFormat(
->getFileFormatByExtension(extension.c_str()); docio::detect_format_by_file_extension(filename));
if (!fop->m_format || if (!fop->m_format ||
!fop->m_format->support(FILE_SUPPORT_SAVE)) { !fop->m_format->support(FILE_SUPPORT_SAVE)) {
fop->setError("%s can't save \"%s\" files\n", PACKAGE, extension.c_str()); fop->setError("%s can't save \"%s\" file (\"%s\")\n", PACKAGE,
filename, base::get_file_extension(filename).c_str());
return fop.release(); return fop.release();
} }

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -33,6 +33,11 @@ const char* FileFormat::extensions() const
return onGetExtensions(); return onGetExtensions();
} }
docio::FileFormat FileFormat::docioFormat() const
{
return onGetDocioFormat();
}
bool FileFormat::load(FileOp* fop) bool FileFormat::load(FileOp* fop)
{ {
ASSERT(support(FILE_SUPPORT_LOAD)); ASSERT(support(FILE_SUPPORT_LOAD));

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -9,6 +9,7 @@
#pragma once #pragma once
#include "base/shared_ptr.h" #include "base/shared_ptr.h"
#include "docio/file_format.h"
#include <vector> #include <vector>
@ -44,6 +45,8 @@ namespace app {
const char* name() const; // File format name const char* name() const; // File format name
const char* extensions() const; // Extensions (e.g. "jpeg,jpg") const char* extensions() const; // Extensions (e.g. "jpeg,jpg")
docio::FileFormat docioFormat() const;
bool load(FileOp* fop); bool load(FileOp* fop);
#ifdef ENABLE_SAVE #ifdef ENABLE_SAVE
bool save(FileOp* fop); bool save(FileOp* fop);
@ -70,6 +73,7 @@ namespace app {
protected: protected:
virtual const char* onGetName() const = 0; virtual const char* onGetName() const = 0;
virtual const char* onGetExtensions() const = 0; virtual const char* onGetExtensions() const = 0;
virtual docio::FileFormat onGetDocioFormat() const = 0;
virtual int onGetFlags() const = 0; virtual int onGetFlags() const = 0;
virtual bool onLoad(FileOp* fop) = 0; virtual bool onLoad(FileOp* fop) = 0;

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -13,6 +13,7 @@
#include "app/file/file_format.h" #include "app/file/file_format.h"
#include "app/file/format_options.h" #include "app/file/format_options.h"
#include "base/string.h" #include "base/string.h"
#include "docio/detect_format.h"
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
@ -93,21 +94,12 @@ FileFormatsList::iterator FileFormatsManager::end()
return m_formats.end(); return m_formats.end();
} }
FileFormat* FileFormatsManager::getFileFormatByExtension(const char* extension) const FileFormat* FileFormatsManager::getFileFormat(const docio::FileFormat docioFormat) const
{ {
char buf[512], *tok; for (FileFormat* ff : m_formats)
if (ff->docioFormat() == docioFormat)
for (FileFormat* ff : m_formats) { return ff;
std::strcpy(buf, ff->extensions()); return nullptr;
for (tok=std::strtok(buf, ","); tok;
tok=std::strtok(NULL, ",")) {
if (base::utf8_icmp(extension, tok) == 0)
return ff;
}
}
return NULL;
} }
} // namespace app } // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -8,6 +8,8 @@
#define APP_FILE_FILE_FORMATS_MANAGER_H_INCLUDED #define APP_FILE_FILE_FORMATS_MANAGER_H_INCLUDED
#pragma once #pragma once
#include "docio/file_format.h"
#include <vector> #include <vector>
namespace app { namespace app {
@ -34,7 +36,7 @@ namespace app {
FileFormatsList::iterator begin(); FileFormatsList::iterator begin();
FileFormatsList::iterator end(); FileFormatsList::iterator end();
FileFormat* getFileFormatByExtension(const char* extension) const; FileFormat* getFileFormat(const docio::FileFormat docioFormat) const;
private: private:
// Register one format. // Register one format.

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -27,6 +27,7 @@ using namespace base;
class FliFormat : public FileFormat { class FliFormat : public FileFormat {
const char* onGetName() const override { return "flc"; } const char* onGetName() const override { return "flc"; }
const char* onGetExtensions() const override{ return "flc,fli"; } const char* onGetExtensions() const override{ return "flc,fli"; }
docio::FileFormat onGetDocioFormat() const override { return docio::FileFormat::FLIC_ANIMATION; }
int onGetFlags() const override { int onGetFlags() const override {
return return
FILE_SUPPORT_LOAD | FILE_SUPPORT_LOAD |

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -63,6 +63,7 @@ class GifFormat : public FileFormat {
const char* onGetName() const override { return "gif"; } const char* onGetName() const override { return "gif"; }
const char* onGetExtensions() const override { return "gif"; } const char* onGetExtensions() const override { return "gif"; }
docio::FileFormat onGetDocioFormat() const override { return docio::FileFormat::GIF_ANIMATION; }
int onGetFlags() const override { int onGetFlags() const override {
return return
FILE_SUPPORT_LOAD | FILE_SUPPORT_LOAD |

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -26,6 +26,7 @@ using namespace base;
class IcoFormat : public FileFormat { class IcoFormat : public FileFormat {
const char* onGetName() const override { return "ico"; } const char* onGetName() const override { return "ico"; }
const char* onGetExtensions() const override { return "ico"; } const char* onGetExtensions() const override { return "ico"; }
docio::FileFormat onGetDocioFormat() const override { return docio::FileFormat::ICO_IMAGES; }
int onGetFlags() const override { int onGetFlags() const override {
return return
FILE_SUPPORT_LOAD | FILE_SUPPORT_LOAD |

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -42,6 +42,7 @@ class JpegFormat : public FileFormat {
const char* onGetName() const override { return "jpeg"; } const char* onGetName() const override { return "jpeg"; }
const char* onGetExtensions() const override { return "jpeg,jpg"; } const char* onGetExtensions() const override { return "jpeg,jpg"; }
docio::FileFormat onGetDocioFormat() const override { return docio::FileFormat::JPEG_IMAGE; }
int onGetFlags() const override { int onGetFlags() const override {
return return
FILE_SUPPORT_LOAD | FILE_SUPPORT_LOAD |

View File

@ -24,6 +24,7 @@
#include "doc/layer.h" #include "doc/layer.h"
#include "doc/palette.h" #include "doc/palette.h"
#include "doc/sprite.h" #include "doc/sprite.h"
#include "docio/detect_format.h"
#include <cstring> #include <cstring>
@ -45,26 +46,34 @@ std::string get_writable_palette_extensions()
return buf; return buf;
} }
Palette* load_palette(const char *filename) Palette* load_palette(const char* filename)
{ {
std::string ext = base::string_to_lower(base::get_file_extension(filename)); docio::FileFormat docioFormat = docio::detect_format(filename);
Palette* pal = NULL; Palette* pal = nullptr;
switch (docioFormat) {
case docio::FileFormat::COL_PALETTE:
pal = doc::file::load_col_file(filename);
break;
case docio::FileFormat::GPL_PALETTE:
pal = doc::file::load_gpl_file(filename);
break;
case docio::FileFormat::HEX_PALETTE:
pal = doc::file::load_hex_file(filename);
break;
case docio::FileFormat::PAL_PALETTE:
pal = doc::file::load_pal_file(filename);
break;
default: {
FileFormat* ff = FileFormatsManager::instance()->getFileFormat(docioFormat);
if (!ff || !ff->support(FILE_SUPPORT_LOAD))
break;
if (ext == "col") {
pal = doc::file::load_col_file(filename);
}
else if (ext == "gpl") {
pal = doc::file::load_gpl_file(filename);
}
else if (ext == "hex") {
pal = doc::file::load_hex_file(filename);
}
else if (ext == "pal") {
pal = doc::file::load_pal_file(filename);
}
else {
FileFormat* ff = FileFormatsManager::instance()->getFileFormatByExtension(ext.c_str());
if (ff && ff->support(FILE_SUPPORT_LOAD)) {
base::UniquePtr<FileOp> fop( base::UniquePtr<FileOp> fop(
FileOp::createLoadDocumentOperation( FileOp::createLoadDocumentOperation(
nullptr, filename, nullptr, filename,
@ -85,6 +94,7 @@ Palette* load_palette(const char *filename)
delete fop->releaseDocument(); delete fop->releaseDocument();
fop->done(); fop->done();
} }
break;
} }
} }
@ -94,26 +104,34 @@ Palette* load_palette(const char *filename)
return pal; return pal;
} }
bool save_palette(const char *filename, const Palette* pal, int columns) bool save_palette(const char* filename, const Palette* pal, int columns)
{ {
std::string ext = base::string_to_lower(base::get_file_extension(filename)); docio::FileFormat docioFormat = docio::detect_format_by_file_extension(filename);
bool success = false; bool success = false;
if (ext == "col") { switch (docioFormat) {
success = doc::file::save_col_file(pal, filename);
} case docio::FileFormat::COL_PALETTE:
else if (ext == "gpl") { success = doc::file::save_col_file(pal, filename);
success = doc::file::save_gpl_file(pal, filename); break;
}
else if (ext == "hex") { case docio::FileFormat::GPL_PALETTE:
success = doc::file::save_hex_file(pal, filename); success = doc::file::save_gpl_file(pal, filename);
} break;
else if (ext == "pal") {
success = doc::file::save_pal_file(pal, filename); case docio::FileFormat::HEX_PALETTE:
} success = doc::file::save_hex_file(pal, filename);
else { break;
FileFormat* ff = FileFormatsManager::instance()->getFileFormatByExtension(ext.c_str());
if (ff && ff->support(FILE_SUPPORT_SAVE)) { case docio::FileFormat::PAL_PALETTE:
success = doc::file::save_pal_file(pal, filename);
break;
default: {
FileFormat* ff = FileFormatsManager::instance()->getFileFormat(docioFormat);
if (!ff || !ff->support(FILE_SUPPORT_SAVE))
break;
int w = (columns > 0 ? MID(0, columns, pal->size()): pal->size()); int w = (columns > 0 ? MID(0, columns, pal->size()): pal->size());
int h = (pal->size() / w) + (pal->size() % w > 0 ? 1: 0); int h = (pal->size() / w) + (pal->size() % w > 0 ? 1: 0);
@ -150,6 +168,7 @@ bool save_palette(const char *filename, const Palette* pal, int columns)
doc->close(); doc->close();
delete doc; delete doc;
break;
} }
} }

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -24,6 +24,7 @@ using namespace base;
class PcxFormat : public FileFormat { class PcxFormat : public FileFormat {
const char* onGetName() const override { return "pcx"; } const char* onGetName() const override { return "pcx"; }
const char* onGetExtensions() const override { return "pcx"; } const char* onGetExtensions() const override { return "pcx"; }
docio::FileFormat onGetDocioFormat() const override { return docio::FileFormat::PCX_IMAGE; }
int onGetFlags() const override { int onGetFlags() const override {
return return
FILE_SUPPORT_LOAD | FILE_SUPPORT_LOAD |

View File

@ -31,6 +31,7 @@ using namespace base;
class PixlyFormat : public FileFormat { class PixlyFormat : public FileFormat {
const char* onGetName() const override { return "anim"; } const char* onGetName() const override { return "anim"; }
const char* onGetExtensions() const override { return "anim"; } const char* onGetExtensions() const override { return "anim"; }
docio::FileFormat onGetDocioFormat() const override { return docio::FileFormat::PIXLY_ANIMATION; }
int onGetFlags() const override { int onGetFlags() const override {
return return
FILE_SUPPORT_LOAD | FILE_SUPPORT_LOAD |

View File

@ -29,6 +29,7 @@ using namespace base;
class PngFormat : public FileFormat { class PngFormat : public FileFormat {
const char* onGetName() const override { return "png"; } const char* onGetName() const override { return "png"; }
const char* onGetExtensions() const override { return "png"; } const char* onGetExtensions() const override { return "png"; }
docio::FileFormat onGetDocioFormat() const override { return docio::FileFormat::PNG_IMAGE; }
int onGetFlags() const override { int onGetFlags() const override {
return return
FILE_SUPPORT_LOAD | FILE_SUPPORT_LOAD |

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2001-2015 David Capello // Copyright (C) 2001-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -25,6 +25,7 @@ using namespace base;
class TgaFormat : public FileFormat { class TgaFormat : public FileFormat {
const char* onGetName() const override { return "tga"; } const char* onGetName() const override { return "tga"; }
const char* onGetExtensions() const override { return "tga"; } const char* onGetExtensions() const override { return "tga"; }
docio::FileFormat onGetDocioFormat() const override { return docio::FileFormat::TARGA_IMAGE; }
int onGetFlags() const override { int onGetFlags() const override {
return return
FILE_SUPPORT_LOAD | FILE_SUPPORT_LOAD |

View File

@ -1,6 +1,6 @@
// Aseprite // Aseprite
// Copyright (C) 2015 Gabriel Rauter // Copyright (C) 2015 Gabriel Rauter
// Copyright (C) 2015 David Capello // Copyright (C) 2015-2016 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
// the End-User License Agreement for Aseprite. // the End-User License Agreement for Aseprite.
@ -41,6 +41,7 @@ class WebPFormat : public FileFormat {
const char* onGetName() const override { return "webp"; } const char* onGetName() const override { return "webp"; }
const char* onGetExtensions() const override { return "webp"; } const char* onGetExtensions() const override { return "webp"; }
docio::FileFormat onGetDocioFormat() const override { return docio::WEBP_ANIMATION; }
int onGetFlags() const override { int onGetFlags() const override {
return return
FILE_SUPPORT_LOAD | FILE_SUPPORT_LOAD |

View File

@ -1,4 +1,4 @@
Copyright (c) 2001-2015 David Capello Copyright (c) 2001-2016 David Capello
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

View File

@ -1,4 +1,4 @@
# Aseprite Document Library # Aseprite Document Library
*Copyright (C) 2001-2015 David Capello* *Copyright (C) 2001-2016 David Capello*
> Distributed under [MIT license](LICENSE.txt) > Distributed under [MIT license](LICENSE.txt)

9
src/docio/CMakeLists.txt Normal file
View File

@ -0,0 +1,9 @@
# Aseprite Document IO Library
# Copyright (c) 2016 David Capello
add_library(docio-lib
detect_format.cpp)
target_link_libraries(docio-lib
flic-lib
base-lib)

View File

@ -1,4 +1,4 @@
Copyright (c) 2014 David Capello Copyright (c) 2016 David Capello
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

4
src/docio/README.md Normal file
View File

@ -0,0 +1,4 @@
# Aseprite Document IO Library
*Copyright (C) 2016 David Capello*
> Distributed under [MIT license](LICENSE.txt)

140
src/docio/detect_format.cpp Normal file
View File

@ -0,0 +1,140 @@
// Aseprite Document IO Library
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#include "docio/detect_format.h"
#include "base/file_handle.h"
#include "base/path.h"
#include "base/string.h"
#include "flic/flic_details.h"
#include <cstring>
#define ASE_MAGIC_NUMBER 0xA5E0
#define BMP_MAGIC_NUMBER 0x4D42 // "BM"
#define JPG_MAGIC_NUMBER 0xD8FF
#define GIF_87_STAMP "GIF87a"
#define GIF_89_STAMP "GIF89a"
#define PNG_MAGIC_DWORD1 0x474E5089
#define PNG_MAGIC_DWORD2 0x0A1A0A0D
namespace docio {
FileFormat detect_format(const std::string& filename)
{
FileFormat ff = detect_format_by_file_content(filename);
if (ff == FileFormat::UNKNOWN)
ff = detect_format_by_file_extension(filename);
return ff;
}
FileFormat detect_format_by_file_content(const std::string& filename)
{
#define IS_MAGIC_WORD(offset, word) \
((buf[offset+0] == (word & 0xff)) && \
(buf[offset+1] == ((word & 0xff00) >> 8)))
#define IS_MAGIC_DWORD(offset, dword) \
((buf[offset+0] == (dword & 0xff)) && \
(buf[offset+1] == ((dword & 0xff00) >> 8)) && \
(buf[offset+2] == ((dword & 0xff0000) >> 16)) && \
(buf[offset+3] == ((dword & 0xff000000) >> 24)))
base::FileHandle handle(base::open_file(filename.c_str(), "rb"));
if (!handle)
return FileFormat::ERROR;
FILE* f = handle.get();
unsigned char buf[8];
int count = fread(buf, 1, 8, f);
if (count >= 2) {
if (IS_MAGIC_WORD(0, BMP_MAGIC_NUMBER))
return FileFormat::BMP_IMAGE;
if (IS_MAGIC_WORD(0, JPG_MAGIC_NUMBER))
return FileFormat::JPEG_IMAGE;
if (count >= 6) {
if (std::strncmp((const char*)buf, GIF_87_STAMP, 6) == 0 ||
std::strncmp((const char*)buf, GIF_89_STAMP, 6) == 0)
return FileFormat::GIF_ANIMATION;
if (IS_MAGIC_WORD(4, ASE_MAGIC_NUMBER))
return FileFormat::ASE_ANIMATION;
if (IS_MAGIC_WORD(4, FLI_MAGIC_NUMBER) ||
IS_MAGIC_WORD(4, FLC_MAGIC_NUMBER))
return FileFormat::FLIC_ANIMATION;
if (count >= 8) {
if (IS_MAGIC_DWORD(0, PNG_MAGIC_DWORD1) &&
IS_MAGIC_DWORD(4, PNG_MAGIC_DWORD2))
return FileFormat::PNG_IMAGE;
}
}
}
return FileFormat::UNKNOWN;
}
FileFormat detect_format_by_file_extension(const std::string& filename)
{
// By extension
const std::string ext = base::string_to_lower(base::get_file_extension(filename));
if (ext == "ase" ||
ext == "aseprite")
return FileFormat::ASE_ANIMATION;
if (ext == "bmp")
return FileFormat::BMP_IMAGE;
if (ext == "col")
return FileFormat::COL_PALETTE;
if (ext == "flc" ||
ext == "fli")
return FileFormat::FLIC_ANIMATION;
if (ext == "gif")
return FileFormat::GIF_ANIMATION;
if (ext == "gpl")
return FileFormat::GPL_PALETTE;
if (ext == "hex")
return FileFormat::HEX_PALETTE;
if (ext == "ico")
return FileFormat::ICO_IMAGES;
if (ext == "jpg" ||
ext == "jpeg")
return FileFormat::JPEG_IMAGE;
if (ext == "pal")
return FileFormat::PAL_PALETTE;
if (ext == "pcx")
return FileFormat::PCX_IMAGE;
if (ext == "anim")
return FileFormat::PIXLY_ANIMATION;
if (ext == "png")
return FileFormat::PNG_IMAGE;
if (ext == "tga")
return FileFormat::TARGA_IMAGE;
if (ext == "webp")
return FileFormat::WEBP_ANIMATION;
return FileFormat::UNKNOWN;
}
} // namespace docio

23
src/docio/detect_format.h Normal file
View File

@ -0,0 +1,23 @@
// Aseprite Document IO Library
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef DOCIO_DETECT_FORMAT_H_INCLUDED
#define DOCIO_DETECT_FORMAT_H_INCLUDED
#pragma once
#include "docio/file_format.h"
#include <string>
namespace docio {
FileFormat detect_format(const std::string& filename);
FileFormat detect_format_by_file_content(const std::string& filename);
FileFormat detect_format_by_file_extension(const std::string& filename);
} // namespace docio
#endif

37
src/docio/file_format.h Normal file
View File

@ -0,0 +1,37 @@
// Aseprite Document IO Library
// Copyright (c) 2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef DOCIO_FILE_FORMAT_H_INCLUDED
#define DOCIO_FILE_FORMAT_H_INCLUDED
#pragma once
namespace docio {
enum class FileFormat {
ERROR = -1,
UNKNOWN = 0,
ASE_ANIMATION, // Aseprite File Format
ASE_PALETTE, // Adobe Swatch Exchange
BMP_IMAGE,
COL_PALETTE,
FLIC_ANIMATION,
GIF_ANIMATION,
GPL_PALETTE,
HEX_PALETTE,
ICO_IMAGES,
JPEG_IMAGE,
PAL_PALETTE,
PCX_IMAGE,
PIXLY_ANIMATION,
PNG_IMAGE,
TARGA_IMAGE,
WEBP_ANIMATION,
};
} // namespace docio
#endif

View File

@ -1,4 +0,0 @@
# Aseprite Image File Formats Library
*Copyright (C) 2014 David Capello*
> Distributed under [MIT license](LICENSE.txt)