Menu

Skip to content
AppleScriptの穴
  • Home
  • Products
  • Books
  • Docs
  • Events
  • Forum
  • About This Blog
  • License
  • 仕事依頼

AppleScriptの穴

Useful & Practical AppleScript archive. Click '★Click Here to Open This Script' Link to download each AppleScript

余白トリミング実験 v3

Posted on 11月 23 by Takaaki Naganoya

背景が透過しているPNG画像で、余計な余白部分を自動でトリミングするAppleScriptの試作品です。実際に画像のトリミングを行います。1024×1024ぐらいまでの大きさのPNG画像が想定しているターゲットで、4Kとか8Kぐらいの画像は想定していません。

既存のCやObjective-Cなどの言語で書かれたトリミングのプログラムは、1ドットずつスキャンしていく方式だったので、そのままの処理をインタプリタ方式のAppleScriptで行うと、遅くて話になりません。

そこで、ブロックごとに分割して、ブロック単位で描画部分がないか(同サイズの透明イメージと比較して同じかどうか)チェックするという方式を採用しました。これは、画像がすべて空白かどうかをチェックする処理の原理を応用したものです。


▲テストに利用したPNG画像(196 × 309 ピクセル)

前バージョン(v2)を実際の用途に利用してみたら、トンでもなく使い物にならなかったので、プログラムのおかしなところを見直して、2段階で処理を行うことでさらに精度を上げてみたのが、このv3です。

画像全体を16×16のブロックに分割して、個別に透明なエリアか描画されているエリアかを判定します(パス1)。

そのままだと処理がラフすぎるので、外周部のブロックをさらに16分割し、外周部だけ透明ブロックかどうかの判定を行います(パス2)。

このテスト画像に対しては、それなりの結果が出ています。前バージョンと比べると大幅に性能向上してます。実戦投入してみるとまた別の感想が出てくるかもしれませんが……。


▲実戦投入。SF Symbolsをコピーした内容を指定色で画像化してクリップボードに入れるAppleScriptで使用してみたら、けっこういい感じに切り抜いてくれました

プログラムもまだ試作品段階なので、無駄な処理が多そうです。パス1とパス2で共通部分が多いので、見直すとメイン部分の長さが半分ぐらいになりそうですが、試作品段階なのであんまり短くしすぎると内容を理解しにくくなりそうで。

AppleScript名:余白トリミング実験 v3.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2024/11/21
—
–  Copyright © 2024 Piyomaru Software, All Rights Reserved
—

use AppleScript
use framework "Foundation"
use framework "AppKit"
use scripting additions

property NSData : a reference to current application’s NSData
property |NSURL| : a reference to current application’s |NSURL|
property NSColor : a reference to current application’s NSColor
property NSString : a reference to current application’s NSString
property NSImage : a reference to current application’s NSImage
property NSScreen : a reference to current application’s NSScreen
property NSBezierPath : a reference to current application’s NSBezierPath
property NSPNGFileType : a reference to current application’s NSPNGFileType
property NSMutableArray : a reference to current application’s NSMutableArray
property NSBitmapImageRep : a reference to current application’s NSBitmapImageRep

–画像分割ブロックサイズ
property imgDivXStep : 16
property imgDivYStep : 16

set aPOSIXpath to POSIX path of (choose file with prompt "PNG画像を選択")

–時間計測用
set a1Dat to current application’s NSDate’s timeIntervalSinceReferenceDate()

–画像自動切り抜き
set cImage to autoTrimImageFromPath(aPOSIXpath) of me

–時間計測用
set b1Dat to current application’s NSDate’s timeIntervalSinceReferenceDate()
set c1Dat to b1Dat – a1Dat
log c1Dat

–ファイル保存
set outPath to POSIX path of (choose file name with prompt "PNG画像の保存ファイル名を指定してください(拡張子入力必須)")
set sRes to saveImageRepAtPathAsPNG(cImage, outPath) of me

–POSIX pathで示したPNG画像(多分)の外周部の余白を自動トリミング
on autoTrimImageFromPath(aPOSIXpath)
  set aURL to |NSURL|’s fileURLWithPath:aPOSIXpath
  
set aImage to NSImage’s alloc()’s initWithContentsOfURL:aURL
  
return autoTrimImage(aImage) of me –return NSImage
end autoTrimImageFromPath

–NSImageの外周部の余白を自動トリミング
on autoTrimImage(aImage)
  script spd
    property outList : {} –Pass 1用
    
