JPEGView/Source/68020/DitherCopyTo8Even.a
Aaron Giles 92bdb55672 JPEGView 3.3 for Macintosh
These are the sources for the final official release of JPEGView for the
Mac, back in 1994.
2015-02-05 00:18:10 -08:00

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