CAD日記

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

ソフト開発

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

投稿日:2020年3月21日 更新日:

先週に引き続き今週もPDFアレコレをバージョンアップ。変更点は以下の通り。

Ver2.02 2020/3/21
・捺印時に画面でクリックしたところに配置できるようにした。(Ver2.01は固定値)
詳細はコチラ。

上でも触れたように、PDFに捺印できるんだったら画面で位置を指定できなきゃ意味がない。課題は画面でクリックした位置を取得して、どうやってPDFの座標系に落とし込むかってことだった。簡単に言うと、クリックした点を画面のX方向とY方向に対して比率で持っておいて、いざPDFに配置するときにその比率分で座標計算するだけでよかった。PDFが90度や270度で回転している場合に、PDFの高さと幅が逆になるってことに気付くのにずいぶん時間がかかってしまった。このあたりは、言葉では伝えられないのでコードで表そう。

マウスクリックしたときの処理で、XY方向の比率を保持して捺印実行部を呼び出している。

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
	if (!m_isMouseClickMode)
		return;
	int p = (int)numericUpDown1.Value;
	if (!(1 <= p && p <= m_maxpage))
		return;

	SizeF size = m_pdfDoc.PageSizes[p-1];
	float h1 = size.Width / size.Height;  // pdfの縦横比
	float h2 = (float)pictureBox1.Width / (float)pictureBox1.Height;  // コントロールの縦横比
	int width = 0, height = 0;
	if (h1 < h2)  // フォーム内にImageを当てはめる判定
	{
		width = (int)((float)pictureBox1.Height * h1);
		height = pictureBox1.Height;
	}
	else
	{
		width = pictureBox1.Width;
		height = (int)((float)pictureBox1.Width / h1);
	}
	Point pnt = e.Location;
	if (pnt.X < 0 || pnt.Y < 0 || pnt.X > width || pnt.Y > height)
	{
		MessageBox.Show("指定した点が用紙範囲外");
		return;
	}
	m_rx = pnt.X / (double)width;
	m_ry = 1.0 - (pnt.Y / (double)height);
	execNatsuin(p);
	m_isMouseClickMode = false;
	ChangeControl();
	this.Cursor = Cursors.Default;
}

捺印実行部の処理。PDFの回転と画面クリック時の比率を考慮。画面中央に捺印イメージがあるので、捺印用PDFの用紙サイズの高さと幅を半分引いている。

public bool Natsuin(ref string file, int pno, string strNtin, double rx, double ry)
{
	string temp = uty.GetTempPDFName();
	bool stat = true;
	PdfReader src = new PdfReader(file);
	PdfReader add = new PdfReader(strNtin);
	try
	{
		int pagesCount = src.NumberOfPages;
		if (0 < pno && pno <= pagesCount)
		{
			iTextSharp.text.Rectangle srcBox = src.GetPageSize(pno);
			iTextSharp.text.Rectangle addBox = add.GetPageSize(1);
			int rot = src.GetPageRotation(pno);
			double pos_y = 0, pos_x = 0;
			if (rot == 0 || rot == 180)
			{
				pos_y = srcBox.Height * ry;
				pos_x = srcBox.Width * rx;
			}
			else  // 90度または270度回転していると、高さ幅が逆になる
			{
				pos_y = srcBox.Width * ry;
				pos_x = srcBox.Height * rx;
			}
			pos_y -= addBox.Height / 2.0;  // 捺印用PDFは中央に捺印イメージがある前提なので、用紙サイズから半分引く
			pos_x -= addBox.Width / 2.0;
			PdfStamper stamper = new PdfStamper(src, new FileStream(temp, FileMode.Create));
			PdfImportedPage page = stamper.GetImportedPage(add, 1);
			stamper.GetImportedPage(src, pno);
			PdfContentByte cb = stamper.GetOverContent(pno);
			cb.AddTemplate(page, pos_x, pos_y);  // 配置点はここで指定する
			stamper.Close();
		}
		else
		{
			stat = false;
			MessageBox.Show("ページが範囲外");
		}
	}
	catch (PdfException ex)
	{
		stat = false;
		MessageBox.Show(string.Format("捺印に失敗({0})", ex.Message));
	}
	finally
	{
		src.Close();
		add.Close();
		if (stat)
		{
			uty.FileDelete(file);
			file = temp;
		}
	}
	return stat;
}

PDFiumの描画エンジンとiTextSharpのPDF編集が組み合わさると、こんなにアレコレできるんだということの一つをはっきり形にできた。でも、まだ課題はある。捺印用PDFが4MBとデカイから、捺印した結果のPDFがデカくなるし、メモリーだってやけに消費してしまう。Web任印というサイトで作ったPDFだからしょうがないんだけど、もっとサイズが小さくならんかね。たぶんハンコ用の文字フォントを埋め込まずにアウトライン化しているためだと思う。たかだか2文字や3文字のために4MBはデカイよな。透過ありの画像またはフォントのベクトル情報で配置できれば、格段にスリム化できるはず。おもしろくなってきたじゃないか。

-ソフト開発

執筆者:


comment

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

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

関連記事

no image

テキストファイルの最大行数

【2018/12/24追記】以下の記事も参考になるかな。 扱えるテキストファイルの最大行数は1億行 バカでかいテキストファイルを作る必要があって、結果約2GBにもなった。 CADから出力するんだけど、 …

zipcopy~圧縮してコピー~ができたのでアップしておく

【zipcopyの概要】 大きなファイルやフォルダをネットワーク越しにコピーする際、圧縮してからコピーすることで、ネットワークの帯域を少しで使わないようにすることを目的とする。以下3つの手順を自動的に …

no image

PDF印刷のアプリ指定

PCにAdobe ReaderとAcrobatの両方が入っている場合、PDFファイルを 右クリックメニューから印刷ってやると、どっちで印刷されるのか? Windows XPまでは、拡張子の関連付けのと …

zipcopy Ver1.07リリース

zipcopyをリビジョンアップして、Ver1.07とした。 詳細は以下の通り。 Ver1.07 2020/3/1 ・zip圧縮と解凍、ファイルコピーと削除処理についてスレッド化して、これら処理中にダ …

WinMergeで複数拡張子を対象とするファイルフィルタと簡単な行フィルタ指定をやってみた

WinMergeでファイル比較することは、SEだったらみんなやっていることと思う。でもファイルフィルタと行フィルタは使ったことがないと思う。おいらだって、何年もWinMergeを使ってきたけど、正規表 …