print-image-gimp.c [plain text]
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include "print_gimp.h"
#include "print-intl.h"
typedef struct
{
GimpDrawable *drawable;
GimpPixelRgn rgn;
int columns;
int ox, oy;
int increment;
int w, h;
int mirror;
gint32 image_ID;
gint32 ncolors;
gint32 real_bpp;
GimpImageBaseType base_type;
guchar *cmap;
guchar *alpha_table;
guchar *tmp;
gint last_printed_percent;
gint initialized;
} Gimp_Image_t;
static const char *Image_get_appname(stp_image_t *image);
static void Image_conclude(stp_image_t *image);
static stp_image_status_t Image_get_row(stp_image_t *image,
unsigned char *data,
size_t byte_limit, int row);
static int Image_height(stp_image_t *image);
static int Image_width(stp_image_t *image);
static void Image_reset(stp_image_t *image);
static void Image_init(stp_image_t *image);
static void Image_transpose(stpui_image_t *image);
static void Image_hflip(stpui_image_t *image);
static void Image_vflip(stpui_image_t *image);
static void Image_rotate_ccw(stpui_image_t *image);
static void Image_rotate_cw(stpui_image_t *image);
static void Image_rotate_180(stpui_image_t *image);
static void Image_crop(stpui_image_t *image, int, int, int, int);
static stpui_image_t theImage =
{
{
Image_init,
Image_reset,
Image_width,
Image_height,
Image_get_row,
Image_get_appname,
Image_conclude,
NULL,
},
Image_transpose,
Image_hflip,
Image_vflip,
Image_rotate_ccw,
Image_rotate_cw,
Image_rotate_180,
Image_crop
};
static void
compute_alpha_table(Gimp_Image_t *image)
{
unsigned val, alpha;
image->alpha_table = stp_malloc(65536 * sizeof(unsigned char));
for (val = 0; val < 256; val++)
for (alpha = 0; alpha < 256; alpha++)
image->alpha_table[(val * 256) + alpha] =
val * alpha / 255 + 255 - alpha;
}
static inline unsigned char
alpha_lookup(Gimp_Image_t *image, int val, int alpha)
{
return image->alpha_table[(val * 256) + alpha];
}
stpui_image_t *
Image_GimpDrawable_new(GimpDrawable *drawable, gint32 image_ID)
{
Gimp_Image_t *im = stp_malloc(sizeof(Gimp_Image_t));
memset(im, 0, sizeof(Gimp_Image_t));
im->drawable = drawable;
gimp_pixel_rgn_init(&(im->rgn), drawable, 0, 0,
drawable->width, drawable->height, FALSE, FALSE);
im->image_ID = image_ID;
im->base_type = gimp_image_base_type(image_ID);
im->initialized = 0;
theImage.im.rep = im;
theImage.im.reset(&(theImage.im));
switch (im->base_type)
{
case GIMP_INDEXED:
im->cmap = gimp_image_get_cmap(image_ID, &(im->ncolors));
im->real_bpp = 3;
break;
case GIMP_GRAY:
im->real_bpp = 1;
break;
case GIMP_RGB:
im->real_bpp = 3;
break;
}
if (im->drawable->bpp == 2 || im->drawable->bpp == 4)
compute_alpha_table(im);
return &theImage;
}
static void
Image_init(stp_image_t *image)
{
}
static void
Image_reset(stp_image_t *image)
{
Gimp_Image_t *im = (Gimp_Image_t *) (image->rep);
im->columns = FALSE;
im->ox = 0;
im->oy = 0;
im->increment = 1;
im->w = im->drawable->width;
im->h = im->drawable->height;
im->mirror = FALSE;
}
static int
Image_width(stp_image_t *image)
{
Gimp_Image_t *im = (Gimp_Image_t *) (image->rep);
return im->w;
}
static int
Image_height(stp_image_t *image)
{
Gimp_Image_t *im = (Gimp_Image_t *) (image->rep);
return im->h;
}
static stp_image_status_t
Image_get_row(stp_image_t *image, unsigned char *data, size_t byte_limit,
int row)
{
Gimp_Image_t *im = (Gimp_Image_t *) (image->rep);
int last_printed_percent;
guchar *inter;
if (!im->initialized)
{
gimp_progress_init(_("Printing..."));
switch (im->base_type)
{
case GIMP_INDEXED:
im->tmp = stp_malloc(im->drawable->bpp * im->w);
break;
case GIMP_GRAY:
if (im->drawable->bpp == 2)
im->tmp = stp_malloc(im->drawable->bpp * im->w);
break;
case GIMP_RGB:
if (im->drawable->bpp == 4)
im->tmp = stp_malloc(im->drawable->bpp * im->w);
break;
}
im->initialized = 1;
}
if (im->tmp)
inter = im->tmp;
else
inter = data;
if (im->columns)
gimp_pixel_rgn_get_col(&(im->rgn), inter,
im->oy + row * im->increment, im->ox, im->w);
else
gimp_pixel_rgn_get_row(&(im->rgn), inter,
im->ox, im->oy + row * im->increment, im->w);
if (im->cmap)
{
int i;
if (im->alpha_table)
{
for (i = 0; i < im->w; i++)
{
int j;
for (j = 0; j < 3; j++)
{
gint32 tval = im->cmap[(3 * inter[2 * i]) + j];
data[(3 * i) + j] = alpha_lookup(im, tval,
inter[(2 * i) + 1]);
}
}
}
else
{
for (i = 0; i < im->w; i++)
{
data[(3 * i) + 0] = im->cmap[(3 * inter[i]) + 0];
data[(3 * i) + 1] = im->cmap[(3 * inter[i]) + 1];
data[(3 * i) + 2] = im->cmap[(3 * inter[i]) + 2];
}
}
}
else if (im->alpha_table)
{
int i;
for (i = 0; i < im->w; i++)
{
int j;
for (j = 0; j < im->real_bpp; j++)
{
gint32 tval = inter[(i * im->drawable->bpp) + j];
data[(i * im->real_bpp) + j] =
alpha_lookup(im, tval,
inter[((i + 1) * im->drawable->bpp) - 1]);
}
}
}
if (im->mirror)
{
int f;
int l;
int b = im->real_bpp;
for (f = 0, l = im->w - 1; f < l; f++, l--)
{
int c;
unsigned char tmp;
for (c = 0; c < b; c++)
{
tmp = data[f*b+c];
data[f*b+c] = data[l*b+c];
data[l*b+c] = tmp;
}
}
}
last_printed_percent = row * 100 / im->h;
if (last_printed_percent > im->last_printed_percent)
{
gimp_progress_update((double) row / (double) im->h);
im->last_printed_percent = last_printed_percent;
}
return STP_IMAGE_STATUS_OK;
}
static void
Image_transpose(stpui_image_t *image)
{
Gimp_Image_t *im = (Gimp_Image_t *) (image->im.rep);
int tmp;
if (im->mirror) im->ox += im->w - 1;
im->columns = !im->columns;
tmp = im->ox;
im->ox = im->oy;
im->oy = tmp;
tmp = im->mirror;
im->mirror = im->increment < 0;
im->increment = tmp ? -1 : 1;
tmp = im->w;
im->w = im->h;
im->h = tmp;
if (im->mirror) im->ox -= im->w - 1;
}
static void
Image_hflip(stpui_image_t *image)
{
Gimp_Image_t *im = (Gimp_Image_t *) (image->im.rep);
im->mirror = !im->mirror;
}
static void
Image_vflip(stpui_image_t *image)
{
Gimp_Image_t *im = (Gimp_Image_t *) (image->im.rep);
im->oy += (im->h-1) * im->increment;
im->increment = -im->increment;
}
static void
Image_crop(stpui_image_t *image, int left, int top, int right, int bottom)
{
Gimp_Image_t *im = (Gimp_Image_t *) (image->im.rep);
int xmax = (im->columns ? im->drawable->height : im->drawable->width) - 1;
int ymax = (im->columns ? im->drawable->width : im->drawable->height) - 1;
int nx = im->ox + im->mirror ? right : left;
int ny = im->oy + top * (im->increment);
int nw = im->w - left - right;
int nh = im->h - top - bottom;
int wmax, hmax;
if (nx < 0) nx = 0;
else if (nx > xmax) nx = xmax;
if (ny < 0) ny = 0;
else if (ny > ymax) ny = ymax;
wmax = xmax - nx + 1;
hmax = im->increment ? ny + 1 : ymax - ny + 1;
if (nw < 1) nw = 1;
else if (nw > wmax) nw = wmax;
if (nh < 1) nh = 1;
else if (nh > hmax) nh = hmax;
im->ox = nx;
im->oy = ny;
im->w = nw;
im->h = nh;
}
static void
Image_rotate_ccw(stpui_image_t *image)
{
Image_transpose(image);
Image_vflip(image);
}
static void
Image_rotate_cw(stpui_image_t *image)
{
Image_transpose(image);
Image_hflip(image);
}
static void
Image_rotate_180(stpui_image_t *image)
{
Image_vflip(image);
Image_hflip(image);
}
static void
Image_conclude(stp_image_t *image)
{
Gimp_Image_t *im = (Gimp_Image_t *) (image->rep);
gimp_progress_update(1);
if (im->alpha_table)
stp_free(im->alpha_table);
if (im->tmp)
stp_free(im->tmp);
}
static const char *
Image_get_appname(stp_image_t *image)
{
static char pluginname[] = "Print plug-in V" VERSION " - " RELEASE_DATE
" for GIMP";
return pluginname;
}