2024/06/23(日)ffmpegでアニメーションgifの容量をできるだけ小さくする

今時は、mp4やmovなどの動画ファイルを気軽にアップロードできますが、プログラムライブラリに動画を同梱する場合は
  • なるべく容量を抑えたい
  • 画質は問わない
  • そのため動作内容がわかればよい
  • 汎用性の高いファイル形式にしておきたい
という要件があると思います。じゃあffmpegで良い感じにできないかといろいろ調べた結果以下のコマンド
./ffmpeg.exe -i "C:\soft\ffmpeg\input.mp4" -vf "fps=1, setpts=PTS/1.5, scale=600:-1, split[a][b]; [a]palettegen=max_colors=8[c]; [b][c]paletteuse;" -ss 3 -loop 0 output.gif
  • 1fps
  • 8色
  • そこそこサイズの幅600
※-ss 3 は元ソース3秒目から変換、パスなどは適宜読み替え。

で600KB程度の数十秒間の動画の作成ができました。

2024/01/26(金)テキストエディタをJmEditorからMeryに。

昔話

その昔、BCC DeveloperというBorland C++の無償コンパイラを利用してWindowsアプリが作れる/作りやすいIDEがあった。
その作者が高機能テキストエディタJmEditorというのソフトも公開していてすごくよくできていて、シンプルなのに必要な機能がほとんどそろっていて非常に動作も軽くて自分はずって手放せないでいました。使い始めたのが2003年とかそれくらいで、Widnows2000のころだったのでもう20年は使っています。そしてWindows10でも動いてるんだからMicrosoftもそれはそれですごい。

移行先

とはいっても、印刷機能がなかったりさすがに古くなっているし、作者のサイトもなくなっていてもうずっとアップデートもありません。
それで移行先をずっと探していました。数年前に検討して少し使っているのは gPad というソフトですが、高機能すぎて自分にはちょっと違うなという感じでした。
そして今回見つけたのがMery、JmEditorの雰囲気になんとなく近くてしっくりきました。
窓の杜でも紹介されていますがこちらはバージョンが古く2.x系で作者のサイトに行くと最新の3.x系の入手が可能です。
現在はVer.3.6.5beta、アップデートも随時行われているので今後はこれを使っていきたいと思います。

それにしても、JmEditorを20年も使っていたのか…。

2022/05/31(火)Processing AndroidModeのcontrolP5ボタン

最近Processingを始めましたが、AndroidModeっていうのがあり、これを使うとProcessingアプリがAndroidスマホで動作します。どちらかというと簡易的にAndroidアプリをProcessingで製作出来る、といった方が分かりやすいかもしれません。そこで早速何か簡単な自分用ツールを作ってみようと思ったのですがいきなり躓きました。
それは、定番なProcessingGUIライブラリのcontrolP5ライブラリをAndroidModeで利用する場合、ボタンイベントが所望の動作にならないというものです。ざっと調べた結果仕様っぽかったので、手軽に使いたい自分には悲しい状況になりました。

どうやらボタンイベントに関する挙動で、マウスXY/クリックによるボタン操作と画面タップによるボタン操作の違いに起因してるようです。
他の方法としては正攻法なAndroidSDKのコンポーネントを使うだとかあるみたいなのですが、難しいことは分かりませんし、カジュアルに使えてアプリ作っていきたいので今回簡易的にボタンコンポーネントクラスを作りました。
  • TapButton.pde
    public class TapButton
    {
      float x;
      float y;
      float w;
      float h;
      String s;
      int fontsize;
      boolean visible;
    
      TapButton(float _x, float _y, float _w, float _h, String _s)
      {
        x = _x;
        y = _y;
        w = _w;
        h = _h;
        s = _s;
        fontsize = int(w / s.length());
        visible = true;
      }
    
      void Draw()
      {
        if (visible)
        {
          rectMode(CENTER);
          textAlign(CENTER, CENTER);
          textSize(fontsize);
    
          fill(255);
          rect(x, y, w, h);
          fill(0);
          text(s, x, y, w, h);
        }
      }
    
      void Visible(boolean b)
      {
        visible = b;
      }
    
      boolean Tapped(TouchEvent touchEvent)
      {
        int tapNum = touchEvent . getNumPointers( ) ;
        float tap_x, tap_y;
        if (0 < tapNum)
        {
          tap_x = touchEvent . getPointer( 0 ).x ;
          tap_y = touchEvent . getPointer( 0 ).y ;
          if ( abs(tap_x - this.x) < (w/2) && abs(tap_y - this.y) < (h/2) && this.visible)
          {
            return true;
          }
        }
        return false;
      }
    }
    
    

  • Test.pde
    import android.os.Bundle;
    import android.view.WindowManager;
    
    static int LetterBox = 16; //Letterbox of application draw area
    int sizeW, sizeH;
    boolean flag_backpress = false;//back button press flag
    boolean flag_exit = false;
    
    TapButton tb1 = new TapButton(500, 400, 300, 100, "button1");
    TapButton tb2 = new TapButton(500, 600, 300, 100, "button2");
    
    public void settings()
    {
      sizeW = displayWidth - LetterBox;
      sizeH = displayHeight - LetterBox;
      size(sizeW, sizeH);
    }
    
    public void setup()
    {
    
      frameRate(30);
    }
    
    void backPressed()
    {
      flag_backpress = true;
    }
    
    public void draw()
    {
    
      //DRAWING PROCESS --------------------------------------------------------------
      background(150);
    
      if (mousePressed)
      {
        textSize(50);
        fill(0);
        textAlign(TOP, LEFT);
        text(Integer.toString(mouseX) + "," + Integer.toString(mouseY), 0, 500);
      }
    
      textSize(32);
      fill(0);
      textAlign(TOP, LEFT);
      text(Integer.toString(displayWidth), 0, 150);
      text(Integer.toString(displayHeight), 300, 150);
    
      ellipseMode(CENTER);  // Set ellipseMode to CENTER
      fill(100);  // Set fill to gray
      ellipse(mouseX, mouseY, 100, 100);  // Draw gray ellipse using CENTER mode
    
      //TapButton draw ---------------------------------------------------------------
      tb1.Draw();
      tb2.Draw();
    
      //MAIN LOOP PROCESS ------------------------------------------------------------
      if (flag_backpress)
      {
        flag_backpress = false;
        textAlign(CENTER, CENTER);
        textSize(100);
        fill(255);
        rect(0, sizeH/2 - 80, sizeW, 160, 32);
        fill(0);
        text("Exiting...", sizeW/2, sizeH/2);
        flag_exit = true;
      } else if (flag_exit)
      {
        delay(1000);
        exit();
      }
    }
    
    public void touchStarted(TouchEvent touchEvent)
    {
      int tapNum = touchEvent . getNumPointers( ) ;
      float x = touchEvent . getPointer( 0 ).x ;
      float y = touchEvent . getPointer( 0 ).y ;
    
      //TapButton
      if (tb1.Tapped(touchEvent))
      {
        tb1.Visible(false);
      }
      if (tb2.Tapped(touchEvent))
      {
        tb1.Visible(true);
      }
    }
    
    
