SQLの窓 イラストAC フリー素材

2014年09月28日

TCPDF + FPDI : PHP で既存 PDF を読み込んで加工してブラウザに送る

8年の月日が流れましたが、FPDFTCPDF に変えても、FPDI が自動的に全て処理するので、TCPDF のプラグインのような形で動作します。

▼ main ではこんなかんじ
require_once("../common/tcpdf_include.php");
require_once("../../fpdi/fpdi.php");
require_once("../common/common.php");
require_once("model.php");
<?php
// ***********************************************
//
//  部   品   名 : モデル
//  プログラム名 : 社員一覧印刷
//  作   成   者 : lightbox
//  作   成   日 : 2014/06/06
//
//  概要 : 
//  印刷処理の為のテンプレート
//  ここでは、プログラム固有の処理を定義します
//
// ***********************************************

// ***********************************************
// データベース読み出し
// ***********************************************
function query() {

	global $connect,$row,$SEARCH_DATA;

	$pdf = new FPDI(
		"L",
		PDF_UNIT,
		"A4",
		true,
		"UTF-8",
		false,
		false		// PDF/A モード
	);

	# PDF を読み込んでページ数を得る
	$pagecount = $pdf->setSourceFile("Book1.pdf");
	# ページ番号より ID を取得する
	$tplidx = $pdf->ImportPage(1);
	//**********************************************************
	// 設定
	//**********************************************************
	$pdf->setFontSubsetting(false);
	$pdf->setPrintHeader(false);
	$pdf->setPrintFooter(false);
	$pdf->SetFont('meiryo001', '', 12);
	// デフォルトが true なので、デバッグ時に混乱しないように false に設定
	$pdf->SetAutoPageBreak(false);

	$pdf->AddPage();
	// テンプレートの適用
	$pdf->useTemplate($tplidx);
	// AddPage 実行後に取得する

	$query = apply_value("select.sql");
	$result = $connect->query($query); 

	$counter = 0;

	$cur_position = print_header( $pdf );
	while ($row = $result->fetch_array(MYSQLI_BOTH)) {

		$counter++;
		if ( $counter > 20 ) {
			$counter = 0;
			$pdf->AddPage();
			// テンプレートの適用
			$pdf->useTemplate($tplidx);
			$cur_position = print_header( $pdf );
		}

		user_text( $pdf, 10, $cur_position, $row['社員コード'] );
		user_text( $pdf, 28, $cur_position, $row['氏名'] );

		$cur_position = user_text( $pdf, 63, $cur_position, number_format($row['給与']), 20, 0, "R" );

	}

	// ブラウザへ PDF を出力します
	$pdf->Output("syain.pdf", "I");

	// 実際の SQL の結果の情報を返します
	return $result;

}

// ***********************************************
// ヘッダ印字
// ***********************************************
function print_header( $pdf ) {

	$page_info = $pdf->getPageDimensions();
	$cur_position = $page_info['tm'];	// トップマージン

	$cur_position = user_text( $pdf, 125, $cur_position, "社員マスター一覧表" );
	$cur_position = user_text( $pdf, 0, $cur_position, "" );
	user_text( $pdf, 10, $cur_position, "コード" );
	user_text( $pdf, 28, $cur_position, "名前" );
	$cur_position = user_text( $pdf, 63, $cur_position, "給与", 20, 0, "R" );

	return $cur_position;

}

?>

TCPDF で動作している場合 FPDI を 読み込んで、TCPDF クラス をそのまま FPDI クラスに変更し、既存 PDF を読み込んで、AddPage する毎にテンプレート使用( $pdf->useTemplate($tplidx) ) を実行するだけです。

本来の目的であるフォームのオーバーレイを想定して、枠線だけを持つ PDF を Microsoft Excel で作成して重ねました。

実行結果

FPDI のドキュメントはこちらを参照