property pass2Res : {} –Pass 2用
  end script
  
  
–PASS 1 16 x 16 Whole Area Scan
  
  
set sRes to aImage’s |size|()
  
–> example: {width:196.0, height:309.0}
  
  
set aHeight to height of sRes
  
set aWidth to width of sRes
  
  
set xBlockSize to (aWidth div imgDivXStep)
  
set yBlockSize to (aHeight div imgDivYStep)
  
  
  
–transparent block sample for PASS 1
  
set blankImg1 to makeNSImageWithFilledWithColor(xBlockSize, yBlockSize, current application’s NSColor’s clearColor()) of me
  
set blankBit1 to blankImg1’s TIFFRepresentation()
  
  
  
  
set (outList of spd) to {}
  
  
repeat with yy from 0 to (aHeight – yBlockSize) by yBlockSize
    set oneLine to ""
    
    
repeat with xx from 0 to (aWidth – xBlockSize) by xBlockSize
      –crop a part of image and check transparent
      
set tmpImg to (my cropNSImageBy:{xx, yy, xBlockSize, yBlockSize} fromImage:aImage)
      
set tmpBit to tmpImg’s TIFFRepresentation()
      
set chkTrans to (blankBit1’s isEqualToData:tmpBit) as boolean
      
      
      
if chkTrans = false then –Not transparent block
        set the end of (outList of spd) to {xPos:xx, yPos:yy}
      end if
      
    end repeat
  end repeat
  
  
  
  
–最大値、最小値を取得
  
set nArray to (NSMutableArray’s arrayWithArray:(outList of spd))
  
  
set xMin to calcMin("xPos", nArray) of me
  
set xMax to calcMax("xPos", nArray) of me
  
  
set yMin to calcMin("yPos", nArray) of me
  
set yMax to calcMax("yPos", nArray) of me
  
  
  
  
–PASS 2: Edge Blocks 64 x 64 scan Most Edge blocks only
  
  
–transparent block sample for PASS 2 (1/4 size)
  
set blankImg2 to makeNSImageWithFilledWithColor(xBlockSize div 4, yBlockSize div 4, current application’s NSColor’s clearColor()) of me
  
set blankBit2 to blankImg2’s TIFFRepresentation()
  
  
  
set aArray to current application’s NSArray’s arrayWithArray:(outList of spd)
  
  
set westList to filterRecListByLabel1(aArray, "xPos == %@", xMin) of me as list
  
set eastList to filterRecListByLabel1(aArray, "xPos == %@", xMax) of me as list
  
set northLIst to filterRecListByLabel1(aArray, "yPos == %@", yMax) of me as list
  
set southLIst to filterRecListByLabel1(aArray, "yPos == %@", yMin) of me as list
  
  
set pass2List to westList & eastList & northLIst & southLIst
  
  
set (pass2Res of spd) to {}
  
  
repeat with i in pass2List
    set origPX to xPos of i
    
set origPY to yPos of i
    
    
repeat with y from 0 to 3
      repeat with x from 0 to 3
        
        
set tmpPX to origPX + (xBlockSize div 4) * x
        
set tmpPY to origPY + (yBlockSize div 4) * y
        
        
set tmpImg to (my cropNSImageBy:{tmpPX, tmpPY, xBlockSize div 4, yBlockSize div 4} fromImage:aImage)
        
set tmpBit2 to tmpImg’s TIFFRepresentation()
        
set chkTrans to (blankBit2’s isEqualToData:tmpBit2) as boolean
        
        
if chkTrans = false then –Not transparent block
          set the end of (pass2Res of spd) to {xPos:tmpPX, yPos:tmpPY}
        end if
      end repeat
    end repeat
  end repeat
  
  
  
set bArray to current application’s NSArray’s arrayWithArray:(pass2Res of spd)
  
  
set x2Min to calcMin("xPos", bArray) of me
  
set x2Max to calcMax("xPos", bArray) of me
  
  
set y2Min to calcMin("yPos", bArray) of me
  
set y2Max to calcMax("yPos", bArray) of me
  
  
–オリジナル画像を切り抜きして返す(NSImage)
  
return my cropNSImageTo:{x2Min, y2Min, x2Max + (xBlockSize div 4), y2Max + (yBlockSize div 4)} fromImage:aImage
end autoTrimImage

on calcMin(aLabel as string, nArray)
  set aStr to "@min." & aLabel
  
set aRes to nArray’s valueForKeyPath:aStr
  
return aRes as anything
end calcMin

on calcMax(aLabel as string, nArray)
  set aStr to "@max." & aLabel
  
set aRes to nArray’s valueForKeyPath:aStr
  
return aRes as anything
end calcMax

–指定サイズの画像を作成し、指定色で塗って返す
on makeNSImageWithFilledWithColor(aWidth, aHeight, fillColor)
  set retinaF to 1.0 —(NSScreen’s mainScreen()’s backingScaleFactor()) as real
  
–>  2.0 (Retina) / 1.0 (Non Retina)
  
  
set anImage to current application’s NSImage’s alloc()’s initWithSize:(current application’s NSMakeSize(aWidth, aHeight))
  
anImage’s lockFocus()
  
—
  
set theRect to {{x:0, y:0}, {height:aHeight / retinaF, width:aWidth / retinaF}}
  
set theNSBezierPath to current application’s NSBezierPath’s bezierPath
  
theNSBezierPath’s appendBezierPathWithRect:theRect
  
—
  
fillColor’s |set|() –色設定
  
theNSBezierPath’s fill() –ぬりつぶし
  
—
  
anImage’s unlockFocus()
  
—
  
return anImage
end makeNSImageWithFilledWithColor

on cropNSImageTo:{x1, y1, x2, y2} fromImage:theImage
  set newWidth to x2 – x1
  
set newHeight to y2 – y1
  
  
set newRect to {{x:x1, y:y1}, {width:newWidth, height:newHeight}}
  
  
theImage’s lockFocus()
  
set theRep to NSBitmapImageRep’s alloc()’s initWithFocusedViewRect:newRect
  
theImage’s unlockFocus()
  
  
set outImage to NSImage’s alloc()’s initWithSize:(theRep’s |size|())
  
outImage’s addRepresentation:theRep
  
  
return outImage
end cropNSImageTo:fromImage:

–NSImageを指定の大きさでトリミング
on cropNSImageBy:{x1, y1, newWidth, newHeight} fromImage:theImage
  set theSize to (theImage’s |size|()) as record
  
set oldHeight to height of theSize
  
  
set newRect to {{x:x1, y:y1}, {width:newWidth, height:newHeight}}
  
  
theImage’s lockFocus()
  
set theRep to NSBitmapImageRep’s alloc()’s initWithFocusedViewRect:newRect
  
theImage’s unlockFocus()
  
  
set outImage to NSImage’s alloc()’s initWithSize:(theRep’s |size|())
  
outImage’s addRepresentation:theRep
  
  
return outImage
end cropNSImageBy:fromImage:

–画像を指定パスにPNG形式で保存
on saveImageRepAtPathAsPNG(anImage, outPath)
  set imageRep to anImage’s TIFFRepresentation()
  
set aRawimg to NSBitmapImageRep’s imageRepWithData:imageRep
  
  
–パスのチルダ展開処理
  
set pathString to NSString’s stringWithString:outPath
  
set newPath to pathString’s stringByExpandingTildeInPath()
  
  
set myNewImageData to (aRawimg’s representationUsingType:(NSPNGFileType) |properties|:(missing value))
  
return (myNewImageData’s writeToFile:newPath atomically:true) as boolean
end saveImageRepAtPathAsPNG

–リストに入れたレコードを、指定の属性ラベルの値で抽出
on filterRecListByLabel1(aArray, aPredicate as string, aVal)
  set aPredicate to current application’s NSPredicate’s predicateWithFormat_(aPredicate, aVal)
  
set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate
  
return filteredArray
end filterRecListByLabel1

★Click Here to Open This Script 

More from my site

  • 余白トリミング実験 v2余白トリミング実験 v2
  • 余白トリミング実験 v1余白トリミング実験 v1
  • 指定画像の余白の自動トリミング指定画像の余白の自動トリミング
  • KGPixelBoundsClipがmacOS 15で動作しない?KGPixelBoundsClipがmacOS 15で動作しない?
  • 画像の空白判定 v4画像の空白判定 v4
  • 指定言語でNLEmbeddingを処理できるかチェック_13_14_15指定言語でNLEmbeddingを処理できるかチェック_13_14_15
(Visited 11 times, 1 visits today)
Posted in Image | Tagged 13.0savvy 14.0savvy 15.0savvy | 1 Comment

1 thoughts on “<span>余白トリミング実験 v3</span>”

  1. 12/17/24
    2:32 PM
    2024年12月17日
    2:32 PM

    Reply

    2024年に書いた価値あるAppleScript – AppleScriptの穴 says:

    […] 余白トリミング実験 v3 […]

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

