Skip to content

Commit

Permalink
Merge branch 'release/2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
huysentruitw committed Nov 28, 2022
2 parents 5d47420 + 7b8548b commit 2e299e7
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 60 deletions.
74 changes: 33 additions & 41 deletions src/Barcoder.Renderer.Image/ImageRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,31 @@ namespace Barcoder.Renderer.Image
{
public sealed class ImageRenderer : IRenderer
{
private readonly IImageEncoder _imageEncoder;
private readonly int _pixelSize;
private readonly int _barHeightFor1DBarcode;
private readonly bool _includeEanContentAsText;
private readonly string _eanFontFamily;
private readonly ImageRendererOptions _options;
private readonly Lazy<IImageEncoder> _imageEncoder;

public ImageRenderer(
int pixelSize = 10,
int barHeightFor1DBarcode = 40,
ImageFormat imageFormat = ImageFormat.Png,
int jpegQuality = 75,
bool includeEanContentAsText = false,
string eanFontFamily = null)
public ImageRenderer(ImageRendererOptions options = null)
{
if (pixelSize <= 0) throw new ArgumentOutOfRangeException(nameof(pixelSize), "Value must be larger than zero");
if (barHeightFor1DBarcode <= 0) throw new ArgumentOutOfRangeException(nameof(barHeightFor1DBarcode), "Value must be larger than zero");
if (jpegQuality < 0 || jpegQuality > 100) throw new ArgumentOutOfRangeException(nameof(jpegQuality), "Value must be a value between 0 and 100");
options = options ?? new ImageRendererOptions();

_pixelSize = pixelSize;
_barHeightFor1DBarcode = barHeightFor1DBarcode;
_imageEncoder = GetImageEncoder(imageFormat, jpegQuality);
_includeEanContentAsText = includeEanContentAsText;
_eanFontFamily = eanFontFamily ?? "Arial";
}
if (options.PixelSize <= 0) throw new ArgumentOutOfRangeException(nameof(options.PixelSize), "Value must be larger than zero");
if (options.BarHeightFor1DBarcode <= 0) throw new ArgumentOutOfRangeException(nameof(options.BarHeightFor1DBarcode), "Value must be larger than zero");
if (options.JpegQuality < 0 || options.JpegQuality > 100) throw new ArgumentOutOfRangeException(nameof(options.JpegQuality), "Value must be a value between 0 and 100");

private static IImageEncoder GetImageEncoder(ImageFormat imageFormat, int jpegQuality)
_options = options;
_imageEncoder = new Lazy<IImageEncoder>(GetImageEncoder);
}

private IImageEncoder GetImageEncoder()
{
switch (imageFormat)
switch (_options.ImageFormat)
{
case ImageFormat.Bmp: return new BmpEncoder();
case ImageFormat.Gif: return new GifEncoder();
case ImageFormat.Jpeg: return new JpegEncoder { Quality = jpegQuality };
case ImageFormat.Jpeg: return new JpegEncoder { Quality = _options.JpegQuality };
case ImageFormat.Png: return new PngEncoder();
default:
throw new NotSupportedException($"Requested image format {imageFormat} is not supported");
throw new NotSupportedException($"Requested image format {_options.ImageFormat} is not supported");
}
}

Expand All @@ -69,8 +59,9 @@ public void Render(IBarcode barcode, Stream outputStream)

private void Render1D(IBarcode barcode, Stream outputStream)
{
int width = (barcode.Bounds.X + 2 * barcode.Margin) * _pixelSize;
int height = (_barHeightFor1DBarcode + 2 * barcode.Margin) * _pixelSize;
int margin = _options.CustomMargin ?? barcode.Margin;
int width = (barcode.Bounds.X + 2 * margin) * _options.PixelSize;
int height = (_options.BarHeightFor1DBarcode + 2 * margin) * _options.PixelSize;

using (var image = new Image<L8>(width, height))
{
Expand All @@ -83,24 +74,25 @@ private void Render1D(IBarcode barcode, Stream outputStream)
continue;
ctx.FillPolygon(
Color.Black,
new Vector2((barcode.Margin + x) * _pixelSize, barcode.Margin * _pixelSize),
new Vector2((barcode.Margin + x + 1) * _pixelSize, barcode.Margin * _pixelSize),
new Vector2((barcode.Margin + x + 1) * _pixelSize, (_barHeightFor1DBarcode + barcode.Margin) * _pixelSize),
new Vector2((barcode.Margin + x) * _pixelSize, (_barHeightFor1DBarcode + barcode.Margin) * _pixelSize));
new Vector2((margin + x) * _options.PixelSize, margin * _options.PixelSize),
new Vector2((margin + x + 1) * _options.PixelSize, margin * _options.PixelSize),
new Vector2((margin + x + 1) * _options.PixelSize, (_options.BarHeightFor1DBarcode + margin) * _options.PixelSize),
new Vector2((margin + x) * _options.PixelSize, (_options.BarHeightFor1DBarcode + margin) * _options.PixelSize));
}
});

