|
!------------------------------------------------------------
!先の投稿 #t5/#1
! で、エンコーダー側DC処理 point transform は、
! "divide by 2^AL" でなく、"arithmetic-shift-right AL" である事を、考慮していない
! 誤りがあり、その訂正版です。
! 先投稿への編集は、出来なくなっているので、これと差し換えて下さい。
!
! itu-t81.pdf の Annex K ( K.9~K.10 P177~P178) 参照
!
!整数出力(負~0)での、"divide by 2^N" と "arithmetic shift right N" の違い。
!
! out (N=1 の時) ┏┛divide by 2 ┌┘arithmetic shift right 1
! │
! │+3 ………┏ (+4) 00000100→ 00000010(商=+2) 00000100→ 00000010(+2)
! │+2 …┏━┛ ( ~) ~ → 00000001(商=+1) ~ → 00000001(+1)
! │+1┏━┛ (+2) 00000010→ 00000001(商=+1) 00000010→ 00000001(+1)
! ────┏━┿━┛────in ( ~) ~ → 00000000(商= 0) ~ → 00000000( 0)
! ┏━╋─┤-1 ( 0) 00000000→ 00000000(商= 0) 00000000→ 00000000( 0)
! ┏━╋─┘…│-2 ( ~) ~ → 00000000(商= 0) ~ → 11111111(-1)
! ╋─┘………│-3 (-2) 11111110→ 11111111(商=-1) 11111110→ 11111111(-1)
! ┘ │ ( ~) ~ → 11111111(商=-1) ~ → 11111110(-2)
! │~│~│~│~│~│~│ (-4) 11111100→ 11111110(商=-2) 11111100→ 11111110(-2)
!-6 -4 -2 0 +2 +4 +6 ( ~) ~ → 11111110(商=-2) ~ → 11111101(-3)
! (-6) 11111010→ 11111101(商=-3) 11111010→ 11111101(-3)
!************************************************************
!訂正版:十進 BASIC による プログレッシブ JPG の展開と画像化。
!
!プログレッシブ JPG 再生過程の画像は、最初のDC成分1枚だけ と、最終完成画、全2枚とした。
!Baseline JPG は、全1枚なので、画数で両者を区別できる。( 描画倍率は、1又は、2倍拡大)
!(必要なら、再生過程 全ての画像も、表示できるよう、SUB IZZRL0 に注釈行がある)
!
!大きな再生画像でも、縮尺を止め、1倍又は、極小な場合の2倍拡大のみにした。
!色差成分 Cb Cr の間引き走査復元の塗潰しは、SUB IDDCT8X8 に組み込み。
!
!具体的、可視的なプログラムで、実行し画像化するので、詳細事項の追跡と御参考に。
!再生できるファイルは、1000x1000 までの JPG だけで、
! baseline , spectral selection , successive approximation の3種類( web 上の、ほぼ全種)
!
!
!1)successive approximation AC.subsequence(Y,Cb,Cr 別々、1bit づつの処理)
! 0 でない追加データ extend (1bit) が 1st.scan も 0 の初めてのデーターになるまで、
! Zero-RUN を続ける。
! その間の、上位桁<>0 の 1st.scan 値 追加データーは、その個数分が、
! extend. に後続している。Zero-RUN 個数 の 0 の次の 0 の位置に、extend.を置く。
! ここでの extend. は group 1 だけで、(0,1) → (-1,+1)
!
! 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 … bit_stream=?何個になるかは、
! 3 1 (0 or 1) (0 or 1) 上位桁 =0 の係数が RRRR 個 になるまでに
! ↓ ↓ 通過した上位桁 <>0 の個数。上図では、4
!
! 新規(上位桁無) エンコーダー側AC処理 point transform は、
! の復号 0 → -1 "divide by 2^AL" なので
! 1 → +1 0 → 無変化。
! 1 → ±符号は上位桁に合せて加算。(絶対値が+1)
!
!
!2)successive approximation DC.subsequence(Y,Cb,Cr 別々、1bit づつの処理)
! ハフマン・コード RRRRssss 部は、存在せず、
! 頭からの bit_stream.で、1bit づつ、全てのblock の DC係数 に加える。
!
! エンコーダー側DC処理 point transform は、
! "arithmetic-shift-right AL" なので
! 0 → 無変化。
! 1 → 上位桁符号に関らず、+加算。(符号無し整数値が+1)
!
!
! ※AL・・・ 係数などの数値が、2^AL のステップ幅で 量子化された値 になっている意。
! ※AH・・・ preceding AL. 同じ BAND で直前の AL 値 (AH=0 は、最初の AL に添える)
!
! (Ah|Al)
! ←──┐ 0 0 全bits のデータ。復元は、(・・・111111.)*2^( point transform =0)
! ・・・111111
!
! 以下3つを加算すると、上と同じになる。
! (Ah|Al)
! ←─┐ 0 2 上位bits のデータ。 復元は、(・・・1111 )*2^( point transform =2)
! ・・・1111xx
! 〟 2 1 1bitづつ、分けて追加。復元は、( 1 )*2^( point transform =1)
! ・・・xxxx1x
! 〟 1 0 復元は、( 1)*2^( point transform =0)
! ・・・xxxxx1
!
!------------------------
DEBUG ON
!------------------------
!JPG.decoder
! Baseline
! Progressive( spectral selection )( successive approximation )
!------------------------
OPTION ARITHMETIC NATIVE
OPTION BASE 0
OPTION CHARACTER byte
SET TEXT background "OPAQUE"
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=1 !等倍で描画、画素数どうり。
LET w=IP( MIN( 500/DX, 500/DY)) !整数倍拡大、1~2の何れかで描画。
IF 2< w THEN LET w=2
IF w< 1 THEN LET w=1
PRINT "描画の倍率=";w
CALL scrns(DX*w, DY*w)
MAT PLOT CELLS,IN 1,1; DX*w, DY*w :D8
END SUB
SUB scrns(px,py)
SET bitmap SIZE px+50,py+50
SET WINDOW 1-20,px+30, py+27,1-23
SET LINE COLOR "cyan"
SET LINE width 3
PLOT LINES:1-3,1-3;px+3,1-3;px+3,py+3;1-3,py+3;1-3,1-3
PLOT TEXT,AT -3,-4: "原画 "& STR$(px/w)& "x"& STR$(py/w)& " 倍率= "& STR$(w)
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
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_
LET D2(U0+U(i),V0+V(i),P)=D2(U0+U(i),V0+V(i),P) +V_*2^Al
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
!===A.C.parts
LET Sa_=1
ELSE
!===A.C.parts
LET Sa_=Ss_
END IF
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 n(10,20,,E0)
!---EOBn extend
LET debug$="EOBn extend"& STR$(RL) !!!
IF 0< RL THEN
LET L_=RL !RL= 1,2,,E (EOB1, EOB2, ・・・, EOB14)
CALL DEC1_EX !keep RL, run_length= V_+2^RL
LET EOB=V_+2^RL -1 !※-1 (1st.count)
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 D2(U0+U(A_),V0+V(A_),P)=V_*2^Al !point transform
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 !group1( -1, 1)
LET D2(U0+U(i),V0+V(i),P)=V01*2^Al
END IF
LET A_=i
END IF
NEXT A_
END SUB
!Page-2 へ続く
|
|