locked
A Graphics object cannot be created from an image that has an indexed pixel format. RRS feed

  • 問題

  • I have used this Overlay function with tif files I create. However, when I download a "real" tif image from our repository, I get the subject line error.

    1. What is an indexed pixel format?

    2. Can I convert it in my code to an acceptible format? or use a different object to accomplish the text overlay header?

            public void Overlay(string fn, string accn)
            {
                string dir = Path.GetDirectoryName(fn);
                string temp = Path.Combine(dir, "temp.tif");
                File.Delete(temp);
                File.Move(fn, temp);
                string msg = "Accn:" + accn;
                FileStream fs = File.Open(temp, FileMode.Open, FileAccess.Read);
                Bitmap bm = (Bitmap)Bitmap.FromStream(fs);
                Graphics graphics = Graphics.FromImage(bm);
                SolidBrush brush = new SolidBrush(Color.Black);
                Font font = new Font("Courier New", 20, FontStyle.Bold);
                Rectangle rect = new Rectangle(8, 8, 300, 80);
                graphics.DrawString(msg, font, brush, rect);
                fs.Close();            
                bm.Save(fn);            
            }
    Thanks,

    Jon Jacobs
    Not sent from my iphone, because I don't have one.

    2013年4月20日 上午 01:55

解答

  • An indexed image is an image with a palette.  GDI+ doesn't support drawing to indexed images.  Draw your indexed image on a non-indexed image and then draw your text on the non-indexed image:

          Bitmap newBitmap = new Bitmap(bm.Width, bm.Height);
          
    Graphics graphics = Graphics.FromImage(newBitmap);
          graphics.DrawImage(bm, 0, 0);

    2013年4月20日 下午 06:47
  • Hi.

    When a "normal" pixel format works somewhat like this: 

    RGB RGB RGB RGB RGB
    
    RGB RGB RGB RGB RGB
    
    RGB RGB RGB RGB RGB
    
    RGB RGB RGB RGB RGB
    
    RGB RGB RGB RGB RGB


    An indexed one defines a palette of colors as an array, and then references those indexes instead of defining a color at each pixel co-ordinate, effectively saving memory and disk space.

    P[] = { RGB, RGB, RGB, RGB, RGB }
    
    P[0] P[3] P[0] P[2] P[1]
    
    P[1] P[2] P[4] P[1] P[0]
    
    P[2] P[3] P[1] P[2] P[2]
    
    P[0] P[3] P[2] P[3] P[1]
    
    P[4] P[3] P[0] P[2] P[1]

    About your problem, I'm guessing that the exception gets thrown at this line: 

    Graphics graphics = Graphics.FromImage(bm);

    According to the documentation of Graphics.FromImage(the remarks section), you can save the indexed image as another format by using the Save(String, ImageFormat) method and then retrieve a Graphics object for the new image.

    So go ahead and try that! Convert the indexed TIFF to, say, PNG, and then call Graphics.FromImage on the converted image.


    Teo Selenius

    • 已標示為解答 Jon Q Jacobs 2013年4月22日 下午 01:28
    2013年4月20日 上午 05:22

