developer tip

PHP에서 이미지 조각을 사용하여 모양을 그리는 방법

copycodes 2021. 1. 8. 08:32
반응형

PHP에서 이미지 조각을 사용하여 모양을 그리는 방법


이미지 조각을 사용하여 프레임 이미지를 만들어야합니다.

예를 들면 :

사용자는 백엔드에서 이미지 조각을 업로드합니다.

여기에 이미지 설명 입력

이제 다음과 같이 프런트 엔드 사용자의 요구 사항에 따라 프런트 엔드에 프레임을 만들어야합니다 (사용자가 프레임의 높이와 너비를 선택한 다음이 이미지 조각을 선택합니다).

여기에 이미지 설명 입력

나는 이것을 할 수있는 방법을 얻지 못하고 있으며 CSS와 html 캔버스로 이것을 시도했지만 운이 없습니다.

어떤 사람은 PHP, CSS 또는 HTML 또는 JavaScript 또는 기타 방법을 사용하여 어떻게이 작업을 수행 할 수 있는지 제안 해 주시겠습니까?

여기에서 실제로 수행해야하는 작업 예제를 볼 수 있습니다.

나만의 프레임 만들기


이미지 전처리가 중요합니다.

수동으로 수행하든 GD 라이브러리를 통해 어떤 식 으로든 즉석에서 수행하든, 최소한 수신중인 이미지를 가져와야합니다.

여기에 이미지 설명 입력

... 그리고 자르고 조여 다음과 같이 깨끗하게 만듭니다 (가장자리 주변의 여백이없고 노치 / 절단이 제거됨).

여기에 이미지 설명 입력

그러면 실제로 작업 할 수있는 이미지가 있습니다.

그렇지 않으면 PURE CSS / JAVASCRIPT

참고 : 여기서는 자바 스크립트를 사용하지 않습니다. html에서 볼 수 있듯이 요소 크기를 동적으로 설정하는 데 사용됩니다.

일반적으로 :beforehtml을 덜 복잡하게 유지하기 위해 상당한 양의 및 ': after'가상 요소를 사용하지만 프레임의 동적 크기 조정이 필요하므로 여러 중첩 된 div 요소를 사용하여 너비에 대한 동적 스타일을 설정해야합니다. 일부 div요소에 중요한 높이 (자바 스크립트가 이러한 요소에 액세스 할 수 있거나 동적 크기 조정이 필요하지 않은 경우 일부는 여전히 의사 요소 임).

참고 : 지금까지 Chrome과 Firefox에서만 이것을 테스트했습니다. 정말 오래된 브라우저는 확실히 비참하게 실패 할 것입니다.

