開発環境 Microsoft Visual C++ 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Win32 コンソール アプリケーション
プロジェクト名 dumpjpg
アプリケーションの種類 コンソール アプリケーション
追加のオプション 空のプロジェクト

開発中。

dumpjpg.c
#include <fcntl.h>	// _O_WTEXT
#include <io.h>		// _setmode
#include <stdio.h>	// _fileno
#include <stdlib.h>	// malloc
#include <tchar.h>
 
typedef unsigned char	UCHAR;
typedef unsigned short	USHORT;
 
// 関数プロトタイプ宣言
USHORT betos(USHORT us);
void* FetchFile(size_t sizeCount);
int ParseFile(void);
int ParseUnknown(void);
int ParseAPPn(void);
int ParseDQT(void);
int ParseSOF0(void);
int ParseDHT(void);
int ParseSOS(void);
 
// グローバル変数
static UCHAR*	g_pucFile;		// ファイル内容
static size_t	g_sizeFile;		// ファイルサイズ
static size_t	g_sizeFileIndex;	// ファイルの指標
 
#define dprintf(fmt, var) _tprintf(_T(#var)_T("=[")fmt##_T("]\n"), var)
 
int _tmain(int argc, TCHAR* argv[])
{
	struct _stat	stat;		// ファイル情報
	FILE*		pFile;		// ファイルポインタ
	TCHAR*		ptcFile;	// ファイル名
 
	_setmode(_fileno(stdout), _O_WTEXT);
	_setmode(_fileno(stderr), _O_WTEXT);
 
	if (argc != 2) {
		_ftprintf(stderr, _T("usage: dumpjpg file\n"));
		return 1;
	}
	ptcFile = argv[1];
 
	// ファイルサイズの取得
	if (_tstat(ptcFile, &stat) != 0) {
		_ftprintf(stderr, _T("error: _tstat[%s]\n"), ptcFile);
		return 1;
	}
	g_sizeFile = stat.st_size;
 
	// ファイルのオープン
	if (_tfopen_s(&pFile, ptcFile, _T("rb")) != 0) {
		_ftprintf(stderr, _T("error: _tfopen_s[%s]\n"), ptcFile);
		return 1;
	}
 
	// メモリの確保
	g_pucFile = (UCHAR*)malloc(g_sizeFile);
	if (g_pucFile == NULL) {
		_ftprintf(stderr, _T("error: malloc[%u]\n"), g_sizeFile);
		return 1;
	}
 
	// ファイルの読み込み
	if (fread(g_pucFile, 1, g_sizeFile, pFile) != g_sizeFile) {
		_ftprintf(stderr, _T("error: fread[%s]\n"), ptcFile);
		return 1;
	}
	fclose(pFile);
 
	// ファイルの解析
	g_sizeFileIndex = 0;
	while (ParseFile() == 0) {
	}
 
	free(g_pucFile);
	return 0;
}
 
// ビッグエンディアン短整数の変換
USHORT betos(USHORT us)
{
	return us << 8 | us >> 8;
}
 
// ファイル内容の取得
void* FetchFile(size_t sizeCount)
{
	void*	pv;
 
	if (g_sizeFile < g_sizeFileIndex + sizeCount) {
		_ftprintf(stderr, _T("error: FetchFile\n"));
		exit(1);
	}
	pv = g_pucFile + g_sizeFileIndex;
	g_sizeFileIndex += sizeCount;
	return pv;
}
 
// ファイルの解析
int ParseFile(void)
{
	UCHAR*	pucMarker;
	size_t	sizeFileIndex;
 
	sizeFileIndex = g_sizeFileIndex;
	pucMarker = (UCHAR*)FetchFile(2);
	_tprintf(_T("\n*** [0x%02X%02X] [0x%08X]\n"),
		pucMarker[0], pucMarker[1], sizeFileIndex);
 
	if (pucMarker[0] != 0xFF) {
		return -1;
	}
 
	switch (pucMarker[1]) {
	case 0xC0:
		ParseSOF0();
		break;
	case 0xC4:
		ParseDHT();
		break;
	case 0xE0:
		ParseAPPn();
		break;
	case 0xD8:
		_tprintf(_T("SOI\n"));	// 画像開始
		break;
	case 0xD9:
		_tprintf(_T("EOI\n"));	// 画像終了
		return 1;
//		break;
	case 0xDA:
		ParseSOS();
		break;
	case 0xDB:
		ParseDQT();
		break;
	default:
		ParseUnknown();
	}
	return 0;
}
 
// 不明
int ParseUnknown(void)
{
	USHORT*	pusLp;
	USHORT	usLp;
 
	_tprintf(_T("Unknown\n"));
 
	pusLp = (USHORT*)FetchFile(2);
	usLp = betos(*pusLp);
	FetchFile(usLp - 2);
	return 0;
}
 
