Some PNG gets black background instead of transparent

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
rokdzone
Posts: 8
Joined: 2015-02-11T08:29:25-07:00
Authentication code: 6789

Some PNG gets black background instead of transparent

Post by rokdzone » 2015-02-11T08:50:18-07:00

I'm using ImageMagick 6.6.5-9 2010-11-15 Q16
with PHP module 3.1.2 (php_imagick-3.1.2-5.3-nts-vc9-x86.zip)

I'm having a bunch of PNG-logotypes which i wan't to scale down to a certain fixed size.
Two of them always gets a black background when resized (allthough original PNG are transparent).
GD-library which i replaced with Imagick could handle this by converting the logotypes to truecolor when reading them.

I have tried the following:

1. Resave the original which failed in Photoshop using PNG24 with a new filename (this is not a solution anyway in my case since i have no control of what the user uploads)..however it did no difference

2. Various other methods like adding $image->setFormat('png24')

This is the specific function:

Code: Select all

public function resize($width = 0, $height = 0, $default = '', $method = 'THUMB', $filter = Imagick::FILTER_CATROM) {
		
		if (!$this->info['width'] || !$this->info['height']) {
			return;
		}
		
		$xpos = 0;
		$ypos = 0;
		$scale = 1;
		
		$scale_w = $width / $this->info['width'];
		$scale_h = $height / $this->info['height'];
		
		if ($default == 'w') {
			$scale = $scale_w;
		} elseif ($default == 'h') {
			$scale = $scale_h;
		} else {
			$scale = min($scale_w, $scale_h);
		}

		if ($scale == 1 && $scale_h == $scale_w && $this->info['mime'] != 'image/png') {
			return;
		}
		
		$new_width = (int)($this->info['width'] * $scale);
		$new_height = (int)($this->info['height'] * $scale);
		$xpos = (int)(($width - $new_width) / 2);
		$ypos = (int)(($height - $new_height) / 2);
		
		$image = $this->image; // this is the image object
		
		if ($method == 'SCALE') {
			$image->scaleImage($new_width, $new_height);
		} elseif ($method == 'THUMB') {
			$image->thumbnailImage($new_width, $new_height, false);
		} elseif ($method == 'RESIZE') {
			$image->resizeImage($new_width, $new_height, $filter, 1);
		}
		
		if ($this->info['mime'] == 'image/png') {
			$background = 'none';
		} else {
			$background = 'white';
		}
		
		$canvas = $this->create(); // creates an empty Imagick instance
		$canvas->newImage($width, $height, new ImagickPixel($background));
		$canvas->compositeImage($image, imagick::COMPOSITE_OVER, $xpos, $ypos);
		
		$this->info['width'] = $width;
		$this->info['height'] = $height;
		
		$this->image = $canvas;
		
		$image->clear(); 
		$image->destroy();
		
	} 
This is the whole Image class which i've built:

Code: Select all

<?php
class Image {
	private $file;
	private $image;
	private $info;

	public function __construct($file) {
		
		if (extension_loaded('imagick')) {
			
			if (file_exists($file)) {
				
				$this->file = $file;
				
				$image = new Imagick();
				$image->readImage($file); 
				$info = $image->identifyImage(true);

				$this->info = array(
					'width'  			=> $info['geometry']['width'],
					'height' 			=> $info['geometry']['height'],
					'filesize'		=> $info['fileSize'],
					'compression'	=> $info['compression'],
					'signature'		=> $info['signature'],
					'colorspace'	=> $info['colorSpace'],
					'units'				=> $info['units'],
					'type'				=> $info['type'],
					'mime'   			=> $info['mimetype']
				);
				
				if ($this->info['mime'] == 'image/png') {
					$image->setFormat('png24');
				}
				
				$this->image = $image;
				
			} else {
				exit('Error: Could not load image ' . $file . '!');
			}
		} else {
			exit('Error: The Imagick component is not installed on your server!');
		} 
	}
	
	private function create($file = false) {
		
		if ($file) {
			return new Imagick($file);
		} else {
			return new Imagick();
		}

	}
	
