爲什麼此代碼將artistImage設置爲0寬度和0高度的圖像?NSImage怪異
NSURL * artistImageURL = [NSURL URLWithString:@「http://userserve-ak.last.fm/serve/252/8581581.jpg」];
NSImage * artistImage = [[NSImage alloc] initWithContentsOfURL:artistImageURL];
爲什麼此代碼將artistImage設置爲0寬度和0高度的圖像?NSImage怪異
NSURL * artistImageURL = [NSURL URLWithString:@「http://userserve-ak.last.fm/serve/252/8581581.jpg」];
NSImage * artistImage = [[NSImage alloc] initWithContentsOfURL:artistImageURL];
NSImage確實爲我加載了這個罰款,但該特定圖像已損壞的元數據。其根據exif數據的分辨率爲7.1999997999228071e-06 dpi。
NSImage尊重文件中的DPI信息,所以如果您嘗試以自然尺寸繪製圖像,則會獲得2520000070像素的範圍。
最後我檢查了,NSImage's
-initWithContentsOfURL:
只適用於文件的URL。您需要首先檢索URL,然後使用-initWithData:
正如Ken所寫的那樣,DPI在這張圖片中混亂了。如果要強制NSImage中設置實時圖像尺寸(忽略DPI),使用所描述的方法在http://borkware.com/quickies/one?topic=NSImage:
NSBitmapImageRep *rep = [[image representations] objectAtIndex: 0];
NSSize size = NSMakeSize([rep pixelsWide], [rep pixelsHigh]);
[image setSize: size];
這通常不安全。這是對NSBitmapImageRep的不安全轉換。例如,任意圖像可能是PDF支持的,在這種情況下,pixelsWide和pixelsHigh會返回NSImageRepMatchesDevice,指示rep是獨立於分辨率的。 NSImageRepMatchesDevice == 0. – Ken
這很好理解......但對於標準的網頁圖像(png,gif,jpg),這不應該發生,對吧? –
不,沒有承諾使用什麼類型 - 這是一種純粹的不安全類型轉換。如果NSBitmapImageRep不贊成使用與CGImage更緊密匹配的新rep子類,這種情況會發生改變的主要原因是。然後明確實例化NSBitmapImageRep的人會得到它的compat,但不是像這樣製作NSImages的人。 – Ken
這或多或少保證.representations包含NSImageRep *(當然並非總是NSBitmapImageRep )。爲了將來的擴展可以安全地進行,可以在下面寫下類似代碼的東西。它還考慮到多個表示(如在某些圖標和.tiff文件中)。
@implementation NSImage (Extension)
- (void) makePixelSized {
NSSize max = NSZeroSize;
for (NSObject* o in self.representations) {
if ([o isKindOfClass: NSImageRep.class]) {
NSImageRep* r = (NSImageRep*)o;
if (r.pixelsWide != NSImageRepMatchesDevice && r.pixelsHigh != NSImageRepMatchesDevice) {
max.width = MAX(max.width, r.pixelsWide);
max.height = MAX(max.height, r.pixelsHigh);
}
}
}
if (max.width > 0 && max.height > 0) {
self.size = max;
}
}
@end
另外值得注意的是,從主線程使用任何'-initWithContentsOfURL:'方法並不是一個好主意,因爲它們將阻止主事件循環。使用異步的'NSURLConnection'對象來創建'NSData'對象,並在完成時通知。 –
NSImage可以從網絡加載。是的,但羅布的觀點。 – Ken