// アプリケーションデータ
int ParseAPPn(void)
{
	USHORT	usLa;			// パラメータ長
	struct SApp {
		char	aucID[5];	// JFIF識別子
		UCHAR	ucV1;		// メジャーバージョン
		UCHAR	ucV2;		// マイナーバージョン
		UCHAR	ucU;		// 密度単位(1:dots/inch)
		USHORT	usXd;		// 横密度
		USHORT	usYd;		// 縦密度
		UCHAR	ucXt;		// サムネイル横ドット数
		UCHAR	ucYt;		// サムネイル縦ドット数
	} *pApp;
	USHORT*	pus;
 
	_tprintf(_T("APPn\n"));
 
	pus = (USHORT*)FetchFile(2);
	usLa = betos(*pus);
	dprintf(_T("%u"), usLa);
	pApp = (struct SApp*)FetchFile(usLa - 2);
	dprintf(_T("%S"), pApp->aucID);
	dprintf(_T("%u"), pApp->ucV1);
	dprintf(_T("%u"), pApp->ucV2);
	dprintf(_T("%u"), pApp->ucU);
	dprintf(_T("%u"), betos(pApp->usXd));
	dprintf(_T("%u"), betos(pApp->usYd));
	dprintf(_T("%u"), pApp->ucXt);
	dprintf(_T("%u"), pApp->ucYt);
 
	return 0;
}
 
// 量子化テーブル定義
int ParseDQT(void)
{
	USHORT	usLq;			// 量子化テーブル定義長(2+65*t)
	struct SDQT {
		UCHAR	ucTq:	4;	// 量子化テーブル識別子
		UCHAR	ucPq:	4;	// エレメント精度
		UCHAR	aucQ[64];	// 量子化テーブルの要素
	} *pDQT;
	USHORT*	pus;
	int	i;
 
	_tprintf(_T("DQT\n"));
 
	pus = (USHORT*)FetchFile(2);
	usLq = betos(*pus);
	dprintf(_T("%u"), usLq);
	pDQT = (struct SDQT*)FetchFile(usLq - 2);
	dprintf(_T("%u"), pDQT->ucPq);
	dprintf(_T("%u"), pDQT->ucTq);
	for (i = 0; i < 64; i++) {
		_tprintf(_T("%02X%c"), pDQT->aucQ[i], _T("   -   \n")[i % 8]);
	}
 
	return 0;
}
 
// フレーム開始:基本DCT方式
int ParseSOF0(void)
{
	USHORT	usLf;			// フレームヘッダ長
#pragma pack(push, 1)
	struct SOF {
		UCHAR	ucP;		// サンプル精度
		USHORT	usX;		// ライン数
		USHORT	usY;		// ライン当たりのサンプル数
		UCHAR	ucNf;		// フレーム内の画像成分数
	} *pSOF;
#pragma pack(pop)
	struct Pa {			// 成分指定パラメータ
		UCHAR	ucC;		// 成分識別子
		UCHAR	ucV:	4;	// 垂直サンプリングファクタ
		UCHAR	ucH:	4;	// 水平サンプリングファクタ
		UCHAR	ucTq;		// 量子化テーブルセレクタ
	} *pPa;
	USHORT*	pus;
	int	i;
 
	_tprintf(_T("SOF0\n"));
 
	pus = (USHORT*)FetchFile(2);
	usLf = betos(*pus);
	dprintf(_T("%u"), usLf);
	pSOF = (struct SOF*)FetchFile(usLf - 2);
	dprintf(_T("%u"), pSOF->ucP);
	dprintf(_T("%u"), betos(pSOF->usX));
	dprintf(_T("%u"), betos(pSOF->usY));
	dprintf(_T("%u"), pSOF->ucNf);
	for (i = 0; i < pSOF->ucNf; i++) {
		pPa = (struct Pa*)(((UCHAR*)pSOF) + 6 + i * 3);
		_tprintf(_T("%d:C=%u H=%u V=%u Tq=%u\n"),
			i + 1, pPa->ucC, pPa->ucH, pPa->ucV, pPa->ucTq);
	}
 
	return 0;
}
 
