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

カテゴリー: Image

画像をAppleScriptでアスキーアート化

Posted on 2月 26 by Takaaki Naganoya

指定の画像をアスキーアート化して、ダイアログ表示するAppleScriptです。

–> Download Script archive with Library

面倒だったのでChatGPTに書かせてみましたが、Retina Display対応や細かい箇所のエラーを取りきれず、途中から自分で書き換えました。

画像のアスキーアート化Scriptは、できることはわかっていつつも、これほど役立たずに時間の無駄なプログラムも珍しいところ。こういうのはChatGPTに書かせるのがお似合いです。

それにしても、けっこうこまめにコメント入れるもんですね。正しい内容かどうかは定かではありませんが……>ChatGPT

AppleScript名:画像をAppleScriptでアスキーアート化.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2025/02/26
—
–  Copyright © 2025 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use scripting additions
use radioLib : script "displayTextView"

property retinaF : missing value

— ファイル選択ダイアログで画像を選ぶ
set imagePath to POSIX path of (choose file with prompt "画像を選択してください:")

— ASCIIアートを生成
set asciiText to convertImageToASCII(imagePath)
display text view asciiText main message "ASCII ART" sub message "Sub Message" with properties {font name:"Courier", size:12, width:620, height:620, color:{255, 255, 255}}

on convertImageToASCII(imagePath)
  set asciiChars to "@%#*+=-:. " — 濃い→薄い順の文字列
  
  
— Retina用のスケールファクターを取得
  
set retinaF to (current application’s NSScreen’s mainScreen()’s backingScaleFactor()) as real
  
  
— 画像を読み込む
  
set imageURL to current application’s NSURL’s fileURLWithPath:imagePath
  
set imageData to current application’s NSImage’s alloc()’s initWithContentsOfURL:imageURL
  
  
— 論理サイズ(points単位)を取得("size"は予約語なのでエスケープ)
  
set imageSize to imageData’s |size|()
  
set {w_pt, h_pt} to {imageSize’s |width|, imageSize’s |height|}
  
  
— リサイズ後の幅(文字数)を指定し、論理サイズに基づいてスケール計算
  
set newWidth to 80
  
set scaleFactor to newWidth / w_pt
  
set newHeight to round (h_pt * scaleFactor * 0.55) — 文字の縦横比調整
  
  
— ピクセル単位のサイズに変換(Retina対応)
  
set pixelWidth to newWidth * retinaF
  
set pixelHeight to newHeight * retinaF
  
set pixelSize to current application’s NSMakeSize(pixelWidth, pixelHeight)
  
  
— 新しいピクセルサイズでNSImageを作成し、元画像を描画
  
set resizedImage to current application’s NSImage’s alloc()’s initWithSize:pixelSize
  
resizedImage’s lockFocus()
  
current application’s NSGraphicsContext’s currentContext()’s setImageInterpolation:(current application’s NSImageInterpolationHigh)
  
imageData’s drawInRect:{{0, 0}, pixelSize} fromRect:{{0, 0}, imageSize} operation:(current application’s NSCompositingOperationCopy) fraction:1.0
  
resizedImage’s unlockFocus()
  
  
— リサイズ後の画像からNSBitmapImageRepを取得
  
set resizedRep to current application’s NSBitmapImageRep’s imageRepWithData:(resizedImage’s TIFFRepresentation())
  
  
— 各ピクセルをASCII文字に変換(Retina対応のため、retinaFごとにサンプリング)
  
set asciiArt to ""
  
set stepX to retinaF as integer
  
set stepY to retinaF as integer
  
  
repeat with y from 0 to (pixelHeight – 1) by stepY
    repeat with x from 0 to (pixelWidth – 1) by stepX
      set pixelColor to (resizedRep’s colorAtX:(x * retinaF) y:(y * retinaF))
      
      
set r to pixelColor’s redComponent()
      
set g to pixelColor’s greenComponent()
      
set b to pixelColor’s blueComponent()
      
set brightness to (r + g + b) / 3
      
      
set charIndex to round (brightness * ((count of asciiChars) – 1))
      
set asciiArt to asciiArt & (character (charIndex + 1) of asciiChars)
    end repeat
    
set asciiArt to asciiArt & linefeed
  end repeat
  
  
return asciiArt
end convertImageToASCII

★Click Here to Open This Script 

Posted in dialog file Image Text | Tagged 13.0savvy 14.0savvy 15.0savvy | Leave a comment

Finder上で選択中のファイルをJPEG形式で指定フォルダに書き出し(自動補正つき)

Posted on 1月 23 by Takaaki Naganoya

Finderの最前面のウィンドウで選択しておいた画像をオープンして自動画質補正を行いつつ、指定の番号からの連番をつけたJPEG画像に変換して指定フォルダに書き込むAppleScriptです。

さっそく、昨日書いた画質自動補正のプログラムを使い回しています。他のものもほぼ、過去に書いたものを使い回しているだけで、新規に書いた部分はほとんどありません。必要以上に長くなっており、おそらく呼び出していないルーチンなども含まれているはずです。

この、連番のJPEG画像はプロジェクターのスライドショー機能を用いて写真を表示するための仕様です。USBメモリなどにJPEG画像を入れておくと、ファイル名順に再生を行ってくれます。

当初はMacをプロジェクターにつないで写真.app(Photos.app)のBGMつきスライドショーを試してみたのですが、BGMに合わせた画像切り替えを行ってくれる一方で、強制的に1写真あたりの表示時間を指定することができず、「これでは使えない」として、プロジェクターの内蔵スライドショー機能を使うことにしたので、このようなScriptを作ったものです。

AppleScript名:Finder上で選択中のファイルをJPEG形式で指定フォルダに書き出し(自動補正つき).scpt
—
–  Created by: Takaaki Naganoya
–  Created on: 2025/01/23
—
–  Copyright © 2025 Piyomaru Software, All Rights Reserved
—

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

property CIFilter : a reference to current application’s CIFilter
property NSArray : a reference to current application’s NSArray
property CIImage : a reference to current application’s CIImage
property NSUUID : a reference to current application’s NSUUID
property |NSURL| : a reference to current application’s |NSURL|
property NSString : a reference to current application’s NSString
property NSImage : a reference to current application’s NSImage
property NSPredicate : a reference to current application’s NSPredicate
property NSPNGFileType : a reference to current application’s NSPNGFileType
property NSBitmapImageRep : a reference to current application’s NSBitmapImageRep

tell application "Finder"
  set aSel to selection as alias list
end tell

set posList to {}
set aCount to 1

set bFol to POSIX path of (choose folder with prompt "出力先フォルダを選択")

repeat with i in aSel
  set j to POSIX path of i
  
set aUTI to getUTIFromFile(j) of me
  
if aUTI is not equal to missing value then
    –ファイルから求めたUTIが指定のUTIに含まれるかをチェック
    
set bRes to filterUTIList({aUTI}, "public.image")
    
    
if bRes is not equal to {} then
      –自動画質調整
      
set aNSImage to makeNSImageFromPOSIXpath(j) of me
      
set bImgRes to autoFiltersForNSImage(aNSImage) of me
      
if bImgRes = false then return
      
      
–NSImageをJPEGで書き出す
      
set aStr to makeFN(aCount, 5) of me
      
set outPath to bFol & aStr & ".jpg"
      
set sRes to saveNSImageAtPathAsJPG(bImgRes, outPath, 0.9) of JPGkit
      
      
set aCount to aCount + 1
      
    else
      log j
    end if
    
    
log j
  end if
end repeat

on autoFiltersForNSImage(aNSImage)
  set aCIImage to convNSImageToCIimage(aNSImage) of me
  
set filterList to aCIImage’s autoAdjustmentFilters
  
if filterList = missing value then return false
  
  
repeat with i in filterList
    set aFilter to contents of i
    (
aFilter’s setValue:(aCIImage) forKey:"inputImage")
    
set aOutImage to (aFilter’s valueForKey:"outputImage")
    
    
copy aOutImage to aCIImage
  end repeat
  
  
set outNSImage to convCIimageToNSImage(aOutImage) of me
  
  
return outNSImage
end autoFiltersForNSImage

on convCIimageToNSImage(aCIImage)
  set aRep to NSBitmapImageRep’s alloc()’s initWithCIImage:aCIImage
  
set tmpSize to aRep’s |size|()
  
set newImg to NSImage’s alloc()’s initWithSize:tmpSize
  
newImg’s addRepresentation:aRep
  
return newImg
end convCIimageToNSImage

on convNSImageToCIimage(aNSImage)
  set tiffDat to aNSImage’s TIFFRepresentation()
  
set aRep to NSBitmapImageRep’s imageRepWithData:tiffDat
  
set newImg to CIImage’s alloc()’s initWithBitmapImageRep:aRep
  
return newImg
end convNSImageToCIimage

on makeNSImageFromAlias(anAlias)
  set imgPath to (POSIX path of anAlias)
  
set aURL to (|NSURL|’s fileURLWithPath:(imgPath))
  
return (NSImage’s alloc()’s initWithContentsOfURL:aURL)
end makeNSImageFromAlias

on makeNSImageFromPOSIXpath(aPOSIX)
  set aURL to (|NSURL|’s fileURLWithPath:(aPOSIX))
  
return (NSImage’s alloc()’s initWithContentsOfURL:aURL)
end makeNSImageFromPOSIXpath

on getUTIFromFile(aPath)
  set aWS to current application’s NSWorkspace’s sharedWorkspace()
  
set pRes to (aWS’s isFilePackageAtPath:aPath) as boolean
  
if pRes = false then
    set superType to (current application’s UTTypeData)
  else
    set superType to (current application’s UTTypePackage)
  end if
  
  
set pathString to current application’s NSString’s stringWithString:aPath
  
set aExt to (pathString’s pathExtension()) as string
  
  
set aUTType to current application’s UTType’s typeWithFilenameExtension:aExt conformingToType:(superType)
  
if aUTType = missing value then return missing value
  
  
set aUTIstr to aUTType’s identifier() as string
  
return aUTIstr
end getUTIFromFile

on filterUTIList(aUTIList, aUTIstr)
  set anArray to NSArray’s arrayWithArray:aUTIList
  
set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr)
  
set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list
  
return bRes
end filterUTIList

on makeFN(aNum, aDigit)
  set aText to "00000000000" & (aNum as text)
  
set aLen to length of aText
  
set aRes to text (aLen – aDigit + 1) thru -1 of aText
  
return aRes
end makeFN

script JPGkit
  use scripting additions
  
use framework "Foundation"
  
use framework "AppKit"
  
property parent : AppleScript
  
  
on saveAImageASJPG(aFile, aNewFile)
    set aPOSIX to (POSIX path of aFile)
    
