From c89dab50dd5ec0c6e24a8bdcb9535f7d1a18d9cf Mon Sep 17 00:00:00 2001 From: "OPTIMUS-PRIME\\craig" Date: Mon, 15 Oct 2018 20:22:58 +0100 Subject: [PATCH 01/12] add initial bits of code for expanding the amount of spec's. Begin adding code to use the new specifications. --- DeathSocket/ColourServices.fs | 14 +++++++++++ DeathSocket/DeathSocket.fsproj | 1 + DeathSocket/Domain.fs | 39 ++++++++++++++++++++++++++++++ DeathSocket/GridPainter.fs | 19 ++++++++++++++- DeathSocket/ImageServices.fs | 43 ++++++++++++++++++++++++++++++++-- DeathSocket/ScratchPad.fsx | 4 ++-- DeathSocketCLI/AssemblyInfo.fs | 4 ++-- TestCentre/LibraryTests.fs | 2 +- 8 files changed, 118 insertions(+), 8 deletions(-) create mode 100644 DeathSocket/ColourServices.fs diff --git a/DeathSocket/ColourServices.fs b/DeathSocket/ColourServices.fs new file mode 100644 index 0000000..606ca0f --- /dev/null +++ b/DeathSocket/ColourServices.fs @@ -0,0 +1,14 @@ +module ColourServices + +open System.Drawing +open DeathSocket.Domain + + // not tested + let convertRGBAToBrush (spec: RGBASpec) = + let a = int spec.alpha + let r = int spec.red + let g = int spec.green + let b = int spec.blue + let colour = Color.FromArgb (a, r, g, b) + new SolidBrush(colour) + diff --git a/DeathSocket/DeathSocket.fsproj b/DeathSocket/DeathSocket.fsproj index 3f8cc01..a4e484c 100644 --- a/DeathSocket/DeathSocket.fsproj +++ b/DeathSocket/DeathSocket.fsproj @@ -7,6 +7,7 @@ + diff --git a/DeathSocket/Domain.fs b/DeathSocket/Domain.fs index 34cc817..c9d1b72 100644 --- a/DeathSocket/Domain.fs +++ b/DeathSocket/Domain.fs @@ -21,4 +21,43 @@ /// The number of rows the grid will have. rows: int ///The number of columns the grid will have. + columns: int } + + /// + /// The specification which uses System.Drawing brush to draw a grid. + /// + // REPLACING IMAGESPEC + type BrushSpec = + { /// The original path of the image which the grid is being added to. + originalPath: string + /// The location of the new gridded image. + savePath: string + /// The (System.Drawing) brush used to draw the grid. This determines the colour. + colour: Brush + /// The thickness of the line on the grid. + penWidth: float32 + /// The number of rows the grid will have. + rows: int + ///The number of columns the grid will have. + columns: int } + + type RGBASpec = + { originalPath: string + savePath: string + alpha: float + red: float + green: float + blue: float + penWidth: float32 + rows: int + columns: int } + + type CMYKSpec = + { originalPath: string + savePath: string + cyan: float + magenta: float + yellow: float + key: float32 + rows: int columns: int } \ No newline at end of file diff --git a/DeathSocket/GridPainter.fs b/DeathSocket/GridPainter.fs index fbb3bba..cc0342d 100644 --- a/DeathSocket/GridPainter.fs +++ b/DeathSocket/GridPainter.fs @@ -28,7 +28,8 @@ namespace DeathSocket /// is not in use or needed by another program/process. /// This is because it is locked whilst in this function. /// - let applyGridAsync spec = + let applyGridAsync (spec: ImageSpec) = + // The spec is to be changed to Brush Spec. async { try validateFilePath spec.originalPath |> ignore @@ -39,6 +40,20 @@ namespace DeathSocket printfn "File could not be found at %s" ex.Message } + // Not tested. + let applyRGBAGridAsync (spec: RGBASpec) = + async { + try + validateFilePath spec.originalPath |> ignore + validatFileType spec.savePath |> ignore + drawRGBAGrid spec + with + | :? FileNotFoundException as ex -> + printfn "File could not be found at %s" ex.Message + } + + // let applyCMYKGridAsync -- to be added at a later date. + /// /// 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. @@ -48,6 +63,7 @@ namespace DeathSocket /// The number of rows the grid should have. /// You will probably only need these when dealing with GUI's. let determineHorizontalLines width height rows = + // To Be moved to its own service and made public. No wrapper needed. createHorizontalLines width height rows /// @@ -59,4 +75,5 @@ namespace DeathSocket /// The number of columns the grid should have. /// You will probably only need these when dealing with GUI's. let determineVerticalLines width height columns = + // To Be moved to its own service and made public. No wrapper needed. createVerticalLines width height columns \ No newline at end of file diff --git a/DeathSocket/ImageServices.fs b/DeathSocket/ImageServices.fs index b6219ed..1152496 100644 --- a/DeathSocket/ImageServices.fs +++ b/DeathSocket/ImageServices.fs @@ -3,20 +3,25 @@ open System.Drawing open System.Drawing.Imaging open DeathSocket + open Validation + open ColourServices + // To Be moved to its own service and made public. No wrapper needed. let createHorizontalLines width height rows = let interval = height / rows [| for point in 1 .. (rows - 1) -> [|Point (0, (interval * point)) Point (width, (interval * point) )|]|] + // To Be moved to its own service and made public. No wrapper needed. let createVerticalLines width height columns = let interval = width / columns [| for point in 1 .. (columns - 1) -> [| Point ((interval * point), 0) Point ((interval * point), height)|]|] - let drawGrid spec = + // To be deleted -- replaced with brush spec. + let drawGrid (spec: ImageSpec) = // The temp. file is used as a way to convert images with indexed pixels. use original = Bitmap.FromFile spec.originalPath use temp = new Bitmap(original) @@ -30,4 +35,38 @@ 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) \ No newline at end of file + clone.Save (spec.savePath) + + // not tested but same as Draw Grid -- this is its replacement + let drawBrushSpecGrid (spec: BrushSpec) = + // The temp. file is used as a way to convert images with indexed pixels. + 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) + + // Not tested + let drawRGBAGrid (spec: RGBASpec) = + // The temp. file is used as a way to convert images with indexed pixels. + 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 ((convertRGBAToBrush 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) diff --git a/DeathSocket/ScratchPad.fsx b/DeathSocket/ScratchPad.fsx index 63444cb..13eaa89 100644 --- a/DeathSocket/ScratchPad.fsx +++ b/DeathSocket/ScratchPad.fsx @@ -30,7 +30,7 @@ let verticalLines = createVerticalLines 300 600 10 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 = +let spec :ImageSpec = { originalPath = desktop + "/test.jpg" savePath = desktop + "/grid.png" colour = Brushes.Chartreuse @@ -39,4 +39,4 @@ let spec = columns = 10 } // Run this when you have finished building the spec. -GridPainter.applyGrid spec |> Async.RunSynchronously +GridPainter.applyGridAsync spec |> Async.RunSynchronously diff --git a/DeathSocketCLI/AssemblyInfo.fs b/DeathSocketCLI/AssemblyInfo.fs index 2352b17..00d540e 100644 --- a/DeathSocketCLI/AssemblyInfo.fs +++ b/DeathSocketCLI/AssemblyInfo.fs @@ -38,8 +38,8 @@ open System.Runtime.InteropServices // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [] -[] -[] +[] +[] do () \ No newline at end of file diff --git a/TestCentre/LibraryTests.fs b/TestCentre/LibraryTests.fs index 4d15747..2810f14 100644 --- a/TestCentre/LibraryTests.fs +++ b/TestCentre/LibraryTests.fs @@ -86,7 +86,7 @@ resetSavingTestArea () let oPath = generateLoadPath () let sPath = generateSavePath oPath - let spec = + let (spec: ImageSpec) = { originalPath = oPath savePath = sPath colour = randomBrush () :?> Brush From 23e3408b0644d7e68bcc2445230828d66a295c74 Mon Sep 17 00:00:00 2001 From: Craig Oates Date: Fri, 19 Oct 2018 17:40:47 +0100 Subject: [PATCH 02/12] refactor ImageSpec to BrushSpec. Comment-out code which uses the ImageSpec and mark code as obsolete when still active. --- DeathSocket/Domain.fs | 2 ++ DeathSocket/GridPainter.fs | 8 +++----- DeathSocket/ImageServices.fs | 32 +++++++++++++++----------------- DeathSocketCLI/Commands.fs | 4 ++-- TestCentre/LibraryTests.fs | 4 ++-- 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/DeathSocket/Domain.fs b/DeathSocket/Domain.fs index c9d1b72..f6f7a4a 100644 --- a/DeathSocket/Domain.fs +++ b/DeathSocket/Domain.fs @@ -5,10 +5,12 @@ module Domain = open System.Drawing + open System /// /// The specification used by Death Socket when adding a grid to an image. /// + [] type ImageSpec = { /// The original path of the image which the grid is being added to. originalPath: string diff --git a/DeathSocket/GridPainter.fs b/DeathSocket/GridPainter.fs index cc0342d..f540b30 100644 --- a/DeathSocket/GridPainter.fs +++ b/DeathSocket/GridPainter.fs @@ -14,7 +14,7 @@ namespace DeathSocket /// Uses the information included in spec and creates a gridded image. /// It then asynchronously saves it. /// Please stick to .bmp, .jpg or .png files. - /// The others (image) file types have not been tested. + /// The other (image) file types have not been tested. /// /// /// The specification used to generate the new gridded image @@ -28,13 +28,13 @@ namespace DeathSocket /// is not in use or needed by another program/process. /// This is because it is locked whilst in this function. /// - let applyGridAsync (spec: ImageSpec) = + let applyBrushSpecGridAsync (spec: BrushSpec) = // The spec is to be changed to Brush Spec. async { try validateFilePath spec.originalPath |> ignore validatFileType spec.savePath |> ignore - drawGrid spec |> ignore + drawBrushSpecGrid spec |> ignore with | :? FileNotFoundException as ex -> printfn "File could not be found at %s" ex.Message @@ -63,7 +63,6 @@ namespace DeathSocket /// The number of rows the grid should have. /// You will probably only need these when dealing with GUI's. let determineHorizontalLines width height rows = - // To Be moved to its own service and made public. No wrapper needed. createHorizontalLines width height rows /// @@ -75,5 +74,4 @@ namespace DeathSocket /// The number of columns the grid should have. /// You will probably only need these when dealing with GUI's. let determineVerticalLines width height columns = - // To Be moved to its own service and made public. No wrapper needed. createVerticalLines width height columns \ No newline at end of file diff --git a/DeathSocket/ImageServices.fs b/DeathSocket/ImageServices.fs index 1152496..521e5ce 100644 --- a/DeathSocket/ImageServices.fs +++ b/DeathSocket/ImageServices.fs @@ -6,14 +6,12 @@ open Validation open ColourServices - // To Be moved to its own service and made public. No wrapper needed. let createHorizontalLines width height rows = let interval = height / rows [| for point in 1 .. (rows - 1) -> [|Point (0, (interval * point)) Point (width, (interval * point) )|]|] - // To Be moved to its own service and made public. No wrapper needed. let createVerticalLines width height columns = let interval = width / columns [| for point in 1 .. (columns - 1) -> @@ -21,21 +19,21 @@ Point ((interval * point), height)|]|] // To be deleted -- replaced with brush spec. - let drawGrid (spec: ImageSpec) = - // The temp. file is used as a way to convert images with indexed pixels. - 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 drawGrid (spec: BrushSpec) = + // // The temp. file is used as a way to convert images with indexed pixels. + // 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) // not tested but same as Draw Grid -- this is its replacement let drawBrushSpecGrid (spec: BrushSpec) = diff --git a/DeathSocketCLI/Commands.fs b/DeathSocketCLI/Commands.fs index 53fbc9c..f70ddad 100644 --- a/DeathSocketCLI/Commands.fs +++ b/DeathSocketCLI/Commands.fs @@ -38,7 +38,7 @@ try printfn "[INFO.] Adding default grid to image..." buildDefaultSpec imgPath newPath - |> applyGridAsync + |> applyBrushSpecGridAsync |> Async.Start showEndOfCommandMessage with @@ -57,7 +57,7 @@ try printfn "[INFO.] Adding grid to image..." buildSpec imgPath numRows numColumns pWidth colour newPath - |> applyGridAsync + |> applyBrushSpecGridAsync |> Async.Start showEndOfCommandMessage with diff --git a/TestCentre/LibraryTests.fs b/TestCentre/LibraryTests.fs index 2810f14..5075547 100644 --- a/TestCentre/LibraryTests.fs +++ b/TestCentre/LibraryTests.fs @@ -86,14 +86,14 @@ resetSavingTestArea () let oPath = generateLoadPath () let sPath = generateSavePath oPath - let (spec: ImageSpec) = + let (spec: BrushSpec) = { originalPath = oPath savePath = sPath colour = randomBrush () :?> Brush penWidth = float32 1 rows = 10 columns = 10 } - applyGridAsync spec + applyBrushSpecGridAsync spec |> Async.RunSynchronously (File.Exists sPath) = true From bd89dd7a8a5b024f8d33bf5c69d99c6c6efbffd8 Mon Sep 17 00:00:00 2001 From: Craig Oates Date: Fri, 19 Oct 2018 18:20:46 +0100 Subject: [PATCH 03/12] add SavingTestArea unit test and script to fix it if its fails. --- DeathSocket/ImageServices.fs | 1 - TestCentre/LibraryTests.fs | 11 +++++++++++ TestCentre/Script.fsx | 22 ++++++++++++++++++++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/DeathSocket/ImageServices.fs b/DeathSocket/ImageServices.fs index 521e5ce..05e0d3c 100644 --- a/DeathSocket/ImageServices.fs +++ b/DeathSocket/ImageServices.fs @@ -35,7 +35,6 @@ // for line in verticalLines do graphics.DrawLines (pen, line) // clone.Save (spec.savePath) - // not tested but same as Draw Grid -- this is its replacement let drawBrushSpecGrid (spec: BrushSpec) = // The temp. file is used as a way to convert images with indexed pixels. use original = Bitmap.FromFile spec.originalPath diff --git a/TestCentre/LibraryTests.fs b/TestCentre/LibraryTests.fs index 5075547..d2638ef 100644 --- a/TestCentre/LibraryTests.fs +++ b/TestCentre/LibraryTests.fs @@ -113,6 +113,7 @@ open Xunit open DeathSocket open System + open System.IO (* This test is a precaution (a test for the tests if you will...). It is here to make sure the property test has what it needs to run. @@ -125,6 +126,16 @@ let imagesAreThere = if length < 100 then false else true Assert.True imagesAreThere + (* This test is a precaution. If the property tests fails, here is a + good place to start. The easiest way to get this test to pass is to + create a folder called "SavingTestArea" in this projects folder + (at the root). You can, also, see script.fs (in Test Centre) for + creating this folder via code. (See "LoadingTestArea contains..." note + for extra context. *) + [] + let ``SavingTestArea folder can be found`` () = + Assert.True (Directory.Exists saveLocation) + [] let ``Divide By Zero Exception is thrown when 0 rows is used when determining horizontal lines`` () = let result () = GridPainter.determineHorizontalLines 100 100 0 diff --git a/TestCentre/Script.fsx b/TestCentre/Script.fsx index e053c75..58283d6 100644 --- a/TestCentre/Script.fsx +++ b/TestCentre/Script.fsx @@ -14,7 +14,7 @@ let loadLocation = __SOURCE_DIRECTORY__ + "/LoadingTestArea" let saveLocation = __SOURCE_DIRECTORY__ + "/SavingTestArea" let random = Random() -(*Resetting the Testing Area Folders Scripts +(* Resetting the Testing Area Folders Scripts =============================================================================== The following scripts are for when you need to "manually" clear out the LoadingTestArea and SavingTestArea folders. If you do not want to open up the @@ -93,4 +93,22 @@ let populateLoadingTestArea () = // You should only need this once. // Make sure you have passed the above into F# Interactive. -populateLoadingTestArea () \ No newline at end of file +populateLoadingTestArea () + +(* Creating the Saving Test Area Script +============================================================================== +This bit of code is for creating the SavingTestArea folder which Test Centre +will use when it runs its tests. You will normally only need to run this code +when you have just cloned this repository or you accidently deleted said +fodler. In other words, you should only need to use it once. *) + +let createSavingTestArea () = + match Directory.Exists saveLocation with + | false -> + Directory.CreateDirectory saveLocation |> ignore + printfn "SavingTestArea created." + | _ -> printfn "SavingTestArea already exists." + +(* Before calling this function, make sure the test checking this folder exists +is failing first. *) +createSavingTestArea () \ No newline at end of file From 01e1c3b3d65d0fa6920c1ac8a3299f8f520c5c90 Mon Sep 17 00:00:00 2001 From: Craig Oates Date: Sat, 20 Oct 2018 10:11:18 +0100 Subject: [PATCH 04/12] rename unit tests which references ImageSpec to BrushSpec. --- DeathSocketCLI/Validation.fs | 2 ++ TestCentre/ConsoleTests.fs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/DeathSocketCLI/Validation.fs b/DeathSocketCLI/Validation.fs index 1225133..c0476a3 100644 --- a/DeathSocketCLI/Validation.fs +++ b/DeathSocketCLI/Validation.fs @@ -32,6 +32,8 @@ (String.Concat("The colour specifed is invalid.\n", "Please use the 'list-colours' command to see what you can use.")) + (* This function creates a consistent line width amoung different image + sizes. Use this when the user has no means to specify a pen width. *) let setPenWidth imgWidth imgHeight = let width = float32 imgWidth let height = float32 imgHeight diff --git a/TestCentre/ConsoleTests.fs b/TestCentre/ConsoleTests.fs index 056847c..32f4d0c 100644 --- a/TestCentre/ConsoleTests.fs +++ b/TestCentre/ConsoleTests.fs @@ -59,7 +59,7 @@ (setPenWidth (Random().Next()) (Random().Next())) > 0.0f [] - let ``Can build the intended default image specification`` () = + let ``Can build the intended default BrushSpec`` () = let defaultSpec = { originalPath = loadPath savePath = savePath @@ -71,7 +71,7 @@ defaultSpec = spec [] - let ``Can build an image specification as intended`` () = + let ``Can build a BrushSpec as intended`` () = let colourString = randomColourString () let brush = parseColour colourString let pWidth = float32 (Random().Next()) From c58b8f0df4b96de505821a4d80fe92721bf4af8f Mon Sep 17 00:00:00 2001 From: Craig Oates Date: Sat, 20 Oct 2018 11:26:16 +0100 Subject: [PATCH 05/12] rename colour service functions and begin writing RGBa convertion test. --- DeathSocket/ColourServices.fs | 15 ++++++++++----- DeathSocket/GridPainter.fs | 8 ++++++++ DeathSocket/ImageServices.fs | 2 +- TestCentre/LibraryTests.fs | 16 +++++++++++++--- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/DeathSocket/ColourServices.fs b/DeathSocket/ColourServices.fs index 606ca0f..3e29ee6 100644 --- a/DeathSocket/ColourServices.fs +++ b/DeathSocket/ColourServices.fs @@ -1,14 +1,19 @@ -module ColourServices +module internal ColourServices -open System.Drawing -open DeathSocket.Domain + open System.Drawing + open DeathSocket.Domain // not tested - let convertRGBAToBrush (spec: RGBASpec) = + let makeBrushFromRGBASpec (spec: RGBASpec) = let a = int spec.alpha let r = int spec.red let g = int spec.green let b = int spec.blue let colour = Color.FromArgb (a, r, g, b) - new SolidBrush(colour) + new SolidBrush (colour) + + // not tested + let makeBrushFromRGBA r g b a = + let colour = Color.FromArgb (a, r, g, b) + new SolidBrush (colour) diff --git a/DeathSocket/GridPainter.fs b/DeathSocket/GridPainter.fs index f540b30..d5e097e 100644 --- a/DeathSocket/GridPainter.fs +++ b/DeathSocket/GridPainter.fs @@ -1,6 +1,7 @@ namespace DeathSocket open System.IO + open ColourServices /// Provides functions which help draw gridded overlays onto images. /// Grid Painter, and all of Death Socket, uses the System.Drawing brushes/colours. @@ -54,6 +55,13 @@ namespace DeathSocket // let applyCMYKGridAsync -- to be added at a later date. + // not tested. + let makeSolidBrushFromRGBA r g b a = makeBrushFromRGBA r g b a + + // not tested or completed. + let makeSolidBrushFromCMYK c m y k = + "" + /// /// 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. diff --git a/DeathSocket/ImageServices.fs b/DeathSocket/ImageServices.fs index 05e0d3c..398321a 100644 --- a/DeathSocket/ImageServices.fs +++ b/DeathSocket/ImageServices.fs @@ -58,7 +58,7 @@ 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 ((convertRGBAToBrush spec), width = spec.penWidth) + 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) diff --git a/TestCentre/LibraryTests.fs b/TestCentre/LibraryTests.fs index d2638ef..152758a 100644 --- a/TestCentre/LibraryTests.fs +++ b/TestCentre/LibraryTests.fs @@ -23,7 +23,6 @@ let rand = Random () - (* These are duplicates from ConsoleTests.fs (both of them). See point about helpers. Tests for checking these locations can be found in ConsoleTests.fs. *) @@ -46,6 +45,8 @@ Intended for horizontal and vertical line tests. *) let newNum () = rand.Next(1, 1000) + let newRGBANum () = rand.Next (255) + let imagesInLoadingTestArea = Directory.GetFileSystemEntries (loadLocation, "*.png") @@ -97,6 +98,15 @@ |> Async.RunSynchronously (File.Exists sPath) = true + [] + // need to write a test which tests the colour is the same once coverted. + let ``Can make a solid brush from RGBA values`` () = + let brush = + makeSolidBrushFromRGBA (newRGBANum ()) (newRGBANum ()) (newRGBANum ()) (newRGBANum ()) + let b = brush :? SolidBrush + b = true + + [] let ``Can return a collection of points which represent a grids horizontal lines`` () = let result = determineHorizontalLines (newNum()) (newNum()) (newNum()) @@ -115,7 +125,7 @@ open System open System.IO - (* This test is a precaution (a test for the tests if you will...). + (* This test is a pre-test test (a test for the tests if you will...). It is here to make sure the property test has what it needs to run. If the property test fails, here is a good place to start. See script.fs (in Test Centre) for information on populating the @@ -126,7 +136,7 @@ let imagesAreThere = if length < 100 then false else true Assert.True imagesAreThere - (* This test is a precaution. If the property tests fails, here is a + (* This test is a pre-test test. If the property tests fails, here is a good place to start. The easiest way to get this test to pass is to create a folder called "SavingTestArea" in this projects folder (at the root). You can, also, see script.fs (in Test Centre) for From 8c403d4e2a28eb91e6b1fbeb7eba5b71dea2a1bf Mon Sep 17 00:00:00 2001 From: Craig Oates Date: Sat, 20 Oct 2018 17:59:29 +0100 Subject: [PATCH 06/12] add test which checkes the colour of solid colour brush. The colour of the brush is set using individual RGBA values. --- TestCentre/LibraryTests.fs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/TestCentre/LibraryTests.fs b/TestCentre/LibraryTests.fs index 152758a..b9dfcc3 100644 --- a/TestCentre/LibraryTests.fs +++ b/TestCentre/LibraryTests.fs @@ -99,12 +99,14 @@ (File.Exists sPath) = true [] - // need to write a test which tests the colour is the same once coverted. - let ``Can make a solid brush from RGBA values`` () = - let brush = - makeSolidBrushFromRGBA (newRGBANum ()) (newRGBANum ()) (newRGBANum ()) (newRGBANum ()) - let b = brush :? SolidBrush - b = true + let ``SolidBrush colour matches the individual RGBA values`` () = + let a = newRGBANum () + let r = newRGBANum () + let g = newRGBANum () + let b = newRGBANum () + let referenceColour = Color.FromArgb (a, r, g, b) + let brush = makeSolidBrushFromRGBA r g b a + brush.Color = referenceColour [] From 1719640dc9c1c27a61c8191df45136cf7893c0ee Mon Sep 17 00:00:00 2001 From: Craig Oates Date: Sun, 21 Oct 2018 06:56:00 +0100 Subject: [PATCH 07/12] create a public function for creating a solid brush using an RGBASpec. Add property tests for the above function. --- DeathSocket/ColourServices.fs | 2 -- DeathSocket/GridPainter.fs | 3 ++- TestCentre/LibraryTests.fs | 24 ++++++++++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/DeathSocket/ColourServices.fs b/DeathSocket/ColourServices.fs index 3e29ee6..fb7d29b 100644 --- a/DeathSocket/ColourServices.fs +++ b/DeathSocket/ColourServices.fs @@ -3,7 +3,6 @@ open System.Drawing open DeathSocket.Domain - // not tested let makeBrushFromRGBASpec (spec: RGBASpec) = let a = int spec.alpha let r = int spec.red @@ -12,7 +11,6 @@ let colour = Color.FromArgb (a, r, g, b) new SolidBrush (colour) - // not tested let makeBrushFromRGBA r g b a = let colour = Color.FromArgb (a, r, g, b) new SolidBrush (colour) diff --git a/DeathSocket/GridPainter.fs b/DeathSocket/GridPainter.fs index d5e097e..44c576e 100644 --- a/DeathSocket/GridPainter.fs +++ b/DeathSocket/GridPainter.fs @@ -55,9 +55,10 @@ namespace DeathSocket // let applyCMYKGridAsync -- to be added at a later date. - // not tested. let makeSolidBrushFromRGBA r g b a = makeBrushFromRGBA r g b a + let makeSolidBrushFromRGBASpec spec = makeBrushFromRGBASpec spec + // not tested or completed. let makeSolidBrushFromCMYK c m y k = "" diff --git a/TestCentre/LibraryTests.fs b/TestCentre/LibraryTests.fs index b9dfcc3..bb0e367 100644 --- a/TestCentre/LibraryTests.fs +++ b/TestCentre/LibraryTests.fs @@ -20,6 +20,7 @@ open System.Drawing open System.Reflection open System.IO + open DeathSocket.Domain let rand = Random () @@ -68,6 +69,18 @@ files |> Array.iter (fun f -> File.Delete(f)) + let makeTestRGBASpec r g b a = + { originalPath = "test path" + savePath = "test path" + alpha = float a + red = float r + green = float g + blue = float b + penWidth = float32 10 + rows = newNum () + columns = newNum () } + + module PropertyTests = open FsCheck.Xunit @@ -108,6 +121,17 @@ let brush = makeSolidBrushFromRGBA r g b a brush.Color = referenceColour + [] + let ``SolidBrush colour matches the RGBASpec`` () = + let a = newRGBANum () + let r = newRGBANum () + let g = newRGBANum () + let b = newRGBANum () + let referenceColour = Color.FromArgb (a, r, g, b) + let referenceSpec = makeTestRGBASpec r g b a + let brush = makeSolidBrushFromRGBASpec referenceSpec + brush.Color = referenceColour + [] let ``Can return a collection of points which represent a grids horizontal lines`` () = From b6662fc0ead184f8523dc8f7889625e23e6b015a Mon Sep 17 00:00:00 2001 From: Craig Oates Date: Sun, 21 Oct 2018 07:19:06 +0100 Subject: [PATCH 08/12] add test which checks the applyRGBAGrid function. --- DeathSocket/GridPainter.fs | 8 +++----- DeathSocket/ImageServices.fs | 1 - TestCentre/LibraryTests.fs | 29 +++++++++++++++++++++++++++-- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/DeathSocket/GridPainter.fs b/DeathSocket/GridPainter.fs index 44c576e..517eb39 100644 --- a/DeathSocket/GridPainter.fs +++ b/DeathSocket/GridPainter.fs @@ -41,7 +41,6 @@ namespace DeathSocket printfn "File could not be found at %s" ex.Message } - // Not tested. let applyRGBAGridAsync (spec: RGBASpec) = async { try @@ -53,15 +52,14 @@ namespace DeathSocket printfn "File could not be found at %s" ex.Message } - // let applyCMYKGridAsync -- to be added at a later date. - let makeSolidBrushFromRGBA r g b a = makeBrushFromRGBA r g b a let makeSolidBrushFromRGBASpec spec = makeBrushFromRGBASpec spec + // let applyCMYKGridAsync -- to be added at a later date. + // not tested or completed. - let makeSolidBrushFromCMYK c m y k = - "" + //let makeSolidBrushFromCMYK c m y k = "" /// /// Determines the (Pen) points needed to draw the appropriate number of horizontal lines (I.E. rows). diff --git a/DeathSocket/ImageServices.fs b/DeathSocket/ImageServices.fs index 398321a..1c249fd 100644 --- a/DeathSocket/ImageServices.fs +++ b/DeathSocket/ImageServices.fs @@ -51,7 +51,6 @@ for line in verticalLines do graphics.DrawLines (pen, line) clone.Save (spec.savePath) - // Not tested let drawRGBAGrid (spec: RGBASpec) = // The temp. file is used as a way to convert images with indexed pixels. use original = Bitmap.FromFile spec.originalPath diff --git a/TestCentre/LibraryTests.fs b/TestCentre/LibraryTests.fs index bb0e367..52c0b9b 100644 --- a/TestCentre/LibraryTests.fs +++ b/TestCentre/LibraryTests.fs @@ -46,6 +46,8 @@ Intended for horizontal and vertical line tests. *) let newNum () = rand.Next(1, 1000) + let newPenWidth () = rand.Next (1, 10) + let newRGBANum () = rand.Next (255) let imagesInLoadingTestArea = @@ -92,7 +94,7 @@ open System [] - let ``Can apply grid to image and save it`` () = + let ``Can apply grid to image and save it using BrushSpec`` () = (* You should end up with one image left over in SavingTestArea. Comment out the "reset" function to see all the images produced, by this test. This will mean you will need to manually delete the @@ -104,13 +106,36 @@ { originalPath = oPath savePath = sPath colour = randomBrush () :?> Brush - penWidth = float32 1 + penWidth = float32 (newPenWidth()) rows = 10 columns = 10 } applyBrushSpecGridAsync spec |> Async.RunSynchronously (File.Exists sPath) = true + [] + let ``Can apply grid to image and save it using RGBASpec`` () = + (* You should end up with one image left over in SavingTestArea. + Comment out the "reset" function to see all the images produced, + by this test. This will mean you will need to manually delete the + images yourself if you do. *) + resetSavingTestArea () + let oPath = generateLoadPath () + let sPath = generateSavePath oPath + let (spec: RGBASpec) = + { originalPath = oPath + savePath = sPath + alpha = float (newRGBANum ()) + red = float (newRGBANum ()) + green = float (newRGBANum ()) + blue = float (newRGBANum ()) + penWidth = float32 (newPenWidth()) + rows = 10 + columns = 10 } + applyRGBAGridAsync spec + |> Async.RunSynchronously + (File.Exists sPath) = true + [] let ``SolidBrush colour matches the individual RGBA values`` () = let a = newRGBANum () From 0a17bb2eedbcb7db2f9541b30503c4ed4535455e Mon Sep 17 00:00:00 2001 From: Craig Oates Date: Sun, 21 Oct 2018 07:27:07 +0100 Subject: [PATCH 09/12] update comments in Test Centre. --- TestCentre/LibraryTests.fs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/TestCentre/LibraryTests.fs b/TestCentre/LibraryTests.fs index 52c0b9b..6199435 100644 --- a/TestCentre/LibraryTests.fs +++ b/TestCentre/LibraryTests.fs @@ -26,7 +26,10 @@ (* These are duplicates from ConsoleTests.fs (both of them). See point about helpers. Tests for checking these locations can be found in - ConsoleTests.fs. *) + ConsoleTests.fs. + Also, these folders should not show up in Visual Studios + Solution Explorer -- unless you are viewing the solution in its folder + format. *) let loadLocation = __SOURCE_DIRECTORY__ + "/LoadingTestArea" let saveLocation = __SOURCE_DIRECTORY__ + "/SavingTestArea" @@ -82,7 +85,6 @@ rows = newNum () columns = newNum () } - module PropertyTests = open FsCheck.Xunit @@ -91,14 +93,14 @@ open DeathSocket.GridPainter open TestingHelpers open System.IO - open System + + (* With regards to the "saving images" tests, you should end up with + one image left over in the SavingTestArea folder. Comment out the + "reset" function to see all the images produced by this test. This will + mean you will need to manually delete the images yourself if you do. *) [] let ``Can apply grid to image and save it using BrushSpec`` () = - (* You should end up with one image left over in SavingTestArea. - Comment out the "reset" function to see all the images produced, - by this test. This will mean you will need to manually delete the - images yourself if you do. *) resetSavingTestArea () let oPath = generateLoadPath () let sPath = generateSavePath oPath @@ -115,10 +117,6 @@ [] let ``Can apply grid to image and save it using RGBASpec`` () = - (* You should end up with one image left over in SavingTestArea. - Comment out the "reset" function to see all the images produced, - by this test. This will mean you will need to manually delete the - images yourself if you do. *) resetSavingTestArea () let oPath = generateLoadPath () let sPath = generateSavePath oPath @@ -157,7 +155,6 @@ let brush = makeSolidBrushFromRGBASpec referenceSpec brush.Color = referenceColour - [] let ``Can return a collection of points which represent a grids horizontal lines`` () = let result = determineHorizontalLines (newNum()) (newNum()) (newNum()) From d6740c012e40586b5158b5e49d33966ba9b5956c Mon Sep 17 00:00:00 2001 From: Craig Oates Date: Sun, 21 Oct 2018 09:58:46 +0100 Subject: [PATCH 10/12] remove function using ImageSpec. --- DeathSocket/ImageServices.fs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/DeathSocket/ImageServices.fs b/DeathSocket/ImageServices.fs index 1c249fd..750e026 100644 --- a/DeathSocket/ImageServices.fs +++ b/DeathSocket/ImageServices.fs @@ -18,23 +18,6 @@ [| Point ((interval * point), 0) Point ((interval * point), height)|]|] - // To be deleted -- replaced with brush spec. - //let drawGrid (spec: BrushSpec) = - // // The temp. file is used as a way to convert images with indexed pixels. - // 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 drawBrushSpecGrid (spec: BrushSpec) = // The temp. file is used as a way to convert images with indexed pixels. use original = Bitmap.FromFile spec.originalPath From ee2911e07114070bfa3f2427fcab4d8a30c9b634 Mon Sep 17 00:00:00 2001 From: Craig Oates Date: Sun, 21 Oct 2018 11:25:45 +0100 Subject: [PATCH 11/12] update comments an remove obsolete functions. --- DeathSocket/Domain.fs | 34 ++------------------------ DeathSocket/GridPainter.fs | 46 ++++++++++++++++++++++++++++++------ DeathSocket/ImageServices.fs | 9 ++++--- 3 files changed, 47 insertions(+), 42 deletions(-) diff --git a/DeathSocket/Domain.fs b/DeathSocket/Domain.fs index f6f7a4a..040a157 100644 --- a/DeathSocket/Domain.fs +++ b/DeathSocket/Domain.fs @@ -5,30 +5,8 @@ module Domain = open System.Drawing - open System - /// - /// The specification used by Death Socket when adding a grid to an image. - /// - [] - type ImageSpec = - { /// The original path of the image which the grid is being added to. - originalPath: string - /// The location of the new gridded image. - savePath: string - /// The (System.Drawing) brush used to draw the grid. This determines the colour. - colour: Brush - /// The thickness of the line on the grid. - penWidth: float32 - /// The number of rows the grid will have. - rows: int - ///The number of columns the grid will have. - columns: int } - - /// /// The specification which uses System.Drawing brush to draw a grid. - /// - // REPLACING IMAGESPEC type BrushSpec = { /// The original path of the image which the grid is being added to. originalPath: string @@ -43,6 +21,8 @@ ///The number of columns the grid will have. columns: int } + /// The specification which uses includes individual RGBA values to + /// draw a grid. type RGBASpec = { originalPath: string savePath: string @@ -52,14 +32,4 @@ blue: float penWidth: float32 rows: int - columns: int } - - type CMYKSpec = - { originalPath: string - savePath: string - cyan: float - magenta: float - yellow: float - key: float32 - rows: int columns: int } \ No newline at end of file diff --git a/DeathSocket/GridPainter.fs b/DeathSocket/GridPainter.fs index 517eb39..60dfa1a 100644 --- a/DeathSocket/GridPainter.fs +++ b/DeathSocket/GridPainter.fs @@ -12,7 +12,7 @@ namespace DeathSocket open ImageServices /// - /// Uses the information included in spec and creates a gridded image. + /// Uses the information included in spec to create a gridded image. /// It then asynchronously saves it. /// Please stick to .bmp, .jpg or .png files. /// The other (image) file types have not been tested. @@ -30,7 +30,6 @@ namespace DeathSocket /// This is because it is locked whilst in this function. /// let applyBrushSpecGridAsync (spec: BrushSpec) = - // The spec is to be changed to Brush Spec. async { try validateFilePath spec.originalPath |> ignore @@ -41,6 +40,23 @@ namespace DeathSocket printfn "File could not be found at %s" ex.Message } + /// + /// Uses the information included in spec to create a gridded image. It + /// then asynchronously saves it. Please stick to .bmp, .jpg or .png + /// files. The other (image) file types have not been tested. + /// + /// + /// The specification used to generate the gridded image. + /// + /// + /// If the file the grid is being applied to cannot be found, + /// a FileNotFoundException will be thrown. + /// + /// let applyRGBAGridAsync (spec: RGBASpec) = async { try @@ -52,15 +68,31 @@ namespace DeathSocket printfn "File could not be found at %s" ex.Message } + /// + /// Creates a Sytsem.Drawing SolidBrush from the individual RGBA values. + /// + /// The red value. + /// The green value. + /// The blue value. + /// The alpha value. + /// + /// Death Socket uses System.Drawing and not System.Media for colours + /// and brushes. + /// let makeSolidBrushFromRGBA r g b a = makeBrushFromRGBA r g b a + /// + /// Creates a System.Drawing SolidBrush from a RGBASpec. + /// + /// + ///The specification which the brush is made from. + /// + /// + /// Death Socket uses System.Drawing and not System.Media for colours + /// and brushes. + /// let makeSolidBrushFromRGBASpec spec = makeBrushFromRGBASpec spec - // let applyCMYKGridAsync -- to be added at a later date. - - // not tested or completed. - //let makeSolidBrushFromCMYK c m y k = "" - /// /// 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. diff --git a/DeathSocket/ImageServices.fs b/DeathSocket/ImageServices.fs index 750e026..8babd60 100644 --- a/DeathSocket/ImageServices.fs +++ b/DeathSocket/ImageServices.fs @@ -3,7 +3,6 @@ open System.Drawing open System.Drawing.Imaging open DeathSocket - open Validation open ColourServices let createHorizontalLines width height rows = @@ -18,8 +17,13 @@ [| Point ((interval * point), 0) Point ((interval * point), height)|]|] + (* 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 listig them all, just assume any function + with a "*Spec" type as a parameter will use this "temp" file. *) + let drawBrushSpecGrid (spec: BrushSpec) = - // The temp. file is used as a way to convert images with indexed pixels. 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) @@ -35,7 +39,6 @@ clone.Save (spec.savePath) let drawRGBAGrid (spec: RGBASpec) = - // The temp. file is used as a way to convert images with indexed pixels. 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) From ee06f141d56af7da34b558217b5847dee50983d7 Mon Sep 17 00:00:00 2001 From: "OPTIMUS-PRIME\\craig" Date: Fri, 26 Oct 2018 16:45:54 +0100 Subject: [PATCH 12/12] update build info. to 0.4 and add XML comments to RGBASpec. --- DeathSocket/DeathSocket.fsproj | 15 +++++++++++++++ DeathSocket/Domain.fs | 12 +++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/DeathSocket/DeathSocket.fsproj b/DeathSocket/DeathSocket.fsproj index a4e484c..80d6bb6 100644 --- a/DeathSocket/DeathSocket.fsproj +++ b/DeathSocket/DeathSocket.fsproj @@ -2,6 +2,21 @@ netstandard2.0 + true + true + 0.4-alpha + Craig Oates + Death Socket + A .Net Standard library which you can plug into to project and draw gridded overlays onto you images. Please note, Death Socket uses System.Drawing brushes and not System.Media brushes. For futher information, visit the projects repository on GitHub. To get a sense of what Death Socket can do, there is a console program you can download seperately (on GitHub). + https://github.com/CraigOates/Death-Socket/tree/master + https://github.com/CraigOates/Death-Socket/blob/master/LICENSE + + Craig Oates + https://github.com/CraigOates/Death-Socket/tree/master + Git + deathsocket craig oates image overlay f# + This release has renamed the ImageSpec to BrushSpec and added a new RGBASpec type. The RGBASpec allows the user to pass in individual RGBA values instead of creating a SolidBrush before adding it to the BrushSpec. +New functions have been added so you can now create a SolidBrush using individual RGBA values or an RGBASpec -- you do not need to do it yourself. Another "apply grid" function has been added , as well, which uses the new RGBASpec. diff --git a/DeathSocket/Domain.fs b/DeathSocket/Domain.fs index 040a157..ae4a174 100644 --- a/DeathSocket/Domain.fs +++ b/DeathSocket/Domain.fs @@ -24,12 +24,22 @@ /// The specification which uses includes individual RGBA values to /// draw a grid. type RGBASpec = - { originalPath: string + { /// The original path of the image which the grid is being added to. + originalPath: string + /// The location of the new gridded image. savePath: string + /// The opacity level of the grid. + /// 0 makes it completely see through and 1 makes it solid. alpha: float + /// The amount of red the grid's line will have. red: float + /// The amount of green the grid's line will have. green: float + /// The amount of blue the grid's line will have. blue: float + /// The thickness of the line on the grid. penWidth: float32 + /// 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