~ overflow ~

Tag: png

PNG Watermarking images with PHP

by z3n on Apr.07, 2010, under Coding, Tips & Hints

Problem:

How to watermark images with png’s alphablending enabled?

Solution:

function image_overlap($background, $foreground, $overlapX=-1, $overlapY=-1) {
	$insertWidth = imagesx($foreground);
	$insertHeight = imagesy($foreground);

	$imageWidth = imagesx($background);
	$imageHeight = imagesy($background);

	$overlapX = ($overlapX == -1) ? $imageWidth-$insertWidth-5 : $overlapX;
	$overlapY = ($overlapY == -1) ? $imageHeight-$insertHeight-5 : $overlapY;

	imagecolortransparent($foreground,imagecolorat($foreground,0,0));
	imagecopymerge($background,$foreground,$overlapX,$overlapY,0,0,$insertWidth,$insertHeight,100);

	return $background;
}
function watermark($src,$watermark,$src_format,$quality=75) {
	if (file_exists($src)) {
		_o("Watermarking: ".$src."...",1);
		switch ($src_format) {
			case "jpg":
				$src_img=imagecreatefromjpeg($src);
				break;
			case "gif":
				$src_img=imagecreatefromgif($src);
				break;
			case "bmp":
				$src_img=imagecreatefrombmp($src);
				break;
			case "png":
				$src_img=imagecreatefrompng($src);
				break;
			default:
				die("Unknown format");
		}

		// prepare source
		$src_size=getimagesize($src);
		$img=imagecreatetruecolor($src_size[0],$src_size[1]);
		imagecopyresampled($img,$src_img,0,0,0,0,$src_size[0],$src_size[1],$src_size[0],$src_size[1]);
		@ imagealphablending($img,true);

		// load watermark
		$watermark_size=getimagesize($watermark);
		$watermark_img=imagecreatefrompng($watermark);
		@ imagealphablending($wartermark_img,true);

		// apply watermark
		$img=image_overlap($img,$watermark_img);
		imagecopy($img,$watermark_img,0,0,0,0,0,0);

		imagedestroy($src_img);
		imagedestroy($watermark_img);

		switch ($src_format) {
			case "jpg":
				imagejpeg($img,$src,$quality);
				break;
			case "gif":
				imagegif($img,$src);
				break;
			case "bmp":
				imagebmp($img,$src);
				break;
			case "png":
				imagepng($img,$src,$quality);
				break;
		}

		imagedestroy($img);
	} else {
		die("Watermark: Source don't exists -- ".$src);
	}
}

Note:

For BMPs you will need the functions on this post.

Leave a Comment :, , , , more...

Image Resizing Functions (… again?!)

by z3n on Mar.27, 2010, under Coding, Tips & Hints

Problem:

Oh yeah i posted this before, but now that i finally got wordpress updates i can use a decent syntax highlighter.

The main function img_resizer, is able to resize gif, png, wbmp, bmp and jpgs with proportional or cropping resize, it’s also got a function to eventually FIX the format if the filename extension is not really the same of the format, like a jpg named as file.bmp. BMP function been taken off php man pages, i will not post author’s full email to avoid spam.

Solution:

function dwordize($str) {
	$a = ord($str[0]);
	$b = ord($str[1]);
	$c = ord($str[2]);
	return $c*256*256 + $b*256 + $a;
}

