mirror of
https://github.com/QB64-Phoenix-Edition/QB64pe.git
synced 2024-09-28 04:07:46 +00:00
9ee89d6ff4
These tests use a variety of sample code (with some of the larger files removed, so they are not complete!) and verifies that they all compile successfully.
729 lines
16 KiB
QBasic
729 lines
16 KiB
QBasic
'JPEG Encoder v2 by Artelius
|
|
'WARNING: OVERWRITES TEST.JPG
|
|
DECLARE FUNCTION Atan2! (X AS SINGLE, Y AS SINGLE)
|
|
DECLARE SUB PutChar (FileNo AS INTEGER, Char AS INTEGER)
|
|
|
|
DECLARE SUB JPEG.Precalc ()
|
|
DECLARE SUB JPEG.Begin (FileNo AS INTEGER, W AS INTEGER, H AS INTEGER, Sampling() AS INTEGER, State AS ANY, QT() AS INTEGER, Huff() AS INTEGER)
|
|
DECLARE SUB JPEG.Block.Output (B() AS INTEGER, State AS ANY, QT() AS INTEGER, Huff() AS INTEGER)
|
|
DECLARE SUB JPEG.StandardQT (quality AS SINGLE, QT() AS INTEGER)
|
|
DECLARE SUB JPEG.Finish (State AS ANY)
|
|
DECLARE FUNCTION JPEG.Category% (X AS INTEGER)
|
|
DECLARE FUNCTION JPEG.Cb% (R AS INTEGER, G AS INTEGER, B AS INTEGER)
|
|
DECLARE FUNCTION JPEG.Cr% (R AS INTEGER, G AS INTEGER, B AS INTEGER)
|
|
DECLARE FUNCTION JPEG.Y% (R AS INTEGER, G AS INTEGER, B AS INTEGER)
|
|
|
|
TYPE JPEGState
|
|
FileNo AS INTEGER
|
|
YCount AS INTEGER
|
|
CbCount AS INTEGER
|
|
CrCount AS INTEGER
|
|
YDC AS INTEGER
|
|
CbDC AS INTEGER
|
|
CrDC AS INTEGER
|
|
Position AS INTEGER
|
|
Leftover AS INTEGER
|
|
LeftoverBits AS INTEGER
|
|
END TYPE
|
|
|
|
'The following are internal to JPEG.
|
|
DECLARE SUB JPEG.ACHuff (RLE AS INTEGER, AC AS INTEGER, Huff() AS INTEGER, A AS INTEGER, State AS ANY)
|
|
DECLARE SUB JPEG.Block.Huffman (B() AS INTEGER, LastDC AS INTEGER, Huff() AS INTEGER, A AS INTEGER, State AS ANY)
|
|
DECLARE SUB JPEG.Block.Transform (B() AS INTEGER, O() AS INTEGER, QT() AS INTEGER, A AS INTEGER)
|
|
DECLARE SUB JPEG.DCHuff (DC AS INTEGER, Huff() AS INTEGER, A AS INTEGER, State AS ANY)
|
|
DECLARE SUB JPEG.GenerateHuffmanTable (Huff() AS INTEGER, A AS INTEGER, B AS INTEGER)
|
|
DECLARE SUB JPEG.PutBinString (BS AS INTEGER, Length AS INTEGER, State AS ANY)
|
|
DECLARE SUB JPEG.PutByte (FileNo AS INTEGER, Byte AS INTEGER)
|
|
DECLARE SUB JPEG.PutRightBinString (BS AS INTEGER, Length AS INTEGER, State AS ANY)
|
|
DECLARE SUB JPEG.PutWord (FileNo AS INTEGER, Word AS INTEGER)
|
|
DECLARE FUNCTION JPEG.Shift% (I AS INTEGER, N AS INTEGER)
|
|
|
|
DEFINT A-Z
|
|
|
|
DIM SHARED Pow2(0 TO 15) AS LONG
|
|
DIM SHARED Cosine(0 TO 7, 0 TO 7) AS SINGLE
|
|
DIM SHARED ZigZagX(0 TO 63) AS INTEGER, ZigZagY(0 TO 63) AS INTEGER
|
|
JPEG.Precalc
|
|
|
|
DIM Huff(0 TO 255, 0 TO 1, 0 TO 1, 0 TO 1) AS INTEGER
|
|
DIM QT(0 TO 7, 0 TO 7, 0 TO 1) AS INTEGER
|
|
DIM State AS JPEGState
|
|
|
|
DIM Sampling(0 TO 2, 0 TO 1) AS INTEGER
|
|
Sampling(0, 0) = 2 'Sampling factor (x then y) for luminance
|
|
Sampling(0, 1) = 2
|
|
Sampling(1, 0) = 1 'Sampling factor for "blue" chrominance
|
|
Sampling(1, 1) = 1
|
|
Sampling(2, 0) = 1 'Sampling factor for "red" chrominance
|
|
Sampling(2, 1) = 1
|
|
|
|
|
|
'Delete file then open for binary
|
|
OPEN "test.jpg" FOR OUTPUT AS #1
|
|
CLOSE
|
|
OPEN "test.jpg" FOR BINARY AS #1
|
|
|
|
'Set quality tables
|
|
'The smaller the paramter, the higher the quality
|
|
'0.01 is 100% quality
|
|
JPEG.StandardQT .5, QT()
|
|
|
|
'Start image (64x64)
|
|
JPEG.Begin 1, 128, 128, Sampling(), State, QT(), Huff()
|
|
|
|
|
|
DIM B(0 TO 7, 0 TO 7) AS INTEGER
|
|
|
|
FOR SuperY = 0 TO 127 STEP 16
|
|
FOR SuperX = 0 TO 127 STEP 16
|
|
|
|
'Output the luminance blocks
|
|
|
|
FOR BlockY = 0 TO 15 STEP 8
|
|
FOR BlockX = 0 TO 15 STEP 8
|
|
FOR OffY = 0 TO 7: FOR OffX = 0 TO 7
|
|
X! = OffX + BlockX + SuperX - 63.5
|
|
Y! = OffY + BlockY + SuperY - 63.5
|
|
D! = SQR(X! * X! + Y! * Y!) / 6 + Atan2(X!, Y!)
|
|
R = 255
|
|
G = 255 - (COS(D!) + 1) * 127.5
|
|
B = 255 - (COS(D!) + 1) * 127.5
|
|
B(OffX, OffY) = JPEG.Y(R, G, B)
|
|
NEXT OffX, OffY
|
|
JPEG.Block.Output B(), State, QT(), Huff()
|
|
NEXT BlockX, BlockY
|
|
|
|
'Output the blue chrominance block
|
|
|
|
FOR OffY = 0 TO 7: FOR OffX = 0 TO 7
|
|
X! = OffX * 2 + SuperX - 63
|
|
Y! = OffY * 2 + SuperY - 63
|
|
D! = SQR(X! * X! + Y! * Y!) / 6 + Atan2(X!, Y!)
|
|
R = 255
|
|
G = 255 - (COS(D!) + 1) * 127.5
|
|
B = 255 - (COS(D!) + 1) * 127.5
|
|
B(OffX, OffY) = JPEG.Cb(R, G, B)
|
|
NEXT OffX, OffY
|
|
JPEG.Block.Output B(), State, QT(), Huff()
|
|
|
|
'Output the red chrominance block
|
|
|
|
FOR OffY = 0 TO 7: FOR OffX = 0 TO 7
|
|
X! = OffX * 2 + SuperX - 63
|
|
Y! = OffY * 2 + SuperY - 63
|
|
D! = SQR(X! * X! + Y! * Y!) / 6 + Atan2(X!, Y!)
|
|
R = 255
|
|
G = 255 - (COS(D!) + 1) * 127.5
|
|
B = 255 - (COS(D!) + 1) * 127.5
|
|
B(OffX, OffY) = JPEG.Cr(R, G, B)
|
|
NEXT OffX, OffY
|
|
JPEG.Block.Output B(), State, QT(), Huff()
|
|
|
|
NEXT SuperX, SuperY
|
|
|
|
|
|
JPEG.Finish State
|
|
|
|
CLOSE
|
|
|
|
END
|
|
|
|
Huff0:
|
|
DATA 0
|
|
DATA 1, 0
|
|
DATA 5, 1, 2, 3, 4, 5
|
|
DATA 1, 6
|
|
DATA 1, 7
|
|
DATA 1, 8
|
|
DATA 1, 9
|
|
DATA 1, 10
|
|
DATA 1, 11
|
|
DATA 0, 0, 0, 0, 0, 0, 0
|
|
|
|
Huff1:
|
|
DATA 0
|
|
DATA 3, 0, 1, 2
|
|
DATA 1, 3
|
|
DATA 1, 4
|
|
DATA 1, 5
|
|
DATA 1, 6
|
|
DATA 1, 7
|
|
DATA 1, 8
|
|
DATA 1, 9
|
|
DATA 1, 10
|
|
DATA 1, 11
|
|
DATA 0, 0, 0, 0, 0
|
|
|
|
Huff2:
|
|
DATA 0
|
|
DATA 2, 1, 2
|
|
DATA 1, 3
|
|
DATA 3, 0, 4, &H11
|
|
DATA 3, 5, &H12, &H21
|
|
DATA 2, &H31, &H41
|
|
DATA 4, 6, &H13, &H51, &H61
|
|
DATA 3, 7, &H22, &H71
|
|
DATA 5, &H14, &H32, &H81, &H91, &HA1
|
|
DATA 5, &H08, &H23, &H42, &HB1, &HC1
|
|
DATA 4, &H15, &H52, &HD1, &HF0
|
|
DATA 4, &H24, &H33, &H62, &H72
|
|
DATA 0
|
|
DATA 0
|
|
DATA 1, &H82
|
|
DATA 125, &H09, &H0A, &H16, &H17, &H18, &H19, &H1A, &H25, &H26, &H27, &H28, &H29, &H2A, &H34, &H35, &H36
|
|
DATA &H37, &H38, &H39, &H3A, &H43, &H44, &H45, &H46, &H47, &H48, &H49, &H4A, &H53, &H54, &H55, &H56
|
|
DATA &H57, &H58, &H59, &H5A, &H63, &H64, &H65, &H66, &H67, &H68, &H69, &H6A, &H73, &H74, &H75, &H76
|
|
DATA &H77, &H78, &H79, &H7A, &H83, &H84, &H85, &H86, &H87, &H88, &H89, &H8A, &H92, &H93, &H94, &H95
|
|
DATA &H96, &H97, &H98, &H99, &H9A, &HA2, &HA3, &HA4, &HA5, &HA6, &HA7, &HA8, &HA9, &HAA, &HB2, &HB3
|
|
DATA &HB4, &HB5, &HB6, &HB7, &HB8, &HB9, &HBA, &HC2, &HC3, &HC4, &HC5, &HC6, &HC7, &HC8, &HC9, &HCA
|
|
DATA &HD2, &HD3, &HD4, &HD5, &HD6, &HD7, &HD8, &HD9, &HDA, &HE1, &HE2, &HE3, &HE4, &HE5, &HE6, &HE7
|
|
DATA &HE8, &HE9, &HEA, &HF1, &HF2, &HF3, &HF4, &HF5, &HF6, &HF7, &HF8, &HF9, &HFA
|
|
|
|
Huff3:
|
|
DATA 0
|
|
DATA 2, 0, 1
|
|
DATA 1, 2
|
|
DATA 2, 3, &H11
|
|
DATA 4, 4, 5, &H21, &H31
|
|
DATA 4, 6, &H12, &H41, &H51
|
|
DATA 3, 7, &H61, &H71
|
|
DATA 4, &H13, &H22, &H32, &H81
|
|
DATA 7, 8, &H14, &H42, &H91, &HA1, &HB1, &HC1
|
|
DATA 5, 9, &H23, &H33, &H52, &HF0
|
|
DATA 4, &H15, &H62, &H72, &HD1
|
|
DATA 4, &HA, &H16, &H24, &H34
|
|
DATA 0
|
|
DATA 1, &HE1
|
|
DATA 2, &H25, &HF1
|
|
DATA 119, &H17, &H18, &H19, &H1A, &H26, &H27, &H28, &H29, &H2A, &H35, &H36, &H37, &H38, &H39, &H3A, &H43
|
|
DATA &H44, &H45, &H46, &H47, &H48, &H49, &H4A, &H53, &H54, &H55, &H56, &H57, &H58, &H59, &H5A, &H63
|
|
DATA &H64, &H65, &H66, &H67, &H68, &H69, &H6A, &H73, &H74, &H75, &H76, &H77, &H78, &H79, &H7A, &H82
|
|
DATA &H83, &H84, &H85, &H86, &H87, &H88, &H89, &H8A, &H92, &H93, &H94, &H95, &H96, &H97, &H98, &H99
|
|
DATA &H9A, &HA2, &HA3, &HA4, &HA5, &HA6, &HA7, &HA8, &HA9, &HAA, &HB2, &HB3, &HB4, &HB5, &HB6, &HB7
|
|
DATA &HB8, &HB9, &HBA, &HC2, &HC3, &HC4, &HC5, &HC6, &HC7, &HC8, &HC9, &HCA, &HD2, &HD3, &HD4, &HD5
|
|
DATA &HD6, &HD7, &HD8, &HD9, &HDA, &HE2, &HE3, &HE4, &HE5, &HE6, &HE7, &HE8, &HE9, &HEA, &HF2, &HF3
|
|
DATA &HF4, &HF5, &HF6, &HF7, &HF8, &HF9, &HFA
|
|
|
|
StandardQT:
|
|
DATA 16, 11, 10, 16, 24, 40, 51, 61
|
|
DATA 12, 12, 14, 19, 26, 58, 60, 55
|
|
DATA 14, 13, 16, 24, 40, 57, 69, 56
|
|
DATA 14, 17, 22, 29, 51, 87, 80, 62
|
|
DATA 18, 22, 37, 56, 68, 109, 103, 77
|
|
DATA 24, 35, 55, 64, 81, 104, 113, 92
|
|
DATA 49, 64, 78, 87, 103, 121, 120, 101
|
|
DATA 72, 92, 95, 98, 112, 100, 103, 99
|
|
|
|
DATA 17, 18, 24, 47, 99, 99, 99, 99
|
|
DATA 18, 24, 26, 66, 99, 99, 99, 99
|
|
DATA 24, 26, 56, 99, 99, 99, 99, 99
|
|
DATA 47, 66, 99, 99, 99, 99, 99, 99
|
|
DATA 99, 99, 99, 99, 99, 99, 99, 99
|
|
DATA 99, 99, 99, 99, 99, 99, 99, 99
|
|
DATA 99, 99, 99, 99, 99, 99, 99, 99
|
|
DATA 99, 99, 99, 99, 99, 99, 99, 99
|
|
|
|
DEFSNG A-Z
|
|
FUNCTION Atan2! (X AS SINGLE, Y AS SINGLE)
|
|
|
|
'Code borrowed from London
|
|
Atan2 = ATN(Y / X) - ATN(1) * 4 * (X < 0 - 2 * (X < 0 AND Y < 0))
|
|
|
|
END FUNCTION
|
|
|
|
SUB JPEG.ACHuff (RLE AS INTEGER, AC AS INTEGER, Huff() AS INTEGER, A AS INTEGER, State AS JPEGState)
|
|
DIM C AS INTEGER, X AS INTEGER
|
|
C = JPEG.Category(AC)
|
|
X = RLE * 16 + C
|
|
JPEG.PutBinString Huff(X, 1, A, 0), Huff(X, 1, A, 1), State
|
|
JPEG.PutRightBinString AC + (AC < 0), C, State
|
|
END SUB
|
|
|
|
SUB JPEG.Begin (FileNo AS INTEGER, W AS INTEGER, H AS INTEGER, Sampling() AS INTEGER, State AS JPEGState, QT() AS INTEGER, Huff() AS INTEGER)
|
|
|
|
DIM I AS INTEGER, J AS INTEGER, X AS INTEGER, Y AS INTEGER, T AS INTEGER
|
|
|
|
State.FileNo = FileNo
|
|
|
|
RESTORE Huff0
|
|
JPEG.GenerateHuffmanTable Huff(), 0, 0
|
|
JPEG.GenerateHuffmanTable Huff(), 0, 1
|
|
JPEG.GenerateHuffmanTable Huff(), 1, 0
|
|
JPEG.GenerateHuffmanTable Huff(), 1, 1
|
|
|
|
|
|
State.YCount = Sampling(0, 0) * Sampling(0, 1)
|
|
State.CbCount = Sampling(1, 0) * Sampling(1, 1)
|
|
State.CrCount = Sampling(2, 0) * Sampling(2, 1)
|
|
State.YDC = 0
|
|
State.CbDC = 0
|
|
State.CrDC = 0
|
|
|
|
State.Position = 0
|
|
|
|
State.Leftover = 0
|
|
State.LeftoverBits = 0
|
|
|
|
|
|
'SOI
|
|
PutChar FileNo, 255
|
|
PutChar FileNo, 216
|
|
'APP0
|
|
PutChar FileNo, 255
|
|
PutChar FileNo, 224
|
|
JPEG.PutWord FileNo, 16
|
|
S$ = "JFIF" + CHR$(0): PUT FileNo, , S$
|
|
PutChar FileNo, 1
|
|
PutChar FileNo, 2
|
|
PutChar FileNo, 0
|
|
PutChar FileNo, 0
|
|
PutChar FileNo, 1
|
|
PutChar FileNo, 0
|
|
PutChar FileNo, 1
|
|
PutChar FileNo, 0
|
|
PutChar FileNo, 0
|
|
|
|
'DQT
|
|
PutChar FileNo, 255
|
|
PutChar FileNo, 219
|
|
JPEG.PutWord FileNo, 132
|
|
|
|
PutChar FileNo, 0
|
|
FOR I = 0 TO 63
|
|
PutChar FileNo, QT(ZigZagX(I), ZigZagY(I), 0)
|
|
NEXT
|
|
|
|
|
|
|
|
PutChar FileNo, 1
|
|
FOR I = 0 TO 63
|
|
PutChar FileNo, QT(ZigZagX(I), ZigZagY(I), 1)
|
|
NEXT
|
|
|
|
|
|
|
|
'DHT
|
|
PutChar FileNo, 255
|
|
PutChar FileNo, 196
|
|
T = 2 + 4 * (16 + 1)
|
|
RESTORE Huff0
|
|
FOR I = 1 TO 16 * 4
|
|
READ X
|
|
FOR J = 1 TO X
|
|
READ Y
|
|
T = T + 1
|
|
NEXT
|
|
NEXT
|
|
|
|
JPEG.PutWord FileNo, T
|
|
|
|
PutChar FileNo, 0
|
|
RESTORE Huff0
|
|
FOR I = 1 TO 16
|
|
READ X
|
|
PutChar FileNo, X
|
|
FOR J = 1 TO X
|
|
READ Y
|
|
NEXT
|
|
NEXT
|
|
RESTORE Huff0
|
|
FOR I = 1 TO 16
|
|
READ X
|
|
FOR J = 1 TO X
|
|
READ Y
|
|
PutChar FileNo, Y
|
|
NEXT
|
|
NEXT
|
|
|
|
PutChar FileNo, 1
|
|
RESTORE Huff1
|
|
FOR I = 1 TO 16
|
|
READ X
|
|
PutChar FileNo, X
|
|
FOR J = 1 TO X
|
|
READ Y
|
|
NEXT
|
|
NEXT
|
|
RESTORE Huff1
|
|
FOR I = 1 TO 16
|
|
READ X
|
|
FOR J = 1 TO X
|
|
READ Y
|
|
PutChar FileNo, Y
|
|
NEXT
|
|
NEXT
|
|
|
|
PutChar FileNo, 16
|
|
RESTORE Huff2
|
|
FOR I = 1 TO 16
|
|
READ X
|
|
PutChar FileNo, X
|
|
FOR J = 1 TO X
|
|
READ Y
|
|
NEXT
|
|
NEXT
|
|
RESTORE Huff2
|
|
FOR I = 1 TO 16
|
|
READ X
|
|
FOR J = 1 TO X
|
|
READ Y
|
|
PutChar FileNo, Y
|
|
NEXT
|
|
NEXT
|
|
|
|
PutChar FileNo, 17
|
|
RESTORE Huff3
|
|
FOR I = 1 TO 16
|
|
READ X
|
|
PutChar FileNo, X
|
|
FOR J = 1 TO X
|
|
READ Y
|
|
NEXT
|
|
NEXT
|
|
RESTORE Huff3
|
|
FOR I = 1 TO 16
|
|
READ X
|
|
FOR J = 1 TO X
|
|
READ Y
|
|
PutChar FileNo, Y
|
|
NEXT
|
|
NEXT
|
|
|
|
'SOF0
|
|
PutChar FileNo, 255
|
|
PutChar FileNo, 192
|
|
JPEG.PutWord FileNo, 8 + 9
|
|
PutChar FileNo, 8
|
|
JPEG.PutWord FileNo, H
|
|
JPEG.PutWord FileNo, W
|
|
|
|
PutChar FileNo, 3
|
|
|
|
PutChar FileNo, 1
|
|
PutChar FileNo, Sampling(0, 0) * 16 + Sampling(0, 1)
|
|
PutChar FileNo, 0
|
|
PutChar FileNo, 2
|
|
PutChar FileNo, Sampling(1, 0) * 16 + Sampling(1, 1)
|
|
PutChar FileNo, 1
|
|
PutChar FileNo, 3
|
|
PutChar FileNo, Sampling(2, 0) * 16 + Sampling(2, 1)
|
|
PutChar FileNo, 1
|
|
|
|
'SOS
|
|
|
|
PutChar FileNo, 255
|
|
PutChar FileNo, 218
|
|
JPEG.PutWord FileNo, 12
|
|
|
|
PutChar FileNo, 3
|
|
|
|
PutChar FileNo, 1
|
|
PutChar FileNo, &H0
|
|
PutChar FileNo, 2
|
|
PutChar FileNo, &H11
|
|
PutChar FileNo, 3
|
|
PutChar FileNo, &H11
|
|
|
|
PutChar FileNo, 0
|
|
PutChar FileNo, 63
|
|
PutChar FileNo, 0
|
|
|
|
END SUB
|
|
|
|
SUB JPEG.Block.Huffman (B() AS INTEGER, LastDC AS INTEGER, Huff() AS INTEGER, A AS INTEGER, State AS JPEGState)
|
|
DIM DC AS INTEGER, I AS INTEGER
|
|
DIM C AS INTEGER
|
|
DC = B(0) - LastDC
|
|
JPEG.DCHuff DC, Huff(), A, State
|
|
B(64) = -1
|
|
|
|
I = 1
|
|
DO
|
|
C = 0
|
|
IF B(I) = 0 THEN
|
|
|
|
DO
|
|
I = I + 1
|
|
C = C + 1
|
|
LOOP WHILE B(I) = 0
|
|
IF I = 64 THEN
|
|
|
|
JPEG.PutBinString Huff(0, 1, A, 0), Huff(0, 1, A, 1), State
|
|
EXIT DO
|
|
END IF
|
|
WHILE C >= 16
|
|
|
|
JPEG.PutBinString Huff(&HF0, 1, A, 0), Huff(&HF0, 1, A, 1), State
|
|
C = C - 16
|
|
WEND
|
|
|
|
END IF
|
|
|
|
|
|
JPEG.ACHuff C, B(I), Huff(), A, State
|
|
I = I + 1
|
|
LOOP WHILE I < 64
|
|
END SUB
|
|
|
|
SUB JPEG.Block.Output (B() AS INTEGER, State AS JPEGState, QT() AS INTEGER, Huff() AS INTEGER)
|
|
|
|
DIM O(0 TO 64) AS INTEGER
|
|
State.Position = State.Position + 1
|
|
IF State.Position > State.YCount + State.CbCount + State.CrCount THEN State.Position = 1
|
|
IF State.Position <= State.YCount THEN
|
|
JPEG.Block.Transform B(), O(), QT(), 0
|
|
JPEG.Block.Huffman O(), State.YDC, Huff(), 0, State
|
|
State.YDC = O(0)
|
|
ELSE
|
|
JPEG.Block.Transform B(), O(), QT(), 1
|
|
IF State.Position <= State.YCount + State.CbCount THEN
|
|
JPEG.Block.Huffman O(), State.CbDC, Huff(), 1, State
|
|
State.CbDC = O(0)
|
|
ELSE
|
|
JPEG.Block.Huffman O(), State.CrDC, Huff(), 1, State
|
|
State.CrDC = O(0)
|
|
END IF
|
|
END IF
|
|
|
|
END SUB
|
|
|
|
SUB JPEG.Block.Transform (B() AS INTEGER, O() AS INTEGER, QT() AS INTEGER, A AS INTEGER)
|
|
DIM U AS INTEGER, V AS INTEGER, X AS INTEGER, Y AS INTEGER
|
|
DIM B2(0 TO 7, 0 TO 7) AS SINGLE
|
|
DIM T AS SINGLE
|
|
|
|
FOR V = 0 TO 7: FOR U = 0 TO 7
|
|
T = 0
|
|
FOR X = 0 TO 7
|
|
T = T + B(X, V) * Cosine(X, U)
|
|
NEXT X
|
|
B2(U, V) = T
|
|
NEXT U, V
|
|
|
|
FOR U = 0 TO 7: FOR V = 0 TO 7
|
|
T = 0
|
|
FOR Y = 0 TO 7
|
|
T = T + B2(U, Y) * Cosine(Y, V)
|
|
NEXT Y
|
|
T = T / 4
|
|
IF U = 0 THEN T = T / SQR(2)
|
|
IF V = 0 THEN T = T / SQR(2)
|
|
B(U, V) = CINT(T / QT(U, V, A))
|
|
NEXT V, U
|
|
|
|
FOR U = 0 TO 63
|
|
O(U) = B(ZigZagX(U), ZigZagY(U))
|
|
NEXT
|
|
|
|
END SUB
|
|
|
|
FUNCTION JPEG.Category% (X AS INTEGER)
|
|
DIM T AS INTEGER, I AS INTEGER
|
|
T = ABS(X)
|
|
WHILE T
|
|
T = T \ 2
|
|
I = I + 1
|
|
WEND
|
|
JPEG.Category = I
|
|
END FUNCTION
|
|
|
|
FUNCTION JPEG.Cb% (R AS INTEGER, G AS INTEGER, B AS INTEGER)
|
|
|
|
JPEG.Cb = -.1687 * R - .3313 * G + .5 * B
|
|
|
|
END FUNCTION
|
|
|
|
FUNCTION JPEG.Cr% (R AS INTEGER, G AS INTEGER, B AS INTEGER)
|
|
|
|
JPEG.Cr = .5 * R - .4187 * G - .0813 * B
|
|
|
|
END FUNCTION
|
|
|
|
SUB JPEG.DCHuff (DC AS INTEGER, Huff() AS INTEGER, A AS INTEGER, State AS JPEGState)
|
|
DIM C AS INTEGER
|
|
C = JPEG.Category(DC)
|
|
JPEG.PutBinString Huff(C, 0, A, 0), Huff(C, 0, A, 1), State
|
|
JPEG.PutRightBinString DC + (DC < 0), C, State
|
|
END SUB
|
|
|
|
SUB JPEG.Finish (State AS JPEGState)
|
|
|
|
DEF SEG = VARSEG(State.Leftover)
|
|
IF State.LeftoverBits > 8 THEN
|
|
JPEG.PutByte State.FileNo, PEEK(VARPTR(State.Leftover) + 1)
|
|
POKE VARPTR(State.Leftover) + 1, State.Leftover AND 255
|
|
State.LeftoverBits = State.LeftoverBits - 8
|
|
END IF
|
|
|
|
IF State.LeftoverBits THEN
|
|
JPEG.PutByte State.FileNo, PEEK(VARPTR(State.Leftover) + 1) OR (Pow2(8 - State.LeftoverBits) - 1)
|
|
END IF
|
|
DEF SEG
|
|
|
|
'EOF marker
|
|
PutChar State.FileNo, 255
|
|
PutChar State.FileNo, 217
|
|
|
|
END SUB
|
|
|
|
SUB JPEG.GenerateHuffmanTable (Huff() AS INTEGER, A AS INTEGER, B AS INTEGER)
|
|
DIM S AS LONG, I AS INTEGER, J AS INTEGER, T AS INTEGER
|
|
DIM X AS INTEGER, Y AS INTEGER
|
|
S = -1
|
|
|
|
FOR I = 1 TO 16
|
|
READ X
|
|
FOR J = 1 TO X
|
|
|
|
IF S = -1 THEN
|
|
S = 0
|
|
ELSE
|
|
S = S + Pow2(T)
|
|
END IF
|
|
|
|
|
|
READ Y
|
|
IF S AND 32768 THEN Huff(Y, A, B, 0) = CINT(S AND 32767&) OR -32768 ELSE Huff(Y, A, B, 0) = S
|
|
Huff(Y, A, B, 1) = I
|
|
T = 16 - I
|
|
|
|
NEXT
|
|
NEXT
|
|
END SUB
|
|
|
|
SUB JPEG.Precalc
|
|
DIM X AS INTEGER, Y AS INTEGER, T AS INTEGER, Dir AS INTEGER, L AS LONG
|
|
|
|
L = 1
|
|
FOR X = 0 TO 15
|
|
Pow2(X) = L
|
|
L = L + L
|
|
NEXT
|
|
FOR Y = 0 TO 7
|
|
FOR X = 0 TO 7
|
|
Cosine(X, Y) = COS((2 * X + 1) * Y * .1963495)
|
|
NEXT X, Y
|
|
|
|
X = 0: Y = 0
|
|
T = 0
|
|
Dir = 0
|
|
DO
|
|
ZigZagX(T) = X
|
|
ZigZagY(T) = Y
|
|
T = T + 1
|
|
IF T = 64 THEN EXIT DO
|
|
IF Dir THEN
|
|
IF Y = 7 THEN
|
|
X = X + 1
|
|
Dir = 0
|
|
ELSEIF X = 0 THEN
|
|
Y = Y + 1
|
|
Dir = 0
|
|
ELSE
|
|
X = X - 1
|
|
Y = Y + 1
|
|
END IF
|
|
|
|
ELSE
|
|
IF Y = 0 THEN
|
|
X = X + 1
|
|
Dir = 1
|
|
ELSEIF X = 7 THEN
|
|
Y = Y + 1
|
|
Dir = 1
|
|
ELSE
|
|
X = X + 1
|
|
Y = Y - 1
|
|
END IF
|
|
END IF
|
|
LOOP
|
|
|
|
|
|
|
|
END SUB
|
|
|
|
SUB JPEG.PutBinString (BS AS INTEGER, Length AS INTEGER, State AS JPEGState)
|
|
DIM Temp AS INTEGER
|
|
|
|
Temp = BS
|
|
State.Leftover = State.Leftover OR JPEG.Shift(Temp, State.LeftoverBits)
|
|
State.LeftoverBits = State.LeftoverBits + Length
|
|
IF State.LeftoverBits >= 16 THEN
|
|
DEF SEG = VARSEG(State.Leftover)
|
|
JPEG.PutByte State.FileNo, PEEK(VARPTR(State.Leftover) + 1)
|
|
DEF SEG
|
|
JPEG.PutByte State.FileNo, State.Leftover AND 255
|
|
State.LeftoverBits = State.LeftoverBits - 16
|
|
State.Leftover = Temp
|
|
END IF
|
|
|
|
END SUB
|
|
|
|
SUB JPEG.PutByte (FileNo AS INTEGER, Byte AS INTEGER)
|
|
DIM C AS STRING * 1
|
|
C = CHR$(Byte)
|
|
PUT FileNo, , C
|
|
IF Byte = 255 THEN C = CHR$(0): PUT FileNo, , C
|
|
END SUB
|
|
|
|
SUB JPEG.PutRightBinString (BS AS INTEGER, Length AS INTEGER, State AS JPEGState)
|
|
|
|
DIM Temp AS LONG
|
|
IF Length THEN
|
|
Temp = (CLNG(BS) AND Pow2(Length) - 1) * Pow2(16 - Length)
|
|
IF Temp AND 32768 THEN Temp = Temp OR -65536
|
|
JPEG.PutBinString CINT(Temp), Length, State
|
|
END IF
|
|
|
|
END SUB
|
|
|
|
SUB JPEG.PutWord (FileNo AS INTEGER, Word AS INTEGER)
|
|
DIM C AS STRING * 1
|
|
C = CHR$(Word \ 256)
|
|
PUT FileNo, , C
|
|
C = CHR$(Word AND 255)
|
|
PUT FileNo, , C
|
|
END SUB
|
|
|
|
FUNCTION JPEG.Shift% (I AS INTEGER, N AS INTEGER)
|
|
DIM T AS LONG
|
|
|
|
IF N = 0 THEN
|
|
JPEG.Shift = I
|
|
I = 0
|
|
EXIT FUNCTION
|
|
END IF
|
|
T = CLNG(I) AND 65535
|
|
|
|
JPEG.Shift = T \ Pow2(N)
|
|
|
|
T = (T AND (Pow2(N) - 1)) * Pow2((16 - N) AND 15)
|
|
IF T AND 32768 THEN I = CINT(T AND 32767&) OR -32768 ELSE I = CINT(T)
|
|
END FUNCTION
|
|
|
|
SUB JPEG.StandardQT (quality AS SINGLE, QT() AS INTEGER)
|
|
|
|
DIM I AS INTEGER, X AS INTEGER, Y AS INTEGER, T AS INTEGER
|
|
RESTORE StandardQT
|
|
|
|
FOR I = 0 TO 1: FOR Y = 0 TO 7: FOR X = 0 TO 7
|
|
READ T
|
|
|
|
QT(X, Y, I) = T * quality
|
|
|
|
IF QT(X, Y, I) = 0 THEN QT(X, Y, I) = 1
|
|
NEXT X, Y, I
|
|
|
|
END SUB
|
|
|
|
FUNCTION JPEG.Y% (R AS INTEGER, G AS INTEGER, B AS INTEGER)
|
|
|
|
JPEG.Y = .299 * R + .587 * G + .114 * B - 128
|
|
|
|
END FUNCTION
|
|
|
|
SUB PutChar (FileNo AS INTEGER, Char AS INTEGER)
|
|
DIM C AS STRING * 1
|
|
C = CHR$(Char)
|
|
PUT FileNo, , C
|
|
END SUB
|