2011-08-26 9 views
34

मैं एक PHP स्क्रिप्ट है कि एक छवि लेता है बनाने के लिए कोशिश कर रहा हूँ जिनमें शामिल हैं:पीएचपी जी.डी. उपयोग एक और छवि को मास्क करने, पारदर्शिता

image1
http://i.stack.imgur.com/eNvlM.png

और फिर एक PNG छवि लागू होता है:

mask
http://i.stack.imgur.com/iJr2I.png

एक मुखौटा के रूप में

अंतिम परिणाम पारदर्शिता बनाए रखने के लिए की जरूरत है:

result
http://i.stack.imgur.com/u0l0I.png

पर सभी संभव मैं जीडी में ऐसा करना चाहते हैं, ImageMagick नहीं वास्तव में एक विकल्प अभी है।

मैं इसके बारे में कैसे जाऊं?

phalacee's post (in "PHP/GD, how to copy a circle from one image to another?") सही लाइनों के साथ प्रतीत होता है लेकिन मुझे विशेष रूप से एक मुखौटा के रूप में एक छवि का उपयोग करने की आवश्यकता है, आकार नहीं।

उत्तर

48

मैट,

आप अंडाकार सफेद काली पृष्ठभूमि पर बजाय काला भरने पारदर्शी पृष्ठभूमि के साथ भरने निम्नलिखित समारोह यह होता है के साथ अपने png करते हैं।

<?php 
// Load source and mask 
$source = imagecreatefrompng('1.png'); 
$mask = imagecreatefrompng('2.png'); 
// Apply mask to source 
imagealphamask($source, $mask); 
// Output 
header("Content-type: image/png"); 
imagepng($source); 

function imagealphamask(&$picture, $mask) { 
    // Get sizes and set up new picture 
    $xSize = imagesx($picture); 
    $ySize = imagesy($picture); 
    $newPicture = imagecreatetruecolor($xSize, $ySize); 
    imagesavealpha($newPicture, true); 
    imagefill($newPicture, 0, 0, imagecolorallocatealpha($newPicture, 0, 0, 0, 127)); 

    // Resize mask if necessary 
    if($xSize != imagesx($mask) || $ySize != imagesy($mask)) { 
     $tempPic = imagecreatetruecolor($xSize, $ySize); 
     imagecopyresampled($tempPic, $mask, 0, 0, 0, 0, $xSize, $ySize, imagesx($mask), imagesy($mask)); 
     imagedestroy($mask); 
     $mask = $tempPic; 
    } 

    // Perform pixel-based alpha map application 
    for($x = 0; $x < $xSize; $x++) { 
     for($y = 0; $y < $ySize; $y++) { 
      $alpha = imagecolorsforindex($mask, imagecolorat($mask, $x, $y)); 
      $alpha = 127 - floor($alpha[ 'red' ]/2); 
      $color = imagecolorsforindex($picture, imagecolorat($picture, $x, $y)); 
      imagesetpixel($newPicture, $x, $y, imagecolorallocatealpha($newPicture, $color[ 'red' ], $color[ 'green' ], $color[ 'blue' ], $alpha)); 
     } 
    } 

    // Copy back to original picture 
    imagedestroy($picture); 
    $picture = $newPicture; 
} 

?> 
+0

धन्यवाद, यह वास्तव में उपयोगी है – Matt

+0

मुझे पता है कि यह पोस्ट कुछ समय के लिए बंद कर दिया गया है, लेकिन रनटाइम कैसा दिख रहा था जब आप इस स्क्रिप्ट को चलाते थे? यह औसत 20 सेकंड या उससे अधिक समय ले रहा है ... मेरा स्रोत/मुखौटा छवियां 250 x 170px हैं ... क्या आप लोगों के बारे में क्या कर रहे हैं? –

+0

निराश, सुनिश्चित नहीं है कि मैं क्या गलत कर रहा था लेकिन यह अब बहुत अच्छा काम करता है: पी धन्यवाद दोस्तों! –

