Scaling Images for Printing

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]…Code
g.DrawString(s, X, Y, 726.5)
Y= Y+ g.StringHeight(s, 72
6.5)+ g.TextHeight
g.DrawString("A) "+frmMain.txtA.text, X, Y, 726.5)
Y=Y+ g.StringHeight("A) "+frmMain.txtA.text, 72
6.5)
g.DrawString("B) "+frmMain.txtB.text, X, Y, 726.5)
Y= Y+ g.StringHeight("B) "+frmMain.txtB.text, 72
6.5)
g.DrawString("C) "+ frmMain.txtC.text, X, Y, 726.5)
Y= Y+ g.StringHeight("C) "+frmMain.txtC.text, 72
6.5)
g.DrawString("D) "+ frmMain.txtD.text, X, Y, 726.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[/code]

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.

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

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 must be doing something wrong here. This is the modified code.

  [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[/code]

I get an Out Of Bounds Exception on:

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

[quote=401744:@Bob Keeney]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.[/quote]

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.

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.

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.

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?

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 !

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]…Code
g.DrawString(s, X, Y, 726.5)
Y= Y+ g.StringHeight(s, 72
6.5)+ g.TextHeight
g.DrawString("A) "+frmMain.txtA.text, X, Y, 726.5)
Y=Y+ g.StringHeight("A) "+frmMain.txtA.Text, 72
6.5)
g.DrawString("B) "+frmMain.txtB.text, X, Y, 726.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, 726.5)
Y= Y+ g.StringHeight("C) "+frmMain.txtC.text, 72
6.5)
g.DrawString("D) "+ frmMain.txtD.text, X, Y, 726.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[/code]

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,

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)

[code]//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[/code]

(editted)

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.

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.

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

[code]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
[/code]

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

[code] 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

[/code]
You just need to change it to:

[code] 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

[/code]

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

[quote=401897:@Alberto De Poo]be something like:

g.DrawPicture(pic, X, Y, newPic.width, newPic.height, 0, 0, pic.width, pic.height)[/quote]

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:

[code] 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[/code]

[quote=401907:@Tim Parnell]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.

[/quote]

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.

[quote=401901:@Jeff Tullin]Hmmm… yes, wrong way round.
revised code here…[/quote]

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.

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:

[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[/code]

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 :wink:

Of course I made a mistake (maybe more):

should be: