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. Web Development
  3. ASP.NET
  4. Handling digital camera images with System.Drawing

Handling digital camera images with System.Drawing

Scheduled Pinned Locked Moved ASP.NET
graphicshelpcsharpwinformshardware
7 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.
  • N Offline
    N Offline
    NeverHeardOfMe
    wrote on last edited by
    #1

    I have a web application that allows users to upload images. On upload, the image is saved to disk, then passed to a routine that crops and resizes it to a specified size, using the System.Drawing.Graphics/Imaging classes - all pretty standard stuff, and it works. Usually. Every now and then it fails, and the only error message I can catch is "A generic error occurred in GDI+." Looking at the files uploaded, my deduction (call me Sherlock) is that they are images from digital cameras, and that it may be the embedded photo information within such files that is causing the problem. I note that if I download them (via FTP), then open them in Paint.NET (say) then save them (without making any (apparent) changes), I can then load them via my application without this error occuring. I would be grateful if anyone has any ideas about what I need to do to enable my application to handle these files without error. Thanks...

    L 1 Reply Last reply
    0
    • N NeverHeardOfMe

      I have a web application that allows users to upload images. On upload, the image is saved to disk, then passed to a routine that crops and resizes it to a specified size, using the System.Drawing.Graphics/Imaging classes - all pretty standard stuff, and it works. Usually. Every now and then it fails, and the only error message I can catch is "A generic error occurred in GDI+." Looking at the files uploaded, my deduction (call me Sherlock) is that they are images from digital cameras, and that it may be the embedded photo information within such files that is causing the problem. I note that if I download them (via FTP), then open them in Paint.NET (say) then save them (without making any (apparent) changes), I can then load them via my application without this error occuring. I would be grateful if anyone has any ideas about what I need to do to enable my application to handle these files without error. Thanks...

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

      is it specific files that fail consistently? how about you try it, and if it fails, you try again say 5 seconds later. I have a theory... :)

      Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

      Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

      N 1 Reply Last reply
      0
      • L Luc Pattyn

        is it specific files that fail consistently? how about you try it, and if it fails, you try again say 5 seconds later. I have a theory... :)

        Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

        Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

        N Offline
        N Offline
        NeverHeardOfMe
        wrote on last edited by
        #3

        Well, always JPG files - tried your suggestion, but it didn't work. But it got me thinking, and I did track down the error to the actual line, which was where the modified file was being saved. I had written the code to always save the modified file in the same image format as the original, but decided to try always saving it as a PNG file instead - and this seems to have solved the problem! So, thanks anyway - not 100% sure what for exactly :-) but I've been stuck on this for ages, and now at least I have a working solution!

        L 1 Reply Last reply
        0
        • N NeverHeardOfMe

          Well, always JPG files - tried your suggestion, but it didn't work. But it got me thinking, and I did track down the error to the actual line, which was where the modified file was being saved. I had written the code to always save the modified file in the same image format as the original, but decided to try always saving it as a PNG file instead - and this seems to have solved the problem! So, thanks anyway - not 100% sure what for exactly :-) but I've been stuck on this for ages, and now at least I have a working solution!

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

          Almost everything that goes wrong in Image.Save (and a few more methods) will result in a "General GDI+ error". Since you now decided to provide some of the essential information (but no code) to figure out which of many possible causes is most likely, my best guess is you did not close the input file. Some ways of doing that is by loading an image in a PictureBox (PB.ImageLocation=...), or by loading an image from file (Image.FromFile or Image.FromStream). Using a different output format and file extension is a sure way to avoid those problems, but it also tells me the core problem is still present, resulting in less than optimal behavior of your app as it will keep files open and images in memory much longer than required. You should fix that. You're welcome anyway. :)

          Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

          Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

          N 1 Reply Last reply
          0
          • L Luc Pattyn

            Almost everything that goes wrong in Image.Save (and a few more methods) will result in a "General GDI+ error". Since you now decided to provide some of the essential information (but no code) to figure out which of many possible causes is most likely, my best guess is you did not close the input file. Some ways of doing that is by loading an image in a PictureBox (PB.ImageLocation=...), or by loading an image from file (Image.FromFile or Image.FromStream). Using a different output format and file extension is a sure way to avoid those problems, but it also tells me the core problem is still present, resulting in less than optimal behavior of your app as it will keep files open and images in memory much longer than required. You should fix that. You're welcome anyway. :)

            Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

            Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

            N Offline
            N Offline
            NeverHeardOfMe
            wrote on last edited by
            #5

            OK, thanks... I didn't post code because I hoped a pointer might be enough for me, but... and then I found a working slution. But still, it would be good to know the "proper" way to solve it! If you can stand looking at some VB code, and don't mind giving it the once over, that'd be great - but as I say, I at least have a working solution, so... also, just to clarify: my issue only occurs with jpg files (AFAIK), but I didn't mean to imply that it always happens with these - just that when it does, it's ben with jpg's.

            Public Function ResizeCropImage(ByVal sFilepath As String, ByVal ext As String) As Integer
            ' sFilepath = relative path to file, including it's name; ext = file extension
            ' this file has already been saved from File Upload control via it's usual SaveAs method
            Try
            Dim FullSizeImage As Image
            FullSizeImage = Image.FromFile(HttpContext.Current.Server.MapPath(sFilepath))

                 If (FullSizeImage.Height < 200) Or (FullSizeImage.Width < 200) Then
                    FullSizeImage.Dispose()
                    ' image is too small
                    System.IO.File.Delete(HttpContext.Current.Server.MapPath(sFilepath))
                    Return 0
                 End If
            
                 Dim imf As System.Drawing.Imaging.ImageFormat
                 Select Case ext
                    Case ".gif"
                       imf = System.Drawing.Imaging.ImageFormat.Gif
                    Case ".png"
                       imf = System.Drawing.Imaging.ImageFormat.Png
                    Case Else '".jpg", ".jpeg"
                       imf = System.Drawing.Imaging.ImageFormat.Jpeg
                 End Select
            
            
                 Dim tmp As Bitmap
                 Dim gX As System.Drawing.Graphics
            
                 Dim bTidy As Boolean = True
            
                 If (FullSizeImage.Height = 200) And (FullSizeImage.Width = 200) Then
                    'nothing to do
                    bTidy = False
                 Else
                    ' resize/crop to 200 x 200
                    Select Case FullSizeImage.Height / FullSizeImage.Width
                       Case Is < 1 'landscape image
                          Dim x1 As Integer
                          tmp = New Bitmap(200, 200)
                          tmp.SetResolution(FullSizeImage.HorizontalResolution, FullSizeImage.VerticalResolution)
                          x1 = CInt((FullSizeImage.Width / 2) - (FullSizeImage.Height / 2))
                          gX = System.Drawing.Graphics.FromImage(tmp)
                          gX.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
                          gX.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality
            
            L 1 Reply Last reply
            0
            • N NeverHeardOfMe

              OK, thanks... I didn't post code because I hoped a pointer might be enough for me, but... and then I found a working slution. But still, it would be good to know the "proper" way to solve it! If you can stand looking at some VB code, and don't mind giving it the once over, that'd be great - but as I say, I at least have a working solution, so... also, just to clarify: my issue only occurs with jpg files (AFAIK), but I didn't mean to imply that it always happens with these - just that when it does, it's ben with jpg's.

              Public Function ResizeCropImage(ByVal sFilepath As String, ByVal ext As String) As Integer
              ' sFilepath = relative path to file, including it's name; ext = file extension
              ' this file has already been saved from File Upload control via it's usual SaveAs method
              Try
              Dim FullSizeImage As Image
              FullSizeImage = Image.FromFile(HttpContext.Current.Server.MapPath(sFilepath))

                   If (FullSizeImage.Height < 200) Or (FullSizeImage.Width < 200) Then
                      FullSizeImage.Dispose()
                      ' image is too small
                      System.IO.File.Delete(HttpContext.Current.Server.MapPath(sFilepath))
                      Return 0
                   End If
              
                   Dim imf As System.Drawing.Imaging.ImageFormat
                   Select Case ext
                      Case ".gif"
                         imf = System.Drawing.Imaging.ImageFormat.Gif
                      Case ".png"
                         imf = System.Drawing.Imaging.ImageFormat.Png
                      Case Else '".jpg", ".jpeg"
                         imf = System.Drawing.Imaging.ImageFormat.Jpeg
                   End Select
              
              
                   Dim tmp As Bitmap
                   Dim gX As System.Drawing.Graphics
              
                   Dim bTidy As Boolean = True
              
                   If (FullSizeImage.Height = 200) And (FullSizeImage.Width = 200) Then
                      'nothing to do
                      bTidy = False
                   Else
                      ' resize/crop to 200 x 200
                      Select Case FullSizeImage.Height / FullSizeImage.Width
                         Case Is < 1 'landscape image
                            Dim x1 As Integer
                            tmp = New Bitmap(200, 200)
                            tmp.SetResolution(FullSizeImage.HorizontalResolution, FullSizeImage.VerticalResolution)
                            x1 = CInt((FullSizeImage.Width / 2) - (FullSizeImage.Height / 2))
                            gX = System.Drawing.Graphics.FromImage(tmp)
                            gX.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
                            gX.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality
              
              L Offline
              L Offline
              Luc Pattyn
              wrote on last edited by
              #6

              Hi, I assume this is the code that includes your work-around, not the one that fails occasionally. If you remove the extension modifications, it may fail because, under some conditions, you attempt an Image.Save whereas your original image still is alive since FullSizeImage.Dispose() only occurs later. The fix is to move FullSizeImage.Dispose() up and put it in between gX.DrawImage() and tmp.Save() I have some more comments: 1. your big three-way switch is unnecessary, you could handle portrait/landscape/square images all the same by using something like:

              x1 = CInt((FullSizeImage.Width / 2) - (FullSizeImage.Height / 2))
              y1=-x1
              if x1<0 then x1=0
              if y1<0 then y1=0
              

              2. I don't think you need bTidy at all. 3. I'm puzzled by your call to SetAttributes; it seems very likely you either don't need it at all, or you also need it when the input image is "too small". 4. I would suggest you replace all those magic "200" constants by a single variable, and probably make it a function parameter. Overall I would suggest you look for simpler ways to organize your code; anytime you duplicate statements (or constants) you should try and find a better way, the DRY principle (Don't Repeat Yourself) is pretty universal. :)

              Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

              Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

              N 1 Reply Last reply
              0
              • L Luc Pattyn

                Hi, I assume this is the code that includes your work-around, not the one that fails occasionally. If you remove the extension modifications, it may fail because, under some conditions, you attempt an Image.Save whereas your original image still is alive since FullSizeImage.Dispose() only occurs later. The fix is to move FullSizeImage.Dispose() up and put it in between gX.DrawImage() and tmp.Save() I have some more comments: 1. your big three-way switch is unnecessary, you could handle portrait/landscape/square images all the same by using something like:

                x1 = CInt((FullSizeImage.Width / 2) - (FullSizeImage.Height / 2))
                y1=-x1
                if x1<0 then x1=0
                if y1<0 then y1=0
                

                2. I don't think you need bTidy at all. 3. I'm puzzled by your call to SetAttributes; it seems very likely you either don't need it at all, or you also need it when the input image is "too small". 4. I would suggest you replace all those magic "200" constants by a single variable, and probably make it a function parameter. Overall I would suggest you look for simpler ways to organize your code; anytime you duplicate statements (or constants) you should try and find a better way, the DRY principle (Don't Repeat Yourself) is pretty universal. :)

                Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                N Offline
                N Offline
                NeverHeardOfMe
                wrote on last edited by
                #7

                No, this is the "old" code that fails... 1. yes, I know... 2. probably 3. yes - it was jst something I tried to (maybe) help, but you're right 4. well, yes, but for thsi app that isn't necessary as it will remain fixed thanks..

                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