function byte3($n) {
	return chr($n & 255) . chr(($n >> 8) & 255) . chr(($n >> 16) & 255);
}
function dword($n) {
	return pack("V", $n);
}
function word($n) {
	return pack("v", $n);
}
function imagebmp(&$img, $filename = false) {
	$wid = imagesx($img);
	$hei = imagesy($img);
	$wid_pad = str_pad('', $wid % 4, "\0");

	$size = 54 + ($wid + $wid_pad) * $hei;

	//prepare & save header
	$header['identifier']		= 'BM';
	$header['file_size']		= dword($size);
	$header['reserved']			= dword(0);
	$header['bitmap_data']		= dword(54);
	$header['header_size']		= dword(40);
	$header['width']			= dword($wid);
	$header['height']			= dword($hei);
	$header['planes']			= word(1);
	$header['bits_per_pixel']	= word(24);
	$header['compression']		= dword(0);
	$header['data_size']		= dword(0);
	$header['h_resolution']		= dword(0);
	$header['v_resolution']		= dword(0);
	$header['colors']			= dword(0);
	$header['important_colors']	= dword(0);

	if ($filename) {
	    $f = fopen($filename, "wb");
	    foreach ($header AS $h) {
	    	fwrite($f, $h);
	    }

		// save pixels
		for ($y=$hei-1; $y>=0; $y--) {
			for ($x=0; $x<$wid; $x++) {
				$rgb = imagecolorat($img, $x, $y);
				fwrite($f, byte3($rgb));
			}
			fwrite($f, $wid_pad);
		}
		fclose($f);
	} else {
	    foreach ($header AS $h)
	    {
	    	echo $h;
	    }

		//save pixels
		for ($y=$hei-1; $y>=0; $y--) {
			for ($x=0; $x<$wid; $x++) {
				$rgb = imagecolorat($img, $x, $y);
				echo byte3($rgb);
			}
			echo $wid_pad;
		}
	}
}
function _ckdir($fn) {
	if (strpos($fn,"/") !== false) {
		$p=substr(substr($fn,0,strrpos($fn,"/")),0,250);
		if (!is_dir($p)) {
			mkdir($p,755,true);
		}
	}
}
function imagecreatefrombmp($p_sFile) { // by alexander at http://www.php.net/manual/en/function.imagecreatefromwbmp.php
  // Load the image into a string
  $file = fopen($p_sFile,"rb");
  $read=fread($file,10);
  while(!feof($file)&&($read<>""))
  	$read.=fread($file,1024);
  $temp=unpack("H*",$read);
  $hex=$temp[1];
  $header=substr($hex,0,108);

  // Process the header
  // Structure: http://www.fastgraph.com/help/bmp_header_format.html
  if (substr($header,0,4) == "424d") {
    // Cut it in parts of 2 bytes
    $header_parts=str_split($header,2);

    // Get the width4 bytes
    $width=hexdec($header_parts[19].$header_parts[18]);

    // Get the height4 bytes
    $height=hexdec($header_parts[23].$header_parts[22]);

    // Unset the header params
    unset($header_parts);
  }

  // Define starting X and Y
  $x=0;
  $y=1;

  // Create newimage
  $image=imagecreatetruecolor($width,$height);

  // Grab the body from the image
  $body=substr($hex,108);

  // Calculate if padding at the end-line is needed
  // Divided by two to keep overview.
  // 1 byte = 2 HEX-chars
  $body_size=(strlen($body)/2);
  $header_size=($width*$height);

  // Use end-line padding? Only when needed
  $usePadding=($body_size>($header_size*3)+4);

  // Using a for-loop with index-calculation instaid of str_split to avoid large memory consumption
  // Calculate the next DWORD-position in the body
  for ($i=0;$i < $body_size;$i+=3) {
    // Calculate line-ending and padding
    if ($x >= $width) {
      // If padding needed, ignore image-padding
      // Shift i to the ending of the current 32-bit-block
      if ($usePadding)
      	$i+=$width%4;

      // Reset horizontal position
      $x=0;

      // Raise the height-position (bottom-up)
      $y++;

      // Reached the image-height? Break the for-loop
      if ($y > $height)
      	break;
    }

    // Calculation of the RGB-pixel (defined as BGR in image-data)
    // Define $i_pos as absolute position in the body
    $i_pos=$i*2;
    $r=hexdec($body[$i_pos+4].$body[$i_pos+5]);
    $g=hexdec($body[$i_pos+2].$body[$i_pos+3]);
    $b=hexdec($body[$i_pos].$body[$i_pos+1]);

    // Calculate and draw the pixel
    $color=imagecolorallocate($image,$r,$g,$b);
    imagesetpixel($image,$x,$height-$y,$color);

    // Raise the horizontal position
    $x++;
  }

  // Unset the body / free the memory
  unset($body);

  // Return image-object
  return $image;
}
function img_force($src,$quality,$w,$h,$saveas,$nocrop,$force) {
	foreach (array("jpg","gif","png") as $x) { // will skip bmp formats
		if ($x != $force) {
			if (img_resizer($src,$quality,$w,$h,$saveas,$nocrop,$x)) {
				return 1;
				break;
			}
		}
	}
	return 0;
}
function img_resizer($src,$quality,$w,$h,$saveas,$nocrop=0,$force=0) { /* v2.72 with auto crop, no crop, automatic file type detection when avalible (requires exif library) */

	if (!is_file($src)) { _o("Source is not a file.");return 0; }
	if (!is_readable($src)) { _o("Can't read: ".$src);return 0; }
	if ((file_exists($saveas)) && (!is_writeable($saveas))) { _o("Can't write to: ".$saveas);return 0; }

	$r=1;

	if (function_exists('exif_imagetype')) { // automatic filetype detection
  	$e=exif_imagetype($src);
  	if ($e == IMAGETYPE_JPEG) {
  		if (!$OldImage=@ImageCreateFromJpeg($src)) { $r=0; }
  	} elseif ($e == IMAGETYPE_GIF) {
  		if (!$OldImage=@ImageCreateFromGif($src)) { $r=0; }
  	} elseif ($e == IMAGETYPE_BMP) { // custom
  		if (!$OldImage=@ImageCreateFrombmp($src)) { $r=0; }
  	} elseif ($e == IMAGETYPE_WBMP) {
  		if (!$OldImage=@ImageCreateFromwbmp($src)) { $r=0; }
  	} elseif ($e == IMAGETYPE_PNG) {
  		if (!$OldImage=@ImageCreateFromPng($src)) { $r=0; }
  	} else {
  		_o("Not a Valid Image! (".$e.") -- ".$src);$r=0;
  	}
	} else { // filename based filetype detection, might be subject to incorrect file extensions, resulting on a error, which when enabled will fall into a try and error `force` mode
  	$e=($force == "0") ? strtolower(substr($src,strrpos($src,".")+1)) : $force;
  	if (($e == "jpg") || ($e == "jpeg")) {
  		if (!$OldImage=@ImageCreateFromJpeg($src)) { $r=0; }
  	} elseif ($e == "gif") {
  		if (!$OldImage=@ImageCreateFromGif($src)) { $r=0; }
  	} elseif ($e == "bmp") { // this is NOT wbmp
  		if (!$OldImage=@ImageCreateFrombmp($src)) { $r=0; }
  	} elseif ($e == "png") {
  		if (!$OldImage=@ImageCreateFromPng($src)) { $r=0; }
  	} else {
  		_o("Not a Valid Image! (".$e.") -- ".$src);$r=0;
  	}
	}

	if ($r) {
		list($width,$height)=getimagesize($src);
		// check if ratios match
		$_ratio=array($width/$height,$w/$h);
		if ($_ratio[0] != $_ratio[1]) { // ratio don't match
			if ($nocrop) { // since we can't crop we will need to do image on a different height/width
    		$hx = (100 / ($width / $w)) * .01;
    		$hx = @round ($height * $hx);

    		$wx = (100 / ($height / $h)) * .01;
    		$wx = @round ($width * $wx);

    		if ($hx < $h) {
    			$h = (100 / ($width / $w)) * .01;
    			$h = @round ($height * $h);
    		} else {
    			$w = (100 / ($height / $h)) * .01;
    			$w = @round ($width * $w);
    		}
			} else { // crop image
  			// find the right scale to use
  			$_scale=min((float)($width/$w),(float)($height/$h));

  			// coords to crop
  			$cropX=(float)($width-($_scale*$w));
  			$cropY=(float)($height-($_scale*$h));

  			// cropped image size
  			$cropW=(float)($width-$cropX);
  			$cropH=(float)($height-$cropY);

  			$crop=ImageCreateTrueColor($cropW,$cropH);
  			ImageCopy($crop,$OldImage,0,0,(int)($cropX/2),(int)($cropY/2),$cropW,$cropH); // crop the middle part of the image to fit the thumbnail's proportions
			}
		}

		// do the thumbnail
		$NewThumb=ImageCreateTrueColor($w,$h);
		if (isset($crop)) { // been cropped
			ImageCopyResampled($NewThumb,$crop,0,0,0,0,$w,$h,$cropW,$cropH);
			ImageDestroy($crop);
		} else { // ratio match, regular resize
			ImageCopyResampled($NewThumb,$OldImage,0,0,0,0,$w,$h,$width,$height);
		}
		_ckdir($saveas);
		ImageJpeg($NewThumb,$saveas,$quality);
		ImageDestroy($NewThumb);
		ImageDestroy($OldImage);
	} elseif (($force == "0") && (!function_exists('exif_imagetype'))) {
		$r=img_force($src,$quality,$w,$h,$saveas,$nocrop,$e);
	}
	return $r;
}

