37#define CLAMP( n, min, max ) {if( n < min ) n=min; else if( n > max ) n = max;}
43 m_wxh = aXsize * aYsize;
83 x = ( x < 0 ) ? 0 : x;
85 y = ( y < 0 ) ? 0 : y;
90 x = ( x < 0 ) ? ( (
m_width - 1 ) + x ) : x;
92 y = ( y < 0 ) ? ( (
m_height - 1 ) + y ) : y;
100 if( ( x < 0 ) || ( x >= (
int)
m_width ) || ( y < 0 ) || ( y >= (
int)
m_height ) )
112 Hline( aCx - aX, aCx + aX, aCy + aY, aValue );
113 Hline( aCx - aX, aCx + aX, aCy - aY, aValue );
114 Hline( aCx - aY, aCx + aY, aCy + aX, aValue );
115 Hline( aCx - aY, aCx + aY, aCy - aX, aValue );
135void IMAGE::Hline(
int aXStart,
int aXEnd,
int aY,
unsigned char aValue )
137 if( ( aY < 0 ) || ( aY >= (
int)
m_height ) || ( ( aXStart < 0 ) && ( aXEnd < 0 ) )
138 || ( ( aXStart >= (
int)
m_width ) && ( aXEnd >= (
int)
m_width ) ) )
141 if( aXStart > aXEnd )
157 unsigned char* pixelPtrEnd = pixelPtr + (
unsigned int) ( ( aXEnd - aXStart ) + 1 );
159 while( pixelPtr < pixelPtrEnd )
173 int xChange = 1 - 2 * aRadius;
181 radiusError += yChange;
184 if( ( 2 * radiusError + xChange ) > 0 )
187 radiusError += xChange;
196 for(
unsigned int it = 0; it <
m_wxh; it++ )
207 if( aImgA ==
nullptr )
212 if( ( aImgA ==
nullptr ) || ( aImgB ==
nullptr ) )
223 for(
unsigned int it = 0;it <
m_wxh; it++ )
229 aV = (aV > 255)?255:aV;
236 for(
unsigned int it = 0;it <
m_wxh; it++ )
249 for(
unsigned int it = 0;it <
m_wxh; it++ )
259 for(
unsigned int it = 0;it <
m_wxh; it++ )
265 (
unsigned char) ( ( ( (
float) aV / 255.0f ) * ( (
float) bV / 255.0f ) ) * 255 );
270 for(
unsigned int it = 0;it <
m_wxh; it++ )
277 for(
unsigned int it = 0;it <
m_wxh; it++ )
284 for(
unsigned int it = 0;it <
m_wxh; it++ )
291 for(
unsigned int it = 0;it <
m_wxh; it++ )
301 for(
unsigned int it = 0;it <
m_wxh; it++ )
311 for(
unsigned int it = 0;it <
m_wxh; it++ )
333 { { 0, -1, -1, -1, 0},
335 {-1, -4, 13, -4, -1},
381 { {-1, -1, -1, -1, 0},
393 { {-1, -1, -1, -1, 0},
405 { {-1, -1, -1, -1, -1},
445 {-1, -2, -4, -2, -1},
477 std::atomic<size_t> nextRow( 0 );
478 std::atomic<size_t> threadsFinished( 0 );
480 size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
482 for(
size_t ii = 0; ii < parallelThreadCount; ++ii )
484 std::thread t = std::thread( [&]()
486 for(
size_t iy = nextRow.fetch_add( 1 ); iy <
m_height; iy = nextRow.fetch_add( 1 ) )
488 for(
size_t ix = 0; ix <
m_width; ix++ )
492 for(
size_t sy = 0; sy < 5; sy++ )
494 for(
size_t sx = 0; sx < 5; sx++ )
496 int factor =
filter.kernel[sx][sy];
497 unsigned char pixelv = aInImg->
Getpixel( ix + sx - 2, iy + sy - 2 );
499 v += pixelv * factor;
518 while( threadsFinished < parallelThreadCount )
519 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
532 const unsigned int radiusSquared = aRadius * aRadius;
534 const unsigned int xCenter =
m_width / 2;
535 const unsigned int yCenter =
m_height / 2;
537 for(
size_t iy = 0; iy <
m_height; iy++ )
539 int yc = iy - yCenter;
541 unsigned int ycsq = yc * yc;
543 for(
size_t ix = 0; ix <
m_width; ix++ )
545 int xc = ix - xCenter;
547 unsigned int xcsq = xc * xc;
549 if( ( xcsq + ycsq ) < radiusSquared )
551 const unsigned int offset = ix + iy *
m_width;
560 for(
size_t sy = 0; sy < 5; sy++ )
562 for(
size_t sx = 0; sx < 5; sx++ )
564 int factor =
filter.kernel[sx][sy];
565 unsigned char pixelv = aInImg->
Getpixel( ix + sx - 2, iy + sy - 2 );
567 v += pixelv * factor;
583 for(
unsigned int i = 0; i <
m_wxh; i++ )
585 int v = aNormalizedFloatArray[i] * 255;
void DBG_SaveBuffer(const wxString &aFileName, const unsigned char *aInBuffer, unsigned int aXSize, unsigned int aYSize)
IMAGE_WRAP m_wraping
current wrapping type
void CircleFilled(int aCx, int aCy, int aRadius, unsigned char aValue)
void EfxFilter(IMAGE *aInImg, IMAGE_FILTER aFilterType)
Apply a filter to the input image and store it in the image class.
void CopyFull(const IMAGE *aImgA, const IMAGE *aImgB, IMAGE_OP aOperation)
Perform a copy operation based on aOperation type.
unsigned int m_width
width of the image
void SaveAsPNG(const wxString &aFileName) const
Save image buffer to a PNG file into the working folder.
void EfxFilter_SkipCenter(IMAGE *aInImg, IMAGE_FILTER aFilterType, unsigned int aRadius)
Apply a filter to the input image and store it in the image class.
unsigned char * GetBuffer() const
Get the image buffer pointer.
void Setpixel(int aX, int aY, unsigned char aValue)
Set a value in a pixel position, position is clamped in accordance with the current clamp settings.
unsigned int m_height
height of the image
unsigned char * m_pixels
buffer to store the image 8bit-channel
void Invert()
Invert the values of this image <- (255 - this)
void SetPixelsFromNormalizedFloat(const float *aNormalizedFloatArray)
Set the current channel from a float normalized (0.0 - 1.0) buffer.
IMAGE(unsigned int aXsize, unsigned int aYsize)
Construct a IMAGE based on image size.
unsigned int GetHeight() const
void plot8CircleLines(int aCx, int aCy, int aX, int aY, unsigned char aValue)
void Hline(int aXStart, int aXEnd, int aY, unsigned char aValue)
Draw a horizontal line.
unsigned char Getpixel(int aX, int aY) const
Get the pixel value from pixel position, position is clamped in accord with the current clamp setting...
bool wrapCoords(int *aXo, int *aYo) const
Calculate the coordinates points in accord with the current clamping settings.
unsigned int GetWidth() const
unsigned int m_wxh
width * height precalc value
static const S_FILTER FILTERS[]
one 8bit-channel image definition.
@ ZERO
Coords that wraps are not evaluated.
@ WRAP
Coords are wrapped around.
@ CLAMP
Coords are clamped to image size.
IMAGE_FILTER
Filter type enumeration.
IMAGE_OP
Image operation type.
5x5 Filter struct parameters