Scaling Images for Printing

  1. 8 months ago

    James R

    20 Aug 2018 Pre-Release Testers, Xojo Pro Connecticut

    Hi,

    I'm trying to print out images that are connected with a block of text for some database records, and I'm having a hard time scaling the images so they will scale down and print out at a proportional size. The code I have is the following:

    .......Code
        g.DrawString(s, X, Y, 72*6.5)
        Y= Y+ g.StringHeight(s, 72*6.5)+ g.TextHeight
        g.DrawString("A) "+frmMain.txtA.text, X, Y, 72*6.5)
        Y=Y+ g.StringHeight("A) "+frmMain.txtA.text, 72*6.5)
        g.DrawString("B) "+frmMain.txtB.text, X, Y, 72*6.5)
        Y= Y+ g.StringHeight("B) "+frmMain.txtB.text, 72*6.5)
        g.DrawString("C) "+ frmMain.txtC.text, X, Y, 72*6.5)
        Y= Y+ g.StringHeight("C) "+frmMain.txtC.text, 72*6.5)
        g.DrawString("D) "+ frmMain.txtD.text, X, Y, 72*6.5)
        Y= Y+ g.StringHeight("D) "+frmMain.txtD.Text, 72*6.5)+ g.TextHeight
        
        If frmMain.txtImage.Text <> "" Then
    
     g.DrawPicture pic,X,Y,90,60,0,0, pic.width, pic.height
         
          Y = Y + pic.Height  + g.TextHeight + g.TextHeight + g.TextHeight
        End If

    The problem is with this line of code:

    g.DrawPicture pic,X,Y,90,60,0,0, pic.width, pic.height

    The problem with the code is that it simply scales the image to 90, 60. So if the customer's image is not set up to a 6 x 9 format it will appear distorted. The customer's images can be landscape or portrait and all different sizes. I want the images to print out smaller so they fit well with the text, but also look proportionally correct.

    How can I write the code so that the pictures print out smaller than the original but proportionally in about the size of 90 x 60? Any help would be appreciated.

    My guess is that you didn't convert the code completely.

    If this works for you:

    g.DrawPicture pic,X,Y,90,60,0,0, pic.width, pic.height

    shouldn't this:

    newPic.graphics.DrawPicture(pic, X, Y, newPic.width, newPic.height, 0, 0, pic.width, pic.height)

    be something like:

    g.DrawPicture(pic, X, Y, newPic.width, newPic.height, 0, 0, pic.width, pic.height)

    Sorry if I'm wrong, I haven't learn graphics yet.

  2. Tim P

    20 Aug 2018 Pre-Release Testers Austin, TX

    Here is a "Resize Image to Fit" method that Sam wrote.
    https://forum.xojo.com/12211-proportionally-resizing-a-picture/p1#p91015

  3. Bob K

    20 Aug 2018 Pre-Release Testers, Xojo Pro Kansas City

    You'll need to figure out the smallest scale that will get either the width to 90 or the height to 60 and then use that same scale on the final dimension that needs to be modified.

    The problem with what you have now is it will ALWAYS be 90 x 60.

  4. James R

    20 Aug 2018 Pre-Release Testers, Xojo Pro Connecticut

    I must be doing something wrong here. This is the modified code.

    Dim maxWidth As Integer
          Dim maxHeight As Integer
          Dim ratio As Double = Min(maxHeight/pic.height, maxWidth/pic.width)
          
          ' Create a new picture to return
          Dim newPic As New Picture( pic.width * ratio, pic.height * ratio )
          
          ' Draw picture in the new size
          newPic.graphics.DrawPicture( pic, X, Y, newPic.width, newPic.height, 0, 0, pic.width, pic.height)
          
          Y = Y + newPic.Height + g.TextHeight + g.TextHeight + g.TextHeight

    I get an Out Of Bounds Exception on:

    newPic.graphics.DrawPicture( pic, X, Y, newPic.width, newPic.height, 0, 0, pic.width, pic.height)

    @Bob K You'll need to figure out the smallest scale that will get either the width to 90 or the height to 60 and then use that same scale on the final dimension that needs to be modified.

    The problem with what you have now is it will ALWAYS be 90 x 60.

    I know Bob, but I don't know what size the customer's images are in. They can be all sorts of sizes. I didn't want to have them size their images to the correct format, but have the code do it for them.

  5. Paul R

    20 Aug 2018 Pre-Release Testers, Xojo Pro Kirkland, WA

    I'm guessing ratio = 0. Are you sure you're assigning something positive to maxHeight and/or maxWidth?

  6. James R

    20 Aug 2018 Pre-Release Testers, Xojo Pro Connecticut

    @Paul R I'm guessing ratio = 0. Are you sure you're assigning something positive to maxHeight and/or maxWidth?

    No I'm not. I'm just using the code Tim forwarded to me and trying to apply it to my project. I think it reports that newPic=Nil.

  7. Greg O

    20 Aug 2018 Xojo Inc

    Right. With maxWidth and maxHeight set to zero, you get a Nil pic. Try setting those to 90 and 60 respectively when you initialize the properties.

  8. Alberto D

    20 Aug 2018 Pre-Release Testers
    Edited 8 months ago

    What is the value of maxWidth and maxHeigth? I see that missing from:

    Dim maxWidth As Integer
    Dim maxHeight As Integer
    Dim ratio As Double = Min(maxHeight/pic.height, maxWidth/pic.width)

    Could that be the problem?

  9. Emile S

    21 Aug 2018 Europe (France, Strasbourg)

    @James R I get an Out Of Bounds Exception on:

    Not only 0 is a bad value, but yu can exceed the size (width/height) or a Picrure on Xojo (32768 ?). The error message as above is incomplete.

    I just get that … yesterday: OutOfBounds with a too large value !

  10. James R

    21 Aug 2018 Pre-Release Testers, Xojo Pro Connecticut
    Edited 8 months ago

    I changed the code to enter in a maxWidth and maxHeight of 90 and 60 as Greg suggested. It now runs without throwing the OutOfBounds Exception and the spacing looks correct, but it does not actually print the image. Where the image goes is blank. Here is the modified code:

    ...Code
        g.DrawString(s, X, Y, 72*6.5)
        Y= Y+ g.StringHeight(s, 72*6.5)+ g.TextHeight
        g.DrawString("A) "+frmMain.txtA.text, X, Y, 72*6.5)
        Y=Y+ g.StringHeight("A) "+frmMain.txtA.Text, 72*6.5)
        g.DrawString("B) "+frmMain.txtB.text, X, Y, 72*6.5)
        Y= Y+ g.StringHeight("B) "+frmMain.txtB.text, 72*6.5)
        g.DrawString(javascript:ETConversation.quote("reply");void(0)"C) "+ frmMain.txtC.text, X, Y, 72*6.5)
        Y= Y+ g.StringHeight("C) "+frmMain.txtC.text, 72*6.5)
        g.DrawString("D) "+ frmMain.txtD.text, X, Y, 72*6.5)
        Y= Y+ g.StringHeight("D) "+frmMain.txtD.Text, 72*6.5)+ g.TextHeight
        
        If frmMain.txtImage.Text <> "" Then
          
          Dim maxWidth As Integer
          Dim maxHeight As Integer
          
          maxHeight=60
          maxWidth=90
          
          Dim ratio As Double = Min( maxHeight/pic.height, maxWidth/pic.width)
          
          ' Create a new picture to return
          Dim newPic As New Picture( pic.width * ratio, pic.height * ratio)
          
          ' Draw picture in the new size
          newPic.graphics.DrawPicture(pic, X, Y, newPic.width, newPic.height, 0, 0, pic.width, pic.height)
        
          Y = Y + newPic.Height + g.TextHeight + g.TextHeight + g.TextHeight
        End If
    
    frmMain.rs.MoveNext

    I also tried using this line instead of the one above and still no picture is drawn.

    g.DrawPicture newPic, X, Y

    I don't see why it will not print the image,

  11. Jeff T

    21 Aug 2018 Pre-Release Testers Midlands of England, Europe
    Edited 8 months ago

    This works but always gives you 90 x 60?

    g.DrawPicture pic,X,Y,90,60,0,0, pic.width, pic.height

    Taking the resize code apart: (untested)

    //which needs more work, reducing the width or reducing the height?
    dim ratio as double
    
    if    90/pic.width < 60/pic.height then
    // more work to do to get the width down to size
    ratio = 90/pic.width
    else
    //height was the limiting factor
    ratio = 60/pic.height
    end if
    
    //now we know how much to adjust by, apply that to both dimensions
    
    g.DrawPicture pic,X,Y,pic.width * ratio ,pic.height * ratio,0,0, pic.width, pic.height

    (editted)

  12. James R

    21 Aug 2018 Pre-Release Testers, Xojo Pro Connecticut
    Edited 8 months ago

    Hi Jeff, thank you for taking the time to help. Your code prints the image, but it does not scale the images down at all. The pictures print in their original sizes.

  13. Alberto D

    21 Aug 2018 Pre-Release Testers Answer

    My guess is that you didn't convert the code completely.

    If this works for you:

    g.DrawPicture pic,X,Y,90,60,0,0, pic.width, pic.height

    shouldn't this:

    newPic.graphics.DrawPicture(pic, X, Y, newPic.width, newPic.height, 0, 0, pic.width, pic.height)

    be something like:

    g.DrawPicture(pic, X, Y, newPic.width, newPic.height, 0, 0, pic.width, pic.height)

    Sorry if I'm wrong, I haven't learn graphics yet.

  14. Jeff T

    21 Aug 2018 Pre-Release Testers Midlands of England, Europe

    Hmmm... yes, wrong way round.
    revised code here..

    Lets say your original image is 200 x 56

    //90/200 = 0.45
    //60/56 = 1.07

    if    0.45  < 1.07 then  
    ratio = 90/200  //= 0.45
    else
    ratio = 60/56  // = 1.07
    end if
    
    
    //so the drawpicture becomes
    
    
    drawpicture pic, x,y,  200 * ratio, 56 * ratio, 0,0, pic.width, pic.height
    
    //or 
    //drawpicture pic, x,y,  200 * 0.45, 56 * 0.45, 0,0, pic.width, pic.height
    //or
    //drawpicture pic, x,y, 90, 25, 0,0, pic.width, pic.height
  15. Alberto D

    21 Aug 2018 Pre-Release Testers

    James, I think that if this was working for you:

        If frmMain.txtImage.Text <> "" Then
    
     g.DrawPicture pic,X,Y,90,60,0,0, pic.width, pic.height
         
          Y = Y + pic.Height  + g.TextHeight + g.TextHeight + g.TextHeight

    You just need to change it to:

        If frmMain.txtImage.Text <> "" Then
    
         Dim ratio As Double = Min( 60/pic.height, 90/pic.width)
    
     g.DrawPicture pic,X,Y,pic.width * ratio,pic.height * ratio,0,0, pic.width, pic.height
         
          Y = Y + pic.Height  + g.TextHeight + g.TextHeight + g.TextHeight
  16. Tim P

    21 Aug 2018 Pre-Release Testers Austin, TX
    Edited 8 months ago

    You guys do realize that the way the original code is written it's a helper function and you're not supposed to be "converting" it, right? There is no need to modify it.

    This will make pic sized to fit within 90x60 and kept at the same aspect ratio:

    pic = pic.ResizeToFit(90, 60)

    I've used that function exactly as it's written in the post within projects, and have never had an issue with it. You are over-engineering things here.

    For illustration purposes:

    ... Code
    if frmMain.txtImage.Text <> "" then
      pic = pic.ResizeToFit(90, 60)
      Y = Y + pic.Height + (3 * g.TextHeight)
    
    end
    
    ... more code
  17. James R

    21 Aug 2018 Pre-Release Testers, Xojo Pro Connecticut

    @Alberto D;Poo be something like:

    g.DrawPicture(pic, X, Y, newPic.width, newPic.height, 0, 0, pic.width, pic.height)

    Hi Alberto,

    That worked great!! That was the line I was looking for. Thank you so much for taking the time to help.

    I doubled the new image size ratio to 120:180 and that seems to display a good size picture to print. I think I will add a slider so the customer can change the actual printed image size to what they want.

    So this is the code I ended up with that works:

         If frmMain.txtImage.Text <> "" Then
            
            Dim maxWidth As Integer
            Dim maxHeight As Integer
            
            maxHeight=120
            maxWidth=180
            
            Dim ratio As Double = Min( maxHeight/pic.height, maxWidth/pic.width)
            
            ' Create a new picture to return
            Dim newPic As New Picture( pic.width * ratio, pic.height * ratio)
            
            ' Draw picture in the new size
            g.DrawPicture(pic, X, Y, newPic.width, newPic.height, 0, 0, pic.width, pic.height)
            
            Y = Y + newPic.Height + g.TextHeight + g.TextHeight + g.TextHeight
          End If

    @Tim P This will make pic sized to fit within 90x60 and kept at the same aspect ratio:

    pic = pic.ResizeToFit(90, 60)
    I've used that function exactly as it's written in the post within projects, and have never had an issue with it. You are over-engineering things here.

    I'm sure I'm doing that Tim. I use a lot of Methods, but I'm not really sure about Functions. I don't really know how to create them or implement them, so I was just trying to use your code to make it work.

    @Jeff T Hmmm... yes, wrong way round.
    revised code here..

    Thank you so much Jeff. I really appreciate you taking the time to help. I don't know what I would do without all the help you guys give me. Thanks to all again.

  18. Alberto D

    21 Aug 2018 Pre-Release Testers

    James, if you look at my other post you can see that you don't need to Dim a newPic.

    As to what Tim is referring to, I know is hard for us newbies to understand some of the things professional programmers are trying to say to us. In short:

    • you add a new method
    • Method Name: ResizeToFit
    • Parameters: extends p as picture, maxWidth as integer, maxHeight
    • Return Type: Picture
    • Now you enter the following code:
        ' Calculate the scale ratio
        
        dim ratio as Double = min( maxHeight/p.height, maxWidth/p.width)
        
        ' Create a new picture to return
        dim newPic as new Picture( p.width * ratio, p.height * ratio )
        
        ' Draw picture in the new size
        newPic.graphics.DrawPicture( p, 0, 0, newPic.width, newPic.height, 0, 0, p.width, p.height)
        
        return newPic

    Now you can use pic.ResizeToFit
    Think of it as new option for pic, just like you have pic.width and pic.height but instead of returning a number like those, it returns a picture.

    So, if you have a pic 400x400 and you want it to fit in 120 height and 180 width, you just do:
    pic = pic.ResizeToFit(180,120)
    now if you check pic.width and pic.height you will see that both are 120.

    Note: I can/do mistakes, be careful with everything I post ;)

  19. Alberto D

    22 Aug 2018 Pre-Release Testers

    Of course I made a mistake (maybe more):

    Parameters: extends p as picture, maxWidth as integer, maxHeight

    should be:

    Parameters: extends p as picture, maxWidth as integer, maxHeight as integer

or Sign Up to reply!