Compare commits

...

6 Commits

Author SHA1 Message Date
Craig Oates bcbb731d41 update library build number to 2020.07.23.1. 4 years ago
Craig Oates 896130a11b update tests and Scratch Pad script. 4 years ago
Craig Oates 507da455bf add grey scale functionality to RGBASpec image type. 4 years ago
Craig Oates 3abf3d3cd7 stub-out drawRGBAGridGrey functionality. 4 years ago
Craig Oates 77f198ffcc refactor applyGridToImageAsync (utilise greyScale better). 4 years ago
Craig Oates b7cd421323 implement rough initial version of convert to greyscale. 4 years ago
  1. 10
      DeathSocket/DeathSocket.fsproj
  2. 14
      DeathSocket/GridPainter.fs
  3. 72
      DeathSocket/ImageServices.fs
  4. 12
      DeathSocket/ScratchPad.fsx
  5. 30
      DeathSocketCLI/Commands.fs
  6. 15
      TestCentre/LibraryTests.fs

10
DeathSocket/DeathSocket.fsproj

@ -4,7 +4,7 @@
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Version>2.0.0.0</Version> <Version>2020.07.23.1</Version>
<Authors>Craig Oates</Authors> <Authors>Craig Oates</Authors>
<Product>Death Socket</Product> <Product>Death Socket</Product>
<Description>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.</Description> <Description>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.</Description>
@ -16,9 +16,9 @@
<RepositoryType>Git</RepositoryType> <RepositoryType>Git</RepositoryType>
<PackageTags>deathsocket grid image overlay f#</PackageTags> <PackageTags>deathsocket grid image overlay f#</PackageTags>
<PackageReleaseNotes>A minor release. The change from 1.x to 2.x is to signify the changing of the projects versioning control system, from GitLab to git.abbether. The projects package information and its NuGet dependencies have been updated.</PackageReleaseNotes> <PackageReleaseNotes>A minor release. The change from 1.x to 2.x is to signify the changing of the projects versioning control system, from GitLab to git.abbether. The projects package information and its NuGet dependencies have been updated.</PackageReleaseNotes>
<AssemblyVersion>2.0.0.0</AssemblyVersion> <AssemblyVersion>2020.07.23.1</AssemblyVersion>
<PackageIconUrl></PackageIconUrl> <PackageIconUrl></PackageIconUrl>
<FileVersion>2.0.0.0</FileVersion> <FileVersion>2020.07.23.1</FileVersion>
<DependsOnNETStandard>true</DependsOnNETStandard> <DependsOnNETStandard>true</DependsOnNETStandard>
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageIcon>death-socket-repo-logo.png</PackageIcon> <PackageIcon>death-socket-repo-logo.png</PackageIcon>
@ -32,7 +32,7 @@
<Compile Include="ImagePrep.fs" /> <Compile Include="ImagePrep.fs" />
<Compile Include="ImageServices.fs" /> <Compile Include="ImageServices.fs" />
<Compile Include="GridPainter.fs" /> <Compile Include="GridPainter.fs" />
<None Include="..\..\..\_temp\death-socket-repo-logo.png"> <None Include="..\..\..\_projects\death-socket\death-socket-repo-logo.png">
<Pack>True</Pack> <Pack>True</Pack>
<PackagePath></PackagePath> <PackagePath></PackagePath>
</None> </None>
@ -46,7 +46,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Update="FSharp.Core" Version="4.7.0" /> <PackageReference Update="FSharp.Core" Version="4.7.2" />
</ItemGroup> </ItemGroup>
</Project> </Project>

14
DeathSocket/GridPainter.fs

