Added xjt plug-in.

--Sven
This commit is contained in:
Sven Neumann 1999-03-23 12:04:08 +00:00
parent 9c2d270ac0
commit 1a3398f0bb
12 changed files with 4818 additions and 3 deletions

View file

@ -1,3 +1,9 @@
Tue Mar 23 12:59:20 MET 1999 Sven Neumann <sven@gimp.org>
* configure.in
* plug-ins/Makefile
* plug-ins/xjt: added xjt plug-in created by Wolfgang Hofer.
Tue Mar 23 12:01:48 MET 1999 Sven Neumann <sven@gimp.org>
* configure.in

View file

@ -219,7 +219,8 @@ dnl Test for libjpeg
AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
jpeg_ok=yes,
jpeg_ok=no
AC_MSG_WARN(*** JPEG plug-in will not be built (JPEG library not found) ***))
AC_MSG_WARN(*** JPEG plug-in will not be built (JPEG library not found) ***)
AC_MSG_WARN(*** XJT plug-in will not be built (JPEG library not found) ***))
if test "$jpeg_ok" = yes; then
AC_MSG_CHECKING([for jpeglib.h])
AC_TRY_CPP(
@ -231,12 +232,13 @@ dnl Test for libjpeg
jpeg_ok=no)
AC_MSG_RESULT($jpeg_ok)
if test "$jpeg_ok" = yes; then
JPEG='jpeg'; LIBJPEG_LIB='-ljpeg'
JPEG='jpeg'; XJT='xjt'; LIBJPEG_LIB='-ljpeg'
AC_CHECK_LIB(jpeg, jpeg_simple_progression,
AC_DEFINE(HAVE_PROGRESSIVE_JPEG),
AC_MSG_WARN(JPEG library does not support progressive saving.))
else
AC_MSG_WARN(*** JPEG plug-in will not be built (JPEG header file not found) ***)
AC_MSG_WARN(*** XJT plug-in will not be built (JPEG header file not found) ***)
fi
fi
fi
@ -600,7 +602,7 @@ fi
GIMPDOCS=
if test -n "$DISTMAKE"; then
WEBBROWSER=webbrowser TIFF=tiff JPEG=jpeg PNG=png AA=aa MPEG=mpeg
XD=xd XPM=xpm GIMPDOCS=docs
XD=xd XJT=xjt XPM=xpm GIMPDOCS=docs
fi
AM_CONDITIONAL(STATICLIBS, test x$enable_static = xyes)
@ -631,6 +633,7 @@ AC_SUBST(LIBXMU_LIB)
AC_SUBST(TIFF)
AC_SUBST(LIBTIFF_LIB)
AC_SUBST(JPEG)
AC_SUBST(XJT)
AC_SUBST(LIBJPEG_LIB)
AC_SUBST(PNG)
AC_SUBST(LIBPNG_LIB)
@ -677,6 +680,7 @@ plug-ins/png/Makefile
plug-ins/tiff/Makefile
plug-ins/webbrowser/Makefile
plug-ins/xd/Makefile
plug-ins/xjt/Makefile
plug-ins/xpm/Makefile
plug-ins/AlienMap/Makefile
plug-ins/CEL/Makefile

View file

@ -14,6 +14,7 @@ SUBDIRS = \
@TIFF@ \
@WEBBROWSER@ \
@XD@ \
@XJT@ \
@XPM@ \
AlienMap \
CEL \

6
plug-ins/xjt/.cvsignore Normal file
View file

@ -0,0 +1,6 @@
Makefile.in
Makefile
.deps
_libs
.libs
xjt

46
plug-ins/xjt/Makefile.am Normal file
View file

@ -0,0 +1,46 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = xjt
EXTRA_DIST = README README_xjt_fileformat.txt
xjt_SOURCES = \
xjt.c xjpeg.c xjpeg.h xpdb_calls.c xpdb_calls.h
INCLUDES = \
$(GTK_CFLAGS) \
-I$(top_srcdir) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimpui.la \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
@LIBJPEG_LIB@ \
-lc
DEPS = \
$(top_builddir)/libgimp/libgimpui.la \
$(top_builddir)/libgimp/libgimp.la
xjt_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

89
plug-ins/xjt/README Normal file
View file

@ -0,0 +1,89 @@
xjt is a file plug-in to load and save GIMP RGB and GRAY Images with
all its layers, channels and guides.
Started implementation TATTOO, PARASITE RESOLUTION 1999.02.01
(see README_xjt_fileformat.txt for more Information about XJT)
The XJT Load/Save Plugin requires:
- GIMP 1.0.0 (or better)
- libjpeg
- Unix tar
- Unix gzip (optional)
- Unix bzip2 (optional)
- gap_patches (optional) **)
**) NO PATCHES are required if you have the latest development version of GIMP 1.1
Installation:
-------------
If You are using GIMP 1.0.2 (or older versions):
# (optional) install gap_patches
# they are available at the registry at:
# http://gimp.foebud.org/registry/detailview.phtml?plugin=gap_patches
# or at:
# http://gimp.foebud.org/registry/detailview.phtml?plugin=gap
cp Makefile.1.0 Makefile
If you are using GIMP 1.1.1
# GIMP 1.1.1 is an unstable prerelease.
cp Makefile.1.1 Makefile
# edit the Makefile to fit your setup
# then type
make # to compile and
make install # to install the plugin
Change Log:
-----------
1.02 1999.02.?? added load/save for resolution, tattoos, and parasites
(works only with gimp 1.1.1)
1.01 1998.11.24 added load/save for guides (works only with gimp 1.1)
added Makefiles to compile xjt under gimp 1.0.2 and 1.1
Restrictions of the XJT release 1.01:
-----------------------------------------
The 1.01 implementation of xjt is now able to save and load
the full Image Information (including guides) on RGB and GRAY Images.
when xjt is used with the latest development version of GIMP 1.1.
If xjt is used with GIMP 1.0.2 (or earlier versions)
there are some restrictions:
GUIDES are ignored at save and load.
(GIMP 1.0.2 has no Interface to access GUIDES from a plugin)
LINKED to load/save the linked state of a Layer
you must install the GAP_PATCHES to the gimp core.
(GIMP 1.0.2 has no Interface to access the Layers LINKED state from a plugin)
FLOATING_SELECTION
are supported by the XJT Fileformat, but you need to apply the GAP_PATCHES
to the gimp core.
Without the patches:
- XJT can not find out the drawable where the floating selection
is attached to. (the PROP_FLOATING_ATTACHED property information
is not saved to the PRP file in that case)
- XJT can not attach the floating selection to a layer or channel
at load. (even if you add the PROP_FLOATING_ATTACHED to the PRP file
with an editor)
The GAP_PATCHES provide some of the missing PDB-interfaces
(except those for guides, tattoos, parasites and resolution)
for GIMP-core versions from 1.0.0 upto 1.0.2.

View file

