/// <summary>
 /// Retrieves the specifed dictionary object as an object encoded with DCTDecode filter (JPEG).
 /// </summary>
 /// <param name="dictionary">The dictionary to extract the object from.</param>
 /// <returns>The image retrieve from the dictionary. If not found or an invalid image, then null is returned.</returns>
 private static Image ImageFromDCTDecode(PdfDictionary dictionary)
 {
   // DCTDecode a lossy filter based on the JPEG standard
   // We can just load directly from the stream.
   MemoryStream stream = new MemoryStream(dictionary.Stream.Value);
   return (Bitmap.FromStream(stream));
 }
Exemplo n.º 2
0
        static bool ExportImage(PdfDictionary image, ref int count)
        {
            bool ret = false;
            try
            {
                string filter = image.Elements.GetName("/Filter");
            
                switch (filter)
                {
                    case "/DCTDecode":
                        ret = ExportJpegImage(image, ref count);
                        break;
                    /* case "/FlateDecode":
                            ExportAsPngImage(image, ref count);
                            break;*/
                    default:
                        ret = true;
                        break;
                }
            }
            catch (Exception)//in case its an object array so we need first to decompress it
            {
                byte[] stream = image.Stream.Value;

                PdfSharp.Pdf.Filters.FlateDecode aug = new PdfSharp.Pdf.Filters.FlateDecode();
                stream = aug.Decode(stream);
                ret = ExportJpegImage(stream, ref count);
            }

            return ret;
        }
Exemplo n.º 3
0
 static void ExportJpegImage(PdfDictionary image, ref int count)
 {
     byte[] stream = image.Stream.Value;
     using (FileStream fs = new FileStream(String.Format("Image{0}.jpg", count++), FileMode.Create, FileAccess.Write))
     {
         fs.Write(stream, 0, stream.Length);
     }
 }
Exemplo n.º 4
0
 internal PdfPage(PdfDictionary dict)
     : base(dict)
 {
     // Set Orientation depending on /Rotate.
     int rotate = Elements.GetInteger(InheritablePageKeys.Rotate);
     if (Math.Abs((rotate / 90)) % 2 == 1)
         _orientation = PageOrientation.Landscape;
 }
Exemplo n.º 5
0
 /// <summary>
 /// </summary>
 public PdfContentWriter(DocumentRenderingContext context, PdfDictionary contentDictionary)
 {
   if (!(contentDictionary is IContentStream))
     throw new ArgumentException("contentDictionary must implement IContentStream.");
   this.context = context;
   this.contentDictionary = contentDictionary;
   this.contentStreamDictionary = (IContentStream)contentDictionary;
   this.renderMode = RenderMode.Default;
   //this.colorMode = page.document.Options.ColorMode;
   //this.options = options;
   this.content = new StringBuilder();
   this.graphicsState = new PdfGraphicsState(this);
 }
        static void ExportImage(PdfDictionary image, ref int count)
        {
            string filter = image.Elements.GetName("/Filter");
            switch (filter)
            {
                case "/DCTDecode":
                    ExportJpegImage(image, ref count);
                    break;

                case "/FlateDecode":
                    ExportAsPngImage(image, ref count);
                    break;
            }

        }
        static void ExportJpegImage(PdfDictionary image, ref int count)
        {

            // Fortunately JPEG has native support in PDF and exporting an image is just writing the stream to a file.

            byte[] stream = image.Stream.Value;

            FileStream fs = new FileStream(String.Format("F:\\Image{0}.jpeg", count++), FileMode.Create, FileAccess.Write);
            
            BinaryWriter bw = new BinaryWriter(fs);

            bw.Write(stream);

            bw.Close();

        }
Exemplo n.º 8
0
    public PdfCIDFont(PdfDocument document, PdfFontDescriptor fontDescriptor, byte[] fontData)
      : base(document)
    {
      Elements.SetName(Keys.Type, "/Font");
      Elements.SetName(Keys.Subtype, "/CIDFontType2");
      PdfDictionary cid = new PdfDictionary();
      cid.Elements.SetString("/Ordering", "Identity");
      cid.Elements.SetString("/Registry", "Adobe");
      cid.Elements.SetInteger("/Supplement", 0);
      Elements.SetValue(Keys.CIDSystemInfo, cid);

      this.fontDescriptor = fontDescriptor;
      Owner.irefTable.Add(fontDescriptor);
      Elements[Keys.FontDescriptor] = fontDescriptor.Reference;

      FontEncoding = PdfFontEncoding.Unicode;
      FontEmbedding = PdfFontEmbedding.Always;
    }