▼ 以下は TCPDF 用の実行環境設定用のファイルです( require_once します )
<?php
// Include the main TCPDF library (search for installation path).
$path = "C:\user\web\tcpdf";
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
require_once('examples/config/tcpdf_config_alt.php');
require_once('tcpdf.php');
?>


▼ 以下は、印字用の関数です( 今回の FPDI に関するでページあふれ対応はしていません )
# **********************************************************
#  テキスト印字
# **********************************************************
function user_text( $pdf, $x, $y, $text, $w=1, $h=0, $p="L" ) {

	text( $pdf, $x, $y, $text, $w, $h, $p );

	return $y;

}

# **********************************************************
# 位置指定印字
# ※ 改行コードで自動改行
# ※ ページあふれで自動改ページ
# ※ 内部印字位置は保存( 元に戻す )
# **********************************************************
function text( $pdf, $x=0, &$y=0, $txt='', $w=1, $h=0, $p="L" ) {

	$a = $pdf->GetX();
	$b = $pdf->GetY();

	$hm = $pdf->getPageHeight( );
	$dm = $pdf->getPageDimensions();
	$tm = $dm['tm'];
	$bm = $dm['bm'];

	$txt = str_replace( "\r","", $txt );
	$data = explode("\n", $txt );
	if ( count( $data ) > 1 ) {
		for( $i = 0; $i < count($data); $i++ ) {
			if ( $i == 0 ) {
				$pdf->SetXY( $x, $y );
			}
			else {
				$y += $pdf->getLastH();
				if ( $y >= ( $hm - $tm - $bm ) ) {
					$pdf->AddPage();
					$y = $tm;
				}
				$pdf->SetXY( $x, $y );
			}
			$pdf->Cell($w, $h, $data[$i], 0, 0, $p);
		}
	}
	else {
		$pdf->SetXY( $x, $y );
		$pdf->Cell($w, $h, $txt, 0, 0, $p);
	}
	$y += $pdf->getLastH();

	$pdf->SetXY($a,$b);

}
TCPDF に関しては、『TCPDFマニュアル(勝手訳)』といのが検索するとすぐ見つかります。これでほぼ OK です。



関連する記事

TCPDF で非埋め込み型として『メイリオ』を使う手順



▼ 以下は古い記事です
2006-11-26 の記事
PDF は、基本ブラウザに埋め込まれるので、Webアプリの印刷処理として最適です。

多少制限もありますが普通に日本語使えますし。知らないと損しますね。

詳細は↓
http://winofsql.jp/VA003334/phpVarious061126183640.htm


一つのパッケージでは無いので構成するのにそれなりの知識が必要になります。ソースも少し書き換えが発生します。

既存のPDF 利用の部分は日本語マニュアル無いみたいですし・・・
でもまあ、プログラマなら理解できる程度の英語です。


posted by at 2014-09-28 01:15 | PHP+PDF | このブログの読者になる | 更新情報をチェックする

2014年09月25日

JavaScript : コンボボックスの OPTION 部分の操作でたいていのテクニック

コンボボックスのリストを全て削除

▼ 実際の実行
<script type="text/javascript">
function resetCombo() {

	var combo = document.frm1.combo1
	combo.length = 0;

}
</script>
<form name="frm1">
	<select name="combo1"
		style='width:150px;'>
		<option value="1">データ1
		</option>
		<option value="2">データ2
		</option>
		<option value="3">データ3
		</option>
		<option value="4">データ4
		</option>
	</select>
</form>
<input type="button"
	value="全て削除"
	onclick='resetCombo();'>
一つづつ削除する場合は、combo.remove(index) です。


コンボボックスにリストを追加する

▼ 実際の実行
<script type="text/javascript">
function addCombo() {

	var combo = document.frm2.combo2;
	var option = null;

	for( i = 0; i < 4; i++ ) {
		option = document.createElement("option");
		option.value = i+1;
		option.text = "オプション"+(i+1);
		combo.appendChild(option)
	}

}
</script>
<form name="frm2">
	<select name="combo2"
		style='width:150px;'>
	</select>
