[gimp] plug-ins: add 1, 2, 4, 8 bit grayscale loading to file-raw
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] plug-ins: add 1, 2, 4, 8 bit grayscale loading to file-raw
- Date: Tue, 12 Jun 2012 18:10:53 +0000 (UTC)
commit 9e97e5c26a7c0569277090f28cd0fd9f5ad09a84
Author: Matthias Wenzel <gimp mazzoo de>
Date: Sun Apr 1 12:11:07 2012 +0200
plug-ins: add 1, 2, 4, 8 bit grayscale loading to file-raw
and put the preview into a scrolled window.
mitch: cleaned up the patch and made the preview area properly
follow the loaded image's size.
plug-ins/common/file-raw.c | 374 +++++++++++++++++++++++++++++++++++---------
1 files changed, 297 insertions(+), 77 deletions(-)
---
diff --git a/plug-ins/common/file-raw.c b/plug-ins/common/file-raw.c
index aecb71e..53de0af 100644
--- a/plug-ins/common/file-raw.c
+++ b/plug-ins/common/file-raw.c
@@ -59,6 +59,10 @@ typedef enum
RAW_RGBA, /* RGB Image with an Alpha channel */
RAW_RGB565, /* RGB Image 16bit, 5,6,5 bits per channel */
RAW_PLANAR, /* Planar RGB */
+ RAW_GRAY_1BPP,
+ RAW_GRAY_2BPP,
+ RAW_GRAY_4BPP,
+ RAW_GRAY_8BPP,
RAW_INDEXED, /* Indexed image */
RAW_INDEXEDA /* Indexed image with an Alpha channel */
} RawType;
@@ -69,6 +73,7 @@ typedef enum
RAW_PALETTE_BGR /* Windows BGRX */
} RawPaletteType;
+
typedef struct
{
gint32 file_offset; /* offset to beginning of image in raw data */
@@ -89,52 +94,56 @@ typedef struct
} RawGimpData;
-static void query (void);
-static void run (const gchar *name,
- gint nparams,
- const GimpParam *param,
- gint *nreturn_vals,
- GimpParam **return_vals);
+static void query (void);
+static void run (const gchar *name,
+ gint nparams,
+ const GimpParam *param,
+ gint *nreturn_vals,
+ GimpParam **return_vals);
/* prototypes for the new load functions */
-static gboolean raw_load_standard (RawGimpData *data,
- gint bpp);
-static gboolean raw_load_rgb565 (RawGimpData *data);
-static gboolean raw_load_planar (RawGimpData *data);
-static gboolean raw_load_palette (RawGimpData *data,
- const gchar *palette_filename);
+static gboolean raw_load_standard (RawGimpData *data,
+ gint bpp);
+static gboolean raw_load_gray (RawGimpData *data,
+ gint bpp,
+ gint bitspp);
+static gboolean raw_load_rgb565 (RawGimpData *data);
+static gboolean raw_load_planar (RawGimpData *data);
+static gboolean raw_load_palette (RawGimpData *data,
+ const gchar *palette_filename);
/* support functions */
-static gint32 get_file_info (const gchar *filename);
-static void raw_read_row (FILE *fp,
- guchar *buf,
- gint32 offset,
- gint32 size);
-static int mmap_read (gint fd,
- gpointer buf,
- gint32 len,
- gint32 pos,
- gint rowstride);
-static void rgb_565_to_888 (guint16 *in,
- guchar *out,
- gint32 num_pixels);
-
-static gint32 load_image (const gchar *filename,
- GError **error);
-static GimpPDBStatusType save_image (const gchar *filename,
- gint32 image_id,
- gint32 drawable_id,
- GError **error);
+static gint32 get_file_info (const gchar *filename);
+static void raw_read_row (FILE *fp,
+ guchar *buf,
+ gint32 offset,
+ gint32 size);
+static int mmap_read (gint fd,
+ gpointer buf,
+ gint32 len,
+ gint32 pos,
+ gint rowstride);
+static void rgb_565_to_888 (guint16 *in,
+ guchar *out,
+ gint32 num_pixels);
+
+static gint32 load_image (const gchar *filename,
+ GError **error);
+static GimpPDBStatusType save_image (const gchar *filename,
+ gint32 image_id,
+ gint32 drawable_id,
+ GError **error);
/* gui functions */
-static void preview_update (GimpPreviewArea *preview);
-static void palette_update (GimpPreviewArea *preview);
-static gboolean load_dialog (const gchar *filename);
-static gboolean save_dialog (const gchar *filename,
- gint32 image_id,
- gint32 drawable_id);
-static void palette_callback (GtkFileChooser *button,
- GimpPreviewArea *preview);
+static void preview_update_size (GimpPreviewArea *preview);
+static void preview_update (GimpPreviewArea *preview);
+static void palette_update (GimpPreviewArea *preview);
+static gboolean load_dialog (const gchar *filename);
+static gboolean save_dialog (const gchar *filename,
+ gint32 image_id,
+ gint32 drawable_id);
+static void palette_callback (GtkFileChooser *button,
+ GimpPreviewArea *preview);
static RawConfig *runtime = NULL;
@@ -404,6 +413,86 @@ raw_load_standard (RawGimpData *data,
return TRUE;
}
+/* this handles black and white, gray with 1, 2, 4, and 8 _bits_ per
+ * pixel images - hopefully lots of binaries too
+ */
+static gboolean
+raw_load_gray (RawGimpData *data,
+ gint bpp,
+ gint bitspp)
+{
+ guchar *in_raw = NULL;
+ guchar *out_raw = NULL;
+ gint in_size;
+ gint out_size;
+ guchar pixel_mask_hi;
+ guchar pixel_mask_lo;
+ guint x;
+ gint i;
+
+ in_size = runtime->image_width * runtime->image_height / (8 / bitspp);
+ out_size = runtime->image_width * runtime->image_height * 3;
+
+ in_raw = g_try_malloc (in_size);
+ if (! in_raw)
+ return FALSE;
+
+ out_raw = g_try_malloc (out_size);
+ if (! out_raw)
+ return FALSE;
+ memset (out_raw, 0, out_size);
+
+ /* calculate a pixel_mask_hi
+ 0x80 for 1 bitspp
+ 0xc0 for 2 bitspp
+ 0xf0 for 4 bitspp
+ 0xff for 8 bitspp
+ and a pixel_mask_lo
+ 0x01 for 1 bitspp
+ 0x03 for 2 bitspp
+ 0x0f for 4 bitspp
+ 0xff for 8 bitspp
+ */
+ pixel_mask_hi = 0x80;
+ pixel_mask_lo = 0x01;
+ for (i = 1; i < bitspp; i++)
+ {
+ pixel_mask_hi |= pixel_mask_hi >> 1;
+ pixel_mask_lo |= pixel_mask_lo << 1;
+ }
+
+ raw_read_row (data->fp, in_raw, runtime->file_offset,
+ in_size);
+
+ x = 0; /* walks though all output pixels */
+ for (i = 0; i < in_size; i++)
+ {
+ guchar bit;
+
+ for (bit = 0; bit < 8 / bitspp; bit++)
+ {
+ guchar pixel_val;
+
+ pixel_val = in_raw[i] & (pixel_mask_hi >> (bit * bitspp));
+ pixel_val >>= 8 - bitspp - bit * bitspp;
+ pixel_val *= 0xff / pixel_mask_lo;
+
+ out_raw[3 * x + 0] = pixel_val;
+ out_raw[3 * x + 1] = pixel_val;
+ out_raw[3 * x + 2] = pixel_val;
+
+ x++;
+ }
+ }
+
+ gimp_pixel_rgn_set_rect (&data->region, out_raw,
+ 0, 0, runtime->image_width, runtime->image_height);
+ g_free (in_raw);
+ g_free (out_raw);
+
+ return TRUE;
+}
+
/* this handles RGB565 images */
static gboolean
raw_load_rgb565 (RawGimpData *data)
@@ -701,6 +790,7 @@ load_image (const gchar *filename,
GimpImageBaseType itype = GIMP_RGB_IMAGE;
gint32 size;
gint bpp = 0;
+ gint bitspp = 8;
data = g_new0 (RawGimpData, 1);
@@ -739,6 +829,30 @@ load_image (const gchar *filename,
itype = GIMP_RGB;
break;
+ case RAW_GRAY_1BPP:
+ bpp = 1;
+ bitspp = 1;
+ ltype = GIMP_RGB_IMAGE;
+ itype = GIMP_RGB;
+ break;
+ case RAW_GRAY_2BPP:
+ bpp = 1;
+ bitspp = 2;
+ ltype = GIMP_RGB_IMAGE;
+ itype = GIMP_RGB;
+ break;
+ case RAW_GRAY_4BPP:
+ bpp = 1;
+ bitspp = 4;
+ ltype = GIMP_RGB_IMAGE;
+ itype = GIMP_RGB;
+ break;
+ case RAW_GRAY_8BPP:
+ bpp = 1;
+ ltype = GIMP_RGB_IMAGE;
+ itype = GIMP_RGB;
+ break;
+
case RAW_INDEXED: /* Indexed */
bpp = 1;
ltype = GIMP_INDEXED_IMAGE;
@@ -753,8 +867,8 @@ load_image (const gchar *filename,
}
/* make sure we don't load image bigger than file size */
- if (runtime->image_height > (size / runtime->image_width / bpp))
- runtime->image_height = size / runtime->image_width / bpp;
+ if (runtime->image_height > (size / runtime->image_width / bpp * 8 / bitspp))
+ runtime->image_height = size / runtime->image_width / bpp * 8 / bitspp;
data->image_id = gimp_image_new (runtime->image_width,
runtime->image_height,
@@ -786,6 +900,19 @@ load_image (const gchar *filename,
raw_load_planar (data);
break;
+ case RAW_GRAY_1BPP:
+ raw_load_gray (data, bpp, bitspp);
+ break;
+ case RAW_GRAY_2BPP:
+ raw_load_gray (data, bpp, bitspp);
+ break;
+ case RAW_GRAY_4BPP:
+ raw_load_gray (data, bpp, bitspp);
+ break;
+ case RAW_GRAY_8BPP:
+ raw_load_gray (data, bpp, bitspp);
+ break;
+
case RAW_INDEXED:
case RAW_INDEXEDA:
raw_load_palette (data, palfile);
@@ -805,12 +932,20 @@ load_image (const gchar *filename,
/* misc GUI stuff */
static void
+preview_update_size (GimpPreviewArea *preview)
+{
+ gtk_widget_set_size_request (GTK_WIDGET (preview),
+ runtime->image_width, runtime->image_height);
+}
+
+static void
preview_update (GimpPreviewArea *preview)
{
gint width;
gint height;
gint32 pos;
gint x, y;
+ gint bitspp = 0;
width = MIN (runtime->image_width, preview->width);
height = MIN (runtime->image_height, preview->height);
@@ -839,7 +974,46 @@ preview_update (GimpPreviewArea *preview)
}
break;
- case RAW_PLANAR:
+ case RAW_RGBA:
+ /* RGB + alpha image */
+ {
+ guchar *row = g_malloc0 (width * 4);
+
+ for (y = 0; y < height; y++)
+ {
+ pos = runtime->file_offset + runtime->image_width * y * 4;
+ mmap_read (preview_fd, row, width * 4, pos, width * 4);
+
+ gimp_preview_area_draw (preview, 0, y, width, 1,
+ GIMP_RGBA_IMAGE, row, width * 4);
+ }
+
+ g_free (row);
+ }
+ break;
+
+ case RAW_RGB565:
+ /* RGB565 image */
+ {
+ guint16 *in = g_malloc0 (width * 2);
+ guchar *row = g_malloc0 (width * 3);
+
+ for (y = 0; y < height; y++)
+ {
+ pos = runtime->file_offset + runtime->image_width * y * 2;
+ mmap_read (preview_fd, in, width * 2, pos, width * 2);
+ rgb_565_to_888 (in, row, width);
+
+ gimp_preview_area_draw (preview, 0, y, width, 1,
+ GIMP_RGB_IMAGE, row, width * 3);
+ }
+
+ g_free (row);
+ g_free (in);
+ }
+ break;
+
+ case RAW_PLANAR:
{
guchar *r_row = g_malloc0 (width);
guchar *g_row = g_malloc0 (width);
@@ -880,42 +1054,73 @@ preview_update (GimpPreviewArea *preview)
}
break;
- case RAW_RGBA:
- /* RGB + alpha image */
- {
- guchar *row = g_malloc0 (width * 4);
+ case RAW_GRAY_1BPP:
+ if (! bitspp) bitspp = 1;
+ case RAW_GRAY_2BPP:
+ if (! bitspp) bitspp = 2;
+ case RAW_GRAY_4BPP:
+ if (! bitspp) bitspp = 4;
+ case RAW_GRAY_8BPP:
+ if (! bitspp) bitspp = 8;
- for (y = 0; y < height; y++)
+ {
+ guint in_size = height * width / (8 / bitspp);
+ guint out_size = height * width * 3;
+ guchar *in_raw = g_malloc0 (in_size);
+ guchar *out_raw = g_malloc0 (out_size);
+ guchar pixel_mask_hi;
+ guchar pixel_mask_lo;
+ gint i;
+
+ /* calculate a pixel_mask_hi
+ 0x80 for 1 bitspp
+ 0xc0 for 2 bitspp
+ 0xf0 for 4 bitspp
+ 0xff for 8 bitspp
+ and a pixel_mask_lo
+ 0x01 for 1 bitspp
+ 0x03 for 2 bitspp
+ 0x0f for 4 bitspp
+ 0xff for 8 bitspp
+ */
+ pixel_mask_hi = 0x80;
+ pixel_mask_lo = 0x01;
+
+ for (i = 1; i < bitspp; i++)
{
- pos = runtime->file_offset + runtime->image_width * y * 4;
- mmap_read (preview_fd, row, width * 4, pos, width * 4);
-
- gimp_preview_area_draw (preview, 0, y, width, 1,
- GIMP_RGBA_IMAGE, row, width * 4);
+ pixel_mask_hi |= pixel_mask_hi >> 1;
+ pixel_mask_lo |= pixel_mask_lo << 1;
}
- g_free (row);
- }
- break;
-
- case RAW_RGB565:
- /* RGB565 image */
- {
- guint16 *in = g_malloc0 (width * 2);
- guchar *row = g_malloc0 (width * 3);
+ mmap_read (preview_fd, in_raw, in_size,
+ runtime->file_offset,
+ in_size);
- for (y = 0; y < height; y++)
+ x = 0; /* walks though all output pixels */
+ for (i = 0; i < in_size; i++)
{
- pos = runtime->file_offset + runtime->image_width * y * 2;
- mmap_read (preview_fd, in, width * 2, pos, width * 2);
- rgb_565_to_888 (in, row, width);
+ guchar bit;
- gimp_preview_area_draw (preview, 0, y, width, 1,
- GIMP_RGB_IMAGE, row, width * 3);
+ for (bit = 0; bit < 8 / bitspp; bit++)
+ {
+ guchar pixel_val;
+
+ pixel_val = in_raw[i] & (pixel_mask_hi >> (bit * bitspp));
+ pixel_val >>= 8 - bitspp - bit * bitspp;
+ pixel_val *= 0xff / pixel_mask_lo;
+
+ out_raw[3 * x + 0] = pixel_val;
+ out_raw[3 * x + 1] = pixel_val;
+ out_raw[3 * x + 2] = pixel_val;
+
+ x++;
+ }
}
- g_free (row);
- g_free (in);
+ gimp_preview_area_draw (preview, 0, 0, width, height,
+ GIMP_RGB_IMAGE, out_raw, width * 3);
+ g_free (in_raw);
+ g_free (out_raw);
}
break;
@@ -1041,8 +1246,9 @@ load_dialog (const gchar *filename)
GtkWidget *dialog;
GtkWidget *main_vbox;
GtkWidget *preview;
- GtkWidget *table;
+ GtkWidget *sw;
GtkWidget *frame;
+ GtkWidget *table;
GtkWidget *combo;
GtkWidget *button;
GtkObject *adj;
@@ -1073,14 +1279,18 @@ load_dialog (const gchar *filename)
main_vbox, TRUE, TRUE, 0);
gtk_widget_show (main_vbox);
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
- gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
- gtk_widget_show (frame);
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start (GTK_BOX (main_vbox), sw, TRUE, TRUE, 0);
+ gtk_widget_set_size_request (sw, PREVIEW_SIZE, PREVIEW_SIZE);
+ gtk_widget_show (sw);
preview = gimp_preview_area_new ();
- gtk_widget_set_size_request (preview, PREVIEW_SIZE, PREVIEW_SIZE);
- gtk_container_add (GTK_CONTAINER (frame), preview);
+ gtk_widget_set_size_request (preview,
+ runtime->image_width, runtime->image_height);
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), preview);
gtk_widget_show (preview);
g_signal_connect_after (preview, "size-allocate",
@@ -1101,6 +1311,10 @@ load_dialog (const gchar *filename)
_("RGB Alpha"), RAW_RGBA,
_("RGB565"), RAW_RGB565,
_("Planar RGB"), RAW_PLANAR,
+ _("B&W 1 bit"), RAW_GRAY_1BPP,
+ _("Gray 2 bit"), RAW_GRAY_2BPP,
+ _("Gray 4 bit"), RAW_GRAY_4BPP,
+ _("Gray 8 bit"), RAW_GRAY_8BPP,
_("Indexed"), RAW_INDEXED,
_("Indexed Alpha"), RAW_INDEXEDA,
NULL);
@@ -1140,6 +1354,9 @@ load_dialog (const gchar *filename)
G_CALLBACK (gimp_int_adjustment_update),
&runtime->image_width);
g_signal_connect_swapped (adj, "value-changed",
+ G_CALLBACK (preview_update_size),
+ preview);
+ g_signal_connect_swapped (adj, "value-changed",
G_CALLBACK (preview_update),
preview);
@@ -1153,6 +1370,9 @@ load_dialog (const gchar *filename)
G_CALLBACK (gimp_int_adjustment_update),
&runtime->image_height);
g_signal_connect_swapped (adj, "value-changed",
+ G_CALLBACK (preview_update_size),
+ preview);
+ g_signal_connect_swapped (adj, "value-changed",
G_CALLBACK (preview_update),
preview);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]