Image Opacity in PdfSharp.NET - pdf

I'm using PDFSharp.NET library to watermark a list of PDFs file. Everything works fine, the website has a lot of samples.
http://www.pdfsharp.net/wiki/Graphics-sample.ashx
The last thing I need is to add the Company Logo, which is big, in the middle of the PDF Page.
I can use a PNG, so that areas which are set as transparent do not "cover" the PDF page".
The pdf is not generated using PDFSharp, but is an "Image" PDF.
For this reason, what I need, is, in addition to the transparency, which works, be able some how to set the Image Opacity!
The code to place the image is this one:
XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Append);
XImage image = XImage.FromFile(mypath);
gfx.DrawImage(image, pwidth/2-image.PixelWidth/2, pheight/2 image.PixelHeight/2);
gfx.Dispose();
Anyone has already faced with that?

I don't know how to alter the opacity of an image while drawing it using PDFsharp (and I'm afraid this can't be done).
So instead I would just open the logo (PNG) with an image processor and set the opacity there.

I was looking in to this aswell now for making a watermark (companyLogo) to place over pdf sheets. The code below lets you change the opacity.
PDFSharp can not change the image opacity. What you can do is change the image you feed to PDF sharp. This has already been answered so I am just sharing my code of doing so.
private void DrawGraphics()
{
XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Append);
Image myTransparenImage = SetImageOpacity(Image.FromFile("MyPath"), (float)opacityYouwant); // opacityYouWant has to be a value between 0.0 and 1.0
XImage image = XImage.FromBitmapSource(Convert(myTransparenImage));
gfx.DrawImage(image, pwidth / 2 - image.PixelWidth / 2, pheight / 2 image.PixelHeight / 2);
gfx.Dispose();
}
public Image SetImageOpacity(Image image, float opacity)
{
try
{
//create a Bitmap the size of the image provided
Bitmap bmp = new Bitmap(image.Width, image.Height);
//create a graphics object from the image
using (Graphics gfx = Graphics.FromImage(bmp))
{
//create a color matrix object
ColorMatrix matrix = new ColorMatrix();
//set the opacity
matrix.Matrix33 = opacity;
//create image attributes
ImageAttributes attributes = new ImageAttributes();
//set the color(opacity) of the image
attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
//now draw the image
gfx.DrawImage(image, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
}
return bmp;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}
public BitmapImage Convert(Image img)
{
using (var memory = new MemoryStream())
{
img.Save(memory, ImageFormat.Png);
memory.Position = 0;
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
return bitmapImage;
}
}

Related

Winforms Itext Ghost Script Rectangular coordinates selection

Using C# and Winforms, I want to display a PDF, select a rectangular region, and then extract that area of text from a number of PDFs. For displaying the PDF, I have a number of options...
Use an "Adobe PDF Reader" control to display the PDF - However, I cant use mouseover events and according to https://forums.adobe.com/thread/1640606 its just not possible to select a region.
Use a "WebBrowser" control to display the PDF, but it appears I have the same issue with mouseover events and cannot select a region.
Convert the PDF to an image (using ghostscript in my case) and displaying it in a picturebox. I'm finding the most success here, as I can now generate and record the coordinates of a rectangular region. When I take these coordinates and apply them to the PDF using Itext, I don't think my rectangular region translates correctly.
My question is, How do I render the GhostScripted image in a picture box maintaining the same ratios so that my coordinates will line up with the PDF?
Thank you in advance for the down votes!!
Here is the current state of my code... Everything works with the exception that my units are off in space somewhere. The action DOES return text, but it's never the text I selected. Im sure its a combination of the coordinate system / units and I will continue to try to understand this.
---- update
With a PDF at 0 deg rotation (portrait), I think the following holds true, or is at least working for me right now... User Units having not been changed, the coordinates taken from selecting in the picturebox need adjusting. The Y coordinates need to be subtracted from the overall height while the X coordinate remains the same.
iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(first.X, 3024-first.Y, last.X, 3024-last.Y);
This is picking text up exactly as expected on 0 deg rotated PDFs. On 90 deg rotated PDFs, the X and Y coordinates just need to be swapped.I am updating the code snippet below to show my working example.
using System;
using System.Drawing;
using System.Windows.Forms;
using Ghostscript.NET.Rasterizer;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
namespace formPdf
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string fileName; // The filename of the pdf
float width; // The width of the PDF in pixels
float hight; // the Height of the PDF in pixels
float rotation; // the Rotation of the PDF 0 or 90
float llx = 0; // The Lower Left X value for applying to the PDF
float lly = 0; // the Lower Left Y value for applying to the PDF
float urx = 0; // the Upper Right X value for applying to the PDF
float ury = 0; // the Upper Right Y value for applying to the PDF
// OnCLick event to open the file browser and select a file... The Width, Height and rotation values are set and the program
// is directed to render the First page of the pdf by calling the setPicture function
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
fileName = openFileDialog1.FileName;
PdfReader reader = new PdfReader(fileName);
iTextSharp.text.Rectangle dim = reader.GetPageSizeWithRotation(1);
width = dim.Width;
hight = dim.Height;
rotation = dim.Rotation;
setPicture(openFileDialog1.FileName);
} catch
{
// do nothing for now
}
}
}
// Using Ghostscript, the image is rendered to a picturebox. DPIs are set assuming the PDF default value is used
private void setPicture(string fileName)
{
GhostscriptRasterizer rasterizer = new GhostscriptRasterizer();
rasterizer.Open(fileName);
Image img = rasterizer.GetPage(72, 72, 1);
pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
pictureBox1.Image = img;
}
// Declare point variables for the user defined rectangle indicating the locatoin of the PDF to be searched...
Point first = new Point();
Point last = new Point();
// The first point is collected on the MouseDown event
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
first = e.Location;
}
// The second point is collected on the mouse down event. Points to be applied to the PDF are adjusted based on the rotation of the PDF.
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
last = e.Location;
if (rotation == 0)
{
llx = first.X;
lly = hight - first.Y;
urx = last.X;
ury = hight - last.Y;
} else if(rotation == 90) {
llx = first.Y;
lly = first.X;
urx = last.Y;
ury = last.X;
}
gettext();
}
// the original PDF is opened with Itext and the text is extracted from t he defined location...
private void gettext()
{
PdfReader reader = new PdfReader(fileName);
iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(llx, lly, urx, ury);
RenderFilter[] renderfilter = new RenderFilter[1];
renderfilter[0] = new RegionTextRenderFilter(rect);
ITextExtractionStrategy textExtractionStrategy = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), renderfilter);
string text = PdfTextExtractor.GetTextFromPage(reader, 1, textExtractionStrategy);
iTextSharp.text.Rectangle mediabox = reader.GetPageSizeWithRotation(1);
MessageBox.Show("", text+" "+mediabox+" "+first+" "+last);
}
// Image Controls....
}
}