set aImage to current application’s NSImage’s alloc()’s initWithContentsOfFile:(aPOSIX)
    
    
set newPath to current application’s NSString’s stringWithString:(POSIX path of aNewFile)
    
set newExt to (newPath’s pathExtension()) as string
    
if newExt is not equal to "jpg" then
      set newPath to repFilePathExtension(newPath, ".jpg") of me
    end if
    
    
set sRes to saveNSImageAtPathAsJPG(aImage, newPath, 1.0) of me
  end saveAImageASJPG
  
  
  
on repFilePathExtension(origPath, newExt)
    set aName to current application’s NSString’s stringWithString:origPath
    
set theExtension to aName’s pathExtension()
    
if (theExtension as string) is not equal to "" then
      set thePathNoExt to aName’s stringByDeletingPathExtension()
      
set newName to (thePathNoExt’s stringByAppendingString:newExt)
    else
      set newName to (aName’s stringByAppendingString:newExt)
    end if
    
return newName as string
  end repFilePathExtension
  
  
  
–NSImageを指定パスにJPEG形式で保存、qulityNumは0.0〜1.0。1.0は無圧縮
  
on saveNSImageAtPathAsJPG(anImage, outPath, qulityNum as real)
    set imageRep to anImage’s TIFFRepresentation()
    
set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:imageRep
    
set pathString to current application’s NSString’s stringWithString:outPath
    
set newPath to pathString’s stringByExpandingTildeInPath()
    
set myNewImageData to (aRawimg’s representationUsingType:(current application’s NSJPEGFileType) |properties|:{NSImageCompressionFactor:qulityNum})
    
set aRes to (myNewImageData’s writeToFile:newPath atomically:true) as boolean
    
return aRes –true/false
  end saveNSImageAtPathAsJPG
end script

★Click Here to Open This Script 

Posted in Image UTI | Tagged 13.0savvy 14.0savvy 15.0savvy | Leave a comment

CoreImageで指定画像をautoAdjustmentFilters

Posted on 1月 21 by Takaaki Naganoya

Core ImageのCIFilterから、autoAdjustmentFiltersを呼び出して、いい感じにKeynote上とかで自動画像調整を行うのと同様に、画像に対して自動調整を行うAppleScriptです。

KeynoteやPages上の画像の自動補正機能は、大当たりすることもなければ大はずしすることもない、なかなかお得な機能です。

ちょっと、Finder上で選択した画像にひととおり自動補正をかけてお茶をにごしたい。

そんな機能が存在しないかと調べていたのですが、autoAdjustmentFiltersの存在は知っていたものの、いろいろ試しては、

current application’s CIImage’s autoAdjustmentFilters()

とか、

current application’s CIFilter’s autoAdjustmentFilters()

などと間違った記述を行なってmissing valueが返ってきては、首をひねりまくっていました。

Googleの検索エンジンで探してもなかなかサンプルに行き当たらないあたり、みんな苦労しているんじゃないかと疑っていますが、これは、

CIImage画像に対してautoAdjustmentFilters()を実行すると、自動調整用のCIFilterにパラメータが設定された状態でarrayに入って返ってくるのでした(これは、わからないぞ)。

半信半疑で実行してみたら、なんとなくそれっぽく自動調整された画像がデスクトップに出力されます。

AppleScript名:CoreImageで指定画像をautoAdjustmentFilters.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2025/01/21
—
–  Copyright © 2025 Piyomaru Software, All Rights Reserved
—

use AppleScript version "2.8"
use framework "Foundation"
use framework "AppKit"
use framework "CoreImage"
use scripting additions

property CIFilter : a reference to current application’s CIFilter
property NSUUID : a reference to current application’s NSUUID
property |NSURL| : a reference to current application’s |NSURL|
property CIImage : a reference to current application’s CIImage
property NSString : a reference to current application’s NSString
property NSImage : a reference to current application’s NSImage
property NSPNGFileType : a reference to current application’s NSPNGFileType
property NSBitmapImageRep : a reference to current application’s NSBitmapImageRep

set imgPath to POSIX path of (choose file)
set aNSImage to makeNSImageFromPOSIXpath(imgPath) of me

set bImgRes to autoFiltersForNSImage(aNSImage) of me
if bImgRes = false then return

set outPath to retUUIDfilePath(POSIX path of (path to desktop), "png") of me
set sRes to saveNSImageAtPathAsPNG(bImgRes, outPath) of me

on autoFiltersForNSImage(aNSImage)
  set aCIImage to convNSImageToCIimage(aNSImage) of me
  
set filterList to aCIImage’s autoAdjustmentFilters
  
if filterList = missing value then return false
  
  
repeat with i in filterList
    set aFilter to contents of i
    (
aFilter’s setValue:(aCIImage) forKey:"inputImage")
    
set aOutImage to (aFilter’s valueForKey:"outputImage")
    
    
copy aOutImage to aCIImage
  end repeat
  
  
set outNSImage to convCIimageToNSImage(aOutImage) of me
  
  
return outNSImage
end autoFiltersForNSImage

on retUUIDfilePath(aPath, aEXT)
  set aUUIDstr to (NSUUID’s UUID()’s UUIDString()) as string
  
set aPath to ((NSString’s stringWithString:aPath)’s stringByAppendingPathComponent:aUUIDstr)’s stringByAppendingPathExtension:aEXT
  
return aPath
end retUUIDfilePath

on convCIimageToNSImage(aCIImage)
  set aRep to NSBitmapImageRep’s alloc()’s initWithCIImage:aCIImage
  
set tmpSize to aRep’s |size|()
  
set newImg to NSImage’s alloc()’s initWithSize:tmpSize
  
newImg’s addRepresentation:aRep
  
return newImg
end convCIimageToNSImage

on convNSImageToCIimage(aNSImage)
  set tiffDat to aNSImage’s TIFFRepresentation()
  
set aRep to NSBitmapImageRep’s imageRepWithData:tiffDat
  
set newImg to CIImage’s alloc()’s initWithBitmapImageRep:aRep
  
return newImg
end convNSImageToCIimage

on makeNSImageFromAlias(anAlias)
  set imgPath to (POSIX path of anAlias)
  
set aURL to (|NSURL|’s fileURLWithPath:(imgPath))
  
return (NSImage’s alloc()’s initWithContentsOfURL:aURL)
end makeNSImageFromAlias

on makeNSImageFromPOSIXpath(aPOSIX)
  set aURL to (|NSURL|’s fileURLWithPath:(aPOSIX))
  
return (NSImage’s alloc()’s initWithContentsOfURL:aURL)
end makeNSImageFromPOSIXpath

–NSImageを指定パスにPNG形式で保存
on saveNSImageAtPathAsPNG(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))
  
set aRes to (myNewImageData’s writeToFile:newPath atomically:true) as boolean
  
return aRes –true/false
end saveNSImageAtPathAsPNG

★Click Here to Open This Script 

Posted in filter Image | Tagged 12.0savvy 13.0savvy 14.0savvy 15.0savvy CIFilter CIImage | Leave a comment

指定フォルダ以下の画像のMD5チェックサムを求めて、重複しているものをピックアップしてダイアログでプレビュー_v4

Posted on 1月 2 by Takaaki Naganoya

指定フォルダ以下の画像(種別問わず)をすべてピックアップして、それぞれMD5チェックサムを計算し、重複しているものをピックアップしてデータとして出力するAppleScriptです。実行にはScript Debuggerを必要とします。今後は、ScriptableなライブラリをXcodeで1本作って、そこにAppleScriptから呼び出すのに便利なFrameworkを突っ込みまくるようにするのかも? 

–> Download Script Bundle within framework and library

前バージョンのScriptでは指定フォルダ直下の画像だけをピックアップするようになっていました、Spotlight検索でサブディレクトリ以下もすべて画像収集するように変更し、本Scriptだけで重複画像のブラウズができるようになっています。NSOutlineView+NSImageでブラウズするダイアログの部品はedama2さんから提供していただいています。

AppleScript名:指定フォルダ以下の画像のMD5チェックサムを求めて、重複しているものをピックアップしてダイアログでプレビュー_v4.scptd
— Created 2015-10-01 by Takaaki Naganoya
— Modified 2015-10-01 by Shane Stanley–With Cocoa-Style Filtering
— Modified 2018-12-01 by Takaaki Naganoya
— Modified 2024-12-19 by Takaaki Naganoya
— Modified 2025-01-01 by Takaaki Naganoya
— Modified 2025-01-02 by Takaaki Naganoya
use AppleScript
use scripting additions
use framework "Foundation"
use framework "AppKit"
use framework "md5Lib" –https://github.com/JoeKun/FileMD5Hash
use outImageV : script "visLib" –NSOUtlineView+NSImageView Lib by edama2
use mdLib : script "Metadata Lib" version "2.0.0"

property |NSURL| : a reference to current application’s |NSURL|
property NSArray : a reference to current application’s NSArray
property NSPredicate : a reference to current application’s NSPredicate
property NSCountedSet : a reference to current application’s NSCountedSet
property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey
property NSString : a reference to current application’s NSString
property NSFileManager : a reference to current application’s NSFileManager
property NSMutableArray : a reference to current application’s NSMutableArray
property NSSortDescriptor : a reference to current application’s NSSortDescriptor

script spd
  property fList : {}
  
property fRes : {}
  
property md5List : {}
  
property fmdList : {}
  
property dupRes : {}
  
property outList : {}
end script

set aFol to POSIX path of (choose folder)
–set aFol to POSIX path of (path to pictures folder)

set (fRes of spd) to mdLib’s searchFolders:{aFol} searchString:("(kMDItemContentTypeTree CONTAINS %@)") searchArgs:{"public.image"}

–すべての画像のMD5チェックサムを計算
set (md5List of spd) to {}
set (fmdList of spd) to {}

repeat with i in (fRes of spd)
  set j to contents of i
  
set md5Res to (current application’s FileHash’s md5HashOfFileAtPath:(j)) as string
  
set the end of (md5List of spd) to md5Res
  
set the end of (fmdList of spd) to {filePath:j, md5:md5Res}
end repeat

–チェックサムが重複している画像を取り出す
set fmdArray to NSArray’s arrayWithArray:(fmdList of spd)

set (dupRes of spd) to returnDuplicatesOnly((md5List of spd)) of me
set (outList of spd) to {}
set procMDs to {}
set aRecord to {}

repeat with i in (dupRes of spd)
  set j to contents of i
  
  
if j is not in procMDs then
    set aRes to filterDictArrayByLabel(fmdArray, "md5 == ’" & j & "’") of me
    
    
