Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

#2 added Enhance.Imaging with CropAndStraighten *enhancer*

  • Loading branch information...
commit 34eeae1e41af5e6ad15dcee6ce63b64ab2a0f63b 1 parent a904828
Jesper Larsen-Ledet authored
43 src/Enhance.Imaging/BitmapExtensions.cs
... ... @@ -0,0 +1,43 @@
  1 +using System;
  2 +using System.ComponentModel;
  3 +using System.Windows;
  4 +using System.Windows.Media.Imaging;
  5 +
  6 +namespace Enhance.Imaging
  7 +{
  8 + ///<summary>
  9 + /// Contains extension methods for System.Drawing.Bitmap classes
  10 + ///</summary>
  11 + public static class BitmapExtensions
  12 + {
  13 + ///<summary>
  14 + /// Converts a System.Drawing.Bitmap to a System.Windows.Media.Imaging.BitmapSource
  15 + ///</summary>
  16 + ///<param name="source">The bitmap to convert</param>
  17 + ///<returns>The converted bitmap</returns>
  18 + public static BitmapSource ToBitmapSource(this System.Drawing.Bitmap source)
  19 + {
  20 + var bitmapHandle = IntPtr.Zero;
  21 + try
  22 + {
  23 + bitmapHandle = source.GetHbitmap();
  24 + var result = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bitmapHandle, IntPtr.Zero, Int32Rect.Empty,
  25 + BitmapSizeOptions.FromEmptyOptions());
  26 + result.Freeze();
  27 + source.Dispose();
  28 + return result;
  29 + }
  30 + catch (Win32Exception ex)
  31 + {
  32 + throw new ImagingException("Failed to create BitmapSource", ex);
  33 + }
  34 + finally
  35 + {
  36 + if (bitmapHandle != IntPtr.Zero)
  37 + {
  38 + NativeMethods.DeleteObject(bitmapHandle);
  39 + }
  40 + }
  41 + }
  42 + }
  43 +}
71 src/Enhance.Imaging/CropAndStraighten.cs
... ... @@ -0,0 +1,71 @@
  1 +using System.Collections.Generic;
  2 +using System.Drawing;
  3 +using System.Drawing.Imaging;
  4 +using System.Linq;
  5 +using AForge.Imaging;
  6 +using AForge.Imaging.Filters;
  7 +
  8 +namespace Enhance.Imaging
  9 +{
  10 + /// <summary>
  11 + /// Extracts, crops, and straightens multiple images in a single scan and returns each as separate bitmaps
  12 + /// </summary>
  13 + public class CropAndStraighten
  14 + {
  15 + public IEnumerable<Bitmap> Apply(Bitmap bitmap)
  16 + {
  17 + // assuming scanned background is white we need to invert for the algo to work
  18 + var copy = new Invert().Apply(bitmap);
  19 +
  20 + copy = EnsureGrayscale(copy);
  21 + new Threshold { ThresholdValue = 25 }.ApplyInPlace(copy);
  22 + new FillHoles().ApplyInPlace(copy);
  23 +
  24 + var blobCounter = new BlobCounter
  25 + {
  26 + // set filtering options
  27 + FilterBlobs = true,
  28 + MinWidth = 50,
  29 + MinHeight = 50,
  30 + };
  31 +
  32 + blobCounter.ProcessImage(copy);
  33 + var blobs = blobCounter.GetObjectsInformation();
  34 +
  35 + if (blobs.Any())
  36 + {
  37 + var invertedOriginal = new Invert().Apply(bitmap);
  38 + foreach (var blob in blobs)
  39 + {
  40 + // use inverted source to ensure correct edge colors
  41 + blobCounter.ExtractBlobsImage(invertedOriginal, blob, false);
  42 + var blobImage = blob.Image.ToManagedImage();
  43 +
  44 + // straighten
  45 + var angle = new DocumentSkewChecker().GetSkewAngle(EnsureGrayscale(blobImage));
  46 + var rotationFilter = new RotateBilinear(-angle) { FillColor = Color.Black };
  47 + blobImage = rotationFilter.Apply(blobImage);
  48 +
  49 + // crop
  50 + blobImage = new ExtractBiggestBlob().Apply(blobImage);
  51 +
  52 + new Invert().ApplyInPlace(blobImage);
  53 + yield return blobImage;
  54 + }
  55 + }
  56 + else
  57 + {
  58 + yield return bitmap;
  59 + }
  60 +
  61 + }
  62 +
  63 + /// <summary>
  64 + /// Make image grayscale if it isn't already. Does not ensure you get a copy
  65 + /// </summary>
  66 + private static Bitmap EnsureGrayscale(Bitmap source)
  67 + {
  68 + return source.PixelFormat == PixelFormat.Format8bppIndexed ? source : Grayscale.CommonAlgorithms.BT709.Apply(source);
  69 + }
  70 + }
  71 +}
