Подтвердить что ты не робот

Обновление метаданных ориентации UIImage?

Основная задача: обновить свойство ориентации EXIF ​​для метаданных, связанных с UIImage. Моя проблема в том, что я не знаю, где свойство ориентации находится во всей информации EXIF.


Обобщенный фон: Я меняю ориентацию изображения, возвращаемого imagePickerController:didFinishPickingMediaWithInfo:, поэтому я думаю, что мне также нужно обновить метаданные перед сохранением изображения с помощью writeImageToSavedPhotosAlbum:(CGImageRef)imageRef metadata:(NSDictionary *)metadata.

Другими словами, если я не изменю его, метаданные будут содержать старую/начальную ориентацию и, следовательно, будут ошибочными. Причина, по которой я меняю ориентацию, заключается в том, что она меня отключает, когда я запускаю процедуру обнаружения лиц Core Image. При фотосъемке с iPhone (устройство) в режиме "Портрет" с использованием передней камеры ориентация UIImageOrientationRight (3). Если я переписал изображение, поэтому ориентация UIImageOrientationUp (0), я получаю хорошие результаты распознавания лиц. Для справки, процедура перезаписи изображения ниже.

Вся ориентация на камеру, которую я нахожу очень запутанной, и, похоже, я все глубже погружаюсь в кодовое отверстие со всем этим. Я просмотрел сообщения (здесь, здесь и здесь. Согласно этому сообщению (qaru.site/info/442772/...):

"Камера на самом деле пейзажная, поэтому вы поднимаетесь или опускаетесь, когда вы делаете снимок в ландшафте и влево или вправо, когда вы берете (в зависимости от того, как вы держите устройство).

... что совершенно сбивает с толку. Если это верно, я бы подумал, что я должен получить ориентацию UIImageOrientationLeftMirrored или UIImageOrientationRightMirrored с передней камерой. И ничто из этого не объяснило бы, почему CIDetector не отвечает за девственное изображение, возвращенное сборщиком.

Я приближаюсь к этой заднице назад, но я не могу ориентироваться...


-(UIImage *)normalizedImage:(UIImage *) thisImage
{
    if (thisImage.imageOrientation == UIImageOrientationUp) return thisImage;

    UIGraphicsBeginImageContextWithOptions(thisImage.size, NO, thisImage.scale);
    [thisImage drawInRect:(CGRect){0, 0, thisImage.size}];
    UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return normalizedImage;
}
4b9b3361

Ответ 1

Взгляните на мой ответ здесь:
заставить UIImagePickerController делать фото в портретной ориентации/размерах iOS

и связанный проект на github (вам не нужно запускать проект, просто посмотрите на readme).

Это больше связано с чтением, а не с написанием метаданных, но оно содержит несколько заметок об Apple imageOrientation и соответствующие метаданные 'Exif' ориентации.

Это может быть полезно прочитать также
Захваченное фото автоматически поворачивается во время загрузки в IOS 6.0 или iPhone

В игре есть две разные постоянные соглашения о нумерации для указания ориентации изображения.

  • Константы kCGImagePropertyOrientation, используемые в тегах метаданных изображений TIFF/IPTC
  • Константы UIImageOrientation, используемые свойством UIImage imageOrientation.

Ориентация камеры на собственные устройства iPhone - левая (с домашней кнопкой справа). Собственные размеры пикселей всегда отражают это, флаги вращения используются для правильного ориентации изображения с ориентацией дисплея.

Apple            UIImage.imageOrientation     TIFF/IPTC kCGImagePropertyOrientation

iPhone native     UIImageOrientationUp    = 0  =  Landscape left  = 1  
rotate 180deg     UIImageOrientationDown  = 1  =  Landscape right = 3  
rotate 90CCW      UIImageOrientationLeft  = 2  =  Portrait  down  = 8  
rotate 90CW       UIImageOrientationRight = 3  =  Portrait  up    = 6  

UIImageOrientation 4-7 map to kCGImagePropertyOrientation 2,4,5,7 - это зеркальные копии.

UIImage выводит свойство imagerOrientation из базовых флагов kCGImagePropertyOrientation - вот почему это свойство только для чтения. Это означает, что до тех пор, пока вы правильно примете флаги метаданных, imageOrientation будет следовать правильно. Но если вы читаете цифры, чтобы применить преобразование, вам нужно знать, какие номера вы ищете.

Ответ 2

Несколько gleanings из моего мира o 'боль в изучении этого:

Фон: Core Image обнаружение лица не срабатывало, и, похоже, оно связано с использованием featuresInImage: options: и используя свойство UIImage.imageOrientation в качестве аргумента. Если изображение отрегулировано так, чтобы оно не вращалось и не отражалось, обнаружение работало нормально, но при прохождении изображения непосредственно с камеры обнаружение не удалось.

Ну... UIImage.imageOrientation ДИФФЕРЕНЦИЯ, чем фактическая ориентация изображения.

Другими словами...

UIImage* tmpImage = [self.imageInfo objectForKey:UIImagePickerControllerOriginalImage];
printf("tmpImage.imageOrientation: %d\n", tmpImage.imageOrientation);

Сообщает значение 3 или UIImageOrientationRight, тогда как использование метаданных, возвращаемых методом UIImagePickerControllerDelegate...

   NSMutableDictionary* metaData = [[tmpInfo objectForKey:@"UIImagePickerControllerMediaMetadata"] mutableCopy];
   printf(" metaData orientation    %d\n", [[metaData objectForKey:@"Orientation"] integerValue]);

Сообщает значение 6 или UIImageOrientationLeftMirrored.

Полагаю, теперь кажется очевидным, что UIImage.imageOrientation - это ориентация дисплея, которая, как представляется, определяется ориентацией исходного изображения и вращением устройства. (Возможно, я ошибаюсь) Поскольку ориентация дисплея отличается, чем фактические данные изображения, использование этого приведет к сбою CIDetector. Тьфу.

Я уверен, что все это служит очень хорошим и важным целям для жидкостных графических интерфейсов и т.д., но это слишком много для меня, потому что все координаты CIDetector также будут в исходной ориентации изображения, что делает CALayer рисуем больным изготовление. Итак, для потомков здесь описано, как изменить свойство Orientation метаданных и изображение, содержащееся в нем. Затем эти метаданные можно использовать для сохранения изображения в CameraRoll.

Решение

// NORMALIZE IMAGE
UIImage* tmpImage = [self normalizedImage:[self.imageInfo objectForKey:UIImagePickerControllerOriginalImage]];
NSMutableDictionary * tmpInfo =[self.imageInfo mutableCopy];
NSMutableDictionary* metaData = [[tmpInfo objectForKey:@"UIImagePickerControllerMediaMetadata"] mutableCopy];

[metaData setObject:[NSNumber numberWithInt:0] forKey:@"Orientation"];
[tmpInfo setObject:tmpImage forKey:@"UIImagePickerControllerOriginalImage"];
[tmpInfo setObject:metaData forKey:@"UIImagePickerControllerMediaMetadata"];

self.imageInfo = tmpInfo;