/* * "$Id$" * * Print plug-in for the GIMP. * * Copyright 1997-2000 Michael Sweet (mike@easysw.com) and * Robert Krawitz (rlk@alum.mit.edu) * Copyright 2000 Charles Briscoe-Smith * * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include #include "libgimp/gimp.h" #include "libgimp/gimpui.h" #include "print_gimp.h" #include "libgimp/stdplugins-intl.h" /* * "Image" ADT * * This file defines an abstract data type called "Image". An Image wraps * a Gimp drawable (or some other application-level image representation) * for presentation to the low-level printer drivers (which do CMYK * separation, dithering and weaving). The Image ADT has the ability * to perform any combination of flips and rotations on the image, * and then deliver individual rows to the driver code. * * Stuff which might be useful to do in this layer: * * - Scaling, optionally with interpolation/filtering. * * - Colour-adjustment. * * - Multiple-image composition. * * Also useful might be to break off a thin application-dependent * sublayer leaving this layer (which does the interesting stuff) * application-independent. */ /* Concrete type to represent image */ typedef struct { GimpDrawable *drawable; GimpPixelRgn rgn; /* * Transformations we can impose on the image. The transformations * are considered to be performed in the order given here. */ /* 1: Transpose the x and y axes (flip image over its leading diagonal) */ int columns; /* Set if returning columns instead of rows. */ /* 2: Translate (ox,oy) to the origin */ int ox, oy; /* Origin of image */ /* 3: Flip vertically about the x axis */ int increment; /* +1 or -1 for offset of row n+1 from row n. */ /* 4: Crop to width w, height h */ int w, h; /* Width and height of output image */ /* 5: Flip horizontally about the vertical centre-line of the image */ int mirror; /* Set if mirroring rows end-for-end. */ } Gimp_Image_t; static const char *Image_get_appname(stp_image_t *image); static void Image_progress_conclude(stp_image_t *image); static void Image_note_progress(stp_image_t *image, double current, double total); static void Image_progress_init(stp_image_t *image); static stp_image_status_t Image_get_row(stp_image_t *image, unsigned char *data, int row); static int Image_height(stp_image_t *image); static int Image_width(stp_image_t *image); static int Image_bpp(stp_image_t *image); static void Image_rotate_180(stp_image_t *image); static void Image_rotate_cw(stp_image_t *image); static void Image_rotate_ccw(stp_image_t *image); static void Image_crop(stp_image_t *image, int left, int top, int right, int bottom); static void Image_vflip(stp_image_t *image); static void Image_hflip(stp_image_t *image); static void Image_transpose(stp_image_t *image); static void Image_reset(stp_image_t *image); static void Image_init(stp_image_t *image); static stp_image_t theImage = { Image_init, Image_reset, Image_transpose, Image_hflip, Image_vflip, Image_crop, Image_rotate_ccw, Image_rotate_cw, Image_rotate_180, Image_bpp, Image_width, Image_height, Image_get_row, Image_get_appname, Image_progress_init, Image_note_progress, Image_progress_conclude, NULL }; stp_image_t * Image_GimpDrawable_new(GimpDrawable *drawable) { Gimp_Image_t *i = g_malloc(sizeof(Gimp_Image_t)); i->drawable = drawable; gimp_pixel_rgn_init(&(i->rgn), drawable, 0, 0, drawable->width, drawable->height, FALSE, FALSE); theImage.rep = i; theImage.reset(&theImage); return &theImage; } static void Image_init(stp_image_t *image) { /* Nothing to do. */ } static void Image_reset(stp_image_t *image) { Gimp_Image_t *i = (Gimp_Image_t *) (image->rep); i->columns = FALSE; i->ox = 0; i->oy = 0; i->increment = 1; i->w = i->drawable->width; i->h = i->drawable->height; i->mirror = FALSE; } static void Image_transpose(stp_image_t *image) { Gimp_Image_t *i = (Gimp_Image_t *) (image->rep); int tmp; if (i->mirror) i->ox += i->w - 1; i->columns = !i->columns; tmp = i->ox; i->ox = i->oy; i->oy = tmp; tmp = i->mirror; i->mirror = i->increment < 0; i->increment = tmp ? -1 : 1; tmp = i->w; i->w = i->h; i->h = tmp; if (i->mirror) i->ox -= i->w - 1; } static void Image_hflip(stp_image_t *image) { Gimp_Image_t *i = (Gimp_Image_t *) (image->rep); i->mirror = !i->mirror; } static void Image_vflip(stp_image_t *image) { Gimp_Image_t *i = (Gimp_Image_t *) (image->rep); i->oy += (i->h-1) * i->increment; i->increment = -i->increment; } /* * Image_crop: * * Crop the given number of pixels off the LEFT, TOP, RIGHT and BOTTOM * of the image. */ static void Image_crop(stp_image_t *image, int left, int top, int right, int bottom) { Gimp_Image_t *i = (Gimp_Image_t *) (image->rep); int xmax = (i->columns ? i->drawable->height : i->drawable->width) - 1; int ymax = (i->columns ? i->drawable->width : i->drawable->height) - 1; int nx = i->ox + i->mirror ? right : left; int ny = i->oy + top * (i->increment); int nw = i->w - left - right; int nh = i->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 = i->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; i->ox = nx; i->oy = ny; i->w = nw; i->h = nh; } static void Image_rotate_ccw(stp_image_t *image) { Image_transpose(image); Image_vflip(image); } static void Image_rotate_cw(stp_image_t *image) { Image_transpose(image); Image_hflip(image); } static void Image_rotate_180(stp_image_t *image) { Image_vflip(image); Image_hflip(image); } static int Image_bpp(stp_image_t *image) { Gimp_Image_t *i = (Gimp_Image_t *) (image->rep); return i->drawable->bpp; } static int Image_width(stp_image_t *image) { Gimp_Image_t *i = (Gimp_Image_t *) (image->rep); return i->w; } static int Image_height(stp_image_t *image) { Gimp_Image_t *i = (Gimp_Image_t *) (image->rep); return i->h; } static stp_image_status_t Image_get_row(stp_image_t *image, unsigned char *data, int row) { Gimp_Image_t *i = (Gimp_Image_t *) (image->rep); if (i->columns) gimp_pixel_rgn_get_col(&(i->rgn), data, i->oy + row * i->increment, i->ox, i->w); else gimp_pixel_rgn_get_row(&(i->rgn), data, i->ox, i->oy + row * i->increment, i->w); if (i->mirror) { /* Flip row -- probably inefficiently */ int f, l, b = i->drawable->bpp; for (f = 0, l = i->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; } } } return STP_IMAGE_OK; } static void Image_progress_init(stp_image_t *image) { gimp_progress_init(_("Printing...")); } static void Image_note_progress(stp_image_t *image, double current, double total) { gimp_progress_update(current / total); } static void Image_progress_conclude(stp_image_t *image) { gimp_progress_update(1); } static const char * Image_get_appname(stp_image_t *image) { static char pluginname[] = PLUG_IN_NAME " plug-in V" PLUG_IN_VERSION " for GIMP"; return pluginname; } /* * End of "$Id$". */