DataEntry.Uni camera support in TestStartEndForm, ver. 3.6.2072

This commit is contained in:
Milan Hanajik
2023-08-01 11:54:01 +02:00
parent 3f35506b26
commit dd5b20ab38
13 changed files with 966 additions and 160 deletions
+520 -25
View File
@@ -11,6 +11,8 @@ using Common;
using Results.Entities;
using TBF.Rig.GenericDevices;
using TBF.Resources;
using System.Threading;
using System.IO;
namespace TBF.Rig.DataEntry.Uni
{
@@ -18,22 +20,48 @@ namespace TBF.Rig.DataEntry.Uni
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestStartEndForm));
const int PicSize = 480;
///
/// Static members and constructor
///
static int wmNr0b;
static Rotation imageRotation;
static bool[] isZoomed;
static Point[] zoomCenterLoc;
///
static TestStartEndForm()
{
wmNr0b = 0;
//imageRotation = new Rotation[40];
isZoomed = new bool[40];
zoomCenterLoc = new Point[40];
}
/// Arguments
public readonly IList<WaterMeter> waterMeters;
readonly IRegReader[] regReaders;
readonly int lineSize;
readonly Sz sz;
readonly FontSz sz;
readonly bool isStartBoxAlwaysEn;
readonly bool isLrOrder; /// true = controls obtain focus after ENTER key in left-right order, false = top-down order
readonly IList<DEItem> colItems;
readonly string formCloseKeys;
public readonly string[] WMStartStateStr;
readonly bool isCameraPicture; /// true = camera picture displayed on the left side
readonly string[] startImages;
readonly string[] endImages;
readonly OcrVidi ocrVidi;
readonly string ocrMessage;
readonly string streamName;
readonly double refVolume;
readonly double warningLimLo; /// limit to display exclamation mark, typically 2x errLimLo
readonly double warningLimHi; /// limit to display exclamation mark, typically 2x errLimHi
/// Derived from arguments in the constructor
readonly bool isEnd;
readonly Tst mode; /// Start, End or Deferred
readonly WaterMeter firstValidWM;
readonly int wmsCount;
readonly int linesCount;
@@ -60,11 +88,25 @@ namespace TBF.Rig.DataEntry.Uni
readonly TextBox[,] textBoxes; /// Text boxes for values in columns
readonly Label[] exclamations;
/// Picture box related
PictureBox pictureBox1;
Label imageProcessingProgressLabel;
ProgressBar imageProcessingProgressBar;
string lastImageName;
int lastWmNr1;
Bitmap lastImage; /// non-zoomed image
Bitmap zoomedImage;
Thread imageProcessingThread; /// Thread to process images
public delegate void OcrTextObtainedDelegate(int ix, bool isEnd, string text);
OcrTextObtainedDelegate ocrTextObtained;
readonly LocalSettings ls;
bool isHandlersEnabled; /// Initially false, set to true after ComboBoxes are filled with data
// Set to 'true' when the form closes
/// Set to 'true' when the form closes
public bool Completed { get { return completed; } }
bool completed;
@@ -76,7 +118,8 @@ namespace TBF.Rig.DataEntry.Uni
{
InitializeComponent();
ControlBox = false;
completed = false;
imageProcessingThread = null;
completed = false;
StartForceCloseHandler();
}
@@ -96,10 +139,11 @@ namespace TBF.Rig.DataEntry.Uni
/// <param name="refVolume">Reference volume, it is used to verify the end state, show/hide exclamation if necessary</param>
/// <param name="errLimLo">Error limit low, it is used to verify the end state, show/hide exclamation if necessary</param>
/// <param name="errLimHi">Error limit high, it is used to verify the end state, show/hide exclamation if necessary</param>
public TestStartEndForm(IList<WaterMeter> waterMeters, IRegReader[] regReaders, int lineSize, string title, Sz sz,
public TestStartEndForm(IList<WaterMeter> waterMeters, IRegReader[] regReaders, int lineSize, string title, FontSz sz,
bool isStartBoxAlwaysEn, bool isLrOrder, string formCloseKeys, IList<DEItem> colItems,
Unit initialVolumeUnit, string[] wmStartStateStr = null,
double refVolume = 0, double errLimLo = 0, double errLimHi = 0)
Unit initialVolumeUnit, bool isCameraPicture, string[] startImages, string[] endImages,
OcrVidi ocrVidi, string ocrMessage, string streamName,
string[] wmStartStateStr = null, double refVolume = 0, double errLimLo = 0, double errLimHi = 0)
: this()
{
this.waterMeters = waterMeters;
@@ -112,6 +156,12 @@ namespace TBF.Rig.DataEntry.Uni
this.formCloseKeys = !string.IsNullOrEmpty(formCloseKeys) ? formCloseKeys : string.Empty;
this.colItems = colItems;
this.VolumeUnit = initialVolumeUnit;
this.isCameraPicture = isCameraPicture;
this.startImages = startImages;
this.endImages = endImages;
this.ocrVidi = ocrVidi;
this.ocrMessage = ocrMessage;
this.streamName = streamName;
this.WMStartStateStr = wmStartStateStr;
this.refVolume = refVolume;
this.warningLimLo = 2 * errLimLo;
@@ -127,6 +177,7 @@ namespace TBF.Rig.DataEntry.Uni
/// Readonly variables derived from arguments
isEnd = (wmStartStateStr != null);
mode = isEnd ? Tst.End : Tst.Start;
wmsCount = waterMeters.Count;
if (WMStartStateStr == null) WMStartStateStr = new string[wmsCount];
fixedErrorLimits = (errLimHi > errLimLo);
@@ -136,6 +187,10 @@ namespace TBF.Rig.DataEntry.Uni
WMEndState = new double[wmsCount];
///
unitComboBox.Text = VolumeUnit.ToDescription();
for (Unit u = 0; u < Unit.Count; u++)
{
if (Units.IsVolume(u)) unitComboBox.Items.Add(u.ToDescription());
}
labels = new Label[wmsCount];
textBoxes = new TextBox[colItems.Count, wmsCount];
exclamations = new Label[wmsCount];
@@ -145,7 +200,7 @@ namespace TBF.Rig.DataEntry.Uni
Font exclamationFont;
switch (sz)
{
case Sz.S:
case FontSz.S:
font = new Font("Verdana", 12, FontStyle.Regular);
//exclamationFont = new Font("Verdana", 24F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(238)));
exclamationFont = new Font("Verdana", 18, FontStyle.Bold);
@@ -158,7 +213,7 @@ namespace TBF.Rig.DataEntry.Uni
break;
default:
case Sz.M:
case FontSz.M:
font = new Font("Verdana", 14, FontStyle.Regular);
exclamationFont = new Font("Verdana", 20, FontStyle.Bold);
meterHeight = 31; /// Height of a ComboBox control
@@ -169,7 +224,7 @@ namespace TBF.Rig.DataEntry.Uni
checkBoxWid = 23;
break;
case Sz.L:
case FontSz.L:
font = new Font("Verdana", 18, FontStyle.Regular);
exclamationFont = new Font("Verdana", 24, FontStyle.Bold);
meterHeight = 37; /// Height of a ComboBox control
@@ -188,11 +243,73 @@ namespace TBF.Rig.DataEntry.Uni
///
/// Table
///
int columnsLeft = 0;
if (isCameraPicture)
{
columnsLeft = PicSize + 10;
largeTextBox.Left += columnsLeft;
largeExclamationLabel.Left += columnsLeft;
/// Picture box
pictureBox1 = new PictureBox
{
Location = new System.Drawing.Point(4, 5),
Name = "pictureBox1",
Size = new System.Drawing.Size(PicSize, PicSize),
SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage,
TabIndex = tabIndex++,
TabStop = false,
};
pictureBox1.Click += new System.EventHandler(pictureBox1_Click);
Controls.Add(pictureBox1);
/// Rotate image button
var rotateImageButton = new Button
{
Font = new System.Drawing.Font("Arial", 27.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(238))),
Location = new System.Drawing.Point(24, PicSize + 31),
Name = "rotateImageButton",
Size = new System.Drawing.Size(50, 50),
TabIndex = tabIndex++,
Text = "↺",
UseVisualStyleBackColor = true,
};
rotateImageButton.Click += new System.EventHandler(rotateImageButton_Click);
Controls.Add(rotateImageButton);
/// Image processing progress bar
imageProcessingProgressBar = new ProgressBar
{
Location = new System.Drawing.Point(100, PicSize + 56),
Name = "imageProcessingProgressBar",
Size = new System.Drawing.Size(246, 23),
TabIndex = tabIndex++,
Visible = false,
};
Controls.Add(imageProcessingProgressBar);
/// Image processing progress label
imageProcessingProgressLabel = new Label
{
AutoSize = true,
Font = new System.Drawing.Font("Verdana", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238))),
Location = new System.Drawing.Point(100, PicSize + 31),
Name = "imageProcessingProgressLabel",
Size = new System.Drawing.Size(249, 18),
TabIndex = tabIndex++,
Text = "Progress of image processing",
Visible = false,
};
Controls.Add(imageProcessingProgressLabel);
}
int columnsTop = hdrHeight;
for (int j = 0; j < linesCount; j++)
{
/// Captions
int capX = margin + j * (meterWidth + margin / 2) + labelWid + spacing;
int capX = columnsLeft + margin + j * (meterWidth + margin / 2) + labelWid + spacing;
int capY = columnsTop - meterHeight;
for (int k = 0; k < colItems.Count; k++)
{
@@ -207,6 +324,7 @@ namespace TBF.Rig.DataEntry.Uni
Parent = this,
};
capX += colItems[k].Width + spacing;
Controls.Add(label);
}
/// Water meters
@@ -215,7 +333,7 @@ namespace TBF.Rig.DataEntry.Uni
int wmPos0 = i + lineSize * j;
if (wmPos0 > wmsCount) continue;
int left = margin + j * (meterWidth + margin / 2);
int left = columnsLeft + margin + j * (meterWidth + margin / 2);
int top = columnsTop + i * (meterHeight + spacing);
var label = new Label
@@ -230,7 +348,7 @@ namespace TBF.Rig.DataEntry.Uni
};
left += labelWid + spacing / 2;
labels[wmPos0] = label;
this.Controls.Add(label);
Controls.Add(label);
/// Columns
for (int k = 0; k < colItems.Count; k++)
@@ -247,13 +365,15 @@ namespace TBF.Rig.DataEntry.Uni
Parent = this,
};
textBox.AcceptsTabChanged += new System.EventHandler(textBox_AcceptsTabChanged);
textBox.TextChanged += new System.EventHandler(textBox_TextChanged);
textBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(textBox_KeyPress);
textBox.MouseClick += new System.Windows.Forms.MouseEventHandler(textBox_MouseClick);
textBox.MouseDown += new System.Windows.Forms.MouseEventHandler(textBox_MouseDown);
left += ci.Width + spacing;
textBoxes[k, wmPos0] = textBox;
this.Controls.Add(textBox);
Controls.Add(textBox);
}
var exclamation = new Label
@@ -268,7 +388,7 @@ namespace TBF.Rig.DataEntry.Uni
Visible = false,
};
exclamations[wmPos0] = exclamation;
this.Controls.Add(exclamation);
Controls.Add(exclamation);
}
}
@@ -277,8 +397,8 @@ namespace TBF.Rig.DataEntry.Uni
///
Rectangle screenRectangle = this.RectangleToScreen(this.ClientRectangle);
int titleBarHeight = screenRectangle.Top - this.Top;
Size = new Size(Math.Max(meterWidth * linesCount + margin * (linesCount + 1), 1300),
titleBarHeight + columnsTop + lineSize * (meterHeight + spacing) + margin);
Size = new Size(columnsLeft + Math.Max(meterWidth * linesCount + margin * (linesCount + 1), 1040),
titleBarHeight + Math.Max(columnsTop + lineSize * (meterHeight + spacing) + margin, isCameraPicture ? 590 : 0));
Localize();
InitializeBoxes();
@@ -286,6 +406,45 @@ namespace TBF.Rig.DataEntry.Uni
/// Set focus to the first enabled ComboBox
}
private void TestStartEndForm_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(ocrMessage))
{
MessageBox.Show(ocrMessage, Strings.Warning, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
int imagesCount = ImagesToProcessCount();
log.WarnFormat("Images to process count = {0}", imagesCount);
///
if (imagesCount > 0 && ocrVidi != null)
{
log.WarnFormat("Starting image processing thread with OcrVidi={0} and OcrStream={1}", ocrVidi, streamName);
/// Delegate for a thread->form communication
ocrTextObtained = new OcrTextObtainedDelegate(OnOcrTextObtained);
/// Show and initalize the progress bar
imageProcessingProgressLabel.Visible = true;
imageProcessingProgressBar.Visible = true;
imageProcessingProgressBar.Minimum = 0;
imageProcessingProgressBar.Value = 0;
imageProcessingProgressBar.Maximum = imagesCount;
/// Start the image processing thread
imageProcessingThread = new Thread(new ThreadStart(ImageProcessingThread));
imageProcessingThread.Start();
}
}
private void TestStartEndForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (imageProcessingThread != null && imageProcessingThread.IsAlive)
{
imageProcessingThread.Join(2000);
}
}
void Localize()
{
okButton.Text = Strings.OkBtnText;
@@ -402,7 +561,136 @@ namespace TBF.Rig.DataEntry.Uni
}
}
private void okButton_Click(object sender, EventArgs eArgs)
int ImagesToProcessCount()
{
int count = 0;
/// Count the images
for (int i = 0; i < wmsCount; i++)
{
if ((mode == Tst.Start || mode == Tst.Both) &&
startStateColumn >= 0 && textBoxes[startStateColumn, i].Enabled &&
startImages != null && startImages.Length > i && !string.IsNullOrEmpty(startImages[i]))
{
count++;
}
if ((mode == Tst.End || mode == Tst.Both) &&
endStateColumn >= 0 && textBoxes[endStateColumn, i].Enabled &&
endImages != null && endImages.Length > i && !string.IsNullOrEmpty(endImages[i]))
{
count++;
}
}
return count;
}
void ImageProcessingThread()
{
double denominator; /// derived from PulsesPerLtr, passed to OcrVidi
string format; /// derived from PulsesPerLtr, passed to OcrVidi
Thread.Sleep(2000);
bool[] startImgProcessed = new bool[wmsCount];
bool[] endImgProcessed = new bool[wmsCount];
for (int attempt = 1; attempt <= 3; attempt++)
{
for (int i = 0; i < wmsCount; i++)
{
double pulsesPerLtr = (regReaders != null && regReaders.Length > i && regReaders[i] != null) ? regReaders[i].PulsesPerLtr : 1;
GetOcrParameters(pulsesPerLtr, out denominator, out format);
if ((mode == Tst.Start || mode == Tst.Both) &&
startStateColumn >= 0 && textBoxes[startStateColumn, i].Enabled &&
startImages != null && startImages.Length > i && !string.IsNullOrEmpty(startImages[i]))
{
if (!startImgProcessed[i])
{
try
{
/// Process a start image
var text = ocrVidi.Recognize(streamName, startImages[i], denominator, format); /// OCR
this.Invoke(ocrTextObtained, new object[] { i, false, text });
startImgProcessed[i] = true;
}
catch (Exception)
{
}
}
}
if ((mode == Tst.End || mode == Tst.Both) &&
endStateColumn >= 0 && textBoxes[endStateColumn, i].Enabled &&
endImages != null && endImages.Length > i && !string.IsNullOrEmpty(endImages[i]))
{
if (!endImgProcessed[i])
{
try
{
/// Process an end image
var text = ocrVidi.Recognize(streamName, endImages[i], denominator, format); /// OCR
this.Invoke(ocrTextObtained, new object[] { i, true, text });
endImgProcessed[i] = true;
}
catch (Exception)
{
}
}
}
}
}
}
void GetOcrParameters(double pulsesPerLtr, out double denominator, out string format)
{
if (pulsesPerLtr == 0.1)
{
denominator = 100;
format = "F2";
}
else if (pulsesPerLtr == 0.01)
{
denominator = 10;
format = "F1";
}
else if (pulsesPerLtr == 10)
{
denominator = 10000;
format = "F4";
}
else // if (pulsesPerLtr == 1)
{
denominator = 1000;
format = "F3";
}
}
public void OnOcrTextObtained(int ix, bool _isEnd, string text)
{
if (_isEnd)
{
if (endStateColumn>= 0 && textBoxes[endStateColumn, ix].Enabled)
{
textBoxes[endStateColumn, ix].Text = text;
LoadImage(null, Tst.End, ix);
}
}
else
{
if (startStateColumn >= 0 && textBoxes[startStateColumn, ix].Enabled)
{
textBoxes[endStateColumn, ix].Text = text;
LoadImage(null, Tst.Start, ix);
}
}
imageProcessingProgressBar.Value++;
}
private void okButton_Click(object sender, EventArgs eArgs)
{
UpdateWMsFromBoxes();
@@ -452,11 +740,11 @@ namespace TBF.Rig.DataEntry.Uni
}
}
private void textBox_KeyPress(object sndr, KeyPressEventArgs e)
private void textBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!isHandlersEnabled) return;
string[] kj = (sndr as TextBox).Name.Split(new char[] { '~' });
string[] kj = (sender as TextBox).Name.Split(new char[] { '~' });
int k = int.Parse(kj[0]);
int j = int.Parse(kj[1]);
@@ -468,7 +756,7 @@ namespace TBF.Rig.DataEntry.Uni
{
if (e.KeyChar == formCloseKeys[ix])
{
okButton_Click(sndr, e);
okButton_Click(sender, e);
return;
}
}
@@ -483,24 +771,30 @@ namespace TBF.Rig.DataEntry.Uni
}
else
{
textBoxes[k, j].Focus();
largeTextBox.Text = string.Format("{0}: {1}", j + 1, textBoxes[k, j].Text);
largeExclamationLabel.Visible = false;
if (k == startStateColumn || k == endStateColumn)
{
LoadImage(sender, (k == startStateColumn) ? Tst.Start : Tst.End, j);
}
textBoxes[k, j].Focus();
}
}
}
/// Handle mouse clicks so that the large text box and the large exclamation mark are updated
private void textBox_MouseClick(object sndr, MouseEventArgs e)
private void textBox_MouseClick(object sender, MouseEventArgs e)
{
textBox_TextChanged(sndr, e);
textBox_TextChanged(sender, e);
}
private void textBox_TextChanged(object sndr, EventArgs e)
private void textBox_TextChanged(object sender, EventArgs e)
{
if (!isHandlersEnabled) return;
string[] kj = (sndr as TextBox).Name.Split(new char[] { '~' });
string[] kj = (sender as TextBox).Name.Split(new char[] { '~' });
int k = int.Parse(kj[0]);
int j = int.Parse(kj[1]);
@@ -531,6 +825,24 @@ namespace TBF.Rig.DataEntry.Uni
}
}
private void textBox_MouseDown(object sender, MouseEventArgs e)
{
textBox_AcceptsTabChanged(sender, e);
}
private void textBox_AcceptsTabChanged(object sender, EventArgs e)
{
if (!isHandlersEnabled) return;
string[] kj = (sender as TextBox).Name.Split(new char[] { '~' });
int k = int.Parse(kj[0]);
int j = int.Parse(kj[1]);
if (k != startStateColumn && k != endStateColumn) return;
LoadImage(sender, (k == startStateColumn) ? Tst.Start : Tst.End, j);
}
/// <summary>
/// Find the next enabled combo box, update k and i.
@@ -578,6 +890,189 @@ namespace TBF.Rig.DataEntry.Uni
return pastTheEndOfArray;
}
/// <summary>
/// Loads appropriate image into pictureBox1.Image
/// Handles mouse clicks and Tab-changes inside text boxes.
/// </summary>
/// <param name="startOrEnd">Tst.Start or Tst.End</param>
/// <param name="wmNr0">0-based WM position</param>
void LoadImage(object sender, Tst startOrEnd, int wmNr0)
{
string imageFileName;
if (startOrEnd == Tst.Start && startImages[wmNr0] != null)
imageFileName = startImages[wmNr0];
else if (startOrEnd == Tst.End && endImages[wmNr0] != null)
imageFileName = endImages[wmNr0];
else
imageFileName = string.Empty;
if (imageFileName == lastImageName)
{
return;
}
lastImageName = imageFileName;
lastWmNr1 = wmNr0 + 1;
if (string.IsNullOrEmpty(imageFileName) || !File.Exists(imageFileName))
{
lastImage = null;
}
else
{
using (Bitmap tempBmp = Image.FromFile(imageFileName) as Bitmap)
{
Rectangle rect;
if (tempBmp.Height < tempBmp.Width)
{
int hght = tempBmp.Height;
int leftMargin = (tempBmp.Width - hght) / 2;
rect = new Rectangle(leftMargin, 0, hght, hght);
}
else
{
int hght = tempBmp.Height;
int wdth = tempBmp.Width;
int margin = (hght - wdth) / 2;
rect = new Rectangle(0, margin, wdth, wdth);
}
//int hght = tempBmp.Height;
//int leftMargin = (tempBmp.Width - hght) / 2;
//lastImage = new Bitmap(tempBmp.Clone(new Rectangle(leftMargin, 0, hght, hght), tempBmp.PixelFormat));
lastImage = new Bitmap(tempBmp.Clone(rect, tempBmp.PixelFormat));
if (isZoomed[wmNr0b])
{
zoomedImage = MakeZoomedImage(lastImage, zoomCenterLoc[wmNr0b]);
}
}
}
ShowImage();
}
/// <summary>
/// Left click = Zoom, Right click = Unzoom
/// </summary>
private void pictureBox1_Click(object sender, EventArgs e)
{
if (lastImage == null) return;
MouseEventArgs me = (MouseEventArgs)e;
if (me.Button == MouseButtons.Left && !isZoomed[wmNr0b])
{
switch (imageRotation)
{
case Rotation.R0:
zoomCenterLoc[wmNr0b] = me.Location;
break;
case Rotation.R90:
zoomCenterLoc[wmNr0b].X = pictureBox1.Size.Height - me.Location.Y - 1;
zoomCenterLoc[wmNr0b].Y = me.Location.X;
break;
case Rotation.R180:
zoomCenterLoc[wmNr0b].X = pictureBox1.Size.Width - me.Location.X - 1;
zoomCenterLoc[wmNr0b].Y = pictureBox1.Size.Height - me.Location.Y - 1;
break;
case Rotation.R270:
zoomCenterLoc[wmNr0b].X = me.Location.Y;
zoomCenterLoc[wmNr0b].Y = pictureBox1.Size.Width - me.Location.X - 1;
break;
}
zoomedImage = MakeZoomedImage(lastImage, zoomCenterLoc[wmNr0b]);
isZoomed[wmNr0b] = true;
ShowImage();
}
else if (me.Button == MouseButtons.Right)
{
isZoomed[wmNr0b] = false;
ShowImage();
}
}
private void rotateImageButton_Click(object sender, EventArgs e)
{
if (lastImage == null) return;
if (++imageRotation == Rotation.Count)
{
imageRotation = Rotation.R0;
}
ShowImage();
}
Bitmap MakeZoomedImage(Bitmap oriImage, Point centerLoc)
{
float picBoxW = (float)pictureBox1.Size.Width;
float picBoxH = (float)pictureBox1.Size.Height;
float newRelX = Math.Max(0, Math.Min(centerLoc.X / picBoxW - 0.25f, 0.5f));
float newRelY = Math.Max(0, Math.Min(centerLoc.Y / picBoxH - 0.25f, 0.5f));
Rectangle newRect = new Rectangle((int)(newRelX * oriImage.Width),
(int)(newRelY * oriImage.Height),
oriImage.Width / 2,
oriImage.Height / 2); /// image resolution, 1280 x 960
return lastImage.Clone(newRect, oriImage.PixelFormat);
}
///
/// Used by ShowImage()
///
Brush lightBrush = new SolidBrush(Color.LightGreen);
Brush darkBrush = new SolidBrush(Color.Green);
Font largeFont = new Font("arial", 24.0F, FontStyle.Bold); /// normal image
Font smallFont = new Font("arial", 12.0F, FontStyle.Bold); /// zoomed image
/// <summary>
/// Show selected image in the picture box.
/// lastWmNr1, lastImage, zoomedImage, isZoomed and imageRotation are used.
/// </summary>
void ShowImage()
{
if (lastImage == null)
{
pictureBox1.Image = new Bitmap(TBF.Properties.Resources.Empty);
return;
}
Bitmap tempBmp = isZoomed[wmNr0b]
? new Bitmap(zoomedImage.Clone(new Rectangle(0, 0, zoomedImage.Width, zoomedImage.Height), zoomedImage.PixelFormat))
: new Bitmap(lastImage.Clone(new Rectangle(0, 0, lastImage.Width, lastImage.Height), lastImage.PixelFormat));
switch (imageRotation)
{
case Rotation.R90: tempBmp.RotateFlip(RotateFlipType.Rotate270FlipNone); break;
case Rotation.R180: tempBmp.RotateFlip(RotateFlipType.Rotate180FlipNone); break;
case Rotation.R270: tempBmp.RotateFlip(RotateFlipType.Rotate90FlipNone); break;
}
/// Write water meter number to the bitmap
using (var grph = Graphics.FromImage(tempBmp))
{
Font font = isZoomed[wmNr0b] ? smallFont : largeFont;
int margin = isZoomed[wmNr0b] ? 1 : 2;
int pixelsCount = 0;
int brightness = 0;
for (int x = margin; x <= 8 * margin; x += margin)
{
for (int y = margin; y <= 8 * margin; y += margin)
{
brightness += (int)tempBmp.GetPixel(x, y).G;
pixelsCount++;
}
}
brightness /= pixelsCount;
Brush brush = (brightness > 160) ? darkBrush : lightBrush;
grph.DrawString(lastWmNr1.ToString(), font, brush, margin, margin);
}
pictureBox1.Image = tempBmp;
}
#region Forced close handling
public void StartForceCloseHandler()