Exemplo n.º 9
0
        static void ExportImage(PdfDictionary image, ref int count)
        {
            string filter = image.Elements.GetName(PdfImage.Keys.Filter);
            switch (filter)
            {
                case "/DCTDecode":
                    ExportJpegImage(image, ref count);
                    break;

                case "":
                case "/FlateDecode":
                    ExportUnfilterableImage(image, ref count);
                    break;

                case "/CCITTFaxDecode":
                case "/RunLengthDecode,":
                default:
                    throw new NotSupportedException();
            }
        }
Exemplo n.º 10
0
    public PdfCIDFont(PdfDocument document, PdfFontDescriptor fontDescriptor, XFont font)
      : base(document)
    {
      Elements.SetName(Keys.Type, "/Font");
      Elements.SetName(Keys.Subtype, "/CIDFontType2");
      // This code is foobar. A PDF literal containing strings is not encrypted, but decryped when opening the PDF file. 
      //Elements.SetValue(Keys.CIDSystemInfo,
      //  new PdfLiteral("<< /Ordering (Identity) /Registry (Adobe) /Supplement 0>>"));
      // Must use real objects because PDF literals containing strings is not encrypted. That causes an error 
      // when the file is decrypted.
      PdfDictionary cid = new PdfDictionary();
      cid.Elements.SetString("/Ordering", "Identity");
      cid.Elements.SetString("/Registry", "Adobe");
      cid.Elements.SetInteger("/Supplement", 0);
      Elements.SetValue(Keys.CIDSystemInfo, cid);

      this.fontDescriptor = fontDescriptor;
      Owner.irefTable.Add(fontDescriptor);
      Elements[Keys.FontDescriptor] = fontDescriptor.Reference;

      FontEncoding = font.PdfOptions.FontEncoding;
      FontEmbedding = font.PdfOptions.FontEmbedding;
    }
Exemplo n.º 11
0
 PdfDictionary CreateDictionary(Type type, PdfDictionary oldDictionary)
 {
   ConstructorInfo ctorInfo;
   PdfDictionary dict;
   if (oldDictionary == null)
   {
     // Use contstructor with signature 'Ctor(PdfDocument owner)'.
     ctorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
       null, new Type[] { typeof(PdfDocument) }, null);
     Debug.Assert(ctorInfo != null, "No appropriate constructor found for type: " + type.Name);
     dict = ctorInfo.Invoke(new object[] { this.owner.Owner }) as PdfDictionary;
   }
   else
   {
     // Use contstructor with signature 'Ctor(PdfDictionary dict)'.
     ctorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
       null, new Type[] { typeof(PdfDictionary) }, null);
     Debug.Assert(ctorInfo != null, "No appropriate constructor found for type: " + type.Name);
     dict = ctorInfo.Invoke(new object[] { oldDictionary }) as PdfDictionary;
   }
   return dict;
 }
Exemplo n.º 12
0
        /// <summary>
        /// Add all inheritable values from the specified page to the specified values structure.
        /// </summary>
        internal static void InheritValues(PdfDictionary page, ref InheritedValues values)
        {
            PdfItem item = page.Elements[InheritablePageKeys.Resources];
            if (item != null)
            {
                PdfReference reference = item as PdfReference;
                if (reference != null)
                    values.Resources = (PdfDictionary)(reference.Value);
                else
                    values.Resources = (PdfDictionary)item;
            }

            item = page.Elements[InheritablePageKeys.MediaBox];
            if (item != null)
                values.MediaBox = new PdfRectangle(item);

            item = page.Elements[InheritablePageKeys.CropBox];
            if (item != null)
                values.CropBox = new PdfRectangle(item);

            item = page.Elements[InheritablePageKeys.Rotate];
            if (item != null)
            {
                if (item is PdfReference)
                    item = ((PdfReference)item).Value;
                values.Rotate = (PdfInteger)item;
            }
        }
Exemplo n.º 13
0
 /// <summary>
 /// Initializes a new instance from an existing dictionary. Used for object type transformation.
 /// </summary>
 public PdfOutline(PdfDictionary dict)
     : base(dict)
 {
     Initialize();
 }