@ -34,22 +34,26 @@ namespace DeathSocket
/// is not in use or needed by another program/process. /// is not in use or needed by another program/process.
/// This is because it is locked whilst in this function. /// This is because it is locked whilst in this function.
/// </remarks> /// </remarks>
let applyGridToImageAsync (spec: ImageSpec) = let applyGridToImageAsync (makeGreyScale: bool) (spec: ImageSpec) =
async { async {
try try
match spec with match spec with
| Brush b -> | Brush b ->
validateIO b.originalPath b.savePath |> ignore validateIO b.originalPath b.savePath |> ignore
drawBrushSpecGrid b match makeGreyScale with
| true -> drawBrushSpecGridGrey b
| false -> drawBrushSpecGrid b
| RGBA r -> | RGBA r ->
validateIO r.originalPath r.savePath |> ignore validateIO r.originalPath r.savePath |> ignore
drawRGBAGrid r match makeGreyScale with
| true -> drawRGBAGridGrey r
| false -> drawRGBAGrid r
| Skia s -> | Skia s ->
validateIO s.originalPath s.savePath |> ignore validateIO s.originalPath s.savePath |> ignore
drawSkiaGrid s drawSkiaGrid s // greyScale not implemented
| SkiaRGB sR -> | SkiaRGB sR ->
validateIO sR.originalPath sR.savePath |> ignore validateIO sR.originalPath sR.savePath |> ignore
drawSkiaRGBGrid sR drawSkiaRGBGrid sR // greyScale not implemented
| _ -> printfn "[DEATH SOCKET INFO] Inappropriate ImageSpec used here. Please use none buffer-based spec's when using this function." | _ -> printfn "[DEATH SOCKET INFO] Inappropriate ImageSpec used here. Please use none buffer-based spec's when using this function."
with with
| :? FileNotFoundException as ex -> | :? FileNotFoundException as ex ->

72
DeathSocket/ImageServices.fs

@ -191,14 +191,45 @@
assume any function with a "*Spec" type as a parameter will use this "temp" assume any function with a "*Spec" type as a parameter will use this "temp"
file. *) file. *)
let drawBrushSpecGridGrey (spec: BrushSpec) =
(* Found this code for this function at:
https://stackoverflow.com/questions/199468/c-sharp-image-clone-out-of-memory-exception *)
use original = Bitmap.FromFile spec.originalPath
use temp = new Bitmap(original)
use clone = new Bitmap(temp.Width, temp.Height)
use g = Graphics.FromImage(clone)
let aM: float32[][] = [|
[| (float32 0.3); (float32 0.3); (float32 0.3); (float32 0.0); (float32 0.0) |];
[| (float32 0.59); (float32 0.59); (float32 0.59); (float32 0.0); (float32 0.0) |];
[| (float32 0.11); (float32 0.11); (float32 0.11); (float32 0.0); (float32 0.0) |];
[| (float32 0.0); (float32 0.0); (float32 0.0); (float32 1.0); (float32 0.0) |];
[| (float32 0.0); (float32 0.0); (float32 0.0); (float32 0.0); (float32 1.0) |];
|]
let colourMatrix = new ColorMatrix(aM)
use attributes = new ImageAttributes()
attributes.SetColorMatrix(colourMatrix)
g.DrawImage(temp, new Rectangle(0, 0, temp.Width, temp.Height),
0, 0, temp.Width, temp.Height, GraphicsUnit.Pixel, attributes)
use graphics = Graphics.FromImage(clone)
use pen = new Pen (spec.colour, width = spec.penWidth)
graphics.DrawImage(clone ,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) = let drawBrushSpecGrid (spec: BrushSpec) =
use original = Bitmap.FromFile spec.originalPath use original = Bitmap.FromFile spec.originalPath
use temp = new Bitmap(original) use temp = new Bitmap(original)
use clone = use clone = temp.Clone(new Rectangle(0, 0, temp.Width, temp.Height), PixelFormat.Format32bppArgb)
temp.Clone(new Rectangle(0, 0, temp.Width, temp.Height), PixelFormat.Format32bppArgb)
use graphics = Graphics.FromImage(clone) use graphics = Graphics.FromImage(clone)
use pen = new Pen (spec.colour, width = spec.penWidth) use pen = new Pen (spec.colour, width = spec.penWidth)
graphics.DrawImage(original,new Rectangle(0, 0, clone.Width, clone.Height)) graphics.DrawImage(clone ,new Rectangle(0, 0, clone.Width, clone.Height))
let horizontalLines = let horizontalLines =
createHorizontalLines (clone.Size.Width) (clone.Size.Height) (spec.rows) createHorizontalLines (clone.Size.Width) (clone.Size.Height) (spec.rows)
let verticalLines = let verticalLines =
@ -221,4 +252,39 @@
createVerticalLines (clone.Size.Width) (clone.Size.Height) (spec.columns) createVerticalLines (clone.Size.Width) (clone.Size.Height) (spec.columns)
for line in horizontalLines do graphics.DrawLines (pen, line) for line in horizontalLines do graphics.DrawLines (pen, line)
for line in verticalLines do graphics.DrawLines (pen, line) for line in verticalLines do graphics.DrawLines (pen, line)
clone.Save (spec.savePath)
let drawRGBAGridGrey (spec: RGBASpec) =
// This part converts the images to greyscale.
use original = Bitmap.FromFile spec.originalPath
use temp = new Bitmap (original)
use clone = new Bitmap(temp.Width, temp.Height)
use g = Graphics.FromImage(clone)
// This can be refactored out into its own function or reachable from
// anywhere in this module. It's used more than once and doesn't use 'use'.
let aM: float32[][] = [|
[| (float32 0.3); (float32 0.3); (float32 0.3); (float32 0.0); (float32 0.0) |];
[| (float32 0.59); (float32 0.59); (float32 0.59); (float32 0.0); (float32 0.0) |];
[| (float32 0.11); (float32 0.11); (float32 0.11); (float32 0.0); (float32 0.0) |];
[| (float32 0.0); (float32 0.0); (float32 0.0); (float32 1.0); (float32 0.0) |];
[| (float32 0.0); (float32 0.0); (float32 0.0); (float32 0.0); (float32 1.0) |];
|]
let colourMatrix = new ColorMatrix(aM) // Maybe put in own function?
use attributes = new ImageAttributes()
attributes.SetColorMatrix(colourMatrix)
g.DrawImage(temp, new Rectangle(0, 0, temp.Width, temp.Height),
0, 0, temp.Width, temp.Height, GraphicsUnit.Pixel, attributes)
use graphics = Graphics.FromImage(clone)
// This part applies the grid.
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) clone.Save (spec.savePath)