if (_includeEanContentAsText && barcode.IsEanBarcode())
EanContentRenderer.Render(image, barcode, fontFamily: _eanFontFamily, scale: _pixelSize);
if (_options.IncludeEanContentAsText && barcode.IsEanBarcode())
EanContentRenderer.Render(image, barcode, fontFamily: _options.EanFontFamily, scale: _options.PixelSize);

image.Save(outputStream, _imageEncoder);
image.Save(outputStream, _imageEncoder.Value);
}
}

private void Render2D(IBarcode barcode, Stream outputStream)
{
int width = (barcode.Bounds.X + 2 * barcode.Margin) * _pixelSize;
int height = (barcode.Bounds.Y + 2 * barcode.Margin) * _pixelSize;
int margin = _options.CustomMargin ?? barcode.Margin;
int width = (barcode.Bounds.X + 2 * margin) * _options.PixelSize;
int height = (barcode.Bounds.Y + 2 * margin) * _options.PixelSize;

using (var image = new Image<L8>(width, height))
{
Expand All @@ -114,15 +106,15 @@ private void Render2D(IBarcode barcode, Stream outputStream)
if (!barcode.At(x, y)) continue;
ctx.FillPolygon(
Color.Black,
new Vector2((barcode.Margin + x) * _pixelSize, (barcode.Margin + y) * _pixelSize),
new Vector2((barcode.Margin + x + 1) * _pixelSize, (barcode.Margin + y) * _pixelSize),
new Vector2((barcode.Margin + x + 1) * _pixelSize, (barcode.Margin + y + 1) * _pixelSize),
new Vector2((barcode.Margin + x) * _pixelSize, (barcode.Margin + y + 1) * _pixelSize));
new Vector2((margin + x) * _options.PixelSize, (margin + y) * _options.PixelSize),
new Vector2((margin + x + 1) * _options.PixelSize, (margin + y) * _options.PixelSize),
new Vector2((margin + x + 1) * _options.PixelSize, (margin + y + 1) * _options.PixelSize),
new Vector2((margin + x) * _options.PixelSize, (margin + y + 1) * _options.PixelSize));
}
}
});

