none
A generic error occurred in GDI+. RRS feed

  • Question

  • I have a water mark method that use bitmap and is fast in performance (if it matters). when I added Dispose it just delayed the error (processed more files the throw the exception) therefor I feel it is memory allocation issue. Debugging doesn't give me much details. Here is my method, I hope someone can improve it or help me figure out how to delete GDI+ objects after done using, I ran out of ideas and enhancement. If i sacrifice little of the speed that is ok.

       public void waterMark(string euroPrefix, string resultedTifFolders, string waterMarkedTif)
            {
    
                //try
                //{
                using (Bitmap bitmap = new Bitmap(resultedTifFolders))
                {
    
                    using (Brush brush = new SolidBrush(Color.Black))
                    {
                        using (Font font = new Font("Arial", 50, GraphicsUnit.Pixel))
                        {
                            Bitmap tempBitmap = new Bitmap(bitmap.Width, bitmap.Height);
    
                            using (Graphics tempGraphics = Graphics.FromImage(tempBitmap))
                            {
                                SizeF euroPrefixSize = tempGraphics.MeasureString(euroPrefix, font);
    
                                tempBitmap = new Bitmap(bitmap.Width, bitmap.Height + (int)euroPrefixSize.Height + 10);
    
                                tempBitmap.SetResolution(300, 300);
    
                                using (Graphics graphics = Graphics.FromImage(tempBitmap))
                                {
                                    graphics.FillRectangle(Brushes.White, 0, 0, bitmap.Width, bitmap.Height + 100);
    
                                    graphics.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
    
                                    Point position = new Point(bitmap.Width - ((int)euroPrefixSize.Width + 200), bitmap.Height + 5);
    
                                    graphics.DrawString((euroPrefix), font, brush, position);
    
                                    tempBitmap.Save(waterMarkedTif, ImageFormat.Tiff);
    
                                    tempBitmap.Dispose();
    
                                    graphics.Dispose();
                                }
    
                                tempGraphics.Dispose();
                            }
    
                            font.Dispose();
                        }
                       // DeleteObject(brush);
                        brush.Dispose();
                    }
    
                    bitmap.Dispose();
          
                }
                //}
                //catch { };
            }

    If anyone wants to see the stack trace I can provide.

    EDIT: when I kill tasks that use GDI+ , my program process more files(watermark more images). Also, the visual studio app dev .exe use same number of GDI objects all the time 137. 


    • Edited by Guest1993 Friday, February 7, 2020 7:28 PM
    Friday, February 7, 2020 6:30 PM

