mirror of
https://github.com/aseprite/aseprite.git
synced 2024-10-03 05:22:23 +00:00
This commit is contained in:
parent
e12233a19d
commit
3cc1c63274
@ -321,6 +321,7 @@
|
|||||||
<option id="to_gray" type="ToGrayAlgorithm" default="ToGrayAlgorithm::DEFAULT" />
|
<option id="to_gray" type="ToGrayAlgorithm" default="ToGrayAlgorithm::DEFAULT" />
|
||||||
<option id="advanced" type="bool" default="false" />
|
<option id="advanced" type="bool" default="false" />
|
||||||
<option id="rgbmap_algorithm" type="doc::RgbMapAlgorithm" default="doc::RgbMapAlgorithm::DEFAULT" />
|
<option id="rgbmap_algorithm" type="doc::RgbMapAlgorithm" default="doc::RgbMapAlgorithm::DEFAULT" />
|
||||||
|
<option id="fit_criteria" type="doc::FitCriteria" default="doc::FitCriteria::DEFAULT" />
|
||||||
</section>
|
</section>
|
||||||
<section id="eyedropper" text="Editor">
|
<section id="eyedropper" text="Editor">
|
||||||
<option id="channel" type="EyedropperChannel" default="EyedropperChannel::COLOR_ALPHA" />
|
<option id="channel" type="EyedropperChannel" default="EyedropperChannel::COLOR_ALPHA" />
|
||||||
|
@ -1255,6 +1255,14 @@ default = Default (Octree)
|
|||||||
rgb5a3 = Table RGB 5 bits + Alpha 3 bits
|
rgb5a3 = Table RGB 5 bits + Alpha 3 bits
|
||||||
octree = Octree
|
octree = Octree
|
||||||
|
|
||||||
|
[best_fit_criteria_selector]
|
||||||
|
label = Color Best Fit Criteria:
|
||||||
|
default = Default (Euclidean)
|
||||||
|
rgb = RGB
|
||||||
|
linearized_rgb = Linearized RGB
|
||||||
|
cie_xyz = CIEXYZ
|
||||||
|
cie_lab = CIELAB
|
||||||
|
|
||||||
[open_file]
|
[open_file]
|
||||||
title = Open
|
title = Open
|
||||||
loading = Loading file
|
loading = Loading file
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!-- Aseprite -->
|
<!-- Aseprite -->
|
||||||
<!-- Copyright (C) 2019-2020 Igara Studio S.A. -->
|
<!-- Copyright (C) 2019-2024 Igara Studio S.A. -->
|
||||||
<!-- Copyright (C) 2017 David Capello -->
|
<!-- Copyright (C) 2017 David Capello -->
|
||||||
<gui>
|
<gui>
|
||||||
<window id="color_mode" text="@.title">
|
<window id="color_mode" text="@.title">
|
||||||
@ -23,10 +23,12 @@
|
|||||||
<check text="@.flatten" id="flatten" />
|
<check text="@.flatten" id="flatten" />
|
||||||
|
|
||||||
<check id="advanced_check" text="@general.advanced_options" cell_hspan="2" />
|
<check id="advanced_check" text="@general.advanced_options" cell_hspan="2" />
|
||||||
<hbox id="advanced" cell_hspan="2">
|
<vbox id="advanced" cell_hspan="2">
|
||||||
<label text="@rgbmap_algorithm_selector.label" />
|
<label text="@rgbmap_algorithm_selector.label" cell_hspan="1" />
|
||||||
<hbox id="rgbmap_algorithm_placeholder" />
|
<hbox id="rgbmap_algorithm_placeholder" cell_hspan="1" />
|
||||||
</hbox>
|
<label text="@best_fit_criteria_selector.label" cell_hspan="1" />
|
||||||
|
<hbox id="best_fit_criteria_placeholder" cell_hspan="1" />
|
||||||
|
</vbox>
|
||||||
|
|
||||||
<separator horizontal="true" />
|
<separator horizontal="true" />
|
||||||
<hbox>
|
<hbox>
|
||||||
|
@ -587,10 +587,12 @@
|
|||||||
<slider id="nonactive_layers_opacity" min="0" max="255" width="128" />
|
<slider id="nonactive_layers_opacity" min="0" max="255" width="128" />
|
||||||
</hbox>
|
</hbox>
|
||||||
<separator text="@.color_quantization" horizontal="true" />
|
<separator text="@.color_quantization" horizontal="true" />
|
||||||
<hbox>
|
<grid columns="2">
|
||||||
<label text="@rgbmap_algorithm_selector.label" />
|
<label text="@rgbmap_algorithm_selector.label" />
|
||||||
<hbox id="rgbmap_algorithm_placeholder" />
|
<hbox id="rgbmap_algorithm_placeholder" />
|
||||||
</hbox>
|
<label text="@best_fit_criteria_selector.label" />
|
||||||
|
<hbox id="best_fit_criteria_placeholder" />
|
||||||
|
</grid>
|
||||||
<separator text="@.performance" horizontal="true" />
|
<separator text="@.performance" horizontal="true" />
|
||||||
<hbox>
|
<hbox>
|
||||||
<check id="shaders_for_color_selectors"
|
<check id="shaders_for_color_selectors"
|
||||||
|
@ -579,6 +579,7 @@ target_sources(app-lib PRIVATE
|
|||||||
ui/alpha_slider.cpp
|
ui/alpha_slider.cpp
|
||||||
ui/app_menuitem.cpp
|
ui/app_menuitem.cpp
|
||||||
ui/backup_indicator.cpp
|
ui/backup_indicator.cpp
|
||||||
|
ui/best_fit_criteria_selector.cpp
|
||||||
ui/browser_view.cpp
|
ui/browser_view.cpp
|
||||||
ui/brush_popup.cpp
|
ui/brush_popup.cpp
|
||||||
ui/button_set.cpp
|
ui/button_set.cpp
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
// Copyright (C) 2019-2024 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2018 David Capello
|
// Copyright (C) 2001-2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -73,7 +73,8 @@ SetPixelFormat::SetPixelFormat(Sprite* sprite,
|
|||||||
const render::Dithering& dithering,
|
const render::Dithering& dithering,
|
||||||
const doc::RgbMapAlgorithm mapAlgorithm,
|
const doc::RgbMapAlgorithm mapAlgorithm,
|
||||||
doc::rgba_to_graya_func toGray,
|
doc::rgba_to_graya_func toGray,
|
||||||
render::TaskDelegate* delegate)
|
render::TaskDelegate* delegate,
|
||||||
|
const FitCriteria fitCriteria)
|
||||||
: WithSprite(sprite)
|
: WithSprite(sprite)
|
||||||
, m_oldFormat(sprite->pixelFormat())
|
, m_oldFormat(sprite->pixelFormat())
|
||||||
, m_newFormat(newFormat)
|
, m_newFormat(newFormat)
|
||||||
@ -108,7 +109,8 @@ SetPixelFormat::SetPixelFormat(Sprite* sprite,
|
|||||||
cel->layer()->isBackground(),
|
cel->layer()->isBackground(),
|
||||||
mapAlgorithm,
|
mapAlgorithm,
|
||||||
toGray,
|
toGray,
|
||||||
&superDel);
|
&superDel,
|
||||||
|
fitCriteria);
|
||||||
|
|
||||||
superDel.nextImage();
|
superDel.nextImage();
|
||||||
}
|
}
|
||||||
@ -208,7 +210,8 @@ void SetPixelFormat::convertImage(doc::Sprite* sprite,
|
|||||||
const bool isBackground,
|
const bool isBackground,
|
||||||
const doc::RgbMapAlgorithm mapAlgorithm,
|
const doc::RgbMapAlgorithm mapAlgorithm,
|
||||||
doc::rgba_to_graya_func toGray,
|
doc::rgba_to_graya_func toGray,
|
||||||
render::TaskDelegate* delegate)
|
render::TaskDelegate* delegate,
|
||||||
|
const doc::FitCriteria fitCriteria)
|
||||||
{
|
{
|
||||||
ASSERT(oldImage);
|
ASSERT(oldImage);
|
||||||
ASSERT(oldImage->pixelFormat() != IMAGE_TILEMAP);
|
ASSERT(oldImage->pixelFormat() != IMAGE_TILEMAP);
|
||||||
@ -218,7 +221,10 @@ void SetPixelFormat::convertImage(doc::Sprite* sprite,
|
|||||||
RgbMap* rgbmap;
|
RgbMap* rgbmap;
|
||||||
int newMaskIndex = (isBackground ? -1 : 0);
|
int newMaskIndex = (isBackground ? -1 : 0);
|
||||||
if (m_newFormat == IMAGE_INDEXED) {
|
if (m_newFormat == IMAGE_INDEXED) {
|
||||||
rgbmap = sprite->rgbMap(frame, sprite->rgbMapForSprite(), mapAlgorithm);
|
rgbmap = sprite->rgbMap(frame,
|
||||||
|
sprite->rgbMapForSprite(),
|
||||||
|
mapAlgorithm,
|
||||||
|
fitCriteria);
|
||||||
if (m_oldFormat == IMAGE_INDEXED)
|
if (m_oldFormat == IMAGE_INDEXED)
|
||||||
newMaskIndex = sprite->transparentColor();
|
newMaskIndex = sprite->transparentColor();
|
||||||
else
|
else
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
// Copyright (C) 2019-2024 Igara Studio S.A.
|
||||||
// Copyright (C) 2001-2017 David Capello
|
// Copyright (C) 2001-2017 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -12,6 +12,7 @@
|
|||||||
#include "app/cmd/with_sprite.h"
|
#include "app/cmd/with_sprite.h"
|
||||||
#include "app/cmd_sequence.h"
|
#include "app/cmd_sequence.h"
|
||||||
#include "doc/color.h"
|
#include "doc/color.h"
|
||||||
|
#include "doc/fit_criteria.h"
|
||||||
#include "doc/frame.h"
|
#include "doc/frame.h"
|
||||||
#include "doc/image_ref.h"
|
#include "doc/image_ref.h"
|
||||||
#include "doc/pixel_format.h"
|
#include "doc/pixel_format.h"
|
||||||
@ -37,7 +38,8 @@ namespace cmd {
|
|||||||
const render::Dithering& dithering,
|
const render::Dithering& dithering,
|
||||||
const doc::RgbMapAlgorithm mapAlgorithm,
|
const doc::RgbMapAlgorithm mapAlgorithm,
|
||||||
doc::rgba_to_graya_func toGray,
|
doc::rgba_to_graya_func toGray,
|
||||||
render::TaskDelegate* delegate);
|
render::TaskDelegate* delegate,
|
||||||
|
const doc::FitCriteria fitCriteria = doc::FitCriteria::DEFAULT);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onExecute() override;
|
void onExecute() override;
|
||||||
@ -56,7 +58,8 @@ namespace cmd {
|
|||||||
const bool isBackground,
|
const bool isBackground,
|
||||||
const doc::RgbMapAlgorithm mapAlgorithm,
|
const doc::RgbMapAlgorithm mapAlgorithm,
|
||||||
doc::rgba_to_graya_func toGray,
|
doc::rgba_to_graya_func toGray,
|
||||||
render::TaskDelegate* delegate);
|
render::TaskDelegate* delegate,
|
||||||
|
const doc::FitCriteria fitCriteria = doc::FitCriteria::DEFAULT);
|
||||||
|
|
||||||
doc::PixelFormat m_oldFormat;
|
doc::PixelFormat m_oldFormat;
|
||||||
doc::PixelFormat m_newFormat;
|
doc::PixelFormat m_newFormat;
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "app/modules/palettes.h"
|
#include "app/modules/palettes.h"
|
||||||
#include "app/sprite_job.h"
|
#include "app/sprite_job.h"
|
||||||
#include "app/transaction.h"
|
#include "app/transaction.h"
|
||||||
|
#include "app/ui/best_fit_criteria_selector.h"
|
||||||
#include "app/ui/dithering_selector.h"
|
#include "app/ui/dithering_selector.h"
|
||||||
#include "app/ui/editor/editor.h"
|
#include "app/ui/editor/editor.h"
|
||||||
#include "app/ui/editor/editor_render.h"
|
#include "app/ui/editor/editor_render.h"
|
||||||
@ -69,7 +70,6 @@ public:
|
|||||||
const doc::frame_t frame,
|
const doc::frame_t frame,
|
||||||
const doc::PixelFormat pixelFormat,
|
const doc::PixelFormat pixelFormat,
|
||||||
const render::Dithering& dithering,
|
const render::Dithering& dithering,
|
||||||
const doc::RgbMapAlgorithm rgbMapAlgorithm,
|
|
||||||
const gen::ToGrayAlgorithm toGray,
|
const gen::ToGrayAlgorithm toGray,
|
||||||
const gfx::Point& pos,
|
const gfx::Point& pos,
|
||||||
const bool newBlend)
|
const bool newBlend)
|
||||||
@ -83,13 +83,11 @@ public:
|
|||||||
sprite, frame,
|
sprite, frame,
|
||||||
pixelFormat,
|
pixelFormat,
|
||||||
dithering,
|
dithering,
|
||||||
rgbMapAlgorithm,
|
|
||||||
toGray,
|
toGray,
|
||||||
newBlend]() { // Copy the matrix
|
newBlend]() { // Copy the matrix
|
||||||
run(sprite, frame,
|
run(sprite, frame,
|
||||||
pixelFormat,
|
pixelFormat,
|
||||||
dithering,
|
dithering,
|
||||||
rgbMapAlgorithm,
|
|
||||||
toGray,
|
toGray,
|
||||||
newBlend);
|
newBlend);
|
||||||
})
|
})
|
||||||
@ -114,7 +112,6 @@ private:
|
|||||||
const doc::frame_t frame,
|
const doc::frame_t frame,
|
||||||
const doc::PixelFormat pixelFormat,
|
const doc::PixelFormat pixelFormat,
|
||||||
const render::Dithering& dithering,
|
const render::Dithering& dithering,
|
||||||
const doc::RgbMapAlgorithm rgbMapAlgorithm,
|
|
||||||
const gen::ToGrayAlgorithm toGray,
|
const gen::ToGrayAlgorithm toGray,
|
||||||
const bool newBlend) {
|
const bool newBlend) {
|
||||||
doc::ImageRef tmp(
|
doc::ImageRef tmp(
|
||||||
@ -136,9 +133,7 @@ private:
|
|||||||
m_image.get(),
|
m_image.get(),
|
||||||
pixelFormat,
|
pixelFormat,
|
||||||
dithering,
|
dithering,
|
||||||
sprite->rgbMap(frame,
|
sprite->rgbMap(frame),
|
||||||
sprite->rgbMapForSprite(),
|
|
||||||
rgbMapAlgorithm),
|
|
||||||
sprite->palette(frame),
|
sprite->palette(frame),
|
||||||
(sprite->backgroundLayer() != nullptr),
|
(sprite->backgroundLayer() != nullptr),
|
||||||
0,
|
0,
|
||||||
@ -193,6 +188,7 @@ public:
|
|||||||
, m_selectedItem(nullptr)
|
, m_selectedItem(nullptr)
|
||||||
, m_ditheringSelector(nullptr)
|
, m_ditheringSelector(nullptr)
|
||||||
, m_mapAlgorithmSelector(nullptr)
|
, m_mapAlgorithmSelector(nullptr)
|
||||||
|
, m_bestFitCriteriaSelector(nullptr)
|
||||||
, m_imageJustCreated(true)
|
, m_imageJustCreated(true)
|
||||||
{
|
{
|
||||||
const auto& pref = Preferences::instance();
|
const auto& pref = Preferences::instance();
|
||||||
@ -219,6 +215,9 @@ public:
|
|||||||
m_mapAlgorithmSelector = new RgbMapAlgorithmSelector;
|
m_mapAlgorithmSelector = new RgbMapAlgorithmSelector;
|
||||||
m_mapAlgorithmSelector->setExpansive(true);
|
m_mapAlgorithmSelector->setExpansive(true);
|
||||||
|
|
||||||
|
m_bestFitCriteriaSelector = new BestFitCriteriaSelector;
|
||||||
|
m_bestFitCriteriaSelector->setExpansive(true);
|
||||||
|
|
||||||
// Select default dithering method
|
// Select default dithering method
|
||||||
{
|
{
|
||||||
int index = m_ditheringSelector->findItemIndex(
|
int index = m_ditheringSelector->findItemIndex(
|
||||||
@ -230,8 +229,12 @@ public:
|
|||||||
// Select default RgbMap algorithm
|
// Select default RgbMap algorithm
|
||||||
m_mapAlgorithmSelector->algorithm(pref.quantization.rgbmapAlgorithm());
|
m_mapAlgorithmSelector->algorithm(pref.quantization.rgbmapAlgorithm());
|
||||||
|
|
||||||
|
// Select default best fit criteria
|
||||||
|
m_bestFitCriteriaSelector->criteria(pref.quantization.fitCriteria());
|
||||||
|
|
||||||
ditheringPlaceholder()->addChild(m_ditheringSelector);
|
ditheringPlaceholder()->addChild(m_ditheringSelector);
|
||||||
rgbmapAlgorithmPlaceholder()->addChild(m_mapAlgorithmSelector);
|
rgbmapAlgorithmPlaceholder()->addChild(m_mapAlgorithmSelector);
|
||||||
|
bestFitCriteriaPlaceholder()->addChild(m_bestFitCriteriaSelector);
|
||||||
|
|
||||||
const bool adv = pref.quantization.advanced();
|
const bool adv = pref.quantization.advanced();
|
||||||
advancedCheck()->setSelected(adv);
|
advancedCheck()->setSelected(adv);
|
||||||
@ -240,6 +243,7 @@ public:
|
|||||||
// Signals
|
// Signals
|
||||||
m_ditheringSelector->Change.connect([this]{ onIndexParamChange(); });
|
m_ditheringSelector->Change.connect([this]{ onIndexParamChange(); });
|
||||||
m_mapAlgorithmSelector->Change.connect([this]{ onIndexParamChange(); });
|
m_mapAlgorithmSelector->Change.connect([this]{ onIndexParamChange(); });
|
||||||
|
m_bestFitCriteriaSelector->Change.connect([this]{ onIndexParamChange(); });
|
||||||
factor()->Change.connect([this]{ onIndexParamChange(); });
|
factor()->Change.connect([this]{ onIndexParamChange(); });
|
||||||
|
|
||||||
advancedCheck()->Click.connect(
|
advancedCheck()->Click.connect(
|
||||||
@ -301,6 +305,13 @@ public:
|
|||||||
return doc::RgbMapAlgorithm::DEFAULT;
|
return doc::RgbMapAlgorithm::DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doc::FitCriteria fitCriteria() const {
|
||||||
|
if (m_bestFitCriteriaSelector)
|
||||||
|
return m_bestFitCriteriaSelector->criteria();
|
||||||
|
else
|
||||||
|
return doc::FitCriteria::DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
gen::ToGrayAlgorithm toGray() const {
|
gen::ToGrayAlgorithm toGray() const {
|
||||||
static_assert(
|
static_assert(
|
||||||
int(gen::ToGrayAlgorithm::LUMA) == 0 &&
|
int(gen::ToGrayAlgorithm::LUMA) == 0 &&
|
||||||
@ -331,7 +342,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_mapAlgorithmSelector)
|
if (m_mapAlgorithmSelector || m_bestFitCriteriaSelector)
|
||||||
pref.quantization.advanced(advancedCheck()->isSelected());
|
pref.quantization.advanced(advancedCheck()->isSelected());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,6 +407,12 @@ private:
|
|||||||
visibleBounds.origin(),
|
visibleBounds.origin(),
|
||||||
doc::BlendMode::SRC);
|
doc::BlendMode::SRC);
|
||||||
|
|
||||||
|
m_editor->sprite()->rgbMap(
|
||||||
|
0,
|
||||||
|
m_editor->sprite()->rgbMapForSprite(),
|
||||||
|
rgbMapAlgorithm(),
|
||||||
|
fitCriteria());
|
||||||
|
|
||||||
m_editor->invalidate();
|
m_editor->invalidate();
|
||||||
progress()->setValue(0);
|
progress()->setValue(0);
|
||||||
progress()->setVisible(false);
|
progress()->setVisible(false);
|
||||||
@ -408,7 +425,6 @@ private:
|
|||||||
m_editor->frame(),
|
m_editor->frame(),
|
||||||
dstPixelFormat,
|
dstPixelFormat,
|
||||||
dithering(),
|
dithering(),
|
||||||
rgbMapAlgorithm(),
|
|
||||||
toGray(),
|
toGray(),
|
||||||
visibleBounds.origin(),
|
visibleBounds.origin(),
|
||||||
Preferences::instance().experimental.newBlend()));
|
Preferences::instance().experimental.newBlend()));
|
||||||
@ -463,6 +479,7 @@ private:
|
|||||||
ConversionItem* m_selectedItem;
|
ConversionItem* m_selectedItem;
|
||||||
DitheringSelector* m_ditheringSelector;
|
DitheringSelector* m_ditheringSelector;
|
||||||
RgbMapAlgorithmSelector* m_mapAlgorithmSelector;
|
RgbMapAlgorithmSelector* m_mapAlgorithmSelector;
|
||||||
|
BestFitCriteriaSelector* m_bestFitCriteriaSelector;
|
||||||
bool m_imageJustCreated;
|
bool m_imageJustCreated;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -485,6 +502,7 @@ private:
|
|||||||
doc::PixelFormat m_format;
|
doc::PixelFormat m_format;
|
||||||
render::Dithering m_dithering;
|
render::Dithering m_dithering;
|
||||||
doc::RgbMapAlgorithm m_rgbmap;
|
doc::RgbMapAlgorithm m_rgbmap;
|
||||||
|
doc::FitCriteria m_fitCriteria = FitCriteria::DEFAULT;
|
||||||
gen::ToGrayAlgorithm m_toGray;
|
gen::ToGrayAlgorithm m_toGray;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -624,7 +642,10 @@ void ChangePixelFormatCommand::onExecute(Context* context)
|
|||||||
{
|
{
|
||||||
bool flatten = false;
|
bool flatten = false;
|
||||||
|
|
||||||
if (context->isUIAvailable() && m_showDlg) {
|
if (!context->isUIAvailable()) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
else if (m_showDlg) {
|
||||||
ColorModeWindow window(Editor::activeEditor());
|
ColorModeWindow window(Editor::activeEditor());
|
||||||
|
|
||||||
window.remapWindow();
|
window.remapWindow();
|
||||||
@ -640,11 +661,17 @@ void ChangePixelFormatCommand::onExecute(Context* context)
|
|||||||
m_format = window.pixelFormat();
|
m_format = window.pixelFormat();
|
||||||
m_dithering = window.dithering();
|
m_dithering = window.dithering();
|
||||||
m_rgbmap = window.rgbMapAlgorithm();
|
m_rgbmap = window.rgbMapAlgorithm();
|
||||||
|
m_fitCriteria = window.fitCriteria();
|
||||||
m_toGray = window.toGray();
|
m_toGray = window.toGray();
|
||||||
flatten = window.flattenEnabled();
|
flatten = window.flattenEnabled();
|
||||||
|
|
||||||
window.saveOptions();
|
window.saveOptions();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// TO DO: in a first approach a simple conversion to indexed color mode
|
||||||
|
// it's just via the old fit criteria (Euclidean color distance).
|
||||||
|
m_fitCriteria = FitCriteria::DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
// No conversion needed
|
// No conversion needed
|
||||||
Doc* doc = context->activeDocument();
|
Doc* doc = context->activeDocument();
|
||||||
@ -679,7 +706,8 @@ void ChangePixelFormatCommand::onExecute(Context* context)
|
|||||||
m_dithering,
|
m_dithering,
|
||||||
m_rgbmap,
|
m_rgbmap,
|
||||||
get_gray_func(m_toGray),
|
get_gray_func(m_toGray),
|
||||||
&job)); // SpriteJob is a render::TaskDelegate
|
&job,
|
||||||
|
m_fitCriteria)); // SpriteJob is a render::TaskDelegate
|
||||||
});
|
});
|
||||||
job.waitJob();
|
job.waitJob();
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "app/recent_files.h"
|
#include "app/recent_files.h"
|
||||||
#include "app/resource_finder.h"
|
#include "app/resource_finder.h"
|
||||||
#include "app/tx.h"
|
#include "app/tx.h"
|
||||||
|
#include "app/ui/best_fit_criteria_selector.h"
|
||||||
#include "app/ui/color_button.h"
|
#include "app/ui/color_button.h"
|
||||||
#include "app/ui/main_window.h"
|
#include "app/ui/main_window.h"
|
||||||
#include "app/ui/pref_widget.h"
|
#include "app/ui/pref_widget.h"
|
||||||
@ -478,6 +479,10 @@ public:
|
|||||||
m_rgbmapAlgorithmSelector.setExpansive(true);
|
m_rgbmapAlgorithmSelector.setExpansive(true);
|
||||||
m_rgbmapAlgorithmSelector.algorithm(m_pref.quantization.rgbmapAlgorithm());
|
m_rgbmapAlgorithmSelector.algorithm(m_pref.quantization.rgbmapAlgorithm());
|
||||||
|
|
||||||
|
bestFitCriteriaPlaceholder()->addChild(&m_bestFitCriteriaSelector);
|
||||||
|
m_bestFitCriteriaSelector.setExpansive(true);
|
||||||
|
m_bestFitCriteriaSelector.criteria(m_pref.quantization.fitCriteria());
|
||||||
|
|
||||||
if (m_pref.editor.showScrollbars())
|
if (m_pref.editor.showScrollbars())
|
||||||
showScrollbars()->setSelected(true);
|
showScrollbars()->setSelected(true);
|
||||||
|
|
||||||
@ -828,6 +833,7 @@ public:
|
|||||||
m_pref.experimental.flashLayer(flashLayer()->isSelected());
|
m_pref.experimental.flashLayer(flashLayer()->isSelected());
|
||||||
m_pref.experimental.nonactiveLayersOpacity(nonactiveLayersOpacity()->getValue());
|
m_pref.experimental.nonactiveLayersOpacity(nonactiveLayersOpacity()->getValue());
|
||||||
m_pref.quantization.rgbmapAlgorithm(m_rgbmapAlgorithmSelector.algorithm());
|
m_pref.quantization.rgbmapAlgorithm(m_rgbmapAlgorithmSelector.algorithm());
|
||||||
|
m_pref.quantization.fitCriteria(m_bestFitCriteriaSelector.criteria());
|
||||||
|
|
||||||
#ifdef LAF_WINDOWS
|
#ifdef LAF_WINDOWS
|
||||||
{
|
{
|
||||||
@ -1842,6 +1848,7 @@ private:
|
|||||||
std::vector<os::ColorSpaceRef> m_colorSpaces;
|
std::vector<os::ColorSpaceRef> m_colorSpaces;
|
||||||
std::string m_templateTextForDisplayCS;
|
std::string m_templateTextForDisplayCS;
|
||||||
RgbMapAlgorithmSelector m_rgbmapAlgorithmSelector;
|
RgbMapAlgorithmSelector m_rgbmapAlgorithmSelector;
|
||||||
|
BestFitCriteriaSelector m_bestFitCriteriaSelector;
|
||||||
ButtonSet* m_themeVars = nullptr;
|
ButtonSet* m_themeVars = nullptr;
|
||||||
SamplingSelector* m_samplingSelector = nullptr;
|
SamplingSelector* m_samplingSelector = nullptr;
|
||||||
};
|
};
|
||||||
|
@ -342,6 +342,7 @@ FOR_ENUM(app::tools::RotationAlgorithm)
|
|||||||
FOR_ENUM(doc::AniDir)
|
FOR_ENUM(doc::AniDir)
|
||||||
FOR_ENUM(doc::BrushPattern)
|
FOR_ENUM(doc::BrushPattern)
|
||||||
FOR_ENUM(doc::ColorMode)
|
FOR_ENUM(doc::ColorMode)
|
||||||
|
FOR_ENUM(doc::FitCriteria)
|
||||||
FOR_ENUM(doc::RgbMapAlgorithm)
|
FOR_ENUM(doc::RgbMapAlgorithm)
|
||||||
FOR_ENUM(filters::HueSaturationFilter::Mode)
|
FOR_ENUM(filters::HueSaturationFilter::Mode)
|
||||||
FOR_ENUM(filters::TiledMode)
|
FOR_ENUM(filters::TiledMode)
|
||||||
|
46
src/app/ui/best_fit_criteria_selector.cpp
Normal file
46
src/app/ui/best_fit_criteria_selector.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2024 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// This program is distributed under the terms of
|
||||||
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "app/ui/best_fit_criteria_selector.h"
|
||||||
|
|
||||||
|
#include "app/i18n/strings.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
BestFitCriteriaSelector::BestFitCriteriaSelector()
|
||||||
|
{
|
||||||
|
// addItem() must match the FitCriteria enum
|
||||||
|
static_assert(int(doc::FitCriteria::DEFAULT) == 0 &&
|
||||||
|
int(doc::FitCriteria::RGB) == 1 &&
|
||||||
|
int(doc::FitCriteria::linearizedRGB) == 2 &&
|
||||||
|
int(doc::FitCriteria::CIEXYZ) == 3 &&
|
||||||
|
int(doc::FitCriteria::CIELAB) == 4,
|
||||||
|
"Unexpected doc::FitCriteria values");
|
||||||
|
|
||||||
|
addItem(Strings::best_fit_criteria_selector_default());
|
||||||
|
addItem(Strings::best_fit_criteria_selector_rgb());
|
||||||
|
addItem(Strings::best_fit_criteria_selector_linearized_rgb());
|
||||||
|
addItem(Strings::best_fit_criteria_selector_cie_xyz());
|
||||||
|
addItem(Strings::best_fit_criteria_selector_cie_lab());
|
||||||
|
|
||||||
|
criteria(doc::FitCriteria::DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
doc::FitCriteria BestFitCriteriaSelector::criteria()
|
||||||
|
{
|
||||||
|
return (doc::FitCriteria)getSelectedItemIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BestFitCriteriaSelector::criteria(const doc::FitCriteria criteria)
|
||||||
|
{
|
||||||
|
setSelectedItemIndex((int)criteria);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace app
|
27
src/app/ui/best_fit_criteria_selector.h
Normal file
27
src/app/ui/best_fit_criteria_selector.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2024 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// This program is distributed under the terms of
|
||||||
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
||||||
|
#ifndef APP_UI_BEST_FIT_CRITERIA_SELECTOR_H_INCLUDED
|
||||||
|
#define APP_UI_BEST_FIT_CRITERIA_SELECTOR_H_INCLUDED
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "doc/fit_criteria.h"
|
||||||
|
#include "doc/palette.h"
|
||||||
|
#include "ui/combobox.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
class BestFitCriteriaSelector : public ui::ComboBox {
|
||||||
|
public:
|
||||||
|
BestFitCriteriaSelector();
|
||||||
|
|
||||||
|
doc::FitCriteria criteria();
|
||||||
|
void criteria(doc::FitCriteria criteria);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace app
|
||||||
|
|
||||||
|
#endif
|
@ -61,6 +61,7 @@ add_library(doc-lib
|
|||||||
primitives.cpp
|
primitives.cpp
|
||||||
remap.cpp
|
remap.cpp
|
||||||
render_plan.cpp
|
render_plan.cpp
|
||||||
|
rgbmap_base.cpp
|
||||||
rgbmap_rgb5a3.cpp
|
rgbmap_rgb5a3.cpp
|
||||||
selected_frames.cpp
|
selected_frames.cpp
|
||||||
selected_layers.cpp
|
selected_layers.cpp
|
||||||
|
23
src/doc/fit_criteria.h
Normal file
23
src/doc/fit_criteria.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Aseprite Document Library
|
||||||
|
// Copyright (C) 2024 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// This file is released under the terms of the MIT license.
|
||||||
|
// Read LICENSE.txt for more information.
|
||||||
|
|
||||||
|
#ifndef DOC_FIT_CRITERIA_H_INCLUDED
|
||||||
|
#define DOC_FIT_CRITERIA_H_INCLUDED
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace doc {
|
||||||
|
|
||||||
|
enum class FitCriteria {
|
||||||
|
DEFAULT = 0,
|
||||||
|
RGB = 1,
|
||||||
|
linearizedRGB = 2,
|
||||||
|
CIEXYZ = 3,
|
||||||
|
CIELAB = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace doc
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (c) 2020-2023 Igara Studio S.A.
|
// Copyright (c) 2020-2024 Igara Studio S.A.
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
// Read LICENSE.txt for more information.
|
// Read LICENSE.txt for more information.
|
||||||
@ -35,19 +35,21 @@ void OctreeNode::addColor(color_t c, int level, OctreeNode* parent,
|
|||||||
(*m_children)[index].addColor(c, level + 1, this, paletteIndex, levelDeep);
|
(*m_children)[index].addColor(c, level + 1, this, paletteIndex, levelDeep);
|
||||||
}
|
}
|
||||||
|
|
||||||
int OctreeNode::mapColor(int r, int g, int b, int a, int mask_index, const Palette* palette, int level) const
|
int OctreeNode::mapColor(int r, int g, int b, int a, int mask_index,
|
||||||
|
const Palette* palette, int level,
|
||||||
|
const OctreeMap* octree) const
|
||||||
{
|
{
|
||||||
// New behavior: if mapColor do not have an exact rgba match, it must calculate which
|
// New behavior: if mapColor do not have an exact rgba match, it must calculate which
|
||||||
// color of the current palette is the bestfit and memorize the index in a octree leaf.
|
// color of the current palette is the bestfit and memorize the index in a octree leaf.
|
||||||
if (level >= 8) {
|
if (level >= 8) {
|
||||||
if (m_paletteIndex == -1)
|
if (m_paletteIndex == -1)
|
||||||
m_paletteIndex = palette->findBestfit(r, g, b, a, mask_index);
|
m_paletteIndex = octree->findBestfit(r, g, b, a, mask_index);
|
||||||
return m_paletteIndex;
|
return m_paletteIndex;
|
||||||
}
|
}
|
||||||
int index = getHextet(r, g, b, a, level);
|
int index = getHextet(r, g, b, a, level);
|
||||||
if (!m_children)
|
if (!m_children)
|
||||||
m_children.reset(new std::array<OctreeNode, 16>());
|
m_children.reset(new std::array<OctreeNode, 16>());
|
||||||
return (*m_children)[index].mapColor(r, g, b, a, mask_index, palette, level + 1);
|
return (*m_children)[index].mapColor(r, g, b, a, mask_index, palette, level + 1, octree);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeNode::collectLeafNodes(OctreeNodes& leavesVector, int& paletteIndex)
|
void OctreeNode::collectLeafNodes(OctreeNodes& leavesVector, int& paletteIndex)
|
||||||
@ -268,10 +270,13 @@ int OctreeMap::mapColor(color_t rgba) const
|
|||||||
rgba_getb(rgba),
|
rgba_getb(rgba),
|
||||||
rgba_geta(rgba),
|
rgba_geta(rgba),
|
||||||
m_maskIndex,
|
m_maskIndex,
|
||||||
m_palette, 0);
|
m_palette, 0,
|
||||||
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeMap::regenerateMap(const Palette* palette, const int maskIndex)
|
void OctreeMap::regenerateMap(const Palette* palette,
|
||||||
|
const int maskIndex,
|
||||||
|
const FitCriteria fitCriteria)
|
||||||
{
|
{
|
||||||
ASSERT(palette);
|
ASSERT(palette);
|
||||||
if (!palette)
|
if (!palette)
|
||||||
@ -280,9 +285,12 @@ void OctreeMap::regenerateMap(const Palette* palette, const int maskIndex)
|
|||||||
// Skip useless regenerations
|
// Skip useless regenerations
|
||||||
if (m_palette == palette &&
|
if (m_palette == palette &&
|
||||||
m_modifications == palette->getModifications() &&
|
m_modifications == palette->getModifications() &&
|
||||||
m_maskIndex == maskIndex)
|
m_maskIndex == maskIndex &&
|
||||||
|
m_fitCriteria == fitCriteria)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_palette = palette;
|
||||||
|
m_fitCriteria = fitCriteria;
|
||||||
m_root = OctreeNode();
|
m_root = OctreeNode();
|
||||||
m_leavesVector.clear();
|
m_leavesVector.clear();
|
||||||
m_maskIndex = maskIndex;
|
m_maskIndex = maskIndex;
|
||||||
@ -293,7 +301,7 @@ void OctreeMap::regenerateMap(const Palette* palette, const int maskIndex)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_maskColor = palette->getEntry(maskIndex);
|
m_maskColor = palette->getEntry(maskIndex);
|
||||||
maskColorBestFitIndex = palette->findBestfit(rgba_getr(m_maskColor),
|
maskColorBestFitIndex = findBestfit(rgba_getr(m_maskColor),
|
||||||
rgba_getg(m_maskColor),
|
rgba_getg(m_maskColor),
|
||||||
rgba_getb(m_maskColor),
|
rgba_getb(m_maskColor),
|
||||||
rgba_geta(m_maskColor), maskIndex);
|
rgba_geta(m_maskColor), maskIndex);
|
||||||
@ -307,7 +315,6 @@ void OctreeMap::regenerateMap(const Palette* palette, const int maskIndex)
|
|||||||
m_root.addColor(palette->entry(i), 0, &m_root, i, 8);
|
m_root.addColor(palette->entry(i), 0, &m_root, i, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_palette = palette;
|
|
||||||
m_modifications = palette->getModifications();
|
m_modifications = palette->getModifications();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (c) 2020-2022 Igara Studio S.A.
|
// Copyright (c) 2020-2024 Igara Studio S.A.
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
// Read LICENSE.txt for more information.
|
// Read LICENSE.txt for more information.
|
||||||
@ -11,7 +11,7 @@
|
|||||||
#include "doc/color.h"
|
#include "doc/color.h"
|
||||||
#include "doc/image_impl.h"
|
#include "doc/image_impl.h"
|
||||||
#include "doc/palette.h"
|
#include "doc/palette.h"
|
||||||
#include "doc/rgbmap.h"
|
#include "doc/rgbmap_base.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -26,6 +26,8 @@
|
|||||||
namespace doc {
|
namespace doc {
|
||||||
|
|
||||||
class OctreeNode;
|
class OctreeNode;
|
||||||
|
class OctreeMap;
|
||||||
|
|
||||||
using OctreeNodes = std::vector<OctreeNode*>;
|
using OctreeNodes = std::vector<OctreeNode*>;
|
||||||
|
|
||||||
class OctreeNode {
|
class OctreeNode {
|
||||||
@ -93,7 +95,9 @@ public:
|
|||||||
void addColor(color_t c, int level, OctreeNode* parent,
|
void addColor(color_t c, int level, OctreeNode* parent,
|
||||||
int paletteIndex = 0, int levelDeep = 7);
|
int paletteIndex = 0, int levelDeep = 7);
|
||||||
|
|
||||||
int mapColor(int r, int g, int b, int a, int mask_index, const Palette* palette, int level) const;
|
int mapColor(int r, int g, int b, int a, int mask_index,
|
||||||
|
const Palette* palette, int level,
|
||||||
|
const OctreeMap* octree) const;
|
||||||
|
|
||||||
void collectLeafNodes(OctreeNodes& leavesVector, int& paletteIndex);
|
void collectLeafNodes(OctreeNodes& leavesVector, int& paletteIndex);
|
||||||
|
|
||||||
@ -117,7 +121,7 @@ private:
|
|||||||
OctreeNode* m_parent = nullptr;
|
OctreeNode* m_parent = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class OctreeMap : public RgbMap {
|
class OctreeMap : public RgbMapBase {
|
||||||
public:
|
public:
|
||||||
void addColor(color_t color, int levelDeep = 7) {
|
void addColor(color_t color, int levelDeep = 7) {
|
||||||
m_root.addColor(color, 0, &m_root, 0, levelDeep);
|
m_root.addColor(color, 0, &m_root, 0, levelDeep);
|
||||||
@ -135,27 +139,23 @@ public:
|
|||||||
const int levelDeep = 7);
|
const int levelDeep = 7);
|
||||||
|
|
||||||
// RgbMap impl
|
// RgbMap impl
|
||||||
void regenerateMap(const Palette* palette, const int maskIndex) override;
|
void regenerateMap(const Palette* palette,
|
||||||
int mapColor(color_t rgba) const override;
|
const int maskIndex,
|
||||||
int maskIndex() const override { return m_maskIndex; }
|
const FitCriteria fitCriteria) override;
|
||||||
int mapColor(const int r, const int g,
|
void regenerateMap(const Palette* palette,
|
||||||
const int b, const int a) const
|
const int maskIndex) override {
|
||||||
{
|
regenerateMap(palette, maskIndex, m_fitCriteria);
|
||||||
ASSERT(r >= 0 && r < 256);
|
|
||||||
ASSERT(g >= 0 && g < 256);
|
|
||||||
ASSERT(b >= 0 && b < 256);
|
|
||||||
ASSERT(a >= 0 && a < 256);
|
|
||||||
return mapColor(rgba(r, g, b, a));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int moodifications() const { return m_modifications; };
|
int mapColor(color_t rgba) const override;
|
||||||
|
|
||||||
|
RgbMapAlgorithm rgbmapAlgorithm() const override {
|
||||||
|
return RgbMapAlgorithm::OCTREE;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OctreeNode m_root;
|
OctreeNode m_root;
|
||||||
OctreeNodes m_leavesVector;
|
OctreeNodes m_leavesVector;
|
||||||
const Palette* m_palette = nullptr;
|
|
||||||
int m_modifications = 0;
|
|
||||||
int m_maskIndex = 0;
|
|
||||||
color_t m_maskColor = 0;
|
color_t m_maskColor = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite Document Library
|
// Aseprite Document Library
|
||||||
// Copyright (c) 2020-2023 Igara Studio S.A.
|
// Copyright (c) 2020-2024 Igara Studio S.A.
|
||||||
// Copyright (c) 2001-2017 David Capello
|
// Copyright (c) 2001-2017 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
@ -26,14 +26,6 @@ namespace doc {
|
|||||||
|
|
||||||
using namespace gfx;
|
using namespace gfx;
|
||||||
|
|
||||||
enum class FitCriteria {
|
|
||||||
OLD,
|
|
||||||
RGB,
|
|
||||||
linearizedRGB,
|
|
||||||
CIEXYZ,
|
|
||||||
CIELAB
|
|
||||||
};
|
|
||||||
|
|
||||||
Palette::Palette()
|
Palette::Palette()
|
||||||
: Palette(0, 256)
|
: Palette(0, 256)
|
||||||
{
|
{
|
||||||
@ -346,85 +338,12 @@ void Palette::initBestfit()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auxiliary function for rgbToOtherSpace()
|
|
||||||
static double f(double t)
|
|
||||||
{
|
|
||||||
if (t > 0.00885645171)
|
|
||||||
return std::pow(t, 0.3333333333333333);
|
|
||||||
else
|
|
||||||
return (t / 0.12841855 + 0.137931034);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auxiliary function for findBestfit()
|
|
||||||
static void rgbToOtherSpace(double& r, double& g, double& b, FitCriteria fc)
|
|
||||||
{
|
|
||||||
if (fc == FitCriteria::RGB)
|
|
||||||
return;
|
|
||||||
double Rl, Gl, Bl;
|
|
||||||
// Linearization:
|
|
||||||
r = r / 255.0;
|
|
||||||
g = g / 255.0;
|
|
||||||
b = b / 255.0;
|
|
||||||
if (r <= 0.04045)
|
|
||||||
Rl = r / 12.92;
|
|
||||||
else
|
|
||||||
Rl = std::pow((r + 0.055) / 1.055, 2.4);
|
|
||||||
if (g <= 0.04045)
|
|
||||||
Gl = g / 12.92;
|
|
||||||
else
|
|
||||||
Gl = std::pow((g + 0.055) / 1.055, 2.4);
|
|
||||||
if (b <= 0.04045)
|
|
||||||
Bl = b / 12.92;
|
|
||||||
else
|
|
||||||
Bl = std::pow((b + 0.055) / 1.055, 2.4);
|
|
||||||
if (fc == FitCriteria::linearizedRGB) {
|
|
||||||
r = Rl;
|
|
||||||
g = Gl;
|
|
||||||
b = Bl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Conversion lineal RGB to CIE XYZ
|
|
||||||
r = 41.24564*Rl + 35.75761 * Gl + 18.04375 * Bl;
|
|
||||||
g = 21.26729*Rl + 71.51522 * Gl + 7.2175 * Bl;
|
|
||||||
b = 1.93339*Rl + 11.91920 * Gl + 95.03041 * Bl;
|
|
||||||
switch (fc) {
|
|
||||||
|
|
||||||
case FitCriteria::CIEXYZ:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case FitCriteria::CIELAB: {
|
|
||||||
// Converting CIEXYZ to CIELAB:
|
|
||||||
// For Standard Illuminant D65:
|
|
||||||
// const double xn = 95.0489;
|
|
||||||
// const double yn = 100.0;
|
|
||||||
// const double zn = 108.884;
|
|
||||||
double xxn = r / 95.0489;
|
|
||||||
double yyn = g / 100.0;
|
|
||||||
double zzn = b / 108.884;
|
|
||||||
double fyyn = f(yyn);
|
|
||||||
|
|
||||||
double Lstar = 116.0 * fyyn - 16.0;
|
|
||||||
double aStar = 500.0 * (f(xxn) - fyyn);
|
|
||||||
double bStar = 200.0 * (fyyn - f(zzn));
|
|
||||||
|
|
||||||
r = Lstar;
|
|
||||||
g = aStar;
|
|
||||||
b = bStar;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Palette::findBestfit(int r, int g, int b, int a, int mask_index) const
|
int Palette::findBestfit(int r, int g, int b, int a, int mask_index) const
|
||||||
{
|
{
|
||||||
ASSERT(r >= 0 && r <= 255);
|
ASSERT(r >= 0 && r <= 255);
|
||||||
ASSERT(g >= 0 && g <= 255);
|
ASSERT(g >= 0 && g <= 255);
|
||||||
ASSERT(b >= 0 && b <= 255);
|
ASSERT(b >= 0 && b <= 255);
|
||||||
ASSERT(a >= 0 && a <= 255);
|
ASSERT(a >= 0 && a <= 255);
|
||||||
|
|
||||||
FitCriteria fc = FitCriteria::OLD;
|
|
||||||
|
|
||||||
if (fc == FitCriteria::OLD) {
|
|
||||||
ASSERT(!col_diff.empty());
|
ASSERT(!col_diff.empty());
|
||||||
|
|
||||||
r >>= 3;
|
r >>= 3;
|
||||||
@ -461,41 +380,6 @@ int Palette::findBestfit(int r, int g, int b, int a, int mask_index) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bestfit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a == 0 && mask_index >= 0)
|
|
||||||
return mask_index;
|
|
||||||
|
|
||||||
int bestfit = 0;
|
|
||||||
double lowest = std::numeric_limits<double>::max();
|
|
||||||
int size = m_colors.size();
|
|
||||||
// Linearice:
|
|
||||||
double x = double(r);
|
|
||||||
double y = double(g);
|
|
||||||
double z = double(b);
|
|
||||||
|
|
||||||
rgbToOtherSpace(x, y, z, fc);
|
|
||||||
|
|
||||||
for (int i=0; i<size; ++i) {
|
|
||||||
color_t rgb = m_colors[i];
|
|
||||||
double Xpal = double(rgba_getr(rgb));
|
|
||||||
double Ypal = double(rgba_getg(rgb));
|
|
||||||
double Zpal = double(rgba_getb(rgb));
|
|
||||||
// Palette color conversion RGB-->XYZ and r,g,b is assumed CIE XYZ
|
|
||||||
rgbToOtherSpace(Xpal, Ypal, Zpal, fc);
|
|
||||||
double xDiff = x - Xpal;
|
|
||||||
double yDiff = y - Ypal;
|
|
||||||
double zDiff = z - Zpal;
|
|
||||||
double aDiff = double(a - rgba_geta(rgb)) / 128.0;
|
|
||||||
|
|
||||||
double diff = xDiff * xDiff + yDiff * yDiff + zDiff * zDiff + aDiff * aDiff;
|
|
||||||
if (diff < lowest) {
|
|
||||||
lowest = diff;
|
|
||||||
bestfit = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bestfit;
|
return bestfit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite Document Library
|
// Aseprite Document Library
|
||||||
// Copyright (c) 2020-2022 Igara Studio S.A.
|
// Copyright (c) 2020-2024 Igara Studio S.A.
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
// Read LICENSE.txt for more information.
|
// Read LICENSE.txt for more information.
|
||||||
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include "base/debug.h"
|
#include "base/debug.h"
|
||||||
#include "doc/color.h"
|
#include "doc/color.h"
|
||||||
|
#include "doc/fit_criteria.h"
|
||||||
|
#include "doc/rgbmap_algorithm.h"
|
||||||
|
|
||||||
namespace doc {
|
namespace doc {
|
||||||
|
|
||||||
@ -20,13 +22,26 @@ namespace doc {
|
|||||||
public:
|
public:
|
||||||
virtual ~RgbMap() { }
|
virtual ~RgbMap() { }
|
||||||
|
|
||||||
virtual void regenerateMap(const Palette* palette, const int maskIndex) = 0;
|
virtual void regenerateMap(const Palette* palette,
|
||||||
|
const int maskIndex,
|
||||||
|
const FitCriteria fitCriteria) = 0;
|
||||||
|
|
||||||
|
virtual void regenerateMap(const Palette* palette,
|
||||||
|
const int maskIndex) = 0;
|
||||||
|
|
||||||
// Should return the best index in a palette that matches the given RGBA values.
|
// Should return the best index in a palette that matches the given RGBA values.
|
||||||
virtual int mapColor(const color_t rgba) const = 0;
|
virtual int mapColor(const color_t rgba) const = 0;
|
||||||
|
|
||||||
virtual int maskIndex() const = 0;
|
virtual int maskIndex() const = 0;
|
||||||
|
|
||||||
|
virtual RgbMapAlgorithm rgbmapAlgorithm() const = 0;
|
||||||
|
|
||||||
|
virtual int modifications() const = 0;
|
||||||
|
|
||||||
|
// Color Best Fit Criteria used to generate the rgbmap
|
||||||
|
virtual FitCriteria fitCriteria() const = 0;
|
||||||
|
virtual void fitCriteria(const FitCriteria fitCriteria) = 0;
|
||||||
|
|
||||||
int mapColor(const int r,
|
int mapColor(const int r,
|
||||||
const int g,
|
const int g,
|
||||||
const int b,
|
const int b,
|
||||||
|
131
src/doc/rgbmap_base.cpp
Normal file
131
src/doc/rgbmap_base.cpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
// Aseprite Document Library
|
||||||
|
// Copyright (c) 2024 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// This file is released under the terms of the MIT license.
|
||||||
|
// Read LICENSE.txt for more information.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "doc/rgbmap_base.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace doc {
|
||||||
|
|
||||||
|
// Auxiliary function for rgbToOtherSpace()
|
||||||
|
double f(double t)
|
||||||
|
{
|
||||||
|
if (t > 0.00885645171)
|
||||||
|
return std::pow(t, 0.3333333333333333);
|
||||||
|
else
|
||||||
|
return (t / 0.12841855 + 0.137931034);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auxiliary function for findBestfit()
|
||||||
|
void RgbMapBase::rgbToOtherSpace(double& r, double& g, double& b) const
|
||||||
|
{
|
||||||
|
if (m_fitCriteria == FitCriteria::RGB)
|
||||||
|
return;
|
||||||
|
double Rl, Gl, Bl;
|
||||||
|
// Linearization:
|
||||||
|
r = r / 255.0;
|
||||||
|
g = g / 255.0;
|
||||||
|
b = b / 255.0;
|
||||||
|
if (r <= 0.04045)
|
||||||
|
Rl = r / 12.92;
|
||||||
|
else
|
||||||
|
Rl = std::pow((r + 0.055) / 1.055, 2.4);
|
||||||
|
if (g <= 0.04045)
|
||||||
|
Gl = g / 12.92;
|
||||||
|
else
|
||||||
|
Gl = std::pow((g + 0.055) / 1.055, 2.4);
|
||||||
|
if (b <= 0.04045)
|
||||||
|
Bl = b / 12.92;
|
||||||
|
else
|
||||||
|
Bl = std::pow((b + 0.055) / 1.055, 2.4);
|
||||||
|
if (m_fitCriteria == FitCriteria::linearizedRGB) {
|
||||||
|
r = Rl;
|
||||||
|
g = Gl;
|
||||||
|
b = Bl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Conversion lineal RGB to CIE XYZ
|
||||||
|
r = 41.24564*Rl + 35.75761 * Gl + 18.04375 * Bl;
|
||||||
|
g = 21.26729*Rl + 71.51522 * Gl + 7.2175 * Bl;
|
||||||
|
b = 1.93339*Rl + 11.91920 * Gl + 95.03041 * Bl;
|
||||||
|
switch (m_fitCriteria) {
|
||||||
|
|
||||||
|
case FitCriteria::CIEXYZ:
|
||||||
|
return;
|
||||||
|
|
||||||
|
case FitCriteria::CIELAB: {
|
||||||
|
// Converting CIEXYZ to CIELAB:
|
||||||
|
// For Standard Illuminant D65:
|
||||||
|
// const double xn = 95.0489;
|
||||||
|
// const double yn = 100.0;
|
||||||
|
// const double zn = 108.884;
|
||||||
|
double xxn = r / 95.0489;
|
||||||
|
double yyn = g / 100.0;
|
||||||
|
double zzn = b / 108.884;
|
||||||
|
double fyyn = f(yyn);
|
||||||
|
|
||||||
|
double Lstar = 116.0 * fyyn - 16.0;
|
||||||
|
double aStar = 500.0 * (f(xxn) - fyyn);
|
||||||
|
double bStar = 200.0 * (fyyn - f(zzn));
|
||||||
|
|
||||||
|
r = Lstar;
|
||||||
|
g = aStar;
|
||||||
|
b = bStar;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int RgbMapBase::findBestfit(int r, int g, int b, int a,
|
||||||
|
int mask_index) const
|
||||||
|
{
|
||||||
|
ASSERT(r >= 0 && r <= 255);
|
||||||
|
ASSERT(g >= 0 && g <= 255);
|
||||||
|
ASSERT(b >= 0 && b <= 255);
|
||||||
|
ASSERT(a >= 0 && a <= 255);
|
||||||
|
|
||||||
|
if (m_fitCriteria == FitCriteria::DEFAULT)
|
||||||
|
return m_palette->findBestfit(r, g, b, a, mask_index);
|
||||||
|
|
||||||
|
if (a == 0 && mask_index >= 0)
|
||||||
|
return mask_index;
|
||||||
|
|
||||||
|
int bestfit = 0;
|
||||||
|
double lowest = std::numeric_limits<double>::max();
|
||||||
|
const int size = m_palette->size();
|
||||||
|
// Linearice:
|
||||||
|
double x = double(r);
|
||||||
|
double y = double(g);
|
||||||
|
double z = double(b);
|
||||||
|
|
||||||
|
rgbToOtherSpace(x, y, z);
|
||||||
|
|
||||||
|
for (int i=0; i<size; ++i) {
|
||||||
|
color_t rgb = m_palette->getEntry(i);
|
||||||
|
double Xpal = double(rgba_getr(rgb));
|
||||||
|
double Ypal = double(rgba_getg(rgb));
|
||||||
|
double Zpal = double(rgba_getb(rgb));
|
||||||
|
// Palette color conversion RGB-->XYZ and r,g,b is assumed CIE XYZ
|
||||||
|
rgbToOtherSpace(Xpal, Ypal, Zpal);
|
||||||
|
const double xDiff = x - Xpal;
|
||||||
|
const double yDiff = y - Ypal;
|
||||||
|
const double zDiff = z - Zpal;
|
||||||
|
const double aDiff = double(a - rgba_geta(rgb)) / 128.0;
|
||||||
|
|
||||||
|
double diff = xDiff * xDiff + yDiff * yDiff + zDiff * zDiff + aDiff * aDiff;
|
||||||
|
if (diff < lowest) {
|
||||||
|
lowest = diff;
|
||||||
|
bestfit = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bestfit;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace doc
|
42
src/doc/rgbmap_base.h
Normal file
42
src/doc/rgbmap_base.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Aseprite Document Library
|
||||||
|
// Copyright (c) 2024 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// This file is released under the terms of the MIT license.
|
||||||
|
// Read LICENSE.txt for more information.
|
||||||
|
|
||||||
|
#ifndef DOC_RGBMAP_BASE_H_INCLUDED
|
||||||
|
#define DOC_RGBMAP_BASE_H_INCLUDED
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "doc/fit_criteria.h"
|
||||||
|
#include "doc/palette.h"
|
||||||
|
#include "doc/rgbmap.h"
|
||||||
|
|
||||||
|
namespace doc {
|
||||||
|
|
||||||
|
class RgbMapBase : public RgbMap {
|
||||||
|
public:
|
||||||
|
int findBestfit(int r, int g, int b, int a,
|
||||||
|
int mask_index) const;
|
||||||
|
|
||||||
|
// RgbMap impl
|
||||||
|
int modifications() const override { return m_modifications; }
|
||||||
|
int maskIndex() const override { return m_maskIndex; }
|
||||||
|
FitCriteria fitCriteria() const override { return m_fitCriteria; }
|
||||||
|
void fitCriteria(const FitCriteria fitCriteria) override {
|
||||||
|
m_fitCriteria = fitCriteria;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void rgbToOtherSpace(double& r, double& g, double& b) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FitCriteria m_fitCriteria;
|
||||||
|
const Palette* m_palette = nullptr;
|
||||||
|
int m_modifications = 0;
|
||||||
|
int m_maskIndex = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace doc
|
||||||
|
|
||||||
|
#endif
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite Document Library
|
// Aseprite Document Library
|
||||||
// Copyright (c) 2020 Igara Studio S.A.
|
// Copyright (c) 2020-2024 Igara Studio S.A.
|
||||||
// Copyright (c) 2001-2015 David Capello
|
// Copyright (c) 2001-2015 David Capello
|
||||||
//
|
//
|
||||||
// This file is released under the terms of the MIT license.
|
// This file is released under the terms of the MIT license.
|
||||||
@ -22,23 +22,21 @@ namespace doc {
|
|||||||
#define ASIZE 8
|
#define ASIZE 8
|
||||||
#define MAPSIZE (RSIZE*GSIZE*BSIZE*ASIZE)
|
#define MAPSIZE (RSIZE*GSIZE*BSIZE*ASIZE)
|
||||||
|
|
||||||
RgbMapRGB5A3::RgbMapRGB5A3()
|
RgbMapRGB5A3::RgbMapRGB5A3() : m_map(MAPSIZE) {}
|
||||||
: m_map(MAPSIZE)
|
|
||||||
, m_palette(nullptr)
|
|
||||||
, m_modifications(0)
|
|
||||||
, m_maskIndex(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void RgbMapRGB5A3::regenerateMap(const Palette* palette, int maskIndex)
|
void RgbMapRGB5A3::regenerateMap(const Palette* palette,
|
||||||
|
const int maskIndex,
|
||||||
|
const FitCriteria fitCriteria)
|
||||||
{
|
{
|
||||||
// Skip useless regenerations
|
// Skip useless regenerations
|
||||||
if (m_palette == palette &&
|
if (m_palette == palette &&
|
||||||
m_modifications == palette->getModifications() &&
|
m_modifications == palette->getModifications() &&
|
||||||
m_maskIndex == maskIndex)
|
m_maskIndex == maskIndex &&
|
||||||
|
m_fitCriteria == fitCriteria)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_palette = palette;
|
m_palette = palette;
|
||||||
|
m_fitCriteria = fitCriteria;
|
||||||
m_modifications = palette->getModifications();
|
m_modifications = palette->getModifications();
|
||||||
m_maskIndex = maskIndex;
|
m_maskIndex = maskIndex;
|
||||||
|
|
||||||
@ -50,7 +48,7 @@ void RgbMapRGB5A3::regenerateMap(const Palette* palette, int maskIndex)
|
|||||||
int RgbMapRGB5A3::generateEntry(int i, int r, int g, int b, int a) const
|
int RgbMapRGB5A3::generateEntry(int i, int r, int g, int b, int a) const
|
||||||
{
|
{
|
||||||
return m_map[i] =
|
return m_map[i] =
|
||||||
m_palette->findBestfit(
|
findBestfit(
|
||||||
scale_5bits_to_8bits(r>>3),
|
scale_5bits_to_8bits(r>>3),
|
||||||
scale_5bits_to_8bits(g>>3),
|
scale_5bits_to_8bits(g>>3),
|
||||||
scale_5bits_to_8bits(b>>3),
|
scale_5bits_to_8bits(b>>3),
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
#include "base/disable_copying.h"
|
#include "base/disable_copying.h"
|
||||||
#include "base/ints.h"
|
#include "base/ints.h"
|
||||||
#include "doc/object.h"
|
#include "doc/object.h"
|
||||||
#include "doc/rgbmap.h"
|
#include "doc/palette.h"
|
||||||
|
#include "doc/rgbmap_base.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ namespace doc {
|
|||||||
class Palette;
|
class Palette;
|
||||||
|
|
||||||
// It acts like a cache for Palette:findBestfit() calls.
|
// It acts like a cache for Palette:findBestfit() calls.
|
||||||
class RgbMapRGB5A3 : public RgbMap {
|
class RgbMapRGB5A3 : public RgbMapBase {
|
||||||
// Bit activated on m_map entries that aren't yet calculated.
|
// Bit activated on m_map entries that aren't yet calculated.
|
||||||
const uint16_t INVALID = 256;
|
const uint16_t INVALID = 256;
|
||||||
|
|
||||||
@ -30,7 +31,14 @@ namespace doc {
|
|||||||
RgbMapRGB5A3();
|
RgbMapRGB5A3();
|
||||||
|
|
||||||
// RgbMap impl
|
// RgbMap impl
|
||||||
void regenerateMap(const Palette* palette, int maskIndex) override;
|
void regenerateMap(const Palette* palette,
|
||||||
|
const int maskIndex,
|
||||||
|
const FitCriteria fitCriteria) override;
|
||||||
|
void regenerateMap(const Palette* palette,
|
||||||
|
const int maskIndex) override {
|
||||||
|
regenerateMap(palette, maskIndex, m_fitCriteria);
|
||||||
|
}
|
||||||
|
|
||||||
int mapColor(const color_t rgba) const override {
|
int mapColor(const color_t rgba) const override {
|
||||||
const uint8_t r = rgba_getr(rgba);
|
const uint8_t r = rgba_getr(rgba);
|
||||||
const uint8_t g = rgba_getg(rgba);
|
const uint8_t g = rgba_getg(rgba);
|
||||||
@ -42,15 +50,14 @@ namespace doc {
|
|||||||
return (v & INVALID) ? generateEntry(i, r, g, b, a): v;
|
return (v & INVALID) ? generateEntry(i, r, g, b, a): v;
|
||||||
}
|
}
|
||||||
|
|
||||||
int maskIndex() const override { return m_maskIndex; }
|
RgbMapAlgorithm rgbmapAlgorithm() const override {
|
||||||
|
return RgbMapAlgorithm::RGB5A3;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int generateEntry(int i, int r, int g, int b, int a) const;
|
int generateEntry(int i, int r, int g, int b, int a) const;
|
||||||
|
|
||||||
mutable std::vector<uint16_t> m_map;
|
mutable std::vector<uint16_t> m_map;
|
||||||
const Palette* m_palette;
|
|
||||||
int m_modifications;
|
|
||||||
int m_maskIndex;
|
|
||||||
|
|
||||||
DISABLE_COPYING(RgbMapRGB5A3);
|
DISABLE_COPYING(RgbMapRGB5A3);
|
||||||
};
|
};
|
||||||
|
@ -440,18 +440,24 @@ RgbMap* Sprite::rgbMap(const frame_t frame) const
|
|||||||
RgbMap* Sprite::rgbMap(const frame_t frame,
|
RgbMap* Sprite::rgbMap(const frame_t frame,
|
||||||
const RgbMapFor forLayer) const
|
const RgbMapFor forLayer) const
|
||||||
{
|
{
|
||||||
return rgbMap(frame,
|
FitCriteria fc = FitCriteria::DEFAULT;
|
||||||
forLayer,
|
RgbMapAlgorithm algo = g_rgbMapAlgorithm;
|
||||||
g_rgbMapAlgorithm);
|
if (m_rgbMap) {
|
||||||
|
fc = m_rgbMap->fitCriteria();
|
||||||
|
algo = m_rgbMap->rgbmapAlgorithm();
|
||||||
|
}
|
||||||
|
return rgbMap(frame, forLayer, algo, fc);
|
||||||
}
|
}
|
||||||
|
|
||||||
RgbMap* Sprite::rgbMap(const frame_t frame,
|
RgbMap* Sprite::rgbMap(const frame_t frame,
|
||||||
const RgbMapFor forLayer,
|
const RgbMapFor forLayer,
|
||||||
RgbMapAlgorithm mapAlgo) const
|
const RgbMapAlgorithm mapAlgo,
|
||||||
|
const FitCriteria fitCriteria) const
|
||||||
{
|
{
|
||||||
if (!m_rgbMap || m_rgbMapAlgorithm != mapAlgo) {
|
if (!m_rgbMap ||
|
||||||
m_rgbMapAlgorithm = mapAlgo;
|
m_rgbMap->rgbmapAlgorithm() != mapAlgo ||
|
||||||
switch (m_rgbMapAlgorithm) {
|
m_rgbMap->fitCriteria() != fitCriteria) {
|
||||||
|
switch (mapAlgo) {
|
||||||
case RgbMapAlgorithm::RGB5A3: m_rgbMap.reset(new RgbMapRGB5A3); break;
|
case RgbMapAlgorithm::RGB5A3: m_rgbMap.reset(new RgbMapRGB5A3); break;
|
||||||
case RgbMapAlgorithm::DEFAULT:
|
case RgbMapAlgorithm::DEFAULT:
|
||||||
case RgbMapAlgorithm::OCTREE: m_rgbMap.reset(new OctreeMap); break;
|
case RgbMapAlgorithm::OCTREE: m_rgbMap.reset(new OctreeMap); break;
|
||||||
@ -460,6 +466,7 @@ RgbMap* Sprite::rgbMap(const frame_t frame,
|
|||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
m_rgbMap->fitCriteria(fitCriteria);
|
||||||
}
|
}
|
||||||
int maskIndex;
|
int maskIndex;
|
||||||
if (forLayer == RgbMapFor::OpaqueLayer)
|
if (forLayer == RgbMapFor::OpaqueLayer)
|
||||||
@ -469,7 +476,7 @@ RgbMap* Sprite::rgbMap(const frame_t frame,
|
|||||||
if (maskIndex == -1)
|
if (maskIndex == -1)
|
||||||
maskIndex = 0;
|
maskIndex = 0;
|
||||||
}
|
}
|
||||||
m_rgbMap->regenerateMap(palette(frame), maskIndex);
|
m_rgbMap->regenerateMap(palette(frame), maskIndex, fitCriteria);
|
||||||
return m_rgbMap.get();
|
return m_rgbMap.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "doc/cel_data.h"
|
#include "doc/cel_data.h"
|
||||||
#include "doc/cel_list.h"
|
#include "doc/cel_list.h"
|
||||||
#include "doc/color.h"
|
#include "doc/color.h"
|
||||||
|
#include "doc/fit_criteria.h"
|
||||||
#include "doc/frame.h"
|
#include "doc/frame.h"
|
||||||
#include "doc/image_buffer.h"
|
#include "doc/image_buffer.h"
|
||||||
#include "doc/image_ref.h"
|
#include "doc/image_ref.h"
|
||||||
@ -167,7 +168,8 @@ namespace doc {
|
|||||||
const RgbMapFor forLayer) const;
|
const RgbMapFor forLayer) const;
|
||||||
RgbMap* rgbMap(const frame_t frame,
|
RgbMap* rgbMap(const frame_t frame,
|
||||||
const RgbMapFor forLayer,
|
const RgbMapFor forLayer,
|
||||||
RgbMapAlgorithm mapAlgo) const;
|
const RgbMapAlgorithm mapAlgo,
|
||||||
|
const FitCriteria fitCriteria = FitCriteria::DEFAULT) const;
|
||||||
|
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
// Frames
|
// Frames
|
||||||
@ -263,7 +265,6 @@ namespace doc {
|
|||||||
gfx::Rect m_gridBounds; // grid settings
|
gfx::Rect m_gridBounds; // grid settings
|
||||||
|
|
||||||
// Current rgb map
|
// Current rgb map
|
||||||
mutable RgbMapAlgorithm m_rgbMapAlgorithm;
|
|
||||||
mutable std::unique_ptr<RgbMap> m_rgbMap;
|
mutable std::unique_ptr<RgbMap> m_rgbMap;
|
||||||
|
|
||||||
Tags m_tags;
|
Tags m_tags;
|
||||||
|
Loading…
Reference in New Issue
Block a user