67 #ifndef _graphicsproceduraledgedetectionmodifier_cpp
68 #define _graphicsproceduraledgedetectionmodifier_cpp
70 #include "Graphics/Procedural/Texture/edgedetectionmodifier.h"
71 #include "Graphics/Procedural/Texture/solidgenerator.h"
72 #include "Graphics/Procedural/Texture/blurmodifier.h"
74 #include "MathTools/mathtools.h"
86 EdgeDetectionSigma(92)
100 for(
Integer Y = 0 ; Y < TargetHeight ; ++Y )
102 for(
Integer X = 0 ; X < TargetWidth ; ++X )
104 Real PixelAlpha = Buffer.
GetAlphaReal(static_cast<Whole>(X),static_cast<Whole>(Y));
106 Vector3 CenterColour = Block[4];
107 Vector3 Difference(0.0,0.0,0.0);
108 for(
Integer Row = 0 ; Row < 3 ; ++Row )
110 for(
Integer Column = 0 ; Column < 3 ; ++Column )
112 if( Row != 1 || Column != 1 ) {
113 Vector3 Temp = CenterColour - Block[Row * 3 + Column];
114 if( MathTools::Abs(Temp.
X) > Difference.
X ) Difference.
X = MathTools::Abs(Temp.
X);
115 if( MathTools::Abs(Temp.
Y) > Difference.
Y ) Difference.
Y = MathTools::Abs(Temp.
Y);
116 if( MathTools::Abs(Temp.
Z) > Difference.
Z ) Difference.
Z = MathTools::Abs(Temp.
Z);
120 TempBuffer.SetPixel(static_cast<Whole>(X),static_cast<Whole>(Y),
ColourValue(Difference.
X,Difference.
Y,Difference.
Z,PixelAlpha));
135 for(
Integer Y = 0 ; Y < TargetHeight ; ++Y )
137 for(
Integer X = 0 ; X < TargetWidth ; ++X )
139 Real PixelAlpha = Buffer.
GetAlphaReal(static_cast<Whole>(X),static_cast<Whole>(Y));
141 Vector3 Difference(0.0,0.0,0.0);
144 for(
Integer Index = 0 ; Index < 3 ; ++Index )
146 Temp = Block[Index] - Block[6 + (2 - Index)];
147 if( MathTools::Abs(Temp.
X) > Difference.
X ) Difference.
X = MathTools::Abs(Temp.
X);
148 if( MathTools::Abs(Temp.
Y) > Difference.
Y ) Difference.
Y = MathTools::Abs(Temp.
Y);
149 if( MathTools::Abs(Temp.
Z) > Difference.
Z ) Difference.
Z = MathTools::Abs(Temp.
Z);
151 Temp = Block[5] - Block[3];
152 if( MathTools::Abs(Temp.
X) > Difference.
X ) Difference.
X = MathTools::Abs(Temp.
X);
153 if( MathTools::Abs(Temp.
Y) > Difference.
Y ) Difference.
Y = MathTools::Abs(Temp.
Y);
154 if( MathTools::Abs(Temp.
Z) > Difference.
Z ) Difference.
Z = MathTools::Abs(Temp.
Z);
156 TempBuffer.SetPixel(static_cast<Whole>(X),static_cast<Whole>(Y),
ColourValue(Difference.
X,Difference.
Y,Difference.
Z,PixelAlpha));
171 for(
Integer Y = 0 ; Y < TargetHeight ; ++Y )
173 for(
Integer X = 0 ; X < TargetWidth ; ++X )
175 Real PixelAlpha = Buffer.
GetAlphaReal(static_cast<Whole>(X),static_cast<Whole>(Y));
178 Vector3 Temp1 = Block[0] + ( Block[1] * 2.0 ) + Block[2] - Block[6] - ( Block[7] * 2.0 ) - Block[8];
179 Temp1 =
Vector3(MathTools::Abs(Temp1.
X),MathTools::Abs(Temp1.
Y),MathTools::Abs(Temp1.
Z));
180 Vector3 Temp2 = Block[2] + ( Block[5] * 2.0 ) + Block[8] - Block[0] - ( Block[3] * 2.0 ) - Block[6];
181 Temp2 =
Vector3(MathTools::Abs(Temp2.
X),MathTools::Abs(Temp2.
Y),MathTools::Abs(Temp2.
Z));
182 Vector3 Difference = Temp1 + Temp2;
184 TempBuffer.SetPixel(static_cast<Whole>(X),static_cast<Whole>(Y),
ColourValue(Difference.
X,Difference.
Y,Difference.
Z,PixelAlpha));
206 Vector3 Difference =
Vector3(-std::numeric_limits<Real>::infinity(),-std::numeric_limits<Real>::infinity(),-std::numeric_limits<Real>::infinity());
207 for(
Integer Y = 0 ; Y < TargetHeight ; ++Y )
209 for(
Integer X = 0 ; X < TargetWidth ; ++X )
212 Vector3 TempVec1 = Block[2] + Block[8] - Block[0] - Block[6] + ( ( Block[5] - Block[3] ) * 2.0 );
213 Vector3 TempVec2 = Block[0] + Block[2] - Block[6] - Block[8] + ( ( Block[1] - Block[7] ) * 2.0 );
214 Gradients[Y * TargetWidth + X] =
Vector3(MathTools::Sqrt(TempVec1.
X * TempVec1.
X + TempVec2.
X * TempVec2.
X), MathTools::Sqrt(TempVec1.
Y * TempVec1.
Y + TempVec2.
Y * TempVec2.
Y), MathTools::Sqrt(TempVec1.
Z * TempVec1.
Z + TempVec2.
Z * TempVec2.
Z));
215 if( Gradients[Y * TargetWidth + X].X > Difference.
X ) Difference.
X = Gradients[Y * TargetWidth + X].X;
216 if( Gradients[Y * TargetWidth + X].Y > Difference.
Y ) Difference.
Y = Gradients[Y * TargetWidth + X].Y;
217 if( Gradients[Y * TargetWidth + X].Z > Difference.
Z ) Difference.
Z = Gradients[Y * TargetWidth + X].Z;
218 Orientations[Y * TargetWidth + X].Zero();
219 if( TempVec1.
X == 0.0 ) {
220 Orientations[Y * TargetWidth + X].X = ( TempVec2.
X == 0.0 ) ? 0.0 : 90.0;
222 Div = TempVec2.
X / TempVec1.
X;
224 Orientations[Y * TargetWidth + X].X = 180.0 - ( MathTools::ATan(-Div) * MathTools::GetRadToDegMultiplier() );
226 Orientations[Y * TargetWidth + X].X = ( MathTools::ATan(Div) * MathTools::GetRadToDegMultiplier() );
229 if( Orientations[Y * TargetWidth + X].X < 22.5 ) {
230 Orientations[Y * TargetWidth + X].X = 0.0;
231 }
else if( Orientations[Y * TargetWidth + X].X < 67.5 ) {
232 Orientations[Y * TargetWidth + X].X = 45.0;
233 }
else if( Orientations[Y * TargetWidth + X].X < 112.5 ) {
234 Orientations[Y * TargetWidth + X].X = 90.0;
235 }
else if( Orientations[Y * TargetWidth + X].X < 157.5 ) {
236 Orientations[Y * TargetWidth + X].X = 135.0;
238 Orientations[Y * TargetWidth + X].X = 0.0;
241 if( TempVec1.
Y == 0.0 ) {
242 Orientations[Y * TargetWidth + X].Y = ( TempVec2.
Y == 0.0 ) ? 0.0 : 90.0;
244 Div = TempVec2.
Y / TempVec1.
Y;
246 Orientations[Y * TargetWidth + X].Y = 180.0 - ( MathTools::ATan(-Div) * MathTools::GetRadToDegMultiplier() );
248 Orientations[Y * TargetWidth + X].Y = ( MathTools::ATan(Div) * MathTools::GetRadToDegMultiplier() );
251 if( Orientations[Y * TargetWidth + X].Y < 22.5 ) {
252 Orientations[Y * TargetWidth + X].Y = 0.0;
253 }
else if( Orientations[Y * TargetWidth + X].Y < 67.5 ) {
254 Orientations[Y * TargetWidth + X].Y = 45.0;
255 }
else if( Orientations[Y * TargetWidth + X].Y < 112.5 ) {
256 Orientations[Y * TargetWidth + X].Y = 90.0;
257 }
else if( Orientations[Y * TargetWidth + X].Y < 157.5 ) {
258 Orientations[Y * TargetWidth + X].Y = 135.0;
260 Orientations[Y * TargetWidth + X].Y = 0.0;
263 if( TempVec1.
Z == 0.0 ) {
264 Orientations[Y * TargetWidth + X].Z = ( TempVec2.
Z == 0.0 ) ? 0.0 : 90.0;
266 Div = TempVec2.
Z / TempVec1.
Z;
268 Orientations[Y * TargetWidth + X].Z = 180.0 - ( MathTools::ATan(-Div) * MathTools::GetRadToDegMultiplier() );
270 Orientations[Y * TargetWidth + X].Z = ( MathTools::ATan(Div) * MathTools::GetRadToDegMultiplier() );
273 if( Orientations[Y * TargetWidth + X].Z < 22.5 ) {
274 Orientations[Y * TargetWidth + X].Z = 0.0;
275 }
else if( Orientations[Y * TargetWidth + X].Z < 67.5 ) {
276 Orientations[Y * TargetWidth + X].Z = 45.0;
277 }
else if( Orientations[Y * TargetWidth + X].Z < 112.5 ) {
278 Orientations[Y * TargetWidth + X].Z = 90.0;
279 }
else if( Orientations[Y * TargetWidth + X].Z < 157.5 ) {
280 Orientations[Y * TargetWidth + X].Z = 135.0;
282 Orientations[Y * TargetWidth + X].Z = 0.0;
289 for(
Integer Y = 1 ; Y < ( TargetHeight - 1 ) ; ++Y )
291 for(
Integer X = 1 ; X < ( TargetWidth - 1 ) ; ++X )
293 Div = Gradients[Y * TargetWidth + X].X / Difference.
X;
294 switch( static_cast<Integer>( Orientations[Y * TargetWidth + X].X ) )
299 if( ( Gradients[Y * TargetWidth + X].X < Gradients[Y * TargetWidth + (X - 1)].X ) || ( Gradients[Y * TargetWidth + X].X < Gradients[Y * TargetWidth + (X + 1)].X ) ) {
306 if( ( Gradients[Y * TargetWidth + X].X < Gradients[(Y + 1) * TargetWidth + (X - 1)].X ) || ( Gradients[Y * TargetWidth + X].X < Gradients[(Y - 1) * TargetWidth + (X + 1)].X ) ) {
313 if( ( Gradients[Y * TargetWidth + X].X < Gradients[(Y + 1) * TargetWidth + X].X ) || ( Gradients[Y * TargetWidth + X].X < Gradients[(Y - 1) * TargetWidth + X].X ) ) {
320 if( ( Gradients[Y * TargetWidth + X].X < Gradients[(Y + 1) * TargetWidth + (X + 1)].X ) || ( Gradients[Y * TargetWidth + X].X < Gradients[(Y - 1) * TargetWidth + (X - 1)].X ) ) {
326 TempBuffer.SetRedReal( static_cast<Whole>(X), static_cast<Whole>(Y), Div );
327 Div = Gradients[Y * TargetWidth + X].Y / Difference.
Y;
328 switch( static_cast<Integer>( Orientations[Y * TargetWidth + X].Y ) )
333 if( ( Gradients[Y * TargetWidth + X].Y < Gradients[Y * TargetWidth + (X - 1)].Y ) || ( Gradients[Y * TargetWidth + X].Y < Gradients[Y * TargetWidth + (X + 1)].Y ) ) {
340 if( ( Gradients[Y * TargetWidth + X].Y < Gradients[(Y + 1) * TargetWidth + (X - 1)].Y ) || ( Gradients[Y * TargetWidth + X].Y < Gradients[(Y - 1) * TargetWidth + (X + 1)].Y ) ) {
347 if( ( Gradients[Y * TargetWidth + X].Y < Gradients[(Y + 1) * TargetWidth + X].Y ) || ( Gradients[Y * TargetWidth + X].Y < Gradients[(Y - 1) * TargetWidth + X].Y ) ) {
354 if( ( Gradients[Y * TargetWidth + X].Y < Gradients[(Y + 1) * TargetWidth + (X + 1)].Y ) || ( Gradients[Y * TargetWidth + X].Y < Gradients[(Y - 1) * TargetWidth + (X - 1)].Y ) ) {
360 TempBuffer.SetGreenReal( static_cast<Whole>(X), static_cast<Whole>(Y), Div );
361 Div = Gradients[Y * TargetWidth + X].Z / Difference.
Z;
362 switch( static_cast<Integer>( Orientations[Y * TargetWidth + X].Z ) )
367 if( ( Gradients[Y * TargetWidth + X].Z < Gradients[Y * TargetWidth + (X - 1)].Z ) || ( Gradients[Y * TargetWidth + X].Z < Gradients[Y * TargetWidth + (X + 1)].Z ) ) {
374 if( ( Gradients[Y * TargetWidth + X].Z < Gradients[(Y + 1) * TargetWidth + (X - 1)].Z ) || ( Gradients[Y * TargetWidth + X].Z < Gradients[(Y - 1) * TargetWidth + (X + 1)].Z ) ) {
381 if( ( Gradients[Y * TargetWidth + X].Z < Gradients[(Y + 1) * TargetWidth + X].Z ) || ( Gradients[Y * TargetWidth + X].Z < Gradients[(Y - 1) * TargetWidth + X].Z ) ) {
388 if( (Gradients[Y * TargetWidth + X].Z < Gradients[(Y + 1) * TargetWidth + (X + 1)].Z ) || ( Gradients[Y * TargetWidth + X].Z < Gradients[(Y - 1) * TargetWidth + (X - 1)].Z ) ) {
394 TempBuffer.SetBlueReal( static_cast<Whole>(X), static_cast<Whole>(Y), Div );
401 for(
Integer Y = 1 ; Y < ( TargetHeight - 1 ) ; ++Y )
403 for(
Integer X = 1 ; X < ( TargetWidth - 1 ) ; ++X )
408 if( Pixel.
RedChannel < static_cast<Real>( this->LowerThreshold ) / 255.0 )
409 TempBuffer.SetRedReal( static_cast<Whole>(X), static_cast<Whole>(Y), 0.0 );
412 if( ( Buffer.
GetRedReal(static_cast<Whole>(X - 1),static_cast<Whole>(Y )) < MaxThreshold ) &&
413 ( Buffer.
GetRedReal(static_cast<Whole>(X + 1),static_cast<Whole>(Y )) < MaxThreshold ) &&
414 ( Buffer.
GetRedReal(static_cast<Whole>(X - 1),static_cast<Whole>(Y - 1)) < MaxThreshold ) &&
415 ( Buffer.
GetRedReal(static_cast<Whole>(X ),static_cast<Whole>(Y - 1)) < MaxThreshold ) &&
416 ( Buffer.
GetRedReal(static_cast<Whole>(X + 1),static_cast<Whole>(Y - 1)) < MaxThreshold ) &&
417 ( Buffer.
GetRedReal(static_cast<Whole>(X - 1),static_cast<Whole>(Y + 1)) < MaxThreshold ) &&
418 ( Buffer.
GetRedReal(static_cast<Whole>(X ),static_cast<Whole>(Y + 1)) < MaxThreshold ) &&
419 ( Buffer.
GetRedReal(static_cast<Whole>(X + 1),static_cast<Whole>(Y + 1)) < MaxThreshold ) )
421 TempBuffer.SetRedReal( static_cast<Whole>(X), static_cast<Whole>(Y), 0.0 );
427 if( Pixel.
GreenChannel < static_cast<Real>( this->LowerThreshold ) / 255.0 )
428 TempBuffer.SetGreenReal( static_cast<Whole>(X), static_cast<Whole>(Y), 0.0 );
431 if( ( Buffer.
GetGreenReal(static_cast<Whole>(X - 1),static_cast<Whole>(Y )) < MaxThreshold ) &&
432 ( Buffer.
GetGreenReal(static_cast<Whole>(X + 1),static_cast<Whole>(Y )) < MaxThreshold ) &&
433 ( Buffer.
GetGreenReal(static_cast<Whole>(X - 1),static_cast<Whole>(Y - 1)) < MaxThreshold ) &&
434 ( Buffer.
GetGreenReal(static_cast<Whole>(X ),static_cast<Whole>(Y - 1)) < MaxThreshold ) &&
435 ( Buffer.
GetGreenReal(static_cast<Whole>(X + 1),static_cast<Whole>(Y - 1)) < MaxThreshold ) &&
436 ( Buffer.
GetGreenReal(static_cast<Whole>(X - 1),static_cast<Whole>(Y + 1)) < MaxThreshold ) &&
437 ( Buffer.
GetGreenReal(static_cast<Whole>(X ),static_cast<Whole>(Y + 1)) < MaxThreshold ) &&
438 ( Buffer.
GetGreenReal(static_cast<Whole>(X + 1),static_cast<Whole>(Y + 1)) < MaxThreshold ) )
440 TempBuffer.SetGreenReal( static_cast<Whole>(X), static_cast<Whole>(Y), 0.0 );
446 if( Pixel.
BlueChannel < static_cast<Real>( this->LowerThreshold ) / 255.0 )
447 TempBuffer.SetBlueReal( static_cast<Whole>(X), static_cast<Whole>(Y), 0.0 );
450 if( ( Buffer.
GetBlueReal(static_cast<Whole>(X - 1),static_cast<Whole>(Y )) < MaxThreshold ) &&
451 ( Buffer.
GetBlueReal(static_cast<Whole>(X + 1),static_cast<Whole>(Y )) < MaxThreshold ) &&
452 ( Buffer.
GetBlueReal(static_cast<Whole>(X - 1),static_cast<Whole>(Y - 1)) < MaxThreshold ) &&
453 ( Buffer.
GetBlueReal(static_cast<Whole>(X ),static_cast<Whole>(Y - 1)) < MaxThreshold ) &&
454 ( Buffer.
GetBlueReal(static_cast<Whole>(X + 1),static_cast<Whole>(Y - 1)) < MaxThreshold ) &&
455 ( Buffer.
GetBlueReal(static_cast<Whole>(X - 1),static_cast<Whole>(Y + 1)) < MaxThreshold ) &&
456 ( Buffer.
GetBlueReal(static_cast<Whole>(X ),static_cast<Whole>(Y + 1)) < MaxThreshold ) &&
457 ( Buffer.
GetBlueReal(static_cast<Whole>(X + 1),static_cast<Whole>(Y + 1)) < MaxThreshold ) )
459 TempBuffer.SetBlueReal( static_cast<Whole>(X), static_cast<Whole>(Y), 0.0 );
473 for(
Integer Row = -1 ; Row < 2 ; ++Row )
475 for(
Integer Column = -1 ; Column < 2 ; ++Column )
477 Integer CurrIndex = ( Row + 1 ) * 3 + ( Column + 1 );
480 if( Row != 0 || Column != 0 ) {
481 if( ( X + Column ) < 0 || ( X + Column ) >= static_cast<Integer>( Buffer.
GetWidth() ) ) {
484 if( ( Y + Row ) < 0 || ( Y + Row ) >= static_cast<Integer>( Buffer.
GetHeight() ) ) {
488 Block[CurrIndex].SetValues( Buffer.
GetRedReal(static_cast<Whole>(X+Column),static_cast<Whole>(Y+Row)),
489 Buffer.
GetGreenReal(static_cast<Whole>(X+Column),static_cast<Whole>(Y+Row)),
490 Buffer.
GetBlueReal(static_cast<Whole>(X+Column),static_cast<Whole>(Y+Row)) );
513 {
return "EdgeDetectionModifier"; }
VectorBlock GetBlock(const Integer X, const Integer Y, TextureBuffer &Buffer) const
Gets the colours of the specified pixel and all surrounding pixels.
ColourChannelType & GetPixel(const Whole X, const Whole Y, const UInt16 Component)
Gets access to the pixel at the specified position in this buffer. the X or Y location go beyond the ...
Real X
Coordinate on the X vector.
Real Z
Coordinate on the Z vector.
Real GetBlueReal(const Whole X, const Whole Y) const
Gets the blue colour value of a specified pixel. the X or Y location go beyond the set size of this t...
Whole GetWidth() const
Get the pixel width of this texture.
Real GetAlphaReal(const Whole X, const Whole Y) const
Gets the alpha colour value of a specified pixel. the X or Y location go beyond the set size of this ...
Use the Sobel Operator algorithm to detect edges.
DetectionMode EdgeDetect
The algorithm to use to detect edges.
int Integer
A datatype used to represent any integer close to.
Real GetGreenReal(const Whole X, const Whole Y) const
Gets the green colour value of a specified pixel. the X or Y location go beyond the set size of this ...
Use the Canny multi-stage algorthm to detect edges.
UInt8 UpperThreshold
The highest value for each colour channel that will be considered valid.
virtual String GetName() const
Gets the name of this modifier.
void ProcessDifference(TextureBuffer &Buffer)
Detect edges in the provided texture by processing pixels above and below the current pixel...
virtual void Modify(TextureBuffer &Buffer)
Alters the generated pixels in a TextureBuffer.
Fills full image with given colour.
static ColourValue Black()
Creates a ColourValue representing the colour Black.
SolidGenerator & SetColour(const ColourValue &Colour)
Sets the colour of the background.
uint8_t UInt8
An 8-bit unsigned integer.
This is a simple class for holding 4 reals representing the colour any give object or lightsource can...
virtual void AddToTextureBuffer(TextureBuffer &Buffer) const
Replaces and populates the pixels as configured in this generator to a TextureBuffer.
A modifier that will attempt to reduce the sharpness of the texture.
float Real
A Datatype used to represent a real floating point number.
EdgeDetectionModifier & SetDetectionType(const DetectionMode Mode)
Sets the detection algorith to use for detecting edges.
BlurModifier & SetSigma(const UInt8 Sigma)
Sets the sigma for each each pixel to be processed.
Real GreenChannel
Value from 0.0 to 1.0 representing the amount of green present in the colour. 1.0 if very green...
std::vector< Vector3 > VectorContainer
Convenience typedef for an array of Vector3's.
void ProcessSobel(TextureBuffer &Buffer)
Detect edges using the Sobel Operator.
VectorContainer VectorBlock
Convenience typedef for returning a 3x3 matrix of Vector3's containing colour data.
UInt8 LowerThreshold
The lowest value for each colour channel that will be considered valid.
virtual ~EdgeDetectionModifier()
Class destructor.
DetectionMode
An enum describing which algorithm to use for edge detection.
A modifier that will reduce the texture to an outline of the detected edges in the texture...
Real Y
Coordinate on the Y vector.
EdgeDetectionModifier & SetEdgeDetectionSigma(const UInt8 Sigma)
Sets the sigma for the blur stage of the Canny filter.
BlurModifier & SetBlurType(const BlurType Blur)
Sets the type of bluring operation to be used.
Detect edges based on difference in colour between the pixel being processed and all surrounding pixe...
EdgeDetectionModifier & SetUpperThreshold(const UInt8 High)
Sets the upper threshold for the Canny filter.
Real GetRedReal(const Whole X, const Whole Y) const
Gets the red colour value of a specified pixel. the X or Y location go beyond the set size of this te...
void ProcessCanny(TextureBuffer &Buffer)
Detect edges using the Canny multi-stage algorithm.
A convenience buffer that stores pixel colour values of a texture to be generated.
This is used to represent a point in space, or a vector through space.
The bulk of the engine components go in this namspace.
Whole GetHeight() const
Get the pixel height of this texture.
Real BlueChannel
Value from 0.0 to 1.0 representing the amount of blue present in the colour. 1.0 if very blue...
void ProcessHomogenity(TextureBuffer &Buffer)
Detect edges in the provided texture by processing all surrounding pixels.
Real RedChannel
Value from 0.0 to 1.0 representing the amount of red present in the colour. 1.0 if very red...
Detect edges based on difference in colour between opposite surrounding pixels.
UInt8 EdgeDetectionSigma
The sigma to set for the blur step of the Canny filter.
std::string String
A datatype used to a series of characters.
EdgeDetectionModifier & SetLowerThreshold(const UInt8 Low)
Sets the lower threshold for the Canny filter.
void SetData(const TextureBuffer &Other)
Copies image data from another buffer into this buffer.
virtual void Modify(TextureBuffer &Buffer)
Alters the generated pixels in a TextureBuffer.
EdgeDetectionModifier()
Blank constructor.