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. Visual Basic
  4. Efficiently resizing an image with a pixel resize

Efficiently resizing an image with a pixel resize

Scheduled Pinned Locked Moved Visual Basic
csharpgraphicsadobealgorithmshelp
8 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
    jacobjordan
    wrote on last edited by
    #1

    I know there are functions built into .NET that will resize images, but they don't do what i want. I am making an icon editor, and it needs to be able to resize images with a pixel resize. That is a type of resize where if you zoom in enough you can actually see the individual pixels of the original images, like Paint Shop Pro or Photoshop (or even paint) do. I have make an algorithm to do this, but it is unbelievably slow, and i need to make it do this almost instantly. I am using the Bitmap class and the Bitmap.GetPixle\Bitmap.SetPixle methods. Here is my algorithm:

    Public Shared Function ResizePixles(ByVal image As Bitmap, ByVal factor As Integer) As Bitmap
        On Error Resume Next
        Dim rbmp As New Bitmap(image.Width \* factor, image.Height \* factor)
        For x As Integer = 0 To image.Width - 1
            For y As Integer = 0 To image.Height - 1
                Dim c As Color = image.GetPixel(x, y)
                For x2 As Integer = x \* factor To x \* factor + factor - 1
                    For y2 As Integer = y \* factor To y \* factor + factor - 1
                        rbmp.SetPixel(x2, y2, c)
                    Next
                Next
            Next
        Next
        Return rbmp
    End Function
    

    As you can see, i have 4 For loops in my code, which makes it very slow.

    if (your.Life == lifestyles.Programming) {     your.Cool = true; } else {     your.Cool = false; }

    L 1 Reply Last reply
    0
    • J jacobjordan

      I know there are functions built into .NET that will resize images, but they don't do what i want. I am making an icon editor, and it needs to be able to resize images with a pixel resize. That is a type of resize where if you zoom in enough you can actually see the individual pixels of the original images, like Paint Shop Pro or Photoshop (or even paint) do. I have make an algorithm to do this, but it is unbelievably slow, and i need to make it do this almost instantly. I am using the Bitmap class and the Bitmap.GetPixle\Bitmap.SetPixle methods. Here is my algorithm:

      Public Shared Function ResizePixles(ByVal image As Bitmap, ByVal factor As Integer) As Bitmap
          On Error Resume Next
          Dim rbmp As New Bitmap(image.Width \* factor, image.Height \* factor)
          For x As Integer = 0 To image.Width - 1
              For y As Integer = 0 To image.Height - 1
                  Dim c As Color = image.GetPixel(x, y)
                  For x2 As Integer = x \* factor To x \* factor + factor - 1
                      For y2 As Integer = y \* factor To y \* factor + factor - 1
                          rbmp.SetPixel(x2, y2, c)
                      Next
                  Next
              Next
          Next
          Return rbmp
      End Function
      

      As you can see, i have 4 For loops in my code, which makes it very slow.

      if (your.Life == lifestyles.Programming) {     your.Cool = true; } else {     your.Cool = false; }

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

      Hi, I haven't used this myself as of late, but are you aware Graphics has an InterpolationMode property, which accepts values such as NearestNeighbor, basically just duplicating pixels, not inventing new ones? If you only need to see it scaled up, use it in a Panel's OnPaint; if you really also need the new Bitmap, do Graphics.FromImage(rnmp) then Graphics.DrawImage :)

      Luc Pattyn [Forum Guidelines] [My Articles]


      Voting for dummies? No thanks. X|


      J 1 Reply Last reply
      0
      • L Luc Pattyn

        Hi, I haven't used this myself as of late, but are you aware Graphics has an InterpolationMode property, which accepts values such as NearestNeighbor, basically just duplicating pixels, not inventing new ones? If you only need to see it scaled up, use it in a Panel's OnPaint; if you really also need the new Bitmap, do Graphics.FromImage(rnmp) then Graphics.DrawImage :)

        Luc Pattyn [Forum Guidelines] [My Articles]


        Voting for dummies? No thanks. X|


        J Offline
        J Offline
        jacobjordan
        wrote on last edited by
        #3

        I have tried all the items in the InterpolationMode when resizing an image with a graphics class, but none produced the result i wanted. I will try with the NearestNeighbor item again, and see if i am mistaken. Also, could you (or anyone) please elaborate on what you ment by the OnPaint thing?

        if (your.Life == lifestyles.Programming) {     your.Cool = true; } else {     your.Cool = false; }

        modified on Tuesday, July 15, 2008 6:49 PM

        L 3 Replies Last reply
        0
        • J jacobjordan

          I have tried all the items in the InterpolationMode when resizing an image with a graphics class, but none produced the result i wanted. I will try with the NearestNeighbor item again, and see if i am mistaken. Also, could you (or anyone) please elaborate on what you ment by the OnPaint thing?

          if (your.Life == lifestyles.Programming) {     your.Cool = true; } else {     your.Cool = false; }

          modified on Tuesday, July 15, 2008 6:49 PM

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

          Hi, You did not specify how exactly it does not what you want. Three ideas: 1) I ran a little experiment, and it seems to work fine, with one proviso: the NearestNeighbour does duplicate pixels, but due to the nearest (not the left) source pixel, it will not duplicate the leftmost/topmost pixel a sufficient number of times. So to be exact, you should proceed as follows (I'll explain in one dimension): input width w1, output width wanted w2, scalefactor f=w2/w1 (use reals for scale!) split the output in three regions, with widths wa,wb,wc wa=f/2 <--- represents half an input pixel wb=(w1-1)*f wc=w2-wa-wb <--- represents half an input pixel now duplicate the leftmost pixel of input to wa, duplicate the rightmost pixel of input to wc, finally do the DrawImage scale with nearestneighbour from w1 to wb (i.e. shifted by wa) That should put every single pixel at the right spot. 2) I am pretty sure the complex copying of the edges could be handled by DrawImage itself, provided you give it appropriate parameters. 3) As an approximation you could do a two step approach: - do DrawImage with Normal InterpolationMode for the full size; - do DrawImage with NearestNeighbour InterpolationMode for a size that is half a pixel smaller on all four edges of the output image (don't modify the input sizes!) :)

          Luc Pattyn [Forum Guidelines] [My Articles]


          Voting for dummies? No thanks. X|


          J 1 Reply Last reply
          0
          • L Luc Pattyn

            Hi, You did not specify how exactly it does not what you want. Three ideas: 1) I ran a little experiment, and it seems to work fine, with one proviso: the NearestNeighbour does duplicate pixels, but due to the nearest (not the left) source pixel, it will not duplicate the leftmost/topmost pixel a sufficient number of times. So to be exact, you should proceed as follows (I'll explain in one dimension): input width w1, output width wanted w2, scalefactor f=w2/w1 (use reals for scale!) split the output in three regions, with widths wa,wb,wc wa=f/2 <--- represents half an input pixel wb=(w1-1)*f wc=w2-wa-wb <--- represents half an input pixel now duplicate the leftmost pixel of input to wa, duplicate the rightmost pixel of input to wc, finally do the DrawImage scale with nearestneighbour from w1 to wb (i.e. shifted by wa) That should put every single pixel at the right spot. 2) I am pretty sure the complex copying of the edges could be handled by DrawImage itself, provided you give it appropriate parameters. 3) As an approximation you could do a two step approach: - do DrawImage with Normal InterpolationMode for the full size; - do DrawImage with NearestNeighbour InterpolationMode for a size that is half a pixel smaller on all four edges of the output image (don't modify the input sizes!) :)

            Luc Pattyn [Forum Guidelines] [My Articles]


            Voting for dummies? No thanks. X|


            J Offline
            J Offline
            jacobjordan
            wrote on last edited by
            #5

            Thanks! With your help, i managed to figure it out. A while back, i posted this question on both ProgrammersHeaven.com and DreamInCode.net and i didn't get an answer on either site. Thanks so much! :-D

            if (your.Life == lifestyles.Programming) {     your.Cool = true; } else {     your.Cool = false; }

            L 1 Reply Last reply
            0
            • J jacobjordan

              Thanks! With your help, i managed to figure it out. A while back, i posted this question on both ProgrammersHeaven.com and DreamInCode.net and i didn't get an answer on either site. Thanks so much! :-D

              if (your.Life == lifestyles.Programming) {     your.Cool = true; } else {     your.Cool = false; }

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

              You're welcome. Glad to be of help. :)

              Luc Pattyn [Forum Guidelines] [My Articles]


              Voting for dummies? No thanks. X|


              1 Reply Last reply
              0
              • J jacobjordan

                I have tried all the items in the InterpolationMode when resizing an image with a graphics class, but none produced the result i wanted. I will try with the NearestNeighbor item again, and see if i am mistaken. Also, could you (or anyone) please elaborate on what you ment by the OnPaint thing?

                if (your.Life == lifestyles.Programming) {     your.Cool = true; } else {     your.Cool = false; }

                modified on Tuesday, July 15, 2008 6:49 PM

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

                Hi, I once assembled a short text giving the essentials of painting: there are several steps to draw something so it becomes visible on the screen: 1. decide upon what object you want to draw; it normally is a Control (e.g. a Panel) or a Form itself. I prefer to add a Panel to a Form, then draw on the Panel. 2. create some variables (Rectangle, struct, class, whatever) that hold the parameters of your drawing. For a rectangle that could be top and left coordinate, and width+height, or just a Rectangle. etc. 3. create a Paint handler (either add your own paint handler to the Paint event, or override the OnPaint method) for that Panel, and do all your drawing in there, using the Graphics class and your variables. 4. when you want to change things, modify the variables and call Panel.Invalidate() or one of its overloads (for selective invalidation). 5. If you want to animate things, perform the move (step 4) inside the Tick handler of a Windows.Forms.Timer BTW: if you need to create some objects (Fonts, Pens, Brushes, ...) either keep them alive in class members (hence create them only once); or create them inside the Paint handler and don't forget to call Dispose() on them. :)

                Luc Pattyn [Forum Guidelines] [My Articles]


                Voting for dummies? No thanks. X|


                1 Reply Last reply
                0
                • J jacobjordan

                  I have tried all the items in the InterpolationMode when resizing an image with a graphics class, but none produced the result i wanted. I will try with the NearestNeighbor item again, and see if i am mistaken. Also, could you (or anyone) please elaborate on what you ment by the OnPaint thing?

                  if (your.Life == lifestyles.Programming) {     your.Cool = true; } else {     your.Cool = false; }

                  modified on Tuesday, July 15, 2008 6:49 PM

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

                  Hi, in my latest experiment, I came up with a really simple way of modifying nearestneighbour into copy_from_left/top; it suffices to indicate half a pixel translation, as in this C# code. The source image has size (w,h) and is translated to (x,y) and scaled up by the fraction zoomT/zoomN:

                  Rectangle r=new Rectangle(x, y, w\*zoomT/zoomN, h\*zoomT/zoomN);
                  g.InterpolationMode=InterpolationMode.NearestNeighbor;
                  g.DrawImage(image, r, -0.5f, -0.5f, w, h, GraphicsUnit.Pixel);
                  

                  So instead of using the pixels 0, 1, 2, ... w-1 of the source image, I am actually using the pixels -0.5, 0.5, 1.5, ... w-1.5 which means whenever I need something in some interval (say the first -0.5 to 0.5) it will take the nearest integer, which is the middle of the translated interval, i.e. the left/top of the original interval! Can't get more simple than that. :)

                  Luc Pattyn [Forum Guidelines] [My Articles]


                  Voting for dummies? No thanks. X|


                  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