Big problems… Attempting to use your code - calling my DitherBitmap which uses Microsoft Bitmap to Dither an image, gets to page 39 and throws a Microsoft Out-of-Memory even though I Dispose of all streams and bitmap objects in the called method.
So - Back to Aspose - I rewrote my code, using the foreach TiffFrame frame in TiffImage pageImage - and use your sample from
https://forum.aspose.com/t/2208where you simply go through a pixel array and convert to Black or White.
This works for a few pages - but throws an Aspose out of memory error trying to save page 13 - even though added/saved pages are around 13k each:
Aspose.Imaging.Exceptions.FrameworkException was caught
HResult=-2146233088
Message=Cannot allocate so many bytes. Use LoadPartialPixels instead.
Source=Aspose.Imaging
StackTrace:
at Aspose.Imaging.RasterImage. .Process(Rectangle , Color[] , Point , Point )
at . . . (Rectangle )
at . . (Rectangle , , , Int32 , Int32 )
at . . (Rectangle , )
at . . (TiffStream , Rectangle , IPartialPixelLoader )
at . . (Rectangle , IPartialPixelLoader )
at Aspose.Imaging.FileFormats.Tiff.TiffFrame.LoadPixelsToCache(Rectangle rectangle, IPartialPixelLoader partialPixelLoader)
at Aspose.Imaging.RasterCachedImage.LoadPixelsInternal(Rectangle rectangle, IPartialPixelLoader pixelLoader)
at Aspose.Imaging.RasterImage. (Rectangle , Color[] , Boolean , IPartialPixelLoader )
at Aspose.Imaging.RasterImage. (Rectangle , Boolean , IPartialPixelLoader )
at Aspose.Imaging.RasterImage.LoadPixels(Rectangle rectangle)
at LINK.Common.Enterprise.DocumentManagement.Document.GetStreamOfReportAndImages(String informationRequestId, Int32 reportingBatchId, String reportPath, String reportFormat, String[] imagePaths, Int32& pageCount)
InnerException:
How / why would I use LoadPartialPixels when I am not specifying a sub-rectangle of any larger image? AND I am only getting the pixels from the frame. It would appear despite being in a using statement - your system has two problems - it is not disposing when dispose is called directly, and looking at the the values of cache used - they remain the same, unchanging between frames - which implies the memory was released - but it is not.
saving each frame as shown in my code below resulted in files saved of this:
06/19/2013 01:56 PM 40,960 Page1_reportheader.tif
06/19/2013 01:56 PM 21,597 Page2_DCUsed0_MCUsed32000244.tif
06/19/2013 01:57 PM 12,675 Page3_DCUsed0_MCUsed32000244.tif
06/19/2013 01:57 PM 13,043 Page4_DCUsed0_MCUsed32000244.tif
06/19/2013 01:57 PM 12,722 Page5_DCUsed0_MCUsed32000244.tif
06/19/2013 01:57 PM 12,759 Page6_DCUsed0_MCUsed32000244.tif
06/19/2013 01:57 PM 12,686 Page7_DCUsed0_MCUsed32000244.tif
06/19/2013 01:57 PM 6,046 Page8_DCUsed0_MCUsed32000244.tif
06/19/2013 01:57 PM 12,198 Page9_DCUsed0_MCUsed32000244.tif
06/19/2013 01:57 PM 13,303 Page10_DCUsed0_MCUsed32000244.tif
06/19/2013 01:57 PM 13,211 Page11_DCUsed0_MCUsed32000244.tif
06/19/2013 01:57 PM 13,522 Page12_DCUsed0_MCUsed32000244.tif
06/19/2013 01:57 PM 13,506 Page13_DCUsed0_MCUsed32000244.tif
which shows no changes in Memory cache used - and you can see by the saved file size - timage couldn’t be bigger than the sum of these added frames I would think…
This code dies on the 13th frame.
I have attached my sample TIF file (note, contains trademarked color company logo which is what needs to be grayscaled - your conversion to G3 or G4 1bpp erases it completely). note: Actual added TIF files may have varying resolution/bpp/size, etc.
This is the one loaded in my document.cs file as the first and only imagePaths entry loaded as imagePath[0] below on line:
using (Stream imageFile = new FileStream(imagePaths[i], FileMode.Open, FileAccess.Read))
My code is (anything missing can be found in my prior submitted document.cs):
Aspose.Imaging.ImageOptions.TiffOptions createOptions =
new Aspose.Imaging.ImageOptions.TiffOptions();
TiffRational rX = new TiffRational(200);
TiffRational rY = new TiffRational(200);
createOptions.BitsPerSample = new ushort[] { 1 };
createOptions.Xresolution = rX;
createOptions.Yresolution = rY;
createOptions.Orientation = Aspose.Imaging.FileFormats.Tiff.Enums.TiffOrientations.TopLeft;
createOptions.PlanarConfiguration = Aspose.Imaging.FileFormats.Tiff.Enums.TiffPlanarConfigs.Contiguous;
createOptions.Photometric = Aspose.Imaging.FileFormats.Tiff.Enums.TiffPhotometrics.MinIsWhite;
createOptions.Compression = Aspose.Imaging.FileFormats.Tiff.Enums.TiffCompressions.CcittFax3;
createOptions.Source = new Aspose.Imaging.Sources.StreamSource(new System.IO.MemoryStream());
using (TiffImage timage = (TiffImage)Aspose.Imaging.Image.Create(createOptions, 1770, 2200))
{
//… code excluded - see document.cs - that adds report header TIF to timage
//…
for (int i = 0; i < imagePaths.Length; i++)
{
using (Stream imageFile = new FileStream(imagePaths[i], FileMode.Open, FileAccess.Read))
{
byte[] tmpBytes = new byte[imageFile.Length];
imageFile.Read(tmpBytes, 0, Convert.ToInt32(imageFile.Length));
MemoryStream copiedStream = new MemoryStream(tmpBytes);
copiedStream.Seek(0, SeekOrigin.Begin);
using (TiffImage pageImage = (TiffImage)Aspose.Imaging.Image.Load(copiedStream))
{
foreach (TiffFrame frame in ((TiffImage)pageImage).Frames)
{
Aspose.Imaging.Color[] pixels = frame.LoadPixels(frame.Bounds);
for (int x = 0; x < pixels.Length; x++)
{
// 0.3F,0.59F, 0.11F
double powerR = .3 * Convert.ToDouble(pixels[x].R);
double powerG = .59 * Convert.ToDouble(pixels[x].G);
double powerB = .11 * Convert.ToDouble(pixels[x].B);
int power = Convert.ToInt32(powerR + powerG + powerB);
if (power > 218)
{
pixels[x] = Aspose.Imaging.Color.White;
}
else
{
pixels[x] = Aspose.Imaging.Color.Black;
}
}
frame.SavePixels(frame.Bounds, pixels);
long Diskremaining = Cache.AllocatedDiskBytesCount;
long Memremaining = Cache.AllocatedMemoryBytesCount;
// create a new frame from
using (TiffFrame addframe = TiffFrame.CreateFrameFrom(frame, new Aspose.Imaging.ImageOptions.TiffOptions(createOptions)))
{
// copy addframe from modified frame and save it as createOptions 1bpp G4 TIF
addframe.SavePixels(frame.Bounds, frame.LoadPixels(frame.Bounds));
// add frame to base timage TIFF file
timage.AddFrame(addframe);
pageCount++;
addframe.Save(@“C:\Temp\Page” + pageCount.ToString() + “_DCUsed” +
Diskremaining.ToString() + “_MCUsed” + Memremaining.ToString() + “.tif”,
addframe.FrameOptions);
addframe.Dispose();
}
frame.Dispose();
} // end foreach frame
} // end pageImage
} // end using imageFile
} // end foreach TIF file to add - there is only one in current testing
Of NOTE: Your latest 1.8 build is MISSING a DrawImage (…) definition mentioned in your documentation that has a parameter named ImageAttributes. The lack of this method according to the API basically destroys much of your documented features.
If this existed - I could use it with ColorMatrix to grayscale the image properly, and then use TiffFrame.GetPixel and TiffFrame.SetPixel to clean it up as I did in my DitherImage method.
The first paragraph states:
There is no DrawImage method that currently takes an ImageAttributes object.
The Microsoft equivalent is (which can be seen in my DitherImage method):
float[][] colorMatrixElements = {
new float[] {0.3F, 0.3F, 0.3F, 0, 0},
new float[] {0.59F, 0.59F, 0.59F, 0, 0},
new float[] {0.11F, 0.11F, 0.11F, 0, 0},
new float[] { 0, 0, 0, 1, 0},
new float[] { 0, 0, 0, 0, 1}};
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bm);
System.Drawing.Imaging.ColorMatrix c = new System.Drawing.Imaging.ColorMatrix(colorMatrixElements);
System.Drawing.Imaging.ImageAttributes attributes = new System.Drawing.Imaging.ImageAttributes();
attributes.SetColorMatrix(c);
g.DrawImage(gsBitmap, new System.Drawing.Rectangle(left, top, destwidth, destheight), 0, 0, srcwidth, srcheight, System.Drawing.GraphicsUnit.Pixel, attributes);
I started writing the equivilent in Aspose code - but without the DrawImage Aspose method - it is useless:
Aspose.Imaging.Image gimage;
Aspose.Imaging.Graphics ga = new Aspose.Imaging.Graphics(gimage);
Aspose.Imaging.ImageAttributes gattributes = new Aspose.Imaging.ImageAttributes();
Aspose.Imaging.ColorMatrix gcolormatrix = new Aspose.Imaging.ColorMatrix(colorMatrixElements);
gattributes.SetColorMatrix(gcolormatrix);
ga.DrawImage(tFrame, new System.Drawing.Rectangle(left, top, destwidth, destheight), 0, 0, srcwidth, srcheight, System.Drawing.GraphicsUnit.Pixel, gattributes);
And another FYI: Your reply above dated: 6-5
contains: -FrameOptions.Resoluition = new TiffRational(200);
There no longer is a .Resolution value - someone apparently removed that API…
I figured out how to set Resolution the hard way:
TiffRational rX = new TiffRational(200);
TiffRational rY = new TiffRational(200);
createOptions.Xresolution = rX;
createOptions.Yresolution = rY;
Thanks for your help,
Todd