Imagine中文文件
很多PHPER在處理圖片庫的時候都會選擇Imagine,不過這個庫只有英文文件,昨日翻譯一下,送給需要的同學。

Imagine是一個PHP5.3+的圖片處理庫,對於圖片的處理可以使用GD2、Imagick或Gmagick。
能實現什麼
Imagine具有強大的功能和簡潔的API介面,眾多PHP框架都採用Imagine來完成對圖片的操作。
目前為止Imagine能實現功能如下
- 圖片的大小調整及裁剪等操作。
- 繪圖,建立基本圖形和高階圖表。
- 蒙版功能,實現影象的半透明或絕對透明功能。
安裝Imagine
可以使用composer方便的進行Imagine安裝,如下程式碼
php composer.phar require imagine/imagine 複製程式碼
在這一章我們使用Imagine完成一些有趣的事情,通過這些事情你可以熟悉Imagine的使用流程。
目錄結構
我們先來熟悉一下Imagine庫的目錄結構

上面目錄具體乾的事情如下
- Draw
- Effects
- Exception
- Filter
- Gd
- Gmagick
- Image
- Imagick
- resources
不要被這麼多目錄所迷惑,Imagine是一個設計非常清晰及現代的圖片庫,支援了主流的底層庫,擴充套件性非常強,作者為了後期擴充套件方便提供了幾個基礎介面來撐起Imagine。
它們分別是
- ImagineInterface
- ImageInterface
- FontInterface
- DrawerInterface
- ....
這裡面最重要的是 ImagineInterface 和 ImageInterface 。
ImagineInterface
ImagineInterface是Imagine的核心,一起從它開始,它存在於 Imagine/Image/ImagineInterface.php ,當然這是一個介面,針對Gd、Imagick和Gmagick不同的庫,在對應資料夾的 Imagine.php 檔案對此介面進行了實現,具體位置請看下面列表。
- Imagine/Gd/Imagine.php
- Imagine/Gmagick/Imagine.php
- Imagine/Imagick/Imagine.php
ImagineInterface就像一個工廠,通過ImagineInterface介面的類可以新建、開啟影象,並且返回一個 ImageInterface 物件,而在 ImageInterface 提供了對圖片的具體操作。
現在我們來舉一個例子
$imagine = new ImagineGdImagine(); $image = $imagine->open('/xxx/image.jpg'); 複製程式碼
上面的例子邏輯是這樣的
- 首先建立一個ImagineInterface物件$imagine,這裡使用的是GD庫
- 使用 image
ImageInterface
通過上面的ImagineInterface我們打開了一個物件,並且得到了ImageInterface的例項化物件,ImageInterface也是一個抽象的介面,針對不同的庫有不同的實現,它們都在叫做Image的類中,目錄如下
- Imagine/Gd/Image.php
- Imagine/Gmagick/Image.php
- Imagine/Imagick/Image.php
開啟任何一個Image.php,你會發現很多熟悉的單詞,比如copy、resize、save、fill等很多方法,這些就是對圖片的具體操作,當然在這裡還可以通過於FontInterface、DrawerInterface等實現更加牛x的效果。
接下來我們擴充套件下上面的例子
$imagine = new ImagineGdImagine(); $image = $imagine->open('/xxx/image.jpg'); $image->save('/xxx/image.png'); 複製程式碼
上面的例子是在xxx目錄下對於開啟的圖片image.jpg,另存為image.png格式,很方便。
總結
我們來總結一下,Imagine的核心思路非常簡單,提供足夠清晰的介面並且容納足夠多的圖片處理庫,針對於對圖片的不同操作,比如Draw、Effects、Filter等建立一系列的介面,然後在具體的庫中對這些介面進行實現。
所以我們在Gd、Gmagick和Imagick檔案下內你看到了相同名稱的檔案。
- Drawer.php
- Effects.php
- Font.php
- Image.php
- Imagine.php
- Layers.php
一套介面,各種庫對其進行實現,這就是 Imagine 。
首先我們要學習下什麼是元資料?元資料是用來描述資料的資料(Data that describes other data),比如一張數碼照片我們可以讀取到拍此照片的相機型別、品牌等等,這些就是元資料。
大神阮一峰曾寫了一篇小文來說元資料,感興趣的可以看看。傳送門
訪問影象元資料
有了Imagine,讀取元資料變的非常簡單,我們只需要呼叫方法即可,請看例子。
$imagine = new ImagineGdImagine(); $image = $imagine->open('/xxx/image.jpg'); var_dump($image->metadata()); 複製程式碼
我們使用metadata方法得到基本的元資料,看看輸出資料的解構。

