41#define CLAMP( n, min, max ) {if( n < min ) n=min; else if( n > max ) n = max;}
47 m_wxh = aXsize * aYsize;
86 case IMAGE_WRAP::CLAMP:
87 x = ( x < 0 ) ? 0 : x;
89 y = ( y < 0 ) ? 0 : y;
93 case IMAGE_WRAP::WRAP:
94 x = ( x < 0 ) ? ( (
m_width - 1 ) + x ) : x;
96 y = ( y < 0 ) ? ( (
m_height - 1 ) + y ) : y;
104 if( ( x < 0 ) || ( x >= (int)
m_width ) || ( y < 0 ) || ( y >= (
int)
m_height ) )
116 Hline( aCx - aX, aCx + aX, aCy + aY, aValue );
117 Hline( aCx - aX, aCx + aX, aCy - aY, aValue );
118 Hline( aCx - aY, aCx + aY, aCy + aX, aValue );
119 Hline( aCx - aY, aCx + aY, aCy - aX, aValue );
139void IMAGE::Hline(
int aXStart,
int aXEnd,
int aY,
unsigned char aValue )
141 if( ( aY < 0 ) || ( aY >= (
int)
m_height ) || ( ( aXStart < 0 ) && ( aXEnd < 0 ) )
142 || ( ( aXStart >= (
int)
m_width ) && ( aXEnd >= (
int)
m_width ) ) )
145 if( aXStart > aXEnd )
161 unsigned char* pixelPtrEnd = pixelPtr + (
unsigned int) ( ( aXEnd - aXStart ) + 1 );
163 while( pixelPtr < pixelPtrEnd )
177 int xChange = 1 - 2 * aRadius;
185 radiusError += yChange;
188 if( ( 2 * radiusError + xChange ) > 0 )
191 radiusError += xChange;
200 for(
unsigned int it = 0; it <
m_wxh; it++ )
209 if( aOperation == IMAGE_OP::RAW )
211 if( aImgA ==
nullptr )
216 if( ( aImgA ==
nullptr ) || ( aImgB ==
nullptr ) )
227 for(
unsigned int it = 0;it <
m_wxh; it++ )
233 aV = (aV > 255)?255:aV;
240 for(
unsigned int it = 0;it <
m_wxh; it++ )
253 for(
unsigned int it = 0;it <
m_wxh; it++ )
263 for(
unsigned int it = 0;it <
m_wxh; it++ )
269 (
unsigned char) ( ( ( (
float) aV / 255.0f ) * ( (
float) bV / 255.0f ) ) * 255 );
274 for(
unsigned int it = 0;it <
m_wxh; it++ )
281 for(
unsigned int it = 0;it <
m_wxh; it++ )
288 for(
unsigned int it = 0;it <
m_wxh; it++ )
294 case IMAGE_OP::BLEND50:
295 for(
unsigned int it = 0;it <
m_wxh; it++ )
305 for(
unsigned int it = 0;it <
m_wxh; it++ )
315 for(
unsigned int it = 0;it <
m_wxh; it++ )
337 { { 0, -1, -1, -1, 0},
339 {-1, -4, 13, -4, -1},
385 { {-1, -1, -1, -1, 0},
397 { {-1, -1, -1, -1, 0},
409 { {-1, -1, -1, -1, -1},
449 {-1, -2, -4, -2, -1},
481 std::atomic<size_t> nextRow( 0 );
482 std::atomic<size_t> threadsFinished( 0 );
484 size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
486 for(
size_t ii = 0; ii < parallelThreadCount; ++ii )
488 std::thread t = std::thread( [&]()
490 for(
size_t iy = nextRow.fetch_add( 1 ); iy <
m_height; iy = nextRow.fetch_add( 1 ) )
492 for( size_t ix = 0; ix < m_width; ix++ )
496 for( size_t sy = 0; sy < 5; sy++ )
498 for( size_t sx = 0; sx < 5; sx++ )
500 int factor = filter.kernel[sx][sy];
501 unsigned char pixelv = aInImg->Getpixel( ix + sx - 2, iy + sy - 2 );
503 v += pixelv * factor;
512 m_pixels[ix + iy * m_width] = v;
522 while( threadsFinished < parallelThreadCount )
523 std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
536 const unsigned int radiusSquared = aRadius * aRadius;
538 const unsigned int xCenter =
m_width / 2;
539 const unsigned int yCenter =
m_height / 2;
541 for(
size_t iy = 0; iy <
m_height; iy++ )
543 int yc = iy - yCenter;
545 unsigned int ycsq = yc * yc;
547 for(
size_t ix = 0; ix <
m_width; ix++ )
549 int xc = ix - xCenter;
551 unsigned int xcsq = xc * xc;
553 if( ( xcsq + ycsq ) < radiusSquared )
555 const unsigned int offset = ix + iy *
m_width;
564 for(
size_t sy = 0; sy < 5; sy++ )
566 for(
size_t sx = 0; sx < 5; sx++ )
568 int factor =
filter.kernel[sx][sy];
569 unsigned char pixelv = aInImg->
Getpixel( ix + sx - 2, iy + sy - 2 );
571 v += pixelv * factor;
587 for(
unsigned int i = 0; i <
m_wxh; i++ )
589 int v = aNormalizedFloatArray[i] * 255;
void DBG_SaveBuffer(const wxString &aFileName, const unsigned char *aInBuffer, unsigned int aXSize, unsigned int aYSize)
Manage an 8-bit channel image.
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.
@ CLAMP
Coords are clamped to image size.
IMAGE_FILTER
Filter type enumeration.
IMAGE_OP
Image operation type.
5x5 Filter struct parameters