set tmpMD5 to filePath of (first item of aRes)
    
    
set tmpRes to {}
    
repeat with ii in aRes
      set jj to contents of ii
      
set idSrcURL to (current application’s NSURL’s fileURLWithPath:(filePath of jj))
      
set the end of tmpRes to {|name|:idSrcURL’s lastPathComponent(), fileURL:idSrcURL, isLeaf:true}
    end repeat
    
    
set aRec to {|name|:j, fileRes:"", isLeaf:false, children:tmpRes}
    
set aRecord’s end to aRec
    
set the end of procMDs to j
    
set the end of (outList of spd) to aRec
  end if
end repeat

–OutlineView+ ImageViewでダイアログ表示
set mainMes to "重複画像一覧"
set subMes to "指定フォルダ以下の重複画像は以下のとおりです"
set aRes to outImageV’s alert:mainMes informativeText:subMes treeData:(outList of spd) isExpand:true

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

–指定フォルダ以下のすべてのファイルを再帰で取得
on retFullpathsWithinAFolderWithRecursive(aFol)
  set anArray to NSMutableArray’s array()
  
set aPath to NSString’s stringWithString:aFol
  
set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath
  
  
repeat
    set aName to (dirEnum’s nextObject())
    
if aName = missing value then exit repeat
    
set aFullPath to aPath’s stringByAppendingPathComponent:aName
    
anArray’s addObject:(aFullPath as string)
  end repeat
  
  
return anArray as list
end retFullpathsWithinAFolderWithRecursive

–Alias listから指定UTIに含まれるものをPOSIX pathのリストで返す
on filterAliasListByUTI(aList, targUTI)
  set newList to {}
  
repeat with i in aList
    set j to POSIX path of i
    
set tmpUTI to my retUTIfromPath(j)
    
set utiRes to my filterUTIList({tmpUTI}, targUTI)
    
if utiRes is not equal to {} then
      set the end of newList to j
    end if
  end repeat
  
return newList
end filterAliasListByUTI

–指定のPOSIX pathのファイルのUTIを求める
on retUTIfromPath(aPOSIXPath)
  set aURL to |NSURL|’s fileURLWithPath:aPOSIXPath
  
set {theResult, theValue} to aURL’s getResourceValue:(reference) forKey:NSURLTypeIdentifierKey |error|:(missing value)
  
  
if theResult = true then
    return theValue as string
  else
    return theResult
  end if
end retUTIfromPath

–UTIリストが指定UTIに含まれているかどうか演算を行う
on filterUTIList(aUTIList, aUTIstr)
  set anArray to NSArray’s arrayWithArray:aUTIList
  
set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr)
  
set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list
  
return bRes
end filterUTIList

on returnDuplicatesOnly(aList as list)
  set aSet to NSCountedSet’s alloc()’s initWithArray:aList
  
set bList to (aSet’s allObjects()) as list
  
  
set dupList to {}
  
repeat with i in bList
    set aRes to (aSet’s countForObject:i)
    
if aRes > 1 then
      set the end of dupList to (contents of i)
    end if
  end repeat
  
  
return dupList
end returnDuplicatesOnly

★Click Here to Open This Script 

Posted in file Image | Tagged 13.0savvy 14.0savvy 15.0savvy | Leave a comment

指定フォルダ以下の画像のMD5チェックサムを求めて、重複しているものをピックアップ

Posted on 12月 19, 2024 by Takaaki Naganoya

指定フォルダ以下の画像(種別問わず)をすべてピックアップして、それぞれMD5チェックサムを計算し、重複しているものをピックアップしてデータとして出力するAppleScriptです。実行にはScript Debuggerを必要とします。内蔵のMD5計算Frameworkはx64/Apple Silicon(ARM64E)のUniversal Binaryでビルドしてあります。

–> –> Download photoDupLister(Script Bundle with Framework in its bundle)

# 本Scriptのファイル収集ルーチンが、再帰で下位フォルダの内容をすべてピックアップするものではありませんでした
# 実際に指定フォルダ以下すべての画像を収集する(Spotlightで)ようにしてみたら5.5万ファイルの処理に26分ほどかかりました

MD5チェックサムが同じということは、同じ画像である可能性が高いものです。

ここで、各画像のチェックサムを計算するさいに、サムネイルを生成してからチェックサムを計算するかどうかという話があります。

サムネイルを作成すべき派の言い分は、そのほうが計算量が減らせるし、同一画像の縮尺違い(拡大/縮小率違い)を求めることもできるというものです。

サムネイル作成否定派の言い分は、そんなもん作る前に画像のチェックサムを計算してしまえ、逆に手間だというものでした。

これは、どちらの意見ももっともだったので、実際にシミュレーションを行ってみるしかないでしょう。そこで、ありもののルーチンを集めて実際に作ってみたのが本Scriptです。サムネイルは作らないで処理してみました。

自分のMacBook Air M2のPicturesフォルダに入っていた約5,000の画像ファイルを処理したところ、16ペアの重複画像がみつかりました。処理にかかる時間はおよそ9秒です(実行するたびに所要時間が若干変化)。おそらく、Intel Macで実行すると数十秒から数分かかるのではないかと。

実用性を確保したい場合には、画像を回転しつつチェックサムを1画像あたり4パターン求めるとか、やはり同じサイズのサムネイル画像を生成してサムネイルに対してMD5チェックサムを計算するとか、画像の類似度を計算するオプションなども欲しいところです。

また、処理内容が並列処理向きなので、並列で処理してみてもよいでしょう。マシン環境を調べてSoCのPコアの個数をかぞえて、Pコアと同数の処理アプレットを生成して並列実行。……余計な処理を行うせいで速くならない可能性が高そうです。

AppleScript名:指定フォルダ以下の画像のMD5チェックサムを求めて、重複しているものをピックアップ
— Created 2015-10-01 by Takaaki Naganoya
— Modified 2015-10-01 by Shane Stanley–With Cocoa-Style Filtering
— Modified 2018-12-01 by Takaaki Naganoya
— Modified 2024-12-19 by Takaaki Naganoya
use AppleScript version "2.8"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use framework "md5Lib" –https://github.com/JoeKun/FileMD5Hash

property |NSURL| : a reference to current application’s |NSURL|
property NSArray : a reference to current application’s NSArray
property NSPredicate : a reference to current application’s NSPredicate
property NSCountedSet : a reference to current application’s NSCountedSet
property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey

script spd
  property fList : {}
  
property fRes : {}
  
property md5List : {}
  
property fmdList : {}
  
property dupRes : {}
  
property outList : {}
end script

set anUTI to "public.image"

set aFol to choose folder
–set aFol to path to pictures folder

set (fList of spd) to getFilePathList(aFol) of me

–指定のFile listのうち画像のみ抽出
set (fRes of spd) to filterAliasListByUTI((fList of spd), "public.image") of me
if (fRes of spd) = {} then return

–すべての画像のMD5チェックサムを計算
set (md5List of spd) to {}
set (fmdList of spd) to {}

repeat with i in (fRes of spd)
  set j to contents of i
  
set md5Res to (current application’s FileHash’s md5HashOfFileAtPath:(j)) as string
  
set the end of (md5List of spd) to md5Res
  
set the end of (fmdList of spd) to {filePath:j, md5:md5Res}
end repeat

–チェックサムが重複している画像を取り出す
set fmdArray to NSArray’s arrayWithArray:(fmdList of spd)

set (dupRes of spd) to returnDuplicatesOnly((md5List of spd)) of me
set (outList of spd) to {}
set procMDs to {}

repeat with i in (dupRes of spd)
  set j to contents of i
  
  
if j is not in procMDs then
    set aRes to filterDictArrayByLabel(fmdArray, "md5 == ’" & j & "’") of me
    
    
set tmpMD5 to filePath of (first item of aRes)
    
    
set tmpRes to {}
    
repeat with ii in aRes
      set jj to contents of ii
      
set the end of tmpRes to filePath of jj
    end repeat
    
    
set aRec to {md5:j, fileRes:tmpRes}
    
set the end of (outList of spd) to aRec
    
set the end of procMDs to j
  end if
end repeat

return (outList of spd)

–リストに入れたレコードを、指定の属性ラベルの値で抽出
on filterDictArrayByLabel(aArray, aPredicate as string)
  –抽出
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat:aPredicate
  
set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate
  
  
–NSArrayからListに型変換して返す
  
set bList to filteredArray as list
  
return bList
end filterDictArrayByLabel

on getFilePathList(aFol)
  set aURL to current application’s |NSURL|’s fileURLWithPath:(POSIX path of aFol)
  
set aFM to current application’s NSFileManager’s defaultManager()
  
set urlArray to aFM’s contentsOfDirectoryAtURL:aURL includingPropertiesForKeys:{} options:(current application’s NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
  
return urlArray as anything
end getFilePathList

–Alias listから指定UTIに含まれるものをPOSIX pathのリストで返す
on filterAliasListByUTI(aList, targUTI)
  set newList to {}
  
repeat with i in aList
    set j to POSIX path of i
    
set tmpUTI to my retUTIfromPath(j)
    
set utiRes to my filterUTIList({tmpUTI}, targUTI)
    
if utiRes is not equal to {} then
      set the end of newList to j
    end if
  end repeat
  
return newList
end filterAliasListByUTI

–指定のPOSIX pathのファイルのUTIを求める
on retUTIfromPath(aPOSIXPath)
  set aURL to |NSURL|’s fileURLWithPath:aPOSIXPath
  
set {theResult, theValue} to aURL’s getResourceValue:(reference) forKey:NSURLTypeIdentifierKey |error|:(missing value)
  
  
if theResult = true then
    return theValue as string
  else
    return theResult
  end if
end retUTIfromPath

–UTIリストが指定UTIに含まれているかどうか演算を行う
on filterUTIList(aUTIList, aUTIstr)
  set anArray to NSArray’s arrayWithArray:aUTIList
  
set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr)
  
set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list
  
return bRes
end filterUTIList

on returnDuplicatesOnly(aList as list)
  set aSet to NSCountedSet’s alloc()’s initWithArray:aList
  
set bList to (aSet’s allObjects()) as list
  
  
set dupList to {}
  
repeat with i in bList
    set aRes to (aSet’s countForObject:i)
    
if aRes > 1 then
      set the end of dupList to (contents of i)
    end if
  end repeat
  
  
return dupList
end returnDuplicatesOnly

★Click Here to Open This Script 

Posted in check sum file Image UTI | Tagged 12.0savvy 13.0savvy 14.0savvy 15.0savvy | Leave a comment

Excel 指定セルに指定画像を貼り込む v2

Posted on 12月 6, 2024 by Takaaki Naganoya