@ -0,0 +1,339 @@
XJT Fileformat specification:
------------------------------
(XJT 1.1, 1998.10.31 - 1999.03.16)
----------------------------------------------------------------
XJT Fileformat was designed to save compressed GIMP Images with
all the properties that are available in GIMP.
XJT uses JPEG compression foreach layer or channel and TAR to
collect all layers in one file. (Layers with alphachannels
are splitted into 2 jpeg files)
Additional property informations about offsets, opacity, layernames etc..
are stored in the readable textfile called "PRP" (Properties)
The resulting tar-file is optionaly compressed a 2.nd time
using GZIP or BZIP2.
(depends on the filename ending "gz" or "bz2")
Filename Extensions are:
image.xjt # plain tar file
image.xjtgz # gzip compressed tar file
image.xjbz2 # bzip2 compressed tar file
Restrictions:
-------------
** XJT does not support INDEXED Images. **
Why should anyone use the new XJT Fileformat ?
---------------------------------------------
XJT Advantages:
- The high JPEG compression rates (1:10 and more) helps
to save a lot of Diskspace.
(especially if you are using GIMP and GAP to
store many images as AnimFrames )
- Saved image keeps all layers channels and properties
- single Layers can be extracted using tar
and then be accessed by many other
jpeg-compatible programs.
XJT Disadvantages:
- JPEG is a lossy compression.
After save and load the bitmapdata
differs a little from the original,
depending on the used quality setting.
==> use GIMP's native xcf format
where you need exactly the original.
Example:
________
Example of PRP file:
--------------------
GIMP_XJ_IMAGE ver:"1.0" w/h:256,256
L0 acl fsl pt o:35,116 n:"Pasted Layer"
L1 ln pt aml eml o:0,7 n:"Pasted Layer"
m1 smc o:0,7 n:"Pasted Layer mask"
l2 fa n:"Background"
c0 op:33.725 iv smc c:255,0,0 n:"saved selection mask"
TAR Contents of the example file
--------------------------------
>tar -tvf example.xjt
-rw-r--r-- hof/users 228 Nov 1 11:19 1998 PRP
-rw-r--r-- hof/users 2352 Nov 1 11:19 1998 c0.jpg
-rw-r--r-- hof/users 3789 Nov 1 11:19 1998 l0.jpg
-rw-r--r-- hof/users 8569 Nov 1 11:19 1998 l1.jpg
-rw-r--r-- hof/users 9098 Nov 1 11:19 1998 l2.jpg
-rw-r--r-- hof/users 3926 Nov 1 11:19 1998 la0.jpg
-rw-r--r-- hof/users 6095 Nov 1 11:19 1998 la1.jpg
-rw-r--r-- hof/users 1623 Nov 1 11:19 1998 lm1.jpg
The example image has dimensions of 256x256 pixels.
The Image Type is RGB (default Property typ:0)
L0 The Image has a floating selection (stored as l0.jpg) at offset 35/116.
The floating selection has an alpha channel (stored in la0.jpg)
The floating selection is the active Layer.
There are 2 further Layers.
L1 at offset 077 is named "Pasted Layer" and is stored in l1.jpg.
This Layer has both an alpha channel (stored in la1.jpg)
and a LayerMask (stored in lm1.jpg)
(the Properties of the LayerMask are stored in an extra Line
of the PRP file beginning with m1)
l2 is the Background Layer without alpha channel. (stored in l2.jpg)
The Floating selection is attached to this layer ("fa" Property)
c0 The image has one extra channel named "saved selection mask"
This channel has full red color (c:255,0,0 property) and an opacity
value of 33.725 % but is invisible ("iv" property)
Syntax of the PRP -file
-----------------------
Image Properties (must be the 1. line in the PRP file)
================
The line starts with
GIMP_XJ_IMAGE Image-fileformat-Identifier
followed by a List of Image properties seperated by Blank:
PROP_VERSION
PROP_DIMENSION
PROP_RESOLUTION
PROP_TYPE 0 == RGB, 1 = GRAY
PROP_GUIDES position, orientation (can occure more than 1 time)
PROP_PARASITES
Layer Properties:
=================
The line starts with
l<nr> Layer description of layer <nr> without alpha channel.
the layers bitmapdata is stored in a jpeg encoded
file named l<nr>.jpg
L<nr> Layer description of layer <nr> with alpha channel.
the layers bitmapdata is stored in a jpeg encoded
file named l<nr>.jpg,
the alpha channel is stored in an additional jpeg encoded
file named la<nr>.jpg,
followed by a List of Layer properties seperated by Blank:
(properties for the default values are not written)
PROP_ACTIVE_LAYER
PROP_FLOATING_SELECTION
PROP_FLOATING_ATTACHED
PROP_OPACITY
PROP_MODE
PROP_VISIBLE
PROP_LINKED
PROP_PRESERVE_TRANSPARENCY
PROP_APPLY_MASK
PROP_EDIT_MASK
PROP_SHOW_MASK
PROP_OFFSETS
PROP_TATTOO
PROP_PARASITES
PROP_NAME
Channel Properties:
===================
The line starts with
c<nr> Channel description of channel <nr>.
the channels bitmapdata is stored in a jpeg encoded
file named c<nr>.jpg
m<nr> Layermask-channel of layer <nr>
the layermask-channels bitmapdata is tored in a jpeg encoded
file named c<nr>.jpg
followed by a List of Channel properties seperated by Blank:
(properties for the default values are not written)
PROP_ACTIVE_CHANNEL
PROP_SELECTION
PROP_FLOATING_ATTACHED
PROP_OPACITY
PROP_VISIBLE
PROP_SHOW_MASKED
PROP_COLOR
PROP_TATTOO
PROP_PARASITES
PROP_NAME
Parasite Properties:
====================
The line starts with
p<nr> Parasite description of parasite <nr>.
the parasite data is stored 1:1 in a
file named p<nr>.pte
followed by a List of Layer properties seperated by Blank:
(properties for the default values are not written)
PROP_NAME
--------------------------
Properties Summary
--------------------------
Property types:
PTYP_BOOLEAN
mnemonic
PTYP_INT
mnemonic:int_value
PTYP_2xINT
mnemonic:int_value,int_value
PTYP_3xINT
mnemonic:int_value,int_value,int_value
PTYP_FLT
mnemonic:float_value
PTYP_2xFLT
mnemonic:float_value,float_value
PTYP_STRING
mnemonic:"string_value"
Properties are written as short mnemonics (1 upto 3 characters) to identify the Property.
Non-boolean Property-mnemonics require a Value seperated by ':'.
For each property there is a defined Defaultvalue. (usually 0, or "" for strings)
The Defaultvalue is assumed when the Token is not specified,
Boolean tokens default always to FALSE and become TRUE when specified.
/* propery mnemonic type default values */
PROP_END, "*", PTYP_NOT_SUPPORTED, 0,
PROP_COLORMAP, "*", PTYP_NOT_SUPPORTED, 0,
PROP_ACTIVE_LAYER, "acl", PTYP_BOOLEAN, FALSE,
PROP_ACTIVE_CHANNEL, "acc", PTYP_BOOLEAN, FALSE,
PROP_SELECTION, "sel", PTYP_BOOLEAN, FALSE,
PROP_FLOATING_SELECTION, "fsl", PTYP_BOOLEAN, FALSE,
PROP_OPACITY, "op", PTYP_FLT, 100.0,
PROP_MODE, "md", PTYP_INT, 0,
PROP_VISIBLE, "iv", PTYP_BOOLEAN, FALSE,
PROP_LINKED, "ln", PTYP_BOOLEAN, FALSE,
PROP_PRESERVE_TRANSPARENCY, "pt", PTYP_BOOLEAN, FALSE,
PROP_APPLY_MASK, "aml", PTYP_BOOLEAN, FALSE,
PROP_EDIT_MASK, "eml", PTYP_BOOLEAN, FALSE,
PROP_SHOW_MASK, "sml", PTYP_BOOLEAN, FALSE,
PROP_SHOW_MASKED, "smc", PTYP_BOOLEAN, FALSE,
PROP_OFFSETS, "o", PTYP_2xINT, 0, 0,
PROP_COLOR, "c", PTYP_3xINT, 0, 0, 0,
PROP_COMPRESSION, "*", PTYP_NOT_SUPPORTED, 0,
PROP_GUIDES, "g", PTYP_2xINT, 0, 0,
PROP_RESOLUTION, "res", PTYP_2xFLT, 72.0, 72.0,
PROP_TATTOO, "tto", PTYP_INT, 0,
PROP_PARASITES, "pte", PTYP_INT, 0,
PROP_FLOATING_ATTACHED, "fa", PTYP_BOOLEAN, FALSE,
PROP_NAME, "n", PTYP_STRING, "",
PROP_DIMENSION, "w/h", PTYP_2xINT, 0, 0,
PROP_TYPE, "typ", PTYP_INT, 0,
PROP_VERSION, "ver", PTYP_STRING, 0,
PROP_OPACITY valid values are
0.0 ( full transparent)
upto
100.0 (full opaque)
PROP_TYPE valid values are:
0 ... RGB
1 ... GRAY
PROP_MODE valid values are:
0 ... NORMAL_MODE
1 ... DISSOLVE_MODE
3 ... MULTIPLY_MODE
4 ... SCREEN_MODE
5 ... OVERLAY_MODE
6 ... DIFFERENCE_MODE
7 ... ADDITION_MODE
8 ... SUBTRACT_MODE
9 ... DARKEN_ONLY_MODE
10 ... LIGHTEN_ONLY_MODE
11 ... HUE_MODE
12 ... SATURATION_MODE
13 ... COLOR_MODE
14 ... VALUE_MODE
-----------------------------------------------------------
changelog:
------------------------------------------------
- XJT Version 1.1
XJT Format 1.1 was extended for
RESOLUTION, TATTOO's, and PARASITES
Please note that TATTOO's and PARASITES are only defined
but not implemented.
(Gimp 1.1.3 has no PDB-Interfaces to enable Plug-Ins
to Load/Save TATTOO's and PARASITES)
PARASITES: The parasite data is stored in a seperate file for each
parasite. The file is named p<id>.pte, where
<id> is a unique integer parasite Id.
A Layer, Channel or Image can have 0 or more PROP_PARASITE
Properties (pte:1 pte:2 ...), where the integer parameter
refers to the unique parasite id.
Parasite entries can have a Name Property.
Extended Example of PRP file with resolution, and parasites:
-------------------------------------------------------------
GIMP_XJ_IMAGE ver:"1.1" w/h:256,256 res:72.0,100.5 pte:1
L0 acl fsl pt o:35,116 n:"Pasted Layer"
L1 ln pt aml eml o:0,7 n:"Pasted Layer" pte:2 pte:3
m1 smc o:0,7 n:"Pasted Layer mask"
l2 fa n:"Background"
c0 op:33.725 iv smc c:255,0,0 n:"saved selection mask" pte:4
p1 n:"image parasite"
p2 n:"layer parasite A"
p3 n:"layer parasite B"
p4 n:"channel parasite"
TAR Contents of the example file
--------------------------------
>tar -tvf example.xjt
-rw-r--r-- hof/users 228 Nov 1 11:19 1998 PRP
-rw-r--r-- hof/users 2352 Nov 1 11:19 1998 c0.jpg
-rw-r--r-- hof/users 3789 Nov 1 11:19 1998 l0.jpg
-rw-r--r-- hof/users 8569 Nov 1 11:19 1998 l1.jpg
-rw-r--r-- hof/users 9098 Nov 1 11:19 1998 l2.jpg
-rw-r--r-- hof/users 3926 Nov 1 11:19 1998 la0.jpg
-rw-r--r-- hof/users 6095 Nov 1 11:19 1998 la1.jpg
-rw-r--r-- hof/users 1623 Nov 1 11:19 1998 lm1.jpg
p1.pte
p2.pte
p3.pte
p4.pte

942
plug-ins/xjt/xjpeg.c Normal file
View file

@ -0,0 +1,942 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* 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.
*/
/* JPEG loading and saving routines adapted for the GIMP XJT fileformat
* -Wolfgang Hofer
*
* This filter is heavily based upon the "example.c" file in libjpeg.
* In fact most of the loading and saving code was simply cut-and-pasted
* from that file. The filter, therefore, also uses libjpeg.
*/
/* revision history:
* version 1.00.00; 1998/10/26 hof: 1.st (pre) release
*/
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Include for External Libraries */
#include <jpeglib.h>
/* GIMP includes */
#include "libgimp/gimp.h"
#include "xjpeg.h"
extern int xjt_debug;
/* Declare local functions.
*/
typedef struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
} *my_error_ptr;
/*
* Here's the routine that will replace the standard error_exit method:
*/
static void
my_error_exit (j_common_ptr cinfo)
{
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
my_error_ptr myerr = (my_error_ptr) cinfo->err;
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
(*cinfo->err->output_message) (cinfo);
/* Return control to the setjmp point */
longjmp (myerr->setjmp_buffer, 1);
}
/* ============================================================================
* xjpg_load_layer
* load layer from jpeg file
* ============================================================================
*/
gint32
xjpg_load_layer (char *filename,
gint32 image_id,
int image_type,
char *layer_name,
gdouble layer_opacity,
GLayerMode layer_mode
)
{
GPixelRgn l_pixel_rgn;
GDrawable *l_drawable;
gint32 l_layer_id;
GDrawableType l_layer_type;
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
FILE *infile;
guchar *l_buf;
guchar **l_rowbuf;
int l_tile_height;
int l_scanlines;
int l_idx, l_start, l_end;
/* We set up the normal JPEG error routines. */
cinfo.err = jpeg_std_error (&jerr.pub);
jerr.pub.error_exit = my_error_exit;
l_layer_type = GRAY_IMAGE;
if ((infile = fopen (filename, "rb")) == NULL)
{
g_warning ("can't open \"%s\"\n", filename);
return -1;
}
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp (jerr.setjmp_buffer))
{
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
jpeg_destroy_decompress (&cinfo);
if (infile)
fclose (infile);
fprintf(stderr, "XJT: JPEG load error\n");
return -1;
}
/* Now we can initialize the JPEG decompression object. */
jpeg_create_decompress (&cinfo);
/* Step 2: specify data source (eg, a file) */
jpeg_stdio_src (&cinfo, infile);
/* Step 3: read file parameters with jpeg_read_header() */
(void) jpeg_read_header (&cinfo, TRUE);
/* We can ignore the return value from jpeg_read_header since
* (a) suspension is not possible with the stdio data source, and
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
* See libjpeg.doc for more info.
*/
/* Step 4: set parameters for decompression */
/* In this example, we don't need to change any of the defaults set by
* jpeg_read_header(), so we do nothing here.
*/
/* Step 5: Start decompressor */
jpeg_start_decompress (&cinfo);
/* We may need to do some setup of our own at this point before reading
* the data. After jpeg_start_decompress() we have the correct scaled
* output image dimensions available, as well as the output colormap
* if we asked for color quantization.
* In this example, we need to make an output work buffer of the right size.
*/
/* temporary buffer */
l_tile_height = gimp_tile_height ();
l_buf = g_new (guchar, l_tile_height * cinfo.output_width * cinfo.output_components);
l_rowbuf = g_new (guchar*, l_tile_height);
for (l_idx = 0; l_idx < l_tile_height; l_idx++)
{
l_rowbuf[l_idx] = l_buf + cinfo.output_width * cinfo.output_components * l_idx;
}
/* Check jpeg file for layer type */
switch (cinfo.output_components)
{
case 1:
l_layer_type = GRAY_IMAGE;
break;
case 3:
l_layer_type = RGB_IMAGE;
break;
default:
fprintf(stderr, "XJT: cant load layer %s (type is not GRAY and not RGB)\n", filename);
fclose (infile);
return -1;
}
l_layer_id = gimp_layer_new (image_id, layer_name,
cinfo.output_width,
cinfo.output_height,
l_layer_type,
layer_opacity,
layer_mode);
if(l_layer_id < 0)
{
fprintf(stderr, "XJT: cant create new layer\n");
fclose (infile);
return -1;
}
l_drawable = gimp_drawable_get (l_layer_id);
gimp_pixel_rgn_init (&l_pixel_rgn, l_drawable, 0, 0, l_drawable->width, l_drawable->height, TRUE, FALSE);
/* Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
/* Here we use the library's state variable cinfo.output_scanline as the
* loop counter, so that we don't have to keep track ourselves.
*/
while (cinfo.output_scanline < cinfo.output_height)
{
l_start = cinfo.output_scanline;
l_end = cinfo.output_scanline + l_tile_height;
l_end = MIN (l_end, cinfo.output_height);
l_scanlines = l_end - l_start;
for (l_idx = 0; l_idx < l_scanlines; l_idx++)
{
jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &l_rowbuf[l_idx], 1);
}
gimp_pixel_rgn_set_rect (&l_pixel_rgn, l_buf, 0, l_start, l_drawable->width, l_scanlines);
gimp_progress_update ((double) cinfo.output_scanline / (double) cinfo.output_height);
}
/* Step 7: Finish decompression */
jpeg_finish_decompress (&cinfo);
/* We can ignore the return value since suspension is not possible
* with the stdio data source.
*/
/* Step 8: Release JPEG decompression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_decompress (&cinfo);
/* free up the temporary buffers */
g_free (l_rowbuf);
g_free (l_buf);
/* After finish_decompress, we can close the input file.
* Here we postpone it until after no more JPEG errors are possible,
* so as to simplify the setjmp error logic above. (Actually, I don't
* think that jpeg_destroy can do an error exit, but why assume anything...)
*/
fclose (infile);
/* At this point you may want to check to see whether any corrupt-data
* warnings occurred (test whether jerr.num_warnings is nonzero).
*/
return (l_layer_id);
} /* end xjpg_load_layer */
/* ============================================================================
* xjpg_load_layer_alpha
* load the layers alpha channel from jpeg file.
* ============================================================================
*/
gint
xjpg_load_layer_alpha (char *filename,
gint32 image_id,
gint32 layer_id
)
{
GPixelRgn l_pixel_rgn;
GDrawable *l_drawable;
GDrawableType l_layer_type;
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
FILE *infile;
guchar *l_buf;
guchar *l_dstbuf;
guchar **l_rowbuf;
int l_tile_height;
int l_scanlines;
int l_idx, l_start, l_end;
int l_alpha_offset;
guchar *l_buf_ptr;
guchar *l_dstbuf_ptr;
/* We set up the normal JPEG error routines. */
cinfo.err = jpeg_std_error (&jerr.pub);
jerr.pub.error_exit = my_error_exit;
l_layer_type = GRAY_IMAGE;
/* add alpha channel */
gimp_layer_add_alpha (layer_id);
if ((infile = fopen (filename, "rb")) == NULL)
{
/* No alpha found, thats OK, use full opaque alpha channel
* (there is no need not store alpha channels on full opaque channels)
* (fixme: if filename exists but is not readable
* we should return -1 to indicate an error
*/
return 0; /* OK */
}
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp (jerr.setjmp_buffer))
{
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
jpeg_destroy_decompress (&cinfo);
if (infile)
fclose (infile);
fprintf(stderr, "XJT: JPEG alpha load error\n");
return -1;
}
/* Now we can initialize the JPEG decompression object. */
jpeg_create_decompress (&cinfo);
/* Step 2: specify data source (eg, a file) */
jpeg_stdio_src (&cinfo, infile);
/* Step 3: read file parameters with jpeg_read_header() */
(void) jpeg_read_header (&cinfo, TRUE);
/* We can ignore the return value from jpeg_read_header since
* (a) suspension is not possible with the stdio data source, and
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
* See libjpeg.doc for more info.
*/
/* Step 4: set parameters for decompression */
/* In this example, we don't need to change any of the defaults set by
* jpeg_read_header(), so we do nothing here.
*/
/* Step 5: Start decompressor */
jpeg_start_decompress (&cinfo);
/* We may need to do some setup of our own at this point before reading
* the data. After jpeg_start_decompress() we have the correct scaled
* output image dimensions available, as well as the output colormap
* if we asked for color quantization.
* In this example, we need to make an output work buffer of the right size.
*/
/* temporary buffer (for read in jpeg lines) */
l_tile_height = gimp_tile_height ();
l_buf = g_new (guchar, l_tile_height * cinfo.output_width * cinfo.output_components);
l_rowbuf = g_new (guchar*, l_tile_height);
for (l_idx = 0; l_idx < l_tile_height; l_idx++)
{
l_rowbuf[l_idx] = l_buf + cinfo.output_width * cinfo.output_components * l_idx;
}
l_drawable = gimp_drawable_get (layer_id);
if(l_drawable == NULL)
{
fprintf(stderr, "XJT: gimp_drawable_get failed on layer id %d\n", (int)layer_id);
fclose(infile);
return -1;
}
/* Check if jpeg file can be used as alpha channel
*/
if((cinfo.output_components != 1) ||
(cinfo.output_width != l_drawable->width) ||
(cinfo.output_height != l_drawable->height))
{
fprintf(stderr, "XJT: cant load %s as alpha channel\n", filename);
fclose (infile);
return -1;
}
/* buffer to read in the layer and merge with the alpha from jpeg file */
l_dstbuf = g_new (guchar, l_tile_height * l_drawable->width * l_drawable->bpp);
gimp_pixel_rgn_init (&l_pixel_rgn, l_drawable, 0, 0, l_drawable->width, l_drawable->height, TRUE, FALSE);
l_alpha_offset = l_drawable->bpp -1;
/* Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
/* Here we use the library's state variable cinfo.output_scanline as the
* loop counter, so that we don't have to keep track ourselves.
*/
while (cinfo.output_scanline < cinfo.output_height)
{
l_start = cinfo.output_scanline;
l_end = cinfo.output_scanline + l_tile_height;
l_end = MIN (l_end, cinfo.output_height);
l_scanlines = l_end - l_start;
for (l_idx = 0; l_idx < l_scanlines; l_idx++)
{
jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &l_rowbuf[l_idx], 1);
}
gimp_pixel_rgn_get_rect (&l_pixel_rgn, l_dstbuf, 0, l_start, l_drawable->width, l_scanlines);
/* copy the loaded jpeg data (from buf) to the layers alpha channel data */
l_idx = l_tile_height * l_drawable->width;
l_buf_ptr = l_buf;
l_dstbuf_ptr = l_dstbuf;
while(l_idx--)
{
l_dstbuf_ptr += l_alpha_offset;
*l_dstbuf_ptr++ = *l_buf_ptr++;
}
gimp_pixel_rgn_set_rect (&l_pixel_rgn, l_dstbuf, 0, l_start, l_drawable->width, l_scanlines);
gimp_progress_update ((double) cinfo.output_scanline / (double) cinfo.output_height);
}
/* Step 7: Finish decompression */
jpeg_finish_decompress (&cinfo);
/* We can ignore the return value since suspension is not possible
* with the stdio data source.
*/
/* Step 8: Release JPEG decompression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_decompress (&cinfo);
/* free up the temporary buffers */
g_free (l_rowbuf);
g_free (l_buf);
g_free (l_dstbuf);
/* After finish_decompress, we can close the input file.
* Here we postpone it until after no more JPEG errors are possible,
* so as to simplify the setjmp error logic above. (Actually, I don't
* think that jpeg_destroy can do an error exit, but why assume anything...)
*/
fclose (infile);
/* At this point you may want to check to see whether any corrupt-data
* warnings occurred (test whether jerr.num_warnings is nonzero).
*/
return (0); /* OK */
} /* xjpg_load_layer_alpha */
/* ============================================================================
* xjpg_load_channel
* load channel from jpeg file
* (call this procedure with drawable_id == -1 to create a new channel,
* if a positive drawable_id is supplied, its content will be overwritten)
* ============================================================================
*/
gint32
xjpg_load_channel (char *filename,
gint32 image_id,
gint32 drawable_id,
char *channel_name,
gdouble channel_opacity,
guchar red, guchar green, guchar blue
)
{
GPixelRgn l_pixel_rgn;
GDrawable *l_drawable;
gint32 l_drawable_id;
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
FILE *infile;
guchar *l_buf;
guchar **l_rowbuf;
int l_tile_height;
int l_scanlines;
int l_idx, l_start, l_end;
guchar l_color[3];
l_color[0] = red;
l_color[1] = green;
l_color[2] = blue;
/* We set up the normal JPEG error routines. */
cinfo.err = jpeg_std_error (&jerr.pub);
jerr.pub.error_exit = my_error_exit;
if ((infile = fopen (filename, "rb")) == NULL)
{
g_warning ("can't open \"%s\"\n", filename);
return -1;
}
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp (jerr.setjmp_buffer))
{
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
jpeg_destroy_decompress (&cinfo);
if (infile)
fclose (infile);
fprintf(stderr, "XJT: JPEG load error\n");
return -1;
}
/* Now we can initialize the JPEG decompression object. */
jpeg_create_decompress (&cinfo);
/* Step 2: specify data source (eg, a file) */
jpeg_stdio_src (&cinfo, infile);
/* Step 3: read file parameters with jpeg_read_header() */
(void) jpeg_read_header (&cinfo, TRUE);
/* We can ignore the return value from jpeg_read_header since
* (a) suspension is not possible with the stdio data source, and
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
* See libjpeg.doc for more info.
*/
/* Step 4: set parameters for decompression */
/* In this example, we don't need to change any of the defaults set by
* jpeg_read_header(), so we do nothing here.
*/
/* Step 5: Start decompressor */
jpeg_start_decompress (&cinfo);
/* We may need to do some setup of our own at this point before reading
* the data. After jpeg_start_decompress() we have the correct scaled
* output image dimensions available, as well as the output colormap
* if we asked for color quantization.
* In this example, we need to make an output work buffer of the right size.
*/
/* temporary buffer */
l_tile_height = gimp_tile_height ();
l_buf = g_new (guchar, l_tile_height * cinfo.output_width * cinfo.output_components);
l_rowbuf = g_new (guchar*, l_tile_height);
for (l_idx = 0; l_idx < l_tile_height; l_idx++)
{
l_rowbuf[l_idx] = l_buf + cinfo.output_width * cinfo.output_components * l_idx;
}
/* Check if jpeg file has one component (a channel cant have more than one)
*/
if(cinfo.output_components != 1)
{
fprintf(stderr, "XJT: cant load RGB layer %s into GRAY Image\n", filename);
fclose (infile);
return -1;
}
if(drawable_id < 0)
{
l_drawable_id = gimp_channel_new (image_id, channel_name,
cinfo.output_width,
cinfo.output_height,
channel_opacity,
l_color);
if(l_drawable_id < 0)
{
fprintf(stderr, "XJT: cant create new channel\n");
fclose (infile);
return -1;
}
}
else
{
l_drawable_id = drawable_id; /* overwrite the given drawable */
}
l_drawable = gimp_drawable_get (l_drawable_id);
if((l_drawable->width != cinfo.output_width)
|| (l_drawable->height != cinfo.output_height)
|| (l_drawable->bpp != cinfo.output_components) )
{
fprintf(stderr, "XJT: cant load-overwrite drawable (size missmatch)\n");
fclose (infile);
return -1;
}
gimp_pixel_rgn_init (&l_pixel_rgn, l_drawable, 0, 0, l_drawable->width, l_drawable->height, TRUE, FALSE);
/* Step 6: while (scan lines remain to be read) */
/* jpeg_read_scanlines(...); */
/* Here we use the library's state variable cinfo.output_scanline as the
* loop counter, so that we don't have to keep track ourselves.
*/
while (cinfo.output_scanline < cinfo.output_height)
{
l_start = cinfo.output_scanline;
l_end = cinfo.output_scanline + l_tile_height;
l_end = MIN (l_end, cinfo.output_height);
l_scanlines = l_end - l_start;
for (l_idx = 0; l_idx < l_scanlines; l_idx++)
{
jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &l_rowbuf[l_idx], 1);
}
gimp_pixel_rgn_set_rect (&l_pixel_rgn, l_buf, 0, l_start, l_drawable->width, l_scanlines);
gimp_progress_update ((double) cinfo.output_scanline / (double) cinfo.output_height);
}
/* Step 7: Finish decompression */
jpeg_finish_decompress (&cinfo);
/* We can ignore the return value since suspension is not possible
* with the stdio data source.
*/
/* Step 8: Release JPEG decompression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_decompress (&cinfo);
/* free up the temporary buffers */
g_free (l_rowbuf);
g_free (l_buf);
/* After finish_decompress, we can close the input file.
* Here we postpone it until after no more JPEG errors are possible,
* so as to simplify the setjmp error logic above. (Actually, I don't
* think that jpeg_destroy can do an error exit, but why assume anything...)
*/
fclose (infile);
/* At this point you may want to check to see whether any corrupt-data
* warnings occurred (test whether jerr.num_warnings is nonzero).
*/
/* Tell the GIMP to display the image.
*/
/* gimp_drawable_flush (l_drawable); */
return (l_drawable_id);
} /* end xjpg_load_channel */
/* ============================================================================
* xjpg_save_drawable
* save as drawable as jpeg file depending on save_mode:
* - save the drawable without alpha channel.
* (optional clear full transparent pixels to 0,
* resulting in better compression)
* - save the alpha channel
* ============================================================================
*/
gint
xjpg_save_drawable (char *filename,
gint32 image_ID,
gint32 drawable_ID,
gint save_mode,
t_JpegSaveVals *jsvals)
{
GPixelRgn pixel_rgn;
GDrawable *drawable;
GDrawableType drawable_type;
struct jpeg_compress_struct cinfo;
struct my_error_mgr jerr;
FILE *outfile;
guchar *temp, *t;
guchar *data;
guchar *src, *s;
int has_alpha;
int rowstride, yend;
int i, j;
int alpha_offset;
guchar alpha_byte;
guchar l_alpha_sum;
alpha_offset = 0;
has_alpha = 0;
src = NULL;
temp = NULL;
data = NULL;
l_alpha_sum = 0xff;
drawable = gimp_drawable_get (drawable_ID);
drawable_type = gimp_drawable_type (drawable_ID);
switch (drawable_type)
{
case RGB_IMAGE:
case GRAY_IMAGE:
if(save_mode == JSVM_ALPHA)
return FALSE; /* there is no alpha to save */
break;
case RGBA_IMAGE:
case GRAYA_IMAGE:
break;
case INDEXED_IMAGE:
/*g_message ("jpeg: cannot operate on indexed color images");*/
return FALSE;
break;
default:
/*g_message ("jpeg: cannot operate on unknown image types");*/
return FALSE;
break;
}
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, FALSE, FALSE);
/* Step 1: allocate and initialize JPEG compression object */
/* We have to set up the error handler first, in case the initialization
* step fails. (Unlikely, but it could happen if you are out of memory.)
* This routine fills in the contents of struct jerr, and returns jerr's
* address which we place into the link field in cinfo.
*/
cinfo.err = jpeg_std_error (&jerr.pub);
jerr.pub.error_exit = my_error_exit;
outfile = NULL;
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp (jerr.setjmp_buffer))
{
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
jpeg_destroy_compress (&cinfo);
if (outfile)
fclose (outfile);
if (drawable)
gimp_drawable_detach (drawable);
return FALSE;
}
/* Now we can initialize the JPEG compression object. */
jpeg_create_compress (&cinfo);
/* Step 2: specify data destination (eg, a file) */
/* Note: steps 2 and 3 can be done in either order. */
/* Here we use the library-supplied code to send compressed data to a
* stdio stream. You can also write your own code to do something else.
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
* requires it in order to write binary files.
*/
if ((outfile = fopen (filename, "wb")) == NULL)
{
g_message ("can't open %s\n", filename);
return FALSE;
}
jpeg_stdio_dest (&cinfo, outfile);
/* Get the input image and a pointer to its data.
*/
switch (drawable_type)
{
case RGB_IMAGE:
case GRAY_IMAGE:
/* # of color components per pixel */
cinfo.input_components = drawable->bpp;
has_alpha = 0;
alpha_offset = 0;
break;
case RGBA_IMAGE:
case GRAYA_IMAGE:
if(save_mode == JSVM_ALPHA)
{
cinfo.input_components = 1;
}
else
{
/* # of color components per pixel (minus the GIMP alpha channel) */
cinfo.input_components = drawable->bpp - 1;
}
alpha_offset = drawable->bpp -1;
has_alpha = 1;
break;
default:
return FALSE;
break;
}
/* Step 3: set parameters for compression */
/* First we supply a description of the input image.
* Four fields of the cinfo struct must be filled in:
*/
/* image width and height, in pixels */
cinfo.image_width = drawable->width;
cinfo.image_height = drawable->height;
/* colorspace of input image */
cinfo.in_color_space = ( (save_mode != JSVM_ALPHA) &&
(drawable_type == RGB_IMAGE ||
drawable_type == RGBA_IMAGE))
? JCS_RGB : JCS_GRAYSCALE;
/* Now use the library's routine to set default compression parameters.
* (You must set at least cinfo.in_color_space before calling this,
* since the defaults depend on the source color space.)
*/
jpeg_set_defaults (&cinfo);
/* Now you can set any non-default parameters you wish to.
* Here we just illustrate the use of quality (quantization table) scaling:
*/
jpeg_set_quality (&cinfo, (int) (jsvals->quality * 100), TRUE /* limit to baseline-JPEG values */);
cinfo.smoothing_factor = (int) (jsvals->smoothing * 100);
cinfo.optimize_coding = jsvals->optimize;
/* Step 4: Start compressor */
/* TRUE ensures that we will write a complete interchange-JPEG file.
* Pass TRUE unless you are very sure of what you're doing.
*/
jpeg_start_compress (&cinfo, TRUE);
/* Step 5: while (scan lines remain to be written) */
/* jpeg_write_scanlines(...); */
/* Here we use the library's state variable cinfo.next_scanline as the
* loop counter, so that we don't have to keep track ourselves.
* To keep things simple, we pass one scanline per call; you can pass
* more if you wish, though.
*/
/* JSAMPLEs per row in image_buffer */
rowstride = drawable->bpp * drawable->width;
temp = (guchar *) malloc (cinfo.image_width * cinfo.input_components);
data = (guchar *) malloc (rowstride * gimp_tile_height ());
src = data;
while (cinfo.next_scanline < cinfo.image_height)
{
if ((cinfo.next_scanline % gimp_tile_height ()) == 0)
{
yend = cinfo.next_scanline + gimp_tile_height ();
yend = MIN (yend, cinfo.image_height);
gimp_pixel_rgn_get_rect (&pixel_rgn, data, 0, cinfo.next_scanline, cinfo.image_width,
(yend - cinfo.next_scanline));
src = data;
}
t = temp;
s = src;
i = cinfo.image_width;
switch(save_mode)
{
case JSVM_DRAWABLE:
if(jsvals->clr_transparent)
{
/* save drawable (clear pixels where alpha is full transparent) */
while (i--)
{
alpha_byte = s[cinfo.input_components];
for (j = 0; j < cinfo.input_components; j++)
{
if(alpha_byte != 0) { *t++ = *s++; }
else { *t++ = 0; s++; }
}
if (has_alpha) /* ignore alpha channel */
{
s++;
}
}
}
else
{
/* save the drawable as it is (ignore alpha channel) */
while (i--)
{
for (j = 0; j < cinfo.input_components; j++)
{
*t++ = *s++;
}
if (has_alpha) /* ignore alpha channel */
{
s++;
}
}
}
break;
case JSVM_ALPHA:
/* save the drawable's alpha cahnnel */
while (i--)
{
s += alpha_offset;
l_alpha_sum &= (*s); /* check all alpha bytes for full opacity */
*t++ = *s++;
}
break;
}
src += rowstride;
jpeg_write_scanlines (&cinfo, (JSAMPARRAY) &temp, 1);
if ((cinfo.next_scanline % 5) == 0)
gimp_progress_update ((double) cinfo.next_scanline / (double) cinfo.image_height);
}
/* Step 6: Finish compression */
jpeg_finish_compress (&cinfo);
/* After finish_compress, we can close the output file. */
fclose (outfile);
if((save_mode == JSVM_ALPHA) && (l_alpha_sum == 0xff))
{
/* all bytes in the alpha channel are set to 0xff
* == full opaque image. We can remove the file
* to save diskspace
*/
remove(filename);
}
/* Step 7: release JPEG compression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_compress (&cinfo);
/* free the temporary buffer */
free (temp);
free (data);
gimp_drawable_detach (drawable);
return TRUE;
} /* end xjpg_save_drawable */

