CAD日記

主にAutoCADのことについて書いているけど、近頃は投資系ネタに注力している。自動売買、仮想通貨、PC関係、プログラミングなど。@caddiary

ソフト開発 DWG

dwgからサムネイル用画像を抜き出す方法2

投稿日:

dwgからサムネイル用画像を抜き出す方法として理屈上の話を書いたが、これだけでは片手落ちだと考えて、プログラム実装のところまで踏み込むことにした。
まずは、dwgからサムネイル用画像を取得して、同名ファイル(拡張子ちがい)で保存するというメイン処理。
どういうことをやっているかは、前の記事および以下の処理から読み取ってくれればよい。

bool CDwgThumbCppDlg::Exec(LPCTSTR pFile)
{
	// ファイルを開く
	CFile file;
	CFileException e;
	if (!file.Open(pFile, CFile::modeRead | CFile::shareDenyNone, &e))
		return false;

	// データのバージョンチェック
	char szBuff[MAX_PATH] = {0};
	file.Seek(0, CFile::begin);
	if (file.Read(szBuff, 6) != 6)
		return false;
	if (lstrcmpA(szBuff, "AC1012") < 0)
		return false;  // バージョンが古い

	// イメージの開始アドレスを得る
	// - 0x0000000D から4バイトがイメージのアドレスになる
	file.Seek(0x0000000D, CFile::begin);
	ULONG lImgOffset = 0;
	if (file.Read(&lImgOffset, 4) != 4)
		return false;
	if (lImgOffset <= 0)
		return false;

	// イメージのブロック数の取得
	// - イメージ関連基準アドレス+20バイトの位置にイメージのブロック数
	// - イメージ関連基準アドレス+21以降9バイト単位でイメージの情報が続く
	BYTE nBlock = 0;
	file.Seek(lImgOffset + 20, CFile::begin);
	file.Read(&nBlock, 1);
	file.Seek(lImgOffset + 21, CFile::begin);

	bool stat = false;
	for (int n = 0; n < (int)nBlock && stat == false; n++)  // 読めたら終了
	{
		if (file.Read(&sImgInf, sizeof(sImgInf)) != sizeof(sImgInf))
			break;
		// ビットマップ
		if (sImgInf.type == 2 && sImgInf.lSize > 0 && sImgInf.lStart >= 0)
		{
			// ビットマップデータの読込
			BYTE* mem = new BYTE[sImgInf.lSize + 10];
			file.Seek(sImgInf.lStart, CFile::begin);
			if (file.Read(mem, sImgInf.lSize) == (UINT)sImgInf.lSize)
			{
				CClientDC dc(this);
				stat =_WriteBitmap(&dc, mem, _MakeRasterFileNmae(pFile, 0));
			}
			delete[] mem;
		}
		// PNG
		if (sImgInf.type == 6 && sImgInf.lSize > 0 && sImgInf.lStart >= 0)
		{
			HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, sImgInf.lSize + 10);
			if (hGlobal == NULL)
				continue;
			BYTE* mem1 = (BYTE*)GlobalLock(hGlobal);
			file.Seek(sImgInf.lStart, CFile::begin);
			if (file.Read(mem1, sImgInf.lSize) == (UINT)sImgInf.lSize)
			{
				// PNGをIStreamに読込み
				GlobalUnlock(hGlobal);
				IStream* pIStream = NULL;
				HRESULT hres = CreateStreamOnHGlobal(hGlobal, TRUE, &pIStream);
				if (hres == S_OK)
				{
					CImage img;
					img.Load(pIStream);
					img.Save(_MakeRasterFileNmae(pFile, 1));
					stat = true;
				}
			}
			GlobalFree(hGlobal);
		}
	}
	return stat;
}

画像ファイル名作成の_MakeRasterFileNmaeは、拡張子を差し替えただけの処理で単純だが、一応以下に載せておく。

static CString _MakeRasterFileNmae(LPCTSTR pFile, int type)
{
	CString src(pFile);
	int pos = src.ReverseFind('.');
	CString dst;
	if (pos != -1)
	{
		dst = src.Mid(0, pos + 1);
		if (type == 0)
			dst += _T("bmp");
		else if (type == 1)
			dst += _T("png");
	}
	return dst;
}

画像のファイル化ということでは、pngは上記処理で完結していてシンプルなのに対して、bmpだと別関数_WriteBitmapを呼び出している。ビットマップファイルはなかなか手ごわくて、DIBとかDDBとかのちがいがあり、パレットで色数を定義してなんてとてもややこしい。ネットで調べて、動くよう組んでみた結果を以下に載せておく。古い形式のビットマップまでサポートしているっぽく汎用性が高いためか、コードが長い。ムダがあるかもしれないが動くからヨシとしておく。
コードが長いことが影響してか、コードをそのまま載せるとWordPressがエラーを返してくるので、テキストファイルでアップロードした。
WriteBitmap

-ソフト開発, DWG

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

関連記事

no image

Teigha

Teigha=ティーガ、とのこと。 DWGdirect 新ブランド名 Teigha (ティーガ) ODAのAutodeskとの戦いの結果は、DWGdirect・OpenDWGといった すでに商標登録し …

no image

OpenDWG

2次元CADのデータ交換で最も使われているのは、DWGです。少し前までは、DXFだったのですが、徐々にDWGに移行しています。SXFというものも流通し始めていますが、まだその比率は低いです。さて、その …

no image

random

JavaScriptと格闘してみたよ。 テーマはランダム。 10個の画像の中から、任意の3個の画像をWebサイトに表示する、 ってのが要求仕様。 Math.floor(Math.random() * …

PDFアレコレで画面の拡大・縮小・移動ができるようにした

PDFアレコレをバージョンアップ。約4か月ぶり。 Ver3.05 2021/6/20 ・PDFの描画位置を左右上下にセンタリングするようにした(以前は左上)。 ・Ctrl+マウスホイール上下操作によっ …

PDFアレコレにページ抽出機能を追加して独自アイコンも組み込んだ

PDFアレコレに念願のページ抽出機能を追加した。ページの操作っていうのはPDF編集においてキモだ。ページの回転を考慮した編集操作が必要だからけっこう苦労しちゃった。変更点は以下の通り。 Ver2.06 …