Microsoft Excelで、指定画像を指定セルに貼り込むAppleScriptです。指定セルの座標を求めて、そこを左上の位置として画像を貼り込みます。

前バージョンが「動かない」という話があって、「そんなバカな?!」と、半信半疑でユーザーと同じドライブ名、フォルダ名、ファイル名、画像形式を採用したら(JPEG形式)同様にエラーになりました。自分がテストしたのは内蔵SSDで、画像形式はPNGだったのですが……

そこで、書き換えてJPEG画像でも、外付けドライブでもエラーにならないように書き換えてみました。

AppleScript名:指定セルに指定画像を貼り込む v2.scpt
—
–  Created by: Takaaki Naganoya
–  Created on: 2024/12/06
—
–  Copyright © 2024 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

property |NSURL| : a reference to current application’s |NSURL|
property NSImage : a reference to current application’s NSImage

–Excel Cell Address (A1) –> Column No, & Row No.
set targCellAddr to "C5"
set {targCellCol, targCellRow} to cellToNumber(targCellAddr) of AddressEncoder
log {targCellCol, targCellRow}

–Column No, & Row No. –> x position & y position
set {targCellX, targCellY} to retExcelCellPositiont(targCellCol, targCellRow) of me
log {targCellX, targCellY}

–Select Image file and get width and height
set anImagePath to choose file
set anImagePOSIX to POSIX path of anImagePath
set aURL to |NSURL|’s fileURLWithPath:anImagePOSIX
set aImage to NSImage’s alloc()’s initWithContentsOfURL:aURL
set overlaySize to aImage’s |size|()

–Place image on worksheet and resize and relocate it
tell application "Microsoft Excel"
  activate
  
  
tell active workbook
    tell active sheet
      set newPic to make new picture at beginning with properties {file name:(anImagePOSIX), height:(overlaySize’s |height|), width:(overlaySize’s |width|), top:targCellY, left position:targCellX}
    end tell
  end tell
end tell

–指定Row, ColumnのCellのpositionを返す
on retExcelCellPositiont(x as integer, y as integer)
  tell application "Microsoft Excel"
    tell active workbook
      tell active sheet
        tell row y
          tell cell x
            set xMin0 to left position
            
set yMin0 to top
            
set xWidth0 to width
            
set yHeight0 to height
          end tell
        end tell
      end tell
    end tell
  end tell
  
  
return {xMin0, yMin0}
end retExcelCellPositiont

script AddressEncoder
  property parent : AppleScript
  
use scripting additions
  
  
— 数値からセルアドレス(A1形式)への変換
  
on numberToCell(columnNumber)
    set columnAddress to ""
    
set tempNumber to columnNumber
    
    
— 列番号をA-Z形式に変換
    
repeat while tempNumber > 0
      set remainder to (tempNumber – 1) mod 26
      
set columnAddress to (character (remainder + 1) of "ABCDEFGHIJKLMNOPQRSTUVWXYZ") & columnAddress
      
set tempNumber to (tempNumber – 1) div 26
    end repeat
    
    
— A1形式のアドレスを返す
    
return columnAddress
  end numberToCell
  
  
  
— セルアドレス(A1形式)から数値への変換
  
on cellToNumber(cellAddress)
    set columnPart to ""
    
set rowPart to ""
    
    
— 列部分と行部分を分離
    
repeat with char in cellAddress
      if char is in "0123456789" then
        set rowPart to rowPart & char
      else
        set columnPart to columnPart & char
      end if
    end repeat
    
    
— 列部分を数値に変換
    
set columnNumber to 0
    
repeat with i from 1 to length of columnPart
      set char to character i of columnPart
      
using terms from scripting additions
        set columnNumber to columnNumber * 26 + (offset of char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
      end using terms from
    end repeat
    
    
— 数値を返す
    
return {columnNumber, (rowPart as integer)}
  end cellToNumber
  
end script

★Click Here to Open This Script 

Posted in Image Object control | Tagged 13.0savvy 14.0savvy 15.0savvy Excel | Leave a comment

Excelで指定セルに指定画像を貼り込む

Posted on 12月 5, 2024 by Takaaki Naganoya

Microsoft Excelで、指定画像を指定セルに貼り込むAppleScriptです。指定セルの座標を求めて、そこを左上の位置として画像を貼り込みます。

本Scriptで、セルアドレスの指定時に「B4」などとアルファベット大文字で指定してください。英小文字で指定するとエラーになります(以後のバージョンでは、ignoring caseで判断部分を囲って対処しています)。

AppleScript名:指定セルに指定画像を貼り込む.scpt
—
–  Created by: Takaaki Naganoya
–  Created on: 2024/12/05
—
–  Copyright © 2024 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

property |NSURL| : a reference to current application’s |NSURL|
property NSImage : a reference to current application’s NSImage

–Excel Cell Address (A1)–+ Column No, & Row No.
set targCellAddr to "A2"
set {targCellCol, targCellRow} to cellToNumber(targCellAddr) of AddressEncoder
log {targCellCol, targCellRow}

–Column No, & Row No. –> x position & y position
set {targCellX, targCellY} to retExcelCellPositiont(targCellCol, targCellRow) of me
log {targCellX, targCellY}

–Select Image file and get width and height
set anImagePath to choose file
set anImagePOSIX to POSIX path of anImagePath
set aURL to |NSURL|’s fileURLWithPath:anImagePOSIX
set aImage to NSImage’s alloc()’s initWithContentsOfURL:aURL
set overlaySize to aImage’s |size|()

–Place image on worksheet and resize and relocate it
tell application "Microsoft Excel"
  activate
  
  
tell active workbook
    tell active sheet
      
      
set aPicShape to make new shape at the beginning
      
set width of aPicShape to (overlaySize’s |width|)
      
set height of aPicShape to (overlaySize’s |height|)
      
set top of aPicShape to targCellY
      
set left position of aPicShape to targCellX
      
      
user picture of aPicShape picture file anImagePOSIX
      
    end tell
  end tell
end tell

–指定Row, ColumnのCellのpositionを返す
on retExcelCellPositiont(x as integer, y as integer)
  tell application "Microsoft Excel"
    tell active workbook
      tell active sheet
        tell row y
          tell cell x
            set xMin0 to left position
            
set yMin0 to top
            
set xWidth0 to width
            
set yHeight0 to height
          end tell
        end tell
      end tell
    end tell
  end tell
  
  
return {xMin0, yMin0}
end retExcelCellPositiont

script AddressEncoder
  property parent : AppleScript
  
use scripting additions
  
  
— 数値からセルアドレス(A1形式)への変換
  
on numberToCell(columnNumber)
    set columnAddress to ""
    
set tempNumber to columnNumber
    
    
— 列番号をA-Z形式に変換
    
repeat while tempNumber > 0
      set remainder to (tempNumber – 1) mod 26
      
set columnAddress to (character (remainder + 1) of "ABCDEFGHIJKLMNOPQRSTUVWXYZ") & columnAddress
      
set tempNumber to (tempNumber – 1) div 26
    end repeat
    
    
— A1形式のアドレスを返す
    
return columnAddress
  end numberToCell
  
  
  
— セルアドレス(A1形式)から数値への変換
  
on cellToNumber(cellAddress)
    set columnPart to ""
    
set rowPart to ""
    
    
— 列部分と行部分を分離
    
repeat with char in cellAddress
      if char is in "0123456789" then
        set rowPart to rowPart & char
      else
        set columnPart to columnPart & char
      end if
    end repeat
    
    
— 列部分を数値に変換
    
set columnNumber to 0
    
repeat with i from 1 to length of columnPart
      set char to character i of columnPart
      
using terms from scripting additions
        set columnNumber to columnNumber * 26 + (offset of char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
      end using terms from
    end repeat
    
    
— 数値を返す
    
return {columnNumber, (rowPart as integer)}
  end cellToNumber
  
end script

★Click Here to Open This Script 

Posted in Image list | Tagged 13.0savvy 14.0savvy 15.0savvy Excel | Leave a comment

書式つきテキストを組み立てて、画像を追加し、RTFDとして保存 v2

Posted on 11月 25, 2024 by Takaaki Naganoya

書式つきテキスト(NSAttributedString)にコンピュータのアイコン画像を添付し、RTFDとしてファイル保存するAppleScriptです。

RTFDはRTFに対して画像などの要素を追加したApple独自の拡張仕様です。書式つきテキストはRTFとしてファイルに書き込んだり、逆にRTFから読み込んで書式つきテキスト化することも可能ですが、画像を添付したらRTFDとして保存する必要があります。

AppleScript名:書式つきテキストを組み立てて、画像を追加し、RTFDとして保存 v2
— Created 2017-09-25 by Takaaki Naganoya
— Modified 2017-09-27 by Shane Stanley
— Modified 2024-11-25 by Takaaki Naganoya
— 2017-2024 Piyomaru Software
use AppleScript
use scripting additions
use framework "Foundation"
use framework "AppKit"

property NSFont : a reference to current application’s NSFont
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 NSDictionary : a reference to current application’s NSDictionary
property NSTextAttachment : a reference to current application’s NSTextAttachment
property NSAttributedString : a reference to current application’s NSAttributedString
property NSMutableDictionary : a reference to current application’s NSMutableDictionary
property NSFontAttributeName : a reference to current application’s NSFontAttributeName
property NSKernAttributeName : a reference to current application’s NSKernAttributeName
property NSImageNameComputer : a reference to current application’s NSImageNameComputer
property NSMutableParagraphStyle : a reference to current application’s NSMutableParagraphStyle
property NSLigatureAttributeName : a reference to current application’s NSLigatureAttributeName
property NSMutableAttributedString : a reference to current application’s NSMutableAttributedString
property NSRTFDTextDocumentType : a reference to current application’s NSRTFDTextDocumentType
property NSUnderlineStyleAttributeName : a reference to current application’s NSUnderlineStyleAttributeName
property NSDocumentTypeDocumentAttribute : a reference to current application’s NSDocumentTypeDocumentAttribute
property NSParagraphStyleAttributeName : a reference to current application’s NSParagraphStyleAttributeName
property NSForegroundColorAttributeName : a reference to current application’s NSForegroundColorAttributeName

set aFile to POSIX path of (choose file name with prompt "保存するファイル名を入力(拡張子.rtfdつきで)")
set aURL to |NSURL|’s fileURLWithPath:aFile

–Attributed Stringを作成
set aFontSize to 48
set aString to "My Mac"
set anAssrStr to makeRTFfromParameters(aString, "HelveticaNeue-Light", aFontSize, -2, (aFontSize * 1.5)) of me

–添付画像を作成
set anAttach to NSTextAttachment’s alloc()’s init()
set anImage to NSImage’s imageNamed:(NSImageNameComputer)
set bImage to my resizeNSImage:anImage toSize:64
anAttach’s setImage:bImage

–添付画像をAttributed Stringに添付
set iconString to NSAttributedString’s attributedStringWithAttachment:anAttach
anAssrStr’s insertAttributedString:iconString atIndex:0 –冒頭に添付

–添付画像つきAttributed StringをRTFDとしてファイル保存
set aStrRange to current application’s NSMakeRange(0, anAssrStr’s |length|())
set attrDict1 to NSDictionary’s dictionaryWithObject:NSRTFDTextDocumentType forKey:NSDocumentTypeDocumentAttribute
set {aFileWrapper, anError} to anAssrStr’s fileWrapperFromRange:aStrRange documentAttributes:(attrDict1) |error|:(reference)
if anError is not equal to missing value then error

set {fRes, fError} to aFileWrapper’s writeToURL:aURL options:(current application’s NSFileWrapperWritingAtomic) originalContentsURL:(missing value) |error|:(reference)

–書式つきテキストを組み立てる
on makeRTFfromParameters(aStr as string, fontName as string, aFontSize as real, aKerning as real, aLineSpacing as real)
  –Font
  
set aVal1 to NSFont’s fontWithName:fontName |size|:aFontSize
  
set aKey1 to (NSFontAttributeName)
  
  
–Color
  
set aVal2 to NSColor’s blackColor()
  
set aKey2 to (NSForegroundColorAttributeName)
  
  
–Kerning
  
set aVal3 to aKerning
  
set akey3 to (NSKernAttributeName)
  
  
–Underline
  
set aVal4 to 0
  
set akey4 to (NSUnderlineStyleAttributeName)
  
  
–Ligature
  
set aVal5 to 2 –all ligature ON
  
set akey5 to (NSLigatureAttributeName)
  
  
–縦書き指定–Japanese tategaki setting (Up to down, right to left direction drawing)
  
set aVal6 to false
  
set aKey6 to (current application’s NSVerticalGlyphFormAttributeName)
  
  
–Paragraph space
  
set aParagraphStyle to NSMutableParagraphStyle’s alloc()’s init()
  
aParagraphStyle’s setMinimumLineHeight:(aLineSpacing)
  
aParagraphStyle’s setMaximumLineHeight:(aLineSpacing)
  
set akey7 to (NSParagraphStyleAttributeName)
  
  
set keyList to {aKey1, aKey2, akey3, akey4, akey5, aKey6, akey7}
  
set valList to {aVal1, aVal2, aVal3, aVal4, aVal5, aVal6, aParagraphStyle}
  
set attrsDictionary to NSMutableDictionary’s dictionaryWithObjects:valList forKeys:keyList
  
  
set attrStr to NSMutableAttributedString’s alloc()’s initWithString:aStr attributes:attrsDictionary
  
return attrStr
end makeRTFfromParameters

on resizeNSImage:aImg toSize:aSize
  if (aImg’s isValid()) as boolean = false then error "Invalid NSImage"
  
  
set tmpView to current application’s NSImageView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aSize, aSize))
  
