assaulter's diary

主にバイクについて

iOSにてfullResoultionImageを扱う際の問題点

前回とは別の話題になります。

iOSでALAssetから画像を取得する際には、メソッドとして

・fullScreenImage

・fullResolutionImage

の2つがありますが、後者のfullResolutionImageを扱う際にハマりポイントがあったので書きます。

ハマりポイント???

iOS5から、iPhone標準のカメラアプリにおいて画像編集ができるようになりました。

普通にサムネとか取得する際には問題ないのですが、fullResolutionImageを取得する際には、この編集結果が適用されないという問題があります。

で、この編集情報が、ALAssetRepresentationのmetadata(辞書形式)の中に、AdjustmentXMPとして格納されています。

XMPの中身

<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0">
   <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
      <rdf:Description rdf:about=""
            xmlns:aas="http://ns.apple.com/adjustment-settings/1.0/">
         <aas:AffineA>1</aas:AffineA>
         <aas:AffineB>0</aas:AffineB>
         <aas:AffineC>0</aas:AffineC>
         <aas:AffineD>1</aas:AffineD>
         <aas:AffineX>-331</aas:AffineX>
         <aas:AffineY>-161</aas:AffineY>
         <aas:CropX>0</aas:CropX>
         <aas:CropY>0</aas:CropY>
         <aas:CropW>1938</aas:CropW>
         <aas:CropH>1420</aas:CropH>
      </rdf:Description>
   </rdf:RDF>
</x:xmpmeta>

・AffineA~AffineYまでがアフィン変換用情報

・CropX~CropHがクロップされた領域情報

なので、自力でパースしてCGAffineなんちゃらしてClipすればいいのですが、iOS6からこのXMLを食わせると良い感じの画像を出力するメソッドがあるらしいのでメモしておきます。

XMP変換君

CIFilterにfilterArrayFromSerializedXMPって関数があるので、コレを使います。以下実装例

- (CGImageRef)getFullResolutionImage {
    ALAssetRepresentation *representation = [self.asset defaultRepresentation];
    
    NSString *XMPString = representation.metadata[@"AdjustmentXMP"];
    NSData *XMP = [XMPString dataUsingEncoding:NSUTF8StringEncoding];
    
    if (XMP) {
        /// iOS5にはないので
        if ([[CIFilter class] respondsToSelector:@selector(filterArrayFromSerializedXMP:inputImageExtent:error:)]) {
            CIImage *image = [CIImage imageWithCGImage:[representation fullResolutionImage]];
            NSArray *filterArray = [CIFilter filterArrayFromSerializedXMP:XMP
                                                         inputImageExtent:image.extent
                                                                    error:nil];
            CIContext *context = [CIContext contextWithOptions:nil];
            
            // add the filters to an image
            for (CIFilter *filter in filterArray) {
                [filter setValue:image forKey:kCIInputImageKey];
                image = [filter outputImage];
            }
            
            // create a CGImageRef which has been edited
            return [context createCGImage:image fromRect:image.extent];
        }
        // iOS5の場合でもXMPが取れるので、頑張るひとはここから頑張る感じ。
        // 今回はfullScreenImageでお茶を濁す。そろそろiOS5切っていいんじゃね・・・?
        return [representation fullScreenImage];
    }
    
    return [representation fullResolutionImage];
}

ちなみにXMPってAdobeの規格らしいっすよ。ただここらへんのカメラ寄りの規格ってちゃんとしたドキュメント無いような気がするのですが、僕の調べ方が悪いんですかね。

追記

わかってるとおもいますが、XMPに入ってる情報は回転とクロップだけなので、画像補正系には対応できません。画像補正すると写真そのものを弄るのかな・・・?