【ImageMagick】グラデーションな色で塗りつぶした縁取り極太テキスト画像って使えるよな

こういうやつ。背景は透明。

コピペで貼り付けるだけでサムネとかSNS画像を作成できます。



 

🖌️ 作り方

ImageMagick で作ります。


brew install imagemagick

まず、透明背景画像を作成します。


magick -size 2000x200 xc:none \
output.png

透明な画像が生成されました。

グラデーションな色で塗りつぶした縁取り極太テキスト画像って使えるよな

続いてこれにテキストを書き込みます。

フォントは「LINE-Seed-JP_OTF-ExtraBold」、フォントの輪郭の線の色と太さは「white」、「10」とします。


magick -size 2000x200 xc:none \
-font LINE-Seed-JP_OTF-ExtraBold \
-pointsize 160 \
-fill none -stroke white -strokewidth 10 \
-annotate +10+160 "お手軽簡単!" \
output.png

グラデーションな色で塗りつぶした縁取り極太テキスト画像って使えるよな

グラデーションな色で塗りつぶした縁取り極太テキスト画像って使えるよな

👉 LINE Seed hatena-bookmark

さらに、この輪郭線の上に「black」で「2」の線を重ねます。


magick -size 2000x200 xc:none \
-font LINE-Seed-JP_OTF-ExtraBold \
-pointsize 160 \
-fill none -stroke white -strokewidth 10 \
-annotate +10+160 "お手軽簡単!" \
-fill none -stroke black -strokewidth 2 \
-annotate +10+160 "お手軽簡単!" \
output.png

グラデーションな色で塗りつぶした縁取り極太テキスト画像

グラデーションな色で塗りつぶした縁取り極太テキスト画像って使えるよな

さらに、この上に、グラデーションの色「red-orange」で塗りつぶされたテキストを重ねます。


magick -size 2000x200 xc:none \
-font LINE-Seed-JP_OTF-ExtraBold \
-pointsize 160 \
-fill none -stroke white -strokewidth 10 \
-annotate +10+160 "お手軽簡単!" \
-fill none -stroke black -strokewidth 2 \
-annotate +10+160 "お手軽簡単!" \
-tile "gradient:red-orange" \
-annotate +10+160 "お手軽簡単!" \
output.png

グラデーションな色で塗りつぶした縁取り極太テキスト画像

グラデーションな色で塗りつぶした縁取り極太テキスト画像って使えるよな

最後に、不要なまわりの透明部分を取り除きます。


magick -size 2000x200 xc:none \
-font LINE-Seed-JP_OTF-ExtraBold \
-pointsize 160 \
-fill none -stroke white -strokewidth 10 \
-annotate +10+160 "お手軽簡単!" \
-fill none -stroke black -strokewidth 2 \
-annotate +10+160 "お手軽簡単!" \
-tile "gradient:red-orange" \
-annotate +10+160 "お手軽簡単!" \
-trim \
output.png

グラデーションな色で塗りつぶした縁取り極太テキスト画像って使えるよな

 

🖌️ まとめ

変更になりそうなパラメータは引数にしておきます。

あと実行後は、プレビューで開いてすぐ確認できるようにしておきます。



お好みの各引数は選択肢として ショートカットにしておけばターミナルを使う必要もない。

それなりのデザイン的なアプリで作るのもいいですが、ササっと作りたい人はどうぞ。




【Mac】プレビューで画像をコピペして保存すると白黒(グレー)になる件 🎨

便利な macOS プレビューアプリですが、

絵を描いて保存した瞬間になぜか白黒になるものがある。

このように丸を描いて保存すると、

こうなってしまいます。

上に画像をコピペで貼り付けした場合もグレーになってしまいます。

エクスポートしても同じ。

画像の形式の話だろうけど、どうしたらいいのか。

👉 プレビューからコピーした画像が白黒にな… - Apple コミュニティ hatena-bookmark

👉 saving Preview annotations color - Apple Community hatena-bookmark

 

🎨 画像形式を確認する

元画像は w.png。

プレビューの [ツール] - [インスペクター] で。

「Gray」と表示されてるのが気になります。

コマンドラインでも見てみます。


❯ file w.png
w.png: PNG image data, 300 x 300, 1-bit grayscale, non-interlaced

