/* PIKA - Photo and Image Kooker Application * a rebranding of The GNU Image Manipulation Program (created with heckimp) * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio * * Original copyright, applying to most contents (license remains unchanged): * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis * * pikatemplate.c * Copyright (C) 2003 Michael Natterer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* This file contains the definition of the image template objects. */ #include "config.h" #include #include #include #include "libpikabase/pikabase.h" #include "libpikacolor/pikacolor.h" #include "libpikaconfig/pikaconfig.h" #include "core-types.h" #include "gegl/pika-babl.h" #include "pikaimage.h" #include "pikaprojection.h" #include "pikatemplate.h" #include "pika-intl.h" #define DEFAULT_RESOLUTION 300.0 enum { PROP_0, PROP_WIDTH, PROP_HEIGHT, PROP_UNIT, PROP_XRESOLUTION, PROP_YRESOLUTION, PROP_RESOLUTION_UNIT, PROP_BASE_TYPE, PROP_PRECISION, PROP_COMPONENT_TYPE, PROP_LINEAR, PROP_TRC, PROP_COLOR_PROFILE, PROP_SIMULATION_PROFILE, PROP_SIMULATION_BPC, PROP_SIMULATION_INTENT, PROP_FILL_TYPE, PROP_COMMENT, PROP_FILENAME, /* compat cruft */ PROP_COLOR_MANAGED }; typedef struct _PikaTemplatePrivate PikaTemplatePrivate; struct _PikaTemplatePrivate { gint width; gint height; PikaUnit unit; gdouble xresolution; gdouble yresolution; PikaUnit resolution_unit; PikaImageBaseType base_type; PikaPrecision precision; GFile *color_profile; GFile *simulation_profile; PikaColorRenderingIntent simulation_intent; gboolean simulation_bpc; PikaFillType fill_type; gchar *comment; gchar *filename; guint64 initial_size; }; #define GET_PRIVATE(template) ((PikaTemplatePrivate *) pika_template_get_instance_private ((PikaTemplate *) (template))) static void pika_template_finalize (GObject *object); static void pika_template_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void pika_template_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static void pika_template_notify (GObject *object, GParamSpec *pspec); G_DEFINE_TYPE_WITH_CODE (PikaTemplate, pika_template, PIKA_TYPE_VIEWABLE, G_ADD_PRIVATE (PikaTemplate) G_IMPLEMENT_INTERFACE (PIKA_TYPE_CONFIG, NULL)) #define parent_class pika_template_parent_class static void pika_template_class_init (PikaTemplateClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); PikaViewableClass *viewable_class = PIKA_VIEWABLE_CLASS (klass); object_class->finalize = pika_template_finalize; object_class->set_property = pika_template_set_property; object_class->get_property = pika_template_get_property; object_class->notify = pika_template_notify; viewable_class->default_icon_name = "pika-template"; viewable_class->name_editable = TRUE; PIKA_CONFIG_PROP_INT (object_class, PROP_WIDTH, "width", _("Width"), NULL, PIKA_MIN_IMAGE_SIZE, PIKA_MAX_IMAGE_SIZE, PIKA_DEFAULT_IMAGE_WIDTH, PIKA_PARAM_STATIC_STRINGS); PIKA_CONFIG_PROP_INT (object_class, PROP_HEIGHT, "height", _("Height"), NULL, PIKA_MIN_IMAGE_SIZE, PIKA_MAX_IMAGE_SIZE, PIKA_DEFAULT_IMAGE_HEIGHT, PIKA_PARAM_STATIC_STRINGS); PIKA_CONFIG_PROP_UNIT (object_class, PROP_UNIT, "unit", _("Unit"), _("The unit used for coordinate display " "when not in dot-for-dot mode."), TRUE, FALSE, PIKA_UNIT_PIXEL, PIKA_PARAM_STATIC_STRINGS); PIKA_CONFIG_PROP_RESOLUTION (object_class, PROP_XRESOLUTION, "xresolution", _("Resolution X"), _("The horizontal image resolution."), DEFAULT_RESOLUTION, PIKA_PARAM_STATIC_STRINGS | PIKA_TEMPLATE_PARAM_COPY_FIRST); PIKA_CONFIG_PROP_RESOLUTION (object_class, PROP_YRESOLUTION, "yresolution", _("Resolution X"), _("The vertical image resolution."), DEFAULT_RESOLUTION, PIKA_PARAM_STATIC_STRINGS | PIKA_TEMPLATE_PARAM_COPY_FIRST); PIKA_CONFIG_PROP_UNIT (object_class, PROP_RESOLUTION_UNIT, "resolution-unit", _("Resolution unit"), NULL, FALSE, FALSE, PIKA_UNIT_INCH, PIKA_PARAM_STATIC_STRINGS); PIKA_CONFIG_PROP_ENUM (object_class, PROP_BASE_TYPE, "image-type", /* serialized name */ _("Image type"), NULL, PIKA_TYPE_IMAGE_BASE_TYPE, PIKA_RGB, PIKA_PARAM_STATIC_STRINGS); PIKA_CONFIG_PROP_ENUM (object_class, PROP_PRECISION, "precision", _("Precision"), NULL, PIKA_TYPE_PRECISION, PIKA_PRECISION_U8_NON_LINEAR, PIKA_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_COMPONENT_TYPE, g_param_spec_enum ("component-type", _("Precision"), NULL, PIKA_TYPE_COMPONENT_TYPE, PIKA_COMPONENT_TYPE_U8, G_PARAM_READWRITE | PIKA_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_TRC, g_param_spec_enum ("trc", _("Linear/Perceptual"), NULL, PIKA_TYPE_TRC_TYPE, PIKA_TRC_NON_LINEAR, G_PARAM_READWRITE | PIKA_PARAM_STATIC_STRINGS)); PIKA_CONFIG_PROP_OBJECT (object_class, PROP_COLOR_PROFILE, "color-profile", _("Color profile"), NULL, G_TYPE_FILE, PIKA_PARAM_STATIC_STRINGS); PIKA_CONFIG_PROP_OBJECT (object_class, PROP_SIMULATION_PROFILE, "simulation-profile", _("Simulation profile"), NULL, G_TYPE_FILE, PIKA_PARAM_STATIC_STRINGS); PIKA_CONFIG_PROP_ENUM (object_class, PROP_SIMULATION_INTENT, "simulation-intent", _("Simulation Rendering Intent"), NULL, PIKA_TYPE_COLOR_RENDERING_INTENT, PIKA_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC, PIKA_PARAM_STATIC_STRINGS); PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_SIMULATION_BPC, "simulation-bpc", _("Use Black Point Compensation for Simulation"), NULL, FALSE, PIKA_PARAM_STATIC_STRINGS); PIKA_CONFIG_PROP_ENUM (object_class, PROP_FILL_TYPE, "fill-type", _("Fill type"), NULL, PIKA_TYPE_FILL_TYPE, PIKA_FILL_BACKGROUND, PIKA_PARAM_STATIC_STRINGS); PIKA_CONFIG_PROP_STRING (object_class, PROP_COMMENT, "comment", _("Comment"), NULL, NULL, PIKA_PARAM_STATIC_STRINGS); PIKA_CONFIG_PROP_STRING (object_class, PROP_FILENAME, "filename", _("Filename"), NULL, NULL, PIKA_PARAM_STATIC_STRINGS); /* compat cruft */ PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_COLOR_MANAGED, "color-managed", NULL, NULL, FALSE, PIKA_PARAM_STATIC_STRINGS | PIKA_CONFIG_PARAM_IGNORE); } static void pika_template_init (PikaTemplate *template) { } static void pika_template_finalize (GObject *object) { PikaTemplatePrivate *private = GET_PRIVATE (object); g_clear_object (&private->color_profile); g_clear_object (&private->simulation_profile); g_clear_pointer (&private->comment, g_free); g_clear_pointer (&private->filename, g_free); G_OBJECT_CLASS (parent_class)->finalize (object); } static void pika_template_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { PikaTemplatePrivate *private = GET_PRIVATE (object); switch (property_id) { case PROP_WIDTH: private->width = g_value_get_int (value); break; case PROP_HEIGHT: private->height = g_value_get_int (value); break; case PROP_UNIT: private->unit = g_value_get_int (value); break; case PROP_XRESOLUTION: private->xresolution = g_value_get_double (value); break; case PROP_YRESOLUTION: private->yresolution = g_value_get_double (value); break; case PROP_RESOLUTION_UNIT: private->resolution_unit = g_value_get_int (value); break; case PROP_BASE_TYPE: private->base_type = g_value_get_enum (value); break; case PROP_PRECISION: private->precision = g_value_get_enum (value); g_object_notify (object, "component-type"); g_object_notify (object, "trc"); break; case PROP_COMPONENT_TYPE: private->precision = pika_babl_precision (g_value_get_enum (value), pika_babl_trc (private->precision)); g_object_notify (object, "precision"); break; case PROP_TRC: private->precision = pika_babl_precision (pika_babl_component_type (private->precision), g_value_get_enum (value)); g_object_notify (object, "precision"); break; case PROP_COLOR_PROFILE: if (private->color_profile) g_object_unref (private->color_profile); private->color_profile = g_value_dup_object (value); break; case PROP_SIMULATION_PROFILE: if (private->simulation_profile) g_object_unref (private->simulation_profile); private->simulation_profile = g_value_dup_object (value); break; case PROP_SIMULATION_INTENT: private->simulation_intent = g_value_get_enum (value); break; case PROP_SIMULATION_BPC: private->simulation_bpc = g_value_get_boolean (value); break; case PROP_FILL_TYPE: private->fill_type = g_value_get_enum (value); break; case PROP_COMMENT: if (private->comment) g_free (private->comment); private->comment = g_value_dup_string (value); break; case PROP_FILENAME: if (private->filename) g_free (private->filename); private->filename = g_value_dup_string (value); break; case PROP_COLOR_MANAGED: /* ignored */ break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void pika_template_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { PikaTemplatePrivate *private = GET_PRIVATE (object); switch (property_id) { case PROP_WIDTH: g_value_set_int (value, private->width); break; case PROP_HEIGHT: g_value_set_int (value, private->height); break; case PROP_UNIT: g_value_set_int (value, private->unit); break; case PROP_XRESOLUTION: g_value_set_double (value, private->xresolution); break; case PROP_YRESOLUTION: g_value_set_double (value, private->yresolution); break; case PROP_RESOLUTION_UNIT: g_value_set_int (value, private->resolution_unit); break; case PROP_BASE_TYPE: g_value_set_enum (value, private->base_type); break; case PROP_PRECISION: g_value_set_enum (value, private->precision); break; case PROP_COMPONENT_TYPE: g_value_set_enum (value, pika_babl_component_type (private->precision)); break; case PROP_TRC: g_value_set_enum (value, pika_babl_trc (private->precision)); break; case PROP_COLOR_PROFILE: g_value_set_object (value, private->color_profile); break; case PROP_SIMULATION_PROFILE: g_value_set_object (value, private->simulation_profile); break; case PROP_SIMULATION_INTENT: g_value_set_enum (value, private->simulation_intent); break; case PROP_SIMULATION_BPC: g_value_set_boolean (value, private->simulation_bpc); break; case PROP_FILL_TYPE: g_value_set_enum (value, private->fill_type); break; case PROP_COMMENT: g_value_set_string (value, private->comment); break; case PROP_FILENAME: g_value_set_string (value, private->filename); break; case PROP_COLOR_MANAGED: /* ignored */ break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void pika_template_notify (GObject *object, GParamSpec *pspec) { PikaTemplatePrivate *private = GET_PRIVATE (object); const Babl *format; gint bytes; if (G_OBJECT_CLASS (parent_class)->notify) G_OBJECT_CLASS (parent_class)->notify (object, pspec); /* the initial layer */ format = pika_babl_format (private->base_type, private->precision, private->fill_type == PIKA_FILL_TRANSPARENT, NULL); bytes = babl_format_get_bytes_per_pixel (format); /* the selection */ format = pika_babl_mask_format (private->precision); bytes += babl_format_get_bytes_per_pixel (format); private->initial_size = ((guint64) bytes * (guint64) private->width * (guint64) private->height); private->initial_size += pika_projection_estimate_memsize (private->base_type, pika_babl_component_type (private->precision), private->width, private->height); } /* public functions */ PikaTemplate * pika_template_new (const gchar *name) { g_return_val_if_fail (name != NULL, NULL); return g_object_new (PIKA_TYPE_TEMPLATE, "name", name, NULL); } void pika_template_set_from_image (PikaTemplate *template, PikaImage *image) { gdouble xresolution; gdouble yresolution; PikaImageBaseType base_type; const PikaParasite *parasite; gchar *comment = NULL; g_return_if_fail (PIKA_IS_TEMPLATE (template)); g_return_if_fail (PIKA_IS_IMAGE (image)); pika_image_get_resolution (image, &xresolution, &yresolution); base_type = pika_image_get_base_type (image); if (base_type == PIKA_INDEXED) base_type = PIKA_RGB; parasite = pika_image_parasite_find (image, "pika-comment"); if (parasite) { guint32 parasite_size; comment = (gchar *) pika_parasite_get_data (parasite, ¶site_size); comment = g_strndup (comment, parasite_size); } g_object_set (template, "width", pika_image_get_width (image), "height", pika_image_get_height (image), "xresolution", xresolution, "yresolution", yresolution, "resolution-unit", pika_image_get_unit (image), "image-type", base_type, "precision", pika_image_get_precision (image), "comment", comment, NULL); if (comment) g_free (comment); } gint pika_template_get_width (PikaTemplate *template) { g_return_val_if_fail (PIKA_IS_TEMPLATE (template), 0); return GET_PRIVATE (template)->width; } gint pika_template_get_height (PikaTemplate *template) { g_return_val_if_fail (PIKA_IS_TEMPLATE (template), 0); return GET_PRIVATE (template)->height; } PikaUnit pika_template_get_unit (PikaTemplate *template) { g_return_val_if_fail (PIKA_IS_TEMPLATE (template), PIKA_UNIT_INCH); return GET_PRIVATE (template)->unit; } gdouble pika_template_get_resolution_x (PikaTemplate *template) { g_return_val_if_fail (PIKA_IS_TEMPLATE (template), 1.0); return GET_PRIVATE (template)->xresolution; } gdouble pika_template_get_resolution_y (PikaTemplate *template) { g_return_val_if_fail (PIKA_IS_TEMPLATE (template), 1.0); return GET_PRIVATE (template)->yresolution; } PikaUnit pika_template_get_resolution_unit (PikaTemplate *template) { g_return_val_if_fail (PIKA_IS_TEMPLATE (template), PIKA_UNIT_INCH); return GET_PRIVATE (template)->resolution_unit; } PikaImageBaseType pika_template_get_base_type (PikaTemplate *template) { g_return_val_if_fail (PIKA_IS_TEMPLATE (template), PIKA_RGB); return GET_PRIVATE (template)->base_type; } PikaPrecision pika_template_get_precision (PikaTemplate *template) { g_return_val_if_fail (PIKA_IS_TEMPLATE (template), PIKA_PRECISION_U8_NON_LINEAR); return GET_PRIVATE (template)->precision; } PikaColorProfile * pika_template_get_color_profile (PikaTemplate *template) { PikaTemplatePrivate *private; g_return_val_if_fail (PIKA_IS_TEMPLATE (template), FALSE); private = GET_PRIVATE (template); if (private->color_profile) return pika_color_profile_new_from_file (private->color_profile, NULL); return NULL; } PikaColorProfile * pika_template_get_simulation_profile (PikaTemplate *template) { PikaTemplatePrivate *private; g_return_val_if_fail (PIKA_IS_TEMPLATE (template), FALSE); private = GET_PRIVATE (template); if (private->simulation_profile) return pika_color_profile_new_from_file (private->simulation_profile, NULL); return NULL; } PikaColorRenderingIntent pika_template_get_simulation_intent (PikaTemplate *template) { PikaTemplatePrivate *private; g_return_val_if_fail (PIKA_IS_TEMPLATE (template), FALSE); private = GET_PRIVATE (template); return private->simulation_intent; } gboolean pika_template_get_simulation_bpc (PikaTemplate *template) { PikaTemplatePrivate *private; g_return_val_if_fail (PIKA_IS_TEMPLATE (template), FALSE); private = GET_PRIVATE (template); return private->simulation_bpc; } PikaFillType pika_template_get_fill_type (PikaTemplate *template) { g_return_val_if_fail (PIKA_IS_TEMPLATE (template), PIKA_FILL_BACKGROUND); return GET_PRIVATE (template)->fill_type; } const gchar * pika_template_get_comment (PikaTemplate *template) { g_return_val_if_fail (PIKA_IS_TEMPLATE (template), NULL); return GET_PRIVATE (template)->comment; } guint64 pika_template_get_initial_size (PikaTemplate *template) { g_return_val_if_fail (PIKA_IS_TEMPLATE (template), 0); return GET_PRIVATE (template)->initial_size; }