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

レイヤ付きPDFを出力する弊害

Illustratorという高価なアプリを使ってPDFを出力すると、PDFにレイヤが付いてしまって非表示にしたはずのレイヤが表示されて困ったなという事象に2回遭遇したので以下に記録。共通しているのが、 …

no image

クラッカー

知人が被害を受けました。以下、知人の経験談です。 便利なソフトを作って一儲けしたい! シェアウェアとして公開して、誰でもダウンロードできるようにすることを考えました。まずは使ってもらわないと、その良さ …

PDFアレコレのユーザーインターフェース改良と回転角度を追加

PDFアレコレのユーザーインターフェース改良と回転角度を追加。 Ver2.07 2020/5/4 ・プレビュー画面のメニューをツールバー形式にして整理した。 ・ページ回転について左90度と180度の回 …

zipcopy Ver1.06リリース

zipcopyをリビジョンアップして、Ver1.06とした。 詳細は以下の通り。 Ver1.06 2020/2/24 ・ファイル削除時のタイムアウト(秒)を設定可能として、初期値を180秒(3分)とし …

最小化したウインドウの位置を保存して復元するとまずい話(C++編)

ウインドウを最小化した状態としてタスクバーから右クリックして閉じるってやると、次回ウインドウを起動したときに画面外に出てしまって、操作不能になるアプリがある。そんなときは、タスクバーの上にカーソルを置 …