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:
David Capello 2023-05-15 13:23:24 -03:00
parent 87075296ed
commit 59f6b78e4f
12 changed files with 166 additions and 337 deletions

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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