ImageIO框架詳細(xì)解析(三) —— 創(chuàng)建和使用圖像源

版本記錄

版本號 時(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 ReferenceCGImageProperties 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)前活動圖像的縮略圖和圖像屬性,如下圖所示鄙陡。

An Info window that displays image properties

你可以看一下ImageInfoPanel.hImageInfoPanel.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的本地化字符串(ImageIOLocalizedStringImagePanel.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ù)~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胁镐,一起剝皮案震驚了整個(gè)濱河市偎血,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌盯漂,老刑警劉巖颇玷,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異就缆,居然都是意外死亡帖渠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進(jìn)店門竭宰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來空郊,“玉大人,你說我怎么就攤上這事切揭∧酰” “怎么了?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵廓旬,是天一觀的道長哼审。 經(jīng)常有香客問我,道長孕豹,這世上最難降的妖魔是什么涩盾? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮励背,結(jié)果婚禮上春霍,老公的妹妹穿的比我還像新娘。我一直安慰自己叶眉,他們只是感情好址儒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布籍胯。 她就那樣靜靜地躺著,像睡著了一般离福。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上炼蛤,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天妖爷,我揣著相機(jī)與錄音,去河邊找鬼理朋。 笑死絮识,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嗽上。 我是一名探鬼主播次舌,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼兽愤!你這毒婦竟也來了彼念?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤浅萧,失蹤者是張志新(化名)和其女友劉穎逐沙,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洼畅,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吩案,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了帝簇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徘郭。...
    茶點(diǎn)故事閱讀 40,110評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖丧肴,靈堂內(nèi)的尸體忽然破棺而出残揉,到底是詐尸還是另有隱情,我是刑警寧澤闪湾,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布冲甘,位于F島的核電站,受9級特大地震影響途样,放射性物質(zhì)發(fā)生泄漏江醇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一何暇、第九天 我趴在偏房一處隱蔽的房頂上張望陶夜。 院中可真熱鬧,春花似錦裆站、人聲如沸条辟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽羽嫡。三九已至本姥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杭棵,已是汗流浹背婚惫。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留魂爪,地道東北人先舷。 一個(gè)月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像滓侍,于是被迫代替她去往敵國和親蒋川。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 版本記錄 前言 ImageIO框架主要用來讀寫大多數(shù)圖像文件格式撩笆。 管理顏色和訪問圖像元數(shù)據(jù)捺球。接下來幾篇我們就詳細(xì)...
    刀客傳奇閱讀 887評論 0 0
  • 翻譯自“Collection View Programming Guide for iOS” 0 關(guān)于iOS集合視...
    lakerszhy閱讀 3,867評論 1 22
  • 關(guān)于資源 適用于計(jì)算機(jī)程序的資源是與程序可執(zhí)行代碼相關(guān)的數(shù)據(jù)文件。資源可以通過將代碼之外的復(fù)雜數(shù)據(jù)集或圖形內(nèi)容創(chuàng)建...
    nicedayCoco閱讀 639評論 0 0
  • 今天我向塔羅牌提出了一個(gè)問題浇衬,當(dāng)父母在生病的的時(shí)候懒构,強(qiáng)烈的表達(dá)了對自己的未來單身生活的擔(dān)憂,該如何應(yīng)對耘擂? 我抽到的...
    魔紅紅閱讀 547評論 1 1
  • 文/欺塵 那些可愛的人兒我想為你寫詩只此一首胆剧,算作約定留作相逢的書信 那些盛開的花兒我想為你寫詩灑下幾片,飄蕩池中...
    欺塵閱讀 495評論 3 17