Atalasoft Knowledge Base

HOWTO: Resample a TIFF with Embedded XMP Annotations


This example resamples every page of a tiff file by fitting it to the destination size, and resizes the annotations included in each page to the same scale. It does not handle font scaling for text based annotations. (Uses DotImage 5.0 or newer)


private void ResampleTiffWithAnnotations(string origPath, string destPath, Size destSize)
      using (Stream fs = new FileStream(origPath, FileMode.Open, FileAccess.Read, FileShare.Read))
         TiffDecoder tDecoder = new TiffDecoder();
         TiffFile tFile = new TiffFile();


         for (int frame = 0; frame < tFile.Images.Count; frame++)
            fs.Seek(0, SeekOrigin.Begin);
            ImageInfo info = RegisteredDecoders.GetImageInfo(fs, frame);
            TiffTag xmpTag = tFile.Images[frame].Tags.LookupTag(TiffTagID.XmpData);

            float scale = CalculateBestFitScale((SizeF)info.Size, (SizeF)destSize);

            fs.Seek(0, SeekOrigin.Begin);
            using (AtalaImage image = tDecoder.ReadScaled(fs, frame, scale, null))
               TiffDirectory tImage = new TiffDirectory(image);
               TiffTagCollection tags = tImage.Tags;

               if (xmpTag != null)
                  tags.Add(ResizeXmpAnnotations(xmpTag, scale));

               tFile.Images.Insert(frame, tImage);


   // Loads annotations into an AnnotationController, resizes them all
   // using the provided scaling, and returns a TiffTag that contains
   // the serialized annotation data
   private TiffTag ResizeXmpAnnotations(TiffTag tag, float scale)
      TiffTag retTag = null;

      if (tag.Data != null && tag.Type == TiffTagDataType.Byte)
         XmpFormatter xmp = new XmpFormatter();
         byte[] data = (byte[])tag.Data;

         using (AnnotationController controller = new AnnotationController())
            controller.Load(data, AnnotationDataFormat.Xmp);

            foreach (LayerAnnotation layer in controller.Layers)
               foreach (AnnotationUI ann in layer.Items)
                  PointF loc = ann.Location;
                  SizeF size = ann.Size;

                  ann.Location = new PointF(loc.X * scale, loc.Y * scale);
                  ann.Size = new SizeF(size.Width * scale, size.Height * scale);

            using (MemoryStream mem = new MemoryStream())
               xmp.Serialize(mem, controller.Layers);
               retTag = new TiffTag(TiffTagID.XmpData, mem.ToArray(), TiffTagDataType.Byte);

      return retTag;

   // Returns the scale corresponding to the best fitting of origSize in maxSize
   private float CalculateBestFitScale(SizeF origSize, SizeF maxSize)
      float zoom = 1;

      if (origSize.Width / maxSize.Width == origSize.Height / maxSize.Height)
      {   // the ratio of the original size is the same as the max size, need to use the minimum due to round off error
         zoom = Math.Min(maxSize.Width / origSize.Width, maxSize.Height / origSize.Height);
      else if (origSize.Width / maxSize.Width > origSize.Height / maxSize.Height)
      {   //size to the width
         zoom = maxSize.Width / origSize.Width;
      {   //size to the height
         zoom = maxSize.Height / origSize.Height;

      return zoom;

Original Article:
Q10170 - HOWTO: Resample a TIFF with Embedded XMP Annotations

Last Modified: 9 Months Ago
Last Modified By: Administrator
Article not rated yet.
Article has been viewed 159 times.
Also In This Category