tmpView’s setImageScaling:(current application’s NSImageScaleProportionallyUpOrDown)
  
tmpView’s setImage:aImg
  
  
set newRect to tmpView’s frame()
  
set newRep to tmpView’s bitmapImageRepForCachingDisplayInRect:newRect
  
  
tmpView’s cacheDisplayInRect:newRect toBitmapImageRep:newRep
  
set newData to newRep’s TIFFRepresentation() –representationUsingType:(current application’s NSPNGFileType) |properties|:(missing value)
  
  
return current application’s NSImage’s alloc()’s initWithData:newData
end resizeNSImage:toSize:

★Click Here to Open This Script 

Posted in Image RTF | Tagged 13.0savvy 14.0savvy 15.0savvy NSAttributedString NSFileWrapper NSTextAttachment | Leave a comment

余白トリミング実験 v3

Posted on 11月 23, 2024 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 

Posted in Image | Tagged 13.0savvy 14.0savvy 15.0savvy | 1 Comment

余白トリミング実験 v2

Posted on 11月 21, 2024 by Takaaki Naganoya

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

この、背景透過画像の余計な余白を自動トリミングする、という部品は割と(個人的に)重要なのでいろいろ試してみたものです。


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


▲オリジナル画像をPreview.appで表示させたところ。背景の余白がある


▲本Scriptで自動トリミングを行ったところ

いろいろチューニングしてみましたが、画像の空白エリアの検出は、「元画像の分割数」に応じていろいろ切り抜きすぎたり、余白が多すぎたりとかなり変動が生じました。

32×32分割だと処理速度的に0.4秒@M2なので、16×16前後が向いている感じでした。20×20ぐらいでも試していますが、結局、切り抜きすぎるのは避けたいところです。

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

use AppleScript version "2.8" — macOS 12 or later
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

script spd
  property outList : {}
end script

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

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

set aURL to |NSURL|’s fileURLWithPath:aFile
set aImage to NSImage’s alloc()’s initWithContentsOfURL:aURL

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
set blankImg to makeNSImageWithFilledWithColor(xBlockSize, yBlockSize, current application’s NSColor’s clearColor()) of me
set blankBit to blankImg’s TIFFRepresentation()

set (outList of spd) to {}

repeat with y from 0 to (aHeight – yBlockSize) by yBlockSize
  set oneLine to ""
  
  
repeat with x from 0 to (aWidth – xBlockSize) by xBlockSize
    –crop a part of image and check transparent
    
set tmpImg to (my cropNSImageBy:{x, y, xBlockSize, yBlockSize} fromImage:aImage)
    
set tmpBit to tmpImg’s TIFFRepresentation()
    
set chkTrans to (blankBit’s isEqualToData:tmpBit) as boolean
    
    
if chkTrans = false then –Not transparent block
      set the end of (outList of spd) to {xPos:x, yPos:y}
    end if
  end repeat
  
end repeat

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

–最大値、最小値を取得
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

–オリジナル画像を切り抜き
set cImage to my cropNSImageTo:{xMin + (xBlockSize / 2), yMin + (yBlockSize / 2), xMax + (xBlockSize / 2), yMax + (yBlockSize / 2)} fromImage:aImage

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

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 (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 theSize to (theImage’s |size|()) as record
  
set oldHeight to height of theSize
  
  
— transpose y value for Cocoa coordintates
  
set y1 to oldHeight – newHeight – 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
  
  
— transpose y value for Cocoa coordintates
  
set y1 to oldHeight – newHeight – 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 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

★Click Here to Open This Script 

Posted in Image | Tagged 13.0savvy 14.0savvy 15.0savvy | Leave a comment

余白トリミング実験 v1

Posted on 11月 21, 2024 by Takaaki Naganoya

背景が透過しているPNG画像で、余計な余白部分を自動でトリミングするAppleScriptの試作品です。


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

いまのところ、画像を細かく分割して、透明な画像かどうかをブロックごとにチェックするだけです。

画像が真っ白かどうか、透明かどうかといったチェックは、すでに高速処理できるノウハウがあったので、ただそれを応用したものです。

実際にAppleScriptだけで記述して、そこそこの速度が出ています。画像の分割ブロック数が8×8だといまひとつで、16×16でもイマイチ。32 x 32分割ブロックぐらいで「そんなもんだろ」という印象。


▲8×8分割ブロック(0.04秒ぐらい @MacBook Air M2)


▲16×16分割ブロック(0.1秒ぐらい @MacBook Air M2)


▲32×32分割ブロック(0.5秒ぐらい @MacBook Air M2)

当初は可変サイズ分割を考えていましたが、そこまで難しい処理をしなくても良さそうな雰囲気。

何らかの画像処理を行った結果で透明部分が余計に存在するエリアを削除しておくぐらいなので、そんなにシビアにチューニングしなくてもよさそうな気がします。そんなに巨大な画像を処理しなければいいんじゃないでしょうか。

もしも、巨大な画像を処理する場合には、サムネイル画像を作成して、その画像に対してこのような処理を行えばいいんじゃないでしょうか。

このScriptは、背景が透過していることを前提に組んでありますが、画像の4隅から色をピックアップして、多数決で透過なのか白なのかを決定してもいいかもしれません。「余白がかならず存在する」画像であれば、このやり方でいいかも?

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

use AppleScript version "2.8" — macOS 12 or later
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 NSBezierPath : a reference to current application’s NSBezierPath
property NSPNGFileType : a reference to current application’s NSPNGFileType
property NSBitmapImageRep : a reference to current application’s NSBitmapImageRep

property imgDivXStep : 8
property imgDivYStep : 8

set aFile to POSIX path of (choose file)

set a1Dat to current application’s NSDate’s timeIntervalSinceReferenceDate()

set aURL to |NSURL|’s fileURLWithPath:aFile
set aImage to NSImage’s alloc()’s initWithContentsOfURL:aURL

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
set blankImg to makeNSImageWithFilledWithColor(xBlockSize, yBlockSize, current application’s NSColor’s clearColor()) of me
set blankBit to blankImg’s TIFFRepresentation()

set outList to ""

repeat with y from 0 to (aHeight – yBlockSize) by yBlockSize
  set oneLine to ""
  
  
repeat with x from 0 to (aWidth – xBlockSize) by xBlockSize
    –crop a part of image and check transparent
    
set tmpImg to (my cropNSImageBy:{x, y, xBlockSize, yBlockSize} fromImage:aImage)
    
set tmpBit to tmpImg’s TIFFRepresentation()
    
set chkTrans to (blankBit’s isEqualToData:tmpBit) as boolean
    
    
if chkTrans = true then
      set oneLine to oneLine & "□" –Transparent Block
    else
      set oneLine to oneLine & "■" –Not transparent Block
    end if
  end repeat
  
  
set outList to outList & oneLine & return
end repeat

set b1Dat to current application’s NSDate’s timeIntervalSinceReferenceDate()
set c1Dat to b1Dat – a1Dat
log c1Dat

return outList

–指定サイズの画像を作成し、指定色で塗ってファイル書き出し
on makeNSImageWithFilledWithColor(aWidth, aHeight, fillColor)
  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, width:aWidth}}
  
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 theSize to (theImage’s |size|()) as record
  
set oldHeight to height of theSize
  
  
— transpose y value for Cocoa coordintates
  
set y1 to oldHeight – newHeight – 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
  
  
— transpose y value for Cocoa coordintates
  
set y1 to oldHeight – newHeight – 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 cropNSImageBy:fromImage:

★Click Here to Open This Script 

Posted in Image | Tagged 13.0savvy 14.0savvy 15.0savvy | Leave a comment

KGPixelBoundsClipがmacOS 15で動作しない?