81
plug-ins/xjt/xjpeg.h Normal file
View file

@ -0,0 +1,81 @@
/* xjpeg.h
*
* This Module contains:
* jpeg load and save procedures for the use in XJT fileformat save
* (based on libjpeg)
*
*/
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* 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.
*/
/* revision history:
* version 1.00.00; 1998/10/26 hof: 1.st (pre) release
*/
#ifndef _XJPEG_H
#define _XJPEG_H
#include "libgimp/gimp.h"
typedef enum {
JSVM_DRAWABLE, /* save the drawable as it is (ignore alpha channel) */
JSVM_ALPHA /* save the alpha channel */
} t_save_mode;
typedef struct
{
gdouble quality;
gdouble smoothing;
gint optimize;
gint clr_transparent; /* clear pixels where alpha is full transparent */
} t_JpegSaveVals;
gint
xjpg_save_drawable (char *filename,
gint32 image_ID,
gint32 drawable_ID,
gint save_mode,
t_JpegSaveVals *jsvals);
gint32
xjpg_load_layer (char *filename,
gint32 image_id,
int image_type,
char *layer_name,
gdouble layer_opacity,
GLayerMode layer_mode
);
gint
xjpg_load_layer_alpha (char *filename,
gint32 image_id,
gint32 layer_id
);
gint32
xjpg_load_channel (char *filename,
gint32 image_id,
gint32 drawable_id,
char *channel_name,
gdouble channel_opacity,
guchar red, guchar green, guchar blue
);
#endif

