JPEG multipage tiff image is taking more time to save.

  • Thread starter Thread starter Ankit Raman
  • Start date Start date
A

Ankit Raman

Guest
Hi,

I am working for Windows Forms application and below issue is for same Winform application.

I have 10MB+ Tiff files having 50 pages, and I want to perform rotation of all the pages by 90 degree at one click only, but after performing the rotation operations for each frames and when it comes to the

Save(Encoder encoder)
then here,
encoder.Save(temporaryStream); // this line is taking more time(almost 5-6 seconds for each page).
Actually,when I debugged the Save method then I realized that it is taking almost 5-6 seconds in saving for each page so for all 50 pages it is taking almost 5-6 minutes of time in saving after rotation, this much of time is too enough for only 50 pages.

Below is my Code snippet:

/// <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);
}
Please help to improve the faulty area in code.
Any suggestion is highly appreciated.

Continue reading...
 
Back
Top