Posted on 11月 19, 2024 by Takaaki Naganoya

画像から透過部分を周囲から切り抜く、KGPixelBoundsClipをCooca Framework化して利用していますが、macOS 15上でこれが動作しないことを確認しました。

このFrameworkをAppleScriptから呼び出せることで、Adobe PhotoshopなどのGUIアプリの併用が必要ないため、応用範囲がものすごく広くなりました。

→ 指定画像の余白の自動トリミング

一般向けに公開していない個人用ツールで、本フレームワークを利用しまくっていました。

しかし、macOS 15+MacBook Air M2(Retina Display)の環境では以前のように動作しません(Universal Binaryビルドずみ)。

本プログラムの動作原理はおそろしく簡単です。

周囲から1ピクセルずつ色を拾って、透明色が続く矩形エリアを検出します。CとかObjective-Cだとパフォーマンスを確保しやすい処理内容ですが(脳筋プログラミング)、インタプリタ型のAppleScriptだとこういう脳筋な処理内容だと著しく不利になります。

目下、

(1)かわりの部品をオープンソースのプロジェクトからみつくろう
(2)その後、OS内で類似の機能が追加されていないか調査する
(3)もう、あとくされないようにAppleScriptで書き換える

といった対処を検討中です。

(1)については、Image+Trim.swiftといったSwiftで書かれたプログラムが見つかっています。AppleScriptから呼び出すためには、Bridging Headerを書く必要があるので、ひたすらダルいです。

(2)については、たぶん実装されていないんでないかと(未調査)

(3)については、1ピクセルずつチェックするのでなければ作れそうです。画像の外周部を画像のサイズから計算して細分化したブロックに分割、このブロックごとに透明かどうかをチェックし、ある程度まとめて処理することで速度を稼げそうな気がします。

あとは、最初にサムネイル画像を作ってしまって、その小さくした画像で外周部から色をピックアップしていくという手段もあります。いくつかの方法を試してどれが一番速いかを調べておく必要がありそうです。

Posted in Image | Tagged 15.0savvy KGPixelBoundsClip | Leave a comment

Pixelmator Proがv3.6.8でHDR画像をサポート

Posted on 9月 1, 2024 by Takaaki Naganoya

Pixelmator Proがv3.6.8でHDR画像のサポートを追加しました。

Pixelmator Pro 3.3.13–> 3.6.8

AppleScript用語辞書の比較で確認された変化は以下のとおりです。

・予約語「JPEG」の類義語として「JPG」を追加定義
・HDR画像の予約語を追加(OpenExr、HDR JPEG、HDR HEIC、HDR AVIF、HDR PNG)
・applicationのプロパティとして「load hdr content」を新設
・documentのプロパティとして「display hdr content」を新設

HDR対応について

Appleの公式資料によれば、現行機種はHDRに対応しているとのこと。

ただし、接続しているディスプレイによって、

「このディスプレイはHDRコンテンツをサポートしていません」(Mac mini M1+Apple Cinema Display)
「このディスプレイはHDRコンテンツのサポートが制限されています」(MacBook Air M2)

といったように、非対応/対応(不完全対応を含む)と状態が分かれるようです。

対応環境でPixelmator ProのHDRサポート状態を変更してHDR画像をオープンする実験は行なってみました。


▲Pixelmator Proの設定ウィンドウ HDRコンテンツのサポートが制限されている(MacBook Air M2)と表示


▲Pixelmator ProでサンプルのHDR JPEGをオープンしたところ

AppleScript名:HDR画像をオープン
tell application "Pixelmator Pro"
  set load hdr content to true
  
set aHDR2 to load hdr content
  
–> true
  
if aHDR2 = false then return
  
  
set aHDRfile to choose file
  
  
open aHDRfile
  
end tell

★Click Here to Open This Script 

HDR画像をオープンしても、HDR表示が行われるかどうかは別の管理になっている(documentのプロパティ)ので、そこも設定する必要があるようです。変更すると画面上でわずかに階調表現に変化が見られました(ちょっとだけ)。

AppleScript名:オープン中のHDR画像をHDR表示する
tell application "Pixelmator Pro"
  –環境チェック
  
set appHDR to load hdr content
  
if appHDR = false then return
  
  
–HDR画像の表示状態を変更
  
tell front document
    set display hdr content to true
    
set docHDR to display hdr content
  end tell
end tell

★Click Here to Open This Script 

Posted in Image Object control | Tagged 13.0savvy 14.0savvy 15.0savvy Pixelmator Pro | Leave a comment

メキシカンハットの描画

Posted on 6月 28, 2024 by Takaaki Naganoya

X(旧称Twitter)の一部で流行っている、むかーーしむかしのBASIC処理サンプルの1つ、メキシカンハット型グラフの描画AppleScriptです。

–> Download full script bundle with libraries

自分もChipmunk BASIC用に移植して投稿していたのですが、AppleScriptにフル書き換えするとどんなもんだと思い、書いてみました。

関数演算ライブラリは、自作のcalcLibASがあるので、これを使い、画像のダイアログ表示用ライブラリを使って画面表示。

AppleScriptでも1秒ぐらいで処理が終了してしまいますが、黒地に緑で描画すると、謎の「味」があります。

AppleScript名:メキシカンハット v2.scptd
— Created 2024-06-28 by Takaaki Naganoya
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use mLib : script "calcLibAS"
use imgDispLib : script "imageDisplayLib"

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 NSBitmapImageRep : a reference to current application’s NSBitmapImageRep

–パラメータから下地になる画像を作成する
set aSize to current application’s NSMakeSize(300, 300)
set anImage to NSImage’s alloc()’s initWithSize:aSize
set backlColor to (NSColor’s colorWithCalibratedRed:0.0 green:0.0 blue:0.0 alpha:1.0)
set anImage to drawImageWithColorFill(anImage, {0, 0, 300, 300}, backlColor) of me

–描画色
set drawColor to (NSColor’s colorWithCalibratedRed:0.0 green:1.0 blue:0.0 alpha:1.0)

–Mexican Hat
set D to {}
set rDnum to pi / 180

repeat 256 times
  set end of D to 100
end repeat

repeat with y from -180 to 180 by 6
  repeat with x from -180 to 180 by 4
    set u to 120 + (x / 3) – (y / 6)
    
if u < 0 or u ≥ 240 then
      —
    else
      set r to rDnum * (sqrt ((x ^ 2) + (y ^ 2)))
      
set z to 100 * (cos (r – 30)) * (cos (3 * r))
      
set v to 40 – y / 6 – z / 2
      
      
if (item u of D) > v then
        set anImage to psetOnImage(anImage, {u, 256 – v}, drawColor) of me
        
copy v to (item u of D)
      end if
    end if
  end repeat
end repeat

–結果表示
dispImage(anImage, "Mexican Hat") of imgDispLib

on psetOnImage(anImage, posDat, fillColor)
  set retinaF to (NSScreen’s mainScreen()’s backingScaleFactor()) as real
  
–>  2.0 (Retina) / 1.0 (Non Retina)
  
  
anImage’s lockFocus() –描画開始
  
  
set origX to (item 1 of posDat) / retinaF
  
set origY to (item 2 of posDat) / retinaF
  
set sizeX to (1) / retinaF
  
set sizeY to (1) / retinaF
  
  
set theRect to {{x:origX, y:origY}, {width:sizeX, height:sizeY}}
  
  
set theNSBezierPath to NSBezierPath’s bezierPath
  (
theNSBezierPath’s appendBezierPathWithRect:theRect)
  
  
fillColor’s |set|() –色設定
  
theNSBezierPath’s fill() –ぬりつぶし
  
  
anImage’s unlockFocus() –描画ここまで
  
  
return anImage –returns NSImage
end psetOnImage

on drawImageWithColorFill(anImage, drawList, fillColor)
  set retinaF to (NSScreen’s mainScreen()’s backingScaleFactor()) as real
  
–>  2.0 (Retina) / 1.0 (Non Retina)
  
  
anImage’s lockFocus() –描画開始
  
  
set origX to (item 1 of drawList) / retinaF
  
set origY to (item 2 of drawList) / retinaF
  
set sizeX to (item 3 of drawList) / retinaF
  
set sizeY to (item 4 of drawList) / retinaF
  
  
set theRect to {{x:origX, y:origY}, {width:sizeX, height:sizeY}}
  
  
set theNSBezierPath to NSBezierPath’s bezierPath
  (
theNSBezierPath’s appendBezierPathWithRect:theRect)
  
  
fillColor’s |set|() –色設定
  
theNSBezierPath’s fill() –ぬりつぶし
  
  
anImage’s unlockFocus() –描画ここまで
  
  
return anImage –returns NSImage
end drawImageWithColorFill

★Click Here to Open This Script 

Posted in 3D dialog Image | Tagged 13.0savvy 14.0savvy 15.0savvy | Leave a comment

アプリケーション操作の次の段階へ

Posted on 1月 28, 2024 by Takaaki Naganoya

GUIアプリケーションの操作において、若干の不満を覚えつつもmacOS上のGUIアプリケーションの操作を行えてきました。

ただ、「次」の段階が見えているのに、GUIアプリケーション側の機能がそれに追いついていなかったり、未実装の部分があったりで、GUIアプリケーション側が足を引っ張っているように見える今日このごろです。

たとえばKeynoteにおいて、特定のグラフィックだけを削除したい(会社ロゴなど)という場合に、メニューに「この部品に近似する部品を削除」といった機能が実装されていてもよさそうな昨今ですが、それはありません。「類似画像を削除」「類似部品を削除」といった処理はやりたくなる部分だと(勝手に)考えるものです。だいたい、OS内の機能を見ても容易に実装できそうに見えます。

Keynote書類にはimageオブジェクトが用意されており、さまざまなプロパティを取得できるようになっていますが、file nameは取得できても、

file属性を取得できない状態です。

AppleScript名:画像からfile属性を取得(できない).scpt
tell application "Keynote"
  tell front document
    set aSel to selection
    
set aaSel to first item of aSel
    
    
set aFile to file of aaSel
    
–> error "Keynoteでエラーが起きました: AppleEventのハンドラで誤りが起きました。" number -10000
  end tell
end tell

★Click Here to Open This Script 

iCloud上に存在するKeynote書類の内部ファイルに対してのパスを表現しづらい、といった理由は理解できるかもしれませんが、用語辞書にfile属性が取れると明記してある以上、file属性は(ローカルに書類が存在するなどの条件下では)取得できるべきだと考えます。

そして、file属性(おそらく、file pathをalias形式で取得できる)を取れれば、画像の「内容」にもアクセスして、「指定の画像に近似するものを削除」といった処理はできるはずです(画像のハッシュ値を計算する処理は別途する必要はあるわけですが)。

