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
22 KiB
Plaintext
1 line
22 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:
|
|
;
|
|
; srcBase = (long) pointer to the first source pixel
|
|
; srcRow = (long) rowBytes for the source pixmap
|
|
; dstBase = (long) pointer to the first destination pixel
|
|
; dstRow = (long) rowBytes for the destination pixmap
|
|
; itAddr = (long) pointer to the inverse color table
|
|
; ctAddr = (long) pointer to the color table
|
|
; theRgn = (long) handle to the destination region
|
|
; boxRect = (Rect) the bounding rectangle of this region
|
|
; height = (word) height of the region bounding box
|
|
; width = (word) width of the region bounding box
|
|
; srcWidth = (word) width of the source rectangle
|
|
; srcHeight = (word) height of the source rectangle
|
|
; dstWidth = (word) width of the destination rectangle
|
|
; dstHeight = (word) height of the destination rectangle
|
|
; xRemainder = (word) starting X remainder for the source counter
|
|
; yRemainder = (word) starting Y remainder for the source counter
|
|
;
|
|
; The following registers will be modified:
|
|
;
|
|
; d0,d1,d2
|
|
; a0,a1
|
|
;
|
|
; Internally, the register usage is as follows:
|
|
;
|
|
; d0 = accumulator
|
|
; d1 = scratch register for expanding 24-bit pixels
|
|
; d2 = scratch [save for d6.l/d7.l]
|
|
; d3 = scratch [multiplier for xy-scale]
|
|
; d4 = (low word) remaining source Y pixels needed for current dest. Y
|
|
; d4 = (high word) dstHeight/srcHeight
|
|
; d5 = (low word) remaining Y fraction of current source pixel
|
|
; d5 = (high word) 1.00
|
|
; d6 = (low word) remaining source Y pixels needed for current dest. X
|
|
; d6 = (high word) dstWidth/srcWidth
|
|
; d7 = (low word) remaining Y fraction of current source pixel
|
|
; d7 = (high word) scratch [save for d5.l]
|
|
;
|
|
; a0 = pointer to 24-bit source row
|
|
; a1 = pointer to 8-bit destination row
|
|
; a2 = sum of the red contributions
|
|
; a3 = sum of the green contributions
|
|
; a4 = sum of the blue contributions
|
|
; a5 = temporary save area for a0
|
|
;
|
|
movem.l d3-d7/a2-a6,-(sp) ;save registers on the stack
|
|
move.l 48(sp),a6 ;get the address of the CopyData structure in a6
|
|
;(based off stack: 10 registers + 1 a6 link + 1 return addr.
|
|
; = 12 * 4 bytes = 48 bytes)
|
|
;
|
|
; Create some room in the stack for our buffers
|
|
;
|
|
clr.l d0 ;zero out d0
|
|
move.w width(a6),d0 ;get width of destination in d0.l
|
|
addq.l #2,d0 ;plus two for overflows
|
|
lsl.l #4,d0 ;times 16 (2 * 6 + 4)
|
|
addq.l #4,d0 ;add 4 for alignment
|
|
sub.l d0,sp ;get it from the stack space
|
|
move.l d0,-(sp) ;and save the amount
|
|
lsr.l #3,d0 ;return to times 2
|
|
move.l d0,d1 ;save that in d1
|
|
lsl.l #1,d0 ;d0 = width * 4
|
|
add.l d1,d0 ; = width * 6
|
|
moveq.l #13,d1 ;offset by 10, plus 3 for rounding up
|
|
add.l sp,d1 ;add in the stack pointer
|
|
andi.l #-4,d1 ;make it longword-aligned (-4 == $fffffffc)
|
|
move.l d1,evenAddr(a6) ;that's the even buffer
|
|
add.l d0,d1 ;point to the odd buffer
|
|
move.l d1,oddAddr(a6) ;save that pointer
|
|
add.l d0,d1 ;point to the scale buffer
|
|
move.l d1,outputAddr(a6) ;now we've got them all
|
|
;
|
|
; Clear the dithering buffers to zeros
|
|
;
|
|
move.l evenAddr(a6),a0 ;point to the evenBuffer
|
|
subq.l #4,d1 ;decrement d1 for the dbra, plus the extras
|
|
@ClearLoop:
|
|
clr.w (a0)+ ;clear this word
|
|
dbra.w d0,@ClearLoop ;loop for all dithering
|
|
;
|
|
; Initialize the region data
|
|
;
|
|
move.l theRgn(a6),a0 ;get theRgn in a0
|
|
lea.l rgnBuffer(a6),a1 ;point a1 to the region buffer
|
|
move.w boxRect+0(a6),d2 ;get box top in d2
|
|
move.w boxRect+2(a6),d3 ;box left in d3
|
|
move.w height(a6),d4 ;height in d4
|
|
move.w width(a6),d5 ;width in d5
|
|
jsr InitRegion ;initialize the region
|
|
move.l a0,-(sp) ;store our pointer to the rgn on the stack
|
|
;
|
|
; Set up the source/destination quantities in the high words of d4-d7
|
|
;
|
|
clr.l d6 ;clear out d6
|
|
move.w dstHeight(a6),d6 ;get dest height there
|
|
moveq.l #10,d0 ;get shift value in d0
|
|
lsl.l d0,d6 ;shift it up by 10 bits
|
|
divu.w srcHeight(a6),d6 ;divide by source height
|
|
addq.w #1,d6 ;plus one to prevent overflows
|
|
swap d6 ;swap it high
|
|
clr.l d4 ;clear out d4
|
|
move.w dstWidth(a6),d4 ;get destination width in d4
|
|
lsl.l d0,d4 ;shift d6 up by 10 bits
|
|
divu.w srcWidth(a6),d4 ;divide by source width
|
|
addq.w #1,d4 ;plus one to prevent overflows
|
|
swap d4 ;into high word of d6
|
|
;
|
|
; Set up the counter "rows" & reset the source Y remainder
|
|
;
|
|
move.w height(a6),rows(a6) ;set up the row counter
|
|
move.w yRemainder(a6),d5 ;restore yRemainder
|
|
;
|
|
; The outermost (row) loop begins here; set up our pointers into the data
|
|
;
|
|
@ScaleRowLoop:
|
|
move.l srcBase(a6),a0 ;get pointer to source in a0
|
|
move.l outputAddr(a6),a1 ;put to destination with a1
|
|
;
|
|
; Reset the "columns" counter and reset the source X remainder
|
|
;
|
|
move.w width(a6),columns(a6);reset the column counter
|
|
move.w xRemainder(a6),d7 ;restore xRemainder
|
|
move.w #512,d3 ;set up our threshhold (512 == $200)
|
|
;
|
|
; The inner (column) loop begins here; set up our counters in the destination system
|
|
;
|
|
@ScaleColLoop:
|
|
move.w #1024,d6 ;initialize our X counter (1024 == $400)
|
|
move.w d6,d4 ;initialize our Y counter
|
|
;
|
|
; Determine what sort of scaling is best for us
|
|
;
|
|
cmp.w d4,d5 ;can we avoid Y scaling?
|
|
bge.s @NoYScale ;if so, check X as well
|
|
cmp.w d6,d7 ;can we at least avoid X scaling?
|
|
blt.w @ScaleXY ;if not, scale in both
|
|
bra.w @ScaleY ;otherwise, scale in Y only
|
|
@NoYScale:
|
|
cmp.w d6,d7 ;do we have to scale in X?
|
|
bge.w @NoScale ;if not, do it quick
|
|
bra.w @ScaleX ;otherwise, just scale X
|
|
;
|
|
; Special case "divides": table lookups <= 8, 1 or 0
|
|
;
|
|
@ScaleColFast:
|
|
addq.w #5,d2 ;restore divisor back to 0-5
|
|
lea sTable(a6),a4 ;point a4 to the table
|
|
move.l 0(a4,d2.w*4),a4 ;look up the longword address
|
|
clr.l d1 ;zero out the accumulator
|
|
move.l a2,d0 ;get red/blue into d0
|
|
move.b 0(a4,d0.w),d1 ;get the red part
|
|
lsl.l #8,d1 ;shift it up 8 bits
|
|
swap d2 ;put green dividend low
|
|
move.b 0(a4,d2.w),d1 ;get the green part
|
|
lsl.l #8,d1 ;shift it up 8 bits
|
|
swap d0 ;put blue dividend low
|
|
move.b 0(a4,d0.w),d1 ;get the blue part
|
|
move.l d1,(a1)+ ;store it in memory
|
|
bra.s @ScaleColSkip ;skip back to the main loop
|
|
@ScaleCol210:
|
|
addq.w #1,d2 ;add 1 back
|
|
bne.s @ScaleCol10 ;if not zero now, try for 1
|
|
swap d2 ;swap d2's words
|
|
lsr.w #1,d2 ;divide by 2
|
|
move.l a2,d1 ;get red/blue parts
|
|
swap d1 ;swap them into the right order
|
|
lsr.l #1,d1 ;shift those down by 1 bit
|
|
ror.l #8,d1 ;rotate down 8 bits
|
|
move.b d2,d1 ;copy in the green
|
|
rol.l #8,d1 ;rotate back
|
|
move.l d1,(a1)+ ;copy that
|
|
bra.s @ScaleColSkip ;skip back to the main loop
|
|
@ScaleCol10:
|
|
addq.w #1,d2 ;add 1 back
|
|
bne.s @ScaleColCopy ;if not zero now, must be 0
|
|
swap d2 ;swap d2's words
|
|
lsl.w #8,d2 ;shift it up 8 bits
|
|
move.l a2,d1 ;get red/blue parts
|
|
swap d1 ;swap them into the right order
|
|
or.w d2,d1 ;or the green into them
|
|
move.l d1,(a1)+ ;copy that
|
|
bra.s @ScaleColSkip ;skip back to the main loop
|
|
@ScaleColCopy:
|
|
move.l (a0),(a1)+ ;just copy last pixel
|
|
bra.s @ScaleColSkip ;skip back to main loop
|
|
;
|
|
; End of the columns loop here; decrement counters and loop until done
|
|
;
|
|
@ScaleColEnd:
|
|
move.l a3,d2 ;get a3 into d2
|
|
subq.w #3,d2 ;subtract off 3
|
|
bmi.s @ScaleCol210 ;if negative, either 2, 1 or 0 pixels
|
|
subq.w #5,d2 ;subtract off 5 more
|
|
ble.s @ScaleColFast ;if negative, do table look-up
|
|
addq.w #8,d2 ;otherwise, restore our divisor
|
|
move.l d2,d0 ;copy d2 to d0
|
|
clr.w d0 ;clear out the divisor
|
|
swap d0 ;get the green part low
|
|
divu.w d2,d0 ;divide by d2
|
|
clr.l d1 ;clear out d1 for storage
|
|
lsl.l #8,d0 ;shift green into place
|
|
move.w d0,d1 ;move it into d1
|
|
move.l a2,d0 ;get red/blue into d0
|
|
clr.w d0 ;zero out red part
|
|
swap d0 ;swap blue down
|
|
divu.w d2,d0 ;divide by d2
|
|
move.b d0,d1 ;store low-order byte
|
|
move.l a2,d0 ;get red/blue again in d0
|
|
swap d0 ;swap halves
|
|
clr.w d0 ;clear out the blue
|
|
swap d0 ;swap red back
|
|
divu.w d2,d0 ;divide by d2
|
|
swap d0 ;swap it back high
|
|
clr.w d0 ;zero the remainder
|
|
or.l d0,d1 ;or into the final result
|
|
move.l d1,(a1)+ ;store it in memory
|
|
@ScaleColSkip:
|
|
subq.w #1,columns(a6) ;decrement columns
|
|
bne.w @ScaleColLoop ;loop if not done
|
|
;
|
|
; We now have a row; save our registers and set up to do a dithered copy
|
|
;
|
|
movem.l d4-d7,-(sp) ;save registers
|
|
move.l outputAddr(a6),a0 ;source here
|
|
move.l dstBase(a6),a1 ;get destination address
|
|
move.l itAddr(a6),a2 ;inverse color table
|
|
move.l ctAddr(a6),a3 ;color table
|
|
lea.l rgnBuffer+4(a6),a4 ;get rgnBuffer address in a4
|
|
move.l a4,d2 ;point d2 (a6) to the region buffer
|
|
move.l evenAddr(a6),d0 ;even address
|
|
move.l oddAddr(a6),d1 ;odd address
|
|
move.l errTable(a6),d6 ;point d6 to the error table
|
|
move.w width(a6),d7 ;column count
|
|
bchg.b #0,evodd+1(a6) ;check the even/odd flag
|
|
beq.s @ScaleEven ;if zero, do an even row
|
|
move.l odd(a6),a4 ;get address of routine
|
|
jsr (a4) ;otherwise, dither as an odd row
|
|
bra.s @ScaleRowEnd ;skip ahead
|
|
@ScaleEven:
|
|
move.l even(a6),a4 ;get address of routine
|
|
jsr (a4) ;dither as an even row
|
|
@ScaleRowEnd:
|
|
movem.l (sp)+,d4-d7 ;restore registers
|
|
;
|
|
; Adjust ourselves for the next row
|
|
;
|
|
subq.w #1,rows(a6) ;decrement rows
|
|
beq.w @ScaleExit ;exit if done
|
|
move.l dstRow(a6),d0 ;get destination row increment in d0
|
|
add.l d0,dstBase(a6) ;point to next destination row
|
|
move.l srcRow(a6),d0 ;get source row increment in d0
|
|
move.w #1024,d4 ;get 1.00 count in d4 (1024 == $400)
|
|
swap d6 ;swap d6 beforehand for speed
|
|
@ScaleIncRow:
|
|
cmp.w d4,d5 ;did we upgrade 1 row?
|
|
bgt.s @ScaleRowNext ;if not, loop
|
|
add.l d0,srcBase(a6) ;point to next source row
|
|
sub.w d5,d4 ;adjust Y for remainder
|
|
move.w d6,d5 ;reset Y count for the new pixel
|
|
bra.s @ScaleIncRow ;handle any further adjustments
|
|
@ScaleRowNext:
|
|
swap d6 ;restore d6
|
|
sub.w d4,d5 ;get the new Y multiplier
|
|
;
|
|
; Update the region counters
|
|
;
|
|
subq.w #1,rgnBuffer(a6) ;decrement the Y region count
|
|
bne.w @ScaleRowLoop ;skip if we're not done
|
|
move.l (sp)+,a0 ;restore region pointer
|
|
lea.l rgnBuffer+4(a6),a1 ;point a1 into the region buffer
|
|
move.w boxRect+2(a6),d0 ;get left end of the box in d0
|
|
jsr UpdateRegion ;update our region
|
|
move.l a0,-(sp) ;push new position again
|
|
bra.w @ScaleRowLoop ;loop for more
|
|
|
|
;------------------------- NoScale ---------------------------
|
|
|
|
@NoScale:
|
|
move.l (a0),(a1)+ ;just copy src->dest
|
|
sub.w d6,d7 ;adjust for remainder
|
|
bra.w @ScaleColSkip ;loop for another
|
|
|
|
;------------------------- ScaleX ----------------------------
|
|
|
|
@ScaleX:
|
|
clr.l d0 ;clear out d0
|
|
move.l d0,a2 ;zero out the colors: red/blue
|
|
move.l d0,a3 ;green/counter
|
|
swap d4 ;swap our update to X low here
|
|
|
|
cmp.w d3,d7 ;are we below the lower threshhold?
|
|
blt.s @SXSkip1 ;if so, skip entirely
|
|
move.l (a0),d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
@SXSkip1:
|
|
addq.l #4,a0 ;point to the next pixel
|
|
sub.w d7,d6 ;adjust the counter
|
|
|
|
cmp.w d6,d4 ;do we include a whole pixel now?
|
|
bgt.s @SXSkip2 ;if not, skip
|
|
@SXLoop2:
|
|
move.l (a0)+,d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
add.l d0,a2 ;add again: red/blue
|
|
add.l d1,a3 ;green/count
|
|
sub.w d4,d6 ;adjust the counter
|
|
cmp.w d6,d4 ;do we include a whole pixel now?
|
|
ble.s @SXLoop2 ;if so, loop again
|
|
@SXSkip2:
|
|
|
|
cmp.w d3,d6 ;are we below the lower threshhold?
|
|
blt.s @SXSkip3 ;if so, skip entirely
|
|
move.l (a0),d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
@SXSkip3:
|
|
move.w d4,d7 ;set up source remainder
|
|
sub.w d6,d7 ;adjust it
|
|
swap d4 ;swap d4 back
|
|
bra.w @ScaleColEnd ;loop for the next pixel
|
|
|
|
;------------------------- ScaleY ----------------------------
|
|
|
|
@ScaleY:
|
|
clr.l d0 ;clear out d0
|
|
move.l d0,a2 ;zero out the colors: red/blue
|
|
move.l d0,a3 ;green/counter
|
|
swap d6 ;swap our update to Y low here
|
|
move.l a0,a4 ;copy a0 into a4 for storage
|
|
move.l srcRow(a6),d2 ;get source row into d2 for speed
|
|
swap d7 ;swap d7 high
|
|
move.w d5,d7 ;save d5 into high word
|
|
swap d7 ;restore d7 now
|
|
|
|
cmp.w d3,d5 ;are we below the lower threshhold?
|
|
blt.s @SYSkip1 ;if so, skip entirely
|
|
move.l (a0),d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
@SYSkip1:
|
|
add.l d2,a0 ;point to the next row
|
|
sub.w d5,d4 ;adjust Y for remainder
|
|
|
|
cmp.w d4,d6 ;do we have a whole pixel to add?
|
|
bgt.s @SYSkip2 ;if not, skip
|
|
@SYLoop2:
|
|
move.l (a0),d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
add.l d2,a0 ;point to the next row
|
|
sub.w d6,d4 ;adjust Y for remainder
|
|
cmp.w d4,d6 ;do we have a whole pixel to add?
|
|
ble.s @SYLoop2 ;if not, skip
|
|
@SYSkip2:
|
|
|
|
cmp.w d3,d4 ;are we below the lower threshhold?
|
|
blt.s @SYSkip3 ;if so, skip entirely
|
|
move.l (a0),d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
@SYSkip3:
|
|
move.w d6,d5 ;reset the source remainder
|
|
sub.w d4,d5 ;adjust Y for remainder
|
|
|
|
swap d6 ;swap d6 back
|
|
swap d7 ;swap d7 high
|
|
move.w d7,d5 ;restore original d5 here
|
|
swap d7 ;restore d7
|
|
move.l a4,a0 ;restore original a0 here
|
|
sub.w d6,d7 ;adjust X for remainder
|
|
bra.w @ScaleColEnd ;loop for the next pixel
|
|
|
|
;------------------------- ScaleXY ----------------------------
|
|
|
|
@ScaleXY:
|
|
clr.l d0 ;clear out d0
|
|
move.l d0,a2 ;zero out the colors: red/blue
|
|
move.l d0,a3 ;green/counter
|
|
move.l a0,a5 ;save a0 in a5
|
|
swap d7 ;swap d7
|
|
move.w d5,d7 ;save d5.l there
|
|
swap d7 ;safely in the high word
|
|
move.w d7,d2 ;save d7 in d2
|
|
|
|
;
|
|
; Handle Y section 1
|
|
;
|
|
cmp.w d3,d5 ;are we below the lower threshhold in Y?
|
|
blt.s @SXYSkipY1 ;if so, skip entirely
|
|
move.l a0,a4 ;copy a0 to a4 for now
|
|
swap d4 ;swap d4 low for fast access
|
|
|
|
cmp.w d3,d7 ;are we below the lower threshhold in X?
|
|
blt.s @SXYSkipY1X1 ;if so, skip entirely
|
|
move.l (a0),d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
@SXYSkipY1X1:
|
|
addq.l #4,a0 ;point to the next pixel
|
|
sub.w d7,d6 ;adjust the counter
|
|
|
|
cmp.w d6,d4 ;do we include a whole pixel now?
|
|
bgt.s @SXYSkipY1X2 ;if not, skip
|
|
@SXYLoopY1X2:
|
|
move.l (a0)+,d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
sub.w d4,d6 ;adjust the counter
|
|
cmp.w d6,d4 ;do we include a whole pixel now?
|
|
ble.s @SXYLoopY1X2 ;if so, loop again
|
|
@SXYSkipY1X2:
|
|
|
|
cmp.w d3,d6 ;are we below the lower threshhold?
|
|
blt.s @SXYSkipY1X3 ;if so, skip entirely
|
|
move.l (a0),d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
@SXYSkipY1X3:
|
|
swap d4 ;swap d4 back
|
|
move.w #1024,d6 ;restore source counter in d6 (1024 == $400)
|
|
move.w d2,d7 ;restore source remainder in d7
|
|
movea.l a4,a0 ;restore a0
|
|
|
|
@SXYSkipY1:
|
|
add.l srcRow(a6),a0 ;point to the next row
|
|
sub.w d5,d4 ;adjust Y for remainder
|
|
|
|
;
|
|
; Handle Y section 2
|
|
;
|
|
swap d6 ;get src pixel contribution in d6
|
|
cmp.w d4,d6 ;still another whole pixel in Y to go?
|
|
bgt.s @SXYSkipY2 ;if not, skip over this section
|
|
|
|
@SXYLoopY2:
|
|
swap d6 ;swap d6 back
|
|
move.l a0,a4 ;copy a0 to a4 for now
|
|
swap d4 ;swap d4 low for fast access
|
|
|
|
cmp.w d3,d7 ;are we below the lower threshhold in X?
|
|
blt.s @SXYSkipY2X1 ;if so, skip entirely
|
|
move.l (a0),d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
@SXYSkipY2X1:
|
|
addq.l #4,a0 ;point to the next pixel
|
|
sub.w d7,d6 ;adjust the counter
|
|
|
|
cmp.w d6,d4 ;do we include a whole pixel now?
|
|
bgt.s @SXYSkipY2X2 ;if not, skip
|
|
@SXYLoopY2X2:
|
|
move.l (a0)+,d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
add.l d0,a2 ;add again: red/blue
|
|
add.l d1,a3 ;green/count
|
|
sub.w d4,d6 ;adjust the counter
|
|
cmp.w d6,d4 ;do we include a whole pixel now?
|
|
ble.s @SXYLoopY2X2 ;if so, loop again
|
|
@SXYSkipY2X2:
|
|
|
|
cmp.w d3,d6 ;are we below the lower threshhold?
|
|
blt.s @SXYSkipY2X3 ;if so, skip entirely
|
|
move.l (a0),d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
@SXYSkipY2X3:
|
|
swap d4 ;swap d4 back
|
|
move.w #1024,d6 ;restore source counter in d6 (1024 == $400)
|
|
move.w d2,d7 ;restore source remainder in d7
|
|
movea.l a4,a0 ;restore a0
|
|
add.l srcRow(a6),a0 ;point to the next row
|
|
swap d6 ;get src pixel contribution in d6
|
|
sub.w d6,d4 ;adjust Y for remainder
|
|
cmp.w d4,d6 ;still another whole pixel in Y to go?
|
|
ble.s @SXYLoopY2 ;if so, loop for more
|
|
|
|
@SXYSkipY2:
|
|
swap d6 ;put d6 back to normal
|
|
|
|
;
|
|
; Handle Y section 3
|
|
;
|
|
sub.l a0,a5 ;subtract current a0 from original in a5
|
|
swap d4 ;swap d4 low for fast access
|
|
cmp.w d3,d4 ;are we below the lower threshhold in Y?
|
|
blt.s @SXYSkipY3 ;if so, skip entirely
|
|
|
|
cmp.w d3,d7 ;are we below the lower threshhold in X?
|
|
blt.s @SXYSkipY3X1 ;if so, skip entirely
|
|
move.l (a0),d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
@SXYSkipY3X1:
|
|
addq.l #4,a0 ;point to the next pixel
|
|
sub.w d7,d6 ;adjust the counter
|
|
|
|
cmp.w d6,d4 ;do we include a whole pixel now?
|
|
bgt.s @SXYSkipY3X2 ;if not, skip
|
|
@SXYLoopY3X2:
|
|
move.l (a0)+,d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
sub.w d4,d6 ;adjust the counter
|
|
cmp.w d6,d4 ;do we include a whole pixel now?
|
|
ble.s @SXYLoopY3X2 ;if so, loop again
|
|
@SXYSkipY3X2:
|
|
|
|
cmp.w d3,d6 ;are we below the lower threshhold?
|
|
blt.s @SXYSkipY3X3 ;if so, skip entirely
|
|
move.l (a0),d1 ;get next pixel
|
|
swap d1 ;swap halves
|
|
move.l d1,d0 ;copy into d0
|
|
lsr.l #8,d1 ;shift green part into bits 16-23
|
|
andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff)
|
|
move.w #1,d1 ;put a 1 in d1's lower word
|
|
add.l d0,a2 ;add into totals: red/blue
|
|
add.l d1,a3 ;green/count
|
|
@SXYSkipY3X3:
|
|
|
|
@SXYContinue:
|
|
move.w d4,d7 ;restore X source fraction
|
|
swap d4 ;swap d4 back
|
|
sub.w d6,d7 ;adjust X for remainder
|
|
swap d7 ;swap d7's words
|
|
move.w d7,d5 ;restore d5
|
|
swap d7 ;put things back
|
|
adda.l a5,a0 ;point back to original row
|
|
bra.w @ScaleColEnd ;scale the values & loop
|
|
|
|
@SXYSkipY3:
|
|
addq.l #4,a0 ;point to the next pixel
|
|
sub.w d7,d6 ;adjust the counter
|
|
@SXYLoopY3:
|
|
cmp.w d6,d4 ;do we include a whole pixel now?
|
|
bgt.s @SXYContinue ;if not, skip
|
|
addq.l #4,a0 ;point to the next pixel
|
|
sub.w d4,d6 ;adjust the counter
|
|
bra.s @SXYLoopY3 ;loop for more
|
|
|
|
@ScaleExit:
|
|
add.l #4,sp ;pop off region position
|
|
move.l (sp)+,d0 ;get length of buffer
|
|
add.l d0,sp ;get it off the stack
|
|
movem.l (sp)+,d3-d7/a2-a6 ;get registers from the stack
|