블로그 이미지
괴스트

예진이와 고고씽!!

Rss feed Tistory
Dev/php 2010/03/24 15:54

리사이징 함수 사용법

크리에이티브 커먼즈 라이선스
Creative Commons License

UPDATE: I’ve added support for PNG alpha transparency which makes this class significantly more useful. Changelog in the class code below.

I keep misplacing this class so I figured I’d post it here so that I know where it is.

I wrote/assembled this class because I wasn’t happy with any of the image manipulation libraries out there. They are either way too complex with a steep learning curve or didn’t work all that great. (I didn’t see any reason to load up a class with 3,000 lines of code just to resize or rotate an image.)

So here it is, a simple class that allows you to open an image, perform common operations, and save. There are no bells and whistles or anything exciting here. Just a collection of commonly used image manipulation functions: Rotate, Flip, Resize, Thumbnail (square and regular), and Crop.

A lot of the class code is original but some of it has been gathered over my life as a programmer from long lost sources. If you recognize your work, leave a comment and I’d be happy to cite you!

The concept is pretty simple.  You open an image, and then perform your operations before saving the output, or writing it to a different file.  The code is not optimized for batch processing of images, so be warned.  It is mainly for when you are accepting uploads of profile photos or similar and need to resize it and generate thumbnails and all that shtuff.  Enjoy and comment any questions/improvements/problems/etc.!

Creation – Getting Started

Before you can start working on an image, you must create an instance of the Image class.

All of these examples use Ephective’s logo as the test image:

view source
print?
1 $I = new Image('ephective.png');

You can also create an empty instance of Image by doing “$I = new Image();” and open, or set the image at a later time:

  • $I->open( file ) – Open a file from disk
  • $I->resource( image resource ) – Set an image resource

Saving

Before I’ll go on to explaining all the functions, you should first know how to save your work.

If you have opened a file from disk, you will probably want to save your changes back to that file.

view source
print?
1 // this will save your changes back to the file that you've opened
2 // if you didn't open a file (passed a resource) this function will not work
3 $I->save()

The second option is to write your changes to a different file.

view source
print?
1 $I->write( 'my_new_file.png' )

You could also get the image resource and do some additional custom processing on your own:

view source
print?
1 // now contains the image resource, you could write it to disk if you'd like
2 $res = $I->resource();

Rotate: $I->rotate( $degrees [ , $bkg ] )

Now that we have the image loaded, we can begin using the simple functions to manipulate it.

Rotate can rotate the image by any number of degrees. If you rotate by anything except a multiple of 90, you will end up with the image appearing on an angle. This will automatically resize the dimensions of the image and set background color using the optional $bkg (defaults to black).  The color must be allocated with imagecolorallocate or whatever it is… an example exists at the end of this page.

view source
print?
1 // rotates the image 38 degrees
2 $I->rotate(38);

Before: After:

Notice how the image is larger and has a black background fill.

There are several shortcut functions to rotate an image and an additional special auto_rotate function.

  • $I->rotate( $degrees [ , $bkg=0 ] )
  • $I->rotate_left()
  • $I->rotate_right()
  • $I->rotate_180() – This turns the image upside down
  • $I->auto_rotate() – There is also a special function called auto_rotate. auto_rotate will check to see if there is any orientation information in the exif data for the image. If there is, the image will automatically be rotated to the correct orientation. Note: This function only works if you have the PHP exif extension.

Here is an example of rotate_left:

view source
print?
1 $I->rotate_left();

rotate_left: rotate_right: rotate_180:

Full Snippet:

view source
print?
1 require 'Image.php';
2   
3 $I = new Image('ephective.png');
4   
5 $I->rotate(38);
6 $I->save(); // will save the changes back to the file
7 $I->destroy(); // free the memory

Flip: $I->flip( $bFlipH [ , $bFlipV=false ] )

Flip will mirror an image in a certain direction—either horizontally or vertically.

There are a few shortcut functions to flip an image.

  • $I->flip( $bFlipH [ , $bFlipV=false ] )
  • $I->flip_h()
  • $I->flip_v()
  • $I->flip_both() – This is the same as rotate_180 only much more processor intense. Just use rotate_180
view source
print?
1 require 'Image.php';
2   
3 $I = new Image('ephective.png');
4   
5 $I->flip_v();
6 $I->save(); // will save the changes back to the file

Before: flip_v: flip_h: flip_both:

Resize: $I->resize( $newdim [ , $square=false [ , $bHeight=false [ , $resample=true ] ] ] )

