Saturday, June 26, 2010

OutOfMemory Exception

The below code is used to merge multipage tiff with single page tiffs.

 private void CreatThumbnail(Image thumbNailImg, int iPagesCount)
        {
            try
            {
                //TRK
                //PictureBox[] picBoxArray = new PictureBox[iPagesCount];
                picBoxArray = new PictureBox[iPagesCount];
                PictureBox picBox = null;

                pnlThumbnail.Controls.Clear();

                
                int iWidth = 300;
                int iHeight = 300;

               
                if (!rbShowPageByPage.Checked && !rbShowBoth.Checked)
                {
                    //TRK - 01 
                    iWidth = 308;
                    iHeight = 550;
                    pnlThumbnail.Size = new Size(966, 560);

                    //iWidth = 500;
                    //iHeight = 550;
                    //pnlThumbnail.Size = new Size(966, 560);
                }
                else
                {
                    pnlThumbnail.Location = new Point(16, 110);
                    pnlThumbnail.Size = new Size(966, 131);
                }

                int iThumbCurrPage = 0;
                
                for (; iThumbCurrPage < iPagesCount; iThumbCurrPage++)
                {
                    //TRK
                    picBox = new PictureBox();
                    thumbNailImg.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, iThumbCurrPage);

                    using (Image myBmp = new Bitmap(thumbNailImg, iWidth, iHeight))
                    {
                        MemoryStream memoryStream = new MemoryStream();
                        myBmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Tiff);
                        picBox.Image = Image.FromStream(memoryStream); // showing the page in the pictureBox1

                        myBmp.Dispose();
                        if (memoryStream != null)
                        {
                            memoryStream.Close();
                            memoryStream.Dispose();
                        }
                        GC.Collect();
                    }

                    picBox.Size = picBox.Image.Size;
                    picBox.Location = new Point(1 + (iThumbCurrPage * (iWidth + 10)), 1);
                    picBoxArray[iThumbCurrPage] = picBox;
                    picBoxArray[iThumbCurrPage].Name = Convert.ToString(iThumbCurrPage);
                    toolTipForControls.SetToolTip(picBoxArray[iThumbCurrPage], MessagesAndToolTips.ThumNailClick);

                    picBoxArray[iThumbCurrPage].Click += new System.EventHandler(this.ThumbNailPictureBox_Click);
                    pnlThumbnail.Controls.Add(picBoxArray[iThumbCurrPage]);

                    if (iThumbCurrPage == 0)
                        objCommonDeclarations.ShowMessage("Loading Page " + Convert.ToString(iThumbCurrPage + 1) + " Of " + Convert.ToString(iPagesCount), "INFO", lblShowMessage);
                    else
                        objCommonDeclarations.ShowMessage("Loading Next Page " + Convert.ToString(iThumbCurrPage + 1) + " Of " + Convert.ToString(iPagesCount), "INFO", lblShowMessage);
                    Application.DoEvents();

                    GC.Collect();
                }

                objCommonDeclarations.ShowMessage("Loading Last " + Convert.ToString(iThumbCurrPage) + " Of " + Convert.ToString(iPagesCount), "INFO", lblShowMessage);
                Application.DoEvents();

                objCommonDeclarations.ShowMessage(string.Empty, "INFO", lblShowMessage);
                Application.DoEvents();

            }
            catch (Exception ex)
            {
                objCommonDeclarations.ShowMessage(ex.Message.ToString(), "ERROR", lblShowMessage);
                objCommonDeclarations.WriteLog(ex.Message.ToString(), false, false);
            }
        }

 private void SwapImages()
        {
            try
            {
                int swapPage = Convert.ToInt32(txtPageNumber.Text.Trim()) - 1;

                //Open file in read only mode 
                using (FileStream fs = new FileStream(@lblFile.Text.Trim(), FileMode.Open, FileAccess.Read))
                {

                    string _sDestinatinPath = Path.Combine(CommonDeclarations.sDestinationPath, Path.GetFileName(@lblFile.Text.Trim()));
                    if (swapPage == 0)
                    {
                        using (Image bmp1 = Image.FromStream(fs))//TRK
                        {
                            bmp1.Save(_sDestinatinPath, ImageFormat.Tiff);

                            fs.Dispose();
                            bmp1.Dispose();
                            GC.Collect();
                        }
                        return;

                        //background
                        //return string.Empty;
                    }

                    ImageCodecInfo imageCodecInfo = GetEncoderInfo("image/tiff");

                    //Image bmp = Image.FromStream(fs);
                    using (Image bmp = Image.FromStream(fs))//TRK
                    {
                        //Bitmap bmp = new Bitmap(fs);

                        int frameCount = bmp.GetFrameCount(FrameDimension.Page);
                        bmp.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, swapPage);

                        //Image newTiff = new Bitmap(bmp, bmp.Width, bmp.Height);
                        //Image newTiff = Converter.ConvertToBitonal(new Bitmap(bmp, bmp.Width, bmp.Height));
                        using (Image newTiff = Converter.ConvertToBitonal(new Bitmap(bmp, bmp.Width, bmp.Height)))
                        {

                            EncoderParameters SaveEncoderParameters = new EncoderParameters(2);
                            System.Drawing.Imaging.Encoder SaveEncoder = System.Drawing.Imaging.Encoder.SaveFlag;
                            EncoderParameter CompressEncodeParam = new EncoderParameter(SaveEncoder, (long)(EncoderValue.MultiFrame));
                            SaveEncoderParameters.Param[0] = CompressEncodeParam;
                            SaveEncoder = System.Drawing.Imaging.Encoder.Compression;
                            CompressEncodeParam = new EncoderParameter(SaveEncoder, (long)(EncoderValue.CompressionCCITT4));
                            SaveEncoderParameters.Param[1] = CompressEncodeParam;


                            System.Drawing.Imaging.Encoder AddEncoder = System.Drawing.Imaging.Encoder.SaveFlag;
                            EncoderParameter AddEncodeParam = new EncoderParameter(AddEncoder, (long)EncoderValue.FrameDimensionPage);
                            System.Drawing.Imaging.Encoder AddCompressionEncoder = System.Drawing.Imaging.Encoder.Compression;
                            EncoderParameter AddCompressionEncodeParam = new EncoderParameter(AddCompressionEncoder, (long)EncoderValue.CompressionCCITT4);
                            EncoderParameters AddEncoderParams = new EncoderParameters(2);

                            AddEncoderParams.Param[0] = AddEncodeParam;
                            AddEncoderParams.Param[1] = AddCompressionEncodeParam;

                            ArrayList swap = new ArrayList();
                            for (int i = 0; i < frameCount; i++)
                            {
                                swap.Add(i);
                            }

                            swap.Insert(0, swap[swapPage]);
                            swap.RemoveAt(swapPage + 1);

                            int pageCount = 0;
                            for (; pageCount < frameCount; pageCount++)
                            {
                                switch (pageCount)
                                {
                                    case 0:

                                        newTiff.Save(_sDestinatinPath, imageCodecInfo, SaveEncoderParameters);
                                        break;
                                    default:

                                        bmp.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, Convert.ToInt32(swap[pageCount]));

                                        try
                                        {
                                            // Convert image to bitonal for saving to file
                                            using (Bitmap newPage = Converter.ConvertToBitonal(new Bitmap(bmp, bmp.Width, bmp.Height)))//TRK
                                            {
                                                newTiff.SaveAdd(newPage, AddEncoderParams);
                                                newPage.Dispose();
                                                GC.Collect();
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            throw ex;
                                        }
                                        finally
                                        {

                                            //GC.WaitForPendingFinalizers();
                                        }
                                        break;
                                }

                                ////Background
                                //objCommonDeclarations.ShowMessage("Reordering Images " + Convert.ToString(pageCount + 1) + " of " + Convert.ToString(frameCount), "INFO", lblShowMessage);
                                //Application.DoEvents();

                                GC.Collect();
                                //GC.WaitForPendingFinalizers();
                            }

                            //////Background
                            //objCommonDeclarations.ShowMessage("Reordering Images " + Convert.ToString(pageCount + 1) + " of " + Convert.ToString(frameCount), "INFO", lblShowMessage);
                            //Application.DoEvents();

                            //////Background
                            //objCommonDeclarations.ShowMessage(string.Empty, "INFO", lblShowMessage);
                            //Application.DoEvents();

                            AddEncoderParams.Param[0] = new EncoderParameter(AddEncoder, (long)EncoderValue.Flush);
                            newTiff.SaveAdd(AddEncoderParams);

                            newTiff.Dispose();
                            GC.Collect();
                        }

                        bmp.Dispose();
                        fs.Dispose();
                        GC.Collect();

                    }
                }
            }
            catch (Exception ex)
            {
                objCommonDeclarations.ShowMessage(ex.Message.ToString(), "ERROR", lblShowMessage);
                //Background
                //return ex.Message.ToString();
                objCommonDeclarations.WriteLog(ex.Message.ToString(), false, false);
            }

            //Background
            //return string.Empty;
        }


