画素データを画面に表示する

 前回、画像をScrollViewへ表示させるプログラムをつくりました。今回は、読み込んだ画像ではなく、自分で用意した画素データを画面に表示するプログラムを作成します。UIの作成を前回と同じなので、UIは準備したという仮定のもとで話を進めます。

前回の記事:「ScrollViewに画像を表示させる」

ウインドウが読み込まれたらScroll Viewへ画像を表示

 では、ウインドウが読み込まれた際に、Scroll Viewへ作成した画素データを表示するプログラムを作ります。以下のようにプログラミングしてください。

    @IBOutlet var ScrollView: NSScrollView!
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        //画像データを作成
        let width:UInt = 300
        let height:UInt = 280
        var imageBytes : UnsafeMutablePointer<Byte>;
        let ByteLength = Int(width) * Int(height) * 4
        imageBytes = UnsafeMutablePointer<Byte>.alloc(ByteLength)
        for i in 0...Int(width)-1{
            for j in 0...Int(height)-1{
                var k: Int = ((Int(width) * j) + i) * 4
                imageBytes[k] = Byte(i%255) // red
                imageBytes[k+1] = Byte(j%255); // green
                imageBytes[k+2] = Byte(0); // blue
                imageBytes[k+3] = Byte(0); // alpha
            }
        }

        //CGDataProvider(データの場所や種類の情報)を作成
        var provider = CGDataProviderCreateWithData(nil,imageBytes, UInt(ByteLength), nil)

        //CGImage(ビットマップ画像)を作成
        var bitsPerComponent:UInt = 8   //画素は8bit
        var bitsPerPixel:UInt = bitsPerComponent * 4    //pxあたりのビット数:4色より
        var bytesPerRow:UInt = UInt(4) * width  //1列あたりのバイト数
        var colorSpaceRef = CGColorSpaceCreateDeviceRGB()
        var bitmapInfo = CGBitmapInfo.ByteOrderDefault
        var renderingIntent = kCGRenderingIntentDefault
        var cgImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, nil, false, renderingIntent)

        //NSImageを作成
        let Size=NSSize(width:Int(width),height:Int(height))
        let img = NSImage(CGImage: cgImage,size:Size)

        //NSImageViewの作成
        var imageSize:NSRect=NSMakeRect(0.0,0.0,CGFloat(width),CGFloat(height))
        var theImageView:NSImageViewR=NSImageViewR(frame:imageSize)
        theImageView.image=img

        //NSImageViewをNSScrollViewへ表示
        self.ScrollView.hasHorizontalScroller=true  //水平スクロールの表示
        self.ScrollView.hasVerticalScroller=true    //垂直スクロールの表示
        self.ScrollView.documentView=theImageView
    }

実行すると以下のように画面が表示されます。

グラデーション

 画素データを表示するには以下の様な手順を取ります。

  1. 画素データの準備
  2. CGDataProvider(データの種類や場所の情報)を作成
  3. CGImage(ビットマップ画像)の作成
  4. NSImageの作成と表示

画素データの準備

 はじめの画素データはバイトデータの配列です。C言語の方法でメモリを確保して配列を準備します。今回は、4色(r,g,b,alpha)で色の深さは1バイト、縦300横280ピクセルなので、

 4\times 1\times 300\times 280バイト

がデータの大きさになります。画像データの保存法はr,g,b,alphaで、横方向に走査します。ですから、座標(i,j)のr,g,b,alphaのデータの位置は、

  1. 赤:4\times(i+j\times W)
  2. 緑:4\times(i+j\times W)+1
  3. 青:4\times(i+j\times W)+2
  4. α:4\times(i+j\times W)+3

となります。ここで、Wは幅で300pxです。

CGDataProvider(データの種類や場所の情報)を作成

 続いてCGDataProviderという作成した画素データがどこにあって、種類は何なのかを指定するということをします。以下のコードで実現しています。

        //CGDataProvider(データの場所や種類の情報)を作成
        var provider = CGDataProviderCreateWithData(nil,imageBytes, UInt(ByteLength), nil)

CGDataProviderの細かいリファレンスは以下の公式ページを参照してください。

CGDataProviderの公式リファレンス

CGImage(ビットマップ画像)の作成

 作成した配列データをビットマップ画像として保存します。OS XのビットマップはCGImageというクラスを用います。作成を以下の通りです。

var cgImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, nil, false, renderingIntent)

CGImageCreateの構造は以下の通りです。

func CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorspace, bitmapInfo, provider, decode, shouldInterpolate, intent)-> CGImage!

入力変数の意味は以下の表にまとめてあります。

変数名 データの型 意味
width UInt 画像の幅
height UInt 画像の高さ
bitsPerPixel UInt 1px当たりのビット数
bytesPerRow UInt 1行あたりのバイト数
colorspace CGColorSpace カラースペース
bitmapInfo CGBitmapInfo  ビットマップ画像の形式
provider CGDataProvider! 画像データ情報であるCGDataProvider
decode UnsafePointer<CGFloat>  デコーディング
shouldInterpolate Bool  補完が必要ならtrue
intent CGColorRenderingIntent  レンダリング設定

CGImageの詳細はリファレンスを参照してください。

CGImageの公式リファレンス

NSImageの作成と表示

 最後に、CGImageをNSImageへ変換して、NSImageをScroll Viewへ表示させて完了です。

        //NSImageを作成
        let Size=NSSize(width:Int(width),height:Int(height))
        let img = NSImage(CGImage: cgImage,size:Size)

        //NSImageViewの作成
        var imageSize:NSRect=NSMakeRect(0.0,0.0,CGFloat(width),CGFloat(height))
        var theImageView:NSImageViewR=NSImageViewR(frame:imageSize)
        theImageView.image=img

        //NSImageViewをNSScrollViewへ表示
        self.ScrollView.hasHorizontalScroller=true  //水平スクロールの表示
        self.ScrollView.hasVerticalScroller=true    //垂直スクロールの表示
        self.ScrollView.documentView=theImageView

著者:安井 真人(やすい まさと)