Death Socket consists of three projects. They are a .Net Standard 2.0 library, a console program and a Test Centre. The purpose of this repository is to provide a way for people to add grids to images.
https://www.craigoates.net/Software/project/13
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
224 lines
10 KiB
224 lines
10 KiB
module internal ImageServices |
|
|
|
open System.IO |
|
open System.Drawing |
|
open System.Drawing.Imaging |
|
open DeathSocket |
|
open ColourServices |
|
open ImagePrep |
|
open SkiaSharp |
|
|
|
(* Note on the Use of Repeated Code |
|
=========================================================================== |
|
In this file, you will find code which seems duplicated. The areas in |
|
question are mostly the graphics/drawing parts of the file. Before you |
|
consider refactoring this code, please note the memory footprint of this |
|
library. By using "use", the objects created are diposed of properly. This, |
|
also, means it is difficult to pass/return them from one function to the |
|
next. Therefore, the decision made was to accept the duplicated code in |
|
exchange for a smaller memory footprint. Several (large) undisposed images |
|
lurking in an end users RAM can grind their computer to a halt. On top of |
|
that, they have no means to make alterations to the code. *) |
|
|
|
(* SkiaSharp Functions |
|
======================================================================== *) |
|
|
|
// Does not work when using SkiaSharp NuGet v. 1.68 |
|
let drawSkiaGrid (spec: SkiaSpec) = |
|
use fileStream = File.Open (spec.originalPath, FileMode.Open) |
|
use skStream = new SKManagedStream (fileStream) |
|
use bitmap = SKBitmap.Decode (skStream) |
|
use shader = |
|
SKShader.CreateBitmap (bitmap, SKShaderTileMode.Mirror, SKShaderTileMode.Mirror) |
|
let imageInfo = new SKImageInfo (bitmap.Width, bitmap.Height) |
|
use surface = SKSurface.Create (imageInfo) |
|
use canvas = surface.Canvas |
|
canvas.Clear (SKColors.White) |
|
|
|
use imageFill = new SKPaint () |
|
imageFill.Style <- SKPaintStyle.Fill |
|
imageFill.Shader <- shader |
|
canvas.DrawPaint (imageFill) |
|
|
|
use stroke = new SKPaint () |
|
stroke.Style <- SKPaintStyle.Stroke |
|
stroke.StrokeWidth <- spec.penWidth |
|
stroke.Color <- spec.skColour |
|
let horizontalLines = |
|
createSKHorizontalLines (bitmap.Width) (bitmap.Height) (spec.rows) |
|
let verticalLines = |
|
createSKVerticalLines (bitmap.Width) (bitmap.Height) (spec.columns) |
|
for hLine in horizontalLines do |
|
canvas.DrawLine (hLine.[0], hLine.[1], stroke) |
|
for vLine in verticalLines do |
|
canvas.DrawLine (vLine.[0], vLine.[1], stroke) |
|
|
|
use snapshot = surface.Snapshot () |
|
use data = |
|
match Path.GetExtension (spec.savePath) with |
|
| ".jpg" | ".JPG" -> snapshot.Encode (SKEncodedImageFormat.Jpeg, 100) |
|
| ".png"| ".PNG" -> snapshot.Encode (SKEncodedImageFormat.Png, 100) |
|
| _ -> invalidArg "savePath" "The file type must be a .jpg or .png file." |
|
use saveStream = File.OpenWrite (spec.savePath) |
|
data.SaveTo (saveStream) |
|
|
|
// Does not work when using SkiaSharp NuGet v. 1.68 |
|
let drawSkiaRGBGrid spec = |
|
use fileStream = File.Open (spec.originalPath, FileMode.Open) |
|
use skStream = new SKManagedStream (fileStream) |
|
use bitmap = SKBitmap.Decode (skStream) |
|
use shader = |
|
SKShader.CreateBitmap (bitmap, SKShaderTileMode.Mirror, SKShaderTileMode.Mirror) |
|
let imageInfo = new SKImageInfo (bitmap.Width, bitmap.Height) |
|
use surface = SKSurface.Create (imageInfo) |
|
use canvas = surface.Canvas |
|
canvas.Clear (SKColors.White) |
|
|
|
use imageFill = new SKPaint () |
|
imageFill.Style <- SKPaintStyle.Fill |
|
imageFill.Shader <- shader |
|
canvas.DrawPaint (imageFill) |
|
|
|
use stroke = new SKPaint () |
|
stroke.Style <- SKPaintStyle.Stroke |
|
stroke.StrokeWidth <- spec.penWidth |
|
stroke.Color <- |
|
new SKColor ((byte spec.red), (byte spec.green), (byte spec.blue)) |
|
let horizontalLines = |
|
createSKHorizontalLines (bitmap.Width) (bitmap.Height) (spec.rows) |
|
let verticalLines = |
|
createSKVerticalLines (bitmap.Width) (bitmap.Height) (spec.columns) |
|
for hLine in horizontalLines do |
|
canvas.DrawLine (hLine.[0], hLine.[1], stroke) |
|
for vLine in verticalLines do |
|
canvas.DrawLine (vLine.[0], vLine.[1], stroke) |
|
|
|
use snapshot = surface.Snapshot () |
|
use data = |
|
match Path.GetExtension (spec.savePath) with |
|
| ".jpg" | ".JPG" -> snapshot.Encode (SKEncodedImageFormat.Jpeg, 100) |
|
| ".png"| ".PNG" -> snapshot.Encode (SKEncodedImageFormat.Png, 100) |
|
| _ -> invalidArg "savePath" "The file type must be a .jpg or .png file." |
|
use saveStream = File.OpenWrite (spec.savePath) |
|
data.SaveTo (saveStream) |
|
|
|
// Does not work when using SkiaSharp NuGet v. 1.68 |
|
let createSkiaBuffer (spec: SkiaBufferSpec) = |
|
use fileStream = File.Open (spec.filePath, FileMode.Open) |
|
use skStream = new SKManagedStream (fileStream) |
|
use bitmap = SKBitmap.Decode (skStream) |
|
use shader = |
|
SKShader.CreateBitmap (bitmap, SKShaderTileMode.Mirror, SKShaderTileMode.Mirror) |
|
let imageInfo = new SKImageInfo (bitmap.Width, bitmap.Height) |
|
use surface = SKSurface.Create (imageInfo) |
|
use canvas = surface.Canvas |
|
canvas.Clear (SKColors.White) |
|
|
|
use imageFill = new SKPaint () |
|
imageFill.Style <- SKPaintStyle.Fill |
|
imageFill.Shader <- shader |
|
canvas.DrawPaint (imageFill) |
|
|
|
use stroke = new SKPaint () |
|
stroke.Style <- SKPaintStyle.Stroke |
|
stroke.StrokeWidth <- spec.penWidth |
|
stroke.Color <- spec.skColour |
|
let horizontalLines = |
|
createSKHorizontalLines (bitmap.Width) (bitmap.Height) (spec.rows) |
|
let verticalLines = |
|
createSKVerticalLines (bitmap.Width) (bitmap.Height) (spec.columns) |
|
for hLine in horizontalLines do |
|
canvas.DrawLine (hLine.[0], hLine.[1], stroke) |
|
for vLine in verticalLines do |
|
canvas.DrawLine (vLine.[0], vLine.[1], stroke) |
|
|
|
use snapshot = surface.Snapshot () |
|
let data = |
|
match Path.GetExtension (spec.filePath) with |
|
| ".jpg" | ".JPG" -> snapshot.Encode (SKEncodedImageFormat.Jpeg, 100) |
|
| ".png"| ".PNG" -> snapshot.Encode (SKEncodedImageFormat.Png, 100) |
|
| _ -> invalidArg "filePath" "The file type must be a .jpg or .png file." |
|
// (data) Buffer returned -- does not dispose automatically. |
|
data |
|
|
|
// Does not work when using SkiaSharp NuGet v. 1.68 |
|
let createSkiaRGBBuffer (spec: SkiaRGBBufferSpec) = |
|
use fileStream = File.Open (spec.filePath, FileMode.Open) |
|
use skStream = new SKManagedStream (fileStream) |
|
use bitmap = SKBitmap.Decode (skStream) |
|
use shader = |
|
SKShader.CreateBitmap (bitmap, SKShaderTileMode.Mirror, SKShaderTileMode.Mirror) |
|
let imageInfo = new SKImageInfo (bitmap.Width, bitmap.Height) |
|
use surface = SKSurface.Create (imageInfo) |
|
use canvas = surface.Canvas |
|
canvas.Clear (SKColors.White) |
|
|
|
use imageFill = new SKPaint () |
|
imageFill.Style <- SKPaintStyle.Fill |
|
imageFill.Shader <- shader |
|
canvas.DrawPaint (imageFill) |
|
|
|
use stroke = new SKPaint () |
|
stroke.Style <- SKPaintStyle.Stroke |
|
stroke.StrokeWidth <- spec.penWidth |
|
stroke.Color <- |
|
new SKColor ((byte spec.red), (byte spec.green), (byte spec.blue)) |
|
let horizontalLines = |
|
createSKHorizontalLines (bitmap.Width) (bitmap.Height) (spec.rows) |
|
let verticalLines = |
|
createSKVerticalLines (bitmap.Width) (bitmap.Height) (spec.columns) |
|
for hLine in horizontalLines do |
|
canvas.DrawLine (hLine.[0], hLine.[1], stroke) |
|
for vLine in verticalLines do |
|
canvas.DrawLine (vLine.[0], vLine.[1], stroke) |
|
|
|
use snapshot = surface.Snapshot () |
|
let data = |
|
match Path.GetExtension (spec.filePath) with |
|
| ".jpg" | ".JPG" -> snapshot.Encode (SKEncodedImageFormat.Jpeg, 100) |
|
| ".png"| ".PNG" -> snapshot.Encode (SKEncodedImageFormat.Png, 100) |
|
| _ -> invalidArg "filePath" "The file type must be a .jpg or .png file." |
|
// (data) Buffer returned -- does not dispose automatically. |
|
data |
|
|
|
(* System.Drawing Functions |
|
======================================================================== *) |
|
|
|
(* Note on Use of Temp. File in Functions which Add A Grid Overlay |
|
=========================================================================== |
|
The temp. file is used in the functions below are there to convert images |
|
with indexed pixels. Instead of listing them all (future additions), just |
|
assume any function with a "*Spec" type as a parameter will use this "temp" |
|
file. *) |
|
|
|
let drawBrushSpecGrid (spec: BrushSpec) = |
|
use original = Bitmap.FromFile spec.originalPath |
|
use temp = new Bitmap(original) |
|
use clone = |
|
temp.Clone(new Rectangle(0, 0, temp.Width, temp.Height), PixelFormat.Format32bppArgb) |
|
use graphics = Graphics.FromImage(clone) |
|
use pen = new Pen (spec.colour, width = spec.penWidth) |
|
graphics.DrawImage(original,new Rectangle(0, 0, clone.Width, clone.Height)) |
|
let horizontalLines = |
|
createHorizontalLines (clone.Size.Width) (clone.Size.Height) (spec.rows) |
|
let verticalLines = |
|
createVerticalLines (clone.Size.Width) (clone.Size.Height) (spec.columns) |
|
for line in horizontalLines do graphics.DrawLines (pen, line) |
|
for line in verticalLines do graphics.DrawLines (pen, line) |
|
clone.Save (spec.savePath) |
|
|
|
let drawRGBAGrid (spec: RGBASpec) = |
|
use original = Bitmap.FromFile spec.originalPath |
|
use temp = new Bitmap (original) |
|
use clone = |
|
temp.Clone (new Rectangle(0, 0, temp.Width, temp.Height), PixelFormat.Format32bppArgb) |
|
use graphics = Graphics.FromImage(clone) |
|
use pen = new Pen ((makeBrushFromRGBASpec spec), width = spec.penWidth) |
|
graphics.DrawImage (original,new Rectangle(0, 0, clone.Width, clone.Height)) |
|
let horizontalLines = |
|
createHorizontalLines (clone.Size.Width) (clone.Size.Height) (spec.rows) |
|
let verticalLines = |
|
createVerticalLines (clone.Size.Width) (clone.Size.Height) (spec.columns) |
|
for line in horizontalLines do graphics.DrawLines (pen, line) |
|
for line in verticalLines do graphics.DrawLines (pen, line) |
|
clone.Save (spec.savePath) |