/* implementation of framing */

    .frameit {
        /* width and height must be set dynamically by javascript see html */ 
        position: relative;
        box-sizing: border-box;
        overflow: hidden;
        padding: 20px; /* at least border size */
    }

    .frameit:before,
    .frameit:after,
    .frameit .sides > div,
    .frameit .corner > div {
        position: absolute;
        background-image: url(http://i.stack.imgur.com/vAgqj.jpg);
        background-size: 100% 20px; /* 100% and border size */
        height: 20px; /* equal to border width of frameit div */
    }

    .frameit:before {
        content: '';
        top: 0;
        left: 0;
        right: 0;
    }

    .frameit:after {
        content: '';
        bottom: 0;
        left: 0;
        right: 0;
    }

    .frameit .sides {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        z-index: 1;
    }

    .frameit .sides > div {
        /* width must be set dynamically by javascript see html */ 
        height: 20px;
    }

    .frameit .sides > div:first-child {
        top: 0;
        left: 20px; /* border width */
        transform-origin: 0 0;
        transform: rotate(90deg);
    }

    .frameit .sides > div:last-child  {
        bottom: 0;
        right: 20px; /* border width */
        transform-origin: 100% 100%;
        transform: rotate(90deg);
    }

    .frameit .sides ~ .corner { /* all corners */
        position: absolute;
        z-index: 2;
        width: 29px; /* square root of ((border-width squared) x 2) round up */
        height: 29px; /* match width */
        overflow: hidden;
    }

    .frameit .TL {
        top: 0;
        left: 0;
        transform-origin: 0 0;
        transform: rotate(-45deg);
    }

    .frameit .TL > div {
        top: inherit;
        left: inherit;
        transform-origin: inherit;
        transform: rotate(45deg);
    }

    .frameit .TR {
        top: 0;
        right: 0;
        transform-origin: 100% 0;
        transform: rotate(45deg);
    }

    .frameit .TR > div {
        top: 0;
        right: 0;
        transform-origin: 100% 0;
        transform: rotate(-45deg);
    }

    .frameit .BR {
        bottom: 0;
        right: 0;
        transform-origin: 100% 100%;
        transform: rotate(-45deg);
    }

    .frameit .BR > div {
       bottom: inherit;
       right: inherit;
       transform-origin: inherit;
       transform: rotate(45deg);
    }

    .frameit .BL {
        bottom: 0;
        left: 0;
        transform-origin: 0 100%;
        transform: rotate(45deg);
    }

    .frameit .BL > div {
        bottom: inherit;
        left: inherit;
        transform-origin: inherit;
        transform: rotate(-45deg);
    }

    /* Optional shading to help define the joint */
    .frameit .sides > div:first-child:before,
    .frameit .sides > div:last-child:before {
       content: '';
       position: absolute;
       top: 0;
       right: 0;
       left: 0;
       bottom: 0;
       background-color: rgba(0,0,0,.07);
    }
<div class="frameit" style="width: 200px; height: 300px;">
   <!-- top and bottom and overall container 
        width and height assumed to be set by javacript by user
   -->
   <div class="sides">
     <!-- left and right sides 
        widths of the children are equal to HEIGHT of container and are 
        assumed to be set by javacript by user
     -->
     <div style="width: 300px;"></div>
     <div style="width: 300px;"></div>
   </div>
   <div class="TL corner"><!-- top left bevel --><div style="width: 200px;"></div></div>
   <div class="TR corner"><!-- top right bevel --><div style="width: 200px;"></div></div>
   <div class="BR corner"><!-- bottom right bevel --><div style="width: 200px;"></div></div>
   <div class="BL corner"><!-- bottom left bevel --><div style="width: 200px;"></div></div>
</div>


답변에 게시 한 샘플 이미지는 프레임 생성에 사용하기에 적합하지 않을 수 있습니다. 프레임의 수평 및 수직면에 대해 2 개의 서로 다른 이미지를 얻어야합니다. 경사와 가장자리는 그에 따라 배치 할 수있는 다른 이미지 일 수도 있습니다.

.frame {
      position: relative;
      width: 500px;
      /*width of the frame*/
    }
    .horizontal-side {
      /*use a horizontal background that can repeat properly*/
      background: url(http://i.stack.imgur.com/vAgqj.jpg) repeat;
    }
    .horizontal-side {
      width: 500px;
      /*width of the frame*/
      height: 20px;
    }
    .vertical-side {
      /*use a vertical background that can repeat properly*/
      background: url(http://i.stack.imgur.com/vAgqj.jpg) repeat;
      width: 20px;
      height: 400px;
      /*height of the frame*/
    }
    .vertical-side.right {
      position: absolute;
      right: 0;
      top: 20px;
      /*same as the horizontal side's hight*/
    }
<div class="frame">
  <div class="horizontal-side top">

  </div>
  <div class="vertical-side left">

  </div>
  <div class="vertical-side right">

  </div>
  <div class="horizontal-side bottom">

  </div>
</div>

@ScottS 답변의 정리 된 이미지로 업데이트되었습니다.


PHP를 통해 단일 이미지를 사용하여 프레임을 만들려고 많이 시도했지만 PHP에서 솔루션을 찾지 못했습니다.

두 가지 답변 (Lucky Soni의 답변 및 ScottS의 답변)의 도움으로 내 요구 사항을 완전히 채우는 스크립트를 만들었습니다 (둘 다 덕분입니다).

First I have created 4 images from single image while uploading:

$file = Input::file('image');
$destinationPath    = 'test/';
$filename           = time() . $file->getClientOriginalName();
$extension          = $file->getClientOriginalExtension();
$upload_success     = $file->move($destinationPath, $filename);

// This will create image for upper horizontal part
$im = new imagick(public_path().'/test/'.$filename);
$im->setImageFormat( "jpg" );
$topUperName = 'hr-uper-'.$filename;
$img_name = public_path().'/20*20/'.$topUperName;
$im->resizeImage(20,20,Imagick::FILTER_LANCZOS,1);
$im->writeImage($img_name);

// This will create image for vertical right part
$vrtRght = 'vrt-right-'.$filename;
$img_name = public_path().'/20*20/'.$vrtRght;
$im->rotateimage('', '90');
$im->writeImage($img_name);

// This will create image for bottom horizontal part
$topUperBtm = 'hr-btm-'.$filename;
$img_name = public_path().'/20*20/'.$topUperBtm;
$im->rotateimage('', '90');
$im->writeImage($img_name);

// This will create image for vertical left part
$vrtlft = 'vrt-left-'.$filename;
$img_name = public_path().'/20*20/'.$vrtlft;
$im->rotateimage('', '90');
$im->writeImage($img_name);

$im->clear();
$im->destroy();

unlink(public_path() . '/' . $filename);

HTML layout:

<div class="frame">
    <div class="horizontal-side top"></div>
    <div class="vertical-side left"></div>
    <div class="vertical-side right"></div>
    <div class="horizontal-side bottom"></div>
    <div class="right-top-corner corner-holder">
        <img class="right-top corner" src="<?php echo url(); ?>/20*20/hr-uper-1448949720a.jpg">
    </div>
    <div class="right-btm-corner corner-holder">
        <img class="right-btm" corner src="<?php echo url(); ?>/20*20/hr-btm-1448949720a.jpg">
    </div>
    <div class="left-top-corner corner-holder">
        <img  class="left-top corner" src="<?php echo url(); ?>/20*20/hr-uper-1448949720a.jpg">
    </div>
    <div class="left-btm-corner corner-holder">
        <img  class="left-btm corner" src="<?php echo url(); ?>/20*20/hr-btm-1448949720a.jpg">
    </div>
</div>

Styling:

.frame {
        position: relative;
        width: 500px; /* dynamic*/
        height: 500px; /* dynamic*/
    }

    .horizontal-side {
        width: 100%;
        height: 100px; /* height of image*/
        position: absolute;
    }
    .horizontal-side.top {
        background: url('<?php echo url(); ?>/20*20/hr-uper-1448949720a.jpg') repeat !important;
    }
    .horizontal-side.bottom {
        background: url('<?php echo url(); ?>/20*20/hr-btm-1448949720a.jpg') repeat !important;
    }
    .horizontal-side.top {
        top: 0 !important;
    }
    .horizontal-side.bottom {
        bottom: 0 !important;
    }
    .vertical-side {
        width: 100px !important; /* width of image*/
        height: 100% !important;
        z-index: 9 !important;
        position: absolute !important;
    }
    .vertical-side.left {
        left: 0 !important;
        background: url('<?php echo url(); ?>/20*20/vrt-left-1448949720a.jpg') repeat !important;
    }
    .vertical-side.right {
        right: 0;
        background: url('<?php echo url(); ?>/20*20/vrt-right-1448949720a.jpg') repeat !important;
    }
    .corner-holder {
        position: absolute !important;
        z-index: 9 !important;
    }
    .right-top-corner{
        right: 0px !important;
    }
    .right-btm-corner {
        bottom: 0 !important;
    }
    .left-top-corner{
        left: 0 !important;
    }
    .left-btm-corner{
        bottom: 0 !important;
        left: 0 !important;
    }

    .corner {
        height: 100px !important; /* corner height (size of image)*/
        width: 100px !important; /*  corner width (size of image)*/
    }
    .right-top {
        clip: polygon(100% 0, 0% 100%, 0 0) !important;
        -webkit-clip-path: polygon(100% 0, 0% 100%, 0 0) !important;
        -moz-clip-path: polygon(100% 0, 0% 100%, 0 0) !important;
        -ms-clip-path: polygon(100% 0, 0% 100%, 0 0) !important;
        -o-clip-path: polygon(100% 0, 0% 100%, 0 0) !important;
        clip-path: polygon(100% 0, 0% 100%, 0 0) !important;
    } 
    .right-btm{
        clip: polygon(0 100%, 0 0, 100% 100%) !important;
        -webkit-clip-path: polygon(0 100%, 0 0, 100% 100%) !important;
        -moz-clip-path: polygon(0 100%, 0 0, 100% 100%) !important;
        -ms-clip-path: polygon(0 100%, 0 0, 100% 100%) !important;
        -o-clip-path: polygon(0 100%, 0 0, 100% 100%) !important;
        clip-path: polygon(0 100%, 0 0, 100% 100%) !important;
    }
    .left-top{
        clip: polygon(100% 0, 0 0, 100% 100%) !important;   
        -webkit-clip-path: polygon(100% 0, 0 0, 100% 100%) !important;   
        -moz-clip-path: polygon(100% 0, 0 0, 100% 100%) !important;   
        -ms-clip-path: polygon(100% 0, 0 0, 100% 100%) !important;   
        -o-clip-path: polygon(100% 0, 0 0, 100% 100%) !important;   
        clip-path: polygon(100% 0, 0 0, 100% 100%) !important;   
    }
    .left-btm{
        clip: polygon(100% 0, 0 100%, 100% 100%) !important;   
        -webkit-clip-path: polygon(100% 0, 0 100%, 100% 100%) !important;   
        -moz-clip-path: polygon(100% 0, 0 100%, 100% 100%) !important;   
        -ms-clip-path: polygon(100% 0, 0 100%, 100% 100%) !important;   
        -o-clip-path: polygon(100% 0, 0 100%, 100% 100%) !important;   
        clip-path: polygon(100% 0, 0 100%, 100% 100%) !important;   
    }

이제 모든 유형의 이미지에서 적절한 프레임을 만들 수 있습니다.


<?php
header('Content-type: image/png');
$png_image = imagecreate(300, 300);
$grey = imagecolorallocate($png_image, 229, 229, 229);
$green = imagecolorallocate($png_image, 128, 204, 204);
imagefilltoborder($png_image, 0, 0, $grey, $grey);

imagefilledrectangle ($png_image, 20, 20, 80, 80, $green);     // SQUARE
imagefilledrectangle ($png_image, 100, 20, 280, 80, $green);   // RECTANGLE
imagefilledellipse ($png_image, 50, 150, 75, 75, $green);      // CIRCLE
imagefilledellipse ($png_image, 200, 150, 150, 75, $green);    // ELLIPSE

$poly_points = array(150, 200, 100, 280, 200, 280);
imagefilledpolygon ($png_image, $poly_points, 3, $green);      // POLYGON

imagepng($png_image);
imagedestroy($png_image);

그것을 시도

스 니펫은 http://www.phpforkids.com/php/php-gd-library-drawing-shapes.php입니다.


나는 당신의 해결책을 보았습니다. 그러나 나는 높이와 너비를 늘리려 고 시도했을 때 적절한 결과를 얻지 못했습니다.

다양한 크기의 이미지를 사용하여이 문제를 해결하려고했습니다.

$file = Input::file('image');
$destinationPath    = 'test/';
$filename           = time() . $file->getClientOriginalName();
$extension          = $file->getClientOriginalExtension();
$upload_success     = $file->move($destinationPath, $filename);

// This will create image for upper horizontal part
$im = new imagick(public_path().'/test/'.$filename);
$im->setImageFormat( "jpg" );

/** Here I have created 4 side images of 20*20 **/  
$topUperName = 'hr-uper-'.$filename;
$img_name = public_path().'/20*20/'.$topUperName;
$im->resizeImage(20,20,Imagick::FILTER_LANCZOS,1);
$im->writeImage($img_name);

// This will create image for vertical right part
$vrtRght = 'vrt-right-'.$filename;
$img_name = public_path().'/20*20/'.$vrtRght;
$im->rotateimage('', '90');
$im->writeImage($img_name);

// This will create image for bottom horizontal part
$topUperBtm = 'hr-btm-'.$filename;
$img_name = public_path().'/20*20/'.$topUperBtm;
$im->rotateimage('', '90');
$im->writeImage($img_name);

// This will create image for vertical left part
$vrtlft = 'vrt-left-'.$filename;
$img_name = public_path().'/20*20/'.$vrtlft;
$im->rotateimage('', '90');
$im->writeImage($img_name);

$im->clear();
$im->destroy();


/** Here I have created 4 side images of 30*30 **/
// This will create image for upper horizontal part
$im2 = new imagick(public_path().'/test/'.$filename);
$im2->setImageFormat( "jpg" );

$topUperName = 'hr-uper-'.$filename;
$img_name = public_path().'/30*30/'.$topUperName;
$im2->resizeImage(30,30,Imagick::FILTER_LANCZOS,1);
$im2->writeImage($img_name);

// This will create image for vertical right part
$vrtRght = 'vrt-right-'.$filename;
$img_name = public_path().'/30*30/'.$vrtRght;
$im2->rotateimage('', '90');
$im2->writeImage($img_name);

// This will create image for bottom horizontal part
$topUperBtm = 'hr-btm-'.$filename;
$img_name = public_path().'/30*30/'.$topUperBtm;
$im2->rotateimage('', '90');
$im2->writeImage($img_name);

// This will create image for vertical left part
$vrtlft = 'vrt-left-'.$filename;
$img_name = public_path().'/30*30/'.$vrtlft;
$im2->rotateimage('', '90');
$im2->writeImage($img_name);

$im2->clear();
$im2->destroy();

/** Here I have created 4 side images of 40*40 **/
// This will create image for upper horizontal part
$im3 = new imagick(public_path().'/test/'.$filename);
$im3->setImageFormat( "jpg" );

$topUperName = 'hr-uper-'.$filename;
$img_name = public_path().'/40*40/'.$topUperName;
$im3->resizeImage(40,40,Imagick::FILTER_LANCZOS,1);
$im3->writeImage($img_name);

// This will create image for vertical right part
$vrtRght = 'vrt-right-'.$filename;
$img_name = public_path().'/40*40/'.$vrtRght;
$im3->rotateimage('', '90');
$im3->writeImage($img_name);

// This will create image for bottom horizontal part
$topUperBtm = 'hr-btm-'.$filename;
$img_name = public_path().'/40*40/'.$topUperBtm;
$im3->rotateimage('', '90');
$im3->writeImage($img_name);

// This will create image for vertical left part
$vrtlft = 'vrt-left-'.$filename;
$img_name = public_path().'/40*40/'.$vrtlft;
$im3->rotateimage('', '90');
$im3->writeImage($img_name);

$im3->clear();
$im3->destroy();


/** Here I have created 4 side images of 50*50 **/
// This will create image for upper horizontal part
$im4 = new imagick(public_path().'/test/'.$filename);
$im4->setImageFormat( "jpg" );

$topUperName = 'hr-uper-'.$filename;
$img_name = public_path().'/50*50/'.$topUperName;
$im4->resizeImage(50,50,Imagick::FILTER_LANCZOS,1);
$im4->writeImage($img_name);

// This will create image for vertical right part
$vrtRght = 'vrt-right-'.$filename;
$img_name = public_path().'/50*50/'.$vrtRght;
$im4->rotateimage('', '90');
$im4->writeImage($img_name);

// This will create image for bottom horizontal part
$topUperBtm = 'hr-btm-'.$filename;
$img_name = public_path().'/50*50/'.$topUperBtm;
$im4->rotateimage('', '90');
$im4->writeImage($img_name);

// This will create image for vertical left part
$vrtlft = 'vrt-left-'.$filename;
$img_name = public_path().'/50*50/'.$vrtlft;
$im4->rotateimage('', '90');
$im4->writeImage($img_name);

$im4->clear();
$im4->destroy();

unlink(public_path() . '/' . $filename);

이미지의 해당 부분을 4 가지 크기로 잘라서 다른 비율로 프레임을 만드는 동안 이러한 크기를 사용할 수 있습니다.

For example if I am going to create a frame 1000*200, then it was breaking the css, because you were using a image of only 20*20 thick image in all sizes of frame.

이제 모든 이미지 크기에 대한 비율을 설정하기 만하면됩니다. 예를 들면 다음과 같습니다.

//you will get this from your ajax call
$width = $_GET['width'];
$width = $_GET['height'];

if($width <= 200){
   $frameImage = 'path-of-your-20*20-image';
}

if($width > 200 && $width <= 500){
   $frameImage = 'path-of-your-30*30-image';
}

if($width > 500 && $width <= 700){
   $frameImage = 'path-of-your-40*40-image';
}

if($width > 700){
   $frameImage = 'path-of-your-50*50-image';
}

// you can set these variable as per your requirement. And then use this image path to create the html of your frame. If you need a big range of your frame then you can also crop and save image in more sizes while uploading.

이것이 당신에게 유용하기를 바랍니다.

참조 URL : https://stackoverflow.com/questions/33514840/how-to-draw-a-shape-using-a-piece-of-image-in-php

반응형