</form>
<input type="button"
	value="データ追加"
	onclick='addCombo();'>
コンボボックスにリストを挿入する

▼ 実際の実行
<script type="text/javascript">
function insertOption() {

	var combo = document.frm3.combo3;
	var option = document.createElement("option");
	option.value = 1.5;
	option.text = "データ1.5";
	combo.insertBefore(option,combo.options[1]);
}
</script>
<form name="frm3">
	<select name="combo3"
		style='width:150px;'>
		<option value="1">データ1
		</option>
		<option value="2">データ2
		</option>
		<option value="3">データ3
		</option>
		<option value="4">データ4
		</option>
	</select>
</form>
<input type="button"
	value="リスト挿入"
	onclick='insertOption();'>
コンボボックスのリスト移動する

▼ 実際の実行
<script type="text/javascript">
function moveOption() {

	var combo = document.frm4.combo4;
	combo.insertBefore(combo.options[1],combo.options[3]);
}
</script>
<form name="frm4">
	<select name="combo4"
		style='width:150px;'>
		<option value="1">データ1
		</option>
		<option value="2">データ2
		</option>
		<option value="3">データ3
		</option>
		<option value="4">データ4
		</option>
	</select>
</form>
<input type="button"
	value="リスト移動"
	onclick='moveOption();'>
コンボボックスのテキスト部分を取得

▼ 実際の実行
<script type="text/javascript">
function getOptionText() {

	var combo = document.frm5.combo5;
	alert( combo.options[2].text );

}
</script>
<form name="frm5">
	<select name="combo5"
		style='width:150px;'>
		<option value="1">データ1
		</option>
		<option value="2">データ2
		</option>
		<option value="3">データ3
		</option>
		<option value="4">データ4
		</option>
	</select>
</form>
<input type="button"
	value="リスト参照"
	onclick='getOptionText();'>
コンボボックスの選択状態を操作する

▼ 実際の実行
<script type="text/javascript">
function selectOption() {

	var combo = document.frm6.combo6;
	combo.selectedIndex = 2;

}
function noSelectOption() {

	var combo = document.frm6.combo6;
	combo.selectedIndex = -1;

}
</script>
<form name="frm6">
	<select name="combo6"
		style='width:150px;'>
		<option value="1">データ1
		</option>
		<option value="2">データ2
		</option>
		<option value="3">データ3
		</option>
		<option value="4">データ4
		</option>
	</select>
</form>
<input type="button"
	value="データ3を選択"
	onclick='selectOption();'>
<input type="button"
	value="未選択"
	onclick='noSelectOption();'>
昔はこの方法は使え無いブラウザがあったかもしれません。全て直感的な操作ですが、本来 options コレクションに対して実行するような内容が、コンボボックスに直接可能になっています。



タグ:javascript
posted by at 2014-09-25 23:54 | JavaScript | このブログの読者になる | 更新情報をチェックする

Google検索は、ドメイン内ディレクトリ指定ができる

Google のヘルプには、現在 検索演算子 と言うページがありますが、説明が単純化されてしまって、ドメインより下の階層を指定可能な事が読み取れなくなっています。

実際には、『演算子 site:support.google.com/websearch/answer』という指定が可能で、HTML から正しい指定をすれば、入力した値で特定のサイトの下位階層のみを検索するように、Google の検索ページに引き渡す事も可能です。

https://www.google.co.jp/?#q=(1)+site:(2)

(1) に URL エンコードした検索文字列が入り、(2) に ドメインと階層を URLエンコードしたものが入ればいいだけです。

関連する記事

ドメイン内検索を任意のページで実行


posted by at 2014-09-25 20:58 | 資料 | このブログの読者になる | 更新情報をチェックする

Three.js : 好きな背景透過画像を飛翔させる

