1// Aseprite
2// Copyright (C) 2001-2015 David Capello
3//
4// This program is distributed under the terms of
5// the End-User License Agreement for Aseprite.
6
7#ifndef FILTERS_NEIGHBORING_PIXELS_H_INCLUDED
8#define FILTERS_NEIGHBORING_PIXELS_H_INCLUDED
9#pragma once
10
11#include "filters/tiled_mode.h"
12#include "doc/image.h"
13#include "doc/image_traits.h"
14
15#include <vector>
16
17namespace filters {
18 using namespace doc;
19
20 // Calls the specified "delegate" for all neighboring pixels in a 2D
21 // (width*height) matrix located in (x,y) where its center is the
22 // (centerX,centerY) element of the matrix.
23 template<typename Traits, typename Delegate>
24 inline void get_neighboring_pixels(const doc::Image* sourceImage, int x, int y,
25 int width, int height,
26 int centerX, int centerY,
27 TiledMode tiledMode,
28 Delegate& delegate)
29 {
30 // Y position to get pixel.
31 int getx, gety = y - centerY;
32 int addx, addy = 0;
33 if (gety < 0) {
34 if (int(tiledMode) & int(TiledMode::Y_AXIS))
35 gety = sourceImage->height() - (-(gety+1) % sourceImage->height()) - 1;
36 else {
37 addy = -gety;
38 gety = 0;
39 }
40 }
41 else if (gety >= sourceImage->height()) {
42 if (int(tiledMode) & int(TiledMode::Y_AXIS))
43 gety = gety % sourceImage->height();
44 else
45 gety = sourceImage->height()-1;
46 }
47
48 for (int dy=0; dy<height; ++dy) {
49 // X position to get pixel.
50 getx = x - centerX;
51 addx = 0;
52 if (getx < 0) {
53 if (int(tiledMode) & int(TiledMode::X_AXIS))
54 getx = sourceImage->width() - (-(getx+1) % sourceImage->width()) - 1;
55 else {
56 addx = -getx;
57 getx = 0;
58 }
59 }
60 else if (getx >= sourceImage->width()) {
61 if (int(tiledMode) & int(TiledMode::X_AXIS))
62 getx = getx % sourceImage->width();
63 else
64 getx = sourceImage->width()-1;
65 }
66
67 typename Traits::const_address_t srcAddress =
68 reinterpret_cast<typename Traits::const_address_t>(sourceImage->getPixelAddress(getx, gety));
69
70 for (int dx=0; dx<width; dx++) {
71 // Call the delegate for each pixel value.
72 delegate(*srcAddress);
73
74 // Update X position to get pixel.
75 if (getx < sourceImage->width()-1) {
76 ++getx;
77 if (addx == 0)
78 ++srcAddress;
79 else
80 --addx;
81 }
82 else if (int(tiledMode) & int(TiledMode::X_AXIS)) {
83 getx = 0;
84 srcAddress =
85 reinterpret_cast<typename Traits::const_address_t>(sourceImage->getPixelAddress(getx, gety));
86 }
87 }
88
89 // Update Y position to get pixel
90 if (gety < sourceImage->height()-1) {
91 if (addy == 0)
92 ++gety;
93 else
94 --addy;
95 }
96 else if (int(tiledMode) & int(TiledMode::Y_AXIS))
97 gety = 0;
98 }
99 }
100
101} // namespace filters
102
103#endif
104