r1pexpb / timthumb

Automatically exported from code.google.com/p/timthumb
0 stars 0 forks source link

Added ability to "Fit Image" to a defined bounding box #61

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Similar to Photoshop's "Fit Image" script, this code will allow you to
maintain the image's original aspect ratio while fitting inside a defined
bounding box.

The "w" and "h" command line parameters become the width and height that
define the final bounding box to fit to.

I have no idea how to use subversion, so maybe someone can officially add
these snippets as an SVN revision...

after fetching and cleaning other command line parameters in the section
    // get properties

//---- new code
    $fit=preg_replace("/[^0-9]+/", "", get_request("fit", 0));
//---- end new code

after the section
    // Get original width and height
    $width = imagesx($image);
    $height = imagesy($image);

//---- new code

if ($fit)
{
 $final_height = $height * ( $new_width / $width );
  if ($final_height>$new_height)
  {
   $new_width = $width * ( $new_height / $height );         
  }
 else
  $new_height=$final_height;
}

//---- end new code

new command line looks like ...w=100&h=500&fit=1&...

Original issue reported on code.google.com by lbal...@gmail.com on 20 Jan 2010 at 10:17

GoogleCodeExporter commented 9 years ago
this fixes the issue with maintaining the aspect ration within the specified
width/height constraints nicely.

Original comment by ayan...@gmail.com on 26 May 2010 at 6:57

GoogleCodeExporter commented 9 years ago
Wondering if I did this wrong... I got it to work, but maybe a cleaner way?

I added the above code, but the to make it work if I leave out "fit" I had to 
add
some if statements below...

Namely $fit==0 to the original code so that it works... is there a better way 
to do
that, I mean cleaner if statement to work in the new fit image parameter?

    if( $fit==0 && $new_width && !$new_height ) {

        $new_height = $height * ( $new_width / $width );

    } elseif($fit==0 && $new_height && !$new_width) {

        $new_width = $width * ( $new_height / $height );

    } elseif($fit==0 && !$new_width && !$new_height) {

        $new_width = $width;
        $new_height = $height;

    }

Original comment by geetjac...@gmail.com on 28 May 2010 at 10:12

