前の月 / 次の月 / 最新

hiChangeLog / 2007-10

2007-10
SMTWTFS
123456
78910111213
14151617181920
21222324252627
28293031

2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12

2007-10-21 Sun

「ファイル番号」をインクリメントするスクリプト [python]

ファイル名の先頭に、"014_xxxx" "019_xxxx" ... などと「ファイル番号」をつけておくと、キレイに並べられるなど整理の見通しが良くなるので、個人的に多用する。

例外的に、あるファイル番号を割込ませたいと思う状況がある。001から020までビッシリとファイル番号が振られているという状況で、014から020のファイル番号をインクリメントして015から021とし、新しく持ってきたファイルに014番を割当てる、といった具合である。

そのためのスクリプトを書いたのでメモ。globをreverseしているのは、偶発的なファイル名重複を避けるため。(021_hoge, 022_hogeなるファイルがある時、021_hoge => 022_hoge というrenameは失敗する。022_hoge => 023_hoge なる rename から行えば重複は生じない)

import re
import glob, os

id_from = 13
reg = re.compile('(\d+)_(.*)')

flist = glob.glob('*')
flist.reverse()
for fname in flist:
    r = reg.search(fname)
    if r:
        id = long(r.group(1))
        body = r.group(2)
        if id >= id_from:
            os.rename(fname, "%03d_%s" % (id+1, body))

動作テストのためのファイル群を作成するスクリプト:
import os
for i in range(1,20):
    f = open('%03d_test' % i, 'w')
    f.write('dummy %d', i)
    f.close

2007-10-16 Tue

Firefoxでファイルをダウンロードする際にOKボタンがグレーアウトしないようにする [Firefox]

WinXP + SP2, Firefox 2.0.0.7 という環境で、Firefoxでファイルをダウンロードする際に、OKボタンがグレーアウトしてしまう。これだとそのままEnterキーを押しても"OK"扱いにはならない。ボタン上でのクリックか、ウィンドウフォーカスを一旦外すと直るので、絶望的に困ってるわけじゃない。でも面倒で気持ち悪いので直したい。Obache WatchingMozilla Firefox質問スレッド(初心者歓迎)の51: 334と同様な症状。

Mozilla Firefox質問スレッド(初心者歓迎)の51: 341-342にその回答が出ていた。以下はその抜粋。

Fxインストールしたフォルダ -> components -> nsHelperAppDlg.js の、
430行目あたり: this.mDialog.document.documentElement.getButton("accept").disabled = true; 
526行目あたり: this.mDialog.document.documentElement.getButton("accept").disabled = true;
をコメントアウトする。

その通りやってみたら、グレーアウトは無くなった。すげえ

UTF-8文字列への変換 [Windowsプログラミング]

Windowsプログラミングにおいて、UTF-8文字列を用意したい場合にはどうすればよいか?

次の作業を行えばよい:MultiByteToWideCharでUnicodeに変換 => WideCharToMultiByteでUTF-8に変換

UTF-8エンコードについて
Yu TANAKA's Works:S-JISからUTF-8への変換

PNGにコメントを埋め込む [画像ファイル][Windowsプログラミング]

画像は情報量が多く情報伝達媒体として極めて優秀だが、ちと検索が難しいので後々の整理が悩ましい。画像のキーワードが既知であれば、それを元に文字からの検索が可能となるので、後々の整理で威力を発揮するだろう。要は画像ファイルにコメントとしてキーワードが埋め込まれていれば便利そうだという話。PNGについてこのへんの事情を調べた。[2006-12-05]も参照。

【前提知識】

もともとPNGファイルにはtEXtチャンクなるコメント用の領域が用意されている。もちろん、libpngからの読み書きが可能である。
PNG利用術
PNGファイル(2)  PNG操作の手順

しかしながら、ここには日本語のデータを入れてはいけない模様。とても残念な仕様である。
PNG Specification: Chunk Specifications 中に次の記述が:"The text string can contain any Latin-1 character."
お絵描き研究室:PNG(原理編)
PNG チャンク編集ツール < 10 < November < 2004 < nulog, NULL::something : out of the headphone

その不満を受けてのことだろうが、iTXtチャンクなる、UTF-8を入れてもいいコメント領域が追加されたようだ。「PNGの常識」と捉えるにはまだ早いのかな?
PNG Specification: Chunk Specifications
煤 - Note 0312