image.Save(outputStream, _imageEncoder);
image.Save(outputStream, _imageEncoder.Value);
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions src/Barcoder.Renderer.Image/ImageRendererOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Barcoder.Renderer.Image
{
public sealed class ImageRendererOptions
{
public int PixelSize { get; set; } = 10;

public int BarHeightFor1DBarcode { get; set; } = 40;

public ImageFormat ImageFormat { get; set; } = ImageFormat.Png;

public int JpegQuality { get; set; } = 75;

public bool IncludeEanContentAsText { get; set; } = false;

public string EanFontFamily { get; set; } = "Arial";

public int? CustomMargin { get; set; } = null;
}
}
27 changes: 16 additions & 11 deletions src/Barcoder.Renderer.Svg/SvgRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ public sealed class SvgRenderer : IRenderer
{
private static readonly int[] Ean8LongerBars = new[] { 0, 2, 32, 34, 64, 66 };
private static readonly int[] Ean13LongerBars = new[] { 0, 2, 46, 48, 92, 94 };
private readonly bool _includeEanContentAsText;

public SvgRenderer(bool includeEanContentAsText = false)
private readonly SvgRendererOptions _options;

public SvgRenderer(SvgRendererOptions options = null)
{
_includeEanContentAsText = includeEanContentAsText;
_options = options ?? new SvgRendererOptions();
}

private bool IncludeEanContent(IBarcode barcode)
=> _includeEanContentAsText && (barcode.Metadata.CodeKind == BarcodeType.EAN13 || barcode.Metadata.CodeKind == BarcodeType.EAN8);
=> _options.IncludeEanContentAsText && (barcode.Metadata.CodeKind == BarcodeType.EAN13 || barcode.Metadata.CodeKind == BarcodeType.EAN8);

public void Render(IBarcode barcode, Stream outputStream)
{
Expand All @@ -36,11 +37,13 @@ private void Render1D(IBarcode barcode, Stream outputStream)
{
var document = SvgDocument.Create();
int height = IncludeEanContent(barcode) ? 55 : 50;
int margin = _options.CustomMargin ?? barcode.Margin;

document.ViewBox = new SvgViewBox
{
Left = 0,
Top = 0,
Width = barcode.Bounds.X + 2 * barcode.Margin,
Width = barcode.Bounds.X + 2 * margin,
Height = height
};
document.Fill = "#FFFFFF";
Expand Down Expand Up @@ -81,14 +84,14 @@ private void Render1D(IBarcode barcode, Stream outputStream)
{
line = document.AddLine();
line.StrokeWidth = 1.5;
line.X1 = line.X2 = x + barcode.Margin - 0.25;
line.X1 = line.X2 = x + margin - 0.25;
line.Y1 = 0;
line.Y2 = lineHeight;
}
else
{
line = document.AddLine();
line.X1 = line.X2 = x + barcode.Margin;
line.X1 = line.X2 = x + margin;
line.Y1 = 0;
line.Y2 = lineHeight;
}
Expand Down Expand Up @@ -128,13 +131,15 @@ private void AddText(SvgDocument doc, double x, double y, string t)

private void Render2D(IBarcode barcode, Stream outputStream)
{
int margin = _options.CustomMargin ?? barcode.Margin;

var document = SvgDocument.Create();
document.ViewBox = new SvgViewBox
{
Left = 0,
Top = 0,
Width = barcode.Bounds.X + 2 * barcode.Margin,
Height = barcode.Bounds.Y + 2 * barcode.Margin
Width = barcode.Bounds.X + 2 * margin,
Height = barcode.Bounds.Y + 2 * margin
};
document.Fill = "#FFFFFF";
document.Stroke = "#000000";
Expand All @@ -150,8 +155,8 @@ private void Render2D(IBarcode barcode, Stream outputStream)
if (barcode.At(x, y))
{
SvgRect rect = group.AddRect();
rect.X = x + barcode.Margin;
rect.Y = y + barcode.Margin;
rect.X = x + margin;
rect.Y = y + margin;
rect.Width = 1;
rect.Height = 1;
}
Expand Down
9 changes: 9 additions & 0 deletions src/Barcoder.Renderer.Svg/SvgRendererOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Barcoder.Renderer.Svg
{
public sealed class SvgRendererOptions
{
public bool IncludeEanContentAsText { get; set; } = false;

public int? CustomMargin { get; set; } = null;
}
}
12 changes: 6 additions & 6 deletions tests/Barcoder.Renderer.Image.Tests/ImageRendererTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public void Render_Barcode2D()
public void Render_ImageFormatBmp_ShouldRenderBmp()
{
// Arrange
var renderer = new ImageRenderer(imageFormat: ImageFormat.Bmp);
var renderer = new ImageRenderer(new ImageRendererOptions { ImageFormat = ImageFormat.Bmp });
IBarcode barcode = QrEncoder.Encode("Hello", ErrorCorrectionLevel.L, Encoding.Unicode);
using var stream = new MemoryStream();

Expand All @@ -93,7 +93,7 @@ public void Render_ImageFormatBmp_ShouldRenderBmp()
public void Render_ImageFormatGif_ShouldRenderGif()
{
// Arrange
var renderer = new ImageRenderer(imageFormat: ImageFormat.Gif);
var renderer = new ImageRenderer(new ImageRendererOptions { ImageFormat = ImageFormat.Gif });
IBarcode barcode = QrEncoder.Encode("Hello", ErrorCorrectionLevel.L, Encoding.Unicode);
using var stream = new MemoryStream();

Expand All @@ -110,7 +110,7 @@ public void Render_ImageFormatGif_ShouldRenderGif()
public void Render_ImageFormatJpeg_ShouldRenderJpeg()
{
// Arrange
var renderer = new ImageRenderer(imageFormat: ImageFormat.Jpeg);
var renderer = new ImageRenderer(new ImageRendererOptions { ImageFormat = ImageFormat.Jpeg });
IBarcode barcode = QrEncoder.Encode("Hello", ErrorCorrectionLevel.L, Encoding.Unicode);
using var stream = new MemoryStream();

Expand All @@ -127,7 +127,7 @@ public void Render_ImageFormatJpeg_ShouldRenderJpeg()
public void Render_ImageFormatPng_ShouldRenderPng()
{
// Arrange
var renderer = new ImageRenderer(imageFormat: ImageFormat.Png);
var renderer = new ImageRenderer(new ImageRendererOptions { ImageFormat = ImageFormat.Png });
IBarcode barcode = QrEncoder.Encode("Hello", ErrorCorrectionLevel.L, Encoding.Unicode);
using var stream = new MemoryStream();

Expand All @@ -150,7 +150,7 @@ private static byte[] RenderBarcodeToByteArray(IRenderer renderer, IBarcode barc
[Fact(Skip = "Integration test")]
public void Render_Ean8_IncludeContentAsText()
{
var renderer = new ImageRenderer(imageFormat: ImageFormat.Png, includeEanContentAsText: true);
var renderer = new ImageRenderer(new ImageRendererOptions { ImageFormat = ImageFormat.Png, IncludeEanContentAsText = true });
IBarcode barcode = EanEncoder.Encode("1234567");
using Stream stream = File.OpenWrite(@"d:\temp\ean8-test.png");
renderer.Render(barcode, stream);
Expand All @@ -159,7 +159,7 @@ public void Render_Ean8_IncludeContentAsText()
[Fact(Skip = "Integration test")]
public void Render_Ean13_IncludeContentAsText()
{
var renderer = new ImageRenderer(imageFormat: ImageFormat.Png, includeEanContentAsText: true);
var renderer = new ImageRenderer(new ImageRendererOptions { ImageFormat = ImageFormat.Png, IncludeEanContentAsText = true });
IBarcode barcode = EanEncoder.Encode("978020137962");
using Stream stream = File.OpenWrite(@"d:\temp\ean13-test.png");
renderer.Render(barcode, stream);
Expand Down
4 changes: 2 additions & 2 deletions tests/Barcoder.Renderer.Svg.Tests/SvgRendererTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ private static string GetExpectedSvgOutput(string resourceName)
[Fact(Skip = "Integration test")]
public void Render_Ean8_IncludeContentAsText()
{
var renderer = new SvgRenderer(includeEanContentAsText: true);
var renderer = new SvgRenderer(new SvgRendererOptions { IncludeEanContentAsText = true });
IBarcode barcode = EanEncoder.Encode("1234567");
using Stream stream = File.OpenWrite(@"d:\temp\ean-test.svg");
renderer.Render(barcode, stream);
Expand All @@ -104,7 +104,7 @@ public void Render_Ean8_IncludeContentAsText()
[Fact(Skip = "Integration test")]
public void Render_Ean13_IncludeContentAsText()
{
var renderer = new SvgRenderer(includeEanContentAsText: true);
var renderer = new SvgRenderer(new SvgRendererOptions { IncludeEanContentAsText = true });
IBarcode barcode = EanEncoder.Encode("978020137962");
using Stream stream = File.OpenWrite(@"d:\temp\ean-test.svg");
renderer.Render(barcode, stream);
Expand Down

0 comments on commit 2e299e7

Please sign in to comment.