GoogleCodeExporter commented 9 years ago
Can you clarify where the code broke in your implementation?  It works great 
for me,
and for ayanpal (comment #1 above).

Original comment by lbal...@gmail.com on 28 May 2010 at 11:25

GoogleCodeExporter commented 9 years ago
Sorry, my explanation was a bit messy.

Here is the original code.

<<<<<<<<<>>>>>>>>>>>
 // Get original width and height
    $width = imagesx($image);
    $height = imagesy($image);

    // generate new w/h if not provided
    if( $new_width && !$new_height ) {

        $new_height = $height * ( $new_width / $width );

    } elseif($new_height && !$new_width) {

        $new_width = $width * ( $new_height / $height );

    } elseif(!$new_width && !$new_height) {

        $new_width = $width;
        $new_height = $height;

    }

<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>

Then to make the script work right wither fit was set or not i had use the code
below, so I actually got it to work but was curious is there was a cleaner way 
to
write the if else if statement.

New code below that works but seems like its got extra stuff that isn't needed.

<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>

    // Get original width and height
    $width = imagesx($image);
    $height = imagesy($image);

    // generate new w/h if not provided
    if ($fit){
        $final_height = $height * ( $new_width / $width );

    if ($final_height>$new_height) {

         $new_width = $width * ( $new_height / $height );   

     } else 

         $new_height=$final_height;
    }

    if( $fit==0 && $new_width && !$new_height ) {

        $new_height = $height * ( $new_width / $width );

    } elseif($fit==0 && $new_height && !$new_width) {

        $new_width = $width * ( $new_height / $height );

    } elseif($fit==0 && !$new_width && !$new_height) {

        $new_width = $width;
        $new_height = $height;

    }
<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>

Original comment by geetjac...@gmail.com on 28 May 2010 at 11:30

GoogleCodeExporter commented 9 years ago
I think I see what you're talking about:  If $fit==TRUE, $new_width or 
$new_height
are set, but then may be re-set by the non-fit algorithm.  I was only 
interested in
getting the fit algorithm to work, so I suspect I overlooked the bug you found 
by not
testing the script when $fit==0.

You did solve that problem by adding if ($fit==0 .... ) into the non-fit 
algorithm,
and I hear you asking if there is a more elegant way to do this.  You can think 
of it
like factoring something out in algebra.  Every statement begins with

if($fit==0 && ....)

so let's factor that out and wrap the whole block in that statement
if ($fit==0) {

if( $new_width && !$new_height ) {

        $new_height = $height * ( $new_width / $width );

    } elseif( $new_height && !$new_width) {

        $new_width = $width * ( $new_height / $height );

    } elseif( !$new_width && !$new_height) {

        $new_width = $width;
        $new_height = $height;

    }
}

Now, looking at it this way, everything happens only if $fit==0, or more 
elegantly,
it is an else statement for if ($fit==1)

So, we need only to wrap the non-fit algorithm in an else clause that is 
relative to
the if ($fit) test.  Here is the code:

if ($fit)
{
 $final_height = $height * ( $new_width / $width );

  if ($final_height>$new_height)
   $new_width = $width * ( $new_height / $height );         
  else

 $new_height=$final_height;
} // end of braces for the conditional statement if ($fit)

// ----------------- end fit to box scaling algorithm ---------------------

//this 'else' blocking here stops the original algorithm from running if $fit==1
//however, if $fit==0, this will still run as it did in the original script

else  
{

 // generate new w/h if not provided -- this is the original algorithm

    if( $new_width && !$new_height ) {

        $new_height = $height * ( $new_width / $width );

    } elseif($new_height && !$new_width) {

        $new_width = $width * ( $new_height / $height );

    } elseif(!$new_width && !$new_height) {

        $new_width = $width;
        $new_height = $height;

    }

} //end else statement from if ($fit==1)

Does this make sense to you?  Thank you for pointing out that flaw in the 
robustness
of this patch!

Original comment by lbal...@gmail.com on 29 May 2010 at 1:00

GoogleCodeExporter commented 9 years ago
Yes that makes sense, thanks so much.

Really liked Tims thumbs script but not being able to keep the aspect ratio was
holding me back from using it to much! 

Now I can use it image by image and fit, stretch, crop or do the default value.

Enjoy the evening.

Original comment by geetjac...@gmail.com on 29 May 2010 at 1:11

GoogleCodeExporter commented 9 years ago
Any update for this issue ?
It's a really requested feature and several implementations have been provided 
so far :
this one, #25 and #78
Any chance we can see this feature pushed ?
thanks.

Original comment by gibbo...@gmail.com on 29 Jun 2010 at 7:51

GoogleCodeExporter commented 9 years ago
by all means, please add this to the codebase!  i have absolutely no idea of 
how to get Subversion up and running, so if you someone could make that happen, 
that would be great.

this code snippet also includes the no-upscaling check from #25, and the 
concept of setting only one constraining parameter from #78.

finally, this code remains backward-compatible with any pre-upgrade 
timthumb(params); calls

again, any help with pushing this into the SVN codebase would be awesome.

/////////////////////////////////////////////////-------------------------//

insert after the fetching and cleaning other command line parameters in the 
section
    // get properties

//---- new code
    $fit=preg_replace("/[^0-9]+/", "", get_request("fit", 0));
//---- end new code

insert after the section
    // Get original width and height
    $width = imagesx($image);
    $height = imagesy($image);

//new code  ---->

//check to make sure we are not upscaling the image

if ($new_width>$width) $new_width=$width;
if ($new_height>$height) $new_height=$height;

//now, if requested, fit to the bounding box without cropping
if ($fit)
{

// this allows us to set only a single constraining parameter for our bounding 
box
if (!$new_width) $new_width=$width;
if (!$new_height) $new_height=$height;

//begin reduction algorithm

 $final_height = $height * ( $new_width / $width );

  if ($final_height>$new_height)
   $new_width = $width * ( $new_height / $height );         
  else

 $new_height=$final_height;
} // end if ($fit)

// ----------------- end fit to box scaling algorithm ---------------------

else  // -- begin non-fit scaling algorithm
{

 // generate new w/h if not provided -- this is the original algorithm
 // note, that this also allows us to set only one resizing dimension

    if( $new_width && !$new_height ) {

        $new_height = $height * ( $new_width / $width );

    } elseif($new_height && !$new_width) {

        $new_width = $width * ( $new_height / $height );

    } elseif(!$new_width && !$new_height) {

        $new_width = $width;
        $new_height = $height;

    }

} //end elseif !($fit)

Original comment by lbal...@gmail.com on 29 Jun 2010 at 3:42

GoogleCodeExporter commented 9 years ago
Thank you for this superb piece of code...

IMHO the only thing that timthumb lacks...

Keep up the good work!
fdanialex

Original comment by fdania...@gmail.com on 27 Aug 2010 at 2:00

GoogleCodeExporter commented 9 years ago
Where can I get the working code that integrates all these great features?
Also timthumb was bundled with my theme i am using on wordpress, so will this 
new code help keep the aspect ratio when the theme is calling in the pictures 
with its own code?

Original comment by i.baj...@gmail.com on 25 Sep 2010 at 4:32

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
This mod works! I'm using it on my web site at www.flashbackfoto.com.br and it 
works perfectly. It should be definately integrated on the official timthumb.php

Original comment by marcusvd...@gmail.com on 16 Nov 2010 at 2:43

GoogleCodeExporter commented 9 years ago
@i.bajrai: just replacing the bundled timthumb.php with the modded version will 
not change the way that your wordpress theme calls timthumb.  if you want to 
change this, you need to search for all instances of the string 
"timthumb.php?foo=x&bar=y" and change the parameters to match your needs, as 
well as add the additional parameter "&fit=1".

Original comment by lbal...@gmail.com on 16 Nov 2010 at 3:19

GoogleCodeExporter commented 9 years ago
Hi lbalzer.
I still don't know if the implementation here is the best (and/or least 
intrusive) on this bugtracker so far.
But I'm quite sure you should provide a "patch" applying against the trunk 
version in the svn.

