ZXing-Core BitMatrix to BitMap - c#

I am using ZXing-Core(0.14.0.2) to create a barcode which gives me a BitMatrix, however I have not found documentation as to how to extract the image part from the BitMatrix and use it as BitMap so I can incorporate in my bigger image. Eventually what I would like to end up with would be something like this:
The code I currently have is:
img = new Bitmap(300, 375);
drawing = Graphics.FromImage(img);
var barCode = new Code128Writer().encode(packageModel.TrackingId.PrintValue, BarcodeFormat.CODE_128, 280, 70);
src = transform **barCode** to **Drawing.Image**
drawing.DrawImage(src, new Rectangle(10, 255, 280, 70));
UPDATE
I now have this code, however I am getting an error You have to set a renderer instance. I dont understand why the interface is not instantiating this class by itself. There is not documentation available revealing how this is supposed to work. I cant use the Write functions because the Rendering is set to null, however I am not sure how to instantiate it.
IBarcodeWriterGeneric<Image> barcodeWriterGeneric = new BarcodeWriterGeneric<Image>
{
Format = BarcodeFormat.CODE_128,
Options = new EncodingOptions
{
Width = 280,
Height = 70
},
Renderer = new PixelData() //HOW DOES THE RENDERER WORK????
};
var test = barcodeWriterGeneric.Write("WORKS");
drawing.DrawImage(test, new Rectangle(10, 255, 280, 70));

Create a renderer that implements IBarcodeRenderer<TOut>. This one works for me in iOS.
var writer = new BarcodeWriter<UIImage>()
{
Format = ZXing.BarcodeFormat.CODE_128,
Options = new EncodingOptions
{
Height = height,
Width = width,
Margin = 0
},
Renderer = new BarcodeRenderer()
};
var image = writer.Write(barcodeValue);
private class BarcodeRenderer : IBarcodeRenderer<UIImage>
{
public UIImage Render(BitMatrix matrix, ZXing.BarcodeFormat format, string content)
{
return RenderMatrix(matrix);
}
public UIImage Render(BitMatrix matrix, ZXing.BarcodeFormat format, string content, EncodingOptions options)
{
return RenderMatrix(matrix);
}
}
/// <summary>
/// Renders the bitmatrix.
/// </summary>
private static UIImage RenderMatrix(BitMatrix matrix)
{
var width = matrix.Width;
var height = matrix.Height;
var black = new CGColor(0f, 0f, 0f);
var white = new CGColor(1.0f, 1.0f, 1.0f);
UIGraphics.BeginImageContext(new CGSize(width, height));
var context = UIGraphics.GetCurrentContext();
for (var x = 0; x < width; x++)
{
for (var y = 0; y < height; y++)
{
context.SetFillColor(matrix[x, y] ? black : white);
context.FillRect(new CGRect(x, y, 1, 1));
}
}
var img = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return img;
}

As far as I can see the ZXing-Core fork is missing the PixelDataRenderer class. It contains only the RawRenderer. You should switch to the original ZXing.Net package with the current version 0.15.0. That one contains the barcode writer class "BarcodeWriterPixelData" which does the necessary initialization of the Renderer property. Next version of ZXing.Net will contain some more specialized bindings to other .Net Core compatible imaging libraries like CoreCompat.System.Drawing, ImageSharp, OpenCV and more. With that bindings you can then generate other output formats besides PixelData.

Related

How to fix QR code generation using ZXing.Net lib

