Skip to content

Commit 83d234a

Browse files
committed
サムネイル作成処理の共通化。PHP8.5テスト通過。
1 parent e8df0f4 commit 83d234a

1 file changed

Lines changed: 205 additions & 131 deletions

File tree

logexporter/petit2poti/petit2poti.php

Lines changed: 205 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@
132132
chmod("poti/src/{$time}{$ext}",PERMISSION_FOR_DEST);
133133
}
134134
$thumbnail="";
135-
if(thumb("src/",$imgfile,$time,$w,$h)){
135+
if(thumbnail_gd::thumb("src/",$imgfile,$time,$w,$h)){
136136
$thumbnail='thumbnail';
137137
}
138138
}
@@ -295,174 +295,248 @@ function check_pch_ext ($filepath) {
295295
return '';
296296
}
297297

298-
//GD版が使えるかチェック
299-
function gd_check(){
300-
$check = array("ImageCreate","ImageCopyResized","ImageCreateFromJPEG","ImageJPEG");
298+
// thumbnail_gd.inc.php for PetitNote (C)さとぴあ @satopian 2021 - 2025
299+
// https://paintbbs.sakura.ne.jp/
300+
// originalscript (C)SakaQ 2005 http://www.punyu.net/php/
301301

302-
//最低限のGD関数が使えるかチェック
303-
if(get_gd_ver() && (ImageTypes() & IMG_JPG)){
304-
foreach ( $check as $cmd ) {
305-
if(!function_exists($cmd)){
306-
return false;
302+
$thumbnail_gd_ver=20250707;
303+
// defined('PERMISSION_FOR_DEST') or define('PERMISSION_FOR_DEST', 0606); //config.phpで未定義なら0606
304+
class thumbnail_gd {
305+
306+
public static function thumb($path,$fname,$time,$max_w,$max_h,$options=[]): ?string {
307+
// $path=basename($path).'/';
308+
$fname=basename($fname);
309+
$time=basename($time);
310+
if(!ctype_digit($time)) {
311+
return null;
312+
}
313+
$fname=$path.$fname;
314+
if(!is_file($fname)){
315+
return null;
316+
}
317+
if(!self::gd_check()||!function_exists("ImageCreate")||!function_exists("ImageCreateFromJPEG")){
318+
return null;
319+
}
320+
if((isset($options['webp'])||isset($options['thumbnail_webp'])) && !function_exists("ImageWEBP")){
321+
return null;
322+
}
323+
324+
$fsize = filesize($fname); // ファイルサイズを取得
325+
list($w,$h) = GetImageSize($fname); // 画像の幅と高さを取得
326+
$w_h_size_over = $max_w && $max_h && ($w > $max_w || $h > $max_h);
327+
$f_size_over = !isset($options['toolarge']) ? ($fsize>1024*1024) : false;
328+
if(!$w_h_size_over && !$f_size_over && !isset($options['webp']) && !isset($options['png2webp']) && !isset($options['png2jpeg'])){
329+
return null;
330+
}
331+
if(!$w_h_size_over || isset($options['png2jpeg']) || isset($options['png2webp']) || !$max_w || !$max_h){//リサイズしない
332+
$out_w = $w;
333+
$out_h = $h;
334+
}else{// リサイズ
335+
$w_ratio = $max_w / $w;
336+
$h_ratio = $max_h / $h;
337+
$ratio = min($w_ratio, $h_ratio);
338+
$out_w = ceil($w * $ratio);//端数の切り上げ
339+
$out_h = ceil($h * $ratio);
340+
}
341+
342+
$mime_type = mime_content_type($fname);
343+
if(!$im_in = self::createImageResource($fname,$mime_type)){
344+
return null;
345+
};
346+
// 出力画像(サムネイル)のイメージを作成
347+
if(function_exists("ImageCreateTrueColor")){
348+
$im_out = ImageCreateTrueColor($out_w, $out_h);
349+
350+
if(self::isTransparencyEnabled($options, $mime_type)){//透明度を扱う時
351+
imagealphablending($im_out, false);
352+
imagesavealpha($im_out, true);//透明
353+
}else{//透明度を扱わない時
354+
if(function_exists("ImageColorAlLocate") && function_exists("imagefill")){
355+
$background = ImageColorAlLocate($im_out, 0xFF, 0xFF, 0xFF);//背景色を白に
356+
imagefill($im_out, 0, 0, $background);
357+
}
307358
}
359+
360+
}else{
361+
$im_out = ImageCreate($out_w, $out_h);
308362
}
309-
}else{
310-
return false;
311-
}
312363

313-
return true;
314-
}
364+
// コピー&再サンプリング&縮小
365+
if(function_exists("ImageCopyResampled")){
366+
ImageCopyResampled($im_out, $im_in, 0, 0, 0, 0, $out_w, $out_h, $w, $h);
367+
}else{
368+
ImageCopyResized($im_out, $im_in, 0, 0, 0, 0, $out_w, $out_h, $w, $h);//"ImageCopyResampled"が無効の時
369+
}
315370

316-
//gdのバージョンを調べる
317-
function get_gd_ver(){
318-
if(function_exists("gd_info")){
319-
$gdver=gd_info();
320-
$phpinfo=$gdver["GD Version"];
321-
$end=strpos($phpinfo,".");
322-
$phpinfo=substr($phpinfo,0,$end);
323-
$length = strlen($phpinfo)-1;
324-
$phpinfo=substr($phpinfo,$length);
325-
return $phpinfo;
326-
}
327-
return false;
328-
}
371+
if(isset($options['toolarge'])){
372+
$outfile = self::overwriteResizedImage($im_out, $fname, $mime_type);
373+
}else{
374+
$outfile = self::createThumbnailImage($im_out, $time, $options);
375+
}
376+
// 作成したイメージを破棄
377+
self::safeImageDestroy($im_in);
378+
self::safeImageDestroy($im_out);
379+
380+
if(!$outfile){
381+
return null;
382+
}
383+
384+
if(!chmod($outfile,PERMISSION_FOR_DEST)){
385+
return null;
386+
}
387+
388+
if(is_file($outfile)){
389+
return $outfile;
390+
}
391+
return null;
329392

330-
function thumb($path,$fname,$time,$max_w,$max_h,$options=[]){
331-
$path='src/';
332-
$fname=basename($fname);
333-
$time=basename($time);
334-
$fname=$path.$fname;
335-
if(!is_file($fname)){
336-
return;
337-
}
338-
if(!gd_check()||!function_exists("ImageCreate")||!function_exists("ImageCreateFromJPEG")){
339-
return;
340393
}
341-
if((isset($options['webp'])||isset($options['thumbnail_webp'])) && (!function_exists("ImageWEBP")||version_compare(PHP_VERSION, '7.0.0', '<'))){
342-
return;
394+
//GD版が使えるかチェック
395+
private static function gd_check(): bool {
396+
// GDモジュールが有効化されているか
397+
if (!extension_loaded('gd')) {
398+
return false;
399+
}
400+
// GDモジュールが動作可能か
401+
if (!function_exists('gd_info')) {
402+
return false;
403+
}
404+
// JPEGのサポートを確認
405+
if (!(ImageTypes() & IMG_JPG)) {
406+
return false;
407+
}
408+
// JPEG出力関数の存在を確認
409+
if (!function_exists('ImageJPEG')) {
410+
return false;
411+
}
412+
return true;
343413
}
344414

345-
$fsize = filesize($fname); // ファイルサイズを取得
346-
list($w,$h) = GetImageSize($fname); // 画像の幅と高さとタイプを取得
347-
$w_h_size_over=($w > $max_w || $h > $max_h);
348-
$f_size_over=!isset($options['toolarge']) ? ($fsize>1024*1024) : false;
349-
if(!$w_h_size_over && !$f_size_over && !isset($options['webp'])){
350-
return;
415+
//GDのイメージを破棄
416+
private static function safeImageDestroy($gdImage): void {
417+
if(PHP_VERSION_ID < 80000) {//PHP8.0未満の時は
418+
imagedestroy($gdImage);
419+
}
351420
}
352-
// リサイズ
353-
$w_ratio = $max_w / $w;
354-
$h_ratio = $max_h / $h;
355-
$ratio = min($w_ratio, $h_ratio);
356-
$out_w = $w_h_size_over ? ceil($w * $ratio):$w;//端数の切り上げ
357-
$out_h = $w_h_size_over ? ceil($h * $ratio):$h;
358-
359-
switch ($mime_type = mime_content_type($fname)) {
360-
case "image/gif":
361-
if(!function_exists("ImageCreateFromGIF")){//gif
362-
return;
363-
}
364-
$im_in = @ImageCreateFromGIF($fname);
365-
if(!$im_in)return;
366-
367-
break;
368-
case "image/jpeg":
369-
$im_in = @ImageCreateFromJPEG($fname);//jpg
370-
if(!$im_in)return;
371-
break;
372-
case "image/png":
373-
if(!function_exists("ImageCreateFromPNG")){//png
374-
return;
375-
}
376-
$im_in = @ImageCreateFromPNG($fname);
377-
if(!$im_in)return;
378-
break;
379-
case "image/webp":
380-
if(!function_exists("ImageCreateFromWEBP")||version_compare(PHP_VERSION, '7.0.0', '<')){//webp
381-
return;
382-
}
383-
$im_in = @ImageCreateFromWEBP($fname);
384-
if(!$im_in)return;
385-
break;
386421

387-
default : return;
422+
// 透明度の処理を行う必要があるかを判断
423+
private static function isTransparencyEnabled($options, $mime_type): bool {
424+
// 透明度を扱うオプションが設定されているか確認
425+
$transparencyOptionsSet = isset($options['toolarge']) || isset($options['webp']) || isset($options['thumbnail_webp']) || isset($options['png2webp']);
426+
427+
// 対象の画像形式で透明度がサポートされているか確認
428+
$transparencySupportedFormats = ["image/png", "image/gif", "image/webp"];
429+
430+
// 透明度を扱うための関数が存在するか確認
431+
$transparencyFunctionsAvailable = function_exists("imagealphablending") && function_exists("imagesavealpha");
432+
433+
return $transparencyOptionsSet && in_array($mime_type, $transparencySupportedFormats) && $transparencyFunctionsAvailable;
388434
}
389-
// 出力画像(サムネイル)のイメージを作成
390-
$exists_ImageCopyResampled = false;
391-
if(function_exists("ImageCreateTrueColor")&&get_gd_ver()=="2"){
392-
$im_out = ImageCreateTrueColor($out_w, $out_h);
393-
if((isset($options['toolarge'])||isset($options['webp'])||isset($options['thumbnail_webp'])) && in_array($mime_type,["image/png","image/gif","image/webp"])){
394-
if(function_exists("imagealphablending") && function_exists("imagesavealpha")){
395-
imagealphablending($im_out, false);
396-
imagesavealpha($im_out, true);//透明
397-
}
398-
}else{
399-
if(function_exists("ImageColorAlLocate") && function_exists("imagefill")){
400-
$background = ImageColorAlLocate($im_out, 0xFF, 0xFF, 0xFF);//背景色を白に
401-
imagefill($im_out, 0, 0, $background);
435+
//各画像フォーマットのリソースを作成
436+
private static function createImageResource($fname,$mime_type) {
437+
switch ($mime_type) {
438+
case "image/gif":
439+
if(!function_exists("ImageCreateFromGIF")){//gif
440+
return null;
402441
}
403-
}
404-
// コピー&再サンプリング&縮小
405-
if(function_exists("ImageCopyResampled")){
406-
ImageCopyResampled($im_out, $im_in, 0, 0, 0, 0, $out_w, $out_h, $w, $h);
407-
$exists_ImageCopyResampled = true;
442+
$im_in = @ImageCreateFromGIF($fname);
443+
if(!$im_in)return null;
444+
break;
445+
case "image/jpeg":
446+
$im_in = @ImageCreateFromJPEG($fname);//jpg
447+
if(!$im_in)return null;
448+
break;
449+
case "image/png":
450+
if(!function_exists("ImageCreateFromPNG")){//png
451+
return null;
452+
}
453+
$im_in = @ImageCreateFromPNG($fname);
454+
if(!$im_in)return null;
455+
break;
456+
case "image/webp":
457+
if(!function_exists("ImageCreateFromWEBP")){//webp
458+
return null;
459+
}
460+
$im_in = @ImageCreateFromWEBP($fname);
461+
if(!$im_in)return null;
462+
break;
463+
464+
default : return null;
408465
}
409-
}else{$im_out = ImageCreate($out_w, $out_h);}
410-
// コピー&縮小
411-
if(!$exists_ImageCopyResampled) ImageCopyResized($im_out, $im_in, 0, 0, 0, 0, $out_w, $out_h, $w, $h);
412-
if(isset($options['toolarge'])){
413-
$outfile=$fname;
414-
//本体画像を縮小
466+
return $im_in;
467+
}
468+
469+
//縮小した画像で上書き
470+
private static function overwriteResizedImage($im_out, $fname, $mime_type): ?string {
471+
$outfile=(string)$fname;
472+
//本体画像を縮小
415473
switch ($mime_type) {
416474
case "image/gif":
417475
if(function_exists("ImagePNG")){
418476
ImagePNG($im_out, $outfile,3);
419477
}else{
420478
ImageJPEG($im_out, $outfile,98);
421479
}
422-
break;
480+
return $outfile;
423481
case "image/jpeg":
424482
ImageJPEG($im_out, $outfile,98);
425-
break;
483+
return $outfile;
426484
case "image/png":
427485
if(function_exists("ImagePNG")){
428486
ImagePNG($im_out, $outfile,3);
429487
}else{
430488
ImageJPEG($im_out, $outfile,98);
431489
}
432-
break;
490+
return $outfile;
433491
case "image/webp":
434-
if(function_exists("ImageWEBP")&&version_compare(PHP_VERSION, '7.0.0', '>=')){
492+
if(function_exists("ImageWEBP")){
435493
ImageWEBP($im_out, $outfile,98);
436494
}else{
437495
ImageJPEG($im_out, $outfile,98);
438496
}
439-
break;
497+
return $outfile;
440498

441-
default : return;
499+
default : return null;
442500

443501
}
444-
445-
}elseif(isset($options['webp'])){
446-
$outfile='poti/webp/'.$time.'t.webp';
447-
ImageWEBP($im_out, $outfile,90);
448-
449-
}elseif(isset($options['thumbnail_webp'])){
450-
$outfile='poti/thumb/'.$time.'s.webp';
451-
ImageWEBP($im_out, $outfile,90);
452-
}else{
453-
$outfile='poti/thumb/'.$time.'s.jpg';
454-
// サムネイル画像を保存
455-
ImageJPEG($im_out, $outfile,90);
456-
}
457-
// 作成したイメージを破棄
458-
if(PHP_VERSION_ID < 80000) {//PHP8.0未満の時は
459-
ImageDestroy($im_in);
460-
ImageDestroy($im_out);
461-
}
462-
if(!chmod($outfile,PERMISSION_FOR_DEST)){
463-
return;
464502
}
503+
//サムネイル作成
504+
private static function createThumbnailImage($im_out, $time, $options): ?string {
505+
506+
if(isset($options['png2jpeg'])){
507+
508+
$outfile=TEMP_DIR.$time.'.jpg.tmp';//一時ファイル
509+
ImageJPEG($im_out, $outfile,98);
510+
511+
} elseif(isset($options['png2webp'])){
512+
513+
if(function_exists("ImageWEBP")){
514+
$outfile=TEMP_DIR.$time.'.webp.tmp';//一時ファイル
515+
ImageWEBP($im_out, $outfile,98);
465516

466-
return is_file($outfile);
517+
}else{
518+
$outfile=TEMP_DIR.$time.'.jpg.tmp';//一時ファイル
519+
ImageJPEG($im_out, $outfile,98);
520+
521+
}
522+
523+
} elseif(isset($options['webp'])){
524+
525+
$outfile="poti/webp/{$time}t.webp";
526+
ImageWEBP($im_out, $outfile,90);
527+
528+
}elseif(isset($options['thumbnail_webp'])){
529+
530+
$outfile="poti/thumb/{$time}s.webp";
531+
ImageWEBP($im_out, $outfile,90);
532+
533+
}else{
467534

535+
$outfile="poti/thumb/{$time}s.jpg";
536+
// サムネイル画像を保存
537+
ImageJPEG($im_out, $outfile,90);
538+
539+
}
540+
return $outfile;
541+
}
468542
}

0 commit comments

Comments
 (0)