logo
Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Post a reply
From:
Message:

Maximum number of characters in each post is: 32767
Bold Italic Underline   Highlight Quote Choose Language for Syntax Highlighting Insert Image Insert an existing Attachment or upload a new File... Create Link   Unordered List Ordered List   Left Justify Center Justify Right Justify   Outdent Indent   More BBCode Tags
Font Color Font Size
Security Image:
Enter The Letters From The Security Image:
  Preview Post Cancel

Last 10 Posts (In reverse order)
Paul Rayman Posted: Wednesday, September 6, 2017 9:18:35 AM(UTC)
 
Thanks!

You can parse the decoded string of generated image stream and find the name of the image with which it was stored inside page's resource dictionary.
Image stream will be contains something like /FX08 Do where the FX08 it is a resource name.
Next you may store that name inside any pdf custom metadata or try to change it to more markable.
TravisNorwood Posted: Wednesday, September 6, 2017 8:32:08 AM(UTC)
 
Perfect. (BTW, the support for this product is a excellent).
We want to insert images (which we have to code to do) and then remove images (which you just gave us the code for).
We want to somehow mark the images we insert so we can remove only those images. I'm investigating how to do this. Any suggestions would be appreciated.
Paul Rayman Posted: Wednesday, September 6, 2017 8:19:10 AM(UTC)
 
Just process each item of that array as a content stream.
Something like following
Code:

PdfTypeStream  contentStream = As<PdfTypeStream>(page.Dictionary["Contents"]);
if(contentStream == null)
{
    var array  = As<PdfTypeArray>(page.Dictionary["Contents"]);
    foreach(var item in  array)
    {
        contentStream = As<PdfTypeStream>(item);
    }
}
TravisNorwood Posted: Wednesday, September 6, 2017 8:06:29 AM(UTC)
 
That worked great. How do you handle the case where the Contents is PdfTypeArray?
Paul Rayman Posted: Saturday, September 2, 2017 9:42:07 PM(UTC)
 
Currently we are working on an easy way to save the changes of the PdfPageObject through GenerateContent method.
But I can't give any forecast when exactly it will be released.

Currently you can try to use the following technique.

Please note, the code below assumes that the page's content is a PdfTypeStream.
But it also can be an array of such contents (PdfTypeArray), so you need to make some corrections in your production code.

However, that part of code is optional.

Note: PdfTypeStream.DecodedText is available since version 3.10.1.2704

Code:

static void Main(string[] args)
{
	using (var doc = PdfDocument.Load(@"d:\1\test.pdf"))
	{
		var page = doc.Pages[0];

		//All images are contains in the page resource dictionary, under XObject key.
		//So, get page's resource dictionary.
		var res = As<PdfTypeDictionary>(page.Dictionary["Resources"]);
		//Get XObject dictionary
		var xObjects = As<PdfTypeDictionary>(res["XObject"]);

		//Find first image in the xObject dictionary
		string nameForRemove = null;
		foreach(var xObject in xObjects)
		{
			var stream = As<PdfTypeStream>(xObject.Value);
			var streamType = As<PdfTypeName>(stream.Dictionary["Subtype"]).Value;
			if(streamType=="Image")
			{
				nameForRemove = xObject.Key;
				break;
			}
		}
		// And remove it.
		xObjects.Remove(nameForRemove);

		///////////// Optional part ////////////////////
		//Remove the reference to the image from the page's content stream.

		//Get content stream
		var contentStream = As<PdfTypeStream>(page.Dictionary["Contents"]);
		//Decode it to the ascii text
		string content = contentStream.DecodedText;
		//Remove reference from that string
		while (RemoveFromContentsStream(ref content, "/" + nameForRemove)) ;
		//Write changes back to the stream.
		//Please note the stream is not compressed now, so we remove all filters and filter params.
		contentStream.Init(System.Text.Encoding.ASCII.GetBytes(content));
		if(contentStream.Dictionary.ContainsKey("Filter"))
			contentStream.Dictionary.Remove("Filter");
		if (contentStream.Dictionary.ContainsKey("DecodeParms"))
			contentStream.Dictionary.Remove("DecodeParms");
		////////////////////////////////////////////////

		//Save changes to the document
		doc.Save(@"d:\1\test2.pdf", Patagames.Pdf.Enums.SaveFlags.NoIncremental);
	}
}