url を指定しない場合は、以下の画像が飛翔します。別に背景透過でなくても、なんでも飛翔するんですが、単純な画像でないと、何がなんだか良くわかりません。

url:
関連する記事

Three.js の canvas_geometry_birds の『鳥』だけを取り出して考える


▼ 以下は、さらに発展型で、カラフルな鳥が飛翔した軌跡を残します。

※ もう一度クリックすると止まります


posted by at 2014-09-25 02:04 | Three.js | このブログの読者になる | 更新情報をチェックする

2014年09月23日

CSS の子要素系の指定は、子としてのありかたであって親はなんであっても良いのですが、セレクタで指定された最初だけなんてのは指定できない

E:nth-child(n)
E:nth-last-child(n)
E:nth-of-type(n)
E:nth-last-of-type(n)
E:first-child
E:last-child
E:first-of-type
E:last-of-type
E:only-child
E:only-of-type

全て試したわけでは無いですが、E は、セレクタでも動作するようです。

いずれにしても、選択された対象が、その親からみてどういう状況かを指定するものであるので、例えば .class とかで任意のクラスの一覧を取得しても、その中の先頭は JavaScript でしか取り出せないです。

.class で取り出したおのおのが、例えば皆長男( first-child ) だったら、全員対象になります。

E:nth-child(n) : 兄弟のうち、上から数えて何番目か
E:nth-last-child(n) : 兄弟のうち、下から数えて何番目か
E:nth-of-type(n) : 兄弟のうち、ある特徴をもった中の何番目か
E:nth-last-of-type(n) : 兄弟のうち、ある特徴をもった中の下から何番目か
E:first-child : 長男または長女
E:last-child : 末っ子
E:first-of-type : 兄弟のうち、ある特徴をもった中で最も年上
E:last-of-type : 兄弟のうち、ある特徴をもった中で最も年下
E:only-child : 兄弟のうち、一人だけ特別な子
E:only-of-type : 兄弟のうち、一人だけある特徴を持った子

なんて意味で、別々の家族を含めた比較は行われないです。



タグ:CSS
posted by at 2014-09-23 13:46 | CSS | このブログの読者になる | 更新情報をチェックする

2014年09月14日

かなのみ系フリーフォントの半角入力をそのまま全角入力に変更する

2014/9/14 追記

