www.webdeveloper.com
Results 1 to 5 of 5

Thread: imagecopymerge setting height to display bottom of image upwards instead of top down?

  1. #1
    Join Date
    Sep 2006
    Location
    Wixom, MI
    Posts
    292

    Question imagecopymerge setting height to display bottom of image upwards instead of top down?

    Not sure if my last post was titled correctly to allow people to understand what I am looking for.

    When using imagecopymerge you can put one image over another and if you set the source height to a pixel value that is half of the total source image height then only the top half of the image is shown and merged on top of the background image etc.

    What I would like to do is reverse that and have the bottom of the image be shown, so if I have 2 images both 200px in height and I set pic 2 to merge over pic 1 with a source height of 100 it would only show the bottom 100px of pic 2 instead of the default where it shows the top 100px.

    Is there an easy way to do this?

    My current code is below.

    PHP Code:
    function imagecopymerge_alpha($dst_im$src_im$dst_x$dst_y$src_x$src_y$src_w$src_h$pct){
        if(!isset(
    $pct)){
            return 
    false;
        }
        
    $pct /= 100;
        
    // Get image width and height
        
    $w imagesx$src_im );
        
    $h imagesy$src_im );
        
    // Turn alpha blending off
        
    imagealphablending$src_imfalse );
        
    // Find the most opaque pixel in the image (the one with the smallest alpha value)
        
    $minalpha 127;
        for( 
    $x 0$x $w$x++ )
        for( 
    $y 0$y $h$y++ ){
            
    $alpha = ( imagecolorat$src_im$x$y ) >> 24 ) & 0xFF;
            if( 
    $alpha $minalpha ){
                
    $minalpha $alpha;
            }
        }
        
    //loop through image pixels and modify alpha for each
        
    for( $x 0$x $w$x++ ){
            for( 
    $y 0$y $h$y++ ){
                
    //get current alpha value (represents the TANSPARENCY!)
                
    $colorxy imagecolorat$src_im$x$y );
                
    $alpha = ( $colorxy >> 24 ) & 0xFF;
                
    //calculate new alpha
                
    if( $minalpha !== 127 ){
                    
    $alpha 127 127 $pct * ( $alpha 127 ) / ( 127 $minalpha );
                } else {
                    
    $alpha += 127 $pct;
                }
                
    //get the color index with new alpha
                
    $alphacolorxy imagecolorallocatealpha$src_im, ( $colorxy >> 16 ) & 0xFF, ( $colorxy >> ) & 0xFF$colorxy 0xFF$alpha );
                
    //set pixel with the new color + opacity
                
    if( !imagesetpixel$src_im$x$y$alphacolorxy ) ){
                    return 
    false;
                }
            }
        }
        
    // The image copy
        
    imagecopy($dst_im$src_im$dst_x$dst_y$src_x$src_y$src_w$src_h);
    }

    $img_a imagecreatefrompng('images/dmbackground.png');
    $img_b imagecreatefrompng('images/dmforeground.png');

    imagecopymerge_alpha($img_a$img_b0000imagesx($img_b), (imagesy($img_b)/100)*65100);

    header("Content-Type: image/png");
    imagesavealpha($img_atrue);
    imagepng($img_aNULL); 
    And it calculates a percentage of the image height of the overlaying image ($img_b) so it only displays that percentage, currently it does this from top to bottom but I need bottom to top, is this possible? I tried using negative numbers and that shows nothing at all.

    Any advice?

    Thanks

  2. #2
    Join Date
    Mar 2011
    Posts
    1,159
    I can't quite see exactly what you're trying to do. If the goal is to take the bottom half of a src_img and overlay it on the dst_img, you can do something simple like:
    Code:
    function overlay_bottom($src, $dst ,$pct) {
      $width = imagesx($src);
      $height = imagesy($src);
      $halfHeight = floor($height/2);
    // imagecopymerge ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h , int $pct )
      imagecopymerge($dst, $src, 0, $halfHeight, 0, $halfHeight, $width, $halfHeight, $pct);
     }
    I'm not clear why you need a percentage of the src_img. If the images are not the same size, you can use imagecopyresized() on the src_img to suit your needs before the merge.

    It's not that I believe this hasn't occurred to you already. I just don't see what the goal is. Perhaps you could post example of the src and dst images along with a mock-up of what you're trying to achieve.

  3. #3
    Join Date
    Sep 2006
    Location
    Wixom, MI
    Posts
    292
    What I am trying to do is as follows, I have a background image lets say could be anything a plain color, pic of a wall, landscape anything, and a foreground image of exactly the same size and shape but most of it is transparent, it contains a pic of maybe a person or object, what this would be used for is a donation goal meter, where in a dynamically generated percentage of a total would be calculated in the php and used to determine how much of the foreground pic to show and thats why I need it going from bottom to top so if the pic was a person it would start by showing the feet then as more donations are tracked the percentage calculation would get higher and higher and the legs would show then the torso etc finally the head, this is just a simplified example of something I am thinking that could be applied to any background and foreground image, perhaps the background image and foreground image are the same except one is black and white the other color and an increased percentage value causes that percentage of thee foreground image to display making the pic look like it is getting color from the bottom upwards as the value changes over time.

    Does that make sense?

    I saw it done once with a pic of a buss covered in graffiti that was started grey and became colored upwards based on a calculation of a donation goal.

  4. #4
    Join Date
    Sep 2006
    Location
    Wixom, MI
    Posts
    292

    resolved

    Thanks for the code you gave i used a bit of what you posted and adapted the code I am using (which works with transparency) and it now works

    PHP Code:
    <?php
    /**
     * PNG ALPHA CHANNEL SUPPORT for imagecopymerge();
     * This is a function like imagecopymerge but it handle alpha channel well!!!
     **/

    // A fix to get a function like imagecopymerge WITH ALPHA SUPPORT
    // Main script by aiden dot mail at freemail dot hu
    // Transformed to imagecopymerge_alpha() by rodrigo dot polo at gmail dot com
    function imagecopymerge_alpha($dst_im$src_im$dst_x$dst_y$src_x$src_y$src_w$src_h$pct){
        if(!isset(
    $pct)){
            return 
    false;
        }
        
    $pct /= 100;
        
    // Get image width and height
        
    $w imagesx$src_im );
        
    $h imagesy$src_im );
        
    // Turn alpha blending off
        
    imagealphablending$src_imfalse );
        
    // Find the most opaque pixel in the image (the one with the smallest alpha value)
        
    $minalpha 127;
        for( 
    $x 0$x $w$x++ )
        for( 
    $y 0$y $h$y++ ){
            
    $alpha = ( imagecolorat$src_im$x$y ) >> 24 ) & 0xFF;
            if( 
    $alpha $minalpha ){
                
    $minalpha $alpha;
            }
        }
        
    //loop through image pixels and modify alpha for each
        
    for( $x 0$x $w$x++ ){
            for( 
    $y 0$y $h$y++ ){
                
    //get current alpha value (represents the TANSPARENCY!)
                
    $colorxy imagecolorat$src_im$x$y );
                
    $alpha = ( $colorxy >> 24 ) & 0xFF;
                
    //calculate new alpha
                
    if( $minalpha !== 127 ){
                    
    $alpha 127 127 $pct * ( $alpha 127 ) / ( 127 $minalpha );
                } else {
                    
    $alpha += 127 $pct;
                }
                
    //get the color index with new alpha
                
    $alphacolorxy imagecolorallocatealpha$src_im, ( $colorxy >> 16 ) & 0xFF, ( $colorxy >> ) & 0xFF$colorxy 0xFF$alpha );
                
    //set pixel with the new color + opacity
                
    if( !imagesetpixel$src_im$x$y$alphacolorxy ) ){
                    return 
    false;
                }
            }
        }
        
    // The image copy
        
    imagecopy($dst_im$src_im$dst_x$dst_y$src_x$src_y$src_w$src_h);
        
    //imagecopymerge($dst, $src, 0, $halfHeight, 0, $halfHeight, $width, $halfHeight, $pct);
    }

    // USAGE EXAMPLE:
    $img_a imagecreatefrompng('images/back.png');
    $img_b imagecreatefrompng('images/front.png');

    // SAME COMMANDS:
    //imagecopymerge_alpha($img_a, $img_b, 0, 0, 0, 0, imagesx($img_b), imagesy($img_b),100);
    imagecopymerge_alpha($img_a$img_b0, (imagesy($img_b)/100)*300, (imagesy($img_b)/100)*30imagesx($img_b), (imagesy($img_b)/100)*30100);

    // OUTPUT IMAGE:
    header("Content-Type: image/png");
    imagesavealpha($img_atrue);
    imagepng($img_aNULL);

    ?>
    In the code the *30 a few lines from the bottom would represent the percentage to not show, so if the donation total was 70% reached then 30 would be used there to show 70% of the image an leave the top 30% hidden.


    Once I finish building the donation calculation part the 30 would be replaced by a variable containing the value.

    Hopefully this complete code will be useful for someone else.

    Thanks again for the help I had such a hard time figuring out that small simple bit

  5. #5
    Join Date
    Mar 2011
    Posts
    1,159
    Okay. I was getting lost between $pct being an alpha setting and your need to calculate a percentage of a dimension. This is just a logic issue then. All in all, it's just a single calculation, but we need to work in terms of the percentage of the image to be shown/drawn/copied rather than 'hidden'. But something like the following should be close:

    Code:
    $toHidePct = 30;
    $toShowPct = 100 - $toHidePct;  // % of the image to actually copy/merge
    $width = imagesx($src_img);
    $height = imagesy($src_img);
    $heightToShow = floor($height * (floor($toShowPct/100));
    $dst_x = 0;
    $dst_y = $height - $heightToShow;
    $src_x = 0;
    $src_y = $height - $heightToShow;
    $src_w = $width;
    $src_h = $heightToShow;
    I generally prefer to work with ImageMagick instead of GD for special effects - especially when transparency is involved. And so I was going to suggest an ImageMagick solution instead, but it occurs to me now that this task could be done a bit easier with JavaScript and CSS. It's getting too late to play with it now, but I'll try to remember to cobble something together in the next day or so.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles