mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-29 19:20:09 +00:00
New default RgbMapAlgorithm to select what could works better at a given time
This commit is contained in:
parent
1779e11f5e
commit
69a7faefa2
@ -221,7 +221,6 @@
|
||||
<option id="load_wintab_driver" type="bool" default="true" />
|
||||
<option id="flash_layer" type="bool" default="false" />
|
||||
<option id="nonactive_layers_opacity" type="int" default="255" />
|
||||
<option id="rgbmap_algorithm" type="doc::RgbMapAlgorithm" default="doc::RgbMapAlgorithm::DEFAULT" />
|
||||
</section>
|
||||
<section id="news">
|
||||
<option id="cache_file" type="std::string" />
|
||||
@ -295,6 +294,7 @@
|
||||
<option id="dithering_factor" type="int" default="100" />
|
||||
<option id="to_gray" type="ToGrayAlgorithm" default="ToGrayAlgorithm::DEFAULT" />
|
||||
<option id="advanced" type="bool" default="false" />
|
||||
<option id="rgbmap_algorithm" type="doc::RgbMapAlgorithm" default="doc::RgbMapAlgorithm::DEFAULT" />
|
||||
</section>
|
||||
<section id="eyedropper" text="Editor">
|
||||
<option id="channel" type="EyedropperChannel" default="EyedropperChannel::COLOR_ALPHA" />
|
||||
|
@ -1076,6 +1076,7 @@ double_high = Double-high Pixels (1:2)
|
||||
|
||||
[rgbmap_algorithm_selector]
|
||||
label = RGB to palette index mapping:
|
||||
default = Default (chose best algorithm automatically)
|
||||
rgb5a3 = Table RGB 5 bits + Alpha 3 bits
|
||||
octree = Octree without Alpha
|
||||
|
||||
|
@ -229,7 +229,7 @@ public:
|
||||
}
|
||||
|
||||
// Select default RgbMap algorithm
|
||||
m_mapAlgorithmSelector->algorithm(pref.experimental.rgbmapAlgorithm());
|
||||
m_mapAlgorithmSelector->algorithm(pref.quantization.rgbmapAlgorithm());
|
||||
|
||||
ditheringPlaceholder()->addChild(m_ditheringSelector);
|
||||
rgbmapAlgorithmPlaceholder()->addChild(m_mapAlgorithmSelector);
|
||||
@ -548,9 +548,11 @@ void ChangePixelFormatCommand::onLoadParams(const Params& params)
|
||||
m_rgbmap = doc::RgbMapAlgorithm::OCTREE;
|
||||
else if (rgbmap == "rgb5a3")
|
||||
m_rgbmap = doc::RgbMapAlgorithm::RGB5A3;
|
||||
else if (rgbmap == "default")
|
||||
m_rgbmap = doc::RgbMapAlgorithm::DEFAULT;
|
||||
else {
|
||||
// Use the configured algorithm by default.
|
||||
m_rgbmap = Preferences::instance().experimental.rgbmapAlgorithm();
|
||||
m_rgbmap = Preferences::instance().quantization.rgbmapAlgorithm();
|
||||
}
|
||||
|
||||
std::string toGray = params.get("toGray");
|
||||
|
@ -57,6 +57,7 @@ public:
|
||||
m_algoSelector.Change.connect(
|
||||
[this](){
|
||||
switch (algorithm()) {
|
||||
case RgbMapAlgorithm::DEFAULT:
|
||||
case RgbMapAlgorithm::RGB5A3:
|
||||
alphaChannel()->setEnabled(true);
|
||||
break;
|
||||
@ -126,7 +127,7 @@ void ColorQuantizationCommand::onExecute(Context* ctx)
|
||||
const Palette* curPalette = site.sprite()->palette(site.frame());
|
||||
|
||||
if (!params().algorithm.isSet())
|
||||
algorithm = pref.experimental.rgbmapAlgorithm();
|
||||
algorithm = pref.quantization.rgbmapAlgorithm();
|
||||
if (!params().withAlpha.isSet())
|
||||
withAlpha = pref.quantization.withAlpha();
|
||||
|
||||
|
@ -264,7 +264,7 @@ void NewFileCommand::onExecute(Context* ctx)
|
||||
render::create_palette_from_sprite(
|
||||
sprite.get(), 0, sprite->lastFrame(), true,
|
||||
&clipboardPalette, nullptr, true,
|
||||
Preferences::instance().experimental.rgbmapAlgorithm());
|
||||
Preferences::instance().quantization.rgbmapAlgorithm());
|
||||
}
|
||||
sprite->setPalette(&clipboardPalette, false);
|
||||
}
|
||||
|
@ -403,7 +403,7 @@ public:
|
||||
|
||||
rgbmapAlgorithmPlaceholder()->addChild(&m_rgbmapAlgorithmSelector);
|
||||
m_rgbmapAlgorithmSelector.setExpansive(true);
|
||||
m_rgbmapAlgorithmSelector.algorithm(m_pref.experimental.rgbmapAlgorithm());
|
||||
m_rgbmapAlgorithmSelector.algorithm(m_pref.quantization.rgbmapAlgorithm());
|
||||
|
||||
if (m_pref.editor.showScrollbars())
|
||||
showScrollbars()->setSelected(true);
|
||||
@ -703,7 +703,7 @@ public:
|
||||
m_pref.experimental.useNativeFileDialog(nativeFileDialog()->isSelected());
|
||||
m_pref.experimental.flashLayer(flashLayer()->isSelected());
|
||||
m_pref.experimental.nonactiveLayersOpacity(nonactiveLayersOpacity()->getValue());
|
||||
m_pref.experimental.rgbmapAlgorithm(m_rgbmapAlgorithmSelector.algorithm());
|
||||
m_pref.quantization.rgbmapAlgorithm(m_rgbmapAlgorithmSelector.algorithm());
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -22,7 +22,7 @@ void FileOpConfig::fillFromPreferences()
|
||||
newBlend = Preferences::instance().experimental.newBlend();
|
||||
defaultSliceColor = Preferences::instance().slices.defaultColor();
|
||||
workingCS = get_working_rgb_space_from_preferences();
|
||||
rgbMapAlgorithm = Preferences::instance().experimental.rgbmapAlgorithm();
|
||||
rgbMapAlgorithm = Preferences::instance().quantization.rgbmapAlgorithm();
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -56,11 +56,11 @@ Preferences::Preferences()
|
||||
|
||||
// Create a connection with the default RgbMapAlgorithm preferences
|
||||
// to change the default algorithm in the "doc" layer.
|
||||
experimental.rgbmapAlgorithm.AfterChange.connect(
|
||||
quantization.rgbmapAlgorithm.AfterChange.connect(
|
||||
[](const doc::RgbMapAlgorithm& newValue){
|
||||
doc::Sprite::SetDefaultRgbMapAlgorithm(newValue);
|
||||
});
|
||||
doc::Sprite::SetDefaultRgbMapAlgorithm(experimental.rgbmapAlgorithm());
|
||||
doc::Sprite::SetDefaultRgbMapAlgorithm(quantization.rgbmapAlgorithm());
|
||||
|
||||
// Create a connection with the default document preferences grid
|
||||
// bounds to sync the default grid bounds for new sprites in the
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2021 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -17,10 +17,12 @@ namespace app {
|
||||
RgbMapAlgorithmSelector::RgbMapAlgorithmSelector()
|
||||
{
|
||||
// addItem() must match the RgbMapAlgorithm enum
|
||||
static_assert(int(doc::RgbMapAlgorithm::RGB5A3) == 0 &&
|
||||
int(doc::RgbMapAlgorithm::OCTREE) == 1,
|
||||
static_assert(int(doc::RgbMapAlgorithm::DEFAULT) == 0 &&
|
||||
int(doc::RgbMapAlgorithm::RGB5A3) == 1 &&
|
||||
int(doc::RgbMapAlgorithm::OCTREE) == 2,
|
||||
"Unexpected doc::RgbMapAlgorithm values");
|
||||
|
||||
addItem(Strings::rgbmap_algorithm_selector_default());
|
||||
addItem(Strings::rgbmap_algorithm_selector_rgb5a3());
|
||||
addItem(Strings::rgbmap_algorithm_selector_octree());
|
||||
|
||||
|
@ -108,6 +108,16 @@ bool Palette::hasAlpha() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Palette::hasSemiAlpha() const
|
||||
{
|
||||
for (int i=0; i<(int)m_colors.size(); ++i) {
|
||||
int a = rgba_geta(getEntry(i));
|
||||
if (a > 0 && a < 255)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Palette::setFrame(frame_t frame)
|
||||
{
|
||||
ASSERT(frame >= 0);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (C) 2020 Igara Studio S.A.
|
||||
// Copyright (C) 2020-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -53,6 +53,9 @@ namespace doc {
|
||||
// Return true if the palette has alpha != 255 in some entry
|
||||
bool hasAlpha() const;
|
||||
|
||||
// Return true if the palette has an alpha value between > 0 and < 255.
|
||||
bool hasSemiAlpha() const;
|
||||
|
||||
frame_t frame() const { return m_frame; }
|
||||
void setFrame(frame_t frame);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2020 Igara Studio S.A.
|
||||
// Copyright (c) 2020-2021 Igara Studio S.A.
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -11,9 +11,9 @@
|
||||
namespace doc {
|
||||
|
||||
enum class RgbMapAlgorithm {
|
||||
DEFAULT, // Select best algorithm (generally octree when alpha is=255 in all colors)
|
||||
RGB5A3,
|
||||
OCTREE,
|
||||
DEFAULT = RGB5A3
|
||||
};
|
||||
|
||||
} // namespace doc
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -388,11 +388,21 @@ RgbMap* Sprite::rgbMap(const frame_t frame,
|
||||
|
||||
RgbMap* Sprite::rgbMap(const frame_t frame,
|
||||
const RgbMapFor forLayer,
|
||||
const RgbMapAlgorithm mapAlgo) const
|
||||
RgbMapAlgorithm mapAlgo) const
|
||||
{
|
||||
int maskIndex = (forLayer == RgbMapFor::OpaqueLayer ?
|
||||
-1: transparentColor());
|
||||
|
||||
if (mapAlgo == RgbMapAlgorithm::DEFAULT) {
|
||||
mapAlgo = RgbMapAlgorithm::OCTREE;
|
||||
for (const auto& pal : getPalettes()) {
|
||||
if (pal->hasSemiAlpha()) {
|
||||
mapAlgo = RgbMapAlgorithm::RGB5A3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_rgbMap || m_rgbMapAlgorithm != mapAlgo) {
|
||||
m_rgbMapAlgorithm = mapAlgo;
|
||||
switch (m_rgbMapAlgorithm) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -149,7 +149,7 @@ namespace doc {
|
||||
const RgbMapFor forLayer) const;
|
||||
RgbMap* rgbMap(const frame_t frame,
|
||||
const RgbMapFor forLayer,
|
||||
const RgbMapAlgorithm mapAlgo) const;
|
||||
RgbMapAlgorithm mapAlgo) const;
|
||||
|
||||
////////////////////////////////////////
|
||||
// Frames
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Render Library
|
||||
// Copyright (c) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2021 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -43,7 +43,7 @@ Palette* create_palette_from_sprite(
|
||||
Palette* palette,
|
||||
TaskDelegate* delegate,
|
||||
const bool newBlend,
|
||||
const RgbMapAlgorithm mappingAlgorithm,
|
||||
RgbMapAlgorithm mapAlgo,
|
||||
const bool calculateWithTransparent)
|
||||
{
|
||||
PaletteOptimizer optimizer;
|
||||
@ -59,19 +59,41 @@ Palette* create_palette_from_sprite(
|
||||
ImageRef flat_image(Image::create(IMAGE_RGB,
|
||||
sprite->width(), sprite->height()));
|
||||
|
||||
// Feed the optimizer with all rendered frames
|
||||
render::Render render;
|
||||
render.setNewBlend(newBlend);
|
||||
|
||||
// Use octree if there are no semi-transparent pixels.
|
||||
if (mapAlgo == RgbMapAlgorithm::DEFAULT) {
|
||||
for (frame_t frame=fromFrame;
|
||||
frame<=toFrame && mapAlgo == RgbMapAlgorithm::DEFAULT;
|
||||
++frame) {
|
||||
render.renderSprite(flat_image.get(), sprite, frame);
|
||||
doc::for_each_pixel<RgbTraits>(
|
||||
flat_image.get(),
|
||||
[&mapAlgo](const color_t p) {
|
||||
if (rgba_geta(p) > 0 && rgba_geta(p) < 255) {
|
||||
mapAlgo = RgbMapAlgorithm::RGB5A3;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (mapAlgo == RgbMapAlgorithm::DEFAULT)
|
||||
mapAlgo = RgbMapAlgorithm::OCTREE;
|
||||
}
|
||||
|
||||
// Feed the optimizer with all rendered frames
|
||||
for (frame_t frame=fromFrame; frame<=toFrame; ++frame) {
|
||||
render.renderSprite(flat_image.get(), sprite, frame);
|
||||
|
||||
switch (mappingAlgorithm) {
|
||||
switch (mapAlgo) {
|
||||
case RgbMapAlgorithm::RGB5A3:
|
||||
optimizer.feedWithImage(flat_image.get(), withAlpha);
|
||||
break;
|
||||
case RgbMapAlgorithm::OCTREE:
|
||||
octreemap.feedWithImage(flat_image.get(), maskColor);
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (delegate) {
|
||||
@ -83,7 +105,8 @@ Palette* create_palette_from_sprite(
|
||||
}
|
||||
}
|
||||
|
||||
switch (mappingAlgorithm) {
|
||||
switch (mapAlgo) {
|
||||
|
||||
case RgbMapAlgorithm::RGB5A3:
|
||||
// Generate an optimized palette
|
||||
optimizer.calculate(
|
||||
@ -93,6 +116,7 @@ Palette* create_palette_from_sprite(
|
||||
sprite->allLayersCount() == 1) ||
|
||||
!calculateWithTransparent)? -1: sprite->transparentColor());
|
||||
break;
|
||||
|
||||
case RgbMapAlgorithm::OCTREE:
|
||||
// TODO check calculateWithTransparent flag
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Rener Library
|
||||
// Copyright (c) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2021 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -53,7 +53,7 @@ namespace render {
|
||||
doc::Palette* newPalette, // Can be NULL to create a new palette
|
||||
TaskDelegate* delegate,
|
||||
const bool newBlend,
|
||||
const RgbMapAlgorithm mappingAlgorithm,
|
||||
RgbMapAlgorithm mapAlgo,
|
||||
const bool calculateWithTransparent = true);
|
||||
|
||||
// Changes the image pixel format. The dithering method is used only
|
||||
|
Loading…
x
Reference in New Issue
Block a user