「Panasonic KX-PD102DのFaxTiffWriterがインストール出来ない」でFaxTiffWriterが作成するTIFFデータとWindowsのFAX Driverが作るTIFFを比較分析した。この分析結果をもとにWindows FAX Driver作成のTIFFをSDメモリーカードに記録し、Panasonic KX-PD102DでFAX送信してみた。
(1)Win FAX DriverのTIFFをスクリプトで変換
・Tagデータの次にImageデータとなるよう配置を変更
・Imageデータの開始位置が固定となるようTagデータを処理
・Resolutionの単位をインチからセンチへ変更。設定値はA4サイズ固定値
・複数ページデータを1ページ毎のファイルにする
・指定された出力ファイル名をページ毎に「ファイル名01」から「ファイル名99」とする
・TIFF拡張子は「tif」とする
splitwinfax.sh
#!/bin/bash
# split win fax pages to files
function readbinary {
data=()
local LC_ALL=C byte i=0 buff
while IFS= read -r -d '' -n 1 byte; do
data[i++]="'$byte"
done
printf -v buff '%d ' "${data[@]}"
data=($buff)
while ((--i>=0)); do ((data[i]&=0xFF)); done
}
function writebinary {
local buff
printf -v buff '\\x%x' "${odata[@]}"
LC_ALL=C printf "$buff"
}
function getbyte() {
printf "%d" ${data[$1]}
}
function get2bytes(){
printf "%d" $((data[$1+1]*256+data[$1]))
}
function get4bytes(){
printf "%d" $((data[$1+3]*16777216+data[$1+2]*65536+data[$1+1]*256+data[$1]))
}
function setbyte() {
odata[$1]=$(printf "$(printf '%d' $2)")
}
function set2bytes() {
odata[$1]=$(printf "$(printf '%d' $(($2%256)) )" )
odata[$1+1]=$(printf "$(printf '%d' $(($2/256)) )" )
}
function set4bytes() {
odata[$1]=$(printf "$(printf '%d' $(($2%256)) )" )
odata[$1+1]=$(printf "$(printf '%d' $(($2%65536/256)) )" )
odata[$1+2]=$(printf "$(printf '%d' $(($2%16777216/65536)) )" )
odata[$1+3]=$(printf "$(printf '%d' $(($2/16777216)) )" )
}
## read tif file
if [[ $1 ]]; then
readbinary < "$1"
else
readbinary
fi
##
odata=(); cofs=0; fnum=1; bnum=1
DD=`date "+%Y%m%d%H%M"`
FN=$(printf $(printf '\\x%x' $((65+${DD:0:4}-2010))))
if [[ ${DD:4:2} -lt 10 ]]; then FN=$FN$(printf $(printf '\\x%x' $(expr 48+${DD:4:2}))); else FN=$FN$(printf $(printf '\\x%x' $((65+${DD:4:2}-10)))); fi
if [[ ${DD:6:2} -lt 10 ]]; then FN=FN$(printf $(printf '\\x%x' $(expr 48+${DD:6:2}))); else FN=$FN$(printf $(printf '\\x%x' $((65+${DD:6:2}-10)))); fi
for (( i=1; i<999; i++ )); do
FNN=""
FNN=$FN$(printf $(printf "%03d" $i))
if [[ ! -d $FNN ]]; then break; fi
done
for (( i=1; i<100; i++ )); do
FNNP=""; FNNP=$FNN$(printf $(printf "%02d" $i))".tif"
if [[ ! -f $FNNP ]]; then fnum=$i; break; fi
done
#offset address 0x04 after '0x49 0x49 0x2a 0x00' is 1st IFD pointer
IFDP=$(get4bytes 4)
IFDC=$(get2bytes $IFDP)
while [ $IFDP -ne 0 ]; do
for (( cofs; cofs<4; cofs++ )); do odata[$cofs]=${data[$cofs]}; done
set4bytes $cofs 8; ((cofs+=4))
set2bytes $cofs $IFDC; ((cofs+=2))
sofs=$((IFDP+2))
for (( i=0; i<$IFDC; i++ )); do
TID=$(get2bytes $((IFDP+2+i*12)))
Ttyp=$(get2bytes $((IFDP+2+i*12+2)))
Tcnt=$(get4bytes $((IFDP+2+i*12+4)))
Tval=$(get4bytes $((IFDP+2+i*12+8)))
case ${TID} in
"273") #0x111 Strip Offsets
imgadr=$Tval; imgtvaladr=$((cofs+8));;
"279") #0x117 StripByCounts
imgsize=$Tval;;
"282") #0x11A X Resolution
xresadr=$Tval; xresval1=$(get4bytes $Tval); xresval2=$(get4bytes $((Tval+4))); xrestvaladr=$((cofs+8));;
"283") #0x11B Y Resolution
yresadr=$Tval; yresval1=$(get4bytes $Tval); yresval2=$(get4bytes $((Tval+4))); yrestvaladr=$((cofs+8));;
"296") #0x128 Resolution Unit
resunit=$Tval; resunittvaladr=$((cofs+8));;
"305") #0x131 software
softtextadr=$Tval; softsize=$Tcnt; softtexttvaladr=$((cofs+8));;
*)
esac
for (( j=cofs; j<$((cofs+12)); j++,sofs++ )); do odata[j]=${data[sofs]}; done
((cofs+=12))
done
set4bytes $cofs 0; ((cofs+=4)) #terminator for IFDP
# X and Y Resolution cm value
set4bytes $cofs 80; set4bytes $xrestvaladr $cofs; ((cofs+=4))
set4bytes $cofs 1; ((cofs+=4))
set4bytes $cofs 77; set4bytes $yrestvaladr $cofs; ((cofs+=4))
set4bytes $cofs 1; ((cofs+=4))
set4bytes $resunittvaladr 3
# Software text value
for (( i=$softtextadr,j=0; j<$softsize; i++,j++ )); do odata[((cofs+j))]=${data[i]}; done
set4bytes $softtexttvaladr $cofs
((cofs+=j))
# Image data must be start at offset 0x10b
setbyte $cofs 32; ((cofs+=1))
for (( i=imgadr, j=0; j<$imgsize; i++,j++ )); do odata[((cofs+j))]=${data[i]}; done
set4bytes $imgtvaladr $cofs
((cofs+=j))
IFDP=$(get4bytes $((IFDP+IFDC*12+2)) )
IFDC=$(get2bytes $IFDP)
writebinary > $(printf "$FNN%02d.tif" $fnum)
printf "Page %02d to the $FNN%02d.tif\n" $bnum $fnum
((fnum+=1)); ((bnum+=1))
cofs=0
done
macOSターミナルで上記シェルスクリプトを実行してページ毎のTIFFファイルを作成。
macOS BigSur バージョン 11.7.10
$ uname -a
Darwin muffin2.matsuura 20.6.0 Darwin Kernel Version 20.6.0: Thu Jul 6 22:12:47 PDT 2023; root:xnu-7195.141.49.702.12~1/RELEASE_X86_64 x86_64
$ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20)
Copyright (C) 2007 Free Software Foundation, Inc.
$ ./splitwinfax.sh /Users/someone/FaxTest2pages.tif
Page 01 to the OBL00101.tif
Page 02 to the OBL00102.tif
$ ls -al OBL*.tif
-rw-r--r-- 1 someone staff 925 11 21 16:56 OBL00101.tif
-rw-r--r-- 1 someone staff 925 11 21 16:56 OBL00102.tif
$ ./splitwinfax.sh /Users/someone/FaxTestExcell.tif
Page 01 to the OBL00103.tif
$ ls -al OBL*.tif
-rw-r--r-- 1 someone staff 925 11 21 16:56 OBL00101.tif
-rw-r--r-- 1 someone staff 925 11 21 16:56 OBL00102.tif
-rw-r--r-- 1 someone staff 925 11 21 16:58 OBL00103.tif
このままでは、fax送信できないので、SDメモリーカードで扱えるように「DOC_INF.BIN」ファイルを用意する。
(2)「DOC_INF.BIN」の生成
mkdocinf.sh
#!/bin/bash
# make doc_inf.bin
dbg=0
DD=`date "+%Y%m%d%H%M"`
TT="WinFax${DD}" #タイトル:半角20文字以下
PN=1 #ファックス頁数
#
function readbinary {
data=()
local LC_ALL=C byte i=0 buff
while IFS= read -r -d '' -n 1 byte; do
data[i++]="'$byte"
done
printf -v buff '%d ' "${data[@]}"
data=($buff)
while ((--i>=0)); do ((data[i]&=0xFF)); done
}
function writebinary {
local buff
printf -v buff '\\x%x' "${odata[@]}"
LC_ALL=C printf "$buff"
}
function getbyte() {
printf "%d" ${data[$1]}
}
function get2bytes(){
printf "%d" $((data[$1+1]*256+data[$1]))
}
function get4bytes(){
printf "%d" $((data[$1+3]*16777216+data[$1+2]*65536+data[$1+1]*256+data[$1]))
}
function setbyte() {
odata[$1]=$(printf "$(printf '%d' $2)")
}
function set2bytes() {
odata[$1]=$(printf "$(printf '%d' $(($2%256)) )" )
odata[$1+1]=$(printf "$(printf '%d' $(($2/256)) )" )
}
function set4bytes() {
odata[$1]=$(printf "$(printf '%d' $(($2%256)) )" )
odata[$1+1]=$(printf "$(printf '%d' $(($2%65536/256)) )" )
odata[$1+2]=$(printf "$(printf '%d' $(($2%16777216/65536)) )" )
odata[$1+3]=$(printf "$(printf '%d' $(($2/16777216)) )" )
}
##
cofs=0
dentnum=0
# the initial data for doc_info.bin file.
odata=(0 0 0 0 12 4 0 0 0 0 12 0 255 255 255 255)
data=(0 0 0 0 12 4 0 0 0 0 12 0 255 255 255 255)
for (( i=12; i<$((1024+12)); i++ )); do odata[i]=255; data[i]=255; done
dentd=(0 0 0 0 87 0 2 3)
dentinfd=(1 0 9 0 0 0 0 0 1 1 3 2 6 232 7 11 11 11 11 3 6 232 7 11 11 11 11 6 10 0 0 0 0 0 0 0 0 0 0 8 20 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 10 2 1 0 11 13 32 32 32 32 32 32 0 0 0 0 0 0 0 12 1 0 14 2 2 0)
if [[ $# -lt 1 ]]; then printf "$0 PageNumber <current doc_inf.bin>\n"; exit; fi
if [[ $1 ]]; then PN=$1; fi
## read doc_inf.bin file to data()
if [[ $2 ]]; then readbinary < "$2"; fi
#
dfirst4=$(get4bytes 0); ddfirst4=0
dentend=$(get4bytes 4); ddentend=1036
dentnum=$(get2bytes 8); ddentnum=0
dentap=12; ddentap=12
dentinfap=$(get2bytes 10); ddentinfap=12
dentinfape=$((dentinfap+dentnum*87)); ddentinfape=12
printf "Loaded ...\n"
if [[ $(get4bytes 4) -eq 0 ]]; then writebinary >"DOC_INF.BIN"; exit; fi
if [[ $dentnum -eq 0 ]]; then set4bytes 0 65536; ddfirst4=65536; fi
#Directory Entry
cofs=$dentap
for (( i=0; i<dentnum; i++ )); do
for (( j=2; j<8; j++ )); do
set2bytes $((cofs+i*8)) $(($(get2bytes $((dentap+i*8)))+8))
odata[$((cofs+i*8+j))]=${data[$((dentap+i*8+j))]}
done
done
((cofs+=8*dentnum));
if [[ $dfirst4 -ne 0 ]]; then ddfirst4=$dfirst4; fi
ddentnum=$dentnum; ddentinfap=$cofs; ddentinfape=$cofs; ddentend=$((ddentinfape+1024))
ddentinfap=$((cofs+8))
set2bytes $cofs $((ddentinfap+87*dentnum))
for (( j=2; j<8; j++ )); do odata[$((cofs+j))]=${dentd[$j]}; done
((cofs+=8))
set2bytes 10 $ddentinfap
((ddentnum+=1)); set2bytes 8 $ddentnum; ddentinfape=$ddentinfap; ddentend=$((ddentinfape+1024))
set2bytes 4 $ddentend
#copy dentinfo 87*dentnum
for (( i=0; i<dentnum; i++ )); do
for (( j=0; j<87; j++ )); do odata[$((cofs+i*87+j))]=${data[$((dentinfap+i*87+j))]}; done
done
((cofs+=dentnum*87))
ddentinfend=$cofs
ddentend=$((ddentinfend+1024))
# Directory Entry Information
for (( i=0; i<87; i++ )); do odata[$((cofs+i))]=${dentinfd[$i]}; done
# ID02-date: 11 data 13 length 6
# ID03-date: 19 data 21 length 6
odata[$((cofs+13))]=$(printf "%d" $((${DD:0:4}%256)))
odata[$((cofs+14))]=$(printf "%d" $((${DD:0:4}/256)))
odata[$((cofs+15))]=$(printf "%d" $(expr ${DD:4:2}))
odata[$((cofs+16))]=$(printf "%d" $(expr ${DD:6:2}))
odata[$((cofs+17))]=$(printf "%d" $(expr ${DD:8:2}))
odata[$((cofs+18))]=$(printf "%d" $(expr ${DD:10:2}))
for (( i=0; i<6; i++ )); do odata[$((cofs+21+i))]=${odata[$((cofs+13+i))]}; done
# ID08-Title: 39 data 41 length 20
TTX=($(printf "${TT}" | iconv -f utf8 -t sjis | od -An -tu1))
for (( i=0; i<${#TTX[@]}&&i<20; i++ )); do odata[$((cofs+41+i))]=${TTX[$i]}; done
# ID0A-Pages: 61 data 63 length 2(short)
odata[$((cofs+63))]=$(printf "%d" $((${PN}%256)))
odata[$((cofs+64))]=$(printf "%d" $((${PN}/256)))
# ID0B-DirectoryName: 65 data 67 length 13
odata[$((cofs+67))]=$((65+${DD:0:4}-2010))
if [[ ${DD:4:2} -lt 10 ]]; then odata[$((cofs+68))]=$(expr 48+${DD:4:2}); else odata[$((cofs+68))]=$((65+${DD:4:2}-10)); fi
if [[ ${DD:6:2} -lt 10 ]]; then odata[$((cofs+69))]=$(expr 48+${DD:6:2}); else odata[$((cofs+69))]=$((65+${DD:6:2}-10)); fi
for (( i=1; i<999; i++ )); do
DRN=""
for (( j=0; j<3; j++ )); do DRN=$DRN$(printf $(printf '\x%x' "${odata[$((cofs+67+j))]}")); done
DRN=$DRN$(printf $(printf "%03d" $i))
if [[ ! -d $DRN ]]; then
printf "New directory name is $DRN\n"
mkdir $DRN
odata[$((cofs+70))]=$((48+${DRN:3:1}))
odata[$((cofs+71))]=$((48+${DRN:4:1}))
odata[$((cofs+72))]=$((48+${DRN:5:1}))
break
fi
done
((cofs+=87)); ddentinfape=$cofs
for (( i=$cofs; i<$((1024+cofs)); i++ )); do odata[i]=255; done
set2bytes 4 $((cofs+1024))
ddentend=$((cofs+1024))
writebinary >"DOC_INF.BIN"
$ ./mkdocinf.sh 3
Loaded ...
New directory name is OBL001
$ ls -d OBL*/
OBL001/
$ ls OBL*.tif
OBL00101.tif OBL00102.tif OBL00103.tif
$ mv OBL*.tif OBL001/
$ ls OBL001/
OBL00101.tif OBL00102.tif OBL00103.tif
$ ls DOC_INF.BIN
DOC_INF.BIN
$
作成された「DOC_INF.BIN」の内容
「赤枠」部は、ページ数
SDメモリーカードをKX-PD102に挿入認識後、「機能」「SDカード」「SDのパソコンデータ送信」
作成したfaxデータのタイトルが表示される。(追記:DOC_INF.BINの時間と表示時間が1分ほどズレている。サンプルデータを作り直したため)
「表示」でページ毎の内容をディスプレーで確認できる。
「ファックス送信」を選択して送信先電話番号を設定してfax送信ができる。
(3)その他
「DOC/OBL001/OBL001.TXT」は、存在しなくとも機能する
「DOC/DOC_INF.BIN」は、SDメモリを挿入認識させると「隠し属性」が設定される
「DOC/DOC_INF.BAK」は、設定されていなくても動作。SDメモリの挿入認識で自動作成される。
SDメモリのファイル名やディレクトリ名は、「小文字」でも機能する