using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows;
using System.Windows.Forms;
namespace UPImage.Data
{
public struct ImageData
{
public String Label { get; set; }
public Bitmap Image { get; set; }
public ImageData(String label, Bitmap image)
: this()
{
Label = label;
Image = image;
}
}
public struct ByteImageData
{
public Char Label { get; set; }
public byte[] Image { get; set; }
public ByteImageData(Char label, byte[] image)
: this()
{
Label = label;
Image = image;
}
}
public class UPDataProvider : IDisposable
{
//private parameters
private int _maxDegreeOfParallelism = Environment.ProcessorCount;
private List<ImageData> imagePatterns;
private List<ByteImageData> byteImagePatterns;
private UPFolder folder;
private Size patternSize;
public bool DatabaseLoaded { get; private set; }
public int PatternsCount { get; private set; }
public int[] RandomTrainingPattern { get; private set; }
public int MaxDegreeOfParallelism
{
get
{
return _maxDegreeOfParallelism;
}
set
{
if (value == _maxDegreeOfParallelism)
return;
if ((value == 0) || (value > Environment.ProcessorCount))
_maxDegreeOfParallelism = -1;
else
_maxDegreeOfParallelism = value;
ParallelOption.MaxDegreeOfParallelism = _maxDegreeOfParallelism;
}
}
public ParallelOptions ParallelOption { get; private set; }
public UPFolder Folder
{
get
{
return folder;
}
}
public List<ImageData> ImagePatterns
{
get
{
return imagePatterns;
}
}
public List<ByteImageData> ByteImagePatterns
{
get
{
return byteImagePatterns;
}
}
public Size PatternSize
{
get
{
return patternSize;
}
set
{
if (patternSize == value)
return;
patternSize = value;
}
}
bool isDataStop;
public bool IsDataStop
{
get
{
return isDataStop;
}
set
{
if (isDataStop == value)
{
return;
}
else
{
isDataStop = value;
lock (this)
{
folder.IsDataStop = isDataStop;
}
}
}
}
public UPDataProvider()
{
ParallelOption = new ParallelOptions();
ParallelOption.TaskScheduler = null;
_maxDegreeOfParallelism = Environment.ProcessorCount;
ParallelOption.MaxDegreeOfParallelism = _maxDegreeOfParallelism;
folder = new UPFolder();
imagePatterns = null;
byteImagePatterns = null;
this.IsDataStop = true;
patternSize = Size.Empty;
}
~UPDataProvider()
{
// In case the client forgets to call
// Dispose , destructor will be invoked for
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed resources
if (folder != null)
{
folder.Dispose();
folder = null;
}
if (imagePatterns != null)
{
imagePatterns.Clear();
imagePatterns = null;
}
if (byteImagePatterns != null)
{
byteImagePatterns.Clear();
byteImagePatterns = null;
}
}
// free native resources
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void LoadUnipenFolderTree(String path)
{
folder.FillFolderTree(path);
}
/// <summary>
/// this function will get partern list of a hierachy
/// </summary>
/// <param name="folderPath"></param>
/// <param name="bmplist"></param>
/// <param name="hierachy"></param>
public void GetPatternsFromFiles(String folderPath)
{
String hierachy = "CHARACTER";
if (imagePatterns != null)
{
imagePatterns.Clear();
imagePatterns = null;
}
imagePatterns = new List<ImageData>();
patternSize.Width = 29;
patternSize.Height = 29;
folder.GetImageData(folderPath, hierachy, imagePatterns, patternSize, 2, true, true);
byteImagePatterns = GetBytePatterns();
PatternsCount = imagePatterns.Count;
}
public void GetPatternsFromFiles(String folderPath,String hierachyString,Size imageSize,int penWidth,bool isGrayscale,bool isLetterOrDigit)
{
String hierachy = hierachyString;
if (imagePatterns != null)
{
imagePatterns.Clear();
imagePatterns = null;
}
imagePatterns = new List<ImageData>();
patternSize.Width = imageSize.Width;
patternSize.Height = imageSize.Height;
folder.GetImageData(folderPath, hierachy, imagePatterns, patternSize, penWidth, isGrayscale, isLetterOrDigit);
byteImagePatterns = GetBytePatterns();
PatternsCount = imagePatterns.Count;
}
private List<ByteImageData> GetBytePatterns()
{
List<ByteImageData> bytesList = null;
this.IsDataStop = false;
if (imagePatterns.Count > 0)
{
bytesList = new List<ByteImageData>();
Parallel.ForEach(imagePatterns, (pattern,loopstate) =>
{
if (pattern.Image != null)
{
ByteImageData imgdata = new ByteImageData();
String label = pattern.Label;
imgdata.Label = label.ToCharArray(1, 1)[0];
imgdata.Image = ConvertGrayscaleBitmaptoBytes(pattern.Image);
lock (this)
{
bytesList.Add(imgdata);
}
}
if (isDataStop)
{
loopstate.Stop();
}
});
this.IsDataStop = true;
}
return bytesList;
}
private byte[] ConvertGrayscaleBitmaptoBytes(Bitmap original)
{
if (original.PixelFormat == PixelFormat.Format8bppIndexed)
{
Bitmap gsBitmap =(Bitmap) original.Clone();
byte[] grayscalebytes = new byte[gsBitmap.Width * gsBitmap.Height];
BitmapData bmpData = gsBitmap.LockBits(new Rectangle(0, 0, gsBitmap.Width, gsBitmap.Height),
ImageLockMode.ReadOnly,
gsBitmap.PixelFormat);
int bytes = Math.Abs(bmpData.Stride) * gsBitmap.Height;
byte[] rgbValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, rgbValues, 0, bytes);
gsBitmap.UnlockBits(bmpData);
int bmpWidth = gsBitmap.Width;
int bmpHeight = gsBitmap.Height;
//
/*TODO: Check potentially-changing upper bound expression "gsBitmap.Height" which is now called only *once*,
to ensure the new Parallel.For call matches behavior in the original for-loop
(where this upper bound expression had previously been evaluated at the start of *every* loop iteration).*/
Parallel.For(0, bmpHeight, ParallelOption, (h, loopstate) =>
{
for (int w = 0; w < bmpWidth; w++)
{
grayscalebytes[h * bmpWidth + w] = rgbValues[h * bmpData.Stride + w];
}
if (isDataStop)
{
loopstate.Stop();
}
});
gsBitmap.Dispose();
return grayscalebytes;
}
else
{
return null;
}
}
}
}