10

यहाँ इस स्क्रिप्ट के लिए एक छोटे से उन्नयन है - मैंने पाया कि यदि स्रोत छवि पारदर्शिता ही है, मुखौटा (ऊपर स्क्रिप्ट का उपयोग) एक वापस पिक्सेल के बजाय स्रोत छवि के पारदर्शी पिक्सेल भूखंडों। नीचे विस्तारित स्क्रिप्ट स्रोत छवि पारदर्शिता को ध्यान में रखती है, और इसे संरक्षित करती है।

// Load source and mask 
$source = imagecreatefrompng('1.png'); 
$mask = imagecreatefrompng('2.png'); 
// Apply mask to source 
imagealphamask($source, $mask); 
// Output 
header("Content-type: image/png"); 
imagepng($source); 

function imagealphamask(&$picture, $mask) { 
// Get sizes and set up new picture 
$xSize = imagesx($picture); 
$ySize = imagesy($picture); 
$newPicture = imagecreatetruecolor($xSize, $ySize); 
imagesavealpha($newPicture, true); 
imagefill($newPicture, 0, 0, imagecolorallocatealpha($newPicture, 0, 0, 0, 127)); 

// Resize mask if necessary 
if($xSize != imagesx($mask) || $ySize != imagesy($mask)) { 
    $tempPic = imagecreatetruecolor($xSize, $ySize); 
    imagecopyresampled($tempPic, $mask, 0, 0, 0, 0, $xSize, $ySize, imagesx($mask), imagesy($mask)); 
    imagedestroy($mask); 
    $mask = $tempPic; 
} 

// Perform pixel-based alpha map application 
for($x = 0; $x < $xSize; $x++) { 
    for($y = 0; $y < $ySize; $y++) { 
     $alpha = imagecolorsforindex($mask, imagecolorat($mask, $x, $y)); 

      if(($alpha['red'] == 0) && ($alpha['green'] == 0) && ($alpha['blue'] == 0) && ($alpha['alpha'] == 0)) 
      { 
       // It's a black part of the mask 
       imagesetpixel($newPicture, $x, $y, imagecolorallocatealpha($newPicture, 0, 0, 0, 127)); // Stick a black, but totally transparent, pixel in. 
      } 
      else 
      { 

       // Check the alpha state of the corresponding pixel of the image we're dealing with.  
       $alphaSource = imagecolorsforindex($source, imagecolorat($source, $x, $y)); 

       if(($alphaSource['alpha'] == 127)) 
       { 
        imagesetpixel($newPicture, $x, $y, imagecolorallocatealpha($newPicture, 0, 0, 0, 127)); // Stick a black, but totally transparent, pixel in. 
       } 
       else 
       { 
        $color = imagecolorsforindex($source, imagecolorat($source, $x, $y)); 
        imagesetpixel($newPicture, $x, $y, imagecolorallocatealpha($newPicture, $color[ 'red' ], $color[ 'green' ], $color[ 'blue' ], $color['alpha'])); // Stick the pixel from the source image in 
       } 


      } 
    } 
} 

// Copy back to original picture 
imagedestroy($picture); 
$picture = $newPicture; 
} 
9

मुझे आपकी स्क्रिप्ट पसंद है, पिक्सेल पूरी तरह से पारदर्शी होने पर अतिरिक्त रंग जानकारी को निकालने का अच्छा विचार है। मुझे केवल एक छोटी सी त्रुटि (आईएमओ) इंगित करना चाहिए, हालांकि अगर कोई इस विधि का उपयोग करना चाहता है।

$color = imagecolorsforindex($source, imagecolorat($source, $x, $y)); 

होना चाहिए

$color = imagecolorsforindex($picture, imagecolorat($picture, $x, $y)); 

भी मैं 100% यकीन है कि तुम क्यों rgb मूल्यों की जाँच कर रहे यहां अगर पिक्सेल 100% पारदर्शी

