Added guess trim edges and guess combine adjustments so scrolling capture can automatically combine without user interaction

This commit is contained in:
Jaex 2015-09-26 03:42:43 +03:00
parent 151ceb2420
commit 022853ef4d
2 changed files with 279 additions and 47 deletions

View file

@ -34,7 +34,8 @@ private void InitializeComponent()
this.tcScrollingCapture = new System.Windows.Forms.TabControl();
this.tpCapture = new System.Windows.Forms.TabPage();
this.tpOutput = new System.Windows.Forms.TabPage();
this.btnGuessSettings = new System.Windows.Forms.Button();
this.btnProcess = new System.Windows.Forms.Button();
this.btnGuessEdges = new System.Windows.Forms.Button();
this.btnCombine = new System.Windows.Forms.Button();
this.gbCombineAdjustments = new System.Windows.Forms.GroupBox();
this.lblCombineLastVertical = new System.Windows.Forms.Label();
@ -52,7 +53,8 @@ private void InitializeComponent()
this.nudTrimRight = new System.Windows.Forms.NumericUpDown();
this.pOutput = new System.Windows.Forms.Panel();
this.pbOutput = new System.Windows.Forms.PictureBox();
this.btnProcess = new System.Windows.Forms.Button();
this.btnGuessCombineAdjustments = new System.Windows.Forms.Button();
this.btnResetCombine = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.nudScrollDelay)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudMaximumScrollCount)).BeginInit();
this.tcScrollingCapture.SuspendLayout();
@ -174,8 +176,10 @@ private void InitializeComponent()
//
// tpOutput
//
this.tpOutput.Controls.Add(this.btnResetCombine);
this.tpOutput.Controls.Add(this.btnGuessCombineAdjustments);
this.tpOutput.Controls.Add(this.btnProcess);
this.tpOutput.Controls.Add(this.btnGuessSettings);
this.tpOutput.Controls.Add(this.btnGuessEdges);
this.tpOutput.Controls.Add(this.btnCombine);
this.tpOutput.Controls.Add(this.gbCombineAdjustments);
this.tpOutput.Controls.Add(this.gbTrimEdges);
@ -188,23 +192,35 @@ private void InitializeComponent()
this.tpOutput.Text = "Output";
this.tpOutput.UseVisualStyleBackColor = true;
//
// btnGuessSettings
// btnProcess
//
this.btnGuessSettings.Location = new System.Drawing.Point(312, 16);
this.btnGuessSettings.Name = "btnGuessSettings";
this.btnGuessSettings.Size = new System.Drawing.Size(168, 23);
this.btnGuessSettings.TabIndex = 8;
this.btnGuessSettings.Text = "1. Guess settings";
this.btnGuessSettings.UseVisualStyleBackColor = true;
this.btnGuessSettings.Click += new System.EventHandler(this.btnGuessSettings_Click);
this.btnProcess.Location = new System.Drawing.Point(312, 88);
this.btnProcess.Name = "btnProcess";
this.btnProcess.Size = new System.Drawing.Size(376, 23);
this.btnProcess.TabIndex = 9;
this.btnProcess.Text = "4. Upload/save depending on after capture settings";
this.btnProcess.UseVisualStyleBackColor = true;
this.btnProcess.Click += new System.EventHandler(this.btnProcess_Click);
//
// btnGuessEdges
//
this.btnGuessEdges.Enabled = false;
this.btnGuessEdges.Location = new System.Drawing.Point(312, 16);
this.btnGuessEdges.Name = "btnGuessEdges";
this.btnGuessEdges.Size = new System.Drawing.Size(376, 23);
this.btnGuessEdges.TabIndex = 8;
this.btnGuessEdges.Text = "1. Guess edge values to trim";
this.btnGuessEdges.UseVisualStyleBackColor = true;
this.btnGuessEdges.Click += new System.EventHandler(this.btnGuessEdges_Click);
//
// btnCombine
//
this.btnCombine.Location = new System.Drawing.Point(312, 48);
this.btnCombine.Enabled = false;
this.btnCombine.Location = new System.Drawing.Point(312, 64);
this.btnCombine.Name = "btnCombine";
this.btnCombine.Size = new System.Drawing.Size(168, 23);
this.btnCombine.Size = new System.Drawing.Size(376, 23);
this.btnCombine.TabIndex = 8;
this.btnCombine.Text = "2. Combine images";
this.btnCombine.Text = "3. Combine images using these settings";
this.btnCombine.UseVisualStyleBackColor = true;
this.btnCombine.Click += new System.EventHandler(this.btnCombine_Click);
//
@ -397,15 +413,26 @@ private void InitializeComponent()
this.pbOutput.TabIndex = 0;
this.pbOutput.TabStop = false;
//
// btnProcess
// btnGuessCombineAdjustments
//
this.btnProcess.Location = new System.Drawing.Point(312, 80);
this.btnProcess.Name = "btnProcess";
this.btnProcess.Size = new System.Drawing.Size(168, 23);
this.btnProcess.TabIndex = 9;
this.btnProcess.Text = "3. Upload/Save";
this.btnProcess.UseVisualStyleBackColor = true;
this.btnProcess.Click += new System.EventHandler(this.btnProcess_Click);
this.btnGuessCombineAdjustments.Enabled = false;
this.btnGuessCombineAdjustments.Location = new System.Drawing.Point(312, 40);
this.btnGuessCombineAdjustments.Name = "btnGuessCombineAdjustments";
this.btnGuessCombineAdjustments.Size = new System.Drawing.Size(376, 23);
this.btnGuessCombineAdjustments.TabIndex = 10;
this.btnGuessCombineAdjustments.Text = "2. Guess combine adjustments";
this.btnGuessCombineAdjustments.UseVisualStyleBackColor = true;
this.btnGuessCombineAdjustments.Click += new System.EventHandler(this.btnGuessCombineAdjustments_Click);
//
// btnResetCombine
//
this.btnResetCombine.Location = new System.Drawing.Point(696, 16);
this.btnResetCombine.Name = "btnResetCombine";
this.btnResetCombine.Size = new System.Drawing.Size(75, 23);
this.btnResetCombine.TabIndex = 11;
this.btnResetCombine.Text = "Reset";
this.btnResetCombine.UseVisualStyleBackColor = true;
this.btnResetCombine.Click += new System.EventHandler(this.btnResetCombine_Click);
//
// ScrollingCaptureForm
//
@ -469,7 +496,9 @@ private void InitializeComponent()
private NumericUpDown nudTrimRight;
private Button btnCombine;
private Label lblCombineLastVertical;
private Button btnGuessSettings;
private Button btnGuessEdges;
private Button btnProcess;
private Button btnGuessCombineAdjustments;
private Button btnResetCombine;
}
}

