Browse Source

Merge pull request #4 from CraigOates/0.3

0.3
master
Craig Oates 6 years ago committed by GitHub
parent
commit
579e48070e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 29
      DeathSocket/Domain.fs
  2. 53
      DeathSocket/GridPainter.fs
  3. 20
      DeathSocket/ImageServices.fs
  4. 13
      DeathSocket/Validation.fs
  5. 8
      DeathSocketCLI/Commands.fs
  6. 4
      DeathSocketCLI/Validation.fs
  7. 44
      TestCentre/LibraryTests.fs
  8. 2
      TestCentre/Script.fsx

29
DeathSocket/Domain.fs

@ -1,23 +1,24 @@
namespace DeathSocket
/// The domain types used by Death Socket.
[<AutoOpen>]
module Domain =
open System.Drawing
open System.Drawing.Imaging
/// <summary>
/// The specification used by Death Socket when adding a grid to an image.
/// </summary>
type ImageSpec =
{ originalPath: string;
savePath: string;
colour: Brush;
penWidth: float32
rows: int;
columns: int }
type StreamSpec =
{ imagePath: string;
format: ImageFormat;
colour: Brush;
penWidth: float32
rows: int;
{ /// 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 }

53
DeathSocket/GridPainter.fs

@ -2,16 +2,61 @@ namespace DeathSocket
open System.IO
/// Provides functions which help draw gridded overlays onto images.
/// Grid Painter, and all of Death Socket, uses the System.Drawing brushes/colours.
/// If you are using System.Media brushes and colour, you will need to convert them.
module GridPainter =
open Validation
open ImageServices
let applyGrid spec =
/// <summary>
/// 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.
/// </summary>
/// <param name="spec">
/// The specification used to generate the new gridded image
/// </param>
/// <exeption cref="System.IO.FileNotFoundException">
/// If the file the grid is being applied to cannot be found,
/// a FileNotFoundException will be thrown.
/// </exception>
/// <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 applyGridAsync spec =
async {
try
validateFilePath |> ignore
validateFilePath spec.originalPath |> ignore
validatFileType spec.savePath |> ignore
drawGrid spec |> ignore
with
| :? FileNotFoundException as ex -> printfn "File could not be found at %s" ex.Message
}
| :? FileNotFoundException as ex ->
printfn "File could not be found at %s" ex.Message
}
/// <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.
/// </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 height rows =
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.
/// </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 height columns =
createVerticalLines width height columns

20
DeathSocket/ImageServices.fs

@ -17,15 +17,17 @@
Point ((interval * point), height)|]|]
let drawGrid spec =
let img = Bitmap.FromFile spec.originalPath
let graphics = Graphics.FromImage img
let pen = new Pen (spec.colour, width = spec.penWidth)
// 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 (img.Size.Width) (img.Size.Height) (spec.columns)
let verticalLines = createVerticalLines (img.Size.Width) (img.Size.Height) (spec.columns)
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)
img.Save (spec.savePath, ImageFormat.Png)
img.Dispose ()
graphics.Dispose ()
pen.Dispose ()
clone.Save (spec.savePath)

13
DeathSocket/Validation.fs

@ -1,9 +1,20 @@
module internal Validation
open System.IO
open System.IO
let validateFilePath path =
match File.Exists path with
| true -> ()
| false -> raise (new FileNotFoundException (path + " could not be found."))
let validatFileType file =
match Path.GetExtension file with
| ".bmp" -> ()
| ".BMP" -> ()
| ".jpg" -> ()
| ".JPG" -> ()
| ".png" -> ()
| ".PNG" -> ()
| ".tif" -> ()
| ".TIF" -> ()
| _ -> invalidArg "savePath" "The file type must be a .bmp, .jpg, .png or .tif file."

8
DeathSocketCLI/Commands.fs

@ -38,8 +38,8 @@
try
printfn "[INFO.] Adding default grid to image..."
buildDefaultSpec imgPath newPath
|> applyGrid
|> Async.RunSynchronously
|> applyGridAsync
|> Async.Start
showEndOfCommandMessage
with
| :? FileNotFoundException as ex -> "[ERROR] No file was found at " + ex.FileName
@ -57,8 +57,8 @@
try
printfn "[INFO.] Adding grid to image..."
buildSpec imgPath numRows numColumns pWidth colour newPath
|> applyGrid
|> Async.RunSynchronously
|> applyGridAsync
|> Async.Start
showEndOfCommandMessage
with
| :? FileNotFoundException as ex -> "[ERROR] No file was found at " + ex.FileName

