I have existing image converted to base64 and I would like to add text on top of it. However this return only the original image. Could you please advise where am I making mistake?
var signatureData = Convert.FromBase64String(signature);
var stream = new MemoryStream(signatureData);
var signatureBitmap = SKBitmap.Decode(stream);
var canvas = new SKCanvas(signatureBitmap);
var origin = new SKPoint();
var paint = new SKPaint
{
TextSize = 10,
IsAntialias = true,
Color = SKColors.Black,
IsStroke = false
};
origin.X = 10;
origin.Y = 30;
paint.TextAlign = SKTextAlign.Left;
canvas.DrawText("text", origin, paint);
canvas.Flush();
var resultImage = SKImage.FromBitmap(signatureBitmap);
var data = resultImage.Encode(SKEncodedImageFormat.Png, 100);
return Convert.ToBase64String(data.ToArray());
This posted question actually worked for me, only the position was wrong so the text was very tiny
Related
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.
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.
I have a chart that I'm displaying to the user and I want to be able to export the chart as an image to disk so they can use it outside of the application (for a presentation or something).
I've managed to get the basic idea working using PngBitmapEncoder and RenderTargetBitmap but the image I get out of it is way to small to really be usable and I want to get a much larger image.
I tried to simply increase the Height and Width of the control I was wanting to render, but the parent seems to have direct control on the render size. From this I tried to duplicate the UIElement in memory but then the render size was (0,0) and when I tried to use methods to get it to render, such as Measure() Arrange() and UpdateLayout() they throw exceptions about needing to decouple the parent to call these, but as it's in memory and not rendered there shouldn't be a parent?
This is all done with Visiblox charting API
Here is what I've got currently, except it doesn't work :(
var width = 1600;
var height = 1200;
var newChart = new Chart { Width = width, Height = height, Title = chart.Title, XAxis = chart.XAxis, YAxis = chart.YAxis, Series = chart.Series};
Debug.WriteLine(newChart.RenderSize);
var size = new Size(width, height);
newChart.Measure(size);
newChart.Arrange(new Rect(size));
newChart.UpdateLayout();
Debug.WriteLine(newChart.RenderSize);
var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
rtb.Render(newChart);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
using (var stream = fileDialog.OpenFile())
encoder.Save(stream);
I've gotten a bit closer, it now render the graph background the axis' etc. but just not the actual lines that are being graphed. Below is an updated source
public static void RenderChartToImage(Chart elementToRender, string filename)
{
if (elementToRender == null)
return;
Debug.Write(elementToRender.RenderSize);
var clone = new Chart();
clone.Width = clone.Height = double.NaN;
clone.HorizontalAlignment = HorizontalAlignment.Stretch;
clone.VerticalAlignment = VerticalAlignment.Stretch;
clone.Margin = new Thickness();
clone.Title = elementToRender.Title;
clone.XAxis = new DateTimeAxis();
clone.YAxis = new LinearAxis() { Range = Range<double>)elementToRender.YAxis.Range};
foreach (var series in elementToRender.Series)
{
var lineSeries = new LineSeries
{
LineStroke = (series as LineSeries).LineStroke,
DataSeries = series.DataSeries
};
clone.Series.Add(lineSeries);
}
var size = new Size(1600, 1200);
clone.Measure(size);
clone.Arrange(new Rect(size));
clone.UpdateLayout();
Debug.Write(clone.RenderSize);
var height = (int)clone.ActualHeight;
var width = (int)clone.ActualWidth;
var renderer = new RenderTargetBitmap(width, height, 96d, 96d, PixelFormats.Pbgra32);
renderer.Render(clone);
var pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(renderer));
using (var file = File.Create(filename))
{
pngEncoder.Save(file);
}
}
So I get out something like this:
Which while big, isn't useful as it has nothing charted.
http://www.visiblox.com/blog/2011/05/printing-visiblox-charts
The main point I was missing was
InvalidationHandler.ForceImmediateInvalidate = true;
Setting this before I rendered the chart in memory and then reverting it once I had finished. From there it was smooth sailing :D
RenderTargetBitmap DrawToImage<T>(T source, double scale) where T:FrameworkElement
{
var clone = Clone(source);
clone.Width = clone.Height = Double.NaN;
clone.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
clone.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
clone.Margin = new Thickness();
var size = new Size(source.ActualWidth * scale, source.ActualHeight * scale);
clone.Measure(size);
clone.Arrange(new Rect(size));
var renderBitmap = new RenderTargetBitmap((int)clone.ActualWidth, (int)clone.ActualHeight, 96, 96, PixelFormats.Pbgra32);
renderBitmap.Render(clone);
return renderBitmap;
}
static T Clone<T>(T source) where T:UIElement
{
if (source == null)
return null;
string xaml = XamlWriter.Save(source);
var reader = new StringReader(xaml);
var xmlReader = XmlTextReader.Create(reader, new XmlReaderSettings());
return (T)XamlReader.Load(xmlReader);
}
I think these might help :
Exporting Visifire Silverlight Chart as Image with a downloadable silverlight solution.
Exporting Chart as Image in WPF
I build a file uploader using silverlight and http://imagetools.codeplex.com/.
Its all ok, but my final file is about 300KB(size) with an 400 x 300(resolution).
When i open it on MS Paint and Save It as jpg again the size is set to normal.
my suspect is de enconde o file is a (png) but i don't now how.
My Code:
public static byte[] resize(string extension,int width,int height,int orientation)
{
//Decoders.AddDecoder<BmpDecoder>();
//Decoders.AddDecoder<PngDecoder>();
Decoders.AddDecoder<JpegDecoder>();
//Decoders.AddDecoder<GifDecoder>();
var newImg = new ExtendedImage();
if (orientation == 0)
newImg = ExtendedImage.Resize(img, width, height, new ImageTools.Filtering.NearestNeighborResizer());
else
newImg = ExtendedImage.Resize(img, height, width, new ImageTools.Filtering.NearestNeighborResizer());
//newImg = applyWaterMark(newImg);
//var s = new MemoryStream();
var s = newImg.ToStreamByExtension(extension);
return ReadFully(s);
}
solved!!
var e = new ImageTools.IO.Jpeg.JpegEncoder();
var s = new MemoryStream(); e.Quality = 90;
e.Encode(newImg,s);
//var s = newImg.ToStream();
return s.GetBuffer();
So, I'm trying to simply add a text annotation to a pdf at the top left corner of a pdf document. Current code is like this:
public static byte[] StampPDFDocument(byte[] pdf, string stampString) {
using (var ms = new MemoryStream()) {
var reader = new iTextSharp.text.pdf.PdfReader(pdf);
var stamper = new iTextSharp.text.pdf.PdfStamper(reader, ms);
var box = reader.GetCropBox(1);
var left = box.Left;
var top = box.Top;
iTextSharp.text.Rectangle newRectangle = new iTextSharp.text.Rectangle(left + 20, top - 20, left + 250, top - 40);
var pcb = new iTextSharp.text.pdf.PdfContentByte(stamper.Writer);
pcb.SetColorFill(iTextSharp.text.BaseColor.RED);
var annot = iTextSharp.text.pdf.PdfAnnotation.CreateFreeText(stamper.Writer, newRectangle, stampString, pcb);
annot.Flags = iTextSharp.text.pdf.PdfAnnotation.FLAGS_PRINT;
annot.BorderStyle = new iTextSharp.text.pdf.PdfBorderDictionary(0, 0);
stamper.AddAnnotation(annot, 1);
stamper.Close();
return ms.ToArray();
}
}
Now, original code was just using box = reader.GetPageSize(1). Well, that I soon realized causes problems if the document has been rotated. Ok. No problem, there is a function called reader.GetPageSizeWithRotation. That worked like a charm. However, now I'm getting documents that have a different cropbox. So the annotation that I was adding was outside the cropbox area. So this current code only works for non rotated documents. The question is, how does one get the top left corener in a pdf document regardless of whether the document is rotated or contains a different cropbox than the document?
Here's what I ended up with.
public static byte[] StampPDFDocument(byte[] pdf, string stampString) {
using (var ms = new MemoryStream()) {
var reader = new iTextSharp.text.pdf.PdfReader(pdf);
var stamper = new iTextSharp.text.pdf.PdfStamper(reader, ms);
int rotation = reader.GetPageRotation(1);
var box = reader.GetPageSizeWithRotation(1);
var cropbox = reader.GetCropBox(1);
float left = cropbox.Left;
float top = cropbox.Top;
if (rotation == 90) {
left = cropbox.Bottom;
top = box.Height - cropbox.Left;
cropbox = new iTextSharp.text.Rectangle(left, top, left + cropbox.Height, top - cropbox.Width);
}
else if (rotation == 180) {
left = box.Width - cropbox.Left - cropbox.Width;
top = box.Height - cropbox.Bottom;
cropbox = new iTextSharp.text.Rectangle(left, top, left + cropbox.Width, top - cropbox.Height);
}
else if (rotation == 270) {
left = box.Width - cropbox.Top;
top = cropbox.Right;
cropbox = new iTextSharp.text.Rectangle(left, top, left + cropbox.Height, top - cropbox.Width);
}
iTextSharp.text.Rectangle newRectangle = new iTextSharp.text.Rectangle(left + 20, top - 20, left + 250, top - 40);
var pcb = new iTextSharp.text.pdf.PdfContentByte(stamper.Writer);
pcb.SetColorFill(iTextSharp.text.BaseColor.RED);
var annot = iTextSharp.text.pdf.PdfAnnotation.CreateFreeText(stamper.Writer, newRectangle, stampString, pcb);
annot.Flags = iTextSharp.text.pdf.PdfAnnotation.FLAGS_PRINT;
annot.Rotate = reader.GetPageRotation(1);
annot.BorderStyle = new iTextSharp.text.pdf.PdfBorderDictionary(0, 0);
stamper.AddAnnotation(annot, 1);
stamper.Close();
return ms.ToArray();
}
}
Here's the source for getPageSizeWithRotation:
public Rectangle getPageSizeWithRotation(int index) {
return getPageSizeWithRotation(pageRefs.getPageNRelease(index));
}
public Rectangle getPageSizeWithRotation(PdfDictionary page) {
Rectangle rect = getPageSize(page);
int rotation = getPageRotation(page);
while (rotation > 0) {
rect = rect.rotate();
rotation -= 90;
}
return rect;
}
So all you need to do to roll your own is to write a function that calls getCropBox() instead of getPageSize().
PS: getCropBox() will return the media box if there's no crop box, so you don't have to call getCropBox and getPageSize separately.