mieki256's diary



2026/03/01() [n年前の日記]

#1 [nitijyou] ネジを外す方法について調べてる

ネジ穴が潰されてしまったネジを外す方法について調べてる。

専用工具があるらしいけれど、今回の対象は電気カミソリの尻のあたりで使われているネジなので、かなり小さい。大き目のネジであれば、金槌で叩いてネジ穴っぽい凹みをつける器具があるらしいけれど…。

以下の工具が使えるのではないかなと検討中。

_なめた精密ネジはずし +0ネジ用(M1〜2.6) | ANEXブランドのドライバー・工具メーカー アネックスツール(株)

メガネのネジにも使えるとアピールする写真が載っているぐらいなので、電気カミソリのソレにも使えるのではないかなあと…。

レビュー動画も眺めてみたけれど、かなり小さいネジを外すことができているので、これでどうにかなるのではないかと期待してしまう…。もっとも、かなり時間はかかるようだけど。

_なめたM.2固定用ねじを外す!(アネックス なめた精密ネジはずし) - YouTube
_RTX3090のネジがなめた【なめた精密ネジはずし】で勝てるのか? - YouTube
_完全になめて引っ掛かりが無くなったネジを回す(なめた精密ねじ外し-2,3本目) - YouTube

最悪、ネジの頭が全部削れてしまっても構わない。そういう状態になればパーツがスポンと抜けるだろうから…。

別の方法 :

ネジ穴が少しでも残っているなら、摩擦抵抗を増やすことでどうにかできそうでもある…。

_ボンド ネジやま救助隊ネジはずし|ボンド商品情報|コニシ株式会社
_セリアで見つけた『ネジはずしサポート』を使ってみる。 : DIYで作る こどもと過ごすおうち時間

昔は100円ショップで売ってた時期もあるらしい。今もあるのだろうか…。無さそうだな…。100円ショップの商品は一期一会だから…。

#2 [anime] 「ルパン三世VS名探偵コナン THE MOVIE」を視聴

BS12で放送されていたので視聴。TVSP「ルパン三世VS名探偵コナン」が人気を得たので劇場版も制作、という流れだろうか。

以前も視聴した記憶があるのだけど、改めて見るとコラボ企画としてよく出来てるなと…。色々なキャラの見せ場をちゃんと用意して、台詞もそのキャラらしさを意識して、話も一本筋が通っていて…。お祭り企画ではあるのだろうけど、実によく出来てる…。

Wikipediaの記述を見ると、コナンの原作者の青山先生も色々な部分で制作に絡んでたらしい。脚本を担当した前川淳さんも1年かけて脚本を練ったと言及してたそうで…。モンキーパンチ先生からキャラをお借りさせていただくのだから、それなりにちゃんとしたものを作らないといかんだろうし気合いは入るわな…。

それはさておき。ルパンVSキッドは何時頃作られるのだろう…。なんちてぽっくん。

#3 [nitijyou] 日記をアップロード

2025/12/31を最後に日記をアップロードしてなかったのでアップロードしておいた。

2026/03/02(月) [n年前の日記]

#1 [nim] Nim言語について少し調べていた

Nim言語というプログラミング言語がある。少し調べてた。

Pythonに近いわけではなかった :

Nim用のソースコードはインデントでプログラムの構造化を実現しているので、一見するとPythonに近い言語なのかなと今まで思い込んでしまっていたのだけど。

よく調べてみると、そういうわけではなかった…。Nimを開発するにあたって影響を受けた言語リスト、なるものがあって、それを眺めると Pascal系の言語のほうが多く、Python からはほんのちょっとしか影響を受けてなかった。たしかにあちこちの仕様を眺めると、これは Pascal っぽいなあ、と思えてきた。どこがどうとは言えないけれど…。

まあ、インデントで構造を示す Python のソレが強烈過ぎるということでもあるのかな…。何かの拍子にインデントがごっそり無くなるだけで全く使えないソースコードになってしまうあたり、Python って独特過ぎる…。だから、インデントが活用されているだけで「ああ、これってPythonっぽいね」と勘違いしてしまうのは仕方ないのかも…。

GLFWはどれを使えばいいのか :

NimでOpenGLは使えるのかどうかが気になってググっていた。OpenGL自体は公式がメンテナンスしているライブラリがあるらしい。ただ、ウインドウ関係を出してくれる GLFW はどれを使えばいいのかよく分からず…。

昔は NimGL なるものがあって、その中に GLFW があったらしいけど、もう NimGL は使われてないという言及も目にしてしまって…。だとすると、GLFW を使いたい時は何が使われてるんだろう…。

もっとも、GLFW を使うとなると Windowsの場合は .dll もアプリと同梱しないといけないことになるのかな…? それとも .exe の中に内包できるのだろうか? よく分からん…。.exe 1つで動く状態にしたいけれど、そんなことできるのかな…。

#2 [anime] 「魔術師クノンは見えている」の演出は上手い

思考メモ。

TVアニメ「魔術師クノンは見えている」を視聴しているのだけど、演出が上手いなと思ったのでメモしておく。

このアニメ、予算やスケジュールが厳しいのか、作画面に関しては大変失礼ながら何一つ褒めるところがないのだけど…。原画からして海外スタジオにお願いしてる回もあるし…。

ただ、演出が上手い。とにかく上手い。惚れ惚れするほどの上手さ。

各話演出を担当してる方が上手いのか、それとも監督さんが指示を出して調整して良くなってるのか、あるいは編集さんあたりが勝手にアレコレやってイイ感じになってるのか分からないのだけど、とにかく上手いなと感心しております。

事例 :

例えば昨晩見た回では…。

学院への入学試験(?)のシーン。先生役がスゴイ魔法を出して、「さあ、この魔法を打ち破って見せなさい」と言いつつ、その際バックでは不穏なBGMが流れているのだけど。カットが切り替わると主人公が 「えっ。そんな試験でいいんですか?」とあっさり言い放ち、今まで流れていた不穏なBGMがスパッと切られてBGM無しになる。

教室内で同期の女子にアプローチをかけてる主人公のシーン。バックではほんわかしたBGMが流れているのだけど。ロッテンマイヤーさん的な女性教師が「呼ばれてるんだから早くしなさい」と言うと同時にそのほんわかBGMがスパッと無くなる。

学院の偉い人との面接シーン。主人公に多少興味を持った凄そうな魔術師が「なんなら私が色々教えてやっても良いぞ…」と言ってる途中なのに主人公が 「じゃあ面接終わったみたいなんで僕帰りますね」とさっさとドアを閉めて行ってしまう。

これは一つか二つ前の回だけど、店内・店主の前で、水で色んな形状を作れる能力を披露した主人公に対し、店主がちょっと恥ずかしそうに 「もしかして…人間の女性の形も作れたり…?」と尋ねようとしたその瞬間に主人公の御付きのメイドが鬼のような形相+めっちゃ早口で 「貴方子供の前で一体何を言い出すんですか!」と相手の言葉を遮る。

いくら言葉で説明してみても実際に映像を見てもらわないと全然ピンとこないだろけど…。とにかくタイミングが絶妙…。ツッコミやボケが入る、そのタイミングだけでついつい笑ってしまう。

この演出家さん、「娯楽映像作品とは時間の制御で見世物に仕立てていくもの」ということをよく分かってらっしゃる…。このあたり、ずっと同じペースでダラーッと流し続けて、せっかく脚本に盛り込んであったボケやツッコミを全て台無しにしちゃう演出家が大半なのに…。この演出家さんは分かってる。ちゃんと分かってる。素晴らしい。

BGMの使い方も上手い。「音楽には場の空気を支配する力がある」から映像作品でも頻繁に活用されるわけだけど。一般的にはそのまま流し続けて雰囲気を醸し出していくテンプレパターンに陥ってしまいそうなところでわざとスパッと切って無音にして冷や水を浴びせてくるというか。こちらの予想を裏切ってくる使い方。そこには飛躍もあるし、コントラストもあるので、これまたついつい笑ってしまう。アニメは総合芸術なのだ、音楽の使い方は武器になるのだということをよく分かってらっしゃる…。

もちろん、こういった見せ方は件のアニメだけがやってるわけでもなく、分かってる演出家さんなら当たり前のようにちょくちょく使ってる手管だったりするのだけど…。テンプレ演出しか出してこない、単に不勉強なのか、それとも全然考えてないのか、スケジュールに追われてそれどころじゃないのか、見ていて首を捻ってしまう演出家さんも結構見かけるわけで…。

まあ、作画面がアレだから、その分演出の上手さが光って見えるという面もあるのだろうけど…。上手いものは上手い。しかも、どのシーンも只の会話のやり取りに過ぎないし、顔芸の類を見せているわけでもないのに、ちゃんと笑わせてくるのだから…。上手いなあ…。

この演出家さんが奇面組リメイク版も担当してくれていたら良かったのになあ…。作画のクオリティは全く同じでも、もうちょっと笑えるアニメになってたんじゃないか…。いや、アレはギャグの種類が違うからちょっとやそっとじゃどうにもならないか…。ダウンタウンの松本氏が「飛躍し過ぎると客がついてこれなくて笑いに繋がらない」と言ってたらしいけど、奇面組のソレはカットが切り替わるたびに前後を無視したネタが盛り込まれるだけだから飛躍を通り越して単に無意味に断絶してるというか…。ここぞというタイミングを一切見定めることなく脈絡のない一発ギャグのみを延々披露し続ける芸人さんが居たとして、はたしてそれは笑えるのかどうか? という…。 *1

BGMの使い方云々 :

BGMの使い方云々でふと思い出したのでメモ。昔、何かのTVアニメで、BGMの使い方に感心した記憶があって…。

男性主人公がそうとは知らずに女性用露天風呂に入ってしまって、のんびり湯に浸かっていたら後から女性客の集団がワラワラと入ってきて思わず岩陰に隠れてしまうという、漫画やアニメでは散々見せられてきたあるあるなシチュエーションで…。ただ、ちょっとした工夫で印象が随分変わっていた。

女性客が談笑しているカットでは、明るくて楽し気で平和的なBGMが流れているのだけど。焦っている男性主人公のカットに切り替わると、まるで戦場にでも居るかのような非常に険しいBGMに切り替わって。また女性客のカットに戻ると平和なBGM。男性主人公のカットになると戦場BGM。それを何度か繰り返す、という…。

見ていて笑いながら唸ってしまった。このBGMの使い方は上手い…。なんというギャップ…。音楽は場の空気を支配する。場の空気を一変してしまう。その特性を活かして、こういう使い方もできるのかと…。飽きるほど見てきたシチュも、たったこれだけの工夫で笑えるシーンになるのだなと…。音楽の力ってスゴイ。いや、こういう使い方にちゃんと気づいて盛り込んでみせたこの演出家さんは偉い。素晴らしい。

これがまた、BGMがブツ切りで切り替わるあたりも上手かった、ような気がする。そのあたり記憶がちょっと定かではないけれど…。実は調整してあったのかもしれないけど…。

例えば映画音楽では、カットやシーンの内容に応じて曲調を変えるというのは比較的当たり前なので、カット毎に流れてる曲の雰囲気が違っているのは全然珍しくもなく…。例えば宮崎アニメも、音楽を担当してる久石譲さんが、横に置いてあるモニタに完成映像を映しながらタイミングを取りつつ指揮棒振ってオーケストラに演奏させて収録していたりするし…。

_劇伴(サウンドトラック)に15.73kHzが収録されている | 音響・映像・電気設備が好き

ただ、その場合、曲調が変わる瞬間も音楽としては一通り繋がってる感じになってしまうはずで…。

そういった事例と比べると、BGMがブツ切りで切り替わるというのは…。各キャラが、同じ時間、同じ場所に居ながら、しかしそれぞれ全く異なる心情が並列して発生しちゃってる感が、音楽の力でより強調されていた感じがするなと…。TVのリモコンのボタンを無造作に押して各チャンネルをザッピングしてるあの感覚に近いのだろうか。それぞれが繋がっていない、異なる流れが、並列してそこにまとまって存在してる感覚。

おそらく曲を作ったり演奏してる側からすれば「ブツ切りで切り替えるのは止めてくれ。それはダサい。カッコ悪い」「言ってくれればちゃんと曲として繋げながらキッチリ切り替わってる音源作りますよ」と言い出しそうな気もするけれど。映像作品に限っては、有無を言わせず曲がブツ切りで変わってしまったほうがより効果的だし、演出としてはそのほうが正解、という場面もあったりするのかもしれないなと…。 *2

このあたり、 _「床屋の満足」 がちょっと潜んでそうな気もする…。

思考メモです。オチは無いです。


*1: もっとも、ああいった構成の延長線上に ―― あの作品のアップデート版として不条理ギャグ漫画群の隆盛が位置しているようにも思うので、ギャグ漫画の歴史というか、変化と発展の流れを示す上ではけして無視できない重要な作品ではなかろうかとも思っているけれど、逆に言えば発展途上中の作品とも言えてしまうわけで、そりゃまあ今となっては面白くないのも自明なのだろうか、とも…。Windows10/11 を使ってる現代において Windows 3.1を「さあどうですか」と差し出されても扱いに困る…。当時としては画期的だったのかもしれんけど…。せめて Me か Vista ならネタになるのになあ。みたいな? 全然違うか。
*2: などと書いてしまったけど、「えっ。あのシーンは映像に合わせて曲を作ってましたよ?」とか言われたらどうしよう…。でもまあ、いつものOPやEDが流れてる途中でいきなりブツッと妙な何かが割り込んでくる系の演出が効果的だった事例もあるので(JOJOシリーズとか)、各要素を単体で見た時の仕上がりと、全部くっつけた時に現れる効果はまた別ですよねということで一つ。

2026/03/03(火) [n年前の日記]

#1 [nim] Nimの勉強中

プログラミング言語Nimの勉強中。環境は Windows11 x64 25H2 + Nim 2.2.8 64bit。

OpenGLが使えるかどうか確認 :

Nim で OpenGLを使いたい場合、opengl というライブラリを import すればいいようで、そのライブラリ/パッケージについては公式でサポートしているらしい。ただ、Nimに標準添付されてるわけでもないようで、別途インストールが必要っぽい? 以下でインストールできた…ような気がする。
nimble install opengl

ただ、OpenGLは描画関係の機能しか持たないので、ウインドウを生成したり、キー入力を検出したりする処理は別の何かで実現しないといけない。

一般的にOpenGLの勉強をする際は、GLUT、freeglut、GLFW あたりを使うことが多い印象だけど…。まあ、GLUT は古いし、バグも放置されたままらしいので、freeglut を使うようになるのだろうけど…。

_OpenGL Utility Toolkit - Wikipedia
_The freeglut Project :: About
_An OpenGL library | GLFW

しかしそのあたりは、別途 DLL が必要になりそうな気がする…。できれば exeファイル1つで動く何かを作りたい。

そこで今回は Windows API を利用してウインドウを生成したり、キー入力等を検出してみることにした。そういう構成なら別途DLLは不要のはず。Windowsに含まれてるから。


Nim から Windows API を利用したい場合、winim というライブラリを利用すると記述が楽になるらしい。

_khchen/winim: Windows API, COM, and CLR Module for Nim

インストールは以下。
nimble install winim

AI(Google Gemini)に、空のウインドウを表示するだけのサンプルを提示してもらって動作確認した。

_main.nim
import winim/lean

# アプリの状態を保持する型(今回はウィンドウハンドルのみ)
type App = object
  hwnd: HWND

# --- 1. ウィンドウプロシージャ(イベント処理) ---
proc windowProc(
    hwnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM
): LRESULT {.stdcall.} =
  case uMsg
  of WM_DESTROY:
    PostQuitMessage(0)
    return 0
  of WM_KEYDOWN:
    if wParam == VK_ESCAPE:
      # ESCキーで終了
      PostMessage(hwnd, WM_CLOSE, 0, 0)
      # DestroyWindow(hwnd)
    return 0
  else:
    return DefWindowProc(hwnd, uMsg, wParam, lParam)

# --- 2. ウィンドウの生成メソッド ---
proc initApp(title: string, width, height: int): App =
  let hInstance = GetModuleHandle(nil)
  let className = "NimSimpleWindow"

  var wc: WNDCLASS
  wc.lpfnWndProc = windowProc
  wc.hInstance = hInstance
  wc.lpszClassName = className
  wc.hCursor = LoadCursor(0, IDC_ARROW)
  wc.hbrBackground = COLOR_WINDOW + 1

  RegisterClass(addr wc)

  let hwnd = CreateWindowEx(
    0,
    className,
    title,
    WS_OVERLAPPEDWINDOW or WS_VISIBLE,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    width.int32,
    height.int32,
    0,
    0,
    hInstance,
    nil,
  )

  # 作成したハンドルを App 型に包んで返す
  result = App(hwnd: hwnd)

# --- 3. メインループメソッド ---
proc run(app: App) =
  var msg: MSG
  # GetMessageは WM_QUIT を受け取ると 0 を返し、ループが終了する
  while GetMessage(addr msg, 0, 0, 0) != 0:
    TranslateMessage(addr msg)
    DispatchMessage(addr msg)

proc main() =
  let myApp = initApp("Nim Win32 Application", 640, 480)
  
  if myApp.hwnd == 0:
    MessageBox(0, "Failed to create the application window.", "Fatal Error", MB_OK or MB_ICONERROR)
    return

  run(myApp)

main()

以下でビルド。main.exe が生成される。
nim c -d:release main.nim
or
nim c -d:release --app:gui main.nim
  • -d:release の指定はデバッグ情報を削除してファイルサイズを小さくしたり、最適化して処理速度を向上させる指定。
  • --app:gui の指定はコンソールを出さない指定。

以下のようなウインドウが表示された。

01_hellowinim_ss01.png


ウインドウの表示ができたので、OpenGLが使えるかテストした。これもAI(Google Gemini)にサンプルを提示してもらって動作確認した。

_main.nim
import winim/lean
import opengl
import std/monotimes

# 必要な情報をまとめる構造体
type AppWindow = object
  hwnd: HWND
  hdc: HDC
  hrc: HGLRC

# --- 1. ウィンドウプロシージャ(イベント処理) ---
proc windowProc(
    hwnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM
): LRESULT {.stdcall.} =
  case uMsg
  of WM_DESTROY:
    PostQuitMessage(0)
    return 0
  of WM_KEYDOWN:
    if wParam == VK_ESCAPE:
      PostMessage(hwnd, WM_CLOSE, 0, 0)
    return 0
  else:
    return DefWindowProc(hwnd, uMsg, wParam, lParam)

# --- 2. ウィンドウとOpenGLの初期化 ---
proc initWindow(width, height: int): AppWindow =
  let hInstance = GetModuleHandle(nil)
  let className = "NimGLWindow"

  var wc: WNDCLASS
  wc.lpfnWndProc = windowProc
  wc.hInstance = hInstance
  wc.lpszClassName = className
  wc.hCursor = LoadCursor(0, IDC_ARROW)
  RegisterClass(addr wc)

  let hwnd = CreateWindowEx(
    0,
    className,
    "Nim OpenGL - Single EXE Framework",
    WS_OVERLAPPEDWINDOW or WS_VISIBLE,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    width.int32,
    height.int32,
    0,
    0,
    hInstance,
    nil,
  )

  # OpenGL初期化
  let hdc = GetDC(hwnd)
  var pfd: PIXELFORMATDESCRIPTOR
  pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR).uint16
  pfd.nVersion = 1
  pfd.dwFlags = PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER
  pfd.iPixelType = PFD_TYPE_RGBA
  pfd.cColorBits = 32

  let pixFormat = ChoosePixelFormat(hdc, addr pfd)
  SetPixelFormat(hdc, pixFormat, addr pfd)

  let hrc = wglCreateContext(hdc)
  wglMakeCurrent(hdc, hrc)
  loadExtensions() # モダンな関数を使えるようにロード

  result = AppWindow(hwnd: hwnd, hdc: hdc, hrc: hrc)

