static void video_convert_ycbcr_to_rgb(video_ycbcr_color_t *src, float sat, float bri, float con, float gam, float tin, palette_entry_t *dst) { float rf, bf, gf; float cb, cr, y; double factor; int r, g, b; cb = src->cb; cr = src->cr; y = src->y; cr += tin; /* apply tint */ /* apply saturation */ cb *= sat; cr *= sat; /* convert YCbCr to RGB */ bf = cb + y; rf = cr + y; gf = y - (0.1145f / 0.5866f) * cb - (0.2989f / 0.5866f) * cr; factor = pow(255.0f, 1.0f - gam); rf = video_gamma(rf, factor, gam, bri, con); gf = video_gamma(gf, factor, gam, bri, con); bf = video_gamma(bf, factor, gam, bri, con); /* convert to int and clip to 8 bit boundaries */ r = (int)rf; g = (int)gf; b = (int)bf; if (r > 255) { r = 255; } if (g > 255) { g = 255; } if (b > 255) { b = 255; } dst->dither = 0; dst->red = (BYTE)r; dst->green = (BYTE)g; dst->blue = (BYTE)b; dst->name = NULL; }
/* conversion of YCbCr to RGB used by video_calc_palette (internal palette) (not used by CRT emu) */ static void video_convert_renderer_to_rgb_gamma(video_ycbcr_color_t *src, float sat, float bri, float con, float gam, float tin, palette_entry_t *dst, int video) { float rf, bf, gf; double factor; int r, g, b; video_ycbcr_color_t tmp; /* DBG(("video_convert_renderer_to_rgb_gamma")); */ tmp.cb = src->cb; tmp.cr = src->cr; tmp.y = src->y; if (video) { tmp.cr += tin; /* apply tint */ /* apply saturation */ tmp.cb *= sat; tmp.cr *= sat; video_convert_ycbcr_to_rgb(&tmp, &r, &g, &b); } else { /* FIXME: tint for ntsc */ tmp.cr += tin; /* apply tint */ /* apply saturation */ tmp.cb *= sat; tmp.cr *= sat; video_convert_yiq_to_rgb(&tmp, &r, &g, &b); } /* do gamma correction */ factor = pow(255.0f, 1.0f - gam); rf = video_gamma((float)r, factor, gam, bri, con); gf = video_gamma((float)g, factor, gam, bri, con); bf = video_gamma((float)b, factor, gam, bri, con); /* convert to int and clip to 8 bit boundaries */ r = (int)rf; g = (int)gf; b = (int)bf; dst->dither = 0; dst->red = (BYTE)RMAX(r,255); dst->green = (BYTE)RMAX(g,255); dst->blue = (BYTE)RMAX(b,255); dst->name = NULL; }
static void video_calc_gammatable (void) { int i; float bri, con, gam, v; uae_u32 vi; bri = ((float)(currprefs.gfx_luminance)) * (128.0f / 1000.0f); con = ((float)(currprefs.gfx_contrast + 1000)) / 1000.0f; gam = ((float)(1000 - currprefs.gfx_gamma)) / 1000.0f; lf = 64 * currprefs.gf[picasso_on].gfx_filter_blur / 1000; hf = 256 - lf * 2; for (i = 0; i < (256 * 3); i++) { v = video_gamma((float)(i - 256), gam, bri, con); vi = (uae_u32)v; if (vi > 255) vi = 255; if (currprefs.gfx_luminance == 0 && currprefs.gfx_contrast == 0 && currprefs.gfx_gamma == 0) vi = i & 0xff; gamma[i] = vi; } }
/* gammatable calculation */ static void video_calc_gammatable(video_resources_t *video_resources) { int i; float bri, con, gam, scn, v; double factor; DWORD vi; bri = ((float)(video_resources->color_brightness - 1000)) * (128.0f / 1000.0f); con = ((float)(video_resources->color_contrast )) / 1000.0f; gam = video_get_gamma(video_resources); scn = ((float)(video_resources->pal_scanlineshade)) / 1000.0f; factor = pow(255.0f, 1.0f - gam); for (i = 0; i < (256 * 3); i++) { v = video_gamma((float)(i - 256), factor, gam, bri, con); vi = (DWORD)v; if (vi > 255) { vi = 255; } gamma_red[i] = color_red[vi]; gamma_grn[i] = color_grn[vi]; gamma_blu[i] = color_blu[vi]; vi = (DWORD)(v * scn); if (vi > 255) { vi = 255; } gamma_red_fac[i * 2] = color_red[vi]; gamma_grn_fac[i * 2] = color_grn[vi]; gamma_blu_fac[i * 2] = color_blu[vi]; v = video_gamma((float)(i - 256) + 0.5f, factor, gam, bri, con); vi = (DWORD)(v * scn); if (vi > 255) { vi = 255; } gamma_red_fac[i * 2 + 1] = color_red[vi]; gamma_grn_fac[i * 2 + 1] = color_grn[vi]; gamma_blu_fac[i * 2 + 1] = color_blu[vi]; } }
static void video_calc_gammatable(int monid) { struct amigadisplay *ad = &adisplays[monid]; float bri, con, gam, gams[3]; bri = ((float)(currprefs.gfx_luminance)) * (128.0f / 1000.0f); con = ((float)(currprefs.gfx_contrast + 1000)) / 1000.0f; gam = ((float)(1000 - currprefs.gfx_gamma)) / 1000.0f - 1.0; gams[0] = gam + ((float)(1000 - currprefs.gfx_gamma_ch[0])) / 1000.0f; gams[1] = gam + ((float)(1000 - currprefs.gfx_gamma_ch[1])) / 1000.0f; gams[2] = gam + ((float)(1000 - currprefs.gfx_gamma_ch[2])) / 1000.0f; lf = 64 * currprefs.gf[ad->picasso_on].gfx_filter_blur / 1000; hf = 256 - lf * 2; for (int i = 0; i < (256 * 3); i++) { for (int j = 0; j < 3; j++) { float val = i - 256; float v; if (currprefs.gfx_threebitcolors == 2) { val *= 2; } else if (currprefs.gfx_threebitcolors == 3) { val = (val * 252.0) / 119.0; } else if (currprefs.gfx_threebitcolors == 1) { val = (val * 252.0) / 238.0; } if (currprefs.gfx_luminance == 0 && currprefs.gfx_contrast == 0 && currprefs.gfx_gamma == 0 && currprefs.gfx_gamma_ch[0] == 0 && currprefs.gfx_gamma_ch[1] == 0 && currprefs.gfx_gamma_ch[2] == 0) { v = val; } else { v = video_gamma(val, gams[j], bri, con); } if (v < 0.0) v = 0.0; if (v > 255.0) v = 255.0; gamma[i][j] = (uae_u32)(v + 0.5); } } }
static void video_calc_ycbcrtable(video_resources_t *video_resources, const video_ycbcr_palette_t *p, video_render_color_tables_t *color_tab) { video_ycbcr_color_t *primary; unsigned int i, lf, hf; float sat, tin, bri, con, gam; float yf, uf, vf; int y, u, v; double factor, len; lf = 64 * video_resources->pal_blur / 1000; hf = 255 - (lf << 1); sat = ((float)(video_resources->color_saturation)) * (256.0f / 1000.0f); tin = (((float)(video_resources->color_tint)) * (50.0f / 2000.0f)) - 25.0f; bri = ((float)(video_resources->color_brightness - 1000)) * (112.0f / 1000.0f); con = ((float)(video_resources->color_contrast )) / 1000.0f; gam = video_get_gamma(video_resources); factor = pow(256.0f, 1.0f - gam); for (i = 0; i < p->num_entries; i++) { SDWORD val; /* create primary table */ primary = &p->entries[i]; val = (SDWORD)(primary->y * 256.0f); color_tab->ytablel[i] = val * lf; color_tab->ytableh[i] = val * hf; color_tab->cbtable[i] = (SDWORD)((primary->cb) * sat); color_tab->cutable[i] = (SDWORD)(0.493111 * primary->cb * 256.0); /* tint, add to cr in odd lines */ val = (SDWORD)(tin); color_tab->crtable[i] = (SDWORD)((primary->cr + val) * sat); color_tab->cvtable[i] = (SDWORD)(0.877283 * (primary->cr + val) * 256.0); yf = (float)(video_gamma(primary->y, factor, gam, bri, con) * 224.0 / 256.0 + 16.5); uf = (float)(0.493111 * primary->cb * sat * con * 224.0 / 256.0 / 256.0 + 128.5); vf = (float)(0.877283 * (primary->cr + tin) * sat * con * 224.0 / 256.0 / 256.0 + 128.5); y = (int)yf; u = (int)uf; v = (int)vf; /* sanity check: cbtable and crtable must be kept in 16 bit range or we might get overflows in eg the CRT renderer */ len = sqrt(((double)color_tab->cbtable[i] * (double)color_tab->cbtable[i]) + ((double)color_tab->crtable[i] * (double)color_tab->crtable[i])); if (len >= (double)0x10000) { log_error(LOG_DEFAULT, "video_calc_ycbcrtable: color %d cbcr vector too long, use lower base saturation.", i); } if (y < 16) { y = 16; } else if (y > 240) { y = 240; } if (u < 16) { u = 16; } else if (u > 240) { u = 240; } if (v < 16) { v = 16; } else if (v > 240) { v = 240; } /* YCbCr to YUV, scale [0, 256] to [0, 255] */ color_tab->yuv_table[i] = (y << 16) | (u << 8) | v; } color_tab->yuv_updated = 0; }
/* called by video_color_update_palette, internal and external palette */ static void video_calc_ycbcrtable(video_resources_t *video_resources, const video_ycbcr_palette_t *p, video_render_color_tables_t *color_tab, int video) { video_ycbcr_color_t *primary; unsigned int i, lf, hf; float sat, tin, bri, con, gam; float yf, uf, vf; int y, u, v; double factor, len; #ifdef DEBUG_VIDEO palette_entry_t temp; #endif DBG(("video_calc_ycbcrtable")); lf = 64 * video_resources->pal_blur / 1000; hf = 255 - (lf << 1); sat = ((float)(video_resources->color_saturation)) * (256.0f / 1000.0f); tin = (((float)(video_resources->color_tint)) * (50.0f / 2000.0f)) - 25.0f; bri = ((float)(video_resources->color_brightness - 1000)) * (112.0f / 1000.0f); con = ((float)(video_resources->color_contrast )) / 1000.0f; gam = video_get_gamma(video_resources, video); factor = pow(256.0f, 1.0f - gam); DBG((" sat:%d bri:%d con:%d gam:%d tin:%d", (int)sat, (int)bri, (int)con, (int)gam, (int)tin)); for (i = 0; i < p->num_entries; i++) { SDWORD val; /* create primary table */ primary = &p->entries[i]; if (video) { val = (SDWORD)(primary->y * 256.0f); color_tab->ytablel[i] = val * lf; color_tab->ytableh[i] = val * hf; /* tint, add to cr in odd lines */ val = (SDWORD)(tin); color_tab->cbtable[i] = (SDWORD)((primary->cb) * sat); color_tab->crtable[i] = (SDWORD)((primary->cr + val) * sat); color_tab->cutable[i] = (SDWORD)(0.493111f * primary->cb * 256.0); /* convert Cb to U */ color_tab->cvtable[i] = (SDWORD)(0.877283f * (primary->cr + val) * 256.0); /* convert Cr to V */ } else { /* for NTSC use one bit less for the fraction in the tables to avoid integer overflows in the CRT renderer */ val = (SDWORD)(primary->y * 128.0f); color_tab->ytablel[i] = (val * lf); color_tab->ytableh[i] = (val * hf); /* FIXME: tint for NTSC */ val = (SDWORD)(tin); color_tab->cbtable[i] = (SDWORD)((primary->cb) * sat) >> 1; color_tab->crtable[i] = (SDWORD)((primary->cr + val) * sat) >> 1; /* FIXME: convert IQ to UV (used by YUV renderers) */ color_tab->cutable[i] = (SDWORD)(primary->cb * 256.0); color_tab->cvtable[i] = (SDWORD)((primary->cr + val) * 256.0); } #ifdef DEBUG_VIDEO video_convert_renderer_to_rgb(primary, &temp, video); DBG((" %2d 'Cb':%4d 'Cr':%4d 'Cr':%6d 'Cb':%6d R:%4d G:%4d B:%4d", i, (int)primary->cb, (int)primary->cr, (int)color_tab->cbtable[i], (int)color_tab->crtable[i], temp.red, temp.green, temp.blue )); #endif yf = (float)(video_gamma(primary->y, factor, gam, bri, con) * 224.0 / 256.0 + 16.5); if (video) { /* PAL: convert CbCr to UV */ uf = (float)(0.493111f * primary->cb * sat * con * 224.0 / 256.0 / 256.0 + 128.5); vf = (float)(0.877283f * (primary->cr + tin) * sat * con * 224.0 / 256.0 / 256.0 + 128.5); } else { /* FIXME: convert IQ to UV (used by YUV renderers) */ uf = (float)(0.493111f * primary->cb * sat * con * 224.0 / 256.0 / 256.0 + 128.5); vf = (float)(0.877283f * (primary->cr + tin) * sat * con * 224.0 / 256.0 / 256.0 + 128.5); } /* sanity check: cbtable and crtable must be kept in 16 bit range or we might get overflows in eg the CRT renderer */ /* FIXME: we need to check more and clamp the values accordingly - it is still possible to "overdrive" the renderer in NTSC mode */ len = sqrt(((double)color_tab->cbtable[i] * (double)color_tab->cbtable[i]) + ((double)color_tab->crtable[i] * (double)color_tab->crtable[i])); if (len >= (double)0x10000) { log_error(LOG_DEFAULT, "video_calc_ycbcrtable: color %d cbcr vector too long, use lower base saturation.", i); } y = (int)RMINMAX(yf, 16, 240); u = (int)RMINMAX(uf, 16, 240); v = (int)RMINMAX(vf, 16, 240); /* YCbCr to YUV, scale [0, 256] to [0, 255] (used by YUV renderers) */ color_tab->yuv_table[i] = (y << 16) | (u << 8) | v; } color_tab->yuv_updated = 0; }