क्या PHP के GDlib imagecopyresampled का उपयोग करते समय PNG छवि पारदर्शिता संरक्षित की जा सकती है?


101

निम्न 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 );

जवाबों:


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

मेरे लिए किया। धन्यवाद ceejayoz।

ध्यान दें, लक्ष्य छवि को अल्फा सेटिंग्स की आवश्यकता होती है, न कि स्रोत छवि की।

संपादित करें: पूर्ण प्रतिस्थापन कोड। नीचे दिए गए जवाब और उनकी टिप्पणियों को भी देखें। यह किसी भी तरह से परिपूर्ण होने की गारंटी नहीं है, लेकिन उस समय मेरी जरूरतों को पूरा किया।

$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 );

5
FIY, यह लक्ष्य छवि बनाए जाने के बाद होना चाहिए। इस मामले में, यह imagecreatetruecolor के बाद होगा।
राइजिंगसुन

आश्चर्य है कि alphablending = falseयहाँ क्यों महत्वपूर्ण है? डॉक्टर ने कहा है ... " imagealphablending($im, false)इसका उपयोग करने के लिए आपको वर्णमाला ( ) को खोलना होगा।"
अठारह

2
न केवल यह उत्तर सही और उपयोगी है, यह विशेष रूप से सहायक है क्योंकि PHP डॉक्स पर पहली टिप्पणी (लिखने के समय) के लिए imagecreatefrompng()सुझाव है कि imagealphablendingसेट किया जाना चाहिए true, जो स्पष्ट रूप से गलत है। बहुत धन्यवाद।
spikyjt

3
यह समाधान, मेरे मामले में GD ठीक ही काम करता है, यदि PNG में एक "नियमित" पारदर्शिता क्षेत्र है, जैसे कि आसपास का पारदर्शी क्षेत्र, यदि इसका कोई जटिल क्षेत्र है, जैसे कि पारदर्शिता के साथ छवि के आंतरिक भाग, यह हमेशा विफल रहता है और काली पृष्ठभूमि डालता है , उदाहरण के लिए यह छवि विफल होती है: seomofo.com/downloads/new-google-logo-knockoff.png । क्या कोई इसकी कोशिश कर सकता है और पुष्टि कर सकता है?
anesede

2
कुछ पारदर्शी png फ़ाइलों के साथ काम करने के लिए प्रतीत नहीं होता है। मैंने एक jpg से एक इमेज बनाने की कोशिश की और एक पारदर्शी png को अंदर कॉपी किया। जैसा कि एसेडेड बताते हैं कि परिणाम एक काला वर्ग है।
RubbelDeCatc

21

आप चीजों को इतना जटिल क्यों बनाते हैं? निम्नलिखित वह है जो मैं उपयोग करता हूं और अब तक इसने मेरे लिए काम किया है।

$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]);

काम नहीं किया, मुझे अभी भी इस छवि के साथ काली पृष्ठभूमि मिलती है: seomofo.com/downloads/new-google-logo-knockoff.png
anesede

दोनों समाधानों की कोशिश कर रहा था: आपका और 150 से अधिक वोटों वाला। आपका समाधान GIF के लिए बहुत अच्छा काम करता है। उपरोक्त एक पीएनजी फाइलों के साथ सबसे अच्छा काम करता है, जबकि आपका समाधान एंटी-अलियासिंग खो रहा है जो आप थंबनेल बनाने में सबसे अच्छा देख सकते हैं (अवरुद्ध, पिक्सेलयुक्त दिखता है)।
जॉनी

11

मेरा मानना ​​है कि इस चाल को करना चाहिए:

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

संपादित करें: PHP डॉक्स के दावों में से किसी को imagealphablendingसच होना चाहिए, न कि झूठ। YMMV।


2
imagealphablendingसही या गलत का उपयोग करने से मुझे हमेशा एक काली पृष्ठभूमि मिलती है।
anesede

PHP7 - मेरे लिए काम
Yehonatan

इसके साथ खेला (PHP 7.x): पीएनजी: कल्पनाशील ($ लक्ष्य, झूठी); // अगर पीएनजी पर सच है: काली पृष्ठभूमि GIF: कल्पनाशील ($ targetImage, सच); // अगर जीआईएफ पर गलत है: काली पृष्ठभूमि
जॉनी

9

एक अतिरिक्त जो कुछ लोगों की मदद कर सकता है:

