mirror of
https://github.com/aaronsgiles/JPEGView.git
synced 2024-06-11 23:29:29 +00:00
92bdb55672
These are the sources for the final official release of JPEGView for the Mac, back in 1994.
1 line
6.6 KiB
Plaintext
1 line
6.6 KiB
Plaintext
;*********************************************************/
|
|
;* This source code copyright (c) 1991-2001, Aaron Giles */
|
|
;* See the Read Me file for licensing information. */
|
|
;* Contact email: mac@aarongiles.com */
|
|
;*********************************************************/
|
|
|
|
;
|
|
; On entry here we expect the following values:
|
|
;
|
|
; a0 = pointer to the 24-bit source pixmap row
|
|
; a1 = pointer to the 8-bit destination pixmap row
|
|
; a2 = pointer to the inverse color table
|
|
; a3 = pointer to the color table
|
|
; d0 = pointer to the even row dithering buffer
|
|
; d1 = pointer to the odd row dithering buffer
|
|
; d2 = pointer to the region buffer
|
|
; d6 = pointer to the range-limit table
|
|
; d7 = (low word) column count
|
|
;
|
|
; The following registers will be modified:
|
|
;
|
|
; d0,d1,d2,d3,d4,d5,d6,d7
|
|
; a0,a1,a3
|
|
;
|
|
; Internally, the register usage is as follows:
|
|
;
|
|
; d0 = accumulator
|
|
; d1 = accumulator
|
|
; d2 = current sum of red components (<< 4)
|
|
; d3 = current sum of green components (<< 4)
|
|
; d4 = current sum of blue components (<< 4)
|
|
; d5 = (low word) ANDing mask = 0x0ff0
|
|
; d5 = (high word) temporary storage for red error
|
|
; d6 = (low word) region column counter
|
|
; d6 = (high word) temporary storage for green error
|
|
; d7 = (low word) column counter
|
|
; d7 = (high word) temporary storage for blue error
|
|
;
|
|
; a0 = pointer to 24-bit source row
|
|
; a1 = pointer to 8-bit destination row
|
|
; a2 = pointer to inverse color table
|
|
; a3 = pointer to color table
|
|
; a4 = pointer to even dithering buffer
|
|
; a5 = pointer to odd dithering buffer
|
|
; a6 = pointer to region buffer
|
|
;
|
|
|
|
movem.l a5/a6,-(sp) ;save a5/a6 on the stack
|
|
move.l d0,a4 ;get the real a4 from d0
|
|
move.l d1,a5 ;and the real a5 from d1
|
|
move.l d2,a6 ;and the real a6 from d2
|
|
;
|
|
; Initialize our counters and clear out next row
|
|
;
|
|
subq.w #1,d7 ;subtract 1 from the width for dbra
|
|
swap d7 ;swap it high
|
|
clr.w d3 ;clear the leftover dithering: red
|
|
clr.w 0(a5) ;clear the odd row dithering: red
|
|
clr.w d4 ;green
|
|
clr.w 2(a5) ;green
|
|
clr.w d5 ;blue
|
|
clr.w 4(a5) ;blue
|
|
;
|
|
; Set up the region column counter in d7
|
|
;
|
|
move.w (a6)+,d7 ;get region start in d7
|
|
bne.s @EvenStart ;if not zero, skip over this business
|
|
sub.w (a6)+,d7 ;otherwise, subtract the next word
|
|
@EvenStart:
|
|
swap d7 ;swap this information high
|
|
exg.l a6,d6 ;point a6 to the range-limit table
|
|
;
|
|
; Begin main loop here
|
|
;
|
|
@EvenLoop:
|
|
swap d7 ;save the column counter
|
|
;
|
|
; Combine the accumulated errors and round to a pixel value
|
|
;
|
|
add.w (a4)+,d3 ;add dithering from previous row: red
|
|
addq.w #8,d3 ;round if necessary
|
|
asr.w #4,d3 ;divide by 16 to get offset
|
|
move.w 0(a6,d3.w*2),d3 ;range-limit this value
|
|
add.w (a4)+,d4 ;add dithering from previous row: green
|
|
addq.w #8,d4 ;round if necessary
|
|
asr.w #4,d4 ;divide by 16 to get offset
|
|
move.w 0(a6,d4.w*2),d4 ;range-limit this value
|
|
add.w (a4)+,d5 ;add dithering from previous row: blue
|
|
addq.w #8,d5 ;round if necessary
|
|
asr.w #4,d5 ;divide by 16 to get offset
|
|
move.w 0(a6,d5.w*2),d5 ;range-limit this value
|
|
;
|
|
; Offset the current pixel by the errors
|
|
;
|
|
move.l (a0)+,d1 ;get source pixel in d1
|
|
move.w d1,d0 ;copy to d0
|
|
lsr.w #8,d0 ;shift to get the green
|
|
add.w d0,d4 ;add to green total
|
|
move.b d1,d0 ;get blue in d0
|
|
add.w d0,d5 ;add to blue total
|
|
swap d1 ;swap words
|
|
move.b d1,d0 ;get red in d0
|
|
add.w d0,d3 ;add to red total
|
|
;
|
|
; Check for overflows and handle them
|
|
;
|
|
bftst d3{16:8} ;check bits 8-15 for red overflow
|
|
beq.s @RedOK ;if okay, skip
|
|
spl.b d3 ;otherwise, set to ff/00
|
|
andi.w #255,d3 ;clear out the upper bits
|
|
@RedOK:
|
|
bftst d4{16:8} ;check bits 8-15 for green overflow
|
|
beq.s @GreenOK ;if okay, skip
|
|
spl.b d4 ;otherwise, set to ff/00
|
|
andi.w #255,d4 ;clear out the upper bits
|
|
@GreenOK:
|
|
bftst d5{16:8} ;check bits 8-15 for blue overflow
|
|
beq.s @BlueOK ;if okay, skip
|
|
spl.b d5 ;otherwise, set to ff/00
|
|
andi.w #255,d5 ;clear out the upper bits
|
|
@BlueOK:
|
|
;
|
|
; Get the inverse color table entry
|
|
;
|
|
move.w d5,d0 ;get the blue bits in d0
|
|
ror.l #8,d0 ;rotate them off the right side
|
|
move.w d4,d0 ;get the green bits in d0
|
|
lsr.w #3,d0 ;shift off the low three bits
|
|
ror.l #5,d0 ;rotate them off the right side
|
|
move.w d3,d0 ;get the red bits in d0
|
|
lsr.w #3,d0 ;shift off the low three bits
|
|
ror.l #6,d0 ;rotate off the right side
|
|
swap d0 ;swap the result into the low word
|
|
clr.w d1 ;make sure the word in d1 is clear
|
|
move.b 0(a2,d0.w),d1 ;get the inverse ctab entry in d1
|
|
;
|
|
; Determine whether or not to draw this pixel, and handle switches
|
|
;
|
|
tst.w d7 ;is d6 negative?
|
|
bmi.s @EvenStore ;if so, store this value
|
|
addq.w #1,a1 ;skip past the current pixel
|
|
subq.w #1,d7 ;decrement this counter
|
|
bne.s @EvenCont ;if non-zero continue
|
|
exg.l d6,a6 ;swap table/region pointers
|
|
sub.w (a6)+,d7 ;get the negative of the next value
|
|
add.w -4(a6),d7 ;and add the previous one
|
|
exg.l d6,a6 ;swap back
|
|
bra.s @EvenCont ;continue
|
|
@EvenStore:
|
|
move.b d1,(a1)+ ;store the value to the output
|
|
addq.w #1,d7 ;increment the counter
|
|
bne.s @EvenCont ;if non-zero, continue
|
|
exg.l d6,a6 ;swap table/region pointers
|
|
move.w (a6)+,d7 ;get the next value
|
|
sub.w -4(a6),d7 ;minus the previous
|
|
exg.l d6,a6 ;swap back
|
|
;
|
|
; Get the real color for this entry
|
|
;
|
|
@EvenCont:
|
|
move.l 4(a3,d1.w*8),d0 ;get the green & blue components in d0
|
|
lsr.w #8,d0 ;shift 'em down
|
|
sub.w d0,d5 ;subtract from the desired blue
|
|
swap d0 ;get the green
|
|
lsr.w #8,d0 ;shift 'em down
|
|
sub.w d0,d4 ;subtract from the desired green
|
|
move.w 2(a3,d1.w*8),d0 ;get the red comonent
|
|
lsr.w #8,d0 ;shift down by 4
|
|
sub.w d0,d3 ;subtract from the desired red
|
|
;
|
|
; Divide the real color by 16 and set up to calculate odd multiples
|
|
;
|
|
move.w d3,d0 ;copy error to d0-d2: red
|
|
move.w d4,d1 ;green
|
|
move.w d5,d2 ;blue
|
|
add.w d0,d0 ;double it in d0-d2: red
|
|
add.w d1,d1 ;green
|
|
add.w d2,d2 ;blue
|
|
;
|
|
; Store 1/16, 3/16, and 5/16 into next row; leave 7/16 for neighbor
|
|
;
|
|
movem.w d3-d5,6(a5) ;store 1/16 at (+1,+1): red/green/blue
|
|
add.w d0,d3 ;add 2 * error = 3/16: red
|
|
add.w d1,d4 ;green
|
|
add.w d2,d5 ;blue
|
|
add.w d3,-6(a5) ;add 3/16 to (-1,+1): red
|
|
add.w d0,d3 ;add 2 * error = 5/16: red
|
|
add.w d4,-4(a5) ;green
|
|
add.w d1,d4 ;green
|
|
add.w d5,-2(a5) ;blue
|
|
add.w d2,d5 ;blue
|
|
add.w d3,(a5)+ ;add 5/16 to (0,+1): red
|
|
add.w d0,d3 ;add 2 * error = 7/16: red
|
|
add.w d4,(a5)+ ;green
|
|
add.w d1,d4 ;green
|
|
add.w d5,(a5)+ ;blue
|
|
add.w d2,d5 ;blue
|
|
;
|
|
; End of loop: go until done
|
|
;
|
|
swap d7 ;restore column counter
|
|
dbra.w d7,@EvenLoop ;loop until done
|
|
movem.l (sp)+,a5/a6 ;restore a5/a6 from the stack
|