// ハフマンテーブル定義
int ParseDHT(void)
{
	USHORT	usLh;
	struct DHT {
		UCHAR	ucTh:	4;	// ハフマンテーブル識別子
		UCHAR	ucTc:	4;	// テーブルクラス(0:DC成分用、1:AC成分用)
		UCHAR	aucL[16];	// 長さiビットの符号語数
		UCHAR	aucV[];		// それぞれの符号語に関連する値
	} *pDHT;
	USHORT*	pus;
	int	iLi;
	int	iLj;
	int	iV;
 
	_tprintf(_T("DHT\n"));
 
	pus = (USHORT*)FetchFile(2);
	usLh = betos(*pus);
	dprintf(_T("%u"), usLh);
	pDHT = (struct DHT*)FetchFile(usLh - 2);
	dprintf(_T("%u"), pDHT->ucTc);
	dprintf(_T("%u"), pDHT->ucTh);
	iV = 0;
	for (iLi = 0; iLi < 16; iLi++) {
		_tprintf(_T("L%d=[%u]\n"), iLi + 1, pDHT->aucL[iLi]);
		for (iLj = 0; iLj < pDHT->aucL[iLi]; iLj++) {
			_tprintf(_T("%02X%c"), pDHT->aucV[iV++],
				_T("   -   -   -   \n")[iLj % 16]);
		}
		if (iLj % 16) {
			_tprintf(_T("\n"));
		}
	}
 
	return 0;
}
 
// スキャン開始
int ParseSOS(void)
{
	USHORT	usLs;			// スキャンヘッダ長
	UCHAR*	pucNs;			// スキャン内の画像成分数
	struct SPa {			// 成分指定パラメータ
		UCHAR	ucCs;		// スキャン成分セレクタ
		UCHAR	ucTa:	4;	// AC成分用ハフマンテーブルセレクタ
		UCHAR	ucTd:	4;	// DC成分用ハフマンテーブルセレクタ
	} *pPa;
	struct SSh {
		UCHAR	ucSs;		// 基本DCT方式では未使用(値固定)
		UCHAR	ucSe;		// 基本DCT方式では未使用(値固定)
		UCHAR	ucAl:	4;	// 基本DCT方式では未使用(値固定)
		UCHAR	ucAh:	4;	// 基本DCT方式では未使用(値固定)
	} *pSh;
	USHORT*	pus;
	UCHAR*	puc;
	UCHAR*	pucNext;
	int	i;
 
	_tprintf(_T("SOS\n"));
 
	// スキャンヘッダ
	pus = (USHORT*)FetchFile(2);
	usLs = betos(*pus);
	dprintf(_T("%u"), usLs);
	pucNs = (UCHAR*)FetchFile(1);
	dprintf(_T("%u"), *pucNs);
	for (i = 0; i < *pucNs; i++) {
		pPa = (struct SPa*)FetchFile(2);
		_tprintf(_T("%d:Cs=[%u] Td=[%u] Ta=[%u]\n"),
			i + 1, pPa->ucCs, pPa->ucTd, pPa->ucTa);
	}
	pSh = (struct SSh*)FetchFile(3);
	dprintf(_T("%u"), pSh->ucSs);
	dprintf(_T("%u"), pSh->ucSe);
	dprintf(_T("%u"), pSh->ucAh);
	dprintf(_T("%u"), pSh->ucAl);
 
	// エントロピー符号化セグメント(インタバル)
	for (i = 0; ; i++) {
		puc = (UCHAR*)FetchFile(1);
		if (*puc == 0xFF) {
			pucNext = (UCHAR*)FetchFile(1);
			if (*pucNext != 0x00) {
				g_sizeFileIndex -= 2;
				break;
			}
		}
		_tprintf(_T("%02X%c"), *puc, _T("   -   \n")[i % 8]);
	}
	_tprintf(_T("\n"));
	return 0;
}
 

出力

*** [0xFFD8] [0x00000000]
SOI

*** [0xFFE0] [0x00000002]
APPn
usLa=[16]
pApp->aucID=[JFIF]
pApp->ucV1=[1]
pApp->ucV2=[1]
pApp->ucU=[1]
betos(pApp->usXd)=[96]
betos(pApp->usYd)=[96]
pApp->ucXt=[0]
pApp->ucYt=[0]

*** [0xFFDB] [0x00000014]
DQT
usLq=[67]
pDQT->ucPq=[0]
pDQT->ucTq=[0]
08 06 06 07-06 05 08 07
07 07 09 09-08 0A 0C 14
0D 0C 0B 0B-0C 19 12 13
0F 14 1D 1A-1F 1E 1D 1A
1C 1C 20 24-2E 27 20 22
2C 23 1C 1C-28 37 29 2C
30 31 34 34-34 1F 27 39
3D 38 32 3C-2E 33 34 32

*** [0xFFDB] [0x00000059]
DQT
usLq=[67]
pDQT->ucPq=[0]
pDQT->ucTq=[1]
09 09 09 0C-0B 0C 18 0D
0D 18 32 21-1C 21 32 32
32 32 32 32-32 32 32 32
32 32 32 32-32 32 32 32
32 32 32 32-32 32 32 32
32 32 32 32-32 32 32 32
32 32 32 32-32 32 32 32
32 32 32 32-32 32 32 32

