mirror of https://github.com/aseprite/aseprite.git
Use a task_token to cancel a filter when we are processing a row
Added FILTER_LOOP_THROUGH_ROW_BEGIN/END macros to simplify some boilerplate code for each filter. In this way if processing just one row takes too much time, canceling the operation is faster.
This commit is contained in:
parent
87075296ed
commit
59f6b78e4f
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
|
@ -64,7 +64,8 @@ FilterManagerImpl::FilterManagerImpl(Context* context, Filter* filter)
|
|||
, m_target(TARGET_ALL_CHANNELS)
|
||||
, m_celsTarget(CelsTarget::Selected)
|
||||
, m_oldPalette(nullptr)
|
||||
, m_progressDelegate(NULL)
|
||||
, m_taskToken(&m_noToken)
|
||||
, m_progressDelegate(nullptr)
|
||||
{
|
||||
int x, y;
|
||||
Image* image = m_site.image(&x, &y);
|
||||
|
|
@ -121,6 +122,7 @@ void FilterManagerImpl::begin()
|
|||
|
||||
m_row = 0;
|
||||
m_mask = (document->isMaskVisible() ? document->mask(): nullptr);
|
||||
m_taskToken = &m_noToken; // Don't use the preview token (which can be canceled)
|
||||
updateBounds(m_mask);
|
||||
}
|
||||
|
||||
|
|
@ -550,4 +552,15 @@ bool FilterManagerImpl::isMaskActive() const
|
|||
return m_site.document()->isMaskVisible();
|
||||
}
|
||||
|
||||
base::task_token& FilterManagerImpl::taskToken() const
|
||||
{
|
||||
ASSERT(m_taskToken); // It's always pointing to a token, m_noToken by default
|
||||
return *m_taskToken;
|
||||
}
|
||||
|
||||
void FilterManagerImpl::setTaskToken(base::task_token& token)
|
||||
{
|
||||
m_taskToken = &token;
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
#include "app/site.h"
|
||||
#include "app/tx.h"
|
||||
#include "base/exception.h"
|
||||
#include "base/task.h"
|
||||
#include "doc/image_impl.h"
|
||||
#include "doc/image_ref.h"
|
||||
#include "doc/pixel_format.h"
|
||||
|
|
@ -62,7 +63,7 @@ namespace app {
|
|||
public:
|
||||
// Interface to report progress to the user and take input from him
|
||||
// to cancel the whole process.
|
||||
class IProgressDelegate {
|
||||
class IProgressDelegate { // TODO replace this with base::task_token
|
||||
public:
|
||||
virtual ~IProgressDelegate() { }
|
||||
|
||||
|
|
@ -105,6 +106,7 @@ namespace app {
|
|||
void flush();
|
||||
void disablePreview();
|
||||
#endif
|
||||
void setTaskToken(base::task_token& token);
|
||||
|
||||
// FilterManager implementation
|
||||
doc::PixelFormat pixelFormat() const override;
|
||||
|
|
@ -119,6 +121,7 @@ namespace app {
|
|||
int y() const override { return m_bounds.y+m_row; }
|
||||
bool isFirstRow() const override { return m_row == 0; }
|
||||
bool isMaskActive() const override;
|
||||
base::task_token& taskToken() const override;
|
||||
|
||||
// FilterIndexedData implementation
|
||||
const doc::Palette* getPalette() const override;
|
||||
|
|
@ -163,6 +166,8 @@ namespace app {
|
|||
CelsTarget m_celsTarget;
|
||||
std::unique_ptr<doc::Palette> m_oldPalette;
|
||||
std::unique_ptr<Tx> m_tx;
|
||||
base::task_token m_noToken;
|
||||
base::task_token* m_taskToken;
|
||||
|
||||
// Hooks
|
||||
float m_progressBase;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ void FilterPreview::setEnablePreview(bool state)
|
|||
|
||||
void FilterPreview::stop()
|
||||
{
|
||||
// Cancel the token (so the filter processing stops immediately)
|
||||
m_filterTask.cancel();
|
||||
{
|
||||
std::scoped_lock lock(m_filterMgrMutex);
|
||||
if (m_timer.isRunning()) {
|
||||
|
|
@ -65,14 +67,14 @@ void FilterPreview::stop()
|
|||
}
|
||||
m_timer.stop();
|
||||
}
|
||||
if (m_filterTask.running()) {
|
||||
m_filterTask.cancel();
|
||||
if (m_filterTask.running())
|
||||
m_filterTask.wait();
|
||||
}
|
||||
}
|
||||
|
||||
void FilterPreview::restartPreview()
|
||||
{
|
||||
// Cancel the token (so the filter processing stops immediately)
|
||||
m_filterTask.cancel();
|
||||
std::scoped_lock lock(m_filterMgrMutex);
|
||||
|
||||
// Restart filter, timer, and task if needed (there is no need to
|
||||
|
|
@ -84,11 +86,18 @@ void FilterPreview::restartPreview()
|
|||
m_filterMgr->beginForPreview();
|
||||
m_timer.start();
|
||||
|
||||
// TODO add timer to restart...
|
||||
|
||||
if (!m_filterTask.running()) {
|
||||
m_filterTask.run([this](base::task_token& token){
|
||||
m_filterTask.run([this](base::task_token& token) {
|
||||
m_filterMgr->setTaskToken(token);
|
||||
onFilterTask(token);
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Is it possible to happen? We cancel the token, the task is
|
||||
// still running, we don't launch it again and we are here.
|
||||
}
|
||||
}
|
||||
|
||||
bool FilterPreview::onProcessMessage(Message* msg)
|
||||
|
|
|
|||
|
|
@ -55,19 +55,9 @@ void BrightnessContrastFilter::applyToRgba(FilterManager* filterMgr)
|
|||
FilterIndexedData* fid = filterMgr->getIndexedData();
|
||||
const Palette* pal = fid->getPalette();
|
||||
Palette* newPal = (m_usePaletteOnRGB ? fid->getNewPalette(): nullptr);
|
||||
const uint32_t* src_address = (uint32_t*)filterMgr->getSourceAddress();
|
||||
uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
|
||||
const int w = filterMgr->getWidth();
|
||||
const Target target = filterMgr->getTarget();
|
||||
|
||||
for (int x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
color_t c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint32_t) {
|
||||
color_t c = *src_address;
|
||||
|
||||
if (newPal) {
|
||||
int i =
|
||||
|
|
@ -82,32 +72,23 @@ void BrightnessContrastFilter::applyToRgba(FilterManager* filterMgr)
|
|||
applyFilterToRgb(target, c);
|
||||
}
|
||||
|
||||
*(dst_address++) = c;
|
||||
*dst_address = c;
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void BrightnessContrastFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
const uint16_t* src_address = (uint16_t*)filterMgr->getSourceAddress();
|
||||
uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress();
|
||||
const int w = filterMgr->getWidth();
|
||||
const Target target = filterMgr->getTarget();
|
||||
|
||||
for (int x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
color_t c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint16_t) {
|
||||
color_t c = *src_address;
|
||||
int k = graya_getv(c);
|
||||
int a = graya_geta(c);
|
||||
|
||||
if (target & TARGET_GRAY_CHANNEL) k = m_cmap[k];
|
||||
|
||||
*(dst_address++) = graya(k, a);
|
||||
*dst_address = graya(k, a);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void BrightnessContrastFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
|
|
@ -121,31 +102,22 @@ void BrightnessContrastFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
return;
|
||||
|
||||
// Apply filter to color region
|
||||
const Target target = filterMgr->getTarget();
|
||||
const Palette* pal = fid->getPalette();
|
||||
const RgbMap* rgbmap = fid->getRgbMap();
|
||||
const uint8_t* src_address = (uint8_t*)filterMgr->getSourceAddress();
|
||||
uint8_t* dst_address = (uint8_t*)filterMgr->getDestinationAddress();
|
||||
const int w = filterMgr->getWidth();
|
||||
|
||||
for (int x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
color_t c = pal->getEntry(*(src_address++));
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint8_t) {
|
||||
color_t c = pal->getEntry(*src_address);
|
||||
applyFilterToRgb(target, c);
|
||||
*(dst_address++) = rgbmap->mapColor(c);
|
||||
*dst_address = rgbmap->mapColor(c);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void BrightnessContrastFilter::onApplyToPalette(FilterManager* filterMgr,
|
||||
const PalettePicks& picks)
|
||||
{
|
||||
const Target target = filterMgr->getTarget();
|
||||
FilterIndexedData* fid = filterMgr->getIndexedData();
|
||||
const Target target = filterMgr->getTarget();
|
||||
const Palette* pal = fid->getPalette();
|
||||
Palette* newPal = fid->getNewPalette();
|
||||
|
||||
|
|
|
|||
|
|
@ -51,20 +51,10 @@ const char* ColorCurveFilter::getName()
|
|||
|
||||
void ColorCurveFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
const uint32_t* src_address = (uint32_t*)filterMgr->getSourceAddress();
|
||||
uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
int x, c, r, g, b, a;
|
||||
int c, r, g, b, a;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint32_t) {
|
||||
c = *src_address;
|
||||
|
||||
r = rgba_getr(c);
|
||||
g = rgba_getg(c);
|
||||
|
|
@ -76,26 +66,17 @@ void ColorCurveFilter::applyToRgba(FilterManager* filterMgr)
|
|||
if (target & TARGET_BLUE_CHANNEL) b = m_cmap[b];
|
||||
if (target & TARGET_ALPHA_CHANNEL) a = m_cmap[a];
|
||||
|
||||
*(dst_address++) = rgba(r, g, b, a);
|
||||
*dst_address = rgba(r, g, b, a);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void ColorCurveFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
const uint16_t* src_address = (uint16_t*)filterMgr->getSourceAddress();
|
||||
uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
int x, c, k, a;
|
||||
int c, k, a;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint16_t) {
|
||||
c = *src_address;
|
||||
|
||||
k = graya_getv(c);
|
||||
a = graya_geta(c);
|
||||
|
|
@ -103,28 +84,19 @@ void ColorCurveFilter::applyToGrayscale(FilterManager* filterMgr)
|
|||
if (target & TARGET_GRAY_CHANNEL) k = m_cmap[k];
|
||||
if (target & TARGET_ALPHA_CHANNEL) a = m_cmap[a];
|
||||
|
||||
*(dst_address++) = graya(k, a);
|
||||
*dst_address = graya(k, a);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void ColorCurveFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
const uint8_t* src_address = (uint8_t*)filterMgr->getSourceAddress();
|
||||
uint8_t* dst_address = (uint8_t*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
const Palette* pal = filterMgr->getIndexedData()->getPalette();
|
||||
const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
|
||||
int x, c, r, g, b, a;
|
||||
int c, r, g, b, a;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint8_t) {
|
||||
c = *src_address;
|
||||
|
||||
if (target & TARGET_INDEX_CHANNEL) {
|
||||
c = m_cmap[c];
|
||||
|
|
@ -144,8 +116,9 @@ void ColorCurveFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
c = rgbmap->mapColor(r, g, b, a);
|
||||
}
|
||||
|
||||
*(dst_address++) = std::clamp(c, 0, pal->size()-1);
|
||||
*dst_address = std::clamp(c, 0, pal->size()-1);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
} // namespace filters
|
||||
|
|
|
|||
|
|
@ -136,21 +136,10 @@ void ConvolutionMatrixFilter::applyToRgba(FilterManager* filterMgr)
|
|||
return;
|
||||
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
|
||||
Target target = filterMgr->getTarget();
|
||||
uint32_t color;
|
||||
GetPixelsDelegateRgba delegate;
|
||||
int x = filterMgr->x();
|
||||
int x2 = x+filterMgr->getWidth();
|
||||
int y = filterMgr->y();
|
||||
|
||||
for (; x<x2; ++x) {
|
||||
// Avoid the non-selected region
|
||||
if (filterMgr->skipPixel()) {
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint32_t) {
|
||||
delegate.reset(m_matrix.get());
|
||||
get_neighboring_pixels<RgbTraits>(src, x, y,
|
||||
m_matrix->getWidth(),
|
||||
|
|
@ -161,7 +150,7 @@ void ConvolutionMatrixFilter::applyToRgba(FilterManager* filterMgr)
|
|||
|
||||
color = get_pixel_fast<RgbTraits>(src, x, y);
|
||||
if (delegate.div == 0) {
|
||||
*(dst_address++) = color;
|
||||
*dst_address = color;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -193,8 +182,9 @@ void ConvolutionMatrixFilter::applyToRgba(FilterManager* filterMgr)
|
|||
else
|
||||
delegate.a = rgba_geta(color);
|
||||
|
||||
*(dst_address++) = rgba(delegate.r, delegate.g, delegate.b, delegate.a);
|
||||
*dst_address = rgba(delegate.r, delegate.g, delegate.b, delegate.a);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void ConvolutionMatrixFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
|
|
@ -203,21 +193,10 @@ void ConvolutionMatrixFilter::applyToGrayscale(FilterManager* filterMgr)
|
|||
return;
|
||||
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress();
|
||||
Target target = filterMgr->getTarget();
|
||||
uint16_t color;
|
||||
GetPixelsDelegateGrayscale delegate;
|
||||
int x = filterMgr->x();
|
||||
int x2 = x+filterMgr->getWidth();
|
||||
int y = filterMgr->y();
|
||||
|
||||
for (; x<x2; ++x) {
|
||||
// Avoid the non-selected region
|
||||
if (filterMgr->skipPixel()) {
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint16_t) {
|
||||
delegate.reset(m_matrix.get());
|
||||
get_neighboring_pixels<GrayscaleTraits>(src, x, y,
|
||||
m_matrix->getWidth(),
|
||||
|
|
@ -228,7 +207,7 @@ void ConvolutionMatrixFilter::applyToGrayscale(FilterManager* filterMgr)
|
|||
|
||||
color = get_pixel_fast<GrayscaleTraits>(src, x, y);
|
||||
if (delegate.div == 0) {
|
||||
*(dst_address++) = color;
|
||||
*dst_address = color;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -246,8 +225,9 @@ void ConvolutionMatrixFilter::applyToGrayscale(FilterManager* filterMgr)
|
|||
else
|
||||
delegate.a = graya_geta(color);
|
||||
|
||||
*(dst_address++) = graya(delegate.v, delegate.a);
|
||||
*dst_address = graya(delegate.v, delegate.a);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void ConvolutionMatrixFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
|
|
@ -256,23 +236,12 @@ void ConvolutionMatrixFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
return;
|
||||
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
uint8_t* dst_address = (uint8_t*)filterMgr->getDestinationAddress();
|
||||
const Palette* pal = filterMgr->getIndexedData()->getPalette();
|
||||
const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
|
||||
Target target = filterMgr->getTarget();
|
||||
uint8_t color;
|
||||
GetPixelsDelegateIndexed delegate(pal);
|
||||
int x = filterMgr->x();
|
||||
int x2 = x+filterMgr->getWidth();
|
||||
int y = filterMgr->y();
|
||||
|
||||
for (; x<x2; ++x) {
|
||||
// Avoid the non-selected region
|
||||
if (filterMgr->skipPixel()) {
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint8_t) {
|
||||
delegate.reset(m_matrix.get());
|
||||
get_neighboring_pixels<IndexedTraits>(src, x, y,
|
||||
m_matrix->getWidth(),
|
||||
|
|
@ -283,7 +252,7 @@ void ConvolutionMatrixFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
|
||||
color = get_pixel_fast<IndexedTraits>(src, x, y);
|
||||
if (delegate.div == 0) {
|
||||
*(dst_address++) = color;
|
||||
*dst_address = color;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +260,7 @@ void ConvolutionMatrixFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
delegate.index = delegate.index / m_matrix->getDiv() + m_matrix->getBias();
|
||||
delegate.index = std::clamp(delegate.index, 0, 255);
|
||||
|
||||
*(dst_address++) = delegate.index;
|
||||
*dst_address = delegate.index;
|
||||
}
|
||||
else {
|
||||
color = pal->getEntry(color);
|
||||
|
|
@ -324,9 +293,10 @@ void ConvolutionMatrixFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
else
|
||||
delegate.a = rgba_geta(color);
|
||||
|
||||
*(dst_address++) = rgbmap->mapColor(delegate.r, delegate.g, delegate.b, delegate.a);
|
||||
*dst_address = rgbmap->mapColor(delegate.r, delegate.g, delegate.b, delegate.a);
|
||||
}
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
} // namespace filters
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
|
|
@ -9,9 +9,29 @@
|
|||
#define FILTERS_FILTER_MANAGER_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/task.h"
|
||||
#include "doc/pixel_format.h"
|
||||
#include "filters/target.h"
|
||||
|
||||
// Creates src_address, dst_address, x, x2, and y variables to iterate
|
||||
// through a row of the target. Skips non-selected areas.
|
||||
// Requires the "filterMgr" variable.
|
||||
#define FILTER_LOOP_THROUGH_ROW_BEGIN(Type) \
|
||||
const Target target = filterMgr->getTarget(); \
|
||||
auto src_address = (const Type*)filterMgr->getSourceAddress(); \
|
||||
auto dst_address = (Type*)filterMgr->getDestinationAddress(); \
|
||||
int x = filterMgr->x(); \
|
||||
const int x2 = x + filterMgr->getWidth(); \
|
||||
[[maybe_unused]] const int y = filterMgr->y(); \
|
||||
auto& token = filterMgr->taskToken(); \
|
||||
for (; x < x2 && !token.canceled(); \
|
||||
++x, ++src_address, ++dst_address) { \
|
||||
if (filterMgr->skipPixel()) \
|
||||
continue;
|
||||
|
||||
#define FILTER_LOOP_THROUGH_ROW_END() \
|
||||
}
|
||||
|
||||
namespace doc {
|
||||
class Image;
|
||||
}
|
||||
|
|
@ -81,6 +101,10 @@ namespace filters {
|
|||
// filter just to a part of the sprite).
|
||||
virtual bool isMaskActive() const = 0;
|
||||
|
||||
// Task token used to cancel the filter operation (the filter can
|
||||
// check this each X pixels to know if the user canceled the
|
||||
// operation)
|
||||
virtual base::task_token& taskToken() const = 0;
|
||||
};
|
||||
|
||||
} // namespace filters
|
||||
|
|
|
|||
|
|
@ -71,19 +71,9 @@ void HueSaturationFilter::applyToRgba(FilterManager* filterMgr)
|
|||
FilterIndexedData* fid = filterMgr->getIndexedData();
|
||||
const Palette* pal = fid->getPalette();
|
||||
Palette* newPal = (m_usePaletteOnRGB ? fid->getNewPalette(): nullptr);
|
||||
const uint32_t* src_address = (uint32_t*)filterMgr->getSourceAddress();
|
||||
uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
|
||||
const int w = filterMgr->getWidth();
|
||||
const Target target = filterMgr->getTarget();
|
||||
|
||||
for (int x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
color_t c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint32_t) {
|
||||
color_t c = *src_address;
|
||||
|
||||
if (newPal) {
|
||||
int i =
|
||||
|
|
@ -98,25 +88,15 @@ void HueSaturationFilter::applyToRgba(FilterManager* filterMgr)
|
|||
applyFilterToRgb(target, c);
|
||||
}
|
||||
|
||||
*(dst_address++) = c;
|
||||
*dst_address = c;
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void HueSaturationFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
const uint16_t* src_address = (uint16_t*)filterMgr->getSourceAddress();
|
||||
uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress();
|
||||
const int w = filterMgr->getWidth();
|
||||
const Target target = filterMgr->getTarget();
|
||||
|
||||
for (int x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
color_t c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint16_t) {
|
||||
color_t c = *src_address;
|
||||
int k = graya_getv(c);
|
||||
int a = graya_geta(c);
|
||||
|
||||
|
|
@ -137,8 +117,9 @@ void HueSaturationFilter::applyToGrayscale(FilterManager* filterMgr)
|
|||
}
|
||||
}
|
||||
|
||||
*(dst_address++) = graya(k, a);
|
||||
*dst_address = graya(k, a);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void HueSaturationFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
|
|
@ -151,24 +132,15 @@ void HueSaturationFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
|
||||
// Apply filter to color region
|
||||
FilterIndexedData* fid = filterMgr->getIndexedData();
|
||||
const Target target = filterMgr->getTarget();
|
||||
const Palette* pal = fid->getPalette();
|
||||
const RgbMap* rgbmap = fid->getRgbMap();
|
||||
const uint8_t* src_address = (uint8_t*)filterMgr->getSourceAddress();
|
||||
uint8_t* dst_address = (uint8_t*)filterMgr->getDestinationAddress();
|
||||
const int w = filterMgr->getWidth();
|
||||
|
||||
for (int x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
color_t c = pal->getEntry(*(src_address++));
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint8_t) {
|
||||
color_t c = pal->getEntry(*src_address);
|
||||
applyFilterToRgb(target, c);
|
||||
*(dst_address++) = rgbmap->mapColor(c);
|
||||
*dst_address = rgbmap->mapColor(c);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void HueSaturationFilter::onApplyToPalette(FilterManager* filterMgr,
|
||||
|
|
|
|||
|
|
@ -27,20 +27,10 @@ const char* InvertColorFilter::getName()
|
|||
|
||||
void InvertColorFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
const uint32_t* src_address = (uint32_t*)filterMgr->getSourceAddress();
|
||||
uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
int x, c, r, g, b, a;
|
||||
int c, r, g, b, a;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint32_t) {
|
||||
c = *src_address;
|
||||
|
||||
r = rgba_getr(c);
|
||||
g = rgba_getg(c);
|
||||
|
|
@ -52,26 +42,17 @@ void InvertColorFilter::applyToRgba(FilterManager* filterMgr)
|
|||
if (target & TARGET_BLUE_CHANNEL) b ^= 0xff;
|
||||
if (target & TARGET_ALPHA_CHANNEL) a ^= 0xff;
|
||||
|
||||
*(dst_address++) = rgba(r, g, b, a);
|
||||
*dst_address = rgba(r, g, b, a);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void InvertColorFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
const uint16_t* src_address = (uint16_t*)filterMgr->getSourceAddress();
|
||||
uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
int x, c, k, a;
|
||||
int c, k, a;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint16_t) {
|
||||
c = *src_address;
|
||||
|
||||
k = graya_getv(c);
|
||||
a = graya_geta(c);
|
||||
|
|
@ -79,28 +60,19 @@ void InvertColorFilter::applyToGrayscale(FilterManager* filterMgr)
|
|||
if (target & TARGET_GRAY_CHANNEL) k ^= 0xff;
|
||||
if (target & TARGET_ALPHA_CHANNEL) a ^= 0xff;
|
||||
|
||||
*(dst_address++) = graya(k, a);
|
||||
*dst_address = graya(k, a);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void InvertColorFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
const uint8_t* src_address = (uint8_t*)filterMgr->getSourceAddress();
|
||||
uint8_t* dst_address = (uint8_t*)filterMgr->getDestinationAddress();
|
||||
const Palette* pal = filterMgr->getIndexedData()->getPalette();
|
||||
const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
int x, c, r, g, b, a;
|
||||
int c, r, g, b, a;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint8_t) {
|
||||
c = *src_address;
|
||||
|
||||
if (target & TARGET_INDEX_CHANNEL)
|
||||
c ^= 0xff;
|
||||
|
|
@ -119,8 +91,9 @@ void InvertColorFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
c = rgbmap->mapColor(r, g, b, a);
|
||||
}
|
||||
|
||||
*(dst_address++) = c;
|
||||
*dst_address = c;
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
} // namespace filters
|
||||
|
|
|
|||
|
|
@ -124,22 +124,10 @@ const char* MedianFilter::getName()
|
|||
void MedianFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
|
||||
Target target = filterMgr->getTarget();
|
||||
int color;
|
||||
int r, g, b, a;
|
||||
int color, r, g, b, a;
|
||||
GetPixelsDelegateRgba delegate(m_channel);
|
||||
int x = filterMgr->x();
|
||||
int x2 = x+filterMgr->getWidth();
|
||||
int y = filterMgr->y();
|
||||
|
||||
for (; x<x2; ++x) {
|
||||
// Avoid the non-selected region
|
||||
if (filterMgr->skipPixel()) {
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint32_t) {
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<RgbTraits>(src, x, y, m_width, m_height, m_width/2, m_height/2,
|
||||
m_tiledMode, delegate);
|
||||
|
|
@ -174,28 +162,18 @@ void MedianFilter::applyToRgba(FilterManager* filterMgr)
|
|||
else
|
||||
a = rgba_geta(color);
|
||||
|
||||
*(dst_address++) = rgba(r, g, b, a);
|
||||
*dst_address = rgba(r, g, b, a);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void MedianFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress();
|
||||
Target target = filterMgr->getTarget();
|
||||
int color, k, a;
|
||||
GetPixelsDelegateGrayscale delegate(m_channel);
|
||||
int x = filterMgr->x();
|
||||
int x2 = x+filterMgr->getWidth();
|
||||
int y = filterMgr->y();
|
||||
|
||||
for (; x<x2; ++x) {
|
||||
// Avoid the non-selected region
|
||||
if (filterMgr->skipPixel()) {
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint16_t) {
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<GrayscaleTraits>(src, x, y, m_width, m_height, m_width/2, m_height/2,
|
||||
m_tiledMode, delegate);
|
||||
|
|
@ -216,37 +194,27 @@ void MedianFilter::applyToGrayscale(FilterManager* filterMgr)
|
|||
else
|
||||
a = graya_geta(color);
|
||||
|
||||
*(dst_address++) = graya(k, a);
|
||||
*dst_address = graya(k, a);
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void MedianFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
uint8_t* dst_address = (uint8_t*)filterMgr->getDestinationAddress();
|
||||
const Palette* pal = filterMgr->getIndexedData()->getPalette();
|
||||
const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
|
||||
Target target = filterMgr->getTarget();
|
||||
int color, r, g, b, a;
|
||||
GetPixelsDelegateIndexed delegate(pal, m_channel, target);
|
||||
int x = filterMgr->x();
|
||||
int x2 = x+filterMgr->getWidth();
|
||||
int y = filterMgr->y();
|
||||
|
||||
for (; x<x2; ++x) {
|
||||
// Avoid the non-selected region
|
||||
if (filterMgr->skipPixel()) {
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
GetPixelsDelegateIndexed delegate(pal, m_channel, filterMgr->getTarget());
|
||||
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint8_t) {
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<IndexedTraits>(src, x, y, m_width, m_height, m_width/2, m_height/2,
|
||||
m_tiledMode, delegate);
|
||||
|
||||
if (target & TARGET_INDEX_CHANNEL) {
|
||||
std::sort(m_channel[0].begin(), m_channel[0].end());
|
||||
*(dst_address++) = m_channel[0][m_ncolors/2];
|
||||
*dst_address = m_channel[0][m_ncolors/2];
|
||||
}
|
||||
else {
|
||||
color = get_pixel_fast<IndexedTraits>(src, x, y);
|
||||
|
|
@ -280,9 +248,10 @@ void MedianFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
else
|
||||
a = rgba_geta(color);
|
||||
|
||||
*(dst_address++) = rgbmap->mapColor(r, g, b, a);
|
||||
*dst_address = rgbmap->mapColor(r, g, b, a);
|
||||
}
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
} // namespace filters
|
||||
|
|
|
|||
|
|
@ -98,12 +98,6 @@ const char* OutlineFilter::getName()
|
|||
void OutlineFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
const uint32_t* src_address = (uint32_t*)filterMgr->getSourceAddress();
|
||||
uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
|
||||
int x = filterMgr->x();
|
||||
const int x2 = x+filterMgr->getWidth();
|
||||
const int y = filterMgr->y();
|
||||
Target target = filterMgr->getTarget();
|
||||
int r, g, b, a, n;
|
||||
color_t c;
|
||||
bool isTransparent;
|
||||
|
|
@ -111,10 +105,7 @@ void OutlineFilter::applyToRgba(FilterManager* filterMgr)
|
|||
GetPixelsDelegateRgba delegate;
|
||||
delegate.init(m_bgColor, m_matrix);
|
||||
|
||||
for (; x<x2; ++x, ++src_address, ++dst_address) {
|
||||
if (filterMgr->skipPixel())
|
||||
continue;
|
||||
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint32_t) {
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<RgbTraits>(src, x, y, 3, 3, 1, 1, m_tiledMode, delegate);
|
||||
|
||||
|
|
@ -134,17 +125,12 @@ void OutlineFilter::applyToRgba(FilterManager* filterMgr)
|
|||
|
||||
*dst_address = c;
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void OutlineFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
const uint16_t* src_address = (uint16_t*)filterMgr->getSourceAddress();
|
||||
uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress();
|
||||
int x = filterMgr->x();
|
||||
const int x2 = x+filterMgr->getWidth();
|
||||
const int y = filterMgr->y();
|
||||
Target target = filterMgr->getTarget();
|
||||
int k, a, n;
|
||||
color_t c;
|
||||
bool isTransparent;
|
||||
|
|
@ -152,10 +138,7 @@ void OutlineFilter::applyToGrayscale(FilterManager* filterMgr)
|
|||
GetPixelsDelegateGrayscale delegate;
|
||||
delegate.init(m_bgColor, m_matrix);
|
||||
|
||||
for (; x<x2; ++x, ++src_address, ++dst_address) {
|
||||
if (filterMgr->skipPixel())
|
||||
continue;
|
||||
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint16_t) {
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<GrayscaleTraits>(src, x, y, 3, 3, 1, 1, m_tiledMode, delegate);
|
||||
|
||||
|
|
@ -173,19 +156,14 @@ void OutlineFilter::applyToGrayscale(FilterManager* filterMgr)
|
|||
|
||||
*dst_address = c;
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void OutlineFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
const uint8_t* src_address = (uint8_t*)filterMgr->getSourceAddress();
|
||||
uint8_t* dst_address = (uint8_t*)filterMgr->getDestinationAddress();
|
||||
const Palette* pal = filterMgr->getIndexedData()->getPalette();
|
||||
const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
|
||||
int x = filterMgr->x();
|
||||
const int x2 = x+filterMgr->getWidth();
|
||||
const int y = filterMgr->y();
|
||||
Target target = filterMgr->getTarget();
|
||||
int r, g, b, a, n;
|
||||
color_t c;
|
||||
bool isTransparent;
|
||||
|
|
@ -193,10 +171,7 @@ void OutlineFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
GetPixelsDelegateIndexed delegate(pal);
|
||||
delegate.init(m_bgColor, m_matrix);
|
||||
|
||||
for (; x<x2; ++x, ++src_address, ++dst_address) {
|
||||
if (filterMgr->skipPixel())
|
||||
continue;
|
||||
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint8_t) {
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<IndexedTraits>(src, x, y, 3, 3, 1, 1, m_tiledMode, delegate);
|
||||
|
||||
|
|
@ -228,6 +203,7 @@ void OutlineFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
|
||||
*dst_address = c;
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
} // namespace filters
|
||||
|
|
|
|||
|
|
@ -49,14 +49,10 @@ const char* ReplaceColorFilter::getName()
|
|||
|
||||
void ReplaceColorFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
const uint32_t* src_address = (uint32_t*)filterMgr->getSourceAddress();
|
||||
uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
int from_r, from_g, from_b, from_a;
|
||||
int src_r, src_g, src_b, src_a;
|
||||
int to_r, to_g, to_b, to_a;
|
||||
int x, c;
|
||||
int c;
|
||||
|
||||
from_r = rgba_getr(m_from);
|
||||
from_g = rgba_getg(m_from);
|
||||
|
|
@ -67,14 +63,8 @@ void ReplaceColorFilter::applyToRgba(FilterManager* filterMgr)
|
|||
to_b = rgba_getb(m_to);
|
||||
to_a = rgba_geta(m_to);
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint32_t) {
|
||||
c = *src_address;
|
||||
src_r = rgba_getr(c);
|
||||
src_g = rgba_getg(c);
|
||||
src_b = rgba_getb(c);
|
||||
|
|
@ -89,41 +79,32 @@ void ReplaceColorFilter::applyToRgba(FilterManager* filterMgr)
|
|||
(ABS(src_g-from_g) <= m_tolerance) &&
|
||||
(ABS(src_b-from_b) <= m_tolerance) &&
|
||||
(ABS(src_a-from_a) <= m_tolerance)) {
|
||||
*(dst_address++) = rgba(
|
||||
*dst_address = rgba(
|
||||
(target & TARGET_RED_CHANNEL ? to_r: src_r),
|
||||
(target & TARGET_GREEN_CHANNEL ? to_g: src_g),
|
||||
(target & TARGET_BLUE_CHANNEL ? to_b: src_b),
|
||||
(target & TARGET_ALPHA_CHANNEL ? to_a: src_a));
|
||||
}
|
||||
else
|
||||
*(dst_address++) = c;
|
||||
*dst_address = c;
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void ReplaceColorFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
const uint16_t* src_address = (uint16_t*)filterMgr->getSourceAddress();
|
||||
uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
int from_v, from_a;
|
||||
int src_v, src_a;
|
||||
int to_v, to_a;
|
||||
int x, c;
|
||||
int c;
|
||||
|
||||
from_v = graya_getv(m_from);
|
||||
from_a = graya_geta(m_from);
|
||||
to_v = graya_getv(m_to);
|
||||
to_a = graya_geta(m_to);
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint16_t) {
|
||||
c = *src_address;
|
||||
src_v = graya_getv(c);
|
||||
src_a = graya_geta(c);
|
||||
|
||||
|
|
@ -132,27 +113,24 @@ void ReplaceColorFilter::applyToGrayscale(FilterManager* filterMgr)
|
|||
|
||||
if ((ABS(src_v-from_v) <= m_tolerance) &&
|
||||
(ABS(src_a-from_a) <= m_tolerance)) {
|
||||
*(dst_address++) = graya(
|
||||
*dst_address = graya(
|
||||
(target & TARGET_GRAY_CHANNEL ? to_v: src_v),
|
||||
(target & TARGET_ALPHA_CHANNEL ? to_a: src_a));
|
||||
}
|
||||
else
|
||||
*(dst_address++) = c;
|
||||
*dst_address = c;
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
void ReplaceColorFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
const uint8_t* src_address = (uint8_t*)filterMgr->getSourceAddress();
|
||||
uint8_t* dst_address = (uint8_t*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
const Palette* pal = filterMgr->getIndexedData()->getPalette();
|
||||
const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
|
||||
int from_r, from_g, from_b, from_a;
|
||||
int src_r, src_g, src_b, src_a;
|
||||
int to_r, to_g, to_b, to_a;
|
||||
int x, c;
|
||||
int c;
|
||||
|
||||
c = pal->getEntry(m_from);
|
||||
from_r = rgba_getr(c);
|
||||
|
|
@ -166,20 +144,14 @@ void ReplaceColorFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
to_b = rgba_getb(c);
|
||||
to_a = rgba_geta(c);
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
FILTER_LOOP_THROUGH_ROW_BEGIN(uint8_t) {
|
||||
c = *src_address;
|
||||
|
||||
if (target & TARGET_INDEX_CHANNEL) {
|
||||
if (ABS(c-m_from) <= m_tolerance)
|
||||
*(dst_address++) = m_to;
|
||||
*dst_address = m_to;
|
||||
else
|
||||
*(dst_address++) = c;
|
||||
*dst_address = c;
|
||||
}
|
||||
else {
|
||||
src_r = rgba_getr(pal->getEntry(c));
|
||||
|
|
@ -196,16 +168,17 @@ void ReplaceColorFilter::applyToIndexed(FilterManager* filterMgr)
|
|||
(ABS(src_g-from_g) <= m_tolerance) &&
|
||||
(ABS(src_b-from_b) <= m_tolerance) &&
|
||||
(ABS(src_a-from_a) <= m_tolerance)) {
|
||||
*(dst_address++) = rgbmap->mapColor(
|
||||
*dst_address = rgbmap->mapColor(
|
||||
(target & TARGET_RED_CHANNEL ? to_r: src_r),
|
||||
(target & TARGET_GREEN_CHANNEL ? to_g: src_g),
|
||||
(target & TARGET_BLUE_CHANNEL ? to_b: src_b),
|
||||
(target & TARGET_ALPHA_CHANNEL ? to_a: src_a));
|
||||
}
|
||||
else
|
||||
*(dst_address++) = c;
|
||||
*dst_address = c;
|
||||
}
|
||||
}
|
||||
FILTER_LOOP_THROUGH_ROW_END()
|
||||
}
|
||||
|
||||
} // namespace filters
|
||||
|
|
|
|||
Loading…
Reference in New Issue