開発環境 |
Microsoft Visual C++ 2010 Express (SP1) |
実行環境 |
Microsoft Windows XP Home Edition (SP3) |
プロジェクトの種類 |
Win32 コンソール アプリケーション |
プロジェクト名 |
lzwdec |
アプリケーションの種類 |
コンソール アプリケーション |
追加のオプション |
空のプロジェクト |
LZWの勉強用で制限事項、改良の余地多々あり。
参考
- GIFフォーマットの詳細 http://www.tohoho-web.com/wwwgif.htm
- 時雨エノキオプト-アセンブリホール2nd-自作ソフト-GIFデコーダ http://www.geocities.jp/warotarock/asen2ndgif001.html
- 辞書テーブルを利用しない新LZW法 http://homepage1.nifty.com/uchi/lzw.htm
- GIF89a Specification http://www.w3.org/Graphics/GIF/spec-gif89a.txt
- LZW and GIF explained http://www.martinreddy.net/gfx/2d/GIF-comp.txt
lzwdec.c
#include <stdio.h>
#include <stdlib.h>
// 型定義
typedef unsigned char UCHAR;
typedef unsigned int UINT;
// 関数プロトタイプ宣言
int LZWDecode(void);
int FetchCodeData(int iCodeSize);
int AddImageData(int iCode);
int AddDicTable(void);
int PrintImageData(void);
// グローバル変数
static UCHAR* g_pucImageData; // 画像データ
static int g_iImageData; // 画像データのサイズ
static int g_iImageIndex; // 画像データの指標
static int g_aiDicTable[0x1000]; // 辞書テーブル
static int g_iDicIndex; // 辞書テーブルの指標
static UCHAR* g_pucCodeData; // コード化データ
static int g_iCodeData; // コード化データのサイズ
static int g_iCodeIndex; // コード化データの指標
static UCHAR g_ucLZWMinimumCodeSize; // 最小コードビット数
static int g_iClearCode; // クリアコード
static int g_iEoICode; // 終了コード
static int g_iCodeSize; // コードのビット数
int main()
{
UCHAR aucImageData[256 * 256];
UCHAR aucCodeData[] = {
//0x00, 0x01, 0x04, 0x04 // 0
//0x00, 0x01, 0x08, 0x04, 0x10, 0x10 // 0 0 0 0
0x00, 0x03, 0xFC, 0x13, 0x48, 0xF0, 0x5F, 0x40 // 1 255 1 255 1 255 1 255
};
g_ucLZWMinimumCodeSize = 8;
g_iClearCode = 1 << g_ucLZWMinimumCodeSize;
g_iEoICode = g_iClearCode + 1;
g_iCodeSize = g_ucLZWMinimumCodeSize + 1;
g_pucImageData = aucImageData;
g_iImageData = _countof(aucImageData);
g_iImageIndex = 0;
FetchCodeData(0);
g_pucCodeData = aucCodeData;
g_iCodeData = _countof(aucCodeData);
g_iCodeIndex = 0;
LZWDecode();
PrintImageData();
return 0;
}
int LZWDecode(void)
{
int iCode;
while (1) {
iCode = FetchCodeData(g_iCodeSize);
printf("%d\n", iCode);
if (iCode < 0) {
return 1;
}
if (iCode == g_iClearCode) {
// 辞書テーブルのクリア
g_iDicIndex = g_iClearCode + 1;
g_aiDicTable[g_iDicIndex] = g_iImageIndex;
g_iCodeSize = g_ucLZWMinimumCodeSize + 1;
continue;
}
if (iCode == g_iEoICode) {
break;
}
if (g_iDicIndex < iCode) {
fprintf(stderr, "error: StringTable %u %d\n",
g_iDicIndex, iCode);
return -1;
}
AddImageData(iCode);
AddDicTable();
if ((1 << g_iCodeSize) <= g_iDicIndex) {
g_iCodeSize++;
}
}
return 0;
}
// コードの取得
// 戻り値:-1=失敗 0以上=コード
int FetchCodeData(int iCodeSize)
{
static UINT uiBits;
static int iBits;
int iCode;
if (iCodeSize <= 0) {
uiBits = 0;
iBits = 0;
return -1;
}
while (iBits < iCodeSize) {
if (g_iCodeData <= g_iCodeIndex) {
return -1;
}
uiBits |= g_pucCodeData[g_iCodeIndex++] << iBits;
iBits += 8;
}
iCode = uiBits & ((1 << iCodeSize) - 1);
uiBits >>= iCodeSize;
iBits -= iCodeSize;
return iCode;
}
// 文字データの追加
int AddImageData(int iCode)
{
int iEnd;
int i;
if (iCode < g_iClearCode) {
if (g_iImageData <= g_iImageIndex) {
return -1;
}
g_pucImageData[g_iImageIndex++] = iCode;
return 0;
}
iEnd = g_aiDicTable[iCode];
for (i = g_aiDicTable[iCode - 1]; i <= iEnd; i++) {
if (g_iImageData <= g_iImageIndex) {
return -1;
}
g_pucImageData[g_iImageIndex++] = g_pucImageData[i];
}
return 0;
}
// 辞書テーブルの追加
int AddDicTable(void)
{
if (_countof(g_aiDicTable) <= ++g_iDicIndex) {
return -1;
}
g_aiDicTable[g_iDicIndex] = g_iImageIndex;
return 0;
}
// 文字データの出力
int PrintImageData(void)
{
int i;
for (i = 0; i < g_iImageIndex; i++) {
printf("%d:%u\n", i, g_pucImageData[i]);
}
return 0;
}
出力
256
1
255
258
260
255
257
0:1
1:255
2:1
3:255
4:1
5:255
6:1
7:255
最終更新:2012年09月01日 16:48