Exemplo n.º 14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PdfAnnotation"/> class.
 /// </summary>
 internal PdfAnnotation(PdfDictionary dict)
   : base(dict)
 {
 }
      /// <summary>
      /// Initializes the item based on the specified PdfDictionary.
      /// </summary>
      /// <param name="dictionary">The dictionary to use for initialization.</param>
      private void Initialize(PdfDictionary dictionary)
      {
        if (dictionary == null) throw new ArgumentNullException("dictionary", "The PDF dictionary item to extract image meta data from was null.");
        if (!dictionary.IsImage()) throw new ArgumentException("The specified dictionary does not represent an image.", "dictionary");

        Height = dictionary.Elements.GetInteger("/Height");
        Width = dictionary.Elements.GetInteger("/Width");
        BitsPerPixel = dictionary.Elements.GetInteger("/BitsPerComponent");
        Length = dictionary.Elements.GetInteger("/Length");

        PdfItem colorSpace = null;
        if (dictionary.Elements.TryGetValue("/ColorSpace", out colorSpace)) {
          ColorSpace = PdfDictionaryColorSpace.Parse(colorSpace);
        }
        else ColorSpace = new PdfRGBColorSpace(); // Default to RGB Color Space
      }
    /// <summary>
    /// Retrieves the specifed dictionary object as an object encoded with FlateDecode filter.
    /// </summary>
    /// <remarks>
    /// FlateDecode a commonly used filter based on the zlib/deflate algorithm (a.k.a. gzip, but not zip) 
    /// defined in RFC 1950 and RFC 1951; introduced in PDF 1.2; it can use one of two groups of predictor 
    /// functions for more compact zlib/deflate compression: Predictor 2 from the TIFF 6.0 specification 
    /// and predictors (filters) from the PNG specification (RFC 2083)
    /// </remarks>
    /// <param name="dictionary">The dictionary to extract the object from.</param>
    /// <returns>The image retrieve from the dictionary. If not found or an invalid image, then null is returned.</returns>
    private static Image ImageFromFlateDecode(PdfDictionary dictionary)
    {
      PdfDictionaryImageMetaData imageData = new PdfDictionaryImageMetaData(dictionary);

      // FlateDecode can be either indexed or a traditional ColorSpace
      bool isIndexed = imageData.ColorSpace.IsIndexed;
      PixelFormat format = GetPixelFormat(imageData.ColorSpace, imageData.BitsPerPixel, isIndexed);

      Bitmap bitmap = new Bitmap(imageData.Width, imageData.Height, format);

      // If indexed, retrieve and assign the color palette for the item.
      if ((isIndexed) && (imageData.ColorSpace.IsRGB)) bitmap.Palette = ((PdfIndexedRGBColorSpace) imageData.ColorSpace).ToColorPalette();
      else if (imageData.ColorSpace is PdfGrayColorSpace) bitmap.Palette = ((PdfGrayColorSpace)imageData.ColorSpace).ToColorPalette(imageData.BitsPerPixel);

      // If not an indexed color, the .NET image component expects pixels to be in BGR order. However, our PDF stream is in RGB order.
      byte[] stream = (format == PixelFormat.Format24bppRgb) ? ConvertRGBStreamToBGR(dictionary.Stream.UnfilteredValue) : dictionary.Stream.UnfilteredValue;

      BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, imageData.Width, imageData.Height), ImageLockMode.WriteOnly, format);
      // We can't just copy the bytes directly; the BitmapData .NET class has a stride (padding) associated with it. 
      int bitsPerPixel = ((((int)format >> 8) & 0xFF));
      int length = (int)Math.Ceiling(bitmapData.Width * bitsPerPixel / 8.0);
      for (int y = 0, height = bitmapData.Height; y < height; y++) {
        int offset = y * length;
        Marshal.Copy(stream, offset, bitmapData.Scan0 + (y * bitmapData.Stride), length);
      }
      bitmap.UnlockBits(bitmapData);

      return (bitmap);
    }
Exemplo n.º 17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PdfContent"/> class.
 /// </summary>
 /// <param name="dict">The dict.</param>
 public PdfContent(PdfDictionary dict) // HACK PdfContent
   : base(dict)
 {
   // A PdfContent dictionary is always unfiltered.
   Decode();
 }