このあたりの処理が、そろそろできてもいいんですが、いろいろ邪魔が入ってできないのが残念な感じがします。

Posted in Image | Tagged 13.0savvy 14.0savvy Keynote | Leave a comment

指定画像をbase64エンコード文字列に変換→デコード

Posted on 7月 29, 2023 by Takaaki Naganoya

指定画像をbase64でエンコードしたのちに、デコードして画像に戻すAppleScriptです。

base64文字列からのデコードだけをテストしたかったのですが、テストのために本来は不要な画像のエンコード部分を付け足しています。

macOS 13.5上で動作確認していますが、OSのバージョンやAppleScriptのバージョンに依存はしないことでしょう。

AppleScript名:指定画像をbase64エンコード文字列に変換→デコード.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2023/07/29
—
–  Copyright © 2023 Piyomaru Software, All Rights Reserved
—
property NSData : a reference to current application’s NSData
property NSString : a reference to current application’s NSString
property NSImage : a reference to current application’s NSImage
property NSPNGFileType : a reference to current application’s NSPNGFileType
property NSBitmapImageRep : a reference to current application’s NSBitmapImageRep
property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding
property NSDataBase64EncodingEndLineWithLineFeed : a reference to current application’s NSDataBase64EncodingEndLineWithLineFeed

use AppleScript version "2.8" — macOS 12 or later
use framework "Foundation"
use scripting additions

set aFile to choose file of type {"public.image"}
set aStr to base64StringFromImageFile(aFile) of me
–> "iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAKuWlDQ1BJQ0MgU……"

set aImage to decodeImageFromBase64String(aStr) of me
–> (NSImage)

–Base64 Decode
on decodeImageFromBase64String(aString)
  set restoreData to NSData’s alloc()’s initWithBase64EncodedString:aString options:0
  
set restoreImage to NSImage’s alloc()’s initWithData:restoreData
  
return restoreImage
end decodeImageFromBase64String

–Base64 Encode
on base64StringFromImageFile(aFile)
  set aPOSIX to POSIX path of aFile
  
set anImage to NSImage’s alloc()’s initWithContentsOfFile:aPOSIX
  
set imageRep to NSBitmapImageRep’s alloc()’s initWithData:(anImage’s TIFFRepresentation())
  
set aPNGdat to imageRep’s representationUsingType:(NSPNGFileType) |properties|:(missing value)
  
set base64Str to aPNGdat’s base64EncodedDataWithOptions:(NSDataBase64EncodingEndLineWithLineFeed)
  
set bStr to (NSString’s alloc()’s initWithData:base64Str encoding:(NSUTF8StringEncoding))
  
return bStr as string –or return NSString (delete as string) for speedy processing
end base64StringFromImageFile

★Click Here to Open This Script 

Posted in Image Text | Tagged 12.0savvy 13.0savvy | Leave a comment

Pixelmator Proで2つの書類のレイヤー表示状態をシンクロ

Posted on 6月 6, 2023 by Takaaki Naganoya

Pixelmator Pro上でオープン中の2つの書類のレイヤー表示状態をシンクロさせるAppleScriptです。

ちょうど、「ゆっくりAppleScript解説」の続刊を作成中で、レイヤー別に部品が分かれている書類(すべてのレイヤー名は同じ)の表情を「同じ状態」にするのが面倒です。

正直なところ、表情名を入力すると該当するレイヤーを表示状態にしてほしいぐらいです。

そこまで行かないにせよ、1つの書類に対して行ったレイヤー表示操作を、もう一度別の書類に対して行わなくてはならないのは大変です(2つの書類を統合して、キャラクター別の差異をレイヤーで吸収するという手もありますが、、、)。

そこで、2つの書類をオープンしておき、最前面の書類のレイヤー表示状態(=表情の操作)を他方の書類に反映させるAppleScriptを書いてみました。

Pixelmator Proバージョン3.3.6に対してレイヤーの取得を指令してみましたが、なかなか大変です。再帰処理で一番上から末端まで、表示状態になっているレイヤーだけを抽出できるかと考えていたのですが、そうもいきません。

再帰処理がダメなので、もうレイヤー名を決め打ちで指定するようにして(つまり、この用途以外には使えないものと割り切って)、各レイヤーグループ内を走査するように記述しました。

AppleScript名:同一名、同一構造の2つの書類のレイヤー表示状況をシンクロ.scpt
—
–  Created by: Takaaki Naganoya
–  Created on: 2023/06/06
—
–  Copyright © 2023 Piyomaru Software, All Rights Reserved
—

use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

tell application "Pixelmator Pro"
  set allD to {}
  
  
set dList to name of every document
  
–> {"ゆっくり素材れいむ.pxd", "ゆっくり素材まりさ.pxd"}
  
  
tell front document
    set d1Name to name of it
    
if d1Name contains "れいむ" then
      set d2Name to retAnItemByCond(dList, "れいむ") of me
    else
      set d2Name to retAnItemByCond(dList, "まりさ") of me
    end if
    
    
tell layer "root"
      tell layer "顔"
        set dList to every layer
        
repeat with i in dList
          set j to contents of i
          
tell j
            set ddList to (name of every layer whose visible is true)
            
if ddList is not equal to {} then
              set aCon to contents of first item of ddList
              
set the end of allD to {"root", "顔", name of j, aCon}
            end if
          end tell
        end repeat
      end tell
    end tell
  end tell
  
  
tell document d2Name
    repeat with i in allD
      copy i to {L1, L2, L3, L4}
      
tell layer L3 of layer L2 of layer L1
        set tmpL to name of every layer
        
repeat with ii in tmpL
          set jj to contents of ii
          
tell layer jj
            if jj = L4 then
              set visible to true
            else
              set visible to false
            end if
          end tell
        end repeat
      end tell
    end repeat
  end tell
end tell

on retAnItemByCond(aList, aParam)
  repeat with i in aList
    set j to contents of i
    
    
if j does not contain aParam then
      return j
    end if
  end repeat
end retAnItemByCond

★Click Here to Open This Script 

Posted in Image | Tagged 11.0savvy 12.0savvy 13.0savvy Pixelmator Pro | Leave a comment

Keynoteでオープン中の書類をすべてデスクトップにPDF書き出しして最初のページをJPEG画像化

Posted on 10月 15, 2022 by Takaaki Naganoya

Keynoteでオープン中の書類すべてをPDF書き出しして、各PDFの最初のページをJPEG画像に書き出すAppleScriptです。書き出し先はデスクトップフォルダです。Keynote v12.1+macOS 12.6.1で動作確認しています。

それぞれ、PDF書き出しするScriptと、PDFをJPEGに変換するAppleScriptは個別に書いて使っていたのですが、処理数が増えるといちいち複数のScriptをかわるがわる実行するのも面倒に。

そこで、PDF書き出し→JPEG変換を行うものを作ってみました。作ったみたといっても、部品はすでに存在していたので繋ぎ合わせただけです。

AppleScript名:すべてデスクトップ上にPDF出力し、最初のページをJPEG出力.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2022/10/14
—
–  Copyright © 2022 Piyomaru Software, All Rights Reserved
—

use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property NSString : a reference to current application’s NSString
property NSFileManager : a reference to current application’s NSFileManager
property NSOrderedSame : a reference to current application’s NSOrderedSame

set outPathList to {}

tell application "Keynote"
  set allDocs to every document
  
if allDocs = {} then return
  
  
repeat with i in allDocs
    set j to contents of i
    
set dRes to exportKeynoteDocToPDF(j) of me
    
set pdfPath to (POSIX path of dRes)
    
set pdfPath to chkExistPOSIXpathAndIncrementChildNumberFull(pdfPath) of me
    
set jRes to (my jpegFromPath:(pdfPath) compressFactor:1.0)
    
set the end of outPathList to jRes
  end repeat
end tell

return outPathList

–Keynote書類からPDF書き出し
on exportKeynoteDocToPDF(targKeynoteDoc)
  
  
tell application "Keynote"
    set dCount to count every document
    
if dCount = 0 then
      –オープン中のKeynote書類がない場合はリターン
      
return false
    end if
    
    
set aPath to file of targKeynoteDoc
  end tell
  
  
set tmpPath to (path to desktop) as string
  
set curPath to (NSString’s stringWithString:(POSIX path of aPath))’s lastPathComponent()’s stringByDeletingPathExtension()’s stringByAppendingString:".pdf"
  
set outPath to (tmpPath & curPath)
  
set outPath to chkExistPOSIXpathAndIncrementChildNumberFull(outPath) of me
  
–do shell script "touch " & quoted form of POSIX path of outPath –Error 6を回避するための記述
  
  
tell application "Keynote"
    –set anOpt to {class:export options, export style:IndividualSlides, all stages:false, skipped slides:true, PDF image quality:Good}
    
–set anOpt to {class:export options, export style:IndividualSlides, all stages:false, skipped slides:true, PDF image quality:Better}
    
set anOpt to {class:export options, export style:IndividualSlides, all stages:false, skipped slides:true, PDF image quality:Best}
    
export targKeynoteDoc to POSIX file outPath as PDF with properties anOpt
  end tell
  
  
return ((POSIX file outPath) as alias)
end exportKeynoteDocToPDF

on jpegFromPath:imagePath compressFactor:compFactor — 0.0 = max compression, 1.0 = none
  — build destination path
  
set pathNSString to current application’s NSString’s stringWithString:imagePath
  
set destPath to pathNSString’s stringByDeletingPathExtension()’s stringByAppendingPathExtension:"jpg"
  
  
— load the file as an NSImage
  
set theImage to current application’s NSImage’s alloc()’s initWithContentsOfFile:imagePath
  
if theImage = missing value then return false
  
  
set theData to theImage’s TIFFRepresentation()
  
set newRep to current application’s NSBitmapImageRep’s imageRepWithData:theData
  
set theData to (newRep’s representationUsingType:(current application’s NSJPEGFileType) |properties|:{NSImageCompressionFactor:compFactor, NSImageProgressive:false})
  
  
set theResult to (theData’s writeToFile:destPath atomically:true) as boolean
  
return destPath as string
end jpegFromPath:compressFactor:

–POSIX path stringを与えると、ファイル名の重複を検出して、ファイル名の名称回避を行って、ファイル名のみを返す
on chkExistPOSIXpathAndIncrementChildNumberFull(a)
  set aa to POSIX path of a
  
set aStr to NSString’s stringWithString:aa
  
set bStr to aStr’s lastPathComponent()
  
  
set cStr to (bStr’s pathExtension()) as string
  
set dStr to (bStr’s stringByDeletingPathExtension()) as string
  
