PHP の画像処理関数を使って PNG 画像を生成できるので、ちょっとやってみた。既存の画像を重ねて一つの画像を作るというようなことができる。サイトで扱う画像にコピーライトのウォーターマークを入れたりと、応用が効く。
必要ファイルの準備
この penguin.png
tag_sale.png
software_package.jpg
とテキストを重ねるのだけど、テキストを挿入するにはフォントファイル (.ttl) が必要になる。
https://ipafont.ipa.go.jp/node26 のようなところからフリーでフォントを落とせる。探せばWEB上に沢山転がっている。日本語の表示には日本語のフォントが必要。今回は ipaexg.ttf というフォントファイルを使う。
この4つのファイルに加えて、簡単なPHPクラスを書いたので、それを配置。
簡単なクラスを書いた
PngLayer.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
<?php class PngLayer { private $___iWidth = 0; private $___iHeight = 0; private $___aImages = array(); /** * @return boolean true on success; false on failure. */ public function addImage( $sImagePath ) { if ( ! file_exists( $sImagePath ) ){ return false; } $_aImageInfo = getimagesize( $sImagePath ) ; $_aImageInfo = $_aImageInfo + array( 'path' => $sImagePath ); if ( ! $this->___iWidth || $this->___iHeight ) { $this->setDimensions( $_aImageInfo[ 0 ], $_aImageInfo[ 1 ] ); } $_frImage = $this->___getImageResource( $_aImageInfo ); if ( false === $_frImage ) { return false; } $this->___aImages[] = $_frImage; return true; } /** * @remark suppots only gif, jpeg, png, bmp * @return false|resource */ private function ___getImageResource( $aImageInfo ) { $_aFunctions = array( // get_defined_constants() 3 => 'imagecreatefrompng', // [IMAGETYPE_GIF] => 1 2 => 'imagecreatefromjpeg', // [IMAGETYPE_JPEG] => 2 1 => 'imagecreatefromgif', // [IMAGETYPE_PNG] => 3 6 => 'imagecreatefromwbmp', // [IMAGETYPE_BMP] => 6 ); $_sFunctiton = isset( $_aFunctions[ $aImageInfo[ 2 ] ] ) ? $_aFunctions[ $aImageInfo[ 2 ] ] : ''; if ( ! $_sFunctiton ) { return false; } return call_user_func_array( $_sFunctiton, array( $aImageInfo[ 'path' ] ) ); } /** * @return boolean */ public function addText( $sText, $iSize, $sColorHex, $iX, $iY, $sFontPath ) { $_frImage = $this->___getTextImage( $sText, $iSize, $sColorHex, $iX, $iY, $sFontPath ); if ( false === $_frImage ) { return false; } $this->___aImages[] = $_frImage; return true; } /** * @return false|resource */ private function ___getTextImage( $sText, $iSize, $sColorHex, $iX, $iY, $sFontPath ) { $_rImage = @imagecreatetruecolor( $this->___iWidth, $this->___iHeight ); if ( false === $_rImage ) { return false; } imagesavealpha( $_rImage, true ); imagealphablending( $_rImage, false ); $white = imagecolorallocatealpha( $_rImage , 255, 255, 255, 127); imagefill( $_rImage, 0, 0, $white ); $_aRGB = sscanf( $sColorHex, '#%02x%02x%02x' ); $_iFontColor = imagecolorallocate( $_rImage, $_aRGB[ 0 ], $_aRGB[ 1 ], $_aRGB[ 2 ] ); imagettftext( $_rImage, $iSize, 0, $iX, $iY, $_iFontColor, $sFontPath, $sText ); return $_rImage; } public function setDimensions( $iWidth, $iHeight ) { $this->___iWidth = $iWidth; $this->___iHeight = $iHeight; } /** * @return string the png image output */ public function get() { $_rImage = $this->___getImagesMerged( $this->___getContainerImageResource( $this->___iWidth, $this->___iHeight ), $this->___aImages, $this->___iWidth, $this->___iHeight ); return $this->___getOutput( $_rImage ); } private function ___getContainerImageResource( $iWidth, $iHeight ) { $_frFinalImage = @imagecreatetruecolor( $iWidth, $iHeight ); if ( false === $_frFinalImage ) { return $this->___getPlainTextImage( 'Error loading', $iWidth, $iHeight ); } imagealphablending( $_frFinalImage, true ); imagesavealpha( $_frFinalImage, true ); return $_frFinalImage; } /** * @return false|resource */ private function ___getPlainTextImage( $sText, $iX, $iY ) { $im = imagecreatetruecolor( $iX, $iY ); if ( false === $im ) { return false; } $bgc = imagecolorallocate($im, 255, 255, 255); $tc = imagecolorallocate($im, 0, 0, 0); imagefilledrectangle($im, 0, 0, $iX, $iY, $bgc ); imagestring( $im, 5, 5, 5, $sText, $tc ); return $im; } /** * Merges images * @return resource An image identifier representing a black image of the specified size. */ private function ___getImagesMerged( $rContainer, array $aImages, $iWidth, $iHeight ) { foreach( $aImages as $_iIndex => $_rImage ) { imagecopy( $rContainer, $_rImage, 0, 0, 0, 0, $iWidth, $iHeight ); } return $rContainer; } /** * @return string */ private function ___getOutput( $rPNG ) { ob_start(); imagepng( $rPNG ); $_sOutput = ob_get_contents(); ob_end_clean(); return $_sOutput; } } |
このクラスをどうやって使うかというと、インスタンス化して、addImage()
と addText()
メソッドでレイヤーを追加して、最後に get()
でアウトプットを取得。以下のような感じ。
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php include( 'PngLayer.php' ); $_oPngLayer = new PngLayer; $_oPngLayer->addImage( "software_package.jpg" ); $_oPngLayer->addImage( "penguin.png" ); $_oPngLayer->addImage( "tag_sale.png" ); $_oPngLayer->addText( '日本語OK', 40, '#555555', 128, 256, 'ipaexg.ttf' ); header( 'Content-Type: image/png' ); echo $_oPngLayer->get(); |
画像
仕上がりはこんな感じ。
ショッピングサイトで商品画像に上からセール中のタグがついてたりするけど、同じようなことができる。
余談というかメモ
ちなみに、サポートしている画像形式は、png
, gif
, jpg
, bmp
の4種類。その判定に getimagesize()
を使った。
getimagesize()
が返す配列のストラクチャは以下のようになる。sample.gif,sample.bmp
, sample.png
, sample.jpg
を同階層に配置して以下の コードを走らせる。インデックス 2
に整数でタイプ情報が格納されている。
1 2 3 4 5 6 7 8 9 10 |
$_aImages = array( 'sample.gif', 'sample.bmp', 'sample.png', 'sample.jpg', ); foreach( $_aImages as $_sImagePath ) { $_aImageInfo = getimagesize( $_sImagePath ) ; var_dump( $_aImageInfo ); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
array (size=7) 0 => int 256 1 => int 264 2 => int 1 3 => string 'width="256" height="264"' (length=24) 'bits' => int 8 'channels' => int 3 'mime' => string 'image/gif' (length=9) array (size=6) 0 => int 256 1 => int 264 2 => int 6 3 => string 'width="256" height="264"' (length=24) 'bits' => int 8 'mime' => string 'image/x-ms-bmp' (length=14) array (size=6) 0 => int 624 1 => int 640 2 => int 3 3 => string 'width="624" height="640"' (length=24) 'bits' => int 8 'mime' => string 'image/png' (length=9) array (size=7) 0 => int 1862 1 => int 1920 2 => int 2 3 => string 'width="1862" height="1920"' (length=26) 'bits' => int 8 'channels' => int 3 'mime' => string 'image/jpeg' (length=10) |