View file

@ -29,6 +29,7 @@
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
@ -45,8 +46,9 @@ public partial class ScrollingCaptureForm : BaseForm
public Image Result { get; set; }
private WindowInfo selectedWindow;
private int currentScrollCount;
private List<Image> images = new List<Image>();
private int currentScrollCount;
private bool isBusy;
public ScrollingCaptureForm(ScrollingCaptureOptions options)
{
@ -71,6 +73,14 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing);
}
protected void OnProcessRequested(Image image)
{
if (ProcessRequested != null)
{
ProcessRequested(image);
}
}
private void btnSelectHandle_Click(object sender, EventArgs e)
{
Hide();
@ -141,8 +151,8 @@ private void StopCapture()
btnCapture.Enabled = true;
this.ShowActivate();
tcScrollingCapture.SelectedTab = tpOutput;
if (pbOutput.Image != null) pbOutput.Image.Dispose();
pbOutput.Image = ImageHelpers.CombineImages(images);
btnGuessEdges.Enabled = btnGuessCombineAdjustments.Enabled = btnCombine.Enabled = images.Count > 1;
ResetCombine();
}
private void Clean()
@ -257,8 +267,14 @@ private void nudCombineLastVertical_ValueChanged(object sender, EventArgs e)
CombineAndPreviewImages();
}
private void btnGuessSettings_Click(object sender, EventArgs e)
private void btnGuessEdges_Click(object sender, EventArgs e)
{
GuessEdges();
}
private void btnGuessCombineAdjustments_Click(object sender, EventArgs e)
{
GuessCombineAdjustments();
}
private void btnCombine_Click(object sender, EventArgs e)
@ -271,11 +287,25 @@ private void btnProcess_Click(object sender, EventArgs e)
OnProcessRequested((Image)Result.Clone());
}
private void btnResetCombine_Click(object sender, EventArgs e)
{
ResetCombine();
}
private void ResetCombine()
{
nudTrimLeft.Value = nudTrimTop.Value = nudTrimRight.Value = nudTrimBottom.Value = nudCombineVertical.Value = nudCombineLastVertical.Value = 0;
CombineAndPreviewImages();
}
private void CombineAndPreviewImages()
{
if (pbOutput.Image != null) pbOutput.Image.Dispose();
Result = CombineImages();
pbOutput.Image = Result;
if (!isBusy)
{
if (pbOutput.Image != null) pbOutput.Image.Dispose();
Result = CombineImages();
pbOutput.Image = Result;
}
}
private Image CombineImages()
@ -294,23 +324,28 @@ private Image CombineImages()
for (int i = 0; i < images.Count; i++)
{
Image newImage = null;
Image image = images[i];
Rectangle rect = new Rectangle(Options.TrimLeftEdge, Options.TrimTopEdge, image.Width - Options.TrimLeftEdge - Options.TrimRightEdge,
image.Height - Options.TrimTopEdge - Options.TrimBottomEdge);
if (i == images.Count - 1)
if (Options.TrimLeftEdge > 0 || Options.TrimTopEdge > 0 || Options.TrimTopEdge > 0 || Options.TrimBottomEdge > 0 ||
Options.CombineAdjustmentVertical > 0 || Options.CombineAdjustmentLastVertical > 0)
{
rect.Y += Options.CombineAdjustmentLastVertical;
rect.Height -= Options.CombineAdjustmentLastVertical;
}
else if (i > 0)
{
rect.Y += Options.CombineAdjustmentVertical;
rect.Height -= Options.CombineAdjustmentVertical;
}
Rectangle rect = new Rectangle(Options.TrimLeftEdge, Options.TrimTopEdge, image.Width - Options.TrimLeftEdge - Options.TrimRightEdge,
image.Height - Options.TrimTopEdge - Options.TrimBottomEdge);
Image newImage = ImageHelpers.CropImage(image, rect);
if (i == images.Count - 1)
{
rect.Y += Options.CombineAdjustmentLastVertical;
rect.Height -= Options.CombineAdjustmentLastVertical;
}
else if (i > 0)
{
rect.Y += Options.CombineAdjustmentVertical;
rect.Height -= Options.CombineAdjustmentVertical;
}
newImage = ImageHelpers.CropImage(image, rect);
}
if (newImage == null)
{
@ -320,15 +355,183 @@ private Image CombineImages()
output.Add(newImage);
}
return ImageHelpers.CombineImages(output);
Image result = ImageHelpers.CombineImages(output);
foreach (Image image in output)
{
if (image != null)
{
image.Dispose();
}
}
output.Clear();
return result;
}
protected void OnProcessRequested(Image image)
private void GuessEdges()
{
if (ProcessRequested != null)
if (images.Count < 2) return;
isBusy = true;
nudTrimLeft.Value = nudTrimTop.Value = nudTrimRight.Value = nudTrimBottom.Value = 0;
Rectangle rect = new Rectangle(0, 0, images[0].Width, images[0].Height);
using (UnsafeBitmap bmp1 = new UnsafeBitmap((Bitmap)images[0], true, ImageLockMode.ReadOnly))
using (UnsafeBitmap bmp2 = new UnsafeBitmap((Bitmap)images[1], true, ImageLockMode.ReadOnly))
{
ProcessRequested(image);
bool valueFound = false;
// Left edge
for (int x = rect.X; !valueFound && x < rect.Width; x++)
{
for (int y = rect.Y; y < rect.Height; y++)
{
if (bmp1.GetPixel(x, y) != bmp2.GetPixel(x, y))
{
valueFound = true;
nudTrimLeft.Value = x;
rect.X = x;
break;
}
}
}
valueFound = false;
// Top edge
for (int y = rect.Y; !valueFound && y < rect.Height; y++)
{
for (int x = rect.X; x < rect.Width; x++)
{
if (bmp1.GetPixel(x, y) != bmp2.GetPixel(x, y))
{
valueFound = true;
nudTrimTop.Value = y;
rect.Y = y;
break;
}
}
}
valueFound = false;
// Right edge
for (int x = rect.Width - 1; !valueFound && x >= rect.X; x--)
{
for (int y = rect.Y; y < rect.Height; y++)
{
if (bmp1.GetPixel(x, y) != bmp2.GetPixel(x, y))
{
valueFound = true;
nudTrimRight.Value = rect.Width - x - 1;
rect.Width = x + 1;
break;
}
}
}
valueFound = false;
// Bottom edge
for (int y = rect.Height - 1; !valueFound && y >= rect.X; y--)
{
for (int x = rect.X; x < rect.Width; x++)
{
if (bmp1.GetPixel(x, y) != bmp2.GetPixel(x, y))
{
valueFound = true;
nudTrimBottom.Value = rect.Height - y - 1;
rect.Height = y + 1;
break;
}
}
}
}
isBusy = false;
}
private void GuessCombineAdjustments()
{
if (images.Count > 1)
{
isBusy = true;
nudCombineVertical.Value = CalculateVerticalOffset(images[0], images[1]);
if (images.Count > 2)
{
nudCombineLastVertical.Value = CalculateVerticalOffset(images[images.Count - 2], images[images.Count - 1]);
}
isBusy = false;
}
}
private int CalculateVerticalOffset(Image img1, Image img2, int ignoreRightOffset = 50, int matchCount = 5)
{
Rectangle rect = new Rectangle(Options.TrimLeftEdge, Options.TrimTopEdge,
img1.Width - Options.TrimLeftEdge - Options.TrimRightEdge - (img1.Width > ignoreRightOffset ? ignoreRightOffset : 0),
img1.Height - Options.TrimTopEdge - Options.TrimBottomEdge);
using (UnsafeBitmap bmp1 = new UnsafeBitmap((Bitmap)img1, true, ImageLockMode.ReadOnly))
using (UnsafeBitmap bmp2 = new UnsafeBitmap((Bitmap)img2, true, ImageLockMode.ReadOnly))
{
for (int y = rect.Y; y < rect.Height; y++)
{
bool isLineMatches = true;
for (int x = rect.X; x < rect.Width; x++)
{
if (bmp2.GetPixel(x, y) != bmp1.GetPixel(x, rect.Height - 1))
{
isLineMatches = false;
break;
}
}
if (isLineMatches)
{
int lineMatchesCount = 0;
int y3 = 2;
for (int y2 = y - 1; y2 >= rect.Y; y2--)
{
bool isLineMatches2 = true;
for (int x2 = rect.X; x2 < rect.Width; x2++)
{
if (bmp2.GetPixel(x2, y2) != bmp1.GetPixel(x2, rect.Height - y3))
{
isLineMatches2 = false;
break;
}
}
if (isLineMatches2)
{
lineMatchesCount++;
y3++;
}
else
{
break;
}
if (lineMatchesCount == matchCount || y2 == rect.Y)
{
return y;
}
}
}
}
}
return 0;
}
}
}