For doing so :
- fetch the last version of timthumb :
svn checkout http://timthumb.googlecode.com/svn/trunk/ timthumb-read-only

- apply your modifications to the codebase in the prettyest way you can

- do :
svn diff > /tmp/issue61.patch

- then attach the file named  /tmp/issue61.patch
- and we will wait for the author to reply.

These commands above should work on both linux and macos.
You just need to install subversion first (the package is available for every 
linux distribution).

regards

Original comment by gibbo...@gmail.com on 24 Nov 2010 at 8:13

GoogleCodeExporter commented 9 years ago
@gibboris -- thanks for the svn instructions.  as crazy as it may seem, i'm not 
developing on linux, but win, and haven't taken the time to comb through all 
the subversion clients available for windows.  at some point, i'll try to get 
to it, though if you've got subversion all up and running, the code in comment 
8 is what i would consider to be my final revision and ready to submit to the 
trunk.

best,
lucas

Original comment by lbal...@gmail.com on 24 Nov 2010 at 8:26

GoogleCodeExporter commented 9 years ago
Ok, after a deeper look I posted several other tickets to cleanup the code a 
bit.

As a first note, you could use :
$fit = (bool) get_request ('fit', 0);
instead of preg_match ?

Then here we are left we a problem.

TimThumb already resizes respecting the ratio, see
elseif($new_height && !$new_width) {
   $new_width = $width * ( $new_height / $height );
   ...
}
Because it allows one of new_width or new_height to be omitted (since, at least 
r28).
You can test with trunk/ :
for a 100x300, you can try :
timthumb.php?src=X&w=50&h=70&zc=0
timthumb.php?src=X&w=50&zc=0
timthumb.php?src=X&h=70&zc=0

So, I think the main point of this patch should be to resize with respect to 
ratio when BOTH dimension are given AND $fit = 1.
That way the two dimensions are taken as limits, so the image will have at 
least 1 of its dimension which match one of the parameters (except if the 
parameter is higher than the current image dimension) which is like the current 
behavior when only one parameter is provided) ...
 BUT it would allows the php script which call timthumb to ALWAYS send both parameters without having to guess which one should omitted.
