php - texto - que significa atributo alt
PHP GD Usa una imagen para enmascarar otra imagen, incluida la transparencia (6)
Aquí hay una pequeña actualización de este script: encontré que si la imagen de origen tiene transparencia en sí misma, la máscara (utilizando el script anterior) traza un píxel posterior en lugar del píxel transparente de la imagen de origen. El script extendido a continuación toma en consideración la transparencia de la imagen fuente y la conserva.
// 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;
}
Estoy tratando de crear un script PHP que tome una imagen:
http://i.stack.imgur.com/eNvlM.png
y luego aplica una imagen PNG:
http://i.stack.imgur.com/iJr2I.png
como una máscara.
El resultado final necesita mantener la transparencia:
http://i.stack.imgur.com/u0l0I.png
Si es posible, quiero hacer esto en GD, ImageMagick no es realmente una opción en este momento.
¿Cómo voy a hacer esto?
La publicación de phalacee (en "PHP / GD, ¿cómo copiar un círculo de una imagen a otra?") parece estar en la línea derecha, pero específicamente necesito usar una imagen como máscara, no como forma.
Hay una biblioteca llamada WideImage que admite máscaras alfa http://wideimage.sourceforge.net/documentation/manipulating-images/
Mate,
Si haces tu png con el relleno blanco ovalado sobre fondo negro en lugar del relleno negro con fondo transparente, la siguiente función lo hace.
<?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;
}
?>
Me gusta su secuencia de comandos, buena idea para eliminar la información de color adicional cuando el píxel es totalmente transparente. Debo señalar solo un pequeño error (IMO) aunque alguien quiera usar este método.
$color = imagecolorsforindex( $source, imagecolorat( $source, $x, $y ) );
debiera ser
$color = imagecolorsforindex( $picture, imagecolorat( $picture, $x, $y ) );
Además, no estoy 100% seguro de por qué está comprobando los valores de rgb aquí si el píxel es 100% transparente
if(($alpha[''red''] == 0) && ($alpha[''green''] == 0) && ($alpha[''blue''] == 0) && ($alpha[''alpha''] == 0))
...
y no estoy seguro de que la fusión alfa del archivo de máscara funcione bien con su método, ya que solo se usa cuando los valores de rgba son todos iguales a 0.
El guión de Jules es bastante bueno también, aunque espera que la máscara sea una representación en escala de grises de una máscara (que es una práctica bastante común).
En la consulta de Matt, buscaba un script que tomara solo la transparencia alfa de una imagen existente y la aplicara a otra imagen. Aquí hay un mod simple de la secuencia de comandos de Jules solo para tomar el alfa de la imagen de la máscara, y preservar el alfa de la imagen de origen.
<?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;
}
?>
Una forma diferente de obtener un efecto similar es pegar el archivo png en una nueva imagen con un color de fondo exclusivo para eliminar temporalmente la transparencia, y establecer el color transparente de la imagen png en el círculo negro. Luego, cuando lo coloca sobre la imagen jpeg, establece el nuevo color transparente en el color de la máscara.
// 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 );
Si el remuestreo o los píxeles semitransparentes lo bajan, en lugar de usar un png como máscara, puede desactivar la combinación y dibujar una forma transparente en la imagen $mask
lugar.
// 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 );
Nota: El código anterior no se ha probado, pero con suerte debe hacer lo que necesita.
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));
}
Aquí hay una pequeña actualización para la primera función. Como ya tiene una imagen transparente, no necesita copiar los píxeles enmascarados. Esto ayudará a la ejecución un poco.