12
DeathSocket/ScratchPad.fsx

@ -51,6 +51,10 @@ let dimensions =
// Change the line thickness (the last parameter) to whatever you want. // Change the line thickness (the last parameter) to whatever you want.
let scaledPen = GridPainter.scaleLineThickness (100, 100) dimensions 8.0 let scaledPen = GridPainter.scaleLineThickness (100, 100) dimensions 8.0
(* THE CODE BELOW DOES NOT INCLUDE THE GREY SCALE FUNCTIONALITY.
I HAVE JUST PLACE 'FALSE' IN PLACE. THE GREY SCALE OPTIONS WILL NEED ADDING
AT SOME POINT. WHEN THAT IS DONE, DELETE THIS COMMENT.*)
// Brush Specification (uses System.Drawing) // Brush Specification (uses System.Drawing)
Brush ({ originalPath = desktop + "/test.jpg" Brush ({ originalPath = desktop + "/test.jpg"
savePath = desktop + "/grid.png" savePath = desktop + "/grid.png"
@ -58,7 +62,7 @@ Brush ({ originalPath = desktop + "/test.jpg"
penWidth = (float32 1) penWidth = (float32 1)
rows = 10 rows = 10
columns = 10 }) columns = 10 })
|> GridPainter.applyGridToImageAsync |> GridPainter.applyGridToImageAsync false
|> Async.Start |> Async.Start
// RGBA Specification (uses System.Drawing) // RGBA Specification (uses System.Drawing)
@ -71,7 +75,7 @@ RGBA ({ originalPath = desktop + "/test.jpg"
penWidth = (float32 1) penWidth = (float32 1)
rows = 10 rows = 10
columns = 10 }) columns = 10 })
|> GridPainter.applyGridToImageAsync |> GridPainter.applyGridToImageAsync false
|> Async.Start |> Async.Start
// Skia Specification (uses SkiaSharp -- use with Xamarin) // Skia Specification (uses SkiaSharp -- use with Xamarin)
@ -81,7 +85,7 @@ Skia ({ originalPath = desktop + "/test.jpg"
penWidth = (float32 1) penWidth = (float32 1)
rows = 10 rows = 10
columns = 10}) columns = 10})
|> GridPainter.applyGridToImageAsync |> GridPainter.applyGridToImageAsync false
|> Async.Start |> Async.Start
// SkiaRGB Specification (uses SkiaSharp -- use with Xamarin) // SkiaRGB Specification (uses SkiaSharp -- use with Xamarin)
@ -93,5 +97,5 @@ SkiaRGB ({ originalPath = desktop + "/test.jpg"
penWidth = (float32 1) penWidth = (float32 1)
rows = 10 rows = 10
columns = 10}) columns = 10})
|> GridPainter.applyGridToImageAsync |> GridPainter.applyGridToImageAsync false
|> Async.Start |> Async.Start