/// 
/// To Merge the Single Page Tifs in folder to a Multipage Tiff Image
/// 
/// This denotes Multipage Image Full Path/// This denotes Single Page Tif Image List/// After Merge where need to store the New Merged Tif Filesprivate bool MergeTifImages(String sMultiPageTif, List lstSingleTifs, String sDestinationPath)
        {
            String SinglePageTif = String.Empty;
            bool sflg = true;
            try
            {
                // To Check Destination Path is Exist or Not, if not create the path and folder structure
                if (!Directory.Exists(@sDestinationPath)) Directory.CreateDirectory(@sDestinationPath);
                //Open file in read only mode 
                using (FileStream fs = new FileStream(@sMultiPageTif, FileMode.Open, FileAccess.Read))
                {
                    //To Form the Destination Tiff File Name
                    String _sDestinatinPath = Path.Combine(@sDestinationPath, Path.GetFileName(@sMultiPageTif));
                    //To Create the Image Codec Info                   
                    ImageCodecInfo imageCodecInfo = GetEncoderInfo("image/tiff");

                    //To Create the New bmp Image from the existing Multipage Tif
                    //Image bmp = Image.FromStream(fs);
                    Image newTiff = null;
                    //To Select the Encoder and Compresstion formates for the Tif Images
                    EncoderParameters SaveEncoderParameters = new EncoderParameters(2);
                    System.Drawing.Imaging.Encoder SaveEncoder = System.Drawing.Imaging.Encoder.SaveFlag;
                    EncoderParameter CompressEncodeParam = new EncoderParameter(SaveEncoder, (long)(EncoderValue.MultiFrame));
                    SaveEncoderParameters.Param[0] = CompressEncodeParam;
                    SaveEncoder = System.Drawing.Imaging.Encoder.Compression;
                    CompressEncodeParam = new EncoderParameter(SaveEncoder, (long)(EncoderValue.CompressionCCITT4));
                    SaveEncoderParameters.Param[1] = CompressEncodeParam;

                    System.Drawing.Imaging.Encoder AddEncoder = System.Drawing.Imaging.Encoder.SaveFlag;
                    EncoderParameter AddEncodeParam = new EncoderParameter(AddEncoder, (long)EncoderValue.FrameDimensionPage);
                    System.Drawing.Imaging.Encoder AddCompressionEncoder = System.Drawing.Imaging.Encoder.Compression;
                    EncoderParameter AddCompressionEncodeParam = new EncoderParameter(AddCompressionEncoder, (long)EncoderValue.CompressionCCITT4);
                    EncoderParameters AddEncoderParams = new EncoderParameters(2);

                    AddEncoderParams.Param[0] = AddEncodeParam;
                    AddEncoderParams.Param[1] = AddCompressionEncodeParam;

                    using (Image bmp = Image.FromStream(fs))
                    {
                        //Get the Page Count, i.e Frame Count
                        int frameCount = bmp.GetFrameCount(FrameDimension.Page);

                        //To Create Temp New Tiff                 
                        newTiff = Converter.ConvertToBitonal(new Bitmap(bmp, bmp.Width, bmp.Height));

                        // To Save the Multipage Tiff
                        newTiff.Save(_sDestinatinPath, imageCodecInfo, SaveEncoderParameters);
                        Application.DoEvents();
                        //To Update frame by frame to the multipage
                        int pageCount = 0;
                        for (; pageCount < frameCount; pageCount++)
                        {
                            switch (pageCount)
                            {
                                case 0:

                                    newTiff.Save(_sDestinatinPath, imageCodecInfo, SaveEncoderParameters);
                                    break;
                                default:
                                    bmp.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, pageCount);
                                    // Convert image to bitonal for saving to file

                                    using (Bitmap newPage = Converter.ConvertToBitonal(new Bitmap(bmp, bmp.Width, bmp.Height)))
                                    {
                                        //Bitmap newPage = Converter.ConvertToBitonal(new Bitmap(bmp, bmp.Width, bmp.Height));
                                        newTiff.SaveAdd(newPage, AddEncoderParams);
                                    }

                                    break;
                            }
                            Application.DoEvents();
                        }
                    }

                    // To Merage the Single Page Tif Image to Multipage Tif Image form Single Tifs List
                    foreach (String SingleTif in lstSingleTifs)
                    {
                        try
                        {
                            CommonDeclarations.WriteLog("Single Page TIF: " + Path.GetFileName(SingleTif), false, false);
                            using (FileStream fs1 = new FileStream(@SingleTif, FileMode.Open, FileAccess.Read))
                            {
                                //To over come Out of memory.
                                //Image Singlebmp = Image.FromStream(fs1);
                                using (Image Singlebmp = Image.FromStream(fs1))
                                {
                                    Application.DoEvents();
                                    int frameCount = Singlebmp.GetFrameCount(FrameDimension.Page);
                                    //To Check the Given Single Page tif is having More than One Frame
                                    if (frameCount > 1)
                                    {
                                        CommonDeclarations.WriteLog("The Selected Single Page TIF Having More Then One Page. Page Count: " + frameCount, false, false);
                                        //This works if Multipage exist 
                                        int pageCount = 0;
                                        for (; pageCount < frameCount; pageCount++)
                                        {
                                            Singlebmp.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, pageCount);
                                            // Convert image to bitonal for saving to file
                                            Bitmap SinglePageTiff = Converter.ConvertToBitonal(new Bitmap(Singlebmp, Singlebmp.Width, Singlebmp.Height));
                                            newTiff.SaveAdd(SinglePageTiff, AddEncoderParams);
                                            //  break;
                                        }
                                    }
                                    else
                                    {
                                        //This will works while Single Frame of Single Tiff Image
                                        using (Bitmap tempBmp = new Bitmap(Singlebmp, Singlebmp.Width, Singlebmp.Height))
                                        {
                                            using (Bitmap SinglePageTifs = Converter.ConvertToBitonal(tempBmp))
                                            {
                                                //Bitmap SinglePageTifs = Converter.ConvertToBitonal(new Bitmap(Singlebmp, Singlebmp.Width, Singlebmp.Height));
                                                Application.DoEvents();
                                                newTiff.SaveAdd(SinglePageTifs, AddEncoderParams);

                                                SinglePageTifs.Dispose();
                                                GC.Collect();
                                            }
                                            tempBmp.Dispose();
                                            GC.Collect();
                                        }
                                    }

                                    Singlebmp.Dispose();
                                    GC.Collect();
                                }

                                fs1.Close();
                                fs1.Dispose();
                                GC.Collect();
                            }
                        }
                        catch (Exception ex)
                        {
                            CommonDeclarations.WriteLog(ex.Message.ToString(), false, false);
                            sflg = false;
                        }

                    }
                    //Save the New Tiff and Encode the Tiff  Images
                    AddEncoderParams.Param[0] = new EncoderParameter(AddEncoder, (long)EncoderValue.Flush);
                    newTiff.SaveAdd(AddEncoderParams);
                    newTiff.Dispose();
                    GC.Collect();

                }
            }
            catch (Exception ex)
            {
                //CommonDeclarations.ShowMessage(ex.Message.ToString(), "ERROR", lblShowMessage);
                CommonDeclarations.WriteLog("Some Error in MergeTifImages, Error: " + ex.Message.ToString(), false, false);
                sflg = false;
            }
            return sflg;
        }

        /// 
        /// To Get the ImageCodecInfo. For Example *.TIF,*.TIFF or *.JPG,*.BMP,*.GIF
        /// 
        /// This denotes MimeType. Kind of Imgage to Get the Image Files Type/// 
        private static ImageCodecInfo GetEncoderInfo(String mimeType)
        {
            int j;
            try
            {
                ImageCodecInfo[] encoders;
                encoders = ImageCodecInfo.GetImageEncoders();
                for (j = 0; j < encoders.Length; ++j)
                {
                    if (encoders[j].MimeType == mimeType)
                        return encoders[j];
                }
                return null;
            }
            catch (Exception ex)
            {
                CommonDeclarations.WriteLog("Some Error in ImageCodecInfo,Error:"+ ex.Message.ToString(), false, false);
                return null;
            }
        }