See how nice it looks with the syntax highligher? :P

Updates:

100407 – Added imagebmp function to save as bmp;

1 Comment :, , , , , , , , more...

IE6 PNG Glitch Summary

by z3n on May.30, 2009, under Notes

Despite all those javascript, css, htc, etc. fixes for correctly displaying a png on IE6 (alpha image hack) there’s a couple of issues that never go away:

- You can’t have a custom position on the PNG background (check this post about alternate background positions if you’re not familiar with it);

- You can’t have it tiling, it always will be streched to the size of the element (scale) or will be shown on it’s regular size;

- If it’s on a background of a DIV links, forms and text will not work right;

- On slower machines it will lag the site;

Leave a Comment :, , more...

IE6 PNG Fix Note

by z3n on Jan.19, 2009, under Notes

The popular “filter:progid:DXImageTransform.Microsoft.AlphaImageLoader” png fix for IE6 will avoid inner complex divs from working right, specially, links will not work. I havent found any fix for this yet, i don’t think that there’s one actually.

Leave a Comment :, more...

IE PNG Workaround Trick

by z3n on Jan.13, 2009, under Coding, Tips & Hints

We all know ie sucks a lot, but when it comes to transparent png it’s another level of suckness.

I’m designing a site with those little shadow borders, like 4px in height, the usual ie6< fix:

filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png', sizingMethod='scale');

apparently work, but if you look closely, for small height divs it don’t work right.

it assumes that the minimum height is the same height of the font on that div, so how stupid is this?

a work around would be:

.your_happy_class { font-size:1px; }

an interesting fact is that IE don’t support the line-height feature right, so if you were thinking in use this, you thought wrong! hahahah

Leave a Comment :, , more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!