Add Traingle to ImageHelper

This commit is contained in:
2025-07-02 11:11:35 -04:00
parent 36fec83f37
commit a6a1d25e74
2 changed files with 85 additions and 13 deletions

View File

@@ -10,9 +10,14 @@ namespace MarketData.CNNProcessing
{
public static class BitmapExtensions
{
// This call is used to generate the training, test, and validation bitmaps..
// This call is used to generate the CNN training, test, and validation bitmaps..
// I noticed a large difference in the accuracy or the model when the quality parameter is 100.
// I therefore intentionally not using EncoderParameters to specify quality but instead taking the default quality.
/// <summary>
/// Save JPG encoded bitmap
/// </summary>
/// <param name="bitmap"></param>
/// <param name="filename"></param>
public static void SaveJPG100(this SKBitmap bitmap, string filename)
{
if(File.Exists(filename))File.Delete(filename);
@@ -22,11 +27,42 @@ namespace MarketData.CNNProcessing
encodedImage.SaveTo(stream);
}
/// <summary>
/// Save JPG encoded bitmap
/// </summary>
/// <param name="bitmap"></param>
/// <param name="stream"></param>
public static void SaveJPG100(this SKBitmap bitmap, Stream stream)
{
using SKImage image = SKImage.FromBitmap(bitmap);
using SKData encodedImage = image.Encode(SKEncodedImageFormat.Jpeg,100);
encodedImage.SaveTo(stream);
}
/// <summary>
/// Save PNG encoded bitmap
/// </summary>
/// <param name="bitmap"></param>
/// <param name="filename"></param>
public static void SavePNG100(this SKBitmap bitmap, string filename)
{
if(File.Exists(filename))File.Delete(filename);
using FileStream stream = new FileStream(filename, FileMode.Create, FileAccess.Write);
using SKImage image = SKImage.FromBitmap(bitmap);
using SKData encodedImage = image.Encode(SKEncodedImageFormat.Png,100);
encodedImage.SaveTo(stream);
}
/// <summary>
/// Save PNG encoded bitmap
/// </summary>
/// <param name="bitmap"></param>
/// <param name="stream"></param>
public static void SavePNG100(this SKBitmap bitmap, Stream stream)
{
using SKImage image = SKImage.FromBitmap(bitmap);
using SKData encodedImage = image.Encode(SKEncodedImageFormat.Png,100);
encodedImage.SaveTo(stream);
}
}
}

View File

@@ -47,7 +47,7 @@ namespace MarketData.CNNProcessing
/// <returns></returns>
public bool LoadImage(string pathFileName)
{
FileStream stream = new FileStream(pathFileName, FileMode.Open);
using FileStream stream = new FileStream(pathFileName, FileMode.Open);
return LoadImage(stream);
}
@@ -220,6 +220,19 @@ namespace MarketData.CNNProcessing
else BitmapExtensions.SaveJPG100(altBitmap,pathFileName);
}
/// <summary>
/// Save the bitmap in PNG format. Note: PNG files support alpha channels, JPG files do not
/// </summary>
/// <param name="pathFileName"></param>
/// <param name="altBitmap"></param>
public void SavePng(String pathFileName,SKBitmap altBitmap=null)
{
Validate();
if(null==altBitmap)BitmapExtensions.SavePNG100(bitmap,pathFileName);
else BitmapExtensions.SavePNG100(altBitmap,pathFileName);
}
// Convert to 8 bits per pixel black and white
private SKBitmap ToBlackAndWhite(SKBitmap bitmap)
{
@@ -420,7 +433,7 @@ namespace MarketData.CNNProcessing
}
/// <summary>
/// Make the bitmap transparent
/// Make the bitmap transparent. Note: PNG format preserves alpha channel while JPG format does not.. so save as PNG if using transparency
/// </summary>
public void Transparent(SKColor color)
{
@@ -613,27 +626,50 @@ namespace MarketData.CNNProcessing
}
/// <summary>
/// Draw a triangle centered inside the bounded area defined by imageWidth, imageHeight
/// Draw a triangle centered inside the bounded area defined by the width and height of the bitmap.
/// </summary>
/// <param name="imageWidth">The width of the bounded area</param>
/// <param name="imageHeight">The height of the bounded area</param>
/// <param name="paintStroke">The paint stroke to to use to outline the triangle</param>
/// <param name="paintFill">The paint stroke to use to fill the triangle</param>
public void DrawTriangle(int imageWidth, int imageHeight, SKPaint paintStroke, SKPaint paintFill)
public void DrawTriangle(SKPaint paintStroke, SKPaint paintFill)
{
Validate();
using SKPath path = new SKPath();
float hLength = (float)imageWidth / 2f;
CreateImage(imageWidth,imageHeight);
Transparent(SKColors.White);
SKPoint txOrigin = pointMapping.MapPoint(new SKPoint(imageWidth/2.0f,imageHeight));
float hLength = (float)Width / 2f;
SKPoint txOrigin = pointMapping.MapPoint(new SKPoint(hLength,Height));
using SKCanvas canvas = new SKCanvas(bitmap);
path.MoveTo(txOrigin.X, txOrigin.Y);
path.LineTo(txOrigin.X - hLength, (txOrigin.Y + imageHeight)-1f);
path.LineTo((txOrigin.X + hLength)-1f, (txOrigin.Y + imageHeight)-1f);
path.LineTo(txOrigin.X - hLength, txOrigin.Y + Height - 1f);
path.LineTo(txOrigin.X + hLength - 1f, txOrigin.Y + Height - 1f);
path.LineTo(txOrigin.X, txOrigin.Y);
path.Close();
canvas.DrawPath(path, paintStroke);
canvas.DrawPath(path, paintFill);
}
/// <summary>
/// Draw a triangle centered at the specified 'origin' and being 'length' width at it's base
/// </summary>
/// <param name="origin">The point origin</param>
/// <param name="length">The length of the base of the triangle</param>
/// <param name="paintStroke">The paint stroke to to use to outline the triangle</param>
/// <param name="paintFill">The paint stroke to use to fill the triangle</param>
public void DrawTriangle(SKPoint origin, int length, SKPaint paintStroke, SKPaint paintFill)
{
Validate();
SKPath path = new SKPath();
SKPoint txOrigin = pointMapping.MapPoint(origin);
float lengthF = (float)length;
float hLength = lengthF / 2f;
float height = (float)Math.Sqrt(Math.Pow(lengthF, 2) - Math.Pow(hLength, 2));
height/=1.15f; // reduce the height by 15%
path.MoveTo(txOrigin.X, txOrigin.Y);
path.LineTo(txOrigin.X - hLength, txOrigin.Y + height);
path.LineTo(txOrigin.X + hLength, txOrigin.Y + height);
path.LineTo(txOrigin.X, txOrigin.Y);
path.Close();
using SKCanvas canvas = new SKCanvas(bitmap);
canvas.DrawPath(path, paintStroke);
canvas.DrawPath(path, paintFill);
}
}
}