テストプログラムは、button1を押すと、button1が消えてbutton2を押すとbutton1が表示されます。
グローバル変数の
TapButton tb1 = new TapButton(500, 400, 300, 100, "button1");
でボタンを定義して、Draw()内の
tb1.Draw();
で描画、タップイベントは
public void touchStarted(TouchEvent touchEvent)内で、
  if (tb1.Tapped(touchEvent))
  {
    tb1.Visible(false);
  }
のようにifで判定してタップ時の処理を書きます。
(ソースコード一部修正:2022/6/12)

2019/07/11(木)sylpheedをコマンドラインで使う

Outlook Expressがない今、それに似たメーラーがSylpheedかなというところ。QMAILっていうのを使ってたのですがメールが読めなくなる、データが飛ぶ、更新がとまってるのでどうにもならない状況。というかOutlook Expressとか古すぎる話だし知らない人の方が多いかもしれない。

そんなわけでSylpheed使っているんですが、コマンドラインで処理できるそうで応用が効きやすそうです。
このサイトが少し参考になります、Webに情報少ない…。
テックメモ Slypheedのメールをコマンドで作成

あと、
sylpheed.exe --help
とするとヘルプが出ます。
使用法: sylpheed.exe [オプション ...] [URL]
  --compose [mailto URL] メッセージ作成ウィンドウを開く
  --attach file1 [file2]...
                         指定したファイルを添付してメッセージ作成
                         ウィンドウを開く
  --receive              新着メッセージを受信する
  --receive-all          全アカウントの新着メッセージを受信する
  --send                 送信待機中のメッセージをすべて送信する
  --status [folder]...   メッセージの総数を表示する
  --status-full [folder]...
                         各フォルダの状態を表示する
  --open folderid/msgnum 新しいウィンドウで既存のメッセージを開く
  --open <file URL>      新しいウィンドウで rfc822 メッセージファイルを開く
  --configdir dirname    設定ファイルを格納するディレクトリを指定する
  --ipcport portnum      IPC リモートコマンド用のポートを指定する
  --dpi dpinum           DPI を強制指定する
  --exit                 Sylpheed を終了する
  --debug                デバッグモード
  --safe-mode            セーフモード
  --help                 このヘルプを表示して終了する
  --version              バージョン情報を出力して終了する

何かキーを押してください...
いまだにPOP3にこだわってメールしてるのかよって話でもありますが…。

2016/04/22(金)IrfanViewのコマンドライン処理をバッチファイルで

仕事で発送伝票を写真に撮って、送り先にメール添付している。
いつも撮った写真をIrfanViewで開き、サイズ調整・シャープ処理をしてからファイル名を「日付+発送伝票.jpg」にしている。
発送する荷物が少なかった最初は特に気にならなかったが、最近は発送数が多いので面倒くさくなってきた。

そこで、バッチファイルを作成してドラッグ&ドロップで一発で処理できるようにした。

以下が"発送伝票.bat"の中身
@echo on
setlocal

cd /d %~dp0
SET str1=%date:~2,2%-%date:~5,2%-%date:~8,2% 発送伝票.jpg

i_view32.exe %1 /resize=(1024,0) /sharpen=50 /aspectratio /jpgq=70  /convert="%str1%"

endlocal
rem pause
setlocalで変数使用を有効にする(らしい)。
cd XXXでbatファイルがあるパスへ移動する、したがってbatファイルはIrfanViewのフォルダにおいて置く。
SET XXXで変数str1に出力ファイル名を設定する。(例:"16-04-23 発送伝票.jpg")
そして、IrfanViewのコマンドラインで、「リサイズ幅1024、シャープ化 50、アスペクト比保持、jpeg品質 70、変換出力」を行う。

以上で、batファイルのショートカットにjpgファイルをドラッグ&ドロップするだけで発送伝票.jpgの出来上がり。
これで煩雑な処理が一つ減った。

あ、ちなみに複数ファイルをドラッグ&ドロップすると最初のファイルだけ変換されるか、動作おかしくなるか…不明。