I am writing a new WPF application that creates some visual elements and then trying to print them on a Poloroid printer. I am successfully printing using the System.Printing classes in WPF as follows:
Dim Pd As PrintDialog = New PrintDialog()
Dim Ps = New LocalPrintServer()
Dim PrintQueue = New PrintQueue(Ps, "Poloroid Printer")
Pd.PrintQueue = PrintQueue
Pd.PrintVisual(Me.Grid1, "Print Job 1") 'this prints out perfectly
The problem is that the poloroid printer has an SDK that you can use to write to the Magstrip on the back of the card. I have a working example using the PrintPageEventArgs in System.Drawing.Printing but I cannot find any close matches for the WPF world. Here is that code:
Private Sub PrintPage(ByVal sender as Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
'...
' Obtain the device context for this printer
deviceContext = e.Graphics.GetHdc().ToInt32()
'... device context is used in SDK to write to magstrip
e.Graphics.ReleaseHdc(New IntPtr(deviceContext))
End Sub
So, my question is:
How can I print my existing markup (XAML) using System.Drawing.Printing
OR
Are there events in the System.Printing to talk to the SDK and getting the Int32 deviceContext?
and I tried to RenderTargetBitmap class to render the visual in WPF to bitmap and convert the bitmap to System.Drawing.Bitmap
RenderTargetBitmap bitmapSource;
...
bitmapSource.Render(visual);
...
using(MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapSource));
enc.Save(outStream);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);
...
}
But printing was not clear and perfect.
Try this
Rect bounds = VisualTreeHelper.GetDescendantBounds(FrontCanvas);
double dpiX =e.Graphics.DpiX , dpiY=e.Graphics.DpiY ;
RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
(int)(bounds.Height * dpiY / 96.0),
dpiX,
dpiY,
PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(FrontCanvas);
ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
}
rtb.Render(dv);
//System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(rtb);
//e.Graphics.DrawImage(rtb, 0, 0);
using (MemoryStream outStream = new MemoryStream())
{
// Use png encoder for data
BitmapEncoder encoder = new PngBitmapEncoder();
// push the rendered bitmap to it
encoder.Frames.Add(BitmapFrame.Create(rtb));
encoder.Save(outStream);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);
e.Graphics.DrawImage(bitmap, 0, 0);
}
I recently answered a similar question that can be found here: https://stackoverflow.com/a/43373398/3393832. That question and answer relate more to magnetic encoding (on ID cards) than image printing, but I will try to give some insight about that here, as well.
For the card images, I actually set up two Grids within my XAML: an outer grid that houses everything (buttons, labels, combo-boxes, the inner grid) and an inner grid that is essentially the image I want to apply, in full, on the card itself. In code, I take a "snapshot" of the inner grid after all elements have been added/updated and simply send that image into the Print Job.
To continue with my previous post (the link above), I add the image print AFTER the magnetic encoding step for the first side of the card (PageCount == 0).
Below is some code that I use to get the Bitmap "snapshot" of the Grid/Full Image without any loss of clarity/resolution or any pixelation:
RenderTargetBitmap rtb = new RenderTargetBitmap(gridWidth, gridHeight, 210, 210, PixelFormats.Pbgra32);
rtb.Render(YourGrid);
// If you need to Crop Anything Out
CroppedBitmap crop = new CroppedBitmap();
crop = new CroppedBitmap(rtb, new Int32Rect(0, 0, gridWidth, gridHeight));
Bitmap bmpToPrint = BitmapSourceToBitmap(crop);
// Helper Method
public Bitmap BitmapSourceToBitmap(BitmapSource bs)
{
Bitmap bitmap;
using (MemoryStream ms = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bs));
enc.Save(ms);
bitmap = new Bitmap(ms);
}
return bitmap;
}
For the Magnetic Encoding, I use e.Graphics.DrawString and for the Image (you guessed it) e.Graphics.DrawImage. Simply call DrawString prior to DrawImage and your Printer Driver should pick up the encode prior to the image within the PrintPage method (again, please refer to the link above for more details into the Print method I am using. This method is also not tied to a printer make or model and is not reliant on any SDK).
Though generic and in need of your particular implementation details, I hope this post helps guide you to a solution that fits your particular needs. Please don't hesitate to ask if you have any follow-up questions or need more detail into the particular elements of the print job itself.
Related
I'm trying to store a XAML in a bitmap file and print it to a pdf file.
My view shows the controls/text like this:
The pdf shows the created bitmap like this:
Here's the code on how I convert my XAML to a bitmap:
MyWindow view = new MyWindow();
view.Title = "SOME TEXT";
//add the table
RenderTargetBitmap bmp = new RenderTargetBitmap((int)view.ActualWidth, (int)view.ActualHeight, 96, 96, PixelFormats.Pbgra32);
bmp.Render(view);
PngBitmapEncoder pngImage = new PngBitmapEncoder();
pngImage.Frames.Add(BitmapFrame.Create(bmp));
//System.Windows.Clipboard.SetImage(pngImage.Frames[0]); //Clipboard still shows the pngImage in high quality!
MemoryStream stream = new MemoryStream();
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(pngImage.Frames[0]);
encoder.Save(stream);
Bitmap myCreatedBitmap = new Bitmap(stream);
I'm using System.Drawing.Printing to print the pdf file. I'm assigning the bitmap in the EventHandler PrintPageEventHandler like this:
e.Graphics.DrawImage(this.bitmap, new Rectangle(e.MarginBounds.X, e.MarginBounds.Y, e.MarginBounds.Width, e.MarginBounds.Height), new Rectangle(posX, posY, e.MarginBounds.Width, e.MarginBounds.Height), GraphicsUnit.Pixel);
What's the reason for the blurry image or how can I convert my XAML to a bitmap with High Resolution and store it in a pdf?
To convert XAML to PDF with high quality, try converting XAML to XPS and XPS to PDF, using Syncfusion .NET PDF library.
Refer the below KB for converting XAML to PDF
https://www.syncfusion.com/kb/8083/how-to-convert-xaml-to-pdf-in-wpf-platform
I am trying to draw some string to bitmap at certain position and copy a barcode bitmap to the new bitmap.I have not done with graphics before so i don't know where to start.
Can anyone guide me on this?my output of the bitmap is a receipt like.
Here is a solution. Please make a grid or canvas and put the barcode image and use a label with desired text and put the label on desired location relative to barcode grid. So, trick is you can immediately take screenshot of this grid using following code.Then, you are done.
public void ConvertToBitmapSource(UIElement element)
{
var target = new RenderTargetBitmap(
(int)element.RenderSize.Width, (int)element.RenderSize.Height,
96, 96, PixelFormats.Pbgra32);
target.Render(element);
var encoder = new PngBitmapEncoder();
var outputFrame = BitmapFrame.Create(target);
encoder.Frames.Add(outputFrame);
using (var file = File.OpenWrite("TestImage.png"))
{
encoder.Save(file);
}
}
I'm just using a .NET port of Pdfium named PdfiumViewer. It just works very well once rendered in the WinForm controls but when I try to render it on a Bitmap to show in the WPF windows (or even saving to disk) the rendered text has problem.
var pdfDoc = PdfiumViewer.PdfDocument.Load(FileName);
int width = (int)(this.ActualWidth - 30) / 2;
int height = (int)this.ActualHeight - 30;
var bitmap = new System.Drawing.Bitmap(width, height);
var g = System.Drawing.Graphics.FromImage(bitmap);
g.FillRegion(System.Drawing.Brushes.White, new System.Drawing.Region(
new System.Drawing.RectangleF(0, 0, width, height)));
pdfDoc.Render(1, g, g.DpiX, g.DpiY, new System.Drawing.Rectangle(0, 0, width, height), false);
// Neither of these are readable
image.Source = BitmapHelper.ToBitmapSource(bitmap);
bitmap.Save("test.bmp");
// Directly rendering to a System.Windows.Forms.Panel control works well
var controlGraphics = panel.CreateGraphics();
pdfDoc.Render(1, controlGraphics, controlGraphics.DpiX, controlGraphics.DpiY,
new System.Drawing.Rectangle(0, 0, width, height), false);
It's notable to say that I tested almost every possible options on the Graphics object including TextContrast,TextRenderingHint,SmoothingMode,PixelOffsetMode, ...
Which configurations I'm missing on the Bitmap object that cause this?
Edit 2
After lots of searching and as #BoeseB mentioned I just found that Pdfium render device handle and bitmaps differently by providing a second render method FPDF_RenderPageBitmap and currently I'm struggling to convert its native BGRA bitmap format to managed Bitmap.
Edit
Different modes of TextRenderingHint
Also tried Application.SetCompatibleTextRenderingDefault(false) with no noticeable difference.
Isn't it your issue ?
Look recent fix for it.
As you can see, repository owner commited newer version of PdfiumViewer. Now you can write this way:
var pdfDoc = PdfDocument.Load(#"mydoc.pdf");
var pageImage = pdfDoc.Render(pageNum, width, height, dpiX, dpiY, isForPrinting);
pageImage.Save("test.png", ImageFormat.Png);
// to display it on WPF canvas
BitmapSource source = ImageToBitmapSource(pageImage);
canvas.DrawImage(source, rect); // canvas is instance of DrawingContext
Here is a popular approach to convert Image to ImageSource
BitmapSource ImageToBitmapSource(System.Drawing.Image image)
{
using(MemoryStream memory = new MemoryStream())
{
image.Save(memory, ImageFormat.Bmp);
memory.Position = 0;
var source = new BitmapImage();
source.BeginInit();
source.StreamSource = memory;
source.CacheOption = BitmapCacheOption.OnLoad;
source.EndInit();
return source;
}
}
I have two images,now i want to overlay the images,such that the other image appears on center or left corner of the other image,and then when finally both the images are overlayed i can store it in another new image object,and i want to all this in code behind only not xaml,how to do this?
if (((Grid)sender).Children.Count > 0)
{
gridBackground = (ImageBrush)(((Grid)sender).Background);
gridBackImage = new System.Windows.Controls.Image();
gridBackImage.Source = gridBackground.ImageSource;
}
System.Windows.Controls.Image imgRejectIcon;
if (((Grid)sender).Children.Count > 0)
{
imgRejectIcon = (System.Windows.Controls.Image)(((Grid)sender).Children[0]);
}
Now i want to merge gridBackImage and imgRejection and store it in new image object
You can arrange your two Images in any way that you want and I'll leave that code for you to do (it'd much simpler to do in XAML). In WPF, all UI controls extend the Visual class. This is very useful for making BitmapImages from UI controls, when used with the RenderTargetBitmap.Render method.
First, arrange your two Image controls into a Grid, or other container control, and then you can pass the container control to the RenderTargetBitmap.Render method and create an Image something like this:
RenderTargetBitmap renderTargetBitmap =
new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
renderTargetBitmap.Render(yourContainerControl);
PngBitmapEncoder pngImage = new PngBitmapEncoder();
pngImage.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
using (Stream fileStream = File.Create(filePath))
{
pngImage.Save(fileStream);
}
I want to do something like that: open an image in the <image> tag and add some other tags on it, for example green rectangle. After that I want to save it like image with rectangle on some part of it. In general user should drag&drop rectangle and could resize it. But the question is: How can I save it? I suppose that I should save parent tag for all of them, for example <grid> or <canvas> but is it possible?
Transform transform = myCanvas.LayoutTransform;
myCanvas.LayoutTransform = null; Size size = new Size(myCanvas.Width,myCanvas.Height); myCanvas.Measure(size);
myCanvas.Arrange(new Rect(size));
RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96d, 96d,PixelFormats.Pbgra32);
renderBitmap.Render(myCanvas);
using (FileStream outStream = new FileStream(path.LocalPath, FileMode.Create))
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
encoder.Save(outStream);
}
myCanvas.LayoutTransform = transform;
For a detailed explanation (and the source of the above code), see this blog post:
http://denisvuyka.wordpress.com/2007/12/03/wpf-diagramming-saving-you-canvas-to-image-xps-document-or-raw-xaml/
You can save as PNG, JPG, etc depending on the encoder that you use