/* babl - dynamically extendable universal pixel conversion library. * Copyright (C) 2005, Øyvind Kolås. * * Optimized 8bit conversion routines as used by legacy GIMP code. * Copyright (C) 2008 Sven Neumann * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, see * . */ #include "config.h" #include #include "babl-internal.h" #include "base/util.h" #include "extensions/util.h" /* lookup tables used in conversion */ #define MAX_SPACES 32 static const Babl *spaces[MAX_SPACES]={NULL,}; static float lut_linear[1 << 8]; static float lut_gamma_2_2[MAX_SPACES][1 << 8]; static int tables_init (const Babl *space) { int i, j; for (j = 0; spaces[j]; j++) { if (spaces[j] == space) return j; } spaces[j] = space; /* fill tables for conversion from 8 bit integer to float */ if (j == 0) for (i = 0; i < 1 << 8; i++) { double value = i / 255.0; lut_linear[i] = value; } /* fill tables for conversion from 8 bit integer to float */ for (i = 0; i < 1 << 8; i++) { double value = i / 255.0; lut_gamma_2_2[j][i] = babl_trc_to_linear (space->space.trc[0], value); } return j; } static inline void u8_linear_to_float_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { float *d = (float *) dst; long n = samples; while (n--) *d++ = lut_linear[*src++]; } static void u8_linear_to_float_linear_assoc (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { float *d = (float *) dst; long n = samples; while (n--) { float alpha = lut_linear[src[3]]; d[0] = lut_linear[src[0]] * alpha; d[1] = lut_linear[src[1]] * alpha; d[2] = lut_linear[src[2]] * alpha; d[3] = alpha; src += 4; d += 4; } } static inline void u8_gamma_2_2_to_float_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { int space_no = tables_init (conversion->conversion.source->format.space); float *d = (float *) dst; long n = samples; while (n--) *d++ = lut_gamma_2_2[space_no][*src++]; } static void conv_rgba8_linear_rgbaF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { u8_linear_to_float_linear (conversion, src, dst, samples * 4); } static void conv_rgba8_linear_ragabaaF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { u8_linear_to_float_linear_assoc (conversion, src, dst, samples); } static void conv_rgba8_gamma_2_2_rgbaF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { int space_no = tables_init (conversion->conversion.source->format.space); float *d = (float *) dst; long n = samples; while (n--) { *d++ = lut_gamma_2_2[space_no][*src++]; *d++ = lut_gamma_2_2[space_no][*src++]; *d++ = lut_gamma_2_2[space_no][*src++]; *d++ = lut_linear[*src++]; } } static void conv_rgb8_linear_rgbF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { u8_linear_to_float_linear (conversion, src, dst, samples * 3); } static void conv_rgb8_gamma_2_2_rgbF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { u8_gamma_2_2_to_float_linear (conversion, src, dst, samples * 3); } static void conv_rgb8_linear_rgbaF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { float *d = (float *) dst; long n = samples; while (n--) { *d++ = lut_linear[*src++]; *d++ = lut_linear[*src++]; *d++ = lut_linear[*src++]; *d++ = 1.0; } } #define conv_rgb8_linear_ragabaaF_linear conv_rgb8_linear_rgbaF_linear static void conv_rgb8_gamma_2_2_rgbaF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { int space_no = tables_init (conversion->conversion.source->format.space); float *d = (float *) dst; long n = samples; while (n--) { *d++ = lut_gamma_2_2[space_no][*src++]; *d++ = lut_gamma_2_2[space_no][*src++]; *d++ = lut_gamma_2_2[space_no][*src++]; *d++ = 1.0; } } static void conv_ga8_linear_gaF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { u8_linear_to_float_linear (conversion, src, dst, samples * 2); } static void conv_ga8_gamma_2_2_gaF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { int space_no = tables_init (conversion->conversion.source->format.space); float *d = (float *) dst; long n = samples; while (n--) { *d++ = lut_gamma_2_2[space_no][*src++]; *d++ = lut_linear[*src++]; } } static void conv_ga8_gamma_2_2_rgba8_gamma_2_2 (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { long n = samples; while (n--) { *dst++ = *src; *dst++ = *src; *dst++ = *src++; *dst++ = *src++; } } static void conv_ga8_linear_rgbaF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { float *d = (float *) dst; long n = samples; while (n--) { float value = lut_linear[*src++]; *d++ = value; *d++ = value; *d++ = value; *d++ = lut_linear[*src++]; } } static void conv_ga8_gamma_2_2_rgbaF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { int space_no = tables_init (conversion->conversion.source->format.space); float *d = (float *) dst; long n = samples; while (n--) { float value = lut_gamma_2_2[space_no][*src++]; *d++ = value; *d++ = value; *d++ = value; *d++ = lut_linear[*src++]; } } static void conv_g8_linear_gF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { u8_linear_to_float_linear (conversion, src, dst, samples); } static void conv_g8_gamma_2_2_gF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { u8_gamma_2_2_to_float_linear (conversion, src, dst, samples); } static void conv_g8_linear_rgbaF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { float *d = (float *) dst; long n = samples; while (n--) { float value = lut_linear[*src++]; *d++ = value; *d++ = value; *d++ = value; *d++ = 1.0; } } static void conv_g8_gamma_2_2_rgbaF_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { int space_no = tables_init (conversion->conversion.source->format.space); float *d = (float *) dst; long n = samples; while (n--) { float value = lut_gamma_2_2[space_no][*src++]; *d++ = value; *d++ = value; *d++ = value; *d++ = 1.0; } } static void conv_rgbaF_linear_rgb8_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { float *fsrc = (float *) src; long n = samples; long int v; while (n--) { v = rint (*fsrc++ * 255.0f); *dst++ = (v < 0) ? 0 : ((v > 255) ? 255 : v); v = rint (*fsrc++ * 255.0f); *dst++ = (v < 0) ? 0 : ((v > 255) ? 255 : v); v = rint (*fsrc++ * 255.0f); *dst++ = (v < 0) ? 0 : ((v > 255) ? 255 : v); fsrc++; } } static void conv_rgbaF_linear_rgba8_linear (const Babl *conversion, unsigned char *src, unsigned char *dst, long samples) { float *fsrc = (float *) src; long n = samples; long int v; while (n--) { v = rint (*fsrc++ * 255.0f); *dst++ = (v < 0) ? 0 : ((v > 255) ? 255 : v); v = rint (*fsrc++ * 255.0f); *dst++ = (v < 0) ? 0 : ((v > 255) ? 255 : v); v = rint (*fsrc++ * 255.0f); *dst++ = (v < 0) ? 0 : ((v > 255) ? 255 : v); v = rint (*fsrc++ * 255.0f); *dst++ = (v < 0) ? 0 : ((v > 255) ? 255 : v); } } int init (void); int init (void) { const Babl *ragabaaF_linear = babl_format_new ( babl_model ("RaGaBaA"), babl_type ("float"), babl_component ("Ra"), babl_component ("Ga"), babl_component ("Ba"), babl_component ("A"), NULL); const Babl *rgbaF_linear = babl_format_new ( babl_model ("RGBA"), babl_type ("float"), babl_component ("R"), babl_component ("G"), babl_component ("B"), babl_component ("A"), NULL); const Babl *rgba8_linear = babl_format_new ( babl_model ("RGBA"), babl_type ("u8"), babl_component ("R"), babl_component ("G"), babl_component ("B"), babl_component ("A"), NULL); const Babl *rgba8_gamma_2_2 = babl_format_new ( babl_model ("R'G'B'A"), babl_type ("u8"), babl_component ("R'"), babl_component ("G'"), babl_component ("B'"), babl_component ("A"), NULL); const Babl *rgbF_linear = babl_format_new ( babl_model ("RGB"), babl_type ("float"), babl_component ("R"), babl_component ("G"), babl_component ("B"), NULL); const Babl *rgb8_linear = babl_format_new ( babl_model ("RGB"), babl_type ("u8"), babl_component ("R"), babl_component ("G"), babl_component ("B"), NULL); const Babl *rgb8_gamma_2_2 = babl_format_new ( babl_model ("R'G'B'"), babl_type ("u8"), babl_component ("R'"), babl_component ("G'"), babl_component ("B'"), NULL); const Babl *gaF_linear = babl_format_new ( babl_model ("YA"), babl_type ("float"), babl_component ("Y"), babl_component ("A"), NULL); const Babl *ga8_linear = babl_format_new ( babl_model ("YA"), babl_type ("u8"), babl_component ("Y"), babl_component ("A"), NULL); const Babl *ga8_gamma_2_2 = babl_format_new ( babl_model ("Y'A"), babl_type ("u8"), babl_component ("Y'"), babl_component ("A"), NULL); const Babl *gF_linear = babl_format_new ( babl_model ("Y"), babl_type ("float"), babl_component ("Y"), NULL); const Babl *g8_linear = babl_format_new ( babl_model ("Y"), babl_type ("u8"), babl_component ("Y"), NULL); const Babl *g8_gamma_2_2 = babl_format_new ( babl_model ("Y'"), babl_type ("u8"), babl_component ("Y'"), NULL); tables_init (babl_space("sRGB")); #define o(src, dst) \ babl_conversion_new (src, dst, "linear", conv_ ## src ## _ ## dst, NULL) o (rgba8_linear, ragabaaF_linear); o (rgba8_linear, rgbaF_linear); o (rgba8_gamma_2_2, rgbaF_linear); o (rgb8_linear, rgbF_linear); o (rgb8_gamma_2_2, rgbF_linear); o (rgb8_linear, rgbaF_linear); o (rgb8_linear, ragabaaF_linear); o (rgb8_gamma_2_2, rgbaF_linear); o (ga8_linear, gaF_linear); o (ga8_gamma_2_2, gaF_linear); o (ga8_linear, rgbaF_linear); o (ga8_gamma_2_2, rgbaF_linear); o (ga8_gamma_2_2, rgba8_gamma_2_2); o (g8_linear, gF_linear); o (g8_gamma_2_2, gF_linear); o (g8_linear, rgbaF_linear); o (g8_gamma_2_2, rgbaF_linear); o (rgbaF_linear, rgb8_linear); o (rgbaF_linear, rgba8_linear); return 0; }