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 を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

関連記事

zipcopy Ver1.05リリース

zipcopyをリビジョンアップして、Ver1.05とした。 詳細は以下の通り。 Ver1.05 2019/9/30 ・7zip使用でない(DotNetZip)場合に、4GB以上のzipへの圧縮ができ …

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

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

no image

通常使うプリンタを取得する

通常使うプリンターを取得する方法をいくつか挙げる。 ①GetDefaultPrinter TCHAR printerName[1024]; DWORD dwBufferSize = 1024; BOO …

C#でzip圧縮と解凍したりasync/awaitで非同期処理をするソースコード公開

zipcopyという名の開発プロジェクトはここらで終わりにしようと思い至ったので、そのソースコードを公開する。 zipcopyのソースコード 開発環境はVisualStudio 2017 C#で、Nu …

no image

C言語

遡ること10数年、初めて学んだコンピュータ言語がC言語でした。以来、ずっとやってます。机の上には本が一冊。 「実習C言語」(アスキー・ラーニングシステム) この本の画像を探してみましたが、古いだけにみ …