mirror of
https://github.com/aaronsgiles/JPEGView.git
synced 2024-06-11 08:29:29 +00:00
92bdb55672
These are the sources for the final official release of JPEGView for the Mac, back in 1994.
1 line
7.0 KiB
Plaintext
1 line
7.0 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
|
|
; 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,-(a7) ;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
|
|
move.w #4080,d5 ;use d5 as a useful anding mask
|
|
clr.w d2 ;clear the leftover dithering: red
|
|
clr.w 0(a5) ;clear the odd row dithering: red
|
|
clr.w d3 ;green
|
|
clr.w 2(a5) ;green
|
|
clr.w d4 ;blue
|
|
clr.w 4(a5) ;blue
|
|
;
|
|
; Set up the region column counter in d6
|
|
;
|
|
move.w (a6)+,d6 ;get region start in d6
|
|
bne.s @EvenLoop ;if not zero, skip over this business
|
|
sub.w (a6)+,d6 ;otherwise, subtract the next word
|
|
bra.s @EvenLoop ;start by updating the region
|
|
;
|
|
; Clamp over/underflows to 255/0
|
|
;
|
|
@FixRed:
|
|
spl.b d2 ;if negative, set to 0, else set to ff
|
|
lsl.w #4,d2 ;shift up 4 bits
|
|
and.w d5,d2 ;and with d5
|
|
bra.s @RedRet ;return
|
|
@FixGreen:
|
|
spl.b d3 ;if negative, set to 0, else set to ff
|
|
lsl.w #4,d3 ;shift up 4 bits
|
|
and.w d5,d3 ;and with d5
|
|
bra.s @GreenRet ;return
|
|
@FixBlue:
|
|
spl.b d4 ;if negative, set to 0, else set to ff
|
|
lsl.w #4,d4 ;shift up 4 bits
|
|
and.w d5,d4 ;and with d5
|
|
bra.s @BlueRet ;return
|
|
|
|
@EvenLoop:
|
|
swap d7 ;save the column counter
|
|
;
|
|
; Combine the various parts of the dithered pixel
|
|
;
|
|
move.l (a0)+,d1 ;get source pixel
|
|
move.l d1,d0 ;copy to d0
|
|
add.w (a4)+,d2 ;get dithering from previous row: red
|
|
lsl.l #4,d0 ;shift pixel value up by 4
|
|
and.w d5,d0 ;isolate the blue
|
|
add.w d0,d4 ;add to the blue total
|
|
add.w (a4)+,d3 ;get dithering from previous row: green
|
|
swap d0 ;get red part in lower 8 bits
|
|
and.w d5,d0 ;keep only the good bits
|
|
add.w d0,d2 ;add it to the leftover red
|
|
add.w (a4)+,d4 ;get dithering from previous row: blue
|
|
lsr.w #4,d1 ;shift pixel down by 4 (upper 8 bits << 4)
|
|
and.w d5,d1 ;keep only the good bits
|
|
add.w d1,d3 ;add it to the leftover green
|
|
;
|
|
; Round, check for overflows, and handle them
|
|
;
|
|
addq.w #8,d2 ;add 1/2 a pixel to the total
|
|
bftst d2{16:4} ;check bits 12-15 for red overflow
|
|
bne.s @FixRed ;if it's set, fix up the red
|
|
@RedRet:
|
|
addq.w #8,d3 ;add 1/2 a pixel to the total
|
|
bftst d3{16:4} ;check bits 12-15 for green overflow
|
|
bne.s @FixGreen ;if it's set, fix up the green
|
|
@GreenRet:
|
|
addq.w #8,d4 ;add 1/2 a pixel to the total
|
|
bftst d4{16:4} ;check bits 12-15 for blue overflow
|
|
bne.s @FixBlue ;if it's set, fix up the blue
|
|
@BlueRet:
|
|
;
|
|
; Calculate the 16-bit pixel value
|
|
;
|
|
move.w d4,d0 ;get the blue bits in d0
|
|
ror.l #8,d0 ;rotate them off the right side
|
|
ror.l #4,d0 ;(12 bits -- we do it in two steps)
|
|
move.w d3,d0 ;get the green bits in d0
|
|
lsr.w #7,d0 ;shift off the low three bits
|
|
ror.l #5,d0 ;rotate them off the right side
|
|
move.w d2,d0 ;get the red bits in d0
|
|
lsr.w #7,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
|
|
;
|
|
; Determine whether or not to draw this pixel, and handle switches
|
|
;
|
|
tst.w d6 ;is d6 negative?
|
|
bmi.s @EvenStore ;if so, store this value
|
|
addq.w #2,a1 ;skip past the current pixel
|
|
subq.w #1,d6 ;decrement this counter
|
|
bne.s @EvenCont ;if non-zero continue
|
|
sub.w (a6)+,d6 ;get the negative of the next value
|
|
add.w -4(a6),d6 ;and add the previous one
|
|
bra.s @EvenCont ;continue
|
|
@EvenStore:
|
|
move.w d0,(a1)+ ;store the value to the output
|
|
addq.w #1,d6 ;increment the counter
|
|
bne.s @EvenCont ;if non-zero, continue
|
|
move.w (a6)+,d6 ;get the next value
|
|
sub.w -4(a6),d6 ;minus the previous
|
|
;
|
|
; Get the real color for this entry
|
|
;
|
|
@EvenCont:
|
|
move.w d2,d0 ;get red value in d0
|
|
lsr.w #7,d0 ;shift down 7 bits
|
|
move.w d0,d1 ;copy to d1
|
|
lsl.w #5,d0 ;shift back 5 bits
|
|
add.w d0,d1 ;add together
|
|
lsl.w #2,d1 ;shift up two more
|
|
sub.w d1,d2 ;subtract from desired red
|
|
move.w d3,d0 ;get green value in d0
|
|
lsr.w #7,d0 ;shift down 7 bits
|
|
move.w d0,d1 ;copy to d1
|
|
lsl.w #5,d0 ;shift back 5 bits
|
|
add.w d0,d1 ;add together
|
|
lsl.w #2,d1 ;shift up two more
|
|
sub.w d1,d3 ;subtract from desired green
|
|
move.w d4,d0 ;get blue value in d0
|
|
lsr.w #7,d0 ;shift down 7 bits
|
|
move.w d0,d1 ;copy to d1
|
|
lsl.w #5,d0 ;shift back 5 bits
|
|
add.w d0,d1 ;add together
|
|
lsl.w #2,d1 ;shift up two more
|
|
sub.w d1,d4 ;subtract from desired blue
|
|
;
|
|
; Divide the real color by 16 and set up to calculate odd multiples
|
|
;
|
|
swap d5 ;save the 0x0ff0 mask
|
|
swap d6 ;save our region info
|
|
asr.w #4,d2 ;divide the error by 16: red
|
|
asr.w #4,d3 ;green
|
|
asr.w #4,d4 ;blue
|
|
move.w d2,d5 ;copy this value to d5-d7: red
|
|
move.w d3,d6 ;green
|
|
move.w d4,d7 ;blue
|
|
add.w d5,d5 ;double it in d5-d7: red
|
|
add.w d6,d6 ;green
|
|
add.w d7,d7 ;blue
|
|
;
|
|
; Store 1/16, 3/16, and 5/16 into next row; leave 7/16 for neighbor
|
|
;
|
|
movem.w d2-d4,6(a5) ;store 1/16 at (+1,+1): red/green/blue
|
|
add.w d5,d2 ;add 2 * error = 3/16: red
|
|
add.w d6,d3 ;green
|
|
add.w d7,d4 ;blue
|
|
add.w d2,-6(a5) ;add 3/16 to (-1,+1): red
|
|
add.w d5,d2 ;add 2 * error = 5/16: red
|
|
add.w d3,-4(a5) ;green
|
|
add.w d6,d3 ;green
|
|
add.w d4,-2(a5) ;blue
|
|
add.w d7,d4 ;blue
|
|
add.w d2,(a5)+ ;add 5/16 to (0,+1): red
|
|
add.w d5,d2 ;add 2 * error = 7/16: red
|
|
add.w d3,(a5)+ ;green
|
|
add.w d6,d3 ;green
|
|
add.w d4,(a5)+ ;blue
|
|
add.w d7,d4 ;blue
|
|
swap d6 ;restore our region info
|
|
swap d5 ;restore 0x0ff0 mask
|
|
;
|
|
; 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
|