You can only resize images and maintain proportions. I figured, in most day-to-day image operations you are resizing photos and such, so why would you want to squish the picture? So, to resize, you will only need to specify the largest dimension you want to allow. To make that a little more clear, think of Facebook profile photos. They always resize to a width of around 200 pixels. This results in some photos being much taller than others, but they are always 200 px wide.

The basic code to do something similar with Image is:

view source
print?
1 $I->resize ( 200 );

There are the following resize functions:

  • $I->resize( $newdim [ , $square=false [ , $bHeight=false [ , $resample=true ] ] ] ) – By default, resize performs the same operation as width. Setting bHeight to true would make resize perform the same as height.
  • $I->width( $newdim [ , $square=false [ , $resample=true ] ] )
  • $I->height( $newdim [ , $square=false [ , $resample=true ] ] )
  • $I->resize_1600()
  • $I->resize_1200()
  • $I->resize_1024()
  • $I->resize_800()
  • $I->resize_640()

When settings the $newdim, you can give an actual pixel count ($newdim=200;), a decimal percentage less than 1 ($newdim=0.5;), or a string percentage ($newdim=’50%’;).

Before: width(60) pixels: width(‘50%’) string percent: width(.3) decimal:

Thumbnail: $I->thumbnail( $dest, $newdim [ , $square=NULL [ , $bHeight=false [ , $out=false [ , $resample=true ] ] ] ] )

Thumbnail is identical to resize except thumbnail does not alter the classes image resource at all. This means that the original image is left untouched.

Crop: $I->crop( $top [ , $right=0 [ , $bottom=0 [ , $left=0 ] ] ] )

Instead of specifying a selection inside the current image, crop works by letting you specify how much to trim off the edges. So if you wanted to trim 50 pixels off the top and bottom sides of the image, you could do the following:

view source
print?
1 $I->crop(50, 0, 50);

There are the following resize functions:

  • $I->crop( $top [ , $right=0 [ , $bottom=0 [ , $left=0 ] ] ] )
  • $I->crop_top( $px )
  • $I->crop_right( $px )
  • $I->crop_bottom( $px )
  • $I->crop_left( $px )
  • $I->crop_h( $px ) – Top and bottom
  • $I->crop_v( $px ) – Left and right
  • $I->crop_all( $px ) – All sides (contract)

Before: crop_all(10): crop(18, 25, 28, 20): crop_v(20): crop_h(20): crop_all(20):

Combining Modifications

You can combine as many modifications as you’d like:

view source
print?
01 $I = new Image('ephective.png');
02   
03 // loop through and incrementally change the color and rotate
04 for ( $i=0; $i < 255; $i+=10 )
05 {
06     $color = imagecolorallocatealpha( $I->resource(), 255, $i, $i, 0 );
07     $I->rotate(5, $color);
08 }
09   
10 // each rotation increases the images dimensions, shrink it down to a reasonable size
11 $I->width(.3);
12   
13 // write the output to a separate file
14 $I->write('ephective-combine.png');
15   
16 // free the memory
17 $I->destroy();