All replies

  • Try this revision:

    public void waterMark( string euroPrefix, string resultedTifFolders, string waterMarkedTif )
    {
    	using( Brush brush = new SolidBrush( Color.Black ) )
    	{
    		using( Font font = new Font( "Arial", 50, GraphicsUnit.Pixel ) )
    		{
    			using( Bitmap original_bitmap = new Bitmap( resultedTifFolders ) )
    			{
    				SizeF euroPrefixSize;
    
    				using( Graphics tempGraphics = Graphics.FromImage( original_bitmap ) )
    				{
    					euroPrefixSize = tempGraphics.MeasureString( euroPrefix, font );
    				}
    
    				using( Bitmap new_bitmap = new Bitmap( original_bitmap.Width, original_bitmap.Height + (int)euroPrefixSize.Height + 10 ) )
    				{
    					using( Graphics graphics = Graphics.FromImage( new_bitmap ) )
    					{
    						graphics.FillRectangle( Brushes.White, 0, 0, original_bitmap.Width, original_bitmap.Height + 100 );
    
    						graphics.DrawImage( original_bitmap, 0, 0, original_bitmap.Width, original_bitmap.Height );
    
    						Point position = new Point( original_bitmap.Width - ( (int)euroPrefixSize.Width + 200 ), original_bitmap.Height + 5 );
    
    						graphics.DrawString( euroPrefix, font, brush, position );
    					}
    
    					new_bitmap.Save( waterMarkedTif, ImageFormat.Tiff );
    				}
    			}
    		}
    	}
    }
    

    • Marked as answer by Guest1993 Friday, February 7, 2020 8:23 PM
    • Unmarked as answer by Guest1993 Friday, February 7, 2020 9:07 PM
    Friday, February 7, 2020 7:46 PM
  • Thank you for the straight answer I just added this :

     new_bitmap.SetResolution(300, 300);

    Although it works fine if all images are tif colored format if it i s "CCITT Group 4 Fax Encoding" it throws this error:  System.Exception: 'A Graphics object cannot be created from an image that has an indexed pixel format.'

    on this line: 

    using (Graphics tempGraphics = Graphics.FromImage(original_bitmap))

    I have some questions:

    1) Why you didn't use Dispose is it good idea to use?

    2)Do you think I will run into the same issue in the future if I process larger amount of files. This folder size was 2.6gb which is very large.

    3) Is it better to use GraphicMagick Than GDI+

    Also, it is worth mentioning that same method(orginal one) worked fine when I needed to call other methods inside of it (when it was slower in processing)

    Again thank you for shearing your experience.



    • Edited by Guest1993 Friday, February 7, 2020 9:11 PM
    Friday, February 7, 2020 8:23 PM
  • Here is How I solved the LZW vs CCITT4 issue: 

    I hope there is more Optimal way than this but this is what I did for now...

       private static ImageCodecInfo GetEncoderInfo(String mimeType)
            {
                int j;
                ImageCodecInfo[] encoders;
                encoders = ImageCodecInfo.GetImageEncoders();
                for (j = 0; j < encoders.Length; ++j)
                {
                    if (encoders[j].MimeType == mimeType)
                        return encoders[j];
                }
                return null;
            }
            #endregion
    
            #region getCompressionType
            public static int GetCompressionType(Image bitmap)
            {
                int compressionTagIndex = Array.IndexOf(bitmap.PropertyIdList, 0x103);
                PropertyItem compressionTag = bitmap.PropertyItems[compressionTagIndex];
                return BitConverter.ToInt16(compressionTag.Value, 0);
            }
    //the above methods will get compression type
      public void waterMark(string euroPrefix, string resultedTifFolders, string waterMarkedTif)
            {
    
                using (Brush brush = new SolidBrush(Color.Black))
                {
                    using (Font font = new Font("Arial", 50, GraphicsUnit.Pixel))
                    {
                        using (Bitmap original_bitmap = new Bitmap(resultedTifFolders))
                        {
                            int compressionTagIndex = Array.IndexOf(original_bitmap.PropertyIdList, 0x103);
                            PropertyItem compressionTag = original_bitmap.PropertyItems[compressionTagIndex];
                            byte[] com = compressionTag.Value;
                            Encoder encoder = Encoder.Compression;
                            EncoderParameters myEncoderParameters = new EncoderParameters(1);
                            EncoderParameter myEncoderParameter = new EncoderParameter(encoder, (long)EncoderValue.CompressionCCITT4);
                            myEncoderParameters.Param[0] = myEncoderParameter;
                            ImageCodecInfo myImageCodecInfo;
                            myImageCodecInfo = GetEncoderInfo("image/tiff");
                            SizeF euroPrefixSize;
                            if (new[] { 5, 7 }.Contains(com[0]))
    
                            {
                                using (Graphics tempGraphics = Graphics.FromImage(original_bitmap))
                                {
                                    euroPrefixSize = tempGraphics.MeasureString(euroPrefix, font);
                                }
    
                                using (Bitmap new_bitmap = new Bitmap(original_bitmap.Width, original_bitmap.Height + (int)euroPrefixSize.Height + 10))
                                {
                                    new_bitmap.SetResolution(300, 300);
                                    using (Graphics graphics = Graphics.FromImage(new_bitmap))
                                    {
    
                                        graphics.FillRectangle(Brushes.White, 0, 0, original_bitmap.Width, original_bitmap.Height + 100);
    
                                        graphics.DrawImage(original_bitmap, 0, 0, original_bitmap.Width, original_bitmap.Height);
    
                                        Point position = new Point(original_bitmap.Width - ((int)euroPrefixSize.Width + 200), original_bitmap.Height + 5);
    
                                        graphics.DrawString(euroPrefix, font, brush, position);
    
                                        new_bitmap.Save(waterMarkedTif, /*ImageFormat.Tiff,*/ myImageCodecInfo, myEncoderParameters);
    
    
                                        new_bitmap.Save(waterMarkedTif, ImageFormat.Tiff);
                                    }
                                }
                                return;
                            }
                            else
                            {
    
                                Bitmap tempBitmap = new Bitmap(original_bitmap.Width, original_bitmap.Height);
    
                                using (Graphics tempGraphics = Graphics.FromImage(tempBitmap))
                                {
                                    euroPrefixSize = tempGraphics.MeasureString(euroPrefix, font);
                                }
                                tempBitmap = new Bitmap(original_bitmap.Width, original_bitmap.Height + (int)euroPrefixSize.Height + 10);
    
                                tempBitmap.SetResolution(300, 300);
    
                                using (Graphics graphics = Graphics.FromImage(tempBitmap))
                                {
                                    graphics.FillRectangle(Brushes.White, 0, 0, original_bitmap.Width, original_bitmap.Height + 100);
    
                                    graphics.DrawImage(original_bitmap, 0, 0, original_bitmap.Width, original_bitmap.Height);
    
                                    Point position = new Point(original_bitmap.Width - ((int)euroPrefixSize.Width + 200), original_bitmap.Height + 5);
    
                                    graphics.DrawString((euroPrefix), font, brush, position);
    
                                    tempBitmap.Save(waterMarkedTif, ImageFormat.Tiff);
                                }
                            }
                        }
                    }
                }
            }
    //this is the slow down by millsec. I still hope there is a better way. 

    Friday, February 7, 2020 10:05 PM
  • Hi Guest1993,

    Thank you for posting here.

    Because you use a lot of using {} statements, in theory, there is no need to manually call the dispose method.

    using statement (C# Reference)

    But I haven't experienced the other two questions of you, so I can't give you an accurate answer for the time being.

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, February 10, 2020 6:28 AM