छवि का निर्माण करते समय कल्पनाशीलता को टॉगल करना संभव है। मुझे जिस विशिष्ट मामले की आवश्यकता थी, मैं पारदर्शी पृष्ठभूमि पर पीएनजी के कुछ अर्ध-पारदर्शी संयोजन करना चाहता था।

पहले आप कल्पना को झूठी बनाने के लिए सेट करें और एक पारदर्शी रंग के साथ नई बनाई गई सच्ची रंगीन छवि भरें। यदि कल्पनाशीलता सही थी, तो कुछ भी नहीं होगा क्योंकि पारदर्शी भरण काला डिफ़ॉल्ट पृष्ठभूमि के साथ विलीन हो जाएगा और परिणामस्वरूप काला होगा।

तब आप कल्पना को सच करने के लिए टॉगल करते हैं और कैनवास पर कुछ पीएनजी छवियों को जोड़ते हैं, जिससे कुछ दृश्यमान दिखाई देते हैं (यानी पूरी छवि को नहीं भरते हैं)।

परिणाम एक पारदर्शी पृष्ठभूमि और कई संयुक्त PNG छवियों के साथ एक छवि है।


6

मैंने 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;
}

3
प्रश्न में कोड के ऊपर इस कोड में पारदर्शिता क्यों संरक्षित है यह जानने के लिए सभी कोड के माध्यम से पढ़ना बेहतर है।
एह

मैंने इन दो पंक्तियों को छोड़ दिया और यह अभी भी काम कर रहा है: $transparent = imagecolorallocatealpha($tmp, 255, 255, 255, 127); imagefilledrectangle($tmp, 0, 0, $newwidth, $newheight, $transparent);
santiago arizti

यह उत्तर बहुत कुछ दिखता है जैसे stackoverflow.com/a/279310/470749
रयान

5

मुझे लगता है कि यह चाल हो सकती है:

$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% हरे रंग के पिक्सेल से छीन लिया जाएगा। किसी भी तरह, आशा है कि यह मदद करता है :)


यदि आप एक बहुत ही बदसूरत रंग के लिए सेट है कि लगभग कोई छवि का उपयोग करेगा यह बहुत उपयोगी हो सकता है।
कोरी

1
स्वीकृत जवाब मेरे काम नहीं आया। imagecreate(...)हालांकि काम के साथ इस जवाब का उपयोग करना । आप एक छवि बनाते हैं, जो आपके द्वारा आवंटित पहले रंग से भर जाती है। फिर आप उस रंग को पारदर्शी सेट करें। यदि लक्ष्य छवि के लिए अक्षरांकन को सही पर सेट किया जाता है, तो दोनों छवियों को मिला दिया जाएगा और पारदर्शिता सही ढंग से काम करती है।
सुमुरै 8

2

संरक्षित पारदर्शिता के संबंध में, फिर हाँ जैसे अन्य पदों में कहा गया है imagesavealpha () को सही पर सेट किया जाना है, अल्फा फ्लैग का उपयोग करने के लिए इमेजेलेप्लडिंग () को झूठे सेट करना होगा और यह काम नहीं करता है।

इसके अलावा, मैंने आपके कोड में दो छोटी चीजें देखीं:

  1. के getimagesize()लिए चौड़ाई / ऊँचाई प्राप्त करने के लिए आपको कॉल करने की आवश्यकता नहीं हैimagecopyresmapled()
  2. $uploadWidthऔर $uploadHeightकिया जाना चाहिए -1के बाद से cordinates पर शुरू होता है, मूल्य 0और नहीं 1, तो यह उन्हें एक खाली पिक्सेल में नक़ल की। इसके साथ प्रतिस्थापित: imagesx($targetImage) - 1और imagesy($targetImage) - 1, सापेक्ष रूप से करना चाहिए :)

0

यहाँ मेरा कुल परीक्षण कोड है। इससे मेरा काम बनता है

$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);

0

स्रोत छवि widthऔर उन heightमानों पर ध्यान दें जो imagecopyresampledकार्य करने के लिए पारित किए गए हैं। यदि वे वास्तविक स्रोत छवि आकार से बड़े हैं, तो शेष छवि क्षेत्र काले रंग से भर जाएगा।


0

मैंने ceejayoz और Cheekysoft के उत्तरों को संयोजित किया, जिसने मेरे लिए सबसे अच्छा परिणाम दिया। इमेजिफ़ेलब्लेंडिंग () और इमेजेवलेफा () के बिना छवि स्पष्ट नहीं है:

$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);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.