Extracting portion of a PDF

I'm trying to extract a portion of a pdf (the coordinates of the section will always remain constant) using PDF Sharp. Then I will resize the portion to 4" x 6" for printing onto a sticky back label. How would I extract the portion of the PDF? This is in a console application, C#.
There is no easy way to extract parts from a PDF file.
A possible workaround: create a new page in label size, then draw the existing page onto the new page so that the required rectangle is visible on the new page.
If needed, draw white rectangles to hide information that is not part of the section you need, but that is visible on the new page.
So here was how I managed to do this, not a perfect solution (you do loose some quality). This uses Spire.PDF, not PDF Sharp as I originally planned. I got fairly lucky in that the output size was nearly 4" X 6". So I just used shrink to fit on print options.
static void Main(string[] args)
{
ConvertPDFToBmp("FilePathOfPDF");
CropAtRect("FilePathOfConvertedImage");
ConvertToPDF("FilePathOfCroppedImage");
}
public static void ConvertPDFToBmp(string filePath)
{
PdfDocument document = new PdfDocument();
document.LoadFromFile(filePath);
Image emf = document.SaveAsImage(0, Spire.Pdf.Graphics.PdfImageType.Bitmap, 400, 400);
emf.Save("FilePath", ImageFormat.Jpeg);
}
public static void CropAtRect(string filePath)
{
Bitmap b = (Bitmap)Bitmap.FromFile(filePath);
Rectangle r = new Rectangle(new /*Where the rectangle starts*/Point(/*Width*/, /*Height*/), (new /*How big is the rectangle*/Size(/*Width*/, /*Height*/)));
Bitmap nb = new Bitmap(r.Width, r.Height);
nb.SetResolution(400, 400); //Scale to keep quality
Graphics g = Graphics.FromImage(nb);
g.DrawImage(b, -r.X, -r.Y);
nb.Save("FilePath", ImageFormat.Jpeg);
}
public static void ConvertToPDF(string filePath)
{
Bitmap b = (Bitmap)Bitmap.FromFile(filePath);
PdfDocument doc = new PdfDocument();
PdfImage pdfImage = PdfImage.FromImage(b);
PdfUnitConvertor uinit = new PdfUnitConvertor();
PdfPageBase page = doc.Pages.Add(new /*Size of PDF Page*/SizeF(585, 365), new PdfMargins(0f));
page.Canvas.DrawImage(pdfImage, new /*Where the image starts*/PointF(0, 0));
doc.SaveToFile("FilePath");
}