view source
print?
001 // v.0.2.1
002 /*
003 CHANGELOG
004   
005 0.2.1       -Added output() screen, in addition to save/write
006             -Added support for PNG transparency
007             -Made contenttype the PNG by default
008   
009 */
010 class Image
011 {
012     var $res            = NULL;
013     var $source         = NULL;
014     var $contenttype    = IMAGETYPE_PNG;
015   
016     /***
017      * Constructor
018      * $src_or_resource: src is the path to an image.  If it exists, the image will be automatically opened
019      *      can also be an already created image resource
020      */
021     function Image ($src_or_resource=NULL)
022     {
023         if( ! is_null($src_or_resource) )
024             if ( is_resource($src_or_resource) )
025                 $this->resource($src_or_resource);
026             else
027                 $this->open($src_or_resource);
028     }
029   
030     /***
031      * Rotate the active image
032      * $degrees: number of degrees to spin the image, if this is something like
033      *      45, it will leave gaps in the frame which will be filled in by $bkg
034      * $bkg: If image is rotated in a way that does not fill the frame, this is the color that will be used
035      */
036     function rotate ($degrees, $bkg='0')
037     {
038         $im = imagerotate( $this->res, $degrees, $bkg );
039         imagedestroy($this->res);
040         $this->res = $im;
041     }
042   
043     /***
044      * Rotate image right
045      * Shortcut function that will rotate the image to the right
046      */
047     function rotate_right() { $this->rotate(270); }
048   
049     /***
050      * Rotate image 180 degrees
051      * Shortcut function that will rotate the image 180 degrees
052      */
053     function rotate_180() { $this->rotate(180); }
054   
055     /***
056      * Rotate image left
057      * Shortcut function that will rotate the image to the left
058      */
059     function rotate_left() { $this->rotate(90); }
060   
061     /***
062      * Attempt to automatically rotate the image based on exif data
063      *  a lot of digital cameras store orientation data of the camera
064      *      this will use that to automatically fix an images orientation
065      *
066      *      Note: This will only work if you have the function exif_read_data
067      *          which is part of PHPs exif data extension
068      */
069     function auto_rotate() {
070         if( ! function_exists('exif_read_data') ) return false;
071         $exif = exif_read_data($this->source);
072   
073         $ort = $exif['IFD0']['Orientation'];
074          switch($ort) // http://www.impulseadventure.com/photo/exif-orientation.html
075          {
076             case 1: // regular, do nothing
077                 break;
078             case 2:
079                 return $this->flip_h();
080             case 3:
081                 return $this->rotate_180();
082             case 4:
083                 return $this->flip_v();
084             case 5:
085                 return ($this->flip_h() && $this->rotate_right());
086             case 6:
087                 return $this->rotate_right();
088             case 7:
089                 return ($this->flip_h() && $this->rotate_left());
090             case 8:
091                 return $this->rotate_left();
092          }
093     }
094   
095     /***
096      * Will flip an image (mirror it)
097      *
098      * $bFlipH: flip horizontal  (true/false)
099      * $bFlipV: flip vertical (true/false)
100      *
101      */
102     function flip($bFlipH, $bFlipV=false)
103     {
104         $imgsrc = $this->res;
105         $width = imagesx($imgsrc);
106         $height = imagesy($imgsrc);
107         $imgdest = imagecreatetruecolor($width, $height);
108         $this->prepare($imgdest);
109   
110         for ($x=0 ; $x<$width ; $x++)
111         {
112             for ($y=0 ; $y<$height ; $y++)
113             {
114                 if ($bFlipH && $bFlipV) imagecopy($imgdest, $imgsrc, $width-$x-1, $height-$y-1, $x, $y, 1, 1);
115                 else if ($bFlipH) imagecopy($imgdest, $imgsrc, $width-$x-1, $y, $x, $y, 1, 1);
116                 else if ($bFlipV) imagecopy($imgdest, $imgsrc, $x, $height-$y-1, $x, $y, 1, 1);
117             }
118         }
119   
120         $this->res = $imgdest;
121         imagedestroy($imgsrc);
122     }
123   
124     /***
125      * Shortcut functions to flip
126      */
127     function flip_h() { $this->flip(true, false); }
128     function flip_v() { $this->flip(false, true); }
129     function flip_both() { $this->flip(true, true); }
130   
131     /***
132      * Resizes an image to fit in a certain size
133      *
134      * $newdim:  This is the largest dimension the image can contain in
135      *      pixels.  If either of the measurements are larger than this size,
136      *      the image will be scaled
137      *
138      * $square: (true/false) make the new image square instead of keeping the dimensions
139      *
140      * $resample: high quality resize?  it is good to turn this off if you are doing
141      *      lots of conversions and quality isn't a huge issue
142      *      resample on/off is a noticeable difference in time
143      */
144     function resize($newdim, $square=false, $bHeight=false, $resample=true) {
145         $src_width  = imagesx( $this->res );
146         $src_height = imagesy( $this->res );
147         $src_w      = $src_width;
148         $src_h      = $src_height;
149         $src_x      = 0;
150         $src_y      = 0;
151   
152         $percent = false;
153         if ( $newdim < 1 )
154             $percent = $newdim;
155         elseif ( substr($newdim, -1) == '%' )
156             $percent = substr($newdim, 0, -1)/100;
157   
158         if ( false !== $percent )
159             $newdim = round( ($bHeight ? ($src_height*$percent) : ($src_width*$percent) ) );
160   
161         if ($square)
162         {
163             $dst_w = $newdim;
164             $dst_h = $newdim;
165             if ( ! $bHeight )
166             {
167                 $src_x = ceil( ( $src_width - $src_height ) / 2 );
168                 $src_w = $src_height;
169                 $src_h = $src_height;
170             }
171             else
172             {
173                 $src_y = ceil( ( $src_height - $src_width ) / 2 );
174                 $src_w = $src_width;
175                 $src_h = $src_width;
176             }
177         }
178         else
179         {
180             if ( ! $bHeight )
181             {
182                 $dst_w = $newdim;
183                 $dst_h = floor( $src_height * ($dst_w / $src_width) );
184             }
185             else
186             {
187                 $dst_h = $newdim;
188                 $dst_w = floor( $src_width * ($dst_h / $src_height) );
189             }
190         }
191         $dst_im = imagecreatetruecolor($dst_w,$dst_h);
192         $this->prepare($dst_im);
193         if ($resample)
194             imagecopyresampled($dst_im, $this->res, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
195         else
196             imagecopyresized($dst_im, $this->res, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
197   
198         imagedestroy($this->res);
199         $this->res = $dst_im;
200     }
201   
202     /***
203      * Shortcut functions to resize an image to certain, standard sizes
204      */
205     function width($newdim, $square=false, $resample=true) { $this->resize($newdim, $square, false, $resample); }
206     function height($newdim, $square=false, $resample=true) { $this->resize($newdim, $square, true, $resample); }
207     function resize_1600($square=false) { $this->resize(1600, $square); }
208     function resize_1200($square=false) { $this->resize(1200, $square); }
209     function resize_1024($square=false) { $this->resize(1024, $square); }
210     function resize_800($square=false) { $this->resize(800, $square); }
211     function resize_640($square=false) { $this->resize(640, $square); }
212   
213     /***
214      * Generate a thumbnail from the loaded image
215      *
216      * $dest:  The destination file on disk to save new thumbnail
217      *
218      * $out: The type of image to create (uses PHPs standard image constants for PNG, JPG, GIF)
219      *
220      * $newdim:  This is the largest dimension the image can contain in
221      *      pixels.  If either of the measurements are larger than this size,
222      *      the image will be scaled
223      *
224      * $square: create a square thumbnail
225      *
226      * $resample: high quality resize?  it is good to turn this off if you are doing
227      *      lots of conversions and quality isn't a huge issue
228      */
229     function thumbnail($dest, $newdim, $square=false, $bHeight=false, $out=NULL, $resample=true) {
230         $src_width  = imagesx($this->res);
231         $src_height = imagesy($this->res);
232         $src_w      = $src_width;
233         $src_h      = $src_height;
234         $src_x      = 0;
235         $src_y      = 0;
236   
237         $percent = false;
238         if ( $newdim < 1 )
239             $percent = $newdim;
240         elseif ( substr($newdim, -1) == '%' )
241             $percent = substr($newdim, 0, -1)/100;
242   
243         if ( false !== $percent )
244             $newdim = round( ($bHeight ? ($src_height*$percent) : ($src_width*$percent) ) );
245   
246         if ($square)
247         {
248             $dst_w = $largest_dim;
249             $dst_h = $largest_dim;
250             if ( ! $bHeight )
251             {
252                 $src_x = ceil( ($src_width - $src_height) / 2 );
253                 $src_w = $src_height;
254                 $src_h = $src_height;
255             }
256             else
257             {
258                 $src_y = ceil( ($src_height - $src_width) / 2 );
259                 $src_w = $src_width;
260                 $src_h = $src_width;
261             }
262         }
263         else
264         {
265             if ( ! $bHeight )
266             {
267                 $dst_w = $largest_dim;
268                 $dst_h = floor( $src_height * ($dst_w / $src_width) );
269             }
270             else
271             {
272                 $dst_h = $largest_dim;
273                 $dst_w = floor( $src_width * ($dst_h / $src_height) );
274             }
275         }
276         $dst_im = imagecreatetruecolor($dst_w,$dst_h);
277         $this->prepare($dst_im);
278         if ($resample)
279             imagecopyresampled($dst_im, $this->res, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
280         else
281             imagecopyresized($dst_im, $this->res, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
282   
283         if ( is_null($out) )
284             $out = $this->contenttype;
285         switch($out)
286         {
287             case IMAGETYPE_PNG:
288               imagepng($dst_im, $dest);
289             break;
290             case IMAGETYPE_GIF:
291               imagegif($dst_im, $dest);
292             break;
293             case IMAGETYPE_JPEG:
294   
295               imagejpeg($dst_im, $dest);
296             break;
297         }
298         imagedestroy($dst_im);
299     }
300   
301     /***
302      * Shortcut functions to some standard thumbnail sizes
303      */
304     function thumbnail_xsmall($dest, $out, $square=false) { $this->thumbnail($dest, $out, 60, $square); }
305     function thumbnail_small($dest, $out, $square=false) { $this->thumbnail($dest, $out, 80, $square); }
306     function thumbnail_medium($dest, $out, $square=false) { $this->thumbnail($dest, $out, 160, $square); }
307     function thumbnail_large($dest, $out, $square=false) { $this->thumbnail($dest, $out, 300, $square); }
308     function thumbnail_xlarge($dest, $out, $square=false) { $this->thumbnail($dest, $out, 512, $square); }
309   
310     /***
311      * Crop an image by N pixels
312      *
313      * Same order as CSS property
314      *
315      * This will crop an image by the number of pixels you specify.
316      *      For example, to crop 10 pixels off the bottom and left sides
317      *      you would do crop(10, 0, 10)
318      */
319     function crop ($top, $right=0, $bottom=0, $left=0)
320     {
321         $w  = imagesx($this->res);
322         $h  = imagesy($this->res);
323         $nw = $w - ($left+$right);
324         $nh = $h - ($top+$bottom);
325         $im = imagecreatetruecolor( $nw, $nh );
326         $this->prepare($im);
327   
328         imagecopy($im, $this->res, 0, 0, $left, $top, $nw, $nh );
329   
330         imagedestroy($this->res);
331         $this->res = $im;
332     }
333   
334     /***
335      * Shortcut functions to crop
336      */
337     function crop_top($px) { $this->crop($px); }
338     function crop_right($px) { $this->crop(0, $px, 0, 0); }
339     function crop_bottom($px) { $this->crop(0, 0, $px, 0); }
340     function crop_left($px) { $this->crop(0, 0, 0, $px); }
341     function crop_h($px) { $this->crop($px, 0, $px, 0); }
342     function crop_v($px) { $this->crop(0, $px, 0, $px); }
343     function crop_all($px) { $this->crop($px, $px, $px, $px); }
344   
345     /***
346      * Open an image from a file on disk
347      */
348     function open($src)
349     {
350         $this->source = $src;
351         switch( ( $this->contenttype = exif_imagetype($src) ) )
352         {
353             case IMAGETYPE_PNG:
354               $this->res = imagecreatefrompng($src);
355             break;
356             case IMAGETYPE_GIF:
357               $this->res = imagecreatefromgif($src);
358             break;
359             case IMAGETYPE_JPEG:
360               $this->res = imagecreatefromjpeg($src);
361             break;
362         }
363   
364         $this->prepare($this->res);
365     }
366   
367     // takes an image resource and a content type and prepares the resource
368     function prepare($res, $contenttype=NULL)
369     {
370         if ( is_null($contenttype) ) $contenttype = $this->contenttype;
371   
372         if ( $contenttype == IMAGETYPE_PNG )
373         {
374             imagesavealpha($res, true);
375             imagealphablending($res, false);
376         }
377     }
378   
379     /***
380      * Get/set image resource
381      */
382     function resource ($res=NULL)
383     {
384         if ( is_null($res) )
385             return $this->res;
386         else
387             $this->res = $res;
388     }
389   
390     /***
391      * Save the image back to the original file
392      */
393     function save($out=NULL)
394     {
395         if ( ! is_null($this->source) )
396             $this->write($this->source, $out);
397     }
398   
399     /***
400      * Save the image to a different location
401      */
402     function write($dest, $out=NULL)
403     {
404         if(is_null($out))
405             $out = $this->contenttype;
406   
407         switch($out)
408         {
409             case IMAGETYPE_PNG:
410               imagepng($this->res, $dest);
411             break;
412             case IMAGETYPE_GIF:
413               imagegif($this->res, $dest);
414             break;
415             case IMAGETYPE_JPEG:
416               imagejpeg($this->res, $dest);
417             break;
418         }
419     }
420   
421     /***
422      * Output the image to the stream (browser)
423      */
424     function output($out=NULL)
425     {
426         switch($out)
427         {
428             default:
429             case IMAGETYPE_PNG:
430               $contenttype = 'png';
431             break;
432             case IMAGETYPE_GIF:
433               $contenttype = 'gif';
434             break;
435             case IMAGETYPE_JPEG:
436               $contenttype = 'jpeg';
437             break;
438         }
439   
440         header('Content-type: image/'.$contenttype);
441         $this->write(NULL, $out);
442     }
443   
444     /***
445      * Kill self
446      */
447     function destroy()
448     {
449         imagedestroy($this->res);
450         $this->source=NULL;
451         $this->contenttype = NULL;
452     }
453 }
454   
455 if( ! function_exists('exif_imagetype') )
456 {
457     function exif_imagetype ( $f )
458     {
459         if ( false !== ( list(,,$type,) = getimagesize( $f ) ) )
460             return $type;
461         return IMAGETYPE_PNG; // meh
462     }
463 }
저작자 표시
TOTAL 114,290 TODAY 48