Не уверен насчет остальных из вас, но я предпочитаю есть свою полную энчиладу.То, что описано выше, будет работать, и в этом нет ничего плохого, но я обнаружил, что некоторые вещи не учтены.Здесь я остановлюсь на моих наблюдениях:
- Сначала предоставляется лучшее представление, которое кажется 72 DPI, даже если разрешение изображения выше этого.Таким образом, вы теряете разрешение
- Во-вторых, что касается многостраничных изображений, таких как изображения в анимированных GIF-файлах или PDF-файлах.Попробуйте анимированный GIF, вы найдете потерянную анимацию
- Наконец, любые метаданные, такие как EXIF, GPS и т. Д., Данные будут потеряны.
Так что если выХотите конвертировать это изображение, вы действительно хотите потерять все это?Если вы хотите съесть свою полную еду, давайте продолжим читать ...
Иногда и я имею в виду, что иногда нет ничего лучше, чем хорошее старое школьное развитие.Да, это означает, что мы должны немного поработать!
Давайте начнем:
Я создаю категорию в NSData.Это классовые методы, потому что вы хотите, чтобы эти вещи были потокобезопасными, и нет ничего более безопасного, чем положить ваши вещи в стек.Существует два типа методов: один для вывода не многостраничных изображений, а другой для вывода многостраничных изображений.
Список отдельных изображений: JPG, PNG,BMP, JPEG-2000
Список нескольких изображений: PDF, GIF, TIFF
Сначала создайте изменяемое пространство данных в памяти.
NSMutableData * imageData = [NSMutableData data];
Во-вторых, получить CGImageSourceRef.Да, звучит некрасиво, не правда ли?Это не так уж плохо, давайте продолжим ... Вы действительно хотите исходное изображение, а не представление или кусок данных NSImage.Тем не менее, у нас есть небольшая проблема.Источник может быть несовместим, поэтому убедитесь, что вы сравнили свой UTI с теми, которые перечислены в CGImageSourceCopyTypeIdentifiers ()
Какой-то код:
CGImageSourceRef imageSource = nil;
if ( /* CHECK YOUR UTI HERE */ )
return CGImageSourceCreateWithURL( (CFURLRef)aURL, nil );
NSImage * anImage = [[NSImage alloc] initWithContentsOfURL:aURL];
if ( anImage )
return CGImageSourceCreateWithData( (CFDataRef)[anImage TIFFRepresentation], nil );
Подождите секунду, почему существует NSImage?Ну, есть некоторые форматы, которые не имеют метаданных, и CGImageSource не поддерживает, но это допустимые изображения.Примером являются изображения PICT старого стиля.
Теперь у нас есть CGImageSourceRef, убедитесь, что он не равен нулю, а затем давайте теперь получим CGImageDestinationRef.Вау все эти ссылки, чтобы отслеживать.Пока мы находимся на уровне 2!
Мы будем использовать эту функцию: CGImageDestinationCreateWithData ()
- 1-й параметр - это ваш imageData (приведение CFMutableDataRef)
- 2-й параметр - вашвыходной UTI, запомни список выше.(например, kUTTypePNG)
3-й параметр - это количество изображений для сохранения.Для отдельных файлов изображений это 1, в противном случае вы можете просто использовать следующее:
CGImageSourceGetCount (imageSource);
4-й параметр равен нулю.
Проверьте, есть ли у вас этот CGImageDestinationRef, и теперь давайте добавим в него наши изображения из источника ... сюда также войдут все / все метаданные и сохранится разрешение.
Для нескольких изображений мыцикл:
for ( NSUInteger i = 0; i < count; ++i )
CGImageDestinationAddImageFromSource( imageDest, imageSource, i, nil );
Для одного изображения это одна строка кода с индексом 0:
CGImageDestinationAddImageFromSource( imageDest, imageSource, 0, nil);
Хорошо, завершите его, чтобы записать его на диск или в контейнер данных:
CGImageDestinationFinalize( imageDest );
Так что в изменяемых данных с самого начала есть все наши данные изображения и метаданные в нем сейчас.
Мы уже закончили?Почти даже с уборкой мусора приходится убирать!Запомните две ссылки: одну для источника и одну для назначения, поэтому сделайте CFRelease ()
Теперь все готово, и в результате вы получите преобразованное изображение, сохраняющее все его метаданные, разрешение и т. Д. ...
Мои методы категории NSData выглядят так:
+ (NSData *) JPGDataFromURL:(NSURL *)aURL;
+ (NSData *) PNGDataFromURL:(NSURL *)aURL;
+ (NSData *) BMPDataFromURL:(NSURL *)aURL;
+ (NSData *) JPG2DataFromURL:(NSURL *)aURL;
+ (NSData *) PDFDataFromURL:(NSURL *)aURL;
+ (NSData *) GIFDataFromURL:(NSURL *)aURL;
+ (NSData *) TIFFDataFromURL:(NSURL *)aURL;
А как насчет изменения размера или ICO / ICNS?Это для другого дня, но в итоге вы сначала решите изменение размера ...
- Создайте контекст с новым размером: CGBitmapContextCreate ()
- Получите ссылку на изображение из индекса: CGImageSourceCreateImageAtIndex()
- Получить копию метаданных: CGImageSourceCopyPropertiesAtIndex ()
- Рисовать изображение в контексте: CGContextDrawImage ()
- Получить измененное изображение из контекста: CGBitmapContextCreateImage ()
- Теперь добавьте изображение и метаданные в Dest Ref: CGImageDestinationAddImage ()
Промойте и повторите для нескольких изображенийвстроено в источник.
Единственное различие между ICO и ICNS состоит в том, что одно является одним изображением, а другое - несколькими изображениями в одном файле.Спорим, ты можешь угадать, что есть что ?!;-) Для этих форматов вы должны изменить размер до определенного размера, иначе возникнет ОШИБКА.Хотя процесс точно такой же, когда вы используете правильный UTI, но изменение размера немного более строгое.
Хорошо, надеюсь, это поможет другим, и вы полны, как я сейчас!
Оппс, забыл упомянуть.Когда вы получаете объект NSData, делайте с ним как хотите, например writeToFile, writeToURL или heck, создайте еще один NSImage, если хотите.
Удачного кодирования!