if(($alpha['red'] == 0) && ($alpha['green'] == 0) && ($alpha['blue'] == 0) && ($alpha['alpha'] == 0)) 
... 

है नहीं कर रहा हूँ और मैं कर रहा हूँ सुनिश्चित नहीं है कि मास्क फ़ाइल से अल्फा ब्लेंडिंग आपकी विधि के साथ अच्छी तरह से काम करेगी, क्योंकि इसका उपयोग केवल तभी किया जाता है जब आरजीबीए सभी बराबर 0

जे ules की लिपि भी बहुत अच्छी है, हालांकि यह मास्क को मास्क के ग्रे पैमाने का प्रतिनिधित्व करने की अपेक्षा करता है (जो कि बहुत आम प्रथा है)।

मैट की क्वेरी में वह एक ऐसी स्क्रिप्ट के बाद था जो मौजूदा छवि से केवल अल्फा पारदर्शिता को पकड़ता है और इसे किसी अन्य छवि पर लागू करता है। मुखौटा छवि से अल्फा को पकड़ने के लिए जूलस की स्क्रिप्ट का एक सरल तरीका यहां दिया गया है, और स्रोत छवि के अल्फा को सुरक्षित रखें।

<?php 
// Load source and mask 
$source = imagecreatefrompng('1.png'); 
$mask = imagecreatefrompng('2.png'); 
// Apply mask to source 
imagealphamask($source, $mask); 
// Output 
header("Content-type: image/png"); 
imagepng($source); 

function imagealphamask(&$picture, $mask) { 
    // Get sizes and set up new picture 
    $xSize = imagesx($picture); 
    $ySize = imagesy($picture); 
    $newPicture = imagecreatetruecolor($xSize, $ySize); 
    imagesavealpha($newPicture, true); 
    imagefill($newPicture, 0, 0, imagecolorallocatealpha($newPicture, 0, 0, 0, 127)); 

    // Resize mask if necessary 
    if($xSize != imagesx($mask) || $ySize != imagesy($mask)) { 
     $tempPic = imagecreatetruecolor($xSize, $ySize); 
     imagecopyresampled($tempPic, $mask, 0, 0, 0, 0, $xSize, $ySize, imagesx($mask), imagesy($mask)); 
     imagedestroy($mask); 
     $mask = $tempPic; 
    } 

    // Perform pixel-based alpha map application 
    for($x = 0; $x < $xSize; $x++) { 
     for($y = 0; $y < $ySize; $y++) { 
      $alpha = imagecolorsforindex($mask, imagecolorat($mask, $x, $y)); 
      //small mod to extract alpha, if using a black(transparent) and white 
      //mask file instead change the following line back to Jules's original: 
      //$alpha = 127 - floor($alpha['red']/2); 
      //or a white(transparent) and black mask file: 
      //$alpha = floor($alpha['red']/2); 
      $alpha = $alpha['alpha']; 
      $color = imagecolorsforindex($picture, imagecolorat($picture, $x, $y)); 
      //preserve alpha by comparing the two values 
      if ($color['alpha'] > $alpha) 
       $alpha = $color['alpha']; 
      //kill data for fully transparent pixels 
      if ($alpha == 127) { 
       $color['red'] = 0; 
       $color['blue'] = 0; 
       $color['green'] = 0; 
      } 
      imagesetpixel($newPicture, $x, $y, imagecolorallocatealpha($newPicture, $color[ 'red' ], $color[ 'green' ], $color[ 'blue' ], $alpha)); 
     } 
    } 

    // Copy back to original picture 
    imagedestroy($picture); 
    $picture = $newPicture; 
} 

?> 
1
for ($y = 0; $y < $ySize; $y++) { 
    $alpha = imagecolorsforindex($mask, imagecolorat($mask, $x, $y)); 
    $alpha = 127 - floor($alpha['red']/2); 
    if (127 == $alpha) { 
    continue; 
    } 
    $color = imagecolorsforindex($picture, imagecolorat($picture, $x, $y)); 
    imagesetpixel($newPicture, $x, $y, imagecolorallocatealpha(
    $newPicture, $color['red'], $color['green'], $color['blue'], $alpha)); 
} 

