mirror of https://github.com/GNOME/gimp.git
plug-ins: Handle single-channel OpenEXR with unknown channel names
OpenEXR allows for arbitrary channel names. Instead of failing once the common ones are checked, this patch checks the number of channels in the file. If there is only one channel, it is treated as grayscale (similar to OpenImageIO's behavior). A debug warning with the channel name is also printed.
This commit is contained in:
parent
4465db5223
commit
b459ce95bb
|
@ -62,6 +62,8 @@ static GimpImage * load_image (GFile *file,
|
|||
gboolean interactive,
|
||||
GError **error);
|
||||
static void sanitize_comment (gchar *comment);
|
||||
void load_dialog (void);
|
||||
|
||||
|
||||
|
||||
G_DEFINE_TYPE (Exr, exr, GIMP_TYPE_PLUG_IN)
|
||||
|
@ -236,6 +238,7 @@ load_image (GFile *file,
|
|||
layer_type = has_alpha ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
|
||||
break;
|
||||
case IMAGE_TYPE_GRAY:
|
||||
case IMAGE_TYPE_UNKNOWN_1_CHANNEL:
|
||||
image_type = GIMP_GRAY;
|
||||
layer_type = has_alpha ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE;
|
||||
break;
|
||||
|
@ -257,6 +260,10 @@ load_image (GFile *file,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (exr_loader_get_image_type (loader) == IMAGE_TYPE_UNKNOWN_1_CHANNEL &&
|
||||
interactive)
|
||||
load_dialog ();
|
||||
|
||||
/* try to load an icc profile, it will be generated on the fly if
|
||||
* chromaticities are given
|
||||
*/
|
||||
|
@ -395,3 +402,50 @@ sanitize_comment (gchar *comment)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
load_dialog (void)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *label;
|
||||
GtkWidget *vbox;
|
||||
gchar *label_text;
|
||||
|
||||
gimp_ui_init (PLUG_IN_BINARY);
|
||||
|
||||
dialog = gimp_dialog_new (_("Import OpenEXR"),
|
||||
"openexr-notice",
|
||||
NULL, 0, NULL, NULL,
|
||||
_("_OK"), GTK_RESPONSE_OK,
|
||||
NULL);
|
||||
|
||||
gimp_window_set_transient (GTK_WINDOW (dialog));
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
|
||||
vbox, TRUE, TRUE, 0);
|
||||
gtk_widget_show (vbox);
|
||||
|
||||
label_text = g_strdup_printf ("<b>%s</b>\n%s", _("Unknown Channel Name"),
|
||||
_("The image contains a single unknown channel.\n"
|
||||
"It has been converted to grayscale."));
|
||||
label = gtk_label_new (NULL);
|
||||
gtk_label_set_markup (GTK_LABEL (label), label_text);
|
||||
|
||||
gtk_label_set_selectable (GTK_LABEL (label), TRUE);
|
||||
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
|
||||
gtk_label_set_yalign (GTK_LABEL (label), 0.0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
g_free (label_text);
|
||||
|
||||
gtk_widget_show (dialog);
|
||||
|
||||
/* run the dialog */
|
||||
gimp_dialog_run (GIMP_DIALOG (dialog));
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
|
|
@ -119,7 +119,35 @@ struct _EXRLoader
|
|||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
int channel_count = 0;
|
||||
const char *channel_name = NULL;
|
||||
|
||||
for (ChannelList::ConstIterator i = channels_.begin();
|
||||
i != channels_.end(); ++i)
|
||||
{
|
||||
channel_count++;
|
||||
|
||||
pt_ = i.channel().type;
|
||||
channel_name = i.name();
|
||||
}
|
||||
|
||||
/* Assume single channel images are grayscale,
|
||||
* no matter what the channel name is. */
|
||||
if (channel_count == 1)
|
||||
{
|
||||
format_string_ = channel_name;
|
||||
image_type_ = IMAGE_TYPE_UNKNOWN_1_CHANNEL;
|
||||
unknown_channel_name_ = channel_name;
|
||||
|
||||
/* TODO: Pass this information back so it can be displayed
|
||||
* in the UI. */
|
||||
printf ("OpenEXR Warning: Single channel image with unknown "
|
||||
"channel %s, loading as grayscale\n", channel_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if (channels_.findChannel("A"))
|
||||
|
@ -149,9 +177,9 @@ struct _EXRLoader
|
|||
}
|
||||
}
|
||||
|
||||
int readPixelRow(char* pixels,
|
||||
int bpp,
|
||||
int row)
|
||||
int readPixelRow(char *pixels,
|
||||
int bpp,
|
||||
int row)
|
||||
{
|
||||
const int actual_row = data_window_.min.y + row;
|
||||
FrameBuffer fb;
|
||||
|
@ -162,6 +190,10 @@ struct _EXRLoader
|
|||
|
||||
switch (image_type_)
|
||||
{
|
||||
case IMAGE_TYPE_UNKNOWN_1_CHANNEL:
|
||||
fb.insert(unknown_channel_name_, Slice(pt_, base, bpp, 0, 1, 1, 0.5));
|
||||
break;
|
||||
|
||||
case IMAGE_TYPE_GRAY:
|
||||
fb.insert("Y", Slice(pt_, base, bpp, 0, 1, 1, 0.5));
|
||||
if (hasAlpha())
|
||||
|
@ -383,6 +415,7 @@ struct _EXRLoader
|
|||
EXRImageType image_type_;
|
||||
bool has_alpha_;
|
||||
std::string format_string_;
|
||||
std::string unknown_channel_name_;
|
||||
};
|
||||
|
||||
EXRLoader*
|
||||
|
|
|
@ -35,7 +35,8 @@ typedef enum
|
|||
typedef enum
|
||||
{
|
||||
IMAGE_TYPE_RGB,
|
||||
IMAGE_TYPE_GRAY
|
||||
IMAGE_TYPE_GRAY,
|
||||
IMAGE_TYPE_UNKNOWN_1_CHANNEL
|
||||
} EXRImageType;
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue