Archive for the 'NSColorSpace' Category

2017/03/02 指定の画像が真っ白かどうか判定する

オープンソースのフレームワーク「GPUImage」(By Brad Larson)を利用して、指定の画像が真っ白かどうかを判定するAppleScriptです。指定画像が真っ白の場合にはtrueを、そうでない場合にはfalseを返します。

テストにあたっては、GPUImageフレームワークをXcodeでビルドして、~/Library/Frameworksフォルダに入れておいてください。

GPUImage.frameworkには特殊なフィルタが存在しており、その中で最もユニークなのが指定画像(NSImage)のヒストグラムを求めるものです。つまり、画像をフィルタ加工するのではなく、分析した結果を画像(NSImage)に出力します。

そのうちの「明度ヒストグラム」のフィルタ(?)を指定して、指定画像の明度分布を求めます(一瞬で)。明度分布のヒストグラムは、横256ドット・高さ3ドットの画像(NSImage)として出力されます。うち、中央の1ドットが左側が0(暗い=黒)右側が255(明るい=白)を表現しています。

white.png
▲GPUImage.frameworkで出力した明度ヒストグラム(真っ白な画像を処理した場合)。幅256ドット、高さ3ドットの画像(高さを90ドットに拡大)。右端(明度=255)のみ白く反応しており、他に明度分布は存在しないことが見て取れる

test2.png

test1.png
▲GPUImage.frameworkで出力した明度ヒストグラム(真っ白ではない画像を処理した場合の処理例)

つまり、画像が真っ白かどうかを判定するという、気が遠くなるほど重そうな画像処理が、わずか256箇所の色情報を調べるだけで、しかもGPUの機能を活用して一瞬で処理できることになります。しかも、AppleScriptで。

  1024×768@72DPIの画像=786,432ドット
  1920×1200@72DPIの画像=2,304,000ドット

これらを全部ループで色検出処理すると、相当の時間がかかるはずです。230万アイテム超のループ処理なんて想像したくもありません。

一応、テストのために、

  1024×768@72DPIの画像で、1ドットだけ黒くしたもの
  1920×1200@72DPIの画像で、1ドットだけ黒くしたもの

の2つを用意して、黒くした1ドットの存在を検出できるかテストしてみたところ、無事検出できました(しかも一瞬で)。

ただし、このことが4Kとか5Kの白い画像に1ドットだけ黒くした場合でも同様に検出できるかどうかは保証のかぎりではありません。

実際に利用するさいには事前にターゲットサイズの白い画像に1ドットだけ黒くして実験して検出可能かどうかを確認。検出できなかった場合には事前に解像度を落とす処理を行うなどの対応が必要です。

AppleScript名:指定の画像が真っ白かどうか判定する
– Created 2017-02-12 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
use framework “GPUImage”
–http://piyocast.com/as/archives/4492

set aFile to POSIX path of (choose file of type {“public.image”} with prompt “Select a Image to check it is white (or not) “)
set anNSImage to current application’s NSImage’s alloc()’s initWithContentsOfFile:aFile
set wRes to my detectAllWhite:anNSImage

–指定のNSImageが真っ白かどうかをチェック
on detectAllWhite:anNSImage
  
  
–明度ヒストグラム画像を取得
  
set imgRes to getHistogramFromImage(anNSImage, 4) of me
  
  
set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:(imgRes’s TIFFRepresentation())
  
  
–白い画像のデータパターン
  
set aWhitePattern to current application’s NSMutableArray’s arrayWithArray:{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0}
  
  
set resArray to current application’s NSMutableArray’s alloc()’s init()
  
repeat with i from 0 to 255
    set origColor to (aRawimg’s colorAtX:i y:1)
    
set srgbColSpace to current application’s NSColorSpace’s genericGrayColorSpace
    
set aColor to (origColor’s colorUsingColorSpace:srgbColSpace)
    
set aWhite to aColor’s whiteComponent()
    (
resArray’s addObject:aWhite)
  end repeat
  
  
set aRes to (resArray’s isEqualTo:aWhitePattern) as boolean
  
return aRes
  
end detectAllWhite:

–指定のNSImageをGPUImage.frameworkで明度ヒストグラム化してNSImageで返す
on getHistogramFromImage(aNSImage, histogramType)
  set aFilter to current application’s GPUImageHistogramFilter’s alloc()’s initWithHistogramType:histogramType
  
set aProcImg to (aFilter’s imageByFilteringImage:aNSImage)
  
return aProcImg
end getHistogramFromImage

–NSImageをGPUImage.frameworkの指定フィルタで処理してNSImageを返す
on filterWithNSImage(aNSImage, filterName as string)
  set aClass to current application’s NSClassFromString(filterName)
  
set aImageFilter to aClass’s alloc()’s init()
  
set aProcImg to (aImageFilter’s imageByFilteringImage:aNSImage)
  
return aProcImg
end filterWithNSImage

★Click Here to Open This Script 

2014/12/02 画像中の色数をカウント

画像中の色数をカウントするAppleScriptの試作品です。

ASOCの機能を使って、色数のカウントを行いますが・・・1024 x 768ピクセル程度の「かわいらしいサイズ」の画像であっても、すべてのピクセルを処理しようとすると、78万アイテム程度のデータを処理する必要があるため、10万アイテムをメドに処理するべき/するべきではないという判断を行うならば、「そのままでは処理すべきではない」ということに。

本Scriptは、画像の一部分だけを取り出して色数のカウントを行います。

色数のカウントについては、画像の間引きや中間調部分の除去などの前処理を行うべきであり、実ファイルを直接調べるような、乱暴な処理で行うべきものではないと考えます。とはいえ、こうした処理に手が届きそうになってきたことは体感できるのではないかと。

普通はPhotoshopなどで処理すべきでしょう。ただ、色数カウントという処理は割と骨が折れそうで、、、

AppleScript名:画像中の色数をカウント
– Created 2014-12-01 by Takaaki Naganoya
– 2014 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ASObjCExtras”
use framework “AppKit”

script spd
  property aColList : {}
end script

set aColList of spd to {}

–画像を選択して読み込む
set a to choose file of type {“public.image”}

set aURL to current application’s SMSFord’s URLFrom:a
set aImage to current application’s NSImage’s alloc()’s initWithContentsOfURL:aURL

–画像のサイズ(幅、高さ)をピクセル数で取得する
set aSize to aImage’s |size|()
set aWidth to aSize’s width()
set aHeight to aSize’s height()

–読み込んだ画像のRaw画像を作成
set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:(aImage’s TIFFRepresentation())

–画像の一部のピクセルの色を取り出して色数をカウント
repeat with xNum from 0 to ((aWidth as integer) - 1)
  –repeat with yNum from 0 to ((aHeight as integer) - 1)
  
repeat with yNum from 0 to 10
    
    
set origColor to (aRawimg’s colorAtX:xNum y:yNum)
    
set srgbColSpace to current application’s NSColorSpace’s deviceRGBColorSpace
    
    
set aColor to (origColor’s colorUsingColorSpace:srgbColSpace)
    
    
set aRed to (aColor’s redComponent()) * 255
    
set aGreen to (aColor’s greenComponent()) * 255
    
set aBlue to (aColor’s blueComponent()) * 255
    
set aAlpha to (aColor’s alphaComponent()) * 255
    
    
set oneCol to {aRed as integer, aGreen as integer, aBlue as integer, aAlpha as integer}
    
    
set the end of aColList of spd to oneCol
    
  end repeat
end repeat

–ユニーク化
set aArray to current application’s NSArray’s arrayWithArray:(aColList of spd)
set bArray to aArray’s valueForKeyPath:“@distinctUnionOfObjects.self”

set bList to bArray’s ASify() as list
length of bList

★Click Here to Open This Script 

2014/12/02 画像の特定のピクセルの色を取得

指定画像を読み込んで、特定のピクセルの色を読み取るAppleScriptです。

画像を読み取るといった処理は、Xcode上でAppleScriptObjCのアプリケーションを作成している時にはよく書きますが、Script Editor上で書くAppleScriptObjCだと新鮮な感じがあります。

とくにWindow上に表示したりはしないのですが、実際に読み込んで色のピックアップができているような気がします。ただ、見えないので本当に合っているのかはもうちょっと試行錯誤を、、、

AppleScriptだけで(Photoshopなどを使わないで)画像処理を行うためのテストの一環で行ってみました。キャプチャ画像のリサイズぐらいは、Cocoaの機能だけで行っておきたいところです。

AppleScript名:画像の特定のピクセルの色を取得
– Created 2014-12-01 by Takaaki Naganoya
– 2014 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "ASObjCExtras"
use framework "AppKit"

–画像を選択して読み込む
set a to choose file of type {"public.image"}

set aURL to current application’s SMSFord’s URLFrom:a
set aImage to current application’s NSImage’s alloc()’s initWithContentsOfURL:aURL

–画像のサイズ(幅、高さ)をピクセル数で取得する
set aSize to aImage’s |size|()
set aWidth to aSize’s width()
set aHeight to aSize’s height()

–読み込んだ画像のRaw画像を作成
set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:(aImage’s TIFFRepresentation())

–画像中の{0, 0}のピクセルの色をRGBAそれぞれ取り出す
set origColor to (aRawimg’s colorAtX:0 y:0)
set srgbColSpace to current application’s NSColorSpace’s deviceRGBColorSpace

set aColor to (origColor’s colorUsingColorSpace:srgbColSpace)

set aRed to (aColor’s redComponent()) * 255
set aGreen to (aColor’s greenComponent()) * 255
set aBlue to (aColor’s blueComponent()) * 255
set aAlpha to (aColor’s alphaComponent()) * 255

set oneCol to {aRed as integer, aGreen as integer, aBlue as integer, aAlpha as integer}
–> {255, 255, 255, 218} – sample

★Click Here to Open This Script