set eStr to (aStr’s stringByDeletingLastPathComponent()) as string
  
  
set aManager to NSFileManager’s defaultManager()
  
set aRes to (aManager’s fileExistsAtPath:aStr) as boolean
  
if aRes = false then return aa
  
  
set hitF to false
  
repeat with i from 1 to 65535
    
    
set tmpPath to (eStr & "/" & dStr & "_" & (i as string) & "." & cStr)
    
set tmpStr to (NSString’s stringWithString:tmpPath)
    
set aRes to (aManager’s fileExistsAtPath:tmpStr) as boolean
    
set bRes to ((tmpStr’s caseInsensitiveCompare:eStr) is not equal to (NSOrderedSame)) as boolean
    
    
if {aRes, bRes} = {false, true} then
      set hitF to true
      
exit repeat
    end if
    
  end repeat
  
  
if hitF = false then return false
  
  
–ファイルパス(フルパス)を返す
  
return (tmpStr as string)
end chkExistPOSIXpathAndIncrementChildNumberFull

★Click Here to Open This Script 

Posted in Image PDF | Tagged 12.0savvy Keynote | Leave a comment

Safariで表示中のYouTubeムービーのサムネイル画像を取得

Posted on 5月 9, 2022 by Takaaki Naganoya

Safariで表示中のYouTubeムービーのサムネール画像を取得、保存、表示するAppleScriptです。

YouTubeのムービーのサムネール画像の取得方法を確認し、動作確認用にダイアログ表示+画像保存の機能を追加したものです。Script Debugger上で動かしている分には、NSImageの内容を結果表示ビューワで自動表示されますが、ない人向けに付けた機能です。

画像自体は、「ピクチャ」フォルダにUUIDつきでPNG形式で保存します。

–> Download Script bundle with Library

掲載リストには、画像表示ライブラリが含まれていないため、そのままでは実行できません。上記のScript Bundleをダウンロードして実行する必要があります。

AppleScript名:Safariで表示中のYouTubeムービーのサムネイル画像を取得.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2022/05/09
—
–  Copyright © 2022 Piyomaru Software, All Rights Reserved
—

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use imgLib : script "imageDisplayLib"

property NSUUID : a reference to current application’s NSUUID
property |NSURL| : a reference to current application’s |NSURL|
property NSString : a reference to current application’s NSString
property NSImage : a reference to current application’s NSImage
property NSPNGFileType : a reference to current application’s NSPNGFileType
property NSURLComponents : a reference to current application’s NSURLComponents
property NSBitmapImageRep : a reference to current application’s NSBitmapImageRep
property NSMutableDictionary : a reference to current application’s NSMutableDictionary

tell application "Safari"
  tell front document
    try
      set aURL to URL
    on error
      set aURL to "https://www.youtube.com/watch?v=_fmDtIV9vvI"
    end try
  end tell
end tell

if aURL does not start with "https://www.youtube.com/watch?" then return

set urlDict to parseURLParamsAsDict(aURL) of me
set aParam to urlDict’s valueForKey:"v"
if aParam = missing value then return

set imgURL to "https://i1.ytimg.com/vi/" & (aParam as string) & "/mqdefault.jpg"
set newURL to |NSURL|’s URLWithString:imgURL
set aImg to NSImage’s alloc()’s initWithContentsOfURL:newURL

set imgPath to (POSIX path of (path to pictures folder) & ((aParam as string) & "_") & (NSUUID’s UUID()’s UUIDString()) as string) & ".png"

–Save
saveNSImageAtPathAsPNG(aImg, imgPath) of me

–Display
dispImage(aImg, "YouTube thumbnail") of imgLib

on parseURLParamsAsDict(aURL)
  set components to NSURLComponents’s alloc()’s initWithString:aURL
  
set qList to (components’s query())’s componentsSeparatedByString:"&"
  
  
set paramRec to NSMutableDictionary’s dictionary()
  
  
repeat with i in qList
    set keyAndValues to (i’s componentsSeparatedByString:"=")
    (
paramRec’s setObject:(keyAndValues’s objectAtIndex:1) forKey:(keyAndValues’s objectAtIndex:0))
  end repeat
  
  
return paramRec
end parseURLParamsAsDict

–NSImageを指定パスにPNG形式で保存
on saveNSImageAtPathAsPNG(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))
  
set aRes to (myNewImageData’s writeToFile:newPath atomically:true) as boolean
  
  
return aRes –成功ならtrue、失敗ならfalseが返る
end saveNSImageAtPathAsPNG

★Click Here to Open This Script 

Posted in Image Record Text URL | Tagged 10.14savvy 10.15savvy 11.0savvy 12.0savvy Safari | Leave a comment

SF Symbolsを名称で指定してPNG画像化

Posted on 4月 15, 2022 by Takaaki Naganoya

SF Symbolsに収録されている文字を、名称で指定してデスクトップにPNG画像で書き出すAppleScriptです。

同フォントは、アプリ上のアイコン素材3,300個以上をフォント化し、再利用しやすくすることで、アイコンで何かの意図を示すことを規格化したいという、現代における象形文字の再発明みたいな存在です。

文化や人種を超えた、非言語コミュニケーションを促進するための基盤としてAppleが整備を行なっているものなんでしょう。文化を縦断したインフラみたいな。

アイコン素材を自分で作るのはつらいので、正直助かっています。Appleが配布しているSF Symbols 3アプリケーションを使って画面上でいろいろ探して、文字を指定できます。

一応、SF Symbols.app自体にも指定フォントを画像化する機能はついているのですが、レンダリング時の指定解像度が低すぎて、プレゼン資料や本のイラストとして利用するには不便すぎます(本来の利用目的である、タブバーのアイコンに指定するのには向いている解像度なんでしょうけれども)。

そこで、指定のフォントの文字を名称で指定するとPNG画像にレンダリングするAppleScriptを作成してみました。

文字を指定するのはできているのですが、フォントのファミリーとかマルチカラーとかの指定の方法がよくわかりません。

AppleScript名:SF Symbolsを名称で指定してPNG画像化 v1a.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2022/04/14
—
–  Copyright © 2022 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.8" — Monterey (12) or later
use framework "Foundation"
use framework "AppKit"
use framework "QuartzCore"
use scripting additions

set aName to "paperplane.circle.fill"
set anImage to current application’s NSImage’s imageWithSystemSymbolName:(aName) accessibilityDescription:(missing value)
set resImg to resizeNSImage(anImage, 50.0) of me

set aDesktopPath to current application’s NSString’s stringWithString:(POSIX path of (path to desktop))
set savePath to aDesktopPath’s stringByAppendingString:((current application’s NSUUID’s UUID()’s UUIDString())’s stringByAppendingPathExtension:"png")

set fRes to saveNSImageAtPathAsPNG(resImg, savePath) of me

on resizeNSImage(aSourceImg, aScale)
  set aSize to aSourceImg’s |size|()
  
set newWidth to (width of aSize) * aScale
  
set newheight to (height of aSize) * aScale
  
  
set targFrame to current application’s NSMakeRect(0, 0, newWidth, newheight)
  
set targImage to current application’s NSImage’s alloc()’s initWithSize:{newWidth, newheight}
  
  
set aKey to {current application’s NSImageHintInterpolation}
  
set aObj to current application’s NSNumber’s numberWithInt:(current application’s NSImageInterpolationLow)
  
set hintRec to current application’s NSDictionary’s dictionaryWithObject:aObj forKey:aKey
  
  
targImage’s lockFocus()
  
aSourceImg’s drawInRect:targFrame fromRect:(current application’s NSZeroRect) operation:(current application’s NSCompositeCopy) fraction:1.0 respectFlipped:true hints:hintRec
  
targImage’s unlockFocus()
  
  
return targImage
end resizeNSImage

–NSImageを指定パスにPNG形式で保存
on saveNSImageAtPathAsPNG(anImage, outPath)
  set imageRep to anImage’s TIFFRepresentation()
  
set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:imageRep
  
set pathString to current application’s NSString’s stringWithString:outPath
  
set newPath to pathString’s stringByExpandingTildeInPath()
  
set myNewImageData to (aRawimg’s representationUsingType:(current application’s NSPNGFileType) |properties|:(missing value))
  
set aRes to (myNewImageData’s writeToFile:newPath atomically:true) as boolean
  
return aRes –成功ならtrue、失敗ならfalseが返る
end saveNSImageAtPathAsPNG

★Click Here to Open This Script 

Posted in Font Image | Tagged 11.0savvy 12.0savvy SF Symbols | Leave a comment

Post navigation

  • Older posts

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

Google Search

Popular posts

  • 開発機としてM2 Mac miniが来たのでガチレビュー
  • CotEditorで2つの書類の行単位での差分検出
  • macOS 13.6.5 AS系のバグ、一切直らず
  • macOS 15, Sequoia
  • 初心者がつまづきやすい「log」コマンド
  • 指定のWordファイルをPDFに書き出す
  • Pages本執筆中に、2つの書類モード切り替えに気がついた
  • Adobe AcrobatをAppleScriptから操作してPDF圧縮
  • メキシカンハットの描画
  • 与えられた文字列の1D Listのすべての順列組み合わせパターン文字列を返す v3(ベンチマーク用)
  • 2023年に書いた価値あるAppleScript
  • Pixelmator Pro v3.6.4でAppleScriptからの操作時の挙動に違和感が
  • Numbersで選択範囲のセルの前後の空白を削除
  • AdobeがInDesign v19.4からPOSIX pathを採用
  • Safariで「プロファイル」機能を使うとAppleScriptの処理に影響
  • Cocoa Scripting Course 続刊計画
  • AppleScriptによる並列処理
  • macOS 14.xでScript Menuの実行速度が大幅に下がるバグ
  • NaturalLanguage.frameworkでNLEmbeddingの処理が可能な言語をチェック
  • AppleScript入門③AppleScriptを使った「自動化」とは?

Tags

10.11savvy (1102) 10.12savvy (1243) 10.13savvy (1392) 10.14savvy (587) 10.15savvy (438) 11.0savvy (283) 12.0savvy (212) 13.0savvy (188) 14.0savvy (138) 15.0savvy (116) CotEditor (64) Finder (51) iTunes (19) Keynote (115) NSAlert (61) NSArray (51) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (53) NSDictionary (28) NSFileManager (23) NSFont (21) NSImage (41) NSJSONSerialization (21) NSMutableArray (63) NSMutableDictionary (22) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (119) NSURL (98) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (75) Pages (54) Safari (44) Script Editor (27) 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
  • check sum
  • 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)
  • 未分類

アーカイブ

  • 2025年2月
  • 2025年1月
  • 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