❯ identify w.png
w.png PNG 300x300 300x300+0+0 8-bit Grayscale Gray 2c 346B 0.000u 0:00.024

❯ pngcheck w.png
OK: w.png (300x300, 1-bit grayscale, non-interlaced, 97.0%).

「grayscale (グレースケール)」とどれも表示されています。

👉 pngcheck - verifies the integrity of PNG, JNG and MNG files

 

🎨 ImageMagick でPNG形式を変換する

以下で変換できるようです。

You need to supply PNG24, PNG8 or PNG32 prefix if planning to use this canvas to layer colour images over. Without it, it creates a Grey colour space. I used 32, as I need "varying degrees of transparency for each pixel"

このキャンバスを使用してカラー画像を重ねる場合は、PNG24、PNG8、または PNG32 プレフィックスを指定する必要があります。これがないとグレーの色空間が作成されます。 私の場合は、各ピクセルの透明度を変える必要があるので 32 を使用しました。


convert w.png png32:w.png

👉 Create blank image in Imagemagick - Stack Overflow hatena-bookmark

上記コマンドを実行して変換後、確認してみます。


❯ file w.png
w.png: PNG image data, 300 x 300, 8-bit/color RGBA, non-interlaced

❯ identify w.png
w.png PNG 300x300 300x300+0+0 8-bit sRGB 1294B 0.000u 0:00.000

❯ pngcheck w.png
OK: w.png (300x300, 32-bit RGB+alpha, non-interlaced, 99.6%).

「graayscale」という文字は消えています。

再度、赤い丸を描いて保存するといけました!

 

🎨 まとめ

最初に開くファイルの形式が保存時に影響する。

ちなみに、ImageMagick が対応してるのは以下。


❯ identify -list format | grep PNG
      JNG* PNG       rw-   JPEG Network Graphics
      MNG* PNG       rw+   Multiple-image Network Graphics (libpng 1.6.39)
      PNG* PNG       rw-   Portable Network Graphics (libpng 1.6.39)
             See http://www.libpng.org/ for details about the PNG format.
    PNG00* PNG       rw-   PNG inheriting bit-depth, color-type from original, if possible
    PNG24* PNG       rw-   opaque or binary transparent 24-bit RGB
    PNG32* PNG       rw-   opaque or transparent 32-bit RGBA
    PNG48* PNG       rw-   opaque or binary transparent 48-bit RGB
    PNG64* PNG       rw-   opaque or transparent 64-bit RGBA
     PNG8* PNG       rw-   8-bit indexed with optional binary transparency

しかし、プレビューアプリだけで完結できないものか。

以下の記事がわかりやすく解説されていました。

👉 ImageMagick で PNG の形式を変換 - awm-Tech hatena-bookmark



【Mac】OS標準 プレビュー アプリで画像を新規作成する方法 🎨

いいアプリ見つけた。

Mac標準ソフト「プレビュー」には、図形や線、テキストなどを挿入できるマークアップ機能が搭載されています。しかし、同機能は既存の画像のみに適用できるほか、同ソフトでは新規ファイルも作成できません。それでも簡単な図を作成するために別のペイントツールをダウンロードしたくないという人には、このソフトがオススメです。コンテクストメニューから起動して新規画像のサイズや色を指定すると、画像を作成して自動的に「プレビュー」を開き、マークアップ機能を使えるようになります。

👉 「プレビュー」用の新規ファイル作成|MacFan hatena-bookmark

と思ったら、なぜか動かないので。

 

🎨 ImageMagick で

定番コマンドラインツールをインストールしておきます。


brew install imagemagick


👉 ImageMagick – Convert, Edit, or Compose Digital Images hatena-bookmark

以下のようなコマンドを使います。


convert -size 200x200 xc:white canvas.png

👉 macos - Create PNG/JPG file with commandline on Mac - Stack Overflow hatena-bookmark

これで真っ白な画像ファイルが生成できます。

 

🎨 ショートカットで開く

画像サイズを選択するようにして、先ほどのコマンドをショートカットに仕込みます。


cd ~/Desktop
convert -size {Chosen Item} xc:white {Chosen Item}.png
open -a Preview {Chosen Item}.png

これで、[サイズ選択] → [画像作成] → [プレビューを開く] の流れが実行できます。

サイズや作成先ディレクトリや拡張子はお好みで。

あと、日本語でOS設定している人は open -a するアプリ名が「プレビュー」なのかも。

 