# --- 3. 描画ロジック(アスペクト比補正付き) ---
proc render(app: AppWindow, angle: float32) =
  # ウィンドウサイズの取得
  var rect: RECT
  GetClientRect(app.hwnd, addr rect)
  let w = (rect.right - rect.left).float32
  let h = (rect.bottom - rect.top).float32

  # ビューポートと投影行列の設定(引き伸ばし防止)
  glViewport(0, 0, w.int32, h.int32)
  glMatrixMode(GL_PROJECTION)
  glLoadIdentity()

  let aspect =
    if h != 0:
      w / h
    else:
      1.0
  if w >= h:
    glOrtho(-aspect, aspect, -1.0, 1.0, -1.0, 1.0)
  else:
    glOrtho(-1.0, 1.0, -1.0 / aspect, 1.0 / aspect, -1.0, 1.0)

  # モデルビュー行列のリセットと描画
  glMatrixMode(GL_MODELVIEW)
  glLoadIdentity()

  glClearColor(0.1, 0.2, 0.3, 1.0)
  glClear(GL_COLOR_BUFFER_BIT)

  # 回転の適用
  glRotatef(angle, 0, 0, 1)

  # 三角形の描画
  glBegin(GL_TRIANGLES)
  glColor3f(1.0, 0.0, 0.0)
  glVertex2f(0.0, 0.8)
  glColor3f(0.0, 1.0, 0.0)
  glVertex2f(-0.8, -0.8)
  glColor3f(0.0, 0.0, 1.0)
  glVertex2f(0.8, -0.8)
  glEnd()

# --- 4. メインループ ---
proc mainLoop(app: AppWindow) =
  var msg: MSG
  var angle: float32 = 0.0
  let rotationSpeed: float32 = 90.0 # 1秒間に90度

  var lastTicks = getMonoTime().ticks

  while true:
    if PeekMessage(addr msg, 0, 0, 0, PM_REMOVE) != 0:
      if msg.message == WM_QUIT:
        break
      TranslateMessage(addr msg)
      DispatchMessage(addr msg)
    else:
      # デルタタイム計算 (.ticks を使用)
      let currentTicks = getMonoTime().ticks
      let dt = (currentTicks - lastTicks).float32 / 1_000_000_000.0
      lastTicks = currentTicks

      angle += rotationSpeed * dt
      # if angle > 360.0:
      #   angle -= 360.0

      render(app, angle)
      SwapBuffers(app.hdc)
      Sleep(15)

# --- 5. メイン ---
proc main() =
  let app = initWindow(800, 600)

  # 使用中のOpenGLのバージョンを表示
  # echo "Vendor:   ", $glGetString(GL_VENDOR)
  # echo "Renderer: ", $glGetString(GL_RENDERER)
  # echo "Version:  ", $glGetString(GL_VERSION)

  mainLoop(app)

main()

ビルドは以下。
nim c -d:release main.nim
or
nim c -d:release --app:gui main.nim

01_rotate_triangle_ss01.png

三角形が回転するアニメーションができた。

CreateWindowEx() を呼んでウインドウを生成するとHWND(ウインドウハンドル)が得られるので、それを使って GetDC(hwnd) すれば、OpenGLを描画するためのデバイスコンテキストが得られるらしい。


ということで、どうやら Nim でも OpenGL は使えそうだなと…。

#2 [nitijyou] 犬用のワイヤー3m版を購入

車庫の横に設置してある犬用の青いワイヤー3m版がボロボロになっていたので、親父さんがヨドバシカメラに何かしら注文するついでに一緒に注文してもらった。


先日、DCMホーマックで137cmのワイヤーを購入した時は税込2,728円だったけど…。こっちのほうが長いのに約500円も安い…。まあ、先日購入したワイヤーはその日のうちに必要だったから仕方ないよな…。

#3 [nitijyou] 「なめた精密ネジはずし」を購入

親父さんが捨てようとした電気カミソリのネジ穴が潰されてしまっていて、分解してバッテリーを取り外すことができない。専用工具をヨドバシカメラで購入。


さてはて、これでネジを外せるのかどうか…。

2026/03/04(水) [n年前の日記]

#1 [nim] Nimの勉強中。その2

プログラミング言語 Nim について勉強中。環境は Windows11 x64 25H2 + Nim 2.2.8 64bit。

スクリーンセーバを作ってみた :

Nim 2.2.8 64bit を使ってWindows用のスクリーンセーバを作ってみた。

_mieki256/ssnimsample: Nim言語製のWindows用スクリーンセーバのサンプル

ほとんどの部分をAI(Google Gemini)に作ってもらったような気もするけれど、途中で嘘を言い出すから不具合の原因を調べて修正するのが大変だった…。

  • ウインドウの生成には winim を使用。
  • フルスクリーン表示、プレビュー画面表示は OpenGL を使用。

_ssnimsample.nim 内の render() を書き換えれば独自のスクリーンセーバを作れるかなと…。

スクリーンセーバ名は、 _resource.rc 内で指定しているので記述を変更すればOK。

とりあえずNim言語を使ってもWindows用のスクリーンセーバを作れそうだと分かった。

nim.cfgについて :

Nimでコンパイルする際、一々コンパイルオプションをつけて作業するのが面倒臭い。
nim c -d:release -d:strip --opt:size --passL:"resource.res" --app:gui main.nim

batファイルを作って対応してたけど、もうちょっといい方法はないか。

nim.cfg なるものがあるらしい。コンパイルオプションを nim.cfg に列挙しておけば、nim c hoge.nim と打つだけで、そのコンパイルオプションを利用してくれるのだとか。

今回は以下のような nim.cfg になった。

nim.cfg
--app:gui
-d:release
-d:strip
--opt:size
--passL:"resource.res"
  • --app:gui ... GUIアプリを作るための指定。実行時にコンソールが出ない。
  • -d:release ... デバッグ情報を削除したり、最適化したりする。
  • -d:strip ... デバッグシンボル情報を削除する指定
  • --opt:size ... ファイルサイズが小さくなるように指定。
  • --passL:"resource.res" ... リンカへの指定。この場合リソースファイル resource.res もリンクせよと指示してる。

nim c hoge.nim と打ったら反映された。

#2 [nim] nimble build について

Nim には nimble というパッケージ管理ツール?があるけれど、これを使ってビルドの指示もできるらしい。

_NimWorld | パッケージ
_Nimble入門 #入門 - Qiita

使用ライブラリを指定 :

.nimble には、そのアプリが利用するライブラリも記述しておかないといけない。

今回は以下のような記述にした。
# Dependencies

requires "nim >= 2.2.8"
requires "winim"
requires "opengl"
  • winim と opengl を利用してるので、requires "xxxx" といった形で列挙していく。
  • バージョン指定もできる。上記の例では、nim は 2.2.8 以上が必要、という記述になっている。

コンパイル前後の処理を指定 :

コンパイルをする前と、した後に、何かしらの処理をさせることもできる。before build: もしくは after build: という指定を使う。

今回は以下のような記述になった。コンパイルする前にリソースファイルの変換を行い、コンパイルした後に .exe を .scr としてコピーしてる。
before build:
  echo "--- [Task] Compiling Resource File ---"
  exec "windres resource.rc -O coff -o resource.res"

after build:
  echo "--- [Task] Creating Screensaver File ---"
  cpFile("ssnimsample.exe", "ssnimsample.scr")
  echo "Done: 'ssnimsample.scr' has been updated successfully."
  • echo "hoge" でコンソールにメッセージ "hoge" を出せる。
  • exec "hoge.exe" で処理を実行する。上記の例では windres を使って、リソースファイル .rc を .res に変換している。
  • cpFile("SOURCE.exe", "DIST.scr") でファイルのコピーができる。

この状態で nimble build と打ったら、リソースファイルを作ってから、コンパイルをして .exe ができて、その .exe が .scr としてコピーされた。

特定の処理を指定 :

.nimble は、タスクと呼ばれる一連の処理を記述していくこともできる。

例えば、以下の記述をすると…。
task hello, "Debug test":
  echo "Hello! Nimble is reading this task correctly."

nimble tasks で、利用できるタスクの一覧が表示される。
> nimble tasks
hello      Debug test

nimble hello と打ってみると…。メッセージが表示された。task hello で指定した処理が行われている。
> nimble hello
  Executing task hello in D:\home2\prg\nim\_public\ssnimsample\ssnimsample\ssnimsample.nimble
Hello! Nimble is reading this task correctly.


生成ファイルを全消去するタスクを用意してみる。いわゆる make clean。

ここでちょっと注意。Makefile に慣れていると、タスク名として clean を記述したくなるけれど、clean というタスク名は既に予約されているので別のタスク名にしないといけない。今回は distclean としてみた。
task distclean, "Remove intermediate files and generated .scr":
  echo "Cleaning project..."
  
  if fileExists("ssnimsample.scr"):
    rmFile("ssnimsample.scr")
    echo "Deleted: ssnimsample.scr"
    
  if fileExists("ssnimsample.exe"):
    rmFile("ssnimsample.exe")
    echo "Deleted: ssnimsample.exe"
    
  if fileExists("resource.res"):
    rmFile("resource.res")
    echo "Deleted: resource.res"
    
  if dirExists("nimcache"):
    rmDir("nimcache")
    echo "Deleted: nimcache directory"
    
  echo "Clean up process completed."
  • if fileExists("hoge.exe"): で、hoge.exe が存在していたら、という指定になる。
  • rmFile() でファイル削除。
  • rmDir() でディレクトリ削除。

nimble distclean と打つと、.scr, .exe, .res が削除された。
> nimble distclean
  Executing task distclean in D:\home2\prg\nim\_public\ssnimsample\ssnimsample\ssnimsample.nimble
Cleaning project...
Deleted: ssnimsample.scr
Deleted: ssnimsample.exe
Deleted: resource.res
Clean up process completed.

#3 [nim] Nimでnglfwを使う

OpenGLを利用する際はウインドウの生成その他の処理を別の何かで行うけれど、GLUT、freeglut、GLFW 等を利用する場合が多い。ただ、それらの .dll が別途必要になると言われることも多く…。

NimでGLFWを使いつつ、exeファイル1つの中に GLFW まで含めてしまうことができる、nglfw というライブラリがあるらしい。

_RowDaBoat/nglfw: Statically linked GLFW 3.x for Nim

GLFWのソース自体を一緒にビルドしてしまうことで、DLLの添付を不要にするらしい。気になったので試用してみた。環境は Windows11 x64 25H2 + Nim 2.2. 64bit。

インストール :

インストールは以下だろうか。githubのURLを指定すればインストールできる模様。
nimble install https://github.com/RowDaBoat/nglfw

ちなみに、git clone や zip のダウンロードでは、nglfw/src/glfw の中身が空になってしまうので、利用するにはもう一手間が必要。

_nglfw/src at master - RowDaBoat/nglfw

件のディレクトリは github上の特定のプロジェクト ―― この場合はGLFWのリポジトリへのリンクを示す機能を使っているので、ただダウンロードしただけでは中身が空になってしまうらしい。nimble install ならリンクを辿って入手してくれるっぽい。

サンプルをビルド :

以下にサンプルがある。

_nglfw/examples at master - RowDaBoat/nglfw

helloclear_OpenGL.nim をビルドしてみた。

_nglfw/examples/helloclear_OpenGL.nim at master - RowDaBoat/nglfw

nim c -d:release helloclear_OpenGL.nim

生成された helloclear_OpenGL.exe を実行してみたら真っ赤なウインドウが表示された。ESCキーで終了することもできた。

ファイルサイズは585KB。小さ過ぎないか…? DLLが別途必要なのでは…?

Dependencies 1.11.1 x64 で .exe を調べてみたら、GLFW.dll 等は要求されていなかった。

_lucasg/Dependencies: A rewrite of the old legacy software "depends.exe" in C# for Windows devs to troubleshoot dll load dependencies issues.

たしかに、GLFWを使いつつ、exeファイル1つで済みそう。

#4 [nitijyou] 電気カミソリの分解で四苦八苦

親父さんが捨てようとしていた電気カミソリ、National ES8046 を分解して、内蔵されているリチウムイオンバッテリーを取り出さないといけない。

_取扱説明書 の「製品を廃棄するときのお願い」ページには分解方法が書いてあるけれど、親父さんがネジ穴を潰してしまったので、最初のパーツを取り外すことすらできない。

そこで、専用工具、「ANEX なめた精密ネジはずし No. 3610-N」をヨドバシカメラから購入した。これで外せたらいいのだけど…。

ダメだった。ネジ穴が更に削れていくだけで、ネジが回っていきそうな気配が無い。20分ぐらいチャレンジしたけど、ダメだった。この工具、使えねえなあ…。めっちゃ期待してたんだけどなあ…。

作戦変更 :

作戦を変えることにした。ネジ穴の周辺に穴を開けて、ネジの頭が、パーツを抑え込まない状態にする。もし修理するつもりで分解するならそんなことしちゃダメだけど、コレは捨てる予定の製品だからボロボロになってもいいだろう…。

数十分かけて、ネジの両脇に2ヶ所穴を開けて、どうにかパーツを取り外せた。

ネジの一部が露出したのでラジオペンチで回そうとしたけれど全然回ってくれない。この固さでは専用工具があっても無理だわな…。ニッパーで少しずつネジの周辺を削り取って、ようやくネジも外すことができた。

しかし、そこからが更に大変。グリップ部分のカバーを外すと4本のネジが見えてくるので、そのネジを外してカバーを取らないといかんのだけど、3本は外せたものの、残り1本が外せない。再度「なめた精密ネジはずし」を投入してみたけれど、やっぱりネジ穴が削れていくだけ。外せそうな予感は皆無。

この工具、マジで全然使えねえ…。何かコツでもあるのだろうか。いや、ネジがガッチリ固まり過ぎた状態では役に立たないということかな…。

また作戦変更。要はネジの頭が抑えてるプラスチック部分さえ無くなってしまえばパーツを外せるはず。ニッパーで少しずつ削っていって、どうにかカバーを外せた。

これでどうにかリチウムイオンバッテリーを取り外せた。なんだかんだで2時間ぐらいかかった。疲労困憊。

Panasonicの設計がマズイ :

Panasonicのこの手の製品の設計がマズイ気がする。この電気カミソリの、元々の持ち主の親父さんは、こんな分解作業を絶対にできないだろう…。
  • ボケてしまっているから、ネジ穴に合うドライバーを選ぶことすらできない。
  • 脳梗塞を起こして半身麻痺状態なので、片腕に力が入らない。両手でしっかり持ってグリグリする系の作業は無理。

今回、自分が居たからどうにか分解できたけど、もし親父さんが独り身で暮らしてる高齢者だったりしたら、こんな作業をできるはずがない…。

するとどうなるか。本体にリチウムイオンバッテリーが入ったままの状態で、不燃ごみとして出す以外に無い。それってゴミを収集する業者さん的にはどうなの? アリなの? ナシだよと言われても困る。だって高齢者に分解作業は無理だし、分解できないのだからバッテリーを取り出せるわけがない。

じゃあどうしたらいいのか…。

  • A. 設計を見直す。廃棄時はもっと簡単にバッテリーを取り出せる設計にする。
  • B. リチウムイオンバッテリーを使わない。製品購入後に市販のニッケル水素充電池をユーザ自身が入れて利用できる製品にする。
  • C. そもそも高齢者には分解作業を要求しない。電器店経由でメーカが製品本体ごと回収する仕組みを普及させるとか…。

とメモしたところで気が付いた。そういえば、小型家電リサイクルというワードを目にした記憶があるなあ…。

_シェーバーの捨て方|無料回収から安全対策まで徹底解説!正しい処分方法を総まとめ - ヤマダ家電情報サイト

自治体や家電店で回収できる仕組みがある程度用意されてる場合もあるのだな…。分解/バッテリーの取り外しが無理そうだったら、そういう仕組みを利用できないか検討すればいいだけ、なのかも。もっとも、地域によってこのあたりの対応には差がありそうな気もするけれど…。

それはともかく。乾電池式シェーバーが気になってきた…。そういうタイプならこういう苦労をしなくても済むよな…。でも電池交換が面倒か。であれば、必ずコンセントかACアダプタを繋いで使うタイプはないのだろうか。ググったけどちょっと見当たらなかった。コードがあると邪魔だと感じる人が多いのだろうか。

こういうのって、スマホで使われたりするモバイルバッテリーの類を活用できないものだろうか…。外部に電源があれば楽になりそうだよな…。持ち運びが不便と言われそうでもあるけど…。いやまあ、そこは素直に乾電池式を選べや、という話になっちゃうか…。

2026/03/05(木) [n年前の日記]

#1 [nim] Nimのソースコードを整形したい

プログラミング言語 Nim のソースコードを整形したい。

nimpretty というツールがあるらしい。Nim と一緒に入ってた。

> nimpretty --help
nimpretty - Nim Pretty Printer Version 0.2
  (c) 2017 Andreas Rumpf
Usage:
  nimpretty [options] nimfiles...
Options:
  --out:file            set the output file (default: overwrite the input file)
  --outDir:dir          set the output dir (default: overwrite the input files)
  --stdin               read input from stdin and write output to stdout
  --indent:N[=0]        set the number of spaces that is used for indentation
                        --indent:0 means autodetection (default behaviour)
  --maxLineLen:N        set the desired maximum line length (default: 80)
  --version             show the version
  --help                show this help

「--stdin」をつけると標準入力から読み取って標準出力に出してくれるらしい。普段使ってるエディタがバッファ内容を標準入力として出してくれる機能を持っているなら、フォーマッタをかけることが出来そう…。

#2 [nim][xyzzy] xyzzyのnim-modeを作成

自分は普段Windows上でxyzzyというテキストエディタを使っているのだけど、この xyzzy をNim言語にも対応させたい。せめてコメント行やキーワードだけでも色付け表示をしたい。

一応 nim-mode (nim-mode.l) を作ってみた。環境は Windows11 x64 25H2 + xyzzy 0.2.2.253。

_nim-mode.l
_Nim

以下のページを参考にさせてもらった。ありがたや。

_xyzzy の音 - hoge-mode をつくる
_xyzzy Lisp Progoramming

使い方 :

それぞれを以下にコピーしてインストール。
(xyzzyインストールフォルダ)\site-lisp\nim-mode.l
(xyzzyインストールフォルダ)\etc\Nim