2459
plug-ins/xjt/xjt.c Normal file

File diff suppressed because it is too large Load diff

782
plug-ins/xjt/xpdb_calls.c Normal file
View file

@ -0,0 +1,782 @@
/* xpdb_calls.c
*
* this module contains calls of procedures in the GIMPs Procedural Database
* IMPORTANT Note:
* some of these procedures are not available in the official GIMP 1.0.2 releases
* (and prior releases)
*
* The missing procedures (except guides) are available as patches to the gimp core.
* If you dont install the patches XJT will work, but some Informations
* can not be saved or loaded.
* - floating selections
* - the layers linked state
* - guides
*
* GIMP 1.1 will provide all the procedures to run XJT at full fuctionality.
* There are no Patches required to run XJT in the latest GIMP 1.1
* development version
*/
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* 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.
*/
/* revision history:
* version 1.02.00; 1999/02/01 hof: PDB-calls to load/save resolution tattoos and parasites
* busy_cursors (needs GIMP 1.1.1)
* version 1.01.00; 1998/11/22 hof: PDB-calls to load/save guides under GIMP 1.1
* version 1.00.00; 1998/10/31 hof: 1.st (pre) release
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* GIMP includes */
#include "libgimp/gimp.h"
#include "xjpeg.h"
/* #include "cursorutil.h" */
/* XJT includes */
#include "xpdb_calls.h"
extern int xjt_debug;
/* ============================================================================
* p_procedure_available
* if requested procedure is available in the PDB return the number of args
* (0 upto n) that are needed to call the procedure.
* if not available return -1
* ============================================================================
*/
gint p_procedure_available(char *proc_name)
{
#define GET_LINKED_PROC "gimp_layer_get_linked"
/* Note: It would be nice to call "gimp_layer_get_linked" direct,
* but there is not such an Interface in gimp 0.99.16
* Workaround:
* I did a patch to implement the "gimp_layer_get_linked"
* procedure, and call it via PDB call if available.
* if not available FALSE is returned.
*/
int l_nparams;
int l_nreturn_vals;
int l_proc_type;
char *l_proc_blurb;
char *l_proc_help;
char *l_proc_author;
char *l_proc_copyright;
char *l_proc_date;
GParamDef *l_params;
GParamDef *l_return_vals;
gint l_rc;
l_rc = 0;
/* Query the gimp application's procedural database
* regarding a particular procedure.
*/
if(gimp_query_procedure (proc_name,
&l_proc_blurb,
&l_proc_help,
&l_proc_author,
&l_proc_copyright,
&l_proc_date,
&l_proc_type,
&l_nparams,
&l_nreturn_vals,
&l_params,
&l_return_vals))
{
/* procedure found in PDB */
return (l_nparams);
}
printf("Warning: Procedure %s not found.\n", proc_name);
return -1;
} /* end p_procedure_available */
/* ---------------------- PDB procedure calls -------------------------- */
/* ============================================================================
* p_get_gimp_selection_bounds
*
* ============================================================================
*/
gint
p_get_gimp_selection_bounds (gint32 image_id, gint32 *x1, gint32 *y1, gint32 *x2, gint32 *y2)
{
static char *l_get_sel_bounds_proc = "gimp_selection_bounds";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_get_sel_bounds_proc) >= 0)
{
return_vals = gimp_run_procedure (l_get_sel_bounds_proc,
&nreturn_vals,
PARAM_IMAGE, image_id,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
*x1 = return_vals[2].data.d_int32;
*y1 = return_vals[3].data.d_int32;
*x2 = return_vals[4].data.d_int32;
*y2 = return_vals[5].data.d_int32;
return(return_vals[1].data.d_int32);
}
printf("XJT: Error: PDB call of %s failed staus=%d\n",
l_get_sel_bounds_proc, (int)return_vals[0].data.d_status);
}
else
{
printf("XJT: Error: Procedure %s not found.\n",l_get_sel_bounds_proc);
}
return(FALSE);
} /* end p_get_gimp_selection_bounds */
/* ============================================================================
* p_gimp_selection_load
*
* ============================================================================
*/
gint
p_gimp_selection_load (gint32 image_id, gint32 channel_id)
{
static char *l_sel_load = "gimp_selection_load";
GParam *return_vals;
int nreturn_vals;
int l_nparams;
l_nparams = p_procedure_available(l_sel_load);
if (l_nparams >= 0)
{
/* check if it can take exactly one channel_id as input (gimp1.1) */
if(l_nparams == 1)
{
/* use the new Interface (Gimp 1.1 style)
* (1.1 knows the image_id where the channel belongs to)
*/
return_vals = gimp_run_procedure (l_sel_load,
&nreturn_vals,
PARAM_CHANNEL, channel_id,
PARAM_END);
}
else
{
/* use the old Interface (Gimp 1.0.2 style) */
return_vals = gimp_run_procedure (l_sel_load,
&nreturn_vals,
PARAM_IMAGE, image_id,
PARAM_CHANNEL, channel_id,
PARAM_END);
}
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return(TRUE);
}
printf("XJT: Error: PDB call of %s failed status=%d\n",
l_sel_load, (int)return_vals[0].data.d_status);
}
else
{
printf("XJT: Error: Procedure %s not found.\n",l_sel_load);
}
return(FALSE);
} /* end p_gimp_selection_load */
/* ============================================================================
* p_layer_set_linked
* set linked state of the layer
* ============================================================================
*/
int
p_layer_set_linked (gint32 layer_id, gint32 new_state)
{
static char *l_set_linked_proc = "gimp_layer_set_linked";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_set_linked_proc) >= 0)
{
return_vals = gimp_run_procedure (l_set_linked_proc,
&nreturn_vals,
PARAM_LAYER, layer_id,
PARAM_INT32, new_state, /* TRUE or FALSE */
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return (0);
}
printf("XJT: Error: p_set_linked to state %d failed\n",(int)new_state);
}
else
{
printf("XJT: Warning: Procedure %s not found. (Layer Can not be set to linked)\n",l_set_linked_proc);
}
return(-1);
} /* end p_layer_set_linked */
/* ============================================================================
* p_layer_get_linked
*
* ============================================================================
*/
gint p_layer_get_linked(gint32 layer_id)
{
#define GET_LINKED_PROC "gimp_layer_get_linked"
/* Note: It would be nice to call "gimp_layer_get_linked" direct,
* but there is not such an Interface in gimp 1.0.2
* Workaround:
* I did a patch to implement the "gimp_layer_get_linked"
* procedure, and call it via PDB call if available.
* if not available FALSE is returned.
*/
int l_nparams;
int l_nreturn_vals;
int l_proc_type;
char *l_proc_blurb;
char *l_proc_help;
char *l_proc_author;
char *l_proc_copyright;
char *l_proc_date;
GParamDef *l_params;
GParamDef *l_return_vals;
gint l_rc;
GParam *return_vals;
int nreturn_vals;
gint32 is_linked;
l_rc = 0;
/* Query the gimp application's procedural database
* regarding a particular procedure.
*/
if(gimp_query_procedure (GET_LINKED_PROC,
&l_proc_blurb,
&l_proc_help,
&l_proc_author,
&l_proc_copyright,
&l_proc_date,
&l_proc_type,
&l_nparams,
&l_nreturn_vals,
&l_params,
&l_return_vals))
{
/* procedure found in PDB */
/* check if it can take exactly one layerid as input
* and give one result int32 parameter (TRUE/FALSE)
*/
if (l_nparams != 1) { l_rc = -1; }
if (l_params[0].type != PARAM_LAYER) { l_rc = -1; }
if (l_nreturn_vals != 1) { l_rc = -1; }
if (l_return_vals[0].type != PARAM_INT32) { l_rc = -1; }
/* free the query information */
g_free (l_proc_blurb);
g_free (l_proc_help);
g_free (l_proc_author);
g_free (l_proc_copyright);
g_free (l_proc_date);
g_free (l_params);
g_free (l_return_vals);
if(l_rc != 0)
{
printf("Warning: Procedure %s has unexpected Interface. (Can not operate on linked layers)\n",GET_LINKED_PROC);
printf("expected: 1, 1, PARAM_LAYER = %d PARAM_INT32 = %d\n", (int)PARAM_LAYER, (int)PARAM_INT32);
printf("l_nparams = %d\n", (int)l_nparams);
printf("l_nreturn_vals = %d\n", (int)l_nreturn_vals);
printf("l_params[0].type = %d\n", (int)l_params[0].type);
printf("l_return_vals[0].type = %d\n", (int)l_return_vals[0].type);
return FALSE;
}
}
else
{
printf("Warning: Procedure %s not found. (Can not operate on linked layers)\n",GET_LINKED_PROC);
return FALSE;
}
/* run the procedure */
is_linked = FALSE;
return_vals = gimp_run_procedure (GET_LINKED_PROC,
&nreturn_vals,
PARAM_LAYER, layer_id,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
is_linked = return_vals[1].data.d_int32;
}
gimp_destroy_params (return_vals, nreturn_vals);
return is_linked;
}
/* ============================================================================
* p_gimp_image_floating_sel_attached_to
*
* ============================================================================
*/
gint32 p_gimp_image_floating_sel_attached_to(gint32 image_id)
{
static char *l_fsel_attached_to_proc = "gimp_image_floating_sel_attached_to";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_fsel_attached_to_proc) >= 0)
{
return_vals = gimp_run_procedure (l_fsel_attached_to_proc,
&nreturn_vals,
PARAM_IMAGE, image_id,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return(return_vals[1].data.d_drawable);
}
printf("XJT: Error: PDB call of %s failed\n", l_fsel_attached_to_proc);
}
else
{
printf("XJT: Warning: Procedure %s not found. %s\n",
l_fsel_attached_to_proc,
"(cant find out drawable where f-sel is attached to)");
}
return(-1);
} /* end p_gimp_image_floating_sel_attached_to */
/* ============================================================================
* p_gimp_floating_sel_attach
*
* ============================================================================
*/
gint p_gimp_floating_sel_attach(gint32 layer_id, gint32 drawable_id)
{
static char *l_fsel_attach_proc = "gimp_floating_sel_attach";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_fsel_attach_proc) >= 0)
{
return_vals = gimp_run_procedure (l_fsel_attach_proc,
&nreturn_vals,
PARAM_LAYER, layer_id,
PARAM_DRAWABLE, drawable_id,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return (0);
}
printf("XJT: Error: PDB call of %s failed\n", l_fsel_attach_proc);
}
else
{
printf("XJT: Warning: Procedure %s not found. %s\n",
l_fsel_attach_proc,
"(cannot attach floating selection)");
}
return(-1);
} /* end p_gimp_floating_sel_attach */
/* ============================================================================
* p_gimp_floating_sel_rigor
*
* ============================================================================
*/
gint p_gimp_floating_sel_rigor(gint32 layer_id, gint32 undo)
{
static char *l_fsel_rigor_proc = "gimp_floating_sel_rigor";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_fsel_rigor_proc) >= 0)
{
return_vals = gimp_run_procedure (l_fsel_rigor_proc,
&nreturn_vals,
PARAM_LAYER, layer_id,
PARAM_INT32, undo,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return (0);
}
printf("XJT: Error: PDB call of %s failed\n", l_fsel_rigor_proc);
}
else
{
printf("XJT: Warning: Procedure %s not found. %s\n",
l_fsel_rigor_proc,
"(cannot attach floating selection)");
}
return(-1);
} /* end p_gimp_floating_sel_rigor */
/* ============================================================================
* p_gimp_floating_sel_relax
*
* ============================================================================
*/
gint p_gimp_floating_sel_relax(gint32 layer_id, gint32 undo)
{
static char *l_fsel_relax_proc = "gimp_floating_sel_relax";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_fsel_relax_proc) >= 0)
{
return_vals = gimp_run_procedure (l_fsel_relax_proc,
&nreturn_vals,
PARAM_LAYER, layer_id,
PARAM_INT32, undo,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return (0);
}
printf("XJT: Error: PDB call of %s failed\n", l_fsel_relax_proc);
}
else
{
printf("XJT: Warning: Procedure %s not found. %s\n",
l_fsel_relax_proc,
"(cannot attach floating selection)");
}
return(-1);
} /* end p_gimp_floating_sel_relax */
/* ============================================================================
* p_gimp_image_add_guide
*
* ============================================================================
*/
gint32 p_gimp_image_add_guide(gint32 image_id, gint32 position, gint32 orientation)
{
static char *l_add_guide_proc;
GParam *return_vals;
int nreturn_vals;
if(orientation == 0 ) /* in GIMP 1.1 we could use (orientation == ORIENTATION_VERTICAL) */
{
l_add_guide_proc = "gimp_image_add_vguide";
}
else
{
l_add_guide_proc = "gimp_image_add_hguide";
}
if (p_procedure_available(l_add_guide_proc) >= 0)
{
return_vals = gimp_run_procedure (l_add_guide_proc,
&nreturn_vals,
PARAM_IMAGE, image_id,
PARAM_INT32, position,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return(return_vals[1].data.d_int32); /* return the guide ID */
}
printf("XJT: Error: PDB call of %s failed\n", l_add_guide_proc);
}
else
{
printf("XJT: Warning: Procedure %s not found. %s\n",
l_add_guide_proc,
"(cannot add guide)");
}
return(-1);
} /* end p_gimp_image_add_guide */
/* ============================================================================
* p_gimp_image_findnext_guide
*
* This procedure takes an image and a guide_id as input and finds the guide_id
* of the successor of the given guide_id in the image's Guide list.
* If the supplied guide_id is 0, the procedure will return the first Guide.
* The procedure will return 0 if given the final guide_id as an argument
* or the image has no guides.
*
* ============================================================================
*/
gint32 p_gimp_image_findnext_guide(gint32 image_id, gint32 guide_id)
{
static char *l_findnext_guide_proc = "gimp_image_findnext_guide";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_findnext_guide_proc) >= 0)
{
return_vals = gimp_run_procedure (l_findnext_guide_proc,
&nreturn_vals,
PARAM_IMAGE, image_id,
PARAM_INT32, guide_id,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return(return_vals[1].data.d_int32); /* return the next guide ID */
}
printf("XJT: Error: PDB call of %s failed\n", l_findnext_guide_proc);
}
else
{
printf("XJT: Warning: Procedure %s not found. %s\n",
l_findnext_guide_proc,
"(if image has guides they are not saved)");
}
return(-1);
} /* end p_gimp_image_findnext_guide */
/* ============================================================================
* p_gimp_image_get_guide_position
*
* ============================================================================
*/
gint32 p_gimp_image_get_guide_position(gint32 image_id, gint32 guide_id)
{
static char *l_get_guide_pos_proc = "gimp_image_get_guide_position";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_get_guide_pos_proc) >= 0)
{
return_vals = gimp_run_procedure (l_get_guide_pos_proc,
&nreturn_vals,
PARAM_IMAGE, image_id,
PARAM_INT32, guide_id,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return(return_vals[1].data.d_int32); /* return the guide position */
}
printf("XJT: Error: PDB call of %s failed\n", l_get_guide_pos_proc);
}
else
{
printf("XJT: Warning: Procedure %s not found. %s\n",
l_get_guide_pos_proc,
"(cannot save guides)");
}
return(-1);
} /* end p_gimp_image_get_guide_position */
/* ============================================================================
* p_gimp_image_get_guide_orientation
*
* ============================================================================
*/
gint p_gimp_image_get_guide_orientation(gint32 image_id, gint32 guide_id)
{
static char *l_get_guide_pos_orient = "gimp_image_get_guide_orientation";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_get_guide_pos_orient) >= 0)
{
return_vals = gimp_run_procedure (l_get_guide_pos_orient,
&nreturn_vals,
PARAM_IMAGE, image_id,
PARAM_INT32, guide_id,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return(return_vals[1].data.d_int32); /* return the guide orientation */
}
printf("XJT: Error: PDB call of %s failed\n", l_get_guide_pos_orient);
}
else
{
printf("XJT: Warning: Procedure %s not found. %s\n",
l_get_guide_pos_orient,
"(cannot save guides)");
}
return(-1);
} /* end p_gimp_image_get_guide_orientation */
/* ============================================================================
* p_gimp_image_get_resolution
*
* ============================================================================
*/
gint32 p_gimp_image_get_resolution (gint32 image_id, float *xresolution, float *yresolution)
{
static char *l_procname = "gimp_image_get_resolution";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_procname) >= 0)
{
return_vals = gimp_run_procedure (l_procname,
&nreturn_vals,
PARAM_IMAGE, image_id,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
*xresolution = return_vals[1].data.d_float;
*yresolution = return_vals[2].data.d_float;
return (0); /* OK */
}
printf("XJT: Error: PDB call of %s failed\n", l_procname);
}
else
{
printf("XJT: Warning: Procedure %s not found. %s\n",
l_procname,
"(cannot save image resolution)");
}
*xresolution = 72.0;
*yresolution = 72.0;
return(-1);
} /* end p_gimp_image_get_resolution */
/* ============================================================================
* p_gimp_image_set_resolution
*
* ============================================================================
*/
gint p_gimp_image_set_resolution (gint32 image_id, float xresolution, float yresolution)
{
static char *l_procname = "gimp_image_set_resolution";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_procname) >= 0)
{
return_vals = gimp_run_procedure (l_procname,
&nreturn_vals,
PARAM_IMAGE, image_id,
PARAM_FLOAT, xresolution,
PARAM_FLOAT, yresolution,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return (0); /* OK */
}
printf("XJT: Error: PDB call of %s failed\n", l_procname);
}
else
{
printf("XJT: Warning: Procedure %s not found. %s\n",
l_procname,
"(cannot save image resolution)");
}
return(-1);
} /* end p_gimp_image_set_resolution */
/* ============================================================================
* p_gimp_layer_get_tattoo
*
* ============================================================================
*/
gint32 p_gimp_layer_get_tattoo (gint32 layer_id)
{
static char *l_procname = "gimp_layer_get_tattoo";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_procname) >= 0)
{
return_vals = gimp_run_procedure (l_procname,
&nreturn_vals,
PARAM_LAYER, layer_id,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return(return_vals[1].data.d_int32); /* OK, return Tattoo Id */
}
printf("XJT: Error: PDB call of %s failed\n", l_procname);
}
else
{
printf("XJT: Warning: Procedure %s not found.\n", l_procname);
}
return(0);
} /* end p_gimp_layer_get_tattoo */
/* ============================================================================
* p_gimp_channel_get_tattoo
*
* ============================================================================
*/
gint32 p_gimp_channel_get_tattoo (gint32 channel_id)
{
static char *l_procname = "gimp_channel_get_tattoo";
GParam *return_vals;
int nreturn_vals;
if (p_procedure_available(l_procname) >= 0)
{
return_vals = gimp_run_procedure (l_procname,
&nreturn_vals,
PARAM_CHANNEL, channel_id,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
return(return_vals[1].data.d_int32); /* OK, return Tattoo Id */
}
printf("XJT: Error: PDB call of %s failed\n", l_procname);
}
else
{
printf("XJT: Warning: Procedure %s not found.\n", l_procname);
}
return(0);
} /* end p_gimp_channel_get_tattoo */

