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

TrustedDWG

AutoCADに関わる人のあいだで、ちょっとした話題になっている。 TrustedDWG=「本当の信頼」なのか。 Autodeskいわく、DWGは世界で最も利用されているデザインデータ形式。 デザイン …

PDFに捺印できるようにしたPDFアレコレを公開

半年ぶりにPDFアレコレをバージョンアップ。変更点は以下の通り。 Ver2.01 2020/3/15 ・プレビューからの捺印機能に対応。捺印用データはとりあえずpdfのみで配置点が固定。  ※そのうち …

no image

プログラムっておもしろいなぁとつくづく思うなり

ここんところぜんぜんプログラムを書いてなくて仕事がつまんなくなってきたところに、トラブル対応があってプログラムをじっくりと書いてみた。いやはやおもしろい。余計な仕事が飛び込んでこない環境で、スピッツ聞 …

扱えるテキストファイルの最大行数は1億行

扱えるテキストファイルの行数の限界が1億行なのが秀丸エディター。その他⇒動作環境⇒環境にて、編集可能な最大行数が10万行~1億行で設定できる(32bitの場合は1000万行まで)。1億行のテキストファ …

PDFアレコレで捺印まわりのバグ修正

PDFアレコレをバージョンアップ。約3か月ぶり。 Ver3.02 2020/10/24 ・捺印などのPDF編集操作後にファイルを閉じて開いて、再編集すると以前編集していたPDFが復活していた。閉じると …