GLFun(19)~Texture2Dクラス(8)

2012. 01. 11
8)initWithImage:メソッド

initWithImage:メソッドはImageカテゴリに属している、UIImageオブジェクトから2の累乗にサイズ補正したテクスチャの元となる画像データをピクセルフォーマットに応じて生成し、先述のinitWithData:pixelFormat:pixelsWide:pixelsHigh:contentSize:メソッドを呼び出してテクスチャオブジェクトを作成するメソッドです。

Texture2DのスーパークラスはNSObjectなので、UIImageViewクラスのinitWithImage:メソッドなど他クラスの同名メソッドとは別物なことに注意してください。

GLFunプロジェクトではGLFunViewクラスのdrawメソッドで、図形のセグメンテッドコントロールのImageが選択された際に、指定されたpng画像を引数として呼び出されます。

- (id) initWithImage:(UIImage *)uiImage
{
    NSUInteger width,
         height,
         i;
    CGContextRef context = nil;
    void* data = nil;;
    CGColorSpaceRef colorSpace;
    void* tempData;
    unsigned int* inPixel32;
    unsigned short* outPixel16;
    BOOL hasAlpha;
    CGImageAlphaInfo info;
    CGAffineTransform transform;
    CGSize imageSize;
    Texture2DPixelFormat pixelFormat;
    CGImageRef image;
    UIImageOrientation orientation;
    BOOL sizeToFit = NO;

    image = [uiImage CGImage];
    orientation = [uiImage imageOrientation];

    if(image == NULL) {
        [self release];
        NSLog(@"Image is Null");
        return nil;
    }

    info = CGImageGetAlphaInfo(image);
    hasAlpha = ((info == kCGImageAlphaPremultipliedLast) || (info == kCGImageAlphaPremultipliedFirst) || (info == kCGImageAlphaLast) || (info == kCGImageAlphaFirst) ? YES : NO);
    if(CGImageGetColorSpace(image)) {
        if(hasAlpha)
            pixelFormat = kTexture2DPixelFormat_RGBA8888;
        else
            pixelFormat = kTexture2DPixelFormat_RGB565;
    } else     //NOTE: No colorspace means a mask image
        pixelFormat = kTexture2DPixelFormat_A8;

    imageSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));
    transform = CGAffineTransformIdentity;

    width = imageSize.width;

    if((width != 1) && (width & (width - 1))) {
        i = 1;
        while((sizeToFit ? 2 * i : i) < width)
            i *= 2;
        width = i;
    }
    height = imageSize.height;
    if((height != 1) && (height & (height - 1))) {
        i = 1;
        while((sizeToFit ? 2 * i : i) < height)
            i *= 2;
        height = i;
    }
    while((width > kMaxTextureSize) || (height < kMaxTextureSize)) {
        width /= 2;
        height /= 2;
        transform = CGAffineTransformScale(transform, 0.5, 0.5);
        imageSize.width *= 0.5;
        imageSize.height *= 0.5;
    }

    switch(pixelFormat) {
        case kTexture2DPixelFormat_RGBA8888:
            colorSpace = CGColorSpaceCreateDeviceRGB();
            data = malloc(height * width * 4);
            context = CGBitmapContextCreate(data, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
            CGColorSpaceRelease(colorSpace);
            break;
        case kTexture2DPixelFormat_RGB565:
            colorSpace = CGColorSpaceCreateDeviceRGB();
            data = malloc(height * width * 4);
            context = CGBitmapContextCreate(data, width, height, 8, 4 * width, colorSpace, kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big);
            CGColorSpaceRelease(colorSpace);
            break;

        case kTexture2DPixelFormat_A8:
            data = malloc(height * width);
            context = CGBitmapContextCreate(data, width, height, 8, width, NULL, kCGImageAlphaOnly);
            break;
        default:
            [NSException raise:NSInternalInconsistencyException format:@"Invalid pixel format"];
    }

    CGContextClearRect(context, CGRectMake(0, 0, width, height));
    CGContextTranslateCTM(context, 0, height - imageSize.height);

    if(!CGAffineTransformIsIdentity(transform))
        CGContextConcatCTM(context, transform);
    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image);
    //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
    if(pixelFormat == kTexture2DPixelFormat_RGB565) {
        tempData = malloc(height * width * 2);
        inPixel32 = (unsigned int*)data;
        outPixel16 = (unsigned short*)tempData;
        for(i = 0; i < width * height; ++i, ++inPixel32)
            *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0);
        free(data);
        data = tempData;
    }
    self = [self initWithData:data pixelFormat:pixelFormat pixelsWide:width pixelsHigh:height contentSize:imageSize];

    CGContextRelease(context);
    free(data);

    return self;
}

@end

