【PHP】画像に透かしを入れつつサムネイルを生成する方法

はじめに

今回はPHPの話題です。
「透かしを入れつつサムネイルを作るツール」を作る必要が出てきました。
まぁきっと次に似たような処理を作る日が来るかも…!ということで、記事化しておきました。
ソースだけです。動くモノは公開していませんので、あしからず…

PHPのコード

サムネイル化&透かし印字するクラス

下記のようにしました。

<?php
define("MAX_WIDTH", 960);
define("MAX_HEIGHT", 720);

class CreateWatermarkedThumbnail{

	// REQUIRE
	private $dest_root_path = "";
	private $img_watermark = "";

	// OPTIONAL
	private $wm_width = 0;
	private $wm_height = 0;
	private $wm_opacity = 50;
	private $wm_margin_right = 8;
	private $wm_margin_bottom = 8;
	private $quality = 85;
	private $delete_original = 0;
	private $prefix = "";

	function __construct($dest, $wm, $params){
		// REQUIRE!!
		$this->dest_root_path = $dest;
		$this->img_watermark = imagecreatefrompng($wm); // watermarkをimgとして生成しておく. 何度も使うし

		// OPTIONAL
		if($params["quality"]) $this->quality = $params["quality"];
		if($params["wm_opacity"]) $this->wm_opacity = $params["wm_opacity"];
		if($params["wm_margin_right"]) $this->wm_margin_right = $params["wm_margin_right"];
		if($params["wm_margin_bottom"]) $this->wm_margin_bottom = $params["wm_margin_bottom"];
		if($params["delete_original"]) $this->delete_original = $params["delete_original"];
		if($params["prefix"]) $this->prefix = $params["prefix"];

		$this->wm_width = imagesx($this->img_watermark);
		$this->wm_height = imagesy($this->img_watermark);
	}

	public function createImg($src){

		// function output
		$result = array(
			"main_path"=> "",
			"is_deleted"=> false, 
			"return_cd"=> 0,
			"msg"=> ""
		);
		
		// dest path
		$src_filename = basename($src);
		$dest_main_path = $this->dest_root_path.$this->prefix.$src_filename;

		// inut source
		$im_orig = imagecreatefromjpeg($src);

		// 基データのw/hを保存
		$orig_width = imagesx($im_orig);
		$orig_height = imagesy($im_orig);

		// 一旦リサイズ値を初期化しておく
		$resized_x = MAX_WIDTH;
		$resized_y = MAX_HEIGHT;

		$rate = 1.0;

		// 横
		if($orig_width > $orig_height){
			$rate = ($orig_height / $orig_width);
			$resized_y = round(MAX_WIDTH * $rate);
		}
		// 縦
		else{
			$rate = ($orig_width / $orig_height);
			$resized_x = round(MAX_HEIGHT * $rate);
		}

		// output canvas
		$im = imagecreatetruecolor($resized_x, $resized_y);

		// resize
		if(
			!imagecopyresampled(
				$im, $im_orig, // 出力/入力
				0, 0, // 出力側x,y
				0, 0, // 入力側x,y
				$resized_x, $resized_y, // 出力側size
				$orig_width, $orig_height // 入力側size
			)
		)
		{
			// error...
			$result["return_cd"] = 9;
			$result["msg"] = "fatal step1";
			return $result;
		}

		// overlap
		if(
			!imagecopy(
				$im,
				$this->img_watermark,
				imagesx($im) - $this->wm_width - $this->wm_margin_right, imagesy($im) - $this->wm_height - $wm_margin_bottom, // 重ね合わせ開始x,y
				0, 0,
				$this->wm_width, $this->wm_height
			)
		)
		{
			// error...
			$result["return_cd"] = 9;
			$result["msg"] = "fatal step2";
			return $result;
		}

		// 出力
		if(imagejpeg($im, $dest_main_path, $this->quality)){
			// image output success!!
			$result["main"] = $dest_main_path;
			$result["is_deleted"] = false;

			// 一応元データを削除する
			if($this->delete_original == 1){
				// 失敗しても本処理の結果には影響を与えないことにします
				$result["is_deleted"] = unlink($src);
			}
		}

		return $result;
	}
	
}

?>

使い方

使い方は、下記のようにまずCreateWatermarkedThumbnailクラスをインスタンス化します。
第1引数は、変換後画像の出力フォルダ(相対パスでok)、
第2引数は、透かし画像へのパス(相対パスでok)
第3引数は、出力画像の品質などのパラメータを連想配列で渡します。

