徒然なるままに、日ぐらしP/Cに向ひて――
メインメニュー
ブログカレンダー
2008年 3月
« 2月   4月 »
 1
2345678
9101112131415
16171819202122
23242526272829
3031  
WordPress カテゴリ一覧
WordPress 検索


富士カメラ5

Kestrel とは、チョウゲンボウのことです。ハトくらいの小さな猛禽類、つまりワシの仲間で、ハヤブサに似ています。
チョウゲンボウにはホバリングという特技があります。よく農地の上空で空中に停止している姿が見られます。小さいけれどカッコイイ、そして最近は都会でも繁殖している頼もしいタカです。
このサイトのURLは、そんなチョウゲンボウから名前を借りました。

2008年3月7日(金曜日)

Base64

カテゴリー: - flyman @ 10時32分48秒

仕事で作っているプログラムに、画像ファイルをBase64エンコードするロジックが必要になった。エンコードしてテキストファイルに埋め込むのである。
開発言語はDelphi(Object Pascal)、プラットホームはWindowsXPだ。
まずは、Indyのコンポーネントを試そうと思ったのだが――使い方が皆目わからない。マニュアルは、どこだ?
と、いうわけで、ネットを検索したら公開されているコードが見つかった(感謝)。シメシメとこれを利用して、取りあえず目標は達成できた。

が、別の機能を盛り込む段になって、やや面倒なことになった。エンコード部分に少し手を入れなければならなそうだ。しかし他人の書いたコードは判らんし、結構色々いじる必要がありそう。

まあ、そんなわけで、エンコードルーチンを一から書くことにした。Base64のロジック自体はそれ程難しいことはない。ファイルを頭から3バイト(24ビット)読んで、6ビットずつ4つに分割、それぞれの6ビットが表す数値(0?63)を予め決められた文字に割り当てる。6ビットで4文字だから、Base64らしい。
詳細は、ググッで貰えば当たるだろう。
とはいえ、イザ作るとなるとそれなりにボロボロにはなるわけで、特にバイトの並び、ビッグエンディアン、リトルエンディアンがどっちがどっちだか判らなくなって落とし穴に落ちまくりだった。

で、出来上がったのが以下のルーチンだ。
Base64.pasとして保存し、使いたいアプリでusesに追加すれば良い。
MIMEでは、エンコードした文字列は76文字で改行することになっている(らしい)。BRにはこの改行コードを指定する。例えば、

b64enc(FromStream, ToStream, brCRLF);

とすれば、FromStreamからデータを読み、Base64エンコードして結果をToStreamに書き出す。改行コードには$0D0Aが付けられる。
改行したくないときは、brNILを指定する。

てなことで、ここ数日、楽しい時を過ごしている。

デコードルーチンやらを付け加えたコードも公開しちゃいます。Base64.pas
最適でもないし、速くもないし、バグもありそうですが、突っ込むときはコッソリお願いします。

=================================================================
{ Base64 エンコード ルーチン 2008/03/06 flyman }

unit Base64;

interface

uses
Classes, SysUtils;

{ストリームをエンコードしてストリームへ}
procedure b64enc(FMStream, TOStream: TStream; BR: Word); Overload;

const
TABLE : array[0..63] of Char = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/’;
brCRLF : Word = $0A0D;
brCR : Word = $000D;
brLF : Word = $000A;
brNIL : Word = $0000;
implementation

// 3バイトデータの並び順を変える
function ReOrder(Src: LongWord): LongWord;
type
Tmp = array[0..3]of Byte;
begin
Result := Src;
Tmp(Result)[2] := Tmp(Src)[0];
Tmp(Result)[0] := Tmp(Src)[2];
end;

{ストリームをエンコードしてストリームへ}
procedure b64enc(FMStream, TOStream: TStream; BR: Word);
var
i,m,count : Integer;
Src : LongWord;
SSize : LongInt;
begin
FMStream.Position := 0;
TOStream.Position := 0;
count := 0;
SSize := FMStream.Size;
for i:=1 to (SSize div 3) do begin
if count=76 then begin
if (BR=brCRLF) then TOStream.Write(brCRLF, 2)
else if (BR=brCR) then TOStream.Write(brCR, 1)
else if (BR=brLF) then TOStream.Write(brLF, 1);
count := 0;
end;
FMStream.Read(Src, 3);
Src := ReOrder(Src);
TOStream.Write(TABLE[(Src shr 18 and $3F)], 1);
TOStream.Write(TABLE[(Src shr 12 and $3F)], 1);
TOStream.Write(TABLE[(Src shr 6 and $3F)], 1);
TOStream.Write(TABLE[(Src and $3F)], 1);
inc(count, 4);
end;
m := SSize mod 3;
if m>0 then begin
if count=76 then begin
if (BR=brCRLF) then TOStream.Write(brCRLF, 2)
else if (BR=brCR) then TOStream.Write(brCR, 1)
else if (BR=brLF) then TOStream.Write(brLF, 1);
end;
FillChar(Src, 3, 0);
FMStream.Read(Src, m);
Src := ReOrder(Src);
case m of
1: begin
TOStream.Write(TABLE[(Src shr 18 and $3F)], 1);
TOStream.Write(TABLE[(Src shr 12 and $3F)], 1);
end;
2: begin
TOStream.Write(TABLE[(Src shr 18 and $3F)], 1);
TOStream.Write(TABLE[(Src shr 12 and $3F)], 1);
TOStream.Write(TABLE[(Src shr 6 and $3F)], 1);
end;
end;
TOStream.Write(’==’, 3 - m);
end;
end;
end.


TrackBacks

このコメントのRSS

TrackBack URL : http://www.kestrel.jp/modules/wordpress/wp-trackback.php/79

この投稿には、まだコメントが付いていません

コメント

_CM_NOTICE

20 queries. 0.020 sec.
Powered by WordPress Module based on WordPress ME & WordPress

ヘッドライン
nikkansports
IT Pro
レスポンス
テーマ選択

(4 テーマ)