It is necessary to generate a QR code from the text. I'm using the ZXing.unity.dll library
using ZXing;
using ZXing.QrCode;
Generating QR code
private static Color32[] Encode(string textForEncoding, int width, int height) {
var writer = new BarcodeWriter {
Format = BarcodeFormat.QR_CODE,
Options = new QrCodeEncodingOptions{
Height = height,
Width = width
}
};
return writer.Write(textForEncoding);
}
public Texture2D generateQR(string text) {
var encoded = new Texture2D (256, 256);
var color32 = Encode(text, encoded.width, encoded.height);
encoded.SetPixels32(color32);
encoded.Apply();
return encoded;
}
Applying the generated QR to the RawImage filled in the field
public RawImage RI;
...
RI.texture = generateQR("https://test.link/123");
The output is a picture with large white edges.
QR code preview pic
Q1 - How to remove white edges;
Q2 - How to make a transparent background;
Q3 - How to change black color to any other
Q3: Sample for changing foreground and background color:
private static Color32[] Encode(string textForEncoding, int width, int height)
{
var writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new QrCodeEncodingOptions
{
Height = height,
Width = width
},
Renderer = new Color32Renderer
{
Background = new Color32(255, 0, 0, 0),
Foreground = new Color32(0, 255, 0, 0)
}
};
return writer.Write(textForEncoding);
}
Q2: I' not absolutely sure, but the following sample should create a transparent background:
private static Color32[] Encode(string textForEncoding, int width, int height)
{
var writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new QrCodeEncodingOptions
{
Height = height,
Width = width
},
Renderer = new Color32Renderer
{
Background = new Color32(0, 0, 0, 255)
}
};
return writer.Write(textForEncoding);
}
Q1: create the image as small as possible without a border and resize it manually
private static Color32[] Encode(string textForEncoding, int width, int height)
{
var writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new QrCodeEncodingOptions
{
Height = width,
Width = height,
Margin = 0
}
};
return writer.Write(textForEncoding);
}
public Texture2D generateQR(string text)
{
// create the image as small as possible without a white border by setting width an height to 1
var color32 = Encode(text, 1, 1);
var widthAndHeight = color32.Length / 2;
var encoded = new Texture2D(widthAndHeight, widthAndHeight);
encoded.SetPixels32(color32);
encoded.Apply();
//
// Attention: insert code for resizing to the desired size here
// I didn't try it myself. Not sure if it works.
//
encoded.Resize(256, 256);
return encoded;
}

How to build a customized 3D Object modeling with Aspose 3D lib

