-
- [1]
改訂 十進 BASIC による プログレッシブ JPG の展開と画像化。
- 投稿者:SECOND
- 投稿日:2009年12月14日(月)20時36分38秒
-
-
!改訂 十進 BASIC による プログレッシブ JPG の展開と画像化。
!
!先投稿では、プログレッシブ JPG 再生過程の画像を、何枚も表示していたが、
!途中画像は、最初のDC成分1枚だけ と、最終完成画、全2枚とした。
!Baseline JPG は、全1枚なので、画数で両者を区別できる。
!(必要なら、再生過程 全ての画像も、表示できるよう、SUB IZZRL0 に注釈行がある)
!
!色差成分 Cb Cr の間引き走査復元の塗潰しを、SUB IDDCT8X8 に統合し、簡素化した。
!その他、各所の手入れ多数。
!
!具体的、可視的なプログラムで、実行し画像化しますので、詳細事項の追跡と御参考に。
!再生できるファイルは、1000x1000 までの JPG だけで、
! baseline , spectral selection , successive approximation の3種類( web 上の、ほぼ全種)
! 参考資料:http://www.w3.org/Graphics/JPEG/itu-t81.pdf
!
!1)successive approximation AC.subsequence(Y,Cb,Cr 別々、1bit づつの処理)
!
! 0 1 1 0 0 0 0 0 0 ?
! 0 0 0 0 0 1 0 0 0 ?
! 0 1 0 0 0 0 0 1 0 ?
! 0 1 1 0 0 1 0 1 0 ?
! 0 1 1 0 0 1 0 1 0 ?
! --------------------------------------------------------------------------
! ±1 b1 b2 0 0 b3 0 b4 ±1 ?
! 前の終り RRRR RRRR RRRR extend. 次の始め
!
! huffman.
! RRRRssss extend. b1 b2 b3 b4 …
! 3 1 (0 or 1) bit_stream=?何個になるかは、上図で、上位桁 =0 の係数が
! -1 +1 (0 or 1) RRRR 個 になるまでに通過した上位桁 <>0 の個数。
! 0 ±1
! 0 → 無変化。
! 1 → ±符号は上位桁に合せて加算。(絶対値が+1)
!
!2)successive approximation DC.subsequence(Y,Cb,Cr 別々、1bit づつの処理)
!
! ハフマン・コード RRRRssss 部は、存在せず、
! 頭からの bit_stream.で、1bit づつ、全てのblock の DC係数 に加える。
!
! AC と同様、0 → 無変化。1 → ±符号は上位桁に合せて加算。(絶対値が+1)
!
!※上記、successive approximation AC, DC とも、加える1は、
! 2^Al 倍の point transfer. としてから、加えます。
!
DEBUG ON
!------------------------
!JPG.decoder
! Baseline
! Progressive( spectral selection )( successive approximation )
!------------------------
OPTION ARITHMETIC NATIVE
OPTION BASE 0
OPTION CHARACTER byte
SET TEXT background "OPAQUE"
ASK BITMAP SIZE bmx,bmy
SET WINDOW 0,bmx, bmy,0
SET ECHO "OFF"
SET COLOR MODE "NATIVE"
!
DIM D8(1000,1000) !MAIN65
DIM D2(1000,1000,2) !Y=D2(,,0) Cb=D2(,,1) Cr=D2(,,2)
DIM D1(1000,1000,2) !Y=D2(,,0) Cb=D2(,,1) Cr=D2(,,2)
DIM MH(2),MV(2) !R_BIN31 SOF0 MCU.Ybr.H()V()
DIM HDC(2),HAC(2) !R_BIN31 hT.table selection
DIM QS(2),CoID(255) !R_BIN31 qT.table selection
DIM M3(2)
!
DIM U(63),V(63) !zigzag
DIM DQ(7,7,3) !blk8x8 DQT
DIM DH(16,7),DV(255,7) !DHT
DIM B(255+1,7),L(255,7) !encorder & decorder's pre_table, length, ( MAKE_H2,MAKE_H0)
DIM A(2000,7) !decorder
DIM B2(2) !Ybr D.C.成分 starting & back_level for difference
DIM T(7,7),X(7),XO(7) !DDCT8X8, IDDCT8X8
!
LET BST=2 !huffman decorder's bit step 1=8.5s 2=6.5s 4=8.0s 8=50.0s
LET SHb=2^BST !huffman decorder n*SHb=(shl n,BST) n/SHb=(shr n,BST)
!
!---zigzag table
FOR V_=0 TO 7
FOR U_=0 TO 7
READ i
LET U(i)=U_
LET V(i)=V_
NEXT U_
NEXT V_
DATA 0, 1, 5, 6,14,15,27,28
DATA 2, 4, 7,13,16,26,29,42
DATA 3, 8,12,17,25,30,41,43
DATA 9,11,18,24,31,40,44,53
DATA 10,19,23,32,39,45,52,54
DATA 20,22,33,38,46,51,55,60
DATA 21,34,37,47,50,56,59,61
DATA 35,36,48,49,57,58,62,63
!
DO
FILE GETNAME FL$, "jpg"
IF FL$="" THEN
PRINT "入力ファイル名無し"
EXIT DO
END IF
PRINT "入力ファイル:"& FL$
!---
CLEAR
CALL IZZRL0 ! D2()<-- decord JPG
PRINT "次のファイル[ 左クリック ]"
beep
DO
MOUSE POLL j,i,mlb,mrb !CHARACTER INPUT CLEAR: w$
WAIT DELAY 0
LOOP UNTIL 0< mlb OR 0< mrb
LOOP UNTIL 0< mrb
PRINT "終了。"
!-------- IZZRL0 call here for display D2()
SUB MAIN65
LET tester=TIME
PRINT "画像の準備中、";
CALL IDDCT8X8 ! D1()<-- iDCT<-- iDQT<-- D2()
!------ JPG 色空間 ----------------------------
! | Y | | 0.2990 +0.5870 +0.1140 | | R |
! |B-Y| = |-0.1687 -0.3313 +0.5000 | | G |
! |R-Y| | 0.5000 -0.4187 -0.0813 | | B |
!
! | R | | 1 0 +1.40200 | | Y |
! | G | = | 1 -0.34414 -0.71414 | |B-Y|
! | B | | 1 +1.77200 0 | |R-Y|
!----------------------------------------------
FOR V0=0 TO DY-1
FOR U0=0 TO DX-1
!--- RGB<-- Ybr
LET w1=IP(D1(U0,V0,0) +1.40200*D1(U0,V0,2)) !R
LET w2=IP(D1(U0,V0,0) -0.34414*D1(U0,V0,1) -0.71414*D1(U0,V0,2)) !G
LET w3=IP(D1(U0,V0,0) +1.77200*D1(U0,V0,1)) !B
IF w1< 0 THEN
LET w1=0
ELSEIF 255< w1 THEN
LET w1=255
END IF
IF w2< 0 THEN
LET w2=0
ELSEIF 255< w2 THEN
LET w2=255
END IF
IF w3< 0 THEN
LET w3=0
ELSEIF 255< w3 THEN
LET w3=255
END IF
LET D8(U0,V0)=w3*65536+w2*256+w1 !(逆)BGR
NEXT U0
NEXT V0
PRINT TRUNCATE(TIME-tester,2);"秒"
LET w=TRUNCATE(MIN( (bmx-1)/DX,(bmy-1)/DY),1)
IF 1< w THEN LET w=IP(w)
IF 4< w THEN LET w=4
PRINT "描画の倍率=";w
MAT PLOT CELLS,IN 1,1; DX*w, DY*w :D8
END SUB
!========================
!inverse haffman Transform.
SUB IZZRL0
LET byt=0 !!!
CALL ROPEN ! FL$
!---
CALL R_BIN31(0) !A() B(i,J)L(i,J)<-- DH(), return at img.top
PRINT right$("000"& BSTR$(byt,16),4) !!!
PRINT "(";STR$(DX);"x";STR$(DY);
!---
MAT D8=ZER(DX-1,DY-1) !MAIN65
LET i=8*MH(0) !MCU Y.Hsize
LET j=8*MV(0) !MCU Y.Vsize
LET DUM=CEIL(DX/i)*i !Uwidth=bound by MCU Y.Hsize
LET DVM=CEIL(DY/j)*j !Vwidth=bound by MCU Y.Vsize
MAT D1=ZER(DUM-1,DVM-1,2) !Y=D1(,,0) Cb=D1(,,1) Cr=D1(,,2)
MAT D2=ZER(DUM-1,DVM-1,2) !Y=D2(,,0) Cb=D2(,,1) Cr=D2(,,2)
LET MH_=MH(0)
LET MV_=MV(0)
LET DU =DUM !Uwidth=bound by MCU Y.Hsize
LET DV_=DVM !Vwidth=bound by MCU Y.Vsize
LET DU8=CEIL(DX/8)*8 !Uwidth=bound by block Y.Hsize
LET DV8=CEIL(DY/8)*8 !Vwidth=bound by block Y.Vsize
!---
PRINT "/ ";STR$(DU8);",";STR$(DV8);"/ ";STR$(DUM);",";STR$(DVM);")"
CALL frame
!---
PRINT "M3()=";M3(0);M3(1);M3(2)
CALL MAIN65 ! Baseline.最終、Progressive.1st.
!---
IF 0< M THEN PRINT " (";STR$(DX);"x";STR$(DY);"/";STR$(U0);",";STR$(V0);") ";debug$;" abort by ";BSTR$(M,16) !!!
PRINT right$("000"& BSTR$(byt-2*SGN(M),16),4) !!!
CALL R_BIN31(M) ! return at img.top, or EOI
!---
DO WHILE M=BVAL("DA",16) !SOS
IF 0<=HAC(0) THEN
LET MV(0)=1
LET MH(0)=1
LET DU=DU8
LET DV_=DV8
END IF
CALL frame
LET MV(0)=MV_
LET MH(0)=MH_
LET DU=DUM
LET DV_=DVM
!---
PRINT "M3()=";M3(0);M3(1);M3(2) !文末参照:M30<>99(balance), M30=99(un-balance)
IF M30=0 OR M30=64 THEN CALL MAIN65 !Progressive.最終スキャン後の画像
!IF M30<>99 THEN CALL MAIN65 !Progressive.各スキャン毎、Ybr 揃った画像のみ
!CALL MAIN65 !Progressive.各スキャン毎、全画像
!---
IF 0< M THEN PRINT " (";STR$(DX);"x";STR$(DY);"/";STR$(U0);",";STR$(V0);") ";debug$;" abort by ";BSTR$(M,16) !!!
PRINT right$("000"& BSTR$(byt-2*SGN(M),16),4)
CALL R_BIN31(M) ! return at img.top
LOOP
CLOSE #1 ! FL$
END SUB
SUB reset0
LET B2(0)=0 !ROUND( YDC0/DQ(0,0,QS(0)) ) !prediction YDC.( 1st.reference level)
LET B2(1)=0 !prediction CbDC.
LET B2(2)=0 !prediction CrDC.
LET Hx=0 !bits stream input buffer 0~(7+8)bits, use fraction
LET BC=0 !stored bits in Hx
LET NA=0 !nest adr. in A()
LET EOB=0 !counter( end_of_band)
LET M=0
LET ext=0
END SUB
!Page-2 へ続く
-
- [2]
Page-2
- 投稿者:SECOND
- 投稿日:2009年12月14日(月)20時39分14秒
-
-
!Page-2 の始め
SUB frame
PRINT " Ss Se AhAl: ";Ss_;Se_;STR$(Ah);STR$(Al)
PRINT " Y HDC HAC: ";IP(HDC(0)/2);IP(HAC(0)/2)
PRINT " Cb : ";IP(HDC(1)/2);IP(HAC(1)/2)
PRINT " Cr : ";IP(HDC(2)/2);IP(HAC(2)/2)
CALL reset0
!---
FOR V09=0 TO DV_-1 STEP 8*MV(0)
FOR U09=0 TO DU-1 STEP 8*MH(0)
IF rct=0 THEN
CALL R_BIN31(0) ! read marker
IF rct<>DRI THEN BREAK ! not RST0~7
CALL reset0 ! Restart
END IF
CALL MCUxx11 ! read picture data
LET rct=rct-1
!---
IF 0< ext THEN
IF ext=103001 THEN
PRINT "abort marker ";BSTR$(M,16)
IF BVAL("D0",16)<=M AND M<=BVAL("D7",16) THEN ! RST0~7( restart marker)
LET rct=DRI ! set counter
CALL reset0 ! Restart
ELSE
EXIT SUB ! others marker
END IF
ELSE
PRINT "file error. display fragment"
LET M=BVAL("D9",16) ! EOI
EXIT SUB
END IF
END IF
NEXT U09
NEXT V09
IF 0< EOB THEN PRINT "EOBn over frame";EOB !!!
END SUB
SUB MCUxx11
!---read MCU
FOR P=0 TO CMO
IF 0<=HDC(P) OR 0<=HAC(P) THEN
FOR V0=V09 TO V09+8*MV(P)-1 STEP 8
FOR U0=U09 TO U09+8*MH(P)-1 STEP 8
WHEN EXCEPTION IN
IF EOB=0 THEN CALL R_BLK0 ELSE LET EOB=EOB-1
USE
LET ext=EXTYPE
EXIT SUB
END WHEN
!---extend bitmap
IF 0< Ah AND 0< Se_ THEN
FOR i=A_ TO Se_
IF D2(U0+U(i),V0+V(i),P)<>0 THEN
LET L_=1
WHEN EXCEPTION IN
CALL DEC1_EX
USE
LET ext=EXTYPE
EXIT SUB
END WHEN
LET V_=SGN(D2(U0+U(i),V0+V(i),P))*V_*2^Al
LET D2(U0+U(i),V0+V(i),P)=D2(U0+U(i),V0+V(i),P) +V_
END IF
NEXT i
LET A_=Ss_
END IF
!---
NEXT U0
NEXT V0
END IF
NEXT P
END SUB
!------
SUB R_BLK0
IF Ss_=0 THEN
!---D.C.part
LET debug$="DC.huffman" !!!
IF Ah=0 THEN !-----baseline.progSS.progSA(1st.scan).
LET J=HDC(P) !huffman D.C.table selection P( 0=Y 1=Cb 2=Cr)
CALL DEC1_NS
LET EL=V_ !extent length
!---D.C.extent
LET debug$="DC.huffman extend" !!!
IF 0< EL THEN
LET L_=EL
CALL DEC1_EX !keep EL, V_=extent value( length EL bits)
LET W=2^(EL-1) !minimum in EL bits length
IF V_< W THEN LET V_=V_-(W*2-1) !restore signed value
LET B2(P)=B2(P)+V_*2^Al !point transform, integrate to D.C.
END IF
LET D2(U0+U(0),V0+V(0),P)=B2(P)
ELSE !-----progSA(2st.scan).
LET L_=1
CALL DEC1_EX
LET V_=SGN(D2(U0+U(0),V0+V(0),P))*V_
LET D2(U0+U(0),V0+V(0),P)=D2(U0+U(0),V0+V(0),P) +V_*2^Al
END IF
LET Sa_=1
ELSE
LET Sa_=Ss_
END IF
!---A.C.parts
IF Se_=0 THEN EXIT SUB !band Ss_~Se_
LET J=HAC(P) !huffman A.C.table selection P( 0=Y 1=Cb 2=Cr)
LET debug$="AC.huffman"
FOR A_=Sa_ TO Se_
CALL DEC1_NS
LET EL=MOD(V_,16) !extent length
LET RL= IP(V_/16) !run length
!---
IF RL<=14 AND EL=0 THEN !End Of Block(00). End Of Band(10,20,,E0)
!---EOBn extend
LET debug$="EOBn extend"& STR$(RL)
IF 0< RL THEN
LET L_=RL !extend= run_length
CALL DEC1_EX !keep RL, V_=run value( length RL bits)
LET EOB=V_+2^RL-1 !RL= End Of Band(10,20,,E0) run length
END IF
EXIT SUB
!---
END IF
!---RL=(0~15)EL=(1~10), RL=(15)EL=(0)
LET debug$="AC.huffman extend" !!!
IF Ah=0 THEN !-----baseline.progSS.progSA(1st.scan).
LET A_=A_+RL !skip zero_run_length 0~15
!---A.C.extent
IF 0< EL THEN !ZRL(16) only skip
LET L_=EL
CALL DEC1_EX !keep EL, V_=extent value( length EL bits)
LET w=2^(EL-1) !minimum in EL bits length
IF V_< w THEN LET V_=V_-(w*2-1) !restore signed value
!---
LET V_=V_*2^Al !point transform
LET D2(U0+U(A_),V0+V(A_),P)=V_
END IF
ELSE !-----progSA(2st.scan).
IF 0< EL THEN !ZRL(16) only skip
LET L_=EL
CALL DEC1_EX !keep EL, V_=extent value( length EL bits)
IF EL<>1 THEN PRINT "AC.2nd.=";EL;V_ !!!
LET V01=V_
END IF
FOR i=A_ TO Se_
IF D2(U0+U(i),V0+V(i),P)<>0 THEN !zz(k)=xxx_1?/0?
LET L_=1
CALL DEC1_EX
LET V_=SGN(D2(U0+U(i),V0+V(i),P))*V_
LET D2(U0+U(i),V0+V(i),P)=D2(U0+U(i),V0+V(i),P) +V_*2^Al
ELSEIF RL=0 THEN !zz(k)=000_V01
EXIT FOR
ELSE !zz(k)=000_0 ,zero run
LET RL=RL-1
END IF
NEXT i
IF 0< EL THEN !ZRL(16) skip
IF V01=0 THEN LET V01=-1
LET D2(U0+U(i),V0+V(i),P)=V01*2^Al
END IF
LET A_=i
END IF
NEXT A_
END SUB
!========================
! decorder
! J= huffman code table selection ( 0=YDC 1=YAC 2=CDC 3=CAC)
! V_= pickup RRRRssss <-- JPG.file
SUB DEC1_NS
DO
IF BC< BST THEN CALL DEC1_IN
LET W=IP(Hx) ! bits width BST
!----
LET W=A(NA+W,J)
IF 32768<=W THEN EXIT DO
LET NA=W ! nest adr. W=0 table end
LET BC=BC-BST
LET Hx=MOD(Hx*SHb,SHb)
LOOP
LET NA=0 ! DU0L LLLL VVVV VVVV
LET L_=MOD(IP(W/256),128) ! U0L LLLL
LET V_=MOD(W,256) ! VVVV VVVV
IF 16< L_ THEN PRINT "unused code" !BREAK !unused code ! LET V_=BVAL("8000",16)
!----
LET W=MOD(L_,BST)
IF 0< W THEN
LET BC=BC-W
LET Hx=MOD(Hx*2^W,SHb)
ELSE
LET BC=BC-BST
LET Hx=MOD(Hx*SHb,SHb)
END IF
END SUB
SUB DEC1_IN
CALL RED_D
LET W=ORD(D$)
IF W=255 THEN
CALL RED_D
LET M=ORD(D$)
IF M<>0 THEN LET w=1/0 ! EXTYPE=3001, ffxx marker, abnormally break
END IF
LET Hx=Hx+W*2^(BST-8-BC)
LET BC=BC+8
END SUB
!-------
SUB DEC1_EX
LET V_=0
DO
IF L_< 1 THEN EXIT SUB
IF BC< L_ THEN CALL DEC1_IN
LET W=IP(Hx)
!----
IF BST>=L_ THEN EXIT DO
LET V_=V_*SHb+W
LET L_=L_-BST
LET BC=BC-BST
LET Hx=MOD(Hx*SHb,SHb)
LOOP
LET V_=V_*2^L_+IP(W*2^(L_-BST))
!----
LET BC=BC-L_
LET Hx=MOD(Hx*2^L_,SHb)
END SUB
!Page-3 へ続く
-
- [3]
Page-3
- 投稿者:SECOND
- 投稿日:2009年12月14日(月)20時41分34秒
-
-
!Page-3 の始め
!============
! B(,J)L(,J)<-- DH(,J) for decorder table A(,J)
!
SUB makeH0(J)
LET i=0 ! コード生成 順番(短い順)
LET Hx=0
LET Tx=BVAL("8000",16)
FOR L_=1 TO 16
FOR P=1 TO DH(L_,J)
LET L(i,J)=L_
LET B(i,J)=Hx ! コード(生成順), 座標DV(頻度降順) と同順。
LET i=i+1
LET Hx=Hx+Tx
NEXT P
LET Tx=Tx/2
NEXT L_
LET B(256,J)=0
FOR i=i TO 255
LET L(i,J)=0
LET B(i,J)=0
NEXT i
END SUB
!============
!A(,J)=output decorder table<-- B(,J) L(,J) DH(,J) DV(,J)
!
SUB makeD0(J)
FOR LH=16 TO 1 STEP -1
IF DH(LH,J)<>0 THEN EXIT FOR
NEXT LH !length max. in huffman table
LET LM=CEIL(LH/BST)*BST !length max. bound by BST
!---
LET I=0 !start huffman table adr.
LET LA=0 !line adr.
LET P=BST !start Decord code width
LET U_=2^(16-BST) !start Decord code step
LET NC=0 !next start Decord code
DO
LET D_=NC !start Decord code
LET NC=-1
LET LB=LA+(65536-D_)/U_ !1st nest adr.
DO
CALL SERCH
IF 0< L_ THEN
LET A(LA,J)= BVAL("8000",16)+L_*256+DV(I,J) !b15=end. +L.+V.
ELSEIF P=LM THEN
LET A(LA,J)= BVAL("C000",16)+LH*256 !b15=end. b14=Unused. +L.
ELSE
IF NC=-1 THEN LET NC=D_
LET A(LA,J)=LB ! nest adr.
LET LB=LB+SHb ! next nest adr.
END IF
LET D_=D_+U_
LET LA=LA+1
LOOP UNTIL IP(D_)=65536
LET P=P+BST
LET U_=U_/SHb !shr(U_,BST)
LOOP UNTIL P>LM
!---
FOR LA=LA TO 255
LET A(LA,J)=0 !(0),table stop mark
NEXT LA
END SUB
SUB SERCH
FOR I=I TO DH(0,J)-1
LET L_=L(I,J)
IF L_<=P THEN LET w=IP(D_/2^(16-L_))*2^(16-L_) ELSE EXIT FOR
IF w<=B(I,J) THEN
IF w=B(I,J) THEN EXIT SUB ELSE EXIT FOR
END IF
NEXT I
LET L_=-1
END SUB
!===========
! Inverse Fast Cosin Transform.( 8x8, iDCT-2 ) ← Inverse Quantization.DQ()
SUB IDDCT8X8
FOR P=0 TO CMO ! (0=Y,1=Cb,2=Cr)
FOR V0=0 TO DV_-1 STEP 8*MV(0)/MV(P)
FOR U0=0 TO DU-1 STEP 8*MH(0)/MH(P)
!----
FOR V_=0 TO 7
FOR U_=0 TO 7
LET X(U_)=D2(U0+U_,V0+V_,P) *DQ(U_,V_,QS(P)) ! Inverse Quantization
NEXT U_
CALL IWANG ! inverse DCT horizontal_row_8
FOR X_=0 TO 7
LET T(X_,V_)=X(X_)
NEXT X_
NEXT V_
!----
FOR X_=0 TO 7
FOR V_=0 TO 7
LET X(V_)=T(X_,V_)
NEXT V_
CALL IWANG ! inverse DCT vertical_column_8
LET i=X_*MH(0) !expand pt.X
FOR Y_=0 TO 7
IF P=0 THEN
LET D1(U0+X_,V0+Y_,P)=X(Y_)+128 ! inverse level shift
ELSE
LET j=Y_*MV(0) !expand pt.Y
!----expand
FOR V_=j TO j+MV(0)-1
FOR U_=i TO i+MH(0)-1
LET D1(U0+U_,V0+V_,P)=X(Y_) ! CbCr to MCU scale
NEXT U_
NEXT V_
!----expand
END IF
NEXT Y_
NEXT X_
!----
NEXT U0
NEXT V0
NEXT P
END SUB
!----inverse Wang.( 8, iDCT-2 )
SUB IWANG
LET XO(0)=SQR(2/8)*X(0)
LET XO(1)=SQR(2/8)*X(4)
LET XO(2)=SQR(2/8)*X(2)
LET XO(3)=SQR(2/8)*X(6)
LET XO(4)=SQR(1/8)*X(1)
LET XO(5)=SQR(1/8)*X(5)
LET XO(6)=SQR(1/8)*X(3)
LET XO(7)=SQR(1/8)*X(7)
!
LET X(4)=(COS(PI /16)*XO(4)+SIN(PI /16)*XO(7))
LET X(5)=(COS(PI*5/16)*XO(5)+SIN(PI*5/16)*XO(6))
LET X(6)=(SIN(PI*5/16)*XO(5)-COS(PI*5/16)*XO(6))
LET X(7)=(SIN(PI /16)*XO(4)-COS(PI /16)*XO(7))
!
LET XO(4)= X(4)+X(5)
LET XO(5)= X(4)-X(5)
LET XO(6)=-X(6)+X(7)
LET XO(7)= X(6)+X(7)
!
LET X(0)=(COS(PI/4)*XO(0)+COS(PI /4)*XO(1))
LET X(1)=(COS(PI/4)*XO(0)-COS(PI /4)*XO(1))
LET X(2)=(SIN(PI/8)*XO(2)-SIN(PI*3/8)*XO(3))
LET X(3)=(COS(PI/8)*XO(2)+COS(PI*3/8)*XO(3))
LET X(4)=XO(4)
LET X(5)=XO(6)
LET X(6)=XO(5)
LET X(7)=XO(7)
!
LET XO(0)=X(0)+X(3)
LET XO(1)=X(1)+X(2)
LET XO(2)=X(1)-X(2)
LET XO(3)=X(0)-X(3)
LET XO(4)=X(7)*SQR(2)
LET XO(5)=X(6)-X(5)
LET XO(6)=X(6)+X(5)
LET XO(7)=X(4)*SQR(2)
!
LET X(0)=XO(0)+XO(7)
LET X(1)=XO(1)+XO(6)
LET X(2)=XO(2)+XO(5)
LET X(3)=XO(3)+XO(4)
LET X(4)=XO(3)-XO(4)
LET X(5)=XO(2)-XO(5)
LET X(6)=XO(1)-XO(6)
LET X(7)=XO(0)-XO(7)
END SUB
!=============
SUB R_BIN31(M) ! decord(M) before new.search(M)
DO
IF M=BVAL("D8",16) THEN ! SOI
MAT DH=ZER ! clear Huffman Table
LET DRI=0 ! clear Restart Interval.value for RST0~7(restart marker)
LET rct=-1 ! Interval.counter, valid (0<=rct), invalid (rct< 0)
MAT M3=ZER ! clear scan band sum
ELSEIF M=BVAL("D9",16) THEN ! EOI
EXIT DO ! close & end_sub
ELSEIF BVAL("D0",16)<=M AND M<=BVAL("D7",16) THEN ! RST0~7( restart marker)
LET rct=DRI ! set counter with Restart Interval
EXIT SUB
ELSEIF 0< M THEN !M=0 is data"FF" in picture area
CALL RED_D
LET N=ORD(D$)*256
CALL RED_D
LET N=N+ORD(D$)-2 ! N=remain size
!---
IF BVAL("E0",16)<=M AND M<=BVAL("EF",16) THEN ! APP0~APP15
CALL FFE0
ELSEIF M=BVAL("DD",16) THEN
CALL FFDD ! DRI load DRI & rct=DRI
ELSEIF M=BVAL("FE",16) THEN
CALL FFFE ! COMMENT
ELSEIF M=BVAL("C4",16) THEN
CALL FFC4 ! DHT
ELSEIF M=BVAL("DB",16) THEN
CALL FFDB ! DQT
ELSEIF M=BVAL("C0",16) OR M=BVAL("C2",16) THEN
PRINT right$("000"& BSTR$(byt-4,16),4)
!---
CALL FFC0 ! SOF0 SOF2
!---
PRINT " SOF";STR$(MOD(M,16));" MCU_HV Ybr ";STR$(MH(0));STR$(MV(0));
PRINT " ";STR$(MH(1));STR$(MV(1));" ";STR$(MH(2));STR$(MV(2))
ELSEIF M=BVAL("DA",16) THEN
CALL FFDA ! SOS
EXIT SUB ! without close
ELSE
BREAK ! new marker
END IF
END IF
!---
DO
LET M=BVAL("D9",16) ! EOI, 256 ! end of file
CHARACTER INPUT #1,IF MISSING THEN EXIT DO :D$
LET byt=byt+1 !!!
LET M=ORD(D$)
LOOP UNTIL M=255 ! 1st.mark
IF M<>255 THEN EXIT DO ! close & end_sub
CALL RED_D
LET M=ORD(D$)
LOOP
CLOSE #1
END SUB
!Page-4 へ続く
-
- [4]
Page-4
- 投稿者:SECOND
- 投稿日:2009年12月14日(月)20時43分29秒
-
-
!Page-4 の始め
!DRI
SUB FFDD
CALL RED_D
LET DRI=ORD(D$)*256
CALL RED_D
LET DRI=DRI+ORD(D$)
LET rct=DRI
END SUB
!APP0
SUB FFE0
FOR W=1 TO N
CALL RED_D
NEXT W
END SUB
!COMMENT
SUB FFFE
FOR W=1 TO N
CALL RED_D
NEXT W
END SUB
!DQT
SUB FFDB
DO WHILE 0< N
CALL RED_D
LET w= IP(ORD(D$)/16) !p=0(byte) p=1(word)
LET J=MOD(ORD(D$),16) !J=0~3 (QT.number)
FOR i=0 TO 63
CALL RED_D
LET DQ(U(i),V(i),J)=ORD(D$)
IF w=1 THEN
CALL RED_D
LET DQ(U(i),V(i),J)=DQ(U(i),V(i),J)*256+ORD(D$)
END IF
NEXT i
LET N=N-65-64*w ! remain size
LOOP
END SUB
!SOF0 SOF2
SUB FFC0
CALL RED_D
IF ORD(D$)<>8 THEN BREAK ! 8bit( 24bitColor ) at RGB.dimension
CALL RED_D
LET W=ORD(D$)*256
CALL RED_D
LET DY=W+ORD(D$) !V.pix.
CALL RED_D
LET W=ORD(D$)*256
CALL RED_D
LET DX=W+ORD(D$) !H.pix.
CALL RED_D
FOR i=0 TO ORD(D$)-1 !1~3 フレーム数、続くID 配置は、暗黙に Y,Cb,Cr の順
CALL RED_D
LET CoID(ORD(D$))=i ! CoID( ID=0~255) <--(Y=0, Cb=1, Cr=2)
CALL RED_D
LET MH(i)= IP(ORD(D$)/16) ! HV Y=11,12,21,22,41 Cb=11,11,11,11,11 Cr=11,11,11,11,11
LET MV(i)=MOD(ORD(D$),16)
CALL RED_D
LET QS(i)=ORD(D$) ! QT.number0~3 <-- QS( Y=0, Cb=1, Cr=2)
NEXT i
IF i=1 THEN LET CMO=0 ELSE LET CMO=2
END SUB
!DHT
SUB FFC4
DO WHILE 0< N
CALL RED_D
LET J=ORD(D$) ! (DC=0 AC=1 | ID0_0~3)
LET J=2*MOD(J,16)+IP(J/16) ! 0~1=ID0.DC~AC 2~3=ID1.DC~AC 4~5=ID2.…
LET DH(0,J)=0 !!!for 2nd.use for clear
FOR i=1 TO 16
CALL RED_D
LET DH(i,J)=ORD(D$)
LET DH(0,J)=DH(0,J)+DH(i,J)
NEXT i
FOR i=0 TO DH(0,J)-1
CALL RED_D
LET DV(i,J)=ORD(D$)
NEXT i
!---
FOR i=i TO 255
LET DV(i,J)=0
NEXT i
CALL makeH0(J) ! make Huffman Code table B() L()
CALL makeD0(J) ! make Huffman Decorder table A()
!---
LET N=N-1-16-DH(0,J) ! remain size
LOOP
END SUB
!SOS
SUB FFDA
CALL RED_D
LET M2=ORD(D$)
MAT HDC=(-2)*CON
MAT HAC=(-2)*CON
FOR i=1 TO M2
CALL RED_D ! ID=0~255( defined by SOFx)
LET w=ORD(D$)
CALL RED_D ! (DC_0~3|AC_0~3) huffman table selection
LET HDC(CoID(w))= IP(ORD(D$)/16)*2 !DC 0~3-->0,2,4,6
LET HAC(CoID(w))=MOD(ORD(D$),16)*2+1 !AC 0~3-->1,3,5,7
NEXT i
CALL RED_D
LET Ss_=ORD(D$) ! low of spectral selection
CALL RED_D
LET Se_=ORD(D$) ! high of spectral selection
CALL RED_D
LET Al=MOD(ORD(D$),16) !successive approximation bit position low ( point transform )
LET Ah=IP(ORD(D$)/16) !successive approximation bit position high ( preceding "Al" )
!--- balance monitor M30 M3() for display timing.
LET w=Se_-Ss_+1
IF Ah<>Al THEN LET w=w*(Ah-Al) ! prog.sa
FOR i=0 TO 2
IF 0<=HAC(i) THEN LET M3(i)=M3(i)+w ! M3()= scan band sum
NEXT i
IF CMO=0 OR M3(0)=M3(1) AND M3(1)=M3(2) THEN LET M30=M3(0) ELSE LET M30=99 ! Ybr.balance
!--- next image data top
END SUB
!プログレッシブ・シーケンスでは、段階的に画像ができるため、
!カラー画像表示のタイミング適正のため、上の様に、モニター変数 M30 を設けた。
!
! (Ah|Al) (バンド幅*ビット幅)の積算
!Ss Se Y Cb Cr ベース・ライン・シーケンス例 baseline
!00 3F 00 00 00 M3()= 64 64 64 …M30=64 完成画。
!Ss Se Y Cb Cr プログレッシブ・シーケンス例 spectral selection
!00 00 00 00 00 M3()= 1 1 1 …M30= 1
!01 05 -- 00 -- M3()= 1 6 1 = 99 99 は、バンド幅(Se-Ss+1)の
!01 05 -- -- 00 M3()= 1 6 6 = 99 累積が、
!01 05 00 -- -- M3()= 6 6 6 …M30= 6 Y,Cb,Cr で揃っていない時。
!06 3F -- 00 -- M3()= 6 64 6 = 99
!06 3F -- -- 00 M3()= 6 64 64 = 99
!06 3F 00 -- -- M3()= 64 64 64 …M30= 64 完成画。
!Ss Se Y Cb Cr プログレッシブ・シーケンス例 successive approximation
!00 00 01 01 01 M3()= -1 -1 -1 …M30= -1
!01 05 02 -- -- M3()= -11 -1 -1 = 99 99 は、バンド幅(Se-Ss+1)と、
!01 3F -- -- 01 M3()= -11 -1 -64 = 99 分割ビット長(Ah-Al)の積の
!01 3F -- 01 -- M3()= -11 -64 -64 = 99 累積が、
!06 3F 02 -- -- M3()=-127 -64 -64 = 99 Y,Cb,Cr で揃っていない時。
!01 3F 21 -- -- M3()= -64 -64 -64 …M30= -64
!00 00 10 10 10 M3()= -63 -63 -63 …M30= -63
!01 3F -- -- 10 M3()= -63 -63 0 = 99
!01 3F -- 10 -- M3()= -63 0 0 = 99
!01 3F 10 -- -- M3()= 0 0 0 …M30= 0 完成画。
SUB ROPEN
OPEN #1 :NAME FL$ ,ACCESS INPUT
END SUB
SUB RED_D
CHARACTER INPUT #1 :D$
LET byt=byt+1 !!!
END SUB
END
-
- [5]
改訂 十進 BASIC で、JPG ファイルを作る。
- 投稿者:SECOND
- 投稿日:2009年12月15日(火)04時53分6秒
-
-
!改訂 十進 BASIC で、JPG ファイルを作る。
!
!ハフマン符号木に、1つ空席を残さないと、開けないビューアの存在や、
!Linux 対策などが、先の投稿で、あちこち散乱していたのを、1つにし、
!Windows Linux 両用に、まとめた。
!
!このリスト最後の EXTERNAL SUB sample() で描く マンデルブロー の画像を、
!原画のサンプルにして、ベースラインJPG ファイルを作ります。
!DCT 変換、ハフマンコード化 …JPG ファイルまでを、BASIC だけで、実行。
!
!ハフマン・コードについては、標準テーブルを使わず、
!ランレングス・頻度の測定と、ハフマン・ツリーの作成を行い、それによる
!専用ハフマン・テーブルで、コード化します。(本来のハフマン・コード。)
!
DEBUG ON
!----------------------
! baseline JPG encoder
!----------------------
! テキスト・ウィンドウの、左上位置(x0,y0)と、幅(xw,yw)。
! CALL SetWindowPos( WinHandle("TEXT" ),0, 15,172,500,520, 0)
! SUB SetWindowPos( handle,C2, x0,y0,xw,yw, nFLG) !nFLG: 0=x0y0xwyw 1=x0y0 2=xwyw
! ASSIGN "user32.dll","SetWindowPos" !← Linux版 は使えない命令。
! END SUB
!----------------------------------------------------------
LET FL$="baseline.jpg" ! 削除すると、ダイアログ・ボックス入力。
SET ECHO "OFF"
ASK DIRECTORY s$
IF FL$>"" THEN PRINT "カレント DIR:"& s$ ELSE file getname FL$, "jpg"
PRINT "出力ファイル:"& FL$
IF FL$>"" THEN PRINT "上書き。又は作成されます。…"& "Ok?[Enter]"
IF FL$>"" THEN CHARACTER INPUT k$
IF FL$="" OR k$<>CHR$(13) THEN
PRINT "中止"
STOP
END IF
OPTION ARITHMETIC NATIVE
OPTION BASE 0
OPTION CHARACTER byte
SET TEXT background "OPAQUE"
ASK BITMAP SIZE bmx,bmy
SET WINDOW 0,bmx, bmy,0
!
DIM D8(1000,1000) !sample picture
DIM D2(1000,1000,2) !Y=D2(,,0) Cb=D2(,,1) Cr=D2(,,2)
DIM MH(2),MV(2) !MCU.Ybr.H()V()
DIM HDC(2),HAC(2) !hT.table selection
DIM QS(2),CoID(255) !qT.table selection
!
DIM U(63),V(63) !zigzag
DIM DQ(7,7,3) !DQT
DIM DH(16,7),DV(255,7) !DHT
DIM B(255+1,7),L(255,7) !huffman.code & length ( MAKE_H2 )
DIM B2(2) !Ybr D.C.成分 starting
DIM T(7,7),X(7),XO(7) !DDCT8X8
!
!---encorder
DIM SV(255,3) !ZFRE0 頻度SV( 座標)
DIM S_(255,3) !MAKE_DHT 頻度SV( 座標)--> 頻度S_( 降順No.) 座標DV( 降順No.)
DIM F_(255),Tr(16,255,3) !TREE3
!---lister
LET crlf$=CHR$(13)& CHR$(10)
DIM W_$(7)
LET W_$(0)="Y.DC"
LET W_$(1)="Y.AC"
LET W_$(2)="C.DC"
LET W_$(3)="C.AC"
!
SET VIEWPORT 0,0.4,0.6,1
CALL sample(DX$,DY$) !サンプルの描画。
LET DX=VAL(DX$)
LET DY=VAL(DY$)
MAT D8=ZER(DX-1,DY-1)
SET VIEWPORT 0, 1, 0, 1
SET WINDOW 0,bmx, bmy,0
! SET COLOR MODE "NATIVE" !← Linux版 は使えない命令。
ASK PIXEL ARRAY (0,0) D8
! MAT PLOT CELLS,IN 250,250; 450,450: D8 ! sample 原画 D8 のチェック
!
LET CMO=2 !CMO=0(mono.) CMO=2(color)
LET SD=1 !encoder 量子化テーブル調整 1/SD
CALL DQTINI !DQ(,,0)~DQ(,,1)~{zigzag U()V()},MH(),MV()
LET DU =CEIL(DX/(8*MH(0)))*8*MH(0) !Uwidth= (8X8)*2 bound by MCU size
LET DV_=CEIL(DY/(8*MV(0)))*8*MV(0) !Vwidth= (8X8)*1
MAT D2=ZER(DU-1,DV_-1,2) !Y=D2(,,0) Cb=D2(,,1) Cr=D2(,,2)
!
! CALL YbrRGB_n ! Ybr D2()<--RGB D8() !← color mode "NATIVE" の場合。
CALL YbrRGB_r ! Ybr D2()<--RGB D8() !← color mode "REGULAR" の場合。
LET MHT=1 ! flag. uncondition making huff.table
CALL DDCT8X8 ! D2() -->DCT -->Quantization
CALL ZZRL0 ! encoder
!---
PRINT "-------------------------"
PRINT "Encoder huffman Code"
FOR J=0 TO CMO+1
CALL list_HT(W_$(J),J) ! value Sort !H2.LST
NEXT J
beep
PRINT "終了"
!--------- JPG 色空間 -------------------------
! | Y | | 0.2990 +0.5870 +0.1140 | | R |
! |B-Y| = |-0.1687 -0.3313 +0.5000 | | G |
! |R-Y| | 0.5000 -0.4187 -0.0813 | | B |
!
! | R | | 1 0 +1.40200 | | Y |
! | G | = | 1 -0.34414 -0.71414 | |B-Y|
! | B | | 1 +1.77200 0 | |R-Y|
!----------------------------------------------
! Windows版 color mode "NATIVE" の場合。
!----------------------------------------
SUB YbrRGB_n !Ybr D2()<--RGB D8() 24bit Color
FOR V0=0 TO DY-1
FOR U0=0 TO DX-1
LET w1= MOD(D8(U0,V0),256) !R
LET w2=MOD(IP(D8(U0,V0)/256),256) !G
LET w3= IP(D8(U0,V0)/65536) !B
LET D2(U0,V0,0)= 0.2990*w1+0.5870*w2+0.1140*w3 !Y
LET D2(U0,V0,1)=-0.1687*w1-0.3313*w2+0.5000*w3 !Cb
LET D2(U0,V0,2)= 0.5000*w1-0.4187*w2-0.0813*w3 !Cr
NEXT U0
NEXT V0
END SUB
!---------------------------------------------------
! Windows版 or Linux版 color mode "REGULAR" の場合。
!---------------------------------------------------
SUB YbrRGB_r !Ybr D2()<--RGB D8() 色指標 Color
FOR V0=0 TO DY-1
FOR U0=0 TO DX-1
ASK COLOR MIX( D8(U0,V0)) w1,w2,w3 ! R,G,B (0~1)
LET D2(U0,V0,0)= 255*( 0.2990*w1+0.5870*w2+0.1140*w3) !Y
LET D2(U0,V0,1)= 255*(-0.1687*w1-0.3313*w2+0.5000*w3) !Cb
LET D2(U0,V0,2)= 255*( 0.5000*w1-0.4187*w2-0.0813*w3) !Cr
NEXT U0
NEXT V0
END SUB
!-----------
SUB DQTINI
RESTORE
!---DQT quantization
FOR j=0 TO 1
FOR V_=0 TO 7
FOR U_=0 TO 7
READ W
LET DQ(U_,V_,j)=CEIL(W/SD) ! inhibit 0
NEXT U_
NEXT V_
NEXT j
!---zigzag-U()V()
FOR V_=0 TO 7
FOR U_=0 TO 7
READ i
LET U(i)=U_
LET V(i)=V_
NEXT U_
NEXT V_
!---HT selection
MAT READ HDC !Y Cb Cr
MAT READ HAC !Y Cb Cr
!---QT selection
MAT READ QS !Y Cb Cr
!---MCU size
MAT MH=CON !Y Cb Cr =1
MAT MV=CON !Y Cb Cr =1
IF 0< CMO THEN
LET MH(0)=2 !Y
LET MV(0)=2 !Y
END IF
END SUB
!---quantization table
!輝度( SMPTE 370M ).Y
!*DQTY
DATA 32, 16, 17, 18, 18, 19, 42, 44
DATA 16, 17, 18, 18, 19, 38, 43, 45
DATA 17, 18, 19, 19, 40, 41, 45, 48
DATA 18, 18, 19, 40, 41, 42, 46, 49
DATA 18, 19, 40, 41, 42, 43, 48,101
DATA 19, 38, 41, 42, 43, 44, 98,104
DATA 42, 43, 45, 46, 48, 98,109,116
DATA 44, 45, 48, 49,101,104,116,123
!---quantization table
!色差( SMPTE 370M ).Cb Cr
!*DQTC
DATA 32, 16, 17, 25, 26, 26, 42, 44
DATA 16, 17, 25, 25, 26, 38, 43, 91
DATA 17, 25, 26, 27, 40, 41, 91, 96
DATA 25, 25, 27, 40, 41, 84, 93,197
DATA 26, 26, 40, 41, 84, 86,191,203
DATA 26, 38, 41, 84, 86,177,197,209
DATA 42, 43, 91, 93,191,197,219,232
DATA 44, 91, 96,197,203,209,232,246
!---Zigzag table
DATA 0, 1, 5, 6,14,15,27,28
DATA 2, 4, 7,13,16,26,29,42
DATA 3, 8,12,17,25,30,41,43
DATA 9,11,18,24,31,40,44,53
DATA 10,19,23,32,39,45,52,54
DATA 20,22,33,38,46,51,55,60
DATA 21,34,37,47,50,56,59,61
DATA 35,36,48,49,57,58,62,63
!---HT selection
DATA 0,2,2 !DC. Y Cb Cr
DATA 1,3,3 !AC. Y Cb Cr
!---QT selection
DATA 0,1,1 ! Y Cb Cr
!Page-2 へ続く
-
- [6]
Page-2
- 投稿者:SECOND
- 投稿日:2009年12月15日(火)04時55分18秒
-
-
!Page-2 の始め
!==========================================
! analizing frequency SV(nnnn,ssss) for DHT
SUB ZFRE0
MAT SV=ZER
LET B2(0)=0 ! Y.DC( start prediction)
LET B2(1)=0 ! Cb.DC
LET B2(2)=0 ! Cr.DC
!---
FOR V09=0 TO DV_-1 STEP 8*MV(0)
FOR U09=0 TO DU-1 STEP 8*MH(0)
!---MCU
FOR P=0 TO CMO ! ( 0=Y 1=Cb 2=Cr)
FOR V0=V09 TO V09+8*MV(P)-1 STEP 8
FOR U0=U09 TO U09+8*MH(P)-1 STEP 8
CALL F_BLK0
NEXT U0
NEXT V0
NEXT P
!---
NEXT U09
NEXT V09
!---
CALL MAKE_DHT !DH( ,J) DV( ,J) <--S_( ,J)
END SUB
! haffman Transform. main
SUB ZZRL0
! ---pass-1 analize frequency SV(nnnn,ssss) -->DV( ,J) DH( ,J)
IF 0< MHT OR DH(0,0)=0 THEN CALL ZFRE0
!---pass-2
CALL MAKE_H2 ! huffman code=B(V,J) len.=L(V,J) <-- DH( ,J) DV( ,J)
!---
LET byt=0 !!!
CALL WOPEN
CALL W_BIN31
!---
LET Hw=0 !bits stream buffer
LET BC=0 !bits in Hw
!---
LET B2(0)=0 ! Y.DC( start prediction)
LET B2(1)=0 ! Cb.DC
LET B2(2)=0 ! Cr.DC
!---
FOR V09=0 TO DV_-1 STEP 8*MV(0)
FOR U09=0 TO DU-1 STEP 8*MH(0)
!---MCU
FOR P=0 TO CMO !( 0=Y 1=Cb 2=Cr)
FOR V0=V09 TO V09+8*MV(P)-1 STEP 8
FOR U0=U09 TO U09+8*MH(P)-1 STEP 8
CALL W_BLK0
NEXT U0
NEXT V0
NEXT P
!---
NEXT U09
NEXT V09
CALL W_FLUSH
!---EOI
CALL WRT_H("FFD9")
CLOSE #1
PRINT "byte size:";byt
END SUB
!------
SUB F_BLK0
LET J=2*SGN(P) ! ( 0=Y 1=Cb 2=Cr)
!---D.C.part
LET W=D2(U0+U(0),V0+V(0),P)
LET SY=W-B2(P)
LET B2(P)=W ! previous of D.C.difference
IF SY<>0 THEN LET SS=LEN(BSTR$(ABS( SY),2)) ELSE LET SS=0 ! bit_length
LET SV(SS,J)=SV(SS,J)+1
!---A.C.parts
FOR AE=63 TO 0 STEP -1
IF 0<>D2(U0+U(AE),V0+V(AE),P) THEN EXIT FOR
NEXT AE
!---
LET Z=0 !zero run counter
FOR A_=1 TO AE
LET SY=D2(U0+U(A_),V0+V(A_),P)
IF SY=0 AND Z< 15 THEN
LET Z=Z+1
ELSE
IF SY<>0 THEN LET SS=LEN(BSTR$(ABS(SY),2)) ELSE LET SS=0 ! bit_length
LET W=Z*16+SS
LET Z=0
LET SV(W,J+1)=SV(W,J+1)+1
END IF
NEXT A_
IF A_< 64 THEN LET SV(0,J+1)=SV(0,J+1)+1 !End Of Block
END SUB
SUB W_BLK0
LET J=2*SGN(P) ! ( 0=Y 1=Cb 2=Cr)
!---D.C.part absolute SY bits length
LET W=D2(U0+U(0),V0+V(0),P)
LET SY=W-B2(P)
LET B2(P)=W ! previous of D.C.difference
IF SY<>0 THEN LET SS=LEN(BSTR$(ABS( SY),2)) ELSE LET SS=0 ! bit_length
LET L_=L(SS,J)
LET Ww=B(SS,J)
CALL W_HUFF
!---D.C.extent
IF SS<>0 THEN
IF SY< 0 THEN LET SY=SY+2^SS-1 !add maxim. in same bit_length.
LET L_=SS
LET Ww=SY*2^(16-L_)
CALL W_HUFF
END IF
!---A.C.parts
FOR AE=63 TO 0 STEP -1
IF 0<>D2(U0+U(AE),V0+V(AE),P) THEN EXIT FOR
NEXT AE
!---
LET Z=0 !zero run counter
FOR A_=1 TO AE
LET SY=D2(U0+U(A_),V0+V(A_),P)
IF SY=0 AND Z< 15 THEN
LET Z=Z+1
ELSE
IF SY<>0 THEN LET SS=LEN(BSTR$(ABS(SY),2)) ELSE LET SS=0 ! bit_length
LET W=Z*16+SS
LET Z=0
LET L_=L(W,J+1)
LET Ww=B(W,J+1)
CALL W_HUFF
!---A.C.extent
IF SS<>0 THEN
IF SY< 0 THEN LET SY=SY+2^SS-1 !add maxim. in same bit_length.
LET L_=SS
LET Ww=SY*2^(16-L_)
CALL W_HUFF
END IF
END IF
NEXT A_
IF A_< 64 THEN
LET L_=L(0,J+1)
LET Ww=B(0,J+1)
CALL W_HUFF !End Of Block
END IF
END SUB
!-----
!Ww:b15 ~0 左詰め 入力 bit_stream. L_:bit長
SUB W_HUFF
LET Hw=Hw+Ww*2^(-BC-8)
LET BC=BC+L_
DO WHILE 8<=BC
CALL WRT_D( IP(Hw))
IF IP(Hw)=255 THEN CALL WRT_D( 0)
LET Hw=FP(Hw)*256
LET BC=BC-8
LOOP
END SUB
!flush bit buffer with byte_bound( fill"1"in blank)
SUB W_FLUSH
IF BC<>0 THEN
LET w=Hw +2^(8-BC)-1
CALL WRT_D( w)
IF w=255 THEN CALL WRT_D( 0)
END IF
END SUB
!=====================
!pre hafman Transform.
!sort frequency S_() of nnnnssss( zero_run_length data)
!make DH() DV()
SUB MAKE_DHT
MAT DH=ZER
!---debug monitor
PRINT "-----------------------------------------"
FOR J=0 TO CMO+1 ! CMO =0=mono =2=color
PRINT "Zero_Run_Length 頻度表 (→)画素bit幅0~15、(↓)直前0数0~15"
PRINT W_$(J)
CALL msg00( SV, 0,255,J, 5) ! SV( 0~255, J)
PRINT "total=";Tx
NEXT J
PRINT
!---
FOR P=0 TO CMO+1 ! P(0~1=Y.DC~AC 2~3=C.DC~AC), CMO( 0=mono 2=color)
!--- make S_(,)DV(,)<-- SV(,)
LET SE=-1
FOR i=0 TO 255
IF SV(i,P)<>0 THEN
LET SE=SE+1
LET S_(SE,P)=SV(i,P)
LET DV(SE,P)=i
END IF
NEXT i
PRINT "===================================="
PRINT W_$(P)
PRINT "Zero Run Length 頻度表を詰めたもの"
CALL msg00( S_, 0,SE,P, 5) ! S_(0~SE, P)
PRINT "表座標(0~F=直前0数:0~F=画素bit長)"
CALL msg0x( DV, 0,SE,P, 5) ! DV(0~SE, P)
!---
CALL Qsort(0,SE)
CALL TREE3
!---
PRINT
PRINT " Encoder DHT table"
PRINT " (→)コード長1~16の、各個数"
CALL msg0x( DH, 1,16 ,P, 3) ! DH(1~16, P)
PRINT " 頻度順の、表座標(0~F=直前0数:0~F=画素bit長)"
CALL msg0x( DV, 0,Tx-1,P, 3) ! DV(0~Tx-1, P)
PRINT
NEXT P
END SUB
SUB msg00( M(,), S,E,J, w)
LET Tx=0
LET w$=""
FOR i=S TO E
LET Tx=Tx+M(i,J)
LET w$=w$& USING$( REPEAT$("#",w),M(i,J))
IF MOD(i-S,16)=15 THEN LET w$=w$& crlf$
NEXT i
IF MOD(i-S,16)=0 THEN PRINT w$; ELSE PRINT w$
END SUB
!Page-3 へ続く
-
- [7]
Page-3
- 投稿者:SECOND
- 投稿日:2009年12月15日(火)04時57分23秒
-
-
!Page-3 の始め
SUB msg0x( M(,), S,E,J, w)
LET Tx=0
LET w$=""
FOR i=S TO E
LET Tx=Tx+M(i,J)
LET w$=w$& REPEAT$(" ",w-2)& RIGHT$("0"& BSTR$(M(i,J),16),2)
IF MOD(i-S,16)=15 THEN LET w$=w$& crlf$
NEXT i
IF MOD(i-S,16)=0 THEN PRINT w$; ELSE PRINT w$
END SUB
!-------------------
! make huffman tree
!
!ハフマン符号木の、最後尾に1つ使わない枝を設けると、その分、符号木の
!枝ぶりが増え、全体のビット長も増え、圧縮コードとしては良くないですが、
!一部のビューアが、それを必要とする。(恐らくバグだと思います。)
!
!下の文中、" !←(+1) 符号木の最下に、空席を1つ作る。" …の行、2つ。
! SE+1 を、SE に戻すと空席は無くなり、本来の状態にも、戻せます。
!
SUB TREE3
MAT Tr=ZER
FOR i=0 TO SE
LET F_(i)=S_(i,P) !数値を壊すので、コピー F_(i)で実行
NEXT i
LET F_(SE+1)=0 !← 空席用
!---minimum pair
DO
LET w=1e8
FOR i=0 TO SE+1 !←(+1) 符号木の最下に、空席を1つ作る。
IF F_(i)< w THEN
LET w=F_(i)
LET Ad1=i ! minimum1 !頻度最小の分岐アドレスAd1
END IF
NEXT i
LET w=1e8
FOR i=0 TO SE+1 !←(+1) 符号木の最下に、空席を1つ作る。
IF F_(i)< w AND i<>Ad1 THEN
LET w=F_(i)
LET Ad2=i ! minimum2 !頻度最小の分岐アドレスAd2
END IF
NEXT i
IF w=1e8 THEN EXIT DO !分岐の組が無くなるまで
!---
LET F_(Ad1)=F_(Ad1)+F_(Ad2) !次の頻度最小の組探しは、2分岐合計を1つにし、
LET F_(Ad2)=1e9 !他方を外して行なう
!---
FOR Le1=16 TO 1 STEP -1 !アドレスAd1の最上 節点レベルLe1 を探す(最初のLe1=0)
IF Tr(Le1,Ad1,1)>0 OR Tr(Le1,Ad1,3)>0 THEN EXIT FOR
NEXT Le1
FOR Le2=16 TO 1 STEP -1 !アドレスAd2の最上 節点レベルLe2 を探す(最初のLe2=0)
IF Tr(Le2,Ad2,1)>0 OR Tr(Le2,Ad2,3)>0 THEN EXIT FOR
NEXT Le2
LET Le0=MAX( Le1,Le2 )+1 !両者何れよりも1つ上の節点レベル(Le0,Ad1)に、
!---
LET Tr(Le0,Ad1,0)=Le1 !分岐先( 節点レベル,アドレス)として2組記入
LET Tr(Le0,Ad1,1)=Ad1
LET Tr(Le0,Ad1,2)=Le2
LET Tr(Le0,Ad1,3)=Ad2
LOOP
!---make DH()
LET k=0
CALL bitl(Le0,Ad1) !全アドレスの nested 段数を求める。
FOR Ad=0 TO SE !nested 段数が同じ Ad の総数を、段数毎に集計
LET DH(Tr(0,Ad,1),P)=DH(Tr(0,Ad,1),P)+1
NEXT Ad
LET DH(0,P)=Ad
END SUB
SUB bitl(Le,Ad) !最上 節点(Le0,Ad1)より全分岐を、底まで辿る
IF 0< Le THEN
LET k=k+1
CALL bitl( Tr(Le,Ad,0), Tr(Le,Ad,1) ) !分岐 nested 1
CALL bitl( Tr(Le,Ad,2), Tr(Le,Ad,3) ) !分岐 nested 2
LET k=k-1
ELSE
LET Tr(0,Ad,1)=k !最上 節点から底までの nested 段数kを書く
END IF
END SUB
!-------------------
! Quick Sort S_()
SUB Qsort(L,R) ! 降順にセット。
local i,j
LET i=L
LET j=R
LET Tx=S_(IP((L+R)/2),P)
DO
DO WHILE S_(i,P) >Tx ! 降順>、昇順<
LET i=i+1
LOOP
DO WHILE Tx >S_(j,P) ! 降順>、昇順<
LET j=j-1
LOOP
IF j< i THEN EXIT DO ! 等号付 j<=i は、暴走。
SWAP S_(i,P),S_(j,P)
SWAP DV(i,P),DV(j,P)
LET i=i+1
LET j=j-1
LOOP UNTIL j< i ! 等号付 j<=i は、低速。
IF L< j THEN CALL Qsort(L,j)
IF i< R THEN CALL Qsort(i,R)
END SUB
!===================================
! make encorder table B()L()<-- DH()
SUB MAKE_H2
MAT L=ZER
FOR J=0 TO CMO+1
LET I=0 ! コード生成 順番(短い順)
LET Hx=0
LET Tx=BVAL("8000",16)
FOR L_=1 TO 16
FOR N=1 TO DH(L_,J)
LET V_=DV(I,J) ! 座標DV(頻度降順)
LET L(V_,J)=L_
LET B(V_,J)=Hx ! コード(座標V_)
LET I=I+1
LET Hx=Hx+Tx
NEXT N
LET Tx=Tx/2
NEXT L_
LET B(256,J)=1
NEXT J
END SUB
!==============================
!Fast Discrete Cosin Transform.( M=8x8, DCT-2 )
SUB DDCT8X8
FOR P=0 TO CMO ! (0=Y,1=Cb,2=Cr)
FOR V0=0 TO DV_-1 STEP 8*MV(0)/MV(P)
FOR U0=0 TO DU-1 STEP 8*MH(0)/MH(P)
FOR Y_=0 TO 7
LET w=Y_*MV(0) !sampling pt.Y
FOR X_=0 TO 7 !level shift, sampling CbCr from MCU
IF P=0 THEN LET X(X_)=D2(U0+X_,V0+Y_,P)-128 ELSE LET X(X_)=D2(U0+X_*MH(0),V0+w,P)
NEXT X_
CALL WANG
FOR U_=0 TO 7
LET T(U_,Y_)=X(U_)
NEXT U_
NEXT Y_
FOR U_=0 TO 7
FOR Y_=0 TO 7
LET X(Y_)=T(U_,Y_)
NEXT Y_
CALL WANG
FOR V_=0 TO 7
LET D2(U0+U_,V0+V_,P)=ROUND( X(V_)/DQ(U_,V_,QS(P)) ) ! Quantization
NEXT V_
NEXT U_
NEXT U0
NEXT V0
NEXT P
END SUB
!=============================
!Fast Discrete Cosin Transform
!Wang.( M=8, DCT-2 )
SUB WANG
LET XO(0)=X(0)+X(7)
LET XO(1)=X(1)+X(6)
LET XO(2)=X(2)+X(5)
LET XO(3)=X(3)+X(4)
LET XO(4)=X(3)-X(4)
LET XO(5)=X(2)-X(5)
LET XO(6)=X(1)-X(6)
LET XO(7)=X(0)-X(7)
!
LET X(0)=XO(0)+XO(3)
LET X(1)=XO(1)+XO(2)
LET X(2)=XO(1)-XO(2)
LET X(3)=XO(0)-XO(3)
LET X(4)=XO(7)*SQR(2)
LET X(5)=XO(6)-XO(5)
LET X(6)=XO(6)+XO(5)
LET X(7)=XO(4)*SQR(2)
!
LET XO(0)=(COS(PI/4)*X(0)+COS(PI/4)*X(1))
LET XO(1)=(COS(PI/4)*X(0)-COS(PI/4)*X(1)) !fin 0(0),1(4)
LET XO(2)=(COS(PI/8)*X(3)+SIN(PI/8)*X(2))
LET XO(3)=(COS(PI*3/8)*X(3)-SIN(PI*3/8)*X(2)) !fin 2(2),3(6)
LET XO(4)=X(4)
LET XO(5)=X(6)
LET XO(6)=X(5)
LET XO(7)=X(7)
!
LET X(4)=XO(4)+XO(5)
LET X(5)=XO(4)-XO(5)
LET X(6)=-XO(6)+XO(7)
LET X(7)=XO(6)+XO(7)
!
LET XO(4)=(COS(PI/16)*X(4)+SIN(PI/16)*X(7))
LET XO(5)=(COS(PI*5/16)*X(5)+SIN(PI*5/16)*X(6))
LET XO(6)=(SIN(PI*5/16)*X(5)-COS(PI*5/16)*X(6))
LET XO(7)=(SIN(PI/16)*X(4)-COS(PI/16)*X(7))
!
LET X(0)=SQR(2/8)*XO(0)
LET X(4)=SQR(2/8)*XO(1)
LET X(2)=SQR(2/8)*XO(2)
LET X(6)=SQR(2/8)*XO(3)
LET X(1)=SQR(1/8)*XO(4)
LET X(5)=SQR(1/8)*XO(5)
LET X(3)=SQR(1/8)*XO(6)
LET X(7)=SQR(1/8)*XO(7)
END SUB
!Page-4 へ続く
-
- [8]
Page-4
- 投稿者:SECOND
- 投稿日:2009年12月15日(火)04時59分7秒
-
-
!Page-4 の始め
!========================
SUB W_BIN31
!---SOI
CALL WRT_H("FFD8")
!---APP0
CALL WRT_H("FFE0")
CALL WRT_W( 2+14) !size
CALL WRT_M("JFIF"& CHR$(0))
CALL WRT_H("0102") !ver 1.2
CALL WRT_D(0) !0=NoUnit 1=dpi 2=dpcm
CALL WRT_W(100) !Xd 100 アスペクト比 IE6(no) imaging(ok)
CALL WRT_W(100) !Yd 100 アスペクト比
CALL WRT_D(0) !Xt 0
CALL WRT_D(0) !Yt 0
!---DQT.Y.C
CALL WRT_H("FFDB")
LET W=2 !start size
FOR J=0 TO CMO/2 !CMO=0(mono.) CMO=2(color)
LET W=W+1+64 !+ID +QT
NEXT J
CALL WRT_W( W) !size
FOR J=0 TO CMO/2 ! CMO=0(mono.) CMO=2(color)
CALL WRT_D(J) !J= (0)Y.DQ (1)C.DQ
FOR I=0 TO 63
CALL WRT_D( DQ(U(i),V(i),J) )
NEXT I
NEXT J
!---SOF0
CALL WRT_H("FFC0")
IF CMO=0 THEN CALL WRT_W( 11) ELSE CALL WRT_W( 17) !size
CALL WRT_D( 8) !8bit at RGB
CALL WRT_W( DY) !V.pixels
CALL WRT_W( DX) !H.pixels
IF CMO=0 THEN
CALL WRT_H("01") !1 items
CALL WRT_H("011100") !Y MCU(H:V) DQT
ELSE
CALL WRT_H("03") !3 items
CALL WRT_H("01"& STR$(MH(0))& STR$(MV(0))& "0"& STR$(QS(0))) !Y MCU(H:V) DQT
CALL WRT_H("02"& STR$(MH(1))& STR$(MV(1))& "0"& STR$(QS(1))) !Cb - -
CALL WRT_H("03"& STR$(MH(2))& STR$(MV(2))& "0"& STR$(QS(2))) !Cr - -
END IF
!---DHT
CALL WRT_H("FFC4")
LET W=2 !start size
FOR J=0 TO CMO+1 !CMO=0(mono.) CMO=2(color)
LET W=W+1+16+DH(0,J) !+ID +HT +VT
NEXT J
CALL WRT_W( W) !size
FOR J=0 TO CMO+1 !CMO=0(mono.) CMO=2(color)
CALL WRT_D( 16*MOD(J,2)+IP(J/2) ) ! 00h=YDC 10h=YAC 01h=CDC 11h=CAC
FOR I=1 TO 16 !(J) 0 =YDC 1 =YAC 2 =CDC 3 =CAC
CALL WRT_D( DH(I,J))
NEXT I
FOR I=0 TO DH(0,J)-1
CALL WRT_D( DV(I,J))
NEXT I
NEXT J
!---SOS
CALL WRT_H("FFDA")
IF CMO=0 THEN
CALL WRT_W(8) !size
CALL WRT_D(1) !1 items
CALL WRT_H("0100") !No. Y.HDC/HAC
ELSE
CALL WRT_W(12) !size
CALL WRT_D( 3) !3 items
CALL WRT_H("0100") !No. Y.HDC/HAC
CALL WRT_H("0211") !No. Cb.HDC/HAC
CALL WRT_H("0311") !No. Cr.HDC/HAC
END IF
CALL WRT_H("003F00") !band 0~63, AhAl=00
END SUB
!----------------
!open write binary
SUB WOPEN
OPEN #1:NAME FL$
ERASE #1
END SUB
!sequential write byte
SUB WRT_D( D)
PRINT #1 :CHR$(D);
LET byt=byt+1 !!!
END SUB
!sequential write word
SUB WRT_W( w)
PRINT #1 :CHR$(IP(w/256));CHR$(MOD(w,256));
LET byt=byt+2 !!!
END SUB
!sequential write binary massage W$
SUB WRT_M( w$)
FOR w=1 TO LEN(w$)
PRINT #1 :MID$(w$,w,1);
NEXT w
LET byt=byt+w-1 !!!
END SUB
!sequential write binary hex.massage w$
SUB WRT_H( w$)
FOR w=1 TO LEN(w$) STEP 2
PRINT #1 :CHR$(BVAL(MID$(w$,w,2),16));
NEXT w
LET byt=byt+LEN(w$)/2 !!!
END SUB
!=====================
! print huffman_table
SUB list_HT( m$,J)
PRINT m$;" 頻度 座標 bit コード(";
IF MOD(B(256,J),2)=1 THEN PRINT "座標順)" ELSE PRINT "生成順、頻度降順)"
LET sum=0
FOR i=0 TO 255
IF L(i,J)<>0 THEN
IF MOD(B(256,J),2)=1 THEN ! 1=Sort_value. Encorder
LET V_=i
LET w$=" "& RIGHT$(" "& STR$(SV(i,J)),4)& " " ! times
LET sum=sum+L(i,J)*SV(i,J)
ELSE ! 0=Sort_length. Decorder
LET V_=DV(i,J)
LET w$=" "& RIGHT$(" "& STR$(S_(i,J)),4)& " " ! times
LET sum=sum+L(i,J)*S_(i,J)
END IF
LET w$=w$& RIGHT$("0"& BSTR$(V_,16),2)& " " ! value
LET w$=w$& RIGHT$(" "& STR$(L(i,J)),2)& " " ! length
!--- huffman code
LET H_=B(i,J) ! code
LET L_=L(i,J) ! length
!--- bit_pattern
LET w$=w$& left$(right$("0000000"& BSTR$(H_,2),16),L_)
PRINT w$
END IF
NEXT i
PRINT " 合計( 頻度 * bit)=";sum
END SUB
END
EXTERNAL SUB sample(DX$,DY$)
! マンデルブロー(Complex\mandelbm.bas の着色改変)
OPTION ARITHMETIC COMPLEX
SET COLOR MODE "REGULAR"
SET POINT STYLE 1
FOR n=1 TO 51
SET COLOR MIX( n) 0 ,0 ,n/51 !BLACK < < BLUE
SET COLOR MIX( 51+n) 0 ,n/51 ,1 !BLUE < < CYAN
SET COLOR MIX(102+n) 0 ,1 ,1-n/51 !CYAN < < GREEN
SET COLOR MIX(153+n) n/51,1 ,0 !GREEN < < YELLOW
SET COLOR MIX(204+n) 1 ,1-n/51,n/51 !YELLOW< < MAGENTA
NEXT n
LET XL=-2
LET XR=.8
LET w1=XR-XL
LET w2=w1/2
SET WINDOW XL, XR,-w2,w2
ASK PIXEL SIZE(XL,-w2; XR,w2) px,py
!
FOR x=XL TO XR+1e-6 STEP w1/(px-1)
FOR y=-w2-.49*w1/(py-1) TO w2 STEP w1/(py-1) !故意に(x,0)を描点の間に挟む。
LET z=0
FOR n=1 TO 255
LET z=z^2+COMPLEX(x,y)
IF 2< ABS(z) THEN
IF n< 64 THEN SET POINT COLOR n*4 ELSE SET POINT COLOR 253
PLOT POINTS :x,y !上下の対象プロットをしない。
EXIT FOR
END IF
NEXT n
NEXT y
NEXT x
LET DX$=STR$(px)
LET DY$=STR$(py)
END SUB
-
- [9]
簡易 JPGファイル解析ツール
- 投稿者:SECOND
- 投稿日:2009年12月17日(木)03時40分41秒
-
-
!----------------------------
! 簡易 JPGファイル解析ツール
!
!表示される記号で、( ? | ? ) のように、真中を縦線で区切った( ) は、
!全体が1バイトで、左右 各々 4bit の数です。
!
!例、ハフマンテーブルの先頭1バイトの注釈は、(DC=0 AC=1| HT_0~3) 、
! 上位4bit が、DC/AC の区別、下位4bit は、標識番号の意味です。
!
!オフセットアドレスは、マーカー先頭にのみ、offset: 0x00… で、表示されます。
!左端の数値は、認識結果で区切られたデーター内容で、オフセットでありません。
!
!すき間の無い4桁数値は、16bit 数値ですが、バイト順は、逆になっておらず、
!ファイルデータ自体が、Big Endian です。
DEBUG ON
!----------------------------
!テキスト・ウィンドウの、左上位置(x0,y0)と、幅(xw,yw)。
CALL SetWindowPos( WinHandle("TEXT" ),0, 15,172,500,520, 0)
SUB SetWindowPos( handle,C2, x0,y0,xw,yw, nFLG) !nFLG: 0=x0y0xwyw 1=x0y0 2=xwyw
ASSIGN "user32.dll","SetWindowPos"
END SUB
!----------------------------------------------------------
OPTION ARITHMETIC NATIVE
OPTION CHARACTER byte
OPTION BASE 0
SET TEXT background "OPAQUE"
SET ECHO "OFF"
LET crlf$=CHR$(13)& CHR$(10)
LET q$=CHR$(34)
DIM d(500), m$( BVAL("C0",16) TO BVAL("FF",16) ), Ybr$(2), AhAl(20,0 TO 3)
DIM QS(2),CoID(255) !qT.<--color selection, color<--ID selection
MAT READ m$
MAT READ Ybr$
CALL zigzag
!
FILE GETNAME file$, "画像(*.jpg)|*.jpg"
IF file$="" THEN
PRINT "入力ファイル名が、ありません。"
STOP
END IF
PRINT "入力ファイル:"& file$
CALL marker(file$)
CALL lstAhAl
IF M<>BVAL("D9",16) THEN
PRINT "Errors in File!,"
beep
END IF
PRINT "file end: 0x";BSTR$(byt-1,16)
SUB lstAhAl
IF 1< SOSn THEN
PRINT " (Ah|Al)"
PRINT "Ss Se Y Cb Cr プログレッシブ・シーケンスの表示"
FOR j=1 TO SOSn
LET w$=""
LET w$=w$& right$("0"& BSTR$(IP(AhAl(j,0)/256),16),2)& " "& right$("0"& BSTR$(MOD(AhAl(j,0),256),16),2)& " "
FOR i=1 TO 3
IF AhAl(j,i)< 0 THEN LET w$=w$& "-- " ELSE LET w$=w$& right$("0"& BSTR$(AhAl(j,i),16),2)& " "
NEXT i
PRINT w$
NEXT j
PRINT
END IF
END SUB
!------------
SUB marker(f$)
PRINT "----------------------------------------"
PRINT f$
OPEN #1 :NAME f$ ,ACCESS INPUT
LET byt=0 !offset counter
DO
DO
LET M=256 ! end of file
CHARACTER INPUT #1,IF MISSING THEN EXIT DO :D$
LET M=ORD(D$)
LET byt=byt+1 !offset counter
LOOP UNTIL M=255 ! 1st.mark
IF M<>255 THEN EXIT DO
CHARACTER INPUT #1 :D$
LET byt=byt+1 !offset counter
!---
LET M=ORD(D$)
IF M=BVAL("00",16) THEN ! 0xff in Picture data
LET ff0=ff0+1
ELSE
IF 0< SOSn AND 0< ff0 THEN PRINT right$(" "& STR$(ff0),3);"* 0xff00 in data"
!--- marker
PRINT
IF BVAL("C0",16)<=M THEN PRINT m$(M)(1:5);q$;m$(M)(6:10);q$; ELSE PRINT "FF";right$("0"& BSTR$(M,16),2);
PRINT TAB(14);"offset: 0x";BSTR$(byt-2,16)
!---
IF BVAL("D0",16)<=M AND M<=BVAL("D7",16) THEN ! RSI_0~7 in Picture data
ELSEIF M=BVAL("D8",16) THEN ! SOI
LET SOSn=0
MAT AhAl=(-1)*CON
ELSEIF M=BVAL("D9",16) THEN ! EOI
EXIT DO ! close#1, exit sub
ELSE
!---segment size
CHARACTER INPUT #1 :D$
LET w=ORD(D$)
CHARACTER INPUT #1 :D$
LET N=w*256+ORD(D$)-2 ! N=remain size
PRINT right$("000"& BSTR$(N+2,16),4);" size"
LET byt=byt+2 !offset counter
!---
IF M=BVAL("E0",16) THEN ! APP0
CALL FFE0_lst
ELSEIF M=BVAL("DB",16) THEN ! DQT
CALL FFDB_lst
ELSEIF m$(M)(6:8)="SOF" THEN ! SOF0~3 SOF5~7 SOF9~11 SOF13~15
CALL FFCx_lst
ELSEIF M=BVAL("C4",16) THEN ! DHT
CALL FFC4_lst
ELSEIF M=BVAL("DD",16) THEN ! DRI
CALL readD(N)
PRINT d(1)*256+d(2);"(decimal)"
ELSEIF M=BVAL("DA",16) THEN ! SOS
CALL FFDA_lst
!---
PRINT
PRINT "Image data, offset: 0x";BSTR$(byt,16)
LET ff0=0
ELSE
CALL skip_(N)
END IF
END IF
END IF
LOOP
CLOSE #1
PRINT
END SUB
!-----
SUB FFE0_lst ! APP0
CALL readW$(5)
PRINT q$;w$(1:4);q$ !"JFIF" ,00h
CALL readD(N-5)
IF w$(1:4)="JFIF" THEN
PRINT right$("0"& BSTR$(d(1),16),2);" ";right$("0"& BSTR$(d(2),16),2);
PRINT TAB(13);"Ver ";STR$(d(1));".";STR$(d(2))
PRINT right$("0"& BSTR$(d(3),16),2);" (0=No_unit 1=dot/inch 2=dot/cm)"
LET i=d(4)*256+d(5)
PRINT right$("000"& BSTR$(i,16),4);" ";i;"Xd アスペクト比" ! IE6(no_efect), imaging(active)
LET i=d(6)*256+d(7)
PRINT right$("000"& BSTR$(i,16),4);" ";i;"Yd アスペクト比"
PRINT right$("0"& BSTR$(d(8),16),2);" ";d(8);"Xt"
PRINT right$("0"& BSTR$(d(9),16),2);" ";d(9);"Yt"
FOR i=1 TO d(8)*d(9) ! (RGB)pixel*Xt*Yt
PRINT BSTR$(d(9+i)*65536+d(10+i)*256+d(11+i),16);" "
NEXT i
ELSEIF w$(1:4)="JFXX" THEN
PRINT BSTR$(d(1),16);" extension_code"
ELSE
PRINT "unknown file"
beep
STOP
END IF
END SUB
SUB FFDB_lst ! DQT
LET i=1
DO
CHARACTER INPUT #1 :D$
LET byt=byt+1 !offset counter
LET d(i)=ORD(D$)
LET w=IP(d(i)/16) !0=8bit 1=16bit
LET i=i+1
FOR s=0 TO 63
CHARACTER INPUT #1 :D$
LET byt=byt+1 !offset counter
LET j=ORD(D$)
IF w=1 THEN
CHARACTER INPUT #1 :D$
LET byt=byt+1 !offset counter
LET j=j*256+ORD(D$)
END IF
LET d( i+V(s)*8+U(s) )=j
NEXT s
LET i=i+s*(1+w)
LOOP UNTIL N< i
!---
LET i=1
DO
PRINT right$("0"& BSTR$(d(i),16),2);" (byte=0 word=1| QT_0~3)";
LET w$=""
LET j=i+1
FOR i=i+1 TO i+64
IF MOD(i-j,8)=0 THEN LET w$=w$& crlf$& " "
LET w$=w$& right$(REPEAT$(" ",3+w*2)& STR$(d(i)),4+w*2)
NEXT i
LET i=i+64*w
PRINT w$
LOOP UNTIL N< i
END SUB
SUB FFCx_lst ! SOF0~3 SOF5~7 SOF9~11 SOF13~15
CALL readD(N)
PRINT right$("0"& BSTR$(d(1),16),2);" precision_8~12bits in RGB source"
PRINT right$("0"& BSTR$(d(2),16),2);" ";right$("0"& BSTR$(d(3),16),2);" V.pix=";d(2)*256+d(3)
PRINT right$("0"& BSTR$(d(4),16),2);" ";right$("0"& BSTR$(d(5),16),2);" H.pix=";d(4)*256+d(5)
PRINT right$("0"& BSTR$(d(6),16),2);" number_in_flame_1~255"
FOR i=7 TO 7+3*(d(6)-1) STEP 3
LET co=(i-7)/3 !co_0~2= Ybr_0~2
LET CoID(d(i))=co !CoID( ID_0~255 )= co_0~2
PRINT right$("0"& BSTR$(d(i),16),2);" ";BSTR$(d(i+1),16);" ";BSTR$(d(i+2),16);" ID_0~255 (H|V)MCU QT …"& Ybr$(co)
LET QS(co)=d(i+2) !QT.numb= QS(co)
NEXT i
END SUB
SUB FFC4_lst ! DHT
CALL readD(N)
LET i=1
DO
PRINT right$("0"& BSTR$(d(i),16),2);" (DC=0 AC=1| HT_0~3)";
LET i=i+1
LET w=16
CALL dumph(i,w,16) ! d(i)~w bytes, return with(i=i+w, w=sum_d(i) )
CALL dumph(i,w,16) ! d(i)~w bytes, return with(i=i+w, w=sum_d(i) )
PRINT
LOOP UNTIL N< i
END SUB
!Page-2 へ続く
-
- [10]
Page-2
- 投稿者:SECOND
- 投稿日:2009年12月17日(木)03時43分35秒
-
-
!Page-2 の始め
SUB dumph(i,w,h) ! d(i)~w bytes, return with(i=i+w, w=sum_d(i) )
LET w$=""
LET j=i
FOR i=i TO i+w-1
IF MOD(i-j,h)=0 THEN LET w$=w$& crlf$& " " !right end, left end
LET w$=w$& " "& right$("0"& BSTR$(d(i),16),2) !Value.Table
IF i=j THEN LET w=d(i) ELSE LET w=w+d(i)
NEXT i
PRINT w$;
END SUB
SUB FFDA_lst !SOS
CALL readD(N)
LET SOSn=SOSn+1
PRINT right$("0"& BSTR$(d(1),16),2);" number_in_scan_1~4"
LET AhAl( SOSn,0)=d(N-2)*256+d(N-1)
FOR i=2 TO N-3 STEP 2
PRINT right$("0"& BSTR$(d(i),16),2);" ";right$("0"& BSTR$(d(i+1),16),2);" ID_0~255 (DC.HT_0~3|AC.HT_0~3) …"& Ybr$(CoID(d(i)))
LET AhAl( SOSn, CoID(d(i))+1 )=d(N) ! Ybr_0~2=CoID( ID_0~255 )
NEXT i
PRINT right$("0"& BSTR$(d(N-2),16),2);" ";right$("0"& BSTR$(d(N-1),16),2);" ";right$("0"& BSTR$(d(N),16),2);" Ss Se (Ah|Al)"
END SUB
SUB skip_(N)
FOR i=1 TO N
CHARACTER INPUT #1 :D$
NEXT i
LET byt=byt+N !offset counter
END SUB
SUB readD(N)
FOR i=1 TO N
CHARACTER INPUT #1 :D$
LET d(i)=ORD(D$)
NEXT i
LET byt=byt+N !offset counter
END SUB
SUB readW$(N)
LET w$=""
FOR i=1 TO N
CHARACTER INPUT #1 :D$
PRINT right$("0"& BSTR$(ORD(D$),16),2);" ";
LET w$=w$& D$
NEXT i
LET byt=byt+N !offset counter
END SUB
DATA "FFC0 SOF0" ,"FFC1 SOF1" ,"FFC2 SOF2" ,"FFC3 SOF3"
DATA "FFC4 DHT" ,"FFC5 SOF5" ,"FFC6 SOF6" ,"FFC7 SOF7"
DATA "FFC8 JPG" ,"FFC9 SOF9" ,"FFCA SOF10","FFCB SOF11"
DATA "FFCC DAC" ,"FFCD SOF13","FFCE SOF14","FFCF SOF15"
DATA "FFD0 RST0" ,"FFD1 RST1" ,"FFD2 RST2" ,"FFD3 RST3"
DATA "FFD4 RST4" ,"FFD5 RST5" ,"FFD6 RST6" ,"FFD7 RST7"
DATA "FFD8 SOI" ,"FFD9 EOI" ,"FFDA SOS" ,"FFDB DQT"
DATA "FFDC DNL" ,"FFDD DRI" ,"FFDE DHP" ,"FFDF EXP"
DATA "FFE0 APP0" ,"FFE1 APP1" ,"FFE2 APP2" ,"FFE3 APP3"
DATA "FFE4 APP4" ,"FFE5 APP5" ,"FFE6 APP6" ,"FFE7 APP7"
DATA "FFE8 APP8" ,"FFE1 APP9" ,"FFE2 APP10","FFE3 APP11"
DATA "FFEC APP12","FFE5 APP13","FFE6 APP14","FFE7 APP15"
DATA "FFF0 JPG0" ,"FFF1 JPG1" ,"FFF2 JPG2" ,"FFF3 JPG3"
DATA "FFF4 JPG4" ,"FFF5 JPG5" ,"FFF6 JPG6" ,"FFF7 JPG7"
DATA "FFF8 JPG8" ,"FFF9 JPG9" ,"FFFA JPG10","FFFB JPG11"
DATA "FFFC JPG12","FFFD JPG13","FFFE COM" ,"FFFF "
DATA "Y ","Cb","Cr"
SUB zigzag
DIM U(63),V(63) !zigzag
FOR V_=0 TO 7
FOR U_=0 TO 7
READ i
LET U(i)=U_
LET V(i)=V_
NEXT U_
NEXT V_
DATA 0, 1, 5, 6,14,15,27,28
DATA 2, 4, 7,13,16,26,29,42
DATA 3, 8,12,17,25,30,41,43
DATA 9,11,18,24,31,40,44,53
DATA 10,19,23,32,39,45,52,54
DATA 20,22,33,38,46,51,55,60
DATA 21,34,37,47,50,56,59,61
DATA 35,36,48,49,57,58,62,63
END SUB
END
-
- [11]
GIF ファイルの解析ツール Ver.22(画像付)
- 投稿者:SECOND
- 投稿日:2009年12月17日(木)09時51分44秒
-
-
! GIF ファイルの解析ツール Ver.22(画像付)
!-------
!先の投稿 http://6317.teacup.com/basic/bbs/bbs?M=RAL&&CID=464 では、
!大きな GIF ファイルの処理速度が、あまりに遅くなっていくので、
!一括処理を止め、細切れに処理するようにし、処理速度が同じ速さを保てる
!ようにしたものです。少し読み難い。
!
! Disposal Method 0,1,2,3 、インタレース画像、GIF アニメ動画などを、
! BASIC 文だけで、シンボリック・ダンプと、画像化を行います。
OPTION CHARACTER BYTE
LET bitfull=12 ! LZW max.bits (~~ 12)
DIM dic$(0 TO 2^bitfull) ! decoder 辞書
!
FILE GETNAME file$, "gif"
IF file$="" THEN
PRINT "入力ファイル名が、ありません。"
STOP
END IF
!
PRINT "入力ファイル:"& file$
OPEN #1: NAME file$, ACCESS INPUT
PRINT "---------"
SET COLOR mode "native"
DIM ncp(0 TO 256) ! native color palette
LET ncp(256)=BVAL("eeeedd",16) ! 256= システム背景色 BGR
SET AREA COLOR ncp(256)
PLOT AREA: 0,0;1,0;1,1;0,1
CALL gif_head
LET i=MAX( Xsw,Ysw )
SET WINDOW -.1*i,1.1*i, 1.1*i,-.1*i
SET LINE STYLE 3
PLOT LINES:-1,-1;Xsw+.5,-1;Xsw+.5,Ysw+.5;-1,Ysw+.5;-1,-1
DIM m(0 TO Xsw-1,0 TO Ysw-1), m3(0 TO Xsw-1,0 TO Ysw-1)
MAT m=ncp(256)*CON
DO
CALL blocks_main
LOOP UNTIL b1$=CHR$(BVAL("3B",16))
PRINT "GIF 終端ブロック"
CALL dump(b1$,2,"block label")
PRINT "---------"
CLOSE #1
!----
SUB gif_head
LET h$=""
CALL readb( h$,13 )
IF h$(1:3)="GIF" THEN PRINT "GIF ヘッダー" ELSE CALL error
LET Xsw= ORD(h$( 8: 8))*256+ORD(h$(7:7))
LET Ysw= ORD(h$(10:10))*256+ORD(h$(9:9))
LET sflg=ORD(h$(11:11)) ! スクリーン情報のフラグ
LET BGco=ORD(h$(12:12))
LET aspect=ORD(h$(13:13))
LET b$=right$("0000000"& BSTR$(sflg,2) ,8)
LET colpix=2^(BVAL(b$(2:4),2)+1)
LET compal=2^(BVAL(b$(6:8),2)+1)
CALL dump(h$( 1: 6),6,"Asc") ! GIF識別文字
CALL dump(h$( 7: 8),2,"screen X_width= "& STR$(Xsw))
CALL dump(h$( 9:10),2,"screen Y_width= "& STR$(Ysw))
CALL dump(h$(11:11),2,"flags= "& b$ )
PRINT TAB(13);b$(1:1);":common_palette on=1/off=0"
PRINT TAB(11);b$(2:4);":colors/pixel 2^(";b$(2:4);"b+1)= ";STR$(colpix)
PRINT TAB(13);b$(5:5);":sort on=1/off=0 パレットの、重要度 色順ソート"
PRINT TAB(11);b$(6:8);":common_palette colors 2^(";b$(6:8);"b+1)= ";STR$(compal)
CALL dump(h$(12:12),2,"back_ground color= "& STR$(BGco))
IF aspect=0 THEN LET b$=".." ELSE LET b$=STR$(aspect)
CALL dump(h$(13:13),2,"アスペクト比 H:V=, 0 は 1:1 その他("& b$& "+15):64" )
CALL palette("common_パレット", c_p$, sflg)
END SUB
!----
SUB blocks_main
LET b1$=""
CALL readb( b1$, 1)
IF b1$=CHR$(BVAL("21",16)) THEN !追加データ・ブロック
CALL option_block
ELSEIF b1$=CHR$(BVAL("2C",16)) THEN !画像ブロック
CALL picture_block
ELSEIF b1$=CHR$(BVAL("3B",16)) THEN !GIF 終端ブロック
ELSE
CALL error
END IF
END SUB
!---追加データ・ブロック。
SUB option_block
PRINT "追加データ・ブロック"
CALL readb( b1$,1) ! w9$= readb_last_byte
IF w9$=CHR$(BVAL("F9",16)) THEN
LET im$=b1$
CALL dump(im$,2,"イメージコントロール・ブロック")
CALL blocks(im$,0,"",1) ! non print (data, byte/行, 注釈, 要求blocks)
LET iflg=ORD(im$(4:4)) ! フラグ
LET imtm=ORD(im$(6:6))*256+ORD(im$(5:5))
LET tcol=ORD(im$(7:7))
LET b$=right$("0000000"& BSTR$(iflg,2),8)
LET t_on=VAL(b$(8:8))
LET tmod=BVAL(b$(4:6),2)
CALL dump(im$(4:4),2,"flags= "& b$ )
PRINT TAB(11);b$(1:3);":blank"
PRINT TAB(11);b$(4:6);":"
PRINT TAB(15);"000= 描画後、そのまま、次の背景へ渡す"
PRINT TAB(15);"001= 描画後、そのまま、次の背景へ渡す"
PRINT TAB(15);"010= 描画後、back_ground color と取替、次の背景へ渡す"
PRINT TAB(15);"011= 描画後、描画前の画像を、次の背景へ渡す"
PRINT TAB(13);b$(7:7);":user click on=1/off=0"
PRINT TAB(13);b$(8:8);":透明色のスイッチ on=1/off=0"
CALL dump(im$(5:6),2,"フレーム表示時間= "& STR$(imtm)& " x10ms" )
CALL dump(im$(7:7),2,"透明色= "& STR$(tcol) )
CALL blocks(im$,16,"",999) ! (data, byte/行, 注釈, 要求blocks)
ELSEIF w9$=CHR$(BVAL("FE",16)) THEN
LET co$=b1$
CALL dump(co$,2,"コメント・ブロック")
CALL blocks(co$,8,"Asc",999) ! (data, byte/行, 注釈, 要求blocks)
ELSEIF w9$=CHR$(BVAL("FF",16)) THEN
LET ap$=b1$
CALL dump(ap$,2,"アプリケーション・ブロック")
CALL blocks(ap$,8,"Asc",1) ! (data, byte/行, 注釈, 要求blocks)
IF ap$(4:11)="NETSCAPE" THEN
CALL blocks(ap$,0,"",1) ! non print (data, byte/行, 注釈, 要求blocks)
CALL dump(ap$(16:16),2,"extension code= 01~07 next data type")
IF MOD(ORD(ap$(16:16)),8)=1 THEN
LET rept=ORD(ap$(18:18))*256+ORD(ap$(17:17))
CALL dump(ap$(17:18),2,"繰返し回数= "& STR$(rept)& " (0=endless)")
ELSE
CALL dump(ap$(17:LEN(ap$)),2,"02= 32bit buffering size, 03~07= ?")
END IF
END IF
CALL blocks(ap$,8,"Asc",999) ! (data, byte/行, 注釈, 要求blocks)
ELSEIF w9$=CHR$(BVAL("01",16)) THEN
LET tx$=b1$
CALL dump(tx$,2,"テキスト・イメージ・ブロック")
CALL blocks(d$,8,"Asc",999) ! (data, byte/行, 注釈, 要求blocks)
ELSE
CALL error
END IF
END SUB
!-------
SUB blocks(d$,m,t$,n) ! d$=data, m=byte/行, t$=注釈, n=要求blocks
FOR n=1 TO n
CALL readb(d$,1) ! w9$= readb_last_byte ! =block Size
CALL dump(w9$,1,"block size")
IF w9$=CHR$(0) THEN EXIT SUB ! block End
LET s=LEN(d$)
CALL readb(d$,ORD(w9$)) ! block data
IF 0< m THEN CALL dump(d$(s+1:LEN(d$)),m,t$)
NEXT n
END SUB
SUB readb(d$,cx) !cx=bytes size
FOR i=1 TO cx
CHARACTER INPUT #1,IF MISSING THEN EXIT FOR :w9$
LET d$=d$& w9$
NEXT i
IF i<=cx THEN CALL error
END SUB
SUB dump(d$,m,t$) ! t$="comment" →;comment t$="Asc" →;"ascii.dump"
FOR j=1 TO LEN(d$) STEP m
LET ww$=right$("0000"& BSTR$(adr,16),5)& " "
FOR i=j TO MIN(j+m-1, LEN(d$))
LET ww$=ww$& " "& right$("0"& BSTR$( ORD(d$(i:i)),16),2)
LET adr=adr+1
NEXT i
IF t$>"" THEN
LET ww$=ww$& REPEAT$(" ",6+3*m-LEN(ww$))
IF t$="Asc" THEN ! ascii.dump
LET ww$=ww$& " ;"""
FOR i=j TO MIN(j+m-1, LEN(d$))
IF " "<=d$(i:i) THEN LET ww$=ww$& d$(i:i) ELSE LET ww$=ww$& "."
NEXT i
LET ww$=ww$& """"
ELSE
IF m=3 THEN LET ww$=ww$& " ;"& STR$(IP(j/3)) ! パレット色番号
IF j=1 THEN LET ww$=ww$& " ;"& t$ ! comment
END IF
END IF
PRINT ww$ ! 行単位、テキスト画面のピカつき減少、高速。
NEXT j
END SUB
!-------
SUB picture_block
PRINT "画像ブロック"
LET pi$=b1$
CALL readb( pi$,9)
CALL dump(pi$(1:1),2,"block label")
LET Xp0=ORD(pi$(3:3))*256+ORD(pi$(2:2))
LET Yp0=ORD(pi$(5:5))*256+ORD(pi$(4:4))
LET Xpw=ORD(pi$(7:7))*256+ORD(pi$(6:6))
LET Ypw=ORD(pi$(9:9))*256+ORD(pi$(8:8))
CALL dump(pi$(2:3),2,"picture.X0_position left= "& STR$(Xp0))
CALL dump(pi$(4:5),2,"picture.Y0_position top= "& STR$(Yp0))
CALL dump(pi$(6:7),2,"picture.X_width= "& STR$(Xpw))
CALL dump(pi$(8:9),2,"picture.Y_width= "& STR$(Ypw))
LET pflg=ORD(pi$(10:10)) ! 画像情報のフラグ
LET b$=right$("0000000"& BSTR$(pflg,2),8)
CALL dump(pi$(10:10),2,"flags= "& b$ )
LET interl=VAL(b$(2:2))
LET pripal=2^(BVAL(b$(6:8),2)+1)
PRINT TAB(13);b$(1:1);":private_palette on=1/off=0"
PRINT TAB(13);b$(2:2);":interlace on=1/off=0, 1~step8 5~step8 3~step4 2~step2"
PRINT TAB(13);b$(3:3);":sort on=1/off=0 パレットの、重要度 色順ソート"
PRINT TAB(12);b$(4:5);":blank"
PRINT TAB(11);b$(6:8);":private_palette colors 2^(";b$(6:8);"b+1)= ";STR$(pripal)
CALL palette("private_パレット", p_p$, pflg)
!---
PRINT "画像データ"
LET LZW$=""
CALL readb( LZW$,1)
CALL dump(LZW$,1,"最小データ・ビット長")
CALL decomp_data
END SUB
!Page-2 へ続く
-
- [12]
Page-2
- 投稿者:SECOND
- 投稿日:2009年12月17日(木)09時53分33秒
-
-
!Page-2 の始め
SUB palette(n$, p$, pf)
PRINT n$;
LET p$=""
IF IP(pf/128)>0 THEN ! pf AND 0x80
PRINT
CALL readb(p$, 3*2^(MOD(pf,8)+1)) ! pf AND 0x07
CALL dump(p$,3,"R G B")
CALL palette10(n$, p$, pf)
ELSE
LET ww$=" 無し。"
IF n$(1:1)="p" AND c_p$>"" THEN
LET ww$=ww$& "→ common_パレット 使用。"
IF bk_p$(1:1)<>"c" THEN CALL palette10("common", c_p$, sflg)
END IF
PRINT ww$
END IF
END SUB
SUB palette10(n$, p$, pf)
FOR i=1 TO 3*2^(MOD(pf,8)+1) STEP 3
LET ncp(IP(i/3))= ORD(p$(i:i))+256*ORD(p$(i+1:i+1))+65536*ORD(p$(i+2:i+2))
NEXT i
LET bk_p$=n$
END SUB
SUB error
beep
PRINT "File Error Stop"
STOP
END SUB
!------------------- 画像データ LZW$ から、原画を見る。------------------
SUB decomp_data
LET obits0=ORD(LZW$(1:1))
LET N000=2^obits0
LET li=2 !start input pointer
LET blkend=0 !clear input block pointer
LET iacc$="" !clear input bit buffer
LET pdata$="" !clear output byte buffer
!---
IF tmod=3 THEN MAT m3=m
LET p_=1
IF interl=0 THEN
CALL intlace( 0, 1) ! start_raster, step !---NO interlace
ELSE
CALL intlace( 0, 8) ! start_raster, step !---0~7step8
WAIT DELAY .5
CALL intlace( 4, 8) ! start_raster, step !---4~7step8
WAIT DELAY .5
CALL intlace( 2, 4) ! start_raster, step !---2~3step4
WAIT DELAY .5
CALL intlace( 1, 2) ! start_raster, step !---1~1step2
END IF
IF tmod=2 THEN MAT m=ncp(256)*CON ! 256= システム背景色
IF tmod=3 THEN MAT m=m3
PRINT "******************* 復元終り"
END SUB
SUB intlace( ss, stp)
FOR j_=Yp0 TO Yp0+Ypw-1
IF MOD(j_-Yp0, stp) >=ss THEN
IF MOD(j_-Yp0, stp) >ss THEN LET p_=p_-Xpw
!---
IF LEN(pdata$)-Xpw< p_ THEN
LET pdata$=pdata$(p_:LEN(pdata$))
CALL LZW_decoder
LET p_=1
END IF
!---
FOR i_=Xp0 TO Xp0+Xpw-1
WHEN EXCEPTION IN
LET col=ORD(pdata$(p_:p_))
IF t_on<>1 OR tcol<>col THEN LET m(i_,j_)=ncp(col)
LET p_=p_+1
USE
END WHEN
NEXT i_
END IF
NEXT j_
MAT PLOT CELLS,IN 0,0; Xsw-1,Ysw-1 :m
END SUB
!-------------
SUB LZW_decoder
DO
LET dicnum=N000+2-1 !start dic.number-1
DO
LET iwidth=LEN( BSTR$(dicnum,2) ) !remake iwidth
IF bitfull< iwidth THEN LET iwidth=bitfull !to handle BAD file
LET dicnum=dicnum+1
CALL inpcode !data on bx
IF bx=-1 OR bx=N000+1 THEN
EXIT SUB
ELSEIF bx=N000 THEN
EXIT DO
ELSE
IF bx< N000 THEN
LET dic$(dicnum)=CHR$(bx)
ELSE
LET dic$(dicnum)=dic$(bx)
LET dic$(dicnum)=dic$(dicnum)& dic$(bx+1)(1:1)
END IF
LET pdata$=pdata$& dic$(dicnum)
END IF
LOOP
IF Xpw< LEN(pdata$) THEN EXIT SUB
LOOP
END SUB
SUB inpcode
LET bx=-1
DO WHILE LEN(iacc$)< iwidth
IF blkend<=li THEN
!--- LZW データ(size:data, size:data, … 0 )
IF LEN(LZW$)< li THEN
IF 2< li THEN PRINT "******************* 復元休止"
LET LZW$=""
CALL blocks(LZW$,16,"",8) ! (data, byte/行, 注釈, 要求blocks)
LET li=1
PRINT "******************* 復元( LZW デコード )"
END IF
!---
LET blksize=ORD(LZW$(li:li))
CALL prthex(CHR$(blksize),"block size") !モニター
IF blksize=0 THEN EXIT SUB
LET li=li+1
LET blkend=li+blksize
END IF
LET iacc$=right$("0000000"& BSTR$(ORD(LZW$(li:li)),2),8)& iacc$
LET li=li+1
LOOP
LET bx=BVAL(right$(iacc$,iwidth),2)
LET iacc$=iacc$(1:LEN(iacc$)-iwidth)
END SUB
SUB prthex(d$,w$)
LET ww$=""
FOR i9=1 TO LEN(d$)
LET ww$=ww$& right$("0"& BSTR$(ORD(d$(i9:i9)),16),2)& " "
NEXT i9
IF w$>"" THEN LET ww$=ww$& "; "& w$
PRINT ww$
END SUB
END
!関連投稿(1ページ未満)
![メインスレッド458] GIF アニメ-ション を作る。
![メインスレッド460] LZW エンコーダーと、デコーダー
-
- [13]
FFT プログラム
- 投稿者:SECOND
- 投稿日:2010年 3月25日(木)05時05分48秒
-
-
DEBUG ON
!******************************************************************
! FFT プログラム
!******************************************************************
!------------------------------------------------------------------------------
! デジタルでのフーリエ変換。 逆変換。
!
! ◆DFT Discrete Fourier Transform ◆IDFT Inverse Discrete Fourier Transform
!
! N-1 N-1
! F(k)= ∑X(r)*exp(-j2π* k*r/N ) X(r)= ( 1/N )* ∑F(k)*exp( j2π* r*k/N )
! r=0 k=0
!
! ※k= 0~N-1 ※r= 0~N-1
!
!------------------------------------------------------------------------------
! DFT が N個の周期波を扱う場合は、その高速算法がある。
! Cooley-Tukey(クーリー・テューキー)型 Fast Fourier Transform
!
! 入力信号の番号を、奇数 偶数の 時間間引き 2分割にする方法と、
! 出力信号の番号を、奇数 偶数の 周波数間引き2分割にする方法の、2通り。
!
! 周期 N の DFT 計算量は、N*N 個の積和であるが、N/2 個の DFT 2つに
! 分ける事が出来れば、(N/2)*(N/2) 個の積和2つになって、ざっとみても
! 1回で、半分に計算量が減る。これを、限界まで進めたもの。
! ( N=512 程度の実用サイズで、計算量が 約1/100 に。詳細は、以下)
!----------------------------------------
! FFT 部分の初期設定
!----------------------------------------
OPTION ARITHMETIC COMPLEX
OPTION BASE 0
!
LET N1=8
LET N1=16
!LET N1=32
!LET N1=64
!LET N1=128
!LET N1=256
!LET N1=512
!LET N1=1024
!LET N1=2048
!LET N1=4096
!LET N1=65536
!
DIM Z(N1*2) !FFT 信号入力、変換出力を、Z() 配列だけの双方向で行なう。
! !データは N1 個であるが、ビットリバースを使わない型だけが、
! !同じサイズの後部余白を、必要とする。Clear は不要。
!
DIM ZO(N1*2) !DFT だけが使用。
!
DIM W19(N1)
LET W2=2*PI/N1
FOR I=0 TO N1
LET w19(I)=EXP(COMPLEX(0,W2*I))
NEXT I
!------------------------------------------------------------------------------
! ◆ 時間間引き型 Decimation In Time
!
! 入力番号を、奇数 偶数の 時間間引き2分割、出力番号を、連続の周波数2分割
! とした 2つの DFT が、合計で、元の DFT と同じになる様に、書くと、
!
! ※W( a/b )=exp(-j2π *a/b )
! N/2-1 N/2-1
! F(k) = ∑X(2r)*W( k*2r/N ) + ∑X(2r+1)*W( k*(2r+1)/N ) ・・・①
! r=0 r=0
! ※k= 0~N/2-1
! N/2-1 N/2-1
! F(k+N/2)= ∑X(2r)*W( (k+N/2)*2r/N ) + ∑X(2r+1)*W( (k+N/2)*(2r+1)/N ) ・・・②
! r=0 r=0
!
!------------------------------------------------------------------------------
! 上の式を、それぞれ整理したもの。 ※W( 整数 )=1, W( 整数+0.5 )=-1
!
! N/2-1 N/2-1
! F(k) = ∑X(2r)*W( k*r/(N/2) ) + W(k/N)*∑X(2r+1)*W( k*r/(N/2) ) ・・・①'
! r=0 r=0
! ※k= 0~N/2-1
! N/2-1 N/2-1
! F(k+N/2)= ∑X(2r)*W( k*r/(N/2) ) - W(k/N)*∑X(2r+1)*W( k*r/(N/2) ) ・・・②'
! r=0 r=0
!
!------------------------------------------------------------------------------
! 半分ずつの X(2r) と X(2r+1) それぞれを新しい入力
! とする 基数=N/2 のDFT 出力の合成になっている。
! この DFT も、さらに2分割し、入れ子構造にしていく。
!
! 2分割を、N(基数)=2 、入力側が、基数=1 の DFT 出力になるまで繰返すと、
! 下の様になる。 ※添え字は、N(基数)=2 の DFT を基準に付け直している。
!
! 基数=1 の出力とは、入力それ自身なので、
! 入力 X(0) X(1) を直接、基数=1 の DFT 出力とみなせる。結果、F(0)=X(0)+X(1)
! F(1)=X(0)-X(1)
! となって、これは、N(基数)=2 のまま、DFT 変換する状況とも同一になる。
! 結局、FFT は、殆どDFT 計算を、しないまま分割だけで、その結果を得ている。
!
! 0 0
! F(0)= ∑X(0)*W(0/1) + W(0/2)*∑X(1)*W(0/1) ・・・①'
! r=0 r=0
!
! 0 0
! F(1)= ∑X(2r)*W(0/1) - W(0/2)*∑X(1)*W(0/1) ・・・②'
! r=0 r=0
!
!------------------------------------------------------------------------------
! 実際のプログラム
!
! ◆ 時間間引き型 Decimation In Time
! N(基数)=8 の場合の例。 数式は右端から、(← 方向)へ2分割を繰返すが、
! 実計算は左端から、(→ 方向)へ
! ※ Wa/b はexp(-j2π*a/b)を乗ずる意。W1/4 は右へ1/4 回転。W1/8 は右へ1/8回転。
! ① は負号を付ける意。 ╋ は加算の意。
!
! 入力信号の順を、番号の上位下位ビットを逆に読む順 (Index Bit Reverse) に入替る。
! ↓
! X0 X0 F0 F0 F0
! ────┬─╋─────┬────╋─────┬──────────╋─
! → \/ \ / \ /
! X1 X4 W0/2 /\ F4 \ / F2 \ / F1
! ────┴①╋─────┬────╋─────┬──────────╋─
! \/ \/ \ \ / /
! X2 X2 F2 W0/4 /\ /\ F4 \ \ / / F2
! ────┬─╋─────┴───①╋─────┬──────────╋─
! \/ / \ \ \/ \/ /
! X3 X6 W0/2 /\ F6 W1/4 / \ F6 \ /\ /\ / F3
! ────┴①╋─────┴───①╋─────┬──────────╋─
! \/ \/ \/ \/
! X4 X1 F1 F1 W0/8 /\ /\ /\ /\ F4
! ────┬─╋─────┬────╋─────┴─────────①╋─
! \/ \ / / \/ \/ \
! X5 X5 W0/2 /\ F5 \ / F3 W1/8 / /\ /\ \ F5
! ────┴①╋─────┬────╋─────┴─────────①╋─
! \/ \/ / / \ \
! X6 X3 F3 W0/4 /\ /\ F5 W2/8 / / \ \ F6
! ────┬─╋─────┴───①╋─────┴─────────①╋─
! \/ / \ / \
! X7 X7 W0/2 /\ F7 W1/4 / \ F7 W3/8 / \ F7
! ────┴①╋─────┴───①╋─────┴─────────①╋─
! ┠基数2のDFT─╂←─ ネスト(Nested)された周波数出力の2分割の重ね ─→┨
!
!
! 計算プログラムは、和と差の1対 の繰返しであり、同じ処理で実行するには、
! 各段の計算結果が、次段の計算の入力にもなるため、同じ場所に書き戻す必要があった。
!
! X0~,F0~ の添え字を、直接の物理アドレスとして、配列を組むと、書き込む前に有った
! データーが使用される前に、上書きされてしまう不都合が発生する。その解決に、
!
! X0~,F0~ の添え字を、論理アドレスとして無視、図の上から下への配置を物理アドレス
! として、配列を用いる計算方法をとる。その為には、
!
! 左の入力信号内容 X0~ を、X0,X4,X2,, の順に入換えておかなければならない。
! この操作を、Index Bit Reverse と呼ぶ。
!
! X0~,F0~ の添え字を、直接の物理アドレスとしても、上書されないように出来れば、
! Index Bit Reverse は、不要なので、その例を最後に紹介する。
!
!---------INDEX BIT REVERSE----
SUB IBrev ! Z() を、その添え字 番号の上位下位ビット順が、
LET J=0 ! 逆になった番号 の位置に並べ替える。
LET N2=N1/2
FOR I=0 TO N1-2
IF I< J THEN swap Z(J),Z(I)
!----- J=000.. 100.. 010.. 110..ビット逆順のUPカウンター
LET K=N2 !K の初期値、100... 最上位ビットだけの数
DO WHILE K<=J !J の K ビット位置が 1 である場合。
LET J=J-K !J の桁上りの為、そのビットを消す
LET K=K/2 !K を、次のビットへ。
LOOP !J の K ビット位置が 0 で loop を出る。
LET J=J+K !J の K ビット位置に 1 を置く
!-----
NEXT I
END SUB
!=========================================
! 高速フーリエ変換 Fast Fourier Transform
! 時間間引き型 DIT (Decimation In Time)
!
SUB FFT_DIT
CALL IBrev !Index Bit Reverse
!-------------
!CALL ref_DIT(0,N1) !再帰型
CALL normal_DIT !通常型(高速)
END SUB
!再帰型(通常型より約1.5倍に遅くなるが、簡潔。)
SUB ref_DIT(J,N)
IF 1< N THEN
CALL ref_DIT(J ,N/2)
CALL ref_DIT(J+N/2,N/2)
LET H=N1 !FFT: N1 IFFT: 0
FOR I=J TO J+N/2-1
LET IK=I+N/2
LET ZT=w19(H)*Z(IK)
LET Z(IK)=Z(I)-ZT !F(k)-Wk/N*F(k+N/2)
LET Z(I)= Z(I)+ZT !F(k)+Wk/N*F(k+N/2)
LET H=H-N1/N !FFT: -N1/N IFFT: +N1/N
NEXT I
END IF
END SUB
!----
!通常型(高速)
SUB normal_DIT
LET K=1
DO WHILE K< N1
LET H=N1 !FFT: N1 IFFT: 0
LET K2=K*2
LET D=N1/K2
FOR J=0 TO K-1
FOR I=J TO N1-1 STEP K2
LET IK=I+K
LET ZT=w19(H)*Z(IK)
LET Z(IK)=Z(I)-ZT !F(k)-Wk/N*F(k+N/2)
LET Z(I)= Z(I)+ZT !F(k)+Wk/N*F(k+N/2)
NEXT I
LET H=H-D !FFT: -D IFFT: +D
NEXT J
LET K=K2
LOOP
END SUB
!Page-2 へ続く
-
- [14]
Page-2
- 投稿者:SECOND
- 投稿日:2010年 3月25日(木)05時08分52秒
-
-
!Page-2 の始め
!=========================================
! 高速フーリエ 逆変換 Inverse Fast Fourier Transform
! 時間間引き型 DIT (Decimation In Time) と同文で、
! 回転子W だけを 逆回しにしたもの。内容は周波数間引きになる。
!
SUB IFFT_DIT
CALL IBrev !Index Bit Reverse
!-------------
!CALL ref_IDIT(0,N1) !再帰型
CALL normal_IDIT !通常型(高速)
!-------------
MAT Z=(1/N1)*Z
END SUB
!再帰型(通常型より約1.5倍に遅くなるが、簡潔。)
SUB ref_IDIT(J,N)
IF 1< N THEN
CALL ref_IDIT(J ,N/2)
CALL ref_IDIT(J+N/2,N/2)
LET H=0 !FFT: N1 IFFT: 0
FOR I=J TO J+N/2-1
LET IK=I+N/2
LET ZT=w19(H)*Z(IK)
LET Z(IK)=Z(I)-ZT !F(k)-Wk/N*F(k+N/2)
LET Z(I)= Z(I)+ZT !F(k)+Wk/N*F(k+N/2)
LET H=H+N1/N !FFT: -N1/N IFFT: +N1/N
NEXT I
END IF
END SUB
!----
!通常型(高速)
SUB normal_IDIT
LET K=1
DO WHILE K< N1
LET H=0 !FFT: N1 IFFT: 0
LET K2=K*2
LET D=N1/K2
FOR J=0 TO K-1
FOR I=J TO N1-1 STEP K2
LET IK=I+K
LET ZT=w19(H)*Z(IK)
LET Z(IK)=Z(I)-ZT !F(k)-Wk/N*F(k+N/2)
LET Z(I)= Z(I)+ZT !F(k)+Wk/N*F(k+N/2)
NEXT I
LET H=H+D !FFT: -D IFFT: +D
NEXT J
LET K=K2
LOOP
END SUB
!------------------------------------------------------------------------------
! ◆ 周波数間引き型 Decimation In Frequency
!
! 入力番号を、連続の時間2分割、出力番号を、奇数 偶数の 周波数間引き2分割
! とした 2つのDFTが、合計で、元のDFTと同じになる様に、書くと、
!
! ※W( a/b )=exp(-j2π *a/b )
! N/2-1 N/2-1
! F(2k) = ∑X(r)*W( 2k*r/N ) + ∑X(r+N/2)*W( 2k*(r+N/2)/N ) ・・・①
! r=0 r=0
! ※k= 0~N/2-1
! N/2-1 N/2-1
! F(2k+1)= ∑X(r)*W( (2k+1)*r/N ) + ∑X(r+N/2)*W( (2k+1)*(r+N/2)/N ) ・・・②
! r=0 r=0
!
!------------------------------------------------------------------------------
! 上の式を、それぞれ整理したもの。 ※W( 整数 )=1, W( 整数+0.5 )=-1
!
! N/2-1
! F(2k) = ∑( X(r)+X(r+N/2) ) *W( k*r/(N/2) ) ・・・①'
! r=0
! ※k= 0~N/2-1
! N/2-1
! F(2k+1)= ∑( X(r)-X(r+N/2) )*W(r/N) *W( k*r/(N/2) ) ・・・②'
! r=0
!
!------------------------------------------------------------------------------
! 半分ずつの X(r)+X(r+N/2) と ( X(r)-X(r+N/2) )*W(r/N) それぞれを新しい入力
! とする基数=N/2 のDFT 出力 2つになっている。
! この DFT も、さらに2分割し、入れ子構造にしていく。
!
! 2分割を、N(基数)=2 、和入力、差入力が、各々1つになるまで繰返すと、
! 下の様になる。 ※添え字は、N(基数)=2 の DFT を基準に付け直している。
!
! これは、基数=1 の DFT で、その入力自身が、その出力になり、
! 入力 X(0)+X(1), (X(0)-X(1))*W(0/2) を直接 DFT 出力とみなせる。
! 結果、F(0)=X(0)+X(1)
! F(1)=X(0)-X(1)
! となって、これは、N(基数)=2 のまま、DFT 変換する状況とも同一になる。
! 結局、FFT は、殆どDFT 計算を、しないまま、分割だけで、終っています。
!
! 0
! F(0)= ∑( X(0)+X(1) ) *W(0/1) ・・・①'
! r=0
!
! 0
! F(1)= ∑( X(0)-X(1) )*W(0/2) *W(0/1) ・・・②'
! r=0
!
!------------------------------------------------------------------------------
! 実際のプログラム
!
! ◆ 周波数間引き型 Decimation In Frequency
! N(基数)=8 の場合の例。 数式は左端から、(→ 方向)へ2分割を繰返す。
! 実計算も左端から、(→ 方向)へ
! ※ Wa/b はexp(-j2π*a/b)を乗ずる意。W1/4 は右へ1/4 回転。W1/8 は右へ1/8回転。
! ① は負号を付ける意。 ╋ は加算の意。
!
! 番号の上位下位ビットを逆に読む順 (Index Bit Reverse) に、出力信号の順を入替る。
! ↓
! X0 X0 X0 F0 F0
! ─┬──────────╋─────┬────╋─────┬─╋────
! \ / \ / \/ →
! X1 \ / X2 \ / X4 /\ W0/2 F4 F1
! ─┬──────────╋─────┬────╋─────┴①╋────
! \ \ / / \/ \/
! X2 \ \ / / X4 /\ /\ W0/4 X2 F2 F2
! ─┬──────────╋─────┴───①╋─────┬─╋────
! \ \/ \/ / / \ \/
! X3 \ /\ /\ / X6 / \ W1/4 X6 /\ W0/2 F6 F3
! ─┬──────────╋─────┴───①╋─────┴①╋────
! \/ \/ \/ \/
! X4 /\ /\ /\ /\ W0/8 X1 X1 F1 F4
! ─┴─────────①╋─────┬────╋─────┬─╋────
! / \/ \/ \ \ / \/
! X5 / /\ /\ \ W1/8 X3 \ / X5 /\ W0/2 F5 F5
! ─┴─────────①╋─────┬────╋─────┴①╋────
! / / \ \ \/ \/
! X6 / / \ \ W2/8 X5 /\ /\ W0/4 X3 F3 F6
! ─┴─────────①╋─────┴───①╋─────┬─╋────
! / \ / \ \/
! X7 / \ W3/8 X7 / \ W1/4 X7 /\ W0/2 F7 F7
! ─┴─────────①╋─────┴───①╋─────┴①╋────
!┠←─ ネスト(Nested)された時間域入力の2分割の重ね ─→╂基数2のDFT─┨
!
!
! 計算プログラムは、和と差の1対 の繰返しであり、同じ処理で実行するには、
! 各段の計算結果が、次段の計算の入力にもなるため、同じ場所に書き戻す必要があった。
!
! X0~,F0~ の添え字を、直接の物理アドレスとして、配列を組むと、書き込む前に有った
! データーが使用される前に、上書きされてしまう不都合が発生する。その解決に、
!
! X0~,F0~ の添え字を、論理アドレスとして無視、図の上から下への配置を物理アドレス
! として、配列を用いる計算方法をとる。その為には、
!
! 右の出力信号内容 F0,F4,F2,, を、最後に F0,F1,F2,, へ戻さなければならない。
! この操作を、Index Bit Reverse と呼ぶ。
!
! X0~,F0~ の添え字を、直接の物理アドレスとしても、上書されないように出来れば、
! Index Bit Reverse は、不要になるので、その例を最後に紹介する。
!
!=========================================
! 高速フーリエ変換 Fast Fourier Transform
! 周波数間引き型 DIF (Decimation In Frequency)
!
SUB FFT_DIF
!CALL ref_DIF(0,N1) !再帰型
CALL normal_DIF !通常型(高速)
!-------------
CALL IBrev !Index Bit Reverse
END SUB
!再帰型(通常型より約1.5倍に遅くなるが、簡潔。)
SUB ref_DIF(J,N)
IF 1< N THEN
LET H=N1 !FFT: N1 IFFT: 0
FOR I=J TO J+N/2-1
LET IK=I+N/2
LET ZT=Z(I)-Z(IK)
LET Z(I)=Z(I)+Z(IK) ! X(r)+X(r+N/2)
LET Z(IK)=ZT*w19(H) !( X(r)-X(r+N/2) )*Wr/N
LET H=H-N1/N !FFT: -N1/N IFFT: +N1/N
NEXT I
CALL ref_DIF(J ,N/2)
CALL ref_DIF(J+N/2,N/2)
END IF
END SUB
!----
!通常型(高速)
SUB normal_DIF
LET N2=N1
DO WHILE 1< N2
LET N11=N2
LET N2=N2/2
LET D=N1/N11
LET H=N1 !FFT: N1 IFFT: 0
FOR J=0 TO N2-1
FOR I=J TO N1-1 STEP N11
LET IK=I+N2
LET ZT=Z(I)-Z(IK)
LET Z(I)=Z(I)+Z(IK) ! X(r)+X(r+N/2)
LET Z(IK)=ZT*w19(H) !( X(r)-X(r+N/2) )*Wr/N
NEXT I
LET H=H-D !FFT: -D IFFT: +D
NEXT J
LOOP
END SUB
!Page-3 へ続く
-
- [15]
Page-3
- 投稿者:SECOND
- 投稿日:2010年 3月25日(木)05時11分12秒
-
-
!Page-3 の始め
!=========================================
! 高速フーリエ 逆変換 Inverse Fast Fourier Transform
! 周波数間引き型 DIF (Decimation In Frequency) と同文で、
! 回転子W だけを 逆回しにしたもの。内容は時間間引きになる。
!
SUB IFFT_DIF
!CALL ref_IDIF(0,N1) !再帰型
CALL normal_IDIF !通常型(高速)
!-------------
CALL IBrev !Index Bit Reverse
!-------------
MAT Z=(1/N1)*Z
END SUB
!再帰型(通常型より約1.5倍に遅くなるが、簡潔。)
SUB ref_IDIF(J,N)
IF 1< N THEN
LET H=0 !FFT: N1 IFFT: 0
FOR I=J TO J+N/2-1
LET IK=I+N/2
LET ZT=Z(I)-Z(IK)
LET Z(I)=Z(I)+Z(IK) ! X(r)+X(r+N/2)
LET Z(IK)=ZT*w19(H) !( X(r)-X(r+N/2) )*Wr/N
LET H=H+N1/N !FFT: -N1/N IFFT: +N1/N
NEXT I
CALL ref_IDIF(J ,N/2)
CALL ref_IDIF(J+N/2,N/2)
END IF
END SUB
!----
!通常型(高速)
SUB normal_IDIF
LET N2=N1
DO WHILE 1< N2
LET N11=N2
LET N2=N2/2
LET D=N1/N11
LET H=0 !FFT: N1 IFFT :0
FOR J=0 TO N2-1
FOR I=J TO N1-1 STEP N11
LET IK=I+N2
LET ZT=Z(I)-Z(IK)
LET Z(I)=Z(I)+Z(IK) ! X(r)+X(r+N/2)
LET Z(IK)=ZT*w19(H) !( X(r)-X(r+N/2) )*Wr/N
NEXT I
LET H=H+D !FFT: -D IFFT: +D
NEXT J
LOOP
END SUB
!=========================================
! INDEX BIT REVERSE を使用しない方法
!
!=========================================
! 高速フーリエ変換 Fast Fourier Transform
! 時間間引き型 DIT (Decimation In Time) without IndexBitReverse
!
SUB FFT_DIT_NB
LET I=0
LET O=MOD(LEN(BSTR$(N1,2)),2)*N1 !bitand(N1,0x5555)
LET N2=N1/2
LET K=1
LET D=N2
DO WHILE K<=N2 ! FFT: FOR H=N1 TO N1-D*(K-1) STEP -D
FOR H=N1 TO N1-D*(K-1) STEP -D !IFFT: FOR H=0 TO D*(K-1) STEP D
FOR I=I TO I+D-1
LET ZT=w19(H)*Z(I+D)
LET Z(O+N2)=Z(I)-ZT
LET Z(O) =Z(I)+ZT
LET O=O+1
NEXT I
LET I=I+D
NEXT H
LET K=K+K
LET D=D/2
IF O<=N1 THEN LET I=0 ELSE LET I=N1
LET O=N1-I
LOOP
END SUB
!=========================================
! 高速フーリエ 逆変換 Inverse Fast Fourier Transform
! 時間間引き型 DIT (Decimation In Time) without IndexBitReverse と同文で、
! 回転子W を 逆回しにしたもの。内容は周波数間引きになる。
!
SUB IFFT_DIT_NB
LET I=0
LET O=MOD(LEN(BSTR$(N1,2)),2)*N1 !bitand(N1,0x5555)
LET N2=N1/2
LET K=1
LET D=N2
DO WHILE K<=N2 ! FFT: FOR H=N1 TO N1-D*(K-1) STEP -D
FOR H=0 TO D*(K-1) STEP D !IFFT: FOR H=0 TO D*(K-1) STEP D
FOR I=I TO I+D-1
LET ZT=w19(H)*Z(I+D)
LET Z(O+N2)=Z(I)-ZT
LET Z(O) =Z(I)+ZT
LET O=O+1
NEXT I
LET I=I+D
NEXT H
LET K=K+K
LET D=D/2
IF O<=N1 THEN LET I=0 ELSE LET I=N1
LET O=N1-I
LOOP
!-------------
MAT Z=(1/N1)*Z
END SUB
!=========================================
! 高速フーリエ変換 Fast Fourier Transform
! 周波数間引き型 DIF (Decimation In Frequency) without IndexBitReverse
!
SUB FFT_DIF_NB
LET I=0
LET O=N1
LET N2=N1/2
LET K=1
LET D=N2
DO WHILE K<=N2 ! FFT: FOR H=N1 TO N1-K*(D-1) STEP -K
FOR H=N1 TO N1-K*(D-1) STEP -K !IFFT: FOR H=0 TO K*(D-1) STEP K
FOR I=I TO I+K-1
LET ZT=Z(I+N2)
LET Z(O+K)=(Z(I)-ZT)*w19(H)
LET Z(O )= Z(I)+ZT
LET O=O+1
NEXT I
LET O=O+K
NEXT H
LET K=K+K
LET D=D/2
IF I>N1 THEN LET I=0 ELSE LET I=N1
IF K=N2 THEN LET O=0 ELSE LET O=N1-I
LOOP
END SUB
!=========================================
! 高速フーリエ 逆変換 Inverse Fast Fourier Transform
! 周波数間引き型 DIF (Decimation In Frequency) without IndexBitReverse と同文で、
! 回転子W を 逆回しにしたもの。内容は時間間引きになる。
!
SUB IFFT_DIF_NB
LET I=0
LET O=N1
LET N2=N1/2
LET K=1
LET D=N2
DO WHILE K<=N2 ! FFT: FOR H=N1 TO N1-K*(D-1) STEP -K
FOR H=0 TO K*(D-1) STEP K !IFFT: FOR H=0 TO K*(D-1) STEP K
FOR I=I TO I+K-1
LET ZT=Z(I+N2)
LET Z(O+K)=(Z(I)-ZT)*w19(H)
LET Z(O )= Z(I)+ZT
LET O=O+1
NEXT I
LET O=O+K
NEXT H
LET K=K+K
LET D=D/2
IF I>N1 THEN LET I=0 ELSE LET I=N1
IF K=N2 THEN LET O=0 ELSE LET O=N1-I
LOOP
!-------------
MAT Z=(1/N1)*Z
END SUB
!Page-4 へ続く
-
- [16]
Page-4
- 投稿者:SECOND
- 投稿日:2010年 3月25日(木)05時12分54秒
-
-
!Page-4 の始め
!******************************************************************
! 上記の評価用プログラム
!******************************************************************
LET ym=10
DIM XC(4),YC(ym),XG(4),YG(ym)
!
LET XCd=7 !dots.chr.Xw
LET YCd=13+1 !dots.chr.Yw+1
LET YFL=1.52 !Data max.amplitude
!
LET XC(0)=5 !left margin
LET XG(0)=XC(0)*XCd
FOR i=1 TO 4
LET XC(i)=XC(i-1)+18
LET XG(i)=XC(i)*XCd
NEXT i
LET YC(0)=YFL+1
LET YG(0)=YC(0)*YCd
FOR i=1 TO ym
LET YC(i)=YC(i-1)+YC(0)+YFL
LET YG(i)=YC(i)*YCd
NEXT i
!
LET i=(XC(4)+13)*XCd
LET j=(YC(ym)+5)*YCd
SET bitmap SIZE i,j
SET WINDOW 0,i-1,j-1,0
!
FOR GS=1 TO 10000
IF FP(N1/GS)=0 THEN
LET XD=(XG(2)-XG(0))/N1*GS !Data pitch
IF 2<=XD THEN EXIT FOR
END IF
NEXT GS
LET YD=YFL*YCd !Data max.amplitude
!
FOR test=0 TO 2
MAT Z=ZER
FOR i=0 TO test
LET Z(i)=1 !試験用 "SIGNAL" 作成。
NEXT i
!----------グリッド-----
CLEAR
SET LINE COLOR "gray"
FOR i=0 TO ym
PLOT LINES: XG(0),YG(i);XG(4),YG(i) !,,,0x1111
NEXT i
FOR i=0 TO 4
PLOT LINES: XG(i),YG(0);XG(i),YG(ym) !,,,0x1111
NEXT i
LET i=XG(0)+XCd*1.3
LET j=YG(ym)+YCd*2.5
PLOT TEXT,AT i+XCd*2,j+YCd*.5 :"実数部 虚数部 絶対値"
SET AREA COLOR 4 ! red
DRAW disk WITH SCALE(10,1)*SHIFT(i,j)
SET AREA COLOR 10 ! dark green
DRAW disk WITH SCALE(10,1)*SHIFT(i+XCd*15,j)
SET AREA COLOR 2 ! blue
DRAW disk WITH SCALE(10,1)*SHIFT(i+XCd*30,j)
!---------------------[0]
PLOT TEXT,AT XG(4)+XCd,YG(0) :"SIGNAL"
CALL SCALE
CALL DRAW_re_im(YG(0))
!CALL DRAW_abs(YG(0))
!---------------------[1] DFT は、著しく遅いため 512 までで休止
IF N1<=512 THEN !! させているが、必要なら 数値を大きく。
CALL FFT(" DFT",YG(1))
CALL SCALE
CALL DRAW_re_im(YG(1))
CALL DRAW_abs(YG(1))
!---------------------[2]
CALL FFT("IDFT",YG(2))
CALL SCALE
CALL DRAW_re_im(YG(2))
!CALL DRAW_abs(YG(2))
ELSE
PLOT TEXT,AT XG(4)+XCd,YG(1)+YCd :" DFT 休止中"
PLOT TEXT,AT XG(4)+XCd,YG(2)+YCd :"IDFT 休止中"
END IF
!---------------------[3]
CALL FFT(" FFT_DIT",YG(3))
CALL SCALE
CALL DRAW_re_im(YG(3))
CALL DRAW_abs(YG(3))
!---------------------[4]
CALL FFT("IFFT_DIT",YG(4))
CALL SCALE
CALL DRAW_re_im(YG(4))
!CALL DRAW_abs(YG(4))
!---------------------[5]
CALL FFT(" FFT_DIF",YG(5))
CALL SCALE
CALL DRAW_re_im(YG(5))
CALL DRAW_abs(YG(5))
!---------------------[6]
CALL FFT("IFFT_DIF",YG(6))
CALL SCALE
CALL DRAW_re_im(YG(6))
!CALL DRAW_abs(YG(6))
!---------------------[7]
CALL FFT(" FFT_DIT_NB",YG(7))
CALL SCALE
CALL DRAW_re_im(YG(7))
CALL DRAW_abs(YG(7))
!---------------------[8]
CALL FFT("IFFT_DIT_NB",YG(8))
CALL SCALE
CALL DRAW_re_im(YG(8))
!CALL DRAW_abs(YG(8))
!---------------------[9]
CALL FFT(" FFT_DIF_NB",YG(9))
CALL SCALE
CALL DRAW_re_im(YG(9))
CALL DRAW_abs(YG(9))
!---------------------[10]
CALL FFT("IFFT_DIF_NB",YG(10))
CALL SCALE
CALL DRAW_re_im(YG(10))
!CALL DRAW_abs(YG(10))
!---------------------
WAIT DELAY 2
NEXT test
beep
!------- full scale of X() Y()-------
SUB SCALE
LET S9=0
FOR I=0 TO N1-1
IF S9< ABS(Z(I)) THEN LET S9=ABS(Z(I))
NEXT I
IF S9=0 THEN LET S9=1E-4
END SUB
!------- draw re(),im()-----------
SUB DRAW_re_im(YG)
SET BEAM MODE "IMMORTAL" !pen-on/off, only plot lines (not_JIS)
PLOT TEXT,AT XG(2)+XCd,YG-YD ,USING"####.###":S9
!----
SET LINE COLOR 4 !red
LET X9=XG(0)
FOR I=0 TO N1+N1 STEP GS
LET Y9=YG-YD*re(Z(MOD(I,N1)))/S9
PLOT LINES: X9,Y9;
IF 5< XD THEN DRAW circle WITH SCALE(1)*SHIFT(X9,Y9)
LET X9=X9+XD
NEXT I
PLOT LINES
!----
SET LINE COLOR 10 !dark green
LET X9=XG(0)
FOR I=0 TO N1+N1 STEP GS
LET Y9=YG-YD*im(Z(MOD(I,N1)))/S9
PLOT LINES: X9,Y9;
IF 5< XD THEN DRAW circle WITH SCALE(1)*SHIFT(X9,Y9)
LET X9=X9+XD
NEXT I
PLOT LINES
END SUB
!------- draw abs()-----------
!v.line&circle
SUB DRAW_abs(YG)
SET LINE COLOR 2 !blue
LET R=INT(XD/5)
IF 3< R THEN LET R=3
LET X9=XG(0)
FOR I=0 TO N1+N1 STEP GS
LET Y9=YG-YD*ABS(Z(MOD(I,N1)))/S9
PLOT LINES: X9,YG;X9,Y9
DRAW circle WITH SCALE(R)*SHIFT(X9,Y9)
LET X9=X9+XD
NEXT I
END SUB
!--------------------------------------
SUB FFT(a$,YG)
PLOT TEXT,AT XG(4)+XCd,YG :a$
LET tm0=TIME
SELECT CASE a$
!
!---- DFT(Discrete Fourier Transform)
CASE " DFT"
CALL DFT !離散フーリエ変換(比較用基準)
CASE "IDFT"
CALL IDFT !離散フーリエ 逆変換(比較用基準)
!
!---- FFT(Fast Fourier Transform)
CASE " FFT_DIT"
CALL FFT_DIT !入力が、時間間引き( Decimation In Time)
CASE "IFFT_DIT"
CALL IFFT_DIT !時間間引き型での、逆変換(周波数間引き入力)
CASE " FFT_DIF"
CALL FFT_DIF !出力が、周波数間引き( Decimation In Frequency)
CASE "IFFT_DIF"
CALL IFFT_DIF !周波数間引き型での、逆変換(時間間引き出力)
!
!---- 以下は、index bit reverse を、不要にした同型。
CASE " FFT_DIT_NB"
CALL FFT_DIT_NB
CASE "IFFT_DIT_NB"
CALL IFFT_DIT_NB
CASE " FFT_DIF_NB"
CALL FFT_DIF_NB
CASE "IFFT_DIF_NB"
CALL IFFT_DIF_NB
CASE ELSE
END SELECT
PLOT TEXT,AT XG(4)+XCd,YG+YCd,USING"#####ms":(TIME-tm0)*1000
END SUB
!=========================================
! Discrete Fourier Transform
! 離散フーリエ変換(比較用基準)
!
SUB DFT
MAT ZO=ZER
FOR K=0 TO N1-1
LET H=N1
FOR I=0 TO N1-1
LET ZO(K)=ZO(K)+w19(H)*Z(I)
LET H=MOD( H-K,N1)
NEXT I
NEXT K
MAT Z=ZO
END SUB
!=========================================
! Inverse Discrete Fourier Transform (standard)
! 離散フーリエ逆変換(比較用基準)
!
SUB IDFT
MAT ZO=ZER
FOR K=0 TO N1-1
LET H=0
FOR I=0 TO N1-1
LET ZO(I)=ZO(I)+w19(H)*Z(K)
LET H=MOD( H+K,N1)
NEXT I
NEXT K
MAT Z=(1/N1)*ZO
END SUB
END
戻る