diff --git a/MarketData/MarketDataLib/CNNProcessing/BitmapExtensions.cs b/MarketData/MarketDataLib/CNNProcessing/BitmapExtensions.cs
index cdbeca2..80edf0f 100755
--- a/MarketData/MarketDataLib/CNNProcessing/BitmapExtensions.cs
+++ b/MarketData/MarketDataLib/CNNProcessing/BitmapExtensions.cs
@@ -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.
+ ///
+ /// Save JPG encoded bitmap
+ ///
+ ///
+ ///
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);
}
+ ///
+ /// Save JPG encoded bitmap
+ ///
+ ///
+ ///
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);
}
+
+ ///
+ /// Save PNG encoded bitmap
+ ///
+ ///
+ ///
+ 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);
+ }
+
+ ///
+ /// Save PNG encoded bitmap
+ ///
+ ///
+ ///
+ 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);
+ }
}
}
diff --git a/MarketData/MarketDataLib/CNNProcessing/ImageHelper.cs b/MarketData/MarketDataLib/CNNProcessing/ImageHelper.cs
index 03c7e97..10d2143 100644
--- a/MarketData/MarketDataLib/CNNProcessing/ImageHelper.cs
+++ b/MarketData/MarketDataLib/CNNProcessing/ImageHelper.cs
@@ -47,7 +47,7 @@ namespace MarketData.CNNProcessing
///
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);
}
+ ///
+ /// Save the bitmap in PNG format. Note: PNG files support alpha channels, JPG files do not
+ ///
+ ///
+ ///
+ 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
}
///
- /// 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
///
public void Transparent(SKColor color)
{
@@ -613,27 +626,50 @@ namespace MarketData.CNNProcessing
}
///
- /// 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.
///
- /// The width of the bounded area
- /// The height of the bounded area
/// The paint stroke to to use to outline the triangle
/// The paint stroke to use to fill the triangle
- 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);
}
+
+ ///
+ /// Draw a triangle centered at the specified 'origin' and being 'length' width at it's base
+ ///
+ /// The point origin
+ /// The length of the base of the triangle
+ /// The paint stroke to to use to outline the triangle
+ /// The paint stroke to use to fill the triangle
+ 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);
+ }
}
}
\ No newline at end of file