75 src/Enhance.Imaging/Enhance.Imaging.csproj
... ... @@ -0,0 +1,75 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  3 + <PropertyGroup>
  4 + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
  5 + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
  6 + <ProductVersion>8.0.30703</ProductVersion>
  7 + <SchemaVersion>2.0</SchemaVersion>
  8 + <ProjectGuid>{070B86C5-77F7-4EDD-B473-43407CE33631}</ProjectGuid>
  9 + <OutputType>Library</OutputType>
  10 + <AppDesignerFolder>Properties</AppDesignerFolder>
  11 + <RootNamespace>Enhance.Imaging</RootNamespace>
  12 + <AssemblyName>Enhance.Imaging</AssemblyName>
  13 + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
  14 + <FileAlignment>512</FileAlignment>
  15 + <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\src\</SolutionDir>
  16 + <RestorePackages>true</RestorePackages>
  17 + </PropertyGroup>
  18 + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
  19 + <DebugSymbols>true</DebugSymbols>
  20 + <DebugType>full</DebugType>
  21 + <Optimize>false</Optimize>
  22 + <OutputPath>bin\Debug\</OutputPath>
  23 + <DefineConstants>DEBUG;TRACE</DefineConstants>
  24 + <ErrorReport>prompt</ErrorReport>
  25 + <WarningLevel>4</WarningLevel>
  26 + </PropertyGroup>
  27 + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
  28 + <DebugType>pdbonly</DebugType>
  29 + <Optimize>true</Optimize>
  30 + <OutputPath>bin\Release\</OutputPath>
  31 + <DefineConstants>TRACE</DefineConstants>
  32 + <ErrorReport>prompt</ErrorReport>
  33 + <WarningLevel>4</WarningLevel>
  34 + </PropertyGroup>
  35 + <ItemGroup>
  36 + <Reference Include="AForge">
  37 + <HintPath>..\packages\AForge.2.2.4\lib\AForge.dll</HintPath>
  38 + </Reference>
  39 + <Reference Include="AForge.Imaging">
  40 + <HintPath>..\packages\AForge.Imaging.2.2.4\lib\AForge.Imaging.dll</HintPath>
  41 + </Reference>
  42 + <Reference Include="AForge.Math">
  43 + <HintPath>..\packages\AForge.Math.2.2.4\lib\AForge.Math.dll</HintPath>
  44 + </Reference>
  45 + <Reference Include="PresentationCore" />
  46 + <Reference Include="System" />
  47 + <Reference Include="System.Core" />
  48 + <Reference Include="System.Drawing" />
  49 + <Reference Include="System.Xml.Linq" />
  50 + <Reference Include="System.Data.DataSetExtensions" />
  51 + <Reference Include="Microsoft.CSharp" />
  52 + <Reference Include="System.Data" />
  53 + <Reference Include="System.Xml" />
  54 + <Reference Include="WindowsBase" />
  55 + </ItemGroup>
  56 + <ItemGroup>
  57 + <Compile Include="BitmapExtensions.cs" />
  58 + <Compile Include="CropAndStraighten.cs" />
  59 + <Compile Include="NativeMethods.cs" />
  60 + <Compile Include="ImagingException.cs" />
  61 + <Compile Include="Properties\AssemblyInfo.cs" />
  62 + </ItemGroup>
  63 + <ItemGroup>
  64 + <None Include="packages.config" />
  65 + </ItemGroup>
  66 + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  67 + <Import Project="$(SolutionDir)\.nuget\nuget.targets" />
  68 + <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
  69 + Other similar extension points exist, see Microsoft.Common.targets.
  70 + <Target Name="BeforeBuild">
  71 + </Target>
  72 + <Target Name="AfterBuild">
  73 + </Target>
  74 + -->
  75 +</Project>
30 src/Enhance.Imaging/ImagingException.cs
... ... @@ -0,0 +1,30 @@
  1 +using System;
  2 +using System.Runtime.Serialization;
  3 +
  4 +namespace Enhance.Imaging
  5 +{
  6 + [Serializable]
  7 + public class ImagingException : Exception
  8 + {
  9 + public ImagingException()
  10 + {
  11 + }
  12 +
  13 + public ImagingException(string message)
  14 + : base(message)
  15 + {
  16 + }
  17 +
  18 + public ImagingException(string message, Exception inner)
  19 + : base(message, inner)
  20 + {
  21 + }
  22 +
  23 + protected ImagingException(
  24 + SerializationInfo info,
  25 + StreamingContext context)
  26 + : base(info, context)
  27 + {
  28 + }
  29 + }
  30 +}
15 src/Enhance.Imaging/NativeMethods.cs
... ... @@ -0,0 +1,15 @@
  1 +using System;
  2 +using System.Runtime.InteropServices;
  3 +
  4 +namespace Enhance.Imaging
  5 +{
  6 + /// <summary>
  7 + /// FxCop requires all Marshalled functions to be in a class called NativeMethods.
  8 + /// </summary>
  9 + internal static class NativeMethods
  10 + {
  11 + [DllImport("gdi32.dll")]
  12 + [return: MarshalAs(UnmanagedType.Bool)]
  13 + internal static extern bool DeleteObject(IntPtr hObject);
  14 + }
  15 +}