30
DeathSocketCLI/Commands.fs

@ -32,15 +32,15 @@
let exit () = Environment.Exit (Environment.ExitCode) let exit () = Environment.Exit (Environment.ExitCode)
[<ListCommand>] [<ListCommand>]
[<Parameters "(image-path: string) (new-path: string)">] [<Parameters "(image-path: string) (new-path: string) (greyScale: bool)">]
[<Description [<Description
"Takes the image at 'image-path' applies a 10x10 grid (in white) to it and saves the result at 'new-path'.">] "Takes the image at 'image-path' applies a 10x10 grid (in white) to it and saves the result at 'new-path'.">]
[<Usage "add-default C:/base-image.png C:/final-image.png">] [<Usage "add-default C:/base-image.png C:/final-image.png true">]
let ``add-default`` imgPath newPath = let ``add-default`` imgPath newPath greyScale=
try try
printfn "[INFO.] Adding default grid to image..." printfn "[INFO.] Adding default grid to image..."
Brush (buildDefaultSpec imgPath newPath) Brush (buildDefaultSpec imgPath newPath)
|> applyGridToImageAsync |> applyGridToImageAsync greyScale
|> Async.Start |> Async.Start
showEndOfCommandMessage showEndOfCommandMessage
with with
@ -51,15 +51,15 @@
[<ListCommand>] [<ListCommand>]
[<Parameters [<Parameters
("(image-path: string) (no-of-rows: int) (no-of-columns: int) " + ("(image-path: string) (no-of-rows: int) (no-of-columns: int) " +
"(pen-width: float32) (colour: string) (new-path: string)")>] "(pen-width: float32) (colour: string) (new-path: string) (greyScale: bool)")>]
[<Description "Adds a grid to an image, using the specified parameters, and saves it.">] [<Description "Adds a grid to an image, using the specified parameters, and saves it.">]
[<Usage [<Usage
"add-grid C:/orignal-image.png 10 5 2 red C:/new-image.png">] "add-grid C:/orignal-image.png 10 5 2 red C:/new-image.png true">]
let ``add-grid`` imgPath numRows numColumns pWidth colour newPath = let ``add-grid`` imgPath numRows numColumns pWidth colour newPath greyScale =
try try
printfn "[INFO.] Adding grid to image..." printfn "[INFO.] Adding grid to image..."
Brush (buildSpec imgPath numRows numColumns pWidth colour newPath) Brush (buildSpec imgPath numRows numColumns pWidth colour newPath)
|> applyGridToImageAsync |> applyGridToImageAsync greyScale
|> Async.Start |> Async.Start
showEndOfCommandMessage showEndOfCommandMessage
with with
@ -87,10 +87,10 @@
hosted alongside the repository on GitHub. hosted alongside the repository on GitHub.
URL: https://github.com/CraigOates/Death-Socket/wiki *) URL: https://github.com/CraigOates/Death-Socket/wiki *)
let ad imgPath newPath = ``add-default`` imgPath newPath let ad imgPath newPath greyScale = ``add-default`` imgPath newPath greyScale
let ag imgPath numRows numColumns pWidth colour newPath = let ag imgPath numRows numColumns pWidth colour newPath greyScale =
``add-grid`` imgPath numRows numColumns pWidth colour newPath ``add-grid`` imgPath numRows numColumns pWidth colour newPath greyScale
let lc () = ``list-colours`` () let lc () = ``list-colours`` ()
@ -109,16 +109,16 @@
printfn "%s" item.Key printfn "%s" item.Key
showEndOfCommandMessage showEndOfCommandMessage
let``add-skia-grid`` imgPath numRows numColumns pWidth colour newPath = let``add-skia-grid`` imgPath numRows numColumns pWidth colour newPath greyScale=
printfn "[INFO.] Adding SkiaSharp grid to image..." printfn "[INFO.] Adding SkiaSharp grid to image..."
Skia (buildSkiaSpec imgPath numRows numColumns pWidth colour newPath) Skia (buildSkiaSpec imgPath numRows numColumns pWidth colour newPath)
|> applyGridToImageAsync |> applyGridToImageAsync greyScale // Not implement in this context.
|> Async.Start |> Async.Start
showEndOfCommandMessage showEndOfCommandMessage
let``add-skia-rgb-grid`` imgPath numRows numColumns pWidth r g b newPath = let``add-skia-rgb-grid`` imgPath numRows numColumns pWidth r g b newPath greyScale =
printfn "[INFO.] Adding SkiaSharp grid to image..." printfn "[INFO.] Adding SkiaSharp grid to image..."
SkiaRGB (buildSkiaRGBSpec imgPath numRows numColumns pWidth r g b newPath) SkiaRGB (buildSkiaRGBSpec imgPath numRows numColumns pWidth r g b newPath)
|> applyGridToImageAsync |> applyGridToImageAsync greyScale // Not implement in this context.
|> Async.Start |> Async.Start
showEndOfCommandMessage showEndOfCommandMessage

