using BBIWARG.Utility;
using Emgu.CV;
using Emgu.CV.Structure;
using System;
using System.Collections.Generic;
using System.Drawing;
namespace BBIWARG.Output
{
///
/// An which provides additional drawing functions.
///
internal class OutputImage : Image
{
///
/// Creates an OutputImage.
///
/// image width
/// image height
public OutputImage(int width, int height)
: base(width, height)
{
}
///
/// Creates an OutputImage.
///
/// image size
public OutputImage(ImageSize size)
: base(size.Width, size.Height)
{
}
///
/// Draws a border around the image.
///
/// color used to draw the border
public void drawBorder(Color color)
{
drawRectangle(new Rectangle(0, 0, Width, Height), color);
}
///
/// Draws a contour.
///
/// contour to draw
/// color used to draw the contour
/// thickness of the contour
public void drawContour(Contour contour, Color color, int thickness = 1)
{
Draw(contour, new Rgb(color), thickness);
}
///
/// Draws a convexity defect.
///
/// the defect to draw
/// color used to draw the points of the defect
/// color used to draw the lines of the defect
public void drawDefect(ConvexityDefect defect, Color pointColor, Color lineColor)
{
drawLineSegment(new Utility.LineSegment2D(defect.OuterShort, defect.Inner), lineColor);
drawLineSegment(new Utility.LineSegment2D(defect.OuterLong, defect.Inner), lineColor);
fillCircle(defect.Inner, 2, pointColor);
fillCircle(defect.OuterShort, 2, pointColor);
fillCircle(defect.OuterLong, 2, pointColor);
}
///
/// Draws a grayscale image into channels of the image.
///
/// the image to draw
/// if a color component is != 0 the corresponding image channel is drawn to and image is scaled by (color component value / 255)
public void drawImage(Image image, Color color)
{
if (color.R != 0)
{
if (color.R != byte.MaxValue)
this[0] = this[0].Or(image.Mul((float)color.R / byte.MaxValue));
else
this[0] = this[0].Or(image);
}
if (color.G != 0)
{
if (color.G != byte.MaxValue)
this[1] = this[1].Or(image.Mul((float)color.G / byte.MaxValue));
else
this[1] = this[1].Or(image);
}
if (color.B != 0)
{
if (color.B != byte.MaxValue)
this[2] = this[2].Or(image.Mul((float)color.B / byte.MaxValue));
else
this[2] = this[2].Or(image);
}
}
///
/// Draws a line segment.
///
/// line segment to draw
/// color used to draw the line segment
/// thickness of the line segment
public void drawLineSegment(Utility.LineSegment2D lineSegment, Color color, int thickness = 1)
{
Draw(new Emgu.CV.Structure.LineSegment2D(lineSegment.P1, lineSegment.P2), new Rgb(color), thickness);
}
///
/// Colors a pixel.
///
/// position of the pixel
/// new color for pixel
public void drawPixel(Point position, Color color)
{
Data[position.Y, position.X, 0] = color.R;
Data[position.Y, position.X, 0] = color.G;
Data[position.Y, position.X, 0] = color.B;
}
///
/// Draws a grid into a quadrangle.
///
/// the quadrangle
/// color used to draw the border lines
/// color used to draw the grid
/// number of rows in the grid
/// number of columns in the grid
public void drawQuadrangleGrid(Quadrangle quad, Color borderColor, Color gridColor, int numRows, int numCols)
{
Vector2D a = quad.TopLeft;
Vector2D b = quad.TopRight;
Vector2D c = quad.BottomRight;
Vector2D d = quad.BottomLeft;
Vector2D relAB = (b - a) / numCols;
Vector2D relDC = (c - d) / numCols;
Vector2D relBC = (c - b) / numRows;
Vector2D relAD = (d - a) / numRows;
for (int i = 1; i < numCols; i++)
{
drawLineSegment(new Utility.LineSegment2D(a + i * relAB, d + i * relDC), gridColor);
}
for (int i = 1; i < numRows; i++)
{
drawLineSegment(new Utility.LineSegment2D(a + i * relAD, b + i * relBC), gridColor);
}
drawLineSegment(new Utility.LineSegment2D(a, b), borderColor);
drawLineSegment(new Utility.LineSegment2D(b, c), borderColor);
drawLineSegment(new Utility.LineSegment2D(c, d), borderColor);
drawLineSegment(new Utility.LineSegment2D(d, a), borderColor);
}
///
/// Draws a unfilled rectangle.
///
/// the rectangle
/// color used to raw the rectangle
/// thickness of the rectangle
public void drawRectangle(Rectangle rect, Color color, int thichness = 0)
{
Draw(rect, new Rgb(color), thichness);
}
///
/// Draws text.
///
/// top left corner to draw the text at
/// the text to draw
/// color used to draw the text
public void drawText(Point position, String text, Color color)
{
MCvFont font = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_PLAIN, 1, 1);
Draw(text, ref font, position, new Rgb(color));
}
///
/// Draws a touch gesture as the current point and a faded line.
///
/// touch positions
/// scale used to transform given positions into positions in the image
/// opacity of the faded lines
public void drawTouchGesture(List positions, Vector2D scale, float opacity = 1)
{
int numPositions = positions.Count;
Color lineColor = Parameters.TouchEventVisualizerLineColor;
Color pointColor = Parameters.TouchEventVisualizerPointColor;
Color lineColorFaded = Color.FromArgb((int)(opacity * lineColor.R), (int)(opacity * lineColor.G), (int)(opacity * lineColor.B));
Color pointColorFaded = Color.FromArgb((int)(opacity * pointColor.R), (int)(opacity * pointColor.G), (int)(opacity * pointColor.B));
for (int i = 1; i < numPositions; i++)
{
drawLineSegment(new Utility.LineSegment2D(positions[i - 1].scale(scale), positions[i].scale(scale)), lineColorFaded);
}
Vector2D lastPos = positions[numPositions - 1].scale(scale);
fillCircle(lastPos, 3, pointColorFaded);
}
///
/// Draws a filled circle.
///
/// center of the circle
/// radius of the circle
/// color used to draw the circle
public void fillCircle(Point position, float radius, Color color)
{
Draw(new CircleF(position, radius), new Rgb(color), 0);
}
///
/// Draws a filled rectangle.
///
/// the rectangle
/// color used to fill the rectangle
public void fillRectangle(Rectangle rect, Color color)
{
Draw(rect, new Rgb(color), -1);
}
///
/// Returns the color at a position.
///
/// x coordinate of the position
/// y coordinate of the position
/// color at position (x, y)
public Color getColorAt(int x, int y)
{
byte red = Data[y, x, 0];
byte green = Data[y, x, 1];
byte blue = Data[y, x, 2];
return Color.FromArgb(red, green, blue);
}
}
}