mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-01 01:13:40 +00:00
Merge branch 'webp-support'
This commit is contained in:
commit
6bfae49eb0
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -10,3 +10,6 @@
|
||||
[submodule "third_party/duktape"]
|
||||
path = third_party/duktape
|
||||
url = https://github.com/aseprite/duktape.git
|
||||
[submodule "third_party/libwebp"]
|
||||
path = third_party/libwebp
|
||||
url = https://chromium.googlesource.com/webm/libwebp
|
||||
|
@ -40,6 +40,7 @@ option(USE_SHARED_JPEGLIB "Use your installed copy of jpeglib" off)
|
||||
option(USE_SHARED_ZLIB "Use your installed copy of zlib" off)
|
||||
option(USE_SHARED_LIBPNG "Use your installed copy of libpng" off)
|
||||
option(USE_SHARED_LIBLOADPNG "Use your installed copy of libloadpng" off)
|
||||
option(USE_SHARED_LIBWEBP "Use your installed copy of libwebp" off)
|
||||
option(USE_SHARED_TINYXML "Use your installed copy of tinyxml" off)
|
||||
option(USE_SHARED_PIXMAN "Use your installed copy of pixman" off)
|
||||
option(USE_SHARED_ALLEGRO4 "Use shared Allegro 4 library (without resize support)" off)
|
||||
@ -106,6 +107,7 @@ set(LIBFREETYPE_DIR ${CMAKE_SOURCE_DIR}/third_party/freetype)
|
||||
set(LIBJPEG_DIR ${CMAKE_SOURCE_DIR}/third_party/jpeg)
|
||||
set(LIBPNG_DIR ${CMAKE_SOURCE_DIR}/third_party/libpng)
|
||||
set(LOADPNG_DIR ${CMAKE_SOURCE_DIR}/third_party/loadpng)
|
||||
set(LIBWEBP_DIR ${CMAKE_SOURCE_DIR}/third_party/libwebp)
|
||||
set(MONGOOSE_DIR ${CMAKE_SOURCE_DIR}/third_party/mongoose)
|
||||
set(PIXMAN_DIR ${CMAKE_SOURCE_DIR}/third_party/pixman)
|
||||
set(SIMPLEINI_DIR ${CMAKE_SOURCE_DIR}/third_party/simpleini)
|
||||
@ -170,6 +172,19 @@ endif()
|
||||
include_directories(${PNG_INCLUDE_DIR})
|
||||
add_definitions(-DPNG_NO_MMX_CODE) # Do not use MMX optimizations in PNG code
|
||||
|
||||
# libwebp
|
||||
if(USE_SHARED_LIBWEBP)
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(WEBP libwebp)
|
||||
if(NOT WEBP_FOUND)
|
||||
message(FATAL_ERROR "libwebp not found")
|
||||
endif()
|
||||
else()
|
||||
set(WEBP_LIBRARIES webp)
|
||||
set(WEBP_INCLUDE_DIR ${LIBWEBP_DIR}/src)
|
||||
endif()
|
||||
include_directories(${WEBP_INCLUDE_DIR})
|
||||
|
||||
# tinyxml
|
||||
if(USE_SHARED_TINYXML)
|
||||
find_library(TINYXML_LIBRARY NAMES tinyxml)
|
||||
|
@ -77,6 +77,7 @@ of the following projects created by third-parties:
|
||||
* [giflib](http://sourceforge.net/projects/giflib/) - [giflib license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/giflib-LICENSE.txt)
|
||||
* [libjpeg](http://www.ijg.org/) - [libjpeg license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/libjpeg-LICENSE.txt)
|
||||
* [libpng](http://www.libpng.org/pub/png/) - [libpng license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/libpng-LICENSE.txt)
|
||||
* [libwebp](https://developers.google.com/speed/webp/) - [libwebp license](https://chromium.googlesource.com/webm/libwebp/+/master/COPYING)
|
||||
* [loadpng](http://tjaden.strangesoft.net/loadpng/) - [zlib license](https://github.com/aseprite/aseprite/tree/master/docs/licenses/ZLIB.txt)
|
||||
* [mongoose](https://github.com/valenok/mongoose) - [MIT license](https://github.com/valenok/mongoose/blob/master/LICENSE)
|
||||
* [pixman](http://www.pixman.org/) - [MIT license](http://cgit.freedesktop.org/pixman/plain/COPYING)
|
||||
|
47
data/widgets/webp_options.xml
Normal file
47
data/widgets/webp_options.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<!-- ASEPRITE -->
|
||||
<!-- Copyright (C) 2015 by Gabriel Rauter -->
|
||||
<gui>
|
||||
<window text="WebP Options" id="webp_options">
|
||||
<vbox>
|
||||
<label text="Save as:" />
|
||||
<radio group="1" text="Lossless WebP" id="lossless" tooltip="Save in simple WebP lossless format." />
|
||||
<hbox>
|
||||
<label width="55" text="Compression:" />
|
||||
<slider min="0" max="9" id="compression" cell_align="horizontal" width="128" />
|
||||
</hbox>
|
||||
<hbox>
|
||||
<label width="55" text="Image Hint:" />
|
||||
<combobox width="128" id="image_hint">
|
||||
<listitem text="Default" value="0" />
|
||||
<listitem text="Picture" value="1" />
|
||||
<listitem text="Photo" value="2" />
|
||||
<listitem text="Graph" value="3" />
|
||||
</combobox>
|
||||
</hbox>
|
||||
<separator horizontal="true" />
|
||||
<radio group="1" text="Lossy WebP" id="lossy" tooltip="Save in simple WebP lossy format." />
|
||||
<hbox>
|
||||
<label width="55" text="Quality:" />
|
||||
<slider min="0" max="100" id="quality" cell_align="horizontal" width="128" />
|
||||
</hbox>
|
||||
<hbox>
|
||||
<label width="55" text="Image Preset:" />
|
||||
<combobox width="128" id="image_preset">
|
||||
<listitem text="Default" value="0" />
|
||||
<listitem text="Picture" value="1" />
|
||||
<listitem text="Photo" value="2" />
|
||||
<listitem text="Drawing" value="3" />
|
||||
<listitem text="Icon" value="4" />
|
||||
<listitem text="Text" value="5" />
|
||||
</combobox>
|
||||
</hbox>
|
||||
<hbox>
|
||||
<boxfiller />
|
||||
<hbox homogeneous="true">
|
||||
<button text="&OK" closewindow="true" id="ok" magnet="true" minwidth="60" />
|
||||
<button text="&Cancel" closewindow="true" />
|
||||
</hbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</window>
|
||||
</gui>
|
@ -274,6 +274,7 @@ add_library(app-lib
|
||||
file/png_format.cpp
|
||||
file/split_filename.cpp
|
||||
file/tga_format.cpp
|
||||
file/webp_format.cpp
|
||||
file_selector.cpp
|
||||
file_system.cpp
|
||||
filename_formatter.cpp
|
||||
@ -412,6 +413,7 @@ target_link_libraries(app-lib
|
||||
${JPEG_LIBRARIES}
|
||||
${GIF_LIBRARIES}
|
||||
${PNG_LIBRARIES}
|
||||
${WEBP_LIBRARIES}
|
||||
${ZLIB_LIBRARIES})
|
||||
|
||||
if(ENABLE_UPDATER)
|
||||
|
@ -29,6 +29,7 @@ extern FileFormat* CreateJpegFormat();
|
||||
extern FileFormat* CreatePcxFormat();
|
||||
extern FileFormat* CreatePngFormat();
|
||||
extern FileFormat* CreateTgaFormat();
|
||||
extern FileFormat* CreateWebPFormat();
|
||||
|
||||
static FileFormatsManager* singleton = NULL;
|
||||
|
||||
@ -67,6 +68,7 @@ void FileFormatsManager::registerAllFormats()
|
||||
registerFormat(CreatePcxFormat());
|
||||
registerFormat(CreatePngFormat());
|
||||
registerFormat(CreateTgaFormat());
|
||||
registerFormat(CreateWebPFormat());
|
||||
}
|
||||
|
||||
void FileFormatsManager::registerFormat(FileFormat* fileFormat)
|
||||
|
352
src/app/file/webp_format.cpp
Normal file
352
src/app/file/webp_format.cpp
Normal file
@ -0,0 +1,352 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2015 Gabriel Rauter
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/console.h"
|
||||
#include "app/context.h"
|
||||
#include "app/document.h"
|
||||
#include "app/file/file.h"
|
||||
#include "app/file/file_format.h"
|
||||
#include "app/file/format_options.h"
|
||||
#include "app/file/webp_options.h"
|
||||
#include "app/ini_file.h"
|
||||
#include "base/file_handle.h"
|
||||
#include "base/convert_to.h"
|
||||
#include "doc/doc.h"
|
||||
|
||||
#include "generated_webp_options.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
|
||||
//include webp librarys
|
||||
#include <webp/decode.h>
|
||||
#include <webp/encode.h>
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace base;
|
||||
|
||||
class WebPFormat : public FileFormat {
|
||||
|
||||
const char* onGetName() const { return "webp"; }
|
||||
const char* onGetExtensions() const { return "webp"; }
|
||||
int onGetFlags() const {
|
||||
return
|
||||
FILE_SUPPORT_LOAD |
|
||||
FILE_SUPPORT_SAVE |
|
||||
FILE_SUPPORT_RGB |
|
||||
FILE_SUPPORT_RGBA |
|
||||
FILE_SUPPORT_SEQUENCES |
|
||||
FILE_SUPPORT_GET_FORMAT_OPTIONS;
|
||||
}
|
||||
|
||||
bool onLoad(FileOp* fop) override;
|
||||
#ifdef ENABLE_SAVE
|
||||
bool onSave(FileOp* fop) override;
|
||||
#endif
|
||||
|
||||
base::SharedPtr<FormatOptions> onGetFormatOptions(FileOp* fop) override;
|
||||
};
|
||||
|
||||
FileFormat* CreateWebPFormat()
|
||||
{
|
||||
return new WebPFormat;
|
||||
}
|
||||
|
||||
const char* getDecoderErrorMessage(VP8StatusCode statusCode) {
|
||||
switch (statusCode) {
|
||||
case VP8_STATUS_OK: return ""; break;
|
||||
case VP8_STATUS_OUT_OF_MEMORY: return "out of memory"; break;
|
||||
case VP8_STATUS_INVALID_PARAM: return "invalid parameters"; break;
|
||||
case VP8_STATUS_BITSTREAM_ERROR: return "bitstream error"; break;
|
||||
case VP8_STATUS_UNSUPPORTED_FEATURE: return "unsupported feature"; break;
|
||||
case VP8_STATUS_SUSPENDED: return "suspended"; break;
|
||||
case VP8_STATUS_USER_ABORT: return "user aborted"; break;
|
||||
case VP8_STATUS_NOT_ENOUGH_DATA: return "not enough data"; break;
|
||||
default: return "unknown error"; break;
|
||||
}
|
||||
}
|
||||
|
||||
bool WebPFormat::onLoad(FileOp* fop)
|
||||
{
|
||||
FileHandle handle(open_file_with_exception(fop->filename, "rb"));
|
||||
FILE* fp = handle.get();
|
||||
|
||||
if (fseek(fp, 0, SEEK_END) != 0) {
|
||||
fop_error(fop, "Error while getting WebP file size for %s\n", fop->filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
long len = ftell(fp);
|
||||
rewind(fp);
|
||||
|
||||
if (len < 4) {
|
||||
fop_error(fop, "%s is corrupt or not a WebP file\n", fop->filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> buf(len);
|
||||
uint8_t* data = &buf.front();
|
||||
|
||||
if (!fread(data, sizeof(uint8_t), len, fp)) {
|
||||
fop_error(fop, "Error while writing to %s to memory\n", fop->filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
WebPDecoderConfig config;
|
||||
if (!WebPInitDecoderConfig(&config)) {
|
||||
fop_error(fop, "LibWebP version mismatch %s\n", fop->filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (WebPGetFeatures(data, len, &config.input) != VP8_STATUS_OK) {
|
||||
fop_error(fop, "Bad bitstream in %s\n", fop->filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
fop->seq.has_alpha = (config.input.has_alpha != 0);
|
||||
|
||||
Image* image = fop_sequence_image(fop, IMAGE_RGB, config.input.width, config.input.height);
|
||||
|
||||
config.output.colorspace = MODE_RGBA;
|
||||
config.output.u.RGBA.rgba = (uint8_t*)image->getPixelAddress(0, 0);
|
||||
config.output.u.RGBA.stride = config.input.width * sizeof(uint32_t);
|
||||
config.output.u.RGBA.size = config.input.width * config.input.height * sizeof(uint32_t);
|
||||
config.output.is_external_memory = 1;
|
||||
|
||||
WebPIDecoder* idec = WebPIDecode(NULL, 0, &config);
|
||||
if (idec == NULL) {
|
||||
fop_error(fop, "Error creating WebP decoder for %s\n", fop->filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
long bytes_remaining = len;
|
||||
long bytes_read = std::max(4l, len/100l);
|
||||
|
||||
while (bytes_remaining > 0) {
|
||||
VP8StatusCode status = WebPIAppend(idec, data, bytes_read);
|
||||
if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {
|
||||
bytes_remaining -= bytes_read;
|
||||
data += bytes_read;
|
||||
if (bytes_remaining < bytes_read) bytes_read = bytes_remaining;
|
||||
fop_progress(fop, 1.0f - ((float)std::max(bytes_remaining, 0l)/(float)len));
|
||||
} else {
|
||||
fop_error(fop, "Error during decoding %s : %s\n", fop->filename.c_str(), getDecoderErrorMessage(status));
|
||||
WebPIDelete(idec);
|
||||
WebPFreeDecBuffer(&config.output);
|
||||
return false;
|
||||
}
|
||||
if (fop_is_stop(fop))
|
||||
break;
|
||||
}
|
||||
|
||||
base::SharedPtr<WebPOptions> webPOptions = base::SharedPtr<WebPOptions>(new WebPOptions());
|
||||
fop->seq.format_options = webPOptions;
|
||||
webPOptions->setLossless(std::min(config.input.format - 1, 1));
|
||||
|
||||
WebPIDelete(idec);
|
||||
WebPFreeDecBuffer(&config.output);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SAVE
|
||||
struct writerData {
|
||||
FILE* fp;
|
||||
FileOp* fop;
|
||||
};
|
||||
|
||||
const char* getEncoderErrorMessage(WebPEncodingError errorCode) {
|
||||
switch (errorCode) {
|
||||
case VP8_ENC_OK: return ""; break;
|
||||
case VP8_ENC_ERROR_OUT_OF_MEMORY: return "memory error allocating objects"; break;
|
||||
case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY: return "memory error while flushing bits"; break;
|
||||
case VP8_ENC_ERROR_NULL_PARAMETER: return "a pointer parameter is NULL"; break;
|
||||
case VP8_ENC_ERROR_INVALID_CONFIGURATION: return "configuration is invalid"; break;
|
||||
case VP8_ENC_ERROR_BAD_DIMENSION: return "picture has invalid width/height"; break;
|
||||
case VP8_ENC_ERROR_PARTITION0_OVERFLOW: return "partition is bigger than 512k"; break;
|
||||
case VP8_ENC_ERROR_PARTITION_OVERFLOW: return "partition is bigger than 16M"; break;
|
||||
case VP8_ENC_ERROR_BAD_WRITE: return "error while flushing bytes"; break;
|
||||
case VP8_ENC_ERROR_FILE_TOO_BIG: return "file is bigger than 4G"; break;
|
||||
case VP8_ENC_ERROR_USER_ABORT: return "abort request by user"; break;
|
||||
case VP8_ENC_ERROR_LAST: return "abort request by user"; break;
|
||||
default: return ""; break;
|
||||
}
|
||||
}
|
||||
|
||||
#if WEBP_ENCODER_ABI_VERSION < 0x0203
|
||||
#define MAX_LEVEL 9
|
||||
// Mapping between -z level and -m / -q parameter settings.
|
||||
static const struct {
|
||||
uint8_t method_;
|
||||
uint8_t quality_;
|
||||
} kLosslessPresets[MAX_LEVEL + 1] = {
|
||||
{ 0, 0 }, { 1, 20 }, { 2, 25 }, { 3, 30 }, { 3, 50 },
|
||||
{ 4, 50 }, { 4, 75 }, { 4, 90 }, { 5, 90 }, { 6, 100 }
|
||||
};
|
||||
int WebPConfigLosslessPreset(WebPConfig* config, int level) {
|
||||
if (config == NULL || level < 0 || level > MAX_LEVEL) return 0;
|
||||
config->lossless = 1;
|
||||
config->method = kLosslessPresets[level].method_;
|
||||
config->quality = kLosslessPresets[level].quality_;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ProgressReport(int percent, const WebPPicture* const pic)
|
||||
{
|
||||
fop_progress(((writerData*)pic->custom_ptr)->fop, (double)percent/(double)100);
|
||||
if (fop_is_stop(((writerData*)pic->custom_ptr)->fop)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int FileWriter(const uint8_t* data, size_t data_size, const WebPPicture* const pic)
|
||||
{
|
||||
return data_size ? (fwrite(data, data_size, 1, ((writerData*)pic->custom_ptr)->fp) == 1) : 1;
|
||||
}
|
||||
|
||||
bool WebPFormat::onSave(FileOp* fop)
|
||||
{
|
||||
FileHandle handle(open_file_with_exception(fop->filename, "wb"));
|
||||
FILE* fp = handle.get();
|
||||
|
||||
struct writerData wd = {fp, fop};
|
||||
|
||||
Image* image = fop->seq.image.get();
|
||||
if (image->width() > WEBP_MAX_DIMENSION || image->height() > WEBP_MAX_DIMENSION) {
|
||||
fop_error(
|
||||
fop, "Error: WebP can only have a maximum width and height of %i but your %s has a size of %i x %i\n",
|
||||
WEBP_MAX_DIMENSION, fop->filename.c_str(), image->width(), image->height()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
base::SharedPtr<WebPOptions> webp_options = fop->seq.format_options;
|
||||
|
||||
WebPConfig config;
|
||||
|
||||
if (webp_options->lossless()) {
|
||||
if (!(WebPConfigInit(&config) && WebPConfigLosslessPreset(&config, webp_options->getMethod()))) {
|
||||
fop_error(fop, "Error for WebP Config Version for file %s\n", fop->filename.c_str());
|
||||
return false;
|
||||
}
|
||||
config.image_hint = webp_options->getImageHint();
|
||||
} else {
|
||||
if (!WebPConfigPreset(&config, webp_options->getImagePreset(), static_cast<float>(webp_options->getQuality()))) {
|
||||
fop_error(fop, "Error for WebP Config Version for file %s\n", fop->filename.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WebPValidateConfig(&config)) {
|
||||
fop_error(fop, "Error in WebP Encoder Config for file %s\n", fop->filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
WebPPicture pic;
|
||||
if (!WebPPictureInit(&pic)) {
|
||||
fop_error(fop, "Error for WebP Picture Version mismatch for file %s\n", fop->filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
pic.width = image->width();
|
||||
pic.height = image->height();
|
||||
if (webp_options->lossless()) {
|
||||
pic.use_argb = true;
|
||||
}
|
||||
|
||||
if (!WebPPictureAlloc(&pic)) {
|
||||
fop_error(fop, "Error for WebP Picture memory allocations for file %s\n", fop->filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!WebPPictureImportRGBA(&pic, (uint8_t*)image->getPixelAddress(0, 0), image->width() * sizeof(uint32_t))) {
|
||||
fop_error(fop, "Error for LibWebP Import RGBA Buffer into Picture for %s\n", fop->filename.c_str());
|
||||
WebPPictureFree(&pic);
|
||||
return false;
|
||||
}
|
||||
|
||||
pic.writer = FileWriter;
|
||||
pic.custom_ptr = &wd;
|
||||
pic.progress_hook = ProgressReport;
|
||||
|
||||
if (!WebPEncode(&config, &pic)) {
|
||||
fop_error(fop, "Error for LibWebP while Encoding %s: %s\n", fop->filename.c_str(), getEncoderErrorMessage(pic.error_code));
|
||||
WebPPictureFree(&pic);
|
||||
return false;
|
||||
}
|
||||
|
||||
WebPPictureFree(&pic);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Shows the WebP configuration dialog.
|
||||
base::SharedPtr<FormatOptions> WebPFormat::onGetFormatOptions(FileOp* fop)
|
||||
{
|
||||
base::SharedPtr<WebPOptions> webp_options;
|
||||
if (fop->document->getFormatOptions())
|
||||
webp_options = base::SharedPtr<WebPOptions>(fop->document->getFormatOptions());
|
||||
|
||||
if (!webp_options)
|
||||
webp_options.reset(new WebPOptions);
|
||||
|
||||
// Non-interactive mode
|
||||
if (!fop->context || !fop->context->isUIAvailable())
|
||||
return webp_options;
|
||||
|
||||
try {
|
||||
// Configuration parameters
|
||||
webp_options->setQuality(get_config_int("WEBP", "Quality", webp_options->getQuality()));
|
||||
webp_options->setMethod(get_config_int("WEBP", "Compression", webp_options->getMethod()));
|
||||
webp_options->setImageHint(get_config_int("WEBP", "ImageHint", webp_options->getImageHint()));
|
||||
webp_options->setImagePreset(get_config_int("WEBP", "ImagePreset", webp_options->getImagePreset()));
|
||||
|
||||
// Load the window to ask to the user the WebP options he wants.
|
||||
|
||||
app::gen::WebpOptions win;
|
||||
win.lossless()->setSelected(webp_options->lossless());
|
||||
win.lossy()->setSelected(!webp_options->lossless());
|
||||
win.quality()->setValue(static_cast<int>(webp_options->getQuality()));
|
||||
win.compression()->setValue(webp_options->getMethod());
|
||||
win.imageHint()->setSelectedItemIndex(webp_options->getImageHint());
|
||||
win.imagePreset()->setSelectedItemIndex(webp_options->getImagePreset());
|
||||
|
||||
win.openWindowInForeground();
|
||||
|
||||
if (win.getKiller() == win.ok()) {
|
||||
webp_options->setQuality(win.quality()->getValue());
|
||||
webp_options->setMethod(win.compression()->getValue());
|
||||
webp_options->setLossless(win.lossless()->isSelected());
|
||||
webp_options->setImageHint(base::convert_to<int>(win.imageHint()->getValue()));
|
||||
webp_options->setImagePreset(base::convert_to<int>(win.imagePreset()->getValue()));
|
||||
|
||||
set_config_int("WEBP", "Quality", webp_options->getQuality());
|
||||
set_config_int("WEBP", "Compression", webp_options->getMethod());
|
||||
set_config_int("WEBP", "ImageHint", webp_options->getImageHint());
|
||||
set_config_int("WEBP", "ImagePreset", webp_options->getImagePreset());
|
||||
}
|
||||
else {
|
||||
webp_options.reset(NULL);
|
||||
}
|
||||
|
||||
return webp_options;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
Console::showException(e);
|
||||
return base::SharedPtr<WebPOptions>(0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace app
|
48
src/app/file/webp_options.h
Normal file
48
src/app/file/webp_options.h
Normal file
@ -0,0 +1,48 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2015 Gabriel Rauter
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
|
||||
#ifndef APP_FILE_WEBP_OPTIONS_H_INCLUDED
|
||||
#define APP_FILE_WEBP_OPTIONS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/file/format_options.h"
|
||||
|
||||
#include <webp/decode.h>
|
||||
#include <webp/encode.h>
|
||||
|
||||
namespace app {
|
||||
// Data for WebP files
|
||||
class WebPOptions : public FormatOptions {
|
||||
public:
|
||||
WebPOptions(): m_lossless(1), m_quality(75), m_method(6), m_image_hint(WEBP_HINT_DEFAULT), m_image_preset(WEBP_PRESET_DEFAULT) {};
|
||||
|
||||
bool lossless() { return m_lossless; }
|
||||
int getQuality() { return m_quality; }
|
||||
int getMethod() { return m_method; }
|
||||
WebPImageHint getImageHint() { return m_image_hint; }
|
||||
WebPPreset getImagePreset() { return m_image_preset; }
|
||||
|
||||
void setLossless(int lossless) { m_lossless = (lossless != 0); }
|
||||
void setLossless(bool lossless) { m_lossless = lossless; }
|
||||
void setQuality(int quality) { m_quality = quality; }
|
||||
void setMethod(int method) { m_method = method; }
|
||||
void setImageHint(int imageHint) { m_image_hint = static_cast<WebPImageHint>(imageHint); }
|
||||
void setImageHint(WebPImageHint imageHint) { m_image_hint = imageHint; }
|
||||
void setImagePreset(int imagePreset) { m_image_preset = static_cast<WebPPreset>(imagePreset); };
|
||||
void setImagePreset(WebPPreset imagePreset) { m_image_preset = imagePreset ; }
|
||||
|
||||
private:
|
||||
bool m_lossless; // Lossless encoding (0=lossy(default), 1=lossless).
|
||||
int m_quality; // between 0 (smallest file) and 100 (biggest)
|
||||
int m_method; // quality/speed trade-off (0=fast, 9=slower-better)
|
||||
WebPImageHint m_image_hint; // Hint for image type (lossless only for now).
|
||||
WebPPreset m_image_preset; // Image Preset for lossy webp.
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
4
third_party/CMakeLists.txt
vendored
4
third_party/CMakeLists.txt
vendored
@ -20,6 +20,10 @@ if(NOT USE_SHARED_LIBPNG)
|
||||
add_subdirectory(libpng)
|
||||
endif()
|
||||
|
||||
if(NOT USE_SHARED_LIBWEBP)
|
||||
add_subdirectory(libwebp-cmake)
|
||||
endif()
|
||||
|
||||
if(NOT USE_SHARED_GIFLIB)
|
||||
add_subdirectory(giflib)
|
||||
endif()
|
||||
|
1
third_party/libwebp
vendored
Submodule
1
third_party/libwebp
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 03fb75221c36ff773379eb5f018d7206f1ef30c9
|
45
third_party/libwebp-cmake/CMakeLists.txt
vendored
Normal file
45
third_party/libwebp-cmake/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
project (webp C)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
add_definitions(-DNDEBUG -DWEBP_USE_THREAD)
|
||||
|
||||
set(LIBWEBP_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../libwebp")
|
||||
|
||||
file(GLOB WEBP_DEC_SRCS
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${LIBWEBP_SOURCE_DIR}/src/dec/*c
|
||||
)
|
||||
|
||||
file(GLOB WEBP_DEMUX_SRCS
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${LIBWEBP_SOURCE_DIR}/src/demux/*c
|
||||
)
|
||||
|
||||
file(GLOB WEBP_DSP_SRCS
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${LIBWEBP_SOURCE_DIR}/src/dsp/*c
|
||||
)
|
||||
|
||||
file(GLOB WEBP_ENC_SRCS
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${LIBWEBP_SOURCE_DIR}/src/enc/*c
|
||||
)
|
||||
|
||||
file(GLOB WEBP_UTILS_SRCS
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${LIBWEBP_SOURCE_DIR}/src/utils/*c
|
||||
)
|
||||
|
||||
file(GLOB WEBP_MUX_SRCS
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${LIBWEBP_SOURCE_DIR}/src/mux/*c
|
||||
)
|
||||
|
||||
file(GLOB WEBP_HEADERS
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${LIBWEBP_SOURCE_DIR}/src/webp/*.h
|
||||
)
|
||||
|
||||
SET(CMAKE_DEBUG_POSTFIX "d")
|
||||
set(WEBP_SOURCE ${WEBP_DEC_SRCS} ${WEBP_DEMUX_SRCS} ${WEBP_DSP_SRCS} ${WEBP_ENC_SRCS} ${WEBP_UTILS_SRCS} ${WEBP_MUX_SRC})
|
||||
add_library(${PROJECT_NAME} STATIC ${WEBP_SOURCE} ${WEBP_HEADERS})
|
Loading…
x
Reference in New Issue
Block a user