4
DeathSocketCLI/Validation.fs

@ -48,8 +48,8 @@
columns = numColumns }
let buildDefaultSpec imgPath newPath =
let stream = new FileStream (imgPath, FileMode.Open)
let image = Image.FromStream (stream, false, false)
use stream = new FileStream (imgPath, FileMode.Open)
use image = Image.FromStream (stream, false, false)
let spec =
{ originalPath = imgPath
savePath = newPath

44
TestCentre/LibraryTests.fs

@ -21,9 +21,12 @@
open System.Reflection
open System.IO
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.*)
ConsoleTests.fs. *)
let loadLocation = __SOURCE_DIRECTORY__ + "/LoadingTestArea"
let saveLocation = __SOURCE_DIRECTORY__ + "/SavingTestArea"
@ -35,14 +38,18 @@
|> Seq.toArray
let randomBrush () =
let item = allColours.[Random().Next(allColours.Length)]
let item = allColours.[rand.Next(allColours.Length)]
item.GetValue(null, null)
(* Max. value is arbitrary (change for performance).
Min. value is to stop divide by zero exceptions.
Intended for horizontal and vertical line tests. *)
let newNum () = rand.Next(1, 1000)
let imagesInLoadingTestArea =
Directory.GetFileSystemEntries (loadLocation, "*.png")
let generateLoadPath () =
let rand = Random ()
let files = imagesInLoadingTestArea
files.[rand.Next(files.Length)]
@ -51,7 +58,7 @@
saveLocation + "/" + fileName
(* To "manually" clear out the SavingTestArea folder, use this function
in script.fsx. More information can be found there, also.*)
in script.fsx. More information can be found there, also. *)
let resetSavingTestArea () =
let files = Directory.GetFileSystemEntries(saveLocation, "*.png")
match files.Length with
@ -68,13 +75,14 @@
open DeathSocket.GridPainter
open TestingHelpers
open System.IO
open System
[<Property>]
let ``Can apply grid to image and save it`` () =
(* 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.*)
images yourself if you do. *)
resetSavingTestArea ()
let oPath = generateLoadPath ()
let sPath = generateSavePath oPath
@ -85,14 +93,26 @@
penWidth = float32 1
rows = 10
columns = 10 }
applyGrid spec
applyGridAsync spec
|> Async.RunSynchronously
(File.Exists sPath) = true
[<Property>]
let ``Can return a collection of points which represent a grids horizontal lines`` () =
let result = determineHorizontalLines (newNum()) (newNum()) (newNum())
result.Length > 0
[<Property>]
let ``Can return a collection of points which represent a grids vertical lines`` () =
let result = determineVerticalLines (newNum()) (newNum()) (newNum())
result.Length > 0
module UnitTests =
open TestingHelpers
open Xunit
open DeathSocket
open System
(* 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.
@ -103,4 +123,14 @@
let ``LoadingTestArea contains at least 100 test images`` () =
let length = imagesInLoadingTestArea.Length
let imagesAreThere = if length < 100 then false else true
Assert.True imagesAreThere
Assert.True imagesAreThere
[<Fact>]
let ``Divide By Zero Exception is thrown when 0 rows is used when determining horizontal lines`` () =
let result () = GridPainter.determineHorizontalLines 100 100 0
Assert.Throws<DivideByZeroException>(fun () -> result () |> ignore)
[<Fact>]
let ``Divide By Zero Exception is thrown when 0 columns is used when determining vertical lines`` () =
let result () = GridPainter.determineVerticalLines 100 100 0
Assert.Throws<DivideByZeroException>(fun () -> result () |> ignore)

2
TestCentre/Script.fsx

@ -44,7 +44,7 @@ resetLoadingTestArea ()
(* Populating LoadingTestArea Folder Scripts
===============================================================================
The following scripts are to help you populate a test folder of images.
The following scripts are to help you populate a test folder with test images.
You can then use these images in LibraryTests.fs -- Property Tests.
The tests consists of loading images from LoadingTestArea, transforming them
and saving them in SavingTestArea. *)

Loading…
Cancel
Save