60
plug-ins/xjt/xpdb_calls.h Normal file
View file

@ -0,0 +1,60 @@
/* xpdb_calls.h
*
*/
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* 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.
*/
/* revision history:
* version 1.02.00; 1999/02/01 hof: PDB-calls to load/save resolution tattoos and parasites
* (needs GIMP 1.1.1)-- UNDER CONSTRUCTION ---
* version 1.01.00; 1998/11/22 hof: PDB-calls to load/save guides under GIMP 1.1
* version 1.00.00; 1998/10/26 hof: 1.st (pre) release
*/
#ifndef _XPDB_CALLS_H
#define _XPDB_CALLS_H
#include "libgimp/gimp.h"
gint p_procedure_available(char *proc_name);
gint p_get_gimp_selection_bounds (gint32 image_id, gint32 *x1, gint32 *y1, gint32 *x2, gint32 *y2);
gint p_gimp_selection_load (gint32 image_id, gint32 channel_id);
int p_layer_set_linked (gint32 layer_id, gint32 new_state);
gint p_layer_get_linked(gint32 layer_id);
gint32 p_gimp_image_floating_sel_attached_to(gint32 image_id);
gint p_gimp_floating_sel_attach(gint32 layer_id, gint32 drawable_id);
gint p_gimp_floating_sel_rigor(gint32 layer_id, gint32 undo);
gint p_gimp_floating_sel_relax(gint32 layer_id, gint32 undo);
gint32 p_gimp_image_add_guide(gint32 image_id, gint32 position, gint32 orientation);
gint32 p_gimp_image_findnext_guide(gint32 image_id, gint32 guide_id);
gint32 p_gimp_image_get_guide_position(gint32 image_id, gint32 guide_id);
gint32 p_gimp_image_get_guide_orientation(gint32 image_id, gint32 guide_id);
void p_gimp_add_busy_cursors();
void p_gimp_remove_busy_cursors(void *);
gint p_gimp_image_get_resolution(gint32 image_id, float *xresolution, float *yresolution);
gint p_gimp_image_set_resolution(gint32 image_id, float xresolution, float yresolution);
gint32 p_gimp_layer_get_tattoo(gint32 layer_id);
gint32 p_gimp_channel_get_tattoo(gint32 channel_id);
Parasite *gimp_image_find_parasite(gint32 image_id, const char *name);
#endif