यहाँ पहले समारोह के लिए एक छोटे से उन्नयन है। चूंकि आपके पास पहले से ही एक पारदर्शी छवि है, इसलिए आपको मास्क किए गए पिक्सेल की प्रतिलिपि बनाने की आवश्यकता नहीं है। यह निष्पादन को थोड़ा सा मदद करेगा।

0

एक समान प्रभाव प्राप्त करने के एक अलग तरह से एक अनूठा पृष्ठभूमि रंग के साथ एक नई छवि पर png फाइल पेस्ट अस्थायी रूप से पारदर्शिता को दूर करने, और पारदर्शी सेट करने के लिए है इसके बजाय पीएनजी छवि का रंग काला सर्कल रंग में। फिर जब आप इसे जेपीईजी छवि पर रखते हैं, तो आप मास्क के रंग में नया पारदर्शी रंग सेट करते हैं।

// Load the Black Circle PNG image 
$png = imagecreatefrompng('mask.png'); 
$width = imagesx($png); 
$height = imagesy($png); 

// Create a mask image 
$mask = imagecreatetruecolor($width, $height); 
// We'll use Magenta as our new transparent colour - set it as the solid background colour. 
$magenta = imagecolorallocate($mask, 255, 0, 255); 
imagefill($mask, 0, 0, $magenta); 

// Copy the png image onto the mask. Destroy it to free up memory. 
imagecopyresampled($mask, $png, 0, 0, 0, 0, $width, $height, $width, $height); 
imagedestroy($png); 

// Set the black portion of the mask to transparent. 
$black = imagecolorallocate($mask, 0, 0, 0); 
imagecolortransparent($mask, $black); 

// Load JPEG image. 
$jpg = imagecreatefromjpeg('image.jpg'); 
$j_width = imagesx($jpg); 
$j_height = imagesx($jpg); 

// Enable alpha blending and copy the png image 
imagealphablending($jpg, true); 
imagecopyresampled($jpg, $mask, 0, 0, 0, 0, $j_width, $j_height, $width, $height); 
imagedestroy($mask); 

// Set the new transparent colour and output new image to browser as a png. 
$magenta = imagecolorallocate($jpg, 255, 0, 255); 
imagecolortransparent($jpg, $magenta); 
imagepng($jpg); 

resampling या अर्द्ध पारदर्शी पिक्सेल एक मुखौटा के रूप में एक png का उपयोग कर नीचे आप मिल रहे हैं, बजाय, आप सम्मिश्रण अक्षम करने के बजाय $mask छवि पर एक पारदर्शी आकार आकर्षित कर सकते हैं।

// Load JPEG Image. 
$jpg = imagecreatefromjpeg('image.jpg'); 
$width = imagesx($jpg); 
$height = imagesx($jpg); 

// Create mask at same size with an opaque background. 
$mask = imagecreatetruecolor($width, $height); 
$magenta = imagecolorallocate($mask, 255, 0, 255); 
imagefill($mask, 0, 0, $magenta); 

// Disable alpha blending and draw a transparent shape onto the mask. 
$transparent = imagecolorallocatealpha($mask, 255, 255, 255, 127); 
imagealphablending($mask, false); 
imagefilledellipse($mask, round($width/2), round($height/2), $width, $height, $transparent); 

// Paste the mask onto the original image and set the new transparent colour. 
imagealphablending($jpg, true); 
imagecopyresampled($jpg, $mask, 0, 0, 0, 0, $width, $height, $width, $height); 
imagedestroy($mask); 
$magenta = imagecolorallocate($jpg, 255, 0, 255); 
imagecolortransparent($jpg, $magenta); 

// Output new image to browser as a png. 
imagepng($jpg); 

नोट: उपर्युक्त कोड अनचाहे है, लेकिन उम्मीद है कि आपको इसकी आवश्यकता है।

संबंधित मुद्दे