Skip to content

Commit

Permalink
Fix bugs + change the smooth option behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
mlaily committed Apr 22, 2018
1 parent 65735b4 commit 83e1c8d
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 66 deletions.
64 changes: 40 additions & 24 deletions MovieBarCodeGenerator/FfmpegWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,49 +102,65 @@ IEnumerable<Bitmap> GetLazyStream()
{
using (cancellationToken.Register(() => process.Kill()))
{
foreach (var item in ReadBitmapStream(process.StandardOutput.BaseStream))
foreach (var item in ReadBitmapStream(process.StandardOutput.BaseStream, cancellationToken))
{
yield return item;
}
cancellationToken.ThrowIfCancellationRequested();
}
}

return GetLazyStream();
}

private IEnumerable<Bitmap> ReadBitmapStream(Stream stdout)
private IEnumerable<Bitmap> ReadBitmapStream(Stream stdout, CancellationToken cancellationToken)
{
using (var reader = new BinaryReader(stdout))
{
while (true)
{
// https://en.wikipedia.org/wiki/BMP_file_format
var magicNumber = reader.ReadBytes(2);
if (magicNumber.Length != 2)
Bitmap bmp;
try
{
break;
// https://en.wikipedia.org/wiki/BMP_file_format
var magicNumber = reader.ReadBytes(2);
if (magicNumber.Length != 2)
{
break;
}

if (magicNumber[0] != 0x42 || magicNumber[1] != 0x4D)
{
throw new InvalidDataException();
}

var bmpSizeBytes = reader.ReadBytes(4);
var bmpSize = BitConverter.ToInt32(bmpSizeBytes, 0);

var remainingDataLength = bmpSize - bmpSizeBytes.Length - magicNumber.Length;
var remainingData = reader.ReadBytes(remainingDataLength);

var ms = new MemoryStream();
ms.Write(magicNumber, 0, magicNumber.Length);
ms.Write(bmpSizeBytes, 0, bmpSizeBytes.Length);
ms.Write(remainingData, 0, remainingData.Length);

// We can't just give it our input stream,
// because it would not stop at the end of the first image.
bmp = new Bitmap(ms);
}

if (magicNumber[0] != 0x42 || magicNumber[1] != 0x4D)
catch (Exception)
{
throw new InvalidDataException();
if (cancellationToken.IsCancellationRequested)
{
cancellationToken.ThrowIfCancellationRequested();
yield break;
}
else
{
throw;
}
}

var bmpSizeBytes = reader.ReadBytes(4);
var bmpSize = BitConverter.ToInt32(bmpSizeBytes, 0);

var remainingDataLength = bmpSize - bmpSizeBytes.Length - magicNumber.Length;
var remainingData = reader.ReadBytes(remainingDataLength);

var ms = new MemoryStream();
ms.Write(magicNumber, 0, magicNumber.Length);
ms.Write(bmpSizeBytes, 0, bmpSizeBytes.Length);
ms.Write(remainingData, 0, remainingData.Length);

// We can't just give it our input stream,
// because it would not stop at the end of the first image.
var bmp = new Bitmap(ms);
yield return bmp;
}
}
Expand Down
19 changes: 8 additions & 11 deletions MovieBarCodeGenerator/ImageProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ public class BarCodeParameters
public int Width { get; set; } = 1000;
public int? Height { get; set; } = null;
public int BarWidth { get; set; } = 1;
public bool Smoothen { get; set; } = false;
}

public class ImageProcessor
Expand Down Expand Up @@ -83,18 +82,16 @@ Graphics GetDrawingSurface(int width, int height)

finalBitmapGraphics?.Dispose();

if (parameters.Smoothen && finalBitmap != null)
{
var onePixelHeight = GetResizedImage(finalBitmap, finalBitmap.Width, 1);
var smoothened = GetResizedImage(onePixelHeight, finalBitmap.Width, finalBitmap.Height);

onePixelHeight.Dispose();
finalBitmap.Dispose();
return finalBitmap;
}

finalBitmap = smoothened;
public Bitmap GetSmoothedCopy(Bitmap inputImage)
{
using (var onePixelHeight = GetResizedImage(inputImage, inputImage.Width, 1))
{
var smoothed = GetResizedImage(onePixelHeight, inputImage.Width, inputImage.Height);
return smoothed;
}

return finalBitmap;
}

// https://stackoverflow.com/a/24199315/755986
Expand Down
27 changes: 19 additions & 8 deletions MovieBarCodeGenerator/MainForm.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

94 changes: 71 additions & 23 deletions MovieBarCodeGenerator/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,11 @@ private async void generateButton_Click(object sender, EventArgs e)