🎨 保存すると白黒になってしまう

ショートカット内コマンドで作成する白キャンバス画像の形式が影響してカラーのまま保存できない。

PNG32:というように作成するファイル名の前にプレフィックスをつけるといい。

ショートカット内コマンドで作成する白キャンバス画像の形式が影響してカラーのまま保存できない。

これでカラーのまま保存できるようになります。

👉 【Mac】プレビューで画像をコピペして保存すると白黒(グレー)になる件 🎨 hatena-bookmark

 

🎨 まとめ

なぜ、Preview は新規キャンバス作成ができないのか。

「プレビュー」ではなくなるからかな。


【Kotlin】data class 同士を「+ (plus)」する

以下の data class


data class Token(
  val prompt: Int = 0, 
  val completion: Int = 0
)

が2つあったとして


val a = Token(1, 2)
val b = Token(10, 20)

これらを足す。

どう書きますか?


println(
  Token(
    a.prompt + b.prompt,
    a.completion + b.completion
  )
)
// Token(prompt=11, completion=22)


println(
  a.copy(
    prompt = a.prompt + b.prompt, 
    completion = a.completion + b.completion
  )
)
// Token(prompt=11, completion=22)

 

🔢 + (plus) 演算子をオーバーロードする

拡張関数で + (plus) 演算子 をオーバーロードします。


operator fun Token.plus(other: Token): Token {
  return Token(prompt + other.prompt, completion + other.completion)
}


println(
  a + b
)
// Token(prompt=11, completion=22)

こんなことできるんですね!

素晴らしい!

【Kotlin】data class を + (plus) する

👉 Operator overloading | Kotlin Documentation hatena-bookmark


【OpenAI】API プロンプトトークン数(利用料金)をカウントする

通常のAPIリクエストではレスポンスボディに利用トークンのカウント数は含まれる。


"usage": {
   "prompt_tokens": 9,
   "completion_tokens": 12,
   "total_tokens": 21
 }

👉 API Reference - OpenAI API hatena-bookmark

しかし「Server-Sent Events(SSE)」では、それをレスポンスで返さない。



👉 【OpenAI】Kotlin OkHttp で Server-Sent Events (SSE) hatena-bookmark

従量制のAPIを利用している限り料金は気になりますよね。

プロンプトのトークンの数をアプリ側で独自にカウントすれば料金(利用トークン数から)は算定できるのでは?

 

🤖 JTokkit

Java のライブラリありますね。OpenAI公式でも紹介されているやつ。


👉 openai-cookbook/How_to_count_tokens_with_tiktoken.ipynb at main · openai/openai-cookbook · GitHub hatena-bookmark

豊富な Java ライブラリを使えるのは Kotlin の便利なところです。

👉 Counting Tokens for ChatML | JTokkit hatena-bookmark

とりあえずテストで動かしてみます。


dependencies {
  testImplementation 'com.knuddels:jtokkit:0.4.0'
}


@Test
fun test_jtokkit() {

  val messages = listOf(
    Message("user", "こんにちはと言ってください。"),
    Message("assistant", "こんにちは!")
  )

  val encoding = Encodings.newDefaultEncodingRegistry()
    .getEncodingForModel(ModelType.GPT_3_5_TURBO)

  val count = messages.sumOf { message ->

    // GPT_3_5_TURBO without name
    listOf(
      4, // per message
      encoding.countTokens(message.role),
      encoding.countTokens(message.content)
    ).sum()

  } + 3 // every reply is primed with <|start|>assistant<|message|>

  println(count)

}


@Serializable
data class Message(
  val role: String,
  val content: String
)

メッセージごと、リプライごとのカウント追加が間違ってるのか、なんなのか。

少しカウント数ずれるんだけども。

 

🤖 まとめ

てか、返せよ Usage。

従量制の有料サービスなんだから。

👉 How to get total_tokens from a stream of CompletionCreateRequests - API - OpenAI Developer Forum hatena-bookmark
👉 How do you get token count when streaming - API - OpenAI Developer Forum hatena-bookmark
👉 How to determine the token usage for a session when using stream:true? - API - OpenAI Developer Forum hatena-bookmark

まあ、Webページで確認すればいいけども。

👉 Usage - OpenAI API hatena-bookmark

大して使ってないからどうでもいいか。