*** [0xFFC0] [0x0000009E]
SOF0
usLf=[17]
pSOF->ucP=[8]
betos(pSOF->usX)=[1]
betos(pSOF->usY)=[1]
pSOF->ucNf=[3]
1:C=1 H=2 V=2 Tq=0
2:C=2 H=1 V=1 Tq=1
3:C=3 H=1 V=1 Tq=1

*** [0xFFC4] [0x000000B1]
DHT
usLh=[31]
pDHT->ucTc=[0]
pDHT->ucTh=[0]
L1=[0]
L2=[1]
00 
L3=[5]
01 02 03 04-05 
L4=[1]
06 
L5=[1]
07 
L6=[1]
08 
L7=[1]
09 
L8=[1]
0A 
L9=[1]
0B 
L10=[0]
L11=[0]
L12=[0]
L13=[0]
L14=[0]
L15=[0]
L16=[0]

*** [0xFFC4] [0x000000D2]
DHT
usLh=[181]
pDHT->ucTc=[1]
pDHT->ucTh=[0]
L1=[0]
L2=[2]
01 02 
L3=[1]
03 
L4=[3]
00 04 11 
L5=[3]
05 12 21 
L6=[2]
31 41 
L7=[4]
06 13 51 61-
L8=[3]
07 22 71 
L9=[5]
14 32 81 91-A1 
L10=[5]
08 23 42 B1-C1 
L11=[4]
15 52 D1 F0-
L12=[4]
24 33 62 72-
L13=[0]
L14=[0]
L15=[1]
82 
L16=[125]
09 0A 16 17-18 19 1A 25-26 27 28 29-2A 34 35 36
37 38 39 3A-43 44 45 46-47 48 49 4A-53 54 55 56
57 58 59 5A-63 64 65 66-67 68 69 6A-73 74 75 76
77 78 79 7A-83 84 85 86-87 88 89 8A-92 93 94 95
96 97 98 99-9A A2 A3 A4-A5 A6 A7 A8-A9 AA B2 B3
B4 B5 B6 B7-B8 B9 BA C2-C3 C4 C5 C6-C7 C8 C9 CA
D2 D3 D4 D5-D6 D7 D8 D9-DA E1 E2 E3-E4 E5 E6 E7
E8 E9 EA F1-F2 F3 F4 F5-F6 F7 F8 F9-FA 

*** [0xFFC4] [0x00000189]
DHT
usLh=[31]
pDHT->ucTc=[0]
pDHT->ucTh=[1]
L1=[0]
L2=[3]
00 01 02 
L3=[1]
03 
L4=[1]
04 
L5=[1]
05 
L6=[1]
06 
L7=[1]
07 
L8=[1]
08 
L9=[1]
09 
L10=[1]
0A 
L11=[1]
0B 
L12=[0]
L13=[0]
L14=[0]
L15=[0]
L16=[0]

*** [0xFFC4] [0x000001AA]
DHT
usLh=[181]
pDHT->ucTc=[1]
pDHT->ucTh=[1]
L1=[0]
L2=[2]
00 01 
L3=[1]
02 
L4=[2]
03 11 
L5=[4]
04 05 21 31-
L6=[4]
06 12 41 51-
L7=[3]
07 61 71 
L8=[4]
13 22 32 81-
L9=[7]
08 14 42 91-A1 B1 C1 
L10=[5]
09 23 33 52-F0 
L11=[4]
15 62 72 D1-
L12=[4]
0A 16 24 34-
L13=[0]
L14=[1]
E1 
L15=[2]
25 F1 
L16=[119]
17 18 19 1A-26 27 28 29-2A 35 36 37-38 39 3A 43
44 45 46 47-48 49 4A 53-54 55 56 57-58 59 5A 63
64 65 66 67-68 69 6A 73-74 75 76 77-78 79 7A 82
83 84 85 86-87 88 89 8A-92 93 94 95-96 97 98 99
9A A2 A3 A4-A5 A6 A7 A8-A9 AA B2 B3-B4 B5 B6 B7
B8 B9 BA C2-C3 C4 C5 C6-C7 C8 C9 CA-D2 D3 D4 D5
D6 D7 D8 D9-DA E2 E3 E4-E5 E6 E7 E8-E9 EA F2 F3
F4 F5 F6 F7-F8 F9 FA 

*** [0xFFDA] [0x00000261]
SOS
usLs=[12]
*pucNs=[3]
1:Cs=[1] Td=[0] Ta=[0]
2:Cs=[2] Td=[1] Ta=[1]
3:Cs=[3] Td=[1] Ta=[1]
pSh->ucSs=[0]
pSh->ucSe=[63]
pSh->ucAh=[0]
pSh->ucAl=[0]
F7 FA 28 A2-80 3F 

*** [0xFFD9] [0x00000275]
EOI
最終更新:2012年09月01日 16:47