第1, 2引数は必須で、第3引数はお好みです。与えなくても良いです。
第3引数のパラメータは下記のようなものが与えられます。

$generator = new CreateWatermarkedThumbnail(
	"./output/", 
	"../images/wm02_w_320.png",
	array(
		"quality"=>"85",			// 品質(0-100)
		"wm_opacity"=>"70",			// 透明度(0-100)
		"wm_margin_right"=>"8",		// 透かし位置(右端からのピクセル数)
		"wm_margin_bottom"=>"12",	// 透かし位置(下端からのピクセル数)
		"delete_original"=>"0", 	// オリジナル画像を削除するか(1:する, 0:しない)
		"prefix"=>"thumb_" 				// 出力ファイルに付与するprefix文字列
	)
);

で、実際に画像のサムネイル化&透かし入れする時は、下記のようにcreateImgメソッドをコールします。

$generator->createImg($path);

はい。以上です。
申し訳ないのですが、出力画像の幅, 高さはパラメータとして与えられるようになっておらず、ソース先頭でconst定義しています。
(私の使い道では、出力画像サイズは絶対に変らない想定だったので)

かんたんにソースの説明

PHPには、なんと素晴らしいことに、簡単にリサイズできる関数や、簡単に画像重ね合わせできる関数が存在します。本当に素晴らしい!

大まかなフローは下記の通りです。

透かし画像をロード(imagecreatefrompng関数)

入力画像をロード(imagecreatefromjpeg関数)

リサイズ(imagecopyresampled関数)

透かし入れ込み(imagecopy関数)

出力(imagejpeg関数)

imagecreatefromXXX関数は、XXX拡張子の画像をロードする関数です。引数に読み込みたいファイルパスを渡すだけのシンプルな関数ですね。

imagecopyresampled関数は、画像を再サンプリングして新しい画像を返却するものです。縮小時はいい感じに補完を行ってくれますので、割と画像が荒れません。すごい。
引数の詳しい説明などは本家のページでご確認下さい。

imagecopy関数は、dst画像にsrc画像をコピーする関数です。
dst側に透かしを入れこまれる側の画像を指定しておけば、重ね合わせてくれる便利機能があります。
その他の詳しいパラメータは本家のページでご確認下さい。

本当に…便利ですね。素晴らしいです。

使う側のサンプル

と書かれても、いまいち使い方が分からないと思いますので、サンプルphpも書いておきます。
下記サンプルは、とあるフォルダ以下にある全ての画像ファイルをサムネイル化&透かし入れ込みするためのソースです。

<?php
// img操作クラス
require("./CreateWatermarkedThumbnail.php");

// 最大処理数
define("MAX_FETCH_FILE", 24);

echo "Resize & Append Watermark Start!!";


// imgHandler生成
$generator = new CreateWatermarkedThumbnail(
	"./output/", 
	"../images/wm02_w_320.png",
	array(
		"quality"=>"85",			// 品質(0-100)
		"wm_opacity"=>"70",			// 透明度(0-100)
		"wm_margin_right"=>"8",		// 透かし位置(右端からのピクセル数)
		"wm_margin_bottom"=>"12",	// 透かし位置(下端からのピクセル数)
		"delete_original"=>"0", 	// オリジナル画像を削除するか(1:する, 0:しない)
		"prefix"=>"thumb_" 				// 出力ファイルに付与するprefix文字列
	)
);

// main process
$input_dir = "./input/";

// 入力ファイルを取得するためにscandirする
$files = scandir($input_dir);

// 念のため。最大ループ数を決めておく
$loop_max = (count($files) > MAX_FETCH_FILE) ? MAX_FETCH_FILE : count($files);
$exec_count = 0;

// 出力結果のファイルパスを納める
$result_filepath = array();

//メイン処理
for($i = 0; $i < $loop_max; $i++){
	$file = $files[$i];
	// 変換対象のファイル
	$path = $input_dir.$file;

	// 対象がファイルなら
	if(!is_dir($path)){
		// 変換実行. 処理結果のパスを格納
		$result = $generator->createImg($path);
		echo "file created. path=".$result;
	}
}

?>

 

はい。今回は以上です。

 

追記:

php本家に、画像イメージは明示的に解放しなくても、処理終了時に解放するよ、とあったので、imagedestroy関数はコールしていません。気になる方は呼び出してください。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です