Replacing image in PDF using PDFBox

I have a PDF document which has a blank image (with grey background). I need to replace this blank image with another image which I have as a byte array.
I replace the image using PDFBox as below:
// Convert byte array to BufferedImage
BufferedImage imgFromBytes = ImageIO.read(new ByteArrayInputStream(imgBytes));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(imgFromBytes, "jpg", baos);
// Replace empty image in pdf with the image generated from byte array
PDXObjectImage newImage = new PDJpeg(doc, new ByteArrayInputStream(baos.toByteArray()));
blankImg.getCOSStream().replaceWithStream(newImage.getCOSStream());
This replaces the blank image in the pdf. But the problem is, the image generated from the byte array is not the same size as compared to the blank image. I guess it does some auto-scaling, because of which there is some blank space at the bottom which is grey in color (due to the background of the blank image).
So I tried re-scaling the image as below:
// Convert byte array to BufferedImage
BufferedImage imgFromBytes = ImageIO.read(new ByteArrayInputStream(imgBytes));
//Re-size the image
BufferedImage resizedImage = new BufferedImage(blankImg.getWidth(), blankImg.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = resizedImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(imgFromBytes, 0, 0, blankImg.getWidth(), blankImg.getHeight(), Color.WHITE, null);
g2d.dispose();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(resizedImage, "jpg", baos);
// Replace empty image in pdf with the image generated from byte array
PDXObjectImage newImage = new PDJpeg(doc, new ByteArrayInputStream(baos.toByteArray()));
blankImg.getCOSStream().replaceWithStream(newImage.getCOSStream());
But this doesn't help me either. I still see the grey background at the bottom. Moreover, this reduces the quality of the image and also chops a bit from the top and bottom of the image generated from the bytes.
What would be the best way to replace the blank image with the image I get from the byte array, so that it fits the size of the blank image perfectly?
Thanks.

Add links to PDF programmatically

I have about 180 PDF files that are generated from a geodatabase. I would like to programmatically add links as hot spots (no text) at the top, bottom, left and right as needed to navigate to the adjoining page files. I would also like to add links over a 3x3 grid in the lower left corner of the page for additional navigation. The grid is already in the existing PDF just no links. Total there will be a possible 14 links added to each page
I am open to suggestions as to how to go about this. I am using Acrobat Pro XI, and I am familiar with various programing languages python, vb.net, C#... Just no experience working directly with PDF files.
This is very late answer. Actually I was searching for free alternative to above paid libraries. I found the following links which can be helpful to others.
Apache PDFBox is a vast java library to create pdf programmatically.
TomRoush/PdfBox-Android is it's android implementation. You can find the sample project with this implementation.
I have added the code for creating clickable links in pdf by using above android library and sample project.
public void createPdf(View v) {
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
// Create a new font object selecting one of the PDF base fonts
PDFont font = PDType1Font.HELVETICA;
// Or a custom font
//try {
// PDType0Font font = PDType0Font.load(document, assetManager.open("MyFontFile.TTF"));
//} catch(IOException e) {
// e.printStackTrace();
//}
PDPageContentStream contentStream;
try {
// Define a content stream for adding to the PDF
contentStream = new PDPageContentStream(document, page);
String preText = "Icons made by ";
String linkText = "My_Site";
float upperRightX = page.getMediaBox().getUpperRightX();
float upperRightY = page.getMediaBox().getUpperRightY();
// Write linkText in blue text
contentStream.beginText();
contentStream.setNonStrokingColor(15, 38, 192);
contentStream.setFont(font, 18);
contentStream.moveTextPositionByAmount( 0, upperRightY-20);
contentStream.drawString(preText + linkText);
contentStream.endText();
// create a link annotation
PDAnnotationLink txtLink = new PDAnnotationLink();
// set up the markup area
float offset = (font.getStringWidth(preText) / 1000) * 18;
float textWidth = (font.getStringWidth(linkText) / 1000) * 18;
PDRectangle position = new PDRectangle();
position.setLowerLeftX(offset);
position.setLowerLeftY(upperRightY - 24f);
position.setUpperRightX(offset + textWidth);
position.setUpperRightY(upperRightY -4);
txtLink.setRectangle(position);
// add an action
PDActionURI action = new PDActionURI();
action.setURI("https://www.**********.com/");
txtLink.setAction(action);
// and that's all ;-)
page.getAnnotations().add(txtLink);
// load 'Social media' icons from 'vector' resources.
float padding = 5, startX = 5, startY = upperRightY-100, width = 25, height=25;
loadVectorIconWithLink(document, page, contentStream, R.drawable.ic_facebook,
"https://www.facebook.com/My_Name/", startX, startY, width, height);
startX += (width + padding);
loadVectorIconWithLink(document, page, contentStream, R.drawable.ic_instagram,
"https://www.instagram.com/My_Name", startX, startY, width, height);
// Make sure that the content stream is closed:
contentStream.close();
// Save the final pdf document to a file
String path = root.getAbsolutePath() + "/Download/Created.pdf";
document.save(path);
document.close();
tv.setText("Successfully wrote PDF to " + path);
} catch (IOException e) {
e.printStackTrace();
}
}
private void loadVectorIconWithLink( PDDocument theDocument,
PDPage thePage,
PDPageContentStream theContentStream,
#DrawableRes int theDrawableId,
String theUriString,
float x, float y, float width, float height
) throws IOException
{
Bitmap alphaImage = getBitmapFromDrawable(this, theDrawableId);
PDImageXObject alphaXimage = LosslessFactory.createFromImage(theDocument, alphaImage);
theContentStream.drawImage(alphaXimage, x, y, width, height );
// create a link annotation
PDAnnotationLink iconLink = new PDAnnotationLink();
PDRectangle position = new PDRectangle( x, y, width, height );
iconLink.setRectangle(position);
// add an action
PDActionURI action1 = new PDActionURI();
action1.setURI(theUriString);
iconLink.setAction(action1);
// and that's all ;-)
thePage.getAnnotations().add(iconLink);
}
public static Bitmap getBitmapFromDrawable(Context context, #DrawableRes int drawableId) {
Drawable drawable = AppCompatResources.getDrawable(context, drawableId);
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else if (drawable instanceof VectorDrawableCompat || drawable instanceof VectorDrawable) {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} else {
throw new IllegalArgumentException("unsupported drawable type");
}
}
There are at least three types of links you might want to add: links to pages within the same document, links to pages in other PDF document, links to URLs on the web.
Docotic.Pdf library can add links of any of these types (please note that I am on of the developers of this library). Here are two relevant examples:
Create link to page
Create hyperlink
There are no examples for how to create links to pages in an other PDF document published online, but you can always contact support if you need such an example.
After continuing to search and not finding any other promising open source solutions I went with Debenu Quick PDF Library. The specific functions I used are are noted below:
AddLinkToFile
AddLinkToPage
Other annotations and hotspot links
The time that the two library functions are going to save me weekly is worth the cost alone. I am sure I will find other use for the other 900+ PDF functions

Image Overflows in Asp.net MVC4

Forgive me if this question is too silly or asked before. I need to display an Image in my web app and the image is stored in db as byte and I produced the image from the byte but the problem is when I'm displaying it in my web app it over flows means the image frame size is 100x100 but the image comes in its actual resolution. How to solve this my current code is given below
controller
[HttpPost]
public ActionResult ByteToImage()
{
ImageDL getImage = new ImageDL();
byte[] image = getImage.CreateImage();
return File(image,"Image/jpeg");
}
Razor
<img alt="" src="#Url.Action("ByteToImage", "User")" height="100" width="100" />
Once you have the Image in a byte[] format you can re-draw the image to any height width you desire:
public FileContentResult GetImage(byte[] imgData, int WIDTH, int HEIGHT)
{
MemoryStream ms = new MemoryStream(imgData);
using (var srcImage = Image.FromStream(ms))
using (var newImage = new Bitmap(WIDTH, HEIGHT))
using (var graphics = Graphics.FromImage(newImage))
using (var stream = new MemoryStream())
{
graphics.DrawImage(srcImage, new Rectangle(0, 0, WIDTH, HEIGHT));
newImage.Save(stream, ImageFormat.Jpeg);//Set your desired image format
return File(stream.ToArray(), "image/jpeg");
}
}
Try the below mentioned image tag with height & width mentioned with style rather than declaring independently, that will provide content clipping in all browsers.
<img style="width:220px;height:115px;" alt="" src="#Url.Action("ByteToImage", "User")"/>