36 src/Enhance.Imaging/Properties/AssemblyInfo.cs
... ... @@ -0,0 +1,36 @@
  1 +using System.Reflection;
  2 +using System.Runtime.CompilerServices;
  3 +using System.Runtime.InteropServices;
  4 +
  5 +// General Information about an assembly is controlled through the following
  6 +// set of attributes. Change these attribute values to modify the information
  7 +// associated with an assembly.
  8 +[assembly: AssemblyTitle("Enhance.Imaging")]
  9 +[assembly: AssemblyDescription("")]
  10 +[assembly: AssemblyConfiguration("")]
  11 +[assembly: AssemblyCompany("")]
  12 +[assembly: AssemblyProduct("Enhance.Imaging")]
  13 +[assembly: AssemblyCopyright("Copyright © 2012")]
  14 +[assembly: AssemblyTrademark("")]
  15 +[assembly: AssemblyCulture("")]
  16 +
  17 +// Setting ComVisible to false makes the types in this assembly not visible
  18 +// to COM components. If you need to access a type in this assembly from
  19 +// COM, set the ComVisible attribute to true on that type.
  20 +[assembly: ComVisible(false)]
  21 +
  22 +// The following GUID is for the ID of the typelib if this project is exposed to COM
  23 +[assembly: Guid("a13d2962-f5a2-4b58-9d15-f6dda37b4454")]
  24 +
  25 +// Version information for an assembly consists of the following four values:
  26 +//
  27 +// Major Version
  28 +// Minor Version
  29 +// Build Number
  30 +// Revision
  31 +//
  32 +// You can specify all the values or you can default the Build and Revision Numbers
  33 +// by using the '*' as shown below:
  34 +// [assembly: AssemblyVersion("1.0.*")]
  35 +[assembly: AssemblyVersion("1.0.0.0")]
  36 +[assembly: AssemblyFileVersion("1.0.0.0")]
6 src/Enhance.Imaging/packages.config
... ... @@ -0,0 +1,6 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<packages>
  3 + <package id="AForge" version="2.2.4" />
  4 + <package id="AForge.Imaging" version="2.2.4" />
  5 + <package id="AForge.Math" version="2.2.4" />
  6 +</packages>
12 src/Enhance.sln
@@ -11,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{9EB6B3
11 11 EndProject
12 12 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Enhance.Logic", "Enhance.Logic\Enhance.Logic.csproj", "{9E94E49F-57CE-4304-9CB1-E243FAB2B1A3}"
13 13 EndProject
  14 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Enhance.Imaging", "Enhance.Imaging\Enhance.Imaging.csproj", "{070B86C5-77F7-4EDD-B473-43407CE33631}"
  15 +EndProject
14 16 Global
15 17 GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 18 Debug|Any CPU = Debug|Any CPU
@@ -41,6 +43,16 @@ Global
41 43 {9E94E49F-57CE-4304-9CB1-E243FAB2B1A3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
42 44 {9E94E49F-57CE-4304-9CB1-E243FAB2B1A3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
43 45 {9E94E49F-57CE-4304-9CB1-E243FAB2B1A3}.Release|x86.ActiveCfg = Release|Any CPU
  46 + {070B86C5-77F7-4EDD-B473-43407CE33631}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  47 + {070B86C5-77F7-4EDD-B473-43407CE33631}.Debug|Any CPU.Build.0 = Debug|Any CPU
  48 + {070B86C5-77F7-4EDD-B473-43407CE33631}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
  49 + {070B86C5-77F7-4EDD-B473-43407CE33631}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
  50 + {070B86C5-77F7-4EDD-B473-43407CE33631}.Debug|x86.ActiveCfg = Debug|Any CPU
  51 + {070B86C5-77F7-4EDD-B473-43407CE33631}.Release|Any CPU.ActiveCfg = Release|Any CPU
  52 + {070B86C5-77F7-4EDD-B473-43407CE33631}.Release|Any CPU.Build.0 = Release|Any CPU
  53 + {070B86C5-77F7-4EDD-B473-43407CE33631}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
  54 + {070B86C5-77F7-4EDD-B473-43407CE33631}.Release|Mixed Platforms.Build.0 = Release|Any CPU
  55 + {070B86C5-77F7-4EDD-B473-43407CE33631}.Release|x86.ActiveCfg = Release|Any CPU
44 56 EndGlobalSection
45 57 GlobalSection(SolutionProperties) = preSolution
46 58 HideSolutionNode = FALSE

0 comments on commit 34eeae1

Please sign in to comment.
Something went wrong with that request. Please try again.