How to use #shrink in Tk

Hi all,

I read in an image and try to resize it. By reading TkPhotoImage class,
I think method #shrink might be the right one but there is no example on
how to use it. I wonder if anyone out there can gives me a clue

thanks,

###############################################################

obj_img=TkPhotoImage.new(“1.jpg”)

obj_img=obj_img.copy(obj_img, :shrink=>30%)# try to resize to 30%
original size but keep width and height ratio

I get this error if I try to create an image with a .jpg file:

/Users/7stud/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/tk.rb:2049:in
_invoke': couldn't recognize data in image file "/Users/7stud/Desktop/photography/broken.jpg" (RuntimeError) from /Users/7stud/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/tk.rb:2049:in_ip_invoke_core’
from /Users/7stud/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/tk.rb:2085:in
_tk_call_core' from /Users/7stud/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/tk.rb:2113:intk_call_without_enc’
from
/Users/7stud/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/tk/image.rb:80:in
initialize' from /Users/7stud/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/tk/image.rb:191:ininitialize’
from
/Users/7stud/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/tk/image.rb:58:in
block (2 levels) in new' from /Users/7stud/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/tk/image.rb:57:insynchronize’
from
/Users/7stud/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/tk/image.rb:57:in
block in new' from /Users/7stud/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/tk/image.rb:56:ininstance_eval’
from
/Users/7stud/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/tk/image.rb:56:in
new' from 1.rb:3:in

However, I think the :shrink might be a true/false value. In any case,
that is a prime example of ruby’s horrible documentation.

Hi 7stud,

I have two additional lines in my script:

require ‘tk’
require ‘tkextlib/tkimg’

Just a few minutes ago I tried :shrink=>true but I don’t see the image
get
resized.

Here is the method for my image:

def insert_image(v_path)
my_image=TkPhotoImage.new(:file=>v_path)
my_image=my_image.copy(my_image,:shrink=>true)
$label_6_picture.image =my_image
$label_6_picture.place(
‘width’ =>my_image.width,‘height’ =>my_image.height,
)
end#insert_image

Any comments?

The shrink option for TkPhotoImage#copy does have an effect in the code
below. If you create a new image with no size or width, then copy an
image to the new image, the new image will have the size and width
of the copied image, say 300x200. If you then use copy() to subsample
the new image, the subsampled image will expand(?) to fit the 300x200
size…which just leaves you with the same sized image (with the image
quality reduced I assume). But if you specify the shrink option when
you subsample the image, then the subsampled image will be a reduced
sized image.

require ‘tk’
require ‘tkextlib/tkimg’ #*******FOR IMAGES

root = TkRoot.new
root.title = “MyWindow”
root[‘geometry’] = ‘800x500-30+50’

img = TkPhotoImage.new(
:file => ‘/Users/7stud/Desktop/photography/broken.jpg’,
)

new_img = TkPhotoImage.new(
)
puts new_img.width
puts new_img.height

new_img.copy(
img,
:from => [0, 100, 300, 300],
)

puts new_img.width
puts new_img.height

new_img.copy(
img,
:from => [0, 100, 300, 300],
:subsample => [3, 3],
:shrink => true, #Try commenting this out to see the difference
)

puts new_img.width
puts new_img.height

label = TkLabel.new(root)
label.image = new_img
label.place(
‘height’ => new_img.height,
‘width’ => new_img.width,
‘x’ => 10,
‘y’ => 10
)

Tk.mainloop

Any comments?

The best description of the shrink option I could find is the following:

-shrink

Shrinks the destination so that its bottom-right corner
matches the bottom-right corner of the data copied in.
This has no effect if the width and height have been
set for the image

—Practical Programming in Tcl and Tk

I think that means the shrink option just sizes the destination image to
the size of the rectangle being copied.

However, according to the ruby TkPhotoImage.new() docs:

==
If you don’t specify a width and height for an image, the image will
expand or shrink to fit the size of the data stored in the image.

So on the one hand the tcl/tk information says copy()'s shrink option
has not effect if you specify a width and height for the image(and I’ve
tested that and it’s true); but on the other hand the ruby docs say that
if you don’t specify a width and height for an image, the image will
automatically shrink or expand to the size of the data stored in it(and
I’ve tested that and it’s true) and the tcl/tk docs also so that, which
seemingly makes the shrink option superfluous.

In any case, you want the subsample option:

require ‘tk’
require ‘tkextlib/tkimg’ #*******FOR IMAGES

root = TkRoot.new
root.title = “MyWindow”
root[‘geometry’] = ‘800x500-30+50’

img = TkPhotoImage.new(
:file => ‘/Users/7stud/Desktop/photography/broken.jpg’,
)

new_img = TkPhotoImage.new(
)
puts new_img.width
puts new_img.height

new_img.copy(
img,
:from => [0, 100, 300, 300],
:subsample => [3, 3],
#:shrink => true,
)

puts new_img.width
puts new_img.height

label = TkLabel.new(root)
label.image = new_img
label.place(
‘height’ => new_img.height,
‘width’ => new_img.width,
‘x’ => 10,
‘y’ => 10
)

Tk.mainloop

–output:–
0
0
100
67

7stud – wrote in post #1149525:

I edited the following section in one of my previous posts so that it
makes sense:

So on the one hand the tcl/tk information says copy()'s shrink option
has no effect if you specify a width and height for the image(and I’ve
tested that and it’s true); but on the other hand the ruby docs say that
if you don’t specify a width and height for an image, the image will
automatically shrink or expand to the size of the data stored in it(and
I’ve tested that and it’s true)(and the tcl/tk docs also say that), which
seemingly makes the shrink option superfluous.

Hi 7stud,

Thank you very much for the explanations and the sample code.

Based on my testing, I don’t see there is a difference using :shrink or
not.The resize function is really the one called subsample— which is
what I need to reduce the size of image.

Just curious: :subsample=>[3,3] can only take integer… which mean
reduce size to 1/3 on x-axis and 1/3 on y-axis, or
#subsample=>[5,5], reduce size to 1/5 on x-axis and 1/5 on y-axis.

If I add one line as :subsample=>[1.2,1.3] and I find out that Ruby will
complain. It is strange to me that :subsample only take integer

Anyway, the option of :subsample for #copy is kind of misnomer to me.

If I add one line as :subsample=>[1.2,1.3] and I find out that
Ruby will complain. It is strange to me that :subsample only
take integer

Pretend these are four pixels:

oooo

Which pixels would be in the subsample if you chose every 1.2 pixels?

Based on my testing, I don’t see there is a difference using :shrink or
not.

Run the example in my last post. Next, comment out the shrink line
and run it again. Is the output the same? I see this output:

with shrink:
0
0
300
200
100
67

without shrink:
0
0
300
200
300
200

…and without shrink, the image size displayed in the tk window isn’t
smaller.

7stud,

Yes, you are right: the image shrinks as I can see on the screen.

But the problem is that :subsample => [2, 2] means that the image will
be 50% of original size. What if I want an image 80%, 83%,etc… of
original size? What are the code samples for these different size?

Thanks,