diff --git a/DeathSocket/Domain.fs b/DeathSocket/Domain.fs index 0fd06ba..5bf5a4b 100644 --- a/DeathSocket/Domain.fs +++ b/DeathSocket/Domain.fs @@ -94,4 +94,12 @@ /// The number of rows the grid will have. rows: int ///The number of columns the grid will have. - columns: int } \ No newline at end of file + columns: int } + + /// Discriminated Union representing the various specification types + /// Death Socket can use to apply a grid to an image. + type ImageSpec = + | Brush of BrushSpec + | RGBA of RGBASpec + | Skia of SkiaSpec + | SkiaRGB of SkiaRGBSpec \ No newline at end of file diff --git a/DeathSocket/GridPainter.fs b/DeathSocket/GridPainter.fs index e12bd8b..e961c71 100644 --- a/DeathSocket/GridPainter.fs +++ b/DeathSocket/GridPainter.fs @@ -15,6 +15,46 @@ namespace DeathSocket open Validation open ImageServices + open System + + /// + /// Uses the information included in spec to create a gridded image. + /// It then asynchronously saves it. Uses .jpg or .png formats only. + /// + /// + /// The specification used to generate the new gridded image. The + /// ImageSpec is a discriminated union, consisting of a Brush, RGBA, + /// Skia or SkiaRGB spec. + /// + /// + /// If the file the grid is being applied to cannot be found, + /// a FileNotFoundException will be thrown. + /// + /// + 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 + with + | :? FileNotFoundException as ex -> + printfn "File could not be found at %s" ex.Message + } // System.Drawing Functions // ======================================================================== @@ -62,6 +102,7 @@ namespace DeathSocket /// is not in use or needed by another program/process. /// This is because it is locked whilst in this function. /// + [] let applyBrushSpecGridAsync (spec: BrushSpec) = async { try @@ -90,6 +131,7 @@ namespace DeathSocket /// is not in use or needed by another program/process. /// This is because it is locked whilst in this function. /// + [] let applyRGBAGridAsync (spec: RGBASpec) = async { try @@ -162,7 +204,6 @@ namespace DeathSocket let determineSKVerticalLines (width: int) (height: int) (columns: int) = createSKVerticalLines width height columns - /// /// Uses the information included in spec to create a gridded image. /// It then asynchronously saves it. Uses .jpg or .png formats only. @@ -178,6 +219,7 @@ namespace DeathSocket /// is not in use or needed by another program/process. /// This is because it is locked whilst in this function. /// + [] let applySkiaGridAsync (spec: SkiaSpec) = async { try @@ -204,6 +246,7 @@ namespace DeathSocket /// is not in use or needed by another program/process. /// This is because it is locked whilst in this function. /// + [] let applySkiaRGBGridAsync (spec: SkiaRGBSpec) = async { try diff --git a/DeathSocket/ScratchPad.fsx b/DeathSocket/ScratchPad.fsx index 4775c49..c719984 100644 --- a/DeathSocket/ScratchPad.fsx +++ b/DeathSocket/ScratchPad.fsx @@ -1,5 +1,6 @@ -#r @"C:\Users\craig\.nuget\packages\skiasharp\1.60.3\lib\netstandard1.3\SkiaSharp.dll" -#r @"C:\Users\craig\.nuget\packages\skiasharp\1.60.3\lib\net45\SkiaSharp.dll" +// These two paths need adjusting to match your computer. +#r @"C:/Users/craig/.nuget/packages/skiasharp/1.60.3/lib/netstandard1.3/SkiaSharp.dll" +#r @"C:/Users/craig/.nuget/packages/skiasharp/1.60.3/lib/net45/SkiaSharp.dll" #load "Domain.fs" #load "Validation.fs" @@ -12,6 +13,8 @@ open System open DeathSocket open Validation open ImageServices +open SkiaSharp + (* Death Socket Scripts =============================================================================== @@ -21,36 +24,63 @@ a nerw image. *) let desktop = Environment.GetFolderPath (Environment.SpecialFolder.Desktop) -(* You will need to provide the image at the location specified. It will throw -an exception if the file cannnot be found.*) -let validationTest = validateFilePath (desktop + "/test.jpg") +(* You will need to provide the image at the location specified. Both throw an +exception if the file cannot be found or is the wrong extension. Death Socket +only works with JPG and PNG.*) +let IOTest = validateFilePath (desktop + "/test.jpg") +let extentionTest = validateSaveFileType (desktop + "/test.jpg") -(* These are not needed to create an image. There here for you to check the -start and end points of each pen stroke/path. *) +(* These are not needed by you to create an image. They here for you to check +the start and end points of each pen stroke/path. *) let horizontalLines = createHorizontalLines 1000 500 10 let verticalLines = createVerticalLines 300 600 10 +let skHorizontalLines = createSKHorizontalLines 550 520 10 +let skVerticalLines = createSKVerticalLines 120 450 22 (* You will need to provide the image and specify its load/save location. -Death Socket assumes either JPEG or PNG files so use other files at your own -risk. Cannot guarantee they will work. Also, either in this spec. can be -changed to suit your needs. *) -let spec: BrushSpec = - { originalPath = desktop + "/test.jpg" - savePath = desktop + "/grid.png" - colour = Brushes.Chartreuse - penWidth = (float32 1) - rows = 10 - columns = 10 } - -// Run this when you have finished building the spec. -GridPainter.applyBrushSpecGridAsync spec |> Async.RunSynchronously - -//***************************************************************************** - -(* Skia Sharp Draft -=============================================================================== -The code below here will eventually be worked into the main codebase or thrown -away. It is here acting as a first draft for integrating the Skia Sharp NuGet -package into Death Socket. *) +Death Socket assumes either JPEG or PNG files.*) + +// Brush Specification (uses System.Drawing) +Brush ({ originalPath = desktop + "/test.jpg" + savePath = desktop + "/grid.png" + colour = Brushes.Chartreuse + penWidth = (float32 1) + rows = 10 + columns = 10 }) +|> GridPainter.applyGridToImageAsync +|> Async.Start + +// RGBA Specification (uses System.Drawing) +RGBA ({ originalPath = desktop + "/test.jpg" + savePath = desktop + "/grid.png" + alpha = float 1 + red = float 122 + green = float 222 + blue = float 100 + penWidth = (float32 1) + rows = 10 + columns = 10 }) +|> GridPainter.applyGridToImageAsync +|> Async.Start + +// Skia Specification (uses SkiaSharp -- use with Xamarin) +Skia ({ originalPath = desktop + "/test.jpg" + savePath = desktop + "/grid.png" + skColour = SKColors.BlueViolet + penWidth = (float32 1) + rows = 10 + columns = 10}) +|> GridPainter.applyGridToImageAsync +|> Async.Start -drawSkiaGrid() \ No newline at end of file +// SkiaRGB Specification (uses SkiaSharp -- use with Xamarin) +SkiaRGB ({ originalPath = desktop + "/test.jpg" + savePath = desktop + "/grid.png" + red = (float32 102) + green = (float32 124) + blue = (float32 224) + penWidth = (float32 1) + rows = 10 + columns = 10}) +|> GridPainter.applyGridToImageAsync +|> Async.Start \ No newline at end of file diff --git a/DeathSocket/Validation.fs b/DeathSocket/Validation.fs index 71128f3..edc208a 100644 --- a/DeathSocket/Validation.fs +++ b/DeathSocket/Validation.fs @@ -13,4 +13,8 @@ | ".JPG" -> () | ".png" -> () | ".PNG" -> () - | _ -> invalidArg "savePath" "The file type must be a .jpg or .png file." \ No newline at end of file + | _ -> invalidArg "savePath" "The file type must be a .jpg or .png file." + + let validateIO iPath oPath = + validateFilePath iPath + validateSaveFileType oPath \ No newline at end of file diff --git a/DeathSocketCLI/Commands.fs b/DeathSocketCLI/Commands.fs index d0fd0ed..e924dbb 100644 --- a/DeathSocketCLI/Commands.fs +++ b/DeathSocketCLI/Commands.fs @@ -8,6 +8,7 @@ open System.IO open Console.Waterworks open Console.Waterworks.Attributes + open DeathSocket.Domain let showEndOfCommandMessage = "[INFO.] Task completed." @@ -38,8 +39,8 @@ let ``add-default`` imgPath newPath = try printfn "[INFO.] Adding default grid to image..." - buildDefaultSpec imgPath newPath - |> applyBrushSpecGridAsync + Brush (buildDefaultSpec imgPath newPath) + |> applyGridToImageAsync |> Async.Start showEndOfCommandMessage with @@ -57,8 +58,8 @@ let ``add-grid`` imgPath numRows numColumns pWidth colour newPath = try printfn "[INFO.] Adding grid to image..." - buildSpec imgPath numRows numColumns pWidth colour newPath - |> applyBrushSpecGridAsync + Brush (buildSpec imgPath numRows numColumns pWidth colour newPath) + |> applyGridToImageAsync |> Async.Start showEndOfCommandMessage with @@ -91,7 +92,7 @@ let ag imgPath numRows numColumns pWidth colour newPath = ``add-grid`` imgPath numRows numColumns pWidth colour newPath - let lc () =``list-colours`` () + let lc () = ``list-colours`` () (* SkiaSharp Command-Methods -- NOT FOR MASS CONSUMPTION ======================================================================= @@ -110,14 +111,14 @@ let``add-skia-grid`` imgPath numRows numColumns pWidth colour newPath = printfn "[INFO.] Adding SkiaSharp grid to image..." - buildSkiaSpec imgPath numRows numColumns pWidth colour newPath - |> applySkiaGridAsync + Skia (buildSkiaSpec imgPath numRows numColumns pWidth colour newPath) + |> applyGridToImageAsync |> Async.Start showEndOfCommandMessage let``add-skia-rgb-grid`` imgPath numRows numColumns pWidth r g b newPath = printfn "[INFO.] Adding SkiaSharp grid to image..." - buildSkiaRGBSpec imgPath numRows numColumns pWidth r g b newPath - |> applySkiaRGBGridAsync + SkiaRGB (buildSkiaRGBSpec imgPath numRows numColumns pWidth r g b newPath) + |> applyGridToImageAsync |> Async.Start showEndOfCommandMessage \ No newline at end of file diff --git a/TestCentre/LibraryTests.fs b/TestCentre/LibraryTests.fs index 6d7e6dc..8e37eb1 100644 --- a/TestCentre/LibraryTests.fs +++ b/TestCentre/LibraryTests.fs @@ -105,7 +105,6 @@ open DeathSocket.GridPainter open TestingHelpers open System.IO - open SkiaSharp (* With regards to the "saving images" tests, you should end up with one image left over in the SavingTestArea folder. Comment out the @@ -117,13 +116,13 @@ resetSavingTestArea () let oPath = generateLoadPath () let sPath = generateSavePath oPath - { originalPath = oPath - savePath = sPath - colour = randomBrush () :?> Brush - penWidth = float32 (newPenWidth()) - rows = 10 - columns = 10 } - |> applyBrushSpecGridAsync + Brush ({ originalPath = oPath + savePath = sPath + colour = randomBrush () :?> Brush + penWidth = float32 (newPenWidth()) + rows = 10 + columns = 10 }) + |> applyGridToImageAsync |> Async.RunSynchronously (File.Exists sPath) = true @@ -132,16 +131,16 @@ resetSavingTestArea () let oPath = generateLoadPath () let sPath = generateSavePath oPath - { originalPath = oPath - savePath = sPath - alpha = float (newRGBANum ()) - red = float (newRGBANum ()) - green = float (newRGBANum ()) - blue = float (newRGBANum ()) - penWidth = float32 (newPenWidth()) - rows = 10 - columns = 10 } - |> applyRGBAGridAsync + RGBA ({ originalPath = oPath + savePath = sPath + alpha = float (newRGBANum ()) + red = float (newRGBANum ()) + green = float (newRGBANum ()) + blue = float (newRGBANum ()) + penWidth = float32 (newPenWidth()) + rows = 10 + columns = 10 }) + |> applyGridToImageAsync |> Async.RunSynchronously (File.Exists sPath) = true @@ -181,13 +180,13 @@ resetSavingTestArea() let oPath = generateLoadPath () let sPath = generateSavePath oPath - { originalPath = oPath - savePath= sPath - skColour = randomSKColour () - penWidth = float32 (newPenWidth()) - rows = newNum () - columns = newNum () } - |> applySkiaGridAsync + Skia ({ originalPath = oPath + savePath= sPath + skColour = randomSKColour () + penWidth = float32 (newPenWidth()) + rows = newNum () + columns = newNum () }) + |> applyGridToImageAsync |> Async.RunSynchronously (File.Exists sPath) = true @@ -196,15 +195,15 @@ resetSavingTestArea() let oPath = generateLoadPath () let sPath = generateSavePath oPath - { originalPath = oPath - savePath= sPath - red = float32 (newRGBANum ()) - green = float32 (newRGBANum ()) - blue = float32 (newRGBANum ()) - penWidth = float32 (newPenWidth()) - rows = newNum () - columns = newNum () } - |> applySkiaRGBGridAsync + SkiaRGB ({ originalPath = oPath + savePath= sPath + red = float32 (newRGBANum ()) + green = float32 (newRGBANum ()) + blue = float32 (newRGBANum ()) + penWidth = float32 (newPenWidth()) + rows = newNum () + columns = newNum () }) + |> applyGridToImageAsync |> Async.RunSynchronously (File.Exists sPath) = true