15
TestCentre/LibraryTests.fs

@ -73,6 +73,13 @@
Intended for horizontal and vertical line tests. *) Intended for horizontal and vertical line tests. *)
let newNum () = rand.Next(1, 1000) let newNum () = rand.Next(1, 1000)
// Used mostly for making the image grey scale when add a grid to it.
let newBool() =
let num = rand.NextDouble()
match num with
| x when num < 0.5 -> true
| _ -> false
let newPenWidth () = rand.Next (1, 10) let newPenWidth () = rand.Next (1, 10)
let newRGBANum () = rand.Next (255) let newRGBANum () = rand.Next (255)
@ -134,7 +141,7 @@
penWidth = float32 (newPenWidth()) penWidth = float32 (newPenWidth())
rows = 10 rows = 10
columns = 10 }) columns = 10 })
|> applyGridToImageAsync |> applyGridToImageAsync (newBool())
|> Async.RunSynchronously |> Async.RunSynchronously
(File.Exists sPath) = true (File.Exists sPath) = true
@ -152,7 +159,7 @@
penWidth = float32 (newPenWidth()) penWidth = float32 (newPenWidth())
rows = 10 rows = 10
columns = 10 }) columns = 10 })
|> applyGridToImageAsync |> applyGridToImageAsync (newBool())
|> Async.RunSynchronously |> Async.RunSynchronously
(File.Exists sPath) = true (File.Exists sPath) = true
@ -199,7 +206,7 @@
penWidth = float32 (newPenWidth()) penWidth = float32 (newPenWidth())
rows = newNum () rows = newNum ()
columns = newNum () }) columns = newNum () })
|> applyGridToImageAsync |> applyGridToImageAsync (newBool())
|> Async.RunSynchronously |> Async.RunSynchronously
(File.Exists sPath) = true (File.Exists sPath) = true
@ -217,7 +224,7 @@
penWidth = float32 (newPenWidth()) penWidth = float32 (newPenWidth())
rows = newNum () rows = newNum ()
columns = newNum () }) columns = newNum () })
|> applyGridToImageAsync |> applyGridToImageAsync (newBool())
|> Async.RunSynchronously |> Async.RunSynchronously
(File.Exists sPath) = true (File.Exists sPath) = true

Loading…
Cancel
Save