هل يمكن الحفاظ على شفافية صورة PNG عند استخدام PHP's GDlib imagecopyresampled؟

StackOverflow https://stackoverflow.com/questions/32243

سؤال

يستخدم مقتطف كود PHP التالي GD لتغيير حجم ملف PNG الذي تم تحميله بواسطة المتصفح إلى 128x128.إنه يعمل بشكل رائع، باستثناء أنه تم استبدال المناطق الشفافة في الصورة الأصلية بلون أسود خالص في حالتي.

بالرغم من imagesavealpha تم تعيين شيء ما ليس صحيحًا تمامًا.

ما هي أفضل طريقة للحفاظ على الشفافية في الصورة المعاد تشكيلها؟

$uploadTempFile = $myField[ 'tmp_name' ]
list( $uploadWidth, $uploadHeight, $uploadType ) 
  = getimagesize( $uploadTempFile );

$srcImage = imagecreatefrompng( $uploadTempFile );    
imagesavealpha( $targetImage, true );

$targetImage = imagecreatetruecolor( 128, 128 );
imagecopyresampled( $targetImage, $srcImage, 
                    0, 0, 
                    0, 0, 
                    128, 128, 
                    $uploadWidth, $uploadHeight );

imagepng(  $targetImage, 'out.png', 9 );
هل كانت مفيدة؟

المحلول

imagealphablending( $targetImage, false );
imagesavealpha( $targetImage, true );

فعلت ذلك بالنسبة لي.شكرا سيجايوز.

لاحظ أن الصورة المستهدفة تحتاج إلى إعدادات ألفا، وليس الصورة المصدر.

يحرر:رمز الاستبدال الكامل.انظر أيضًا الإجابات أدناه وتعليقاتها.ليس من المؤكد أن يكون هذا مثاليًا بأي شكل من الأشكال، ولكنه حقق احتياجاتي في ذلك الوقت.

$uploadTempFile = $myField[ 'tmp_name' ]
list( $uploadWidth, $uploadHeight, $uploadType ) 
  = getimagesize( $uploadTempFile );

$srcImage = imagecreatefrompng( $uploadTempFile ); 

$targetImage = imagecreatetruecolor( 128, 128 );   
imagealphablending( $targetImage, false );
imagesavealpha( $targetImage, true );

imagecopyresampled( $targetImage, $srcImage, 
                    0, 0, 
                    0, 0, 
                    128, 128, 
                    $uploadWidth, $uploadHeight );

imagepng(  $targetImage, 'out.png', 9 );

نصائح أخرى

لماذا تجعل الأمور معقدة للغاية؟ما يلي هو ما أستخدمه وقد قام بالمهمة نيابةً عني حتى الآن.

$im = ImageCreateFromPNG($source);
$new_im = imagecreatetruecolor($new_size[0],$new_size[1]);
imagecolortransparent($new_im, imagecolorallocate($new_im, 0, 0, 0));
imagecopyresampled($new_im,$im,0,0,0,0,$new_size[0],$new_size[1],$size[0],$size[1]);

أعتقد أن هذا يجب أن يفعل الخدعة:

$srcImage = imagecreatefrompng($uploadTempFile);
imagealphablending($srcImage, false);
imagesavealpha($srcImage, true);

يحرر: يدعي شخص ما في مستندات PHP imagealphablending يجب أن يكون صحيحا، وليس كاذبا.YMMV.

إضافة قد تفيد البعض:

من الممكن تبديل مزج الحروف الأبجدية أثناء إنشاء الصورة.في الحالة المحددة التي كنت بحاجة فيها إلى ذلك، كنت أرغب في دمج بعض صور PNG شبه الشفافة على خلفية شفافة.

قم أولاً بتعيين imagealphablending على false وملء الصورة الملونة الحقيقية التي تم إنشاؤها حديثًا بلون شفاف.إذا كان imagealphablending صحيحًا، فلن يحدث شيء لأن التعبئة الشفافة ستندمج مع الخلفية الافتراضية السوداء وينتج عنها اللون الأسود.

ثم تقوم بتبديل imagealphablending إلى true وإضافة بعض صور PNG إلى اللوحة القماشية، مع ترك بعض الخلفية مرئية (على سبيل المثال.لا تملأ الصورة بأكملها).

والنتيجة هي صورة بخلفية شفافة والعديد من صور PNG المدمجة.

لقد قمت بإنشاء وظيفة لتغيير حجم الصورة مثل JPEG/GIF/PNG باستخدام copyimageresample ولا تزال صور PNG تحافظ على الشفافية:

$myfile=$_FILES["youimage"];

function ismyimage($myfile) {
    if((($myfile["type"] == "image/gif") || ($myfile["type"] == "image/jpg") || ($myfile["type"] == "image/jpeg") || ($myfile["type"] == "image/png")) && ($myfile["size"] <= 2097152 /*2mb*/) ) return true; 
    else return false;
}