【コード】

tEXtチャンクの読み書きはPNG利用術を見るとよくわかる。
だけどiTXtのサンプルコードはあんまり見ない。Re: g_warnings in png loaderくらい?ちょっとやってみて、独断でうまくいったっぽいと感じたのでメモする。

libpngは libpng-1.2.22-no-config.tar.gz を使用。このバージョンでは、iTXtの機能はデフォルトでは無効になっている(pngconf.h の474行目 "iTXt support was turned off by default")。これを有効にするために、503行目あたり(iTXt関連の#defineが終わった直後)に無理矢理以下をねじこみ、その上でコンパイルしてライブラリを作成した。

#define PNG_iTXt_SUPPORTED
#define PNG_READ_iTXt_SUPPORTED
#define PNG_READ_iTXt
#define PNG_WRITE_iTXt_SUPPORTED
#define PNG_WRITE_iTXt

そのライブラリを使ったプログラム中で、下記のコードでiTXtにコメントを埋め込めたようだ。見ての通り文字列の宣言と変換はお手軽いいかげんなコードだが、これは現在の本質ではない。
png_text text_ptr[3];
const WCHAR* wstr[3] = {L"これが1番目です", L"これは2番目かも", L"そして3番目だ"};
char str[3][1024];
char key[3][32];
for(int i=0; i<3; i++){
    sprintf(key[i], "My Key %d", i);
    WideCharToMultiByte(CP_UTF8, 0, wstr[i], -1, str[i], 1024, NULL, NULL);
    text_ptr[i].key = key[i];
    text_ptr[i].text = str[i];
    text_ptr[i].compression = PNG_ITXT_COMPRESSION_NONE;
    text_ptr[i].text_length = 0;
    text_ptr[i].itxt_length = strlen(text_ptr[i].text);
    text_ptr[i].lang = NULL;
    text_ptr[i].lang_key = NULL;
}
png_set_text(png_ptr, info_ptr, text_ptr, 3);
こうして作ったPNGは次の通り:
上記コードでコメントを埋め込んだPNG

コメントの有無の確認はpngtxtで行った。TweakPNG(ver. 1.2.1)でもiTXtチャンクの有無は確認できたが、日本語は表示できないみたい。ソースが入手できるので、表示できるように修正できるかなと思ったが面倒なのでやめた。

読み込む際のコードはtEXtの場合と特に違いはなさそう。下記内容のmain.cppを用意し、ビルドしたらば、ちゃんとUTF-8でコメントを吐いてくれた(標準出力をテキストファイルにリダイレクトした上で見た)。なお下記はPNG利用術の「読み込み」節のコードをここでの目的に照らして必要最小限に削ったものである。省略は私が勝手に行ったことであり、また、コードそのものに私のオリジナルな部分は一切無い。

ビルドのコマンドライン:
cl /MD main.cpp libpng.lib zlib.lib

main.cpp:
#include <stdio.h>
#include <stdlib.h>
#include "png.h"

void check_if_png(char *file_name, FILE **fp);
void read_png_info(FILE *fp, png_structp *png_ptr, png_infop *info_ptr);

#define PNG_BYTES_TO_CHECK (4)

int main()
{
  FILE            *fp;
  png_structp     png_ptr;
  png_infop       info_ptr;
  png_uint_32     i;
  
    check_if_png("test.png", &fp);
  read_png_info(fp, &png_ptr, &info_ptr);

{         // 以下8行はtEXtチャンクを取得し表示します
  png_textp       text_ptr;
  int             num_text;
  
  if (png_get_text(png_ptr, info_ptr, &text_ptr, &num_text))
          for (i = 0; i < num_text; i++)
                  printf("%s", text_ptr[i].text);
}
  png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
  fclose(fp);
  return 0;
}

void check_if_png(char *file_name, FILE **fp)
{
  char    sig[PNG_BYTES_TO_CHECK];
  
  if ((*fp = fopen(file_name, "rb")) == NULL)
          exit(EXIT_FAILURE);
  if (fread(sig, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) {
          fclose(*fp);
          exit(EXIT_FAILURE);
  }
}

void read_png_info(FILE *fp, png_structp *png_ptr, png_infop *info_ptr)
{
  *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (*png_ptr == NULL) {
          fclose(fp);
          exit(EXIT_FAILURE);
  }
  *info_ptr = png_create_info_struct(*png_ptr);
  if (*info_ptr == NULL) {
          png_destroy_read_struct(png_ptr, (png_infopp)NULL, (png_infopp)NULL);
          fclose(fp);
          exit(EXIT_FAILURE);
  }
  if (setjmp((*png_ptr)->jmpbuf)) {
          png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
          fclose(fp);
          exit(EXIT_FAILURE);
  }
  png_init_io(*png_ptr, fp);
  png_set_sig_bytes(*png_ptr, PNG_BYTES_TO_CHECK);
  png_read_info(*png_ptr, *info_ptr);
}

2007-10-15 Mon

libpngとzlibを使用したVC++のプロジェクトで「競合」によるビルド失敗が、マルチスレッドDLLで解決した [Windowsプログラミング][C/C++][画像ファイル]

libpngzlibを使ってVC++(non MFC)でプログラムを書こうと思った。(VS.NET 2003)

まずはライブラリをコンパイルする。libpng-1.2.22-no-config.tar.gzとzlib-1.2.3.tar.gzをダウンロードした。展開し、zlibの内容をlibpngと「兄弟」となるように配置(例えばC:\temp\libpng\(libpngの中身)、C:\temp\zlib\(zlibの中身))。で、(libpng)\projects\visualc71\libpng.sln を開き、ビルド => 構成マネージャから LIB Release を選んで、ビルドするとライブラリができる。このあたりは (libpng)\projects\visualc71\README.txt に書いてある。Win32_LIB_Releaseディレクトリのlibpng.lib、zlib.libを、またソースファイルからpng.h、pngconf.h、zlib.h、zconf.hを持ってくれば使用準備は整う。

さてプログラムを書いてビルドしたらば、「競合」によって失敗した。内容から解決法まで、下記と同様であった。
2006-10-26 - 王様の箱庭::blog

エラーは下記のようなものである。プロジェクトのプロパティから C/C++ => コード生成 => ランタイムライブラリ を「マルチスレッドDLL」にすることでエラーは消えた。なぜうまくいったかは理解していない。

...
step1 error LNK2005: _abort は既に LIBC.lib(abort.obj) で定義されています。
...
step1 fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました。
step1 warning LNK4098: defaultlib 'MSVCRTD' は他のライブラリの使用と競合しています。/NODEFAULTLIB:library を使用してください。

libpng生成とpng出力も参考にした。

2007-10-14 Sun

pythonでoutline-mode [python][emacs]

ソースを書いている際、だんだんファイル中のコード量が増えてきて見通しが悪くなることがよくある。
emacsのoutline-modeがこんな時に活躍する。さてこれをpythonのソースに適用したい場合はどうすればよいか?

そのものズバリのものが有志により作成済みであった。世の中広い。.emacsにコピペして、pyファイルのバッファで python-outline すればOK。
Python outline mode in emacs

2007-10-13 Sat

UnicodeEncodeError発生時の対処法を学んだ [python]

pythonでCGIを作成している。(ローカルで練習中:Apache 2.2.6 on WinXP SP2, python 2.4)
formで送る文字列に日本語を含めたとたんにUnicodeEncodeErrorが出るようになってしまった。わけわかんねーと思っていたが、そのものズバリの記述を発見した。
UnicodeEncodeErrorが発生した場合は、sitecustomize.pyでデフォルトのエンコーディングを指定する。

内容を理解しないままに、C:\Program Files\python24\Lib\sitecustomize.pyを作成し

import sys
sys.setdefaultencoding('utf-8')
と記述したらエラーは出なくなったし日本語変数のやりとりもうまくいっているようだ。

Referrer (Inside): [2008-05-13-1]

2007-10-10 Wed

Mathematicaで小数点の位置とか指数部とか仮数部とか [Mathematica]

タイトルのキーワードについての文書のありかをメモ。
2.9.7 数値の出力書式
3.1.6 機械精度の数値

maildropとMaildir形式とmh形式 [C/C++][メール]

maildropを便利に使用している。これはメールを振り分け後Maildir形式かmbox形式で保存する。以下 man maildropfilterの記述の抜粋。

   TO - DELIVER MESSAGE TO A MAILBOX
              to expression

       The  to  statement  delivers the message to a mailbox.  expression must
       evaluate to a valid mailbox. A valid mailbox is either a mailbox  file,
       a maildir, or an external program (which includes forwarding to another
       address).

(中略)

       Otherwise,  expression  names  the  mailbox where maildrop delivers the
       message.  If expression is  a  directory,  maildrop  assumes  that  the
       directory is a maildir directory.  Otherwise, maildrop will deliver the
       message to a file, formatted in traditional mailbox  format.   maildrop
       will  use  either  dot-locking,  or flock()-locking when delivering the
       message to the file.

メールを読むのにはWanderlustを使用している。だがこれだと(Wanderlustのせいではないのだろうが)Maildir形式のメールを読むのは重く、一方mbox形式だと複数メールで1ファイルなので何かのきっかけで多数のメールを巻き込んでオシャカになるのが怖い。なんでmh形式でメールを読みたい。

maildropでmh形式の保存はできないようだ。procmailならできるみたいだが、設定ファイルの書式が意味不明なので使いたくない。そこで、Maildir => mh の変換ができないもんかと考え、調べたが、同様な考えの人は多くないみたい。

しょうがないので、そのためのプログラムを書いてみた。標準入力の内容に連番のファイル名をつけて保存するだけのもの。maildropは任意のプログラムにメールの内容を標準入力経由で渡せるので、これを用いればmaildropから連番ファイル名でメールを保存できる。これを「mh形式」と呼んでいいのかどうかは知らん(既存プログラムのソースを突き合わせて確認する必要があるがやってない)が、こうしてたまったメールはWanderlustから無事読めているので、問題無さげ。実際、http://cvs.sourceforge.jp/cgi-bin/viewcvs.cgi/*checkout*/win2linux/w2l-tools/scripts/mbox2mh?rev=1.4 を見てもメールの中身に連番ファイル名を振ってるだけみたいだし。

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <dirent.h>

void log(const char*);
unsigned int LargestFilenameNumber(const char*);

int main(int argc, char* argv[]){
        char c;
        FILE *fp;
        char fname[256];
        int newfilenum;
        const char* dirname = argv[1];

        if(argc != 2){
                log("invalid argument");
                return -1;
        }

        newfilenum = LargestFilenameNumber(dirname)+1;
        if(newfilenum == 0){
                log("error in LargestFilenameNumber");
                return -1;
        }

        if(dirname[strlen(dirname)-1] == '/') sprintf(fname, "%s%d", dirname, newfilenum);
        else sprintf(fname, "%s/%d", dirname, newfilenum);
        fp = fopen(fname, "w");
        if(fp == NULL){
                log("error in file opening");
                return -1;
        }

        while(1){
                c = fgetc(stdin);
                if(c == EOF) break;
                fputc(c, fp);
        }
        fclose(fp);
        return 0;
}

unsigned int LargestFilenameNumber(const char* dirname){
        DIR *dir;
        unsigned int filenum, filenum_max;
        char dummy;
        char fname[256];
        struct dirent *dp;
        if((dir=opendir(dirname))==NULL) return -1;

        filenum_max = 0;
        while((dp = readdir(dir)) != NULL){
                if((strcmp(dp->d_name, ".")==0) || (strcmp(dp->d_name, "..")==0)) continue;
                // sscanf return value ex. "1.eml" => 2, "hoge" => 0, "67" => 1
                if(sscanf(dp->d_name, "%u%c", &filenum, &dummy) != 1) continue;
                filenum_max = filenum_max > filenum ? filenum_max : filenum;
        }
        closedir(dir);
        return filenum_max;

}

void log(const char* str){
        FILE *fp;
        struct tm *st;
        time_t t;
        char month[][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

        t = time(NULL);
        st = localtime(&t);

        fp = fopen("hiStdin2Mh_log", "a");
        fprintf(fp, "%d %s %.2d: %.2d:%.2d:%.2d\n", st->tm_year+1900, month[st->tm_mon], st->tm_mday, st->tm_hour, st->tm_min, st->tm_sec);
        fprintf(fp, "%s\n\n", str);
        fclose(fp);
}

Referrer (Inside): [2008-01-05-2]

2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12

最終更新時間: 2010-03-08 22:21