Support black and white deskew

This commit is contained in:
Ben Olden-Cooligan 2019-06-16 15:49:07 -04:00
parent 296974ab7c
commit 7452197a6a
6 changed files with 73 additions and 18 deletions

View File

@ -15,6 +15,17 @@ namespace NAPS2.Sdk.Tests.Images
public void Deskew()
{
var image = new GdiImage(DeskewTestsData.skewed);
Assert.Equal(StoragePixelFormat.RGB24, image.PixelFormat);
var deskewer = new HoughLineDeskewer();
var skewAngle = deskewer.GetSkewAngle(image);
Assert.InRange(skewAngle, 15.5, 16.5);
}
[Fact]
public void DeskewBlackAndWhite()
{
var image = new GdiImage(DeskewTestsData.skewed_bw);
Assert.Equal(StoragePixelFormat.BW1, image.PixelFormat);
var deskewer = new HoughLineDeskewer();
var skewAngle = deskewer.GetSkewAngle(image);
Assert.InRange(skewAngle, 15.5, 16.5);

View File

@ -69,5 +69,15 @@ namespace NAPS2.Sdk.Tests.Images {
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap skewed_bw {
get {
object obj = ResourceManager.GetObject("skewed_bw", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View File

@ -121,4 +121,7 @@
<data name="skewed" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\skewed.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="skewed_bw" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\skewed_bw.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@ -297,6 +297,9 @@
<ItemGroup>
<None Include="Resources\skewed.jpg" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\skewed_bw.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -374,11 +374,11 @@ namespace NAPS2.Images.Transforms
return monoBitmap;
}
public static unsafe BitArray[] ConvertToBitArrays(IImage bitmap)
{
// TODO: Support black & white images
int thresholdAdjusted = 140 * 1000;
int bytesPerPixel = GetBytesPerPixel(bitmap);
bool bitPerPixel = bitmap.PixelFormat == StoragePixelFormat.BW1;
int bytesPerPixel = bitPerPixel ? 0 : GetBytesPerPixel(bitmap);
var bitmapData = bitmap.Lock(LockMode.ReadOnly, out var scan0, out var stride);
byte* data = (byte*)scan0;
@ -387,25 +387,53 @@ namespace NAPS2.Images.Transforms
var bitArrays = new BitArray[h];
PartitionRows(h, (start, end) =>
if (bitPerPixel)
{
for (int y = start; y < end; y++)
PartitionRows(h, (start, end) =>
{
var outRow = new BitArray(w);
bitArrays[y] = outRow;
byte* row = data + stride * y;
for (int x = 0; x < w; x++)
for (int y = start; y < end; y++)
{
byte* pixel = row + x * bytesPerPixel;
byte r = *pixel;
byte g = *(pixel + 1);
byte b = *(pixel + 2);
// Use standard values for grayscale conversion to weight the RGB values
int luma = r * 299 + g * 587 + b * 114;
outRow[x] = luma < thresholdAdjusted;
var outRow = new BitArray(w);
bitArrays[y] = outRow;
byte* row = data + stride * y;
for (int x = 0; x < w; x += 8)
{
byte monoByte = *(row + x / 8);
for (int k = 7; k >= 0; k--)
{
if (x + k < w)
{
outRow[x] = (monoByte & 1) > 0;
}
monoByte >>= 1;
}
}
}
}
});
});
}
else
{
int thresholdAdjusted = 140 * 1000;
PartitionRows(h, (start, end) =>
{
for (int y = start; y < end; y++)
{
var outRow = new BitArray(w);
bitArrays[y] = outRow;
byte* row = data + stride * y;
for (int x = 0; x < w; x++)
{
byte* pixel = row + x * bytesPerPixel;
byte r = *pixel;
byte g = *(pixel + 1);
byte b = *(pixel + 2);
// Use standard values for grayscale conversion to weight the RGB values
int luma = r * 299 + g * 587 + b * 114;
outRow[x] = luma < thresholdAdjusted;
}
}
});
}
bitmap.Unlock(bitmapData);