php5 image factory class
Posted: Mon Sep 11, 2006 9:51 pm
I've been working on a image factory. Its got four pieces: 1. Image manager 2. image abstract class, 3. image type class and 4. A custom exception class.
As I've had a problem building God classes in the past, I've been wondering if these classes are too tightly coupled. So does it smell?
The code is not polished, but I'm interested in any feedback you can give me. I'm especially interested in design and object relations.
Should gg_image_manager::manage_image() return a gg_image object?
This is the first time I've used a built in Exception class let alone extend it. Hows this:
Here's an example of how you might use the classes.
As I've had a problem building God classes in the past, I've been wondering if these classes are too tightly coupled. So does it smell?
The code is not polished, but I'm interested in any feedback you can give me. I'm especially interested in design and object relations.
Should gg_image_manager::manage_image() return a gg_image object?
Code: Select all
class gg_image_manager{
private $img;
private $img_dest;
private $img_info;
private $img_maxd;
private $img_width;
private $img_height;
public function __construct($image, $max_demension, $dest = ''){
if( $this->gd_loaded() === true ){
$this->img = $image;
try{
$this->set_image_info();
} catch ( image_exception $e){
$e->__toString('Image file ('.$this->img.') does not exist! ');
}
$this->img_maxd = $max_demension;
$this->img_dest = $dest;
$this->calc_image_size($this->img_info[0], $this->img_info[1]);
} else {
die('GD extension not loaded. Contact your system administrator.');
}
}
protected function set_image_info(){
if(file_exists($this->img)){
$this->img_info = getimagesize($this->img);
} else {
throw new image_exception("This image file does not exist.");
}
}
protected function gd_loaded(){
if (extension_loaded('gd')) {
return true;
} else {
return false;
}
}
public function manage_image(){
//key values below match key value pairs for array
//returned by getimagesize. Add a new supported file
//type by adding a new offspring image class with name
//gg_{file_ext_type_below}_image
$image_types = array( 1 => 'gif',
2 => 'jpeg', 3 => 'png', 4 => 'swf',
5 => 'psd', 6 => 'bmp', 7 => 'tiff',
8 => 'tiff2', 9 => 'jpc', 10 => 'jp2',
11 => 'jpx', 12 => 'jb2', 13 => 'swc',
14 => 'iff', 15 => 'wbmp', 16 => 'xbm');
$offspring = "gg_".$image_types[$this->img_info[2]]."_image";
return new $offspring ( $this );
}
private function calc_image_size($img_width, $img_height){
$aspect_ratio = $img_width / $img_height;
//Do we need to resize the image?
if ( ($img_width > $this->img_maxd) || ($img_height > $this->img_maxd) ){
//Yes, Width is greater than height.
if ( $img_width > $img_height ) {
$this->img_width = $this->img_maxd;
$this->img_height = $this->img_width / $aspect_ratio;
//Width is less than height
} elseif ( $img_width < $img_height ) {
$this->img_height = $this->img_maxd;
$this->img_width = $this->img_height * $aspect_ratio;
//Dimensions equal each other.
} elseif ( $img_width == $img_height ){
$this->img_width = $this->img_maxd;
$this->img_height = $this->img_maxd;
} else {
return FALSE;
}
} else {
$this->img_width = $img_width;
$this->img_height = $img_height;
}
}
public function get_image_info(){
return $this->img_info;
}
public function get_image(){
return $this->img;
}
public function get_image_dest(){
return $this->img_dest;
}
public function get_image_maxd(){
return $this->img_maxd;
}
public function get_image_height(){
return $this->img_height;
}
public function get_image_width(){
return $this->img_width;
}
}Code: Select all
abstract class gg_image extends gg_image_manager{
protected $img_resource;
protected $img_new;
protected $img_manager;
abstract function create_image();
abstract function image_header();
abstract function is_gd_capable();
abstract function create_image_from();
abstract function generate_image();
function __construct( gg_image_manager $img_manager ){
//make the img_manager object available to the class.
$this->img_manager = $img_manager;
}
protected function image_resize(){
$img_info = $this->img_manager->get_image_info();
$new_width = $this->img_manager->get_image_width();
$new_height = $this->img_manager->get_image_height();
$this->img_new = @imagecreatetruecolor($new_width, $new_height );
if(!empty($this->img_resource)){
if (!imagecopyresampled ( $this->img_new, $this->img_resource, 0, 0, 0, 0, $new_width, $new_height, $img_info[0], $img_info[1] )){
throw new image_exception("Image not resampled");
}
} else {
throw new image_exception("Height and or width is missing");
}
}
protected function __destruct(){
if($this->img_resource){
imagedestroy($this->img_resource);
}
}
}Code: Select all
class gg_jpeg_image extends gg_image {
protected $img_manager;
protected $img_res = 72;
public function generate_image(){
//make sure gd is capable of handling this file type.
if($this->is_gd_capable()){
$this->image_header($this->img_manager->get_image());
try{
//First try to create a resource from existing image.
$this->create_image_from();
//Second try to resize the old image.
$this->image_resize();
//Finally try to output or save image.
$this->create_image();
} catch ( image_exception $e){
//If something goes wrong output error image;
$e->__toString();
}
} else {
die('Sorry your version of GD does not support jpg file types');
}
}
public function image_header(){
header('Content-type: image/jpeg');
}
public function is_gd_capable(){
if(imagetypes() & IMG_JPG){
return true;
} else {
return false;
}
}
public function create_image_from(){
$this->img_resource = @imagecreatefromjpeg ($this->img_manager->get_image());
if(empty($this->img_resource)){
throw new image_exception('No image resource/id created');
}
}
public function create_image(){
$img_dest = $this->img_manager->get_image_dest();
if( !imagejpeg( $this->img_new, $this->img_dest, $this->img_res ) ){
throw new image_exception('Image not saved or output.');
}
}
public function set_image_res( int $res){
$this->img_res = $res;
}
public function get_image_res(){
return $this->img_res;
}
}Code: Select all
class image_exception extends Exception{
protected $img_manager;
function __construct(gg_image_manager $im ){
$this->img_manager = $im;
}
function __toString($message=""){
//die( $this->img_manager->get_image()." ".$message );
$image_width = strlen($message)*12;
$im = imagecreatetruecolor($image_width, 30);
$bgc = imagecolorallocate($im, 255, 255, 255);
$tc = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, $image_width, 30, $bgc);
header('Content-type: image/jpeg');
imagestring($im, 1, 5, 5, $message, $tc);
imagejpeg($im);
}
}Code: Select all
$imgm = new gg_image_manager('old_house1.jpg', 200);
$img = $imgm->manage_image();
$img->generate_image();