static inline void set_half (GeglTile * dst_tile, GeglTile * src_tile, gint width, gint height, const Babl * format, gint i, gint j) { guchar *dst_data = gegl_tile_get_data (dst_tile); guchar *src_data = gegl_tile_get_data (src_tile); gint components = babl_format_get_n_components (format); gint bpp = babl_format_get_bytes_per_pixel (format); if (i) dst_data += bpp * width / 2; if (j) dst_data += bpp * width * height / 2; if (babl_format_get_type (format, 0) == babl_type ("float")) { downscale_float (components, width, height, width * bpp, src_data, dst_data); } else if (babl_format_get_type (format, 0) == babl_type ("u8")) { downscale_u8 (components, width, height, width * bpp, src_data, dst_data); } else { set_half_nearest (dst_tile, src_tile, width, height, format, i, j); } }
void gegl_resample_boxfilter (guchar *dest_buf, const guchar *source_buf, const GeglRectangle *dst_rect, const GeglRectangle *src_rect, gint s_rowstride, gdouble scale, const Babl *format, gint d_rowstride) { const Babl *comp_type = babl_format_get_type (format, 0); const gint bpp = babl_format_get_bytes_per_pixel (format); if (comp_type == gegl_babl_float()) gegl_resample_boxfilter_float (dest_buf, source_buf, dst_rect, src_rect, s_rowstride, scale, bpp, d_rowstride); else if (comp_type == gegl_babl_u8()) gegl_resample_boxfilter_u8 (dest_buf, source_buf, dst_rect, src_rect, s_rowstride, scale, bpp, d_rowstride); else if (comp_type == gegl_babl_u16()) gegl_resample_boxfilter_u16 (dest_buf, source_buf, dst_rect, src_rect, s_rowstride, scale, bpp, d_rowstride); else if (comp_type == gegl_babl_u32()) gegl_resample_boxfilter_u32 (dest_buf, source_buf, dst_rect, src_rect, s_rowstride, scale, bpp, d_rowstride); else if (comp_type == gegl_babl_double()) gegl_resample_boxfilter_double (dest_buf, source_buf, dst_rect, src_rect, s_rowstride, scale, bpp, d_rowstride); else gegl_resample_nearest (dest_buf, source_buf, dst_rect, src_rect, s_rowstride, scale, bpp, d_rowstride); }
static cmsUInt32Number determine_lcms_format (const Babl *babl, cmsHPROFILE profile) { cmsUInt32Number format = COLORSPACE_SH (PT_ANY); gint channels, bpc, alpha; const Babl *type; channels = cmsChannelsOf (cmsGetColorSpace (profile)); alpha = babl_format_get_n_components (babl) - channels; bpc = babl_format_get_bytes_per_pixel (babl) / babl_format_get_n_components (babl); type = babl_format_get_type (babl, 0); if (type == babl_type ("half") || type == babl_type ("float") || type == babl_type ("double")) format |= FLOAT_SH (1); /* bpc == 8 overflows the bitfield otherwise */ bpc &= 0x07; /* * This is needed so the alpha component lines up with RGBA float * for our memcpy hack later on. */ if (alpha > 1 || (alpha && channels != 3)) return 0; format |= EXTRA_SH (alpha) | CHANNELS_SH (channels) | BYTES_SH (bpc); return format; }
static gboolean operation_source_process (GeglOperation *operation, GeglBuffer *output, const GeglRectangle *result, gint level) { const Babl *out_format = gegl_operation_get_format (operation, "output"); if ((result->width > 0) && (result->height > 0)) { GeglBufferIterator *iter; if (gegl_operation_use_opencl (operation) && babl_format_get_n_components (out_format) == 4 && babl_format_get_type (out_format, 0) == babl_type ("float")) { GeglBufferClIterator *cl_iter; gboolean err; GEGL_NOTE (GEGL_DEBUG_OPENCL, "GEGL_OPERATION_POINT_RENDER: %s", GEGL_OPERATION_GET_CLASS (operation)->name); cl_iter = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE); while (gegl_buffer_cl_iterator_next (cl_iter, &err) && !err) { err = checkerboard_cl_process (operation, cl_iter->tex[0], cl_iter->size[0], &cl_iter->roi[0], level); if (err) { gegl_buffer_cl_iterator_stop (cl_iter); break; } } if (err) GEGL_NOTE (GEGL_DEBUG_OPENCL, "Error: %s", GEGL_OPERATION_GET_CLASS (operation)->name); else return TRUE; } iter = gegl_buffer_iterator_new (output, result, level, out_format, GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) checkerboard_process (operation, iter->data[0], iter->length, &iter->roi[0], level); } return TRUE; }
GimpPrecision gimp_babl_format_get_precision (const Babl *format) { const Babl *type; g_return_val_if_fail (format != NULL, -1); type = babl_format_get_type (format, 0); if (type == babl_type ("u8")) return GIMP_PRECISION_U8; else if (type == babl_type ("u16")) return GIMP_PRECISION_U16; else if (type == babl_type ("u32")) return GIMP_PRECISION_U32; else if (type == babl_type ("half")) return GIMP_PRECISION_HALF; else if (type == babl_type ("float")) return GIMP_PRECISION_FLOAT; g_return_val_if_reached (-1); }
void gegl_downscale_2x2 (const Babl *format, gint src_width, gint src_height, guchar *src_data, gint src_rowstride, guchar *dst_data, gint dst_rowstride) { const gint bpp = babl_format_get_bytes_per_pixel (format); const Babl *comp_type = babl_format_get_type (format, 0); if (comp_type == gegl_babl_float()) gegl_downscale_2x2_float (bpp, src_width, src_height, src_data, src_rowstride, dst_data, dst_rowstride); else if (comp_type == gegl_babl_u8()) gegl_downscale_2x2_u8 (bpp, src_width, src_height, src_data, src_rowstride, dst_data, dst_rowstride); else if (comp_type == gegl_babl_u16()) gegl_downscale_2x2_u16 (bpp, src_width, src_height, src_data, src_rowstride, dst_data, dst_rowstride); else if (comp_type == gegl_babl_u32()) gegl_downscale_2x2_u32 (bpp, src_width, src_height, src_data, src_rowstride, dst_data, dst_rowstride); else if (comp_type == gegl_babl_double()) gegl_downscale_2x2_double (bpp, src_width, src_height, src_data, src_rowstride, dst_data, dst_rowstride); else gegl_downscale_2x2_nearest (bpp, src_width, src_height, src_data, src_rowstride, dst_data, dst_rowstride); }
static void lcms_layers_transform_rgb (gint *layers, gint num_layers, cmsHPROFILE src_profile, cmsHPROFILE dest_profile, GimpColorRenderingIntent intent, gboolean bpc) { gint i; for (i = 0; i < num_layers; i++) { gint32 layer_id = layers[i]; const Babl *layer_format; gboolean has_alpha; const Babl *type; const Babl *iter_format = NULL; cmsUInt32Number lcms_format = 0; cmsHTRANSFORM transform = NULL; gint *children; gint num_children; children = gimp_item_get_children (layer_id, &num_children); if (children) { lcms_layers_transform_rgb (children, num_children, src_profile, dest_profile, intent, bpc); g_free (children); continue; } layer_format = gimp_drawable_get_format (layer_id); has_alpha = babl_format_has_alpha (layer_format); type = babl_format_get_type (layer_format, 0); if (type == babl_type ("u8")) { if (has_alpha) { lcms_format = TYPE_RGBA_8; iter_format = babl_format ("R'G'B'A u8"); } else { lcms_format = TYPE_RGB_8; iter_format = babl_format ("R'G'B' u8"); } } else if (type == babl_type ("u16")) { if (has_alpha) { lcms_format = TYPE_RGBA_16; iter_format = babl_format ("R'G'B'A u16"); } else { lcms_format = TYPE_RGB_16; iter_format = babl_format ("R'G'B' u16"); } } else if (type == babl_type ("half")) /* 16-bit floating point (half) */ { #ifdef TYPE_RGB_HALF_FLT /* half float types are only in lcms 2.4 and newer */ if (has_alpha) { lcms_format = TYPE_RGBA_HALF_FLT; iter_format = babl_format ("R'G'B'A half"); } else { lcms_format = TYPE_RGB_HALF_FLT; iter_format = babl_format ("R'G'B' float"); } #endif /* TYPE_RGB_HALF_FLT */ } else if (type == babl_type ("float")) { if (has_alpha) { lcms_format = TYPE_RGBA_FLT; iter_format = babl_format ("R'G'B'A float"); } else { lcms_format = TYPE_RGB_FLT; iter_format = babl_format ("R'G'B' float"); } } else if (type == babl_type ("double")) { if (has_alpha) { #ifdef TYPE_RGBA_DBL /* RGBA double not implemented in lcms */ lcms_format = TYPE_RGBA_DBL; iter_format = babl_format ("R'G'B'A double"); #endif /* TYPE_RGBA_DBL */ } else { lcms_format = TYPE_RGB_DBL; iter_format = babl_format ("R'G'B' double"); } } if (lcms_format == 0) { g_printerr ("lcms: layer format %s not supported, " "falling back to float\n", babl_get_name (layer_format)); if (has_alpha) { lcms_format = TYPE_RGBA_FLT; iter_format = babl_format ("R'G'B'A float"); } else { lcms_format = TYPE_RGB_FLT; iter_format = babl_format ("R'G'B' float"); } } transform = cmsCreateTransform (src_profile, lcms_format, dest_profile, lcms_format, intent, cmsFLAGS_NOOPTIMIZE | (bpc ? cmsFLAGS_BLACKPOINTCOMPENSATION : 0)); if (transform) { GeglBuffer *src_buffer; GeglBuffer *dest_buffer; GeglBufferIterator *iter; gint layer_width; gint layer_height; gint layer_bpp; gboolean layer_alpha; gdouble progress_start = (gdouble) i / num_layers; gdouble progress_end = (gdouble) (i + 1) / num_layers; gdouble range = progress_end - progress_start; gint count = 0; gint done = 0; src_buffer = gimp_drawable_get_buffer (layer_id); dest_buffer = gimp_drawable_get_shadow_buffer (layer_id); layer_width = gegl_buffer_get_width (src_buffer); layer_height = gegl_buffer_get_height (src_buffer); layer_bpp = babl_format_get_bytes_per_pixel (iter_format); layer_alpha = babl_format_has_alpha (iter_format); iter = gegl_buffer_iterator_new (src_buffer, NULL, 0, iter_format, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); gegl_buffer_iterator_add (iter, dest_buffer, NULL, 0, iter_format, GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) { /* lcms doesn't touch the alpha channel, simply * copy everything to dest before the transform */ if (layer_alpha) memcpy (iter->data[1], iter->data[0], iter->length * layer_bpp); cmsDoTransform (transform, iter->data[0], iter->data[1], iter->length); } g_object_unref (src_buffer); g_object_unref (dest_buffer); gimp_drawable_merge_shadow (layer_id, TRUE); gimp_drawable_update (layer_id, 0, 0, layer_width, layer_height); if (count++ % 32 == 0) { gimp_progress_update (progress_start + (gdouble) done / (layer_width * layer_height) * range); } cmsDeleteTransform (transform); } } }
gint gegl_buffer_export_png (GeglBuffer *gegl_buffer, const gchar *path, gint compression, gint bd, gint src_x, gint src_y, gint width, gint height) { FILE *fp; gint i; png_struct *png; png_info *info; guchar *pixels; png_color_16 white; int png_color_type; gchar format_string[16]; const Babl *format; gint bit_depth = 8; if (!strcmp (path, "-")) { fp = stdout; } else { fp = fopen (path, "wb"); } if (!fp) { return -1; } { const Babl *babl; /*= gegl_buffer->format;*/ g_object_get (gegl_buffer, "format", &babl, NULL); if (babl_format_get_type (babl, 0) != babl_type ("u8")) bit_depth = 16; if (bd == 16) bit_depth = 16; else bit_depth = 8; if (babl_format_has_alpha (babl)) if (babl_format_get_n_components (babl) != 2) { png_color_type = PNG_COLOR_TYPE_RGB_ALPHA; strcpy (format_string, "R'G'B'A "); } else { png_color_type = PNG_COLOR_TYPE_GRAY_ALPHA; strcpy (format_string, "Y'A "); } else if (babl_format_get_n_components (babl) != 1) { png_color_type = PNG_COLOR_TYPE_RGB; strcpy (format_string, "R'G'B' "); } else { png_color_type = PNG_COLOR_TYPE_GRAY; strcpy (format_string, "Y' "); } } if (bit_depth == 16) strcat (format_string, "u16"); else strcat (format_string, "u8"); png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png == NULL) { if (stdout != fp) fclose (fp); return -1; } info = png_create_info_struct (png); if (setjmp (png_jmpbuf (png))) { if (stdout != fp) fclose (fp); return -1; } png_set_compression_level (png, compression); png_init_io (png, fp); png_set_IHDR (png, info, width, height, bit_depth, png_color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_DEFAULT); if (png_color_type == PNG_COLOR_TYPE_RGB || png_color_type == PNG_COLOR_TYPE_RGB_ALPHA) { white.red = 0xff; white.blue = 0xff; white.green = 0xff; } else white.gray = 0xff; png_set_bKGD (png, info, &white); png_write_info (png, info); #if BYTE_ORDER == LITTLE_ENDIAN if (bit_depth > 8) png_set_swap (png); #endif format = babl_format (format_string); pixels = g_malloc0 (width * babl_format_get_bytes_per_pixel (format)); for (i=0; i< height; i++) { GeglRectangle rect; rect.x = src_x; rect.y = src_y+i; rect.width = width; rect.height = 1; gegl_buffer_get (gegl_buffer, &rect, 1.0, babl_format (format_string), pixels, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); png_write_rows (png, &pixels, 1); } png_write_end (png, info); png_destroy_write_struct (&png, &info); g_free (pixels); if (stdout != fp) fclose (fp); return 0; }
/** * gimp_color_profile_get_format: * @format: a #Babl format * @lcms_format: return location for an lcms format * * This function takes a #Babl format and returns the lcms format to * be used with that @format. It also returns a #Babl format to be * used instead of the passed @format, which usually is the same as * @format, unless lcms doesn't support @format. * * Note that this function currently only supports RGB, RGBA, R'G'B', * R'G'B'A, Y, YA, Y', Y'A and the cairo-RGB24 and cairo-ARGB32 formats. * * Return value: the #Babl format to be used instead of @format, or %NULL * is the passed @format is not supported at all. * * Since: 2.10 **/ const Babl * gimp_color_profile_get_format (const Babl *format, guint32 *lcms_format) { const Babl *output_format = NULL; const Babl *type; const Babl *model; gboolean has_alpha; gboolean gray; gboolean linear; g_return_val_if_fail (format != NULL, NULL); g_return_val_if_fail (lcms_format != NULL, NULL); has_alpha = babl_format_has_alpha (format); type = babl_format_get_type (format, 0); model = babl_format_get_model (format); if (format == babl_format ("cairo-RGB24")) { *lcms_format = TYPE_RGB_8; return babl_format ("R'G'B' u8"); } else if (format == babl_format ("cairo-ARGB32")) { *lcms_format = TYPE_RGBA_8; return babl_format ("R'G'B'A u8"); } else if (model == babl_model ("RGB") || model == babl_model ("RGBA")) { gray = FALSE; linear = TRUE; } else if (model == babl_model ("R'G'B'") || model == babl_model ("R'G'B'A")) { gray = FALSE; linear = FALSE; } else if (model == babl_model ("Y") || model == babl_model ("YA")) { gray = TRUE; linear = TRUE; } else if (model == babl_model ("Y'") || model == babl_model ("Y'A")) { gray = TRUE; linear = FALSE; } else if (babl_format_is_palette (format)) { if (has_alpha) { *lcms_format = TYPE_RGBA_8; return babl_format ("R'G'B'A u8"); } else { *lcms_format = TYPE_RGB_8; return babl_format ("R'G'B' u8"); } } else { g_printerr ("format: %s\n" "has_alpha = %s\n" "type = %s\n" "model = %s\n", babl_get_name (format), has_alpha ? "TRUE" : "FALSE", babl_get_name (type), babl_get_name (model)); g_return_val_if_reached (NULL); } *lcms_format = 0; if (type == babl_type ("u8")) { if (has_alpha) { if (gray) *lcms_format = TYPE_GRAYA_8; else *lcms_format = TYPE_RGBA_8; } else { if (gray) *lcms_format = TYPE_GRAY_8; else *lcms_format = TYPE_RGB_8; } output_format = format; } else if (type == babl_type ("u16")) { if (has_alpha) { if (gray) *lcms_format = TYPE_GRAYA_16; else *lcms_format = TYPE_RGBA_16; } else { if (gray) *lcms_format = TYPE_GRAY_16; else *lcms_format = TYPE_RGB_16; } output_format = format; } else if (type == babl_type ("half")) /* 16-bit floating point (half) */ { if (has_alpha) { if (gray) *lcms_format = TYPE_GRAYA_HALF_FLT; else *lcms_format = TYPE_RGBA_HALF_FLT; } else { if (gray) *lcms_format = TYPE_GRAY_HALF_FLT; else *lcms_format = TYPE_RGB_HALF_FLT; } output_format = format; } else if (type == babl_type ("float")) { if (has_alpha) { if (gray) *lcms_format = TYPE_GRAYA_FLT; else *lcms_format = TYPE_RGBA_FLT; } else { if (gray) *lcms_format = TYPE_GRAY_FLT; else *lcms_format = TYPE_RGB_FLT; } output_format = format; } else if (type == babl_type ("double")) { if (has_alpha) { if (gray) *lcms_format = TYPE_GRAYA_DBL; else *lcms_format = TYPE_RGBA_DBL; } else { if (gray) *lcms_format = TYPE_GRAY_DBL; else *lcms_format = TYPE_RGB_DBL; } output_format = format; } if (*lcms_format == 0) { g_printerr ("%s: layer format %s not supported, " "falling back to float\n", G_STRFUNC, babl_get_name (format)); if (has_alpha) { if (gray) { *lcms_format = TYPE_GRAYA_FLT; if (linear) output_format = babl_format ("YA float"); else output_format = babl_format ("Y'A float"); } else { *lcms_format = TYPE_RGBA_FLT; if (linear) output_format = babl_format ("RGBA float"); else output_format = babl_format ("R'G'B'A float"); } } else { if (gray) { *lcms_format = TYPE_GRAY_FLT; if (linear) output_format = babl_format ("Y float"); else output_format = babl_format ("Y' float"); } else { *lcms_format = TYPE_RGB_FLT; if (linear) output_format = babl_format ("RGB float"); else output_format = babl_format ("R'G'B' float"); } } } return output_format; }
gdouble * gegl_color_get_components (GeglColor *color, GValue *value, gint *components_length) { Babl *format; if (G_TYPE_POINTER == G_VALUE_TYPE(value)) format = g_value_get_pointer (value); else { *components_length = 0; return NULL; } if (!color || !format) { *components_length = 0; return NULL; } else { gint components = babl_format_get_n_components (format); gint bpp = babl_format_get_bytes_per_pixel (format); const Babl *comp_type = babl_format_get_type (format, 0); gdouble *result = g_new (gdouble, components); *components_length = components; if (comp_type == babl_type ("u8")) { int i; guint8 *pixel_buf = alloca (bpp * components); gegl_color_get_pixel (color, format, pixel_buf); for (i = 0; i < components; ++i) result[i] = pixel_buf[i]; } else if (comp_type == babl_type ("u16")) { int i; guint16 *pixel_buf = alloca (bpp * components); gegl_color_get_pixel (color, format, pixel_buf); for (i = 0; i < components; ++i) result[i] = pixel_buf[i]; } else if (comp_type == babl_type ("u32")) { int i; guint32 *pixel_buf = alloca (bpp * components); gegl_color_get_pixel (color, format, pixel_buf); for (i = 0; i < components; ++i) result[i] = pixel_buf[i]; } else if (comp_type == babl_type ("float")) { int i; float *pixel_buf = alloca (bpp * components); gegl_color_get_pixel (color, format, pixel_buf); for (i = 0; i < components; ++i) result[i] = pixel_buf[i]; } else if (comp_type == babl_type ("double")) { gegl_color_get_pixel (color, format, result); } else { g_free (result); *components_length = 0; } return result; } }
void gegl_color_set_components (GeglColor *color, GValue *value, gdouble *components, gint components_length) { Babl *format; if (!(G_TYPE_POINTER == G_VALUE_TYPE(value))) return; format = g_value_get_pointer (value); if (!color || !format || components_length != babl_format_get_n_components (format)) return; else { gint bpp = babl_format_get_bytes_per_pixel (format); const Babl *comp_type = babl_format_get_type (format, 0); if (comp_type == babl_type ("u8")) { int i; guint8 *pixel_buf = alloca (bpp * components_length); for (i = 0; i < components_length; ++i) pixel_buf[i] = components[i]; gegl_color_set_pixel (color, format, pixel_buf); } else if (comp_type == babl_type ("u16")) { int i; guint16 *pixel_buf = alloca (bpp * components_length); for (i = 0; i < components_length; ++i) pixel_buf[i] = components[i]; gegl_color_set_pixel (color, format, pixel_buf); } else if (comp_type == babl_type ("u32")) { int i; guint32 *pixel_buf = alloca (bpp * components_length); for (i = 0; i < components_length; ++i) pixel_buf[i] = components[i]; gegl_color_set_pixel (color, format, pixel_buf); } else if (comp_type == babl_type ("float")) { int i; float *pixel_buf = alloca (bpp * components_length); for (i = 0; i < components_length; ++i) pixel_buf[i] = components[i]; gegl_color_set_pixel (color, format, pixel_buf); } else if (comp_type == babl_type ("double")) { gegl_color_set_pixel (color, format, components); } } }
static int export_tiff (GeglOperation *operation, GeglBuffer *input, const GeglRectangle *result) { GeglProperties *o = GEGL_PROPERTIES(operation); Priv *p = (Priv*) o->user_data; gshort color_space, compression = COMPRESSION_NONE; gushort bits_per_sample, samples_per_pixel; gboolean has_alpha, alpha_is_premultiplied = FALSE; gushort sample_format, predictor = 0; gushort extra_types[1]; glong rows_per_stripe = 1; gint bytes_per_row; const Babl *type, *model; gchar format_string[32]; const Babl *format; g_return_val_if_fail(p->tiff != NULL, -1); TIFFSetField(p->tiff, TIFFTAG_SUBFILETYPE, 0); TIFFSetField(p->tiff, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(p->tiff, TIFFTAG_IMAGEWIDTH, result->width); TIFFSetField(p->tiff, TIFFTAG_IMAGELENGTH, result->height); format = gegl_buffer_get_format(input); model = babl_format_get_model(format); type = babl_format_get_type(format, 0); if (model == babl_model("Y") || model == babl_model("Y'")) { has_alpha = FALSE; color_space = PHOTOMETRIC_MINISBLACK; model = babl_model("Y'"); samples_per_pixel = 1; } else if (model == babl_model("YA") || model == babl_model("Y'A")) { has_alpha = TRUE; alpha_is_premultiplied = FALSE; color_space = PHOTOMETRIC_MINISBLACK; model = babl_model("Y'A"); samples_per_pixel = 2; } else if (model == babl_model("YaA") || model == babl_model("Y'aA")) { has_alpha = TRUE; alpha_is_premultiplied = TRUE; color_space = PHOTOMETRIC_MINISBLACK; model = babl_model("Y'aA"); samples_per_pixel = 2; } else if (model == babl_model("RGB") || model == babl_model("R'G'B'")) { has_alpha = FALSE; color_space = PHOTOMETRIC_RGB; model = babl_model("R'G'B'"); samples_per_pixel = 3; predictor = 2; } else if (model == babl_model("RGBA") || model == babl_model("R'G'B'A")) { has_alpha = TRUE; alpha_is_premultiplied = FALSE; color_space = PHOTOMETRIC_RGB; model = babl_model("R'G'B'A"); samples_per_pixel = 4; predictor = 2; } else if (model == babl_model("RaGaBaA") || model == babl_model("R'aG'aB'aA")) { has_alpha = TRUE; alpha_is_premultiplied = TRUE; color_space = PHOTOMETRIC_RGB; model = babl_model("R'aG'aB'aA"); samples_per_pixel = 4; predictor = 2; } else { g_warning("color space not supported: %s", babl_get_name(model)); has_alpha = TRUE; alpha_is_premultiplied = TRUE; color_space = PHOTOMETRIC_RGB; model = babl_model("R'aG'aB'aA"); samples_per_pixel = 4; predictor = 2; } TIFFSetField(p->tiff, TIFFTAG_PHOTOMETRIC, color_space); TIFFSetField(p->tiff, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel); TIFFSetField(p->tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); if (has_alpha) { if (alpha_is_premultiplied) extra_types[0] = EXTRASAMPLE_ASSOCALPHA; else extra_types[0] = EXTRASAMPLE_UNASSALPHA; TIFFSetField(p->tiff, TIFFTAG_EXTRASAMPLES, 1, extra_types); } if (predictor != 0) { if (compression == COMPRESSION_LZW) TIFFSetField(p->tiff, TIFFTAG_PREDICTOR, predictor); else if (compression == COMPRESSION_ADOBE_DEFLATE) TIFFSetField(p->tiff, TIFFTAG_PREDICTOR, predictor); } if (type == babl_type("u8")) { sample_format = SAMPLEFORMAT_UINT; bits_per_sample = 8; } else if (type == babl_type("half")) { sample_format = SAMPLEFORMAT_IEEEFP; bits_per_sample = 16; } else if (type == babl_type("u16")) { sample_format = SAMPLEFORMAT_UINT; bits_per_sample = 16; } else if (type == babl_type("float")) { sample_format = SAMPLEFORMAT_IEEEFP; bits_per_sample = 32; } else if (type == babl_type("u32")) { sample_format = SAMPLEFORMAT_UINT; bits_per_sample = 32; } else if (type == babl_type("double")) { sample_format = SAMPLEFORMAT_IEEEFP; bits_per_sample = 64; } else { g_warning("sample format not supported: %s", babl_get_name(type)); sample_format = SAMPLEFORMAT_UINT; type = babl_type("u8"); bits_per_sample = 8; } TIFFSetField(p->tiff, TIFFTAG_BITSPERSAMPLE, bits_per_sample); TIFFSetField(p->tiff, TIFFTAG_SAMPLEFORMAT, sample_format); TIFFSetField(p->tiff, TIFFTAG_COMPRESSION, compression); if ((compression == COMPRESSION_CCITTFAX3 || compression == COMPRESSION_CCITTFAX4) && (bits_per_sample != 1 || samples_per_pixel != 1)) { g_critical("only monochrome pictures can be compressed " "with \"CCITT Group 4\" or \"CCITT Group 3\""); return -1; } g_snprintf(format_string, 32, "%s %s", babl_get_name(model), babl_get_name(type)); format = babl_format(format_string); /* "Choose RowsPerStrip such that each strip is about 8K bytes." */ bytes_per_row = babl_format_get_bytes_per_pixel(format) * result->width; while (bytes_per_row * rows_per_stripe <= 8192) rows_per_stripe++; rows_per_stripe = MIN(rows_per_stripe, result->height); TIFFSetField(p->tiff, TIFFTAG_ROWSPERSTRIP, rows_per_stripe); return save_contiguous(operation, input, result, format); }
/** * gimp_color_profile_get_format: * @format: a #Babl format * @lcms_format: return location for an lcms format * * This function takes a #Babl format and returns the lcms format to * be used with that @format. It also returns a #Babl format to be * used instead of the passed @format, which usually is the same as * @format, unless lcms doesn't support @format. * * Note that this function currently only supports RGB, RGBA, R'G'B' and * R'G'B'A formats. * * Return value: the #Babl format to be used instead of @format, or %NULL * is the passed @format is not supported at all. * * Since: 2.10 **/ const Babl * gimp_color_profile_get_format (const Babl *format, guint32 *lcms_format) { const Babl *output_format = NULL; const Babl *type; const Babl *model; gboolean has_alpha; gboolean linear; g_return_val_if_fail (format != NULL, NULL); g_return_val_if_fail (lcms_format != NULL, NULL); has_alpha = babl_format_has_alpha (format); type = babl_format_get_type (format, 0); model = babl_format_get_model (format); if (model == babl_model ("RGB") || model == babl_model ("RGBA")) { linear = TRUE; } else if (model == babl_model ("R'G'B'") || model == babl_model ("R'G'B'A")) { linear = FALSE; } else { g_return_val_if_reached (NULL); } *lcms_format = 0; if (type == babl_type ("u8")) { if (has_alpha) *lcms_format = TYPE_RGBA_8; else *lcms_format = TYPE_RGB_8; output_format = format; } else if (type == babl_type ("u16")) { if (has_alpha) *lcms_format = TYPE_RGBA_16; else *lcms_format = TYPE_RGB_16; output_format = format; } else if (type == babl_type ("half")) /* 16-bit floating point (half) */ { if (has_alpha) *lcms_format = TYPE_RGBA_HALF_FLT; else *lcms_format = TYPE_RGB_HALF_FLT; output_format = format; } else if (type == babl_type ("float")) { if (has_alpha) *lcms_format = TYPE_RGBA_FLT; else *lcms_format = TYPE_RGB_FLT; output_format = format; } else if (type == babl_type ("double")) { if (has_alpha) { #ifdef TYPE_RGBA_DBL /* RGBA double not implemented in lcms */ *lcms_format = TYPE_RGBA_DBL; output_format = format; #endif /* TYPE_RGBA_DBL */ } else { *lcms_format = TYPE_RGB_DBL; output_format = format; } } if (*lcms_format == 0) { g_printerr ("%s: layer format %s not supported, " "falling back to float\n", G_STRFUNC, babl_get_name (format)); if (has_alpha) { *lcms_format = TYPE_RGBA_FLT; if (linear) output_format = babl_format ("RGBA float"); else output_format = babl_format ("R'G'B'A float"); } else { *lcms_format = TYPE_RGB_FLT; if (linear) output_format = babl_format ("RGB float"); else output_format = babl_format ("R'G'B' float"); } } return output_format; }