After running the application I looked how much memory the Proces use. Object.Dispose(); doesn't release the memory occuped by the object immediately. It shows constant memory increase when seeing. After using GC.Collect(); if frees the memory. Afterwares no OutOfMemory Exception thrown. Here we added each image to a panel(pnlThumbnail) pnlThumbnail.Controls.Add(picBoxArray[iThumbCurrPage]); This occupies more memory. We have to clear that in the following way.
//Clear the picture box stored in thumbnailArray
                if (picBoxArray != null)
                {
                    foreach (PictureBox tempPb in picBoxArray)
                    {
                        if (tempPb.Image != null)
                        {
                            tempPb.Image.Dispose();
                            tempPb.Image = null;

                            GC.Collect();
                        }
                    }
                    picBoxArray = null;
                }

                for (int clearPictureBox = 0; clearPictureBox < pnlThumbnail.Controls.Count; clearPictureBox++)
                {

                    PictureBox pb = pnlThumbnail.Controls[clearPictureBox] as PictureBox;

                    pnlThumbnail.Controls.Remove(pb);

                    if (pb.Image != null)
                    {
                        pb.Image.Dispose();
                        pb.Image = null;
                    }
                }
                
                if (pbShowTiffImage.Image != null)
                {
                    pbShowTiffImage.Image = null;
                    pbShowTiffImage.Invalidate();
                    GC.Collect();
                }
                                
                //The above one is better than this
                //foreach (IDisposable control in pnlThumbnail.Controls)
                //    control.Dispose(); 

                pnlThumbnail.Controls.Clear();
                GC.Collect();
REferences Tracking down managed memory leaks (how to find a GC leak) IDisposable.Dispose Method Detecting .NET application memory leaks memory leak with delegates and workflow foundation http://msdn.microsoft.com/en-us/magazine/cc163491.aspx Memory Leak Detection in .NET

No comments: