Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Multi-Page TIFF support

Multi-Page TIFF support

Scheduled Pinned Locked Moved C#
graphicshelpwinforms
10 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    Jordy Kaiwa Ruiter
    wrote on last edited by
    #1

    So, I gave this a try today for my ImageViewer UserControl (See my articles for more detail on it). And people have requested me to implement Multi-Page TIFF support. Now I have been trying lots of different techniques for it but none of them seem to really work. My UserControl accepts images in 2 different ways. By passing in a FilePath or an Image through properties. Both these properties end up with having storing the image into a Bitmap. Now this Bitmap is used in my Draw methods and if I try to do a SelectActiveFrame() it crashes on me with GDI+ An generic error has occured ExternalException (0x80004005). What I tried to do is creating a new Bitmap of the original and then doing the SelectActiveFrame() and that did not crash. However it did not display either. Here is a sample of my code from my DrawObject class:

    // Gets the total number of frames in the .tiff file
    pages = this.bmp.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);
    currentPage = 0;
    if (pages > 1) { multiPage = true; } else { multiPage = false; }

    public void NextPage()
    {
    try
    {
    if (this.bmp != null)
    {
    int nextPage = this.currentPage + 1;

         if (nextPage <= this.pages)
         {
            Bitmap myImg = new Bitmap(this.bmp);
                                                
            myImg.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, nextPage);
    
            this.bmp.Dispose();
            this.bmp = null;
    
            this.bmp = myImg;
    
            currentPage = nextPage;
         }
      }
    

    }
    catch (Exception ex)
    {
    System.Windows.Forms.MessageBox.Show("ImageViewer error: " + ex.ToString());
    }
    }

    And here is the code that calls the NextPage() function:

    drawing.NextPage();

    pbFull.Refresh();
    UpdatePanels(true);

    And PreviousPage() is exactly the same but with a minus ofcourse. Any help would be much appreciated, I've been staring at it for hours now :(

    L 1 Reply Last reply
    0
    • J Jordy Kaiwa Ruiter

      So, I gave this a try today for my ImageViewer UserControl (See my articles for more detail on it). And people have requested me to implement Multi-Page TIFF support. Now I have been trying lots of different techniques for it but none of them seem to really work. My UserControl accepts images in 2 different ways. By passing in a FilePath or an Image through properties. Both these properties end up with having storing the image into a Bitmap. Now this Bitmap is used in my Draw methods and if I try to do a SelectActiveFrame() it crashes on me with GDI+ An generic error has occured ExternalException (0x80004005). What I tried to do is creating a new Bitmap of the original and then doing the SelectActiveFrame() and that did not crash. However it did not display either. Here is a sample of my code from my DrawObject class:

      // Gets the total number of frames in the .tiff file
      pages = this.bmp.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);
      currentPage = 0;
      if (pages > 1) { multiPage = true; } else { multiPage = false; }

      public void NextPage()
      {
      try
      {
      if (this.bmp != null)
      {
      int nextPage = this.currentPage + 1;

           if (nextPage <= this.pages)
           {
              Bitmap myImg = new Bitmap(this.bmp);
                                                  
              myImg.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, nextPage);
      
              this.bmp.Dispose();
              this.bmp = null;
      
              this.bmp = myImg;
      
              currentPage = nextPage;
           }
        }
      

      }
      catch (Exception ex)
      {
      System.Windows.Forms.MessageBox.Show("ImageViewer error: " + ex.ToString());
      }
      }

      And here is the code that calls the NextPage() function:

      drawing.NextPage();

      pbFull.Refresh();
      UpdatePanels(true);

      And PreviousPage() is exactly the same but with a minus ofcourse. Any help would be much appreciated, I've been staring at it for hours now :(

      L Offline
      L Offline
      Luc Pattyn
      wrote on last edited by
      #2

      Hi, I don't expect "new Bitmap(image)" to return a multi-page image, so what you should try is select the page you want in the original image, then create a new bitmap from it. there are some CodeProjects about multi-page TIFF images, here[^] is one. :)

      Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


      Prolific encyclopedia fixture proof-reader browser patron addict?
      We all depend on the beast below.


      J 1 Reply Last reply
      0
      • L Luc Pattyn

        Hi, I don't expect "new Bitmap(image)" to return a multi-page image, so what you should try is select the page you want in the original image, then create a new bitmap from it. there are some CodeProjects about multi-page TIFF images, here[^] is one. :)

        Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


        Prolific encyclopedia fixture proof-reader browser patron addict?
        We all depend on the beast below.


        J Offline
        J Offline
        Jordy Kaiwa Ruiter
        wrote on last edited by
        #3

        Well that is exactly what I tried to do Originally, and I already looked at the exact multi-page tiff viewer. The problem is, within the viewer when switching to the next page it loads the entire TIFF file again and then makes a Bitmap of it. The problem with this is, my UserControl doesn't neccesarily has to have a file path (Because it can be passed in programmetically aswell). And to store the original TIFF file next to the Bitmap it would mean that I need double the resource for the same image. And once the TIFF file is loaded, there is no way to tell when opening a new image (going to next page for example) if it's A.) The same TIFF file. B.) Actually a Multi-Page TIFF file. What this means is that I have no idea when to Dispose() the original TIFF file which would result in using unneccesary resources. With Multi-page TIFF files this could be ALOT! I also tried Cloning the object but when I do that it gets locked and I get the same GDI+ generic error. Believe me I tried so many things. I was just hoping someone would be like.. You forgot this little line. Thanks for your help tho :)

        modified on Thursday, April 29, 2010 8:03 AM

        L 1 Reply Last reply
        0
        • J Jordy Kaiwa Ruiter

          Well that is exactly what I tried to do Originally, and I already looked at the exact multi-page tiff viewer. The problem is, within the viewer when switching to the next page it loads the entire TIFF file again and then makes a Bitmap of it. The problem with this is, my UserControl doesn't neccesarily has to have a file path (Because it can be passed in programmetically aswell). And to store the original TIFF file next to the Bitmap it would mean that I need double the resource for the same image. And once the TIFF file is loaded, there is no way to tell when opening a new image (going to next page for example) if it's A.) The same TIFF file. B.) Actually a Multi-Page TIFF file. What this means is that I have no idea when to Dispose() the original TIFF file which would result in using unneccesary resources. With Multi-page TIFF files this could be ALOT! I also tried Cloning the object but when I do that it gets locked and I get the same GDI+ generic error. Believe me I tried so many things. I was just hoping someone would be like.. You forgot this little line. Thanks for your help tho :)

          modified on Thursday, April 29, 2010 8:03 AM

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #4

          :confused:

          Jordy "Kaiwa" Ruiter wrote:

          to store the original TIFF file next to the Bitmap it would mean that I need double the resource for the same image

          I don't think so. You load the (multi-page) image once, and keep one (or more) references to it; and you need a bitmap that represents one page, that will cost you a fraction of the multi-page image. You could encapsulate things in a little class (more error handling may be needed):

          class MultiPageImage {
          private Image image;

          public Image Image {
              get {
                  return image;
              }
              set {
                  if (image!=null) image.Dispose;
                  image=value;
              }
          }
          
          public Bitmap GetBitmap() {
              if (image==null) return null;
              return new Bitmap(image);
          }
          
          public Bitmap GetBitmap(int pageNumber) {
              if (image==null) return null;
              image.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, nextPage);
              return new Bitmap(image);
          }
          

          }

          Warning: if you don't actually copy the multi-page image, the current page setting is affecting both this class and the external image users. For perfect encapsulation, one would have to copy the image in the setter property. :)

          Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


          Prolific encyclopedia fixture proof-reader browser patron addict?
          We all depend on the beast below.


          modified on Thursday, April 29, 2010 8:00 AM

          J 1 Reply Last reply
          0
          • L Luc Pattyn

            :confused:

            Jordy "Kaiwa" Ruiter wrote:

            to store the original TIFF file next to the Bitmap it would mean that I need double the resource for the same image

            I don't think so. You load the (multi-page) image once, and keep one (or more) references to it; and you need a bitmap that represents one page, that will cost you a fraction of the multi-page image. You could encapsulate things in a little class (more error handling may be needed):

            class MultiPageImage {
            private Image image;

            public Image Image {
                get {
                    return image;
                }
                set {
                    if (image!=null) image.Dispose;
                    image=value;
                }
            }
            
            public Bitmap GetBitmap() {
                if (image==null) return null;
                return new Bitmap(image);
            }
            
            public Bitmap GetBitmap(int pageNumber) {
                if (image==null) return null;
                image.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, nextPage);
                return new Bitmap(image);
            }
            

            }

            Warning: if you don't actually copy the multi-page image, the current page setting is affecting both this class and the external image users. For perfect encapsulation, one would have to copy the image in the setter property. :)

            Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


            Prolific encyclopedia fixture proof-reader browser patron addict?
            We all depend on the beast below.


            modified on Thursday, April 29, 2010 8:00 AM

            J Offline
            J Offline
            Jordy Kaiwa Ruiter
            wrote on last edited by
            #5

            Damn.. Unbelievable, I just implemented this entire thing. Took like half an hour to find out that it gives me the exact same error. {"A generic error occurred in GDI+."} System.Exception {System.Runtime.InteropServices.ExternalException} Any other ideas? :(

            L 1 Reply Last reply
            0
            • J Jordy Kaiwa Ruiter

              Damn.. Unbelievable, I just implemented this entire thing. Took like half an hour to find out that it gives me the exact same error. {"A generic error occurred in GDI+."} System.Exception {System.Runtime.InteropServices.ExternalException} Any other ideas? :(

              L Offline
              L Offline
              Luc Pattyn
              wrote on last edited by
              #6

              What happened to your other message, the one with:

              Jordy "Kaiwa" Ruiter wrote:

              Woah.. You're right! Why didn't I think of something like that? Well I'm gonna give it a try then :) I think I've stared at the same code for too long to come up with this! I'll let you know the outcome!

              you are not supposed to remove messages, just keep the thread flow intact, as laid out in the forum guidelines.

              Jordy "Kaiwa" Ruiter wrote:

              the exact same error.

              you should provide more information; where does this occur? under what circumstances? is it always the same frame of the same image that fails? try some others. What is the source of your multiTIFF? Everything that fails inside GDI+ is reported as a "Generic error", making it hard to pinpoint. Is there some other utility that reads and shows all pages correctly? If you suspect an early Dispose() call, just remove them all to see if that helps; this is only a test, NOT a recommendation. :)

              Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


              Prolific encyclopedia fixture proof-reader browser patron addict?
              We all depend on the beast below.


              J 1 Reply Last reply
              0
              • L Luc Pattyn

                What happened to your other message, the one with:

                Jordy "Kaiwa" Ruiter wrote:

                Woah.. You're right! Why didn't I think of something like that? Well I'm gonna give it a try then :) I think I've stared at the same code for too long to come up with this! I'll let you know the outcome!

                you are not supposed to remove messages, just keep the thread flow intact, as laid out in the forum guidelines.

                Jordy "Kaiwa" Ruiter wrote:

                the exact same error.

                you should provide more information; where does this occur? under what circumstances? is it always the same frame of the same image that fails? try some others. What is the source of your multiTIFF? Everything that fails inside GDI+ is reported as a "Generic error", making it hard to pinpoint. Is there some other utility that reads and shows all pages correctly? If you suspect an early Dispose() call, just remove them all to see if that helps; this is only a test, NOT a recommendation. :)

                Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


                Prolific encyclopedia fixture proof-reader browser patron addict?
                We all depend on the beast below.


                J Offline
                J Offline
                Jordy Kaiwa Ruiter
                wrote on last edited by
                #7

                Ah sorry, I figured a double post wasn't really nice either. But anyway. I found a "fix". It seems that if I use Bitmap.FromFile() to open the TIFF file that browsing through pages is possible. And the first post explained exactly the issue, with it being the same error i ment the same function that crashes SelectActiveFrame() I'm going to try and work it out with Bitmap.FromFile() instead of Bitmap.FromStream().

                L 1 Reply Last reply
                0
                • J Jordy Kaiwa Ruiter

                  Ah sorry, I figured a double post wasn't really nice either. But anyway. I found a "fix". It seems that if I use Bitmap.FromFile() to open the TIFF file that browsing through pages is possible. And the first post explained exactly the issue, with it being the same error i ment the same function that crashes SelectActiveFrame() I'm going to try and work it out with Bitmap.FromFile() instead of Bitmap.FromStream().

                  L Offline
                  L Offline
                  Luc Pattyn
                  wrote on last edited by
                  #8

                  IIRC there is a little note in the FromStream() documentation that states one should keep the stream open as long as the image is alive; you now have discovered a very good reason for this unexplained statement. :)

                  Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


                  Prolific encyclopedia fixture proof-reader browser patron addict?
                  We all depend on the beast below.


                  J 1 Reply Last reply
                  0
                  • L Luc Pattyn

                    IIRC there is a little note in the FromStream() documentation that states one should keep the stream open as long as the image is alive; you now have discovered a very good reason for this unexplained statement. :)

                    Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


                    Prolific encyclopedia fixture proof-reader browser patron addict?
                    We all depend on the beast below.


                    J Offline
                    J Offline
                    Jordy Kaiwa Ruiter
                    wrote on last edited by
                    #9

                    That actually makes alot of sense yes. I solved it with a different approach just working out the last issues with dragging and dropping :) Thanks for your help! (A copy of the code will soon be updated in my article if you are interested ;))

                    L 1 Reply Last reply
                    0
                    • J Jordy Kaiwa Ruiter

                      That actually makes alot of sense yes. I solved it with a different approach just working out the last issues with dragging and dropping :) Thanks for your help! (A copy of the code will soon be updated in my article if you are interested ;))

                      L Offline
                      L Offline
                      Luc Pattyn
                      wrote on last edited by
                      #10

                      :thumbsup:

                      Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


                      Prolific encyclopedia fixture proof-reader browser patron addict?
                      We all depend on the beast below.


                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups