Многостраничное изображение TIFF в формате JPEG требует больше времени для сохранения - PullRequest
0 голосов
/ 12 июля 2020

У меня есть файлы Tiff размером 10 МБ + с 50 страницами, и я хочу выполнить поворот всех страниц на 90 градусов одним щелчком мыши, но после выполнения операций поворота для каждого кадра и когда дело доходит до

Save(Encoder encoder)

тогда здесь

encoder.Save(temporaryStream); // this line is taking more time(almost 5-6 seconds for each page).

На самом деле, когда я отлаживал метод Save, я понял, что для каждой страницы требуется почти 5-6 секунд, поэтому для всех 50 страниц это занимает почти 5-6 минут на сохранение после ротации, этого времени достаточно для всего 50 страниц.

Ниже мой фрагмент кода:

  /// <summary>
  /// An object for thread-safe synchronization.
  /// </summary>
  internal object SyncRoot { get { return _guardedState; } }
 
  private BitmapDecoder _p_decoder;

  /// <summary>
  /// The bitmap decoder. Created on demand
  /// </summary>
  internal BitmapDecoder Decoder
  {
     get
     {
        if (_p_decoder == null)
           _p_decoder = CreateDecoder();

        return _p_decoder;
     }
     set
     {
        _p_decoder = value;
        // page count needs recalculating
        _p_pageCount = UncalculatedPageCount;
     }
  }

  /// <summary>
  /// Whether or not the object has been disposed.
  /// </summary>
  protected bool IsDisposed
  {
     get
     {
        lock (_guardedState)
        {
           return _guardedState.IsDisposed;
        }
     }
     private set
     {
        lock (_guardedState)
        {
           _guardedState.IsDisposed = value;
        }
     }
  }

  /// <summary>
  /// Rotate all pages in the stream by the given amount
  /// </summary>
  /// <param name="pageNumbers">The number of the pages to be rotated</param>
  /// <param name="rotationOperation">The type of rotation to perform</param>
  public void RotateAllPages(IEnumerable<int> pageNumbers, RotationDegrees rotationOperation)
  {
     lock (SyncRoot)
     {
        foreach (var pageNumber in pageNumbers)
        {
           if (Disposed)
              throw new ObjectDisposedException(GetType().Name);

           if (!PageManipulationSupported) throw new NotSupportedException();

           // sanity check
           if ((pageNumber < 1) || pageNumber > PageCount)
              throw new ArgumentOutOfRangeException("Page out of range: " + pageNumber, "pageNumber");

           RotatePage(pageNumber, rotationOperation);
        }
     }
  }
  /// <summary>
  /// Rotates a page in the stream by the given number of degrees.
  /// </summary>
  /// <param name="pageNumber">The number of the page to be rotated.</param>
  /// <param name="rotationOperation">The type of rotation to perform.</param>
  internal override void RotatePage(int pageNumber, RotationDegrees rotationOperation)
  {
     if (_mimeType != MimeTypes.Image.Tiff)
     {
        RotatePages(pageNumber, rotationOperation);
     }
      // Flush the contents
     Stream.Flush();
     RecreateState();
  }
  
  
  private void RotatePages(int pageNumber, RotationDegrees rotationOperation)
  {
     EnsureNotDisposed();

     // create the encoder
     BitmapEncoder encoder = BitmapEncoder.Create(Decoder.CodecInfo.ContainerFormat);

     // copy the destination frames
     foreach (BitmapFrame frame in Decoder.Frames)
        encoder.Frames.Add(frame);
     double angleOfRotation = (double)rotationOperation;

     BitmapFrame oldFrame = encoder.Frames[pageNumber - 1];

     // Create the TransformedBitmap to use as the Image source.
     TransformedBitmap tb = new TransformedBitmap();

     // Properties must be set between BeginInit and EndInit calls.
     tb.BeginInit();

     tb.Source = new CachedBitmap(oldFrame, BitmapCreateOptions.None, BitmapCacheOption.None);

     RotateTransform transform = new RotateTransform(angleOfRotation);
     tb.Transform = transform;

     tb.EndInit();

     encoder.Frames.RemoveAt(pageNumber - 1);
     encoder.Frames.Insert(pageNumber - 1, BitmapFrame.Create(tb));

     Save(encoder);
  }

  /// <summary>
  /// Saves the contents of a bitmap encoder to <see cref="Stream"/>.
  /// </summary>
  /// <param name="encoder">
  /// The encoder from which to obtain the data to save.
  /// </param>
  private void Save(BitmapEncoder encoder)
  {
     // save to a temporary stream
     string tempFileName = Path.GetTempFileName();

     try
     {
        using (FileStream temporaryStream = new FileStream(tempFileName, FileMode.OpenOrCreate))
        {
           if (encoder.Frames.Count > 0)
              encoder.Save(temporaryStream);

           // write back out to permanent stream
           if (Stream.CanWrite && Stream.CanSeek)
              CopyStream(temporaryStream, Stream);
           else
              throw new UnauthorizedAccessException();
        }
     }
     finally
     {
        // Delete the temporary file
        File.Delete(tempFileName);
     }
  }
 /// <summary>
  /// Recreates the core's internal state to avoid cached stale data
  /// being used.
  /// </summary>
  protected override void RecreateState()
  {
     // clear the decoder cache
     Decoder = null;
  }
  /// <summary>
  /// method for copying streams
  /// </summary>
  /// <param name="input">The source stream</param>
  /// <param name="output">The destination stream</param>
  protected static void CopyStream(Stream input, Stream output)
  {
     input.Seek(0, SeekOrigin.Begin);
     output.Seek(0, SeekOrigin.Begin);
     output.SetLength(0);

     byte[] buffer = new byte[4096];
     int read;

     while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        output.Write(buffer, 0, read);
     output.Seek(0, SeekOrigin.Begin);
  }

Пожалуйста, помогите исправить неисправный область в коде. Любое предложение приветствуется.

...