Exemplo n.º 18
0
 internal void SetOwner(PdfDictionary dict)
 {
   ChangeOwner(dict);
 }
    /// <summary>
    /// Retrieves the specifed dictionary object as an object encoded with CCITTFaxDecode filter (TIFF).
    /// </summary>
    /// <param name="dictionary">The dictionary to extract the object from.</param>
    /// <returns>The image retrieve from the dictionary. If not found or an invalid image, then null is returned.</returns>
    private static Image ImageFromCCITTFaxDecode(PdfDictionary dictionary)
    {
      Image image = null;
      PdfDictionaryImageMetaData imageData = new PdfDictionaryImageMetaData(dictionary);

      PixelFormat format = GetPixelFormat(imageData.ColorSpace, imageData.BitsPerPixel, true);
      Bitmap bitmap = new Bitmap(imageData.Width, imageData.Height, format);

      // Determine if BLACK=1, create proper indexed color palette.
      CCITTFaxDecodeParameters ccittFaxDecodeParameters = new CCITTFaxDecodeParameters(dictionary.Elements["/DecodeParms"].Get() as PdfDictionary);
      if (ccittFaxDecodeParameters.BlackIs1) bitmap.Palette = PdfIndexedColorSpace.CreateColorPalette(Color.Black, Color.White);
      else bitmap.Palette = PdfIndexedColorSpace.CreateColorPalette(Color.White, Color.Black);

      using (MemoryStream stream = new MemoryStream(GetTiffImageBufferFromCCITTFaxDecode(imageData, dictionary.Stream.Value))) {
        using (Tiff tiff = Tiff.ClientOpen("<INLINE>", "r", stream, new TiffStream())) {
          if (tiff == null) return (null);

          int stride = tiff.ScanlineSize();
          byte[] buffer = new byte[stride];
          for (int i = 0; i < imageData.Height; i++) {
            tiff.ReadScanline(buffer, i);

            Rectangle imgRect = new Rectangle(0, i, imageData.Width, 1);
            BitmapData imgData = bitmap.LockBits(imgRect, ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
            Marshal.Copy(buffer, 0, imgData.Scan0, buffer.Length);
            bitmap.UnlockBits(imgData);
          }
        }
      }
      return (bitmap);
    }
Exemplo n.º 20
0
 PdfItem CreateValue(Type type, PdfDictionary oldValue)
 {
   ConstructorInfo ctorInfo = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
     null, new Type[] { typeof(PdfDocument) }, null);
   PdfObject obj = ctorInfo.Invoke(new object[] { this.owner.Owner }) as PdfObject;
   if (oldValue != null)
   {
     obj.Reference = oldValue.Reference;
     obj.Reference.Value = obj;
     if (obj is PdfDictionary)
     {
       PdfDictionary dict = (PdfDictionary)obj;
       dict.elements = ((PdfDictionary)oldValue).elements;
     }
   }
   return obj;
 }
    private static PdfDictionary ProcessFilters(PdfDictionary dictionary)
    {
      PdfDictionary result;

      // Create a dictionary mapping (i.e. switch statement) to process the expected filters.
      var map = new Dictionary<string, Func<byte[], byte[]>>() {
        { "/FlateDecode", (d) => {
          var decoder = new FlateDecode();
          return (decoder.Decode(d));
        } }
      };

      // Get all of the filters.
      var filters = ((PdfArray)dictionary.Elements["/Filter"])
                                         .Elements.Where(e => e.IsName())
                                         .Select(e => ((PdfName)e).Value)
                                         .ToList();
      // If only one filter in array. Just rewrite the /Filter
      if (filters.Count == 1) {
        result = dictionary.Clone();
        result.Elements["/Filter"] = new PdfName(filters[0]);
        return (result);
      }
      
      // Process each filter in order. The last filter should be the actual encoded image.
      byte[] data = dictionary.Stream.Value;
      for(int index = 0; index < (filters.Count - 1); index++) {
        if (! map.ContainsKey(filters[index])) {
          throw new NotSupportedException(String.Format("Encountered embedded image with multiple filters: \"{0}\". Unable to process the filter: \"{1}\".",
                                                        String.Join(",", filters), filters[index]));
        }
        data = map[filters[index]].Invoke(data);
      }

      result = new PdfDictionary();
      result.Elements.Add("/Filter", new PdfName(filters.Last()));
      foreach (var element in dictionary.Elements.Where(e => !String.Equals(e.Key, "/Filter", StringComparison.OrdinalIgnoreCase))) {
        result.Elements.Add(element.Key, element.Value);
      }
      result.CreateStream(data);

      return(result);
    }