	public function perspective($offset = array(), $background = 'transparent') {
			
		if (count($offset) > 7) {
			
			$points = array(0,0,
								(float)$offset['transform_topleft_x'], (float)$offset['transform_topleft_y'],
								0, $this->image->getImageHeight(),
								(float)$offset['transform_bottomleft_x'], (float)$offset['transform_bottomleft_y'],
								$this->image->getImageWidth(), 0,
								(float)$offset['transform_topright_x'], (float)$offset['transform_topright_y'],
								$this->image->getImageWidth(), $this->image->getImageHeight(),
								(float)$offset['transform_bottomright_x'], (float)$offset['transform_bottomright_y']
			);
				
			$this->image->setImageMatte(true);
			$this->image->setImageMatteColor($background);
			$this->image->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_TRANSPARENT);
			$this->image->distortImage(Imagick::DISTORTION_PERSPECTIVE, $points, true);
			
		}
		
	}
	
	public function save($file, $quality = 90) {
		
		$info = pathinfo($file);

		$extension = strtolower($info['extension']);
		
		if (is_object($this->image)) {
			if ($extension == 'jpeg' || $extension == 'jpg') {
				$this->image->setImageFormat('jpg');
				$this->image->setImageCompression(imagick::COMPRESSION_JPEG2000);
				$this->image->setImageCompressionQuality($quality);
				$this->image->stripImage();
			} elseif ($extension == 'png') {
				$this->image->setImageFormat('png');
				$this->image->setImageCompression(0);
			} elseif ($extension == 'gif') {
				$this->image->setImageFormat('gif');
			}
			
			$this->image->writeImage($file);
			
		}
	}
	
	public function output() {
		
		return $this->image;
		
	}
	
	public function base64output($quality = 90) {
		
		if ($this->info['mime']) {
			
			$response = new Response();
			
			$response->addHeader('Content-Type: ' . $this->info['mime']);
			$response->addHeader('Content-transfer-encoding: base64');
			$response->addHeader('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
			$response->addHeader('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
			$response->addHeader('Cache-Control: post-check=0, pre-check=0');
			$response->addHeader('Pragma: no-cache');
			
			if ($this->info['mime'] == 'image/jpeg') {
				$this->image->setImageFormat('jpg');
				$this->image->setImageCompression(imagick::COMPRESSION_JPEG2000);
				$this->image->setImageCompressionQuality($quality);
				$this->image->stripImage();
			} elseif ($this->info['mime'] == 'image/png') {
				$this->image->setImageFormat('png');
				$this->image->setImageCompression(0);
			} elseif ($this->info['mime'] == 'image/gif') {
				$this->image->setImageFormat('gif');
			}
			
			ob_start();
			echo $this->image;	
			return base64_encode(ob_get_clean());
			
		}
		
	}
	
	public function resize($width = 0, $height = 0, $default = '', $method = 'THUMB', $filter = Imagick::FILTER_CATROM) {
		
		if (!$this->info['width'] || !$this->info['height']) {
			return;
		}
		
		$xpos = 0;
		$ypos = 0;
		$scale = 1;
		
		$scale_w = $width / $this->info['width'];
		$scale_h = $height / $this->info['height'];
		
		if ($default == 'w') {
			$scale = $scale_w;
		} elseif ($default == 'h') {
			$scale = $scale_h;
		} else {
			$scale = min($scale_w, $scale_h);
		}

		if ($scale == 1 && $scale_h == $scale_w && $this->info['mime'] != 'image/png') {
			return;
		}
		
		$new_width = (int)($this->info['width'] * $scale);
		$new_height = (int)($this->info['height'] * $scale);
		$xpos = (int)(($width - $new_width) / 2);
		$ypos = (int)(($height - $new_height) / 2);
		
		$image = $this->image;
		
		if ($method == 'SCALE') {
			$image->scaleImage($new_width, $new_height);
		} elseif ($method == 'THUMB') {
			$image->thumbnailImage($new_width, $new_height, false);
		} elseif ($method == 'RESIZE') {
			$image->resizeImage($new_width, $new_height, $filter, 1);
		}
		
		if ($this->info['mime'] == 'image/png') {
			$background = 'none';
		} else {
			$background = 'white';
		}
		
		$canvas = $this->create();
		$canvas->newImage($width, $height, new ImagickPixel($background));
		$canvas->compositeImage($image, imagick::COMPOSITE_OVER, $xpos, $ypos);
		
		$this->info['width'] = $width;
		$this->info['height'] = $height;
		
		$this->image = $canvas;
		
		$image->clear(); 
		$image->destroy();
		
	}
	
	public function scale($width = 0, $height = 0, $method = 'THUMB', $filter = Imagick::FILTER_CATROM) {
		
		if ($method == 'SCALE') {
			$this->image->scaleImage($width, $height);
		} elseif ($method == 'THUMB') {
			$this->image->thumbnailImage($width, $height, false);
		} elseif ($method == 'RESIZE') {
			$this->image->resizeImage($width, $height, $filter, 1);
		}
		
		$this->info['width'] = $this->image->getImageWidth();
		$this->info['height'] = $this->image->getImageHeight();
		
	}
	
	public function watermark($file, $position = 'bottomright', $x = 0, $y = 0) {
		
		$watermark = $this->create($file);
	
		$watermark_width = $watermark->getImageWidth();
		$watermark_height = $watermark->getImageHeight();

		switch($position) {
			case 'topleft':
				$watermark_pos_x = 0;
				$watermark_pos_y = 0;
				break;
			case 'topright':
				$watermark_pos_x = $this->info['width'] - $watermark_width;
				$watermark_pos_y = 0;
				break;
			case 'bottomleft':
				$watermark_pos_x = 0;
				$watermark_pos_y = $this->info['height'] - $watermark_height;
				break;
			case 'bottomright':
				$watermark_pos_x = $this->info['width'] - $watermark_width;
				$watermark_pos_y = $this->info['height'] - $watermark_height;
				break;
			case 'custom':
				$watermark_pos_x = $x;
				$watermark_pos_y = $y;
				break;
		}
		
		$image = $this->image;
		$image->compositeImage($watermark, imagick::COMPOSITE_OVER, $watermark_pos_x, $watermark_pos_y);
		
		$this->image = $image;
		
	}
	
	public function opacity($opacity) {
		
		if ($opacity < 1) {
			$this->image->evaluateImage(Imagick::EVALUATE_MULTIPLY, $opacity, Imagick::CHANNEL_ALPHA);
		}
		
	}
	
	public function crop($top_x, $top_y, $bottom_x, $bottom_y) {
		
		$this->image->cropImage($bottom_x, $bottom_y, $top_x, $top_y);
		
		$this->info['width'] = $this->image->getImageWidth();
		$this->info['height'] = $this->image->getImageHeight();
		
	}
	
	public function rotate($degree, $color = '#00000000') {
		
		$this->image->rotateImage(new ImagickPixel($color), $degree);

		$this->info['width'] = $this->image->getImageWidth();
		$this->info['height'] = $this->image->getImageHeight();
		
	}
	
	public function composite($watermark, $x = 0, $y = 0) {
		
		$this->image->compositeImage($watermark, imagick::COMPOSITE_OVER, $x, $y);
		
		$this->info['width'] = $this->image->getImageWidth();
		$this->info['height'] = $this->image->getImageHeight();
		
	}
	
	private function merge($file, $x = 0, $y = 0, $opacity = 1) {
		
		$merge = $this->create($file);
		
		if ($opacity < 1) {
			$merge->evaluateImage(Imagick::EVALUATE_MULTIPLY, $opacity, Imagick::CHANNEL_ALPHA);
		}
		
		$this->image->compositeImage($merge, imagick::COMPOSITE_OVER, $x, $y);
		
	}
	
	public function __destruct() {
		
		$this->image->clear(); 
		$this->image->destroy();
		
	}

}

Post Reply