電子書籍(PDF)をオンラインストアで販売中!

Google Search

Popular posts

  • 開発機としてM2 Mac miniが来たのでガチレビュー
  • macOS 13.6.5 AS系のバグ、一切直らず
  • CotEditorで2つの書類の行単位での差分検出
  • Apple純正マウス、キーボードのバッテリー残量取得
  • macOS 15, Sequoia
  • 初心者がつまづきやすい「log」コマンド
  • ディスプレイをスリープ状態にして処理続行
  • 指定のWordファイルをPDFに書き出す
  • Adobe AcrobatをAppleScriptから操作してPDF圧縮
  • メキシカンハットの描画
  • 与えられた文字列の1D Listのすべての順列組み合わせパターン文字列を返す v3(ベンチマーク用)
  • Pages本執筆中に、2つの書類モード切り替えに気がついた
  • macOS 13 TTS環境の変化について
  • 2023年に書いた価値あるAppleScript
  • Pixelmator Pro v3.6.4でAppleScriptからの操作時の挙動に違和感が
  • 可変次元のベクトルに対応したコサイン類似度計算
  • AdobeがInDesign v19.4からPOSIX pathを採用
  • Safariで「プロファイル」機能を使うとAppleScriptの処理に影響
  • Cocoa Scripting Course 続刊計画
  • NaturalLanguage.frameworkでNLEmbeddingの処理が可能な言語をチェック

Tags

10.11savvy (1102) 10.12savvy (1243) 10.13savvy (1392) 10.14savvy (587) 10.15savvy (438) 11.0savvy (282) 12.0savvy (204) 13.0savvy (160) 14.0savvy (106) 15.0savvy (84) CotEditor (63) Finder (51) iTunes (19) Keynote (112) NSAlert (61) NSArray (51) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (51) NSDictionary (27) NSFileManager (23) NSFont (19) NSImage (41) NSJSONSerialization (21) NSMutableArray (62) NSMutableDictionary (21) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (117) NSURL (97) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (70) Pages (52) Safari (44) Script Editor (26) WKUserContentController (21) WKUserScript (20) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

  • 2D Bin Packing
  • 3D
  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • Beginner
  • Benchmark
  • beta
  • Bluetooth
  • Books
  • boolean
  • bounds
  • Bug
  • Calendar
  • call by reference
  • Clipboard
  • Cocoa-AppleScript Applet
  • Code Sign
  • Color
  • Custom Class
  • dialog
  • diff
  • drive
  • Droplet
  • exif
  • file
  • File path
  • filter
  • folder
  • Font
  • Font
  • GAME
  • geolocation
  • GUI
  • GUI Scripting
  • Hex
  • History
  • How To
  • iCloud
  • Icon
  • Image
  • Input Method
  • Internet
  • iOS App
  • JavaScript
  • JSON
  • JXA
  • Keychain
  • Keychain
  • Language
  • Library
  • list
  • Locale
  • Localize
  • Machine Learning
  • Map
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • parallel processing
  • PDF
  • Peripheral
  • PRODUCTS
  • QR Code
  • Raw AppleEvent Code
  • Record
  • rectangle
  • recursive call
  • regexp
  • Release
  • Remote Control
  • Require Control-Command-R to run
  • REST API
  • Review
  • RTF
  • Sandbox
  • Screen Saver
  • Script Libraries
  • sdef
  • search
  • Security
  • selection
  • shell script
  • Shortcuts Workflow
  • Sort
  • Sound
  • Spellchecker
  • Spotlight
  • SVG
  • System
  • Tag
  • Telephony
  • Text
  • Text to Speech
  • timezone
  • Tools
  • Update
  • URL
  • UTI
  • Web Contents Control
  • WiFi
  • XML
  • XML-RPC
  • イベント(Event)
  • 未分類

アーカイブ

  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2024年2月
  • 2024年1月
  • 2023年12月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年12月
  • 2019年11月
  • 2019年10月
  • 2019年9月
  • 2019年8月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年11月
  • 2018年10月
  • 2018年9月
  • 2018年8月
  • 2018年7月
  • 2018年6月
  • 2018年5月
  • 2018年4月
  • 2018年3月
  • 2018年2月

https://piyomarusoft.booth.pm/items/301502

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org

Forum Posts

  • 人気のトピック
  • 返信がないトピック

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org
Proudly powered by WordPress
Theme: Flint by Star Verte LLC