Exemplo n.º 22
0
 /// <summary>
 /// Initializes a new instance from an existing dictionary. Used for object type transformation.
 /// </summary>
 protected PdfDictionary(PdfDictionary dict)
   : base(dict)
 {
   if (dict.elements != null)
     dict.elements.ChangeOwner(this);
   if (dict.stream != null)
     dict.stream.SetOwner(this);
 }
 /// <param name="dictionary">The dictionary object o parse.</param>
 public PdfDictionaryImageMetaData(PdfDictionary dictionary)
 {
   Initialize(dictionary);
 }
Exemplo n.º 24
0
        private IScannedImage ExportAsPngImage(PdfPage page, PdfDictionary image)
        {
            int width = image.Elements.GetInteger(PdfImage.Keys.Width);
            int height = image.Elements.GetInteger(PdfImage.Keys.Height);
            int bitsPerComponent = image.Elements.GetInteger(PdfImage.Keys.BitsPerComponent);

            var buffer = image.Stream.UnfilteredValue;

            Bitmap bitmap;
            ScanBitDepth bitDepth;
            switch (bitsPerComponent)
            {
                case 8:
                    bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
                    bitDepth = ScanBitDepth.C24Bit;
                    RgbToBitmapUnmanaged(height, width, bitmap, buffer);
                    break;
                case 1:
                    bitmap = new Bitmap(width, height, PixelFormat.Format1bppIndexed);
                    bitDepth = ScanBitDepth.BlackWhite;
                    BlackAndWhiteToBitmapUnmanaged(height, width, bitmap, buffer);
                    break;
                default:
                    throw new NotImplementedException("Unsupported image encoding (expected 24 bpp or 1bpp)");
            }

            using (bitmap)
            {
                bitmap.SetResolution(bitmap.Width / (float)page.Width.Inch, bitmap.Height / (float)page.Height.Inch);
                return scannedImageFactory.Create(bitmap, bitDepth, true);
            }
        }
      /// <param name="dictionary">The dictionary element to parse / retrieve.</param>
      public CCITTFaxDecodeParameters(PdfDictionary dictionary):this()
      {
        if (dictionary == null) return;

        if (dictionary.Elements.ContainsKey(_K)) {
          K = dictionary.Elements.GetInteger(_K);
        }
        if (dictionary.Elements.ContainsKey(END_OF_LINE)) {
          EndOfLine = dictionary.Elements.GetBoolean(END_OF_LINE);
        }
        if (dictionary.Elements.ContainsKey(ENCODED_BYTE_ALIGN)) {
          EncodedByteAlign = dictionary.Elements.GetBoolean(ENCODED_BYTE_ALIGN);
        }
        if (dictionary.Elements.ContainsKey(COLUMNS)) {
          Columns = dictionary.Elements.GetInteger(COLUMNS);
        }
        if (dictionary.Elements.ContainsKey(ROWS)) {
          Rows = dictionary.Elements.GetInteger(ROWS);
        }
        if (dictionary.Elements.ContainsKey(END_OF_BLOCK)) {
          EndOfBlock = dictionary.Elements.GetBoolean(END_OF_BLOCK);
        }
        if (dictionary.Elements.ContainsKey(BLACK_IS_1)) {
          BlackIs1 = dictionary.Elements.GetBoolean(BLACK_IS_1);
        }
        if (dictionary.Elements.ContainsKey(DAMAGED_ROWS_BEFORE_ERROR)) {
          DamagedRowsBeforeError = dictionary.Elements.GetInteger(DAMAGED_ROWS_BEFORE_ERROR);
        }
      }
Exemplo n.º 26
0
        private void ShrinkJpegImage(PdfDictionary image, int quality)
        {
            try
            {
                string filter = image.Elements.GetName("/Filter");
                if (filter != "/DCTDecode") return;

                Stream originalImageStream = new MemoryStream(image.Stream.Value);
                Image originalJpegImage = Image.FromStream(originalImageStream);

                byte[] newJpegImage = SaveJpeg(originalJpegImage, quality);

                image.Stream.Value = newJpegImage;
            }
            catch (Exception)
            {
                return;
            }
        }