Adding $fit should be enough for this script.
(of course the php script does not call timthumb, but build the scr attr of 
<img>)

So, because ratio-resizing is already there, the feature onlt here to ease the 
scripts in their arguments definition algorithm

Thus the only case the patch should care about is when
- $_GET['h'] is set and valid
- $_GET['w'] is set and valid
- $_GET['fit'] is casted as TRUE

If you agree with the above, would you want to provide a small patch which only 
care about this ?

what to do if both limits are lower than the real dimension, should we start by 
resizing the height, grab the ratio (say X%) then apply it to the width.
Which is the same as resizing the width, grab the ratio (say Y%), then apply it 
to the height.

I may miss the point, but that's why I implemented the patch in #78 : instead 
of adding $fit, I added w2 and h2.
So w=X&h2=Y start with ratio-resizing against the width, then, if the new 
height > h2, then we ratio-resize again againt the height.
I don't really remember why I did it like this, but you may want to have a look 
there. It just put the ratio routine in a function a calls it twice if h2 or w2 
is provided. You may want to replace it with $fit.

best regards

Original comment by gibbo...@gmail.com on 25 Nov 2010 at 3:19

GoogleCodeExporter commented 9 years ago
It's taken a while, but this is now added!

Use parameter zc = 2

Original comment by BinaryMoon on 6 Feb 2011 at 9:39

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Good day everyone.i am new with this timthumb.where i will put this code in the 
timthumb.php ?..this is the code from comment 8:

//---- new code
    $fit=preg_replace("/[^0-9]+/", "", get_request("fit", 0));
//---- end new code

insert after the section
    // Get original width and height
    $width = imagesx($image);
    $height = imagesy($image);

//new code  ---->

//check to make sure we are not upscaling the image

if ($new_width>$width) $new_width=$width;
if ($new_height>$height) $new_height=$height;

//now, if requested, fit to the bounding box without cropping
if ($fit)
{

// this allows us to set only a single constraining parameter for our bounding 
box
if (!$new_width) $new_width=$width;
if (!$new_height) $new_height=$height;

//begin reduction algorithm

 $final_height = $height * ( $new_width / $width );

  if ($final_height>$new_height)
   $new_width = $width * ( $new_height / $height );         
  else

 $new_height=$final_height;
} // end if ($fit)

// ----------------- end fit to box scaling algorithm ---------------------

else  // -- begin non-fit scaling algorithm
{

 // generate new w/h if not provided -- this is the original algorithm
 // note, that this also allows us to set only one resizing dimension

    if( $new_width && !$new_height ) {

        $new_height = $height * ( $new_width / $width );

    } elseif($new_height && !$new_width) {

        $new_width = $width * ( $new_height / $height );

    } elseif(!$new_width && !$new_height) {

        $new_width = $width;
        $new_height = $height;

    }

} //end elseif !($fit)

any help, advice and suggestion will be highly appreciated...thank you.

Original comment by edrylsec...@gmail.com on 22 Jun 2011 at 8:24

GoogleCodeExporter commented 9 years ago
hello there.is it possible to fit the original size which is 356 x 599 to the 
target size 303 x 177.?.please help..

Original comment by Jason08...@gmail.com on 23 Jun 2011 at 2:41

GoogleCodeExporter commented 9 years ago
@edrylsec You dont need to custom the code anymore, he added it to the main 
file. use zc = 2 the comment above yours.

Original comment by i...@anagr.am on 23 Jun 2011 at 2:58

GoogleCodeExporter commented 9 years ago
@ i...@anagr.am    Your Good..Your great..it really works..thank you so 
much...but the main point that i want to know is similar to the post of comment 
20..any suggestions or ideas?..thanks in advance..

Original comment by edrylsec...@gmail.com on 23 Jun 2011 at 6:13

GoogleCodeExporter commented 9 years ago
To both above, I think you would be able to do that with cropping.

timthumb.php?src=image.jpg&h=177&w=303

You dont even need to use any of the other variables.  Will cut off the bottom 
and the top of the image. If you want it to only crop the bottom then you can 
use this on the end &a=b or only the top &a=t

Original comment by geetjac...@gmail.com on 23 Jun 2011 at 3:28