[iOS] QRコードを生成して画像に合成する


写真を撮ってサーバーにアップロード
↓
アップロード先のURLをQRコードにして元の写真に合成
みたいな処理を実装した時の自分用メモ。

# iOS 7に限定できる場合

**Core Image**の`CIQRCodeGenerator`フィルターを利用する。
参考：[iOS 7でバーコード・QRコードを読み取る方法と生成する方法（おまけもあるよ）](http://qiita.com/hkato193/items/c36a940c2929a124e416)

※`CIQRCodeGenerator`フィルターで生成したQRコードの画像はものすごく小さいので注意

# QR-Code-Encoder-for-Objective-C を利用する方法

Cocoapodsで導入可能な[QR-Code-Encoder-for-Objective-C](http://myang-git.github.io/QR-Code-Encoder-for-Objective-C/)を利用すると↓のような短いコードでQRコードのUIImageを生成できる。

```cpp:sample.mm
//the qrcode is square. now we make it 250 pixels wide
int qrcodeImageDimension = 250;
    
//the string can be very long
NSString* aVeryLongURL = @"http://thelongestlistofthelongeststuffatthelongestdomainnameatlonglast.com/";
    
//first encode the string into a matrix of bools,
//TRUE for black dot and FALSE for white. Let the encoder decide the error correction level and version
DataMatrix* qrMatrix = [QREncoder encodeWithECLevel:QR_ECLEVEL_AUTO version:QR_VERSION_AUTO string:aVeryLongURL];
    
//then render the matrix
UIImage* qrcodeImage = [QREncoder renderDataMatrix:qrMatrix imageDimension:qrcodeImageDimension];
```


## Cocoapods

```Podfile
platform :ios
pod 'QR-Code-Encoder-for-Objective-C'
```

`pod install` でインストール

## 利用方法
まずはじめに、このライブラリはC++のソースを利用しているので、`#import "QREncoder.h"` を書く実装ファイルの拡張子を`.mm`に変更する。

`UIImagePickerController`を使って撮影した写真をアップロードして、そのURLからQRコードを生成、元の写真に合成して保存するような場合こんな感じになる。
注意点として、`+[QREncoder renderDataMatrix:imageDimension:]`で生成されるQRコードのUIImageには余白がないので、単純に描画するとリーダーが反応してくれないことがある。（`CIQRCodeGenerator`フィルターは必要な余白も含めた画像を生成してくれる）
白い背景でない画像に合成する時などは、QRコードの周りに適度な余白を描画する必要がある。


```objc:SomeViewController.mm
#import "QREncoder.h"

...

#pragma mark -
#pragma UIImagePickerControllerDelegate

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
    CGSize size = [image size];
    UIGraphicsBeginImageContext(size);
    CGRect rect;
    rect.origin = CGPointZero;
    rect.size = size;
    [image drawInRect:rect];

    //upload image and get its URL
    NSString *imageUrl = @"http://xxxxxxxxxx";
    DataMatrix *qrMatrix = [QREncoder encodeWithECLevel:QR_ECLEVEL_AUTO version:QR_VERSION_AUTO string:imageUrl];
    int qrDimention = 640;
    UIImage *qrImage = [QREncoder renderDataMatrix:qrMatrix imageDimension:qrDimention];
    //At first, draw white background and then draw QR code
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextFillRect(context, CGRectMake(image.size.width - qrDimention - 140.0f,
                                          image.size.height - qrDimention - 140.0f,
                                          qrDimention + 80.0f,
                                          qrDimention + 80.0f));
    [qrImage drawAtPoint:CGPointMake(image.size.width - qrDimention - 100.0f,
                                     image.size.height - qrDimention - 100.0f)];

    UIImage *mergedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    image = mergedImage;
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    [library writeImageToSavedPhotosAlbum:image.CGImage
                              orientation:(ALAssetOrientation)image.imageOrientation
                          completionBlock:^(NSURL *assetURL, NSError *error) {
        /* Do something */
    }];
}
```