iOS UIImage 轉 NSData 方案
前言:需要把image 轉為二進制data 進行存儲 壓縮 上傳 時預判原始圖大小時候使用了UIImagePNGRepresentation發現比原圖大引發以下內容總結
常用方案1
// 加載圖片 UIImage *image = [UIImage imageNamed:@"test1.jpg"]; // 將圖片轉換為NSData對象 NSData *imageData = UIImageJPEGRepresentation(image, 1);
參數解釋:
-
image:要轉換的UIImage對象。
- 這是需要轉換為JPEG數據的原始圖像對象。
-
compressionQuality:表示JPEG壓縮質量的參數,范圍為0.0到1.0。
- compressionQuality值為0.0表示最高壓縮,圖像質量最低。
- compressionQuality值為1.0表示無壓縮,圖像質量最高。 (?? 1.0 不代表當前獲取的data 和 原始data 一樣大,甚至遠遠大于原始data)
- compressionQuality值在0.0和1.0之間表示不同程度的壓縮和圖像質量權衡。
關鍵點:
- 當壓縮參數越接近1 圖像質量越高,那么轉換后的JPEG數據將保留較高的圖像質量,但會占用更多的空間。
- 圖像內容復雜度:如果原始圖像包含復雜的紋理、細節和顏色變化等特征,JPEG壓縮算法會產生較大的數據文件。這是因為JPEG是一種有損壓縮格式,會在壓縮過程中舍棄部分圖像細節,但仍然需要更多的數據來表示復雜的圖像內容。
- 原始圖像已經是JPEG格式:如果原始圖像已經是JPEG格式,再次進行JPEG轉換可能會導致數據的進一步損失,并且文件大小可能會變大。這是因為每次重新壓縮JPEG圖像時,會引入額外的壓縮失真和冗余數據。
- 原始圖像的壓縮方式不同:UIImageJPEGRepresentation使用的是系統的JPEG壓縮算法,而原始圖像可能是使用其他方式進行壓縮或存儲的(如其他圖像編輯軟件或網絡服務)。不同的壓縮方式可能會導致文件大小的差異。
總而言之,JPEG圖像的文件大小取決于多個因素,包括壓縮質量、圖像內容復雜度和壓縮算法等。因此,如果發現使用UIImageJPEGRepresentation轉換后的JPEG數據比原始圖像大很多,可以適當調整壓縮質量參數,或嘗試其他的圖像壓縮方法來優化文件大小。
常用方案2
// 加載圖片 UIImage *image = [UIImage imageNamed:@"test1.png"]; // 將圖片轉換為NSData對象 NSData *imageData = UIImagePNGRepresentation(image);
關鍵點:
- 透明性:PNG格式支持圖像的透明性,而JPEG格式不支持。因此,如果原始圖像包含透明通道或需要保留透明性,則應選擇使用UIImagePNGRepresentation來保持圖像的完整性。
- 壓縮質量:與JPEG不同,PNG是一種無損壓縮格式,不會對圖像數據進行壓縮或丟失。因此,UIImagePNGRepresentation函數不接受關于壓縮質量的參數,轉換后的PNG數據的大小與原始圖像保持一致,可能會比JPEG數據更大。
- 色彩空間:將UIImage對象轉換為PNG數據時,保留了原始圖像的色彩空間和位深度信息。即使原始圖像采用了較高的位深度(例如16位),轉換后的PNG數據也能夠保持相同的位深度,以保留更多的顏色信息。這在需要更精確色彩表示的應用場景中是重要的。
- 內存消耗:由于PNG數據是無損壓縮的,轉換大尺寸或高分辨率的UIImage對象時可能會占用相對較大的內存空間。因此,在處理大型圖像時,要確保內存使用情況合理控制,避免出現內存警告或崩潰。
- 其他格式轉換考慮:除了PNG格式,如果需要在應用程序中處理圖像的其他用途,如網絡傳輸、顯示在UIImageView中,或者在支持的圖像編輯庫中進行處理,可能需要將UIImage對象轉換為其他合適的格式,如JPEG或HEIC等。
總之,通過理解UIImagePNGRepresentation的一些特性和限制,可以根據具體需求合理選擇使用和處理PNG格式的圖像數據。
方案3:CGImageDestinationCreateWithData
+ (NSData *)kfz_rawData:(UIImage *)image
{
NSDictionary *options = @{(__bridge NSString *)kCGImageSourceShouldCache : @NO,
(__bridge NSString *)kCGImageSourceShouldCacheImmediately : @NO
};//目的是不期望圖片有緩存和解碼行為
NSMutableData *data = [NSMutableData data];
CGImageDestinationRef destRef = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)data, kUTTypeJPEG, 1, (__bridge CFDictionaryRef)options);
CGImageDestinationAddImage(destRef, image.CGImage, (__bridge CFDictionaryRef)options);
CGImageDestinationFinalize(destRef);
CFRelease(destRef);
return data;
}
參數解釋:
CGImageDestinationCreateWithData函數是Core Graphics框架中用于創建一個基于數據的目標對象的函數。他接受4個參數:
- data:一個CFMutableData對象,用于存儲圖像數據。調用CGImageDestinationFinalize時,最終的圖像數據將被寫入這個data對象。
- type:一個CFStringRef,指定要創建的圖像數據的文件類型。你可以使用常量如kUTTypeJPEG、kUTTypePNG、kUTTypeGIF等來表示不同的文件類型。
- count:一個size_t值,指定要創建的圖像數據中圖像的數量。通常只需要使用1,表示只有一個圖像。
- options:一個CFDictionaryRef類型的字典,包含一些可選的參數和選項。你可以在這個字典中指定圖像的相關設置,如壓縮質量、色彩空間、背景顏色等。如果你不需要特定的選項,可以將其設置為nil,使用默認選項參考如下:
-
對于JPEG文件(
kUTTypeJPEG),默認選項通常包括:- 壓縮質量為0.75,即75%的圖像質量。
- 使用RGB顏色空間。
-
對于PNG文件(
kUTTypePNG),默認選項通常包括:- 不進行壓縮,即無損壓縮。
- 使用RGBA顏色空間。
-
對于GIF文件(
kUTTypeGIF),默認選項通常包括:- 使用LZW壓縮算法。
- 使用RGBA顏色空間。
最終,該函數會返回一個CGImageDestinationRef對象,該對象可以用于將圖像數據添加到目標中,并完成最終的圖像輸出。
關鍵特點:
-
目標類型靈活性:CGImageDestinationCreateWithData允許你選擇將圖像數據寫入的目標類型。你可以使用不同的圖像容器類型,如JPEG、PNG、GIF等,根據需要選擇適合的目標。
-
減少內存占用:使用CGImageDestinationCreateWithData,你可以逐步將圖像數據寫入目標,而不需要一次性將整個圖像數據加載到內存中。這對于處理大型圖像或內存受限的環境非常有用。
-
動畫支持:CGImageDestinationCreateWithData還支持創建一個包含多個幀的圖像目標,從而創建一個具有動畫效果的圖像文件。你可以按順序添加多個圖像幀到目標中,并設置每個幀的壓縮參數和屬性。
-
自定義選項:你可以通過提供自定義的屬性鍵值對來自定義圖像寫入過程??梢钥刂茍D像的壓縮質量、元數據、縮放、字節對齊等參數和屬性。
-
錯誤處理:如果在圖像寫入過程中出現錯誤,CGImageDestinationCreateWithData可以提供錯誤處理功能。你可以檢查狀態來獲取有關錯誤的信息或狀態碼,并根據需要進行適當的錯誤處理。
綜上所述,CGImageDestinationCreateWithData提供了一種靈活且可定制的方式,用于將圖像數據寫入指定目標。它的特點包括目標類型的選擇、內存占用的減少、動畫支持、自定義選項和錯誤處理。這使得它成為處理圖像寫入操作時的有效工具。
和方案2的比較:
CGImageDestinationCreateWithData和UIImageJPEGRepresentation這兩種方法都可以將UIImage對象轉換為JPEG格式的NSData數據,但它們有一些不同之處。
- 靈活性和控制性:
-
CGImageDestinationCreateWithData方法允許你指定更多的選項和參數來控制輸出圖像的質量、緩存行為以及其他屬性。你可以使用選項字典來自定義編碼過程,并根據需求進行優化。UIImageJPEGRepresentation方法相對簡單,只需傳入一個UIImage對象和一個質量參數(0.0到1.0之間的值)即可。它提供了一個簡便的方式來進行圖像轉換,但沒有提供對更多選項的直接訪問。
- 性能和效率:
-
CGImageDestinationCreateWithData方法在處理大尺寸圖像時可能會更加高效,因為它可以逐步寫入數據,而不需要完全加載整個圖像到內存中。這對于處理內存受限的情況或處理大型圖像時可能是一個優勢。UIImageJPEGRepresentation方法會將整個UIImage對象加載到內存中,并一次性轉換為NSData數據。對于小型圖像和常規用途,這可能沒有明顯影響,但處理大圖像時可能會占用更多的內存。
因此,選擇哪種方法取決于你的具體需求。如果你需要更多的控制權和靈活性,以及能夠處理大型圖像,那么CGImageDestinationCreateWithData可能更適合。如果你需要一個簡單且易于使用的方法來轉換圖像,并且對性能和內存使用沒有過多要求,那么UIImageJPEGRepresentation可以是一個很好的選擇。
參考鏈接:
1、https://www.jianshu.com/p/dac08fa1704a (UIImage 轉 NSData調研)
2、https://www.jianshu.com/p/ea475f608526 (iOS UIImage圖片文件大?。?/p>
posted on 2023-07-28 15:42 ACM_Someone like you 閱讀(2612) 評論(0) 收藏 舉報
浙公網安備 33010602011771號