c#文档图片自动纠偏
本文导语: 代码如下:public class Deskew { // Representation of a line in the image. private class HougLine { // Count of points in the line. public int Count; // Index in Matrix. ...
public class Deskew
{
// Representation of a line in the image.
private class HougLine
{
// Count of points in the line.
public int Count;
// Index in Matrix.
public int Index;
// The line is represented as all x,y that solve y*cos(alpha)-x*sin(alpha)=d
public double Alpha;
}
// The Bitmap
public Bitmap _internalBmp;
// The range of angles to search for lines
const double ALPHA_START = -20;
const double ALPHA_STEP = 0.2;
const int STEPS = 40 * 5;
const double STEP = 1;
// Precalculation of sin and cos.
double[] _sinA;
double[] _cosA;
// Range of d
double _min;
int _count;
// Count of points that fit in a line.
int[] _hMatrix;
// Calculate the skew angle of the image cBmp.
public double GetSkewAngle()
{
// Hough Transformation
Calc();
// Top 20 of the detected lines in the image.
HougLine[] hl = GetTop(20);
// Average angle of the lines
double sum = 0;
int count = 0;
for (int i = 0; i hl[j - 1].Count)
{
HougLine tmp = hl[j];
hl[j] = hl[j - 1];
hl[j - 1] = tmp;
j -= 1;
}
}
}
for (int i = 0; i 0)
{
pixelFormat = PixelFormat.Format24bppRgb;
}
Bitmap tmpBitmap = new Bitmap(bmp.Width, bmp.Height, pixelFormat);
tmpBitmap.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
Graphics g = Graphics.FromImage(tmpBitmap);
try
{
g.FillRectangle(Brushes.White, 0, 0, bmp.Width, bmp.Height);
g.RotateTransform(angle);
g.DrawImage(bmp, 0, 0);
}
catch
{
}
finally
{
g.Dispose();
}
if (pixelFormatOld == PixelFormat.Format8bppIndexed) tmpBitmap = CopyTo8bpp(tmpBitmap);
else if (pixelFormatOld == PixelFormat.Format1bppIndexed) tmpBitmap = CopyTo1bpp(tmpBitmap);
return tmpBitmap;
}
在最后进行图片选择时,位深度为1、4、8的索引图片是没办法直接用Graphics进行旋转操作的,需要图像的PixelFormat再做旋转。
现在只实现位深度为1和8的索引图片还原。
private static Bitmap CopyTo1bpp(Bitmap b)
{
int w = b.Width, h = b.Height; Rectangle r = new Rectangle(0, 0, w, h);
if (b.PixelFormat != PixelFormat.Format32bppPArgb)
{
Bitmap temp = new Bitmap(w, h, PixelFormat.Format32bppPArgb);
temp.SetResolution(b.HorizontalResolution, b.VerticalResolution);
Graphics g = Graphics.FromImage(temp);
g.DrawImage(b, r, 0, 0, w, h, GraphicsUnit.Pixel);
g.Dispose();
b = temp;
}
BitmapData bdat = b.LockBits(r, ImageLockMode.ReadOnly, b.PixelFormat);
Bitmap b0 = new Bitmap(w, h, PixelFormat.Format1bppIndexed);
b0.SetResolution(b.HorizontalResolution, b.VerticalResolution);
BitmapData b0dat = b0.LockBits(r, ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed);
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
int index = y * bdat.Stride + (x * 4);
if (Color.FromArgb(Marshal.ReadByte(bdat.Scan0, index + 2), Marshal.ReadByte(bdat.Scan0, index + 1), Marshal.ReadByte(bdat.Scan0, index)).GetBrightness() > 0.5f)
{
int index0 = y * b0dat.Stride + (x >> 3);
byte p = Marshal.ReadByte(b0dat.Scan0, index0);
byte mask = (byte)(0x80 >> (x & 0x7));
Marshal.WriteByte(b0dat.Scan0, index0, (byte)(p | mask));
}
}
}
b0.UnlockBits(b0dat);
b.UnlockBits(bdat);
return b0;
}
private static Bitmap CopyTo8bpp(Bitmap bmp)
{
if (bmp == null) return null;
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);
int width = bmpData.Width;
int height = bmpData.Height;
int stride = bmpData.Stride;
int offset = stride - width * 3;
IntPtr ptr = bmpData.Scan0;
int scanBytes = stride * height;
int posScan = 0, posDst = 0;
byte[] rgbValues = new byte[scanBytes];
Marshal.Copy(ptr, rgbValues, 0, scanBytes);
byte[] grayValues = new byte[width * height];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
double temp = rgbValues[posScan++] * 0.11 +
rgbValues[posScan++] * 0.59 +
rgbValues[posScan++] * 0.3;
grayValues[posDst++] = (byte)temp;
}
posScan += offset;
}
Marshal.Copy(rgbValues, 0, ptr, scanBytes);
bmp.UnlockBits(bmpData);
Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
bitmap.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
int offset0 = bitmapData.Stride - bitmapData.Width;
int scanBytes0 = bitmapData.Stride * bitmapData.Height;
byte[] rawValues = new byte[scanBytes0];
int posSrc = 0;
posScan = 0;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
rawValues[posScan++] = grayValues[posSrc++];
}
posScan += offset0;
}
Marshal.Copy(rawValues, 0, bitmapData.Scan0, scanBytes0);
bitmap.UnlockBits(bitmapData);
ColorPalette palette;
using (Bitmap bmp0 = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
{
palette = bmp0.Palette;
}
for (int i = 0; i < 256; i++)
{
palette.Entries[i] = Color.FromArgb(i, i, i);
}
bitmap.Palette = palette;
return bitmap;
}