版本記錄
版本號 | 時(shí)間 |
---|---|
V1.0 | 2017.10.17 |
前言
ImageIO
框架主要用來讀寫大多數(shù)圖像文件格式起暮。 管理顏色和訪問圖像元數(shù)據(jù)捎废。接下來幾篇我們就詳細(xì)的解析這個(gè)框架秀睛。感興趣的可以看我寫的上面幾篇笼痹。
1. ImageIO框架詳細(xì)解析(一) —— 基本概覽
2. ImageIO框架詳細(xì)解析(二) —— 使用ImageIO基礎(chǔ)
創(chuàng)建和使用圖像源
一個(gè)圖像源抽象了數(shù)據(jù)訪問任務(wù),并消除了通過原始內(nèi)存緩沖區(qū)管理數(shù)據(jù)的需求识补。圖像源可以包含多個(gè)圖像族淮、縮略圖圖像、每個(gè)圖像的屬性和圖像文件凭涂。當(dāng)您使用圖像數(shù)據(jù)并在OS X v10.4中運(yùn)行應(yīng)用程序時(shí)祝辣,圖像源是將圖像數(shù)據(jù)移動到應(yīng)用程序的首選方法。創(chuàng)建CGImageSource
對象后切油,可以使用CGImageSource Reference中描述的函數(shù)獲取圖像蝙斜、縮略圖、圖像屬性和其他圖像信息澎胡。
Creating an Image from an Image Source - 從圖像源創(chuàng)建一個(gè)圖像
您將使用Image I/ O
框架執(zhí)行的最常見的任務(wù)之一是創(chuàng)建來自圖像源的圖像孕荠,類似于Listing 2 - 1
所示的圖像。這個(gè)例子展示了如何從路徑名創(chuàng)建圖像源攻谁,然后提取圖像岛琼。當(dāng)您創(chuàng)建一個(gè)圖像源對象時(shí),您可以提供一個(gè)關(guān)于映像源文件格式的提示巢株。
當(dāng)您從一個(gè)圖像源創(chuàng)建圖像時(shí),您必須指定一個(gè)索引熙涤,并且您可以提供一個(gè)屬性字典(鍵值對)來指定諸如是否創(chuàng)建縮略圖或允許緩存之類的事情阁苞。 CGImageSource Reference和CGImageProperties Reference 列表鍵和每個(gè)鍵值的預(yù)期數(shù)據(jù)類型。
您需要提供一個(gè)索引值祠挫,因?yàn)槟承﹫D像文件格式允許多個(gè)圖像駐留在同一個(gè)源文件中那槽。對于只包含一個(gè)圖像的圖像源文件,傳遞0等舔。通過調(diào)用函數(shù)CGImageSourceGetCount骚灸,您可以在一個(gè)圖像源文件中找到圖像的數(shù)目。
//Listing 2-1 Creating an image from an image source
CGImageRef MyCreateCGImageFromFile (NSString* path)
{
// Get the URL for the pathname passed to the function.
NSURL *url = [NSURL fileURLWithPath:path];
CGImageRef myImage = NULL;
CGImageSourceRef myImageSource;
CFDictionaryRef myOptions = NULL;
CFStringRef myKeys[2];
CFTypeRef myValues[2];
// Set up options if you want them. The options here are for
// caching the image in a decoded form and for using floating-point
// values if the image format supports them.
myKeys[0] = kCGImageSourceShouldCache;
myValues[0] = (CFTypeRef)kCFBooleanTrue;
myKeys[1] = kCGImageSourceShouldAllowFloat;
myValues[1] = (CFTypeRef)kCFBooleanTrue;
// Create the dictionary
myOptions = CFDictionaryCreate(NULL, (const void **) myKeys,
(const void **) myValues, 2,
&kCFTypeDictionaryKeyCallBacks,
& kCFTypeDictionaryValueCallBacks);
// Create an image source from the URL.
myImageSource = CGImageSourceCreateWithURL((CFURLRef)url, myOptions);
CFRelease(myOptions);
// Make sure the image source exists before continuing
if (myImageSource == NULL){
fprintf(stderr, "Image source is NULL.");
return NULL;
}
// Create an image from the first item in the image source.
myImage = CGImageSourceCreateImageAtIndex(myImageSource,
0,
NULL);
CFRelease(myImageSource);
// Make sure the image exists before continuing
if (myImage == NULL){
fprintf(stderr, "Image not created from image source.");
return NULL;
}
return myImage;
}
Creating a Thumbnail Image from an Image Source - 從圖像源創(chuàng)建縮略圖
一些圖像源文件包含可以檢索的縮略圖慌植。如果縮略圖還沒有出現(xiàn)甚牲,那么圖像I / O提供了創(chuàng)建它們的選項(xiàng)义郑。您還可以指定最大縮略圖尺寸,以及是否將變換應(yīng)用于縮略圖圖像丈钙。
Listing 2 - 2
展示了如何從數(shù)據(jù)創(chuàng)建圖像源非驮,建立一個(gè)包含與縮略圖相關(guān)的選項(xiàng)的字典,然后創(chuàng)建一個(gè)縮略圖雏赦。你可以使用kCGImageSourceCreateThumbnailWithTransform
鍵來指定是否縮略圖圖像應(yīng)該旋轉(zhuǎn)和縮放劫笙,以匹配完整圖像的方向和的像素長寬比。
// Listing 2-2 Creating a thumbnail image
CGImageRef MyCreateThumbnailImageFromData (NSData * data, int imageSize)
{
CGImageRef myThumbnailImage = NULL;
CGImageSourceRef myImageSource;
CFDictionaryRef myOptions = NULL;
CFStringRef myKeys[3];
CFTypeRef myValues[3];
CFNumberRef thumbnailSize;
// Create an image source from NSData; no options.
myImageSource = CGImageSourceCreateWithData((CFDataRef)data,
NULL);
// Make sure the image source exists before continuing.
if (myImageSource == NULL){
fprintf(stderr, "Image source is NULL.");
return NULL;
}
// Package the integer as a CFNumber object. Using CFTypes allows you
// to more easily create the options dictionary later.
thumbnailSize = CFNumberCreate(NULL, kCFNumberIntType, &imageSize);
// Set up the thumbnail options.
myKeys[0] = kCGImageSourceCreateThumbnailWithTransform;
myValues[0] = (CFTypeRef)kCFBooleanTrue;
myKeys[1] = kCGImageSourceCreateThumbnailFromImageIfAbsent;
myValues[1] = (CFTypeRef)kCFBooleanTrue;
myKeys[2] = kCGImageSourceThumbnailMaxPixelSize;
myValues[2] = (CFTypeRef)thumbnailSize;
myOptions = CFDictionaryCreate(NULL, (const void **) myKeys,
(const void **) myValues, 2,
&kCFTypeDictionaryKeyCallBacks,
& kCFTypeDictionaryValueCallBacks);
// Create the thumbnail image using the specified options.
myThumbnailImage = CGImageSourceCreateThumbnailAtIndex(myImageSource,
0,
myOptions);
// Release the options dictionary and the image source
// when you no longer need them.
CFRelease(thumbnailSize);
CFRelease(myOptions);
CFRelease(myImageSource);
// Make sure the thumbnail image exists before continuing.
if (myThumbnailImage == NULL){
fprintf(stderr, "Thumbnail image not created from image source.");
return NULL;
}
return myThumbnailImage;
}
Incrementally Loading an Image - 增量加載圖片
如果您有一個(gè)非常大的圖像星岗,或者在web上加載圖像數(shù)據(jù)填大,您可能希望創(chuàng)建一個(gè)增量圖像源,這樣您就可以在積累圖像數(shù)據(jù)時(shí)繪制它俏橘。您需要執(zhí)行以下任務(wù)允华,以增量地從CFData
對象加載圖像:
- 創(chuàng)建用于累積圖像數(shù)據(jù)的
CFData
對象。 - 創(chuàng)建一個(gè)增量圖像源敷矫,通過調(diào)用CGImageSourceCreateIncremental函數(shù)例获。
- 向CFData對象添加圖像數(shù)據(jù)。
- 調(diào)用函數(shù)CGImageSourceUpdateData曹仗,傳遞CFData對象和一個(gè)布爾值(bool數(shù)據(jù)類型)榨汤,指定數(shù)據(jù)參數(shù)是否包含整個(gè)圖像,或者只是部分圖像數(shù)據(jù)怎茫。在任何情況下收壕,數(shù)據(jù)參數(shù)必須包含到那個(gè)點(diǎn)累積的所有圖像文件數(shù)據(jù)。
- 如果你積累了足夠的圖像數(shù)據(jù)轨蛤,調(diào)用CGImageSourceCreateImageAtIndex創(chuàng)建一個(gè)圖像蜜宪,畫出部分圖像,然后釋放它祥山。
- 通過調(diào)用函數(shù)CGImageSourceGetStatusAtIndex檢查是否含有所有的數(shù)據(jù)圃验。如果圖像完成,這個(gè)函數(shù)將返回
kCGImageStatusComplete
缝呕。如果圖像不完整澳窑,重復(fù)步驟3和4,直到它完整供常。 - 釋放增量圖像源摊聋。
Displaying Image Properties - 展示圖像屬性
數(shù)碼照片被貼上了大量關(guān)于圖像尺寸、分辨率栈暇、方位麻裁、顏色輪廓、光圈、計(jì)量模式煎源、焦距色迂、創(chuàng)建日期、關(guān)鍵字薪夕、標(biāo)題等大量的信息脚草。這些信息對于圖像處理和編輯非常有用,但前提是數(shù)據(jù)在用戶接口中公開原献。盡管CGImageSourceCopyPropertiesAtIndex函數(shù)檢索一個(gè)圖像源中圖像相關(guān)聯(lián)的所有屬性的一個(gè)字典馏慨。你需要寫代碼來遍歷字典檢索,然后顯示這些信息姑隅。
在本節(jié)中写隶,您將看到詳細(xì)的OS X ImageApp 樣例代碼中的例程,這是一個(gè)您可以下載和嘗試的圖像顯示應(yīng)用程序讲仰。ImageApp
樣本代碼的一個(gè)特征是一個(gè)圖像信息窗口慕趴,它顯示當(dāng)前活動圖像的縮略圖和圖像屬性,如下圖所示鄙陡。
你可以看一下ImageInfoPanel.h
和ImageInfoPanel.m
文件中對該面板的所有實(shí)現(xiàn)細(xì)節(jié)冕房,您還需要查看項(xiàng)目的nib文件候址,以了解窗口和綁定是如何設(shè)置的诞吱。要了解如何使用CGImageSource
函數(shù)來支持圖像編輯應(yīng)用程序石咬,請查看Listing 2 - 3
微宝。清單后面出現(xiàn)了每一行代碼的詳細(xì)說明。請記住行瑞,這個(gè)例程并不是一個(gè)獨(dú)立的例行程序——您不能簡單地將它粘貼到您自己的程序中叹阔。這是ImageApp
樣本代碼的摘錄截酷。
Listing 2-3 A routine that creates an image source and retrieves properties
- (void) setURL:(NSURL*)url
{
if ([url isEqual:mUrl])
return;
mUrl = url;
CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)url, NULL); // 1
if (source)
{
NSDictionary* props =
(NSDictionary*) CGImageSourceCopyPropertiesAtIndex(source, 0, NULL); // 2
[mTree setContent:[self propTree:props]]; // 3
NSDictionary* thumbOpts = [NSDictionary dictionaryWithObjectsAndKeys:
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform,
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageIfAbsent,
[NSNumber numberWithInt:128], (id)kCGImageSourceThumbnailMaxPixelSize,
nil]; // 4
CGImageRef image = CGImageSourceCreateThumbnailAtIndex(source, 0,
(CFDictionaryRef)thumbOpts); // 5
[mThumbView setImage:image]; // 6
CGImageRelease(image); // 7
[mFilePath setStringValue:[mUrl path]]; // 8
NSString* uti = (NSString*)CGImageSourceGetType(source); // 9
[mFileType setStringValue:[NSString stringWithFormat:@"%@\n%@",
ImageIOLocalizedString(uti), uti]]; // 10
CFDictionaryRef fileProps = CGImageSourceCopyProperties(source, nil); // 11
[mFileSize setStringValue:[NSString stringWithFormat:@"%@ bytes",
(id)CFDictionaryGetValue(fileProps, kCGImagePropertyFileSize)]]; // 12
}
else // 13
{
[mTree setContent:nil];
[mThumbView setImage:nil];
[mFilePath setStringValue:@""];
[mFileType setStringValue:@""];
[mFileSize setStringValue:@""];
}
}
下面是代碼的作用:
從傳遞給例程的URL創(chuàng)建一個(gè)圖像源對象蔓同。
復(fù)制位于索引位置0的圖像的屬性饶辙。一些圖像文件格式可以支持不止一個(gè)圖像,但是這個(gè)例子假設(shè)一個(gè)圖像(或者斑粱,感興趣的圖像始終是文件中的第一個(gè)圖像)弃揽。CGImageSourceCopyPropertiesAtIndex函數(shù)返回一個(gè)
CFDictionary
對象。在這里则北,代碼將CFDictionary作為NSDictionary對象蹋宦,因?yàn)檫@些數(shù)據(jù)類型是可互換的(有時(shí)稱為自由橋接)。返回的字典包含鍵值對的屬性咒锻。然而,有些值本身就是包含屬性的字典守屉』笸В看一下圖Figure 2-1,您不僅會看到簡單的鍵值對(比如顏色模型- rgb),還會看到
Exif
屬性滨巴、IPTC
屬性思灌、JFIF
屬性和TIFF
屬性,每個(gè)都是一個(gè)字典恭取。點(diǎn)擊一個(gè)信息披露三角形泰偿,其中一個(gè)顯示了字典中的屬性。您需要獲得這些字典和它們的屬性蜈垮,以便在Info
面板中顯示它們耗跛。這就是下一步完成的事情。從字典中提取屬性并將其設(shè)置為樹控制器攒发。如果你看一下
ImageInfoPanel.h
文件调塌,您將看到mTree
變量是一個(gè)NSTreeController
對象,它是接口構(gòu)建器中的一個(gè)outlet惠猿。這個(gè)控制器管理一個(gè)對象樹羔砾。在本例中,對象是圖像的屬性偶妖。
propTree:
方法在ImageInfoPanel.m
文件中提供姜凄。它的目的是遍歷上一步中檢索到的屬性字典,提取圖像屬性趾访,并構(gòu)建綁定到NSTreeController
對象的數(shù)組态秧。屬性將出現(xiàn)在圖Figure 2-1的鍵和值表中。在從圖像源創(chuàng)建圖像時(shí)腹缩,設(shè)置一個(gè)選項(xiàng)字典屿聋。選項(xiàng)是在字典中傳遞的。圖 Figure 2-1所示的信息面板顯示了一個(gè)縮略圖藏鹊。這里的代碼設(shè)置了創(chuàng)建一個(gè)縮略圖的選項(xiàng)润讥,該縮略圖被旋轉(zhuǎn)并縮放到完整圖像的相同方向和縱橫比。如果一個(gè)縮略圖還不存在盘寡,就會創(chuàng)建一個(gè)縮略圖楚殿,其最大像素大小是
128 * 128
像素。使用前面步驟中設(shè)置的選項(xiàng)竿痰,從圖像源中的第一個(gè)圖像創(chuàng)建一個(gè)縮略圖脆粥。
將縮略圖設(shè)置為
Info
面板中的視圖。釋放圖像影涉,不再需要它了变隔。
從傳遞給方法的URL中提取路徑,并將字符串設(shè)置為綁定到Info面板的文本字段蟹倾。這是圖Figure 2-1中的路徑文本字段匣缘。
獲取圖像源的統(tǒng)一類型標(biāo)識符猖闪。(這可以與源中的圖像的類型不同)。
調(diào)用一個(gè)函數(shù)來檢索
UTI
的本地化字符串(ImageIOLocalizedString
在ImagePanel.m
中聲明)肌厨,然后將字符串設(shè)置為綁定到Info面板的文本字段培慌。這是圖Figure 2-1中的類型文本字段。檢索與圖像源關(guān)聯(lián)的屬性的字典柑爸。這些屬性應(yīng)用于容器(例如文件大小)吵护,而不一定是圖像源中的單個(gè)圖像。
從前面步驟中獲得的圖像源字典中檢索文件大小的值表鳍,然后將關(guān)聯(lián)的字符串設(shè)置為綁定到Info面板的文本字段馅而。這是圖 Figure 2-1所示的大小文本字段。
如果源沒有創(chuàng)建进胯,則確保用戶界面中的所有字段都反映了這個(gè)事實(shí)用爪。
后記
未完,待續(xù)~~~