There is a Windows program that generates PNG from HTML via WebBrowser.
This PNG must then be inserted into a PDF that is opened in Adobe Acrobat Reader DC as a stamp.
Below is a code that draws a PNG and sends it to the clipboard.
static void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var webBrowser = (WebBrowser)sender;
Bitmap bitmap = new Bitmap(webBrowser.Width, webBrowser.Height, PixelFormat.Format32bppArgb);
webBrowser.DrawToBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
bitmap.MakeTransparent(Color.White);
Clipboard.SetImage(bitmap);
}
The image is clipboard with a gray background, although when saved via bitmap.Save("img.png", ImageFormat.Png); the background is indeed transparent.
using (MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Png);
var data = new DataObject("PNG", stream);
Clipboard.Clear();
Clipboard.SetDataObject(data, true);
}
Tried saving the image to a MemoryStream and sending it to the clipboard as a DataObject. In this case, the clipboard is left empty.
Thanks to Nyerguds, I know that by default the Windows clipboard does not preserve transparency. But due to lack of experience, I can't figure out how to apply it myself.
How can I keep the transparency of the image for later pasting?
Related
I have that function to convert BitmapImage to Bitmap:
private Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
{
using(MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapImage));
enc.Save(outStream);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);
return new Bitmap(bitmap);
}
}
My images have black background (as .PNG they've transparent background).
How can I make them always have a transparent background?
If your display technology is WinForms, the answer is: You can not really. WinForms is a few decades to old to support proper transparency on the Display side.
Windows Forms is pretty good at feining Transparency, but not that good: https://www.codeproject.com/Articles/25048/How-to-Use-Transparent-Images-and-Labels-in-Window
Right now I have the following code, which works fine to display my dynamically created image in the web page, but it overwrites whatever controls there were. How do I display the image inside a specific control, instead?
Ideally, I would like it to be displayed inside a panel (Panel1) that I have defined on my page.
Response.Clear();
Response.ContentType = "image/png";
Bitmap bmp = new Bitmap(W, H, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(bmp);
//lots of drawing code
using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
ms.WriteTo(Response.OutputStream);
}
bmp.Dispose();
Response.End();
As I said, this works beautifully, except that it overwrites whatever controls I have on my page with the image, while I would like to constrain it to remain inside a panel.
is there a way to achieve this?
you need to an image control inside your panel, and the ImageUrl attribute of that, must be set to send its request to a new page or handler, and at that page, you need to write your bitmap, i have posted solution for this ...Here...
check that
assume you have a page named PageA.aspx containing a panel, you need an image element, inside the panel, like this:
<asp:Image ID="Image1"
runat="server"
CssClass="w120px h120px"
ImageUrl='newpage.aspx' />
notice to ImageUrl Attribute...
this image sends a request to newpage.aspx to get the picture...
in the page_load of newpage.aspx you need to write your MemoryStream which is containing your picture to the Response like this:
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.ContentType = "image/png";
Bitmap bmp = new Bitmap(W, H, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(bmp);
//lots of drawing code
using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
Response.BinaryWrite(ms.ToArray());
}
bmp.Dispose();
Response.End();
}
This one is slightly confusing...
I am using Adobe's PDF Viewer control to view PDFs but I want the user to be able to drag an image onto the PDF and then when they click save it adds the image to the PDF at that location.
Implementing the PDF viewer proved quite difficult but I decided in the end to use Adobe's control, take a picture and then allow the user to draw the image ontop of the picture of the PDF. When they click save I am going to use PDFSharp to put the image onto the PDF once I've worked out where it goes but the problem I have at the moment is that I can't get a picture of the PDF.
The following code is used to get the picture but the Panel that it is attached to just appears with a white background with a red 'X' and border...
using (Bitmap bitmap = new Bitmap(adobePDFViewer1.Width, adobePDFViewer1.Height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(new Point(adobePDFViewer1.Left, adobePDFViewer1.Top), Point.Empty, adobePDFViewer1.Size);
}
panelOverPdfViewer.BackgroundImage = bitmap;
}
I don't think this is the best way of doing it but I couldn't work out any others. Any help would be appreciated!
EDIT:
Following a very helpful answer below this is working code:
Here is the code I used:
Bitmap printscreen = new Bitmap(adobePDFViewer1.Width, adobePDFViewer1.Height);
Graphics graphics = Graphics.FromImage(printscreen as Image);
int left = this.Left + 396;
int top = this.Top + 30;
graphics.CopyFromScreen(left, top, 0, 0, printscreen.Size);
pictureBoxOverPDFView.Image = printscreen;
Look at this this Print-Screen
and try this for test work of CopyFromScreen
private void PrintScreen()
{
Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics graphics = Graphics.FromImage(printscreen as Image);
graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size);
printscreen.Save(#"C:\Temp\printscreen.jpg", ImageFormat.Jpeg);
}
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.
I wrote a little utility class that saves BitmapSource objects to image files. The image files can be either bmp, jpeg, or png. Here is the code:
public class BitmapProcessor
{
public void SaveAsBmp(BitmapSource bitmapSource, string path)
{
Save(bitmapSource, path, new BmpBitmapEncoder());
}
public void SaveAsJpg(BitmapSource bitmapSource, string path)
{
Save(bitmapSource, path, new JpegBitmapEncoder());
}
public void SaveAsPng(BitmapSource bitmapSource, string path)
{
Save(bitmapSource, path, new PngBitmapEncoder());
}
private void Save(BitmapSource bitmapSource, string path, BitmapEncoder encoder)
{
using (var stream = new FileStream(path, FileMode.Create))
{
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
encoder.Save(stream);
}
}
}
Each of the three Save methods work, but I get unexpected results with bmp and jpeg. Png is the only format that produces an exact reproduction of what I see if I show the BitmapSource on screen using a WPF Image control.
Here are the results:
BMP - too dark
too dark http://img822.imageshack.us/img822/7403/terrainbmp.png
JPEG - too saturated
too saturated http://img816.imageshack.us/img816/8127/terrainjpeg.jpg
PNG - correct
correct http://img810.imageshack.us/img810/6243/terrainpng.png
Why am I getting completely different results for different file types?
I should note that the BitmapSource in my example uses an alpha value of 0.1 (which is why it appears very desaturated), but it should be possible to show the resulting colors in any image format. I know if I take a screen capture using something like HyperSnap, it will look correct regardless of what file type I save to.
Here's a HyperSnap screen capture saved as a bmp:
correct http://img815.imageshack.us/img815/9966/terrainbmphypersnap.png
As you can see, this isn't a problem, so there's definitely something strange about WPF's image encoders.
Do I have a setting wrong? Am I missing something?
I don't personally think it too surprising to see what you're seeing. BMP and JPG don't support opacity and PNG does.
Take this code, which creates a partially transparent blue rectangle in an image.
WriteableBitmap bm = new WriteableBitmap( 100, 100, 96, 96, PixelFormats.Pbgra32, null );
bm.Lock();
Bitmap bmp = new Bitmap( bm.PixelWidth, bm.PixelHeight, bm.BackBufferStride, System.Drawing.Imaging.PixelFormat.Format32bppArgb, bm.BackBuffer );
using( Graphics g = Graphics.FromImage( bmp ) ) {
var color = System.Drawing.Color.FromArgb( 20, System.Drawing.Color.Blue);
g.FillRectangle(
new System.Drawing.SolidBrush( color ),
new RectangleF( 0, 0, bmp.Width, bmp.Height ) );
}
bmp.Save( #".\000_foo.bmp", System.Drawing.Imaging.ImageFormat.Bmp );
bmp.Save( #".\000_foo.jpg", System.Drawing.Imaging.ImageFormat.Jpeg );
bmp.Save( #".\000_foo.png", System.Drawing.Imaging.ImageFormat.Png );
bmp.Dispose();
bm.AddDirtyRect( new Int32Rect( 0, 0, bm.PixelWidth, bm.PixelHeight ) );
bm.Unlock();
new BitmapProcessor().SaveAsBmp( bm, #".\foo.bmp" );
new BitmapProcessor().SaveAsJpg( bm, #".\foo.jpg" );
new BitmapProcessor().SaveAsPng( bm, #".\foo.png" );
The PNG formats always work, whether it's System.Drawing or the WPF encoders. The JPG and BMP encoders do not work. They show a solid blue rectangle.
The key here is I failed to specify a background color in my image. Without a background color, the image won't render correctly in formats that don't support an alpha channel (BMP/JPG). With one extra line of code:
g.Clear( System.Drawing.Color.White );
g.FillRectangle(
new System.Drawing.SolidBrush( color ),
new RectangleF( 0, 0, bmp.Width, bmp.Height ) );
My image has a background color, so the encoders that do not support an alpha channel can determine what the output color should be per pixel. Now all my images look correct.
In your case, you should either RenderTargetBitmap a control with a background color specified, or paint a background color when you're rendering your image.
And FYI, the reason your 3rd party print screen works is that ultimately the transparent colors have a background color at that point (being on a window which has a background color). But inside WPF, you're dealing with elements that don't have one set; using RTB on an element does not inherit its various parent element's properties like background color.