string inputPath;
string outputPath;
string smoothedOutputPath;
BarCodeParameters parameters;
try
{
(inputPath, outputPath, parameters) = GetValidatedParameters();
(inputPath, outputPath, smoothedOutputPath, parameters) = GetValidatedParameters();
}
catch (OperationCanceledException)
{
Expand All @@ -108,7 +109,13 @@ private async void generateButton_Click(object sender, EventArgs e)
var progress = new PercentageProgressHandler(percentage =>
{
var progressBarValue = Math.Min(100, (int)Math.Round(percentage * 100, MidpointRounding.AwayFromZero));
Invoke(new Action(() => progressBar1.Value = progressBarValue));
Invoke(new Action(() =>
{
if (_cancellationTokenSource != null)
{
progressBar1.Value = progressBarValue;
}
}));
});

_cancellationTokenSource = new CancellationTokenSource();
Expand Down Expand Up @@ -142,22 +149,21 @@ await Task.Run(() =>
catch (Exception ex)
{
MessageBox.Show(this,
$@"Sorry, something went wrong, and it probably won't resolve on its own.
$@"Sorry, something went wrong.
Here is all the info available at the time of the error (press Ctrl+C to copy it).
Input: {inputPath}
Output width: {parameters.Width}
Output height: {parameters.Height}
Bar width: {parameters.BarWidth}
Smoothen: {parameters.Smoothen}
Error: {ex}",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
finally
{
generateButton.Text = GenerateButtonText;
_cancellationTokenSource.Dispose();
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = null;
}

Expand All @@ -171,36 +177,79 @@ Here is all the info available at the time of the error (press Ctrl+C to copy it
{
MessageBox.Show(this, $" Unable to save the image: {ex}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

if (smoothedOutputPath != null)
{
Bitmap smoothed;
try
{
smoothed = _imageProcessor.GetSmoothedCopy(result);
}
catch (Exception ex)
{
MessageBox.Show(this, $"An error occured while creating the smoothed version of the barcode. Error: {ex}",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}

try
{
smoothed.Save(smoothedOutputPath);
}
catch (Exception ex)
{
MessageBox.Show(this, $" Unable to save the smoothed image: {ex}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}

private (string InputPath, string OutputPath, BarCodeParameters Parameters) GetValidatedParameters()
private (string InputPath, string OutputPath, string SmoothedOutputPath, BarCodeParameters Parameters)
GetValidatedParameters()
{
var inputPath = inputPathTextBox.Text.Trim(new [] { '"' });
var inputPath = inputPathTextBox.Text.Trim(new[] { '"' });
if (!File.Exists(inputPath))
{
throw new Exception("The input file does not exist.");
}

var outputPath = outputPathTextBox.Text.Trim(new[] { '"' });
if (string.IsNullOrWhiteSpace(outputPath) || outputPath.Any(x => Path.GetInvalidPathChars().Contains(x)))
{
throw new Exception("The output path is invalid.");
}

if (!Path.HasExtension(outputPath))
void ValidateOutputPath(ref string path)
{
outputPath += ".png";
}
if (string.IsNullOrWhiteSpace(path))
{
path = "output.png";
}

if (File.Exists(outputPath))
{
var promptResult = MessageBox.Show(
$"The file '{outputPath}' already exists. Are you sure you want to overwrite it?",
"Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (promptResult != DialogResult.Yes)
if (!Path.HasExtension(path))
{
path += ".png";
}

if (path.Any(x => Path.GetInvalidPathChars().Contains(x)))
{
throw new OperationCanceledException();
throw new Exception("The output path is invalid.");
}

if (File.Exists(path))
{
var promptResult = MessageBox.Show(this,
$"The file '{path}' already exists. Do you want to overwrite it?",
"Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (promptResult != DialogResult.Yes)
{
throw new OperationCanceledException();
}
}
}

ValidateOutputPath(ref outputPath);

string smoothedOutputPath = null;
if (smoothCheckBox.Checked)
{
smoothedOutputPath = $"{Path.GetFileNameWithoutExtension(outputPath)}_smoothed{Path.GetExtension(outputPath)}";
ValidateOutputPath(ref smoothedOutputPath);
}

if (!int.TryParse(barWidthTextBox.Text, out var barWidth))
Expand Down Expand Up @@ -228,13 +277,12 @@ Here is all the info available at the time of the error (press Ctrl+C to copy it

var parameters = new BarCodeParameters()
{
Smoothen = smoothCheckBox.Checked,
BarWidth = barWidth,
Width = imageWidth,
Height = imageHeight
};

return (inputPath, outputPath, parameters);
return (inputPath, outputPath, smoothedOutputPath, parameters);
}

private void browseInputPathButton_Click(object sender, EventArgs e)
Expand Down
3 changes: 3 additions & 0 deletions MovieBarCodeGenerator/MainForm.resx
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@
<metadata name="smoothCheckBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="label7.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
Expand Down

0 comments on commit 83e1c8d

Please sign in to comment.