I'm trying to build a 3D object model. But my code just has rendered a 3D model with a specific colour in the image.
How can I create a 3D object with 6 images for each surface like a Rubik cube?
This is my code, using Aspose 3D lib and C#:
private void Form1_Load(object sender, EventArgs e)
{
//Create a FBX file with embedded textures
Scene scene = new Scene();
scene.Open("BetterShirt.obj");
//Create an embedded texture
Texture tex = new Texture()
{
Content = CreateTextureContent(),
FileName = "face.png",
WrapModeU = Aspose.ThreeD.Shading.WrapMode.Wrap,
};
tex.SetProperty("TexProp", "value");
//create a material with custom property
//Aspose.ThreeD.Shading.
Material mat = scene.RootNode.ChildNodes[0].Material;
mat.SetTexture(Material.MapDiffuse, tex);
mat.SetProperty("MyProp", 1.0);
scene.RootNode.ChildNodes[0].Material = mat;
//save this to file
scene.Save("exported.obj", FileFormat.WavefrontOBJ);
}
private static byte[] CreateTextureContent()
{
using (var bitmap = new Bitmap(256, 256))
{
using (var g = Graphics.FromImage(bitmap))
{
g.Clear(Color.White);
LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, 128, 128),
Color.Moccasin, Color.Blue, 45);
using (var font = new Font(FontFamily.GenericSerif, 40))
{
g.DrawString("Aspose.3D", font, brush, Point.Empty);
}
}
using (var ms = new MemoryStream())
{
//bitmap.Save(ms, ImageFormat.Png);
return ms.ToArray();
}
}
}
build an 3D object model with 6 images
We have devised below code based on your requirements. Comments have also been added for your reference. Please try using it in your environment and then share your kind feedback with us.
private static void RubikCube()
{
Bitmap[] bitmaps = CreateRubikBitmaps();
Scene scene = new Scene();
//create a box and convert it to mesh, so we can manually specify the material per face
var box = (new Box()).ToMesh();
//create a material mapping, the box mesh generated from Box primitive class contains 6 polygons, then we can reference the material of polygon(specified by MappingMode.Polygon) by index(ReferenceMode.Index)
var materials = (VertexElementMaterial)box.CreateElement(VertexElementType.Material, MappingMode.Polygon, ReferenceMode.Index);
//and each polygon uses different materials, the indices of these materials are specified below
materials.SetIndices(new int[] {0, 1, 2, 3, 4, 5});
//create the node and materials(referenced above)
var boxNode = scene.RootNode.CreateChildNode(box);
for (int i = 0; i < bitmaps.Length; i++)
{
//create material with texture
var material = new LambertMaterial();
var tex = new Texture();
using (var ms = new MemoryStream())
{
bitmaps[i].Save(ms, ImageFormat.Png);
var bytes = ms.ToArray();
//Save it to Texture.Content as embedded texture, thus the scene with textures can be exported into a single FBX file.
tex.Content = bytes;
//Give it a name and save it to disk so it can be opened with .obj file
tex.FileName = string.Format("cube_{0}.png", i);
File.WriteAllBytes(tex.FileName, bytes);
//Dispose the bitmap since we're no longer need it.
bitmaps[i].Dispose();
}
//the texture is used as diffuse
material.SetTexture(Material.MapDiffuse, tex);
//attach it to the node where contains the box mesh
boxNode.Materials.Add(material);
}
//save it to file
//3D viewer of Windows 10 does not support multiple materials, you'll see same textures in each face, but the tools from Autodesk does
scene.Save("test.fbx", FileFormat.FBX7500ASCII);
//NOTE: Multiple materials of mesh in Aspose.3D's OBJ Exporter is not supported yet.
//But we can split the mesh with multiple materials into different meshes by using PolygonModifier.SplitMesh
PolygonModifier.SplitMesh(scene, SplitMeshPolicy.CloneData);
//following code will also generate a material library file(test.mtl) which uses the textures exported in above code.
scene.Save("test.obj", FileFormat.WavefrontOBJ);
}
private static Bitmap[] CreateRubikBitmaps()
{
Brush[] colors = { Brushes.White, Brushes.Red, Brushes.Blue, Brushes.Yellow, Brushes.Orange, Brushes.Green};
Bitmap[] bitmaps = new Bitmap[6];
//initialize the cell colors
int[] cells = new int[6 * 9];
for (int i = 0; i < cells.Length; i++)
{
cells[i] = i / 9;
}
//shuffle the cells
Random random = new Random();
Array.Sort(cells, (a, b) => random.Next(-1, 2));
//paint each face
// size of each face is 256px
const int size = 256;
// size of cell is 80x80
const int cellSize = 80;
// calculate padding size between each cell
const int paddingSize = (size - cellSize * 3) / 4;
int cellId = 0;
for (int i = 0; i < 6; i++)
{
bitmaps[i] = new Bitmap(size, size, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
using (Graphics g = Graphics.FromImage(bitmaps[i]))
{
g.Clear(Color.Black);
for (int j = 0; j < 9; j++)
{
//calculate the cell's position
int row = j / 3;
int column = j % 3;
int y = row * (cellSize + paddingSize) + paddingSize;
int x = column * (cellSize + paddingSize) + paddingSize;
Brush cellBrush = colors[cells[cellId++]];
//paint cell
g.FillRectangle(cellBrush, x, y, cellSize, cellSize);
}
}
}
return bitmaps;
}
PS: I work with Aspose as Developer Evangelist.

Moving UWP InkStrokes for Offscreen Rendering

I am capturing InkStrokes and have a need to create a scaled bitmap image of the strokes in the background. The captured images need to be of uniform size regardless of how big the bounding box of the ink.
For example, if original ink stroke is drawn and the bounding box top/left is 100,100 and size is 200,200 on the ink canvas, I want the ink to start at 0,0 of the new rendered bitmap that is 50,50 size (ignore impact of stroke width right now).
I have figured out how to scale the ink strokes (thanks StackOverflow) but not how to move the strokes. Right now, it seems I have to create a bitmap the size of the InkCanvas, render the scaled ink, then crop bigger image to the correct size.
I've tried using the InkStroke.PointTranslate via
var scaleMatrix = Matrix3x2.CreateScale(scale);
scaleMatrix.Translation = -offset; // top/left of ink stroke bounding box
stroke.PointTransform = scaleMatrix;
But the coordinates do not come out correct.
Any help much appreciated.
You can combine transformations by multiplying matrices. This works for me
var strokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
var boundingBox = inkCanvas.InkPresenter.StrokeContainer.BoundingRect;
var matrix1 = Matrix3x2.CreateTranslation((float)-boundingBox.X, (float)-boundingBox.Y);
var matrix2 = Matrix3x2.CreateScale(0.5f);
var builder = new InkStrokeBuilder();
var newStrokeList = new List<InkStroke>();
foreach (var stroke in strokes)
{
newStrokeList.Add(builder.CreateStrokeFromInkPoints
(stroke.GetInkPoints(), matrix1 * matrix2));
}
//Add the translated and scaled strokes to the inkcanvas
inkCanvas.InkPresenter.StrokeContainer.AddStrokes(newStrokeList);
Maybe I was still doing something wrong, but it appears you cannot use InkStrokeBuilder.CreateStrokeFromInkPoints with more than one kind of transform. I tried all kinds of combinations/approaches, and just could not get it to work.
Here is my solution...
private static IList<InkStroke> GetScaledAndTransformedStrokes(IList<InkStroke> strokeList, float scale)
{
var builder = new InkStrokeBuilder();
var newStrokeList = new List<InkStroke>();
var boundingBox = strokeList.GetBoundingBox();
foreach (var singleStroke in strokeList)
{
var translateMatrix = new Matrix(1, 0, 0, 1, -boundingBox.X, -boundingBox.Y);
var newInkPoints = new List<InkPoint>();
var originalInkPoints = singleStroke.GetInkPoints();
foreach (var point in originalInkPoints)
{
var newPosition = translateMatrix.Transform(point.Position);
var newInkPoint = new InkPoint(newPosition, point.Pressure, point.TiltX, point.TiltY, point.Timestamp);
newInkPoints.Add(newInkPoint);
}
var newStroke = builder.CreateStrokeFromInkPoints(newInkPoints, new Matrix3x2(scale, 0, 0, scale, 0, 0));
newStrokeList.Add(newStroke);
}
return newStrokeList;
}
I ended up having to apply my own translate transform then use the builder.CreateStrokeFromInkPoints with a scale matrix applied to get the results I wanted. GetBoundingBox is my own extension:
public static class RectExtensions
{
public static Rect CombineWith(this Rect r, Rect rect)
{
var top = (r.Top < rect.Top) ? r.Top : rect.Top;
var left = (r.Left < rect.Left) ? r.Left : rect.Left;
var bottom = (r.Bottom < rect.Bottom) ? rect.Bottom : r.Bottom;
var right = (r.Right < rect.Right) ? rect.Right : r.Right;
var newRect = new Rect(new Point(left, top), new Point(right, bottom));
return newRect;
}
}

Using Imagecomparer, How can I exclude a middle section of a ToleranceRectangle from being compared?

I am using imagecomparer in my mobile test project and I am able to compare a baseline image to a current screenshot, but the problem comes in where there is a section of the screenshot that is always changing and I would like to exclude that part from being compared. Here is my code:
private bool RunVisualCheck(string screen, string resultsPath, string baseline = "baseline.jpeg", string screenshot = "screenshot.jpeg")
{
GetScreenshot(resultsPath + screenshot);
var baselineImage = Image.FromFile(resultsPath + baseline);
var actualImage = Image.FromFile(resultsPath + screenshot);
Image diffImage;
int ignoreTop = 64;
var compareArea = new List<ToleranceRectangle>
{
new ToleranceRectangle()
{
Rectangle = new Rectangle(0,ignoreTop,baselineImage.Width, baselineImage.Height - ignoreTop),
Difference = new ColorDifference()
}
};
bool goodCompare = ImageComparer.Compare(actualImage, baselineImage, compareArea, out diffImage);
if (!goodCompare)
{
diffImage.Save(resultsPath + "diffImage.jpeg");
}
return goodCompare;
}
private void GetScreenshot(string pathFile)
{
System.Threading.Thread.Sleep(2000); // Temp fix to wait until page loads
var srcFiler = ((ITakesScreenshot)mobileDriver).GetScreenshot();
srcFiler.SaveAsFile(pathFile, ImageFormat.Jpeg);
}
Here is an example (not the app being tested) where I would like to exclude the area inside the red rectangle from the overall screenshot from being compared.
Mobile Screenshot Example
Is there an easy way to do this?
Found a better approach than trying to exclude a section from being compared. Thanks to a coworkers suggestion, I am blacking out the sections that do not need comparing and then saving this image. Doing this on the baseline image and the screenshot will have the same effect as excluding it altogether. Here is the code:
Image image = Image.FromFile(#"C:\Screenshots\Screenshot.jpeg");
using (Graphics g = Graphics.FromImage(image))
{
SolidBrush brush = new SolidBrush(Color.Black);
Size size = new Size(image.Width, 64);
Point point = new Point(0, 0);
Rectangle rectangle;
rectangle = new Rectangle(point, size);
g.FillRectangle(brush, rectangle);
}
image.Save(#"C:\Screenshots\Screenshot.jpeg");

How to change the QR Code version from 3 to 10 in ZXing

I have created an application which generates me a qr code image with ZXing library, but it uses version 3 for the qr code and I want to know if I can change it to version 10...I am new to the ZXing library...
This is the code:
public void CreateQRImage(string inputData)
{
if (radioRH.Checked)
{
if (inputData.Trim() == String.Empty)
{
System.Windows.Forms.MessageBox.Show("Data must not be empty.");
}
BarcodeWriter qrcoder = new ZXing.BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new ZXing.QrCode.QrCodeEncodingOptions
{
ErrorCorrection = ZXing.QrCode.Internal.ErrorCorrectionLevel.H,
Height = 250,
Width = 250
}
};
string tempFileName = System.IO.Path.GetTempPath() + inputData + ".png";
Image image;
String data = inputData;
var result = qrcoder.Write(inputData);
image = new Bitmap(result);
image.Save(tempFileName);
System.Diagnostics.Process.Start(tempFileName);
var textRes = qrcoder.Write(inputData);
int textWidth = 230, textHeight = 20;
// creating new bitmap having imcreased width
var img = new Bitmap(textRes.Width + textWidth, textRes.Height);
using (var g = Graphics.FromImage(img))
using (var font = new Font(FontFamily.GenericMonospace, 14))
using (var brush = new SolidBrush(Color.Black))
using (var bgBrush = new SolidBrush(Color.White))
using (var format = new StringFormat() { Alignment = StringAlignment.Near })
{
// filling background with white color
g.FillRectangle(bgBrush, 0, 0, img.Width, img.Height);
// drawing the generated image over new one
g.DrawImage(textRes, new Point(0, 0));
// drawing text
g.DrawString(inputData, font, brush, textRes.Width, (result.Height - textHeight) / 2, format);
}
img.Save(tempFileName);
}
I want the QR Code image to be changed from this (version 3)
To this (version 10)
I know this is an old question, but I recently had the same problem.
I was asked by my company to generate version 4 QR codes (33 by 33), but Zxing was defaulting to a lower version.
This is not documented hardly at all on the net, but there is a way to force Zxing to generate a specific version of QR code. In your code sample, just add "QrVersion = 10" to the format options:
BarcodeWriter qrcoder = new ZXing.BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new ZXing.QrCode.QrCodeEncodingOptions
{
ErrorCorrection = ZXing.QrCode.Internal.ErrorCorrectionLevel.H,
Height = 250,
Width = 250,
QrVersion = 10
}
};
This will produce a version-10 QR code.
**Note: If you set a low QrVersion number (for example, 4), then try to put lots of data into the QR code, an error will be thrown.

Categories