Crop or mask an image into a circle

核能气质少年 提交于 2019-11-27 03:52:10
tom

Here is one way with ImageMagick that will acomplish this without using a mask:

convert -size 200x200 xc:none -fill walter.jpg -draw "circle 100,100 100,1" circle_thumb.png

Jonathan Hell

For those who need to do this in pure PHP using Imagick, you will need to refer to this question : circularize an image with imagick

Hope this will help.

J.

For those who wants a solution in PHP, providing the picture already cropped into a circle:

// convert the picture
    $w = 640;  $h=480; // original size
    $original_path="/location/of/your/original-picture.jpg";
    $dest_path="/location/of/your/picture-crop-transp.png";
    $src = imagecreatefromstring(file_get_contents($original_path));
    $newpic = imagecreatetruecolor($w,$h);
    imagealphablending($newpic,false);
    $transparent = imagecolorallocatealpha($newpic, 0, 0, 0, 127);
    $r=$w/2;
    for($x=0;$x<$w;$x++)
        for($y=0;$y<$h;$y++){
            $c = imagecolorat($src,$x,$y);
            $_x = $x - $w/2;
            $_y = $y - $h/2;
            if((($_x*$_x) + ($_y*$_y)) < ($r*$r)){
                imagesetpixel($newpic,$x,$y,$c);
            }else{
                imagesetpixel($newpic,$x,$y,$transparent);
            }
        }
    imagesavealpha($newpic, true);
    imagepng($newpic, $dest_path);
    imagedestroy($newpic);
    imagedestroy($src);

For those who want a node/js based solution, you can create a circular crop at specified coordinates using node-gm like this:

gm(original)
   .crop(233, 233,29,26)
   .resize(size, size)
   .write(output, function(err) {
      gm(size, size, 'none')
         .fill(output)
         .drawCircle(size/2,size/2, size/2, 0)
         .write(output, function(err) {
            console.log(err || 'done');
         });
    });

You can use a lib like JCrop (demo) to allow the user to crop the image on the front-end and pass the coordinates (w,h,x,y) into crop().

You can use this function if you want to circular the corners of an image. To make the circle image, you need to set $Radius to 50%; If the $source_url is a square, the output will be the circle, otherwise it will be oval.The output will be a PNG file with transparent background.

public function Crop_ByRadius($source_url,$destination_url="",$Radius="0px" ,$Keep_SourceFile = TRUE){

    /*
        Output File is png, Because for crop we need transparent color

        if success :: this function returns url of Created File
        if Fial :: returns FALSE

        $Radius Input Examples :: 
                            100     => 100px                    
                            100px   => 100px                    
                            50%     => 50%                  
    */

    if( !file_exists($source_url) || $Radius == NULL )
        return FALSE;

    if( $destination_url == NULL || $destination_url == "" ) $destination_url = $source_url;


    $PathInfo = pathinfo($destination_url);
    $destination_url = $PathInfo['dirname'].DIRECTORY_SEPARATOR.$PathInfo['filename'].".png";

    $ImageInfo = getimagesize($source_url);
    $w = $ImageInfo[0];
    $h = $ImageInfo[1];
    $mime = $ImageInfo['mime'];

    if( $mime != "image/jpeg" && $mime != "image/jpg" && $mime != "image/png")
        return FALSE;

    if( strpos($Radius,"%") !== FALSE ){
        //$Radius by Cent
        $Radius = intval( str_replace("%","",$Radius) );
        $Smallest_Side = $w <= $h ? $w : $h;
        $Radius = $Smallest_Side * $Radius / 100; 

    }else{
        $Radius = strtolower($Radius);
        $Radius = str_replace("px","",$Radius);
    }

    $Radius = is_numeric($Radius) ? intval($Radius) : 0;

    if( $Radius == 0 ) return FALSE;

    $src = imagecreatefromstring(file_get_contents($source_url));
    $newpic = imagecreatetruecolor($w,$h);
    imagealphablending($newpic,false);
    $transparent = imagecolorallocatealpha($newpic, 0, 0, 0, 127);
    //$transparent = imagecolorallocatealpha($newpic, 255, 0, 0, 0);//RED For Test

    $r = $Radius / 2;

    /********************** Pixel step config ********************************/

    $Pixel_Step_def = 0.4;//smaller step take longer time! if set $Pixel_Step=0.1 result is better than  $Pixel_Step=1 but it take longer time!

    //We select the pixels we are sure are in range, to Take up the bigger steps and shorten the processing time

    $Sure_x_Start = $Radius +1;
    $Sure_x_End = $w - $Radius -1;
    $Sure_y_Start = $Radius +1;
    $Sure_y_End = $h - $Radius -1;
    if( $w <= $h ){
        //We want to use the larger side to make processing shorter
        $Use_x_Sure = FALSE;
        $Use_y_Sure = TRUE;
    }else{
        $Use_x_Sure = TRUE;
        $Use_y_Sure = FALSE;
    }
    /********************** Pixel step config END********************************/


    $Pixel_Step = $Pixel_Step_def;
    for( $x=0; $x < $w ; $x+=$Pixel_Step ){

        if( $Use_x_Sure && $x > $Sure_x_Start && $x < $Sure_x_End ) $Pixel_Step = 1;else $Pixel_Step = $Pixel_Step_def; 

        for( $y=0; $y < $h ; $y+=$Pixel_Step){
            if( $Use_y_Sure && $y > $Sure_y_Start && $y < $Sure_y_End ) $Pixel_Step = 1;else $Pixel_Step = $Pixel_Step_def; 

            $c = imagecolorat($src,$x,$y);

            $_x = ($x - $Radius) /2;
            $_y = ($y - $Radius) /2;
            $Inner_Circle = ( ( ($_x*$_x) + ($_y*$_y) ) < ($r*$r) );
            $top_Left = ($x > $Radius || $y > $Radius) || $Inner_Circle;

            $_x = ($x - $Radius) /2 - ($w/2 - $Radius);
            $_y = ($y - $Radius) /2;
            $Inner_Circle = ( ( ($_x*$_x) + ($_y*$_y) ) < ($r*$r) );
            $top_Right = ($x < ($w - $Radius) || $y > $Radius) || $Inner_Circle;

            $_x = ($x - $Radius) /2;
            $_y = ($y - $Radius) /2 - ($h/2 - $Radius);
            $Inner_Circle = ( ( ($_x*$_x) + ($_y*$_y) ) < ($r*$r) );
            $Bottom_Left =  ($x > $Radius || $y < ($h - $Radius) ) || $Inner_Circle;

            $_x = ($x - $Radius) /2 - ($w/2 - $Radius);
            $_y = ($y - $Radius) /2 - ($h/2 - $Radius);
            $Inner_Circle = ( ( ($_x*$_x) + ($_y*$_y) ) < ($r*$r) );
            $Bottom_Right = ($x < ($w - $Radius) || $y < ($h - $Radius) ) || $Inner_Circle;

            if($top_Left && $top_Right && $Bottom_Left && $Bottom_Right ){

                imagesetpixel($newpic,$x,$y,$c);

            }else{
                imagesetpixel($newpic,$x,$y,$transparent);
            }

        }
    }


    if( !$Keep_SourceFile && $source_url != $destination_url){
        unlink($source_url);
    }


    imagesavealpha($newpic, true);
    imagepng($newpic, $destination_url);
    imagedestroy($newpic);
    imagedestroy($src);


    return $destination_url;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!