public static T As<T>(PdfTypeBase pdfType) where T : PdfTypeBase
{
	if (typeof(T) == pdfType.GetType())
		return (T)pdfType;
	else if (pdfType is PdfTypeIndirect)
	{
		PdfTypeBase obj = (pdfType as PdfTypeIndirect).Direct;
		return As<T>(obj);
	}
	return null;
}

private static bool RemoveFromContentsStream(ref string content, string nameForRemove)
{
	int startIdx = content.IndexOf(nameForRemove);
	if (startIdx < 0)
		return false;

	int endIdx = content.IndexOf("Do", startIdx);
	if (endIdx < 0)
		return false;
	endIdx += 2;

	content = content.Remove(startIdx, endIdx - startIdx);
	return true;
}
TravisNorwood Posted: Tuesday, August 29, 2017 1:16:44 PM(UTC)
 
I use the following code (that I got from this forum) to add an image to a PDF. That works well.
Now we have a situation where the user needs to remove the image from the PDF. How do I remove an image from a PDF?

Code:

        public static void AddImageToPage(PdfPage page, System.Drawing.Bitmap bmp, Point atPoint)
        {
            using(PdfImageObject signaturePDFImage = InsertImageToPage(page, bmp, atPoint))
            {
                InsertIntoDictionary(page, signaturePDFImage);
            }
        }

        private static PdfImageObject InsertImageToPage(PdfPage page, System.Drawing.Bitmap bmp, Point atPoint)
        {
            var bi = bmp.LockBits(
                new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height),
                System.Drawing.Imaging.ImageLockMode.ReadOnly,
                System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            //Create PdfBitmap object from .Net bitmap
            var bitmap = new PdfBitmap(
                bmp.Width,
                bmp.Height,
                BitmapFormats.FXDIB_Argb,
                bi.Scan0,
                bi.Stride);

            //Create pdf image object and then set PdfBitmap object into it.
            var image = PdfImageObject.Create(page.Document);
            image.SetBitmap(bitmap);

            //Scale image object to it's actual width and heihgt
            image.SetMatrix(bmp.Width, 0, 0, bmp.Height, (float)atPoint.X, (float)atPoint.Y);

            page.PageObjects.InsertObject(image);
            return image;
        }

        private static void InsertIntoDictionary(PdfPage page, PdfImageObject image)
        {
            //Get page dictionary, list of indirect objects and original page content
            var pageDict = page.Dictionary;
            var list = PdfIndirectList.FromPdfDocument(page.Document);

            //Convert contents to array. 
            PdfTypeArray array = ConvertContentsToArray(pageDict["Contents"], list, pageDict);

            //Get stream of image.
            IntPtr streamHandle = Pdfium.FPDFImageObj_GenerateStream(image.Handle, page.Handle);
            var stream = PdfTypeStream.Create(streamHandle);

            //Add image's stream into list of indirect objects and then add it to array.
            int num = list.Add(stream);
            array.AddIndirect(list, num);
        }

        public static PdfTypeArray ConvertContentsToArray(PdfTypeBase contents, PdfIndirectList list, PdfTypeDictionary pageDict)
        {
            //check the original content whether it's an array
            if(contents is PdfTypeArray)
                return contents as PdfTypeArray;  //if contents is a array just return it
            else if(contents is PdfTypeIndirect)
            {
                if((contents as PdfTypeIndirect).Direct is PdfTypeArray)
                    return (contents as PdfTypeIndirect).Direct as PdfTypeArray; //if contents is a reference to array then return that array
                else if((contents as PdfTypeIndirect).Direct is PdfTypeStream)
                {
                    //if contents is a reference to a stream then create a new array and insert stream as a first element of array
                    var array = PdfTypeArray.Create();
                    array.AddIndirect(list, (contents as PdfTypeIndirect).Direct);
                    //Add array into list of indirect objects
                    list.Add(array);
                    //And set it as a contents of the page
                    pageDict.SetIndirectAt("Contents", list, array);
                    return array;
                }
                else
                    throw new Exception("Unexpected content type");
            }
            else
                throw new Exception("Unexpected content type");
        }