~/.xyzzy に以下を記述。
;; nim-mode
(require "nim-mode")
(push '("\\.nim$" . nim-mode) *auto-mode-alist*)
(define-key *nim-mode-map* #\C-. 'nim-completion)    ;; C-. でキーワード補完

;; ソースフォーマッタ(nimpretty)の呼び出しを指定
(setq *nim-format-command* "nimpretty --stdin --indent:2")
(define-key *nim-mode-map* #\C-M-f 'nimpretty)    ;; Ctrl + Alt + f で呼び出し

  • C-. で、予約語リスト(キーワードリスト)に従って補完ができる。
  • Alt + Ctrl + f で nimpretty を呼び出してソース整形ができる。

制限 :

ざっくりとした色付け表示しかされません。例えば「:」を打ってからEnterを叩いたら1階層右にインデントしながら改行、みたいな機能は未実装です。

色付け表示も、コメント関係は怪しいです。Nim はコメント記述に関して以下の記述もできるらしいけど、そういった記述には未対応です…。
  • ## コメント
  • ##[ 複数行コメント ]##
  • discard """ 複数行コメント """

_Nim Manual

予約語/キーワードファイルも、これでどの程度網羅できているのか…。上記のマニュアルページに載っていたワードは列挙してあるはずだけど…。

まあ、自分の場合、ガッツリとソースを書くなら VSCode (Microsoft Visual Studio Code)を起動してそっちで書き始めるので…。xyzzy がビューア代わりになればそれでいいや、と…。

余談 :

今回このメジャーモードは xyzzy の userパッケージ内に登録されているのだろうと思うけど。

一般的にこういったメジャーモードは editorパッケージ(ed::パッケージ?)に登録して作成される場合がほとんどに見えた。しかし真似してみたところ「名前が衝突するので、exportできません editor:nim-mode」とエラーが表示されてしまった…。

以下の記述で何かおかしいところがあるのだろうか…?
(provide "nim-mode")

;; ed:パッケージに属すると宣言
(in-package "editor")

;; シンボルを外部から参照できるようにする
(export '(
          nim-mode
          *nim-mode-map*
          *nim-keyword-file*
          *nim-mode-syntax-table*
          *nim-mode-abbrev-table*
          *nim-format-command*
          *nim-mode-hook*
          nim-completion
          nim-nitsuite
          ))

単に (require "nim-mode") しか書いてない状態でもエラーが出る。何故だろう…。

2026/03/06追記 :

「名前が衝突〜」のエラーが出る理由が分かった。~/.xyzzy 内に以下を記述してたのだけど、ここが先に処理されてしまって、「nim-mode」という名前が衝突していた…。

;; ----------------------------------------
;; 1行コメントをトグル
;;
;; xyzzy の音 - 編集
;; http://hie.s64.xrea.com/xyzzy/note/edit.html#toggle-one-line-comment

(defvar *one-line-comment-alist*
  '(
    (awk-mode   . ("#"))
    (css-mode   . ("/* " " */"))
    (html+-mode . ("<!-- " " -->"))
    (lisp-mode  . (";"))
    (lisp-interaction-mode . (";"))
    (php-mode   . ("//"))
    (sql-mode   . ("--"))
    (java-mode  . ("//"))
    (c++-mode   . ("//"))
    (perl-mode  . ("#"))
    (ruby-mode  . ("#"))
    (py-mode    . ("#"))
    (nim-mode   . ("#"))
    ))

上記の変数が設定される際、userパッケージに「nim-mode」というシンボル? 名前? が一旦登録される。その後 nim-mode.l内で ―― editorパッケージ内で「nim-mode」というシンボルを他のパッケージも利用できるように export しようとすると、もう「nim-mode」というシンボルはuserパッケージ側で持ってしまっているから「名前が衝突〜」とエラーが出てしまう、ということなのだろう。

元ページにしっかり注意書きが書いてあった…。見落としていた…。

*one-line-comment-alist* の設定は,各モードの設定より後に記述する必要があるのだと思います。

xyzzy の音 - 編集 より


~/.xyzzy の最後のあたりに件の記述を配置し直したらエラーが出なくなった…。

この *one-line-comment-alist* は、呼び出される関数よりも後のほうで記述してもいいらしい。関数を呼び出した時に定義済みなら動作に問題は無い、とAIが言っている。本当かな…? 一応その配置でも動いたように見えているけど…。

一応 nim-mode.l も (in-package "editor") 等を記述した版に修正しておいた。

2026/03/06(金) [n年前の日記]

#1 [xyzzy] xyzzyの設定を見直し中

テキストエディタ xyzzy用に _nim-mode.l を作って追加したけれど、ついでに設定ファイル ~/.xyzzy の内容を見直し中。

関数を追加 :

せっかくだから、ここ最近欲しいなと思っていた関数を ~/.xyzzy に追加した。AI(Google Gemini)に作成してもらった。

セレクション(選択範囲)の上下に入力文字列を追加する。tag - /tag という形でセレクションを挟み込む。

;; ----------------------------------------
;; セレクションの直前と直後に「tag」「/tag」を挿入

(defun enclose-selection-with-tag ()
  "選択範囲の直前と直後に tag /tag を挿入。"
  (interactive) ; 引数を取らず、関数内で入力を制御
  (or (pre-selection-p)
      (error "Selection(選択範囲)がありません。(;_;)"))

  ;; read-string で入力を取得
  (let ((tag (read-string "Insrt Tag name: " :default "PRE")))
    (when (and tag (not (string= tag "")))
      (let ((from (selection-mark))
            (to (selection-point)))

        ;; 選択方向(上下)に関わらず from を小さく、to を大きく補正
        (if (> from to)
            (rotatef from to))

        (save-excursion
          ;; 選択範囲の後ろから挿入(位置ズレ防止)
          (goto-char to)
          (insert "/" tag "\n")

          ;; 選択範囲の前に挿入
          (goto-char from)
          (insert tag "\n"))))))

;; C-z m に割り当て
(global-set-key '(#\C-z #\m) 'enclose-selection-with-tag)

このぐらいの長さの関数なら、AIと数回やり取りするだけでAIが作ってくれる。凄い時代になった…。

ただ、ちょっと突っ込んだ質問をAIにすると、おそらくは Emacs関連の情報をそれっぽく織り交ぜてガンガン嘘をつき始める…。Emacs も xyzzy も、どちらも Lisp で機能を拡張できるけど、Emacs は Emacs Lisp、xyzzy は Common Lisp で、API?も色々違うんだよなあ…。マイナーな言語、マイナーなアプリはツラい。

別の関数も追加 :

セレクション(選択範囲)の行頭から入力した文字列を削除する関数も追加してみた。

outcomment-selection は 以下のページで紹介されてる関数をそっくりそのまま利用させてもらった。

_xyzzy の音 - 編集

;; ----------------------------------------
;; セレクションの指定行頭文字を削除

(defun outcomment-selection (key)
  (or (pre-selection-p)
      (error "selectionがない。"))
  (let ((from (selection-mark))
        (to (selection-point)))
    (if (> from to)
        (rotatef from to))
    (save-excursion
      (save-restriction
        (narrow-to-region from to)
        (goto-char from)
        (replace-buffer (concat "^" key) "" :regexp t)))))

(defun my-ask-and-outcomment (key)
  "ミニバッファで入力された文字列を選択範囲の行頭から削除します。"
  (interactive "sKey to remove: ") ; "s"は文字列(string)を入力させる指定
  (outcomment-selection key))

;; C-z e に割り当て
(global-set-key '(#\C-z #\e) 'my-ask-and-outcomment)

ミニバッファ上で文字列を入力する際に、interactive を使う方法と、read-string を使う方法があるようだけど…。後者はデフォルト値を設定できるあたりが便利なのだろうか? というわけでもないな…。interactive も初期値を指定することができそう。関数を実行して即座に入力させるか、何か処理してから入力させるか、呼び出すタイミングを変更できるかどうかが違うのだろうか。

_interactive - 関数

2026/03/07() [n年前の日記]

#1 [nitijyou] トイレ用ブラシを購入

Seriaフレスポ須賀川店でトイレ用ブラシ(トイレクリーナー)を購入したことをメモ。


_セリアで合計330円! トイレ掃除に3つの愛用グッズ【あってよかった】- 家電 Watch
_セリアの優秀トイレグッズ3選。トイレットペーパーで掃除できるトングなど【あってよかった】- 家電 Watch
_ポイっと清潔トイレ用シートお掃除トング【公式】≪1個からお届け≫Can★Doネットショップ
_便器掃除 ポイっと清潔!トイレ用 シートでお掃除トング 344160

ソフトタイプ ―― ふわふわした感じの材質でできているトイレ用ブラシはSeriaで売ってる、とメモしておく。昨日、ダイソー、CanDo、ワッツを探したけど売ってなかった。まさか一番近い100円ショップで取り扱っていたなんて…。当時どこで買ったのか全くメモしてなかったから無駄足を踏む結果になってしまった。こういう時のためにメモしておかないとダメだな…。

ホームセンターでも似たタイプは売ってるけれど、最安で税込607円だった。

2026/03/08() [n年前の日記]

#1 [pc] レトロPCの解像度について少し調べてた

画像生成AI、Stable Diffusion web UI を触ってるうちに、ふとなんとなく思いついた。昔のPCのゲーム画像をimg2img(i2i)したらどうなるんだろうなと…。昔のTVゲーム画像をi2iしてこうなりましたと紹介する記事を目にしてこれは面白いなと思った記憶もあるので、ちょっとやってみようかなと…。

ところが、PC-9801のゲーム画像を探すあたりで悩み始めてしまった。PC-9801の画面解像度って、640x480 (4:3) ではなかった気がするぞ…?

ググってみたら、やはりPC-9801の画面解像度は640x400だった。

_色いろいろ
_パーソナルなコンピュータのグラフィック事情 (第6回: 640x400) | Electrelic

640x480より縦方向のドット数が若干少ない。PC-8801は640x200だったので、それと比べたら倍のドット数になってるけれど…。

ん? ちょっと待て。なんだかおかしいぞ。640x480 を 4:3 のディスプレイに表示すると1ドットが正方形になるわけだけど…。PC-9801の640x400を、昔は4:3のディスプレイに表示していたわけだから、その場合1ドットが正方形にはならないのではないか? そのへんどうだったっけ。忘れた…。

ググってるうちに少し分かってきた。やはり昔のPC、レトロPCの画面は、1ドットが正方形にはなってないのが当たり前だったらしい。PC-9801の場合、1ドットは微妙に縦に長い状態になってた模様。

すると、画像生成AIに元画像として渡す時はどうすればいいんだ…? 何かしらの画像編集ソフトで640x400を640x480に拡大して、4:3の画像として渡せばいいのだろうか。

あるいは、解像度だけを見ると 640x400 は 16:10 なのだから、16:9 に引き延ばして、というか縮めて利用するのも手だろうか。その場合横に伸びる/縦に縮むと考えればいいのかな…。よく分からなくなってきた…。

もう一つ、気になることが…。PC-9801は4096色中の16色しか出せなかったから、タイルペイントだか市松模様だかディザだかで見た目の色数を増やしていたけれど、これをそのまま画像生成AIに渡しても問題は出ないのだろうか?

AI(Google Gemini)に尋ねてみたら「アンタそりゃ問題が出るよ」と言ってきた。元画像をどれだけ忠実に処理するかの設定にもよるけれど、そこにノイズがあると判断されたり、テクスチャの一種と判断されてしまうらしい…。「ガウスぼかしでも使ってぼかしてから元画像として利用したらどうか」とも言ってきた。やっぱりそうなっちゃうかなあ…。

2026/03/10追記 :

PC-9801用ゲームの640x400の画像を640x480に引き延ばしてみたら、どう見ても縦方向に長い画像になってしまって首を捻った。

ググり直してみたら、どうやら当時もドットが正方形に見えるのが正常に表示されている状態で、縦長になってしまうのはアスペクト比を調整できないダメなディスプレイで表示してしまった状態、という扱いだったような気配を感じた。でも変な話だな…。その場合、4:3のディスプレイで表示したら上下に黒帯が入ってしまいそうだけど…。そのことについては気にしてなかったのだろうか…?

水平周波数が24.8KHzとか31.5KHzとかそのへんも関係してくるっぽい。自分も一応PC-9821を使っていた時期があるのだけど、完全にそのあたりは忘れてる…。

#2 [anime] 「名探偵コナン 緋色の不在証明」を視聴

BS12で放送されていたので視聴。TVアニメ「名探偵コナン」の中の、赤井秀一というキャラに関するエピソードをまとめた総集編らしい。TVシリーズ特別編集版となっているから映画版というわけではなかったのね…。と思ったけどトムスエンタテインメントのサイトでは映画のマークがついてるな…。ググってみたら別の映画版が公開延期になったので急遽作られて上映された、という経緯で映画扱いになってるっぽい。

自分は「名探偵コナン」をほとんど見てないので、なるほどそういう設定なのかと勉強になった。いやまあ、そもそも赤井秀一なるキャラが元々どういう設定のキャラなのかは知らないままだけど…。

2026/03/09(月) [n年前の日記]

#1 [gimp] GIMPでMAG画像フォーマットを開きたい

GIMPでPC-9801時代のMAG画像フォーマットを開きたい。そんなことできるのかな…。

環境は Windows11 x64 25H2 + GIMP 2.10.38 or GIMP 2.8.22。

gimp_mag_loader.pyを試用 :

ググってみたら以下のページでMAGを開けるようにするPython-Fuが公開されていた。ありがたや。試用させてもらおう…。

_GIMP関連 / 狼どもの熱き砂漠

gimp_mag_loader.zip を入手して解凍すると、gimp_mag_loader.py が入っている。Python-Fuスクリプトを入れてあるフォルダにコピーしてインストール。

GIMPのメニュー項目に追加するタイプではなく、GIMPで画像ファイルを開こうとした際に動作するタイプのスクリプトらしい。

インストールできたかどうかは、GIMPのプロシージャブラウザで確認できる。
  1. フィルター → Python-Fu → コンソール。
  2. Pythonコンソールが開くので、下のほうにある「参照」ボタンをクリックするとプロシージャブラウザが開く。
  3. 検索欄に「mag-」と打って、python-fu-MAG-load というメソッド? 関数? が表示されたらインストールできている。

あるいは、ファイル → 開く/インポート → ファイル選択ダイアログ上でファイル形式の中に「MAG」があるか確認。

さておき、GIMPのウインドウにMAG画像をドラッグアンドドロップしたところ、MAG画像を開くことができた。

注意点その1。ファイルパスの中に日本語が含まれていると読み込みに失敗する。「'J:\日本語フォルダ\HOGE.MAG' を開くことに失敗しました。 MAG plug-in could not open image」といった感じのエラーメッセージが表示されてしまった。ファイルを移動して英数字のみのファイルパスにしたら読み込めた。

注意点その2。Pythonで処理しているせいか読み込みに時間がかかる。

RECOILを試用 :

レトロPCで使われていた画像フォーマットをひたすら網羅した RECOIL という読み込みライブラリがある模様。

_RECOIL
_RECOIL - Formats
_RECOIL - Windows

膨大な数の画像フォーマットに対応している…。「NEC PC-98」で検索すると、MAG, MKI, PI にも対応しているようだなと…。

Windows用のバイナリは .msi でインストールできるようだけど、今回は GIMP のみが対応できればいいので、Manual installation から recoil-6.4.5-win64.zip を入手した。32bit版の recoil-6.4.5-win32.zip にはGIMP用プラグインは入ってなかった。

解凍すると以下のファイルが入ってる。
COPYING.txt
file-recoil.exe
IM_MOD_RL_recoil_.dll
RECOIL.plg64
recoil2png.exe
RecoilPaintDotNet.dll
recoilwin.exe
thumbrecoil.dll
Xrecoil.usr

GIMP用プラグインは file-recoil.exe。これをGIMPのプラグインフォルダにコピーしてインストールする。

exeで提供されてるせいか、読み込みはそれなりに速い印象。

注意点。このプラグインも、日本語を含むファイルパスの画像は読み込みに失敗した。英数字のみのファイルパスなら読み込めた。このあたりもしかしてGIMP自体の問題なのでは…?

ところで、このバイナリファイル群は、それぞれ何のアプリ用なのだろう…。見た感じ、RecoilPaintDotNet.dll はPaint.NET用だろうけど…。AI (Google Gemini)に尋ねてみたら以下の回答が出てきた。合ってるのかどうか分からんけど…。
COPYING.txt : ライセンス文書(利用規約)
file-recoil.exe : GIMP用プラグイン
IM_MOD_RL_recoil_.dll : ImageMagick用モジュール
RECOIL.plg64 : Adobe Photoshop (64bit版) 用プラグイン
recoil2png.exe : CUIツール。MAG等をPNGに一括変換できる
RecoilPaintDotNet.dll : Paint.NET用プラグイン
recoilwin.exe : RECOIL専用簡易ビューア。単体で画像を閲覧できる。
thumbrecoil.dll : Windowsエクスプローラー用。フォルダ内で画像をサムネイル表示する拡張
Xrecoil.usr : XnView用プラグイン

Paint.NET 5.1.11 の FileTypesフォルダにRecoilPaintDotNet.dll をコピーして、Paint.NET のウインドウに日本語を含むファイルパスのMAG画像をドラッグアンドドロップしてみたら、あっさり開けた。

GIMP自体がマルチバイト文字を含むファイルパスを正しく処理できていない可能性がありそう…。

2026/03/10(火) [n年前の日記]

#1 [nitijyou] 人感・明暗センサ付きLED電球を購入

ヨドバシカメラの通販サイトで、人感・明暗センサ付きLED電球を購入。


トイレ前というか、玄関と台所の間に設置していたLED電球と交換してみた。今まで使っていたLED電球は、オーム電機 LDA7D-G AG27。6.7W。60形相当。

本当は100W相当の製品が欲しかったけど、売ってないのだよな…。オーム電機が一応出しているけれど、他のメーカは60Wや40W相当の製品しか出してない…。オーム電機のソレも取り扱っている店が圧倒的に少なくて…。何故なんだろう。

何にせよ、親父さんが夜中にトイレに行く時に、これで多少は楽になるといいのだけど…。今までも人感センサ付きLEDライトを設置してあったけど、乾電池式だから明るさはちょっと物足りなかった。今回交換してみて、明るさについてはバッチリ。乾電池交換の手間が無くなるあたりも助かる。

問題が出てくるとしたら、今までの癖で、ついつい壁のスイッチをOFFにしてしまいそうなあたり。自分もやりそうになってしまった。次にその場所に来る人が困ってしまう…。

2026/03/11(水) [n年前の日記]

#1 「アナザーストーリーズ 運命の分岐点 テトリスと鉄のカーテン」を視聴

NHK-BSで放送されていたので視聴。TVゲーム「テトリス」が開発された経緯と、その後の展開を紹介していく内容。原作者のアレクセイ・パジトノフ氏、ゲームボーイへの移植の権利関係で活躍したヘンク・ロジャース氏へのインタビュー映像も流れていた。

_アレクセイ・パジトノフ - Wikipedia
_ヘンク・ブラウアー・ロジャース - Wikipedia

興味深い内容だった。世界的に大ヒットしたゲームでありながら、ゴルバチョフ氏の登場が数年遅れていたら、原作者は政府に処刑されていた可能性もあるのだろうか…。

権利関係が面倒臭いことになっていたと聞いた記憶があるけれど、そのあたりも紹介されていた。ブラックオニキスのパッケージが画面に映って「おお…」と思ってしまった…。

関連情報をググっていたら以下の記事に遭遇。

_プーチンに敢然と立ち向かったテトリス作者・パジトノフ|サイボーグMSX

2026/03/12(木) [n年前の日記]

#1 [pc] SSDの空き容量が少なくなってきた

画像生成AI関係のファイルを入れているSSDの空き容量が少なくなってきた…。調べてみたらモデルデータだけで1TBぐらい入ってる。普段選んでるモデルデータは大体決まっているのだからそれ以外は外付けHDDに逃がしたほうが、とは思うのだけど、何かの拍子にそれらのデータを使いたくなる時もあるのではないかと不安になってしまって…。

仮想PCのイメージも入ってるから、そっちを外付けHDDに移動するほうがいいかな…。滅多に使わないし、そもそもサブPCにLinuxはインストールしてあるからそっちで実験すればいいわけだし。

2026/03/13(金) [n年前の日記]

#1 [pc] SSD内を整理中

SSD内に入れていた仮想PCのHDDイメージを外付けHDDに逃がした。70GBぐらいは空いただろうか…。

VMWareのイメージは、フォルダごと移動して、後からVMWareで「開く」を選べば「これは移動したイメージなのか? コピーしたイメージなのか?」と尋ねてくるので作業はできたのだけど…。VirtualBox の場合はどうすればいいのだろうか…。

ググってみたら、VirtualBoxもイメージをそのまま移動するだけでいいらしい。後で試してみよう…。

2026/03/14() [n年前の日記]

#1 [pc] SSD内を整理中。その2

SSD内に入れていた仮想PC VirtualBox の仮想PCイメージを外付けHDDに移動した。これでSSD上に200GBほどの空き容量を作れた…。

#2 [linux] Endless OSを試用してみたかったけど挫折

VirtualBoxの仮想PCイメージを外付けHDDに移動したけれど、Endless OS というLinuxのディストリビューションのイメージがあった。以前、20250610版を試した時は日本語フォントの追加方法すら分からなくて試用を諦めたのだけど、現状ではどうなってるのか気になってきたので20260128版を試用してみることにした。

環境は Windows11 x64 25H2 + VirtualBox 7.2.6 r172322。

eos-eos6.0-amd64-amd64.260128-073115.base.ovf.zip をダウンロードして解凍。中には以下の3つのファイルが入ってた。
eos-eos6.0-amd64-amd64.260128-073115.base.mf
eos-eos6.0-amd64-amd64.260128-073115.base.ovf
eos-eos6.0-amd64-amd64.260128-073115.base.vmdk

VirtualBoxを起動して、ファイル → 仮想アプライアンスのインポート。.ovfを選択してインポート。

一応起動はしたのだけど、マウスカーソルが時々動かなくなる…。反応がギクシャクしてるというか…。

LibreOfficeを起動したら日本語化されてない…。ソフトウェアアップデートを選んでアップデートしたら、LibreOffice が日本語設定になったけれど全部文字化け…。

日本語の入力方法も分からない…。半角/全角キーも、Ctrl + Space も機能しない…。そもそもキーボードレイアウトが英語キーボードになっている気がする…。

このOSはメーカ側が用意したパッケージしかインストールできないそうで、他のDebian系ディストリビューションのように足りないパッケージを sudo apt install で色々追加していくことができないっぽい。

おそらくだけど、英語圏で使うことを前提にしたディストリビューションなのではないかな…。LibreOfficeすら文字化けしちゃってるのでは試用すら難しい。初回のセットアップ時は英語以外も選べるように見えたし、デスクトップ上では日本語も表示されているから最低限の日本語フォントは既に入っているのだろうけど…。

諦めてイメージごと削除することにした。このOSはちょっと使えない感じだなと…。いやまあ、英語圏なら問題無く使えるのかもしれないけれど…。

しかしどうしてマウスカーソルがギクシャクするのだろう…。VirtualBoxは全般的にそうなのかなと疑ったけど、antiX 2.1 64bitを起動してみたらマウスカーソルがちゃんとスルスル動いてくれた。これは仮想PCの設定のせいだろうか…。

余談。antiXのバージョンの確認方法 :

cat /etc/antix-version で確認できるっぽい。

$ cat /etc/antix-version
antiX-23.1_x64-base Arditi del Popolo 21 February 2024

neofetch ではこのあたりの情報が出てこなかった。"OS: Debian GNU/Linux 12 (bookworm) x86_64" と出てきてしまう。

#3 [nitijyou] 右膝が痛い

犬の散歩中、右膝にズキンとした感じの痛み。数日前から右膝に重い感じがあったけれど、ずっと炎症でも起こしていたのだろうか…。今現在、家族の中で犬の散歩をできるのは自分しか居ないので、歩けない状態になったら困る…。

2026/03/15() [n年前の日記]

#1 [anime] 「名探偵コナン 本庁の刑事恋物語 結婚前夜」を視聴

BS12で放送されていたので視聴。名探偵コナンのTVシリーズ特別編集版、らしい。

女性刑事(佐藤刑事)と男性刑事(高木刑事)絡みのエピソードを集めた総集編のようで、最後のあたりで劇場版に繋がるとのナレーションがあった。

劇中で、フガフガした感じの声優さんが出ていたのだけど、ググってみたら松本清長という管理官のキャラを加藤精三さんが演じていたらしい。

_加藤精三 (声優) - Wikipedia

「巨人の星」の星一徹を演じていた方だけど、この総集編を作った時点では故人になっていて、ライブラリで音声を用意した、とあるな…。というか他のキャラの音声は全部新録だったのか…。

本編中でスマホとガラケーが同居していてなんだかちょっと気になった。白鳥刑事?はスマホを使っていて、少年探偵団や管理官はガラケー使用で…。どういう基準で分けていたのだろう…。最近はコナン君もスマホを使ってた気がするので、移行してる時期のエピソードだったのかな。

2026/03/16(月) [n年前の日記]

#1 [linux] Zorin OS 18を試用してみようとしているところ

Ubuntu Linuxからの派生ディストリビューション、Zorin OS 18 を仮想PC VMware上で動かしてみようとしているところ。

設定関係で試行錯誤中。明日の日記にメモしておくつもり。

2026/03/17(火) [n年前の日記]

#1 [linux] Zorin OS 18を試用

「Windows10のサポート期間が終了したのでLinuxを入れてみる」という記事をいくつか目にしたのだけど、Zorin OSを導入してみる事例が多いような印象を受けた。

Zorin OSは、Debian Linux をベースにして派生した Ubuntu Linux から更に派生したディストリビューション。かなり昔にちょっとだけ試用した記憶もあるけれど、最近はどんな感じなっているのか気になる。少し試用してみようかなと。

環境は Windows11 x64 25H2 + VMware Workstation 17 Pro 17.6.4 build-24832109。

インストール :

公式サイトは以下。

_Zorin OS - Make your computer better.

現行版は18。有償版のProと、無償で利用できるCore版があるらしい。

動作が軽いとされていたLite版もあるらしいのだけど、Lite版は廃止予定らしい。

_Getting Zorin OS Lite - Zorin Help

今回はCore版を試用。Zorin-OS-18-Core-64-bit-r3.iso を入手。

VMware上で仮想PCを新規作成。
  • インストール元 : 後でOSをインストール
  • ゲストOS : Linux
  • バージョン : Ubuntu 64bit
  • 他は推奨設定のまま。
最後に「ハードウェアカスタマイズ」をクリックして、光学ドライブ(新規 CD/DVD(SATA))に入手したisoを指定。

インストール自体はすんなりできた。ただ、日本語入力ができない…。

日本語入力の設定 :

Ubuntu系は ibus ではなく fcitx5 を使うと安定するらしい。

_ZorinOSの日本語入力で詰まったら、ibusを捨ててfcitx5にすると幸せになれる件(実体験) - OS ManiaX
_Zorin OS - 18 - Core GNOME -基本操作 - 日本語入力

上記ページに従って、fcitx5をインストールして、ibusをアンインストール。
sudo apt install fcitx5 fcitx5-mozc fcitx5-frontend-gtk2 gnome-shell-extensions
sudo apt remove ibus

mkdir -p ~/.config/autostart
cp /usr/share/applications/org.fcitx.Fcitx5.desktop ~/.config/autostart/

ただ、この作業をすると、日本語キーボードが消滅して、英語キーボード(キーボード - 英語(US))とmozcの組み合わせになってしまう。日本語キーボードを追加して、英語キーボードを削除する。

  1. タスクバー右下のキーボードみたいなアイコンをクリック → 設定。
  2. 右側で「キーボード - 日本語」を選んで、真ん中の「<」をクリックすれば追加できる。
  3. 左側で「キーボード - 日本語」を選んで、真ん中の上向き三角をクリックして一番最初に持ってくる。
  4. 左側で「キーボード - 英語(US)」を選んで、真ん中の「>」をクリックして除去。

ちょっとよく分からないのが、Japanese (OADG 109A) を選ぶように解説してる記事もあって…。Windows用のキー配置になっているのが OADG 109A ということらしいけど…。

_UbuntuでFcitx5を使うときの日本語入力の不安定な挙動を解消する|Web係りのおじさん

とりあえず、OADG 109A を選んでおこう…。

これで、「半角/全角」または「Ctrl + Space」でIME?が起動して日本語を入力できる状態になった。

しかし、毎回起動するたびに、上のほうに何かメッセージが出てくる…。

ウェイランド診断

入力メソッドのポップアップを提供するために、Input Method Panel GNOME Shell Extensions をインストールすることをお勧めします。
https://extensions.gnome.org/extension/261/kimpanel/
そうしないと、GNOME Shell のアクティビティ検索ボックスで入力する時に、入力メソッドのポップアップが表示されないことがあります。
詳細は
https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland#GNOME
を参照してください。

_https://extensions.gnome.org/extension/261/kimpanel/
_https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland#GNOME

Zorin OS 18 上で、Webブラウザを起動して、上記のURLを開いた。「ここをクリックしてブラウザー拡張機能をインストールしてください. 」と書いてあるので指示に従ってクリック。ブラウザ上に拡張機能がインストールされて、先ほどのページを開き直すとON/OFFを選べるようになった。

また、どこかしらに以下を記述して設定しないといけないらしいが…。
XMODIFIERS=@im=fcitx
QT_IM_MODULE=fcitx
GTK_IM_MODULE=fcitx

or 

XMODIFIERS=@im=fcitx
QT_IM_MODULES="wayland;fcitx"
GTK_IM_MODULE=fcitx

_fcitx5の公式から見る2026年の設定事情
_Zorin OS - 16 - 基本操作 - 日本語入力

どのファイルに書くかで、記述の仕方が変わってくるらしい…。

とりあえず /etc/environment に以下の形で追記してみた。
export LANG="ja_JP.UTF-8"
export XMODIFIERS="@im=fcitx"
export XMODIFIER="@im=fcitx"
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export DefaultIMModule=fcitx

件のメッセージは出なくなった。

でも、本当に /etc/environment に書いてしまっていいのだろうか。別のファイルのほうが妥当だったりして…?

NumLockを有効化 :

numlockx をインストールして自動起動するようにすればいいらしい。

_Zorin OS でテンキー(NumLock)をオンにする方法 Kubuntu | shattered-blog.com

sudo apt install numlockx

スタートメニュー → システムツール → Startup Applications → 追加。コマンドとして numlockx on を指定すればいいらしい。名前や説明は適当に。

ただ、VMware上では期待した結果になってないような…。実機で動かせば違うのかな?

_Ubuntu22.04 起動時にNumlockオン | ろっひー

GNOMEがNumLockの状態を記憶できるように設定することもできるらしい。一度 NumLockキーを叩いて有効にしておけば、再起動後も状態を再現してくれる。
gsettings get org.gnome.desktop.peripherals.keyboard remember-numlock-state

gsettings set org.gnome.desktop.peripherals.keyboard remember-numlock-state true

日本語フォルダを英語にする :

インストール直後は「デスクトップ」「ダウンロード」といった日本語名のフォルダになってしまっている。「Desktop」「Downloads」にしたい。

sudo apt-get install xdg-user-dirs-gtk
LANG=C xdg-user-dirs-gtk-update

ログアウトして、再度ログイン。

_Ubuntu: ユーザーディレクトリ名を標準の英語表記に変更する手順

フォントを追加 :

sudo apt install fonts-ipafont fonts-ipaexfont fonts-takao fonts-mplus fonts-migmix fonts-mmcedar fonts-umeplus fonts-motoya-l-maruberi fonts-droid-fallback xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable xfonts-shinonome xfonts-intl-japanese xfonts-intl-japanese-big xfonts-kaname xfonts-intl-arabic xfonts-intl-asian xfonts-intl-chinese xfonts-intl-chinese-big xfonts-intl-european xfonts-intl-phonetic emacs-intl-fonts fonts-motoya-l-cedar fonts-horai-umefont fonts-ricty-diminished fonts-urw-base35 fonts-liberation fonts-texgyre xfonts-mplus fonts-noto -y

sudo apt install xfonts-naga10 ttf-mscorefonts-installer -y

HackGen 2.10.0 もインストール。
wget https://github.com/yuru7/HackGen/releases/download/v2.10.0/HackGen_v2.10.0.zip
wget https://github.com/yuru7/HackGen/releases/download/v2.10.0/HackGen_NF_v2.10.0.zip
unzip HackGen_v2.10.0.zip
unzip HackGen_NF_v2.10.0.zip
mv HackGen_v2.10.0 HackGen
mv HackGen_NF_v2.10.0 HackGen_NF
rm HackGen/HackGen35*
rm HackGen_NF/HackGen35*
sudo mv ./HackGen /usr/share/fonts
cd HackGen_NF
sudo cp *.ttf /usr/share/fonts/HackGen/
fc-cache -fv
fc-list : family | grep HackGen

Wineを試用 :

Windows用のアプリをLinux上で動かせるWineが気になったのでインストールしてみた。Zorin OSの場合、zorin-windows-app-support というパッケージをインストールすればいいのかな…?

sudo apt install zorin-windows-app-support 

結構時間がかかった…。

_脱Windows Zorin OSってどんな感じ? Windowsソフトを実行できるか検証 Linux - Qiita

日本語フォントを表示するアプリは文字化けするので、winetricks と cjkfonts をインストールしないといけないらしい。
sudo apt install winetricks

export WINEPREFIX="$HOME/.wine"
winetricks cjkfonts

Windows98時代のドローソフト G.CREW5 をインストールしてみたけれど…。一見動いたように見えたけど、サンプルファイルを開いたらレイアウトが崩れまくり。Wineの設定でWindows98にしてみたところ、表示されてなかったテキストボックス内の文章が表示されるようになって少し改善したけれど、ロゴ等の表示位置はおかしいまま。なかなか厳しいなと…。ただ、アプリによってはちゃんと動きそうな気配はする…。

雑感 :

見た目がオシャレなディストリビューションだなと…。

ただ、自分は普段 Ubuntu Linux や Debian Linux も使っているので、機能面で Zorin OS ならでは、といった部分を感じられず…。Ubuntu や Debian でええやん、という感想になってしまって…。

インストール直後から日本語入力ができない点もちょっと気になる。このあたり、英語圏で利用されることを前提にして作られてそうな気配も…。

でも、あちこちがオシャレなんだよなあ…。ここまでオシャレだと「Windowsじゃなくても、これでいいじゃないか」という気分になれそうではある…。

#2 [anime] 「Song of the Sea」を視聴

Eテレで放送されていた版を録画していたので視聴。アイルランドの手描きアニメ映画。トム・ムーア監督作品。アイルランドのアニメスタジオ、Cartoon Saloon による制作。

一部のカットは Moho を使って作られている、という宣伝記事を頻繁に目にしていたので気になっていたのだけど…。なるほど、こういうアニメだったのか…。実に独特な絵柄/スタイルでイイ感じ。おそらくはアイルランドの民話を基にした設定やストーリーなのだろうけど、それもまた独特な雰囲気に繋がってる印象を受けた。色々な賞を取ったとか、アカデミー賞にノミネートされていたという話にも納得。この出来なら当然の流れというか…。

主に、フランス発のアニメ制作ソフト TVPaint で作られていたらしい。TVPaint を使えばこういったアニメを作れますよという実績になりそうだなと…。ただ、ググってみたら TVPaint ってお値段が高い…。30万円ぐらいする…。サブスクリプションではなく買い切りタイプ/永続ライセンスなのでそのあたりは安心かもしれないけれど。

監督さんのインタビュー記事を目にしたけれど、スタジオジブリの「となりのトトロ」「千と千尋の神隠し」に影響を受けたそうで。アニミズムがどうとか…。たしかに妖精云々のあたりは共通点がありそうだなと…。ジブリ作品に登場する各キャラは、日本国内では妖精とは言われてないけれど、欧米ではどれも妖精扱いなんだろうな。

メイキング映像を眺めた限りでは、従来の手描きアニメと同様に、原画も動画も線で描いて仕上げていく作り方だったようで…。CGソフトを活用して静止画を動画にするとか、あるいはパーツ分けしてカットアウトで動かすソレを期待してたので、その点は少し残念。やっぱりコツコツ描かないとこういうアニメは作れないのだなあ…。 _なんとかインチキできんのか。

2026/03/18(水) [n年前の日記]

#1 [cg_tools] 某画像編集ソフトを試用中

とある画像編集ソフト? お絵かきソフト? を試用中。Windows上で動作して、無料で利用できるフリーソフト。

ソフト名は…ちょっと書けない。ソレ書いちゃうとたぶん面倒臭いことになりそうなので…。Windows95/98時代から公開されていて、機能は豊富だけど操作感やUIにかなりクセがあると定評のソフト。この手のソフトに詳しいインターネット老人なら「ああ、アレかあ。いや、それともあっちか?」と分かるかも。あっちよりユーザ数が少なかったのではないかと思えるほうです。解説ドキュメント内で「使いこなせない/理解できないお前が悪い」と隙あらばとにかくdisってくるほう。「じゃあアレかあ」。そうそう、ソレソレ。…ドキュメントを眺めてる人ってそのソフトにせっかく興味を持ってくれたありがたい人達なはずなんだけど、なんでいきなり喧嘩を吹っ掛け始めるのかさっぱり分からない…。 _店の暖簾をくぐったばかりの客にいきなり「帰れ!」って怒鳴り出す店主 っぽいよな…。

それはともかく、別件でググってたら件のソフトは Delphi で実装されてるという情報を目にして興味が湧いたわけで…。先日まで Delphi や Lazarus を触ってたから、Delphi/Lazarusで画像編集ソフトを作るとしたら一体どの程度のものが作れるのかちょっと気になっていて。そのあたりを把握できるかもしれないなと…。

感想 :

思考メモ。感想には個人差があります。それと、Delphi/Lazarus はあまり詳しくないのでたぶん頓珍漢なこと書いてると思います。

少し触ってみた印象だけど…。「頑張れば Delphi でここまでのものを作れてしまうのか」と素直に感心すると同時に、「ひょっとして Delphi で作るとこんな惨状(?)になってしまいがちなのだろうか?」という不安も湧いてきたというか…。

仮に Delphi/Lazarus で画像編集ソフトを作ろうとする場合、懸念事項として2点あるかなと…。

懸念その1。Delphi にGC(ガベージコレクション)が無いこと。

Delphi の元になった Pascal というプログラミング言語は、C言語より古い言語なので、C/C++と同様にGCが無くて…。GCはメモリ解放を自動でイイ感じにやってくれる機能なので、それが無いとなると、プログラマーは意識してメモリ解放を逐一指示しないといけない。だけど人間がやることだからついうっかり忘れてしまうことがちょくちょくあって、そのうっかりがソフトの動作を不安定にしている可能性はないのかなあ、どうなのかなあ、と…。

というのも。件のソフト、ちょっと触っただけでも数回ほど無言で落ちてしまって…。まだ基本操作しかしてないはずなのに落ちるのは萎える…。お前は Project Dogwaffle か!。なんちてぽっくん。 *1 また、何かの拍子に描画ツールが正常動作しなくなったり、説明のためのポップアップが出てこない状態に陥って、終了/再起動しないと元に戻らなかったりして…。

この不安定さは Delphi で作ったせいなのか、GC が無いとこういう出来になっちゃうのかなと…。いやまあ、そんなこと言ったら C/C++ で作ったアプリだって同じ問題抱えるじゃんよって話になるけれど。こういうのって、処理の速さと、バグが混入しやすくなることのトレードオフだったりするんかな…。もっとも今は C/C++ 並みに速いけどGCも持ってる言語が色々あるのでそっちを選んだほうがいいのかも。

懸念その2。UIの機能面について実装の難しさがありそう。

例えば、Lazarus/Free Pascal で作られた _LazPaint という画像編集ソフトがあるのだけど。これも今回試用したソフトと似た感じの…UIの奇妙さ?を感じるというか…。ちょっと言語化して上手く説明できないのだけど、見た目からしてなんだか妙な感じが…。なんだろうな、これは…。ツールバー回りの見た目がギクシャクしてるというか…。上手く説明できない…。それと、UIレイアウトをユーザがほとんどカスタマイズできない点も気になる…。

Delphi なら VCL、Lazarus なら LCL という、GUIアプリを作るためのライブラリが用意されているのだけど。この VCL/LCL はOSのAPIのラッパーのような感じらしくて、基本的なGUI部品ならすんなり出せるし、OSが持ってる機能を呼び出してるだけだから実行バイナリのファイルサイズも小さくなる利点があって…。ただ、OSが持ってる基本機能で済む場合はそれで十分だけど、それ以上のことをしようとすると…どうなんだろうなと…。これは勝手な想像だけど、今風のGUIアプリを作ろうとするとおそらく機能が足りなくて、そこは自前で実装することになってギクシャクした感じになるのかなと…。

例えば GIMP はシングルウインドウモード時に各ウインドウの配置をユーザが好きなように変えられるのだけど、あのあたりはおそらく GTK が担当してたりするんかなと。違うのかな…。他の画像編集ソフト/お絵かきソフトでもそういったことができるけど、そういった部分は Qt とかそういうアレが担当してたりするのでは、と…。

Paint.NET は C# + .NET Framework で作られているらしいけど、あの見た目も .NET Framework ならでは、だったりするんかな…。Windows API だけでは足りてない部分を .NET Framework が補ってるんじゃないのか…。

そう考えると、Delphi/Lazarus でその手のソフトを作ろうとすると、今風のGUIアプリならできて当然のことができなくなったり…するんかなあ…。どうなのかなあ。どうなんでしょうねえ…。

いやまあ、どの機能も頑張れば自前で実装できるのだろうけど。そもそも昔は Qt とか .NET Framework とか無かったわけで、UI面で機能追加するには全部自前でやるしかなかったはずで。GTK だって GIMP を作るために自前で作っていた部分を「コレって他でも使えそうだよな」と別に分けたソレなので。GIMP Toolkit の略称で GTK なので。だから頑張れば作れるはず。頑張れば。

ただ、今から作るなら、既に用意されてるアレコレを積極的に利用させてもらったほうがいいよなと…。そういったGUIライブラリ/フレームワークって色んなソフトで使ってるから、バグ報告もちゃんと上がってくるし、パッチも当たる可能性が高いしで、自分で実装するより信頼性ははるかに高いはず。

おそらく、Delphi/Lazarus にも、既にそういうライブラリだかフレームワークだかがありそうな気もする…。よく調べてないけど、Delphi の FMX(FireMonkey)って本来そのあたりもカバーするはずだったのかな、とも。

もっとも、今から画像編集ソフト/お絵かきソフトを作る意味って無いだろうな…。
  • FireAlpaca や Krita を触ると「これでいいじゃん」って気分になるし。
  • GIMP だって昔と違って安定して動いてるし。
  • Webブラウザ上で動いてしまう画像編集ソフトすら存在する時代だし。
  • 元々有償ソフトだったはずの Affinity Studio 3.0 も無償で利用できることになったし。

そもそも、お絵かきするならクリスタ(CLIP STUDIO PAINT)を使うべきだよな…。圧倒的なユーザ数だし、解説記事も山のようにあるし。しかもそのユーザ達がせっせとペンやブラシやモデルデータや各種素材を作ってアップロードして、コミュニティ全体で作業の効率化がどんどん進んでる。「みんなで幸せになろうよ」的感覚を味わえるCGソフトのような気もしてきた。

いやまあ、画像生成AIの台頭もあって、今後自分で絵を描く人が減ってしまうのではという懸念もあるけれど…。となるとますます、画像編集ソフトを新規に作る意味なんて無くなっていくよなあ…。

ただ、このコンポーネントをフォームに貼り付けるだけで画像の拡大縮小表示やスクロールができるよ、みたいなものは欲しい気も…。レイヤーも重ねて表示出来たりすると嬉しい。とか妄想するとそれって画像編集ソフト作るのと変わらないじゃんってことになりそうだけど。ちょっとした実験をする時に、そういうのが欲しくなるというか…。

感想には個人差があります。思考メモです。オチは無いです。

*1: 海外製の Project Dogwaffle という画像編集ソフトはパレットウインドウ上で色を選択しただけで落ちるので…。一応、設定で少し症状を緩和できる。

2026/03/19(木) [n年前の日記]

#1 [nitijyou] 自宅サーバ止めてました

09:00-13:50の間、自宅サーバを止めてました。申し訳ないです。

停電があるという話を耳にして慌てて電源を落としたのだけど、後で確認してみたら停電なんて無かったようで…。自分は寝ぼけてたのか…? 階下でそういう会話をしていたような気がするのだけど…。おかしいなあ…。

#2 [cg_tools] 某画像編集ソフトを試用中。その2

とある画像編集ソフト? お絵かきソフト? をまだ試用中。Windows上で動く、無料で利用できるフリーソフト。

思考メモ。オチは無いです。

今となっては高機能ではないのかも :

Project Dogwaffle のように基本機能はアレだけど特定の機能が実に魅力的だったりしないかなと期待しながら触っていたのだけど…。

残念ながら今のところ、このソフトならではの機能が見つからず…。「この機能、(GIMP|FireAlpaca|Krita|.+)にもあるよな…」みたいな印象で…。期待に応えてくれるソフトではなさそう…。

Windows95/98時代なら、これだけ機能が実装されているフリーソフトはとても珍しかったのだろうけど、今時の画像編集ソフトであればどれもこれも持っていて当たり前の機能ばかり…。このソフトに対する当時の評には必ずと言っていいほど「高機能」と書かれていたけれど、それはあくまで昔の話。今眺めると「フツー」「平凡」という評になってしまいそう…。

でもまあ、それは当然で。今時 Windows95/98 を触って「新しいな!」なんて誰も思わないわけで、CGソフトだってそういうものだよな…。

もっとも、基本機能に独自性があって、手放せない画材としてずっと使われていた事例もあるか…。たしかSAIはそういう感じの扱われ方だったような…。もしかすると Adobe Flash (Adobe Animate) もそういう面があるのだろうか。Painter も一時期まではそういうところがあった気もしてきた。ブラシエンジンに手を入れて描き味が変わってしまってユーザが嘆きつつ離れていった記憶もあるけれど…。

ならばこのソフトの基本機能はどうなのかと考えると…。そこも今となっては「フツー」なんだよな…。せめて「このフィルタは使えそう」「他では見たことないな」みたいな部分があれば違うのだろうけど…。でも、そこも無いんだよな…。

UIデザイン云々 :

このソフト、ちょっと触っているだけでも色々考えさせられる…。GUIアプリのUIデザインとは一体どうあるべきなのか、ついつい悩み始めてしまう…。とりあえず、「どんなに高機能でも呼び出し方(UI)が分からなければユーザにとってその機能は存在していないも同然」と言える気がする。

ただ、「だったら機能を削減すればええやろ」と考えちゃうのは違う気もして…。機能数が問題ではなく、どこにその機能があるのか「類推」しにくい配置なのが問題じゃなかろうか…。結局は「直観的に使えない」という話になるのだろうけど、単に各機能の分類、階層化、優先順位のつけ方が上手くできてないだけではないのかなあ…。

例えば、色とブラシ形状って別の要素だと思うけど、どうして同じウインドウに両方の設定項目をギッシリと詰め込んでいるのか。いや、考えは分かる。描いていく時に両方のパラメータを弄る機会が多いから並べておいたほうが効率がええやろと考えたんだろうけど、そこをまとめちゃうとどの設定項目が何の設定なのか途端に分かりづらくなる。だからフツーは別ウインドウに分けておくわけで…。

各GUI部品がギチギチに詰め込まれているのも厳しい。いや、考えは分かる。デスクトップの解像度が低い時代に作られたソフトだから少しでも面積を小さくしたかったのだろうし、各ボタンへのマウスカーソルの移動距離が短ければ作業効率も上がるやろと考えてた可能性もありそうだなと。だけど見た瞬間にどこに何があるのか分からない印象になるわけで…。だからフツーは要素別に分類しつつ隙間を入れてどれがどれだか把握しやすくするわけで…。

まあ、作業効率の改善と初見時の分かりやすさはトレードオフなので、どっちに舵を切りますかというところもあるのだけど、初見で分からなくて投げ出されたら作業効率もへったくれもないやろという…。

フィルタの分類も、なんというか…。フィルタには大別して、「既に画像があることを前提としたフィルタ」と、「何もない状態で描画することを前提にしたフィルタ」があるけれど、このソフトはそのどちらも雑然と同じ階層にまとめられていたりして…。フィルタ数が少ない場合はそれでもいいのだけど、これだけ数が多くなってくると階層を使った上手な分類は必須…。

フィルタの分類については色んなソフトを眺めるだけでも、分類に使ってるワードが大体決まってることが分かりそう。いや、G'MIC の分類を参考にするだけでも結構違うかも。G'MICは何百種類ものフィルタが入ってるから上手く分類しないと…。

もっとも、G'MIC は検索欄にワードを打ち込んでリストアップして呼び出すのが前提になってそうでもあるか。フォルダという、ある意味単一のタグで分類する概念ではなく、検索で探し出すやり方。Windowsのスタートメニューも、Linuxのデスクトップ環境も、最近はそういうノリになってるよな…。

たしかこういうのって Apple がやり始めたファイル整理の仕方だった気がする。全部一ヶ所に入れてしまえ。使いたくなったら検索で呼び出せばええんや。みたいな。もっとも、毎回一々検索するのは面倒だからブックマーク相当の機能も必要になってくるんだろうけど、そのうちブックマークもパンパンになるよな…。

まあ、そんな感じで色々考え始めちゃうよなと…。

blenderを思い出す :

このソフトを触っていて、3DCGソフトのblenderをちょっと思い出したりもした。

あのソフトも膨大な機能を持っているソフトだけど、ある時期までは「右クリックで選択」という仕様だったので、独特の操作感だの、操作にクセがあるだの、散々言われてた記憶があって…。

だけど 2.80 の時点で大鉈を振って、「左クリックで選択」をデフォルトにしたのだよな…。ただ、そのままだと今まで使ってたユーザが困るので、初回起動時にどちらにしたいか選択できるようにしていたはず。

するとどうでしょう。「これなら使える」的にユーザがどんどん増えて、今では大人気の3DCGソフトに。おそらくだけど、元々人気を獲得できるだけのポテンシャルは十分に持っていたのだろうなと。だけど独特なUI仕様がその展開を邪魔してた。もし、昔の仕様のまま、ずっといつまでも大鉈を振わなかったら、一体どうなっていたのかなと想像したりもするわけで…。

UI仕様ってそのぐらい大事なんだろうな…。プログラマーってついつい機能面のほうを優先して考えちゃうところがあるけれど、それ以前にまずUIのほうが重要…。いや、機能もやっぱり大事か。その機能を使ってみて「なんじゃこりゃ。使えんわ」と思われたらやっぱり離れていくし。たぶんコレって両輪なんだろう…。

教材として有用かも :

もしも、どこかの学校で、UIデザインについて教える授業があったとしたら、このソフトは教材として大変有用なのではないかなあと妄想してしまったりもする。良い例ではなく、悪い例、反面教師として役立つ教材として…。「このUIの問題点を列挙して、改善策を提示しなさい」というお題を出せば、学生さん達はまるで湯水の如く次々にアイデアを出してきそう。

既にある程度形になっているものを目にすることで、ようやく理想像が具体的な形で見えてくることってあるよなと…。例えば「未来少年コナン」を作ってた頃の宮崎駿監督が上がってきた富野コンテを目にしてまるごとゴミ箱に捨てたという噂を聞いたことがあるけれど、それってたぶん、庵野監督がエヴァ新劇を作ってた時にスタッフに言ってた「これじゃないということがわかった」という状態だったのではなかろうか。誰かが提示したソレを見て「違う。そうじゃない」と思えたら、おそらく正解にちょっと近づくことができているはずで。

目の前に何も無い状態で「理想的なUIを考えなさい」と言ってもフツーは出てこないけど、「このUI、どう思う? 何がマズイと思う? どうしたらいいんだろね?」という問いなら頭も回り始めるというか…。


まあ、触ってるだけで色々なことを考え始めてしまうソフトだなと思ったと、ただそれだけの話です。思考メモです。

AIの登場で画像編集ソフトというジャンルが無くなっていくかもしれないこんな時期に自分は今頃一体何を書いてるんだろうという気もしてきた…。

2026/03/20(金) [n年前の日記]

#1 [cg_tools] Pixiaを試用

無料で利用できる画像編集ソフト Pixia を試用。Windows向けアプリ。画像編集ソフトというか、お絵かきソフトだろうか。環境は Windows11 x64 25H2。

Pixia は、Windows3.1/95時代に市販されていた画像編集ソフト DaisyArt の開発者さんが機能削減を意識しながら開発・公開したソフトだそうで。また、Ver. 1.x からUIを維持した 4.x系と、UIを改変した 5.x、6.x系があるらしい。

インストール :

今回は Pixia 4.90d と 6.62b を試用してみることにした。

_Pixia書庫室

以下のファイルを入手。
pix490dj.exe
pix662bj.exe

それぞれ実行するとインストール処理が始まる。今回は D:\Program Files (x86)\Pixia4\ と D:\Program Files (x86)\Pixia6\ にインストールした。

一応、追加フィルタも入手。
pxaddflt2.exe
PixiaToneFilterSet.exe

実行すると、4.x系にインストールするか、6.x系にインストールするかを尋ねてきた。「はい」をクリックすれば4.x系にインストールされて、「いいえ」をクリックすれば6.x系にインストールできる模様。

感想 :

機能削減版を意識していると言うだけあって、本当に最低限の機能しか実装されてない印象を受けた。たしかに初心者が迷うことはなさそうではあるけれど…。

今は色々な画像処理ソフト/お絵かきソフトがあるので、あえてこのソフトを選択する理由が思いつかない感じはする…。

よく分からない点 :

4.90d はブラシの描画が途切れ途切れになってしまった。どこかに各点を繋げる設定があるんだろうか? 4.90d はブラシツールが1つしかないけれど、6.62b は線を繋げて描画できるブラシ(フリーハンド(補間))と、旧来のブラシ?(フルーハンド)が別ツールとして用意されているらしい。

キャンバスを再描画する時 ―― 例えばズーム率を変更した際、キャンバス内をベロンベロンと書き換えている様子が見えるあたりはちょっと気になる。AMD Ryzen 5 5600X + RAM 32GB ではスペックが足りない…? そんなはずは…。

6.62b のベジェ曲線っぽいアイコンのツールがよく分からない…。制御点を左クリックで打っていって、後になってから制御点を調整できるのかなと思ったけれど、制御点をドラッグしようとしただけで新しい制御点が追加されてしまう…。どういう操作をすることが前提のツールなのか…。

4.90d でベジェ曲線ツールを使うと全然違う動作になった。新しい制御点は作られない。6.62b のソレはバグなんだろうか。

6.62b で、表示 → 表示設定、を選んで、ダイアログを表示してから閉じるとアプリが不正終了することに気づいた。どうやら 6.x は開発途中っぽい…。でも、2024/10/08 に公開されたバイナリなのに、ずっとバグ修正されないままというのも妙だな…。開発中止状態なのかな…。

2026/03/21追記 :

再度 4.90d を起動してみたらブラシ描画が途切れなかった。よく見るとツールバーには「フリーハンド(補間)」が表示されていた。どうして初回時は途切れ途切れになったんだろう…。

ファイル → ツールバーのカスタマイズ、で、各ツールの表示状態を変更可能と知った。4.90d も、実は 6.62b と同じぐらいツールが用意されていた。デフォルトではツールバー上に表示されない設定になっていただけだった。

6.62b x86 をアンインストールして 6.61p x64 をインストールして試用してみたら、UI配置が全然違っていた…。ただ、ベジェ曲線(領域 - ベジェ曲線) の操作感は相変わらずで…。やはりバグなんだろうか…。

6.61p x64 で、ツールバーの何もないところを右クリックすると配置場所を選べることに気づいたけれど、別の場所に配置するとツールアイコンがごっそり消滅することに気づいた。再起動することが前提なんだろうか…。

4.90d も、ベジェ曲線ツールの操作が厳しい…。接線ハンドルを移動しようとしてクリックやドラッグをしたつもりが、新規に領域を作ってしまって、今まで作った領域が問答無用で消滅、という場面が何度もあって…。しかも Undo で戻らない…。GIMP や Krita のほうが全然マシな操作感だな…。

関連情報をググっていたら、Pixia はかなり不具合が多いソフトだったようで…。新しいWindowsが登場すると不具合が増えてるようにも見えたので、一見動いているように見えているけど、実は新OSに対応できてない可能性があるのかもしれない…?

試用してみたものの、Krita や FireAlpaca のほうが全然良さそうに思えてきた。このソフトを触ってると、不可解な動作にちょくちょく遭遇して、次第にイライラしてくる…。このソフトをあえて今から使う理由もやはり思いつかないし、アンインストールすることにした…。

画像編集ソフトの開発って大変なんだな…。GIMP や Krita は、よくまああそこまで不具合をコツコツと無くしていったものだなと感心してしまった。もっとも、バグ報告システム/バグトラッキングシステムや、ソース管理ツールを導入したことによる効果もあるのだろう…。

#2 [anime] 「アポカリプスホテル」最終回を視聴

BS12で放送されていたTVアニメ「アポカリプスホテル」の最終回を視聴。都市圏では去年放送されていたアニメだろうけど、BS放送では初、つまり、初の日本全国放送だったわけで…。

実に変なアニメで、面白かった…。素晴らしい…。

何より、漫画家の竹本泉先生がキャラデザ原案をしているというのが…良い…。メガCDで「ゆみみみっくす」をプレイして楽しんでいた人種としては竹本泉先生の名前が出てくるだけで「おっ」って感じなわけでして…。あくまでキャラデザ原案のはずだけど、あの独特な作風との共通点をどこか感じるアニメだったなと…。

#3 [anime] 「えんとつ町のプペル」を視聴

地上波で放送されていたので視聴。絵本を原作としたCGアニメ映画、という説明でいいのだろうか。

タイトルはあちこちで見かけていたけれど、どういう作品なのか全く知らなかったので、なるほどこういうアニメだったのかとスッキリできた。

制作は STUDIO 4℃。ゴイスな映像のアニメを次々に作ってきたスタジオ。長編のCGアニメとしてはこの作品が初、だそうで。一見すると絵本に見えそうな映像になっていて、こんな映像が作れてしまう時代になったのかと…。もちろん今までノウハウを貯めてきて、更に試行錯誤して作ってるからここまで作れるのだろうけど…。クリック一つでこんな映像にはならないだろう…。「CGは 魔法の小箱じゃ ないんだよ」(by 宮崎駿)。

話の流れも分かりやすかった。ファンタジー作品らしくて良いのでは。

町の住民達が主人公達を言葉の暴力で叩きまくるあたりが見ていて辛かった…。原作者の体験が反映されてそうだけど、子供向けアニメとして捉えた場合はある意味教育的なシーンと言えるのだろうか。こういうことしちゃダメですよ、客観的に見ると酷いでしょ? みたいな。

制作がSTUDIO 4℃な時点で箸にも棒にも掛からぬアニメにはならないだろうと予想はしていたけれど、映像面はちゃんとしてるし、イイ感じの出来ではなかろうかと…。名作とまでは言えないとしてもフツーに良作佳作として扱われてしかるべきアニメのように思えた。

個人的には、ゴミでできたロボットという設定が好きなので、そこらへんもグッドだったかも。子供の頃、ボスボロットが結構好きだったので…。アレってたしかそこらへんのゴミを集めて作ったロボットだった気がする。なんだか分からないアレコレをかき集めてロボットを作るのって、子供心に夢があるというか、浪漫があるよな…。「ガンヘッド」もそういう感じだし…。

余談。原作者はタモリさんから絵本作家になることを薦められてこうなった、という話を目にして、タモリさんスゲーなと…。そりゃまあ、こういう話をいくら思いついても漫才コントの類では披露できんわな…。披露されても困る…。

2026/03/31追記 :


2026/03/21() [n年前の日記]

#1 [cg_tools][neta] 画像フィルタプラグインの共通規格は無いのだろうか

妄想メモ。

画像編集ソフトやお絵かきソフトを触っていて、ふとなんとなく思った。画像フィルタプラグインの共通規格って無いのかな…。

えてして画像編集ソフトのフィルタって、それぞれが自前で実装して組み込んであるのだろうと想像するわけだけど。そのせいで、やれこの画像編集ソフトはフィルタが少ないだの、この画像編集ソフトはフィルタ数が多いだの、このフィルタはこの画像編集ソフトでしか使えないだの、そういう話になってしまう。

もし、フィルタの共通規格があって、それに沿って作られていれば、ユーザが慣れ親しんだ画像編集ソフトがその規格に対応しているだけで、フィルタを選び放題になるのではないかと…。

例えば、DTM/DAWソフトがVSTiに対応してれば色んなソフトウェアシンセサイザーを選び放題だったりするわけだけど。そういう状況を画像編集ソフトというジャンル上でも実現できないものかなあ…。あくまでフィルタ処理に限っての話だけど。

これといったものは無いっぽい :

自分如きが思いつくネタなんて既に誰かが当の昔に思いついていて、ある程度文書化してあったり、そこそこ普及してたりするのではないか。

そう思ってググってみたのだけど…。見つからない…。どうやらそういう規格は無いっぽい?

これが動画編集ソフトというジャンルであれば、 _OpenFX (API)_Frei0r があるらしい。後者はFFMPEGから利用することもできるそうで。

_ffmpeg で使える frei0r フィルタの使い方 | ニコラボ
_ffmpegとFrei0r - suzuzusu日記

画像編集ソフト向け、静止画を対象にした規格は無いのだろうか。AI (Google Gemini) に尋ねてみたら、「Photoshopプラグイン(.8bf) や GEGL はどうか」と言ってきた。

Photoshopプラグインは、Photoshopのバージョン違いによる互換性の問題があり過ぎる…。SDKは入手可能らしいけど、おそらく仕様が公開されてるわけではないだろうし…。8bf対応と謳ってるフリーソフトを試用してみたけれど、使いたかったプラグインが動かなくてガッカリしたことが何度もある…。

GEGLは、ソフトに組み込んだ状態で使うものじゃないのだろうか…。後からユーザが何か作って追加するソレとはちょっと違うんじゃないかな…。

動画編集ソフト用のフィルタを画像編集ソフトで利用できないものだろうか。そう思って、OpenFX や frei0r について少し調べてみたけれど、難しそう…。

動画編集ソフト用なら AviUtl の .auf はどうだろう。AviUtl本体の作者様とは別の方が .auf を作成してる事例があるので、作れないというわけではないだろうけど…。

G'MICはどうか :

何百種類もの画像フィルタを使えるようにする G'MIC というフィルタ集があるけれど、それを画像編集ソフトが組み込むだけでも一気に利用できるフィルタ数が増えそうな気はする…。それでもいいんじゃないか…。

組み込めるようにするための、libgmic というものもあるらしい。

_G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing - Libgmic

また、Python から G'MIC を利用できるようにするためのパッケージもあるらしい。

_GreycLab/gmic-py: Python binding for the G'MIC Image Processing Framework

後は、G'MICに基本的な画像フィルタも用意されていれば、一々各自実装しなくても済みそうな…。確認してみたけれどガウスぼかし(Gaussian Blur)は入ってた。一般的によく見かけるフィルタは抑えてそうかも。

2026/03/22() [n年前の日記]

#1 [cg_tools][python] 別の実行バイナリに画像データを渡す方法を調べてた

画像編集ソフト用フィルタプラグインの共通規格って作れないのかなと妄想していたけれど、ふと疑問が湧いた。

画像編集ソフトから、フィルタプラグインの実行バイナリに、どうやって画像データを渡せばいいのだろう…?

例えば、GIMPのフィルタプラグインは実行バイナリ(.exe)の形で提供されているけれど、GIMPの実行バイナリが管理してる画像データ(レイヤーデータ)を、プラグインの実行バイナリに渡して処理をさせているわけだから…。ある実行バイナリから別の実行バイナリに画像データを渡すことは可能なのだろう。

AI(Google Gemini)に、どうやったらそんなことができるのか尋ねてみたところ、以下の方法を提示された。

方法その1。やり取り用の仮ファイルを作成して、それを別の実行バイナリに渡す。なるほど、その方法は分かりやすいな…。毎回ストレージ上に仮ファイルが作成されてしまうのがちょっとアレだけど…。

方法その2。各OSが持っているはずのパイプ機能を使う。標準入力とか標準出力とかそのあたりを利用して渡せるのだとか。

方法その3。共有メモリを介してやり取りする。

本当にできそうなのか実験してみた。環境は Windows11 x64 25H2 + Python 3.10.10 64bit。

パイプ機能で渡す方法 :

パイプを使って画像データを渡すPythonスクリプトをAI(Google Gemini)に作ってもらった。一発では動くスクリプトが出てこなかったけど、数回やり取りしたら動くようになった。

  • 親スクリプトは Pillow を使って画像を開いてから、子スクリプトを実行する。
  • 親スクリプトは、子スクリプトの標準入力(STDIN)に画像データを送る。画像データの先頭には画像の横幅と縦幅を付加しておく。
  • 子スクリプトは標準入力から得られた画像データに対して何らかの処理をする。今回はグレースケール化のみをしてみた。
  • 子スクリプトの処理の進捗具合は STDERR に出力される。親スクリプトは STDERR を読み取ってコンソールに出力する。
  • 親スクリプトは、子スクリプトの標準出力(STDOUT)から処理後の画像データを受け取って表示する。

_親スクリプト parent.py
import subprocess
import struct
import threading
from PIL import Image


def log_reader(pipe):
    """
    標準エラー出力をリアルタイムで読み取って表示する関数。
    メインスレッドとは別に動かすことで、子プロセスが吐き出すログを
    メインの読み書き処理を止めずに処理できます。
    """
    try:
        with pipe:
            # pipe.readline はデータが来るまで待機し、b''(空)が来たら終了
            for line in iter(pipe.readline, b""):
                # decode()でbytesを文字列に変換。strip()で末尾の改行を除去
                print(f"[Child Log]: {line.decode().strip()}")
    except Exception as e:
        print(f"Log error: {e}")


def run_example(image_path):
    # 画像を開き、RGBA形式(1ピクセル4バイト)に統一して読み込み
    img = Image.open(image_path).convert("RGBA")
    width, height = img.size
    img_bytes = img.tobytes()

    # 子プロセス(child.py)を起動
    # すべての入出力を PIPE で接続し、親からコントロール可能にする
    process = subprocess.Popen(
        ["python", "child.py"],
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        bufsize=0,  # バイナリデータのやり取りで遅延を防ぐためバッファリングを無効化
    )

    # 1. 進捗(stderr)を読み取る専用スレッドを開始
    # ※重要:ここを別スレッドにしないと、子プロセスがstderrに大量のログを出した際、
    #  OSのパイプバッファがいっぱいになり、子プロセスが停止(デッドロック)してしまいます。
    t = threading.Thread(target=log_reader, args=(process.stderr,))
    t.daemon = True  # 親スクリプトが異常終了してもこのスレッドが残らないように設定
    t.start()

    # 2. 子プロセスへデータを送信
    # child.py 側が待っている 8byte のヘッダー(幅・高さ)をパック
    header = struct.pack("ii", width, height)

    print(f"Sending image data ({width}x{height})...")

    # ヘッダーと画像本体を結合して stdin へ書き込み
    process.stdin.write(header + img_bytes)

    # 書き込み終了を明示的に伝える(EOFを送る)。
    # これにより、child.py 側の stdin.read() が「これ以上データが来ない」と判断し、処理が進みます。
    process.stdin.close()

    # 3. 処理済みデータ(stdout)を受信
    # stderr の読み取りは別スレッドに任せているため、メインスレッドは stdout の受信に専念できます
    print("Waiting for processed image...")
    result_bytes = process.stdout.read()

    # 子プロセスの終了を待ち、リソースをクリーンアップ
    process.wait()

    # ログ出力スレッドが残っている場合、最大1秒待機して同期をとる
    t.join(timeout=1)

    # 受信したバイナリを Pillow で画像オブジェクトに戻す
    if result_bytes:
        res_img = Image.frombytes("RGBA", (width, height), result_bytes)

        # プレビュー表示(Windowsのフォトアプリ等が起動します)
        res_img.show()

        print("Success: Image received and displayed.")
    else:
        print("エラー: データを受信できませんでした。")


if __name__ == "__main__":
    # カレントディレクトリに input.png がある前提
    run_example("input.png")

_子スクリプト child.py
import sys
import struct


def process_image_real_progress():
    # Windows環境などで改行コードの自動変換(\n -> \r\n)を防ぐため、
    # .buffer を使用してバイナリモードでストリームを扱います。
    stdin = sys.stdin.buffer
    stdout = sys.stdout.buffer
    stderr = sys.stderr

    # 1. ヘッダー読み込み。画像の幅と高さを取得
    # 親側で struct.pack('ii', w, h) して送られてくることを想定(4byte * 2 = 8byte)
    header = stdin.read(8)
    if not header:
        return

    # 'i'はsigned int (4byte)。リトルエンディアンで展開されます
    width, height = struct.unpack("ii", header)

    # 2. 全データ読み込み(一気に読み込んでメモリ上で保持)
    # RGBA 32bit (4byte) 前提の計算: width * height * 4
    # 大容量画像の場合はメモリ負荷に注意が必要ですが、1枚単位ならこの手法が高速です
    raw_data = stdin.read(width * height * 4)

    # 処理後のデータを格納するためのバッファを先に確保(不変なbytesではなく可変なbytearrayを使用)
    processed_data = bytearray(len(raw_data))

    # 3. 行単位でループ処理を行い、計算と進捗の書き出しを両立させる
    for y in range(height):
        # 処理対象の行のバイト配列上の開始・終了インデックスを計算
        row_start = y * width * 4
        row_end = row_start + (width * 4)

        # 1行分のピクセルを走査。4バイト刻み(R, G, B, A)で処理
        for i in range(row_start, row_end, 4):
            # RGBAの各要素を抽出
            r = raw_data[i]
            g = raw_data[i + 1]
            b = raw_data[i + 2]
            a = raw_data[i + 3]

            # 輝度計算 (ITU-R BT.601) に基づくグレースケール変換
            # 重み付け: R=0.299, G=0.587, B=0.114
            v = int(0.299 * r + 0.587 * g + 0.114 * b)

            # 処理結果を格納。RGBすべてに同じ輝度値を代入し、Alphaは元の値を維持
            processed_data[i] = v
            processed_data[i + 1] = v
            processed_data[i + 2] = v
            processed_data[i + 3] = a

        # 標準エラー出力(stderr)を使って進捗を表示
        # stdoutは画像データ用に使用しているため、混ざらないようstderrを使います。
        # 20行ごともしくは最終行で進捗を出力(頻繁なIOによる速度低下を防止)
        if y % 20 == 0 or y == height - 1:
            progress = int((y + 1) / height * 100)
            # \n を含めて書き出すことで、親プロセス側で readline() して取得可能
            stderr.write(f"Processing: {progress}%\n")
            stderr.flush()

    # 4. 変換済みの画像バイナリを一括して標準出力へ書き出し
    stdout.write(processed_data)

    # 明示的にフラッシュし、パイプの先(親プロセス)へデータを送り出す
    stdout.flush()


if __name__ == "__main__":
    process_image_real_progress()

対象画像は以下。

input.png

_input.png

以下で実行。
> python parent.py

Sending image data (512x512)...
Waiting for processed image...
[Child Log]: Processing: 0%
[Child Log]: Processing: 4%
[Child Log]: Processing: 8%
...
[Child Log]: Processing: 97%
[Child Log]: Processing: 100%
Success: Image received and displayed.

以下の結果になった。

result_ss01.png

たしかに、パイプを利用することで、親スクリプトから子スクリプトに画像データを渡して、フィルタ処理の結果を得ることができた。

共有メモリで渡す方法 :

Python 3.8 から、共有メモリを簡単に利用できる multiprocessing.shared_memory というライブラリが標準添付されるようになったらしい。その機能を使って親スクリプトから子スクリプトに画像データを渡してみる。これも AI(Google Gemini)に作ってもらった。

  • 親スクリプトは Pillow で画像を開いてから、子スクリプトを実行する。
  • 親スクリプトは、標準入力を利用して、子スクリプトに「共有メモリの名前」「画像の横幅」「縦幅」を渡す。
  • 子スクリプトは標準入力から「共有メモリの名前」「画像の横幅」「縦幅」を取得して、共有メモリ上の画像データにアクセスする。
  • 子スクリプト側の処理の進捗具合は STDERR を介して親スクリプトに伝える。
  • 処理結果は共有メモリを介して親スクリプト側が取得する。

_parent_shm.py
import subprocess
import struct
import threading
from multiprocessing import shared_memory
from PIL import Image


def log_reader(pipe):
    """子の進捗ログを読み取る"""
    with pipe:
        for line in iter(pipe.readline, b""):
            print(f"[Child Log]: {line.decode().strip()}")


def run_simple_shm(image_path):
    # 画像準備
    img = Image.open(image_path).convert("RGBA")
    width, height = img.size
    img_bytes = img.tobytes()
    size = len(img_bytes)

    # 1. 共有メモリの作成とデータ書き込み
    shm = shared_memory.SharedMemory(create=True, size=size)
    try:
        shm.buf[:size] = img_bytes

        # 2. 子プロセス起動
        # セマフォを使わないため、単純な Popen でOK
        process = subprocess.Popen(
            ["python", "child_shm.py"],
            stdin=subprocess.PIPE,
            stderr=subprocess.PIPE,
            bufsize=0,
        )

        # 進捗表示用スレッド
        t = threading.Thread(target=log_reader, args=(process.stderr,))
        t.start()

        # 3. メモリ情報を子に送信
        # 固定長 64byte の名前と、幅・高さの int を送る
        header = struct.pack("64sii", shm.name.encode(), width, height)
        process.stdin.write(header)
        process.stdin.close()

        # 4. 子の終了を待つ
        # これにより、子がメモリを書き換え終わるまで親は待機します(=同期)
        print("Child process is working...")
        process.wait()
        t.join()

        # 5. 処理結果をメモリから直接読み出して表示
        print("Displaying result from Shared Memory.")
        res_img = Image.frombytes("RGBA", (width, height), shm.buf[:size])
        res_img.show()

    finally:
        # 6. リソース解放
        shm.close()
        shm.unlink()


if __name__ == "__main__":
    run_simple_shm("input.png")

_child_shm.py
import sys
import struct
from multiprocessing import shared_memory


def process_shm_simple():
    # 1. 親からメモリ名と画像サイズを受信 (計72byte)
    # メモリ名(64byte) + 幅(4byte) + 高さ(4byte)
    header = sys.stdin.buffer.read(72)
    if len(header) < 72:
        return

    shm_name_raw, width, height = struct.unpack("64sii", header)
    shm_name = shm_name_raw.decode().strip("\x00")

    # 2. 既存の共有メモリに接続
    try:
        shm = shared_memory.SharedMemory(name=shm_name)
        data = shm.buf

        # 3. 画像処理(グレースケール化)
        # メモリを直接書き換えるため、戻り値を stdout で送る必要がありません
        for y in range(height):
            row_offset = y * width * 4
            for x in range(width):
                offset = row_offset + (x * 4)

                # RGBAを取得して輝度計算
                r, g, b, a = data[offset: offset + 4]
                v = int(0.299 * r + 0.587 * g + 0.114 * b)

                # 直接上書き
                data[offset] = v
                data[offset + 1] = v
                data[offset + 2] = v
                # Alphaは維持

            # 進捗報告(stderrを使用)
            if y % 20 == 0 or y == height - 1:
                progress = int((y + 1) / height * 100)
                sys.stderr.write(f"Progress: {progress}%\n")
                sys.stderr.flush()

        # 4. クローズ(アンリンクは親の役目)
        shm.close()

    except Exception as e:
        sys.stderr.write(f"Child Error: {e}\n")


if __name__ == "__main__":
    process_shm_simple()

実行は以下。
> python parent_shm.py

Child process is working...
[Child Log]: Progress: 0%
[Child Log]: Progress: 4%
[Child Log]: Progress: 8%
[Child Log]: Progress: 11%
...
[Child Log]: Progress: 97%
[Child Log]: Progress: 100%
Displaying result from Shared Memory.

パイプを使った場合と同じ結果が得られた。

共有メモリとやらを使うことでも、別の実行バイナリに画像データを渡して処理させることが可能と分かった。ただ、標準入力からアレコレ渡したり、STDERR で進捗状態を取得するのはどうなんだろうとは思うけど…。

とりあえずこういうことができるのであれば、GIMPのフィルタプラグインと同様に、実行バイナリの形でフィルタプラグインを公開配布することもできそうだなと…。いやまあ、そういう共通規格を作るとしたら、という話だけど。後は、どういうパラメータをどういうフォーマットで渡すかを考えれば形になるのかもしれない。ヘッダー部分に色々入れるとして、ヘッダーサイズを内包したり、画像データサイズを内包したり…。おそらくレイヤー情報を数枚渡す場合もあるだろうし…。

余談。今から規格を作る意味はなさそう :

余談。今回の実験で、別の実行バイナリ(フィルタプラグイン)に画像データを渡す方法はいくつかあると分かったけれど。仮に、こういった方法を利用してフィルタプラグインの規格を作ってみたとしても、おそらく誰も使わないだろうなと思えてきた。

と言うのも、既存の画像編集ソフトは既に自前で各フィルタを実装しちゃってるものが大半なので…。「今更そんな規格を提唱されてもねえ」「当の昔に自分で実装しちゃったからそんな規格は要らねえ」みたいな。

8bitPC時代のMSXみたいなものかも。MSX規格に沿ってなかった、それ以前からあったPC製品シリーズのほうがスペックは高いしやれることも多いから、今更MSX規格と言われてもウチはそんなの作りませんよ…みたいな。

これから画像編集ソフトを新規に開発する場合は、そういった規格があれば助かるのかもしれないけれど、「仕様を把握して対応するのが面倒臭いから独自実装でいいや」ということになりそうでもある…。

DTM/DAWソフトのVSTi/VSTeのようには行かないのだろうな…。

そう考えると、既にあるGIMPのプラグインを利用できるようにするラッパーを作るとか、G'MICを自作アプリに組み込むためのチュートリアル文書でも作ったほうが良さそうかもしれないなと…。

「そういうのはPhotoshopプラグインでいいじゃん」と言われそうな気もするけれど8bfはバージョン毎の互換性の問題が…。

#2 [anime] 「名探偵コナン 灰原哀物語〜黒鉄のミステリートレイン〜」を視聴

BS12で放送されていたので視聴。TVアニメ「名探偵コナン」の、TVシリーズ特別編集版、らしい。灰原哀というキャラにフォーカスを当てた…わけでもないか…。一応最初のあたりで件のキャラについての設定を紹介していたけれど、大半はミステリートレインを舞台にした話だった。

途中で出てきた 怪盗キッドがトリック(?)の肝になっていて、つくづく便利なキャラだなと…。

コナンの母親と敵の女性との関係を自分は知らないので、そのあたりのシーンは見ていて「???」になってしまった。知り合いなの? あの2人。自分はコナンシリーズってほとんど見ていないので各キャラの関係がさっぱり…。

2026/03/23(月) [n年前の日記]

#1 [cg_tools][gmic][python] G'MIC CLIを勉強中

G'MICという、無料で利用できる数百種類の画像フィルタ集がある。

_G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing - Main

一般的には、GIMP、Krita、Paint.NET等の画像編集ソフトから呼び出して、GUIでパラメータを指定して利用することがほとんどだろうけど…。この G'MIC には CLI版があって、ImageMagick っぽい感じのコマンドラインツールとして利用することもできる。

その G'MIC CLI (gmic.exe) の使い方について勉強中。

環境は Windows11 x64 25H2 + G'MIC CLI 3.7.4。

インストール :

公式ページの、「Command-line interface (CLI):」から入手。

_G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing - Download

gmic_3.7.4_cli_win64.zip を入手して解凍。今回は D:\home2\bin\gmic_cli\ に配置した。

余談だけど、G'MIC CLI 3.7.4 をインストールしたのに、バージョン表示は 3.7.3 になってるな…。
> gmic version

  gmic: GREYC's Magic for Image Computing: Command-Line Interface
        Version 3.7.3 (pre-release #26031110)
        (https://gmic.eu)

        Copyright (c) 2008-2026, David Tschumperlテゥ / GREYC / CNRS.
        (https://www.greyc.fr)

パスを通す :

環境変数PATHに G'MIC CLI (gmic.exe) のインストール場所を追加しておけば gmic.exe が使えるようになるけれど…。

自分の場合は実験時しか使わないだろうから、batファイルを実行した時だけ環境変数PATHに追加して使えるようにしてみた。このbatファイルはAI(Google Gemini)に作ってもらった。

gmic.bat
@echo off
if defined HOMEBIN (
    echo # HOMEBIN is defined: %HOMEBIN% >&2
    set "GMICCLIPATH=%HOMEBIN%\gmic_cli"
) else (
    echo # HOMEBIN is NOT defined. Using default path. >&2
    set "GMICCLIPATH=D:\home2\bin\gmic_cli"
)
where gmic.exe >nul 2>nul
if %ERRORLEVEL% neq 0 (
    echo # Not found gmic.exe. Adding to Path... >&2
    set "PATH=%GMICCLIPATH%;%PATH%"
    echo # G'MIC CLI is now enabled. [%GMICCLIPATH%] >&2
)
gmic.exe %*

gmic.bat を実行すると、gmic.exe が見えてるか見えてないかで処理を分けて、見えてない時だけ環境変数PATHの先頭にgmic.exeの場所を追加する。その後、同じコマンドプロンプトの中で gmic と打てば gmic.exe のほうが呼ばれる状態になる。

echo行の最後についている「>&2」は、STDERR に出力せよという指定。そのままだと標準出力(STDOUT)に出してしまうけれど、標準入力/標準出力を利用した実験をする時にマズいので、STDERR に出力するようにしておいた。

サンプル画像を使う :

G'MIC CLI(gmic.exe)には各種実験に使えそうなサンプル画像も同梱/内蔵されているらしい。

以下で取り出せる。
gmic sp lena o out.png
or
gmic sample lena output out.png
  • sp/sample : サンプル画像を利用するという指定。
  • lena : lena画像を指定。
  • o/output : 出力を指定
  • out.png : 今回の出力画像ファイル名。

リファレンスは以下にある。

_gmic_reference.pdf

リファレンスによると、サンプル画像として以下を指定できるらしい。めっちゃある…。わざわざ実験用画像を用意しなくても済むのはありがたい。
apples
balloons
barbara
boats
bottles
butterfly
cameraman
car
cat
cliff
chick
colorful
david
dog
duck
eagle
elephant
earth
flower
fruits
gmicky
gmicky_mahvin
gmicky_wilber
greece
gummy
house
inside
landscape
leaf
lena
leno
lion
mandrill
monalisa
monkey
parrots
pencils
peppers
portrait0
portrait1
portrait2
portrait3
portrait4
portrait5
portrait6
portrait7
portrait8
portrait9
roddy
rooster
rose
square
swan
teddy
tiger
tulips
wall
waterfall
zelda

標準出力に結果を出力 :

G'MIC CLI(gmic.exe)は、標準入力から画像データを受け取ったり、標準出力に画像データを送ったりすることができるらしい。

標準出力に画像データを送る例。サンプル画像「tiger」を、標準出力に、pngフォーマットで送っている。
gmic sample tiger output -.png > out.png
  • 「-」という指定は標準入力や標準出力を示す。
  • その後に続く拡張子指定 ―― 「.png」等で画像フォーマットを指定する。
  • 「> out.png」により標準出力の結果を out.png としてファイル保存する。リダイレクトと呼ぶらしい。


gmicで標準出力に画像データを送り、パイプを経由して別のgmicの標準入力に渡して、グレースケール化して、また標準出力に送ってファイル保存する例。
gmic sp lena o -.png | gmic input -.png to_gray o -.png > out.png
  • sp lena : サンプル画像として lena を用意している。sample lena と書いても良い。
  • o -.png : 標準出力にpngフォーマットで出力。 output -.png と書いても良い。
  • 「|」がパイプ。標準出力を標準入力に渡すための指定。
  • input -.png : 標準入力からpngフォーマットの画像を受け取る。i -.png と書いても良い。
  • to_gray : グレースケール化。luminance を指定しても似た結果になる。
  • > out.png : 標準出力の結果を out.png としてファイル保存。


ベタデータで送る場合は以下。
gmic sp lena o -.raw,uint8 | gmic i -.raw,uint8,512,512,1,3 to_gray o -.png > out.png
  • -.raw,uint8 で、ベタデータをbyte単位で送るという指示になる。
  • 受け取る側は、-.raw,uint8,横幅,縦幅,枚数,チャンネル数、を指定する…のだと思う。最後のあたりは理解が怪しい。
  • ベタデータの場合は、画像サイズ、枚数、チャンネル数などが分からないので、それらの情報も伝えないといけない。
  • RGB画像ならチャンネル数は3に、RGBA画像ならチャンネル数は4になる。

標準入力から画像データを読み込んで表示するPythonスクリプト :

gmic から標準出力に画像を送った際、どんな画像になったのか確認するのが面倒臭い。標準入力から画像データを読み込んで表示するPythonスクリプトをAI(Google Gemini)に作成してもらった。

環境は Windows11 x64 25H2 + Python 3.10.10 64bit。Pillow 11.3.0 + tkinter を使ってる。

_view_stdin.py
import sys
import io
import tkinter as tk
from PIL import Image, ImageTk

def display_in_tkinter():
    # 1. 標準入力からバイナリデータを読み込む
    input_data = sys.stdin.buffer.read()
    if not input_data:
        print("Error : Not found data")
        return

    try:
        # 2. Pillowで画像データとして読み込み
        pil_img = Image.open(io.BytesIO(input_data))
        
        # 3. Tkinterウィンドウの設定
        root = tk.Tk()
        root.title("Stdin Image Viewer")

        # --- キーバインド設定 ---
        # ESCキー、大文字Q、小文字q のいずれかでウィンドウを閉じる
        root.bind('<Escape>', lambda e: root.destroy())
        root.bind('<q>', lambda e: root.destroy())
        root.bind('<Q>', lambda e: root.destroy())

        # 4. Pillowの画像をTkinter用のフォーマットに変換
        tk_img = ImageTk.PhotoImage(pil_img)

        # 5. ラベルウィジェットに画像をセットして配置
        label = tk.Label(root, image=tk_img)
        label.pack(padx=10, pady=10)

        # 6. Closeボタンの追加
        # command=root.destroy を指定することでクリック時に終了します
        btn = tk.Button(root, text="Close (Q)", command=root.destroy, width=20)
        btn.pack(pady=5)

        # ウィンドウを表示
        root.mainloop()

    except Exception as e:
        print(f"Error : {e}")

if __name__ == "__main__":
    display_in_tkinter()
  • ESCキー、Qキーを押せば終了する。


以下のような感じで使える。
cat lena.png | py view_stdin.py
gmic sp lena o -.png | py view_stdin.py

以下のような見た目になる。

view_stdin_ss01.png

Ubuntu Linux上でインストールされるバージョン :

Ubuntu Linux 24.04 LTS上で gmic をインストールするとバージョンは何になるのかが気になった。Ubuntu Linux 24.04 LTS をベースにしている Zorin OS 18 上で確認してみた。

sudo apt install gmic
sudo apt install imagemagick

```
$ gmic version

  gmic: GREYC's Magic for Image Computing: command-line interface
        Version 2.9.4
        (https://gmic.eu)

        Copyright (c) 2008-2026, David Tschumperle / GREYC / CNRS.
        (https://www.greyc.fr)

$ convert -version
Version: ImageMagick 6.9.12-98 Q16 x86_64 18038 https://legacy.imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC Modules OpenMP(4.5) 
Delegates (built-in): bzlib djvu fftw fontconfig freetype heic jbig jng jp2 jpeg lcms lqr ltdl lzma openexr pangocairo png raw tiff webp wmf x xml zlib

gmic 2.9.4、ImageMagick 6.9.2-98 Q16 か…。古いね…。

ImageMagick が7系ではなく6系なのは、他のアプリとの兼ね合いなんだろう…。6系はコマンド名が convert だけど、7系では magick になっていたはずだし…。

Ubuntu Linux系なら、例えば以下で gmic の動作確認ができる。
gmic sp lena o -.png | display -
  • 標準出力の内容を確認するには ImageMagick の display が使える。
  • 「-」を記述することで標準入力/標準出力であることを指定する。

2026/03/24(火) [n年前の日記]

#1 [cg_tools] ImageMagickのdisplayのWindows版は無いのだろうか

アレコレ実験しているうちに、標準入力から画像データを受け取って表示するツールは無いのかなと思えてきた。Linux環境であれば ImageMagick の display を使えるのだろうけど、Windows上ではどうすれば…。

Windows版の ImageMagick には display は無いらしい。その代わり、昔は imdisplay というツールが付属していた。ただ、最近の ImageMagick ではサポートされなくなって、同梱されなくなった。

_ImageMagick/IMDisplay
_IM Display missing in Windows - ImageMagick/ImageMagick - Discussion #7399
_Shortcut "ImageMagick Display" is pointing to old version - 7.1.1.29 - Issue #7246 - ImageMagick/ImageMagick
_How to pipe an image to imdisplay (on Windows)? - ImageMagick/ImageMagick - Discussion #2164
_Windows installation win: and show: don't work - Issue #7609 - ImageMagick/ImageMagick
_WriteBlob Failed 'win:.' Can't figure out why. - Issue #667 - emcconville/wand

そもそも imdisplay は標準入力から画像データを受け取ることができない、という話も出ているようで…。

また、以前は代わりに「win:」なる指定を使うこともできていたらしいけれど、それも最近はサポートされなくなったようで…。

ImageGlassがお勧めされている模様 :

ImageMagick のメンテナさんは「代わりに ImageGlass を使え」「内部で ImageMagick が使われているから imdisplay と似たようなもの」と言及しているけれど、その ImageGlass も標準入力から画像データを受け取って表示する機能は無いっぽいのだよな…。

_ImageGlass - A lightweight, versatile image viewer

ただ、ImageGlass には、開いてる画像が更新されたら自動で表示更新する機能があるので、処理結果の画像ファイル名を同じ名前にして ImageGlass で開いておけば、実験中に結果画像を確認できる。

まあ、標準入力/標準出力を利用して画像処理の実験をする機会自体が少ないだろうし…。そういうツールが無くてもフツーは困らないのだろうな…。

#2 [gmic][imagemagick] gmicとImageMagickを繋げる

コマンドラインで画像処理ができるツール、ImageMagick の convert (magick convert) も、標準入力や標準出力を利用することができるらしい。

下記の例では、convert が標準入力から受け取った画像データにガウシアンぼかしをかけて標準出力に送っている。
cat input.png | convert - -gaussian-blur 10x10 - | py view_stdin.py


ベタデータを扱う際は、.raw の指定が使える模様。ただ、ベタデータは、画像サイズ、チャンネル毎の深さ、チャンネル数(RGB/RGBA)の情報を持っていないので、それらは別途指定しないといけない。
convert lena.png rgb:-.raw | convert -depth 8 -size 512x512 rgb:-.raw out.png

gmicとの連携 :

gmic と組み合わせてみたけれど…。

gmic sp tiger o -.raw | convert -depth 8 -size 750x500 rgb:- out.png

変な画像になってしまった。RGBチャンネルが順に並んだ白黒画像になっているように見える。

gmic と ImageMagick は .raw の画像データの並びが違っていて、そのせいで gmic の出力結果を ImageMagick側で正しく処理できないらしい。
  • gmicは、RRRRRR,GGGGGG,BBBBBB の並びになっている。
  • ImageMagick は、RGB,RGB,RGB,RGB... の並びになっている。

gmic 側に permute cxyz を指定することで、ImageMagick 側と同様のデータの並びに変更することができる模様。

以下の指定で、gmic が内蔵しているサンプル画像 tiger が再現された。
gmic sp tiger permute cxyz o -.raw | convert -depth 8 -size 750x500 rgb:- out.png


convert (ImageMagick)側の最後の出力を標準出力にしてみる。
gmic sp tiger permute cxyz o -.raw | convert -depth 8 -size 750x500 rgb:- png:- | py view_stdin.py
  • png:- と記述することで、標準出力に pngフォーマットで送るという指示になる。


ImageMagick側でガウシアンぼかしをかけてみる。
gmic sp tiger permute cxyz o -.raw | convert -depth 8 -size 750x500 rgb:- -gaussian-blur 10x10 png:- | py view_stdin.py

#3 [gmic][python] rawデータに変換してgmicに渡して処理をさせる

画像を読み込んで、gmic用rawデータの並びに変換して、標準出力に送るPythonスクリプトを、AI(Google Gemini)に作成してもらった。これを使って gmic の標準入力に画像データを渡して処理ができるか確認したい。

環境は Windows11 x64 25H2 + Python 3.10.10 64bit + Pillow 11.3.0。

_img2raw.py
import sys
import argparse
from PIL import Image


# 画像を読み込み、指定された形式のRAWデータとして標準出力に送る
def image_to_raw(image_path, interleaved=False):
    try:
        with Image.open(image_path) as img:
            # アルファチャンネルの有無を判定して適切なモードへ変換
            if "A" in img.getbands():
                img = img.convert("RGBA")
            else:
                img = img.convert("RGB")

            if interleaved:
                # ピクセル並びをインターリーブ形式(RGBRGB... / RGBARGBArgba...)にする
                # tobytes() は Pillow のメモリレイアウト(インターリーブ)をそのまま返す
                sys.stdout.buffer.write(img.tobytes())
            else:
                # プレーンごとに並べる Planar形式 (RRR...GGG...BBB...)
                # split() で各チャンネルに分離して順番に書き出す
                channels = img.split()
                for channel in channels:
                    sys.stdout.buffer.write(channel.tobytes())

    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="Convert image to RAW data and send to stdout."
    )
    parser.add_argument("input", help="Input image file path.")
    parser.add_argument(
        "-i",
        "--interleaved",
        action="store_true",
        help="Output in interleaved format (RGBRGB... / RGBARGBArgba...).",
    )

    args = parser.parse_args()
    image_to_raw(args.input, interleaved=args.interleaved)

使い方は以下。

python img2raw.py lena.png > out.raw

py img2raw.py lena.png | gmic i -.raw,uint8,512,512,1,3 blur 10.0 o -.png > out.png
py img2raw.py lena.png | gmic input -.raw,uint8,512,512,1,3 blur 10.0 output -.png > out.png

py img2raw.py -i lena.png | convert -depth 8 -size 512x512 rgb:- png:- > out.png

rawデータは、画像サイズ、枚数、チャンネル数などの情報を持っていないので、それらの情報は別途指定して読み込む必要がある。

#4 [anime] 「数分間のエールを」を視聴

Eテレで放送されていた版を録画していたので視聴。日本で制作されたCGアニメ映画。MV制作を趣味にしている少年が主人公のストーリー。という説明で合ってるのかどうか…。

これは…いいな…。実にイイ感じの映画なのでは…。何かしらを作ったことがある人にはちょっと色々と刺さってきそうな内容のように思えた。素晴らしい。

脚本は花田十輝さん。少年少女の青春モノ企画ならまずこの人でしょう的ポジションになってる印象だけど、まとめ方、仕上げ方が上手いなあ…。さすがや…。

セルルックのようでいてちょっと違う、独特なスタイルの映像だったので、制作状況が気になってググってしまった。

_『数分間のエールを』No.1:映像制作チーム Hurray! が送る、初の劇場アニメーション
_『数分間のエールを』No.2:ルックデベロップメントと、「未明」MVの制作
_『数分間のエールを』No.3:モーションキャプチャと、画づくりの変遷

これまでMV制作を行ってきた映像クリエイター3人がコアメンバーになりつつ、別スタジオにも手助けしてもらって作った感じだったらしい。劇場アニメなのに基本3人で作ってしまうなんて、凄い時代になった…。

メインツールが blender だったとのことで「マジか」と思ってしまった。blenderでここまでの映像が作れてしまうのかと感心。手描きアニメの後追いにならないように映像スタイルについては独自性を追求したというのがまたイイ感じ。このスタイルのアニメ映像には新鮮さを感じた。

各カットにPCアプリのアレコレが挿入される見せ方にも感心。あの手のソレは、使ってる人なら瞬時に分かる記号のようなものになってきているのだなと…。

なにはともあれ、これはいいものを見せてもらったという印象。このアニメは良い。実に良い。素晴らしい。

2026/03/25(水) [n年前の日記]

#1 [gmic] G'MIC CLIについて勉強中。その2

コマンドラインで画像フィルタ処理ができる、G'MIC CLI (gmic.exe) について勉強中。環境は Windows11 x64 25H2 + G'MIC CLI 3.7.4 (内部バージョンは3.7.3のまま。たぶんバグだろう…)。

デフォルトパラメータの指定 :

gmic のフィルタの中には、引数が要らないものと、引数が必要なものがある。

以下は引数が不要な例。グレースケール化フィルタを使ってる。
gmic sp lena to_gray o -.png | py view_stdin.py

引数が必要な場合は以下のような記述になる。
gmic sp lena glow 16 o -.png | py view_stdin.py
gmic sp lena boxfitting 2,16,0.25,1 o -.png | py view_stdin.py

ただ、引数が必要なフィルタは、えてしてデフォルト値を持っている。デフォルトパラメータを指定したい時は「,」を記述すればいいらしい。
gmic sp lena glow , o -.png | py view_stdin.py
gmic sp lena boxfitting , o -.png | py view_stdin.py

gmic parse_cliが動かない :

チュートリアル記事には、以下を打てば apply という文字列を含んだコマンドの一覧が表示されるとあるのだけど。

_Start Here

gmic parse_cli print,apply

試してみても何も出てこなくて悩んでしまった。環境は Windows11 x64 25H2 + gmic 3.7.4 / Ubuntu Linux 22.04 LTS + gmic 2.9.4。


以下を打ったら状況が変わった。
> gmic update

[gmic]./ Start G'MIC interpreter (v.3.7.3).
[gmic]./ Update command definition file 'C:\Users\USERNAME\AppData\Roaming\gmic\update373.gmic' from the G'MIC server.
[gmic]./ End G'MIC interpreter.

おそらくだけど、ネット上から update373.gmic を入手して所定の場所に置かれたように見える。

この後、以下を打ったらチュートリアル記事にあったように表示されるようになった。
> gmic parse_cli print,apply

[gmic]./ Start G'MIC interpreter (v.3.7.3).
[gmic]./ Parse '#@cli' command(s) 'apply' and output in 'print' mode.
apply_camera3d
apply_camera
...
apply_video
[gmic]./ End G'MIC interpreter.

C:\Users\USERNAME\AppData\Roaming\gmic\ を眺めてみると、update351.gmic だの update373.gmic が入っていた。数字部分はおそらく gmic のバージョン番号だろう…。gmic parse_cli は update???.gmic を読み取って、その中に記述されてるコマンドについて表示する仕様なのかもしれない。

とにかく、gmic CLI をインストールしたら gmic update を打っておけ、ということかな…。

ただ、Ubuntu Linux 22.04 LTS + gmic 2.9.4 で gmic update と打っても、gmic parse_cli print,apply の結果は変わらなかった。Windows版限定なのか、それとも gmic 3.x なら効果があるのか…。


余談。Ubuntu Linux 20.04 LTS上で gmic をインストールしたら 2.4.5 だった。gmic 2.4.5 の時点では parse_cli というコマンドは実装されてないように見えた。

余談その2。件のフォルダの中には、ここ最近使用したサンプル画像も入ってた。gmic sample lena 等でサンプル画像を使おうとすると、ネットからダウンロードして件のフォルダに置かれるということかも…。最初から内蔵してるわけじゃなさそうだな…。たぶん。

#2 [nitijyou] 洗面所の掃除用に歯ブラシを購入

Seriaヨークベニマル須賀川西店で、洗面所の掃除用に歯ブラシを購入。


歯ブラシは洗面所の掃除に使う予定。親父さんが入れ歯を洗面所で洗うたびにポリグリップ的なものを排水溝にそのまま流して詰まってしまうので、家族が歯ブラシの類で排水溝周りを掃除しないといけないのだけど。一度使ったら歯ブラシの毛がポリグリップだらけでベタベタになるから捨てるしかなく。使い古しの歯ブラシの在庫が全部無くなってしまった。新品でもったいないけど仕方ない…。

カーテンクリップは、ネズミ捕りの餌を仕掛けるのに使えないかと…。今まで干し芋(さつまいも)を糸で縛ってつけてたけど、手がベタベタになるので悩んでいて…。これならバチンと挟むだけで済むんじゃないか。済むといいな…。

#3 [nitijyou] 日記をアップロード

2026/02/28を最後に日記をアップロードしてなかったのでアップロードしておいた。

2026/03/26(木) [n年前の日記]

#1 [gmic] G'MIC CLIについて勉強中。その3

G'MIC CLI、及び G'MIC-Qt について勉強中。

環境は、Windows11 x64 25H2 + G'MIC CLI 3.7.4 (内部では 3.7.3 という扱いになってる)。

GIMPからG'MIC CLIを呼び出して処理させる :

GIMP 2.10.38 Portable から G'MIC CLI 3.7.4 (gmic.exe) を呼び出して、画像フィルタ処理ができるかどうか実験してみた。環境は Windows11 x64 25H2。

GIMP の Python-Fuスクリプトを作って実験した。
  1. レイヤー内容をベタデータ(raw)にして、
  2. パイプで gmic.exe の標準入力に送り、
  3. gmic.exe に何らかの処理をさせたら結果を標準出力に出させて、
  4. パイプ経由で GIMP の Python-Fuスクリプトが受け取って、
  5. 新規レイヤーを作って書き込む。

念のために書いておくけれど…。G'MIC は GIMP用に G'MIC-Qt plug-in for GIMP というプラグインを用意してあって、そのプラグインを導入すればGUIでパラメータを指定して G'MIC に処理をさせることができてしまう。だから、今回作成したスクリプトに実用性は全く無い。これっぽっちもない。「GIMP で G'MIC を使いたい? G'MIC-Qt plug-in を使いましょうね」で終わる話。

じゃあどうしてこんなスクリプトをわざわざ作成したのかと言うと…。何らかの画像処理ソフトから、G'MIC CLI(gmic.exe) のような外部プログラムに、標準入力/標準出力を使って画像データを送ってフィルタ処理をさせることが本当にできるのかどうかを実証したかったから。

こういうことができるなら、標準入力/標準出力でやり取りすることが前提の、フィルタ処理しかしない実行バイナリを作るだけでも、画像処理ソフト側から利用できるフィルタの種類を増やしていくことができたりするのかなあ、と…。

ソースは以下になった。かなりの部分を AI(Google Gemini)に作ってもらった…。

_m256_gmic_cli_pipe.py
"""
GIMPからG'MIC CLI(gmic.exe)を呼び出して処理ができるか実験。
GIMPのレイヤー内容をベタデータにして、
gmic.exe の標準入力にパイプで送り、
処理結果を標準出力に出させてパイプで受け取り、
新規レイヤーに書き出すPython-fuスクリプト。
外部のexeにフィルタ処理をさせられるかどうかの実験。

by mieki256

* Menu : Filters > Misc > G'MIC CLI Pipe...
* Windows11 x64 25H2 + GIMP 2.10.38 Portable
* Ver. 0.0.1  2026.03.25 初版。
"""

from gimpfu import *
import subprocess
import os
import array


# GIMP(Interleaved) -> G'MIC(Planar)
def convert_to_planar(interleaved_raw, width, height, bpp):
    """GIMPのRGBRGB...形式をG'MICのRRR...GGG...形式に変換する"""
    interleaved_data = array.array("B", interleaved_raw)

    planar_list = []
    for c in range(bpp):
        # 各チャンネルのデータを抽出 (スライス [開始:終了:ステップ] を利用)
        planar_list.append(interleaved_data[c::bpp])

    # 全チャンネルのデータを結合してバイナリ文字列で返す
    return "".join([c_data.tostring() for c_data in planar_list])


# G'MIC(Planar) -> GIMP(Interleaved)
def convert_to_interleaved(planar_raw, width, height, bpp):
    """G'MICのRRR...GGG...形式をGIMPのRGBRGB...形式に復元する"""
    num_pixels = width * height
    received_planar = array.array("B", planar_raw)

    # 空の配列を用意して、チャンネルごとに値を埋め戻す
    output_interleaved = array.array("B", [0] * (num_pixels * bpp))
    for c in range(bpp):
        # c番目のチャンネルデータを抽出
        channel_data = received_planar[c * num_pixels: (c + 1) * num_pixels]
        # インターリーブの位置 [c, c+bpp, c+2bpp...] に代入
        output_interleaved[c::bpp] = channel_data

    return output_interleaved.tostring()


def python_fu_gmic_cli_pipe(image, drawable, gmic_dir, gmic_command):
    """メイン処理"""

    # G'MIC CLIの場所を一時的に環境変数PATHの先頭に追加する
    if gmic_dir and os.path.isdir(gmic_dir):
        current_path = os.environ.get("PATH", "")
        os.environ["PATH"] = gmic_dir + os.pathsep + current_path
    else:
        gimp.message("Invalid directory.")
        return

    # ユーザー入力をスペースで分割してリスト化
    user_cmds = gmic_command.split() if gmic_command else ["blur", "2"]

    image.undo_group_start()  # undoできるようにしておく

    # レイヤーの横幅、縦幅、チャンネル数を取得
    width = drawable.width
    height = drawable.height
    bpp = drawable.bpp  # RGBなら3, RGBAなら4

    # GIMP(Interleaved) -> Planar 変換
    gimp.progress_init("Preparing Planar data...")
    pr = drawable.get_pixel_rgn(0, 0, width, height, False, False)
    planar_data = convert_to_planar(pr[0:width, 0:height], width, height, bpp)

    # G'MICの引数構築
    # 入力: -.raw,uint8,幅,高さ,1,チャンネル数 (G'MICのraw指定は w,h,d,s)
    # 出力: -.raw,uint8
    # "-" は標準入力/標準出力を示す
    gmic_exe = "gmic.exe" if os.name == "nt" else "gmic"
    cmd = [
        gmic_exe,
        "i",
        "-.raw,uint8,{w},{h},1,{c}".format(w=width, h=height, c=bpp),
    ]
    cmd.extend(user_cmds)  # ユーザーが入力したコマンドを挿入
    cmd.extend(["cut", "0,255", "o", "-.raw,uint8"])  # 出力設定を追加

    # パイプの構築
    try:
        proc = subprocess.Popen(
            cmd,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            env=os.environ,
            shell=(os.name == "nt"),
        )

        # パイプへ送信してgmic側で受信
        pdb.gimp_progress_set_text("G'MIC processing...")
        stdout_data, stderr_data = proc.communicate(input=planar_data)

        if proc.returncode != 0:
            gimp.message("G'MIC Error: " + stderr_data)
            return

        # Planar -> GIMP(Interleaved) 復元
        pdb.gimp_progress_set_text("Restoring Interleaved data...")
        interleaved_bytes = convert_to_interleaved(stdout_data, width, height, bpp)

        # レイヤーへの書き出し
        new_layer = gimp.Layer(
            image, "G'MIC Output", width, height, drawable.type, 100, NORMAL_MODE
        )
        image.add_layer(new_layer, 0)

        pr_new = new_layer.get_pixel_rgn(0, 0, width, height, True, True)
        pr_new[0:width, 0:height] = interleaved_bytes

        new_layer.flush()
        new_layer.merge_shadow(True)
        new_layer.update(0, 0, width, height)

    except Exception as e:
        gimp.message("Error: " + str(e))

    image.undo_group_end()
    gimp.displays_flush()  # 画像の表示を更新
    return


# ----------------------------------------
# GIMPへのメニュー登録、ダイアログの指定
register(
    "python-fu-gmic-cli-pipe",  # プロシジャの名前
    "Process layer with G'MIC CLI via pipe",  # プロシジャの説明文
    "Sends raw pixel data to gmic.exe and receives processed data.",  # PDBに登録する追加情報
    "mieki256",  # 作者名
    "mieki256",  # Copyright
    "2026.03.25",  # 作成日
    "G'MIC CLI Pipe...",  # メニュー名
    "RGB*",  # 対応する画像タイプ
    # ダイアログの指定
    [
        # (型, 変数名, 説明文, デフォルト値)
        (PF_IMAGE, "image", "Input image", None),
        (PF_DRAWABLE, "drawable", "Input drawable", None),
        (PF_DIRNAME, "gmic_dir", "G'MIC CLI location", "D:\\home2\\bin\\gmic_dir\\"),
        (PF_STRING, "gmic_command", "G'MIC Command", "blur 10"),
    ],
    [],  # 戻り値の定義
    python_fu_gmic_cli_pipe,  # 処理を埋け持つ関数名
    menu="<Image>/Filters/Misc",  # メニューの登録場所
)

main()  # プラグインを駆動させるための関数

  • GIMP側では、フィルタ → Misc → G'MIC CLI Pipe... で呼び出せる。
  • ダイアログ上で、G'MIC CLI が入っているディレクトリと、任意の G'MIC用コマンドを指定できる。

実行すれば、G'MIC CLI でフィルタ処理をして結果を取得することができる。

これで一応、標準入力/標準出力を利用して、外部の実行バイナリに画像データを送ったり、受け取ったりすることができそうだと分かった。おそらくだけど、ImageMagick等もこんな感じで利用できる可能性がありそう。

ただ、一般的にはこういうのって共有メモリを使ってやり取りするものじゃないのかなという気も…。その場合OS毎に異なる処理を書かないといけないよな…。クロスプラットフォーム対応にはならないかも…。いやまあ、今回書いたスクリプトも、おそらく Windows上でしか動かないものになってそうだけど。

一番簡単なのは、一時ファイルを作成してやり取りすることかもしれない。毎回ストレージを汚す(?)のがちょっと気になるけれど…。


余談。今回、ベタデータの並びの違いでちょっとハマった。
  • GIMP側のベタデータは RGB,RGB,RGB... の順で並んでる。
  • G'MIC CLI側のベタデータは RRRRR,GGGGG,BBBBB の順で並んでる。

G'MIC側で並びを変更することができないかなと、 _permute というコマンドを試してみたけれど、その場合フィルタ処理が正しく行われない状態になってしまって…。仕方なく、Python-Fu側で並びを変換してから送り付けて、受け取ったデータもPython-Fu側で並びを変換して使うことにした。

GIMP の Python-Fu が Pillow を使えたら、並びを変換するあたりの処理をもっと簡単に書くことができたんだけど…。画像処理ライブラリを、GIMP側とPython側で2つ持ってしまうことになるだろうけど、Python側でも持っていれば楽になるところが多いのではないかと思うのだよなあ…。

endlについて :

G'MIC には、かつて watercolor というフィルタが存在していたらしいのだけど、何らかの理由で現行版のリストから削除されてしまったそうで…。

_G'MIC Watercolor Effect? - GIMP Chat
_watercolor effect? - Software - discuss.pixls.us

一説によると、RGB画像なら処理できるけどRGBA画像は処理できなくていきなりエラーが出るから削除されたとか、作者がメンテナンスしなくなったので削除されたとか、コードが多過ぎるので削除されたとか…。理由ははっきりしていないっぽい。

しかし、ソースコードは残っているので、user.gmic に自分で追加して使えた時期があるらしい。ただ、G'MIC 3.7.4 の段階ではエラーを出して動作しない。

どうにか動かせないものかなと試していたら、G'MICの仕様がちょっとだけ分かったのでメモ。

まず、中で fx_gaussian_blur を使おうとしているけれど、そういう名前のフィルタは現行版G'MICでは無くなっている。ただ、fx_blur_gaussian という名前のフィルタは存在している模様。試しに fx_blur_gaussian に置換してみたら該当箇所でエラーは出なくなった。

もう一つ、一番最後の「endl a c endl done」という行で「endl なんてコマンドは知らねえよ」とエラーが出る。何だこれは…。どういう意味の指定なんだ…。

ググっていたら、ちょっと分かってきた。

_G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing
_local(l) … done

  • G'MIC は local - endlocal というブロック?を指定することができる。
  • endlocal は endl と省略形を書いて済ませることができたらしい。
  • 現行版 G'MIC では、local - done と書いてしまっていいことになってる。

AI(Google Gemini) によると、「最近の G'MIC はブロックの終了を示すコマンドについて、done と書いておけば済むことになりました」とのこと。AIがそう言っている。嘘かもしれんけど。

すると「endl a c endl done」は、以下の指定だったのだろう。
  • local - endlocal のブロックを2つ閉じて、
  • もう一つ何かのブロックを done で閉じる。

そして、現行版に合わせて書くなら done を3つ書けばいいということになりそう。

途中に入ってる「a c」は何だろう? もしかすると「append c」の略だったりしないか…? リファレンスの「Command Shortcuts:」のあたりで、a は append と書いてあるし…。c は cut の省略形とも書いてあるけれど、ソースの上のほうに変数らしき感じで何度も出現してるから、ここでは変数扱いなのではないかな…。

_gmic_reference.pdf

そんなわけで、以下のように書き換えてみた。
endl a c endl done

↓

done
append c
done
done

この状態にしたらエラーが出ずに動作するようになった。

ただ、以前行っていた処理内容と全く同じ処理をしているのか、そこは分からない…。途中で使われている各種フィルタの仕様が変わってしまっている可能性もあるので…。ただ、一応それっぽい感じのフィルタ処理になっている感じはする…。

消えると怖いので一応置いておく。

_watercolor.gmic.txt

G'MIC-Qt plug-inの中にサンプル画像があった :

GIMP + G'MIC-Qt plug-in の動作を確認していたら、サンプル画像を出すこともできると分かった。「sample」で検索すれば「Sample Image」が出てくる。lena や dog や tiger 等々選び放題。

キャンバスサイズよりサンプル画像のサイズが大きい場合は、キャンバスサイズがサンプル画像の大きさに変更される。

GIMP側で、画像 → キャンバスをレイヤーに合わせる、を選べば、キャンバスサイズをレイヤーサイズに変更することができる。

G'MICのdemoがスゴイ :

G'MIC-Qt のフィルタ種類について確認していたら。「Games & Demos」というのがあって、選んでみてちょっと驚いてしまった。パックマンが動いてる…。まあ、起動するまで時間がかかるけど…。

つまり、G'MICのスクリプトはこのぐらいの処理なら全然実現できる可能性を秘めてますよ、ということなんだろうな…。そりゃまあ、変数やIF文が使えるみたいだし、プログラムだって書けるということなんだろうけど…。

日本語名のフィルタがほとんど動かない :

Windows11 x64 25H2 + GIMP + G'MIC-Qt 3.7.4 を試用していたら、日本語名で表示されてるフィルタのほとんどが動作しないことに気づいた。何故…。全部動かないのかと思ったら、中にはちゃんと動くものもある。何故…。

ただ、同じ処理をするフィルタが英語名でも用意されてるようで、そちらを使えば実用上の問題は無いのかなと…。

2026/03/27(金) [n年前の日記]

#1 [golang] 標準入力から受け取った画像データを表示する簡易ビューワを作った

先日、Pythonを使って、標準入力から受け取った画像データを表示するスクリプトを作成してみたけれど。

_mieki256's diary - G'MIC CLIを勉強中

似た処理をする実行バイナリ(exe)を作れるのかどうかが気になってきたので、試しに Go言語 1.25.7 + fyne で作成してみた。ほとんど AI(Google Gemini)に作成してもらったような気もするけれど…。

せっかくだから github にアップロードしておいた。

_mieki256/siiview: 標準入力から受け取った画像データをウインドウ表示するGo言語製簡易ビューワ

このプログラムを作成したことで、Go言語で作成した実行バイナリも標準入力からデータを受け取って処理することが可能と分かった。

でもまあ、使う機会はほとんどないけれど…。もし、使うとしても、先日作ったPythonスクリプトのほうが対応する画像形式が多いだろうし…。

#2 [anime] 「ミッチェル家とマシンの反乱」を視聴

Eテレで放送された版を録画していたので視聴。海外のCGアニメ映画。2026/01/02放送と記録されてた。ようやく消化できた…。

タイトルから、ホームコメディアニメなのかなと勝手に想像していたけれど、実際に見てみたらSFアクションアニメだった…。ええ…そういうアニメだったんだ…。

CGアニメなのだけど、非リアル系のスタイルを追求したのであろう映像になっていて…。服や肌のテクスチャは手塗り感があるテクスチャになってたり、背景のCGモデルも昔の手描きアニメの質感に似せてあったりして、CGアニメの世界も随分前からアナログ感の取り込みを意識する状況になってきているのだなあと…。

また、キャラの顔の周りに、ハートマークだの、虹だの、日本で言うところの漫符に近い何かが上乗せされていて…。アレは何だろう。デコレーション? プリクラとかでよく見かけるヤツだけど…。そういうものをガンガン挿入するノリも独特だなと…。

カットが切り替わると全く違うスタイルの映像が提示されたりするあたり、とにかく目まぐるしい映像。本来こういう映像は手描きアニメでしか作れないはずだったけど、CGアニメでも全然できるようになってきたのだなと…。この自由奔放さを目にしてしまうと、おそらくは大量生産の弊害で作業フローが硬直化して型にハマった/どこかで見た気がする映像しか提示できなくなってしまった手描きアニメの先行きってなんとも暗いなと…。いや、こういう作品から影響を受けて、手描きアニメも自由奔放さを取り戻してくれれば…。とかなんとかそんな余計なことまで考え始めてしまうぐらいに興味深い映像だった。

脚本は「家族」をテーマにしたソレだったけれど、かなりの予算をかけて制作される映画はちゃんとリターンが得られる確率を高めるために、全世界で共通して通用する「家族」というテーマを採用せざるをえないのかもしれないなと…。いやまあ、他にもあるだろうとは思うけど。友情とか。恋愛とか。でもまあ、「家族」は鉄板ネタではあるわな…。

視聴後に関連情報をググってみたら、本来は劇場公開作品として作られていたけれどコロナ禍のせいで難しくなってNetflixで配信することになった作品だったらしい。また、「スパイダーバース」のスタッフが手掛けた作品だったそうで、ある人は「スパイダーバースのスタッフが作ったクレヨンしんちゃん」と称していて、なんとなく雰囲気が分かったような気にもなったけど、自分「スパイダーバース」って未見なので…。

そういえば、母親キャラの鼻が左右のどちらかに曲がっているようなモデリングになっていて感心した。「パーフェクトではない家族像」を描くためのちょっとした工夫としてパーフェクトでないモデリング形状をあえて盛り込んでみる、その思考がパーフェクト…。

#3 [anime] 「名探偵コナン 探偵たちの鎮魂歌」を視聴

金曜ロードショーで放送されていたので視聴。劇場版。2006年の作品で、劇場版としては10作目らしい。

設定としては、 集められた探偵が爆弾を仕掛けられて事件の全貌を明らかにさせられる、とか、 子供達にも爆弾が仕掛けられてあわや大ピンチ、といった感じだった。

あちこちのカットでCGが使われていて、この時期にはもうこのぐらい使われていたのだなと…。

怪盗キッドが色々なピンチの場面で便宜を図ってくれて、やはりあのキャラは便利だなと…。

後に安室役を演じる方が出演していて、しかも台詞が…。偶然とは言え、聞いていて複雑な気分になってしまった。その台詞内容、いいのかよ。なんか色々当てはまり過ぎる。いや、この時点ではまさかあんなことになるなんて誰も予想できなかったから仕方ないけど…。

登場した女性ゲストキャラが峰不二子っぽくて興味深かった。後に「ルパンVSコナン」が作られるのだろうけど…。青山先生、本当にルパンシリーズが好きなのかもしれないな…。

2026/03/28() [n年前の日記]

#1 [lazarus] Lazarusの勉強中

Lazarus 4.4 を使って作成したGUIアプリから、G'MIC CLI 3.7.4 (gmic.exe) を呼び出して処理をさせられないか実験中。

ほとんどの部分を AI (Google Gemini)に作ってもらってるな…。まあ、一発で動くソースは滅多に出てこないのだけど。コンパイルエラーもバンバン出る。

2026/03/29() [n年前の日記]

#1 [lazarus][gmic] G'MIC CLIを呼び出すGUIアプリをLazarusで作成してみた

G'MIC CLI (gmic.exe) を呼び出して、標準入出力から画像データのやり取りをするGUIアプリを Lazarus で作成してみた。せっかくだから github にアップロードしておいた。

_mieki256/LazGmicPipe: G'MIC CLIを呼び出すLazarus製GUIアプリのサンプル

念のために書いておくけれど、画像ファイルに対してG'MICのフィルタをかけたいなら、スタンドアロンで動作する G'MIC-Qt (G'MIC-Qt stand-alone interface, gmic_3.7.4_qt_win64.zip) が存在するのでそれを使えば済む話。今回作成したアプリの実用性は全く無いです。これっぽっちも無いです。

_G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing - Download

じゃあどうしてこんなアプリをわざわざ作ったかと言えば…。G'MIC CLI や ImageMagick のようなコマンドラインツールに、標準入出力を経由して画像データを送って処理させるGUIアプリを作れそうかどうか実証したかったからで…。GUIアプリは標準入出力を利用できない、みたいな制限があったら困るなと…。試してみたらそんな制限は無かったので一安心。Lazarus で作れたのだから、おそらく Delphi や C# でも作れるんじゃないか…。

ただ、G'MIC をアプリに組み込みたいなら、C++アプリ用に libgmic というものもあるらしいので、C++で作成するなら libgmic を使ったほうがいいのかもしれない。

_G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing - Libgmic

#2 [cg_tools] 画像処理サーバについて妄想

妄想メモ。

ここ数日 G'MIC 関連について色々実験してるけれど、ふとなんとなく。こういった画像処理を行う専用サーバを用意して各画像編集ソフトから利用する仕組みって作れないものかなと妄想を始めてしまった。

いや、でも、考えてみたら、今時のスマホアプリなら、当の昔にそういう仕組みが実現されてたりするか…。スマホのCPUスペックは低いからスマホ本体に画像処理させると結果が出てくるまで待たされるだろうし、だからサーバにデータを送って処理させて、結果をスマホアプリで取得して表示する事例が多いのではないか…。

もっとも、そのやり取りをする際の仕様/フォーマットは公開されてない場合が多そう…。他社製アプリからサーバ資源を消費されたらタダ乗りみたいなものだろうから、仕様を隠してる場合が多いのではないかなあ…。

もし、そのあたりの仕様が規格化されていて、どんなアプリからも各社の画像処理サーバを利用できるようになっていたら、一体どういう世界になるんだろう? それはユーザ側にとって便利なのか、そうでもないのか…。

Photoshop や GIMP や Krita にフィルタを導入するのではなく、フィルタ名とURLを登録して使う感じになるのかな…。それって便利なのか…?

#3 [pc] 親父さんが使ってたマウスが壊れたっぽい

親父さんが使ってた3ボタンワイヤレスマウス、ELECOM M-LE10DRWH が昨日? 一昨日? に壊れたっぽい。


別のワイヤレスマウスを接続したらマウスカーソルが表示されてフツーに動いたので、OS側で不具合が出てるわけではなさそう。マウスが壊れてしまったとしか思えない。ボタンは壊れてないようだけど、ポインティング関連部分だけがピンポイント(?)で壊れたのだろう…。

ELECOM M-LE10DRWH を購入したのは…。日記を検索したら _2025/12/31 だった。約3ヶ月使ったら壊れてしまったことになる。さすがELECOM製品。保証期間は1年間となっているけれど、交換可能なのかどうか…。

妹が購入したけれど合わなくて使ってなかったエルゴノミクスワイヤレスマウス、サンワサプライ 400-MA092SS があるとのことで、ひとまずソレを親父さんに渡して様子を見ることにした。ただ、エルゴノミクスマウスだから、親父さんが慣れることができるかどうか…。多ボタンマウスなので、4番5番ボタンを誤操作で押してしまいそうでもある…。

省電力モードからの復帰絡みだろうか :

件のマウスは、一旦省電力モード? スリープモード? に入ると、左ボタンをクリックしないとマウスカーソルが出てこないことを思い出した。もしかして、省電力モードからの復帰が上手く行っていないのだろうか…。だとすると左ボタンが壊れている可能性もあるのだろうか…。

2026/03/31追記 :

壊れたと思われるマウスを自分のPCに接続して動作確認してみたけれど、やはりマウスカーソルの移動がおかしかった。

親父さん用PCに繋いだ時とは違って、一応マウスカーソルは表示されたのだけど、動かしているうちにちょっとずつ反応が無くなってきて、そのうちマウスカーソルが完全に動かなくなる。マウスを裏返して光学センサ部分を眺めると、通常なら赤いLEDの光が見えるはずが、チラチラと点滅したり、全く光らなくなったりで…。

念のために電池交換をしてみてもこういう症状が出ているので、やはり壊れているのではないかなあ…。

#4 [anime] 「名探偵コナン vs. 怪盗キッド」を視聴

BS12で放送されていたので視聴。TVシリーズの特別編集版ということらしい。

一部のカットはこの総集編用の新作なのだろうか。デジタル制作に見えたし…。最初のあたりのエピソードはセル+フィルムで作ってた感じの映像に見えた…けれどそれにしてはカメラが全然ブレてないな…。これもデジタル制作なんだろうか。当時は低解像度で作ってただけ?

工藤新一 vs キッド、コナン vs キッドの、2つのエピソードをまとめた感じの構成だった。1時間半の回想シーン…。

2026/03/30(月) [n年前の日記]

#1 [gmic] G'MICのフィルタの作り方を勉強中

G'MIC用のフィルタを作ってみたい。作り方について勉強中。

以上、30 日分です。

過去ログ表示

Prev - 2026/03 -
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project