; ; This source handles conversion from yuv to rgb space, which includes ; initialization of the conversion & clamp tables. ; ; Original routines are in 24bit.c, which mainly contained those lovely ; just-perfectly-fit-for-assembler-kick-ass constructions. ; ; Michael Rausch 14-4-94 1:12:57 ; SECTION text,CODE ;************************************************************************************ ; We'll define the "ConvertColor" macro here to do fixed point arithmetic ; that'll convert from YCrCb to RGB using: ; R = L + 1.40200*Cr ; G = L - 0.34414*Cb - 0.71414*Cr ; B = L + 1.77200*Cb ; ; void InitColorDither(void) XDEF @InitColorDither @InitColorDither: lea Cb_r_tab,a0 Cr_gb_off EQU 256*4 lea Cb_r_tab+Cr_gb_off,a1 move.w #255,d0 moveq #-128,d1 crgbtabs: move.w d1,d2 muls.w #179,d2 ; 1.40200 asr.w #7,d2 add.w d2,d2 move.w d2,(a0)+ ;br move.w d1,d2 muls.w #-91,d2 ; -0.71414 asr.w #7,d2 add.w d2,d2 move.w d2,(a1)+ ;bg move.w d1,d2 muls.w #-44,d2 ; -0.34414 asr.w #7,d2 add.w d2,d2 move.w d2,(a0)+ ;rg move.w d1,d2 muls.w #226,d2 ; 1.77200 asr.w #7,d2 add.w d2,d2 move.w d2,(a1)+ ;rb addq.l #1,d1 dbra d0,crgbtabs ; ; create the clamp tables, including the shifted one ; ; IMPORTANT: The first versions had a MUCH too low clampsize, resulting in really ; annoying purple artifacts !!! ; clampsize EQU 192 moveq #0,d1 lea _clamp-clampsize*2,a0 ; clear lower and upper 64 bytes move.w #clampsize-1,d0 fill_ct1:move.w #$ff00,((clampsize+256)*2,a0) move.w d1,(a0)+ dbra d0,fill_ct1 move.w #255,d0 fill_ct2:move.w d1,(a0)+ add.w #$100,d1 dbra d0,fill_ct2 rts ;************************************************************************************ ;void ColorDitherImage(unsigned char *lum, unsigned char *cr, unsigned char *cb, ; unsigned char *out, int rows, int cols) XDEF @ColorDitherImage_lores @ColorDitherImage_lores: ; a0 unsigned char *lum ; a1 unsigned char *cr ; 4(sp) unsigned char *cb ; 8(sp) unsigned char *out ; d0 int rows ; d1 int cols cdi_regs REG d2-d7/a2-a6 ; 6+5=11 movem.l cdi_regs,-(sp) ;saved7 EQU 0 saverows EQU 4 savecols EQU 8 localvars EQU savecols+4 cb_offset EQU localvars+11*4+4 out_offset EQU cb_offset+4 sub.w #localvars,sp move.l d1,(savecols,sp) lsr.l #1,d0 subq.l #1,d0 move.l d0,d7 move.l a0,a2 ; lum1 move.l a2,a3 add.l d1,a3 ; lum2 = lum1+cols move.l a1,a4 ; cr channel move.l cb_offset(sp),d5 sub.l a4,d5 ; cb channel is addressed via its offset to the cr channel lea Cb_r_tab,a5 ; conversion tab(s) move.l (out_offset,sp),a0 ; row1 move.l a0,a1 add.l d1,d1 add.l d1,a1 ; row2=row1+cols*2 all_rows_lores: move.l (savecols,sp),d6 lsr.l #1,d6 subq.l #1,d6 all_cols_lores: ; free: d4 moveq #0,d1 moveq #0,d2 move.b (a4,d5.l),d1 ; CB channel move.b (a4)+,d2 ; CR channel move.l (a5,d1.w*4),d0 ; cb_r cb_g move.l (Cr_gb_off,a5,d2.w*4),d1 ; cr_g cr_b move.w d1,d2 swap d1 add.w d0,d1 swap d0 sub.w d1,d0 sub.w d1,d2 ext.l d1 add.l #_clamp,d1 ; d0 cb_r *2 ; d1 (cr_g+cb_g) *2 ; d2 cr_b *2 moveq #0,d3 ; *lum++ move.b (a2)+,d3 move.l d1,a6 ; clamp table includes on L add.l d3,d3 add.l d3,a6 move.w (a6,d0.w),d3 ; r or.b (a6),d3 ; g swap d3 move.b (a2)+,d3 ; *lum++ move.l d1,a6 ; clamp table includes on L add.w d3,d3 add.w d3,a6 move.w (a6,d2.w),d3 ; b or.b (a6),d3 ; g move.l d3,(a0)+ ; *row1++ moveq #0,d3 ; *lum++ move.b (a3)+,d3 move.l d1,a6 ; clamp table includes on L add.l d3,d3 add.l d3,a6 move.w (a6,d0.w),d3 ; r move.b (a6),d3 ; g swap d3 move.b (a3)+,d3 ; *lum++ move.l d1,a6 ; clamp table includes on L add.w d3,d3 add.w d3,a6 move.w (a6,d2.w),d3 ; b move.b (a6),d3 ; g move.l d3,(a1)+ ; *row1++ dbra d6,all_cols_lores move.l savecols(sp),d0 ; next line in the luminance channel add.l d0,a2 add.l d0,a3 add.l d0,d0 ; 2 bytes per pixel add.l d0,a0 ; next line in the output row add.l d0,a1 dbra d7,all_rows_lores add.w #localvars,sp movem.l (sp)+,cdi_regs rts ;************************************************************************************ XDEF @ColorDitherImage_RGB @ColorDitherImage_RGB: movem.l cdi_regs,-(sp) sub.w #localvars,sp move.l d1,(savecols,sp) lsr.l #1,d0 subq.l #1,d0 move.l d0,d7 move.l a0,a2 ; lum1 move.l a2,a3 add.l d1,a3 ; lum2 = lum1+cols move.l a1,a4 ; cr channel move.l cb_offset(sp),d5 sub.l a4,d5 ; cb channel is addressed via its offset to the cr channel lea Cb_r_tab,a5 ; conversion tab(s) move.l (out_offset,sp),a0 ; row1 move.l a0,a1 lsl.l #2,d1 add.l d1,a1 ; row2=row1+cols*4 all_rows_rgb: move.l (savecols,sp),d6 lsr.l #1,d6 subq.l #1,d6 all_cols_rgb: ; still free: d4 moveq #0,d1 moveq #0,d2 move.b (a4,d5.l),d1 ; CB channel move.b (a4)+,d2 ; CR channel move.l (a5,d1.w*4),d0 ; cb_r cb_g move.l (Cr_gb_off,a5,d2.w*4),d1 ; cr_g cr_b move.w d1,d2 swap d1 add.w d0,d1 swap d0 sub.w d2,d0 sub.w d2,d1 ext.l d2 add.l #_clamp,d2 exg a4,d2 ; d0 cb_r *2 ; d1 (cr_g+cb_g) *2 ; d2 cr_b *2 moveq #0,d3 ; *lum++ move.b (a2)+,d3 lea (a4,d3.w*2),a6 move.b (a6,d0.w),d3 swap d3 move.w (a6,d1.w),d3 move.b (a6),d3 move.l d3,(a0)+ moveq #0,d3 ; *lum++ move.b (a2)+,d3 lea (a4,d3.w*2),a6 move.b (a6,d0.w),d3 swap d3 move.w (a6,d1.w),d3 move.b (a6),d3 move.l d3,(a0)+ moveq #0,d3 ; *lum2++ move.b (a3)+,d3 lea (a4,d3.w*2),a6 move.b (a6,d0.w),d3 swap d3 move.w (a6,d1.w),d3 move.b (a6),d3 move.l d3,(a1)+ moveq #0,d3 ; *lum2++ move.b (a3)+,d3 lea (a4,d3.w*2),a6 move.b (a6,d0.w),d3 swap d3 move.w (a6,d1.w),d3 move.b (a6),d3 move.l d3,(a1)+ move.l d2,a4 dbra d6,all_cols_rgb move.l savecols(sp),d0 ; next line in the luminance channel add.l d0,a2 add.l d0,a3 lsl.l #2,d0 ; 4 bytes per pixel add.l d0,a0 ; next line in the output row add.l d0,a1 dbra d7,all_rows_rgb add.w #localvars,sp movem.l (sp)+,cdi_regs rts ;************************************************************************************ XDEF @ColorDitherImage @ColorDitherImage: movem.l cdi_regs,-(sp) sub.w #localvars,sp move.l d1,(savecols,sp) lsr.l #1,d0 subq.l #1,d0 move.l d0,d7 move.l a0,a2 ; lum1 move.l a2,a3 add.l d1,a3 ; lum2 = lum1+cols move.l a1,a4 ; cr channel move.l cb_offset(sp),d5 sub.l a4,d5 ; cb channel is addressed via its offset to the cr channel lea Cb_r_tab,a5 ; conversion tab(s) move.l (out_offset,sp),a0 ; row1 move.l a0,a1 lsl.l #2,d1 add.l d1,a1 ; row2=row1+cols*4 all_rows: move.l (savecols,sp),d6 lsr.l #1,d6 subq.l #1,d6 all_cols: ; still free: d4 moveq #0,d1 moveq #0,d2 move.b (a4,d5.l),d1 ; CB channel move.b (a4)+,d2 ; CR channel move.l (a5,d1.w*4),d0 ; cb_r cb_g move.l (Cr_gb_off,a5,d2.w*4),d1 ; cr_g cr_b move.w d1,d2 swap d1 add.w d0,d1 swap d0 sub.w d2,d0 sub.w d2,d1 ext.l d2 add.l #_clamp,d2 exg a4,d2 ; d0 cb_r *2 ; d1 (cr_g+cb_g) *2 ; d2 cr_b *2 moveq #0,d3 ; *lum++ move.b (a2)+,d3 lea (a4,d3.w*2),a6 move.w (a6),d3 ; b BRG0 move.b (a6,d0.w),d3 ; r swap d3 move.w (a6,d1.w),d3 ; g move.l d3,(a0)+ ; *row1++ moveq #0,d3 ; *lum++ move.b (a2)+,d3 lea (a4,d3.w*2),a6 move.w (a6),d3 ; b BRG0 move.b (a6,d0.w),d3 ; r swap d3 move.w (a6,d1.w),d3 ; g move.l d3,(a0)+ ; *row1++ moveq #0,d3 ; *lum2++ move.b (a3)+,d3 lea (a4,d3.w*2),a6 move.w (a6),d3 ; b BRG0 move.b (a6,d0.w),d3 ; r swap d3 move.w (a6,d1.w),d3 ; g move.l d3,(a1)+ ; *row2++ moveq #0,d3 ; *lum2++ move.b (a3)+,d3 lea (a4,d3.w*2),a6 move.w (a6),d3 ; b BRG0 move.b (a6,d0.w),d3 ; r swap d3 move.w (a6,d1.w),d3 ; g move.l d3,(a1)+ ; *row2++ move.l d2,a4 dbra d6,all_cols move.l savecols(sp),d0 ; next line in the luminance channel add.l d0,a2 add.l d0,a3 lsl.l #2,d0 ; 4 bytes per pixel add.l d0,a0 ; next line in the output row add.l d0,a1 dbra d7,all_rows add.w #localvars,sp movem.l (sp)+,cdi_regs rts ;************************************************************************************ XDEF @ColorDitherImage_12bit @ColorDitherImage_12bit: movem.l cdi_regs,-(sp) sub.w #localvars,sp move.l d1,(savecols,sp) lsr.l #1,d0 subq.l #1,d0 move.l d0,d7 move.l a0,a2 ; lum1 move.l a2,a3 add.l d1,a3 ; lum2 = lum1+cols move.l a1,a4 ; cr channel move.l cb_offset(sp),d5 sub.l a4,d5 ; cb channel is addressed via its offset to the cr channel lea Cb_r_tab,a5 ; conversion tab(s) move.l (out_offset,sp),a0 ; row1 move.l a0,a1 add.l d1,a1 ; row2=row1+cols all_rows_12bit: move.l (savecols,sp),d6 lsr.l #1,d6 subq.l #1,d6 all_cols_12bit: moveq #0,d1 moveq #0,d2 move.b (a4,d5.l),d1 ; CB channel move.b (a4)+,d2 ; CR channel move.l (a5,d1.w*4),d0 ; cb_r cb_g move.l (Cr_gb_off,a5,d2.w*4),d1 ; cr_g cr_b move.w d1,d2 swap d1 add.w d0,d1 swap d0 sub.w d1,d0 sub.w d1,d2 ext.l d1 add.l #_clamp,d1 ; d0 cb_r *2 ; d1 (cr_g+cb_g) *2 ; d2 cr_b *2 moveq #0,d3 ; *lum++ moveq #0,d4 move.b (a2)+,d3 move.l d1,a6 ; clamp table includes on L add.l d3,d3 add.l d3,a6 move.w (a6,d0.w),d3 ; r lsl.l #4,d3 move.w (a6),d3 ; g lsl.l #4,d3 move.b (a2)+,d4 ; *lum++ move.l d1,a6 ; clamp table includes on L add.w d4,d4 add.l d4,a6 move.w (a6,d2.w),d3 ; b lsr.l #4,d3 move.b (a6),d3 ; g lsr.l #4,d3 move.w d3,(a0)+ ; *row1++ moveq #0,d3 ; *lum++ moveq #0,d4 move.b (a3)+,d3 move.l d1,a6 ; clamp table includes on L add.l d3,d3 add.l d3,a6 move.w (a6,d0.w),d3 ; r lsl.l #4,d3 move.w (a6),d3 ; g lsl.l #4,d3 move.b (a3)+,d4 ; *lum++ move.l d1,a6 ; clamp table includes on L add.w d4,d4 add.l d4,a6 move.w (a6,d2.w),d3 ; b lsr.l #4,d3 move.b (a6),d3 ; g lsr.l #4,d3 move.w d3,(a1)+ ; *row1++ dbra d6,all_cols_12bit move.l savecols(sp),d0 ; next line in the luminance channel add.l d0,a2 add.l d0,a3 add.l d0,a0 ; next line in the output row add.l d0,a1 dbra d7,all_rows_12bit add.w #localvars,sp movem.l (sp)+,cdi_regs rts ;************************************************************************************ SECTION __MERGED,BSS ; ; uv conversion table; contains 4 sets describing the relation between the two ; chrominance channels and the four-times bigger luminance channel. ; Cb_r_tab: ds.l 2*256 ; clamp table ; ; clamp[x] = 0xff00 ; *(&clamp[x]-1) = 0x00ff ; ; an offset into this clamp table could very easily implement overall brightness control! ; ; we can reuse this special construct in video.c/sutils.s ; XDEF _clamp ds.w clampsize _clamp: ds.w 256+clampsize END