今はサイトが消失している ttfedit 配布サイト(http://www.uri.sakura.ne.jp/~cosmic/yuno/) ですが、https://archive.org/web/ で検索すると、2003 年の 2月で無事ダウンロード(ttfedit.lzh)できました。

関連する記事

ttfedit の使い方の、とても重要な部分


非常にマニアックな目的ですし、使用条件としてそれを許さないように『読める表現』になっているフォントもあります(改造不可とか)が、フリーフォントである以上使いやすいほうがいいですよね。個人的な利便性で言えばそういう事になります。

しかし、そうそう簡単でも無い処理のようで、8,000円で買った TTEdit にはそんな機能はありません。

▼ TTEdit で グレイグラフィックさんところの Mike を表示したもの


購入する前、正直期待していたのですが、この程度の価格帯では無理なのかもしれません。なんですが・・・・この TTEdit と フォント作成オペレーション機能が全く同じシステムで、今は無き ttfedit というソフトにはその機能が備わっています。自分は偶然たまたまそのソフトを昔から持っていて、目的を達成する事ができましたが、より利便性を高める機能が簡単に使えない現状にちょっと疑問を感じたりするのでした。

▼ ttfedit で グレイグラフィックさんところの Mike を表示したもの


全自動というわけには当然なりませんが、現在の文字コードを入力した文字のコードに変更する機能があるので、かな文字程度の量ですと、そんなに時間もかからずに変換ができます。もちろん、それなりに間違っていないか入力文字と表示文字を確認したりする事は必要ですが、TTEdit では、フォントを作成する事に特化されているようで、コードの編集機能はありませんでした( 結構 HELP が簡単で、結局メニューから見える事以上はできないのです )

時間があれば、世の中の他のフリーソフトを探したいところですが、フォントに関してはどうも未開の地のような印象があります( あんまり需要無いでしょうし・・・ )

でも、TTEdit は、描いた絵から文字データを作成できるので、純粋にフォントを作りたい人にとっては『8,000円は安い!』と言わせる事のできるものだとは思います





posted by at 2014-09-14 17:52 | フリーフォントではんこ画像 | このブログの読者になる | 更新情報をチェックする

2014年09月11日

無事みつけた Pencil-sketch.scm でイラストを加工したら、やはり一番の出来で挿絵っぽくなりました。



本来なら、ここから手作業で仕上げするところなんでしょうが、とりあえず濃さの調整のみを行いました。ただの背景ではなく人物のラインが重要なので、このスクリプト以外は良い結果は出なかったです。

GIMP の場合は面倒ですが、一応スクリプトを触れるので、いろいろなイラストのバリーエーションの一つの選択肢として大きいです。最近 Bryce という景観作成ソフトを使い始めて、最初にイラストの背景に使ったのがこの画像です。以下、カラーバージョンです。

Elf Team





関連する記事

GIMP : 鉛筆スクリプト / quick-sketch.scm と FU_sketch_pencil-sketch-BW.scm



posted by at 2014-09-11 23:26 | GIMP スクリプト | このブログの読者になる | 更新情報をチェックする

GIMP : 鉛筆スクリプト / quick-sketch.scm と FU_sketch_pencil-sketch-BW.scm



昔、Pencil-sketch.scm というスクリプトがあって、あちらこちらで紹介されているのですが、現在配布サイトが消滅していました。自分が紹介したのは、2006年11月18日 でしたが、インターネット上の情報としては、2012 年ごろまではダウンロードできたようです。

残念ながら、Pencil-sketch.scm は見つからないので、他のスクリプトを探して二つ見つけました。

※ コメントをいただいて、http://archive.org/web/ にある事を教えていただきました。( ページの最後にスクリプトの結果があります )

▼ 元画像


quick-sketch.scm

Quick sketch

白黒の濃度を 0 から 200 まで変更する事ができますが、ぼかしたオリジナル画像を、元の画像の上に覆い焼きしているだけなので、鉛筆画像というより、白黒効果プラスアルファといった感じです。

▼ 30


▼ 180



FU_sketch_pencil-sketch-BW.scm

Script-Fu -> Pencil Sketch BW
※ 本体だけでは無く、パターンのダウンロードが必要なので注意して下さい

オプションとして、以下のチェックから最初から ON になっていますが、これだと合成されてしまうので、チェックを外して実行します



▼ 合成されたもの


背景部分の薄いところも雰囲気を出す為にそれ用のパターンレイヤーが合成されています。

▼ パーツの一枚(レイヤー)

※ パターンを非表示にすると、こんな感じになります。


Pencil-sketch.scm(みつかりました)



あきらかに、前の二つより複雑な処理を行っている気がします。GIMP のスクリプトを読むのは結構気合がいるので読んでませんが、plugin も多くつかわれていたりと、特に plug-in-gauss-iir がキモのようでした(FU_sketch_pencil-sketch-BW.scm でも使われています)。

ソースコードの先頭にライセンス記述があるので貼っておきます
; The GIMP -- an image manipulation program
; Copyright (C) 1995 Spencer Kimball and Peter Mattis
; ---------------------------------------------------------------------
; The GIMP script-fu  Pencil Sketch for GIMP1.2 - 2.6
; Copyright (C) 2004 Tamagoro <tamagoro_1@yahoo.co.jp>
; ---------------------------------------------------------------------
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
; 
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
; 
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
; ---------------------------------------------------------------------

(define (script-fu-pencil-sketch image drawable)
  (let* (
 	     (W (car (gimp-image-width image)))
 	     (H (car (gimp-image-height image)))
 	     (type (car (gimp-drawable-type drawable)))
 	     (select (car (gimp-selection-is-empty image)))
 	     (select-channel)
 	     (backup-layer)
 	     (copy-layer)
 	     (base-layer)  )
  	
 	(gimp-image-undo-group-start image)
 	(if (equal? select FALSE) 
 	(begin 
 	    (set! select-channel (car (gimp-selection-save image)))
 	    (set! backup-layer (car (gimp-layer-copy drawable 1)))))

 	(if (< type 2) (gimp-desaturate drawable))
 	(plug-in-normalize 1 image drawable)
 	(plug-in-noisify 1 image drawable FALSE 0.01 0.01 0.01 0.00)
 	(plug-in-sharpen 1 image drawable 70)
 	(plug-in-noisify 1 image drawable FALSE 0.01 0.01 0.01 0.00)

	(set! copy-layer (car (gimp-layer-copy drawable 1)))
 	(gimp-image-add-layer image copy-layer -1)
 	(gimp-layer-set-mode copy-layer DIVIDE)
 	(plug-in-gauss-iir 1 image copy-layer (+ 1 (/ (+ W H) 500)) TRUE TRUE)
 	(set! base-layer (car (gimp-image-merge-down image copy-layer 2)))

 	(set! copy-layer (car (gimp-layer-copy base-layer 1)))
 	(gimp-image-add-layer image copy-layer -1)
 	(gimp-brightness-contrast copy-layer 0 125)
 	(gimp-invert copy-layer)
 	(gimp-layer-set-mode copy-layer SCREEN)
 	(gimp-layer-set-opacity copy-layer 60)
 	(set! base-layer (car (gimp-image-merge-down image copy-layer 2)))
 	(plug-in-normalize 1 image base-layer)

 	(set! copy-layer (car (gimp-layer-copy base-layer 1)))
 	(gimp-image-add-layer image copy-layer -1)
 	(gimp-invert copy-layer)
 	(gimp-layer-set-mode copy-layer OVERLAY)
 	(gimp-layer-set-opacity copy-layer 50)
 	(set! base-layer (car (gimp-image-merge-down image copy-layer 2)))

 	(set! copy-layer (car (gimp-layer-copy base-layer 1)))
 	(gimp-image-add-layer image copy-layer -1)
 	(plug-in-gauss-iir 1 image copy-layer 1 TRUE TRUE)
 	(gimp-layer-set-opacity copy-layer 60)
 	(set! base-layer (car (gimp-image-merge-down image copy-layer 2)))
 	(if (< type 2)
 	    (plug-in-vpropagate 1 image base-layer 2 TRUE 1.0 15 0 255)
 	    (begin (gimp-convert-rgb image)
 	       (plug-in-vpropagate 1 image base-layer 2 TRUE 1.0 15 0 255)
 	       (gimp-convert-grayscale image)) )
  	(gimp-levels base-layer 0 30 255 1.0 0 255)

	(if (equal? select FALSE) 
	    (begin 
 		   (gimp-image-add-layer image backup-layer -1)
 		   (gimp-selection-load select-channel)
 		   (gimp-edit-clear backup-layer)
 		   (gimp-image-remove-channel image select-channel)
 		   (gimp-image-merge-down image backup-layer 2)) )

 	(gimp-image-undo-group-end image)
 	(gimp-displays-flush)
  )
)

(script-fu-register "script-fu-pencil-sketch"
 	"鉛筆画"
 	"鉛筆画のように加工します"
 	"Tamagoro <tamagoro_1@yahoo.co.jp>"
 	"Tamagoro"
 	"October 2004"
 	"RGB*, GRAY*"
 	 SF-IMAGE      _"Image"     0
 	 SF-DRAWABLE   _"Drawable"  0
)

(script-fu-menu-register "script-fu-pencil-sketch"
 	"<Image>/Script-Fu/写真加工"
)



posted by at 2014-09-11 02:00 | GIMP スクリプト | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します