所有回覆

  • Hi.

    When a "normal" pixel format works somewhat like this: 

    RGB RGB RGB RGB RGB
    
    RGB RGB RGB RGB RGB
    
    RGB RGB RGB RGB RGB
    
    RGB RGB RGB RGB RGB
    
    RGB RGB RGB RGB RGB


    An indexed one defines a palette of colors as an array, and then references those indexes instead of defining a color at each pixel co-ordinate, effectively saving memory and disk space.

    P[] = { RGB, RGB, RGB, RGB, RGB }
    
    P[0] P[3] P[0] P[2] P[1]
    
    P[1] P[2] P[4] P[1] P[0]
    
    P[2] P[3] P[1] P[2] P[2]
    
    P[0] P[3] P[2] P[3] P[1]
    
    P[4] P[3] P[0] P[2] P[1]

    About your problem, I'm guessing that the exception gets thrown at this line: 

    Graphics graphics = Graphics.FromImage(bm);

    According to the documentation of Graphics.FromImage(the remarks section), you can save the indexed image as another format by using the Save(String, ImageFormat) method and then retrieve a Graphics object for the new image.

    So go ahead and try that! Convert the indexed TIFF to, say, PNG, and then call Graphics.FromImage on the converted image.


    Teo Selenius

    • 已標示為解答 Jon Q Jacobs 2013年4月22日 下午 01:28
    2013年4月20日 上午 05:22
  • An indexed image is an image with a palette.  GDI+ doesn't support drawing to indexed images.  Draw your indexed image on a non-indexed image and then draw your text on the non-indexed image:

          Bitmap newBitmap = new Bitmap(bm.Width, bm.Height);
          
    Graphics graphics = Graphics.FromImage(newBitmap);
          graphics.DrawImage(bm, 0, 0);

    2013年4月20日 下午 06:47
  • Hi, how do I do this part:  Convert the indexed TIFF to, say, PNG, and then call Graphics.FromImage on the converted image.

    Thank you

    2020年1月6日 下午 05:11
  • Hi, how do I do this part:  Convert the indexed TIFF to, say, PNG, and then call Graphics.FromImage on the converted image.

    Thank you

    Based in John Wien's example above, you dont need to declare anything again with .fromimage,  you have the graphics surface there already with the original tiff drawn on it. You can just continue to draw on that graphic. If that is what you want to do.

    Here is an example of saving the original tif as png similar to what John showed. 

    Then the example opens the saved png and draws "tommytwotrain" on it with graphics from image.

    You could also draw on the same g after saving it etc.

    PS You should try to start a new thread with your own question instead of adding to an old thread.

    :)

    public partial class Form3 : Form { private Bitmap MemoryBmp; public Form3() { InitializeComponent(); } private void Form3_Load(object sender, EventArgs e) { { // draw a new copy of the tif and save as png using (var tifBmp = new Bitmap(@"C:\bitmaps\drg mak cover front 600.tif")) using (Graphics g = Graphics.FromImage(tifBmp) ) {

    g.DrawImage(tifBmp, 0, 0, bitmap.Width, bitmap.Height); //g.DrawImage(tifBmp, 0, 0); tifBmp.Save(@"c:\test\tifBmp1.png"); } // open the saved png file, make a graphics surface, // draw on the graphics, and then show in the form MemoryBmp = new Bitmap(@"c:\test\tifBmp1.png"); using (Graphics g = Graphics.FromImage(MemoryBmp)) { g.DrawString("tommytwotrain", new Font("arial", 18, FontStyle.Bold), Brushes.Lime, 10, 600); this.BackgroundImage = MemoryBmp; this.BackgroundImageLayout = ImageLayout.Zoom; } } } }



    • 已編輯 tommytwotrain 2020年1月6日 下午 11:18 add size drawimage
    2020年1月6日 下午 06:56
  • [

    [HttpPost]
            public ActionResult Index(string text, int text1)
          {
                
                DirectoryInfo dir = new DirectoryInfo(@"C:\Users\name\Desktop\images");
                FileInfo[] files = dir.GetFiles();
                string value = text;
                int value1 = text1;
                //string file = Path.GetFileNameWithoutExtension(postedFile.FileName) + ".png";
                foreach (FileInfo file in files)
                {
                    // string newfile = Path.GetFileNameWithoutExtension(file.FileName) + ".png";
                    //if (postedFile != null)
                    //{
                    // Load document
                 
                    using (Bitmap bitmap = new Bitmap(file.FullName))
                    {
                        Bitmap tempBitmap = new Bitmap(bitmap.Width, bitmap.Height);
                        using (Graphics graphics = Graphics.FromImage(tempBitmap))
                        {
                            graphics.DrawImage(bitmap, 0, 0);
                           // graphics.DrawLine();
                            Brush brush = new SolidBrush(Color.Black);
                            Font font = new Font("Arial", 10, FontStyle.Italic, GraphicsUnit.Pixel);
                            SizeF textSize = new SizeF();
                            textSize = graphics.MeasureString(value, font);
                            Point position = new Point(bitmap.Width - ((int)textSize.Width + 30), bitmap.Height - ((int)textSize.Height + 10));
                            graphics.DrawString((value + value1++), font, brush, position);
                            using (MemoryStream mStream = new MemoryStream())
                            {
                                mStream.Position = 0;
                                tempBitmap.Save(mStream, ImageFormat.Tiff);
                                string _path = Path.Combine(Server.MapPath("~/UploadedFolders"), file.Name);
                                tempBitmap.Save(_path);
                                
                            }
                        }
                    }
    
    
    
                }
           
                return View();
            }
    

    the issue here is the resulting image is extremaly small. Is there a way to save it as original size.

    or how can i convert everything in that directory to png then edit.

    thank you.




    • 已編輯 HelpIsNice 2020年1月6日 下午 08:06
    2020年1月6日 下午 08:05