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.

248 lines
11 KiB

namespace DeathSocket
open System.IO
open ColourServices
/// Provides functions which help draw gridded overlays onto images.
/// Death Socket, uses System.Drawing's brushes and colours.
/// If you are using System.Media brushes and colour, you will need to
/// convert them. Death Socket, also, uses SkiaSharp for cross platform
/// functionality. If you are using Death Socket on Windows Desktop, use
/// functions which do not include "Skia" in their name. If you are using
/// Death Socket in a Xamarin/UWP project you should use the SkiaSharp
/// functions.
module GridPainter =
open ValidationServices
open ImagePrep
open ImageServices
open SkiaSharp
/// <summary>
/// Uses the information included in spec to create a gridded image.
/// It then asynchronously saves it. Uses .jpg or .png formats only.
/// Please note: Any buffer-based spec's (E.G. SkiaBufferSpec) will be
/// ignored by this function.
/// </summary>
/// <param name="spec">
/// The specification used to generate the new gridded image. The
/// ImageSpec is a discriminated union, consisting of a Brush, RGBA,
/// Skia or SkiaRGB spec.
/// </param>
/// <remarks>
/// Make sure the image, which is having the overlay added to it,
/// is not in use or needed by another program/process.
/// This is because it is locked whilst in this function.
/// </remarks>
let applyGridToImageAsync (spec: ImageSpec) =
async {
try
match spec with
| Brush b ->
validateIO b.originalPath b.savePath |> ignore
drawBrushSpecGrid b
| RGBA r ->
validateIO r.originalPath r.savePath |> ignore
drawRGBAGrid r
| Skia s ->
validateIO s.originalPath s.savePath |> ignore
drawSkiaGrid s
| SkiaRGB sR ->
validateIO sR.originalPath sR.savePath |> ignore
drawSkiaRGBGrid sR
| _ -> printfn "[DEATH SOCKET INFO] Inappropriate ImageSpec used here. Please use none buffer-based spec's when using this function."
with
| :? FileNotFoundException as ex ->
printfn "File could not be found at %s" ex.Message
}
/// <summary>
/// Determines the current scale an image is viewed at (E.G. scaled
/// preview in image viewer). The (pen) line thickness is then updated
/// to match this preview scale and can be used when drawing a grid
/// line on the scaled preview of the image.
/// </summary>
/// <param name="previewDimension">
/// The width or height of the image when previewed (I.E. in a GUI).
/// </param>
/// <param name="actualDimension">
/// The width or height of the actual image.
/// </param>
/// <param name="lineThickness">
/// The thickness of the pen used to draw the grid line.
/// </param>
/// <remarks>
/// You should find you only need this function when dealing with
/// previewing an image in a GUI. Another thing to note is the
/// SkiaSharp based functions already scale the grid lines for you. So,
/// you should not need to use this function when using them.
/// </remarks>
let scaleLineThickness (previewDimensions: int * int) (actualDimensions: int * int) (lineThickness: double) =
validateDimensions previewDimensions |> ignore
validateDimensions actualDimensions |> ignore
validateLineThickness |> ignore
adjustLineThickness previewDimensions actualDimensions lineThickness
/// <summary>
/// Reads an (jpg or png) image and return its width and height as a
/// tuple, (width * hight).
/// </summary>
/// <param name="imageType">
/// The name of the graphics library used to read and determine the
/// images dimensions.
/// </param>
/// <remarks>
/// The image type is determined by the graphics library used. It is
/// called "ImageType" and not "GraphicsLibUsed" because the image/file
/// information is the thing this function cares about most of all. How
/// it is read and what library it uses it secondary.
///</remarks>
let determineImageDimensions (imgType: ImageType) =
try
match imgType with
| SkiaSharp s ->
validateFilePath s |> ignore
determineSkiaDimensions s
| SystemDrawing d ->
validateFilePath d |> ignore
determineSystemDrawingDimensions d
with
| :? FileNotFoundException as ex ->
printfn "%s" ex.Message
reraise ()
(* System.Drawing Functions
==================================================================== *)
/// <summary>
/// Determines the (Pen) points needed to draw the appropriate number
/// of horizontal lines (I.E. rows). Each item in the array includes a
/// start and end co-ordinate (point) for each line.
/// Use this function when targeting .Net/Mono).
/// </summary>
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
/// <param name="rows">The number of rows the grid should have.</param>
/// <remarks>
/// You will probably only need these when dealing with GUI's.
/// </remarks>
let determineHorizontalLines (width: int) (height: int) (rows: int) =
createHorizontalLines width height rows
/// <summary>
/// Determines the (Pen) points needed to draw the appropriate number
/// of vertical lines (I.E. columns). Each item in the array includes a
/// start and end co-ordinate (point) for each line.
/// Use this function when targeting Windows Desktop (or Mono).
/// </summary>
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
/// <param name="columns">
/// The number of columns the grid should have.
/// </param>
/// <remarks>
/// You will probably only need these when dealing with GUI's.
/// </remarks>
let determineVerticalLines (width: int) (height: int) (columns: int) =
createVerticalLines width height columns
/// <summary>
/// Creates a Sytsem.Drawing SolidBrush from the individual RGBA values.
/// Use this function when targeting .Net/Mono).
/// </summary>
/// <param name="r">The red value.</param>
/// <param name="g">The green value.</param>
/// <param name="b">The blue value.</param>
/// <param name="a">The alpha value.</param>
/// <remarks>
/// Death Socket uses System.Drawing and not System.Media for colours
/// and brushes.
/// </remarks>
let makeSolidBrushFromRGBA (r: int) (g: int) (b:int) (a: int) =
makeBrushFromRGBA r g b a
/// <summary>
/// Creates a System.Drawing SolidBrush from a RGBASpec.
/// Use this function when targeting .Net/Mono).
/// </summary>
/// <param name="spec">
/// The specification which the brush is made from.
/// </param>
/// <remarks>
/// Death Socket uses System.Drawing and not System.Media for colours
/// and brushes.
/// </remarks>
let makeSolidBrushFromRGBASpec (spec: RGBASpec) =
makeBrushFromRGBASpec spec
(* SkiaSharp Functions
==================================================================== *)
/// <summary>
/// Uses the information included in spec to create a SKData buffer.
/// The buffer will contain a gridded image which you can then use in
/// any way you see fit. Accepted image formats are limited to .jpg
/// and .png. Please note: Any non buffer-based spec's (E.G. SkiaSpec)
/// will be ignored by this function.
/// </summary>
/// <param name="spec">
/// The specification used to generate the new SKData buffer. The
/// ImageSpec is a discriminated union, consisting of a SkiaBuffer and
/// a SkiaRGBBuffer spec.
/// </param>
/// <remarks>
/// Make sure the image, which is used to create the SKData buffer,
/// is not in use or needed by another program/process.
/// This is because it is locked whilst in this function.
/// </remarks>
let createSKDataAsync (spec: ImageSpec) =
async {
try
match spec with
| SkiaBuffer s ->
validateFilePath s.filePath |> ignore
return createSkiaBuffer s
| SkiaRGBBuffer sR ->
validateFilePath sR.filePath |> ignore
return createSkiaRGBBuffer sR
| _ ->
printfn "[DEATH SOCKET INFO] Inappropriate ImageSpec used here. Please use buffer-based spec's when using this function. Returning an empty SKData object."
return SKData.Empty
with
| :? FileNotFoundException as ex ->
printfn "%s" ex.Message |> ignore
return SKData.Empty
}
/// <summary>
/// Determines the (SKPoints) points needed to draw the appropriate
/// number of horizontal lines (I.E. rows). Each item in the array
/// included a start and end co-ordinate (SKPoint) for each line.
/// Use this function when targeting Xamarin/UWP/.Net Core (SkiaSharp).
/// </summary>
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
/// <param name="rows">The number of rows the grid should have.</param>
/// <remarks>
/// This function is part of the SkiaSharp functions provided
/// by Death Socket.
/// </remarks>
let determineSKHorizontalLines (width: int) (height: int) (rows: int) =
createSKHorizontalLines width height rows
/// <summary>
/// Determines the (SKPoints) points needed to draw the appropriate
/// number of vertical lines (I.E. columns). Each item in the array
/// included a start and end co-ordinate (SKPoint) for each line.
/// Use this function when targeting Xamarin/UWP/.Net Core (SkiaSharp).
/// </summary>
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
/// <param name="columns">The number of columns the grid should have.
/// </param>
/// <remarks>
/// This function is part of the SkiaSharp functions provided by Death
/// Socket.
/// </remarks>
let determineSKVerticalLines (width: int) (height: int) (columns: int) =
createSKVerticalLines width height columns