function upload_file($myfile) {         
    if(ismyimage($myfile)) {
        $information=getimagesize($myfile["tmp_name"]);
        $mywidth=$information[0];
        $myheight=$information[1];

        $newwidth=$mywidth;
        $newheight=$myheight;
        while(($newwidth > 600) || ($newheight > 400 )) {
            $newwidth = $newwidth-ceil($newwidth/100);
            $newheight = $newheight-ceil($newheight/100);
        } 

        $files=$myfile["name"];

        if($myfile["type"] == "image/gif") {
            $tmp=imagecreatetruecolor($newwidth,$newheight);
            $src=imagecreatefromgif($myfile["tmp_name"]);
            imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $mywidth, $myheight);
            $con=imagegif($tmp, $files);
            imagedestroy($tmp);
            imagedestroy($src);
            if($con){
                return true;
            } else {
                return false;
            }
        } else if(($myfile["type"] == "image/jpg") || ($myfile["type"] == "image/jpeg") ) {
            $tmp=imagecreatetruecolor($newwidth,$newheight);
            $src=imagecreatefromjpeg($myfile["tmp_name"]); 
            imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $mywidth, $myheight);
            $con=imagejpeg($tmp, $files);
            imagedestroy($tmp);
            imagedestroy($src);
            if($con) {  
                return true;
            } else {
                return false;
            }
        } else if($myfile["type"] == "image/png") {
            $tmp=imagecreatetruecolor($newwidth,$newheight);
            $src=imagecreatefrompng($myfile["tmp_name"]);
            imagealphablending($tmp, false);
            imagesavealpha($tmp,true);
            $transparent = imagecolorallocatealpha($tmp, 255, 255, 255, 127);
            imagefilledrectangle($tmp, 0, 0, $newwidth, $newheight, $transparent); 
            imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $mywidth, $myheight);
            $con=imagepng($tmp, $files);
            imagedestroy($tmp);
            imagedestroy($src);
            if($con) {
                return true;
            } else {
                return false;
            }
        }   
    } else
          return false;
}

أفترض أن هذا قد يؤدي إلى الحيلة:

$uploadTempFile = $myField[ 'tmp_name' ]
list( $uploadWidth, $uploadHeight, $uploadType ) 
  = getimagesize( $uploadTempFile );

$srcImage = imagecreatefrompng( $uploadTempFile );

$targetImage = imagecreatetruecolor( 128, 128 );

$transparent = imagecolorallocate($targetImage,0,255,0);
imagecolortransparent($targetImage,$transparent);
imagefilledrectangle($targetImage,0,0,127,127,$transparent);

imagecopyresampled( $targetImage, $srcImage, 
                    0, 0, 
                    0, 0, 
                    128, 128, 
                    $uploadWidth, $uploadHeight );

imagepng(  $targetImage, 'out.png', 9 );

الجانب السلبي هو أنه سيتم تجريد الصورة من كل بكسل أخضر بنسبة 100٪.على أية حال، نأمل أن يساعد :)

إعادة تصنيف الحفاظ على الشفافية، ثم نعم كما هو مذكور في المنشورات الأخرى يجب تعيين imagesavealpha() على true، لاستخدام علامة ألفا imagealphablending() يجب تعيينها على false وإلا فلن يعمل.

لقد لاحظت أيضًا شيئين بسيطين في شفرتك:

  1. لا تحتاج إلى الاتصال getimagesize() للحصول على العرض/الارتفاع ل imagecopyresmapled()
  2. ال $uploadWidth و $uploadHeight يجب ان يكون -1 القيمة، حيث أن الإحداثيات تبدأ من 0 و لا 1, ، لذلك سيتم نسخها إلى بكسل فارغ.استبداله بـ: imagesx($targetImage) - 1 و imagesy($targetImage) - 1, ، ينبغي أن تفعل نسبيا :)

هنا هو رمز الاختبار الإجمالي الخاص بي.إنه يعمل بالنسبة لي

$imageFileType = pathinfo($_FILES["image"]["name"], PATHINFO_EXTENSION);
$filename = 'test.' . $imageFileType;
move_uploaded_file($_FILES["image"]["tmp_name"], $filename);

$source_image = imagecreatefromjpeg($filename);

$source_imagex = imagesx($source_image);
$source_imagey = imagesy($source_image);

$dest_imagex = 400;
$dest_imagey = 600;
$dest_image = imagecreatetruecolor($dest_imagex, $dest_imagey);

imagecopyresampled($dest_image, $source_image, 0, 0, 0, 0, $dest_imagex, $dest_imagey, $source_imagex, $source_imagey);

imagesavealpha($dest_image, true);
$trans_colour = imagecolorallocatealpha($dest_image, 0, 0, 0, 127);
imagefill($dest_image, 0, 0, $trans_colour);

imagepng($dest_image,"test1.png",1);

انتبه إلى الصورة المصدر width و height القيم التي تم تمريرها إلى imagecopyresampled وظيفة.إذا كانت أكبر من حجم الصورة المصدر الفعلي، فسيتم ملء بقية مساحة الصورة باللون الأسود.

لقد قمت بدمج الإجابات من ceejayoz وCheekysoft، والتي أعطت أفضل نتيجة بالنسبة لي.بدون imagealphablending() وimagesavealpha() الصورة غير واضحة:

$img3 = imagecreatetruecolor(128, 128);
imagecolortransparent($img3, imagecolorallocate($img3, 0, 0, 0));
imagealphablending( $img3, false );
imagesavealpha( $img3, true );
imagecopyresampled($img3, $srcImage, 0, 0, 0, 0, 128, 128, $uploadWidth, $uploadHeight);
imagepng($img3, 'filename.png', 9);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top