davies has asked for the wisdom of the Perl Monks concerning the following question:

use strict; use warnings; use Tk; use Tk::JPEG; use GD; my $file = $ARGV[0]; my $mw = MainWindow->new(); my $ww = $mw->screenwidth; my $wh = $mw->screenheight; my $imgd = GD::Image->newFromJpeg($file); my ($iw, $ih) = $imgd->getBounds(); my $imtk; if ($iw > $ww or $ih > $wh) { my $wratio = $ww / $iw; my $ratio = $wh / $ih; $ratio = $wratio if $wratio < $ratio; $imgd->copyResampled($imgd, 0, 0, 0, 0, $iw * $ratio, $ih * $ratio +, $iw, $ih); $imtk = $mw->Photo(-data => $imgd->jpeg(), -format => 'jpeg'); } else { $imtk = $mw->Photo(-file => $file, -format => 'jpeg'); } $mw->Label(-image => $imtk)->pack(-expand => 1, -fill => 'both'); $mw->update; MainLoop;

This code works when used on a file smaller than the screen. On a larger file, it fails with the error

couldn't recognize image data at C:/Strawberry/perl/site/lib/Tk/Image. +pm line 21.

Note that this is a reference to the Tk::Image module, not my code. Putting in print statements identifies the failing line as line 20 of my code, i.e. the line before the } else {. I cannot find anything in the Tk or GD docs to indicate what I'm doing wrong.

Regards,

John Davies

Replies are listed 'Best First'.
Re: Tk not recognising GD image
by Discipulus (Canon) on May 07, 2022 at 21:00 UTC
    Hello davies,

    Grepping cpan I contemplate the following...

    if (formatPtr == NULL) { if ((formatObj != NULL) && !matched) { Tcl_AppendResult(interp, "image format \"", formatString, "\" is not supported", (char *) NULL); } else { Tcl_AppendResult(interp, "couldn't recognize image data", (char *) NULL); } return TCL_ERROR; }

    ..but no clues for me.

    Tk and images is always hard to manage, at least for me: search for my posts about the matter to see how many doubts I have..

    Then I always get back to my own code that runs; in this case tk-jepg-custom-rotator published here too.

    I found that a temporary GD image is needed and for Tk part you need an extra pass: MIME::Base64 encoding when you feed -data to Tk::Photo

    Here a working version of your code:

    use strict; use warnings; use Tk; use Tk::JPEG; use GD; use MIME::Base64; # <---------- my $file = $ARGV[0]; my $mw = MainWindow->new(); my $ww = $mw->screenwidth; my $wh = $mw->screenheight; my $imgd = GD::Image->newFromJpeg($file); my ($iw, $ih) = $imgd->getBounds(); print "screen size $ww x $wh and image is $iw x $ih\n"; my $imtk; if ($iw > $ww or $ih > $wh) { my $wratio = $ww / $iw; my $ratio = $wh / $ih; $ratio = $wratio if $wratio < $ratio; # temporary GD image needed (dunno why) my $fullscreen = GD::Image->new($ww,$wh); # <--------------- $fullscreen->copyResampled( $imgd , # source image 0, # X center of the destination +image 0, # Y center of the destination +image 0, # X specify the upper left cor +ner of a rectangle in the source image 0, # Y specify the upper left cor +ner of a rectangle in the source image $ww, # final width $wh, # final height $iw, # source width to copy $ih, # source height to copy ); $imtk = $mw->Photo(-data => MIME::Base64::encode( $fullscreen->jpe +g()) ); # <--------------- } else { $imtk = $mw->Photo(-file => $file, -format => 'jpeg'); } $mw->Label(-image => $imtk)->pack(-expand => 1, -fill => 'both'); $mw->update; MainLoop;

    L*

    PS you can find interesting also my picwoodpecker where image are also rotated based on exiff tags

    PPS

    > I cannot find anything in the Tk or GD docs to indicate what I'm doing wrong.

    In the Tk::Photo documentation I read:

    > -data => string

    > Specifies the contents of the image as a string. The string can contain base64 encoded data or binary data. The format of the string must be one of those for which there is an image file format handler that will accept string data. If both the -data and -file options are specified, the -file option takes precedence.

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

      Your solution works perfectly. Thank you. Reading "The string can contain base64 encoded data or binary data", I could not see what was wrong with my binary data. But I have more interesting things to investigate, now you have helped me.

      Regards,

      John Davies

        But I have more interesting things to investigate

        The error arises in pTk/mTk/generic/tkImgPhoto.c:
        if (formatPtr == NULL) { ... code that might avoid the error by break()ing from the enclosing for() loop } if (formatPtr == NULL) { if ((formatObj != NULL) && !matched) { Tcl_AppendResult(interp, "image format \"", formatString, "\" is not supported", (char *) NULL); } else { Tcl_AppendResult(interp, "couldn't recognize image data", (char *) NULL); } return TCL_ERROR; }
        So ... there are cases where (formatPtr == NULL) is not necessarily an error.
        Perhaps yours should be one such case, but it's currently being undetected ? (I've no idea.)

        Anyway .... just a starting point for you once the "more interesting things" have been investigated ;-)

        Cheers,
        Rob