通過結果我們看到metadata方法得到的是 ImageMetadataMetadataBag 類物件,包含的資訊是 filepath 和 uri。
元資料讀取器(metadata reader)
你可能差異元資料就這點資訊麼? 還可以更多 。
Imagine內建提供了兩種元資料讀取器,它們負責讀出影象元資料並提供給上面的metadata,預設的讀取器是 Imagine/Image/Metadata/DefaultMetadataReader.php 。
還有一個叫做 Imagine/Image/Metadata/ExifMetadataReader.php,使用 ExifMetadataReader 可以讀取影象的Exif資訊,接下來我們學習如何讓Imgaine使用 ExifMetadataReader 讀取器。
use ImagineImageMetadataExifMetadataReader; $imagine = new ImagineGdImagine(); $image = $imagine->setMetadataReader(new ExifMetadataReader())->open('/xxx/image.jpg'); var_dump($image->metadata()); 複製程式碼
看明白了吧,我們需要呼叫 $imagine 的setMetadataReader方法並傳入ExifMetadataReader物件。
注意ExifMetadataReader的生效需要你的PHP擁有exif擴充套件,否則會有如下報錯。

當這一切都滿足後,你通過 metadata() 得到的 MetadataBag 物件將擁有Exif資訊,你可以獲得更多有用的。
自定義
一般來說使用 ExifMetadataReader 我們就足以滿足業務需求了,但是Imagine還是提供了MetadataReaderInterface介面,允許我們自己定義自己的元資料讀取器。
方法可以參考內建的另種讀取器,繼承於虛擬類 AbstractMetadataReader即可。
在Imagine處理圖片時座標是一個非常重要的概念,比如裁剪、伸縮等等都需要用到它,本章帶你瞭解它。
座標系統
在初中的時候我們學過座標系,它叫笛卡爾座標,如下圖

這是我們學的,左下角是起點(x=0,y=0),但是Imagine座標系統中起點位置有所不同,它以左上角為起點,相應地向右和向下延伸。另外就是沒有負座標。
相關類
Imagine中提供給了兩個介面,分別是
- ImagineImagePointInterface 表示邊界框中的單個點
- ImagineImageBoxInterface 代表尺寸(寬度,高度)
分別比ImagineImage下的Box類和Point類所實現,並且被其他類所使用,比如當我們呼叫$image->getSize的時候就用到。