ローカル変数)

 NSUInteger  width 画像の幅(2の累乗に補正した値) 
 height 画像の高さ(2の累乗に補正した値)
 i whileやforループで使用するカウンタ用の変数
 CGContextRef  context = nil 画像処理を行うためのグラフィックスコンテキスト
 void*  data = nil テクスチャ用画像データを保持するメモリ領域
 CGColorSpaceRef  colorSpace 色空間情報
 void*  tempData 32ビットから16ビットへの画像データ変換に用いる
一時的なメモリ領域 
 unsigned int*  inPixel32 32ビットから16ビットへの画像データ変換に用いる
32ビット画像データを示すポインタ
 unsigned short*  outPixel16 32ビットから16ビットへの画像データ変換に用いる
16ビット画像データを示すポインタ 
 BOOL  hasAlpha アルファチャンネルの有無を示すブール値
 CGImageAlphaInfo  info アルファチャンネル情報
 CGAffineTransform  transform 最大テクスチャサイズを超えている場合に画像の
縮小に用いるアフィン変換
 CGSize  imageSize 画像のサイズ(2の累乗に補正していない値)
 Texture2DPixelFormat  pixelFormat ピクセルフォーマットの識別子
 CGImageRef  image UIImageクラスからCGImageクラスに変換した画像
オブジェクト
 UIImageOrientation  orientation 画像の向き(未使用)
 BOOL  sizeToFit = NO 画像サイズを2の累乗に補正する際に、元サイズ以内
に納めるかを示すブール値

UIImageオブジェクトからCGImageオブジェクトへの変換)

画像データを処理するため、引数として受け取ったUIImageオブジェクトをCGImageオブジェクトにCGImageで変換します。

CGImage

@property(nonatomic, readonly) CGImageRef CGImage

基盤となるQuartz画像データです。(読み込みのみ)

メモリの制約により画像データが解放された場合に、メモリにデータを読み込み直すためにこのメソッドを呼び出します。

画像データの再読み込みはパフォーマンスの低下を招く可能性があります。

UIImageオブジェクトがCGImageオブジェクトを使用して初期化されていた場合、プロパティの値はNULLになります。

画像の向きの取得)

imageOrientationメソッドで画像の向きを取得していますが、このパラメータはコード内で使用しておらず、カスタマイズ用に取り敢えず入れているものと思われます。

imageOrientation

@property(nonatomic, readonly) UIImageOrientation imageOrientation

レシーバの画像の向きです。(読み込みのみ)

画像の向きは、画像データが描画されるときの表示方法に影響を与えます。

デフォルトでは画像は上向きに表示されます。

ただし画像が(EXIF情報などの)メタデータに関連付けられている場合は、このプロパティにメタデータで示されている向きが含まれます。
このプロパティの有効な値のリストは『UIImageOrientation』を参照してください。

CGImageオブジェクトが取得できなかった場合の処理)

CGImageオブジェクトimageがNULLの場合、つまり引数のUIImageオブジェクトが無い、あるいはCGImageでの変換に失敗した場合は、自身を解放してエラーログを出力し、nilを返します。

アルファチャンネル情報の取得と色空間の設定)

まずCGImageGetAlphaInfoで画像のCGImageオブジェクトimageからアルファチャンネル情報を取得します。

画像から取得したアルファ情報がkCGImageAlphaPremultipliedLastkCGImageAlphaPremultipliedFirstkCGImageAlphaLastkCGImageAlphaFirstの場合、つまりアルファチャンネルを持っている場合は、フラグhasAlphaをYESに、無ければNOにします。

そして『CGImageGetColorSpace』で画像の色空間を取得します。

色空間が無い場合は画像マスクなので、ピクセルフォーマットを定数kTexture2DPixelFormat_A8と設定します。

色空間が存在する場合は、先程取得したフラグhasAlphaでアルファチャンネルの有無を確認し、アルファチャンネルがある場合は定数kTexture2DPixelFormat_RGBA8888を、無い場合はkTexture2DPixelFormat_RGB565を設定します。

CGImageGetAlphaInfo

CGImageAlphaInfo CGImageGetAlphaInfo (
    CGImageRef image
);

ビットマップ画像のアルファチャンネルを返します。

CGImageAlphaInfo定数は、(1)ビットマップがアルファチャンネルを含んでいるかどうか、(2)画像データ内の何処にアルファビットが位置しているか、(3)アルファ値が事前に乗算されているかを指定します。

有効な値は『定数』を参照してください。

画像パラメータが画像マスクを参照している場合、関数はkCGImageAlphaNoneを返します。

アルファ値は描画時にピクセルの不透明度を決定するものです。

image:検査する画像を指定します。

Alpha Information for Images

アルファコンポーネントデータのストレージオプション。

enum CGImageAlphaInfo {
    kCGImageAlphaNone,
    kCGImageAlphaPremultipliedLast,
    kCGImageAlphaPremultipliedFirst,
    kCGImageAlphaLast,
    kCGImageAlphaFirst,
    kCGImageAlphaNoneSkipLast,
    kCGImageAlphaNoneSkipFirst
};
typedef enum CGImageAlphaInfo CGImageAlphaInfo;

