mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-14 13:21:34 +00:00
Merge e20ba700493920ffb0e496c9233c67b1dba6f41e into fc63532fef3b75d95759d93dab2b5622d5a12b6d
This commit is contained in:
commit
b06ee008b8
@ -1,5 +1,5 @@
|
||||
// Aseprite Render Library
|
||||
// Copyright (c) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (c) 2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -12,7 +12,6 @@
|
||||
#include "render/ordered_dither.h"
|
||||
|
||||
#include "render/dithering.h"
|
||||
#include "render/dithering_matrix.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
@ -216,12 +215,105 @@ doc::color_t OrderedDither2::ditherRgbPixelToIndex(const DitheringMatrix& matrix
|
||||
return index;
|
||||
}
|
||||
|
||||
void dither_two_color_case(DitheringAlgorithmBase& algorithm,
|
||||
const Dithering& dithering,
|
||||
const doc::Image* srcImage,
|
||||
doc::Image* dstImage,
|
||||
const doc::Palette* palette,
|
||||
const int color1Index,
|
||||
const int color2Index,
|
||||
const int maskIndex,
|
||||
TaskDelegate* delegate)
|
||||
{
|
||||
const int luma1 = doc::rgba_luma(palette->getEntry(color1Index));
|
||||
const int luma2 = doc::rgba_luma(palette->getEntry(color2Index));
|
||||
const int lightIndex = (luma1 > luma2 ? color1Index : color2Index);
|
||||
const int darkIndex = (luma1 > luma2 ? color2Index : color1Index);
|
||||
|
||||
const doc::LockImageBits<doc::RgbTraits> srcBits(srcImage);
|
||||
doc::LockImageBits<doc::IndexedTraits> dstBits(dstImage);
|
||||
auto srcIt = srcBits.begin();
|
||||
auto dstIt = dstBits.begin();
|
||||
const int w = srcImage->width();
|
||||
const int h = srcImage->height();
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x, ++srcIt, ++dstIt) {
|
||||
ASSERT(srcIt != srcBits.end());
|
||||
ASSERT(dstIt != dstBits.end());
|
||||
*dstIt = algorithm.ditherRgbPixelToIndexForTwoColors(dithering.matrix(),
|
||||
*srcIt,
|
||||
x,
|
||||
y,
|
||||
lightIndex,
|
||||
darkIndex,
|
||||
maskIndex);
|
||||
|
||||
if (delegate) {
|
||||
if (!delegate->continueTask())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (delegate) {
|
||||
delegate->notifyTaskProgress(double(y + 1) / double(h));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have only two different colors in the palette
|
||||
bool two_color_case_confirmation(const doc::RgbMap* rgbmap,
|
||||
const doc::Palette* palette,
|
||||
const bool is_background,
|
||||
int& color1Index,
|
||||
int& color2Index,
|
||||
int& maskIndex)
|
||||
{
|
||||
if (!is_background && rgbmap && rgbmap->maskIndex() != -1)
|
||||
maskIndex = rgbmap->maskIndex();
|
||||
else
|
||||
maskIndex = palette->findMaskColor();
|
||||
int i1 = -1;
|
||||
int i2 = -1;
|
||||
int i = 0;
|
||||
for (; i < palette->size(); i++) {
|
||||
if (i != maskIndex) {
|
||||
i1 = i;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; i < palette->size(); i++) {
|
||||
if (i != maskIndex && palette->getEntry(i1) != palette->getEntry(i)) {
|
||||
i2 = i;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; i < palette->size(); i++) {
|
||||
const doc::color_t c = palette->getEntry(i);
|
||||
if (i != maskIndex && palette->getEntry(i1) != c && palette->getEntry(i2) != c) {
|
||||
color1Index = -1;
|
||||
color2Index = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (i1 == -1 || i2 == -1) {
|
||||
color1Index = -1;
|
||||
color2Index = -1;
|
||||
return false;
|
||||
}
|
||||
color1Index = i1;
|
||||
color2Index = i2;
|
||||
return true;
|
||||
}
|
||||
|
||||
void dither_rgb_image_to_indexed(DitheringAlgorithmBase& algorithm,
|
||||
const Dithering& dithering,
|
||||
const doc::Image* srcImage,
|
||||
doc::Image* dstImage,
|
||||
const doc::RgbMap* rgbmap,
|
||||
const doc::Palette* palette,
|
||||
const bool is_background,
|
||||
TaskDelegate* delegate)
|
||||
{
|
||||
const int w = srcImage->width();
|
||||
@ -230,26 +322,48 @@ void dither_rgb_image_to_indexed(DitheringAlgorithmBase& algorithm,
|
||||
algorithm.start(srcImage, dstImage, dithering.factor());
|
||||
|
||||
if (algorithm.dimensions() == 1) {
|
||||
const doc::LockImageBits<doc::RgbTraits> srcBits(srcImage);
|
||||
doc::LockImageBits<doc::IndexedTraits> dstBits(dstImage);
|
||||
auto srcIt = srcBits.begin();
|
||||
auto dstIt = dstBits.begin();
|
||||
int color1Index = -1;
|
||||
int color2Index = -1;
|
||||
int maskIndex = -1;
|
||||
if (two_color_case_confirmation(rgbmap,
|
||||
palette,
|
||||
is_background,
|
||||
color1Index,
|
||||
color2Index,
|
||||
maskIndex)) {
|
||||
dither_two_color_case(algorithm,
|
||||
dithering,
|
||||
srcImage,
|
||||
dstImage,
|
||||
palette,
|
||||
color1Index,
|
||||
color2Index,
|
||||
maskIndex,
|
||||
delegate);
|
||||
}
|
||||
else {
|
||||
const doc::LockImageBits<doc::RgbTraits> srcBits(srcImage);
|
||||
doc::LockImageBits<doc::IndexedTraits> dstBits(dstImage);
|
||||
auto srcIt = srcBits.begin();
|
||||
auto dstIt = dstBits.begin();
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x, ++srcIt, ++dstIt) {
|
||||
ASSERT(srcIt != srcBits.end());
|
||||
ASSERT(dstIt != dstBits.end());
|
||||
*dstIt = algorithm.ditherRgbPixelToIndex(dithering.matrix(), *srcIt, x, y, rgbmap, palette);
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x, ++srcIt, ++dstIt) {
|
||||
ASSERT(srcIt != srcBits.end());
|
||||
ASSERT(dstIt != dstBits.end());
|
||||
*dstIt =
|
||||
algorithm.ditherRgbPixelToIndex(dithering.matrix(), *srcIt, x, y, rgbmap, palette);
|
||||
|
||||
if (delegate) {
|
||||
if (!delegate->continueTask())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (delegate) {
|
||||
if (!delegate->continueTask())
|
||||
return;
|
||||
delegate->notifyTaskProgress(double(y + 1) / double(h));
|
||||
}
|
||||
}
|
||||
|
||||
if (delegate) {
|
||||
delegate->notifyTaskProgress(double(y + 1) / double(h));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Render Library
|
||||
// Copyright (c) 2019 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2017 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -15,6 +15,7 @@
|
||||
#include "doc/rgbmap.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/size.h"
|
||||
#include "render/dithering_matrix.h"
|
||||
#include "render/task_delegate.h"
|
||||
|
||||
namespace render {
|
||||
@ -50,6 +51,23 @@ public:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Special case of two colors in the palette
|
||||
static doc::color_t ditherRgbPixelToIndexForTwoColors(const DitheringMatrix& matrix,
|
||||
const doc::color_t color,
|
||||
const int x,
|
||||
const int y,
|
||||
const int lightIndex,
|
||||
const int darkIndex,
|
||||
const doc::color_t transparentIndex)
|
||||
{
|
||||
// Alpha=0, output transparent color
|
||||
if (transparentIndex >= 0 && doc::rgba_geta(color) == 0)
|
||||
return transparentIndex;
|
||||
|
||||
const int luma = doc::rgba_luma(color);
|
||||
return (luma * (matrix.maxValue() + 1) > 255 * matrix(y, x)) ? lightIndex : darkIndex;
|
||||
}
|
||||
};
|
||||
|
||||
class OrderedDither : public DitheringAlgorithmBase {
|
||||
@ -86,6 +104,7 @@ void dither_rgb_image_to_indexed(DitheringAlgorithmBase& algorithm,
|
||||
doc::Image* dstImage,
|
||||
const doc::RgbMap* rgbmap,
|
||||
const doc::Palette* palette,
|
||||
const bool is_background,
|
||||
TaskDelegate* delegate = nullptr);
|
||||
|
||||
} // namespace render
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Render Library
|
||||
// Copyright (c) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (c) 2019-2025 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -164,7 +164,14 @@ Image* convert_pixel_format(const Image* image,
|
||||
break;
|
||||
}
|
||||
if (dither)
|
||||
dither_rgb_image_to_indexed(*dither, dithering, image, new_image, rgbmap, palette, delegate);
|
||||
dither_rgb_image_to_indexed(*dither,
|
||||
dithering,
|
||||
image,
|
||||
new_image,
|
||||
rgbmap,
|
||||
palette,
|
||||
is_background,
|
||||
delegate);
|
||||
return new_image;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user