PointInterface
每一個座標都有如下方法
- getX()
- getY()
- in(BoxInterface $box)
- __toString()
BoxInterface
每個盒子或影象或形狀都有一個大小,以下幾種方法:
- getWidth() - 返回整數寬度
- getHeight() - 返回整數高度
- scale( ratio
- increase( size新增給每一方
- contains(BoxInterface start = null)-檢查給定 start位置。如果沒有$start給出位置,則假定為(0,0)
- square()- 返回整數的當前平方,例如BoxInterface,用於確定框中畫素的總數
- __toString()- 返回當前的字串表示BoxInterface,例如100x100 px
- widen($width) - 將框調整為給定寬度,約束比例並返回新框
- heighten($height) - 將框調整到給定高度,約束比例並返回新框
場景
PointInterface 和 BoxInterface 經常用到其他方法或新建一個影象並繪製的場景,關於這些場景我們會在接下來的章節中逐漸涉及。
Imagine提供了比較強大的繪製能力,我們可以通過Imagine新建一個模板,然後繪製圖形。在這一篇裡你也能更加熟練的使用上一篇的座標相關介面。
做一個圖
我們現在實現一個需求,很簡單,一張橙色背景400x300的影象,然後畫一個線,開始啦
use ImagineGdImagine; use ImagineImagePoint; use ImagineImageBox; use ImagineImagePaletteRGB; $palette = new RGB(); $imagine = new Imagine(); $box = new Box(400,300); $image = $imagine->create($box,$palette->color('#FF6900')); $image->draw()->line(new Point(200,150),new Point(250,250),$palette->color('#000000')); $image->show('png'); 複製程式碼
上面程式碼的結果如下

結果分析
針對上面的圖片,我們來複盤一下Imagine的實現思路。
- 首先我們要使用 $imagine->create 方法生成一個影象,影象包含尺寸和背景色。
- 尺寸是由上一篇的Box介面實現類來完成的,$box = new Box(400,300);,顏色則是RGB類。
- 然後呼叫$image的draw()方法,此方法的結果是得到一個drawer物件,同時擁有很多方法。
- 我們使用drawer物件的line方法,畫一條線。
- 隨後將圖片以png的格式展示出來。
繪製方法一覽
通過上面我們知道要繪圖其實是呼叫了Image物件的draw方法,此刻我們看看draw內部的邏輯。
// Imagine/Gd/Image.php public function draw() { return new Drawer($this->resource); } 複製程式碼
draw方法如此簡單,僅僅return了Drawer的例項化物件,因此Imagine的繪圖功能就回到了Drawer類上了。
還記得我們之前說的麼?Imagine更多是提供了一系列的介面,因此在Gd等庫中的Drawer類就是對DrawerInterface介面的實現,這個介面在 Imagine/Draw/DrawerInterface.php 中。
接下來我們看看Imagine的繪圖功能到底有哪些?
- arc 弧線
- chord 弦
- ellipse 橢圓
- line 直線
- pieSlice 餅圖
- dot 點
- polygon 多邊形
- text 文字
對,DrawerInterface介面定義了8個方法,所以實現此介面的類都需要實現它們,繪圖是最好練習Box和Point的途徑,建議你多畫一畫。
一般來說,當我們使用Imagine時涉及到了顏色,不會直接傳遞顏色值,而是傳遞一個Palette物件,比如下面的例子。
$palette = new ImagineImagePaletteCMYK(); $imagine->create(new ImagineImageBox(10, 10), $palette->color('#FFFFFF')); 複製程式碼
支援類
Imagine提供了兩個類,RGB和CMYK。
- new ImagineImagePaletteRGB();
- new ImagineImagePaletteCMYK();
使用上首先呼叫響應的類,例項化
$palette = new ImagineImagePaletteRGB(); 複製程式碼
得到物件後呼叫color方法,傳入顏色值,得到一個Color物件,這個Color物件經常作為其他方法的引數。
$white = $palette->color('fff', 100); $white = $palette->color('ffffff', 100); $white = $palette->color('#fff', 100); $white = $palette->color('#ffffff', 100); $white = $palette->color(0xFFFFFF, 100); $white = $palette->color(array(255, 255, 255), 100); 複製程式碼
color方法有兩個引數
- 顏色值
- 透明度
改變模式
這個需求你可能很少遇見但是它存在,我們將一個圖片從CMYK模式改為RGB模式,可以如下操作。
$image = $imagine->open('my-cmyk-jpg.jpg'); $image->usePalette(new ImagineImagePaletteRGB()) ->save('my-rgb-jpg.jpg'); 複製程式碼
注意
這裡需要注意,不同的驅動對顏色的支援有所區別
- GD僅支援RGB影象。
- Imagick支援CMYK,RGB和灰度色彩空間。
- Gmagick僅支援CMYK和RGB色彩空間。
圖層的概念經常出現在作圖軟體中,比如PS軟體匯出PSD檔案,還有就是gif格式的圖片,Imagine通過其layers方法提供了此功能。
注意並不是所有的庫都支援圖層,比如GD庫就不支援,因此如果你想使用圖層請不要選擇它。
關於圖層我在這裡並不打算做詳細的講解,一來這是進階內容,二來使用圖層生成動畫操作並不常用,不過有些操作依然很有用,那就是圖層的讀取,比如你想抽取一個gif動圖的某一層,甚至包含對一些多圖層圖片的資料分析,使用imagine更加適合。
常用方法
得到一個圖片圖層的數量
$image = $imagine->open('image.jpg'); echo "Image contains " . count($image->layers()) . " layers"; 複製程式碼
迴圈每個圖層
$image = $imagine->open('image.jpg'); foreach ($image->layers() as $layer) { // ... } 複製程式碼
匯出gif動畫的每一層為圖片
$i = 0; foreach ($imagine->open('cats.gif')->layers() as $layer) { $layer->save("frame-$i.png"); $i++; } 複製程式碼
給一個gif檔案每一層新增文字
$image = $imagine->open('cats.gif'); $i = 0; foreach ($image->layers() as $layer) { $layer->draw() ->text($i, new Font('coolfont.ttf', 12, $image->palette()->color('white')), new Point(10, 10)); $i++; } // save modified animation $image->save('cats-modified.gif', array('flatten' => 'false')); 複製程式碼
Imagine還提供功能齊全的特效API。要使用api,您需要使用ImageInterface::effects()方法從當前影象例項獲取效果例項。
我們先來一個最簡單的例子
$imagine = new Imagine(); $image = $imagine->open(Yii::getAlias("@webroot")."/images/qrcode.jpeg"); $image->effects() ->grayscale(); 複製程式碼
套路都是一樣的,通過$image->effects()獲得Effects類物件,然後執行一些列特效方法,而無論是GD、Imagick還是Gmagick庫的Effects類都是對 Imagine/Effects/EffectsInterface.php 介面的實現。
支援的特效
Imagine支援5中圖片效果,我們一個一個說。
gamma
gamma在平時是不常用的,只有在專業的影象領域才會使用,可以理解為色階,是灰階亮度值與灰階等級之間的數學關係。
這裡的Gamma功能是校正影象色階,使得影象看起來顏色更加正確。數字值取值範圍只有最小值沒有最大值只要 >=1.0都可以。
$image = $imagine->open(Yii::getAlias("@webroot")."/images/qrcode.jpeg"); $image->effects() ->gamma(2.0); 複製程式碼
negative
在數碼相機時代之前,佔統治地位的是膠捲相機,膠捲底片與洗出來的相片相比,底片的RGB值就是相片的RGB值取反,即:底片的紅色=255-相片的紅色,底片的綠色=255-相片的綠色,底片的藍色=255-相片的藍色。
$image = $imagine->open(Yii::getAlias("@webroot")."/images/qrcode.jpeg"); $image->effects() ->negative(); 複製程式碼
grayscale
使用Grayscale使圖片所有的色彩丟棄,只保留黑白兩種顏色,沒有取值。
$image = $imagine->open(Yii::getAlias("@webroot")."/images/qrcode.jpeg"); $image->effects() ->grayscale(); 複製程式碼
colorize
使用colorize引數,調整圖片的紅綠藍三個基礎色來改變圖片顏色。
此功能僅適用於Gd和Imagick驅動程式。
$imagine = new Imagine(); $p = new RGB(); $color = $p->color("#FF6900"); $image = $imagine->open(Yii::getAlias("@webroot")."/images/qrcode.jpeg"); $image->effects() ->colorize($color); 複製程式碼
sharpen
圖片銳化就是補償影象的輪廓,增強影象的邊緣及灰度跳變的部分,使影象變得清晰。
$image = $imagine->open(Yii::getAlias("@webroot")."/images/qrcode.jpeg"); $image->effects() ->sharpen(); 複製程式碼
blur
模糊化一張圖片
$image = $imagine->open(Yii::getAlias("@webroot")."/images/qrcode.jpeg"); $image->effects() ->blur(3); 複製程式碼