Exemplo n.º 27
0
    /// <summary>
    /// Writes the stream of the specified dictionary.
    /// </summary>
    public void WriteStream(PdfDictionary value, bool omitStream)
    {
      StackItem stackItem = (StackItem)this.stack[this.stack.Count - 1];
      Debug.Assert(stackItem.Object is PdfDictionary);
      Debug.Assert(stackItem.Object.IsIndirect);
      stackItem.HasStream = true;

      if (this.lastCat == CharCat.NewLine)
        WriteRaw(">>\nstream\n");
      else
        WriteRaw(" >>\nstream\n");

      if (omitStream)
        WriteRaw("  «...stream content omitted...»\n");  // useful for debugging only
      else
      {
        byte[] bytes = value.Stream.Value;
        if (bytes.Length != 0)
        {
          if (this.securityHandler != null)
          {
            bytes = (byte[])bytes.Clone();
            bytes = this.securityHandler.EncryptBytes(bytes);
          }
          Write(bytes);
          if (this.lastCat != CharCat.NewLine)
            WriteRaw('\n');
        }
      }
      WriteRaw("endstream\n");
    }
Exemplo n.º 28
0
        internal override void WriteObject(PdfWriter writer)
        {
            // HACK: temporarily flip media box if Landscape
            PdfRectangle mediaBox = MediaBox;
            // TODO: Take /Rotate into account
            if (_orientation == PageOrientation.Landscape)
                MediaBox = new PdfRectangle(mediaBox.X1, mediaBox.Y1, mediaBox.Y2, mediaBox.X2);

#if true
            // Add transparency group to prevent rendering problems of Adobe viewer.
            // Update (PDFsharp 1.50 beta 3): Add transparency group only of ColorMode is defined.
            // Rgb is the default for the ColorMode, but if user sets it to Undefined then
            // we respect this and skip the transparency group.
            TransparencyUsed = true; // TODO: check XObjects
            if (TransparencyUsed && !Elements.ContainsKey(Keys.Group) &&
                _document.Options.ColorMode != PdfColorMode.Undefined)
            {
                PdfDictionary group = new PdfDictionary();
                _elements["/Group"] = group;
                if (_document.Options.ColorMode != PdfColorMode.Cmyk)
                    group.Elements.SetName("/CS", "/DeviceRGB");
                else
                    group.Elements.SetName("/CS", "/DeviceCMYK");
                group.Elements.SetName("/S", "/Transparency");
                //False is default: group.Elements["/I"] = new PdfBoolean(false);
                //False is default: group.Elements["/K"] = new PdfBoolean(false);
            }
#endif

#if DEBUG_
            PdfItem item = Elements["/MediaBox"];
            if (item != null)
                item.GetType();
#endif
            base.WriteObject(writer);

            if (_orientation == PageOrientation.Landscape)
                MediaBox = mediaBox;
        }
Exemplo n.º 29
0
 internal PdfCustomValue(PdfDictionary dict)
   : base(dict)
 {
   // TODO: uncompress stream
 }
Exemplo n.º 30
0
        /// <summary>
        /// Inherit values from parent node.
        /// </summary>
        internal static void InheritValues(PdfDictionary page, InheritedValues values)
        {
            // HACK: I'M ABSOLUTELY NOT SURE WHETHER THIS CODE COVERS ALL CASES.
            if (values.Resources != null)
            {
                PdfDictionary resources;
                PdfItem res = page.Elements[InheritablePageKeys.Resources];
                if (res is PdfReference)
                {
                    resources = (PdfDictionary)((PdfReference)res).Value.Clone();
                    resources.Document = page.Owner;
                }
                else
                    resources = (PdfDictionary)res;

                if (resources == null)
                {
                    resources = values.Resources.Clone();
                    resources.Document = page.Owner;
                    page.Elements.Add(InheritablePageKeys.Resources, resources);
                }
                else
                {
                    foreach (PdfName name in values.Resources.Elements.KeyNames)
                    {
                        if (!resources.Elements.ContainsKey(name.Value))
                        {
                            PdfItem item = values.Resources.Elements[name];
                            if (item is PdfObject)
                                item = item.Clone();
                            resources.Elements.Add(name.ToString(), item);
                        }
                    }
                }
            }

            if (values.MediaBox != null && page.Elements[InheritablePageKeys.MediaBox] == null)
                page.Elements[InheritablePageKeys.MediaBox] = values.MediaBox;

            if (values.CropBox != null && page.Elements[InheritablePageKeys.CropBox] == null)
                page.Elements[InheritablePageKeys.CropBox] = values.CropBox;

            if (values.Rotate != null && page.Elements[InheritablePageKeys.Rotate] == null)
                page.Elements[InheritablePageKeys.Rotate] = values.Rotate;
        }