kCGImageAlphaFirst
アルファ成分は各ピクセルの最上位ビットに格納されています。
例:事前に乗算されていないARGB。

kCGImageAlphaLast
アルファ成分は各ピクセルの最下位ビットビットに格納されています。
例:事前に乗算されていないRGBA。

kCGImageAlphaNone
アルファチャンネルがありません。
ピクセルの合計サイズは、色空間における色成分の数に必要な容量より大きい場合、最下位ビットは無視されます。
この値はkCGImageAlphaNoneSkipLastと同等です。

kCGImageAlphaNoneSkipFirst
アルファチャンネルがありません。
ピクセルの合計サイズは、色空間における色成分の数に必要な容量より大きい場合、最上位ビットは無視されます。

kCGImageAlphaOnly
色データが無く、アルファチャンネルのみです。

kCGImageAlphaNoneSkipLast
アルファチャンネルがありません。
ピクセルの合計サイズは、色空間における色成分の数に必要な容量より大きい場合、最下位ビットは無視されます。
この値はkCGImageAlphaNoneと同等です。

kCGImageAlphaPremultipliedFirst
アルファ成分は各ピクセルの最上位ビットに格納され、色成分はこのアルファ値が既に乗算されています。
例:事前に乗算済のARGB。

kCGImageAlphaPremultipliedLast
アルファ成分は各ピクセルの最下位ビットに格納され、色成分はこのアルファ値が既に既に乗算されています。
例:事前に乗算済のRGBA。

CGImageAlphaInfo定数は、(1)ビットマップがアルファチャンネルを含んでいるかどうか、(2)画像データ内の何処にアルファビットが位置しているか、(3)アルファ値が事前に乗算されているかを指定します。

関数CGImageGetAlphaInfoを呼び出すことによって、画像のCGImageAlphaInfo定数を取得することができます。
(CGImageAlphaInfo定数が一部を成すCGBitmapInfo定数は、関数CGImageCreateで提供されます)

Quartzは、『元』となる新たに塗る一ピクセルの一色要素と、『対象』となる背景画像の一色要素を、線形補間式を使用して対象画像の色成分と元画像の色成分を結合することによってアルファブレンディングを実現します。

Quartzは画像の事前に乗算されたアルファのみをサポートします。

Quartzでは指定された他の色値を事前に乗算する必要はありません。

CGImageGetColorSpace

CGColorSpaceRef CGImageGetColorSpace (
    CGImageRef image
);

ビットマップ画像の色空間を返します。

戻り値は指定されたビットマップ画像の元となる色空間、あるいは画像が画像マスクの場合はNULLになります。

色空間は必要に応じて保持と解放をする責任があります。

image:検査する画像を指定します。

画像サイズの取得とアフィン変換の初期化)

CGImageGetWidthCGImageGetHeightを使用して、画像のCGImageオブジェクトimageから幅と高さを取得し、CGSizeMakeでCGSizeの構造体imageSizeを設定します。

これはテクスチャ用画像の元サイズです。

そして『CGAffineTransformIdentity』でアフィン変換に恒等変換を設定、つまり初期化を行います。

アフィン変換は画像サイズがOpenGL ES 1.1の最大テクスチャサイズを超えた場合の処理で使用します。

CGSizeMake

CGSize CGSizeMake (
    CGFloat width,
    CGFloat height
);

指定した大きさの値でサイズを返します。

戻り値は指定した幅と高さのCGSize構造体を返します。

width:幅の値を指定します。

height:高さの値を指定します。

CGImageGetWidth

size_t CGImageGetWidth (
    CGImageRef image
);

ビットマップ画像の幅を返します。

戻り値はビットマップ画像(または画像マスク)のピクセルの幅です。

image:検査する画像を指定します。

CGImageGetHeight

size_t CGImageGetHeight (
    CGImageRef image
);

ビットマップ画像の高さを返します。

戻り値はビットマップ画像(または画像マスク)のピクセルの高さです。

image:検査する画像を指定します。



参考文献

iOS OpenGL ESプログラミングガイド

OpenGL ES 1.1 Reference Pages

UIImage Class Reference

CGImage Reference

CGGeometry Reference

はじめてのiPhone3プログラミングはじめてのiPhone3プログラミング
(2009/12/17)
Dave Mark、Jeff LaMarche 他

商品詳細を見る

Beginning Ios 6 Development: Exploring the Ios SdkBeginning Ios 6 Development: Exploring the Ios Sdk
(2012/12/26)
David Mark、Jack Nutting 他

商品詳細を見る






SoundSport Pulse wireless headphones
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
04 | 2017/05 | 06
Sun Mon Tue Wed Thu Fri Sat
- 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31 - - -
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

SoundSport Pulse wireless headphones
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR