home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ARM Club 3
/
TheARMClub_PDCD3.iso
/
hensa
/
graphics
/
randjpeg_1
/
source
/
s
/
mapchangefsi
Wrap
Text File
|
1996-01-21
|
6KB
|
188 lines
; mapchangefsi.s
; MACHINE: RISC OS
; LANGUAGE: OBJASM assembler
; AUTHOR: Cy Booker, cy@cheepnis.demon.co.uk
; LICENSE: FreeWare, Copyright (c) Cy Booker 1996
; PURPOSE: Given an arbitary 48-bit colour, what is the closest 8-bit colour number?
; assuming the default 256 colour palette
;
; Note the algorithm used is based on the one inside Acorns' ChangeFSI
; but modified slightly by me to be faster and more accurate
;
; ChangeFSI's algorithm is the same as the one posted to UseNet
;
; Message-ID: <12463@acorn.co.uk>
; Date: 30 Jan 92 12:20:23 GMT
; From: RWilson@acorn.co.uk
; Subject: How to find the closest colour out of the RISC OS 256
;
; And so I hereby acknowledge that I'm using their spiffy code
;
; in middle we have |intensity-difference| <-- 0x3fff
; so |i|^2 <= 0x0fff8001
; and so |d|^2 <= 3.|i|^2 <= 0x2ffe8003
; so total scale must be < 2^32/(|d|^2) , ie < ~5
; but this does not leave enough accuracy really, so we shift by a bit
;
; the weights we want are:
; Red * 0.212671 * 14 ~= 3 / 4 ~= 0x0.c
; Green * 0.715160 * 14 ~= 10 / 4 ~= 0x2.8
; Blue * 0.072169 * 14 ~= 1 / 4 ~= 0x0.4
;
; note we will divide by 4 to ensure total < 2^32
; (ie 0x3fff*0x3fff*3*14/2 < 2^32)
;
GET OS:Hdr.os
;
EXPORT map_scaled_rgb_to_8bpp_colour_number_changefsi
IMPORT default_wimp_palette_as_tuples
AREA |ARM$$code|, CODE, READONLY
ROUT
;
; In R0 -> structure
; R1 = red nominally [0, 0xffff], but clipped as necessary
; R2 = green nominally [0, 0xffff], but clipped as necessary
; R3 = blue nominally [0, 0xffff], but clipped as necessary
; Out R0 <-- palette entry %BGgRbrTt (bits 8-31 are zero)
; structure[0] = error in approximating red intensity
; structure[1] = error in approximating green intensity
; structure[2] = error in approximating blue intensity
;
ROUT
map_scaled_rgb_to_8bpp_colour_number_changefsi
str RN a1
red RN a2
grn RN a3
blu RN a4
tint RN v1
dmin RN v2
dist RN v3
colour RN v4
best RN v5
mtint RN v6
x RN ip
y RN lr
dr RN tint
dg RN dmin
db RN dist
bits * 16 ; the inline weighting functions assume bits <= 16
STMFD sp!, {v1-v6, lr}
MOV lr, #1 << bits
CMP red, lr ; ensure in range [0, 0xffff]
MOVHS red, #0
SUBGE red, lr, #1
CMP grn, lr
MOVHS grn, #0
SUBGE grn, lr, #1
CMP blu, lr
MOVHS blu, #0
SUBGE blu, lr, #1
;
MOV dmin, #&ffffffff
MOV tint, #&30 << 23
0
RSB mtint, tint, #&20 << 23
SUB y, blu, blu, LSR #4 ; y ~= blu * 16 / 17
ADDS x, mtint, y, LSL #31 - bits
MOVVSS x, #&c0 << 23
MOVMI x, #0
AND x, x, #&c0 << 23 ; %0Bb0 0000 0000 0000 0000 0000 0000 0000
ADD x, x, tint ; %0BbT t000 0000 0000 0000 0000 0000 0000
ADD colour, x, x, LSR #4 ; colour = blu << 23
[ bits > 8
ADD x, colour, colour, LSR #8 ; %0BbT tBbT tBbT tBbT t000 0000 0000 0000
[ bits > 16
ADD x, x, x, LSR #16 ; %0BbT tBbT tBbT tBbT tBbT tBbT tBbT tBbT
]
]
SUBS y, blu, x, LSR #31 - bits ; bug in changefsi here!
RSBLT y, y, #0 ; speeds up MUL instruction
MUL dist, y, y ; dist = blu * 0x1.0
SUB y, grn, grn, LSR #4
ADDS x, mtint, y, LSL #31 - bits
MOVVSS x, #&c0 << 23
MOVMI x, #0
AND x, x, #&c0 << 23
ADD x, tint, x
ADD x, x, x, LSR #4
ORR colour, colour, x, LSR #8 ; colour |= grn << 15
[ bits > 8
ADD x, x, x, LSR #8
[ bits > 16
ADD x, x, x, LSR #16
]
]
SUBS y, grn, x, LSR #31 - bits
RSBLT y, y, #0
MUL x, y, y
MOV x, x, LSL #1
ADD dist, x, dist, LSR #2 ; dist = blu * 0x0.4 + grn * 0x2.0
ADD dist, dist, x, LSR #3 ; dist = blu * 0x0.4 + grn * 0x2.8
SUB y, red, red, LSR #4
ADDS x, mtint, y, LSL #31 - bits
MOVVSS x, #&c0 << 23
MOVMI x, #0
AND x, x, #&c0 << 23
ADD x, tint, x
ADD x, x, x, LSR #4
ORR colour, colour, x, LSR #16 ; colour |= red << 7
[ bits > 8
ADD x, x, x, LSR #8
[ bits > 16
ADD x, x, x, LSR #16
]
]
SUBS y, red, x, LSR #31 - bits
RSBLT y, y, #0
MULNE x, y, y
ADDNE dist, dist, x, LSR #2 ; dist = blu * 0x0.4 + grn * 0x2.8 + red * 0x0.4
ADDNE dist, dist, x, LSR #1 ; dist = blu * 0x0.4 + grn * 0x2.8 + red * 0x0.c
CMP dist, dmin
MOVLS dmin, dist
MOVLS best, colour
SUBS tint, tint, #&10 << 23
BGE %BT0
MOVS x, best, LSR #11
AND x, x, #&07 ; x= %00000rTt
ORRCS x, x, #&10 ; x= %000R0rTt
MOVS y, best, LSL #2
ORRCS x, x, #&80 ; x= %B00R0rTt
ORRMI x, x, #&08 ; x= %B00RbrTt
ANDS y, best, #&c0 << 15
ORRNE x, x, y, LSR #16 ; y= %BGgRbrTt
LDR y, =default_wimp_palette_as_tuples
ADD y, y, x, LSL #2
ADD y, y, x, LSL #3
LDMIA y, {dr, dg, db}
SUB red, red, dr
SUB grn, grn, dg
SUB blu, blu, db
STMIA str, {red, grn, blu} ; store error
MOV a1, x
LDMFD sp!, {v1-v6, pc}^
END