1
1
mirror of https://gitlab.gnome.org/GNOME/gimp.git synced 2025-10-06 01:12:40 +02:00

Compare commits

...

137 Commits

Author SHA1 Message Date
People doing a 16 bpc version of gimp
bd0007e9f7 Fixing some float & float16 cases for these.
-calvin@rhythm.com
1998-11-24 02:07:23 +00:00
People doing a 16 bpc version of gimp
dc992fb7a1 Lets make sure we create the right plugin makefiles.
-calvin@rhythm.com
1998-11-19 19:23:25 +00:00
People doing a 16 bpc version of gimp
39c6056efe And added an endian test --needed by the float16 type
-calvin@rhythm.com
1998-11-19 18:22:08 +00:00
People doing a 16 bpc version of gimp
c149effc68 Various bug fixes for float16 type.
Fixed a display bug for float type.
Added invert, posterize, color_balance float16 code.
compiler fixes for transform_core.c and displaylut.c
-calvin@rhythm.com
1998-11-19 18:20:02 +00:00
People doing a 16 bpc version of gimp
8107aeeb25 Couldnt find a header.
-calvin@rhythm.com
1998-11-07 03:14:48 +00:00
People doing a 16 bpc version of gimp
0166bceaf7 Fixed endian-ness problems for the float and float16 types.
-calvin@rhythm.com
1998-11-07 01:54:15 +00:00
People doing a 16 bpc version of gimp
25899e5bd3 Changed the 16bit float macros to pass in a temp variable.
-calvin@rhythm.com
1998-11-07 00:59:03 +00:00
People doing a 16 bpc version of gimp
6117968c72 - fix a gint <-> gfloat typo in cubic interpolation alpha handling
- fix a gint <-> gfloat typo in cubic interpolation alpha handling

ray lehtiniemi <rayl@netrover.com>
1998-11-06 17:22:51 +00:00
People doing a 16 bpc version of gimp
64b1660841 re-implement transform_core_do() to minimize the cut&paste required for
re-implement transform_core_do() to minimize the cut&paste required for
new data precisions.  this version also scales better for cubic
interpolation.  a 2K image is ~5% slower than the original code for
non-interpolated, but takes only about half as long for for cubic.


ray lehtiniemi <rayl@netrover.com>
1998-11-06 16:03:23 +00:00
People doing a 16 bpc version of gimp
147b629943 - fix init problem in clone options dialog - make edit->fill use
- fix init problem in clone options dialog
- make edit->fill use background, not black

ray lehtiniemi <rayl@netrover.com>
1998-10-15 23:09:54 +00:00
People doing a 16 bpc version of gimp
f45f1089a6 A fix for an uninitialized variable in float16 code, and
an updated gbr load/save to work with float16.

Sorry for too many separate commits.

-calvin@rhythm.com
1998-10-15 19:23:33 +00:00
People doing a 16 bpc version of gimp
b30d794070 Added some constants for 16bit float image types.
-calvin@rhythm.com
1998-10-15 19:15:58 +00:00
People doing a 16 bpc version of gimp
67d7f74e56 Fix a little bug where FLOAT16 was mistaken to be FLOAT.
-calvin@rhythm.com
1998-10-15 00:29:51 +00:00
People doing a 16 bpc version of gimp
32c38e2778 Heres the beginnings of the display lut mechanism.
-calvin@rhythm.com
1998-10-15 00:05:30 +00:00
People doing a 16 bpc version of gimp
afe4a2a3b2 Changes to work with the display lut mechanism.
-calvin@rhythm.com
1998-10-15 00:04:04 +00:00
People doing a 16 bpc version of gimp
388e2ef598 - misc float16 bugfixes
- misc float16 bugfixes

ray lehtiniemi <rayl@netrover.com>
1998-10-14 19:13:39 +00:00
People doing a 16 bpc version of gimp
65e299e921 - fix undo bug in blend tool - add a simple busy-wait cursor
- fix undo bug in blend tool
- add a simple busy-wait cursor

ray lehtiniemi <rayl@netrover.com>
1998-10-13 18:05:36 +00:00
People doing a 16 bpc version of gimp
535b595601 Taking out bad code for RGBA 8 and 16bit images, left from yesterday.
-calvin@rhythm.com
1998-10-09 22:16:56 +00:00
People doing a 16 bpc version of gimp
598d5878e2 More bug fixes for 16bit float. RGBA image painting was wrong.
-calvin@rhythm.com
1998-10-09 01:52:23 +00:00
People doing a 16 bpc version of gimp
04a918efbd - off by one in layer_pick_correlate()
- off by one in layer_pick_correlate()

ray lehtiniemi <rayl@netrover.com>
1998-10-08 23:40:59 +00:00
People doing a 16 bpc version of gimp
e0535e24e7 Fixing a move tool and selection bug for 16bit floats.
-calvin@rhythm.com
1998-10-08 21:44:30 +00:00
People doing a 16 bpc version of gimp
853508dfbc - add missing break statements - precision wrapper layer_pick_correlate()
- add missing break statements
- precision wrapper layer_pick_correlate()
- use fabs not abs

ray lehtiniemi <rayl@netrover.com>
1998-10-08 21:25:14 +00:00
People doing a 16 bpc version of gimp
435a9d25ed More changes for the 16bit float format.
-calvin@rhythm.com
1998-10-08 00:17:08 +00:00
People doing a 16 bpc version of gimp
eacf8f4826 - fix a bunch of silly blend bugs - bezier select works for float images -
- fix a bunch of silly blend bugs
- bezier select works for float images
- fix unref bug in transform core

ray lehtiniemi <rayl@netrover.com>
1998-10-07 20:41:58 +00:00
People doing a 16 bpc version of gimp
e2fe3d2447 Added files for the 16bit float format.
-calvin@rhythm.com
1998-10-07 19:35:45 +00:00
People doing a 16 bpc version of gimp
9039979015 Changes for a 16bit float type.
-calvin@rhythm.com
1998-10-07 19:33:20 +00:00
People doing a 16 bpc version of gimp
23fb662336 - add a new alignment type to clone tool options, 'registered'. it copies
- add a new alignment type to clone tool options, 'registered'.  it copies
  pixels from src image to the same coords in dest image, which is useful
  for quickly fixing dust or scratches using the previous/next frame

ray lehtiniemi <rayl@netrover.com>
1998-10-07 00:40:24 +00:00
People doing a 16 bpc version of gimp
be947159ca Fix comment - 16 bit works. 1998-10-03 19:27:37 +00:00
People doing a 16 bpc version of gimp
5a4e95f312 - 16 bit backend
- 16 bit backend

ray lehtiniemi <rayl@netrover.com>
1998-10-02 19:53:44 +00:00
People doing a 16 bpc version of gimp
23322b6732 Updates to make work with 16 bit data types (not float, yet) -wrb. 1998-10-02 02:00:07 +00:00
People doing a 16 bpc version of gimp
00c818b183 Added coord order check to channel_bounds(), in case of empty mask and
the coords never get set -wrb
1998-10-02 01:51:02 +00:00
People doing a 16 bpc version of gimp
70d229b555 Filling in some code to do float channels.
--calvin@rhythm.com
1998-10-01 21:01:48 +00:00
People doing a 16 bpc version of gimp
1181669b07 - color selector now uses the current default precision
- color selector now uses the current default precision

ray lehtiniemi <rayl@netrover.com>
1998-10-01 16:48:48 +00:00
People doing a 16 bpc version of gimp
04a839c635 - memory usage and redisplay performance enhancements
- memory usage and redisplay performance enhancements

ray lehtiniemi <rayl@netrover.com>
1998-09-30 23:47:33 +00:00
People doing a 16 bpc version of gimp
35bab937aa Fixes for painting speed for 16bit channels.
--calvin@rhythm.com
1998-09-30 20:09:48 +00:00
People doing a 16 bpc version of gimp
45de373f2f - extensive performance tweaking
- extensive performance tweaking

ray lehtiniemi <rayl@netrover.com>
1998-09-27 01:17:54 +00:00
People doing a 16 bpc version of gimp
e08df73aff - implement wrapped pixelareas - implement pattern fills using a pattern
- implement wrapped pixelareas
- implement pattern fills using a pattern canvas in a wrapped pixelarea
  and calling copy_area

ray lehtiniemi <rayl@netrover.com>
1998-09-26 17:48:44 +00:00
People doing a 16 bpc version of gimp
135015b148 - prepare pixelarea to do wrapped areas
- prepare pixelarea to do wrapped areas

- clean up places that (mis)used pixelarea solely to pass
  bounding box info (primarily gimage_apply_painthit(),
  find_mask_boundary() and a few area funcs)

ray lehtiniemi <rayl@netrover.com>
1998-09-25 01:35:26 +00:00
People doing a 16 bpc version of gimp
660b758e86 Fixes for render_preview for displaying 16bit channel images in
the layer/channel dialog. We can do layers now for 16bit images...
-calvin@rhythm.com
1998-09-24 01:15:19 +00:00
People doing a 16 bpc version of gimp
ecde4eb8b4 - fix an oversight exposed by that last commit
- fix an oversight exposed by that last commit

rayl lehtiniemi <rayl@netrover.com>
1998-09-24 00:34:33 +00:00
People doing a 16 bpc version of gimp
9c5ba76a37 - gdisplay_flush() performance tweak
- gdisplay_flush() performance tweak

ray lehtiniemi <rayl@netrover.com>
1998-09-23 18:22:03 +00:00
People doing a 16 bpc version of gimp
823dd0f78d Changes for layers and channels to make 16bit channels possible.
-calvin@rhythm.com
1998-09-23 00:33:48 +00:00
People doing a 16 bpc version of gimp
3ac135b0ff - oops, forgot to enable 8bit/floating point seed fill
- oops, forgot to enable 8bit/floating point seed fill

ray lehtiniemi <rayl@netrover.com>
1998-09-22 20:47:06 +00:00
People doing a 16 bpc version of gimp
d6039553a7 - off-by-one in image undo and blend tool with active selection - cosmetic
- off-by-one in image undo and blend tool with active selection
- cosmetic reformatting

ray lehtiniemi <rayl@netrover.com>
1998-09-22 18:27:07 +00:00
People doing a 16 bpc version of gimp
bd6ac5a408 so it turns out that implementing a seed fill algorithm while making no
so it turns out that implementing a seed fill algorithm while making
no assumptions about memory layout or data precision is not exactly
trivial.  this is a first cut, with magic wand and bucket applications.

ray lehtiniemi <rayl@netrover.com>
1998-09-18 21:40:54 +00:00
People doing a 16 bpc version of gimp
f816ac395d A couple of bug fixes to channel_bounds for 16bit channel images.
So that inverting selections works for them.
--calvin@rhythm.com
1998-09-16 16:46:13 +00:00
People doing a 16 bpc version of gimp
6707c45523 - complete set of copy routines - cosmetic change to eye dropper
- complete set of copy routines
 - cosmetic change to eye dropper

ray lehtiniemi <rayl@netrover.com>
1998-09-14 20:22:32 +00:00
People doing a 16 bpc version of gimp
ce7efc0dcb 16 bit bezier select backend
16 bit bezier select backend

ray lehtiniemi <rayl@netrover.com>
1998-09-12 00:52:53 +00:00
People doing a 16 bpc version of gimp
24b0061b41 16 bit free select backend
16 bit free select backend

ray lehtiniemi <rayl@netrover.com>
1998-09-12 00:03:20 +00:00
People doing a 16 bpc version of gimp
b51525fd16 Made channel.c and boundary.c work for 16bit channels. Also temporarily removed
some macros in paint_funcs till debugging is over.
-calvin@rhythm.com
1998-09-11 22:55:42 +00:00
People doing a 16 bpc version of gimp
627ea7587e Removing debugging calls.
-calvin@rhythm.com
1998-09-10 20:12:02 +00:00
People doing a 16 bpc version of gimp
328435c35d Mostly bug fixes for the paint_funcs
scale_area, gaussian_blur_area and thin_area.

--calvin@rhythm.com
1998-09-10 19:38:23 +00:00
People doing a 16 bpc version of gimp
54b4d44c7b fixes for by_color_select
ray lehtiniemi <rayl@netrover.com>
1998-09-09 03:06:56 +00:00
People doing a 16 bpc version of gimp
795996ea82 Made some fixes to the 16bit convolve code. Fixed some compile problems
for the sgi compiler.

-calvin@rhythm.com
1998-09-08 17:34:55 +00:00
People doing a 16 bpc version of gimp
d4c812187b - channel_value() returns gfloat - channel_add_segment() et al. accept
- channel_value() returns gfloat
- channel_add_segment() et al. accept gfloat
- add invert_area()
- finish color picker

ray lehtiniemi <rayl@netrover.com>
1998-09-03 01:53:13 +00:00
People doing a 16 bpc version of gimp
440aa0bcb2 transform core updates.
transform core updates.

ray lehtiniemi <rayl@netrover.com>
1998-08-31 02:37:26 +00:00
People doing a 16 bpc version of gimp
46e3761bab - finish RGB<->GRAY conversions in convert.c - fix some (no where near
- finish RGB<->GRAY conversions in convert.c
- fix some (no where near all) -Wall -ansi -pedantic warnings
- drawable_type () is now gone
- replace valid_combinations array in gimage.c with a routine
  that examines and validates src/dest tags
- use drawable_width (), drawable_height () instead of directly
  accessing drawable member variables
- eliminate drawable member vars width, height, tag, delegate to
  tiles object

ray lehtiniemi <rayl@netrover.com>
1998-08-25 03:43:35 +00:00
People doing a 16 bpc version of gimp
c94046dc58 once more, from the right directory this time :-(
once more, from the right directory this time :-(

- add canvas_init machinery (tile_manager_validate equivalent)
- fix bugs in compositing code
- layers/channels dialog, previews
- all color handling should be fairly precision independent now
- replaced gimage_type and gimage_base_type with Tags
- remove concept of flat vs. layered gimages

ray lehtiniemi <rayl@netrover.com>
1998-08-20 00:55:39 +00:00
People doing a 16 bpc version of gimp
f31986d6b4 clean up some 255 scale factors for opacities first crack at previews
clean up some 255 scale factors for opacities
first crack at previews (work in progress)
- remove subsample_area and layer_preview_scale, replace with scale_area
- reimplement render_preview using combine_areas

ray lehtiniemi <rayl@netrover.com>
1998-08-17 01:18:41 +00:00
People doing a 16 bpc version of gimp
c80d01311d - remove a few unused funcs - mark some FIXMEs - update TODO
- remove a few unused funcs
- mark some FIXMEs
- update TODO
1998-08-13 00:20:58 +00:00
People doing a 16 bpc version of gimp
5f67f8d536 - convert transform_core based tools - continue converting selection tools
- convert transform_core based tools
- continue converting selection tools
- layer_new cleanups
- some FIXME cleanups
- misc varargs fixes in pixelarea

ray lehtiniemi <rayl@netrover.com>
1998-08-09 23:11:22 +00:00
People doing a 16 bpc version of gimp
7d162722a5 - add x,y values to Canvas for the moment - fix pixelarea bug that was
- add x,y values to Canvas for the moment
- fix pixelarea bug that was killing rect_select
- add a prefs option for default precision
- continue wrapping guchar pointers with PixelRows

ray lehtiniemi <rayl@netrover.com>
1998-08-07 22:26:36 +00:00
People doing a 16 bpc version of gimp
cd5ac220e3 ok, finished the merge from gimp-1-0. time to make it all work again :-)
ok, finished the merge from gimp-1-0.  time to make it all work again :-)

ray lehtiniemi <rayl@netrover.com>
1998-08-03 02:05:48 +00:00
People doing a 16 bpc version of gimp
dbca959628 Changed C++ style comments to ANSCI C 1998-07-31 17:07:40 +00:00
People doing a 16 bpc version of gimp
6ee0d7dc9c Added prototypes 1998-07-31 17:06:46 +00:00
People doing a 16 bpc version of gimp
faf95c3458 missed these..
ray lehtiniemi <rayl@netrover.com>
1998-07-31 00:18:48 +00:00
People doing a 16 bpc version of gimp
74f29ebec8 merge everything from 0.99.16 -> 1.0.0 into HOLLYWOOD. also, reformat code
merge everything from 0.99.16 -> 1.0.0 into HOLLYWOOD.  also, reformat
code to minimize the diff between GIMP-1.0 head revision and HOLLYWOOD
head revision.  this is to try and get a better idea of exactly what
we've changed.

this passes a basic sanity, but a patch this size has probably broken
something.

ray lehtiniemi <rayl@netrover.com>
1998-07-31 00:10:50 +00:00
People doing a 16 bpc version of gimp
c981275642 Add shared memory support from command line startup. 1998-07-15 22:51:51 +00:00
People doing a 16 bpc version of gimp
615e1240eb Add shared memory support from command line 1998-07-15 22:51:00 +00:00
People doing a 16 bpc version of gimp
82331210ca Changed *wrong* comments and added shmem offset 1998-07-15 19:31:53 +00:00
People doing a 16 bpc version of gimp
61b1b04294 Added defines also located in tag.c (should be removed from tag.c) 1998-07-15 19:28:22 +00:00
People doing a 16 bpc version of gimp
a2b11da38c Added offset capability to pointer. 1998-07-15 19:26:30 +00:00
People doing a 16 bpc version of gimp
094009c438 Added comment 1998-07-15 19:25:52 +00:00
People doing a 16 bpc version of gimp
6e20971b06 added demo of a shared memory canvas. two or more gimps can simultaneously
added demo of a shared memory canvas.  two or more gimps can simultaneously
manipulate an image in a piece of shared memory.

- added shmbuf.[ch]
- readded script-fu plugins
- added simple shmbuf script-fu routines
- modified routines that create Canvas objects appropriately
- updated sgml docs

ray lehtiniemi <rayl@netrover.com>
1998-07-10 14:05:21 +00:00
People doing a 16 bpc version of gimp
8fe6ecc813 More stuff for selections for 16bit channels.
-calvin (cwilliamson@berlin.snafu.de)
1998-07-09 09:24:54 +00:00
People doing a 16 bpc version of gimp
296ecbf9a1 Changes to get selections working for 16bit channels. Made
all the gimage/layer/channel stuff use tags,canvas, and pixelareas.
--calvin (cwilliamson@berlin.snafu.de)
1998-07-08 16:40:43 +00:00
People doing a 16 bpc version of gimp
23bccb7c5a some Canvas rework -- created readonly and readwrite ref functions --
some Canvas rework
  -- created readonly and readwrite ref functions
  -- added canvas_init hooks for gimage_validate()

pixelarea work
  -- make pixelarea_process() handle sparse images (autoalloc == OFF)
  -- exported pixelarea_ref/unref

misc stuff
  -- update code to use new canvas ref functions
  -- disabled gimage_validate() until we 16bit the gimage code
  -- swap_area() didn;t swap all pixels at some precisions
  -- added more checks in image_render() for unsupported format/precision pairs
  -- added warnings when calling deprecated functions
  -- remove unused canvas_clone()
  -- eraser tool uses ERASE_MODE, duh

ray lehtiniemi <rayl@netrover.com>
1998-07-04 03:00:13 +00:00
People doing a 16 bpc version of gimp
3211017dcd fix a few cores
ray lehtiniemi <rayl@netrover.com>
1998-06-27 01:50:14 +00:00
People doing a 16 bpc version of gimp
25c3aa8752 Removing paint_funcs_row --its not needed now since we set up
all our function pointers in paint_funcs_area.
-calvin (cwilliamson@berlin.snafu.de)
1998-06-24 17:42:25 +00:00
People doing a 16 bpc version of gimp
d918eb5302 added a linuxdoc document describing project progress to date
ray lehtiniemi <rayl@netrover.com>
1998-06-22 23:46:21 +00:00
People doing a 16 bpc version of gimp
a8421651db Taking out the debugging stuff I checked in yesterday.
-calvin (cwilliamson@berlin.snafu.de)
1998-06-18 11:21:32 +00:00
People doing a 16 bpc version of gimp
a2e46f06c0 Just trying to remove lookup_tables.[ch]. I dont know what
all this other files are showing up as modified. I didnt
modify them....
calvin (cwilliamson@berlin.snafu.de)
1998-06-17 15:34:56 +00:00
People doing a 16 bpc version of gimp
a8d03cea85 Cleaned up the image_render code for 16bit/float situations.
Removed the lookup tables for 16bit to 8bit until we understand
a little better what and where to put the display LUTs. Removed
lookup_tables.[ch] from Makefile.am.

calvin (cwilliamson@berlin.snafu.de)
1998-06-17 15:26:35 +00:00
People doing a 16 bpc version of gimp
339ca8061d Convert C++ style comments to "C" 1998-06-16 01:31:36 +00:00
People doing a 16 bpc version of gimp
35b8931b6d Made the initial changes for image adjustments tools for 16bit
and float channel data. The histogram and all the
tools that use it (equalize, threshold, levels)
arent finished but all the others are.

calvin (cwilliamson@berlin.snafu.de)
1998-06-15 17:24:11 +00:00
People doing a 16 bpc version of gimp
f0437fcd47 - completed removal of Paint objects
- completed removal of Paint objects

ray lehtiniemi <rayl@netrover.com>
1998-05-28 03:07:25 +00:00
People doing a 16 bpc version of gimp
30c9e13e28 - temporarily remove most plugins from makefile to speed build process
- temporarily remove most plugins from makefile to speed build process
  (only sgi, tiff, pat, and gbr are built for the moment)

- add a configure option --enable-precision={u8,u16,float} to set the
  default precision for image data. instead of using -DU16_SUPPORT and
  #ifdefs, use PRECISION_CONFIG whereever a Precision is required.

- use gfloat instead of Paint to pass opacities and blend factors

- remove a bit of dead code in paint_funcs_area

- fix a bug in clone tool when cloning to the same gimage


ray lehtiniemi <rayl@netrover.com>
1998-05-19 00:14:25 +00:00
People doing a 16 bpc version of gimp
774adf1c41 - minor undo fix - rename misleading functions to avoid repeat of above
- minor undo fix
- rename misleading functions to avoid repeat of above problem

- most things use tilebuf by default now

- add some data members to cache constant values instead of
  always recomputing them

- prototype of "fast blend tool" which does the blend in several steps
  instead of all in one go.  leads to an order of magnitude speed
  increase for 1000x1000 pixel 16 bit images.

ray lehtiniemi <rayl@netrover.com>
1998-05-08 02:38:26 +00:00
People doing a 16 bpc version of gimp
61845ff53d Whoops. Left in a debugging call.
--calvin (cwilliamson@berlin.snafu.de)
1998-05-05 12:50:50 +00:00
People doing a 16 bpc version of gimp
34c0257077 Fixed a potential overflow bug for reading 16bit [0-65535] type
tiff images.
--calvin (cwilliamson@berlin.snafu.de)
1998-05-05 10:37:54 +00:00
People doing a 16 bpc version of gimp
9dc2008545 Small bug fix for HOLLYWOODS sgi plugin for converting shorts from
sgilib to unsigned shorts which everyone using 16bit channel
sgi files seems to use.
--calvin (cwilliamson@berlin.snafu.de)
1998-05-05 10:35:19 +00:00
People doing a 16 bpc version of gimp
8826337e11 Changes for the pattern plugin for 16bit channels.
--calvin (cwilliamson@berlin.snafu.de)
1998-05-05 10:27:19 +00:00
People doing a 16 bpc version of gimp
fb3948b7f8 Bug fixes for the gbr and 16bit channels.
--calvin (cwilliamson@berlin.snafu.de)
1998-05-05 10:25:59 +00:00
People doing a 16 bpc version of gimp
d3a31408f0 Patterns converted to 16bit channels. Fixed some bugs in 16bit channels
brushes code. Made pattern clone work. Fixed the multiply mode for
16bit painting.
--calvin (cwilliamson@berlin.snafu.de)
1998-05-05 10:07:30 +00:00
People doing a 16 bpc version of gimp
b7b7e47822 - clean up some junk
- undo kind of works now

ray lehtiniemi <rayl@netrover.com>
1998-04-22 03:38:45 +00:00
People doing a 16 bpc version of gimp
1a2c2ad9a1 Changes to convolve to make the blur/sharpen work in 16bit channels.
Changes to gimage_replace to work for this case.
Added a break in clone.c that was left out before.
--calvin (cwilliamson@berlin.snafu.de)
1998-04-16 15:42:54 +00:00
People doing a 16 bpc version of gimp
27561731bd - airbrush, pencil, and eraser tools converted - minor bug fix to
- airbrush, pencil, and eraser tools converted
- minor bug fix to swap_areas()

ray lehtiniemi <rayl@netrover.com>
1998-04-10 01:59:04 +00:00
People doing a 16 bpc version of gimp
89054c902e remove some routines from canvas/tilebuf/flatbuf and move the functionality
into a smarter copy_area/copy_row

initial blend tool functionality
- no asupsample
- no shapeburst
- other than that, seems to work fine

ray lehtiniemi <rayl@netrover.com>
1998-04-01 04:20:11 +00:00
People doing a 16 bpc version of gimp
fe14ba14d7 Made the unpremultiplying a little better for 16bit tiffs.
-calvin  (cwilliamson@berlin.snafu.de)
1998-03-26 15:44:46 +00:00
People doing a 16 bpc version of gimp
72f1923548 Added an include and a comment about minpixel and maxpixel.
-calvin (cwilliamson@berlin.snafu.de)
1998-03-26 15:41:44 +00:00
People doing a 16 bpc version of gimp
5a3ac8077f Some changes for 16bit cloning, and some small bug fixes.
-calvin (cwilliamson@berlin.snafu.de)
1998-03-26 15:38:08 +00:00
People doing a 16 bpc version of gimp
2b3f5ed6f7 sgi can save 16bit too.
-calvin (cwilliamson@berlin.snafu.de)
1998-03-20 22:30:46 +00:00
People doing a 16 bpc version of gimp
09df52fdd4 tiff can save 16bit/channel now too.
-calvin (cwilliamson@berlin.snafu.de)
1998-03-20 22:23:10 +00:00
People doing a 16 bpc version of gimp
a463c8e74e gbrs can save out 16bit/float now
-calvin(cwilliamson@berlin.snafu.de)
1998-03-20 22:21:23 +00:00
People doing a 16 bpc version of gimp
fa63c8f828 Added some images/drawable types for plugins to recognize 16bit/float
images.
-calvin(cwilliamson@berlin.snafu.de)
1998-03-20 22:20:05 +00:00
People doing a 16 bpc version of gimp
eb9521999c And some more stuff in the ISSUES_DEFINES as well.
-calvin
1998-03-20 22:17:30 +00:00
People doing a 16 bpc version of gimp
13318e8265 Some tag related work to convert types-to-tags and vice versa
before passing to libgimp. This is all by way of getting
tiff, sgi and gbr to read 16bit and float files.
-calvin (cwilliamson@berlin.snafu.de)
1998-03-20 22:16:23 +00:00
People doing a 16 bpc version of gimp
edfcccfde8 initial pass at making the clone tool tags-aware
ray lehtiniemi <rayl@netrover.com>
1998-03-19 03:31:34 +00:00
People doing a 16 bpc version of gimp
92c143dc11 just a commit of changes in progress, no real need to update until i get
just a commit of changes in progress, no real need to update until
i get the clone tool working...

ray lehtiniemi <rayl@netrover.com>


API changes
-----------
- fundamental changes to canvas allocation and initialization and
  canvas_ref() semantics.  this is still in flux till i finish clone tool
- introduce "portion" concept into canvas.h
- replace "Tiling" concept with "Storage" concept

internal changes
----------------
 - remove tilemanager/tempbuf glue from canvas.h
 - start to rationalize gimage_apply_painthit()
 - add trace.h and trace.c
 - copy_area() rowstride fix
 - add a "hard" option to paintbrush
 - unnest headers
1998-03-17 00:39:49 +00:00
People doing a 16 bpc version of gimp
800ac4bb22 Various changes to paint with 16bit brushes. Some changes to routines
for tag versions of gimage_new drawable_configure layer_new.
Added some switches to turn off the 1 pixel subsampling border of
brushes to debug paint_funcs for 16bit.
-calvin (cwilliamson@berlin.snafu.de)
1998-03-16 19:58:06 +00:00
People doing a 16 bpc version of gimp
c4869e7bd4 Changes to gbr.c to deal with tags for 16bit brushes.
-calvin(cwilliamson@berlin.snafu.de)
1998-03-12 16:33:17 +00:00
People doing a 16 bpc version of gimp
da03f509ed Changes for 16bit/float brushes.
Changes to pass canvas data to libgimp(and plugins)
Bugfix for portion_width in pixelarea.c
-calvin (cwilliamson@berlin.snafu.de)
1998-03-12 16:31:16 +00:00
People doing a 16 bpc version of gimp
d36303a0d7 Added include of canvas.h 1998-03-11 16:17:07 +00:00
People doing a 16 bpc version of gimp
0401424d8e Fixing a tag bug in combine_areas.
-calvin (cwilliamson@berlin.snafu.de)
1998-03-05 11:52:40 +00:00
People doing a 16 bpc version of gimp
c8a089040c sync to trunk misc bug fixes
sync to trunk
misc bug fixes

Ray Lehtiniemi <rayl@netrover.com>
1998-03-04 05:36:43 +00:00
People doing a 16 bpc version of gimp
8cebd1de86 sync to trunk
Ray Lehtiniemi <rayl@netrover.com>
1998-03-04 05:35:12 +00:00
People doing a 16 bpc version of gimp
741ec4924a Added canvas field to Drawable and some prototypes to
palette.h.
--calvin (cwilliamson@berlin.snafu.de)
1998-03-02 11:42:34 +00:00
People doing a 16 bpc version of gimp
d581adcdbb Changed the ISSUES_DEFINES file too.
-calvin (cwilliamson@berlin.snafu.de)
1998-03-02 00:47:32 +00:00
People doing a 16 bpc version of gimp
53613b3ce3 More changes for getting rays canvas going.
-calvin (cwilliamson@berlin.snafu.de)
1998-03-02 00:22:35 +00:00
People doing a 16 bpc version of gimp
186dca947a Changes to get rays canvas painting/display up and working.
--calvin (cwilliamson@berlin.snafu.de)
1998-03-02 00:14:49 +00:00
People doing a 16 bpc version of gimp
4145c52a08 woowoo! paintbrush now draws in 8 bit mode using new architecture. "that's
woowoo!  paintbrush now draws in 8 bit mode using new architecture.  "that's
one small step for 8 bit painting, one giant leap for arbitrary precision
drawables" :-)

also fixed a lot of silly off-by-ones and memory leaks, and added some "print
yourself" routines for some objects.


Ray Lehtiniemi <rayl@netrover.com>
1998-03-01 18:18:08 +00:00
People doing a 16 bpc version of gimp
ec6a231ca3 Changed image_render to use Rays Canvas stuff.
Added routines for copying a data from a PixelArea to
a PixelRow.

Added ISSUES_DEFINES file for comments.
-calvin (cwilliamson@berlin.snafu.de)
1998-02-26 22:50:21 +00:00
People doing a 16 bpc version of gimp
92d21ad728 - tons of error checking added - most of gimage_apply_painthit() is in
- tons of error checking added
- most of gimage_apply_painthit() is in place

  Ray Lehtiniemi <rayl@netrover.com>
1998-02-26 04:05:34 +00:00
People doing a 16 bpc version of gimp
a03ebd5b40 paintbrush is now using the PaintCore16 code.
Ray Lehtiniemi <rayl@netrover.com>
1998-02-25 04:18:35 +00:00
People doing a 16 bpc version of gimp
c4a0a913b4 - restructure paint_core_16.c
- add painthit stubs to gimage

- remove canvas_realloc()

- add canvas_init() concept
- add canvas_ref() return code
- propagate changes to flatbuf and tilebuf

- pixelarea now uses canvas_init()

  Ray Lehtiniemi <rayl@netrover.com>
1998-02-23 01:05:03 +00:00
People doing a 16 bpc version of gimp
17286692ab OOps, never mind -wrb. 1998-02-22 17:55:48 +00:00
People doing a 16 bpc version of gimp
bcf64a2ff9 Wrb- added link.[ch] to Makefile 1998-02-21 22:23:12 +00:00
People doing a 16 bpc version of gimp
80d92443af Wrb- cast void* pointer to (guchar*) for pointer arithmetic calculations. 1998-02-21 22:20:11 +00:00
People doing a 16 bpc version of gimp
9e9c6ddd3f Added function protos 1998-02-21 22:19:22 +00:00
People doing a 16 bpc version of gimp
ed4deb978e Wrb - Convert C++ style comments to C, fix function pointer useage. 1998-02-21 22:18:36 +00:00
People doing a 16 bpc version of gimp
1c01525ab5 Convert C++ style comments to C style -wrb. 1998-02-21 22:16:50 +00:00
People doing a 16 bpc version of gimp
1cb3b3a6fd refcount changes from trunk
fix link errors
merge calvin's changes

 - rayl@netrover.com
1998-02-21 21:27:35 +00:00
People doing a 16 bpc version of gimp
43eefacc5f changes from trunk 1998-02-21 21:15:28 +00:00
People doing a 16 bpc version of gimp
b87426f2dd Fixing some link errors for these.
-calvin (cwilliamson@berlin.snafu.de)
1998-02-21 17:35:10 +00:00
People doing a 16 bpc version of gimp
b7b0acd62f Added files for HOLLYWOOD paint_funcs.
--calvin (cwilliamson@berlin.snafu.de)
1998-02-20 17:05:57 +00:00
People doing a 16 bpc version of gimp
8b8860f129 HOLLYWOOD branch changes to:
paint_funcs to allow for 16bit/float data.

 image_render.c to display 16bit/float data.

  --calvin (cwilliamson@berlin.snafu.de)
1998-02-20 16:55:00 +00:00
People doing a 16 bpc version of gimp
7267751ebc - initial code for 16 bit/floating point image support
- bring across GimpDrawable code from trunk
 - stuff compiles and links but doesn't do anything yet

    rayl@netrover.com
1998-02-12 03:24:27 +00:00
1102 changed files with 141758 additions and 71951 deletions

View File

@@ -9,3 +9,5 @@ gimprc
config.status
libtool
aclocal.m4
gimprc_user
gimptool

View File

@@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -305,7 +305,8 @@ the "copyright" line and a pointer to where the full notice is found.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.

2490
ChangeLog

File diff suppressed because it is too large Load Diff

100
INSTALL
View File

@@ -1,15 +1,18 @@
There are three basic steps to building and installing the
GIMP on unix:
1. You need to have installed GTK version 0.99.1 or better
1. You need to have installed GTK version 1.0.1 or better
2. You may want to install other third party libraries that
are needed for some of the available plugins: TIFF, PNG,
JPEG, MPEG, etc.
3. Configure the GIMP by running the `configure' script.
4. Build the GIMP by running `make'.
5. Install the GIMP by running `make install'.
6. Install the gimp-data package. Be sure to install this, or you
won't have the GIMP's datafiles installed.
6. Optionally install the separate gimp-data-extras package.
Please make sure you don't have any old GTK, jpeg, etc. libraries lying
around on your system, otherwise configure will fail to find the new
ones.
Generic instructions for configuring and compiling auto-configured
packages are included below. Here is an illustration of commands that
@@ -51,27 +54,11 @@ recognizes. These are:
the gimp uses to search for its configuration files from ~/.gimp (the
directory .gimp in the users home directory) to DIR.
5. --with-libtiff=DIR. This option specifies the location of the
tiff library and header files. For instance, the libtiff library
may reside in "/usr/local". This may be specified by
--with-libtiff="/usr/local". (Note: The compilation process
should automatically find the tiff library if it resides in
"/usr/local").
6. --with-libjpeg=DIR. This option specifies the location of the
jpeg library and header files. For instance, the libjpeg library
may reside in "/usr/local". This may be specified by
--with-libjpeg="/usr/local". (Note: The compilation process
should automatically find the tiff library if it resides in
"/usr/local").
The `make' command builds several things:
- The libraries `gtk+/glib/libglib.la', `gtk+/gdk/libgdk.la',
`gtk+/gtk/libgtk.la', `libgimp/libgimp.la', `libgimp/libgimpi.la' and
- The libraries `libgimp/libgimp.la', `libgimp/libgimpi.la' and
`libgimp/libgimpui.la'. The `.la' suffix is used by libtool, the
program used to ease the compilation of shared libraries on
different platforms.
- The test programs `gtk+/glib/testglib' and `gtk+/gtk/testgtk'.
- The plug-in programs in the `plug-ins' subdirectory.
- The main GIMP program in `app/gimp'.
@@ -81,6 +68,79 @@ the libgimp library, the plug-ins, and the GIMP executable. After
running `make install' and assuming the build process was successful
you should be able to run `gimp'.
When ./configure fails
======================
'configure' tries to compile and run a short GTK program. There are
several reasons why this might fail:
* The 'gtk-config' script installed with GTK could not be found.
(This script is used to get information about where GTK is
installed.)
Fix: Either make sure that this program is in your path, or set
the environment variable GTK_CONFIG to the full pathname to
this program before running configure.
* The GTK libraries were not found at run time. The details
of how to fix this problem will depend on the system:
Fix: On Linux and other systems using ELF libraries, add the
directory to /etc/ld.so.conf or to the environment variable
LD_LIBRARY_PATH, and run 'ldconfig'.
On other systems, it may be necessary to encode this path
into the executable, by setting the LDFLAGS environment variable
before running configure. For example:
LDFLAGS="-R/home/joe/lib" ./configure
or
LDFLAGS="-Wl,-rpath -Wl,/home/joe/lib" ./configure
* An old version of the GTK libraries was found instead of
your newly installed version. This commonly happens if a
binary package of GTK was previously installed on your system,
and you later compiled GTK from source.
Fix: remove the old libraries and include files.
A detailed log of the ./configure output is written to the file
config.log. This may help diagnose problems.
If you are sure of what you're doing, you can bypass the sanity check and
just go by what gtk-config by using the --disable-gtktest option. Please
only use this in dire circumstances.
After fixing a problem, it is safest to delete the file 'config.cache'
before re-running ./configure.
When ./configure fails on plug-ins
==================================
There are some GIMP plug-ins that need additional third-party libraries
installed on your system. For example to compile the plug-ins that load
and save JPEG, PNG or TIFF files you need the related libraries and header
files installed, otherwise you'll get a message that plugin xyz will not
be build.
If you are sure that those libraries are correctly installed, but configure
fails to detect them, the following might help:
Set your LDFLAGS environment variable to look for the library in a certain
place, e.g. if you are working in a bash shell you would say:
export LDFLAGS="-L<path_to_library> -L<path_to_another_one>"
before you run configure.
Set your CPPFLAGS environment variable to look for the header file in a
certain place, e.g. if you are working in a bash shell you would say:
export CPPFLAGS="-I<path_to_header_file> -I<path_to_another_one>"
before you run configure.
It's wise to remove the file 'config.cache' before re-running configure.
Generic Instructions for Building Auto-Configured Packages
==========================================================

View File

@@ -1,13 +1,20 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = libgimp plug-ins app docs
SUBDIRS = libgimp plug-ins app
EXTRA_DIST = TODO TODO-DIST NOTES gtkrc gimp_logo.ppm rmshm user_install gimp_tips.txt ps-menurc
bin_SCRIPTS = gimptool
gimpdata_DATA = gimprc gtkrc gimp_logo.ppm gimp_tips.txt ps-menurc
EXTRA_DIST = TODO gtkrc gimp_logo.ppm gimp_splash.ppm rmshm user_install gimp_tips.txt ps-menurc gimp.1 gimptool.1 gtkrc.forest2 gimp.m4
gimpdata_DATA = gimprc gimprc_user gtkrc gimp_logo.ppm gimp_splash.ppm gimp_tips.txt ps-menurc gtkrc.forest2
gimpdata_SCRIPTS = user_install
man_MANS=gimp.1 gimptool.1
m4datadir = $(datadir)/aclocal
m4data_DATA = gimp.m4
scriptdata =
.PHONY: files populate checkin release

1
NEWS
View File

@@ -0,0 +1 @@
GIMP 1.0 Released!

9
NOTES
View File

@@ -1,8 +1,8 @@
Some notes on GIMP-0.99.17:
Some notes on GIMP-0.99.16:
* The AA, MathMap, GimpTcl, GAG, user_filter, rcm, FractalExplorer, and Gfig
plugins are included but not yet integrated into the build cause of instability
or other unresolved issues.
* The AA, MathMap, GimpTcl, GAG, user_filter, rcm, and Gfig plugins are
included but not yet integrated into the build cause of instability or
other unresolved issues.
Please read the file TODO-DIST to find more information about things
that were not included or that are (possibly) broken in this distribution.
@@ -11,4 +11,3 @@ that were not included or that are (possibly) broken in this distribution.
-- Federico Mena <federico@nuclecu.unam.mx>
-- Christoph Hoegl <darkwing@bsddmail.franken.de>
-- Manish Singh <yosh@gimp.org>

56
README
View File

@@ -1,12 +1,7 @@
The GIMP: the GNU Image Manipulation Program
--------------------------------------------
This is version 0.99.17 of the GIMP. For the most part it contains all
of the features that will be in version 1.0 of the GIMP. It does,
however, lack a) documentation, b) robustness and c) some of the
plug-ins found in the 0.54 version.
The main difference between v0.99.17 and much earlier versions is the
The main difference between v1.0 and much earlier versions is the
use of a tile based memory management for images. This allows the GIMP
to work with images much larger than physical memory in a usable
fashion. Before such memory management, the GIMP was nearly unusable
@@ -16,16 +11,6 @@ limited by disk space. It is due to the switch to a tile based memory
management system that old plug-ins will not work with this version of
the GIMP.
The GIMP uses GNU libtool in order to build shared libraries on a
variety of systems. While this is very nice for making usable
binaries, it can be a pain when trying to debug a program. For that
reason, compilation of shared libraries can be turned off by
specifying the "--disable-shared" option to "configure". Similarly,
compiling with "-O2" instead of "-g" can be specified by using the
"--disable-debug" option to "configure". We strongly recommend
compiling with the debugging flag as the GIMP appears to be much more
buggy when compiled with optimization turned on. Your mileage may vary.
The plug-in API has changed drastically from previous versions. The
result is that it is now possible to access much of the GIMP's
internals through a database of procedures aptly named the procedure
@@ -65,12 +50,11 @@ Script-fu console.
Lastly, there is new file format (xcf) designed specifically for
saving GIMP images. It handles layers, channels and tiles as well as
saving all of the state information about the image, such as the
active channel, the selection, etc. The format needs testing to make
sure that it really is portable (we think we did it right) as well as
robust. It also will probably change sometime in (near) the future to
implement some form of compression for the tiles.
active channel, the selection, etc. It also will probably change
sometime in the future to implement some form of compression for the
tiles.
The GIMP's new home page is at
The GIMP's home page is at
http://www.gimp.org
@@ -79,7 +63,7 @@ tutorials, news, etc. All things GIMP-ish are available from there.
The automated plug-in registry is located at
http://gimp.foebud.org/registry
http://registry.gimp.org
There you can get the latest versions of plug-ins using a convenient
forms-based interface.
@@ -97,39 +81,39 @@ substituting <list-name> for "gimp-user" or "gimp-developer" (without
the quotes, of course) depending on the list you want to subscribe
to. The mailing list archives can be found at
http://www.levien.com/~gimp-dev/current/
http://www.findmail.com/listsaver/gimp-developer/
http://www.findmail.com/listsaver/gimp-user/
Gimp-user is a mailing list dedicated to user problems, hints and
tips, discussion of cool effects, etc. Gimp-developer is oriented to
GIMP core and plug-in developers. Most people will only want to be
subscribed to gimp-user.
And finally, for the real junkies, there are two IRC channels devoted
to the GIMP :-) On EFNET there is a small #gimp channel. On Byxnet (a
private mostly-GIMP network) there is #gimp, too. Some of the Byxnet
servers are:
And finally, for the real junkies, there is an IRC channel devoted to
the GIMP :-) On Byxnet (a private mostly-GIMP network) there is #gimp.
Many of the developers hang out there. Some of the Byxnet servers are:
irc.mint.net:6666
irc.canweb.net:6667
rudolf.canberra.edu.au:6666
levien.com:6666
More information about Byxnet can be found at
You can customize the look of the interface quite a bit my editing the
~/.gimp/gtkrc file. A sample file, gtkrc.forest, is included (Thanks to
Tuomas Kuosmanen)
http://rudolf.canberra.edu.au/gimp/byxnet.html
Manish Singh (yosh@gimp.org) has contributed a set of keybindings similar
to those in Adobe Photoshop (tm). You can find them in the ps-menurc file.
To use them, copy this file to ~/.gimp/menurc
Included is a set of keybindings similar to those in Adobe Photoshop (tm).
You can find them in the ps-menurc file. To use them, copy this file to
~/.gimp/menurc
We sincerely hope you enjoy the program. Please report problems to
gimp-developer@scam.xcf.berkeley.edu. Before reporting a problem, you
may want to see if someone else has already did (check the mailing
list archives for this).
bugs@gimp.org. Before reporting a problem, you may want to see if someone
else has already did (check the http://www.wilberworks.com/bugs.cgi for
this).
Have fun,
Spencer Kimball <spencer@xcf.berkeley.edu>
Peter Mattis <petm@xcf.berkeley.edu>
Federico Mena <federico@nuclecu.unam.mx>
Manish Singh <yosh@gimp.org>

7
TODO
View File

@@ -1,9 +1,6 @@
Please add things to this file when the need to do them is
discovered.
* Fix srand/srandom and rand/random confusion in plugins
* configure: SunOS 4 SEEK_* and RAND_MAX defines
* configure: check for regex library presence
brightness_contrast.c : 326 active_tool->preserve CP error
levels.c : 2077 active_tool->preserve CP error

91
app/ISSUES_DEFINES Normal file
View File

@@ -0,0 +1,91 @@
Issues
BRUSHES_C_1_cw
Need a way to decide what to make default brush precisions.
Maybe make one of each type supported by the compile options.
BRUSHES_C_2_cw
I dont know if there is an analogue to temp_buf_swap to put here.
There are a number of these in this file.
BRUSHES_C_3_cw
This is a hack for version 1 and 2 of the gbr file.
BRUSHES_C_4_cw
Make some square solid brushes for debugging paint_funcs.
BRUSHES_C_5_cw
A check for data types. Should be done differently.
BRUSH_SELECT_C_1_cw
These routines should be passed tags when color brushes are
introduced -- not just generic data like now. So for now
this will only display gray-scale brushes.
BRUSH_HEADER_C_2_cw
FILE_VERSION changed to 3 for Brushes in gimp16.
DRAWABLE_CMDS_C_1_cw
Here we get the drawable tag and convert it to a plugin
GDrawableType and pass this to the plugin.
GIMAGE_CMDS_C_1_cw
This is a partial hack to get an appropriate GImageType
base_type to pass to the plugin (ie need one of the
extended "RGB,GRAY,...,U16_RGB,U16_GRAY,...,FLOAT_RGB,..)
types to pass to plugin.
GIMAGE_CMDS_C_2_cw
This is "glue" to make an appropriate tag for the
new image from one of the extended GImageTypes from
the plugin. Calls gimage_new_tag instead of
gimage_new.
LAYER_CMDS_C_1_cw
Here we convert the plugin GDrawableType to a drawable tag to
pass to layer_new_tag.
PAINT_CORE_16_C_1_cw
Commented out the grab pointer for debugging
PAINT_CORE_16_C_2_cw
I changed the brush mask to a canvas in paint_core_init.
PAINT_CORE_16_C_3_cw
I commented out this canvas_delete because the brush
mask is a true canvas now.
PAINT_CORE_16_C_4_cw
This is where the +2 needs to be dekludged to make brushse
of the exact ui-advertised size for debugging in the
paint_funcs. Also see the brush_mask_get function. I wrote
code for solidify for 16bit/float but have not written
subsample for 16bit/float. So if using 16bit you have
to make sure BRUSH_WITH_BORDER is not defined.
PIXELAREA_C_1_cw
Not sure what to do with the subsample parameter here. scale_area
does use this value.
PIXELAREA_C_2_cw
Same as above .. subsample not used.
PIXELAREA_C_3_cw
I fixed a portion width bug. If the width isnt clamped here
it can actually be as large as the whole canvas (when canvas
is flat_buf) even if the desired pixelarea width was originally
set. pixelarea_width() was returning widths bigger than the
original pixelarea width.
PIXELAREA_C_4_cw
fixed portion height clamp bug (see above).
PLUG_IN_C_1_cw
Once the shadow canvas for drawable is working set up this.
PLUG_IN_C_2_cw
Once the shadow canvas for drawable is working set up this.
PLUG_IN_C_3_cw
Here the shared memory segment tile to pass
plugins is allocated to size TILE_WIDTH x TILE_HEIGHT x TAG_MAX_BYTES

View File

@@ -5,6 +5,40 @@ scriptdata =
bin_PROGRAMS = gimp
gimp_SOURCES = \
\
tag.c \
tag.h \
canvas.c \
canvas.h \
pixelrow.c \
pixelrow.h \
pixelarea.c \
pixelarea.h \
paint_funcs_row_u8.c \
paint_funcs_row_u8.h \
paint_funcs_row_u16.c \
paint_funcs_row_u16.h \
paint_funcs_row_float.c \
paint_funcs_row_float.h \
paint_funcs_row_float16.c \
paint_funcs_row_float16.h \
float16.c \
float16.h \
displaylut.c \
displaylut.h \
paint_funcs_area.c \
paint_funcs_area.h \
tilebuf.c \
tilebuf.h \
flatbuf.c \
flatbuf.h \
shmbuf.c \
shmbuf.h \
paint_core_16.c \
paint_core_16.h \
trace.c \
trace.h \
\
about_dialog.c \
about_dialog.h \
actionarea.c \
@@ -179,8 +213,6 @@ gimp_SOURCES = \
layers_dialogP.h \
levels.c \
levels.h \
linked.h \
linked.c \
magnify.c \
magnify.h \
main.c \
@@ -189,12 +221,10 @@ gimp_SOURCES = \
menus.h \
move.c \
move.h \
ops_buttons.c \
ops_buttons.h \
palette.c \
palette.h \
paint_core.c \
paint_core.h \
paint_funcs.c \
paint_funcs.h \
paintbrush.c \
paintbrush.h \
pattern_header.h \
@@ -218,6 +248,8 @@ gimp_SOURCES = \
rect_select.c \
rect_select.h \
rect_selectP.h \
regex.h \
regex.c \
resize.c \
resize.h \
rotate_tool.c \
@@ -268,14 +300,25 @@ EXTRA_DIST = \
tools/eye.xbm \
tools/layer.xbm \
tools/linked.xbm \
tools/mask.xbm
tools/mask.xbm \
tools/anchor.xpm \
tools/anchor_is.xpm \
tools/delete.xpm \
tools/delete_is.xpm \
tools/duplicate.xpm \
tools/duplicate_is.xpm \
tools/lower.xpm \
tools/lower_is.xpm \
tools/new.xpm \
tools/new_is.xpm \
tools/raise.xpm \
tools/raise_is.xpm
CPPFLAGS = \
-DLIBDIR=\""$(gimpplugindir)"\" \
-DDATADIR=\""$(gimpdatadir)"\" \
-DGIMPDIR=\""$(gimpdir)"\" \
-DVERSION=\"$(VERSION)\" \
-DNDEBUG
-DPRECISION_CONFIG=$(precision)
INCLUDES = \
$(X_CFLAGS) \

View File

@@ -2,5 +2,94 @@ convert to using gtk+
remove traces of autodialog
remove traces of action areas
remove use of mem chunks from memutils.[ch]
remove use of linked.[ch]
remove use of xmalloc and xfree (use g_malloc and g_free instead)
Canvas validator routines
this is well underway
8 bitness
HALF_WAY
channel_value return 0-255, this gets used a lot. what semantics do we
want?
indexed color handling
the current code has dropped support for converting indexed to RGB via
gimage->cmap. we should look at adding this back sometime.
drawable creation
provide alternate constructors that accept a prebuilt Canvas instead of
parameters for building one.
convert brush storage header 'type' field to store a Tag instead
convert pattern storage header 'type' field to store a Tag instead
fix blend supersampling
do bucket_fill patterns
fix alpha channel on bucket_fill
fix composite previews in channels dialog
fix previews to use a checkered buffer for transparent layers
do color_panel
self contained, used only in channels_dialog
do color_picker
completely self contained
do convert.c
????
fix convolve
it darkens the area being convolved
multiply/separate alpha for images with alpha channel
fix equalize
two inner loops needs precision wrapping
several lookup tables
fix free_select
scan_convert is totally 8 bit
fix fuzzy_select
seed fill is partially commented out
fix gimage
initial_area and combine_areas have a really messy interface.
do histogram
????
do histogram_tool
????
fix iscissors
lots of work
do shapeburst_area
do threshold
????
fix transform_core
only the low level guts remains, high level stuff is done
xcf
should fix this at some point
fix scale_area and update previews to use it

View File

@@ -1,10 +1,33 @@
/* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "gtk/gtk.h"
#include <gtk/gtk.h>
#include "libgimp/gimpfeatures.h"
#include "about_dialog.h"
#include "interface.h"
#include "config.h"
#define ANIMATION_STEPS 16
#define ANIMATION_SIZE 2
@@ -41,11 +64,14 @@ static char *scroll_text[] =
"Zach Beane",
"Tom Bech",
"Marc Bless",
"Edward Blevins",
"Roberto Boyd",
"Seth Burgess",
"Brent Burton",
"Francisco Bustamante",
"Ed Connel",
"Andreas Dilger",
"Misha Dynin",
"Larry Ewing",
"David Forsyth",
"Jim Geuther",
@@ -57,8 +83,12 @@ static char *scroll_text[] =
"Simon Janes",
"Tim Janik",
"Tuomas Kuosmanen",
"Peter Kirchgessner",
"Nick Lamb",
"Karl LaRocca",
"Jens Lautenbacher",
"Laramie Leavitt",
"Elliot Lee",
"Raph Levien",
"Adrian Likins",
"Ingo Luetkebohle",
@@ -87,8 +117,10 @@ static char *scroll_text[] =
"Tristan Tarrant",
"Owen Taylor",
"Ian Tester",
"Andy Thomas",
"James Wang",
"Kris Wehner",
"Matthew Wilson",
};
static int nscroll_texts = sizeof (scroll_text) / sizeof (scroll_text[0]);
static int scroll_text_widths[100] = { 0 };
@@ -111,13 +143,12 @@ about_dialog_create (int timeout)
if (!about_dialog)
{
about_dialog = gtk_window_new (GTK_WINDOW_DIALOG);
gtk_window_set_wmclass (GTK_WINDOW (about_dialog), "about_dialog", "Gimp");
gtk_window_set_title (GTK_WINDOW (about_dialog), "About the GIMP");
gtk_window_set_policy (GTK_WINDOW (about_dialog), FALSE, FALSE, FALSE);
gtk_window_position (GTK_WINDOW (about_dialog), GTK_WIN_POS_CENTER);
gtk_signal_connect (GTK_OBJECT (about_dialog), "destroy",
(GtkSignalFunc) about_dialog_destroy, NULL);
gtk_signal_connect (GTK_OBJECT (about_dialog), "delete_event",
(GtkSignalFunc) about_dialog_destroy, NULL);
gtk_signal_connect (GTK_OBJECT (about_dialog), "unmap_event",
(GtkSignalFunc) about_dialog_unmap, NULL);
gtk_signal_connect (GTK_OBJECT (about_dialog), "button_press_event",
@@ -159,7 +190,7 @@ about_dialog_create (int timeout)
style->font = gdk_font_load ("-Adobe-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*");
gtk_widget_push_style (style);
label = gtk_label_new ("Version " VERSION " brought to you by");
label = gtk_label_new ("Version " GIMP_VERSION " brought to you by");
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
gtk_widget_show (label);
@@ -196,6 +227,10 @@ about_dialog_create (int timeout)
gtk_container_add (GTK_CONTAINER (aboutframe), scroll_area);
gtk_widget_show (scroll_area);
label = gtk_label_new ("Please visit http://www.gimp.org/ for more info");
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
gtk_widget_show (label);
gtk_widget_realize (scroll_area);
gdk_window_set_background (scroll_area->window, &scroll_area->style->white);
}
@@ -240,6 +275,7 @@ static int
about_dialog_load_logo (GtkWidget *window)
{
GtkWidget *preview;
GdkGC *gc;
char buf[1024];
unsigned char *pixelrow;
FILE *fp;
@@ -251,7 +287,7 @@ about_dialog_load_logo (GtkWidget *window)
sprintf (buf, "%s/gimp_logo.ppm", DATADIR);
fp = fopen (buf, "r");
fp = fopen (buf, "rb");
if (!fp)
return 0;
@@ -292,12 +328,15 @@ about_dialog_load_logo (GtkWidget *window)
}
gtk_widget_realize (window);
logo_pixmap = gdk_pixmap_new (window->window, logo_width, logo_height, -1);
logo_pixmap = gdk_pixmap_new (window->window, logo_width, logo_height,
gtk_preview_get_visual ()->depth);
gc = gdk_gc_new (logo_pixmap);
gtk_preview_put (GTK_PREVIEW (preview),
logo_pixmap, window->style->black_gc,
logo_pixmap, gc,
0, 0, 0, 0, logo_width, logo_height);
gdk_gc_destroy (gc);
gtk_widget_destroy (preview);
gtk_widget_unref (preview);
g_free (pixelrow);
fclose (fp);

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "appenv.h"
#include "actionarea.h"

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __ACTIONAREA_H__
#define __ACTIONAREA_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
@@ -54,19 +54,21 @@
#include "layers_dialog.h"
#include "layer_select.h"
#include "levels.h"
#include "paint_funcs_area.h"
#include "palette.h"
#include "patterns.h"
#include "plug_in.h"
#include "posterize.h"
#include "resize.h"
#include "scale.h"
#include "tag.h"
#include "threshold.h"
#include "tips_dialog.h"
#include "tools.h"
#include "undo.h"
/* external functions */
extern layers_dialog_layer_merge_query (GImage *, int);
extern void layers_dialog_layer_merge_query (GImage *, int);
typedef struct {
GtkWidget *dlg;
@@ -74,7 +76,8 @@ typedef struct {
GtkWidget *width_entry;
int width;
int height;
int type;
Format format;
Storage storage;
int fill_type;
} NewImageValues;
@@ -94,7 +97,8 @@ static void file_new_toggle_callback (GtkWidget *, gpointer);
/* static variables */
static int last_width = 256;
static int last_height = 256;
static int last_type = RGB;
static Format last_format = FORMAT_RGB;
static Storage last_storage = STORAGE_TILED;
static int last_fill_type = BACKGROUND_FILL;
/* preferences local functions */
@@ -111,6 +115,7 @@ static GtkWidget *prefs_dlg = NULL;
static int old_transparency_type;
static int old_transparency_size;
static int old_levels_of_undo;
static int old_marching_speed;
static int old_allow_resize_windows;
static int old_auto_save;
static int old_preview_size;
@@ -120,7 +125,8 @@ static int old_cubic_interpolation;
static int old_confirm_on_close;
static int old_default_width;
static int old_default_height;
static int old_default_type;
static Format old_default_format;
static Precision old_default_precision;
static int new_dialog_run;
static int old_stingy_memory_use;
static int old_tile_cache_size;
@@ -174,7 +180,9 @@ file_new_ok_callback (GtkWidget *widget,
GImage *gimage;
GDisplay *gdisplay;
Layer *layer;
int type;
Precision precision = PRECISION_NONE;
Format format = FORMAT_NONE;
Alpha alpha = ALPHA_NONE;
vals = data;
@@ -185,36 +193,47 @@ file_new_ok_callback (GtkWidget *widget,
last_width = vals->width;
last_height = vals->height;
last_type = vals->type;
last_format = vals->format;
last_storage = vals->storage;
last_fill_type = vals->fill_type;
switch (vals->fill_type)
{
case BACKGROUND_FILL:
case FOREGROUND_FILL:
case WHITE_FILL:
type = (vals->type == RGB) ? RGB_GIMAGE : GRAY_GIMAGE;
case NO_FILL:
format = (vals->format == FORMAT_RGB) ? FORMAT_RGB: FORMAT_GRAY;
alpha = ALPHA_NO;
break;
case TRANSPARENT_FILL:
type = (vals->type == RGB) ? RGBA_GIMAGE : GRAYA_GIMAGE;
format = (vals->format == FORMAT_RGB) ? FORMAT_RGB: FORMAT_GRAY;
alpha = ALPHA_YES;
break;
default:
type = RGB_IMAGE;
format = FORMAT_NONE;
alpha = ALPHA_NONE;
break;
}
gimage = gimage_new (vals->width, vals->height, vals->type);
precision = default_precision;
/* Make the background (or first) layer */
layer = layer_new (gimage->ID, gimage->width, gimage->height,
type, "Background", OPAQUE, NORMAL);
{
Tag tag = tag_new ( precision, format, alpha);
gimage = gimage_new (vals->width, vals->height, tag);
/* Make the background (or first) layer */
layer = layer_new (gimage->ID, gimage->width, gimage->height,
tag, vals->storage, "Background", OPAQUE_OPACITY, NORMAL);
}
if (layer) {
/* add the new layer to the gimage */
gimage_disable_undo (gimage);
gimage_add_layer (gimage, layer, 0);
gimage_enable_undo (gimage);
drawable_fill (GIMP_DRAWABLE(layer), vals->fill_type);
if (vals->fill_type != NO_FILL)
drawable_fill (GIMP_DRAWABLE(layer), vals->fill_type);
gimage_clean_all (gimage);
@@ -231,7 +250,7 @@ file_new_delete_callback (GtkWidget *widget,
{
file_new_cancel_callback (widget, data);
return FALSE;
return TRUE;
}
@@ -279,7 +298,7 @@ file_new_cmd_callback (GtkWidget *widget,
{
last_width = default_width;
last_height = default_height;
last_type = default_type;
last_format = default_format;
new_dialog_run = 1;
}
@@ -292,25 +311,27 @@ file_new_cmd_callback (GtkWidget *widget,
gdisp = NULL;
vals = g_malloc (sizeof (NewImageValues));
vals->storage = last_storage;
vals->fill_type = last_fill_type;
if (gdisp)
{
vals->width = gdisp->gimage->width;
vals->height = gdisp->gimage->height;
vals->type = gimage_base_type (gdisp->gimage);
vals->format = tag_format (gimage_tag (gdisp->gimage));
}
else
{
vals->width = last_width;
vals->height = last_height;
vals->type = last_type;
vals->format = last_format;
}
if (vals->type == INDEXED)
vals->type = RGB; /* no indexed images */
if (vals->format == FORMAT_INDEXED)
vals->format = FORMAT_RGB; /* no indexed images */
vals->dlg = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (vals->dlg), "new_image", "Gimp");
gtk_window_set_title (GTK_WINDOW (vals->dlg), "New Image");
gtk_window_position (GTK_WINDOW (vals->dlg), GTK_WIN_POS_MOUSE);
@@ -394,22 +415,65 @@ file_new_cmd_callback (GtkWidget *widget,
button = gtk_radio_button_new_with_label (NULL, "RGB");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) RGB);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) FORMAT_RGB);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->type);
if (vals->type == RGB)
&vals->format);
if (vals->format == FORMAT_RGB)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "Grayscale");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) GRAY);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) FORMAT_GRAY);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->type);
if (vals->type == GRAY)
&vals->format);
if (vals->format == FORMAT_GRAY)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
frame = gtk_frame_new ("Storage Type");
gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
gtk_widget_show (frame);
radio_box = gtk_vbox_new (FALSE, 1);
gtk_container_border_width (GTK_CONTAINER (radio_box), 2);
gtk_container_add (GTK_CONTAINER (frame), radio_box);
gtk_widget_show (radio_box);
button = gtk_radio_button_new_with_label (NULL, "Tiled");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) STORAGE_TILED);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->storage);
if (vals->storage == STORAGE_TILED)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "Flat");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) STORAGE_FLAT);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->storage);
if (vals->storage == STORAGE_FLAT)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "Shared Memory");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) STORAGE_SHM);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->storage);
if (vals->storage == STORAGE_SHM)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
@@ -456,6 +520,28 @@ file_new_cmd_callback (GtkWidget *widget,
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "Foreground");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) FOREGROUND_FILL);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->fill_type);
if (vals->fill_type == FOREGROUND_FILL)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "No Fill");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) NO_FILL);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->fill_type);
if (vals->fill_type == NO_FILL)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
gtk_widget_show (vals->dlg);
}
@@ -512,8 +598,8 @@ file_save_as_cmd_callback (GtkWidget *widget,
Still no settings for default-brush, default-gradient,
default-palette, default-pattern, gamma-correction, color-cube,
marching-ants-speed, show-rulers, ruler-units. No widget for
confirm-on-close although a lot of stuff is there.
show-rulers, ruler-units. No widget for confirm-on-close although
a lot of stuff is there.
No UI feedback for the fact that some settings won't take effect
until the next Gimp restart.
@@ -562,22 +648,25 @@ file_prefs_ok_callback (GtkWidget *widget,
if (levels_of_undo < 0)
{
message_box("Error: Levels of undo must be zero or greater.",
NULL, NULL);
g_message ("Error: Levels of undo must be zero or greater.");
levels_of_undo = old_levels_of_undo;
return;
}
if (marching_speed < 50)
{
g_message ("Error: Marching speed must be 50 or greater.");
marching_speed = old_marching_speed;
return;
}
if (default_width < 1)
{
message_box("Error: Default width must be one or greater.",
NULL, NULL);
g_message ("Error: Default width must be one or greater.");
default_width = old_default_width;
return;
}
if (default_height < 1)
{
message_box("Error: Default height must be one or greater.",
NULL, NULL);
g_message ("Error: Default height must be one or greater.");
default_height = old_default_height;
return;
}
@@ -608,6 +697,7 @@ file_prefs_save_callback (GtkWidget *widget,
gchar *save_palette_path;
gchar *save_plug_in_path;
gchar *save_gradient_path;
int restart_notification = FALSE;
file_prefs_ok_callback (widget, dlg);
@@ -626,6 +716,8 @@ file_prefs_save_callback (GtkWidget *widget,
if (levels_of_undo != old_levels_of_undo)
update = g_list_append (update, "undo-levels");
if (marching_speed != old_marching_speed)
update = g_list_append (update, "marching-ants-speed");
if (allow_resize_windows != old_allow_resize_windows)
update = g_list_append (update, "allow-resize-windows");
if (auto_save != old_auto_save)
@@ -650,8 +742,10 @@ file_prefs_save_callback (GtkWidget *widget,
if (default_width != old_default_width ||
default_height != old_default_height)
update = g_list_append (update, "default-image-size");
if (default_type != old_default_type)
if (default_format != old_default_format)
update = g_list_append (update, "default-image-type");
if (default_precision != old_default_precision)
update = g_list_append (update, "default-image-precision");
if (preview_size != old_preview_size)
update = g_list_append (update, "preview-size");
if (transparency_type != old_transparency_type)
@@ -662,56 +756,67 @@ file_prefs_save_callback (GtkWidget *widget,
{
update = g_list_append (update, "stingy-memory-use");
stingy_memory_use = edit_stingy_memory_use;
restart_notification = TRUE;
}
if (edit_tile_cache_size != tile_cache_size)
{
update = g_list_append (update, "tile-cache-size");
tile_cache_size = edit_tile_cache_size;
restart_notification = TRUE;
}
if (edit_install_cmap != install_cmap)
if (edit_install_cmap != old_install_cmap)
{
update = g_list_append (update, "install-colormap");
install_cmap = edit_install_cmap;
restart_notification = TRUE;
}
if (edit_cycled_marching_ants != cycled_marching_ants)
{
update = g_list_append (update, "colormap-cycling");
cycled_marching_ants = edit_cycled_marching_ants;
restart_notification = TRUE;
}
if (file_prefs_strcmp (temp_path, edit_temp_path))
{
update = g_list_append (update, "temp-path");
temp_path = edit_temp_path;
restart_notification = TRUE;
}
if (file_prefs_strcmp (swap_path, edit_swap_path))
{
update = g_list_append (update, "swap-path");
swap_path = edit_swap_path;
restart_notification = TRUE;
}
if (file_prefs_strcmp (brush_path, edit_brush_path))
{
update = g_list_append (update, "brush-path");
brush_path = edit_brush_path;
restart_notification = TRUE;
}
if (file_prefs_strcmp (pattern_path, edit_pattern_path))
{
update = g_list_append (update, "pattern-path");
pattern_path = edit_pattern_path;
restart_notification = TRUE;
}
if (file_prefs_strcmp (palette_path, edit_palette_path))
{
update = g_list_append (update, "palette-path");
palette_path = edit_palette_path;
restart_notification = TRUE;
}
if (file_prefs_strcmp (plug_in_path, edit_plug_in_path))
{
update = g_list_append (update, "plug-in-path");
plug_in_path = edit_plug_in_path;
restart_notification = TRUE;
}
if (file_prefs_strcmp (gradient_path, edit_gradient_path))
{
update = g_list_append (update, "gradient-path");
gradient_path = edit_gradient_path;
restart_notification = TRUE;
}
save_gimprc (&update, &remove);
@@ -727,6 +832,9 @@ file_prefs_save_callback (GtkWidget *widget,
palette_path = save_palette_path;
plug_in_path = save_plug_in_path;
gradient_path = save_gradient_path;
if (restart_notification)
g_message ("You will need to restart GIMP for these changes to take effect.");
g_list_free (update);
g_list_free (remove);
@@ -740,7 +848,7 @@ file_prefs_delete_callback (GtkWidget *widget,
file_prefs_cancel_callback (widget, dlg);
/* the widget is already destroyed here no need to try again */
return FALSE;
return TRUE;
}
static void
@@ -751,6 +859,7 @@ file_prefs_cancel_callback (GtkWidget *widget,
prefs_dlg = NULL;
levels_of_undo = old_levels_of_undo;
marching_speed = old_marching_speed;
allow_resize_windows = old_allow_resize_windows;
auto_save = old_auto_save;
no_cursor_updating = old_no_cursor_updating;
@@ -759,7 +868,8 @@ file_prefs_cancel_callback (GtkWidget *widget,
confirm_on_close = old_confirm_on_close;
default_width = old_default_width;
default_height = old_default_height;
default_type = old_default_type;
default_format = old_default_format;
default_precision = old_default_precision;
if (preview_size != old_preview_size)
{
lc_dialog_rebuild (old_preview_size);
@@ -810,15 +920,19 @@ file_prefs_toggle_callback (GtkWidget *widget,
cubic_interpolation = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&confirm_on_close)
confirm_on_close = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&old_stingy_memory_use)
old_stingy_memory_use = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&old_install_cmap)
old_install_cmap = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&old_cycled_marching_ants)
old_cycled_marching_ants = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&default_type)
else if (data==&edit_stingy_memory_use)
edit_stingy_memory_use = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&edit_install_cmap)
edit_install_cmap = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&edit_cycled_marching_ants)
edit_cycled_marching_ants = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&default_format)
{
default_type = (long) gtk_object_get_user_data (GTK_OBJECT (widget));
default_format = (long) gtk_object_get_user_data (GTK_OBJECT (widget));
}
else if (data==&default_precision)
{
default_precision = (Precision) gtk_object_get_user_data (GTK_OBJECT (widget));
}
else if (GTK_TOGGLE_BUTTON (widget)->active)
{
@@ -960,6 +1074,7 @@ file_pref_cmd_callback (GtkWidget *widget,
old_transparency_type = transparency_type;
old_transparency_size = transparency_size;
old_levels_of_undo = levels_of_undo;
old_marching_speed = marching_speed;
old_allow_resize_windows = allow_resize_windows;
old_auto_save = auto_save;
old_preview_size = preview_size;
@@ -969,7 +1084,8 @@ file_pref_cmd_callback (GtkWidget *widget,
old_confirm_on_close = confirm_on_close;
old_default_width = default_width;
old_default_height = default_height;
old_default_type = default_type;
old_default_format = default_format;
old_default_precision = default_precision;
old_stingy_memory_use = edit_stingy_memory_use;
old_tile_cache_size = edit_tile_cache_size;
old_install_cmap = edit_install_cmap;
@@ -983,6 +1099,7 @@ file_pref_cmd_callback (GtkWidget *widget,
file_prefs_strset (&old_gradient_path, edit_gradient_path);
prefs_dlg = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (prefs_dlg), "preferences", "Gimp");
gtk_window_set_title (GTK_WINDOW (prefs_dlg), "Preferences");
/* handle the wm close signal */
@@ -1101,27 +1218,80 @@ file_pref_cmd_callback (GtkWidget *widget,
button = gtk_radio_button_new_with_label (NULL, "RGB");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) RGB);
if (default_type == RGB)
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) FORMAT_RGB);
if (last_format == FORMAT_RGB)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&default_type);
&default_format);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "Grayscale");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) GRAY);
if (last_type == GRAY)
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) FORMAT_GRAY);
if (last_format == FORMAT_GRAY)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&default_type);
&default_format);
gtk_widget_show (button);
hbox = gtk_hbox_new (FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
gtk_widget_show (hbox);
frame = gtk_frame_new ("Image precision");
gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
gtk_widget_show (frame);
radio_box = gtk_vbox_new (FALSE, 1);
gtk_container_border_width (GTK_CONTAINER (radio_box), 2);
gtk_container_add (GTK_CONTAINER (frame), radio_box);
gtk_widget_show (radio_box);
button = gtk_radio_button_new_with_label (NULL, "U8");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) PRECISION_U8);
if (default_precision == PRECISION_U8)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&default_precision);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "U16");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) PRECISION_U16);
if (default_precision == PRECISION_U16)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&default_precision);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "FLOAT");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) PRECISION_FLOAT);
if (default_precision == PRECISION_FLOAT)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&default_precision);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "FLOAT16");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) PRECISION_FLOAT16);
if (default_precision == PRECISION_FLOAT16)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&default_precision);
gtk_widget_show (button);
hbox = gtk_hbox_new (FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
gtk_widget_show (hbox);
label = gtk_label_new ("Preview size:");
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
@@ -1247,14 +1417,18 @@ file_pref_cmd_callback (GtkWidget *widget,
&allow_resize_windows);
gtk_widget_show (button);
button = gtk_check_button_new_with_label("Auto save");
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button),
/* Don't show the Auto-save button until we really
have auto-saving in the gimp.
button = gtk_check_button_new_with_label("Auto save");
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button),
auto_save);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&auto_save);
gtk_widget_show (button);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&auto_save);
gtk_widget_show (button);
*/
button = gtk_check_button_new_with_label("Disable cursor updating");
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button),
@@ -1287,6 +1461,9 @@ file_pref_cmd_callback (GtkWidget *widget,
sprintf (buffer, "%d", marching_speed);
gtk_entry_set_text (GTK_ENTRY (entry), buffer);
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (entry), "changed",
(GtkSignalFunc) file_prefs_text_callback,
&marching_speed);
gtk_widget_show (entry);
label = gtk_label_new ("Interface");
@@ -1309,7 +1486,7 @@ file_pref_cmd_callback (GtkWidget *widget,
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&old_stingy_memory_use);
&edit_stingy_memory_use);
gtk_widget_show (button);
hbox = gtk_hbox_new (FALSE, 2);
@@ -1327,7 +1504,7 @@ file_pref_cmd_callback (GtkWidget *widget,
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (entry), "changed",
(GtkSignalFunc) file_prefs_text_callback,
&old_tile_cache_size);
&edit_tile_cache_size);
gtk_widget_show (entry);
button = gtk_check_button_new_with_label("Install colormap (8-bit only)");
@@ -1335,7 +1512,7 @@ file_pref_cmd_callback (GtkWidget *widget,
install_cmap);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&old_install_cmap);
&edit_install_cmap);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
@@ -1344,8 +1521,10 @@ file_pref_cmd_callback (GtkWidget *widget,
cycled_marching_ants);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&old_cycled_marching_ants);
&edit_cycled_marching_ants);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
if (g_visual->depth != 8)
gtk_widget_set_sensitive (GTK_WIDGET(button), FALSE);
gtk_widget_show (button);
label = gtk_label_new ("Environment");
@@ -1635,7 +1814,7 @@ select_border_cmd_callback (GtkWidget *widget,
sprintf (initial, "%d", gimage_mask_border_radius);
query_string_box ("Border Selection", "Border selection by:", initial,
gimage_mask_border_callback, gdisp->gimage);
gimage_mask_border_callback, (gpointer) gdisp->gimage->ID);
}
void
@@ -1649,7 +1828,7 @@ select_feather_cmd_callback (GtkWidget *widget,
sprintf (initial, "%f", gimage_mask_feather_radius);
query_string_box ("Feather Selection", "Feather selection by:", initial,
gimage_mask_feather_callback, gdisp->gimage);
gimage_mask_feather_callback, (gpointer) gdisp->gimage->ID);
}
void
@@ -1663,7 +1842,7 @@ select_grow_cmd_callback (GtkWidget *widget,
sprintf (initial, "%d", gimage_mask_grow_pixels);
query_string_box ("Grow Selection", "Grow selection by:", initial,
gimage_mask_grow_callback, gdisp->gimage);
gimage_mask_grow_callback, (gpointer) gdisp->gimage->ID);
}
void
@@ -1677,7 +1856,7 @@ select_shrink_cmd_callback (GtkWidget *widget,
sprintf (initial, "%d", gimage_mask_shrink_pixels);
query_string_box ("Shrink Selection", "Shrink selection by:", initial,
gimage_mask_shrink_callback, gdisp->gimage);
gimage_mask_shrink_callback, (gpointer) gdisp->gimage->ID);
}
void
@@ -1689,6 +1868,10 @@ select_by_color_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) BY_COLOR_SELECT].toolbar_position]);
by_color_select_initialize ((void *) gdisp->gimage);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -1943,6 +2126,10 @@ image_posterize_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) POSTERIZE].toolbar_position]);
posterize_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -1954,6 +2141,10 @@ image_threshold_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) THRESHOLD].toolbar_position]);
threshold_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -1965,6 +2156,11 @@ image_color_balance_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) COLOR_BALANCE].toolbar_position]);
color_balance_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -1976,6 +2172,10 @@ image_brightness_contrast_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) BRIGHTNESS_CONTRAST].toolbar_position]);
brightness_contrast_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -1987,6 +2187,10 @@ image_hue_saturation_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) HUE_SATURATION].toolbar_position]);
hue_saturation_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -1998,6 +2202,10 @@ image_curves_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) CURVES].toolbar_position]);
curves_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -2009,6 +2217,10 @@ image_levels_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) LEVELS].toolbar_position]);
levels_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -2094,6 +2306,7 @@ image_resize_cmd_callback (GtkWidget *widget,
/* the dialog */
image_resize->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (image_resize->shell), "image_resize", "Gimp");
gtk_window_set_title (GTK_WINDOW (image_resize->shell), "Image Resize");
gtk_window_set_policy (GTK_WINDOW (image_resize->shell), FALSE, FALSE, TRUE);
gtk_window_position (GTK_WINDOW (image_resize->shell), GTK_WIN_POS_MOUSE);
@@ -2140,6 +2353,7 @@ image_scale_cmd_callback (GtkWidget *widget,
/* the dialog */
image_scale->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (image_scale->shell), "image_scale", "Gimp");
gtk_window_set_title (GTK_WINDOW (image_scale->shell), "Image Scale");
gtk_window_set_policy (GTK_WINDOW (image_scale->shell), FALSE, FALSE, TRUE);
gtk_window_position (GTK_WINDOW (image_scale->shell), GTK_WIN_POS_MOUSE);
@@ -2173,6 +2387,10 @@ image_histogram_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) HISTOGRAM].toolbar_position]);
histogram_tool_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -2259,12 +2477,44 @@ layers_mask_select_cmd_callback (GtkWidget *widget,
gdisplays_flush ();
}
void
layers_add_alpha_channel_cmd_callback (GtkWidget *widget,
gpointer client_data)
{
GDisplay * gdisp;
gdisp = gdisplay_active ();
layer_add_alpha ( gdisp->gimage->active_layer);
gdisplays_flush ();
}
void
tools_default_colors_cmd_callback (GtkWidget *widget,
gpointer client_data)
{
palette_set_default_colors ();
}
void
tools_swap_colors_cmd_callback (GtkWidget *widget,
gpointer client_data)
{
palette_swap_colors ();
}
void
tools_select_cmd_callback (GtkWidget *widget,
gpointer client_data)
{
GDisplay * gdisp;
/* Activate the approriate widget */
gtk_widget_activate (tool_widgets[tool_info[(long) client_data].toolbar_position]);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -2377,7 +2627,7 @@ image_resize_callback (GtkWidget *w,
}
else
{
message_box("Resize Error: Both width and height must be greater than zero.", NULL, NULL);
g_message ("Resize Error: Both width and height must be greater than zero.");
return;
}
}
@@ -2407,7 +2657,7 @@ image_scale_callback (GtkWidget *w,
}
else
{
message_box("Scale Error: Both width and height must be greater than zero.", NULL, NULL);
g_message ("Scale Error: Both width and height must be greater than zero.");
return;
}
}
@@ -2424,7 +2674,7 @@ image_delete_callback (GtkWidget *w,
{
image_cancel_callback (w, client_data);
return FALSE;
return TRUE;
}
@@ -2449,7 +2699,9 @@ gimage_mask_feather_callback (GtkWidget *w,
GImage *gimage;
double feather_radius;
gimage = (GImage *) client_data;
if (!(gimage = gimage_get_ID ((int)client_data)))
return;
feather_radius = atof (call_data);
gimage_mask_feather (gimage, feather_radius);
@@ -2465,7 +2717,9 @@ gimage_mask_border_callback (GtkWidget *w,
GImage *gimage;
int border_radius;
gimage = (GImage *) client_data;
if (!(gimage = gimage_get_ID ((int)client_data)))
return;
border_radius = atoi (call_data);
gimage_mask_border (gimage, border_radius);
@@ -2481,7 +2735,9 @@ gimage_mask_grow_callback (GtkWidget *w,
GImage *gimage;
int grow_pixels;
gimage = (GImage *) client_data;
if (!(gimage = gimage_get_ID ((int)client_data)))
return;
grow_pixels = atoi (call_data);
gimage_mask_grow (gimage, grow_pixels);
@@ -2497,9 +2753,17 @@ gimage_mask_shrink_callback (GtkWidget *w,
GImage *gimage;
int shrink_pixels;
gimage = (GImage *) client_data;
if (!(gimage = gimage_get_ID ((int)client_data)))
return;
shrink_pixels = atoi (call_data);
gimage_mask_shrink (gimage, shrink_pixels);
gdisplays_flush ();
}

View File

@@ -77,6 +77,9 @@ void layers_merge_cmd_callback (GtkWidget *, gpointer);
void layers_flatten_cmd_callback (GtkWidget *, gpointer);
void layers_alpha_select_cmd_callback (GtkWidget *, gpointer);
void layers_mask_select_cmd_callback (GtkWidget *, gpointer);
void layers_add_alpha_channel_cmd_callback (GtkWidget *, gpointer);
void tools_default_colors_cmd_callback (GtkWidget *, gpointer);
void tools_swap_colors_cmd_callback (GtkWidget *, gpointer);
void tools_select_cmd_callback (GtkWidget *, gpointer);
void filters_repeat_cmd_callback (GtkWidget *, gpointer);
void dialogs_brushes_cmd_callback (GtkWidget *, gpointer);

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <errno.h>
@@ -36,6 +36,7 @@
#include "app_procs.h"
#include "appenv.h"
#include "canvas.h"
#include "drawable.h"
#include "datafiles.h"
#include "errors.h"
@@ -45,8 +46,13 @@
#include "gimprc.h"
#include "interface.h"
#include "menus.h"
#include "pixelarea.h"
#include "plug_in.h"
#include "tag.h"
#define FIXME
#define TILE_WIDTH 64
#define TILE_HEIGHT 64
#define SEPARATE_PROGRESS_BAR
@@ -66,7 +72,12 @@ struct _PlugInBlocked
char *proc_name;
};
#define COPY_AREA_TO_BUFFER 0
#define COPY_BUFFER_TO_AREA 1
static void plug_in_copyarea (PixelArea *a,
guchar *buf,
gint direction);
static int plug_in_write (int fd,
guint8 *buf,
gulong count);
@@ -114,6 +125,11 @@ static void plug_in_args_destroy (Argument *args,
static Argument* progress_init_invoker (Argument *args);
static Argument* progress_update_invoker (Argument *args);
static Argument* message_invoker (Argument *args);
static Argument* message_handler_get_invoker (Argument *args);
static Argument* message_handler_set_invoker (Argument *args);
static GSList *plug_in_defs = NULL;
static GSList *gimprc_proc_defs = NULL;
@@ -184,6 +200,77 @@ static ProcRecord progress_update_proc =
};
static ProcArg message_args[] =
{
{ PDB_STRING,
"message",
"Message to display in the dialog." }
};
static ProcRecord message_proc =
{
"gimp_message",
"Displays a dialog box with a message",
"Displays a dialog box with a message. Useful for status or error reporting.",
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1995-1996",
PDB_INTERNAL,
1,
message_args,
0,
NULL,
{ { message_invoker } },
};
static ProcArg message_handler_get_out_args[] =
{
{ PDB_INT32,
"handler",
"the current handler type: { MESSAGE_BOX (0), CONSOLE (1) }" }
};
static ProcRecord message_handler_get_proc =
{
"gimp_message_handler_get",
"Returns the current state of where warning messages are displayed.",
"This procedure returns the way g_message warnings are displayed. They can be shown in a dialog box or printed on the console where gimp was started.",
"Manish Singh",
"Manish Singh",
"1998",
PDB_INTERNAL,
0,
NULL,
1,
message_handler_get_out_args,
{ { message_handler_get_invoker } },
};
static ProcArg message_handler_set_args[] =
{
{ PDB_INT32,
"handler",
"the new handler type: { MESSAGE_BOX (0), CONSOLE (1) }" }
};
static ProcRecord message_handler_set_proc =
{
"gimp_message_handler_set",
"Controls where warning messages are displayed.",
"This procedure controls how g_message warnings are displayed. They can be shown in a dialog box or printed on the console where gimp was started.",
"Manish Singh",
"Manish Singh",
"1998",
PDB_INTERNAL,
1,
message_handler_set_args,
0,
NULL,
{ { message_handler_set_invoker } },
};
void
plug_in_init ()
{
@@ -198,6 +285,11 @@ plug_in_init ()
procedural_db_register (&progress_init_proc);
procedural_db_register (&progress_update_proc);
/* initialize the message box procedural db calls */
procedural_db_register (&message_proc);
procedural_db_register (&message_handler_get_proc);
procedural_db_register (&message_handler_set_proc);
/* initialize the gimp protocol library and set the read and
* write handlers.
*/
@@ -211,15 +303,16 @@ plug_in_init ()
*/
if (use_shm)
{
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * 4, IPC_CREAT | 0777);
#define PLUG_IN_C_3_cw
shm_ID = shmget (IPC_PRIVATE, TILE_WIDTH * TILE_HEIGHT * TAG_MAX_BYTES, IPC_CREAT | 0777);
if (shm_ID == -1)
g_warning ("shmget failed...disabling shared memory tile transport\n");
g_message ("shmget failed...disabling shared memory tile transport\n");
else
{
shm_addr = (guchar*) shmat (shm_ID, 0, 0);
if (shm_addr == (guchar*) -1)
{
g_warning ("shmat failed...disabling shared memory tile transport\n");
g_message ("shmat failed...disabling shared memory tile transport\n");
shm_ID = -1;
}
@@ -234,7 +327,16 @@ plug_in_init ()
datafiles_read_directories (plug_in_path, plug_in_init_file, MODE_EXECUTABLE);
/* read the pluginrc file for cached data */
sprintf (filename, "%s/pluginrc", gimp_directory ());
if (pluginrc_path)
{
if (*pluginrc_path == '/')
strcpy(filename, pluginrc_path);
else
sprintf(filename, "%s/%s", gimp_directory(), pluginrc_path);
}
else
sprintf (filename, "%s/pluginrc", gimp_directory ());
app_init_update_status("Resource configuration", filename, -1);
parse_gimprc_file (filename);
@@ -253,7 +355,8 @@ plug_in_init ()
if (plug_in_def->query)
{
write_pluginrc = TRUE;
g_print ("query plug-in: \"%s\"\n", plug_in_def->prog);
if ((be_verbose == TRUE) || (no_splash == TRUE))
g_print ("query plug-in: \"%s\"\n", plug_in_def->prog);
plug_in_query (plug_in_def->prog, plug_in_def);
}
app_init_update_status(NULL, plug_in_def->prog, nth/nplugins);
@@ -289,7 +392,8 @@ plug_in_init ()
/* write the pluginrc file if necessary */
if (write_pluginrc)
{
g_print ("writing \"%s\"\n", filename);
if ((be_verbose == TRUE) || (no_splash == TRUE))
g_print ("writing \"%s\"\n", filename);
plug_in_write_rc (filename);
}
@@ -301,9 +405,11 @@ plug_in_init ()
/* run the available extensions */
tmp = proc_defs;
g_print ("Starting extensions: ");
if ((be_verbose == TRUE) || (no_splash == TRUE))
g_print ("Starting extensions: ");
app_init_update_status("Extensions", "", 0);
nplugins = g_slist_length(tmp); nth = 0;
while (tmp)
{
proc_def = tmp->data;
@@ -313,13 +419,16 @@ plug_in_init ()
(proc_def->db_info.num_args == 0) &&
(proc_def->db_info.proc_type == PDB_EXTENSION))
{
g_print ("%s ", proc_def->db_info.name);
if ((be_verbose == TRUE) || (no_splash == TRUE))
g_print ("%s ", proc_def->db_info.name);
app_init_update_status(NULL, proc_def->db_info.name,
nth/nplugins);
plug_in_run (&proc_def->db_info, NULL, FALSE, TRUE);
}
}
g_print ("\n");
if ((be_verbose == TRUE) || (no_splash == TRUE))
g_print ("\n");
/* free up stuff */
tmp = plug_in_defs;
@@ -522,7 +631,7 @@ plug_in_file_handler (char *name,
}
proc_def->prefixes_list = plug_in_extensions_parse (proc_def->prefixes);
/* MAGICS can be proc_def->prefixes */
/* MAGICS can be proc_def->magics */
if (proc_def->magics != magics)
{
if (proc_def->magics)
@@ -636,7 +745,7 @@ plug_in_new (char *name)
path = search_in_path (plug_in_path, name);
if (!path)
{
warning ("unable to locate plug-in: \"%s\"", name);
g_message ("unable to locate plug-in: \"%s\"", name);
return NULL;
}
}
@@ -665,6 +774,7 @@ plug_in_new (char *name)
plug_in->my_write = 0;
plug_in->his_read = 0;
plug_in->his_write = 0;
plug_in->input_id = 0;
plug_in->write_buffer_index = 0;
plug_in->temp_proc_defs = NULL;
plug_in->progress = NULL;
@@ -715,7 +825,7 @@ plug_in_open (PlugIn *plug_in)
*/
if ((pipe (my_read) == -1) || (pipe (my_write) == -1))
{
warning ("unable to open pipe");
g_message ("unable to open pipe");
return 0;
}
@@ -763,7 +873,7 @@ plug_in_open (PlugIn *plug_in)
}
else if (plug_in->pid == -1)
{
warning ("unable to run plug-in: %s\n", plug_in->args[0]);
g_message ("unable to run plug-in: %s\n", plug_in->args[0]);
plug_in_destroy (plug_in);
return 0;
}
@@ -1051,11 +1161,13 @@ plug_in_repeat (int with_interface)
}
void
plug_in_set_menu_sensitivity (int base_type)
plug_in_set_menu_sensitivity (Tag t)
{
PlugInProcDef *proc_def;
GSList *tmp;
int sensitive = FALSE;
int base_type = tag_to_drawable_type (t);
tmp = proc_defs;
while (tmp)
{
@@ -1063,36 +1175,39 @@ plug_in_set_menu_sensitivity (int base_type)
tmp = tmp->next;
if (proc_def->image_types_val && proc_def->menu_path)
switch (base_type)
{
case -1:
menus_set_sensitive (proc_def->menu_path, FALSE);
break;
case RGB_GIMAGE:
menus_set_sensitive (proc_def->menu_path,
proc_def->image_types_val & RGB_IMAGE);
break;
case RGBA_GIMAGE:
menus_set_sensitive (proc_def->menu_path,
proc_def->image_types_val & RGBA_IMAGE);
break;
case GRAY_GIMAGE:
menus_set_sensitive (proc_def->menu_path,
proc_def->image_types_val & GRAY_IMAGE);
break;
case GRAYA_GIMAGE:
menus_set_sensitive (proc_def->menu_path,
proc_def->image_types_val & GRAYA_IMAGE);
break;
case INDEXED_GIMAGE:
menus_set_sensitive (proc_def->menu_path,
proc_def->image_types_val & INDEXED_IMAGE);
break;
case INDEXEDA_GIMAGE:
menus_set_sensitive (proc_def->menu_path,
proc_def->image_types_val & INDEXEDA_IMAGE);
break;
}
{
switch (base_type)
{
case -1:
sensitive = FALSE;
break;
case RGB_GIMAGE:
sensitive = proc_def->image_types_val & RGB_IMAGE;
break;
case RGBA_GIMAGE:
sensitive = proc_def->image_types_val & RGBA_IMAGE;
break;
case GRAY_GIMAGE:
sensitive = proc_def->image_types_val & GRAY_IMAGE;
break;
case GRAYA_GIMAGE:
sensitive = proc_def->image_types_val & GRAYA_IMAGE;
break;
case INDEXED_GIMAGE:
sensitive = proc_def->image_types_val & INDEXED_IMAGE;
break;
case INDEXEDA_GIMAGE:
sensitive = proc_def->image_types_val & INDEXEDA_IMAGE;
break;
}
menus_set_sensitive (proc_def->menu_path, sensitive);
if (last_plug_in && (last_plug_in == &(proc_def->db_info)))
{
menus_set_sensitive ("<Image>/Filters/Repeat last", sensitive);
menus_set_sensitive ("<Image>/Filters/Re-show last", sensitive);
}
}
}
}
@@ -1129,18 +1244,18 @@ plug_in_handle_message (WireMessage *msg)
plug_in_handle_quit ();
break;
case GP_CONFIG:
g_warning ("received a config message (should not happen)\n");
g_message ("plug_in_handle_message(): received a config message (should not happen)\n");
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_REQ:
plug_in_handle_tile_req (msg->data);
break;
case GP_TILE_ACK:
g_warning ("received a config message (should not happen)\n");
g_message ("plug_in_handle_message(): received a config message (should not happen)\n");
plug_in_close (current_plug_in, TRUE);
break;
case GP_TILE_DATA:
g_warning ("received a config message (should not happen)\n");
g_message ("plug_in_handle_message(): received a config message (should not happen)\n");
plug_in_close (current_plug_in, TRUE);
break;
case GP_PROC_RUN:
@@ -1151,7 +1266,7 @@ plug_in_handle_message (WireMessage *msg)
plug_in_close (current_plug_in, FALSE);
break;
case GP_TEMP_PROC_RUN:
g_warning ("received a temp proc run message (should not happen)\n");
g_message ("plug_in_handle_message(): received a temp proc run message (should not happen)\n");
plug_in_close (current_plug_in, TRUE);
break;
case GP_TEMP_PROC_RETURN:
@@ -1182,8 +1297,13 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
GPTileData tile_data;
GPTileData *tile_info;
WireMessage msg;
TileManager *tm;
Tile *tile;
PixelArea a;
Canvas *canvas;
GimpDrawable *drawable;
gint ntile_cols, ntile_rows;
gint ewidth, eheight;
gint i, j;
gint x, y;
if (tile_req->drawable_ID == -1)
{
@@ -1198,60 +1318,85 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
if (!gp_tile_data_write (current_writefd, &tile_data))
{
g_warning ("plug_in_handle_tile_req: ERROR");
g_message ("plug_in_handle_tile_req: ERROR");
plug_in_close (current_plug_in, TRUE);
return;
}
if (!wire_read_msg (current_readfd, &msg))
{
g_warning ("plug_in_handle_tile_req: ERROR");
g_message ("plug_in_handle_tile_req: ERROR");
plug_in_close (current_plug_in, TRUE);
return;
}
if (msg.type != GP_TILE_DATA)
{
g_warning ("expected tile data and received: %d\n", msg.type);
g_message ("expected tile data and received: %d\n", msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
tile_info = msg.data;
drawable = drawable_get_ID (tile_info->drawable_ID);
if (tile_info->shadow)
tm = drawable_shadow (drawable_get_ID (tile_info->drawable_ID));
canvas = drawable_shadow (drawable);
else
tm = drawable_data (drawable_get_ID (tile_info->drawable_ID));
canvas = drawable_data (drawable);
if (!tm)
if (!canvas)
{
g_warning ("plug-in requested invalid drawable (killing)\n");
g_message ("plug-in requested invalid drawable (killing)\n");
plug_in_close (current_plug_in, TRUE);
return;
}
tile = tile_manager_get (tm, tile_info->tile_num, 0);
if (!tile)
/* Find the upper left corner (x,y) of the plugins tile with index tile_num. */
ntile_cols = ( drawable_width (drawable) + TILE_WIDTH - 1 ) / TILE_WIDTH;
ntile_rows = ( drawable_height (drawable) + TILE_HEIGHT - 1 ) / TILE_HEIGHT;
i = tile_info->tile_num % ntile_cols;
j = tile_info->tile_num / ntile_cols;
x = TILE_WIDTH * i;
y = TILE_HEIGHT * j;
/*printf ("Get tilenum: %d, (i,j)=(%d,%d) (x,y)=(%d,%d) (rows,cols)=(%d,%d)\n",
tile_info->tile_num, i, j, x, y, ntile_rows, ntile_cols);*/
/* Make sure there is some valid canvas data there on the gimp side */
canvas_portion_refrw (canvas, x, y);
if (!canvas_portion_data( canvas, x, y))
{
g_warning ("plug-in requested invalid tile (killing)\n");
g_message ("plug-in requested invalid tile (killing)\n");
plug_in_close (current_plug_in, TRUE);
canvas_portion_unref (canvas, x, y);
return;
}
/* Now find the plugins tile ewidth and eheight */
if (i == (ntile_cols - 1))
ewidth = drawable_width(drawable) - ((ntile_cols - 1) * TILE_WIDTH);
else
ewidth = TILE_WIDTH;
tile_ref (tile);
if (tile_data.use_shm)
memcpy (tile->data, shm_addr, tile_size (tile));
else
memcpy (tile->data, tile_info->data, tile_size (tile));
tile_unref (tile, TRUE);
if (j == (ntile_rows - 1))
eheight = drawable_height(drawable) - ((ntile_rows - 1) * TILE_HEIGHT);
else
eheight = TILE_HEIGHT;
/* Now copy the data from plugins tile to the gimp's canvas */
pixelarea_init (&a, canvas, x, y, ewidth, eheight, TRUE);
if (tile_data.use_shm)
plug_in_copyarea (&a, shm_addr, COPY_BUFFER_TO_AREA); /* shm to gimp */
else
plug_in_copyarea (&a, tile_info->data, COPY_BUFFER_TO_AREA); /* pipe buffer to gimp */
canvas_portion_unref (canvas, x, y);
wire_destroy (&msg);
if (!gp_tile_ack_write (current_writefd))
{
g_warning ("plug_in_handle_tile_req: ERROR");
g_message ("plug_in_handle_tile_req: ERROR");
plug_in_close (current_plug_in, TRUE);
return;
}
@@ -1259,59 +1404,84 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
else
{
if (tile_req->shadow)
tm = drawable_shadow (drawable_get_ID (tile_req->drawable_ID));
canvas = drawable_shadow (drawable_get_ID (tile_req->drawable_ID));
else
tm = drawable_data (drawable_get_ID (tile_req->drawable_ID));
if (!tm)
canvas = drawable_data (drawable_get_ID (tile_req->drawable_ID));
if (!canvas)
{
g_warning ("plug-in requested invalid drawable (killing)\n");
g_message ("plug-in requested invalid drawable (killing)\n");
plug_in_close (current_plug_in, TRUE);
return;
}
tile = tile_manager_get (tm, tile_req->tile_num, 0);
if (!tile)
drawable = drawable_get_ID (tile_req->drawable_ID);
/* Find the lower left corner (x,y) of the plugins tile with index tile_num. */
ntile_cols = ( drawable_width (drawable) + TILE_WIDTH - 1 ) / TILE_WIDTH;
ntile_rows = ( drawable_height (drawable) + TILE_HEIGHT - 1 ) / TILE_HEIGHT;
i = tile_req->tile_num % ntile_cols;
j = tile_req->tile_num / ntile_cols;
x = TILE_WIDTH * i;
y = TILE_HEIGHT * j;
/*printf ("Put tilenum: %d, (i,j)=(%d,%d) (x,y)=(%d,%d) (rows,cols)=(%d,%d)\n",
tile_req->tile_num, i, j, x, y, ntile_rows, ntile_cols);*/
canvas_portion_refro (canvas, x, y);
if (!canvas_portion_data( canvas, x, y))
{
g_warning ("plug-in requested invalid tile (killing)\n");
g_message ("plug-in requested invalid tile (killing)\n");
plug_in_close (current_plug_in, TRUE);
canvas_portion_unref (canvas, x, y);
return;
}
tile_data.drawable_ID = tile_req->drawable_ID;
tile_data.tile_num = tile_req->tile_num;
tile_data.shadow = tile_req->shadow;
tile_data.bpp = tile->bpp;
tile_data.width = tile->ewidth;
tile_data.height = tile->eheight;
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
tile_ref (tile);
if (tile_data.use_shm)
memcpy (shm_addr, tile->data, tile_size (tile));
tile_data.bpp = tag_bytes (canvas_tag (canvas));
/* Find the plugins notion of ewidth and eheight of the tile */
if (i == (ntile_cols - 1))
ewidth = drawable_width(drawable) - ((ntile_cols - 1) * TILE_WIDTH);
else
tile_data.data = tile->data;
ewidth = TILE_WIDTH;
if (j == (ntile_rows - 1))
eheight = drawable_height(drawable) - ((ntile_rows - 1) * TILE_HEIGHT);
else
eheight = TILE_HEIGHT;
tile_data.height = eheight;
tile_data.width = ewidth;
tile_data.use_shm = (shm_ID == -1) ? FALSE : TRUE;
/*printf(" ewidth = %d, eheight = %d \n", ewidth, eheight);*/
pixelarea_init (&a, canvas, x, y, ewidth, eheight, FALSE);
if (tile_data.use_shm)
plug_in_copyarea (&a, shm_addr, COPY_AREA_TO_BUFFER); /* gimp to shm*/
else
plug_in_copyarea (&a, tile_data.data, COPY_AREA_TO_BUFFER); /* gimp to pipe buffer */
canvas_portion_unref (canvas, x, y);
if (!gp_tile_data_write (current_writefd, &tile_data))
{
g_warning ("plug_in_handle_tile_req: ERROR");
g_message ("plug_in_handle_tile_req: ERROR");
plug_in_close (current_plug_in, TRUE);
return;
}
tile_unref (tile, FALSE);
if (!wire_read_msg (current_readfd, &msg))
{
g_warning ("plug_in_handle_tile_req: ERROR");
g_message ("plug_in_handle_tile_req: ERROR");
plug_in_close (current_plug_in, TRUE);
return;
}
if (msg.type != GP_TILE_ACK)
{
g_warning ("expected tile ack and received: %d\n", msg.type);
g_message ("expected tile ack and received: %d\n", msg.type);
plug_in_close (current_plug_in, TRUE);
return;
}
@@ -1320,6 +1490,56 @@ plug_in_handle_tile_req (GPTileReq *tile_req)
}
}
static void
plug_in_copyarea (PixelArea *a, guchar *buf, gint direction)
{
void *pag;
Tag a_tag = pixelarea_tag (a);
gint bpp = tag_bytes (a_tag);
guchar *d, *s;
gint d_rowstride, s_rowstride;
gint width, height;
for (pag = pixelarea_register (1, a) ;
pag != NULL;
pag = pixelarea_process (pag))
{
height = pixelarea_height (a);
width = pixelarea_width (a);
if (direction == COPY_AREA_TO_BUFFER)
{
/* copy from a to buf */
s = pixelarea_data (a);
s_rowstride = pixelarea_rowstride (a);
d = buf;
d_rowstride = width * bpp;
/* printf("putting data : s_rowstride: %d, d_rowstride: %d\n",
s_rowstride, d_rowstride);
printf("pixelarea width : %d, height: %d\n", width, height);*/
}
else
{
/* copy from buf to a */
s = buf;
s_rowstride = width * bpp;
d = pixelarea_data (a);
d_rowstride = pixelarea_rowstride (a);
/* printf("getting data : s_rowstride: %d, d_rowstride: %d\n",
s_rowstride, d_rowstride);
printf("pixelarea width : %d, height: %d\n", width, height);*/
}
while ( height --)
{
memcpy(d, s, width * bpp);
d += d_rowstride;
s += s_rowstride;
}
}
}
static void
plug_in_handle_proc_run (GPProcRun *proc_run)
{
@@ -1335,7 +1555,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!proc_rec)
{
/* THIS IS PROBABLY NOT CORRECT -josh */
g_warning ("PDB lookup failed on %s\n", proc_run->name);
g_message ("PDB lookup failed on %s\n", proc_run->name);
plug_in_args_destroy (args, proc_run->nparams, FALSE);
return;
}
@@ -1359,7 +1579,7 @@ plug_in_handle_proc_run (GPProcRun *proc_run)
if (!gp_proc_return_write (current_writefd, &proc_return))
{
g_warning ("plug_in_handle_proc_run: ERROR");
g_message ("plug_in_handle_proc_run: ERROR");
plug_in_close (current_plug_in, TRUE);
return;
}
@@ -1403,7 +1623,7 @@ plug_in_handle_proc_return (GPProcReturn *proc_return)
plug_in_push (blocked->plug_in);
if (!gp_proc_return_write (current_writefd, proc_return))
{
g_warning ("plug_in_handle_proc_run: ERROR");
g_message ("plug_in_handle_proc_run: ERROR");
plug_in_close (current_plug_in, TRUE);
return;
}
@@ -1442,7 +1662,7 @@ plug_in_handle_proc_install (GPProcInstall *proc_install)
if ((proc_install->nparams < 1) ||
(proc_install->params[0].type != PDB_INT32))
{
g_warning ("plug-in \"%s\" attempted to install procedure \"%s\" which "
g_message ("plug-in \"%s\" attempted to install procedure \"%s\" which "
"does not take the standard plug-in args",
current_plug_in->args[0], proc_install->name);
return;
@@ -1455,7 +1675,7 @@ plug_in_handle_proc_install (GPProcInstall *proc_install)
(proc_install->params[1].type != PDB_IMAGE) ||
(proc_install->params[2].type != PDB_DRAWABLE))
{
g_warning ("plug-in \"%s\" attempted to install procedure \"%s\" which "
g_message ("plug-in \"%s\" attempted to install procedure \"%s\" which "
"does not take the standard plug-in args",
current_plug_in->args[0], proc_install->name);
return;
@@ -1468,7 +1688,7 @@ plug_in_handle_proc_install (GPProcInstall *proc_install)
(proc_install->params[1].type != PDB_STRING) ||
(proc_install->params[2].type != PDB_STRING))
{
g_warning ("plug-in \"%s\" attempted to install procedure \"%s\" which "
g_message ("plug-in \"%s\" attempted to install procedure \"%s\" which "
"does not take the standard plug-in args",
current_plug_in->args[0], proc_install->name);
return;
@@ -1483,7 +1703,7 @@ plug_in_handle_proc_install (GPProcInstall *proc_install)
(proc_install->params[3].type != PDB_STRING) ||
(proc_install->params[4].type != PDB_STRING))
{
g_warning ("plug-in \"%s\" attempted to install procedure \"%s\" which "
g_message ("plug-in \"%s\" attempted to install procedure \"%s\" which "
"does not take the standard plug-in args",
current_plug_in->args[0], proc_install->name);
return;
@@ -1491,7 +1711,7 @@ plug_in_handle_proc_install (GPProcInstall *proc_install)
}
else
{
g_warning ("plug-in \"%s\" attempted to install procedure \"%s\" in "
g_message ("plug-in \"%s\" attempted to install procedure \"%s\" in "
"an invalid menu location. Use either \"<Toolbox>\", \"<Image>\", "
"\"<Load>\", or \"<Save>\".",
current_plug_in->args[0], proc_install->name);
@@ -1511,7 +1731,7 @@ plug_in_handle_proc_install (GPProcInstall *proc_install)
proc_install->params[i].type == PDB_STRINGARRAY) &&
proc_install->params[i-1].type != PDB_INT32)
{
g_warning ("plug_in \"%s\" attempted to install procedure \"%s\" "
g_message ("plug_in \"%s\" attempted to install procedure \"%s\" "
"which fails to comply with the array parameter "
"passing standard. Argument %d is noncompliant.",
current_plug_in->args[0], proc_install->name, i);
@@ -1536,7 +1756,7 @@ plug_in_handle_proc_install (GPProcInstall *proc_install)
break;
case PDB_TEMPORARY:
prog = g_strdup ("none");
prog = "none";
tmp = current_plug_in->temp_proc_defs;
break;
@@ -1628,7 +1848,7 @@ plug_in_handle_proc_install (GPProcInstall *proc_install)
/* If there is a menu path specified, create a menu entry */
if (proc_install->menu_path)
{
entry.path = g_strdup (proc_install->menu_path);
entry.path = proc_install->menu_path;
entry.accelerator = NULL;
entry.callback = plug_in_callback;
entry.callback_data = proc;
@@ -1967,9 +2187,8 @@ plug_in_query (char *filename,
}
plug_in_pop ();
plug_in_destroy (plug_in);
}
plug_in_destroy (plug_in);
}
}
@@ -2093,7 +2312,7 @@ plug_in_callback (GtkWidget *widget,
}
else
{
g_warning ("Uh-oh, no active gdisplay for the plug-in!");
g_message ("Uh-oh, no active gdisplay for the plug-in!");
g_free (args);
return;
}
@@ -2112,7 +2331,7 @@ plug_in_callback (GtkWidget *widget,
}
else
{
g_warning ("Uh-oh, no active gdisplay for the temporary procedure!");
g_message ("Uh-oh, no active gdisplay for the temporary procedure!");
g_free (args);
return;
}
@@ -2425,7 +2644,7 @@ plug_in_params_to_args (GPParam *params,
colorarray[2] = params[i].data.d_color.blue;
break;
case PDB_REGION:
g_warning ("the \"region\" arg type is not currently supported");
g_message ("the \"region\" arg type is not currently supported");
break;
case PDB_DISPLAY:
args[i].value.pdb_int = params[i].data.d_display;
@@ -2583,7 +2802,7 @@ plug_in_args_to_params (Argument *args,
}
break;
case PDB_REGION:
g_warning ("the \"region\" arg type is not currently supported");
g_message ("the \"region\" arg type is not currently supported");
break;
case PDB_DISPLAY:
params[i].data.d_display = args[i].value.pdb_int;
@@ -2667,7 +2886,7 @@ plug_in_params_destroy (GPParam *params,
case PDB_COLOR:
break;
case PDB_REGION:
g_warning ("the \"region\" arg type is not currently supported");
g_message ("the \"region\" arg type is not currently supported");
break;
case PDB_DISPLAY:
case PDB_IMAGE:
@@ -2741,7 +2960,7 @@ plug_in_args_destroy (Argument *args,
g_free (args[i].value.pdb_pointer);
break;
case PDB_REGION:
g_warning ("the \"region\" arg type is not currently supported");
g_message ("the \"region\" arg type is not currently supported");
break;
case PDB_DISPLAY:
case PDB_IMAGE:
@@ -2862,6 +3081,7 @@ plug_in_progress_init (PlugIn *plug_in,
if (!plug_in->progress)
{
plug_in->progress = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (plug_in->progress), "plug_in_progress", "Gimp");
gtk_window_set_title (GTK_WINDOW (plug_in->progress), prune_filename (plug_in->args[0]));
gtk_widget_set_uposition (plug_in->progress, progress_x, progress_y);
gtk_signal_connect (GTK_OBJECT (plug_in->progress), "destroy",
@@ -2952,3 +3172,34 @@ progress_update_invoker (Argument *args)
return procedural_db_return_args (&progress_update_proc, success);
}
static Argument*
message_invoker (Argument *args)
{
g_message (args[0].value.pdb_pointer, NULL, NULL);
return procedural_db_return_args (&message_proc, TRUE);
}
static Argument*
message_handler_get_invoker (Argument *args)
{
Argument *return_args;
return_args = procedural_db_return_args (&message_handler_get_proc, TRUE);
return_args[1].value.pdb_int = message_handler;
return return_args;
}
static Argument*
message_handler_set_invoker (Argument *args)
{
int success = TRUE;
if ((args[0].value.pdb_int >= MESSAGE_BOX) &&
(args[0].value.pdb_int <= CONSOLE))
message_handler = args[0].value.pdb_int;
else
success = FALSE;
return procedural_db_return_args (&message_handler_set_proc, success);
}

View File

@@ -13,19 +13,22 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include "appenv.h"
#include "airbrush.h"
#include "brushes.h"
#include "canvas.h"
#include "drawable.h"
#include "errors.h"
#include "gdisplay.h"
#include "paint_funcs.h"
#include "paint_core.h"
#include "gdisplay.h" /* for airbrush_time_out() */
#include "gimage.h"
#include "paint_core_16.h"
#include "paint_funcs_area.h"
#include "palette.h"
#include "airbrush.h"
#include "selection.h"
#include "pixelarea.h"
#include "pixelrow.h"
#include "tools.h"
typedef struct _AirbrushTimeout AirbrushTimeout;
@@ -137,7 +140,7 @@ create_airbrush_options (void)
return options;
}
void *
static void *
airbrush_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
int state)
@@ -231,39 +234,36 @@ airbrush_time_out (gpointer client_data)
}
static void
airbrush_motion (PaintCore *paint_core,
GimpDrawable *drawable,
double pressure)
static void
airbrush_motion (
PaintCore * paint_core,
GimpDrawable * drawable,
double pressure
)
{
GImage *gimage;
TempBuf * area;
unsigned char col[MAX_CHANNELS];
Canvas * painthit;
PixelArea a;
/* Get the working canvas */
painthit = paint_core_16_area (paint_core, drawable);
pixelarea_init (&a, painthit, 0, 0, 0, 0, TRUE);
if (!drawable)
return;
/* construct the paint hit */
{
COLOR16_NEW (paint, canvas_tag (painthit));
if (! (gimage = drawable_gimage (drawable)))
return;
gimage_get_foreground (gimage, drawable, col);
if (! (area = paint_core_get_paint_area (paint_core, drawable)))
return;
/* color the pixels */
col[area->bytes - 1] = OPAQUE;
/* color the pixels */
color_pixels (temp_buf_data (area), col,
area->width * area->height, area->bytes);
/* paste the newly painted area to the image */
paint_core_paste_canvas (paint_core, drawable,
(int) (pressure * 2.55),
(int) (get_brush_opacity () * 255),
get_brush_paint_mode (),
SOFT, CONSTANT);
COLOR16_INIT (paint);
palette_get_foreground (&paint);
color_area (&a, &paint);
}
/* apply it to the image */
paint_core_16_area_paste (paint_core, drawable,
(gfloat) pressure / 100.0,
(gfloat) get_brush_opacity (),
SOFT,
CONSTANT,
get_brush_paint_mode ());
}

View File

@@ -13,20 +13,17 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __AIRBRUSH_H__
#define __AIRBRUSH_H__
#include "tools.h"
#include "paint_core.h"
#include "procedural_db.h"
struct _ProcRecord;
struct _tool;
void * airbrush_paint_func (PaintCore *, GimpDrawable *, int);
Tool * tools_new_airbrush (void);
void tools_free_airbrush (Tool *);
struct _tool * tools_new_airbrush (void);
void tools_free_airbrush (struct _tool *);
/* Procedure definition and marshalling function */
extern ProcRecord airbrush_proc;
extern struct _ProcRecord airbrush_proc;
#endif /* __AIRBRUSH_H__ */

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <signal.h>
#include <stdio.h>
@@ -22,6 +22,10 @@
#include <sys/param.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include "libgimp/gimpfeatures.h"
#include "appenv.h"
#include "app_procs.h"
#include "batch.h"
@@ -42,27 +46,44 @@
#include "layers_dialog.h"
#include "levels.h"
#include "menus.h"
#include "paint_funcs.h"
#include "paint_funcs_area.h"
#include "palette.h"
#include "patterns.h"
#include "plug_in.h"
#include "procedural_db.h"
#include "temp_buf.h"
#include "tile_swap.h"
#include "tips_dialog.h"
#include "tools.h"
#include "undo.h"
#include "xcf.h"
#include <gtk/gtk.h>
#include "errors.h"
#include "config.h"
#define LOGO_WIDTH_MIN 350
#define LOGO_HEIGHT_MIN 110
#define NAME "The GIMP"
#define BROUGHT "brought to you by"
#define AUTHORS "Spencer Kimball and Peter Mattis"
#define SHOW_NEVER 0
#define SHOW_LATER 1
#define SHOW_NOW 2
/* Function prototype for affirmation dialog when exiting application */
static void app_exit_finish (void);
static void really_quit_dialog (void);
static Argument* quit_invoker (Argument *args);
static void make_initialization_status_window(void);
static void destroy_initialization_status_window(void);
static int splash_logo_load (GtkWidget *window);
static int splash_logo_load_size (GtkWidget *window);
static void splash_logo_draw (GtkWidget *widget);
static void splash_text_draw (GtkWidget *widget);
static void splash_logo_expose (GtkWidget *widget);
static gint is_app_exit_finish_done = FALSE;
static ProcArg quit_args[] =
{
{ PDB_INT32,
@@ -104,6 +125,185 @@ gimp_init (int gimp_argc,
}
batch_init ();
/* Handle showing dialogs with gdk_quit_adds here */
if (!no_interface && show_tips)
tips_dialog_create ();
}
static GtkWidget *logo_area = NULL;
static GdkPixmap *logo_pixmap = NULL;
static int logo_width = 0;
static int logo_height = 0;
static int logo_area_width = 0;
static int logo_area_height = 0;
static int show_logo = SHOW_NEVER;
static guint max_label_length = MAXPATHLEN;
static int
splash_logo_load_size (GtkWidget *window)
{
char buf[1024];
FILE *fp;
if (logo_pixmap)
return TRUE;
sprintf (buf, "%s/gimp_splash.ppm", DATADIR);
fp = fopen (buf, "r");
if (!fp)
return 0;
fgets (buf, 1024, fp);
if (strcmp (buf, "P6\n") != 0)
{
fclose (fp);
return 0;
}
fgets (buf, 1024, fp);
fgets (buf, 1024, fp);
sscanf (buf, "%d %d", &logo_width, &logo_height);
fclose (fp);
return TRUE;
}
static int
splash_logo_load (GtkWidget *window)
{
GtkWidget *preview;
GdkGC *gc;
char buf[1024];
unsigned char *pixelrow;
FILE *fp;
int count;
int i;
if (logo_pixmap)
return TRUE;
sprintf (buf, "%s/gimp_splash.ppm", DATADIR);
fp = fopen (buf, "r");
if (!fp)
return 0;
fgets (buf, 1024, fp);
if (strcmp (buf, "P6\n") != 0)
{
fclose (fp);
return 0;
}
fgets (buf, 1024, fp);
fgets (buf, 1024, fp);
sscanf (buf, "%d %d", &logo_width, &logo_height);
fgets (buf, 1024, fp);
if (strcmp (buf, "255\n") != 0)
{
fclose (fp);
return 0;
}
preview = gtk_preview_new (GTK_PREVIEW_COLOR);
gtk_preview_size (GTK_PREVIEW (preview), logo_width, logo_height);
pixelrow = g_new (guchar, logo_width * 3);
for (i = 0; i < logo_height; i++)
{
count = fread (pixelrow, sizeof (unsigned char), logo_width * 3, fp);
if (count != (logo_width * 3))
{
gtk_widget_destroy (preview);
g_free (pixelrow);
fclose (fp);
return 0;
}
gtk_preview_draw_row (GTK_PREVIEW (preview), pixelrow, 0, i, logo_width);
}
gtk_widget_realize (window);
logo_pixmap = gdk_pixmap_new (window->window, logo_width, logo_height,
gtk_preview_get_visual ()->depth);
gc = gdk_gc_new (logo_pixmap);
gtk_preview_put (GTK_PREVIEW (preview),
logo_pixmap, gc,
0, 0, 0, 0, logo_width, logo_height);
gdk_gc_destroy (gc);
gtk_widget_unref (preview);
g_free (pixelrow);
fclose (fp);
return TRUE;
}
static void
splash_text_draw (GtkWidget *widget)
{
GdkFont *font = NULL;
font = gdk_font_load ("-Adobe-Helvetica-Bold-R-Normal--*-140-*-*-*-*-*-*");
gdk_draw_string (widget->window,
font,
widget->style->fg_gc[GTK_STATE_NORMAL],
((logo_area_width - gdk_string_width (font, NAME)) / 2),
(0.25 * logo_area_height),
NAME);
font = gdk_font_load ("-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*");
gdk_draw_string (widget->window,
font,
widget->style->fg_gc[GTK_STATE_NORMAL],
((logo_area_width - gdk_string_width (font, GIMP_VERSION)) / 2),
(0.45 * logo_area_height),
GIMP_VERSION);
gdk_draw_string (widget->window,
font,
widget->style->fg_gc[GTK_STATE_NORMAL],
((logo_area_width - gdk_string_width (font, BROUGHT)) / 2),
(0.65 * logo_area_height),
BROUGHT);
gdk_draw_string (widget->window,
font,
widget->style->fg_gc[GTK_STATE_NORMAL],
((logo_area_width - gdk_string_width (font, AUTHORS)) / 2),
(0.80 * logo_area_height),
AUTHORS);
/*
* This is a hack: we try to compute a good guess for the maximum number
* of charcters that will fit into the splash-screen using the given font
*/
max_label_length = (float)strlen (AUTHORS) *
( (float)logo_area_width / (float)gdk_string_width (font, AUTHORS) );
}
static void
splash_logo_draw (GtkWidget *widget)
{
gdk_draw_pixmap (widget->window,
widget->style->black_gc,
logo_pixmap,
0, 0,
((logo_area_width - logo_width) / 2), ((logo_area_height - logo_height) / 2),
logo_width, logo_height);
}
static void
splash_logo_expose (GtkWidget *widget)
{
switch (show_logo) {
case SHOW_NEVER:
case SHOW_LATER:
splash_text_draw (widget);
break;
case SHOW_NOW:
splash_logo_draw (widget);
}
}
static GtkWidget *win_initstatus = NULL;
@@ -118,48 +318,75 @@ destroy_initialization_status_window(void)
if(win_initstatus)
{
gtk_widget_destroy(win_initstatus);
win_initstatus = label1 = label2 = pbar = NULL;
if (logo_pixmap != NULL)
gdk_pixmap_unref(logo_pixmap);
win_initstatus = label1 = label2 = pbar = logo_area = NULL;
logo_pixmap = NULL;
gtk_idle_remove(idle_tag);
}
}
static void my_idle_proc(void)
{
/* Do nothing. This is needed to stop the GIMP
from blocking in gtk_main_iteration() */
}
static void
make_initialization_status_window(void)
{
if(no_interface == FALSE)
if (no_interface == FALSE)
{
GtkWidget *vbox;
if (no_splash == FALSE)
{
GtkWidget *vbox;
win_initstatus = gtk_window_new(GTK_WINDOW_DIALOG);
gtk_window_set_title(GTK_WINDOW(win_initstatus),
"GIMP Startup");
win_initstatus = gtk_window_new(GTK_WINDOW_DIALOG);
gtk_signal_connect (GTK_OBJECT (win_initstatus), "delete_event",
GTK_SIGNAL_FUNC (gtk_true),
NULL);
gtk_window_set_wmclass (GTK_WINDOW(win_initstatus), "gimp_startup", "Gimp");
gtk_window_set_title(GTK_WINDOW(win_initstatus),
"GIMP Startup");
vbox = gtk_vbox_new(TRUE, 5);
gtk_container_add(GTK_CONTAINER(win_initstatus), vbox);
if (no_splash_image == FALSE && splash_logo_load_size (win_initstatus))
{
show_logo = SHOW_LATER;
}
vbox = gtk_vbox_new(FALSE, 4);
gtk_container_add(GTK_CONTAINER(win_initstatus), vbox);
gtk_widget_push_visual (gtk_preview_get_visual ());
gtk_widget_push_colormap (gtk_preview_get_cmap ());
logo_area = gtk_drawing_area_new ();
gtk_widget_pop_colormap ();
gtk_widget_pop_visual ();
gtk_signal_connect (GTK_OBJECT (logo_area), "expose_event",
(GtkSignalFunc) splash_logo_expose, NULL);
logo_area_width = ( logo_width > LOGO_WIDTH_MIN ) ? logo_width : LOGO_WIDTH_MIN;
logo_area_height = ( logo_height > LOGO_HEIGHT_MIN ) ? logo_height : LOGO_HEIGHT_MIN;
gtk_drawing_area_size (GTK_DRAWING_AREA (logo_area), logo_area_width, logo_area_height);
gtk_box_pack_start_defaults(GTK_BOX(vbox), logo_area);
label1 = gtk_label_new("");
gtk_box_pack_start_defaults(GTK_BOX(vbox), label1);
label2 = gtk_label_new("");
gtk_box_pack_start_defaults(GTK_BOX(vbox), label2);
label1 = gtk_label_new("");
gtk_box_pack_start_defaults(GTK_BOX(vbox), label1);
label2 = gtk_label_new("");
gtk_box_pack_start_defaults(GTK_BOX(vbox), label2);
pbar = gtk_progress_bar_new();
gtk_box_pack_start_defaults(GTK_BOX(vbox), pbar);
pbar = gtk_progress_bar_new();
gtk_box_pack_start_defaults(GTK_BOX(vbox), pbar);
gtk_widget_show(vbox);
gtk_widget_show (logo_area);
gtk_widget_show(label1);
gtk_widget_show(label2);
gtk_widget_show(pbar);
gtk_widget_show(vbox);
gtk_widget_show(label1);
gtk_widget_show(label2);
gtk_widget_show(pbar);
gtk_window_position(GTK_WINDOW(win_initstatus),
GTK_WIN_POS_CENTER);
gtk_window_position(GTK_WINDOW(win_initstatus),
GTK_WIN_POS_CENTER);
gtk_widget_show(win_initstatus);
gtk_widget_show(win_initstatus);
gtk_window_set_policy (GTK_WINDOW (win_initstatus), FALSE, TRUE, FALSE);
}
}
}
@@ -168,8 +395,9 @@ app_init_update_status(char *label1val,
char *label2val,
float pct_progress)
{
if(no_interface == FALSE
&& win_initstatus)
char *temp;
if(no_interface == FALSE && no_splash == FALSE && win_initstatus)
{
GdkRectangle area = {0, 0, -1, -1};
if(label1val
@@ -180,6 +408,14 @@ app_init_update_status(char *label1val,
if(label2val
&& strcmp(label2val, GTK_LABEL(label2)->label))
{
while ( strlen (label2val) > max_label_length )
{
temp = strchr (label2val, '/');
if (temp == NULL) /* for sanity */
break;
temp++;
label2val = temp;
}
gtk_label_set(GTK_LABEL(label2), label2val);
}
if(pct_progress >= 0
@@ -188,7 +424,7 @@ app_init_update_status(char *label1val,
gtk_progress_bar_update(GTK_PROGRESS_BAR(pbar), pct_progress);
}
gtk_widget_draw(win_initstatus, &area);
idle_tag = gtk_idle_add(my_idle_proc, NULL);
idle_tag = gtk_idle_add((GtkFunction) gtk_true, NULL);
gtk_main_iteration();
gtk_idle_remove(idle_tag);
}
@@ -198,14 +434,28 @@ app_init_update_status(char *label1val,
#define RESET_BAR()
void
app_init ()
app_init (void)
{
char filename[MAXPATHLEN];
char *gimp_dir;
char *path;
make_initialization_status_window();
gimp_dir = gimp_directory ();
if (gimp_dir[0] != '\000')
{
sprintf (filename, "%s/gtkrc", gimp_dir);
if ((be_verbose == TRUE) || (no_splash == TRUE))
g_print ("parsing \"%s\"\n", filename);
gtk_rc_parse (filename);
}
make_initialization_status_window();
if (no_interface == FALSE && no_splash == FALSE && win_initstatus) {
splash_text_draw (logo_area);
}
/*
* Initialize the procedural database
* We need to do this first because any of the init
@@ -217,33 +467,33 @@ app_init ()
RESET_BAR();
procedural_db_register (&quit_proc);
gimp_dir = gimp_directory ();
if (gimp_dir[0] != '\000')
RESET_BAR();
parse_gimprc (); /* parse the local GIMP configuration file */
/* Now we are ready to draw the splash-screen-image to the start-up window */
if (no_interface == FALSE)
{
sprintf (filename, "%s/gtkrc", gimp_dir);
g_print ("parsing \"%s\"\n", filename);
app_init_update_status("Resource configuration", filename, -1);
gtk_rc_parse (filename);
if (no_splash_image == FALSE && show_logo && splash_logo_load (win_initstatus)) {
show_logo = SHOW_NOW;
splash_logo_draw (logo_area);
}
}
RESET_BAR();
file_ops_pre_init (); /* pre-initialize the file types */
RESET_BAR();
xcf_init (); /* initialize the xcf file format routines */
RESET_BAR();
parse_gimprc (); /* parse the local GIMP configuration file */
if (no_data == FALSE)
{
RESET_BAR();
brushes_init (); /* initialize the list of gimp brushes */
RESET_BAR();
patterns_init (); /* initialize the list of gimp patterns */
RESET_BAR();
palettes_init (); /* initialize the list of gimp palettes */
RESET_BAR();
gradients_init (); /* initialize the list of gimp gradients */
}
RESET_BAR();
app_init_update_status ("Looking for data files", "Brushes", 0.00);
brushes_init (no_data); /* initialize the list of gimp brushes */
app_init_update_status (NULL, "Patterns", 0.25);
patterns_init (no_data); /* initialize the list of gimp patterns */
app_init_update_status (NULL, "Palettes", 0.50);
palettes_init (no_data); /* initialize the list of gimp palettes */
app_init_update_status (NULL, "Gradients", 0.75);
gradients_init (no_data); /* initialize the list of gimp gradients */
app_init_update_status (NULL, NULL, 1.00);
plug_in_init (); /* initialize the plug in structures */
RESET_BAR();
file_ops_post_init (); /* post-initialize the file types */
@@ -262,30 +512,43 @@ app_init ()
if (no_interface == FALSE)
{
get_standard_colormaps ();
/* this has to be done after the colormaps are setup */
palette_set_default_colors ();
create_toolbox ();
display_u8_init();
gximage_init ();
render_setup (transparency_type, transparency_size);
tools_options_dialog_new ();
tools_select (RECT_SELECT);
if (show_tips)
tips_dialog_create ();
message_handler = MESSAGE_BOX;
}
color_transfer_init ();
get_active_brush ();
get_active_pattern ();
paint_funcs_setup ();
paint_funcs_area_setup ();
}
static void
app_exit_finish ()
int
app_exit_finish_done (void)
{
return is_app_exit_finish_done;
}
void
app_exit_finish (void)
{
if (app_exit_finish_done ())
return;
is_app_exit_finish_done = TRUE;
message_handler = CONSOLE;
lc_dialog_free ();
gdisplays_delete ();
global_edit_free ();
named_buffers_free ();
swapping_free ();
brushes_free ();
patterns_free ();
palettes_free ();
@@ -296,7 +559,7 @@ app_exit_finish ()
brush_select_dialog_free ();
pattern_select_dialog_free ();
palette_free ();
paint_funcs_free ();
paint_funcs_area_free ();
procedural_db_free ();
plug_in_kill ();
menus_quit ();
@@ -309,8 +572,8 @@ app_exit_finish ()
render_free ();
tools_options_dialog_free ();
}
gtk_exit (0);
/* gtk_exit (0); */
gtk_main_quit();
}
void
@@ -319,6 +582,8 @@ app_exit (int kill_it)
/* If it's the user's perogative, and there are dirty images */
if (kill_it == 0 && gdisplays_dirty () && no_interface == FALSE)
really_quit_dialog ();
else if (no_interface == FALSE)
toolbox_free ();
else
app_exit_finish ();
}
@@ -332,11 +597,11 @@ really_quit_callback (GtkButton *button,
GtkWidget *dialog)
{
gtk_widget_destroy (dialog);
app_exit_finish ();
toolbox_free ();
}
static void
really_quit_cancel_callback (GtkButton *button,
really_quit_cancel_callback (GtkWidget *widget,
GtkWidget *dialog)
{
menus_set_sensitive ("<Toolbox>/File/Quit", TRUE);
@@ -349,9 +614,9 @@ really_quit_delete_callback (GtkWidget *widget,
GdkEvent *event,
gpointer client_data)
{
really_quit_cancel_callback (GTK_BUTTON(widget), (GtkWidget *) client_data);
really_quit_cancel_callback (widget, (GtkWidget *) client_data);
return FALSE;
return TRUE;
}
static void
@@ -365,6 +630,7 @@ really_quit_dialog ()
menus_set_sensitive ("<Image>/File/Quit", FALSE);
dialog = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (dialog), "really_quit", "Gimp");
gtk_window_set_title (GTK_WINDOW (dialog), "Really Quit?");
gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
gtk_container_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 2);
@@ -411,3 +677,316 @@ quit_invoker (Argument *args)
return return_args;
}
/*
** Shared memory initialization & setup routine.
*/
gint32
gimp_shmem_init( int precision, key_t shmid, int chans, long offset,
int xSize, int ySize )
{
Argument *return_vals;
int nreturn_vals;
int r;
gint32 layer_ID;
gint32 display_ID;
gint32 drawable = U16_RGB_GIMAGE;
gint32 image_ID;
gint type = RGB;
/*printf( "gimp_shmem_init: entering.\n" );*/
/*
** Initialize the application
*/
app_init ();
/*
** Setup the shared memory segments
*/
/*printf( "gimp_shmem_init: past app_init.\n" );*/
return_vals = procedural_db_run_proc ("shmseg_attach",
&nreturn_vals,
PDB_INT32, shmid,
PDB_INT32, offset,
PDB_END );
r = return_vals[0].value.pdb_int;
procedural_db_destroy_args( return_vals, nreturn_vals );
if( r != PDB_SUCCESS )
{
message_box( "SHM Attach operation failed.", NULL, NULL );
return -1;
}
/*printf( "gimp_shmem_init: past attach.\n" );*/
switch( precision )
{
case PRECISION_U8:
switch( chans )
{
case 1:
type = GRAY;
break;
case 3:
case 4:
type = RGB;
break;
}
break;
case PRECISION_U16:
switch( chans )
{
case 1:
type = U16_GRAY;
break;
case 3:
case 4:
type = U16_RGB;
break;
}
break;
case PRECISION_FLOAT:
switch( chans )
{
case 1:
type = FLOAT_GRAY;
break;
case 3:
case 4:
type = FLOAT_RGB;
break;
}
break;
case PRECISION_FLOAT16:
switch( chans )
{
case 1:
type = FLOAT16_GRAY;
break;
case 3:
case 4:
type = FLOAT16_RGB;
break;
}
break;
}
return_vals = procedural_db_run_proc ("gimp_image_new",
&nreturn_vals,
PDB_INT32, xSize,
PDB_INT32, ySize,
PDB_INT32, type,
PDB_END );
r = return_vals[0].value.pdb_int;
image_ID = return_vals[1].value.pdb_int;
procedural_db_destroy_args( return_vals, nreturn_vals );
if( r != PDB_SUCCESS )
{
message_box( "New of image failed.", NULL, NULL );
return -1;
}
/*printf( "gimp_shmem_init: past gimage_new_proc.\n" );*/
switch( precision )
{
case PRECISION_U8:
switch( chans )
{
case 1:
drawable = GRAY_GIMAGE;
break;
case 3:
drawable = RGB_GIMAGE;
break;
case 4:
drawable = RGBA_GIMAGE;
break;
}
break;
case PRECISION_U16:
switch( chans )
{
case 1:
drawable = U16_GRAY_GIMAGE;
break;
case 3:
drawable = U16_RGB_GIMAGE;
break;
case 4:
drawable = U16_RGBA_GIMAGE;
break;
}
break;
case PRECISION_FLOAT:
switch( chans )
{
case 1:
drawable = FLOAT_GRAY_GIMAGE;
break;
case 3:
drawable = FLOAT_RGB_GIMAGE;
break;
case 4:
drawable = FLOAT_RGBA_GIMAGE;
break;
}
break;
case PRECISION_FLOAT16:
switch( chans )
{
case 1:
drawable = FLOAT16_GRAY_GIMAGE;
break;
case 3:
drawable = FLOAT16_RGB_GIMAGE;
break;
case 4:
drawable = FLOAT16_RGBA_GIMAGE;
break;
}
break;
}
/*
** HACK Alert! In layer_cmds.c, "layer_new_invoker" is sensitive
** to any bits set in the upper byte of the drawable word. If any
** are set, it sets the storage type to STORAGE_SHM instead of
** STORAGE_FLAT (the default)
*/
drawable += 256;
return_vals = procedural_db_run_proc ("gimp_layer_new",
&nreturn_vals,
PDB_IMAGE, image_ID,
PDB_INT32, xSize,
PDB_INT32, ySize,
PDB_INT32, drawable,
PDB_STRING, "Chalice Shmem Image",
PDB_FLOAT, 100.,
PDB_INT32, NORMAL_MODE,
PDB_END );
r = return_vals[0].value.pdb_int;
layer_ID = return_vals[1].value.pdb_int;
procedural_db_destroy_args( return_vals, nreturn_vals );
if( r != PDB_SUCCESS )
{
message_box( "New of layer failed.", NULL, NULL );
return -1;
}
/*printf( "gimp_shmem_init: past layer_new_proc.\n" );*/
/*
** Disable the undo while we add the layer
*/
return_vals = procedural_db_run_proc ("gimp_image_disable_undo",
&nreturn_vals,
PDB_IMAGE, image_ID,
PDB_END );
r = return_vals[0].value.pdb_int;
procedural_db_destroy_args( return_vals, nreturn_vals );
if( r != PDB_SUCCESS )
{
message_box( "Disable of undo failed.", NULL, NULL );
return -1;
}
/*printf( "gimp_shmem_init: past gimage_disable_undo_proc.\n" );*/
/*
** Add the layer
*/
return_vals = procedural_db_run_proc ("gimp_image_add_layer",
&nreturn_vals,
PDB_IMAGE, image_ID,
PDB_LAYER, layer_ID,
PDB_INT32, 0,
PDB_END );
r = return_vals[0].value.pdb_int;
procedural_db_destroy_args( return_vals, nreturn_vals );
if( r != PDB_SUCCESS )
{
message_box( "Layer add failed.", NULL, NULL );
return -1;
}
/*
** Re-enable the undo
*/
return_vals = procedural_db_run_proc ("gimp_image_enable_undo",
&nreturn_vals,
PDB_IMAGE, image_ID,
PDB_END );
r = return_vals[0].value.pdb_int;
procedural_db_destroy_args( return_vals, nreturn_vals );
if( r != PDB_SUCCESS )
{
message_box( "Re-enable of undo failed.", NULL, NULL );
return -1;
}
/*printf( "gimp_shmem_init: past gimage_enable_undo_proc.\n" );*/
/*
** Setup the displayable image
*/
return_vals = procedural_db_run_proc ("gimp_display_new",
&nreturn_vals,
PDB_IMAGE, image_ID,
PDB_END );
r = return_vals[0].value.pdb_int;
display_ID = return_vals[1].value.pdb_int;
procedural_db_destroy_args( return_vals, nreturn_vals );
if( r != PDB_SUCCESS )
{
message_box( "Display new failed.", NULL, NULL );
return -1;
}
/*printf( "gimp_shmem_init: past gdisplay_new_proc.\n" );*/
/*
** Refresh
*/
gdisplays_flush();
return image_ID;
}

View File

@@ -13,15 +13,19 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __APP_PROCS_H__
#define __APP_PROCS_H__
/* Function declarations */
void gimp_init (int, char **);
/*typedef int key_t;*/
gint32 gimp_shmem_init (int p, key_t k, int s, long o, int xs, int ys);
void app_init (void);
void app_exit (int);
void app_exit_finish (void);
int app_exit_finish_done (void);
void app_init_update_status(char *label1val, char *label2val, float pct_progress);
#endif /* APP_PROCS_H */

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __APPENV_H__
#define __APPENV_H__
@@ -28,7 +28,19 @@
#define MINIMUM(x,y) ((x < y) ? x : y)
#define MAXIMUM(x,y) ((x > y) ? x : y)
typedef enum {
MESSAGE_BOX,
CONSOLE
} MessageHandlerType;
extern int no_interface;
extern int no_splash;
extern int no_splash_image;
extern int no_data;
extern int be_verbose;
extern int use_debug_handler;
extern int console_messages;
extern MessageHandlerType message_handler;
#endif /* APPENV_H */

View File

@@ -16,7 +16,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
@@ -30,7 +30,6 @@
#include <math.h>
#include <string.h>
#include "appenv.h"
#include "asupsample.h"
@@ -114,9 +113,18 @@ adaptive_supersample_area(int x1, int y1, int x2, int y2, int max_depth, double
block = g_malloc((sub_pixel_size + 1) * sizeof(sample_t *)); /* Rows */
for (y = 0; y < (sub_pixel_size + 1); y++)
/* Columns */
block[y] = g_malloc0((sub_pixel_size + 1) * sizeof(sample_t));
for (y = 0; y < (sub_pixel_size + 1); y++) {
block[y] = g_malloc((sub_pixel_size + 1) * sizeof(sample_t)); /* Columns */
for (x = 0; x < (sub_pixel_size + 1); x++) {
block[y][x].ready = 0;
block[y][x].color.r = 0;
block[y][x].color.g = 0;
block[y][x].color.b = 0;
block[y][x].color.a = 0;
}
}
/* Render region */
@@ -144,9 +152,10 @@ adaptive_supersample_area(int x1, int y1, int x2, int y2, int max_depth, double
/* Copy samples from top row to block */
memcpy(block[0],
top_row + ((x - x1) * sub_pixel_size),
sizeof(sample_t) * sub_pixel_size);
for (xtt = 0, xt = (x - x1) * sub_pixel_size;
xtt < (sub_pixel_size + 1);
xtt++, xt++)
block[0][xtt] = top_row[xt];
/* Render pixel on (x, y) */
@@ -162,9 +171,10 @@ adaptive_supersample_area(int x1, int y1, int x2, int y2, int max_depth, double
top_row[((x - x1) + 1) * sub_pixel_size] = block[0][sub_pixel_size];
memcpy(bot_row + ((x - x1) * sub_pixel_size),
block[sub_pixel_size],
sub_pixel_size * sizeof(sample_t));
for (xtt = 0, xt = (x - x1) * sub_pixel_size;
xtt < (sub_pixel_size + 1);
xtt++, xt++)
bot_row[xt] = block[sub_pixel_size][xtt];
/* Swap first and last columns */
@@ -216,7 +226,7 @@ render_sub_pixel(int max_depth, int depth, sample_t **block,
/* Get offsets for corners */
dx1 = (double) (x1 - sub_pixel_size / 2) / sub_pixel_size;
dx1 = (double) (x1 - sub_pixel_size / 2) / sub_pixel_size;
dx3 = (double) (x3 - sub_pixel_size / 2) / sub_pixel_size;
dy1 = (double) (y1 - sub_pixel_size / 2) / sub_pixel_size;

View File

@@ -16,7 +16,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/

View File

@@ -13,16 +13,20 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#include "appenv.h"
#include "errors.h"
#include "float16.h"
#include "boundary.h"
#include "canvas.h"
#include "pixelarea.h"
/* half intensity for mask */
#define HALF_WAY 127
#define HALF_WAY_16BIT 32767
/* BoundSeg array growth parameter */
#define MAX_SEGS_INC 2048
@@ -45,11 +49,22 @@ static int num_empty_l = 0;
static int max_empty_segs = 0;
/* global state variables--improve parameter efficiency */
static PixelRegion * cur_PR;
static Canvas * cur_mask;
static int cur_x;
static int cur_y;
static int cur_w;
static int cur_h;
typedef void (*FindEmptySegsLineFunc) (PixelArea *, gint, gint, gint *, gint *, gint, gint, gint);
static FindEmptySegsLineFunc find_empty_segs_line_func (Tag);
static void find_empty_segs_line_u8 (PixelArea *, gint, gint, gint *, gint *, gint, gint, gint);
static void find_empty_segs_line_u16 (PixelArea *, gint, gint, gint *, gint *, gint, gint, gint);
static void find_empty_segs_line_float (PixelArea *, gint, gint, gint *, gint *, gint, gint, gint);
static void find_empty_segs_line_float16 (PixelArea *, gint, gint, gint *, gint *, gint, gint, gint);
/* local function prototypes */
static void find_empty_segs (PixelRegion *, int, int *, int, int *,
static void print_boundary (BoundSeg * b, int num_segs);
static void find_empty_segs (int, int *, int, int *,
BoundaryType, int, int, int, int);
static void make_seg (int, int, int, int, int);
static void allocate_vert_segs (void);
@@ -58,11 +73,41 @@ static void process_horiz_seg (int, int, int, int, int);
static void make_horiz_segs (int, int, int, int *, int, int);
static void generate_boundary (BoundaryType, int, int, int, int);
/* Function definitions */
void print_boundary (BoundSeg * b, int num_segs)
{
int i;
printf (" num_segs is %d\n", num_segs);
for (i= 0; i < num_segs; i++)
{
printf (" %d %d %d %d \n", b[i].x1, b[i].y1, b[i].x2, b[i].y2);
}
}
static
FindEmptySegsLineFunc
find_empty_segs_line_func (Tag t)
{
switch (tag_precision (t))
{
case PRECISION_U8:
return find_empty_segs_line_u8;
case PRECISION_U16:
return find_empty_segs_line_u16;
case PRECISION_FLOAT:
return find_empty_segs_line_float;
case PRECISION_FLOAT16:
return find_empty_segs_line_float16;
default:
return NULL;
}
}
/* Function definitions */
static void
find_empty_segs (PixelRegion *maskPR,
int scanline,
find_empty_segs (int scanline,
int empty_segs[],
int max_empty,
int *num_empty,
@@ -72,20 +117,23 @@ find_empty_segs (PixelRegion *maskPR,
int x2,
int y2)
{
unsigned char *data;
int x;
int start, end;
int val, last;
int tilex;
Tile *tile = NULL;
gint mask_x, mask_y, mask_w, mask_h;
PixelArea area;
Tag tag = canvas_tag (cur_mask);
FindEmptySegsLineFunc find_empty_segs_line = find_empty_segs_line_func (tag);
mask_x = cur_x;
mask_y = cur_y;
mask_w = cur_w;
mask_h = cur_h;
data = NULL;
start = 0;
end = 0;
*num_empty = 0;
if (scanline < maskPR->y || scanline >= (maskPR->y + maskPR->h))
if (scanline < mask_y || scanline >= mask_y + mask_h)
{
empty_segs[(*num_empty)++] = 0;
empty_segs[(*num_empty)++] = G_MAXINT;
@@ -106,43 +154,200 @@ find_empty_segs (PixelRegion *maskPR,
}
else if (type == IgnoreBounds)
{
start = maskPR->x;
end = maskPR->x + maskPR->w;
start = mask_x;
end = mask_x + mask_w;
if (scanline < y1 || scanline >= y2)
x2 = -1;
}
tilex = -1;
/*get pixelarea for scanline from start to end */
pixelarea_init (&area, cur_mask,
start, scanline,
end - start, 1,
FALSE);
(*find_empty_segs_line) (&area,
start, end,
num_empty, empty_segs,
type, x1, x2);
}
void find_empty_segs_line_u8(
PixelArea *area,
int start,
int end,
int *num_empty,
int *empty_segs,
int type,
int x1,
int x2
)
{
guchar *data;
guint8 *d;
int x;
int val, last;
gint width;
gint chan;
Tag tag = pixelarea_tag (area);
gint num_channels = tag_num_channels (tag);
void *pag;
empty_segs[(*num_empty)++] = 0;
last = -1;
x = start;
for (x = start; x < end; x++)
/*If format has an alpha, chan is set to that,
else its just the gray channel*/
chan = num_channels - 1;
for (pag = pixelarea_register (1, area);
pag != NULL;
pag = pixelarea_process (pag))
{
/* Check to see if we must advance to next tile */
if ((x / TILE_WIDTH) != tilex)
{
if (tile)
tile_unref (tile, FALSE);
tile = tile_manager_get_tile (maskPR->tiles, x, scanline, 0);
tile_ref (tile);
data = tile->data + tile->bpp *
((scanline % TILE_HEIGHT) * tile->ewidth + (x % TILE_WIDTH)) + (tile->bpp - 1);
tilex = x / TILE_WIDTH;
}
data = pixelarea_data (area);
d = (guint8*)data;
width = pixelarea_width (area);
while( width --)
{
empty_segs[*num_empty] = x;
val = (d[chan] > HALF_WAY)? 1: -1;
empty_segs[*num_empty] = x;
val = (*data > HALF_WAY) ? 1 : -1;
/* The IgnoreBounds case */
if (val == 1 && type == IgnoreBounds)
if (x >= x1 && x < x2)
val = -1;
/* The IgnoreBounds case */
if (val == 1 && type == IgnoreBounds)
if (x >= x1 && x < x2)
val = -1;
if (last * val < 0)
(*num_empty)++;
last = val;
if (last * val < 0)
(*num_empty)++;
last = val;
d += num_channels;
x++;
}
}
data += tile->bpp;
if (last > 0)
empty_segs[(*num_empty)++] = x;
empty_segs[(*num_empty)++] = G_MAXINT;
}
void find_empty_segs_line_u16(
PixelArea *area,
int start,
int end,
int *num_empty,
int *empty_segs,
int type,
int x1,
int x2
)
{
guchar *data;
guint16 *d;
int x;
int val, last;
gint width;
gint chan;
Tag tag = pixelarea_tag (area);
gint num_channels = tag_num_channels (tag);
void *pag;
empty_segs[(*num_empty)++] = 0;
last = -1;
x = start;
/*If format has an alpha, chan is set to that,
else its just the gray channel*/
chan = num_channels - 1;
for (pag = pixelarea_register (1, area);
pag != NULL;
pag = pixelarea_process (pag))
{
data = pixelarea_data (area);
d = (guint16*)data;
width = pixelarea_width (area);
while( width --)
{
empty_segs[*num_empty] = x;
val = (d[chan] > HALF_WAY_16BIT)? 1: -1;
/* The IgnoreBounds case */
if (val == 1 && type == IgnoreBounds)
if (x >= x1 && x < x2)
val = -1;
if (last * val < 0)
(*num_empty)++;
last = val;
d += num_channels;
x++;
}
}
if (last > 0)
empty_segs[(*num_empty)++] = x;
empty_segs[(*num_empty)++] = G_MAXINT;
}
void find_empty_segs_line_float(
PixelArea *area,
int start,
int end,
int *num_empty,
int *empty_segs,
int type,
int x1,
int x2
)
{
guchar *data;
gfloat *d;
int x;
int val, last;
gint width;
gint chan;
Tag tag = pixelarea_tag (area);
gint num_channels = tag_num_channels (tag);
void *pag;
empty_segs[(*num_empty)++] = 0;
last = -1;
x = start;
/*If format has an alpha, chan is set to that,
else its just the gray channel*/
chan = num_channels - 1;
for (pag = pixelarea_register (1, area);
pag != NULL;
pag = pixelarea_process (pag))
{
data = pixelarea_data (area);
d = (gfloat*)data;
width = pixelarea_width (area);
while( width --)
{
empty_segs[*num_empty] = x;
val = (d[chan] > .5)? 1: -1;
/* The IgnoreBounds case */
if (val == 1 && type == IgnoreBounds)
if (x >= x1 && x < x2)
val = -1;
if (last * val < 0)
(*num_empty)++;
last = val;
d += num_channels;
x++;
}
}
if (last > 0)
@@ -150,10 +355,70 @@ find_empty_segs (PixelRegion *maskPR,
empty_segs[(*num_empty)++] = G_MAXINT;
if (tile)
tile_unref (tile, FALSE);
}
void find_empty_segs_line_float16(
PixelArea *area,
int start,
int end,
int *num_empty,
int *empty_segs,
int type,
int x1,
int x2
)
{
guchar *data;
guint16 *d;
int x;
int val, last;
gint width;
gint chan;
Tag tag = pixelarea_tag (area);
gint num_channels = tag_num_channels (tag);
void *pag;
ShortsFloat u;
empty_segs[(*num_empty)++] = 0;
last = -1;
x = start;
/*If format has an alpha, chan is set to that,
else its just the gray channel*/
chan = num_channels - 1;
for (pag = pixelarea_register (1, area);
pag != NULL;
pag = pixelarea_process (pag))
{
data = pixelarea_data (area);
d = (guint16*)data;
width = pixelarea_width (area);
while( width --)
{
empty_segs[*num_empty] = x;
val = (FLT (d[chan], u) > .5)? 1: -1;
/* The IgnoreBounds case */
if (val == 1 && type == IgnoreBounds)
if (x >= x1 && x < x2)
val = -1;
if (last * val < 0)
(*num_empty)++;
last = val;
d += num_channels;
x++;
}
}
if (last > 0)
empty_segs[(*num_empty)++] = x;
empty_segs[(*num_empty)++] = G_MAXINT;
}
static void
make_seg (int x1,
@@ -186,11 +451,13 @@ static void
allocate_vert_segs (void)
{
int i;
int j = cur_w + cur_x;
/* allocate and initialize the vert_segs array */
vert_segs = (int *) g_realloc ((void *) vert_segs, (cur_PR->w + cur_PR->x + 1) * sizeof (int));
vert_segs = (int *) g_realloc ((void *) vert_segs,
(j + 1) * sizeof (int));
for (i = 0; i <= (cur_PR->w + cur_PR->x); i++)
for (i = 0; i <= j; i++)
vert_segs[i] = -1;
}
@@ -201,7 +468,7 @@ allocate_empty_segs (void)
int need_num_segs;
/* find the maximum possible number of empty segments given the current mask */
need_num_segs = cur_PR->w + 2;
need_num_segs = cur_w + 2;
if (need_num_segs > max_empty_segs)
{
@@ -302,22 +569,22 @@ generate_boundary (BoundaryType type,
}
else if (type == IgnoreBounds)
{
start = cur_PR->y;
end = cur_PR->y + cur_PR->h;
start = cur_y;
end = cur_y + cur_h;
}
/* Find the empty segments for the previous and current scanlines */
find_empty_segs (cur_PR, start - 1, empty_segs_l,
find_empty_segs (start - 1, empty_segs_l,
max_empty_segs, &num_empty_l,
type, x1, y1, x2, y2);
find_empty_segs (cur_PR, start, empty_segs_c,
find_empty_segs (start, empty_segs_c,
max_empty_segs, &num_empty_c,
type, x1, y1, x2, y2);
for (scanline = start; scanline < end; scanline++)
{
/* find the empty segment list for the next scanline */
find_empty_segs (cur_PR, scanline + 1, empty_segs_n,
find_empty_segs (scanline + 1, empty_segs_n,
max_empty_segs, &num_empty_n,
type, x1, y1, x2, y2);
@@ -340,9 +607,12 @@ generate_boundary (BoundaryType type,
}
}
BoundSeg *
find_mask_boundary (PixelRegion *maskPR,
find_mask_boundary (Canvas * mask,
int x,
int y,
int w,
int h,
int *num_elems,
BoundaryType type,
int x1,
@@ -356,7 +626,14 @@ find_mask_boundary (PixelRegion *maskPR,
* has more than 1 bytes/pixel, the last byte of each pixel is
* used to determine the boundary outline.
*/
cur_PR = maskPR;
if (w == 0) w = canvas_width (mask);
if (h == 0) h = canvas_height (mask);
cur_mask = mask;
cur_x = x;
cur_y = y;
cur_w = w;
cur_h = h;
/* Calculate the boundary */
generate_boundary (type, x1, y1, x2, y2);
@@ -371,6 +648,7 @@ find_mask_boundary (PixelRegion *maskPR,
memcpy (new_segs, tmp_segs, (sizeof (BoundSeg) * num_segs));
}
/*print_boundary (new_segs, num_segs);*/
/* Return the new boundary */
return new_segs;
}
@@ -467,7 +745,7 @@ sort_boundary (BoundSeg *segs,
}
if (x != startx || y != starty)
g_warning ("Unconnected boundary group!");
g_message ("sort_boundary(): Unconnected boundary group!");
/* Mark the end of a group */
*num_groups = *num_groups + 1;

View File

@@ -13,14 +13,13 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BOUNDARY_H__
#define __BOUNDARY_H__
#include "paint_funcs.h"
typedef struct _BoundSeg BoundSeg;
struct _Canvas;
struct _BoundSeg
{
@@ -37,7 +36,11 @@ typedef enum
} BoundaryType;
BoundSeg * find_mask_boundary (PixelRegion *, int *, BoundaryType, int, int, int, int);
BoundSeg * find_mask_boundary (struct _Canvas *,
int, int, int, int,
int *, BoundaryType,
int, int, int, int);
BoundSeg * sort_boundary (BoundSeg *, int, int *);
#endif /* __BOUNDARY_H__ */

View File

@@ -13,23 +13,29 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "appenv.h"
#include "actionarea.h"
#include "canvas.h"
#include "color_balance.h"
#include "color_transfer.h"
#include "drawable.h"
#include "float16.h"
#include "general.h"
#include "gimage_mask.h"
#include "gdisplay.h"
#include "image_map.h"
#include "interface.h"
#include "paint_funcs_area.h"
#include "pixelarea.h"
#include "pixelrow.h"
#define TEXT_WIDTH 55
#define SQR(x) ((x) * (x))
#define SHADOWS 0
#define MIDTONES 1
@@ -43,6 +49,16 @@
#define YB_TEXT 0x20
#define ALL 0xFF
/* for lightening */
gdouble * highlights_add_ptr;
gdouble * midtones_add_ptr;
gdouble * shadows_add_ptr;
/* for darkening */
gdouble * highlights_sub_ptr;
gdouble * midtones_sub_ptr;
gdouble * shadows_sub_ptr;
typedef struct _ColorBalance ColorBalance;
struct _ColorBalance
@@ -103,102 +119,602 @@ static void color_balance_yb_text_update (GtkWidget *, gpo
static void *color_balance_options = NULL;
static ColorBalanceDialog *color_balance_dialog = NULL;
static void color_balance (PixelRegion *, PixelRegion *, void *);
static void color_balance (PixelArea *, PixelArea *, void *);
static Argument * color_balance_invoker (Argument *);
static gdouble f0_u8 (gdouble);
static gdouble f1_u8 (gdouble);
static gdouble f2_u8 (gdouble);
static gdouble f0 (gdouble);
static gdouble f1 (gdouble);
static gdouble f2 (gdouble);
static void color_balance_allocate_transfer_arrays (gint);
static void color_balance_free_transfer_arrays (void);
typedef void (*ColorBalanceInitTransfersFunc)(void);
ColorBalanceInitTransfersFunc color_balance_init_transfers;
typedef void (*ColorBalanceRowFunc)(PixelRow *, PixelRow *, double *, double *, double *, gint);
ColorBalanceRowFunc color_balance_row;
static void color_balance_funcs (Tag drawable_tag);
static void color_balance_init_transfers_u8 (void);
static void color_balance_row_u8 (PixelRow *, PixelRow *, double *, double *, double *, gint);
static void color_balance_init_transfers_u16 (void);
static void color_balance_row_u16 (PixelRow *, PixelRow *, double *, double *, double *, gint);
static void color_balance_init_transfers_float (void);
static void color_balance_row_float (PixelRow *, PixelRow *, double *, double *, double *, gint);
static void color_balance_init_transfers_float16 (void);
static void color_balance_row_float16 (PixelRow *, PixelRow *, double *, double *, double *, gint);
/* color balance machinery */
static void
color_balance_funcs (Tag drawable_tag)
{
switch (tag_precision (drawable_tag))
{
case PRECISION_U8:
color_balance_row = color_balance_row_u8;
color_balance_init_transfers = color_balance_init_transfers_u8;
break;
case PRECISION_U16:
color_balance_row = color_balance_row_u16;
color_balance_init_transfers = color_balance_init_transfers_u16;
break;
case PRECISION_FLOAT:
color_balance_row = color_balance_row_float;
color_balance_init_transfers = color_balance_init_transfers_float;
case PRECISION_FLOAT16:
color_balance_row = color_balance_row_float16;
color_balance_init_transfers = color_balance_init_transfers_float16;
break;
default:
color_balance_row = NULL;
color_balance_init_transfers = NULL;
break;
}
}
static void
color_balance (PixelRegion *srcPR,
PixelRegion *destPR,
color_balance (PixelArea *src_area,
PixelArea *dest_area,
void *user_data)
{
ColorBalanceDialog *cbd;
unsigned char *src, *s;
unsigned char *dest, *d;
int alpha;
int r, g, b;
int r_n, g_n, b_n;
int w, h;
double *cyan_red_transfer[3];
double *magenta_green_transfer[3];
double *yellow_blue_transfer[3];
cbd = (ColorBalanceDialog *) user_data;
/* Set the transfer arrays (for speed) */
cyan_red_transfer[SHADOWS] = (cbd->cyan_red[SHADOWS] > 0) ? shadows_add : shadows_sub;
cyan_red_transfer[MIDTONES] = (cbd->cyan_red[MIDTONES] > 0) ? midtones_add : midtones_sub;
cyan_red_transfer[HIGHLIGHTS] = (cbd->cyan_red[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
magenta_green_transfer[SHADOWS] = (cbd->magenta_green[SHADOWS] > 0) ? shadows_add : shadows_sub;
magenta_green_transfer[MIDTONES] = (cbd->magenta_green[MIDTONES] > 0) ? midtones_add : midtones_sub;
magenta_green_transfer[HIGHLIGHTS] = (cbd->magenta_green[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
yellow_blue_transfer[SHADOWS] = (cbd->yellow_blue[SHADOWS] > 0) ? shadows_add : shadows_sub;
yellow_blue_transfer[MIDTONES] = (cbd->yellow_blue[MIDTONES] > 0) ? midtones_add : midtones_sub;
yellow_blue_transfer[HIGHLIGHTS] = (cbd->yellow_blue[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
alpha = (srcPR->bytes == 4) ? TRUE : FALSE;
PixelRow src_row, dest_row;
ColorBalanceDialog *cbd = (ColorBalanceDialog *) user_data;
int h= pixelarea_height (src_area);
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
r = r_n = s[RED_PIX];
g = g_n = s[GREEN_PIX];
b = b_n = s[BLUE_PIX];
r_n += cbd->cyan_red[SHADOWS] * cyan_red_transfer[SHADOWS][r_n];
r_n = BOUNDS (r_n, 0, 255);
r_n += cbd->cyan_red[MIDTONES] * cyan_red_transfer[MIDTONES][r_n];
r_n = BOUNDS (r_n, 0, 255);
r_n += cbd->cyan_red[HIGHLIGHTS] * cyan_red_transfer[HIGHLIGHTS][r_n];
r_n = BOUNDS (r_n, 0, 255);
g_n += cbd->magenta_green[SHADOWS] * magenta_green_transfer[SHADOWS][g_n];
g_n = BOUNDS (g_n, 0, 255);
g_n += cbd->magenta_green[MIDTONES] * magenta_green_transfer[MIDTONES][g_n];
g_n = BOUNDS (g_n, 0, 255);
g_n += cbd->magenta_green[HIGHLIGHTS] * magenta_green_transfer[HIGHLIGHTS][g_n];
g_n = BOUNDS (g_n, 0, 255);
b_n += cbd->yellow_blue[SHADOWS] * yellow_blue_transfer[SHADOWS][b_n];
b_n = BOUNDS (b_n, 0, 255);
b_n += cbd->yellow_blue[MIDTONES] * yellow_blue_transfer[MIDTONES][b_n];
b_n = BOUNDS (b_n, 0, 255);
b_n += cbd->yellow_blue[HIGHLIGHTS] * yellow_blue_transfer[HIGHLIGHTS][b_n];
b_n = BOUNDS (b_n, 0, 255);
if (cbd->preserve_luminosity)
{
rgb_to_hls (&r, &g, &b);
rgb_to_hls (&r_n, &g_n, &b_n);
g_n = g;
hls_to_rgb (&r_n, &g_n, &b_n);
}
d[RED_PIX] = r_n;
d[GREEN_PIX] = g_n;
d[BLUE_PIX] = b_n;
if (alpha)
d[ALPHA_PIX] = s[ALPHA_PIX];
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
pixelarea_getdata (src_area, &src_row, h);
pixelarea_getdata (dest_area, &dest_row, h);
(*color_balance_row) (&src_row, &dest_row,
cbd->cyan_red,
cbd->magenta_green,
cbd->yellow_blue,
cbd->preserve_luminosity);
}
}
static void
color_balance_row_u8 (
PixelRow *src_row,
PixelRow *dest_row,
double * cr,
double * mg,
double * yb,
gint preserve_luminosity
)
{
Tag src_tag = pixelrow_tag (src_row);
Tag dest_tag = pixelrow_tag (dest_row);
gint src_num_channels = tag_num_channels (src_tag);
gint dest_num_channels = tag_num_channels (dest_tag);
guint8 *s, *d;
int has_alpha;
int r, g, b;
int r_n, g_n, b_n;
double *cyan_red_transfer[3];
double *magenta_green_transfer[3];
double *yellow_blue_transfer[3];
gint w = pixelrow_width (src_row);
/* Set the transfer arrays (for speed) */
cyan_red_transfer[SHADOWS] = (cr[SHADOWS] > 0) ? shadows_add_ptr : shadows_sub_ptr;
cyan_red_transfer[MIDTONES] = (cr[MIDTONES] > 0) ? midtones_add_ptr : midtones_sub_ptr;
cyan_red_transfer[HIGHLIGHTS] = (cr[HIGHLIGHTS] > 0) ? highlights_add_ptr : highlights_sub_ptr;
magenta_green_transfer[SHADOWS] = (mg[SHADOWS] > 0) ? shadows_add_ptr : shadows_sub_ptr;
magenta_green_transfer[MIDTONES] = (mg[MIDTONES] > 0) ? midtones_add_ptr : midtones_sub_ptr;
magenta_green_transfer[HIGHLIGHTS] = (mg[HIGHLIGHTS] > 0) ? highlights_add_ptr : highlights_sub_ptr;
yellow_blue_transfer[SHADOWS] = (yb[SHADOWS] > 0) ? shadows_add_ptr : shadows_sub_ptr;
yellow_blue_transfer[MIDTONES] = (yb[MIDTONES] > 0) ? midtones_add_ptr : midtones_sub_ptr;
yellow_blue_transfer[HIGHLIGHTS] = (yb[HIGHLIGHTS] > 0) ? highlights_add_ptr : highlights_sub_ptr;
s = (guint8 *)pixelrow_data (src_row);
d = (guint8 *)pixelrow_data (dest_row);
has_alpha = tag_alpha (src_tag) == ALPHA_YES? TRUE: FALSE;
while (w--)
{
r = r_n = s[RED_PIX];
g = g_n = s[GREEN_PIX];
b = b_n = s[BLUE_PIX];
r_n += cr[SHADOWS] * cyan_red_transfer[SHADOWS][r_n];
r_n = BOUNDS (r_n, 0, 255);
r_n += cr[MIDTONES] * cyan_red_transfer[MIDTONES][r_n];
r_n = BOUNDS (r_n, 0, 255);
r_n += cr[HIGHLIGHTS] * cyan_red_transfer[HIGHLIGHTS][r_n];
r_n = BOUNDS (r_n, 0, 255);
g_n += mg[SHADOWS] * magenta_green_transfer[SHADOWS][g_n];
g_n = BOUNDS (g_n, 0, 255);
g_n += mg[MIDTONES] * magenta_green_transfer[MIDTONES][g_n];
g_n = BOUNDS (g_n, 0, 255);
g_n += mg[HIGHLIGHTS] * magenta_green_transfer[HIGHLIGHTS][g_n];
g_n = BOUNDS (g_n, 0, 255);
b_n += yb[SHADOWS] * yellow_blue_transfer[SHADOWS][b_n];
b_n = BOUNDS (b_n, 0, 255);
b_n += yb[MIDTONES] * yellow_blue_transfer[MIDTONES][b_n];
b_n = BOUNDS (b_n, 0, 255);
b_n += yb[HIGHLIGHTS] * yellow_blue_transfer[HIGHLIGHTS][b_n];
b_n = BOUNDS (b_n, 0, 255);
if (preserve_luminosity)
{
rgb_to_hls (&r, &g, &b);
rgb_to_hls (&r_n, &g_n, &b_n);
g_n = g;
hls_to_rgb (&r_n, &g_n, &b_n);
}
d[RED_PIX] = r_n;
d[GREEN_PIX] = g_n;
d[BLUE_PIX] = b_n;
if (has_alpha)
d[ALPHA_PIX] = s[ALPHA_PIX];
s += src_num_channels;
d += dest_num_channels;
}
}
static void
color_balance_row_u16 (
PixelRow *src_row,
PixelRow *dest_row,
double * cr,
double * mg,
double * yb,
gint preserve_luminosity
)
{
Tag src_tag = pixelrow_tag (src_row);
Tag dest_tag = pixelrow_tag (dest_row);
gint src_num_channels = tag_num_channels (src_tag);
gint dest_num_channels = tag_num_channels (dest_tag);
guint16 *s, *d;
int has_alpha;
int r, g, b;
int r_n, g_n, b_n;
double *cyan_red_transfer[3];
double *magenta_green_transfer[3];
double *yellow_blue_transfer[3];
gint w = pixelrow_width (src_row);
gfloat cr_shadows, cr_midtones, cr_highlights;
gfloat mg_shadows, mg_midtones, mg_highlights;
gfloat yb_shadows, yb_midtones, yb_highlights;
/* Set the transfer arrays (for speed) */
cyan_red_transfer[SHADOWS] = (cr[SHADOWS] > 0) ? shadows_add_ptr : shadows_sub_ptr;
cyan_red_transfer[MIDTONES] = (cr[MIDTONES] > 0) ? midtones_add_ptr : midtones_sub_ptr;
cyan_red_transfer[HIGHLIGHTS] = (cr[HIGHLIGHTS] > 0) ? highlights_add_ptr : highlights_sub_ptr;
magenta_green_transfer[SHADOWS] = (mg[SHADOWS] > 0) ? shadows_add_ptr : shadows_sub_ptr;
magenta_green_transfer[MIDTONES] = (mg[MIDTONES] > 0) ? midtones_add_ptr : midtones_sub_ptr;
magenta_green_transfer[HIGHLIGHTS] = (mg[HIGHLIGHTS] > 0) ? highlights_add_ptr : highlights_sub_ptr;
yellow_blue_transfer[SHADOWS] = (yb[SHADOWS] > 0) ? shadows_add_ptr : shadows_sub_ptr;
yellow_blue_transfer[MIDTONES] = (yb[MIDTONES] > 0) ? midtones_add_ptr : midtones_sub_ptr;
yellow_blue_transfer[HIGHLIGHTS] = (yb[HIGHLIGHTS] > 0) ? highlights_add_ptr : highlights_sub_ptr;
/* scale cr, mg, yb to [0-65535] */
cr_shadows = (cr[SHADOWS]/255.0) * 65535;
cr_midtones = (cr[MIDTONES]/255.0) * 65535;
cr_highlights = (cr[HIGHLIGHTS]/255.0) * 65535;
mg_shadows = (mg[SHADOWS]/255.0) * 65535;
mg_midtones = (mg[MIDTONES]/255.0) * 65535;
mg_highlights = (mg[HIGHLIGHTS]/255.0) * 65535;
yb_shadows = (yb[SHADOWS]/255.0) * 65535;
yb_midtones = (yb[MIDTONES]/255.0) * 65535;
yb_highlights = (yb[HIGHLIGHTS]/255.0) * 65535;
s = (guint16 *)pixelrow_data (src_row);
d = (guint16 *)pixelrow_data (dest_row);
has_alpha = tag_alpha (src_tag) == ALPHA_YES? TRUE: FALSE;
while (w--)
{
r = r_n = s[RED_PIX];
g = g_n = s[GREEN_PIX];
b = b_n = s[BLUE_PIX];
r_n += cr_shadows * cyan_red_transfer[SHADOWS][r_n];
r_n = BOUNDS (r_n, 0, 65535);
r_n += cr_midtones * cyan_red_transfer[MIDTONES][r_n];
r_n = BOUNDS (r_n, 0, 65535);
r_n += cr_highlights * cyan_red_transfer[HIGHLIGHTS][r_n];
r_n = BOUNDS (r_n, 0, 65535);
g_n += mg_shadows * magenta_green_transfer[SHADOWS][g_n];
g_n = BOUNDS (g_n, 0, 65535);
g_n += mg_midtones * magenta_green_transfer[MIDTONES][g_n];
g_n = BOUNDS (g_n, 0, 65535);
g_n += mg_highlights * magenta_green_transfer[HIGHLIGHTS][g_n];
g_n = BOUNDS (g_n, 0, 65535);
b_n += yb_shadows * yellow_blue_transfer[SHADOWS][b_n];
b_n = BOUNDS (b_n, 0, 65535);
b_n += yb_midtones * yellow_blue_transfer[MIDTONES][b_n];
b_n = BOUNDS (b_n, 0, 65535);
b_n += yb_highlights * yellow_blue_transfer[HIGHLIGHTS][b_n];
b_n = BOUNDS (b_n, 0, 65535);
if (preserve_luminosity)
{
#if 0
rgb_to_hls (&r, &g, &b);
rgb_to_hls (&r_n, &g_n, &b_n);
g_n = g;
hls_to_rgb (&r_n, &g_n, &b_n);
#endif
}
d[RED_PIX] = r_n;
d[GREEN_PIX] = g_n;
d[BLUE_PIX] = b_n;
if (has_alpha)
d[ALPHA_PIX] = s[ALPHA_PIX];
s += src_num_channels;
d += dest_num_channels;
}
}
static void
color_balance_row_float (
PixelRow *src_row,
PixelRow *dest_row,
double * cr,
double * mg,
double * yb,
gint preserve_luminosity
)
{
Tag src_tag = pixelrow_tag (src_row);
Tag dest_tag = pixelrow_tag (dest_row);
gint src_num_channels = tag_num_channels (src_tag);
gint dest_num_channels = tag_num_channels (dest_tag);
gfloat *s, *d;
int has_alpha;
gdouble r, g, b;
gdouble r_n, g_n, b_n;
gfloat cr_shadows, cr_midtones, cr_highlights;
gfloat mg_shadows, mg_midtones, mg_highlights;
gfloat yb_shadows, yb_midtones, yb_highlights;
gdouble (*cyan_red_transfer[3])(gdouble);
gdouble (*magenta_green_transfer[3])(gdouble);
gdouble (*yellow_blue_transfer[3])(gdouble);
gint w = pixelrow_width (src_row);
/* scale cr, mg, yb to [0-1] */
cr_shadows = cr[SHADOWS]/255.0;
cr_midtones = cr[MIDTONES]/255.0;
cr_highlights = cr[HIGHLIGHTS]/255.0;
mg_shadows = mg[SHADOWS]/255.0;
mg_midtones = mg[MIDTONES]/255.0;
mg_highlights = mg[HIGHLIGHTS]/255.0;
yb_shadows = yb[SHADOWS]/255.0;
yb_midtones = yb[MIDTONES]/255.0;
yb_highlights = yb[HIGHLIGHTS]/255.0;
/* Set the function_ptrs for the computations */
cyan_red_transfer[SHADOWS] = (cr[SHADOWS] > 0) ? f2: f0;
cyan_red_transfer[MIDTONES] = f2;
cyan_red_transfer[HIGHLIGHTS] = (cr[HIGHLIGHTS] > 0) ? f1 : f2;
magenta_green_transfer[SHADOWS] = (mg[SHADOWS] > 0) ? f2 : f0;
magenta_green_transfer[MIDTONES] = f2;
magenta_green_transfer[HIGHLIGHTS] = (mg[HIGHLIGHTS] > 0) ? f1 : f2;
yellow_blue_transfer[SHADOWS] = (yb[SHADOWS] > 0) ? f2 : f0;
yellow_blue_transfer[MIDTONES] = f2;
yellow_blue_transfer[HIGHLIGHTS] = (yb[HIGHLIGHTS] > 0) ? f1 : f2;
s = (gfloat *)pixelrow_data (src_row);
d = (gfloat *)pixelrow_data (dest_row);
has_alpha = tag_alpha (src_tag) == ALPHA_YES? TRUE: FALSE;
while (w--)
{
r = r_n = s[RED_PIX];
g = g_n = s[GREEN_PIX];
b = b_n = s[BLUE_PIX];
r_n += cr_shadows * cyan_red_transfer[SHADOWS](r_n);
r_n = BOUNDS (r_n, 0, 1.0);
r_n += cr_midtones * cyan_red_transfer[MIDTONES](r_n);
r_n = BOUNDS (r_n, 0, 1.0);
r_n += cr_highlights * cyan_red_transfer[HIGHLIGHTS](r_n);
r_n = BOUNDS (r_n, 0, 1.0);
g_n += mg_shadows * magenta_green_transfer[SHADOWS](g_n);
g_n = BOUNDS (g_n, 0, 1.0);
g_n += mg_midtones * magenta_green_transfer[MIDTONES](g_n);
g_n = BOUNDS (g_n, 0, 1.0);
g_n += mg_highlights * magenta_green_transfer[HIGHLIGHTS](g_n);
g_n = BOUNDS (g_n, 0, 1.0);
b_n += yb_shadows * yellow_blue_transfer[SHADOWS](b_n);
b_n = BOUNDS (b_n, 0, 1.0);
b_n += yb_midtones * yellow_blue_transfer[MIDTONES](b_n);
b_n = BOUNDS (b_n, 0, 1.0);
b_n += yb_highlights * yellow_blue_transfer[HIGHLIGHTS](b_n);
b_n = BOUNDS (b_n, 0, 1.0);
if (preserve_luminosity)
{
#if 0
rgb_to_hls (&r, &g, &b);
rgb_to_hls (&r_n, &g_n, &b_n);
g_n = g;
hls_to_rgb (&r_n, &g_n, &b_n);
#endif
}
d[RED_PIX] = r_n;
d[GREEN_PIX] = g_n;
d[BLUE_PIX] = b_n;
if (has_alpha)
d[ALPHA_PIX] = s[ALPHA_PIX];
s += src_num_channels;
d += dest_num_channels;
}
}
static void
color_balance_row_float16 (
PixelRow *src_row,
PixelRow *dest_row,
double * cr,
double * mg,
double * yb,
gint preserve_luminosity
)
{
Tag src_tag = pixelrow_tag (src_row);
Tag dest_tag = pixelrow_tag (dest_row);
gint src_num_channels = tag_num_channels (src_tag);
gint dest_num_channels = tag_num_channels (dest_tag);
guint16 *s, *d;
int has_alpha;
gdouble r, g, b;
gdouble r_n, g_n, b_n;
gfloat cr_shadows, cr_midtones, cr_highlights;
gfloat mg_shadows, mg_midtones, mg_highlights;
gfloat yb_shadows, yb_midtones, yb_highlights;
gdouble (*cyan_red_transfer[3])(gdouble);
gdouble (*magenta_green_transfer[3])(gdouble);
gdouble (*yellow_blue_transfer[3])(gdouble);
gint w = pixelrow_width (src_row);
ShortsFloat u;
/* scale cr, mg, yb to [0-1] */
cr_shadows = cr[SHADOWS]/255.0;
cr_midtones = cr[MIDTONES]/255.0;
cr_highlights = cr[HIGHLIGHTS]/255.0;
mg_shadows = mg[SHADOWS]/255.0;
mg_midtones = mg[MIDTONES]/255.0;
mg_highlights = mg[HIGHLIGHTS]/255.0;
yb_shadows = yb[SHADOWS]/255.0;
yb_midtones = yb[MIDTONES]/255.0;
yb_highlights = yb[HIGHLIGHTS]/255.0;
/* Set the function_ptrs for the computations */
cyan_red_transfer[SHADOWS] = (cr[SHADOWS] > 0) ? f2: f0;
cyan_red_transfer[MIDTONES] = f2;
cyan_red_transfer[HIGHLIGHTS] = (cr[HIGHLIGHTS] > 0) ? f1 : f2;
magenta_green_transfer[SHADOWS] = (mg[SHADOWS] > 0) ? f2 : f0;
magenta_green_transfer[MIDTONES] = f2;
magenta_green_transfer[HIGHLIGHTS] = (mg[HIGHLIGHTS] > 0) ? f1 : f2;
yellow_blue_transfer[SHADOWS] = (yb[SHADOWS] > 0) ? f2 : f0;
yellow_blue_transfer[MIDTONES] = f2;
yellow_blue_transfer[HIGHLIGHTS] = (yb[HIGHLIGHTS] > 0) ? f1 : f2;
s = (guint16 *)pixelrow_data (src_row);
d = (guint16 *)pixelrow_data (dest_row);
has_alpha = tag_alpha (src_tag) == ALPHA_YES? TRUE: FALSE;
while (w--)
{
r = r_n = FLT (s[RED_PIX], u);
g = g_n = FLT (s[GREEN_PIX], u);
b = b_n = FLT (s[BLUE_PIX], u);
r_n += cr_shadows * cyan_red_transfer[SHADOWS](r_n);
r_n = BOUNDS (r_n, 0, 1.0);
r_n += cr_midtones * cyan_red_transfer[MIDTONES](r_n);
r_n = BOUNDS (r_n, 0, 1.0);
r_n += cr_highlights * cyan_red_transfer[HIGHLIGHTS](r_n);
r_n = BOUNDS (r_n, 0, 1.0);
g_n += mg_shadows * magenta_green_transfer[SHADOWS](g_n);
g_n = BOUNDS (g_n, 0, 1.0);
g_n += mg_midtones * magenta_green_transfer[MIDTONES](g_n);
g_n = BOUNDS (g_n, 0, 1.0);
g_n += mg_highlights * magenta_green_transfer[HIGHLIGHTS](g_n);
g_n = BOUNDS (g_n, 0, 1.0);
b_n += yb_shadows * yellow_blue_transfer[SHADOWS](b_n);
b_n = BOUNDS (b_n, 0, 1.0);
b_n += yb_midtones * yellow_blue_transfer[MIDTONES](b_n);
b_n = BOUNDS (b_n, 0, 1.0);
b_n += yb_highlights * yellow_blue_transfer[HIGHLIGHTS](b_n);
b_n = BOUNDS (b_n, 0, 1.0);
if (preserve_luminosity)
{
#if 0
rgb_to_hls (&r, &g, &b);
rgb_to_hls (&r_n, &g_n, &b_n);
g_n = g;
hls_to_rgb (&r_n, &g_n, &b_n);
#endif
}
d[RED_PIX] = FLT16 (r_n, u);
d[GREEN_PIX] = FLT16 (g_n, u);
d[BLUE_PIX] = FLT16 (b_n, u);
if (has_alpha)
d[ALPHA_PIX] = s[ALPHA_PIX];
s += src_num_channels;
d += dest_num_channels;
}
}
static void
color_balance_allocate_transfer_arrays (gint size)
{
highlights_add_ptr = (gdouble *)g_malloc ( sizeof (gdouble) * size );
midtones_add_ptr = (gdouble *)g_malloc ( sizeof (gdouble) * size );
shadows_add_ptr = (gdouble *)g_malloc ( sizeof (gdouble) * size );
highlights_sub_ptr = (gdouble *)g_malloc ( sizeof (gdouble) * size );
midtones_sub_ptr = (gdouble *)g_malloc ( sizeof (gdouble) * size );
shadows_sub_ptr = (gdouble *)g_malloc ( sizeof (gdouble) * size );
}
static void
color_balance_free_transfer_arrays (void)
{
if (highlights_add_ptr)
g_free (highlights_add_ptr);
if (midtones_add_ptr)
g_free (midtones_add_ptr);
if (shadows_add_ptr)
g_free (shadows_add_ptr);
if (highlights_sub_ptr)
g_free (highlights_sub_ptr);
if (midtones_sub_ptr)
g_free (midtones_sub_ptr);
if (shadows_sub_ptr)
g_free (shadows_sub_ptr);
highlights_add_ptr = NULL;
midtones_add_ptr = NULL;
shadows_add_ptr = NULL;
highlights_sub_ptr = NULL;
midtones_sub_ptr = NULL;
shadows_sub_ptr = NULL;
}
static void
color_balance_init_transfers_u8 (void)
{
gint i;
color_balance_allocate_transfer_arrays (256);
for (i = 0; i < 256; i++)
{
highlights_add_ptr[i] = shadows_sub_ptr[255 - i] = f1_u8 ((double)i);
midtones_add_ptr[i] = midtones_sub_ptr[i] = f2_u8 ((double)i);
shadows_add_ptr[i] = highlights_sub_ptr[i] = f2_u8 ((double)i);
}
}
static void
color_balance_init_transfers_u16 (void)
{
gdouble x;
gint i;
color_balance_allocate_transfer_arrays (65536);
for (i = 0; i < 65536; i++)
{
x = ((double)i/65535.0);
highlights_add_ptr[i] = shadows_sub_ptr[65535 - i] = f1(x);
midtones_add_ptr[i] = midtones_sub_ptr[i] = f2(x);
shadows_add_ptr[i] = highlights_sub_ptr[i] = f2(x);
}
}
static void
color_balance_init_transfers_float (void)
{
}
static void
color_balance_init_transfers_float16 (void)
{
}
static
gdouble f0_u8(
gdouble x
)
{
return 1.075 - 1/((255.0-x)/16.0 + 1);
}
static
gdouble f1_u8(
gdouble x
)
{
return 1.075 - 1/(x/16.0 + 1);
}
static
gdouble f0(
gdouble x
)
{
return 1.075 - 1.0 /(.0625 * (1.0-x) + 1.0);
}
static
gdouble f1(
gdouble x
)
{
return 1.075 - 1.0 /(.0625 * x + 1.0);
}
/* Formula for midtones_add, midtones_sub,
shadows_add and highlights_sub arrays [0-255] based*/
static
gdouble f2_u8(
gdouble x
)
{
return 0.667 * (1 - SQR ((x - 127.0) / 127.0));
}
static
gdouble f2(
gdouble x
)
{
return .667 * (1.0 - SQR ( 2.0 * x - 1.0));
}
/* by_color select action functions */
static void
@@ -206,6 +722,10 @@ color_balance_button_press (Tool *tool,
GdkEventButton *bevent,
gpointer gdisp_ptr)
{
GDisplay *gdisp;
gdisp = gdisp_ptr;
tool->drawable = gimage_active_drawable (gdisp->gimage);
}
static void
@@ -251,7 +771,10 @@ color_balance_control (Tool *tool,
case HALT :
if (color_balance_dialog)
{
active_tool->preserve = TRUE;
image_map_abort (color_balance_dialog->image_map);
active_tool->preserve = FALSE;
color_balance_free_transfer_arrays();
color_balance_dialog->image_map = NULL;
color_balance_cancel_callback (NULL, (gpointer) color_balance_dialog);
}
@@ -283,6 +806,9 @@ tools_new_color_balance ()
tool->arrow_keys_func = standard_arrow_keys_func;
tool->cursor_update_func = color_balance_cursor_update;
tool->control_func = color_balance_control;
tool->preserve = FALSE;
tool->gdisp_ptr = NULL;
tool->drawable = NULL;
return tool;
}
@@ -296,7 +822,7 @@ tools_free_color_balance (Tool *tool)
/* Close the color select dialog */
if (color_balance_dialog)
color_balance_ok_callback (NULL, (gpointer) color_balance_dialog);
color_balance_cancel_callback (NULL, (gpointer) color_balance_dialog);
g_free (color_bal);
}
@@ -305,13 +831,14 @@ void
color_balance_initialize (void *gdisp_ptr)
{
GDisplay *gdisp;
GimpDrawable *drawable;
int i;
gdisp = (GDisplay *) gdisp_ptr;
if (! drawable_color (gimage_active_drawable (gdisp->gimage)))
{
message_box ("Color balance operates only on RGB color drawables.", NULL, NULL);
g_message ("Color balance operates only on RGB color drawables.");
return;
}
@@ -330,14 +857,22 @@ color_balance_initialize (void *gdisp_ptr)
color_balance_dialog->magenta_green[i] = 0.0;
color_balance_dialog->yellow_blue[i] = 0.0;
}
color_balance_dialog->drawable = gimage_active_drawable (gdisp->gimage);
drawable = gimage_active_drawable (gdisp->gimage);
/* Set up the function pointers for our data type */
color_balance_funcs (drawable_tag (drawable));
/* Init the transfer arrays */
(*color_balance_init_transfers) ();
color_balance_dialog->drawable = drawable;
color_balance_dialog->image_map = image_map_create (gdisp_ptr, color_balance_dialog->drawable);
color_balance_update (color_balance_dialog, ALL);
}
/****************************/
/* Select by Color dialog */
/* Color Balance dialog */
/****************************/
/* the action area structure */
@@ -347,7 +882,7 @@ static ActionAreaItem action_items[] =
{ "Cancel", color_balance_cancel_callback, NULL, NULL }
};
ColorBalanceDialog *
static ColorBalanceDialog *
color_balance_new_dialog ()
{
ColorBalanceDialog *cbd;
@@ -383,6 +918,7 @@ color_balance_new_dialog ()
/* The shell and main vbox */
cbd->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (cbd->shell), "color_balance", "Gimp");
gtk_window_set_title (GTK_WINDOW (cbd->shell), "Color Balance");
/* handle the wm close signal */
@@ -611,8 +1147,10 @@ static void
color_balance_preview (ColorBalanceDialog *cbd)
{
if (!cbd->image_map)
g_warning ("No image map");
g_message ("color_balance_preview(): No image map");
active_tool->preserve = TRUE;
image_map_apply (cbd->image_map, color_balance, (void *) cbd);
active_tool->preserve = FALSE;
}
static void
@@ -625,12 +1163,19 @@ color_balance_ok_callback (GtkWidget *widget,
if (GTK_WIDGET_VISIBLE (cbd->shell))
gtk_widget_hide (cbd->shell);
active_tool->preserve = TRUE;
if (!cbd->preview)
image_map_apply (cbd->image_map, color_balance, (void *) cbd);
if (cbd->image_map)
{
image_map_commit (cbd->image_map);
color_balance_free_transfer_arrays();
}
active_tool->preserve = FALSE;
cbd->image_map = NULL;
}
@@ -642,7 +1187,7 @@ color_balance_delete_callback (GtkWidget *w,
{
color_balance_cancel_callback (w, client_data);
return FALSE;
return TRUE;
}
static void
@@ -657,7 +1202,10 @@ color_balance_cancel_callback (GtkWidget *widget,
if (cbd->image_map)
{
active_tool->preserve = TRUE;
image_map_abort (cbd->image_map);
active_tool->preserve = FALSE;
color_balance_free_transfer_arrays();
gdisplays_flush ();
}
@@ -916,7 +1464,7 @@ ProcRecord color_balance_proc =
static Argument *
color_balance_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
PixelArea src_area, dest_area;
int success = TRUE;
int int_value;
ColorBalanceDialog cbd;
@@ -953,6 +1501,10 @@ color_balance_invoker (Argument *args)
if (drawable == NULL || gimage != drawable_gimage (drawable))
success = FALSE;
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
/* transfer_mode */
if (success)
{
@@ -1017,11 +1569,15 @@ color_balance_invoker (Argument *args)
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
pixelarea_init (&src_area, drawable_data (drawable),
x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixelarea_init (&dest_area, drawable_shadow (drawable),
x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
color_balance (&srcPR, &destPR, (void *) &cbd);
for (pr = pixelarea_register (2, &src_area, &dest_area);
pr != NULL;
pr = pixelarea_process (pr))
color_balance (&src_area, &dest_area, (void *) &cbd);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __COLOR_BALANCE_H__
#define __COLOR_BALANCE_H__

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CURVES_H__
#define __CURVES_H__

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __HUE_SATURATION_H__
#define __HUE_SATURATION_H__

View File

@@ -13,14 +13,13 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "appenv.h"
#include "linked.h"
#include "pixel_region.h"
#include "tile_manager_pvt.h"
@@ -40,7 +39,7 @@ typedef struct _PixelRegionIterator PixelRegionIterator;
struct _PixelRegionIterator
{
link_ptr pixel_regions;
GSList *pixel_regions;
int region_width;
int region_height;
int portion_width;
@@ -292,7 +291,7 @@ pixel_regions_register (int num_regions, ...)
}
/* Add the pixel region holder to the list */
PRI->pixel_regions = add_to_list (PRI->pixel_regions, PRH);
PRI->pixel_regions = g_slist_prepend (PRI->pixel_regions, PRH);
}
va_end (ap);
@@ -305,7 +304,7 @@ void *
pixel_regions_process (PRI_ptr)
void *PRI_ptr;
{
link_ptr list;
GSList *list;
PixelRegionHolder *PRH;
PixelRegionIterator *PRI;
@@ -342,7 +341,7 @@ pixel_regions_process (PRI_ptr)
}
}
list = next_item (list);
list = g_slist_next (list);
}
return pixel_regions_configure (PRI);
@@ -352,7 +351,7 @@ void
pixel_regions_process_stop (PRI_ptr)
void *PRI_ptr;
{
link_ptr list;
GSList *list;
PixelRegionHolder *PRH;
PixelRegionIterator *PRI;
@@ -381,7 +380,7 @@ pixel_regions_process_stop (PRI_ptr)
}
}
list = next_item (list);
list = g_slist_next (list);
}
if (PRI->pixel_regions)
@@ -390,9 +389,9 @@ pixel_regions_process_stop (PRI_ptr)
while (list)
{
g_free (list->data);
list = next_item (list);
list = g_slist_next (list);
}
free_list (PRI->pixel_regions);
g_slist_free (PRI->pixel_regions);
g_free (PRI);
}
}
@@ -405,7 +404,7 @@ static int
get_portion_height (PRI)
PixelRegionIterator *PRI;
{
link_ptr list;
GSList *list;
PixelRegionHolder *PRH;
int min_height = G_MAXINT;
int height;
@@ -437,7 +436,7 @@ get_portion_height (PRI)
min_height = height;
}
list = next_item (list);
list = g_slist_next (list);
}
return min_height;
@@ -448,7 +447,7 @@ static int
get_portion_width (PRI)
PixelRegionIterator *PRI;
{
link_ptr list;
GSList *list;
PixelRegionHolder *PRH;
int min_width = G_MAXINT;
int width;
@@ -480,7 +479,7 @@ get_portion_width (PRI)
min_width = width;
}
list = next_item (list);
list = g_slist_next (list);
}
return min_width;
@@ -492,7 +491,7 @@ pixel_regions_configure (PRI)
PixelRegionIterator *PRI;
{
PixelRegionHolder *PRH;
link_ptr list;
GSList *list;
/* Determine the portion width and height */
PRI->portion_width = get_portion_width (PRI);
@@ -507,9 +506,9 @@ pixel_regions_configure (PRI)
while (list)
{
g_free (list->data);
list = next_item (list);
list = g_slist_next (list);
}
free_list (PRI->pixel_regions);
g_slist_free (PRI->pixel_regions);
g_free (PRI);
}
@@ -529,7 +528,7 @@ pixel_regions_configure (PRI)
pixel_region_configure (PRH, PRI);
}
list = next_item (list);
list = g_slist_next (list);
}
return PRI;

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __PIXEL_REGION_H__
#define __PIXEL_REGION_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <errno.h>
#include <stdlib.h>
@@ -68,10 +68,11 @@ temp_buf_to_color (src_buf, dest_buf)
while (num_bytes--)
{
unsigned char tmpch;
*dest++ = *src++; /* alpha channel */
*dest++ = *src;
*dest++ = *src;
*dest++ = *src++;
*dest++ = tmpch = *src++;
*dest++ = tmpch;
*dest++ = tmpch;
}
}
@@ -115,7 +116,7 @@ temp_buf_new (width, height, bytes, x, y, col)
{
long i;
int j;
unsigned char * init, * data;
unsigned char * data;
TempBuf * temp;
temp = (TempBuf *) g_malloc (sizeof (TempBuf));
@@ -128,21 +129,46 @@ temp_buf_new (width, height, bytes, x, y, col)
temp->swapped = FALSE;
temp->filename = NULL;
temp->data = temp_buf_allocate (width * height * bytes);
temp->data = data = temp_buf_allocate (width * height * bytes);
/* initialize the data */
if (col)
{
i = width * height;
data = temp->data;
while (i--)
{
j = bytes;
init = col;
while (j--)
*data++ = *init++;
}
/* First check if we can save a lot of work */
if (bytes == 1)
{
memset (data, *col, width * height);
}
else if ((bytes == 3) && (col[1] == *col) && (*col == col[2]))
{
memset (data, *col, width * height * 3);
}
else if ((bytes == 4) && (col[1] == *col) && (*col == col[2]) && (col[2] == col[3]))
{
memset (data, *col, (width * height) << 2);
}
else
{
/* No, we cannot */
unsigned char * dptr;
/* Fill the first row */
dptr = data;
for (i = width - 1; i >= 0; --i)
{
unsigned char * init;
j = bytes;
init = col;
while (j--)
*dptr++ = *init++;
}
/* Now copy from it (we set bytes to bytesperrow now) */
bytes *= width;
while (--height)
{
memcpy (dptr, data, bytes);
dptr += bytes;
}
}
}
return temp;
@@ -159,7 +185,7 @@ temp_buf_copy (src, dest)
if (!src)
{
warning ("trying to copy a temp buf which is NULL.");
g_message ("trying to copy a temp buf which is NULL.");
return dest;
}
@@ -169,25 +195,24 @@ temp_buf_copy (src, dest)
{
new = dest;
if (dest->width != src->width || dest->height != src->height)
warning ("In temp_buf_copy, the widths or heights don't match.");
g_message ("In temp_buf_copy, the widths or heights don't match.");
/* The temp buf is smart, and can translate between color and gray */
/* (only necessary if not we allocated it */
if (src->bytes != new->bytes)
{
if (src->bytes == 4) /* RGB color */
temp_buf_to_gray (src, new);
else if (src->bytes == 2) /* grayscale */
temp_buf_to_color (src, new);
else
g_message ("Cannot convert from indexed color.");
return new;
}
}
/* The temp buf is smart, and can translate between color and gray */
if (src->bytes != new->bytes)
{
if (src->bytes == 4) /* RGB color */
temp_buf_to_gray (src, new);
else if (src->bytes == 2) /* grayscale */
temp_buf_to_color (src, new);
else
warning ("Cannot convert from indexed color.");
}
else
{
/* make the copy */
length = src->width * src->height * src->bytes;
memcpy (temp_buf_data (new), temp_buf_data (src), length);
}
/* make the copy */
length = src->width * src->height * src->bytes;
memcpy (temp_buf_data (new), temp_buf_data (src), length);
return new;
}
@@ -246,7 +271,7 @@ temp_buf_copy_area (src, dest, x, y, w, h, border)
if (!src)
{
warning ("trying to copy a temp buf which is NULL.");
g_message ("trying to copy a temp buf which is NULL.");
return dest;
}
@@ -270,7 +295,7 @@ temp_buf_copy_area (src, dest, x, y, w, h, border)
{
new = dest;
if (dest->bytes != src->bytes)
warning ("In temp_buf_copy_area, the widths or heights or bytes don't match.");
g_message ("In temp_buf_copy_area, the widths or heights or bytes don't match.");
}
/* Set the offsets for the dest */
@@ -287,7 +312,8 @@ temp_buf_copy_area (src, dest, x, y, w, h, border)
destR.rowstride = new->bytes * new->width;
destR.data = temp_buf_data (new) + (y1 - y) * destR.rowstride + (x1 - x) * srcR.bytes;
copy_region (&srcR, &destR);
/* paint_funcs.c is no longer being built */
/* copy_region (&srcR, &destR); */
return new;
}
@@ -439,7 +465,7 @@ temp_buf_swap (buf)
{
if (stat_buf.st_mode & S_IFDIR)
{
warning ("Error in temp buf caching: \"%s\" is a directory (cannot overwrite)",
g_message ("Error in temp buf caching: \"%s\" is a directory (cannot overwrite)",
filename);
g_free (filename);
return;
@@ -455,7 +481,7 @@ temp_buf_swap (buf)
else
{
perror ("Error in temp buf caching");
warning ("Cannot write \"%s\"", filename);
g_message ("Cannot write \"%s\"", filename);
g_free (filename);
return;
}
@@ -473,6 +499,7 @@ temp_buf_unswap (buf)
{
struct stat stat_buf;
FILE * fp;
gboolean succ = FALSE;
if (!buf || !buf->swapped)
return;
@@ -491,12 +518,18 @@ temp_buf_unswap (buf)
buf->data = temp_buf_allocate (buf->width * buf->height * buf->bytes);
/* Find out if the filename of the swapped data is an existing file... */
/* (buf->filname HAS to be != 0 */
if (!stat (buf->filename, &stat_buf))
{
if ((fp = fopen (buf->filename, "r")))
{
fread (buf->data, buf->width * buf->height * buf->bytes, 1, fp);
size_t blocksRead;
blocksRead = fread (buf->data, buf->width * buf->height * buf->bytes, 1, fp);
fclose (fp);
if (blocksRead != 1)
perror ("Read error on temp buf");
else
succ = TRUE;
}
else
perror ("Error in temp buf caching");
@@ -504,11 +537,10 @@ temp_buf_unswap (buf)
/* Delete the swap file */
unlink (buf->filename);
}
else
warning ("Error in temp buf caching: information swapped to disk was lost!");
if (!succ)
g_message ("Error in temp buf caching: information swapped to disk was lost!");
if (buf->filename)
g_free (buf->filename); /* free filename */
g_free (buf->filename); /* free filename */
buf->filename = NULL;
}
@@ -539,7 +571,7 @@ temp_buf_swap_free (buf)
unlink (buf->filename);
}
else
warning ("Error in temp buf disk swapping: information swapped to disk was lost!");
g_message ("Error in temp buf disk swapping: information swapped to disk was lost!");
if (buf->filename)
g_free (buf->filename); /* free filename */

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __TEMP_BUF_H__
#define __TEMP_BUF_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
@@ -27,6 +27,7 @@
#include "image_map.h"
#include "interface.h"
#include "threshold.h"
#include "pixelarea.h"
#define TEXT_WIDTH 45
#define HISTOGRAM_WIDTH 256
@@ -53,6 +54,7 @@ struct _ThresholdDialog
int color;
int low_threshold;
int high_threshold;
int bins;
gint preview;
};
@@ -66,7 +68,7 @@ static void threshold_cursor_update (Tool *, GdkEventMotion *, gpointer);
static void threshold_control (Tool *, int, gpointer);
static ThresholdDialog * threshold_new_dialog (void);
static ThresholdDialog * threshold_new_dialog (gint);
static void threshold_preview (ThresholdDialog *);
static void threshold_ok_callback (GtkWidget *, gpointer);
static void threshold_cancel_callback (GtkWidget *, gpointer);
@@ -78,127 +80,269 @@ static void threshold_high_threshold_text_update (GtkWidget *, gpo
static void *threshold_options = NULL;
static ThresholdDialog *threshold_dialog = NULL;
static void threshold (PixelRegion *, PixelRegion *, void *);
static void threshold_histogram_info (PixelRegion *, PixelRegion *, HistogramValues, void *);
static void threshold_histogram_range (int, int, HistogramValues, void *);
static void threshold (PixelArea *, PixelArea *, void *);
static void threshold_histogram_info (PixelArea *, PixelArea *, HistogramValues, void *);
static void threshold_histogram_range (int, int, int, HistogramValues, void *);
static Argument * threshold_invoker (Argument *);
/* threshold machinery */
/*
* TBD -WRB need to make work with float data
*/
static void
threshold (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
threshold (PixelArea *src_area,
PixelArea *dest_area,
void *user_data)
{
ThresholdDialog *td;
unsigned char *src, *s;
unsigned char *dest, *d;
int has_alpha, alpha;
int w, h, b;
int value;
gint has_alpha;
gint w, h, b;
guint8 *src, *dest;
Tag src_tag = pixelarea_tag (src_area);
gint s_num_channels = tag_num_channels (src_tag);
gint alpha = tag_alpha (src_tag);
Tag dest_tag = pixelarea_tag (dest_area);
gint d_num_channels = tag_num_channels (dest_tag);
td = (ThresholdDialog *) user_data;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
h = pixelarea_height (src_area);
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
if (td->color)
{
value = MAX (s[RED_PIX], s[GREEN_PIX]);
value = MAX (value, s[BLUE_PIX]);
has_alpha = (alpha == ALPHA_YES) ? TRUE: FALSE;
alpha = has_alpha ? s_num_channels - 1 : s_num_channels;
value = (value >= td->low_threshold && value <= td->high_threshold ) ? 255 : 0;
}
else
value = (s[GRAY_PIX] >= td->low_threshold && s[GRAY_PIX] <= td->high_threshold) ? 255 : 0;
if( tag_precision( src_tag ) != tag_precision( dest_tag ) )
{
g_warning( "threshold: src & dest not same bit depth." );
return;
}
for (b = 0; b < alpha; b++)
d[b] = value;
src = (guint8*)pixelarea_data (src_area);
dest = (guint8*)pixelarea_data (dest_area);
if (has_alpha)
d[alpha] = s[alpha];
switch( tag_precision( dest_tag ) )
{
case PRECISION_U8:
{
guint8 *s, *d;
gint value;
s += srcPR->bytes;
d += destPR->bytes;
}
while (h--)
{
w = pixelarea_width (src_area);
s = src;
d = dest;
while (w--)
{
if (td->color)
{
value = MAX (s[RED_PIX], s[GREEN_PIX]);
value = MAX (value, s[BLUE_PIX]);
src += srcPR->rowstride;
dest += destPR->rowstride;
}
value = (value >= td->low_threshold && value <= td->high_threshold ) ? 255 : 0;
}
else
value = (s[GRAY_PIX] >= td->low_threshold && s[GRAY_PIX] <= td->high_threshold) ? 255 : 0;
for (b = 0; b < alpha; b++)
d[b] = value;
if (has_alpha)
d[alpha] = s[alpha];
s += s_num_channels;
d += d_num_channels;
}
src += pixelarea_rowstride (src_area);
dest += pixelarea_rowstride (dest_area);
}
break;
}
case PRECISION_U16:
{
guint16 *s, *d;
gint value;
while (h--)
{
w = pixelarea_width (src_area);
s = (guint16*)src;
d = (guint16*)dest;
while (w--)
{
if (td->color)
{
value = MAX (s[RED_PIX], s[GREEN_PIX]);
value = MAX (value, s[BLUE_PIX]);
value = (value >= td->low_threshold && value <= td->high_threshold ) ? 65535 : 0;
}
else
value = (s[GRAY_PIX] >= td->low_threshold && s[GRAY_PIX] <= td->high_threshold) ? 65535 : 0;
for (b = 0; b < alpha; b++)
d[b] = value;
if (has_alpha)
d[alpha] = s[alpha];
s += s_num_channels;
d += d_num_channels;
}
src += pixelarea_rowstride (src_area);
dest += pixelarea_rowstride (dest_area);
}
break;
}
case PRECISION_FLOAT:
{
g_warning( "threshold_float not implemented yet." );
break;
}
}
}
/*
* TBD -WRB need to make work with float data
*/
static void
threshold_histogram_info (PixelRegion *srcPR,
PixelRegion *maskPR,
threshold_histogram_info (PixelArea *src_area,
PixelArea *mask_area,
HistogramValues values,
void *user_data)
{
ThresholdDialog *td;
unsigned char *src, *s;
unsigned char *mask, *m;
int w, h;
int value;
gint has_alpha;
int w, h;
int value;
guint8 *src, *mask = NULL;
mask = NULL;
m = NULL;
Tag src_tag = pixelarea_tag (src_area);
gint s_num_channels = tag_num_channels (src_tag);
gint alpha = tag_alpha (src_tag);
Tag mask_tag = pixelarea_tag (mask_area);
gint m_num_channels = tag_num_channels (mask_tag);
if( mask_area && (tag_precision( src_tag ) != tag_precision( mask_tag )) )
{
g_warning( "threshold: src & mask not same bit depth." );
return;
}
td = (ThresholdDialog *) user_data;
h = srcPR->h;
src = srcPR->data;
h = pixelarea_height (src_area);
if (maskPR)
mask = maskPR->data;
has_alpha = (alpha == ALPHA_YES) ? TRUE: FALSE;
alpha = has_alpha ? s_num_channels - 1 : s_num_channels;
while (h--)
{
w = srcPR->w;
s = src;
src = (guint8*)pixelarea_data (src_area);
if (maskPR)
m = mask;
if (mask_area)
mask = (guint8*)pixelarea_data (mask_area);
while (w--)
{
if (td->color)
{
value = MAX (s[RED_PIX], s[GREEN_PIX]);
value = MAX (value, s[BLUE_PIX]);
}
else
value = s[GRAY_PIX];
switch( tag_precision( src_tag ) )
{
case PRECISION_U8:
{
guint8 *s, *m = NULL;
gint value;
if (maskPR)
values[HISTOGRAM_VALUE][value] += (double) *m / 255.0;
else
values[HISTOGRAM_VALUE][value] += 1.0;
while (h--)
{
w = pixelarea_width (src_area);
s = src;
s += srcPR->bytes;
if (mask_area)
m = mask;
if (maskPR)
m += maskPR->bytes;
}
while (w--)
{
if (td->color)
{
value = MAX (s[RED_PIX], s[GREEN_PIX]);
value = MAX (value, s[BLUE_PIX]);
}
else
value = s[GRAY_PIX];
src += srcPR->rowstride;
if (mask_area)
values[HISTOGRAM_VALUE][value] += (double) *m / 255.0;
else
values[HISTOGRAM_VALUE][value] += 1.0;
if (maskPR)
mask += maskPR->rowstride;
}
s += s_num_channels;
if (mask_area)
m += m_num_channels;
}
src += pixelarea_rowstride (src_area);
if (mask_area)
mask += pixelarea_rowstride (mask_area);
}
break;
}
case PRECISION_U16:
{
guint16 *s, *m = NULL;
gint value;
while (h--)
{
w = pixelarea_width (src_area);
s = (guint16*)src;
if (mask_area)
m = (guint16*)mask;
while (w--)
{
if (td->color)
{
value = MAX (s[RED_PIX], s[GREEN_PIX]);
value = MAX (value, s[BLUE_PIX]);
}
else
value = s[GRAY_PIX];
if (mask_area)
values[HISTOGRAM_VALUE][value] += (double) *m / 65535.0;
else
values[HISTOGRAM_VALUE][value] += 1.0;
s += s_num_channels;
if (mask_area)
m += m_num_channels;
}
src += pixelarea_rowstride (src_area);
if (mask_area)
mask += pixelarea_rowstride (mask_area);
}
break;
}
case PRECISION_FLOAT:
{
g_warning( "threshold_float not implemented yet." );
break;
}
}
}
static void
threshold_histogram_range (int start,
int end,
int bins,
HistogramValues values,
void *user_data)
{
@@ -209,6 +353,7 @@ threshold_histogram_range (int start,
td->low_threshold = start;
td->high_threshold = end;
td->bins = bins;
sprintf (text, "%d", start);
gtk_entry_set_text (GTK_ENTRY (td->low_threshold_text), text);
sprintf (text, "%d", end);
@@ -225,6 +370,10 @@ threshold_button_press (Tool *tool,
GdkEventButton *bevent,
gpointer gdisp_ptr)
{
GDisplay *gdisp;
gdisp = gdisp_ptr;
tool->drawable = gimage_active_drawable (gdisp->gimage);
}
static void
@@ -270,7 +419,9 @@ threshold_control (Tool *tool,
case HALT :
if (threshold_dialog)
{
active_tool->preserve = TRUE;
image_map_abort (threshold_dialog->image_map);
active_tool->preserve = FALSE;
threshold_dialog->image_map = NULL;
threshold_cancel_callback (NULL, (gpointer) threshold_dialog);
}
@@ -281,19 +432,21 @@ threshold_control (Tool *tool,
Tool *
tools_new_threshold ()
{
Tool * tool;
Threshold * private;
Tool * tool;
Threshold * private;
/* The tool options */
if (!threshold_options)
threshold_options = tools_register_no_options (THRESHOLD, "Threshold Options");
#if 0
/* The threshold dialog */
if (!threshold_dialog)
threshold_dialog = threshold_new_dialog ();
else
if (!GTK_WIDGET_VISIBLE (threshold_dialog->shell))
gtk_widget_show (threshold_dialog->shell);
#endif
tool = (Tool *) g_malloc (sizeof (Tool));
private = (Threshold *) g_malloc (sizeof (Threshold));
@@ -309,6 +462,7 @@ tools_new_threshold ()
tool->arrow_keys_func = standard_arrow_keys_func;
tool->cursor_update_func = threshold_cursor_update;
tool->control_func = threshold_control;
tool->preserve = FALSE;
return tool;
}
@@ -322,7 +476,7 @@ tools_free_threshold (Tool *tool)
/* Close the color select dialog */
if (threshold_dialog)
threshold_ok_callback (NULL, (gpointer) threshold_dialog);
threshold_cancel_callback (NULL, (gpointer) threshold_dialog);
g_free (thresh);
}
@@ -331,18 +485,34 @@ void
threshold_initialize (void *gdisp_ptr)
{
GDisplay *gdisp;
gint bins;
gdisp = (GDisplay *) gdisp_ptr;
if (drawable_indexed (gimage_active_drawable (gdisp->gimage)))
{
message_box ("Threshold does not operate on indexed drawables.", NULL, NULL);
g_message ("Threshold does not operate on indexed drawables.");
return;
}
switch( tag_precision( gimage_tag( gdisp->gimage ) ) )
{
case PRECISION_U8:
bins = 256;
break;
case PRECISION_U16:
bins = 65536;
break;
case PRECISION_FLOAT:
g_warning( "histogram_float not implemented yet." );
return;
}
/* The threshold dialog */
if (!threshold_dialog)
threshold_dialog = threshold_new_dialog ();
threshold_dialog = threshold_new_dialog ( bins );
else
if (!GTK_WIDGET_VISIBLE (threshold_dialog->shell))
gtk_widget_show (threshold_dialog->shell);
@@ -373,8 +543,11 @@ static ActionAreaItem action_items[] =
{ "Cancel", threshold_cancel_callback, NULL, NULL }
};
ThresholdDialog *
threshold_new_dialog ()
/*
* TBD - WRB -make work with float data
*/
static ThresholdDialog *
threshold_new_dialog (gint bins)
{
ThresholdDialog *td;
GtkWidget *vbox;
@@ -385,11 +558,13 @@ threshold_new_dialog ()
td = g_malloc (sizeof (ThresholdDialog));
td->preview = TRUE;
td->low_threshold = 127;
td->high_threshold = 255;
td->high_threshold = bins-1;
td->low_threshold = td->high_threshold/2;
td->bins = bins;
/* The shell and main vbox */
td->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (td->shell), "threshold", "Gimp");
gtk_window_set_title (GTK_WINDOW (td->shell), "Threshold");
/* handle the wm close signal */
@@ -411,8 +586,16 @@ threshold_new_dialog ()
/* low threshold text */
td->low_threshold_text = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (td->low_threshold_text), "127");
gtk_widget_set_usize (td->low_threshold_text, TEXT_WIDTH, 25);
if( bins == 256 )
{
gtk_entry_set_text (GTK_ENTRY (td->low_threshold_text), "127");
gtk_widget_set_usize (td->low_threshold_text, TEXT_WIDTH, 25);
}
else
{
gtk_entry_set_text (GTK_ENTRY (td->low_threshold_text), "32767");
gtk_widget_set_usize (td->low_threshold_text, TEXT_WIDTH*1.5, 25);
}
gtk_box_pack_start (GTK_BOX (hbox), td->low_threshold_text, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (td->low_threshold_text), "changed",
(GtkSignalFunc) threshold_low_threshold_text_update,
@@ -421,8 +604,16 @@ threshold_new_dialog ()
/* high threshold text */
td->high_threshold_text = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY (td->high_threshold_text), "255");
gtk_widget_set_usize (td->high_threshold_text, TEXT_WIDTH, 25);
if( bins == 256 )
{
gtk_entry_set_text (GTK_ENTRY (td->high_threshold_text), "255");
gtk_widget_set_usize (td->high_threshold_text, TEXT_WIDTH, 25);
}
else
{
gtk_entry_set_text (GTK_ENTRY (td->high_threshold_text), "65535");
gtk_widget_set_usize (td->high_threshold_text, TEXT_WIDTH*1.5, 25);
}
gtk_box_pack_start (GTK_BOX (hbox), td->high_threshold_text, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (td->high_threshold_text), "changed",
(GtkSignalFunc) threshold_high_threshold_text_update,
@@ -438,7 +629,7 @@ threshold_new_dialog ()
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, FALSE, 0);
td->histogram = histogram_create (HISTOGRAM_WIDTH, HISTOGRAM_HEIGHT,
td->histogram = histogram_create (HISTOGRAM_WIDTH, HISTOGRAM_HEIGHT, bins,
threshold_histogram_range, (void *) td);
gtk_container_add (GTK_CONTAINER (frame), td->histogram->histogram_widget);
gtk_widget_show (td->histogram->histogram_widget);
@@ -480,7 +671,7 @@ static void
threshold_preview (ThresholdDialog *td)
{
if (!td->image_map)
g_warning ("No image map");
g_message ("threshold_preview(): No image map");
image_map_apply (td->image_map, threshold, (void *) td);
}
@@ -495,12 +686,15 @@ threshold_ok_callback (GtkWidget *widget,
if (GTK_WIDGET_VISIBLE (td->shell))
gtk_widget_hide (td->shell);
active_tool->preserve = TRUE;
if (!td->preview)
image_map_apply (td->image_map, threshold, (void *) td);
if (td->image_map)
image_map_commit (td->image_map);
active_tool->preserve = FALSE;
td->image_map = NULL;
}
@@ -511,7 +705,7 @@ threshold_delete_callback (GtkWidget *w,
{
threshold_cancel_callback (w, client_data);
return FALSE;
return TRUE;
}
static void
@@ -526,7 +720,9 @@ threshold_cancel_callback (GtkWidget *widget,
if (td->image_map)
{
active_tool->preserve = TRUE;
image_map_abort (td->image_map);
active_tool->preserve = FALSE;
gdisplays_flush ();
}
@@ -573,6 +769,9 @@ threshold_low_threshold_text_update (GtkWidget *w,
}
}
/*
* TBD - WRB -make work with float data
*/
static void
threshold_high_threshold_text_update (GtkWidget *w,
gpointer data)
@@ -583,7 +782,7 @@ threshold_high_threshold_text_update (GtkWidget *w,
td = (ThresholdDialog *) data;
str = gtk_entry_get_text (GTK_ENTRY (w));
value = BOUNDS (((int) atof (str)), td->low_threshold, 255);
value = BOUNDS (((int) atof (str)), td->low_threshold, td->bins-1);
if (value != td->high_threshold)
{
@@ -610,11 +809,11 @@ ProcArg threshold_args[] =
},
{ PDB_INT32,
"low_threshold",
"the low threshold value: (0 <= low_threshold <= 255)"
"the low threshold value: (0 <= low_threshold <= maxbright)"
},
{ PDB_INT32,
"high_threshold",
"the high threshold value: (0 <= high_threshold <= 255)"
"the high threshold value: (0 <= high_threshold <= maxbright)"
}
};
@@ -641,11 +840,14 @@ ProcRecord threshold_proc =
};
/*
* TBD - WRB -make work with float data
*/
static Argument *
threshold_invoker (args)
Argument *args;
{
PixelRegion srcPR, destPR;
PixelArea src_area, dest_area;
int success = TRUE;
ThresholdDialog td;
GImage *gimage;
@@ -653,6 +855,7 @@ threshold_invoker (args)
int low_threshold;
int high_threshold;
int int_value;
int max, bins;
int x1, y1, x2, y2;
void *pr;
@@ -675,11 +878,35 @@ threshold_invoker (args)
if (drawable == NULL || gimage != drawable_gimage (drawable))
success = FALSE;
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
if( success )
{
switch( tag_precision( gimage_tag( gimage ) ) )
{
case PRECISION_U8:
bins = 256;
max = bins-1;
break;
case PRECISION_U16:
bins = 65536;
max = bins-1;
break;
case PRECISION_FLOAT:
g_warning( "histogram_float not implemented yet." );
success = FALSE;
}
}
/* low threhsold */
if (success)
{
int_value = args[2].value.pdb_int;
if (int_value >= 0 && int_value < 256)
if (int_value >= 0 && int_value <= max)
low_threshold = int_value;
else
success = FALSE;
@@ -688,7 +915,7 @@ threshold_invoker (args)
if (success)
{
int_value = args[3].value.pdb_int;
if (int_value >= 0 && int_value < 256)
if (int_value >= 0 && int_value <= max)
high_threshold = int_value;
else
success = FALSE;
@@ -706,15 +933,14 @@ threshold_invoker (args)
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
pixelarea_init (&src_area, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixelarea_init (&dest_area, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
threshold (&srcPR, &destPR, (void *) &td);
for (pr = pixelarea_register (2, &src_area, &dest_area); pr != NULL; pr = pixelarea_process (pr))
threshold (&src_area, &dest_area, (void *) &td);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}
return procedural_db_return_args (&threshold_proc, success);
}

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __THRESHOLD_H__
#define __THRESHOLD_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __TILE_MANAGER_PVT_H__
#define __TILE_MANAGER_PVT_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "tile_cache.h"
@@ -35,6 +35,8 @@ tile_manager_new (int toplevel_width,
int width, height;
int i;
g_warning ("tile_manager_new() was called");
tm = g_new (TileManager, 1);
tmp1 = tile_manager_calc_levels (toplevel_width, TILE_WIDTH);

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __TILE_MANAGER_H__
#define __TILE_MANAGER_H__

View File

@@ -70,13 +70,14 @@ static Gap* tile_swap_gap_new (long start,
static void tile_swap_gap_destroy (Gap *gap);
static initialize = TRUE;
static int initialize = TRUE;
static GHashTable *swap_files = NULL;
static GList *open_swap_files = NULL;
static int nopen_swap_files = 0;
static int next_swap_num = 1;
static long swap_file_grow = 16 * TILE_WIDTH * TILE_HEIGHT * 4;
static gboolean seek_err_msg = TRUE, read_err_msg = TRUE, write_err_msg = TRUE;
static void
tile_swap_print_gaps (DefSwapFile *def_swap_file)
@@ -104,7 +105,7 @@ tile_swap_exit1 (gpointer key,
DefSwapFile *def_swap_file;
if (tile_ref_count != 0)
g_print ("tile ref count balance: %d\n", tile_ref_count);
g_message ("tile ref count balance: %d\n", tile_ref_count);
swap_file = value;
if (swap_file->swap_func == tile_swap_default)
@@ -112,7 +113,7 @@ tile_swap_exit1 (gpointer key,
def_swap_file = swap_file->user_data;
if (def_swap_file->swap_file_end != 0)
{
g_print ("swap file not empty: \"%s\"\n", swap_file->filename);
g_message ("swap file not empty: \"%s\"\n", swap_file->filename);
tile_swap_print_gaps (def_swap_file);
}
@@ -252,7 +253,7 @@ tile_swap_command (Tile *tile,
swap_file = g_hash_table_lookup (swap_files, &tile->swap_num);
if (!swap_file)
{
g_warning ("could not find swap file for tile");
g_message ("could not find swap file for tile");
return;
}
@@ -287,7 +288,7 @@ tile_swap_open (SwapFile *swap_file)
swap_file->fd = open (swap_file->filename, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
if (swap_file->fd == -1)
{
g_warning ("unable to open swap file...BAD THINGS WILL HAPPEN SOON");
g_message ("unable to open swap file...BAD THINGS WILL HAPPEN SOON");
return;
}
@@ -326,7 +327,7 @@ tile_swap_default (int fd,
tile_swap_default_delete (def_swap_file, fd, tile);
break;
case SWAP_COMPRESS:
g_warning ("tile_swap_default: SWAP_COMPRESS: UNFINISHED");
g_message ("tile_swap_default: SWAP_COMPRESS: UNFINISHED");
break;
}
@@ -352,7 +353,9 @@ tile_swap_default_in (DefSwapFile *def_swap_file,
offset = lseek (fd, tile->swap_offset, SEEK_SET);
if (offset == -1)
{
g_warning ("unable to seek to tile location on disk: %d", err);
if (seek_err_msg)
g_message ("unable to seek to tile location on disk: %d", err);
seek_err_msg = FALSE;
return;
}
}
@@ -369,7 +372,9 @@ tile_swap_default_in (DefSwapFile *def_swap_file,
if (err <= 0)
{
g_warning ("unable to read tile data from disk: %d ( %d ) bytes read", err, nleft);
if (read_err_msg)
g_message ("unable to read tile data from disk: %d ( %d ) bytes read", err, nleft);
read_err_msg = FALSE;
return;
}
@@ -380,6 +385,8 @@ tile_swap_default_in (DefSwapFile *def_swap_file,
/* Do not delete the swap from the file */
/* tile_swap_default_delete (def_swap_file, fd, tile); */
read_err_msg = seek_err_msg = TRUE;
}
static void
@@ -407,7 +414,9 @@ tile_swap_default_out (DefSwapFile *def_swap_file,
offset = lseek (fd, tile->swap_offset, SEEK_SET);
if (offset == -1)
{
g_warning ("unable to seek to tile location on disk: %d", errno);
if (seek_err_msg)
g_message ("unable to seek to tile location on disk: %d", errno);
seek_err_msg = FALSE;
return;
}
}
@@ -418,7 +427,9 @@ tile_swap_default_out (DefSwapFile *def_swap_file,
err = write (fd, tile->data + rbytes - nleft, nleft);
if (err <= 0)
{
g_warning ("unable to write tile data to disk: %d ( %d ) bytes written", err, nleft);
if (write_err_msg)
g_message ("unable to write tile data to disk: %d ( %d ) bytes written", err, nleft);
write_err_msg = FALSE;
return;
}
@@ -429,6 +440,8 @@ tile_swap_default_out (DefSwapFile *def_swap_file,
g_free (tile->data);
tile->data = NULL;
write_err_msg = seek_err_msg = TRUE;
}
static void

View File

@@ -84,39 +84,134 @@ batch_is_cmd (char *cmd)
return (paren_level == 0);
}
static char *
get_tok(char **rest)
{
char *tok_start, *tok;
int i,j,len,escapes;
/* Skip delimiters */
while((**rest != 0) &&
(**rest == ' ' || **rest == '\t'))
(*rest)++;
/* token starts here */
tok_start = *rest;
if(**rest == '"'){
/* Handle string */
/* Skip quote */
(*rest)++;
tok_start++;
len = 0;
escapes = 0;
/* Scan to end while skipping escaped quotes */
while((**rest != 0) &&
(**rest != '"')){
if(**rest == '\\'){
(*rest)++;
escapes++;
}
(*rest)++;
len++;
}
if(**rest == '"'){
(*rest)++;
tok = g_malloc(len+1);
}
else{
g_print("String not properly terminated.");
return NULL;
}
/* Copy the string while converting the escaped characters. */
/* Only double quote and backspace is accepted other escapes are ignored. */
j = 0;
for (i=0;i < len + escapes;i++){
if(tok_start[i] != '\\')
tok[j++] = tok_start[i];
else{
i++;
if(tok_start[i] == '"' || tok_start[i] == '\\')
tok[j++] = tok_start[i];
}
}
tok[j] = 0;
}
else{
/* Handle number or identifier */
while((**rest != 0) &&
((**rest >= 'a' && **rest <= 'z') ||
(**rest >= 'A' && **rest <= 'Z') ||
(**rest >= '0' && **rest <= '9') ||
(**rest == '-') ||
(**rest == '_')))
(*rest)++;
if (*rest != tok_start){
len = *rest - tok_start;
tok = g_malloc(len+1);
strncpy(tok,tok_start,len);
tok[len]=0;
}
else{
if(**rest == 0){
g_print("Unexpected end of command argument.");
return NULL;
}
/* One character token - normally "(" or ")" */
tok = g_malloc(2);
tok[0] = *rest[0];
tok[1] = 0;
(*rest)++;
}
}
return tok;
}
static void
batch_run_cmd (char *cmd)
{
ProcRecord *proc;
Argument *args;
Argument *vals;
char *rest;
char *cmdname;
char *tmpname;
char *t;
int i;
cmd = strchr (cmd, '(');
if (!cmd)
rest = cmd;
t = get_tok(&rest);
if (!t || t[0] != '(')
return;
cmd += 1;
g_free(t);
cmdname = cmd;
cmd = strtok (cmd, " )");
if (!cmd)
cmdname = get_tok (&rest);
if (!cmdname)
return;
t = cmdname;
while (*t)
{
if (*t == '-')
*t = '_';
t++;
}
proc = procedural_db_lookup (cmdname);
if (!proc)
{
g_print ("could not find procedure: \"%s\"\n", cmdname);
return;
/* Lame hack for "-" to "_" conversion */
t = tmpname = g_strdup (cmdname);
while (*t)
{
if (*t == '-')
*t = '_';
t++;
}
proc = procedural_db_lookup (tmpname);
if (!proc)
{
g_print ("could not find procedure: \"%s\"\n", cmdname);
return;
}
g_free (tmpname);
}
/* (gimp-procedural-db-dump "/tmp/pdb_dump") */
@@ -131,25 +226,28 @@ batch_run_cmd (char *cmd)
case PDB_INT32:
case PDB_INT16:
case PDB_INT8:
cmd = strtok (NULL, " \t)");
if (!cmd)
t = get_tok (&rest);
if (!t)
goto error;
args[i].value.pdb_int = atoi (cmd);
args[i].value.pdb_int = atoi (t);
g_free(t);
break;
case PDB_FLOAT:
cmd = strtok (NULL, " \t)");
if (!cmd)
t = get_tok (&rest);
if (!t)
goto error;
args[i].value.pdb_float = atof (cmd);
args[i].value.pdb_float = atof (t);
g_free(t);
break;
case PDB_STRING:
cmd = strtok (NULL, "\"");
if (!cmd)
t = get_tok (&rest);
if (!t)
goto error;
args[i].value.pdb_pointer = g_strdup (cmd);
args[i].value.pdb_pointer = g_strdup (t);
g_free(t);
break;
case PDB_INT32ARRAY:
case PDB_INT16ARRAY:
@@ -221,10 +319,12 @@ batch_run_cmd (char *cmd)
break;
}
g_free(cmdname);
return;
error:
g_print ("Unable to run batch command: %s because of bad arguments.\n", cmdname);
g_free(cmdname);
}
static void

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
@@ -23,10 +23,15 @@
#include "draw_core.h"
#include "edit_selection.h"
#include "errors.h"
#include "float16.h"
#include "gdisplay.h"
#include "gimage_mask.h"
#include "linked.h"
#include "gimprc.h"
#include "rect_select.h"
#include "interface.h"
#include "paint_funcs_area.h"
#include "pixelarea.h"
#include "pixelrow.h"
#define BEZIER_START 1
#define BEZIER_ADD 2
@@ -71,7 +76,7 @@ struct _bezier_select
BezierPoint *last_point; /* the last point on the curve */
int num_points; /* number of points in the curve */
Channel *mask; /* null if the curve is open */
link_ptr *scanlines; /* used in converting a curve */
GSList **scanlines; /* used in converting a curve */
};
static void bezier_select_reset (BezierSelect *);
@@ -94,9 +99,10 @@ static void bezier_draw_segment_points (BezierSelect *, GdkPoint *, int);
static void bezier_compose (BezierMatrix, BezierMatrix, BezierMatrix);
static void bezier_convert (BezierSelect *, GDisplay *, int, int);
static void bezier_convert_helper (BezierSelect *, int, int, int);
static void bezier_convert_points (BezierSelect *, GdkPoint *, int);
static void bezier_convert_line (link_ptr *, int, int, int, int);
static link_ptr bezier_insert_in_list (link_ptr, int);
static void bezier_convert_line (GSList **, int, int, int, int);
static GSList * bezier_insert_in_list (GSList *, int);
static BezierMatrix basis =
{
@@ -139,6 +145,7 @@ tools_new_bezier_select ()
tool->arrow_keys_func = standard_arrow_keys_func;
tool->cursor_update_func = rect_select_cursor_update;
tool->control_func = bezier_select_control;
tool->preserve = FALSE;
return tool;
}
@@ -172,8 +179,7 @@ bezier_select_load (void *gdisp_ptr,
gdisp = (GDisplay *) gdisp_ptr;
/* select the bezier tool */
tools_select (BEZIER_SELECT);
gtk_widget_activate (tool_widgets[tool_info[BEZIER_SELECT].toolbar_position]);
tool = active_tool;
tool->state = ACTIVE;
tool->gdisp_ptr = gdisp_ptr;
@@ -247,9 +253,10 @@ bezier_select_button_press (Tool *tool,
grab_pointer = 0;
/* If the tool was being used in another image...reset it */
if (tool->state == ACTIVE && gdisp_ptr != tool->gdisp_ptr)
if (tool->state == ACTIVE && gdisp_ptr != tool->gdisp_ptr) {
draw_core_stop(bezier_sel->core, tool);
bezier_select_reset (bezier_sel);
}
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, TRUE, 0);
/* get halfwidth in image coord */
@@ -378,7 +385,7 @@ bezier_select_button_press (Tool *tool,
points = points->next;
} while (points != start_pt);
if (!grab_pointer && channel_value (bezier_sel->mask, x, y))
if (!grab_pointer && channel_value (bezier_sel->mask, x, y) != 0)
{
/* If we're antialiased, then recompute the
* mask...
@@ -1039,17 +1046,11 @@ bezier_convert (BezierSelect *bezier_sel,
int subdivisions,
int antialias)
{
PixelRegion maskPR;
BezierPoint * points;
BezierPoint * start_pt;
link_ptr list;
unsigned char *buf, *b;
int draw_type;
int * vals, val;
int start, end;
int x, x2, w;
int i, j;
int i;
if (!bezier_sel->closed)
fatal_error ("tried to convert an open bezier curve");
@@ -1063,28 +1064,25 @@ bezier_convert (BezierSelect *bezier_sel,
/* get the new mask's maximum extents */
if (antialias)
{
buf = (unsigned char *) g_malloc (width);
width = gdisp->gimage->width * SUPERSAMPLE;
height = gdisp->gimage->height * SUPERSAMPLE;
draw_type = AA_IMAGE_COORDS;
/* allocate value array */
vals = (int *) g_malloc (sizeof (int) * width);
}
else
{
buf = NULL;
width = gdisp->gimage->width;
height = gdisp->gimage->height;
draw_type = IMAGE_COORDS;
vals = NULL;
}
/* create a new mask */
bezier_sel->mask = channel_new_mask (gdisp->gimage->ID, gdisp->gimage->width,
gdisp->gimage->height);
bezier_sel->mask = channel_ref (channel_new_mask (gdisp->gimage->ID,
gdisp->gimage->width,
gdisp->gimage->height,
tag_precision (gimage_tag (gdisp->gimage))));
/* allocate room for the scanlines */
bezier_sel->scanlines = g_malloc (sizeof (link_ptr) * height);
bezier_sel->scanlines = g_malloc (sizeof (GSList *) * height);
/* zero out the scanlines */
for (i = 0; i < height; i++)
@@ -1114,75 +1112,15 @@ bezier_convert (BezierSelect *bezier_sel,
bezier_convert_line (bezier_sel->scanlines, lastx, lasty,
bezier_sel->points->x, bezier_sel->points->y);
pixel_region_init (&maskPR, drawable_data (GIMP_DRAWABLE(bezier_sel->mask)),
0, 0,
drawable_width (GIMP_DRAWABLE(bezier_sel->mask)),
drawable_height (GIMP_DRAWABLE(bezier_sel->mask)), TRUE);
for (i = 0; i < height; i++)
{
list = bezier_sel->scanlines[i];
/* zero the vals array */
if (antialias && !(i % SUPERSAMPLE))
memset (vals, 0, width * sizeof (int));
while (list)
{
x = (long) list->data;
list = list->next;
if (!list)
warning ("cannot properly scanline convert bezier curve: %d", i);
else
{
/* bounds checking */
x = BOUNDS (x, 0, width);
x2 = BOUNDS ((long) list->data, 0, width);
w = x2 - x;
if (!antialias)
channel_add_segment (bezier_sel->mask, x, i, w, 255);
else
for (j = 0; j < w; j++)
vals[j + x] += 255;
list = next_item (list);
}
}
if (antialias && !((i+1) % SUPERSAMPLE))
{
b = buf;
start = 0;
end = width;
for (j = start; j < end; j += SUPERSAMPLE)
{
val = 0;
for (x = 0; x < SUPERSAMPLE; x++)
val += vals[j + x];
*b++ = (unsigned char) (val / SUPERSAMPLE2);
}
pixel_region_set_row (&maskPR, 0, (i / SUPERSAMPLE),
drawable_width (GIMP_DRAWABLE(bezier_sel->mask)), buf);
}
free_list (bezier_sel->scanlines[i]);
}
if (antialias)
{
g_free (vals);
g_free (buf);
}
bezier_convert_helper (bezier_sel, antialias, width, height);
g_free (bezier_sel->scanlines);
bezier_sel->scanlines = NULL;
channel_invalidate_bounds (bezier_sel->mask);
}
static void
bezier_convert_points (BezierSelect *bezier_sel,
GdkPoint *points,
@@ -1207,7 +1145,7 @@ bezier_convert_points (BezierSelect *bezier_sel,
}
static void
bezier_convert_line (link_ptr *scanlines,
bezier_convert_line (GSList ** scanlines,
int x1,
int y1,
int x2,
@@ -1323,33 +1261,467 @@ bezier_convert_line (link_ptr *scanlines,
}
}
static link_ptr
bezier_insert_in_list (link_ptr list,
static GSList *
bezier_insert_in_list (GSList * list,
int x)
{
link_ptr orig = list;
link_ptr rest;
GSList * orig = list;
GSList * rest;
if (!list)
return add_to_list (list, (void *) ((long) x));
return g_slist_prepend (list, (void *) ((long) x));
while (list)
{
rest = next_item (list);
rest = g_slist_next (list);
if (x < (long) list->data)
{
rest = add_to_list (rest, list->data);
rest = g_slist_prepend (rest, list->data);
list->next = rest;
list->data = (void *) ((long) x);
return orig;
}
else if (!rest)
{
append_to_list (list, (void *) ((long) x));
g_slist_append (list, (void *) ((long) x));
return orig;
}
list = next_item (list);
list = g_slist_next (list);
}
return orig;
}
static void
bezier_convert_helper_u8 (
BezierSelect * bezier_sel,
int antialias,
int width,
int height
)
{
PixelArea maskPR;
unsigned char *buf, *b;
int * vals, val;
int start, end;
GSList * list;
int x, x2, w;
int i, j;
if (antialias)
{
buf = (unsigned char *) g_malloc (width/SUPERSAMPLE);
vals = (int *) g_malloc (sizeof (int) * width);
}
else
{
buf = NULL;
vals = NULL;
}
pixelarea_init (&maskPR, drawable_data (GIMP_DRAWABLE(bezier_sel->mask)),
0, 0,
0, 0,
TRUE);
for (i = 0; i < height; i++)
{
list = bezier_sel->scanlines[i];
/* zero the vals array */
if (antialias && !(i % SUPERSAMPLE))
memset (vals, 0, width * sizeof (int));
while (list)
{
x = (long) list->data;
list = list->next;
if (!list)
g_message ("cannot properly scanline convert bezier curve: %d", i);
else
{
/* bounds checking */
x = BOUNDS (x, 0, width);
x2 = BOUNDS ((long) list->data, 0, width);
w = x2 - x;
if (!antialias)
channel_add_segment (bezier_sel->mask, x, i, w, 1.0);
else
for (j = 0; j < w; j++)
vals[j + x] += 255;
list = g_slist_next (list);
}
}
if (antialias && !((i+1) % SUPERSAMPLE))
{
b = buf;
start = 0;
end = width;
for (j = start; j < end; j += SUPERSAMPLE)
{
val = 0;
for (x = 0; x < SUPERSAMPLE; x++)
val += vals[j + x];
*b++ = (unsigned char) (val / SUPERSAMPLE2);
}
{
int w = drawable_width (GIMP_DRAWABLE(bezier_sel->mask));
PixelRow row;
pixelrow_init (&row, pixelarea_tag (&maskPR), (guchar*) buf, w);
pixelarea_write_row (&maskPR, &row, 0, (i / SUPERSAMPLE), w);
}
}
g_slist_free (bezier_sel->scanlines[i]);
}
if (antialias)
{
g_free (vals);
g_free (buf);
}
}
static void
bezier_convert_helper_u16 (
BezierSelect * bezier_sel,
int antialias,
int width,
int height
)
{
PixelArea maskPR;
guint16 *buf, *b;
int * vals, val;
int start, end;
GSList * list;
int x, x2, w;
int i, j;
if (antialias)
{
buf = (guint16 *) g_malloc (width/SUPERSAMPLE*sizeof (guint16));
vals = (int *) g_malloc (sizeof (int) * width);
}
else
{
buf = NULL;
vals = NULL;
}
pixelarea_init (&maskPR, drawable_data (GIMP_DRAWABLE(bezier_sel->mask)),
0, 0,
0, 0,
TRUE);
for (i = 0; i < height; i++)
{
list = bezier_sel->scanlines[i];
/* zero the vals array */
if (antialias && !(i % SUPERSAMPLE))
memset (vals, 0, width * sizeof (int));
while (list)
{
x = (long) list->data;
list = list->next;
if (!list)
g_message ("cannot properly scanline convert bezier curve: %d", i);
else
{
/* bounds checking */
x = BOUNDS (x, 0, width);
x2 = BOUNDS ((long) list->data, 0, width);
w = x2 - x;
if (!antialias)
channel_add_segment (bezier_sel->mask, x, i, w, 1.0);
else
for (j = 0; j < w; j++)
vals[j + x] += 65535;
list = g_slist_next (list);
}
}
if (antialias && !((i+1) % SUPERSAMPLE))
{
b = buf;
start = 0;
end = width;
for (j = start; j < end; j += SUPERSAMPLE)
{
val = 0;
for (x = 0; x < SUPERSAMPLE; x++)
val += vals[j + x];
*b++ = (guint16) (val / SUPERSAMPLE2);
}
{
int w = drawable_width (GIMP_DRAWABLE(bezier_sel->mask));
PixelRow row;
pixelrow_init (&row, pixelarea_tag (&maskPR), (guchar*) buf, w);
pixelarea_write_row (&maskPR, &row, 0, (i / SUPERSAMPLE), w);
}
}
g_slist_free (bezier_sel->scanlines[i]);
}
if (antialias)
{
g_free (vals);
g_free (buf);
}
}
static void
bezier_convert_helper_float (
BezierSelect * bezier_sel,
int antialias,
int width,
int height
)
{
PixelArea maskPR;
gfloat *buf, *b;
gfloat * vals, val;
int start, end;
GSList * list;
int x, x2, w;
int i, j;
if (antialias)
{
buf = (gfloat *) g_malloc (width/SUPERSAMPLE*sizeof (gfloat));
vals = (gfloat *) g_malloc (sizeof (gfloat) * width);
}
else
{
buf = NULL;
vals = NULL;
}
pixelarea_init (&maskPR, drawable_data (GIMP_DRAWABLE(bezier_sel->mask)),
0, 0,
0, 0,
TRUE);
for (i = 0; i < height; i++)
{
list = bezier_sel->scanlines[i];
/* zero the vals array */
if (antialias && !(i % SUPERSAMPLE))
memset (vals, 0, width * sizeof (gfloat));
while (list)
{
x = (long) list->data;
list = list->next;
if (!list)
g_message ("cannot properly scanline convert bezier curve: %d", i);
else
{
/* bounds checking */
x = BOUNDS (x, 0, width);
x2 = BOUNDS ((long) list->data, 0, width);
w = x2 - x;
if (!antialias)
channel_add_segment (bezier_sel->mask, x, i, w, 1.0);
else
for (j = 0; j < w; j++)
vals[j + x] += 1.0;
list = g_slist_next (list);
}
}
if (antialias && !((i+1) % SUPERSAMPLE))
{
b = buf;
start = 0;
end = width;
for (j = start; j < end; j += SUPERSAMPLE)
{
val = 0;
for (x = 0; x < SUPERSAMPLE; x++)
val += vals[j + x];
*b++ = (gfloat) (val / SUPERSAMPLE2);
}
{
int w = drawable_width (GIMP_DRAWABLE(bezier_sel->mask));
PixelRow row;
pixelrow_init (&row, pixelarea_tag (&maskPR), (guchar*) buf, w);
pixelarea_write_row (&maskPR, &row, 0, (i / SUPERSAMPLE), w);
}
}
g_slist_free (bezier_sel->scanlines[i]);
}
if (antialias)
{
g_free (vals);
g_free (buf);
}
}
static void
bezier_convert_helper_float16 (
BezierSelect * bezier_sel,
int antialias,
int width,
int height
)
{
PixelArea maskPR;
guint16 *buf, *b;
gfloat * vals, val;
int start, end;
GSList * list;
int x, x2, w;
int i, j;
ShortsFloat u;
if (antialias)
{
buf = (guint16 *) g_malloc (width/SUPERSAMPLE*sizeof (guint16));
vals = (gfloat *) g_malloc (sizeof (gfloat) * width);
}
else
{
buf = NULL;
vals = NULL;
}
pixelarea_init (&maskPR, drawable_data (GIMP_DRAWABLE(bezier_sel->mask)),
0, 0,
0, 0,
TRUE);
for (i = 0; i < height; i++)
{
list = bezier_sel->scanlines[i];
/* zero the vals array */
if (antialias && !(i % SUPERSAMPLE))
memset (vals, 0, width * sizeof (gfloat));
while (list)
{
x = (long) list->data;
list = list->next;
if (!list)
g_message ("cannot properly scanline convert bezier curve: %d", i);
else
{
/* bounds checking */
x = BOUNDS (x, 0, width);
x2 = BOUNDS ((long) list->data, 0, width);
w = x2 - x;
if (!antialias)
channel_add_segment (bezier_sel->mask, x, i, w, 1.0);
else
for (j = 0; j < w; j++)
vals[j + x] += 1.0;
list = g_slist_next (list);
}
}
if (antialias && !((i+1) % SUPERSAMPLE))
{
b = buf;
start = 0;
end = width;
for (j = start; j < end; j += SUPERSAMPLE)
{
val = 0;
for (x = 0; x < SUPERSAMPLE; x++)
val += vals[j + x];
*b++ = FLT16 ((gfloat) (val / SUPERSAMPLE2), u);
}
{
gint w = drawable_width (GIMP_DRAWABLE(bezier_sel->mask));
PixelRow row;
pixelrow_init (&row, pixelarea_tag (&maskPR), (guchar*) buf, w);
pixelarea_write_row (&maskPR, &row, 0, (i / SUPERSAMPLE), w);
}
}
g_slist_free (bezier_sel->scanlines[i]);
}
if (antialias)
{
g_free (vals);
g_free (buf);
}
}
static void
bezier_convert_helper (
BezierSelect * bezier_sel,
int antialias,
int width,
int height
)
{
switch (tag_precision (drawable_tag (GIMP_DRAWABLE (bezier_sel->mask))))
{
case PRECISION_U8:
bezier_convert_helper_u8 (bezier_sel,
antialias,
width,
height);
break;
case PRECISION_U16:
bezier_convert_helper_u16 (bezier_sel,
antialias,
width,
height);
break;
case PRECISION_FLOAT:
bezier_convert_helper_float (bezier_sel,
antialias,
width,
height);
case PRECISION_FLOAT16:
bezier_convert_helper_float16 (bezier_sel,
antialias,
width,
height);
break;
case PRECISION_NONE:
g_warning ("bezier_convert_helper bad precision");
break;
}
}

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BEZIER_SELECT_H__
#define __BEZIER_SELECT_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BEZIER_SELECTP_H__
#define __BEZIER_SELECTP_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <stdio.h>
@@ -31,18 +31,27 @@
#include "gimage_mask.h"
#include "gradient.h"
#include "interface.h"
#include "paint_funcs.h"
#include "palette.h"
#include "selection.h"
#include "tools.h"
#include "undo.h"
#include "pixelarea.h"
#include "pixelrow.h"
#include "canvas.h"
#include "paint_funcs_area.h"
/* target size */
#define TARGET_HEIGHT 15
#define TARGET_WIDTH 15
#define SQR(x) ((x) * (x))
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif /* M_PI */
/* the Blend structures */
typedef enum
@@ -70,7 +79,7 @@ typedef enum
{
REPEAT_NONE,
REPEAT_SAWTOOTH,
REPEAT_TRIANGULAR,
REPEAT_TRIANGULAR
} RepeatMode;
typedef double (*RepeatFunc)(double);
@@ -96,6 +105,7 @@ struct _BlendOptions
int paint_mode;
GradientType gradient_type;
RepeatMode repeat;
GtkWidget *repeat_mode_menu;
int supersample;
GtkWidget *frame;
int max_depth;
@@ -113,12 +123,15 @@ typedef struct {
RepeatFunc repeat_func;
} RenderBlendData;
#define FIXME
#if 0
typedef struct {
PixelRegion *PR;
PixelArea *PR;
unsigned char *row_data;
int bytes;
int width;
} PutPixelData;
#endif
/* local function prototypes */
static void blend_scale_update (GtkAdjustment *, double *);
@@ -165,17 +178,19 @@ static double gradient_repeat_none(double val);
static double gradient_repeat_sawtooth(double val);
static double gradient_repeat_triangular(double val);
static void gradient_precalc_shapeburst (GImage *gimage, GimpDrawable *drawable, PixelRegion *PR, double dist);
static void gradient_precalc_shapeburst (GImage *gimage, GimpDrawable *drawable, int x, int y, int w, int h, double dist);
static void gradient_render_pixel(double x, double y, color_t *color, void *render_data);
static void gradient_render_pixel (double x, double y, gfloat * color, void * render_data);
#define FIXME
#if 0
static void gradient_put_pixel(int x, int y, color_t color, void *put_pixel_data);
static void gradient_fill_region (GImage *gimage, GimpDrawable *drawable, PixelRegion *PR,
#endif
static void gradient_fill_region (GImage *gimage, GimpDrawable *drawable, int x, int y,
int width, int height,
BlendMode blend_mode, GradientType gradient_type,
double offset, RepeatMode repeat,
int supersample, int max_depth, double threshold,
double sx, double sy, double ex, double ey);
double sx, double sy, double ex, double ey, gfloat, int);
static void calc_rgb_to_hsv(double *r, double *g, double *b);
static void calc_hsv_to_rgb(double *h, double *s, double *v);
@@ -184,16 +199,8 @@ static BlendOptions *create_blend_options (void);
static Argument *blend_invoker (Argument *);
/* variables for the shapeburst algs */
static PixelRegion distR =
{
NULL, /* data */
NULL, /* tiles */
0, /* rowstride */
0, 0, /* w, h */
0, 0, /* x, y */
4, /* bytes */
0 /* process count */
};
static Canvas * distance_canvas;
/* the blend option menu items -- the blend modes */
static MenuItem blend_option_items[] =
@@ -246,6 +253,8 @@ gradient_type_callback (GtkWidget *w,
gpointer client_data)
{
blend_options->gradient_type = (GradientType) client_data;
gtk_widget_set_sensitive (blend_options->repeat_mode_menu,
(blend_options->gradient_type < 6));
}
static void
@@ -440,6 +449,8 @@ create_blend_options ()
gtk_widget_show(label);
gtk_widget_show(rt_option_menu);
options->repeat_mode_menu = rt_option_menu;
/* show the whole table */
gtk_widget_show (table);
@@ -538,15 +549,10 @@ blend_button_press (Tool *tool,
gdisp = (GDisplay *) gdisp_ptr;
blend_tool = (BlendTool *) tool->private;
switch (drawable_type (gimage_active_drawable (gdisp->gimage)))
if (tag_format (drawable_tag (gimage_active_drawable (gdisp->gimage))) == FORMAT_INDEXED)
{
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
message_box ("Blend: Invalid for indexed images.", NULL, NULL);
g_message ("Blend: Invalid for indexed images.");
return;
break;
default:
break;
}
/* Keep the coordinates of the target */
@@ -613,7 +619,7 @@ blend_button_release (Tool *tool,
if (return_vals[0].value.pdb_int == PDB_SUCCESS)
gdisplays_flush ();
else
message_box ("Blend operation failed.", NULL, NULL);
g_message ("Blend operation failed.");
procedural_db_destroy_args (return_vals, nreturn_vals);
}
@@ -650,9 +656,9 @@ blend_cursor_update (Tool *tool,
gdisp = (GDisplay *) gdisp_ptr;
switch (drawable_type (gimage_active_drawable (gdisp->gimage)))
switch (tag_format (drawable_tag (gimage_active_drawable (gdisp->gimage))))
{
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
case FORMAT_INDEXED:
gdisplay_install_tool_cursor (gdisp, GDK_TOP_LEFT_ARROW);
break;
default:
@@ -741,44 +747,19 @@ blend (GImage *gimage,
double endx,
double endy)
{
TileManager *buf_tiles;
PixelRegion bufPR;
int has_alpha;
int has_selection;
int bytes;
int x1, y1, x2, y2;
has_selection = drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
has_alpha = drawable_has_alpha (drawable);
bytes = drawable_bytes (drawable);
/* Always create an alpha temp buf (for generality) */
if (! has_alpha)
{
has_alpha = TRUE;
bytes += 1;
}
buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes);
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
(void) drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
gradient_fill_region (gimage, drawable,
&bufPR, (x2 - x1), (y2 - y1),
blend_mode, gradient_type, offset, repeat,
supersample, max_depth, threshold,
(startx - x1), (starty - y1),
(endx - x1), (endy - y1));
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
gimage_apply_image (gimage, drawable, &bufPR, TRUE,
(opacity * 255) / 100, paint_mode, NULL, x1, y1);
/* update the image */
x1, y1, (x2 - x1), (y2 - y1),
blend_mode, gradient_type, offset, repeat,
supersample, max_depth, threshold,
startx, starty,
endx, endy,
opacity/100.0, paint_mode);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
/* free the temporary buffer */
tile_manager_destroy (buf_tiles);
}
@@ -886,7 +867,7 @@ gradient_calc_square_factor (double dist,
offset = offset / 100.0;
r = MAXIMUM(abs(x), abs(y));
r = MAXIMUM(fabs(x), fabs(y));
rat = r / dist;
if (rat < offset)
@@ -993,20 +974,19 @@ gradient_calc_bilinear_factor (double dist,
} /* gradient_calc_bilinear_factor */
static double
gradient_calc_shapeburst_angular_factor (double x,
double y)
static double
gradient_calc_shapeburst_angular_factor (
double x,
double y
)
{
int ix, iy;
Tile *tile;
float value;
ix = (int) BOUNDS (x, 0, distR.w);
iy = (int) BOUNDS (y, 0, distR.h);
tile = tile_manager_get_tile (distR.tiles, ix, iy, 0);
tile_ref (tile);
value = 1.0 - *(((float *) tile->data) + ((iy % TILE_HEIGHT) * tile->ewidth + (ix % TILE_WIDTH)));
tile_unref (tile, FALSE);
float value = 0;
gfloat * data;
(void) canvas_portion_refro (distance_canvas, x, y);
if ((data = (gfloat*) canvas_portion_data (distance_canvas, x, y)) != NULL)
value = 1.0 - *data;
canvas_portion_unref (distance_canvas, x, y);
return value;
}
@@ -1016,37 +996,31 @@ static double
gradient_calc_shapeburst_spherical_factor (double x,
double y)
{
int ix, iy;
Tile *tile;
float value;
ix = (int) BOUNDS (x, 0, distR.w);
iy = (int) BOUNDS (y, 0, distR.h);
tile = tile_manager_get_tile (distR.tiles, ix, iy, 0);
tile_ref (tile);
value = *(((float *) tile->data) + ((iy % TILE_HEIGHT) * tile->ewidth + (ix % TILE_WIDTH)));
value = 1.0 - sin (0.5 * M_PI * value);
tile_unref (tile, FALSE);
float value = 0;
gfloat * data;
(void) canvas_portion_refro (distance_canvas, x, y);
if ((data = (gfloat*) canvas_portion_data (distance_canvas, x, y)) != NULL)
value = 1.0 - sin (0.5 * M_PI * (*data));
canvas_portion_unref (distance_canvas, x, y);
return value;
}
static double
gradient_calc_shapeburst_dimpled_factor (double x,
double y)
static double
gradient_calc_shapeburst_dimpled_factor (
double x,
double y
)
{
int ix, iy;
Tile *tile;
float value;
ix = (int) BOUNDS (x, 0, distR.w);
iy = (int) BOUNDS (y, 0, distR.h);
tile = tile_manager_get_tile (distR.tiles, ix, iy, 0);
tile_ref (tile);
value = *(((float *) tile->data) + ((iy % TILE_HEIGHT) * tile->ewidth + (ix % TILE_WIDTH)));
value = cos (0.5 * M_PI * value);
tile_unref (tile, FALSE);
float value = 0;
gfloat * data;
(void) canvas_portion_refro (distance_canvas, x, y);
if ((data = (gfloat*) canvas_portion_data (distance_canvas, x, y)) != NULL)
value = cos (0.5 * M_PI * (*data));
canvas_portion_unref (distance_canvas, x, y);
return value;
}
@@ -1082,34 +1056,38 @@ gradient_repeat_triangular(double val)
return fmod(val, 1.0);
}
/*****/
static void
gradient_precalc_shapeburst (GImage *gimage,
GimpDrawable *drawable,
PixelRegion *PR,
double dist)
static void
gradient_precalc_shapeburst (
GImage * gimage,
GimpDrawable * drawable,
int x,
int y,
int w,
int h,
double dist
)
{
Channel *mask;
PixelRegion tempR;
float max_iteration;
float *distp;
int size;
void * pr;
unsigned char white[1] = { OPAQUE };
Canvas * tempRbuf;
PixelArea tempR;
/* allocate the distance map */
if (distR.tiles)
tile_manager_destroy (distR.tiles);
distR.tiles = tile_manager_new (PR->w, PR->h, sizeof (float));
if (distance_canvas)
canvas_delete (distance_canvas);
distance_canvas = canvas_new (tag_new (PRECISION_FLOAT, FORMAT_GRAY, ALPHA_NO),
w, h, STORAGE_TILED);
/* allocate the selection mask copy */
tempR.tiles = tile_manager_new (PR->w, PR->h, 1);
pixel_region_init (&tempR, tempR.tiles, 0, 0, PR->w, PR->h, TRUE);
#define FIXME
tempRbuf = canvas_new (tag_new (PRECISION_U8, FORMAT_GRAY, ALPHA_NO),
w, h, STORAGE_TILED);
pixelarea_init (&tempR, tempRbuf, 0, 0, w, h, TRUE);
/* If the gimage mask is not empty, use it as the shape burst source */
if (! gimage_mask_is_empty (gimage))
{
PixelRegion maskR;
Channel * mask;
PixelArea maskR;
int x1, y1, x2, y2;
int offx, offy;
@@ -1118,11 +1096,11 @@ gradient_precalc_shapeburst (GImage *gimage,
/* the selection mask */
mask = gimage_get_mask (gimage);
pixel_region_init (&maskR, drawable_data (GIMP_DRAWABLE(mask)),
x1 + offx, y1 + offy, (x2 - x1), (y2 - y1), FALSE);
pixelarea_init (&maskR, drawable_data (GIMP_DRAWABLE(mask)),
x1 + offx, y1 + offy, (x2 - x1), (y2 - y1), FALSE);
/* copy the mask to the temp mask */
copy_region (&maskR, &tempR);
copy_area (&maskR, &tempR);
}
/* otherwise... */
else
@@ -1130,44 +1108,69 @@ gradient_precalc_shapeburst (GImage *gimage,
/* If the intended drawable has an alpha channel, use that */
if (drawable_has_alpha (drawable))
{
PixelRegion drawableR;
PixelArea drawableR;
pixel_region_init (&drawableR, drawable_data (drawable), PR->x, PR->y, PR->w, PR->h, FALSE);
pixelarea_init (&drawableR, drawable_data (drawable),
x, y, w, h, FALSE);
extract_alpha_region (&drawableR, NULL, &tempR);
extract_alpha_area (&drawableR, NULL, &tempR);
}
/* Otherwise, just fill the shapeburst to white */
else
color_region (&tempR, white);
{
COLOR16_NEW (paint, pixelarea_tag (&tempR));
COLOR16_INIT (paint);
palette_get_white (&paint);
color_area (&tempR, &paint);
}
}
pixel_region_init (&tempR, tempR.tiles, 0, 0, PR->w, PR->h, TRUE);
pixel_region_init (&distR, distR.tiles, 0, 0, PR->w, PR->h, TRUE);
max_iteration = shapeburst_region (&tempR, &distR);
{
gfloat max_iteration;
PixelArea distR;
pixelarea_init (&tempR, tempRbuf,
0, 0, w, h, TRUE);
pixelarea_init (&distR, distance_canvas,
0, 0, w, h, TRUE);
/* normalize the shapeburst with the max iteration */
if (max_iteration > 0)
{
pixel_region_init (&distR, distR.tiles, 0, 0, PR->w, PR->h, TRUE);
max_iteration = shapeburst_area (&tempR, &distR);
for (pr = pixel_regions_register (1, &distR); pr != NULL; pr = pixel_regions_process (pr))
{
distp = (float *) distR.data;
size = distR.w * distR.h;
/* normalize the shapeburst with the max iteration */
if (max_iteration > 0)
{
void * pr;
while (size--)
*distp++ /= max_iteration;
}
pixelarea_init (&distR, distance_canvas,
0, 0, w, h, TRUE);
pixel_region_init (&distR, distR.tiles, 0, 0, PR->w, PR->h, FALSE);
}
tile_manager_destroy (tempR.tiles);
for (pr = pixelarea_register (1, &distR);
pr != NULL;
pr = pixelarea_process (pr))
{
gint w, h;
PixelRow row;
gfloat * distp;
h = pixelarea_height (&distR);
while (h--)
{
pixelarea_getdata (&distR, &row, h);
distp = (gfloat *) pixelrow_data (&row);
w = pixelrow_width (&row);
while (w--)
*distp++ /= max_iteration;
}
}
}
}
canvas_delete (tempRbuf);
}
static void
gradient_render_pixel(double x, double y, color_t *color, void *render_data)
gradient_render_pixel(double x, double y, gfloat *color, void *render_data)
{
RenderBlendData *rbd;
double factor;
@@ -1231,24 +1234,32 @@ gradient_render_pixel(double x, double y, color_t *color, void *render_data)
factor = (*rbd->repeat_func)(factor);
/* Blend the colors */
if (rbd->blend_mode == CUSTOM_MODE)
grad_get_color_at(factor, &color->r, &color->g, &color->b, &color->a);
else
{
/* Blend values */
color->r = rbd->fg.r + (rbd->bg.r - rbd->fg.r) * factor;
color->g = rbd->fg.g + (rbd->bg.g - rbd->fg.g) * factor;
color->b = rbd->fg.b + (rbd->bg.b - rbd->fg.b) * factor;
color->a = rbd->fg.a + (rbd->bg.a - rbd->fg.a) * factor;
if (rbd->blend_mode == FG_BG_HSV_MODE)
calc_hsv_to_rgb(&color->r, &color->g, &color->b);
}
{
color_t c;
if (rbd->blend_mode == CUSTOM_MODE)
grad_get_color_at(factor, &c.r, &c.g, &c.b, &c.a);
else
{
c.r = rbd->fg.r + (rbd->bg.r - rbd->fg.r) * factor;
c.g = rbd->fg.g + (rbd->bg.g - rbd->fg.g) * factor;
c.b = rbd->fg.b + (rbd->bg.b - rbd->fg.b) * factor;
c.a = rbd->fg.a + (rbd->bg.a - rbd->fg.a) * factor;
if (rbd->blend_mode == FG_BG_HSV_MODE)
calc_hsv_to_rgb(&c.r, &c.g, &c.b);
}
color[0] = c.r;
color[1] = c.g;
color[2] = c.b;
color[3] = c.a;
}
}
#define FIXME
#if 0
static void
gradient_put_pixel(int x, int y, color_t color, void *put_pixel_data)
{
@@ -1283,12 +1294,13 @@ gradient_put_pixel(int x, int y, color_t color, void *put_pixel_data)
if (x == (ppd->width - 1))
pixel_region_set_row(ppd->PR, 0, y, ppd->width, ppd->row_data);
}
#endif
static void
gradient_fill_region (GImage *gimage,
GimpDrawable *drawable,
PixelRegion *PR,
int x,
int y,
int width,
int height,
BlendMode blend_mode,
@@ -1301,31 +1313,33 @@ gradient_fill_region (GImage *gimage,
double sx,
double sy,
double ex,
double ey)
double ey,
gfloat opacity,
int mode
)
{
RenderBlendData rbd;
#define FIXME
#if 0
PutPixelData ppd;
unsigned char r, g, b;
int x, y;
int endx, endy;
void *pr;
unsigned char *data;
color_t color;
#endif
PixelRow col;
gfloat d[3];
/* Get foreground and background colors, normalized */
pixelrow_init (&col, tag_new (PRECISION_FLOAT, FORMAT_RGB, ALPHA_NO), (guchar *) d, 1);
palette_get_foreground (&col);
palette_get_foreground(&r, &g, &b);
rbd.fg.r = r / 255.0;
rbd.fg.g = g / 255.0;
rbd.fg.b = b / 255.0;
rbd.fg.r = d[0];
rbd.fg.g = d[1];
rbd.fg.b = d[2];
rbd.fg.a = 1.0; /* Foreground is always opaque */
palette_get_background(&r, &g, &b);
palette_get_background (&col);
rbd.bg.r = r / 255.0;
rbd.bg.g = g / 255.0;
rbd.bg.b = b / 255.0;
rbd.bg.r = d[0];
rbd.bg.g = d[1];
rbd.bg.b = d[2];
rbd.bg.a = 1.0; /* opaque, for now */
switch (blend_mode)
@@ -1388,7 +1402,7 @@ gradient_fill_region (GImage *gimage,
case ShapeburstSpherical:
case ShapeburstDimpled:
rbd.dist = sqrt(SQR(ex - sx) + SQR(ey - sy));
gradient_precalc_shapeburst(gimage, drawable, PR, rbd.dist);
gradient_precalc_shapeburst(gimage, drawable, x, y, width, height, rbd.dist);
break;
default:
@@ -1431,11 +1445,15 @@ gradient_fill_region (GImage *gimage,
if (supersample)
{
#define FIXME
#if 0
/* Initialize put pixel data */
#define FIXME
/* the PR arg here was a PixelArea that was used only for the x,
y, w, h values */
ppd.PR = PR;
ppd.row_data = g_malloc(width * PR->bytes);
ppd.bytes = PR->bytes;
ppd.row_data = g_malloc(width * tag_bytes (pixelarea_tag (PR)));
ppd.bytes = tag_bytes (pixelarea_tag (PR));
ppd.width = width;
/* Render! */
@@ -1449,38 +1467,98 @@ gradient_fill_region (GImage *gimage,
/* Clean up */
g_free(ppd.row_data);
#endif
}
else
{
for (pr = pixel_regions_register(1, PR); pr != NULL; pr = pixel_regions_process(pr))
{
data = PR->data;
endx = PR->x + PR->w;
endy = PR->y + PR->h;
Canvas * render;
Canvas * apply;
Tag rendertag;
Tag applytag;
for (y = PR->y; y < endy; y++)
for (x = PR->x; x < endx; x++)
{
gradient_render_pixel(x, y, &color, &rbd);
#define FOO 64
if (PR->bytes >= 3)
{
*data++ = color.r * 255.0;
*data++ = color.g * 255.0;
*data++ = color.b * 255.0;
*data++ = color.a * 255.0;
}
else
{
/* Convert to grayscale */
/* figure out what tags to use */
rendertag = tag_new (PRECISION_FLOAT, FORMAT_RGB, ALPHA_YES);
applytag = drawable_tag (drawable);
applytag = tag_set_alpha (applytag, ALPHA_YES);
*data++ = 255.0 * (0.30 * color.r +
0.59 * color.g +
0.11 * color.b);
*data++ = color.a * 255.0;
}
}
}
/* alloc canvases */
render = canvas_new (rendertag,
width, FOO,
STORAGE_TILED);
apply = canvas_new (applytag,
width, FOO,
STORAGE_TILED);
/* register a single undo instead of one per strip. */
drawable_apply_image (drawable, x, y, x+width, y+height, NULL);
{
PixelArea PRrender;
PixelArea PRapply;
void * pr;
int yy;
/* render the blend in 64 pixel tall strips */
for (yy = 0;
yy < height;
yy += FOO)
{
/* init the rendering area */
pixelarea_init (&PRrender, render,
0, 0,
0, 0,
TRUE);
/* render the width x 64 strip */
for (pr = pixelarea_register(1, &PRrender);
pr != NULL;
pr = pixelarea_process(pr))
{
gint y_s = pixelarea_y (&PRrender);
gint h_s = pixelarea_height (&PRrender);
for (;
h_s--;
y_s++)
{
gint x_s = pixelarea_x (&PRrender);
gint w_s = pixelarea_width (&PRrender);
for (;
w_s--;
x_s++)
{
gradient_render_pixel (x + x_s, y + yy + y_s,
(gfloat*) canvas_portion_data (render, x_s, y_s),
&rbd);
}
}
}
/* convert the strip to image format */
pixelarea_init (&PRrender, render,
0, 0,
0, 0,
TRUE);
pixelarea_init (&PRapply, apply,
0, 0,
0, 0,
TRUE);
copy_area (&PRrender, &PRapply);
/* apply the strip to the image */
gimage_apply_painthit (gimage, drawable,
NULL, apply,
0, 0,
0, 0,
FALSE, opacity, mode, x, y + yy);
}
}
}
}
@@ -1653,6 +1731,7 @@ tools_new_blend ()
tool->arrow_keys_func = standard_arrow_keys_func;
tool->cursor_update_func = blend_cursor_update;
tool->control_func = blend_control;
tool->preserve = TRUE;
return tool;
}
@@ -1670,9 +1749,9 @@ tools_free_blend (Tool *tool)
draw_core_free (blend_tool->core);
/* free the distance map data if it exists */
if (distR.tiles)
tile_manager_destroy (distR.tiles);
distR.tiles = NULL;
if (distance_canvas)
canvas_delete (distance_canvas);
distance_canvas = NULL;
g_free (blend_tool);
}

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BLEND_H__
#define __BLEND_H__

View File

@@ -13,16 +13,20 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#include "appenv.h"
#include "errors.h"
#include "float16.h"
#include "boundary.h"
#include "canvas.h"
#include "pixelarea.h"
/* half intensity for mask */
#define HALF_WAY 127
#define HALF_WAY_16BIT 32767
/* BoundSeg array growth parameter */
#define MAX_SEGS_INC 2048
@@ -45,11 +49,22 @@ static int num_empty_l = 0;
static int max_empty_segs = 0;
/* global state variables--improve parameter efficiency */
static PixelRegion * cur_PR;
static Canvas * cur_mask;
static int cur_x;
static int cur_y;
static int cur_w;
static int cur_h;
typedef void (*FindEmptySegsLineFunc) (PixelArea *, gint, gint, gint *, gint *, gint, gint, gint);
static FindEmptySegsLineFunc find_empty_segs_line_func (Tag);
static void find_empty_segs_line_u8 (PixelArea *, gint, gint, gint *, gint *, gint, gint, gint);
static void find_empty_segs_line_u16 (PixelArea *, gint, gint, gint *, gint *, gint, gint, gint);
static void find_empty_segs_line_float (PixelArea *, gint, gint, gint *, gint *, gint, gint, gint);
static void find_empty_segs_line_float16 (PixelArea *, gint, gint, gint *, gint *, gint, gint, gint);
/* local function prototypes */
static void find_empty_segs (PixelRegion *, int, int *, int, int *,
static void print_boundary (BoundSeg * b, int num_segs);
static void find_empty_segs (int, int *, int, int *,
BoundaryType, int, int, int, int);
static void make_seg (int, int, int, int, int);
static void allocate_vert_segs (void);
@@ -58,11 +73,41 @@ static void process_horiz_seg (int, int, int, int, int);
static void make_horiz_segs (int, int, int, int *, int, int);
static void generate_boundary (BoundaryType, int, int, int, int);
/* Function definitions */
void print_boundary (BoundSeg * b, int num_segs)
{
int i;
printf (" num_segs is %d\n", num_segs);
for (i= 0; i < num_segs; i++)
{
printf (" %d %d %d %d \n", b[i].x1, b[i].y1, b[i].x2, b[i].y2);
}
}
static
FindEmptySegsLineFunc
find_empty_segs_line_func (Tag t)
{
switch (tag_precision (t))
{
case PRECISION_U8:
return find_empty_segs_line_u8;
case PRECISION_U16:
return find_empty_segs_line_u16;
case PRECISION_FLOAT:
return find_empty_segs_line_float;
case PRECISION_FLOAT16:
return find_empty_segs_line_float16;
default:
return NULL;
}
}
/* Function definitions */
static void
find_empty_segs (PixelRegion *maskPR,
int scanline,
find_empty_segs (int scanline,
int empty_segs[],
int max_empty,
int *num_empty,
@@ -72,20 +117,23 @@ find_empty_segs (PixelRegion *maskPR,
int x2,
int y2)
{
unsigned char *data;
int x;
int start, end;
int val, last;
int tilex;
Tile *tile = NULL;
gint mask_x, mask_y, mask_w, mask_h;
PixelArea area;
Tag tag = canvas_tag (cur_mask);
FindEmptySegsLineFunc find_empty_segs_line = find_empty_segs_line_func (tag);
mask_x = cur_x;
mask_y = cur_y;
mask_w = cur_w;
mask_h = cur_h;
data = NULL;
start = 0;
end = 0;
*num_empty = 0;
if (scanline < maskPR->y || scanline >= (maskPR->y + maskPR->h))
if (scanline < mask_y || scanline >= mask_y + mask_h)
{
empty_segs[(*num_empty)++] = 0;
empty_segs[(*num_empty)++] = G_MAXINT;
@@ -106,43 +154,200 @@ find_empty_segs (PixelRegion *maskPR,
}
else if (type == IgnoreBounds)
{
start = maskPR->x;
end = maskPR->x + maskPR->w;
start = mask_x;
end = mask_x + mask_w;
if (scanline < y1 || scanline >= y2)
x2 = -1;
}
tilex = -1;
/*get pixelarea for scanline from start to end */
pixelarea_init (&area, cur_mask,
start, scanline,
end - start, 1,
FALSE);
(*find_empty_segs_line) (&area,
start, end,
num_empty, empty_segs,
type, x1, x2);
}
void find_empty_segs_line_u8(
PixelArea *area,
int start,
int end,
int *num_empty,
int *empty_segs,
int type,
int x1,
int x2
)
{
guchar *data;
guint8 *d;
int x;
int val, last;
gint width;
gint chan;
Tag tag = pixelarea_tag (area);
gint num_channels = tag_num_channels (tag);
void *pag;
empty_segs[(*num_empty)++] = 0;
last = -1;
x = start;
for (x = start; x < end; x++)
/*If format has an alpha, chan is set to that,
else its just the gray channel*/
chan = num_channels - 1;
for (pag = pixelarea_register (1, area);
pag != NULL;
pag = pixelarea_process (pag))
{
/* Check to see if we must advance to next tile */
if ((x / TILE_WIDTH) != tilex)
{
if (tile)
tile_unref (tile, FALSE);
tile = tile_manager_get_tile (maskPR->tiles, x, scanline, 0);
tile_ref (tile);
data = tile->data + tile->bpp *
((scanline % TILE_HEIGHT) * tile->ewidth + (x % TILE_WIDTH)) + (tile->bpp - 1);
tilex = x / TILE_WIDTH;
}
data = pixelarea_data (area);
d = (guint8*)data;
width = pixelarea_width (area);
while( width --)
{
empty_segs[*num_empty] = x;
val = (d[chan] > HALF_WAY)? 1: -1;
empty_segs[*num_empty] = x;
val = (*data > HALF_WAY) ? 1 : -1;
/* The IgnoreBounds case */
if (val == 1 && type == IgnoreBounds)
if (x >= x1 && x < x2)
val = -1;
/* The IgnoreBounds case */
if (val == 1 && type == IgnoreBounds)
if (x >= x1 && x < x2)
val = -1;
if (last * val < 0)
(*num_empty)++;
last = val;
if (last * val < 0)
(*num_empty)++;
last = val;
d += num_channels;
x++;
}
}
data += tile->bpp;
if (last > 0)
empty_segs[(*num_empty)++] = x;
empty_segs[(*num_empty)++] = G_MAXINT;
}
void find_empty_segs_line_u16(
PixelArea *area,
int start,
int end,
int *num_empty,
int *empty_segs,
int type,
int x1,
int x2
)
{
guchar *data;
guint16 *d;
int x;
int val, last;
gint width;
gint chan;
Tag tag = pixelarea_tag (area);
gint num_channels = tag_num_channels (tag);
void *pag;
empty_segs[(*num_empty)++] = 0;
last = -1;
x = start;
/*If format has an alpha, chan is set to that,
else its just the gray channel*/
chan = num_channels - 1;
for (pag = pixelarea_register (1, area);
pag != NULL;
pag = pixelarea_process (pag))
{
data = pixelarea_data (area);
d = (guint16*)data;
width = pixelarea_width (area);
while( width --)
{
empty_segs[*num_empty] = x;
val = (d[chan] > HALF_WAY_16BIT)? 1: -1;
/* The IgnoreBounds case */
if (val == 1 && type == IgnoreBounds)
if (x >= x1 && x < x2)
val = -1;
if (last * val < 0)
(*num_empty)++;
last = val;
d += num_channels;
x++;
}
}
if (last > 0)
empty_segs[(*num_empty)++] = x;
empty_segs[(*num_empty)++] = G_MAXINT;
}
void find_empty_segs_line_float(
PixelArea *area,
int start,
int end,
int *num_empty,
int *empty_segs,
int type,
int x1,
int x2
)
{
guchar *data;
gfloat *d;
int x;
int val, last;
gint width;
gint chan;
Tag tag = pixelarea_tag (area);
gint num_channels = tag_num_channels (tag);
void *pag;
empty_segs[(*num_empty)++] = 0;
last = -1;
x = start;
/*If format has an alpha, chan is set to that,
else its just the gray channel*/
chan = num_channels - 1;
for (pag = pixelarea_register (1, area);
pag != NULL;
pag = pixelarea_process (pag))
{
data = pixelarea_data (area);
d = (gfloat*)data;
width = pixelarea_width (area);
while( width --)
{
empty_segs[*num_empty] = x;
val = (d[chan] > .5)? 1: -1;
/* The IgnoreBounds case */
if (val == 1 && type == IgnoreBounds)
if (x >= x1 && x < x2)
val = -1;
if (last * val < 0)
(*num_empty)++;
last = val;
d += num_channels;
x++;
}
}
if (last > 0)
@@ -150,10 +355,70 @@ find_empty_segs (PixelRegion *maskPR,
empty_segs[(*num_empty)++] = G_MAXINT;
if (tile)
tile_unref (tile, FALSE);
}
void find_empty_segs_line_float16(
PixelArea *area,
int start,
int end,
int *num_empty,
int *empty_segs,
int type,
int x1,
int x2
)
{
guchar *data;
guint16 *d;
int x;
int val, last;
gint width;
gint chan;
Tag tag = pixelarea_tag (area);
gint num_channels = tag_num_channels (tag);
void *pag;
ShortsFloat u;
empty_segs[(*num_empty)++] = 0;
last = -1;
x = start;
/*If format has an alpha, chan is set to that,
else its just the gray channel*/
chan = num_channels - 1;
for (pag = pixelarea_register (1, area);
pag != NULL;
pag = pixelarea_process (pag))
{
data = pixelarea_data (area);
d = (guint16*)data;
width = pixelarea_width (area);
while( width --)
{
empty_segs[*num_empty] = x;
val = (FLT (d[chan], u) > .5)? 1: -1;
/* The IgnoreBounds case */
if (val == 1 && type == IgnoreBounds)
if (x >= x1 && x < x2)
val = -1;
if (last * val < 0)
(*num_empty)++;
last = val;
d += num_channels;
x++;
}
}
if (last > 0)
empty_segs[(*num_empty)++] = x;
empty_segs[(*num_empty)++] = G_MAXINT;
}
static void
make_seg (int x1,
@@ -186,11 +451,13 @@ static void
allocate_vert_segs (void)
{
int i;
int j = cur_w + cur_x;
/* allocate and initialize the vert_segs array */
vert_segs = (int *) g_realloc ((void *) vert_segs, (cur_PR->w + cur_PR->x + 1) * sizeof (int));
vert_segs = (int *) g_realloc ((void *) vert_segs,
(j + 1) * sizeof (int));
for (i = 0; i <= (cur_PR->w + cur_PR->x); i++)
for (i = 0; i <= j; i++)
vert_segs[i] = -1;
}
@@ -201,7 +468,7 @@ allocate_empty_segs (void)
int need_num_segs;
/* find the maximum possible number of empty segments given the current mask */
need_num_segs = cur_PR->w + 2;
need_num_segs = cur_w + 2;
if (need_num_segs > max_empty_segs)
{
@@ -302,22 +569,22 @@ generate_boundary (BoundaryType type,
}
else if (type == IgnoreBounds)
{
start = cur_PR->y;
end = cur_PR->y + cur_PR->h;
start = cur_y;
end = cur_y + cur_h;
}
/* Find the empty segments for the previous and current scanlines */
find_empty_segs (cur_PR, start - 1, empty_segs_l,
find_empty_segs (start - 1, empty_segs_l,
max_empty_segs, &num_empty_l,
type, x1, y1, x2, y2);
find_empty_segs (cur_PR, start, empty_segs_c,
find_empty_segs (start, empty_segs_c,
max_empty_segs, &num_empty_c,
type, x1, y1, x2, y2);
for (scanline = start; scanline < end; scanline++)
{
/* find the empty segment list for the next scanline */
find_empty_segs (cur_PR, scanline + 1, empty_segs_n,
find_empty_segs (scanline + 1, empty_segs_n,
max_empty_segs, &num_empty_n,
type, x1, y1, x2, y2);
@@ -340,9 +607,12 @@ generate_boundary (BoundaryType type,
}
}
BoundSeg *
find_mask_boundary (PixelRegion *maskPR,
find_mask_boundary (Canvas * mask,
int x,
int y,
int w,
int h,
int *num_elems,
BoundaryType type,
int x1,
@@ -356,7 +626,14 @@ find_mask_boundary (PixelRegion *maskPR,
* has more than 1 bytes/pixel, the last byte of each pixel is
* used to determine the boundary outline.
*/
cur_PR = maskPR;
if (w == 0) w = canvas_width (mask);
if (h == 0) h = canvas_height (mask);
cur_mask = mask;
cur_x = x;
cur_y = y;
cur_w = w;
cur_h = h;
/* Calculate the boundary */
generate_boundary (type, x1, y1, x2, y2);
@@ -371,6 +648,7 @@ find_mask_boundary (PixelRegion *maskPR,
memcpy (new_segs, tmp_segs, (sizeof (BoundSeg) * num_segs));
}
/*print_boundary (new_segs, num_segs);*/
/* Return the new boundary */
return new_segs;
}
@@ -467,7 +745,7 @@ sort_boundary (BoundSeg *segs,
}
if (x != startx || y != starty)
g_warning ("Unconnected boundary group!");
g_message ("sort_boundary(): Unconnected boundary group!");
/* Mark the end of a group */
*num_groups = *num_groups + 1;

View File

@@ -13,14 +13,13 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BOUNDARY_H__
#define __BOUNDARY_H__
#include "paint_funcs.h"
typedef struct _BoundSeg BoundSeg;
struct _Canvas;
struct _BoundSeg
{
@@ -37,7 +36,11 @@ typedef enum
} BoundaryType;
BoundSeg * find_mask_boundary (PixelRegion *, int *, BoundaryType, int, int, int, int);
BoundSeg * find_mask_boundary (struct _Canvas *,
int, int, int, int,
int *, BoundaryType,
int, int, int, int);
BoundSeg * sort_boundary (BoundSeg *, int, int *);
#endif /* __BOUNDARY_H__ */

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
@@ -21,12 +21,16 @@
#include "appenv.h"
#include "actionarea.h"
#include "brightness_contrast.h"
#include "canvas.h"
#include "drawable.h"
#include "float16.h"
#include "general.h"
#include "gimage_mask.h"
#include "gdisplay.h"
#include "image_map.h"
#include "interface.h"
#include "pixelarea.h"
#include "pixelrow.h"
#define TEXT_WIDTH 45
#define TEXT_HEIGHT 25
@@ -66,6 +70,10 @@ struct _BrightnessContrastDialog
gint preview;
};
/* brightness and contrast transfer luts */
static PixelRow brightness_lut;
static PixelRow contrast_lut;
/* brightness contrast action functions */
static void brightness_contrast_button_press (Tool *, GdkEventButton *, gpointer);
@@ -85,72 +93,209 @@ static void brightness_contrast_brightness_scale_update (GtkAdjustment *, gpoi
static void brightness_contrast_contrast_scale_update (GtkAdjustment *, gpointer);
static void brightness_contrast_brightness_text_update (GtkWidget *, gpointer);
static void brightness_contrast_contrast_text_update (GtkWidget *, gpointer);
static gint brightness_contrast_brightness_text_check (char *, BrightnessContrastDialog *);
static gint brightness_contrast_contrast_text_check (char *, BrightnessContrastDialog *);
static void *brightness_contrast_options = NULL;
static BrightnessContrastDialog *brightness_contrast_dialog = NULL;
static void brightness_contrast (PixelRegion *, PixelRegion *, void *);
static Argument * brightness_contrast_invoker (Argument *);
static double brightness_func (double, double);
static double contrast_func (double, double);
static void brightness_contrast_funcs (Tag);
/* data type function pointers */
typedef void (*BrightnessContrastInitTransfersFunc)(void *);
static BrightnessContrastInitTransfersFunc brightness_contrast_init_transfers;
typedef void (*BrightnessContrastFunc)(PixelArea *, PixelArea *, void *);
static BrightnessContrastFunc brightness_contrast;
static void brightness_contrast_init_transfers_u8 (void *);
static void brightness_contrast_u8 (PixelArea *, PixelArea *, void *);
static void brightness_contrast_init_transfers_u16 (void *);
static void brightness_contrast_u16 (PixelArea *, PixelArea *, void *);
static void brightness_contrast_init_transfers_float(void *);
static void brightness_contrast_float (PixelArea *, PixelArea *, void *);
static void brightness_contrast_init_transfers_float16(void *);
static void brightness_contrast_float16 (PixelArea *, PixelArea *, void *);
static void
brightness_contrast_funcs (Tag drawable_tag)
{
switch (tag_precision (drawable_tag))
{
case PRECISION_U8:
brightness_contrast = brightness_contrast_u8;
brightness_contrast_init_transfers = brightness_contrast_init_transfers_u8;
break;
case PRECISION_U16:
brightness_contrast = brightness_contrast_u16;
brightness_contrast_init_transfers = brightness_contrast_init_transfers_u16;
break;
case PRECISION_FLOAT:
brightness_contrast = brightness_contrast_float;
brightness_contrast_init_transfers = brightness_contrast_init_transfers_float;
break;
case PRECISION_FLOAT16:
brightness_contrast = brightness_contrast_float16;
brightness_contrast_init_transfers = brightness_contrast_init_transfers_float16;
break;
default:
brightness_contrast = NULL;
brightness_contrast_init_transfers = NULL;
break;
}
}
/* brightness contrast machinery */
static void
brightness_contrast (PixelRegion *srcPR,
PixelRegion *destPR,
void *user_data)
static double brightness_func (double x, double b)
{
BrightnessContrastDialog *bcd;
unsigned char *src, *s;
unsigned char *dest, *d;
unsigned char brightness[256];
unsigned char contrast[256];
double power;
if (b < 0)
return x * (1.0 + b);
else
return x + (1.0 - x) * b;
}
static double contrast_func (double x, double c)
{
double value, power;
value = (x > .5) ? (1.0 - x) : x;
if (c < 0)
{
/*value = value ? value : .0039215;*/
power = 1.0 + 2.0 * c;
}
else
{
power = (c == .5) ? .5 : 1.0 / (1.0 - 2.0*c);
}
value = .5 * pow ( 2.0 * value , power );
value = BOUNDS (value, 0.0, 1.0);
return (x > .5) ? (1.0 - value) : value;
}
static void
brightness_contrast_init_transfers_u8 (void * user_data)
{
gint i;
BrightnessContrastDialog *bcd = (BrightnessContrastDialog *) user_data;
guint8 *brightness_data = (guint8*) pixelrow_data (&brightness_lut);
guint8 *contrast_data = (guint8*) pixelrow_data (&contrast_lut);
Tag lut_tag = tag_new (PRECISION_U8, FORMAT_GRAY, ALPHA_NO);
gdouble brightness = bcd->brightness;
gdouble contrast = bcd->contrast;
/* allocate memory for the transfers if we dont have it yet */
if (!brightness_data && !contrast_data)
{
brightness_data = (guint8 *)g_malloc ( sizeof (guint8) * 256 );
contrast_data = (guint8 *)g_malloc ( sizeof (guint8) * 256 );
}
for (i = 0; i < 256; i++)
brightness_data[i] = (guint8) (255.0 * brightness_func ( (gdouble)i/255.0,
brightness));
for (i = 0; i < 256; i++)
contrast_data[i] = (guint8) (255.0 * contrast_func ( (gdouble)i/255.0,
contrast));
pixelrow_init (&brightness_lut, lut_tag, brightness_data, 256);
pixelrow_init (&contrast_lut, lut_tag, contrast_data, 256);
}
static void
brightness_contrast_init_transfers_u16 (void * user_data)
{
gint i;
BrightnessContrastDialog *bcd = (BrightnessContrastDialog *) user_data;
guint16 *brightness_data = (guint16*) pixelrow_data (&brightness_lut);
guint16 *contrast_data = (guint16*) pixelrow_data (&contrast_lut);
Tag lut_tag = tag_new (PRECISION_U16, FORMAT_GRAY, ALPHA_NO);
gdouble brightness = bcd->brightness;
gdouble contrast = bcd->contrast;
/* allocate memory for the transfers if we dont have it yet */
if (!brightness_data && !contrast_data)
{
brightness_data = (guint16 *)g_malloc ( sizeof (guint16) * 65536 );
contrast_data = (guint16 *)g_malloc ( sizeof (guint16) * 65536 );
}
for (i = 0; i < 65536; i++)
brightness_data[i] = (guint16) (65535.0 * brightness_func ( (gdouble)i/65535.0,
brightness));
for (i = 0; i < 65536; i++)
contrast_data[i] = (guint16) (65535.0 * contrast_func ( (double)i/65535.0,
contrast));
pixelrow_init (&brightness_lut, lut_tag, (guchar*)brightness_data, 65536);
pixelrow_init (&contrast_lut, lut_tag, (guchar*)contrast_data, 65536);
}
static void
brightness_contrast_init_transfers_float (void * user_data)
{
}
static void
brightness_contrast_init_transfers_float16 (void * user_data)
{
}
static void
brightness_contrast_free_transfers (void)
{
guchar * brightness_lut_data = pixelrow_data (&brightness_lut);
guchar * contrast_lut_data = pixelrow_data (&brightness_lut);
if (brightness_lut_data)
g_free (brightness_lut_data);
if (contrast_lut_data)
g_free (contrast_lut_data);
pixelrow_init (&brightness_lut, tag_null(), NULL, 0);
pixelrow_init (&contrast_lut, tag_null(), NULL, 0);
}
static void
brightness_contrast_u8 (PixelArea *src_area,
PixelArea *dest_area,
void *user_data)
{
Tag src_tag = pixelarea_tag (src_area);
Tag dest_tag = pixelarea_tag (dest_area);
gint src_num_channels = tag_num_channels (src_tag);
gint dest_num_channels = tag_num_channels (dest_tag);
guchar *src, *dest;
guint8 *s, *d;
unsigned char *brightness;
unsigned char *contrast;
int has_alpha;
int alpha;
int w, h, b;
int value;
int i;
bcd = (BrightnessContrastDialog *) user_data;
/* Set the transfer arrays (for speed) */
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
has_alpha = (srcPR->bytes == 2 || srcPR->bytes == 4);
alpha = has_alpha ? srcPR->bytes - 1 : srcPR->bytes;
if (bcd->brightness < 0)
for (i = 0; i < 256; i++)
brightness[i] = (unsigned char) ((i * (255 + bcd->brightness)) / 255);
else
for (i = 0; i < 256; i++)
brightness[i] = (unsigned char) (i + ((255 - i) * bcd->brightness) / 255);
if (bcd->contrast < 0)
for (i = 0; i < 256; i++)
{
value = (i > 127) ? (255 - i) : i;
value = (int) (127.0 * pow ((double) (value ? value : 1) / 127.0,
(double) (127 + bcd->contrast) / 127.0));
value = BOUNDS (value, 0, 255);
contrast[i] = (i > 127) ? (255 - value) : value;
}
else
for (i = 0; i < 256; i++)
{
value = (i > 127) ? (255 - i) : i;
power = (bcd->contrast == 127) ? 127 : 127.0 / (127 - bcd->contrast);
value = (int) (127.0 * pow ((double) value / 127.0, power));
value = BOUNDS (value, 0, 255);
contrast[i] = (i > 127) ? (255 - value) : value;
}
src = (guchar *)pixelarea_data (src_area);
dest = (guchar *)pixelarea_data (dest_area);
brightness = (guint8*) pixelrow_data (&brightness_lut);
contrast = (guint8*) pixelrow_data (&contrast_lut);
has_alpha = tag_alpha (src_tag) == ALPHA_YES ? TRUE: FALSE;
alpha = has_alpha ? src_num_channels - 1 : src_num_channels;
h = pixelarea_height (src_area);
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
s = (guint8*)src;
d = (guint8*)dest;
w = pixelarea_width (src_area);
while (w--)
{
for (b = 0; b < alpha; b++)
@@ -159,23 +304,169 @@ brightness_contrast (PixelRegion *srcPR,
if (has_alpha)
d[alpha] = s[alpha];
s += srcPR->bytes;
d += destPR->bytes;
s += src_num_channels;
d += dest_num_channels;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
src += pixelarea_rowstride (src_area);
dest += pixelarea_rowstride (dest_area);
}
}
static void
brightness_contrast_u16 (PixelArea *src_area,
PixelArea *dest_area,
void *user_data)
{
Tag src_tag = pixelarea_tag (src_area);
Tag dest_tag = pixelarea_tag (dest_area);
gint src_num_channels = tag_num_channels (src_tag);
gint dest_num_channels = tag_num_channels (dest_tag);
guchar *src, *dest;
guint16 *s, *d;
guint16 *brightness;
guint16 *contrast;
int has_alpha;
int alpha;
int w, h, b;
/* by_color select action functions */
src = (guchar *)pixelarea_data (src_area);
dest = (guchar *)pixelarea_data (dest_area);
brightness = (guint16*) pixelrow_data (&brightness_lut);
contrast = (guint16*) pixelrow_data (&contrast_lut);
has_alpha = tag_alpha (src_tag) == ALPHA_YES ? TRUE: FALSE;
alpha = has_alpha ? src_num_channels - 1 : src_num_channels;
h = pixelarea_height (src_area);
while (h--)
{
s = (guint16*)src;
d = (guint16*)dest;
w = pixelarea_width (src_area);
while (w--)
{
for (b = 0; b < alpha; b++)
d[b] = contrast[brightness[s[b]]];
if (has_alpha)
d[alpha] = s[alpha];
s += src_num_channels;
d += dest_num_channels;
}
src += pixelarea_rowstride (src_area);
dest += pixelarea_rowstride (dest_area);
}
}
static void
brightness_contrast_float (PixelArea *src_area,
PixelArea *dest_area,
void *user_data)
{
Tag src_tag = pixelarea_tag (src_area);
Tag dest_tag = pixelarea_tag (dest_area);
gint src_num_channels = tag_num_channels (src_tag);
gint dest_num_channels = tag_num_channels (dest_tag);
guchar *src, *dest;
gfloat *s, *d;
int has_alpha;
int alpha;
int w, h, b;
BrightnessContrastDialog *bcd = (BrightnessContrastDialog *) user_data;
gdouble brightness = (gfloat)bcd->brightness;
gdouble contrast = (gfloat)bcd->contrast;
src = (guchar *)pixelarea_data (src_area);
dest = (guchar *)pixelarea_data (dest_area);
has_alpha = tag_alpha (src_tag) == ALPHA_YES ? TRUE: FALSE;
alpha = has_alpha ? src_num_channels - 1 : src_num_channels;
h = pixelarea_height (src_area);
while (h--)
{
s = (gfloat*)src;
d = (gfloat*)dest;
w = pixelarea_width (src_area);
while (w--)
{
for (b = 0; b < alpha; b++)
d[b] = contrast_func (brightness_func(s[b], brightness), contrast);
if (has_alpha)
d[alpha] = s[alpha];
s += src_num_channels;
d += dest_num_channels;
}
src += pixelarea_rowstride (src_area);
dest += pixelarea_rowstride (dest_area);
}
}
static void
brightness_contrast_float16 (PixelArea *src_area,
PixelArea *dest_area,
void *user_data)
{
Tag src_tag = pixelarea_tag (src_area);
Tag dest_tag = pixelarea_tag (dest_area);
gint src_num_channels = tag_num_channels (src_tag);
gint dest_num_channels = tag_num_channels (dest_tag);
guchar *src, *dest;
guint16 *s, *d;
int has_alpha;
int alpha;
int w, h, b;
BrightnessContrastDialog *bcd = (BrightnessContrastDialog *) user_data;
gdouble brightness = (gfloat)bcd->brightness;
gdouble contrast = (gfloat)bcd->contrast;
ShortsFloat u;
gfloat sb, db;
src = (guchar *)pixelarea_data (src_area);
dest = (guchar *)pixelarea_data (dest_area);
has_alpha = tag_alpha (src_tag) == ALPHA_YES ? TRUE: FALSE;
alpha = has_alpha ? src_num_channels - 1 : src_num_channels;
h = pixelarea_height (src_area);
while (h--)
{
s = (guint16*)src;
d = (guint16*)dest;
w = pixelarea_width (src_area);
while (w--)
{
for (b = 0; b < alpha; b++)
{
sb = FLT (s[b], u);
db = contrast_func (brightness_func(sb, brightness), contrast);
d[b] = FLT16 (db, u);
}
if (has_alpha)
d[alpha] = s[alpha];
s += src_num_channels;
d += dest_num_channels;
}
src += pixelarea_rowstride (src_area);
dest += pixelarea_rowstride (dest_area);
}
}
static void
brightness_contrast_button_press (Tool *tool,
GdkEventButton *bevent,
gpointer gdisp_ptr)
{
GDisplay *gdisp;
gdisp = gdisp_ptr;
tool->drawable = gimage_active_drawable (gdisp->gimage);
}
static void
@@ -217,7 +508,10 @@ brightness_contrast_control (Tool *tool,
case HALT :
if (brightness_contrast_dialog)
{
image_map_abort (brightness_contrast_dialog->image_map);
active_tool->preserve = TRUE;
image_map_abort (brightness_contrast_dialog->image_map);
active_tool->preserve = FALSE;
brightness_contrast_free_transfers();
brightness_contrast_dialog->image_map = NULL;
brightness_contrast_cancel_callback (NULL, (gpointer) brightness_contrast_dialog);
}
@@ -250,6 +544,9 @@ tools_new_brightness_contrast ()
tool->arrow_keys_func = standard_arrow_keys_func;
tool->cursor_update_func = brightness_contrast_cursor_update;
tool->control_func = brightness_contrast_control;
tool->preserve = FALSE;
tool->gdisp_ptr = NULL;
tool->drawable = NULL;
return tool;
}
@@ -263,7 +560,7 @@ tools_free_brightness_contrast (Tool *tool)
/* Close the color select dialog */
if (brightness_contrast_dialog)
brightness_contrast_ok_callback (NULL, (gpointer) brightness_contrast_dialog);
brightness_contrast_cancel_callback (NULL, (gpointer) brightness_contrast_dialog);
g_free (bc);
}
@@ -272,12 +569,13 @@ void
brightness_contrast_initialize (void *gdisp_ptr)
{
GDisplay *gdisp;
GimpDrawable *drawable;
gdisp = (GDisplay *) gdisp_ptr;
if (drawable_indexed (gimage_active_drawable (gdisp->gimage)))
{
message_box ("Brightness-Contrast does not operate on indexed drawables.", NULL, NULL);
g_message ("Brightness-Contrast does not operate on indexed drawables.");
return;
}
@@ -288,12 +586,20 @@ brightness_contrast_initialize (void *gdisp_ptr)
if (!GTK_WIDGET_VISIBLE (brightness_contrast_dialog->shell))
gtk_widget_show (brightness_contrast_dialog->shell);
drawable = gimage_active_drawable (gdisp->gimage);
/* Set up the function pointers for our data type */
brightness_contrast_funcs (drawable_tag (drawable));
pixelrow_init (&brightness_lut, tag_null(), NULL , 0);
pixelrow_init (&contrast_lut, tag_null(), NULL, 0);
/* Initialize dialog fields */
brightness_contrast_dialog->image_map = NULL;
brightness_contrast_dialog->brightness = 0.0;
brightness_contrast_dialog->contrast = 0.0;
brightness_contrast_dialog->drawable = gimage_active_drawable (gdisp->gimage);
brightness_contrast_dialog->drawable = drawable;
brightness_contrast_dialog->image_map = image_map_create (gdisp_ptr,
brightness_contrast_dialog->drawable);
@@ -312,7 +618,7 @@ static ActionAreaItem action_items[] =
{ "Cancel", brightness_contrast_cancel_callback, NULL, NULL }
};
BrightnessContrastDialog *
static BrightnessContrastDialog *
brightness_contrast_new_dialog ()
{
BrightnessContrastDialog *bcd;
@@ -329,6 +635,7 @@ brightness_contrast_new_dialog ()
/* The shell and main vbox */
bcd->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (bcd->shell), "brightness_contrast", "Gimp");
gtk_window_set_title (GTK_WINDOW (bcd->shell), "Brightness-Contrast");
/* handle wm close signal */
@@ -350,11 +657,11 @@ brightness_contrast_new_dialog ()
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 2, 2);
data = gtk_adjustment_new (0, -127, 127.0, 1.0, 1.0, 0.0);
data = gtk_adjustment_new (0, -.5, .51, .001, .01, .01);
bcd->brightness_data = GTK_ADJUSTMENT (data);
slider = gtk_hscale_new (GTK_ADJUSTMENT (data));
gtk_widget_set_usize (slider, SLIDER_WIDTH, SLIDER_HEIGHT);
gtk_scale_set_digits (GTK_SCALE (slider), 0);
gtk_scale_set_digits (GTK_SCALE (slider), 3);
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
gtk_table_attach (GTK_TABLE (table), slider, 1, 2, 0, 1,
@@ -384,11 +691,11 @@ brightness_contrast_new_dialog ()
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 2, 2);
data = gtk_adjustment_new (0, -127.0, 127.0, 1.0, 1.0, 0.0);
data = gtk_adjustment_new (0, -.5, .51, .001, .01, .01);
bcd->contrast_data = GTK_ADJUSTMENT (data);
slider = gtk_hscale_new (GTK_ADJUSTMENT (data));
gtk_widget_set_usize (slider, SLIDER_WIDTH, SLIDER_HEIGHT);
gtk_scale_set_digits (GTK_SCALE (slider), 0);
gtk_scale_set_digits (GTK_SCALE (slider), 3);
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
gtk_table_attach (GTK_TABLE (table), slider, 1, 2, 1, 2,
@@ -459,12 +766,12 @@ brightness_contrast_update (BrightnessContrastDialog *bcd,
}
if (update & BRIGHTNESS_TEXT)
{
sprintf (text, "%0.0f", bcd->brightness);
sprintf (text, "%0.3f", bcd->brightness);
gtk_entry_set_text (GTK_ENTRY (bcd->brightness_text), text);
}
if (update & CONTRAST_TEXT)
{
sprintf (text, "%0.0f", bcd->contrast);
sprintf (text, "%0.3f", bcd->contrast);
gtk_entry_set_text (GTK_ENTRY (bcd->contrast_text), text);
}
}
@@ -473,8 +780,11 @@ static void
brightness_contrast_preview (BrightnessContrastDialog *bcd)
{
if (!bcd->image_map)
g_warning ("No image map");
g_message ("brightness_contrast_preview(): No image map");
active_tool->preserve = TRUE;
(*brightness_contrast_init_transfers) ((void *)bcd);
image_map_apply (bcd->image_map, brightness_contrast, (void *) bcd);
active_tool->preserve = FALSE;
}
static void
@@ -488,11 +798,21 @@ brightness_contrast_ok_callback (GtkWidget *widget,
if (GTK_WIDGET_VISIBLE (bcd->shell))
gtk_widget_hide (bcd->shell);
active_tool->preserve = TRUE;
if (!bcd->preview)
{
(*brightness_contrast_init_transfers) ((void *)bcd);
image_map_apply (bcd->image_map, brightness_contrast, (void *) bcd);
}
if (bcd->image_map)
{
image_map_commit (bcd->image_map);
brightness_contrast_free_transfers();
}
active_tool->preserve = FALSE;
bcd->image_map = NULL;
}
@@ -504,7 +824,7 @@ brightness_contrast_delete_callback (GtkWidget *w,
{
brightness_contrast_cancel_callback (w, d);
return FALSE;
return TRUE;
}
static void
@@ -519,7 +839,10 @@ brightness_contrast_cancel_callback (GtkWidget *widget,
if (bcd->image_map)
{
active_tool->preserve = TRUE;
image_map_abort (bcd->image_map);
brightness_contrast_free_transfers();
active_tool->preserve = FALSE;
gdisplays_flush ();
}
@@ -583,39 +906,44 @@ static void
brightness_contrast_brightness_text_update (GtkWidget *w,
gpointer data)
{
BrightnessContrastDialog *bcd;
char *str;
int value;
str = gtk_entry_get_text (GTK_ENTRY (w));
bcd = (BrightnessContrastDialog *) data;
value = BOUNDS (((int) atof (str)), -127, 127);
if ((int) bcd->brightness != value)
{
bcd->brightness = value;
BrightnessContrastDialog *bcd = (BrightnessContrastDialog *) data;
char *str = gtk_entry_get_text (GTK_ENTRY (w));
if (brightness_contrast_brightness_text_check (str, bcd))
{
brightness_contrast_update (bcd, BRIGHTNESS_SLIDER);
if (bcd->preview)
brightness_contrast_preview (bcd);
}
}
}
static gint
brightness_contrast_brightness_text_check (
char *str,
BrightnessContrastDialog *bcd
)
{
gfloat value;
value = BOUNDS (atof (str), -.5, .5);
if (bcd->brightness != value)
{
bcd->brightness = value;
return TRUE;
}
return FALSE;
}
static void
brightness_contrast_contrast_text_update (GtkWidget *w,
gpointer data)
{
BrightnessContrastDialog *bcd;
char *str;
int value;
BrightnessContrastDialog *bcd = (BrightnessContrastDialog *) data;
char *str = gtk_entry_get_text (GTK_ENTRY (w));
str = gtk_entry_get_text (GTK_ENTRY (w));
bcd = (BrightnessContrastDialog *) data;
value = BOUNDS (((int) atof (str)), -127, 127);
if ((int) bcd->contrast != value)
if (brightness_contrast_contrast_text_check (str, bcd))
{
bcd->contrast = value;
brightness_contrast_update (bcd, CONTRAST_SLIDER);
if (bcd->preview)
@@ -623,6 +951,23 @@ brightness_contrast_contrast_text_update (GtkWidget *w,
}
}
static gint
brightness_contrast_contrast_text_check (
char *str,
BrightnessContrastDialog *bcd
)
{
gfloat value;
value = BOUNDS (atof (str), -.5, .5);
if (bcd->contrast != value)
{
bcd->contrast = value;
return TRUE;
}
return FALSE;
}
/* The brightness_contrast procedure definition */
ProcArg brightness_contrast_args[] =
@@ -671,7 +1016,7 @@ ProcRecord brightness_contrast_proc =
static Argument *
brightness_contrast_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
PixelArea src_area, dest_area;
int success = TRUE;
int int_value;
BrightnessContrastDialog bcd;
@@ -701,6 +1046,10 @@ brightness_contrast_invoker (Argument *args)
if (drawable == NULL || gimage != drawable_gimage (drawable))
success = FALSE;
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
/* brightness */
if (success)
{
@@ -725,16 +1074,26 @@ brightness_contrast_invoker (Argument *args)
{
bcd.brightness = brightness;
bcd.contrast = contrast;
brightness_contrast_funcs(drawable_tag (drawable));
pixelrow_init (&brightness_lut, tag_null(), NULL , 0);
pixelrow_init (&contrast_lut, tag_null(), NULL, 0);
(*brightness_contrast_init_transfers)(&bcd);
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixelarea_init (&src_area, drawable_data (drawable),
x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixelarea_init (&dest_area, drawable_shadow (drawable),
x1, y1, (x2 - x1), (y2 - y1), TRUE);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
brightness_contrast (&srcPR, &destPR, (void *) &bcd);
for (pr = pixelarea_register (2, &src_area, &dest_area);
pr != NULL;
pr = pixelarea_process (pr))
(*brightness_contrast) (&src_area, &dest_area, (void *) &bcd);
brightness_contrast_free_transfers();
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
}

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BRIGHTNESS_CONTRAST_H__
#define __BRIGHTNESS_CONTRAST_H__

View File

@@ -13,17 +13,18 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BRUSH_HEADER_H__
#define __BRUSH_HEADER_H__
typedef struct _BrushHeader BrushHeader;
#define FILE_VERSION 2
#define FILE_VERSION 3
#define GBRUSH_MAGIC (('G' << 24) + ('I' << 16) + ('M' << 8) + ('P' << 0))
#define sz_BrushHeader (sizeof (BrushHeader))
#define BRUSH_HEADER_C_2_cw
/* All field entries are MSB */
struct _BrushHeader
@@ -32,7 +33,7 @@ struct _BrushHeader
unsigned int version; /* brush file version # */
unsigned int width; /* width of brush */
unsigned int height; /* height of brush */
unsigned int bytes; /* depth of brush in bytes--always 1 */
unsigned int type; /* = bpp in version <= 2, but layer type in version >= 3*/
unsigned int magic_number;/* GIMP brush magic number */
unsigned int spacing; /* brush spacing */
};

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
@@ -23,10 +23,13 @@
#include "brushes.h"
#include "brush_select.h"
#include "buildmenu.h"
#include "canvas.h"
#include "colormaps.h"
#include "disp_callbacks.h"
#include "errors.h"
#include "paint_funcs.h"
#include "float16.h"
#include "paint_funcs_area.h"
#include "tag.h"
#define STD_CELL_WIDTH 24
@@ -66,6 +69,22 @@ static void preview_scroll_update (GtkAdjustment *, gpointer);
static void opacity_scale_update (GtkAdjustment *, gpointer);
static void spacing_scale_update (GtkAdjustment *, gpointer);
/* get row for different data types */
static void display_brush_get_row_u8 (guchar *, Canvas *, gint, gint);
static void display_brush_get_row_u16 (guchar *, Canvas *, gint, gint);
static void display_brush_get_row_float (guchar *, Canvas *, gint, gint);
static void display_brush_get_row_float16 (guchar *, Canvas *, gint, gint);
/* Convert row of brush to 8bit display */
typedef void (*DisplayBrushGetRowFunc) (guchar *, Canvas *, gint, gint);
static DisplayBrushGetRowFunc display_brush_get_row_funcs[4] =
{
display_brush_get_row_u8,
display_brush_get_row_u16,
display_brush_get_row_float,
display_brush_get_row_float16
};
/* the option menu items -- the paint modes */
static MenuItem option_items[] =
{
@@ -133,12 +152,14 @@ brush_select_new ()
bsp = g_malloc (sizeof (_BrushSelect));
bsp->redraw = TRUE;
bsp->scroll_offset = 0;
bsp->brush_popup = NULL;
/* The shell and main vbox */
bsp->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (bsp->shell), "brushselection", "Gimp");
gtk_window_set_title (GTK_WINDOW (bsp->shell), "Brush Selection");
gtk_window_set_policy(GTK_WINDOW(bsp->shell), TRUE, TRUE, FALSE);
gtk_window_set_policy(GTK_WINDOW(bsp->shell), FALSE, TRUE, FALSE);
vbox = gtk_vbox_new (FALSE, 1);
gtk_container_border_width (GTK_CONTAINER (vbox), 2);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (bsp->shell)->vbox), vbox, TRUE, TRUE, 0);
@@ -268,8 +289,12 @@ brush_select_new ()
gtk_widget_show (bsp->shell);
/* calculate the scrollbar */
if(no_data)
brushes_init(FALSE);
/* This is done by size_allocate anyway, which is much better */
preview_calc_scrollbar (bsp);
/* render the brushes into the newly created image structure */
display_brushes (bsp);
@@ -324,7 +349,10 @@ brush_popup_open (BrushSelectP bsp,
{
gint x_org, y_org;
gint scr_w, scr_h;
gchar *src, *buf;
gint brush_width, brush_height;
guchar *buf;
Tag brush_tag;
Precision brush_prec;
/* make sure the popup exists and is not visible */
if (bsp->brush_popup == NULL)
@@ -351,30 +379,28 @@ brush_popup_open (BrushSelectP bsp,
gdk_window_get_origin (bsp->preview->window, &x_org, &y_org);
scr_w = gdk_screen_width ();
scr_h = gdk_screen_height ();
x = x_org + x - brush->mask->width * 0.5;
y = y_org + y - brush->mask->height * 0.5;
brush_width = canvas_width (brush->mask);
brush_height = canvas_height (brush->mask);
x = x_org + x - brush_width * 0.5;
y = y_org + y - brush_height * 0.5;
x = (x < 0) ? 0 : x;
y = (y < 0) ? 0 : y;
x = (x + brush->mask->width > scr_w) ? scr_w - brush->mask->width : x;
y = (y + brush->mask->height > scr_h) ? scr_h - brush->mask->height : y;
gtk_preview_size (GTK_PREVIEW (bsp->brush_preview), brush->mask->width, brush->mask->height);
x = (x + brush_width > scr_w) ? scr_w - brush_width : x;
y = (y + brush_height > scr_h) ? scr_h - brush_height : y;
gtk_preview_size (GTK_PREVIEW (bsp->brush_preview), brush_width, brush_height);
gtk_widget_popup (bsp->brush_popup, x, y);
/* Draw the brush */
buf = g_new (gchar, brush->mask->width);
src = temp_buf_data (brush->mask);
for (y = 0; y < brush->mask->height; y++)
buf = g_new (gchar, brush_width);
brush_tag = canvas_tag (brush->mask);
brush_prec = tag_precision (brush_tag);
for (y = 0; y < brush_height; y++)
{
/* Invert the mask for display. We're doing this because
* a value of 255 in the mask means it is full intensity.
* However, it makes more sense for full intensity to show
* up as black in this brush preview window...
*/
for (x = 0; x < brush->mask->width; x++)
buf[x] = 255 - src[x];
gtk_preview_draw_row (GTK_PREVIEW (bsp->brush_preview), buf, 0, y, brush->mask->width);
src += brush->mask->width;
(*display_brush_get_row_funcs [brush_prec-1]) (buf, brush->mask, y, brush_width);
gtk_preview_draw_row (GTK_PREVIEW (bsp->brush_preview), buf, 0, y, brush_width);
}
g_free(buf);
@@ -395,55 +421,167 @@ display_brush (BrushSelectP bsp,
int col,
int row)
{
TempBuf * brush_buf;
unsigned char * src, *s;
unsigned char * buf, *b;
Canvas *brush_buf_canvas = brush->mask;
unsigned char * buf;
int width, height;
int offset_x, offset_y;
int yend;
int ystart;
int i, j;
int i;
Tag brush_tag = canvas_tag (brush->mask);
Precision brush_prec = tag_precision (brush_tag);
Alpha brush_alpha = tag_alpha (brush_tag);
if ( brush_alpha == ALPHA_YES )
{
g_warning("Brush %s has alpha channel. Cant display.\n", brush->name);
return;
}
buf = (unsigned char *) g_malloc (sizeof (char) * bsp->cell_width);
brush_buf = brush->mask;
/* calculate the offset into the image */
width = (brush_buf->width > bsp->cell_width) ? bsp->cell_width :
brush_buf->width;
height = (brush_buf->height > bsp->cell_height) ? bsp->cell_height :
brush_buf->height;
width = (canvas_width (brush_buf_canvas) > bsp->cell_width) ? bsp->cell_width :
canvas_width (brush_buf_canvas);
height = (canvas_height(brush_buf_canvas) > bsp->cell_height) ? bsp->cell_height :
canvas_height(brush_buf_canvas);
offset_x = col * bsp->cell_width + ((bsp->cell_width - width) >> 1);
offset_y = row * bsp->cell_height + ((bsp->cell_height - height) >> 1)
- bsp->scroll_offset;
ystart = BOUNDS (offset_y, 0, bsp->preview->requisition.height);
yend = BOUNDS (offset_y + height, 0, bsp->preview->requisition.height);
/* Get the pointer into the brush mask data */
src = mask_buf_data (brush_buf) + (ystart - offset_y) * brush_buf->width;
/* Fill the brush display buffer and display it */
for (i = ystart; i < yend; i++)
{
/* Invert the mask for display. We're doing this because
* a value of 255 in the mask means it is full intensity.
* However, it makes more sense for full intensity to show
* up as black in this brush preview window...
*/
s = src;
b = buf;
for (j = 0; j < width; j++)
*b++ = 255 - *s++;
(*display_brush_get_row_funcs [brush_prec-1]) (buf, brush_buf_canvas,
i - offset_y , width);
gtk_preview_draw_row (GTK_PREVIEW (bsp->preview), buf, offset_x, i, width);
src += brush_buf->width;
}
g_free (buf);
}
static void
display_brush_get_row_u8(
guchar *buf,
Canvas *brush_canvas,
gint row,
gint width
)
{
Tag tag = canvas_tag (brush_canvas);
gint channels_per_row = tag_num_channels (tag) * canvas_width (brush_canvas);
guint8 * s = (guint8*)canvas_portion_data (brush_canvas,0,0) + row * channels_per_row;
guchar *b = buf;
gint i;
Format f = tag_format (canvas_tag (brush_canvas));
switch (f)
{
case FORMAT_GRAY:
/* Invert the mask for display. */
for (i = 0; i < width; i++)
{
*b++ = 255 - *s++;
}
break;
default:
break;
}
}
#define U16_TO_U8(x) ((x)>>8)
static void
display_brush_get_row_u16(
guchar *buf,
Canvas *brush_canvas,
gint row,
gint width
)
{
Tag tag = canvas_tag (brush_canvas);
gint channels_per_row = tag_num_channels (tag) * canvas_width (brush_canvas);
guint16 * s = (guint16*)canvas_portion_data (brush_canvas,0,0) + row * channels_per_row;
guchar *b = buf;
gint i;
Format f = tag_format (canvas_tag (brush_canvas));
switch (f)
{
case FORMAT_GRAY:
/* Invert the mask for display. */
for (i = 0; i < width; i++)
{
*b++ = 255 - U16_TO_U8(*s++);
}
break;
default:
break;
}
}
static void
display_brush_get_row_float(
guchar *buf,
Canvas *brush_canvas,
gint row,
gint width
)
{
Tag tag = canvas_tag (brush_canvas);
gint channels_per_row = tag_num_channels (tag) * canvas_width (brush_canvas);
gfloat * s = (gfloat*)canvas_portion_data (brush_canvas,0,0) + row * channels_per_row;
guchar *b = buf;
gint i;
Format f = tag_format (canvas_tag (brush_canvas));
switch (f)
{
case FORMAT_GRAY:
/* Invert the mask for display. */
for (i = 0; i < width; i++)
{
*b++ = 255 - (gint)(255 * *s++ + .5);
}
break;
default:
break;
}
}
static void
display_brush_get_row_float16(
guchar *buf,
Canvas *brush_canvas,
gint row,
gint width
)
{
Tag tag = canvas_tag (brush_canvas);
gint channels_per_row = tag_num_channels (tag) * canvas_width (brush_canvas);
guint16 * s = (guint16*)canvas_portion_data (brush_canvas,0,0) + row * channels_per_row;
guchar *b = buf;
gint i;
Format f = tag_format (canvas_tag (brush_canvas));
ShortsFloat u;
switch (f)
{
case FORMAT_GRAY:
/* Invert the mask for display. */
for (i = 0; i < width; i++)
{
*b++ = 255 - (gint)(255 * FLT (*s++, u) + .5);
}
break;
default:
break;
}
}
static void
display_setup (BrushSelectP bsp)
@@ -467,7 +605,7 @@ display_setup (BrushSelectP bsp)
static void
display_brushes (BrushSelectP bsp)
{
link_ptr list = brush_list; /* the global brush list */
GSList * list = brush_list; /* the global brush list */
int row, col;
GBrushP brush;
@@ -499,7 +637,7 @@ display_brushes (BrushSelectP bsp)
col = 0;
}
list = next_item (list);
list = g_slist_next (list);
}
}
@@ -596,16 +734,28 @@ preview_calc_scrollbar (BrushSelectP bsp)
int num_rows;
int page_size;
int max;
int offs;
/* int rowy; */
bsp->scroll_offset = 0;
offs = bsp->scroll_offset;
num_rows = (num_brushes + NUM_BRUSH_COLUMNS - 1) / NUM_BRUSH_COLUMNS;
max = num_rows * bsp->cell_width;
if (!num_rows) num_rows = 1;
page_size = bsp->preview->allocation.height;
page_size = ((page_size < max) ? page_size : max);
/*
rowy = (get_active_brush()->index / NUM_BRUSH_COLUMNS) * bsp->cell_width
+ bsp->cell_width/2;
if((rowy < offs) || (rowy > (offs + page_size)))
offs = rowy - page_size/2;
offs = MIN(MAX(offs, 0), max - page_size);
*/
bsp->scroll_offset = offs;
bsp->sbar_data->value = bsp->scroll_offset;
bsp->sbar_data->upper = max;
bsp->sbar_data->page_size = (page_size < max) ? page_size : max;
/* bsp->sbar_data->page_size = page_size; */
bsp->sbar_data->page_size = ((page_size < max) ? page_size : max);
bsp->sbar_data->page_increment = (page_size >> 1);
bsp->sbar_data->step_increment = bsp->cell_width;
@@ -653,7 +803,7 @@ update_active_brush_field (BrushSelectP bsp)
gtk_label_set (GTK_LABEL (bsp->brush_name), brush->name);
/* Set brush size */
sprintf (buf, "(%d X %d)", brush->mask->width, brush->mask->height);
sprintf (buf, "(%d X %d)", canvas_width(brush->mask), canvas_height(brush->mask));
gtk_label_set (GTK_LABEL (bsp->brush_size), buf);
/* Set brush spacing */
@@ -693,13 +843,12 @@ brush_select_events (GtkWidget *widget,
GDK_BUTTON1_MOTION_MASK |
GDK_BUTTON_RELEASE_MASK),
NULL, NULL, bevent->time);
/* Make this brush the active brush */
select_brush (brush);
/* Show the brush popup window if the brush is too large */
if (brush->mask->width > bsp->cell_width ||
brush->mask->height > bsp->cell_height)
if (canvas_width (brush->mask) > bsp->cell_width ||
canvas_height(brush->mask) > bsp->cell_height)
brush_popup_open (bsp, bevent->x, bevent->y, brush);
}
}
@@ -718,7 +867,7 @@ brush_select_events (GtkWidget *widget,
}
break;
case GDK_DELETE:
g_warning ("test");
/* g_warning ("test"); */
break;
default:
@@ -733,7 +882,7 @@ brush_select_delete_callback (GtkWidget *w, GdkEvent *e, gpointer data)
{
brush_select_close_callback (w, data);
return FALSE;
return TRUE;
}
static void
@@ -763,7 +912,12 @@ brush_select_refresh_callback (GtkWidget *w,
bsp = (BrushSelectP) client_data;
/* re-init the brush list */
brushes_init ();
brushes_init(FALSE);
/* update the active selection */
active = get_active_brush ();
if (active)
brush_select_select (bsp, active->index);
/* recalculate scrollbar extents */
preview_calc_scrollbar (bsp);
@@ -771,10 +925,7 @@ brush_select_refresh_callback (GtkWidget *w,
/* render the brushes into the newly created image structure */
display_brushes (bsp);
/* update the active selection */
active = get_active_brush ();
if (active)
brush_select_select (bsp, active->index);
/* update the display */
if (bsp->redraw)

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BRUSH_SELECT_H__
#define __BRUSH_SELECT_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <stdio.h>
@@ -27,18 +27,25 @@
#include "brush_header.h"
#include "brush_select.h"
#include "buildmenu.h"
#include "canvas.h"
#include "clone.h"
#include "colormaps.h"
#include "datafiles.h"
#include "errors.h"
#include "general.h"
#include "gimprc.h"
#include "linked.h"
#include "menus.h"
#include "paint_funcs_area.h"
#include "palette.h"
#include "pixelarea.h"
#include "pixelrow.h"
#include "tag.h"
/* global variables */
GBrushP active_brush = NULL;
link_ptr brush_list = NULL;
GSList * brush_list = NULL;
int num_brushes = 0;
double opacity = 1.0;
@@ -54,57 +61,142 @@ static Argument *return_args;
static int have_default_brush = 0;
/* static function prototypes */
static link_ptr insert_brush_in_list (link_ptr, GBrushP);
static void create_default_brush (void);
static GSList * insert_brush_in_list (GSList *, GBrushP);
static GBrushP create_default_brush (gint, gint);
static void load_brush (char *filename);
static void free_brush (GBrushP);
static void brushes_free_one (gpointer, gpointer);
static gint brush_compare_func (gpointer, gpointer);
/* function declarations */
void
brushes_init ()
brushes_init (int no_data)
{
link_ptr list;
GSList * list;
GBrushP gb_start = NULL;
gint gb_count = 0;
if (brush_list)
brushes_free ();
brushes_free();
brush_list = NULL;
num_brushes = 0;
if (!brush_path)
create_default_brush ();
else
{
GBrushP brush;
/* Make a 1x1 brush if no path */
brush = create_default_brush (1, 1);
#define BRUSHES_C_2_cw
/* Swap the brush to disk (if we're being stingy with memory) */
if (stingy_memory_use)
{
/*temp_buf_swap (brush->mask);*/
g_warning( "brush_init: canvas_swap not implemented.");
}
brush_list = insert_brush_in_list(brush_list, brush);
/* Make this the default, active brush */
active_brush = brush;
have_default_brush = 1;
}
else if(!no_data)
datafiles_read_directories (brush_path, load_brush, 0);
/* assign indexes to the loaded brushes */
list = brush_list;
while (list) {
/* Set the brush index */
((GBrush *) list->data)->index = num_brushes++;
list = next_item (list);
#define BRUSHES_C_4_cw
/* Make some extra brushes for debugging paint_funcs */
#if 1
{
GBrushP brush;
brush = create_default_brush(1,1);
brush_list = insert_brush_in_list(brush_list, brush);
brush = create_default_brush(2,2);
brush_list = insert_brush_in_list(brush_list, brush);
brush = create_default_brush(3,3);
brush_list = insert_brush_in_list(brush_list, brush);
brush = create_default_brush(5,5);
brush_list = insert_brush_in_list(brush_list, brush);
brush = create_default_brush(10,10);
brush_list = insert_brush_in_list(brush_list, brush);
brush = create_default_brush(20,20);
brush_list = insert_brush_in_list(brush_list, brush);
brush = create_default_brush(30,30);
brush_list = insert_brush_in_list(brush_list, brush);
brush = create_default_brush(40,40);
brush_list = insert_brush_in_list(brush_list, brush);
brush = create_default_brush(50,50);
brush_list = insert_brush_in_list(brush_list, brush);
brush = create_default_brush(100,100);
brush_list = insert_brush_in_list(brush_list, brush);
brush = create_default_brush(200,200);
brush_list = insert_brush_in_list(brush_list, brush);
}
#endif
while (list) {
/* Set the brush index */
/* ALT make names unique */
GBrushP gb = (GBrushP)list->data;
gb->index = num_brushes++;
list = g_slist_next(list);
if(list) {
GBrushP gb2 = (GBrushP)list->data;
if(gb_start == NULL) {
gb_start = gb;
}
if(gb_start->name
&& gb2->name
&& (strcmp(gb_start->name,gb2->name) == 0)) {
gint b_digits = 2;
gint gb_tmp_cnt = gb_count++;
/* Alter gb2... */
g_free(gb2->name);
while((gb_tmp_cnt /= 10) > 0)
b_digits++;
/* name str + " #" + digits + null */
gb2->name = g_malloc(strlen(gb_start->name)+3+b_digits);
sprintf(gb2->name,"%s #%d",gb_start->name,gb_count);
}
else
{
gb_start = gb2;
gb_count = 0;
}
}
}
}
static void
brushes_free_one (gpointer data, gpointer dummy)
{
free_brush ((GBrushP) data);
}
static gint
brush_compare_func (gpointer first, gpointer second)
{
return strcmp (((GBrushP)first)->name, ((GBrushP)second)->name);
}
void
brushes_free ()
{
link_ptr list;
GBrushP brush;
list = brush_list;
while (list)
{
brush = (GBrushP) list->data;
free_brush (brush);
list = next_item (list);
}
free_list (list);
if (brush_list) {
g_slist_foreach (brush_list, brushes_free_one, NULL);
g_slist_free (brush_list);
}
have_default_brush = 0;
active_brush = NULL;
@@ -140,91 +232,49 @@ get_active_brush ()
}
static link_ptr
insert_brush_in_list (list, brush)
link_ptr list;
GBrushP brush;
static GSList *
insert_brush_in_list (GSList *list, GBrushP brush)
{
link_ptr tmp;
link_ptr prev;
link_ptr new_link;
GBrushP b;
int val;
/* Insert the item in the list */
if (list)
{
prev = NULL;
tmp = list;
do {
if (tmp)
{
b = (GBrushP) tmp->data;
/* do the comparison needed for the insertion sort */
val = strcmp (brush->name, b->name);
}
else
val = -1;
if (val <= 0)
{
/* this is the place the item goes */
/* Insert the item into the list. We'll have to create
* a new link and then do a little insertion.
*/
new_link = alloc_list ();
if (!new_link)
fatal_error ("Unable to allocate memory");
new_link->data = brush;
new_link->next = tmp;
if (prev)
prev->next = new_link;
if (tmp == list)
list = new_link;
return list;
}
/* Advance to the next item in the list.
*/
prev = tmp;
tmp = next_item (tmp);
} while (prev);
}
else
/* There are no items in the brush list, so we'll just start
* one right now.
*/
list = add_to_list (list, brush);
return list;
return g_slist_insert_sorted (list, brush, brush_compare_func);
}
static void
create_default_brush ()
static GBrushP
create_default_brush (gint width, gint height)
{
GBrushP brush;
gchar filled[] = { 255 };
#define BRUSHES_C_1_cw
Tag brush_tag = tag_new (default_precision, FORMAT_GRAY, ALPHA_NO);
brush = g_new (GBrush, 1);
brush->filename = NULL;
brush->name = g_strdup ("Default");
brush->mask = temp_buf_new (1, 1, 1, 0, 0, filled);
brush->mask = canvas_new (brush_tag, width, height, STORAGE_FLAT);
brush->spacing = 25;
/* Fill the default brush canvas with white */
{
COLOR16_NEWDATA (init, gfloat,
PRECISION_FLOAT, FORMAT_RGB, ALPHA_NO) = {1.0, 1.0, 1.0};
COLOR16_NEW (paint, canvas_tag (brush->mask));
/* Swap the brush to disk (if we're being stingy with memory) */
if (stingy_memory_use)
temp_buf_swap (brush->mask);
/* init the paint with the correctly formatted color */
COLOR16_INIT (init);
COLOR16_INIT (paint);
copy_row (&init, &paint);
brush_list = insert_brush_in_list(brush_list, brush);
/* Make this the default, active brush */
active_brush = brush;
have_default_brush = 1;
/* fill the area using the paint */
{
PixelArea area;
pixelarea_init (&area, brush->mask,
0, 0, 0, 0, TRUE);
color_area (&area, &paint);
}
}
return brush;
}
static void
@@ -237,7 +287,8 @@ load_brush(char *filename)
BrushHeader header;
unsigned int * hp;
int i;
gint bytes;
Tag tag;
brush = (GBrushP) g_malloc (sizeof (GBrush));
brush->filename = g_strdup (filename);
@@ -276,8 +327,8 @@ load_brush(char *filename)
return;
}
}
/* Check for correct version */
if (header.version != FILE_VERSION)
/* Check for version 1 or 2 */
if (header.version == 1 || header.version == 2)
{
/* If this is a version 1 brush, set the fp back 8 bytes */
if (header.version == 1)
@@ -287,18 +338,42 @@ load_brush(char *filename)
/* spacing is not defined in version 1 */
header.spacing = 25;
}
else
{
warning ("Unknown GIMP version #%d in \"%s\"\n", header.version,
filename);
/* If its version 1 or 2 the type field contains just
the number of bytes and must be converted to a drawable type. */
#define BRUSHES_C_3_cw
if (header.type == 1)
header.type = GRAY_GIMAGE;
else if (header.type == 3)
header.type = RGB_GIMAGE;
}
else if (header.version != FILE_VERSION)
{
g_message ("Unknown GIMP version #%d in \"%s\"\n", header.version,
filename);
fclose (fp);
free_brush (brush);
return;
}
tag = tag_from_drawable_type ( header.type );
#define BRUSHES_C_5_cw
if (tag_precision (tag) != default_precision )
{
fclose (fp);
free_brush (brush);
return;
}
}
}
/* Get a new brush mask */
brush->mask = temp_buf_new (header.width, header.height, header.bytes, 0, 0, NULL);
brush->mask = canvas_new (tag,
header.width,
header.height,
STORAGE_FLAT );
brush->spacing = header.spacing;
/* Read in the brush name */
@@ -307,7 +382,7 @@ load_brush(char *filename)
brush->name = (char *) g_malloc (sizeof (char) * bn_size);
if ((fread (brush->name, 1, bn_size, fp)) < bn_size)
{
warning ("Error in GIMP brush file...aborting.");
g_message ("Error in GIMP brush file...aborting.");
fclose (fp);
free_brush (brush);
return;
@@ -315,19 +390,27 @@ load_brush(char *filename)
}
else
brush->name = g_strdup ("Unnamed");
/* ref the canvas to allocate memory */
canvas_portion_refrw (brush->mask, 0, 0);
/* Read the brush mask data */
/* Read the image data */
if ((fread (temp_buf_data (brush->mask), 1, header.width * header.height, fp)) <
header.width * header.height)
warning ("GIMP brush file appears to be truncated.");
bytes = tag_bytes (tag);
if ((fread (canvas_portion_data (brush->mask,0,0), 1, header.width * header.height * bytes, fp)) <
header.width * header.height * bytes)
g_message ("GIMP brush file appears to be truncated.");
canvas_portion_unref (brush->mask,0,0);
/* Clean up */
fclose (fp);
/* Swap the brush to disk (if we're being stingy with memory) */
if (stingy_memory_use)
temp_buf_swap (brush->mask);
{
/*temp_buf_swap (brush->mask);*/
g_warning( "load_brush: canvas_swap not implemented.");
}
brush_list = insert_brush_in_list(brush_list, brush);
@@ -341,40 +424,38 @@ load_brush(char *filename)
GBrushP
get_brush_by_index (index)
int index;
get_brush_by_index (int index)
{
link_ptr list;
GBrushP brush;
GSList *list;
GBrushP brush = NULL;
list = brush_list;
list = g_slist_nth (brush_list, index);
if (list)
brush = (GBrushP) list->data;
while (list)
{
brush = (GBrushP) list->data;
if (brush->index == index)
return brush;
list = next_item (list);
}
return NULL;
return brush;
}
void
select_brush (brush)
GBrushP brush;
select_brush (GBrushP brush)
{
/* Make sure the active brush is swapped before we get a new one... */
if (stingy_memory_use)
temp_buf_swap (active_brush->mask);
{
/*temp_buf_swap (active_brush->mask);*/
g_warning( "select_brush: canvas_swap not implemented.");
}
/* Set the active brush */
active_brush = brush;
/* Make sure the active brush is unswapped... */
if (stingy_memory_use)
temp_buf_unswap (brush->mask);
{
/*temp_buf_unswap (brush->mask);*/
g_warning( "select_brush: canvas_swap not implemented.");
}
/* Keep up appearances in the brush dialog */
if (brush_select_dialog)
@@ -407,7 +488,7 @@ free_brush (brush)
GBrushP brush;
{
if (brush->mask)
temp_buf_free (brush->mask);
canvas_delete (brush->mask);
if (brush->filename)
g_free (brush->filename);
if (brush->name)
@@ -476,8 +557,8 @@ brushes_get_brush_invoker (Argument *args)
if (success)
{
return_args[1].value.pdb_pointer = g_strdup (brushp->name);
return_args[2].value.pdb_int = brushp->mask->width;
return_args[3].value.pdb_int = brushp->mask->height;
return_args[2].value.pdb_int = canvas_width (brushp->mask);
return_args[3].value.pdb_int = canvas_height (brushp->mask);
return_args[4].value.pdb_int = brushp->spacing;
}
@@ -497,7 +578,7 @@ brushes_refresh_brush_invoker (Argument *args)
*/
success = TRUE ;
brushes_init();
brushes_init(FALSE);
return procedural_db_return_args (&brushes_refresh_brush_proc, success);
}
@@ -579,7 +660,7 @@ static Argument *
brushes_set_brush_invoker (Argument *args)
{
GBrushP brushp;
link_ptr list;
GSList *list;
char *name;
success = (name = (char *) args[0].value.pdb_pointer) != NULL;
@@ -600,7 +681,7 @@ brushes_set_brush_invoker (Argument *args)
break;
}
list = next_item (list);
list = g_slist_next (list);
}
}
@@ -925,7 +1006,7 @@ static Argument *
brushes_list_invoker (Argument *args)
{
GBrushP brushp;
link_ptr list;
GSList *list;
char **brushes;
int i;
@@ -939,7 +1020,7 @@ brushes_list_invoker (Argument *args)
brushp = (GBrushP) list->data;
brushes[i++] = g_strdup (brushp->name);
list = next_item (list);
list = g_slist_next (list);
}
return_args = procedural_db_return_args (&brushes_list_proc, success);

View File

@@ -13,16 +13,15 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BRUSHES_H__
#define __BRUSHES_H__
#include "linked.h"
#include <glib.h>
#include "procedural_db.h"
#include "temp_buf.h"
struct _Canvas;
typedef struct _GBrush GBrush, * GBrushP;
struct _GBrush
@@ -31,16 +30,16 @@ struct _GBrush
char * name; /* brush's name--for brush selection dialog */
int spacing; /* brush's spacing */
int index; /* brush's index... */
TempBuf * mask; /* the actual mask... */
struct _Canvas * mask; /* the actual mask as canvas */
};
/* global variables */
extern link_ptr brush_list;
extern GSList * brush_list;
extern int num_brushes;
/* function declarations */
void brushes_init (void);
void brushes_init (int no_data);
void brushes_free (void);
void brush_select_dialog_free (void);
void select_brush (GBrushP);

View File

@@ -13,24 +13,28 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include "appenv.h"
#include "brush_select.h"
#include "bucket_fill.h"
#include "canvas.h"
#include "drawable.h"
#include "fuzzy_select.h"
#include "gdisplay.h"
#include "gimage_mask.h"
#include "interface.h"
#include "paint_funcs.h"
#include "paint_funcs_area.h"
#include "palette.h"
#include "patterns.h"
#include "pixelarea.h"
#include "pixelrow.h"
#include "selection.h"
#include "tools.h"
#include "undo.h"
/* the Bucket Fill structures */
typedef enum
{
@@ -57,13 +61,6 @@ static void bucket_fill_control (Tool *, int, gpointer);
static void bucket_fill (GImage *, GimpDrawable *, FillMode, int,
double, double, int, double, double);
static void bucket_fill_region (FillMode, PixelRegion *, PixelRegion *,
unsigned char *, TempBuf *, int, int, int);
static void bucket_fill_line_color (unsigned char *, unsigned char *,
unsigned char *, int, int, int);
static void bucket_fill_line_pattern (unsigned char *, unsigned char *,
TempBuf *, int, int, int, int, int);
static Argument *bucket_fill_invoker (Argument *);
@@ -148,7 +145,7 @@ create_bucket_options (void)
/* the new options structure */
options = (BucketOptions *) g_malloc (sizeof (BucketOptions));
options->opacity = 100.0;
options->threshold = 15.0;
options->threshold = 7;
options->fill_mode = FgColorFill;
options->paint_mode = NORMAL;
options->sample_merged = FALSE;
@@ -188,7 +185,7 @@ create_bucket_options (void)
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
threshold_scale_data = gtk_adjustment_new (15.0, 1.0, 255.0, 1.0, 1.0, 0.0);
threshold_scale_data = gtk_adjustment_new (7.0, 0.0, 100.0, 1.0, 1.0, 0.0);
threshold_scale = gtk_hscale_new (GTK_ADJUSTMENT (threshold_scale_data));
gtk_box_pack_start (GTK_BOX (hbox), threshold_scale, TRUE, TRUE, 0);
gtk_scale_set_value_pos (GTK_SCALE (threshold_scale), GTK_POS_TOP);
@@ -254,7 +251,7 @@ create_bucket_options (void)
}
void
static void
bucket_fill_button_press (tool, bevent, gdisp_ptr)
Tool *tool;
GdkEventButton *bevent;
@@ -284,7 +281,7 @@ bucket_fill_button_press (tool, bevent, gdisp_ptr)
}
void
static void
bucket_fill_button_release (tool, bevent, gdisp_ptr)
Tool *tool;
GdkEventButton *bevent;
@@ -318,7 +315,7 @@ bucket_fill_button_release (tool, bevent, gdisp_ptr)
PDB_INT32, (gint32) fill_mode,
PDB_INT32, (gint32) bucket_options->paint_mode,
PDB_FLOAT, (gdouble) bucket_options->opacity,
PDB_FLOAT, (gdouble) bucket_options->threshold,
PDB_FLOAT, (gdouble) bucket_options->threshold * 2.55,
PDB_INT32, (gint32) bucket_options->sample_merged,
PDB_FLOAT, (gdouble) bucket_tool->target_x,
PDB_FLOAT, (gdouble) bucket_tool->target_y,
@@ -327,7 +324,7 @@ bucket_fill_button_release (tool, bevent, gdisp_ptr)
if (return_vals[0].value.pdb_int == PDB_SUCCESS)
gdisplays_flush ();
else
message_box ("Bucket Fill operation failed.", NULL, NULL);
g_message ("Bucket Fill operation failed.");
procedural_db_destroy_args (return_vals, nreturn_vals);
}
@@ -372,7 +369,7 @@ bucket_fill_cursor_update (tool, mevent, gdisp_ptr)
*/
if (gimage_mask_is_empty (gdisp->gimage))
ctype = GDK_TCROSS;
else if (gimage_mask_value (gdisp->gimage, x, y))
else if (gimage_mask_value (gdisp->gimage, x, y) != 0)
ctype = GDK_TCROSS;
}
}
@@ -401,73 +398,41 @@ bucket_fill (gimage, drawable, fill_mode, paint_mode,
int sample_merged;
double x, y;
{
TileManager *buf_tiles;
PixelRegion bufPR, maskPR;
PixelArea maskPR;
Channel * mask = NULL;
int bytes, has_alpha;
int x1, y1, x2, y2;
unsigned char col [MAX_CHANNELS];
unsigned char *d1, *d2;
GPatternP pattern;
TempBuf * pat_buf;
int new_buf = 0;
pat_buf = NULL;
if (fill_mode == FgColorFill)
gimage_get_foreground (gimage, drawable, col);
else if (fill_mode == BgColorFill)
gimage_get_background (gimage, drawable, col);
else if (fill_mode == PatternFill)
/* error check args */
switch (fill_mode)
{
pattern = get_active_pattern ();
if (!pattern)
{
message_box ("No available patterns for this operation.", NULL, NULL);
return;
}
/* If the pattern doesn't match the image in terms of color type,
* transform it. (ie pattern is RGB, image is indexed)
*/
if (((pattern->mask->bytes == 3) && !drawable_color (drawable)) ||
((pattern->mask->bytes == 1) && !drawable_gray (drawable)))
{
int size;
if ((pattern->mask->bytes == 1) && drawable_color (drawable))
pat_buf = temp_buf_new (pattern->mask->width, pattern->mask->height, 3, 0, 0, NULL);
else
pat_buf = temp_buf_new (pattern->mask->width, pattern->mask->height, 1, 0, 0, NULL);
d1 = temp_buf_data (pattern->mask);
d2 = temp_buf_data (pat_buf);
size = pattern->mask->width * pattern->mask->height;
while (size--)
{
gimage_transform_color (gimage, drawable, d1, d2,
(pattern->mask->bytes == 3) ? RGB : GRAY);
d1 += pattern->mask->bytes;
d2 += pat_buf->bytes;
}
new_buf = 1;
}
else
pat_buf = pattern->mask;
case FgColorFill:
case BgColorFill:
break;
case PatternFill:
{
GPatternP pattern = get_active_pattern ();
if (!pattern || !pattern->mask)
{
g_message ("No available patterns for this operation.");
return;
}
}
break;
default:
g_warning ("bad fill type");
return;
}
bytes = drawable_bytes (drawable);
has_alpha = drawable_has_alpha (drawable);
/* If there is no selection mask, the do a seed bucket
* fill...To do this, calculate a new contiguous region
*/
/* we need a selection mask. either use the existing one, or
calculate a new one using a seed fill */
if (! drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2))
{
mask = find_contiguous_region (gimage, drawable, TRUE, (int) threshold,
mask = find_contiguous_region (gimage, drawable, TRUE, threshold,
(int) x, (int) y, sample_merged);
channel_bounds (mask, &x1, &y1, &x2, &y2);
@@ -479,13 +444,16 @@ bucket_fill (gimage, drawable, fill_mode, paint_mode,
/* Limit the channel bounds to the drawable's extents */
drawable_offsets (drawable, &off_x, &off_y);
x1 = BOUNDS (x1, off_x, (off_x + drawable_width (drawable)));
y1 = BOUNDS (y1, off_y, (off_y + drawable_height (drawable)));
x2 = BOUNDS (x2, off_x, (off_x + drawable_width (drawable)));
y2 = BOUNDS (y2, off_y, (off_y + drawable_height (drawable)));
pixel_region_init (&maskPR, drawable_data (GIMP_DRAWABLE(mask)),
x1, y1, (x2 - x1), (y2 - y1), TRUE);
pixelarea_init (&maskPR, drawable_data (GIMP_DRAWABLE(mask)),
x1, y1,
(x2 - x1), (y2 - y1),
FALSE);
/* translate mask bounds to drawable coords */
x1 -= off_x;
@@ -494,157 +462,94 @@ bucket_fill (gimage, drawable, fill_mode, paint_mode,
y2 -= off_y;
}
else
pixel_region_init (&maskPR, drawable_data (GIMP_DRAWABLE(mask)),
x1, y1, (x2 - x1), (y2 - y1), TRUE);
/* if the gimage doesn't have an alpha channel,
* make sure that the temp buf does. We need the
* alpha channel to fill with the region calculated above
*/
if (! has_alpha)
{
bytes ++;
has_alpha = 1;
}
{
pixelarea_init (&maskPR, drawable_data (GIMP_DRAWABLE(mask)),
x1, y1,
(x2 - x1), (y2 - y1),
FALSE);
}
}
buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes);
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
{
PixelArea bufPR;
Canvas * buf_tiles;
buf_tiles = canvas_new (tag_set_alpha (drawable_tag (drawable), ALPHA_YES),
(x2 - x1), (y2 - y1),
STORAGE_TILED);
pixelarea_init (&bufPR, buf_tiles,
0, 0,
0, 0,
TRUE);
if (mask)
bucket_fill_region (fill_mode, &bufPR, &maskPR, col, pat_buf, x1, y1, has_alpha);
else
bucket_fill_region (fill_mode, &bufPR, NULL, col, pat_buf, x1, y1, has_alpha);
switch (fill_mode)
{
case FgColorFill:
case BgColorFill:
{
COLOR16_NEW (col, canvas_tag (buf_tiles));
COLOR16_INIT (col);
if (fill_mode == FgColorFill)
palette_get_foreground (&col);
else
palette_get_background (&col);
color_area (&bufPR, &col);
}
break;
case PatternFill:
{
PixelArea patPR;
GPatternP pat = get_active_pattern ();
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
gimage_apply_image (gimage, drawable, &bufPR, TRUE,
(opacity * 255) / 100, paint_mode, NULL, x1, y1);
pixelarea_init2 (&patPR, pat->mask,
0, 0,
0, 0,
REFTYPE_READ, EDGETYPE_WRAP) ;
copy_area (&patPR, &bufPR);
}
break;
default:
g_warning ("bad fill type");
return;
}
/* if we did a seed fill, copy it to the alpha channel */
if (mask)
{
pixelarea_init (&bufPR, buf_tiles,
0, 0,
0, 0,
TRUE);
apply_mask_to_area (&bufPR, &maskPR, 1.0);
}
/* apply painthit to the image */
gimage_apply_painthit (gimage, drawable,
NULL, buf_tiles,
0, 0,
0, 0,
TRUE,
(opacity / 100.0), paint_mode, x1, y1);
canvas_delete (buf_tiles);
}
/* update the image */
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
/* free the temporary buffer */
tile_manager_destroy (buf_tiles);
/* free the mask */
/* clean up */
if (mask)
channel_delete (mask);
if (new_buf)
temp_buf_free (pat_buf);
}
static void
bucket_fill_line_color (buf, mask, col, has_alpha, bytes, width)
unsigned char * buf, * mask;
unsigned char * col;
int has_alpha;
int bytes;
int width;
{
int alpha, b;
alpha = (has_alpha) ? bytes - 1 : bytes;
while (width--)
{
for (b = 0; b < alpha; b++)
buf[b] = col[b];
if (has_alpha)
{
if (mask)
buf[alpha] = *mask++;
else
buf[alpha] = OPAQUE;
}
buf += bytes;
}
}
static void
bucket_fill_line_pattern (buf, mask, pattern, has_alpha, bytes, x, y, width)
unsigned char * buf, * mask;
TempBuf * pattern;
int has_alpha;
int bytes;
int x, y;
int width;
{
unsigned char *pat, *p;
int alpha, b;
int i;
/* Get a pointer to the appropriate scanline of the pattern buffer */
pat = temp_buf_data (pattern) +
(y % pattern->height) * pattern->width * pattern->bytes;
alpha = (has_alpha) ? bytes - 1 : bytes;
for (i = 0; i < width; i++)
{
p = pat + ((i + x) % pattern->width) * pattern->bytes;
for (b = 0; b < alpha; b++)
buf[b] = p[b];
if (has_alpha)
{
if (mask)
buf[alpha] = *mask++;
else
buf[alpha] = OPAQUE;
}
buf += bytes;
}
}
static void
bucket_fill_region (fill_mode, bufPR, maskPR, col, pattern, off_x, off_y, has_alpha)
FillMode fill_mode;
PixelRegion * bufPR;
PixelRegion * maskPR;
unsigned char * col;
TempBuf * pattern;
int off_x, off_y;
int has_alpha;
{
unsigned char *s, *m;
int y;
void *pr;
for (pr = pixel_regions_register (2, bufPR, maskPR); pr != NULL; pr = pixel_regions_process (pr))
{
s = bufPR->data;
if (maskPR)
m = maskPR->data;
else
m = NULL;
for (y = 0; y < bufPR->h; y++)
{
switch (fill_mode)
{
case FgColorFill:
case BgColorFill:
bucket_fill_line_color (s, m, col, has_alpha, bufPR->bytes, bufPR->w);
break;
case PatternFill:
bucket_fill_line_pattern (s, m, pattern, has_alpha, bufPR->bytes,
off_x + bufPR->x, off_y + y + bufPR->y, bufPR->w);
break;
}
s += bufPR->rowstride;
if (maskPR)
m += maskPR->rowstride;
}
}
}
/*********************************/
/* Global bucket fill functions */
/*********************************/
@@ -673,6 +578,7 @@ tools_new_bucket_fill ()
tool->arrow_keys_func = standard_arrow_keys_func;
tool->cursor_update_func = bucket_fill_cursor_update;
tool->control_func = bucket_fill_control;
tool->preserve = TRUE;
return tool;
}
@@ -827,7 +733,7 @@ bucket_fill_invoker (args)
{
fp_value = args[5].value.pdb_float;
if (fp_value >= 0.0 && fp_value <= 255.0)
threshold = fp_value;
threshold = fp_value / 255.0;
else
success = FALSE;
}

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BUCKET_FILL_H__
#define __BUCKET_FILL_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "appenv.h"
#include "buildmenu.h"

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BUILDMENU_H__
#define __BUILDMENU_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
@@ -21,6 +21,7 @@
#include "appenv.h"
#include "boundary.h"
#include "by_color_select.h"
#include "canvas.h"
#include "colormaps.h"
#include "drawable.h"
#include "draw_core.h"
@@ -29,8 +30,12 @@
#include "gimprc.h"
#include "gdisplay.h"
#include "rect_select.h"
#include "paint_funcs_area.h"
#include "pixelarea.h"
#include "pixelrow.h"
#define DEFAULT_FUZZINESS 15
#define DEFAULT_FUZZINESS 0.10 /* was 15/255 originally */
#define PREVIEW_WIDTH 256
#define PREVIEW_HEIGHT 256
#define PREVIEW_EVENT_MASK GDK_EXPOSURE_MASK | \
@@ -54,7 +59,7 @@ struct _ByColorDialog
GtkWidget *preview;
GtkWidget *gimage_name;
int threshold; /* threshold value for color select */
gfloat threshold; /* threshold value for color select */
int operation; /* Add, Subtract, Replace */
GImage *gimage; /* gimage which is currently under examination */
};
@@ -82,68 +87,18 @@ static void by_color_select_preview_button_press (ByColorDialog *, G
static SelectionOptions *by_color_options = NULL;
static ByColorDialog *by_color_dialog = NULL;
static int is_pixel_sufficiently_different (unsigned char *, unsigned char *, int, int, int, int);
static Channel * by_color_select_color (GImage *, GimpDrawable *, unsigned char *, int, int, int);
static void by_color_select (GImage *, GimpDrawable *, unsigned char *, int, int, int, int, double, int);
static Channel * by_color_select_color (GImage *, GimpDrawable *, PixelRow *, int, gfloat, int);
static void by_color_select (GImage *, GimpDrawable *, PixelRow *, gfloat, int, int, int, double, int);
static Argument * by_color_select_invoker (Argument *);
/* by_color selection machinery */
static int
is_pixel_sufficiently_different (unsigned char *col1,
unsigned char *col2,
int antialias,
int threshold,
int bytes,
int has_alpha)
{
int diff;
int max;
int b;
int alpha;
max = 0;
alpha = (has_alpha) ? bytes - 1 : bytes;
/* if there is an alpha channel, never select transparent regions */
if (has_alpha && col2[alpha] == 0)
return 0;
for (b = 0; b < alpha; b++)
{
diff = col1[b] - col2[b];
diff = abs (diff);
if (diff > max)
max = diff;
}
if (antialias && threshold > 0)
{
float aa;
aa = 1.5 - ((float) max / threshold);
if (aa <= 0)
return 0;
else if (aa < 0.5)
return (unsigned char) (aa * 512);
else
return 255;
}
else
{
if (max > threshold)
return 0;
else
return 255;
}
}
static Channel *
by_color_select_color (GImage *gimage,
GimpDrawable *drawable,
unsigned char *color,
PixelRow *color,
int antialias,
int threshold,
gfloat threshold,
int sample_merged)
{
/* Scan over the gimage's active layer, finding pixels within the specified
@@ -151,96 +106,49 @@ by_color_select_color (GImage *gimage,
* use the same antialiasing scheme as in fuzzy_select. Modify the gimage's
* mask to reflect the additional selection
*/
PixelArea imagePR, maskPR;
Channel *mask;
PixelRegion imagePR, maskPR;
unsigned char *image_data;
unsigned char *mask_data;
unsigned char *idata, *mdata;
unsigned char rgb[MAX_CHANNELS];
int has_alpha, indexed;
Canvas * image;
int width, height;
int bytes, color_bytes, alpha;
int i, j;
void * pr;
int d_type;
/* Get the image information */
if (sample_merged)
{
bytes = gimage_composite_bytes (gimage);
d_type = gimage_composite_type (gimage);
has_alpha = (d_type == RGBA_GIMAGE ||
d_type == GRAYA_GIMAGE ||
d_type == INDEXEDA_GIMAGE);
indexed = d_type == INDEXEDA_GIMAGE || d_type == INDEXED_GIMAGE;
width = gimage->width;
height = gimage->height;
pixel_region_init (&imagePR, gimage_composite (gimage), 0, 0, width, height, FALSE);
image = gimage_projection (gimage);
}
else
{
bytes = drawable_bytes (drawable);
d_type = drawable_type (drawable);
has_alpha = drawable_has_alpha (drawable);
indexed = drawable_indexed (drawable);
width = drawable_width (drawable);
height = drawable_height (drawable);
pixel_region_init (&imagePR, drawable_data (drawable), 0, 0, width, height, FALSE);
image = drawable_data (drawable);
}
if (indexed) {
/* indexed colors are always RGB or RGBA */
color_bytes = has_alpha ? 4 : 3;
} else {
/* RGB, RGBA, GRAY and GRAYA colors are shaped just like the image */
color_bytes = bytes;
}
mask = channel_new_mask (gimage->ID,
width, height,
tag_precision (drawable_tag (drawable)));
alpha = bytes - 1;
mask = channel_new_mask (gimage->ID, width, height);
pixel_region_init (&maskPR, drawable_data (GIMP_DRAWABLE(mask)),
0, 0, width, height, TRUE);
pixelarea_init (&imagePR, image,
0, 0,
width, height,
FALSE);
/* iterate over the entire image */
for (pr = pixel_regions_register (2, &imagePR, &maskPR); pr != NULL; pr = pixel_regions_process (pr))
{
image_data = imagePR.data;
mask_data = maskPR.data;
for (i = 0; i < imagePR.h; i++)
{
idata = image_data;
mdata = mask_data;
for (j = 0; j < imagePR.w; j++)
{
/* Get the rgb values for the color */
gimage_get_color (gimage, d_type, rgb, idata);
/* Plug the alpha channel in there */
if (has_alpha)
rgb[color_bytes - 1] = idata[alpha];
/* Find how closely the colors match */
*mdata++ = is_pixel_sufficiently_different (color, rgb, antialias,
threshold, color_bytes, has_alpha);
idata += bytes;
}
image_data += imagePR.rowstride;
mask_data += maskPR.rowstride;
}
}
pixelarea_init (&maskPR, drawable_data (GIMP_DRAWABLE(mask)),
0, 0,
width, height,
TRUE);
absdiff_area (&imagePR, &maskPR, color, threshold, antialias);
return mask;
}
static void
by_color_select (GImage *gimage,
GimpDrawable *drawable,
unsigned char *color,
int threshold,
PixelRow *color,
gfloat threshold,
int op,
int antialias,
int feather,
@@ -292,6 +200,8 @@ by_color_select_button_press (Tool *tool,
gdisp = (GDisplay *) gdisp_ptr;
by_color_sel = (ByColorSelect *) tool->private;
tool->drawable = gimage_active_drawable (gdisp->gimage);
if (!by_color_dialog)
return;
@@ -334,9 +244,6 @@ by_color_select_button_release (Tool *tool,
GDisplay * gdisp;
int x, y;
GimpDrawable *drawable;
Tile *tile;
unsigned char col[MAX_CHANNELS];
unsigned char *data;
int use_offsets;
gdisp = (GDisplay *) gdisp_ptr;
@@ -348,6 +255,8 @@ by_color_select_button_release (Tool *tool,
/* First take care of the case where the user "cancels" the action */
if (! (bevent->state & GDK_BUTTON3_MASK))
{
Canvas * canvas;
use_offsets = (by_color_options->sample_merged) ? FALSE : TRUE;
gdisplay_untransform_coords (gdisp, by_color_sel->x, by_color_sel->y, &x, &y, FALSE, use_offsets);
@@ -356,37 +265,39 @@ by_color_select_button_release (Tool *tool,
{
if (x < 0 || y < 0 || x >= gdisp->gimage->width || y >= gdisp->gimage->height)
return;
tile = tile_manager_get_tile (gimage_composite (gdisp->gimage), x, y, 0);
tile_ref (tile);
data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
canvas = gimage_projection (gdisp->gimage);
}
else
{
if (x < 0 || y < 0 || x >= drawable_width (drawable) || y >= drawable_height (drawable))
return;
tile = tile_manager_get_tile (drawable_data (drawable), x, y, 0);
tile_ref (tile);
data = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
canvas = drawable_data (drawable);
}
gimage_get_color (gdisp->gimage, gimage_composite_type(gdisp->gimage), col, data);
tile_unref (tile, FALSE);
if (canvas_portion_refro (canvas, x, y) == REFRC_OK)
{
PixelRow col;
/* select the area */
by_color_select (gdisp->gimage, drawable, col,
by_color_dialog->threshold,
by_color_sel->operation,
by_color_options->antialias,
by_color_options->feather,
by_color_options->feather_radius,
by_color_options->sample_merged);
pixelrow_init (&col, canvas_tag (canvas), canvas_portion_data (canvas, x, y), 1);
/* select the area */
by_color_select (gdisp->gimage, drawable, &col,
by_color_dialog->threshold,
by_color_sel->operation,
by_color_options->antialias,
by_color_options->feather,
by_color_options->feather_radius,
by_color_options->sample_merged);
/* show selection on all views */
gdisplays_flush ();
canvas_portion_unref (canvas, x, y);
/* show selection on all views */
gdisplays_flush ();
/* update the preview window */
by_color_select_render (by_color_dialog, gdisp->gimage);
by_color_select_draw (by_color_dialog, gdisp->gimage);
/* update the preview window */
by_color_select_render (by_color_dialog, gdisp->gimage);
by_color_select_draw (by_color_dialog, gdisp->gimage);
}
}
}
@@ -476,6 +387,9 @@ tools_new_by_color_select ()
tool->arrow_keys_func = standard_arrow_keys_func;
tool->cursor_update_func = by_color_select_cursor_update;
tool->control_func = by_color_select_control;
tool->gdisp_ptr = NULL;
tool->drawable = NULL;
tool->preserve = TRUE;
return tool;
}
@@ -520,7 +434,7 @@ by_color_select_initialize (void *gimage_ptr)
/* Select by Color dialog */
/****************************/
ByColorDialog *
static ByColorDialog *
by_color_select_new_dialog ()
{
ByColorDialog *bcd;
@@ -536,7 +450,7 @@ by_color_select_new_dialog ()
GtkWidget *radio_button;
GtkObject *data;
GSList *group = NULL;
int i;
guint i;
char *button_names[4] =
{
"Replace",
@@ -559,6 +473,7 @@ by_color_select_new_dialog ()
/* The shell and main vbox */
bcd->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (bcd->shell), "by_color_selection", "Gimp");
gtk_window_set_title (GTK_WINDOW (bcd->shell), "By Color Selection");
gtk_container_border_width (GTK_CONTAINER (GTK_DIALOG (bcd->shell)->action_area), 2);
@@ -599,7 +514,7 @@ by_color_select_new_dialog ()
gtk_container_border_width (GTK_CONTAINER (options_box), 5);
gtk_box_pack_start (GTK_BOX (hbox), options_box, TRUE, TRUE, 0);
/* Create the active brush label */
/* Create the active image label */
util_box = gtk_hbox_new (FALSE, 2);
gtk_box_pack_start (GTK_BOX (options_box), util_box, FALSE, FALSE, 0);
bcd->gimage_name = gtk_label_new ("Inactive");
@@ -634,7 +549,7 @@ by_color_select_new_dialog ()
gtk_box_pack_start (GTK_BOX (options_box), util_box, FALSE, FALSE, 0);
label = gtk_label_new ("Fuzziness Threshold");
gtk_box_pack_start (GTK_BOX (util_box), label, FALSE, FALSE, 2);
data = gtk_adjustment_new (bcd->threshold, 0.0, 255.0, 1.0, 1.0, 0.0);
data = gtk_adjustment_new (bcd->threshold, 0.0, 1.0, 0.01, 0.1, 0.0);
slider = gtk_hscale_new (GTK_ADJUSTMENT (data));
gtk_box_pack_start (GTK_BOX (util_box), slider, TRUE, TRUE, 0);
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
@@ -679,41 +594,37 @@ by_color_select_render (ByColorDialog *bcd,
GImage *gimage)
{
Channel * mask;
MaskBuf * scaled_buf = NULL;
Canvas * scaled_buf = NULL;
unsigned char *buf;
PixelRegion srcPR, destPR;
unsigned char * src;
int subsample;
int width, height;
int srcwidth;
PixelArea srcPR, destPR;
int width, height, w, h;
int i;
int scale;
mask = gimage_get_mask (gimage);
if ((drawable_width (GIMP_DRAWABLE(mask)) > PREVIEW_WIDTH) ||
(drawable_height (GIMP_DRAWABLE(mask)) > PREVIEW_HEIGHT))
w = drawable_width (GIMP_DRAWABLE (mask));
h = drawable_height (GIMP_DRAWABLE (mask));
width = w;
height = h;
scale = FALSE;
if ((width > PREVIEW_WIDTH) || (height > PREVIEW_HEIGHT))
{
if (((float) drawable_width (GIMP_DRAWABLE (mask)) / (float) PREVIEW_WIDTH) >
((float) drawable_height (GIMP_DRAWABLE (mask)) / (float) PREVIEW_HEIGHT))
if (((float) width / (float) PREVIEW_WIDTH) >
((float) height / (float) PREVIEW_HEIGHT))
{
height = (height * PREVIEW_WIDTH) / width;
width = PREVIEW_WIDTH;
height = (drawable_height (GIMP_DRAWABLE (mask)) * PREVIEW_WIDTH) / drawable_width (GIMP_DRAWABLE (mask));
}
else
{
width = (drawable_width (GIMP_DRAWABLE (mask)) * PREVIEW_HEIGHT) / drawable_height (GIMP_DRAWABLE (mask));
height = PREVIEW_HEIGHT;
width = (width * PREVIEW_HEIGHT) / height;
height = PREVIEW_HEIGHT;
}
scale = TRUE;
}
else
{
width = drawable_width (GIMP_DRAWABLE (mask));
height = drawable_height (GIMP_DRAWABLE (mask));
scale = FALSE;
}
if ((width != bcd->preview->requisition.width) ||
(height != bcd->preview->requisition.height))
@@ -730,60 +641,65 @@ by_color_select_render (ByColorDialog *bcd,
if (gimage_mask_is_empty (gimage))
return;
scaled_buf = canvas_new (tag_new (tag_precision (gimage_tag (gimage)),
FORMAT_GRAY,
ALPHA_NO),
width,
height,
STORAGE_FLAT);
pixelarea_init (&srcPR, drawable_data (GIMP_DRAWABLE (mask)),
0, 0,
w, h,
FALSE);
pixelarea_init (&destPR, scaled_buf,
0, 0,
width, height,
TRUE);
if (scale)
{
/* calculate 'acceptable' subsample */
subsample = 1;
while ((width * (subsample + 1) * 2 < drawable_width (GIMP_DRAWABLE (mask))) &&
(height * (subsample + 1) * 2 < drawable_height (GIMP_DRAWABLE (mask))))
subsample = subsample + 1;
pixel_region_init (&srcPR, drawable_data (GIMP_DRAWABLE (mask)),
0, 0,
drawable_width (GIMP_DRAWABLE (mask)),
drawable_height (GIMP_DRAWABLE (mask)), FALSE);
scaled_buf = mask_buf_new (width, height);
destPR.bytes = 1;
destPR.x = 0;
destPR.y = 0;
destPR.w = width;
destPR.h = height;
destPR.rowstride = srcPR.bytes * width;
destPR.data = mask_buf_data (scaled_buf);
destPR.tiles = NULL;
subsample_region (&srcPR, &destPR, subsample);
scale_area (&srcPR, &destPR);
}
else
{
pixel_region_init (&srcPR, drawable_data (GIMP_DRAWABLE (mask)),
0, 0,
drawable_width (GIMP_DRAWABLE (mask)),
drawable_height (GIMP_DRAWABLE (mask)), FALSE);
scaled_buf = mask_buf_new (width, height);
destPR.bytes = 1;
destPR.x = 0;
destPR.y = 0;
destPR.w = width;
destPR.h = height;
destPR.rowstride = srcPR.bytes * width;
destPR.data = mask_buf_data (scaled_buf);
destPR.tiles = NULL;
copy_region (&srcPR, &destPR);
copy_area (&srcPR, &destPR);
}
src = mask_buf_data (scaled_buf);
srcwidth = scaled_buf->width;
for (i = 0; i < height; i++)
{
gtk_preview_draw_row (GTK_PREVIEW (bcd->preview), src, 0, i, width);
src += srcwidth;
}
{
PixelArea a;
PixelRow srcrow, dstrow;
int w, h;
mask_buf_free (scaled_buf);
w = canvas_width (scaled_buf);
h = canvas_height (scaled_buf);
buf = (unsigned char *) g_malloc (w);
pixelrow_init (&dstrow,
tag_new (PRECISION_U8,
FORMAT_GRAY,
ALPHA_NO),
buf,
w);
pixelarea_init (&a, scaled_buf,
0, 0,
0, 0,
FALSE);
for (i = 0; i < h; i++)
{
pixelarea_getdata (&a, &srcrow, i);
copy_row (&srcrow, &dstrow);
gtk_preview_draw_row (GTK_PREVIEW (bcd->preview), buf, 0, i, width);
}
g_free (buf);
}
canvas_delete (scaled_buf);
}
static void
@@ -830,9 +746,14 @@ by_color_select_reset_callback (GtkWidget *widget,
ByColorDialog *bcd;
bcd = (ByColorDialog *) client_data;
if (!bcd->gimage)
return;
/* check if the image associated to the mask still exists */
if (!drawable_gimage (GIMP_DRAWABLE(gimage_get_mask (bcd->gimage))))
return;
/* reset the mask */
gimage_mask_clear (bcd->gimage);
@@ -851,7 +772,7 @@ by_color_select_delete_callback (GtkWidget *w,
{
by_color_select_close_callback (w, client_data);
return FALSE;
return TRUE;
}
static void
@@ -872,7 +793,7 @@ by_color_select_fuzzy_update (GtkAdjustment *adjustment,
ByColorDialog *bcd;
bcd = (ByColorDialog *) data;
bcd->threshold = (int) adjustment->value;
bcd->threshold = adjustment->value;
}
static void
@@ -882,13 +803,17 @@ by_color_select_preview_button_press (ByColorDialog *bcd,
int x, y;
int replace, operation;
GimpDrawable *drawable;
Tile *tile;
unsigned char *col;
Canvas * image;
if (!bcd->gimage)
return;
drawable = gimage_active_drawable (bcd->gimage);
/* check if the gimage associated to the drawable still exists */
if (!drawable_gimage (drawable))
return;
/* Defaults */
replace = FALSE;
operation = REPLACE;
@@ -912,9 +837,7 @@ by_color_select_preview_button_press (ByColorDialog *bcd,
y = bcd->gimage->height * bevent->y / bcd->preview->requisition.height;
if (x < 0 || y < 0 || x >= bcd->gimage->width || y >= bcd->gimage->height)
return;
tile = tile_manager_get_tile (gimage_composite (bcd->gimage), x, y, 0);
tile_ref (tile);
col = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
image = gimage_projection (bcd->gimage);
}
else
{
@@ -925,20 +848,27 @@ by_color_select_preview_button_press (ByColorDialog *bcd,
y = drawable_height (drawable) * bevent->y / bcd->preview->requisition.height - offy;
if (x < 0 || y < 0 || x >= drawable_width (drawable) || y >= drawable_height (drawable))
return;
tile = tile_manager_get_tile (drawable_data (drawable), x, y, 0);
tile_ref (tile);
col = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
image = drawable_data (drawable);
}
by_color_select (bcd->gimage, drawable, col,
bcd->threshold,
operation,
by_color_options->antialias,
by_color_options->feather,
by_color_options->feather_radius,
by_color_options->sample_merged);
canvas_portion_refro (image, x, y);
tile_unref (tile, FALSE);
{
PixelRow col;
pixelrow_init (&col, canvas_tag (image),
canvas_portion_data (image, x, y), 1);
by_color_select (bcd->gimage, drawable, &col,
bcd->threshold,
operation,
by_color_options->antialias,
by_color_options->feather,
by_color_options->feather_radius,
by_color_options->sample_merged);
}
canvas_portion_unref (image, x, y);
/* show selection on all views */
gdisplays_flush ();
@@ -1020,17 +950,18 @@ by_color_select_invoker (Argument *args)
GImage *gimage;
GimpDrawable *drawable;
int op;
int threshold;
gfloat threshold;
int antialias;
int feather;
int sample_merged;
unsigned char color[3];
guchar _color[TAG_MAX_BYTES];
PixelRow color;
double feather_radius;
int int_value;
drawable = NULL;
op = REPLACE;
threshold = 0;
threshold = 0.0;
/* the gimage */
if (success)
@@ -1050,19 +981,23 @@ by_color_select_invoker (Argument *args)
/* color */
if (success)
{
int i;
unsigned char *color_array;
PixelRow temp;
color_array = (unsigned char *) args[2].value.pdb_pointer;
for (i = 0; i < 3; i++)
color[i] = color_array[i];
pixelrow_init (&temp, tag_new (PRECISION_U8, FORMAT_RGB, ALPHA_NO),
color_array, 1);
pixelrow_init (&color, drawable_tag (drawable),
_color, 1);
copy_row (&temp, &color);
}
/* threshold */
if (success)
{
int_value = args[3].value.pdb_int;
if (int_value >= 0 && int_value <= 255)
threshold = int_value;
threshold = (gfloat) int_value / 255.0;
else
success = FALSE;
}
@@ -1105,7 +1040,7 @@ by_color_select_invoker (Argument *args)
/* call the ellipse_select procedure */
if (success)
by_color_select (gimage, drawable, color, threshold, op,
by_color_select (gimage, drawable, &color, threshold, op,
antialias, feather, feather_radius, sample_merged);
return procedural_db_return_args (&by_color_select_proc, success);

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BY_COLOR_SELECT_H__
#define __BY_COLOR_SELECT_H__

746
app/canvas.c Normal file
View File

@@ -0,0 +1,746 @@
/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <string.h>
#include "canvas.h"
#include "flatbuf.h"
#include "shmbuf.h"
#include "tilebuf.h"
#include "trace.h"
struct _Canvas
{
/* the image size */
int width;
int height;
/* should a ref of a non-existent area allocate the memory? */
AutoAlloc autoalloc;
/* the physical buffer holding the image */
Storage storage;
void * rep;
/* function and data for initializing new memory */
CanvasInitFunc init_func;
void * init_data;
/* cached info about the physical rep */
Tag tag;
int bytes;
/* this is so wrong */
int x;
int y;
};
int
canvas_fixme_getx (
Canvas * c
)
{
return (c ? c->x : 0);
}
int
canvas_fixme_gety (
Canvas * c
)
{
return (c ? c->y : 0);
}
int
canvas_fixme_setx (
Canvas * c,
int n
)
{
return (c ? c->x=n : 0);
}
int
canvas_fixme_sety (
Canvas * c,
int n
)
{
return (c ? c->y=n : 0);
}
Canvas *
canvas_new (
Tag tag,
int w,
int h,
Storage storage
)
{
Canvas *c;
c = (Canvas *) g_malloc (sizeof (Canvas));
c->storage = storage;
c->autoalloc = AUTOALLOC_ON;
c->tag = tag;
c->bytes = tag_bytes (tag);
c->width = w;
c->height = h;
c->init_func = NULL;
c->init_data = NULL;
c->x = 0;
c->y = 0;
switch (storage)
{
case STORAGE_FLAT:
c->rep = (void *) flatbuf_new (tag, w, h, c);
break;
case STORAGE_TILED:
c->rep = (void *) tilebuf_new (tag, w, h, c);
break;
case STORAGE_SHM:
c->rep = (void *) shmbuf_new (tag, w, h, c);
break;
default:
c->storage = STORAGE_NONE;
c->rep = NULL;
c->tag = tag_null ();
c->bytes = tag_bytes (c->tag);
break;
}
return c;
}
void
canvas_delete (
Canvas * c
)
{
if (c)
{
if (c->rep)
{
switch (c->storage)
{
case STORAGE_FLAT:
flatbuf_delete ((FlatBuf *) c->rep);
break;
case STORAGE_TILED:
tilebuf_delete ((TileBuf *) c->rep);
break;
case STORAGE_SHM:
shmbuf_delete ((ShmBuf *) c->rep);
break;
default:
break;
}
}
g_free (c);
}
}
void
canvas_info (
Canvas *c
)
{
if (c)
{
trace_begin ("Canvas 0x%x", c);
trace_printf ("Width: %d Height: %d", c->width, c->height);
trace_printf (c->autoalloc==AUTOALLOC_ON ? "AutoAlloc" : "No AutoAlloc" );
if (c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
tilebuf_info ((TileBuf *) c->rep);
break;
case STORAGE_FLAT:
flatbuf_info ((FlatBuf *) c->rep);
break;
case STORAGE_SHM:
shmbuf_info ((ShmBuf *) c->rep);
break;
default:
trace_printf ("Unknown image data");
break;
}
}
else
{
trace_printf ("No image data");
}
trace_end ();
}
}
Tag
canvas_tag (
Canvas * c
)
{
return ( c ? c->tag : tag_null ());
}
Precision
canvas_precision (
Canvas * c
)
{
return ( c ? tag_precision (c->tag) : PRECISION_NONE);
}
Format
canvas_format (
Canvas * c
)
{
return ( c ? tag_format (c->tag) : FORMAT_NONE);
}
Alpha
canvas_alpha (
Canvas * c
)
{
return ( c ? tag_alpha (c->tag) : ALPHA_NONE);
}
Storage
canvas_storage (
Canvas * c
)
{
return ( c ? c->storage : STORAGE_NONE);
}
AutoAlloc
canvas_autoalloc (
Canvas * c
)
{
return ( c ? c->autoalloc : AUTOALLOC_NONE);
}
AutoAlloc
canvas_set_autoalloc (
Canvas * c,
AutoAlloc aa
)
{
if (c)
switch (aa)
{
case AUTOALLOC_OFF:
case AUTOALLOC_ON:
c->autoalloc = aa;
default:
break;
}
return canvas_autoalloc (c);
}
int
canvas_width (
Canvas * c
)
{
return ( c ? c->width : 0);
}
int
canvas_height (
Canvas * c
)
{
return ( c ? c->height : 0);
}
int
canvas_bytes (
Canvas * c
)
{
return ( c ? c->bytes : 0);
}
/* debugging counters */
int ref_ro = 0;
int ref_rw = 0;
int ref_un = 0;
int ref_fa = 0;
int ref_uf = 0;
RefRC
canvas_portion_refro (
Canvas * c,
int x,
int y
)
{
RefRC rc = REFRC_FAIL;
if (c && c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
rc = tilebuf_portion_refro ((TileBuf *) c->rep, x, y);
break;
case STORAGE_FLAT:
rc = flatbuf_portion_refro ((FlatBuf *) c->rep, x, y);
break;
case STORAGE_SHM:
rc = shmbuf_portion_refro ((ShmBuf *) c->rep, x, y);
break;
default:
break;
}
}
switch (rc)
{
case REFRC_OK:
ref_ro++;
break;
case REFRC_FAIL:
default:
ref_fa++;
break;
}
return rc;
}
RefRC
canvas_portion_refrw (
Canvas * c,
int x,
int y
)
{
RefRC rc = REFRC_FAIL;
if (c && c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
rc = tilebuf_portion_refrw ((TileBuf *) c->rep, x, y);
break;
case STORAGE_FLAT:
rc = flatbuf_portion_refrw ((FlatBuf *) c->rep, x, y);
break;
case STORAGE_SHM:
rc = shmbuf_portion_refrw ((ShmBuf *) c->rep, x, y);
break;
default:
break;
}
}
switch (rc)
{
case REFRC_OK:
ref_rw++;
break;
case REFRC_FAIL:
default:
ref_fa++;
break;
}
return rc;
}
RefRC
canvas_portion_unref (
Canvas * c,
int x,
int y
)
{
RefRC rc = REFRC_FAIL;
if (c && c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
rc = tilebuf_portion_unref ((TileBuf *) c->rep, x, y);
break;
case STORAGE_FLAT:
rc = flatbuf_portion_unref ((FlatBuf *) c->rep, x, y);
break;
case STORAGE_SHM:
rc = shmbuf_portion_unref ((ShmBuf *) c->rep, x, y);
break;
default:
break;
}
}
switch (rc)
{
case REFRC_OK:
ref_un++;
break;
case REFRC_FAIL:
default:
ref_uf++;
break;
}
return rc;
}
guint
canvas_portion_width (
Canvas * c,
int x,
int y
)
{
if (c && c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
return tilebuf_portion_width ((TileBuf *) c->rep, x, y);
break;
case STORAGE_FLAT:
return flatbuf_portion_width ((FlatBuf *) c->rep, x, y);
break;
case STORAGE_SHM:
return shmbuf_portion_width ((ShmBuf *) c->rep, x, y);
break;
default:
break;
}
}
return 0;
}
guint
canvas_portion_height (
Canvas * c,
int x,
int y
)
{
if (c && c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
return tilebuf_portion_height ((TileBuf *) c->rep, x, y);
break;
case STORAGE_FLAT:
return flatbuf_portion_height ((FlatBuf *) c->rep, x, y);
break;
case STORAGE_SHM:
return shmbuf_portion_height ((ShmBuf *) c->rep, x, y);
break;
default:
break;
}
}
return 0;
}
guint
canvas_portion_y (
Canvas * c,
int x,
int y
)
{
if (c && c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
return tilebuf_portion_y ((TileBuf *) c->rep, x, y);
break;
case STORAGE_FLAT:
return flatbuf_portion_y ((FlatBuf *) c->rep, x, y);
break;
case STORAGE_SHM:
return shmbuf_portion_y ((ShmBuf *) c->rep, x, y);
break;
default:
break;
}
}
return 0;
}
guint
canvas_portion_x (
Canvas * c,
int x,
int y
)
{
if (c && c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
return tilebuf_portion_x ((TileBuf *) c->rep, x, y);
break;
case STORAGE_FLAT:
return flatbuf_portion_x ((FlatBuf *) c->rep, x, y);
break;
case STORAGE_SHM:
return shmbuf_portion_x ((ShmBuf *) c->rep, x, y);
break;
default:
break;
}
}
return 0;
}
guchar *
canvas_portion_data (
Canvas * c,
int x,
int y
)
{
if (c && c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
return tilebuf_portion_data ((TileBuf *) c->rep, x, y);
break;
case STORAGE_FLAT:
return flatbuf_portion_data ((FlatBuf *) c->rep, x, y);
break;
case STORAGE_SHM:
return shmbuf_portion_data ((ShmBuf *) c->rep, x, y);
break;
default:
break;
}
}
return NULL;
}
guint
canvas_portion_rowstride (
Canvas * c,
int x,
int y
)
{
if (c && c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
return tilebuf_portion_rowstride ((TileBuf *) c->rep, x, y);
break;
case STORAGE_FLAT:
return flatbuf_portion_rowstride ((FlatBuf *) c->rep, x, y);
break;
case STORAGE_SHM:
return shmbuf_portion_rowstride ((ShmBuf *) c->rep, x, y);
break;
default:
break;
}
}
return 0;
}
guint
canvas_portion_alloced (
Canvas * c,
int x,
int y
)
{
if (c && c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
return tilebuf_portion_alloced ((TileBuf *) c->rep, x, y);
break;
case STORAGE_FLAT:
return flatbuf_portion_alloced ((FlatBuf *) c->rep, x, y);
break;
case STORAGE_SHM:
return shmbuf_portion_alloced ((ShmBuf *) c->rep, x, y);
break;
default:
break;
}
}
return FALSE;
}
guint
canvas_portion_alloc (
Canvas * c,
int x,
int y
)
{
if (c && c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
return tilebuf_portion_alloc ((TileBuf *) c->rep, x, y);
break;
case STORAGE_FLAT:
return flatbuf_portion_alloc ((FlatBuf *) c->rep, x, y);
break;
case STORAGE_SHM:
return shmbuf_portion_alloc ((ShmBuf *) c->rep, x, y);
break;
default:
break;
}
}
return FALSE;
}
guint
canvas_portion_unalloc (
Canvas * c,
int x,
int y
)
{
if (c && c->rep)
{
switch (c->storage)
{
case STORAGE_TILED:
return tilebuf_portion_unalloc ((TileBuf *) c->rep, x, y);
break;
case STORAGE_FLAT:
return flatbuf_portion_unalloc ((FlatBuf *) c->rep, x, y);
break;
case STORAGE_SHM:
return shmbuf_portion_unalloc ((ShmBuf *) c->rep, x, y);
break;
default:
break;
}
}
return FALSE;
}
/*
FIXME:
this doesn;t work right for tiles. edge tiles only get the
"on-image" portion inited. the part that lies off the image isn;t
inited because the portion_width and portion_height ignore it.
the proper fix for this is to split portion out of canvas and deal
only with tiles at the canvas level. for now we just memset the
chunk to zero in portion_alloc */
guint
canvas_portion_init (
Canvas * c,
int x,
int y,
int w,
int h
)
{
if (c)
{
if (c->init_func)
{
return c->init_func (c, x, y, w, h, c->init_data);
}
return TRUE;
}
return FALSE;
}
void
canvas_portion_init_setup (
Canvas * c,
CanvasInitFunc func,
void * data
)
{
if (c)
{
c->init_func = func;
c->init_data = data;
}
}

124
app/canvas.h Normal file
View File

@@ -0,0 +1,124 @@
/* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __CANVAS_H__
#define __CANVAS_H__
#include "tag.h"
/* what sort of physical representation to use */
typedef struct _Canvas Canvas;
typedef enum
{
STORAGE_NONE = 0,
STORAGE_FLAT = 1,
STORAGE_TILED = 2,
STORAGE_SHM = 3
} Storage;
/* should a ref of an unalloced portion automatically allocate the
memory or simply fail */
typedef enum
{
AUTOALLOC_NONE = 0,
AUTOALLOC_OFF = 1,
AUTOALLOC_ON = 2
} AutoAlloc;
/* ways to reference a portion */
typedef enum
{
REFTYPE_NONE = 0,
REFTYPE_READ = 1,
REFTYPE_WRITE = 2
} RefType;
/* the result of referencing a portion. a successful ref means the
data pointer is non-null */
typedef enum
{
REFRC_NONE = 0,
REFRC_OK = 1,
REFRC_FAIL = 2
} RefRC;
Canvas * canvas_new (Tag, int w, int h, Storage);
void canvas_delete (Canvas *);
void canvas_info (Canvas *);
Tag canvas_tag (Canvas *);
Precision canvas_precision (Canvas *);
Format canvas_format (Canvas *);
Alpha canvas_alpha (Canvas *);
Storage canvas_storage (Canvas *);
AutoAlloc canvas_autoalloc (Canvas *);
AutoAlloc canvas_set_autoalloc (Canvas *, AutoAlloc);
int canvas_width (Canvas *);
int canvas_height (Canvas *);
int canvas_bytes (Canvas *);
/* a portion is a rectangular area of a Canvas that resides on a
single underlying chunk of memory (eg: a tile) */
/* return the TOP LEFT coordinate of the tile this pixel lies on */
guint canvas_portion_x (Canvas *, int x, int y);
guint canvas_portion_y (Canvas *, int x, int y);
/* return the maximum width and height of the rectangle that has the
specified TOP LEFT pixel AND is contained on a single tile */
guint canvas_portion_width (Canvas *, int x, int y);
guint canvas_portion_height (Canvas *, int x, int y);
/* get the data pointer and rowstride for the rectangle with the
specified TOP LEFT corner */
guchar * canvas_portion_data (Canvas *, int x, int y);
guint canvas_portion_rowstride (Canvas *, int x, int y);
/* check if a pixel needs to have memory allocated, alloc and dealloc
the memory */
guint canvas_portion_alloced (Canvas *, int x, int y);
guint canvas_portion_alloc (Canvas *, int x, int y);
guint canvas_portion_unalloc (Canvas *, int x, int y);
/* allocate and/or swap in the backing store for this pixel */
RefRC canvas_portion_refro (Canvas *, int x, int y);
RefRC canvas_portion_refrw (Canvas *, int x, int y);
RefRC canvas_portion_unref (Canvas *, int x, int y);
/* initialize the backing store for this pixel */
typedef guint (*CanvasInitFunc) (Canvas *, int, int, int, int, void *);
void canvas_portion_init_setup (Canvas *, CanvasInitFunc, void *);
guint canvas_portion_init (Canvas *, int x, int y, int w, int h);
/* FIXME FIXME FIXME */
int canvas_fixme_getx (Canvas *);
int canvas_fixme_gety (Canvas *);
int canvas_fixme_setx (Canvas *, int);
int canvas_fixme_sety (Canvas *, int);
#endif /* __CANVAS_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CHANNEL_H__
#define __CHANNEL_H__
@@ -21,8 +21,11 @@
#include "drawable.h"
#include "boundary.h"
#include "temp_buf.h"
#include "tile_manager.h"
#include "tag.h"
struct _Canvas;
struct _PixelRow;
/* OPERATIONS */
@@ -32,7 +35,7 @@
#define INTERSECT 3
/* Half way point where a region is no longer visible in a selection */
#define HALF_WAY 127
#define HALF_WAY 0.5
/* structure declarations */
@@ -64,15 +67,18 @@ typedef struct _mask_undo MaskUndo;
struct _mask_undo
{
TileManager * tiles; /* the actual mask */
struct _Canvas * tiles; /* the actual mask */
int x, y; /* offsets */
};
/* function declarations */
Channel * channel_new (int, int, int, char *, int, unsigned char *);
Channel * channel_new (int, int, int, Precision, char *, gfloat, struct _PixelRow *);
Channel * channel_copy (Channel *);
Channel * channel_ref (Channel *);
void channel_unref (Channel *);
Channel * channel_get_ID (int);
void channel_delete (Channel *);
void channel_scale (Channel *, int, int);
@@ -80,23 +86,22 @@ void channel_resize (Channel *, int, int, int, int);
/* access functions */
unsigned char * channel_data (Channel *);
int channel_toggle_visibility (Channel *);
TempBuf * channel_preview (Channel *, int, int);
struct _Canvas *channel_preview (Channel *, int, int);
void channel_invalidate_previews (int);
/* selection mask functions */
Channel * channel_new_mask (int, int, int);
Channel * channel_new_mask (int, int, int, Precision);
int channel_boundary (Channel *, BoundSeg **, BoundSeg **,
int *, int *, int, int, int, int);
int channel_bounds (Channel *, int *, int *, int *, int *);
int channel_value (Channel *, int, int);
gfloat channel_value (Channel *, int, int);
int channel_is_empty (Channel *);
void channel_add_segment (Channel *, int, int, int, int);
void channel_sub_segment (Channel *, int, int, int, int);
void channel_inter_segment (Channel *, int, int, int, int);
void channel_add_segment (Channel *, int, int, int, gfloat);
void channel_sub_segment (Channel *, int, int, int, gfloat);
void channel_inter_segment (Channel *, int, int, int, gfloat);
void channel_combine_rect (Channel *, int, int, int, int, int);
void channel_combine_ellipse (Channel *, int, int, int, int, int, int);
void channel_combine_mask (Channel *, Channel *, int, int, int);

View File

@@ -13,13 +13,15 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include "appenv.h"
#include "general.h"
#include "gimage.h"
#include "gimprc.h"
#include "paint_funcs_area.h"
#include "channel.h"
#include "channel_cmds.h"
@@ -40,13 +42,14 @@ channel_new_invoker (Argument *args)
int gimage_id;
int width, height;
char *name;
int opacity;
unsigned char color[3];
gfloat opacity;
unsigned char _color[3];
PixelRow color;
Argument *return_args;
channel = NULL;
gimage_id = -1;
opacity = 255;
opacity = 1.0;
success = TRUE;
if (success)
@@ -69,7 +72,7 @@ channel_new_invoker (Argument *args)
{
fp_value = args[4].value.pdb_float;
if (fp_value >= 0 && fp_value <= 100)
opacity = (int) ((fp_value * 255) / 100);
opacity = fp_value / 100;
else
success = FALSE;
}
@@ -79,12 +82,15 @@ channel_new_invoker (Argument *args)
unsigned char *color_array;
color_array = (unsigned char *) args[5].value.pdb_pointer;
pixelrow_init (&color, tag_new (PRECISION_U8, FORMAT_RGB, ALPHA_NO),
_color, 1);
for (i = 0; i < 3; i++)
color[i] = color_array[i];
_color[i] = color_array[i];
}
if (success)
success = ((channel = channel_new (gimage_id, width, height, name, opacity, color)) != NULL);
success = ((channel = channel_new (gimage_id, width, height, default_precision, name, opacity, &color)) != NULL);
return_args = procedural_db_return_args (&channel_new_proc, success);
@@ -691,7 +697,7 @@ channel_get_opacity_invoker (Argument *args)
{
int_value = args[0].value.pdb_int;
if ((channel = channel_get_ID (int_value)))
opacity = ((channel->opacity) * 100.0) / 255.0;
opacity = (channel->opacity) * 100.0;
else
success = FALSE;
}
@@ -763,7 +769,7 @@ channel_set_opacity_invoker (Argument *args)
if (success)
{
opacity = args[1].value.pdb_float;
channel->opacity = (int) ((opacity * 255) / 100);
channel->opacity = opacity / 100.0;
}
return procedural_db_return_args (&channel_set_opacity_proc, success);
@@ -823,10 +829,10 @@ channel_get_color_invoker (Argument *args)
int_value = args[0].value.pdb_int;
if ((channel = channel_get_ID (int_value)))
{
color = (unsigned char *) g_malloc (3);
color[RED_PIX] = channel->col[RED_PIX];
color[GREEN_PIX] = channel->col[GREEN_PIX];
color[BLUE_PIX] = channel->col[BLUE_PIX];
PixelRow c;
color = (unsigned char *) g_malloc (3);
pixelrow_init (&c, tag_new (PRECISION_U8, FORMAT_RGB, ALPHA_NO), color, 1);
copy_row (&channel->col, &c);
}
else
success = FALSE;
@@ -888,7 +894,6 @@ channel_set_color_invoker (Argument *args)
{
Channel *channel;
unsigned char * color;
int i;
success = TRUE;
if (success)
@@ -899,9 +904,10 @@ channel_set_color_invoker (Argument *args)
}
if (success)
{
PixelRow c;
color = (unsigned char *) args[1].value.pdb_pointer;
for (i = 0; i < 3; i++)
channel->col[i] = color[i];
pixelrow_init (&c, tag_new (PRECISION_U8, FORMAT_RGB, ALPHA_NO), color, 1);
copy_row (&c, &channel->col);
}
return procedural_db_return_args (&channel_set_color_proc, success);

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CHANNEL_CMDS_H__
#define __CHANNEL_CMDS_H__

View File

@@ -13,20 +13,24 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "appenv.h"
#include "actionarea.h"
#include "canvas.h"
#include "channel_ops.h"
#include "drawable.h"
#include "floating_sel.h"
#include "general.h"
#include "gdisplay.h"
#include "interface.h"
#include "paint_funcs_area.h"
#include "palette.h"
#include "pixelarea.h"
#include "pixelrow.h"
#include "channel_pvt.h"
@@ -101,6 +105,7 @@ channel_ops_offset (void *gimage_ptr)
off_d->gimage_id = gimage->ID;
off_d->dlg = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (off_d->dlg), "offset", "Gimp");
gtk_window_set_title (GTK_WINDOW (off_d->dlg), "Offset");
/* handle the wm close signal */
@@ -221,12 +226,12 @@ offset (GImage *gimage,
int offset_x,
int offset_y)
{
PixelRegion srcPR, destPR;
TileManager *new_tiles;
PixelArea srcPR, destPR;
Canvas *new_tiles;
int width, height;
int src_x, src_y;
int dest_x, dest_y;
unsigned char fill[MAX_CHANNELS] = { 0 };
Tag tag = tag_set_alpha (drawable_tag (drawable), ALPHA_YES);
if (!drawable)
return;
@@ -248,7 +253,7 @@ offset (GImage *gimage,
if (offset_x == 0 && offset_y == 0)
return;
new_tiles = tile_manager_new (width, height, drawable_bytes (drawable));
new_tiles = canvas_new (tag, width, height, STORAGE_TILED);
if (offset_x >= 0)
{
src_x = 0;
@@ -278,10 +283,10 @@ offset (GImage *gimage,
/* Copy the center region */
if (width && height)
{
pixel_region_init (&srcPR, drawable_data (drawable), src_x, src_y, width, height, FALSE);
pixel_region_init (&destPR, new_tiles, dest_x, dest_y, width, height, TRUE);
pixelarea_init (&srcPR, drawable_data (drawable), src_x, src_y, width, height, FALSE);
pixelarea_init (&destPR, new_tiles, dest_x, dest_y, width, height, TRUE);
copy_region (&srcPR, &destPR);
copy_area (&srcPR, &destPR);
}
/* Copy appropriately for wrap around */
@@ -318,10 +323,10 @@ offset (GImage *gimage,
/* intersecting region */
if (offset_x != 0 && offset_y != 0)
{
pixel_region_init (&srcPR, drawable_data (drawable), src_x, src_y,
pixelarea_init (&srcPR, drawable_data (drawable), src_x, src_y,
ABS (offset_x), ABS (offset_y), FALSE);
pixel_region_init (&destPR, new_tiles, dest_x, dest_y, ABS (offset_x), ABS (offset_y), TRUE);
copy_region (&srcPR, &destPR);
pixelarea_init (&destPR, new_tiles, dest_x, dest_y, ABS (offset_x), ABS (offset_y), TRUE);
copy_area (&srcPR, &destPR);
}
/* X offset */
@@ -329,20 +334,20 @@ offset (GImage *gimage,
{
if (offset_y >= 0)
{
pixel_region_init (&srcPR, drawable_data (drawable), src_x, 0,
pixelarea_init (&srcPR, drawable_data (drawable), src_x, 0,
ABS (offset_x), drawable_height (drawable) - ABS (offset_y), FALSE);
pixel_region_init (&destPR, new_tiles, dest_x, dest_y + offset_y,
pixelarea_init (&destPR, new_tiles, dest_x, dest_y + offset_y,
ABS (offset_x), drawable_height (drawable) - ABS (offset_y), TRUE);
}
else if (offset_y < 0)
{
pixel_region_init (&srcPR, drawable_data (drawable), src_x, src_y - offset_y,
pixelarea_init (&srcPR, drawable_data (drawable), src_x, src_y - offset_y,
ABS (offset_x), drawable_height (drawable) - ABS (offset_y), FALSE);
pixel_region_init (&destPR, new_tiles, dest_x, 0,
pixelarea_init (&destPR, new_tiles, dest_x, 0,
ABS (offset_x), drawable_height (drawable) - ABS (offset_y), TRUE);
}
copy_region (&srcPR, &destPR);
copy_area (&srcPR, &destPR);
}
/* X offset */
@@ -350,32 +355,37 @@ offset (GImage *gimage,
{
if (offset_x >= 0)
{
pixel_region_init (&srcPR, drawable_data (drawable), 0, src_y,
pixelarea_init (&srcPR, drawable_data (drawable), 0, src_y,
drawable_width (drawable) - ABS (offset_x), ABS (offset_y), FALSE);
pixel_region_init (&destPR, new_tiles, dest_x + offset_x, dest_y,
pixelarea_init (&destPR, new_tiles, dest_x + offset_x, dest_y,
drawable_width (drawable) - ABS (offset_x), ABS (offset_y), TRUE);
}
else if (offset_x < 0)
{
pixel_region_init (&srcPR, drawable_data (drawable), src_x - offset_x, src_y,
pixelarea_init (&srcPR, drawable_data (drawable), src_x - offset_x, src_y,
drawable_width (drawable) - ABS (offset_x), ABS (offset_y), FALSE);
pixel_region_init (&destPR, new_tiles, 0, dest_y,
pixelarea_init (&destPR, new_tiles, 0, dest_y,
drawable_width (drawable) - ABS (offset_x), ABS (offset_y), TRUE);
}
copy_region (&srcPR, &destPR);
copy_area (&srcPR, &destPR);
}
}
/* Otherwise, fill the vacated regions */
else
{
COLOR16_NEW (fill, tag);
COLOR16_INIT (fill);
if (fill_type == OFFSET_BACKGROUND)
{
palette_get_background (&fill[0], &fill[1], &fill[2]);
if (drawable_has_alpha (drawable))
fill[drawable_bytes (drawable) - 1] = OPAQUE;
palette_get_background (&fill);
}
else if (fill_type == OFFSET_TRANSPARENT)
{
palette_get_transparent (&fill);
}
if (offset_x >= 0 && offset_y >= 0)
{
dest_x = 0;
@@ -400,46 +410,49 @@ offset (GImage *gimage,
/* intersecting region */
if (offset_x != 0 && offset_y != 0)
{
pixel_region_init (&destPR, new_tiles, dest_x, dest_y, ABS (offset_x), ABS (offset_y), TRUE);
color_region (&destPR, fill);
pixelarea_init (&destPR, new_tiles, dest_x, dest_y, ABS (offset_x), ABS (offset_y), TRUE);
color_area (&destPR, &fill);
}
/* X offset */
if (offset_x != 0)
{
if (offset_y >= 0)
pixel_region_init (&destPR, new_tiles, dest_x, dest_y + offset_y,
pixelarea_init (&destPR, new_tiles, dest_x, dest_y + offset_y,
ABS (offset_x), drawable_height (drawable) - ABS (offset_y), TRUE);
else if (offset_y < 0)
pixel_region_init (&destPR, new_tiles, dest_x, 0,
pixelarea_init (&destPR, new_tiles, dest_x, 0,
ABS (offset_x), drawable_height (drawable) - ABS (offset_y), TRUE);
color_region (&destPR, fill);
color_area (&destPR, &fill);
}
/* X offset */
if (offset_y != 0)
{
if (offset_x >= 0)
pixel_region_init (&destPR, new_tiles, dest_x + offset_x, dest_y,
pixelarea_init (&destPR, new_tiles, dest_x + offset_x, dest_y,
drawable_width (drawable) - ABS (offset_x), ABS (offset_y), TRUE);
else if (offset_x < 0)
pixel_region_init (&destPR, new_tiles, 0, dest_y,
pixelarea_init (&destPR, new_tiles, 0, dest_y,
drawable_width (drawable) - ABS (offset_x), ABS (offset_y), TRUE);
color_region (&destPR, fill);
color_area (&destPR, &fill);
}
}
/* push an undo */
drawable_apply_image (drawable, 0, 0, drawable_width (drawable), drawable_height (drawable),
drawable_data (drawable), FALSE);
drawable_apply_image (drawable, 0, 0,
drawable_width (drawable), drawable_height (drawable),
drawable_data (drawable));
/* swap the tiles */
drawable->tiles = new_tiles;
/* update the drawable */
drawable_update (drawable, 0, 0, drawable_width (drawable), drawable_height (drawable));
drawable_update (drawable,
0, 0,
0, 0);
}
/*
@@ -484,7 +497,7 @@ offset_delete_callback (GtkWidget *widget,
{
offset_cancel_callback (widget, data);
return FALSE;
return TRUE;
}
static void

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CHANNEL_OPS_H__
#define __CHANNEL_OPS_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CHANNEL_PVT_H__
#define __CHANNEL_PVT_H__
@@ -21,8 +21,7 @@
#include "drawable.h"
#include "boundary.h"
#include "temp_buf.h"
#include "tile_manager.h"
#include "pixelrow.h"
#include "drawable_pvt.h"
@@ -30,8 +29,9 @@ struct _GimpChannel
{
GimpDrawable drawable;
unsigned char col[3]; /* RGB triplet for channel color*/
int opacity; /* Channel opacity */
PixelRow col; /* channel color*/
unsigned char _col[TAG_MAX_BYTES];
gfloat opacity; /* Channel opacity */
int show_masked; /* Show masked areas--as */
/* opposed to selected areas */

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
@@ -33,15 +33,26 @@
#include "general.h"
#include "interface.h"
#include "layers_dialogP.h"
#include "paint_funcs.h"
#include "ops_buttons.h"
#include "palette.h"
#include "paint_funcs_area.h"
#include "resize.h"
#include "tools/eye.xbm"
#include "tools/channel.xbm"
#include "tools/new.xpm"
#include "tools/new_is.xpm"
#include "tools/raise.xpm"
#include "tools/raise_is.xpm"
#include "tools/lower.xpm"
#include "tools/lower_is.xpm"
#include "tools/duplicate.xpm"
#include "tools/duplicate_is.xpm"
#include "tools/delete.xpm"
#include "tools/delete_is.xpm"
#include "channel_pvt.h"
#include "pixelarea.h"
#define PREVIEW_EVENT_MASK GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_ENTER_NOTIFY_MASK
#define BUTTON_EVENT_MASK GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | \
@@ -84,7 +95,7 @@ struct _ChannelsDialog {
GtkAcceleratorTable *accel_table;
int num_components;
int base_type;
Format format;
ChannelType components[3];
double ratio;
int image_width, image_height;
@@ -94,7 +105,7 @@ struct _ChannelsDialog {
int gimage_id;
Channel * active_channel;
Layer *floating_sel;
link_ptr channel_widgets;
GSList *channel_widgets;
};
/* channels dialog widget routines */
@@ -143,6 +154,9 @@ static GdkPixmap *channel_pixmap[3] = { NULL, NULL, NULL };
static int suspend_gimage_notify = 0;
static guint32 button_click_time = 0;
static int button_last_id = 0;
static MenuItem channels_ops[] =
{
{ "New Channel", 'N', GDK_CONTROL_MASK,
@@ -160,6 +174,16 @@ static MenuItem channels_ops[] =
{ NULL, 0, 0, NULL, NULL, NULL, NULL },
};
/* the ops buttons */
static OpsButton channels_ops_buttons[] =
{
{ new_xpm, new_is_xpm, channels_dialog_new_channel_callback, "New Channel", NULL, NULL, NULL, NULL, NULL, NULL },
{ raise_xpm, raise_is_xpm, channels_dialog_raise_channel_callback, "Raise Channel", NULL, NULL, NULL, NULL, NULL, NULL },
{ lower_xpm, lower_is_xpm, channels_dialog_lower_channel_callback, "Lower Channel", NULL, NULL, NULL, NULL, NULL, NULL },
{ duplicate_xpm, duplicate_is_xpm, channels_dialog_duplicate_channel_callback, "Duplicate Channel", NULL, NULL, NULL, NULL, NULL, NULL },
{ delete_xpm, delete_is_xpm, channels_dialog_delete_channel_callback, "Delete Channel", NULL, NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
};
/**************************************/
/* Public channels dialog functions */
@@ -170,6 +194,7 @@ channels_dialog_create ()
{
GtkWidget *vbox;
GtkWidget *listbox;
GtkWidget *button_box;
if (!channelsD)
{
@@ -205,10 +230,21 @@ channels_dialog_create ()
gtk_signal_connect (GTK_OBJECT (channelsD->channel_list), "event",
(GtkSignalFunc) channel_list_events,
channelsD);
gtk_container_set_focus_vadjustment (GTK_CONTAINER (channelsD->channel_list),
gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (listbox)));
GTK_WIDGET_UNSET_FLAGS (GTK_SCROLLED_WINDOW (listbox)->vscrollbar, GTK_CAN_FOCUS);
gtk_widget_show (channelsD->channel_list);
gtk_widget_show (listbox);
/* The ops buttons */
button_box = ops_button_box_new (lc_shell, tool_tips, channels_ops_buttons);
gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 2);
gtk_widget_show (button_box);
/* Set up signals for map/unmap for the accelerators */
gtk_signal_connect (GTK_OBJECT (channelsD->vbox), "map",
(GtkSignalFunc) channels_dialog_map_callback,
@@ -230,7 +266,7 @@ channels_dialog_flush ()
GImage *gimage;
Channel *channel;
ChannelWidget *cw;
link_ptr list;
GSList *list;
int gimage_pos;
int pos;
@@ -243,7 +279,7 @@ channels_dialog_flush ()
/* Check if the gimage extents have changed */
if ((gimage->width != channelsD->gimage_width) ||
(gimage->height != channelsD->gimage_height) ||
(gimage_base_type (gimage) != channelsD->base_type))
(tag_format (gimage_tag (gimage)) != channelsD->format))
{
channelsD->gimage_id = -1;
channels_dialog_update (gimage->ID);
@@ -255,7 +291,7 @@ channels_dialog_flush ()
{
cw = (ChannelWidget *) list->data;
cw->visited = FALSE;
list = next_item (list);
list = g_slist_next (list);
}
/* Add any missing channels */
@@ -271,7 +307,7 @@ channels_dialog_flush ()
else
cw->visited = TRUE;
list = next_item (list);
list = g_slist_next (list);
}
/* Remove any extraneous auxillary channels */
@@ -279,7 +315,7 @@ channels_dialog_flush ()
while (list)
{
cw = (ChannelWidget *) list->data;
list = next_item (list);
list = g_slist_next (list);
if (cw->visited == FALSE && cw->type == Auxillary)
/* will only be true for auxillary channels */
@@ -288,11 +324,11 @@ channels_dialog_flush ()
/* Switch positions of items if necessary */
list = channelsD->channel_widgets;
pos = -channelsD->num_components;
pos = -channelsD->num_components + 1;
while (list)
{
cw = (ChannelWidget *) list->data;
list = next_item (list);
list = g_slist_next (list);
if (cw->type == Auxillary)
if ((gimage_pos = gimage_get_channel_index (gimage, cw->channel)) != pos)
@@ -326,7 +362,7 @@ channels_dialog_update (int gimage_id)
ChannelWidget *cw;
GImage *gimage;
Channel *channel;
link_ptr list;
GSList *list;
GList *item_list;
if (!channelsD)
@@ -345,7 +381,7 @@ channels_dialog_update (int gimage_id)
while (list)
{
cw = (ChannelWidget *) list->data;
list = next_item(list);
list = g_slist_next (list);
channel_widget_delete (cw);
}
channelsD->channel_widgets = NULL;
@@ -361,44 +397,48 @@ channels_dialog_update (int gimage_id)
/* The image components */
item_list = NULL;
switch ((channelsD->base_type = gimage_base_type (gimage)))
switch ((channelsD->format = gimage_format (gimage)))
{
case RGB:
case FORMAT_RGB:
cw = create_channel_widget (gimage, NULL, Red);
channelsD->channel_widgets = append_to_list (channelsD->channel_widgets, cw);
channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
item_list = g_list_append (item_list, cw->list_item);
channelsD->components[0] = Red;
cw = create_channel_widget (gimage, NULL, Green);
channelsD->channel_widgets = append_to_list (channelsD->channel_widgets, cw);
channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
item_list = g_list_append (item_list, cw->list_item);
channelsD->components[1] = Green;
cw = create_channel_widget (gimage, NULL, Blue);
channelsD->channel_widgets = append_to_list (channelsD->channel_widgets, cw);
channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
item_list = g_list_append (item_list, cw->list_item);
channelsD->components[2] = Blue;
channelsD->num_components = 3;
break;
case GRAY:
case FORMAT_GRAY:
cw = create_channel_widget (gimage, NULL, Gray);
channelsD->channel_widgets = append_to_list (channelsD->channel_widgets, cw);
channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
item_list = g_list_append (item_list, cw->list_item);
channelsD->components[0] = Gray;
channelsD->num_components = 1;
break;
case INDEXED:
case FORMAT_INDEXED:
cw = create_channel_widget (gimage, NULL, Indexed);
channelsD->channel_widgets = append_to_list (channelsD->channel_widgets, cw);
channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
item_list = g_list_append (item_list, cw->list_item);
channelsD->components[0] = Indexed;
channelsD->num_components = 1;
break;
case FORMAT_NONE:
g_warning ("doh");
return;
}
/* The auxillary image channels */
@@ -408,10 +448,10 @@ channels_dialog_update (int gimage_id)
/* create a channel list item */
channel = (Channel *) list->data;
cw = create_channel_widget (gimage, channel, Auxillary);
channelsD->channel_widgets = append_to_list (channelsD->channel_widgets, cw);
channelsD->channel_widgets = g_slist_append (channelsD->channel_widgets, cw);
item_list = g_list_append (item_list, cw->list_item);
list = next_item (list);
list = g_slist_next (list);
}
/* get the index of the active channel */
@@ -423,6 +463,8 @@ channels_dialog_update (int gimage_id)
void
channels_dialog_clear ()
{
ops_button_box_set_insensitive (channels_ops_buttons);
suspend_gimage_notify++;
gtk_list_clear_items (GTK_LIST (channelsD->channel_list), 0, -1);
suspend_gimage_notify--;
@@ -431,7 +473,7 @@ channels_dialog_clear ()
void
channels_dialog_free ()
{
link_ptr list;
GSList *list;
ChannelWidget *cw;
if (channelsD == NULL)
@@ -446,7 +488,7 @@ channels_dialog_free ()
while (list)
{
cw = (ChannelWidget *) list->data;
list = next_item(list);
list = g_slist_next (list);
channel_widget_delete (cw);
}
channelsD->channel_widgets = NULL;
@@ -454,10 +496,10 @@ channels_dialog_free ()
channelsD->floating_sel = NULL;
if (channelsD->preview)
gtk_widget_destroy (channelsD->preview);
gtk_object_sink (GTK_OBJECT (channelsD->preview));
if (channelsD->ops_menu)
gtk_widget_destroy (channelsD->ops_menu);
gtk_object_sink (GTK_OBJECT (channelsD->ops_menu));
g_free (channelsD);
channelsD = NULL;
@@ -513,20 +555,25 @@ channels_dialog_set_menu_sensitivity ()
/* new channel */
gtk_widget_set_sensitive (channels_ops[0].widget, !fs_sensitive);
ops_button_set_sensitive (channels_ops_buttons[0], !fs_sensitive);
/* raise channel */
gtk_widget_set_sensitive (channels_ops[1].widget, !fs_sensitive && aux_sensitive);
ops_button_set_sensitive (channels_ops_buttons[1], !fs_sensitive && aux_sensitive);
/* lower channel */
gtk_widget_set_sensitive (channels_ops[2].widget, !fs_sensitive && aux_sensitive);
ops_button_set_sensitive (channels_ops_buttons[2], !fs_sensitive && aux_sensitive);
/* duplicate channel */
gtk_widget_set_sensitive (channels_ops[3].widget, !fs_sensitive && aux_sensitive);
ops_button_set_sensitive (channels_ops_buttons[3], !fs_sensitive && aux_sensitive);
/* delete channel */
gtk_widget_set_sensitive (channels_ops[4].widget, !fs_sensitive && aux_sensitive);
ops_button_set_sensitive (channels_ops_buttons[4], !fs_sensitive && aux_sensitive);
/* channel to selection */
gtk_widget_set_sensitive (channels_ops[5].widget, aux_sensitive);
}
void
static void
channels_dialog_set_channel (ChannelWidget *channel_widget)
{
GtkStateType state;
@@ -580,7 +627,7 @@ channels_dialog_set_channel (ChannelWidget *channel_widget)
}
void
static void
channels_dialog_unset_channel (ChannelWidget * channel_widget)
{
GtkStateType state;
@@ -635,7 +682,7 @@ channels_dialog_unset_channel (ChannelWidget * channel_widget)
}
void
static void
channels_dialog_position_channel (ChannelWidget *channel_widget,
int new_index)
{
@@ -650,15 +697,17 @@ channels_dialog_position_channel (ChannelWidget *channel_widget,
/* Remove the channel from the dialog */
list = g_list_append (list, channel_widget->list_item);
gtk_list_remove_items (GTK_LIST (channelsD->channel_list), list);
channelsD->channel_widgets = g_slist_remove (channelsD->channel_widgets, channel_widget);
suspend_gimage_notify--;
/* Add it back at the proper index */
gtk_list_insert_items (GTK_LIST (channelsD->channel_list), list, new_index + channelsD->num_components);
channelsD->channel_widgets = g_slist_insert (channelsD->channel_widgets, channel_widget, new_index + channelsD->num_components);
}
void
static void
channels_dialog_add_channel (Channel *channel)
{
GImage *gimage;
@@ -677,14 +726,14 @@ channels_dialog_add_channel (Channel *channel)
item_list = g_list_append (item_list, channel_widget->list_item);
position = gimage_get_channel_index (gimage, channel);
channelsD->channel_widgets = insert_in_list (channelsD->channel_widgets, channel_widget,
channelsD->channel_widgets = g_slist_insert (channelsD->channel_widgets, channel_widget,
position + channelsD->num_components);
gtk_list_insert_items (GTK_LIST (channelsD->channel_list), item_list,
position + channelsD->num_components);
}
void
static void
channels_dialog_remove_channel (ChannelWidget *channel_widget)
{
GList *list = NULL;
@@ -699,12 +748,10 @@ channels_dialog_remove_channel (ChannelWidget *channel_widget)
list = g_list_append (list, channel_widget->list_item);
gtk_list_remove_items (GTK_LIST (channelsD->channel_list), list);
gtk_widget_destroy (channel_widget->list_item);
suspend_gimage_notify--;
/* Delete the channel_widget */
channel_widget_delete (channel_widget);
suspend_gimage_notify--;
}
@@ -733,6 +780,15 @@ channel_list_events (GtkWidget *widget,
gtk_menu_popup (GTK_MENU (channelsD->ops_menu), NULL, NULL, NULL, NULL, 3, bevent->time);
return TRUE;
}
/* Grumble - we have to handle double clicks ourselves because channels_dialog_flush is broken */
if (channel_widget->type == Auxillary)
if ((event->button.time < (button_click_time + 250)) && (channel_widget->ID == button_last_id)) {
channels_dialog_edit_channel_query (channel_widget);
return TRUE;
} else {
button_click_time = event->button.time;
button_last_id = channel_widget->ID;
}
break;
case GDK_2BUTTON_PRESS:
@@ -746,10 +802,10 @@ channel_list_events (GtkWidget *widget,
switch (kevent->keyval)
{
case GDK_Up:
printf ("up arrow\n");
/* printf ("up arrow\n"); */
break;
case GDK_Down:
printf ("down arrow\n");
/* printf ("down arrow\n"); */
break;
default:
return FALSE;
@@ -920,7 +976,7 @@ static ChannelWidget *
channel_widget_get_ID (Channel *channel)
{
ChannelWidget *lw;
link_ptr list;
GSList *list;
if (!channelsD)
return NULL;
@@ -933,7 +989,7 @@ channel_widget_get_ID (Channel *channel)
if (lw->channel == channel)
return lw;
list = next_item(list);
list = g_slist_next (list);
}
return NULL;
@@ -1031,6 +1087,8 @@ create_channel_widget (GImage *gimage,
gtk_widget_show (vbox);
gtk_widget_show (list_item);
gtk_widget_ref (channel_widget->list_item);
return channel_widget;
}
@@ -1042,9 +1100,10 @@ channel_widget_delete (ChannelWidget *channel_widget)
gdk_pixmap_unref (channel_widget->channel_pixmap);
/* Remove the channel widget from the list */
channelsD->channel_widgets = remove_from_list (channelsD->channel_widgets, channel_widget);
channelsD->channel_widgets = g_slist_remove (channelsD->channel_widgets, channel_widget);
/* Free the widget */
/* Release the widget */
gtk_widget_unref (channel_widget->list_item);
g_free (channel_widget);
}
@@ -1092,6 +1151,7 @@ channel_widget_button_events (GtkWidget *widget,
static int exclusive;
ChannelWidget *channel_widget;
GtkWidget *event_widget;
GdkEventButton *bevent;
gint return_val;
int visible;
int width, height;
@@ -1101,8 +1161,8 @@ channel_widget_button_events (GtkWidget *widget,
{
case Auxillary:
visible = GIMP_DRAWABLE(channel_widget->channel)->visible;
width = GIMP_DRAWABLE(channel_widget->channel)->width;
height = GIMP_DRAWABLE(channel_widget->channel)->height;
width = drawable_width (GIMP_DRAWABLE(channel_widget->channel));
height = drawable_height (GIMP_DRAWABLE(channel_widget->channel));
break;
default:
visible = gimage_get_component_visible (channel_widget->gimage, channel_widget->type);
@@ -1123,6 +1183,13 @@ channel_widget_button_events (GtkWidget *widget,
case GDK_BUTTON_PRESS:
return_val = TRUE;
bevent = (GdkEventButton *) event;
if (bevent->button == 3) {
gtk_menu_popup (GTK_MENU (channelsD->ops_menu), NULL, NULL, NULL, NULL, 3, bevent->time);
return TRUE;
}
button_down = 1;
click_widget = widget;
gtk_grab_add (click_widget);
@@ -1207,6 +1274,7 @@ channel_widget_preview_events (GtkWidget *widget,
GdkEvent *event)
{
GdkEventExpose *eevent;
GdkEventButton *bevent;
ChannelWidget *channel_widget;
int valid;
@@ -1214,6 +1282,16 @@ channel_widget_preview_events (GtkWidget *widget,
switch (event->type)
{
case GDK_BUTTON_PRESS:
bevent = (GdkEventButton *) event;
if (bevent->button == 3) {
gtk_menu_popup (GTK_MENU (channelsD->ops_menu), NULL, NULL, NULL, NULL, 3, bevent->time);
return TRUE;
}
break;
case GDK_EXPOSE:
if (!preview_size)
channel_widget_no_preview_redraw (channel_widget);
@@ -1265,7 +1343,7 @@ channel_widget_preview_events (GtkWidget *widget,
static void
channel_widget_preview_redraw (ChannelWidget *channel_widget)
{
TempBuf * preview_buf;
Canvas * preview_buf;
int width, height;
int channel;
@@ -1280,8 +1358,8 @@ channel_widget_preview_redraw (ChannelWidget *channel_widget)
switch (channel_widget->type)
{
case Auxillary:
width = GIMP_DRAWABLE(channel_widget->channel)->width;
height = GIMP_DRAWABLE(channel_widget->channel)->height;
width = drawable_width (GIMP_DRAWABLE(channel_widget->channel));
height = drawable_height (GIMP_DRAWABLE(channel_widget->channel));
channel_widget->width = (int) (channelsD->ratio * width);
channel_widget->height = (int) (channelsD->ratio * height);
preview_buf = channel_preview (channel_widget->channel,
@@ -1310,13 +1388,13 @@ channel_widget_preview_redraw (ChannelWidget *channel_widget)
case Auxillary: channel = -1; break;
default: channel = -1; break;
}
render_preview (preview_buf,
channelsD->preview,
channelsD->image_width,
channelsD->image_height,
channel);
gtk_preview_put (GTK_PREVIEW (channelsD->preview),
channel_widget->channel_pixmap,
channel_widget->channel_preview->style->black_gc,
@@ -1476,7 +1554,7 @@ channel_widget_eye_redraw (ChannelWidget *channel_widget)
static void
channel_widget_exclusive_visible (ChannelWidget *channel_widget)
{
link_ptr list;
GSList *list;
ChannelWidget *cw;
int visible = FALSE;
@@ -1501,7 +1579,7 @@ channel_widget_exclusive_visible (ChannelWidget *channel_widget)
}
}
list = next_item (list);
list = g_slist_next (list);
}
/* Now, toggle the visibility for all channels except the specified one */
@@ -1532,7 +1610,7 @@ channel_widget_exclusive_visible (ChannelWidget *channel_widget)
channel_widget_eye_redraw (cw);
list = next_item (list);
list = g_slist_next (list);
}
}
@@ -1632,7 +1710,8 @@ struct _NewChannelOptions {
};
static char *channel_name = NULL;
static unsigned char channel_color[3] = {0, 0, 0};
static PixelRow channel_color;
static unsigned char channel_color_data[TAG_MAX_BYTES];
static void
new_channel_query_ok_callback (GtkWidget *w,
@@ -1641,7 +1720,6 @@ new_channel_query_ok_callback (GtkWidget *w,
NewChannelOptions *options;
Channel *new_channel;
GImage *gimage;
int i;
options = (NewChannelOptions *) client_data;
if (channel_name)
@@ -1651,12 +1729,12 @@ new_channel_query_ok_callback (GtkWidget *w,
if ((gimage = gimage_get_ID (options->gimage_id)))
{
new_channel = channel_new (gimage->ID, gimage->width, gimage->height,
channel_name, (int) (255 * options->opacity) / 100,
options->color_panel->color);
default_precision,
channel_name, options->opacity / 100.0,
&options->color_panel->color);
drawable_fill (GIMP_DRAWABLE(new_channel), TRANSPARENT_FILL);
for (i = 0; i < 3; i++)
channel_color[i] = options->color_panel->color[i];
copy_row (&options->color_panel->color, &channel_color);
gimage_add_channel (gimage, new_channel, -1);
gdisplays_flush ();
@@ -1686,7 +1764,7 @@ new_channel_query_delete_callback (GtkWidget *w,
{
new_channel_query_cancel_callback (w, client_data);
return FALSE;
return TRUE;
}
static void
@@ -1718,10 +1796,19 @@ channels_dialog_new_channel_query (int gimage_id)
options = (NewChannelOptions *) g_malloc (sizeof (NewChannelOptions));
options->gimage_id = gimage_id;
options->opacity = 50.0;
options->color_panel = color_panel_new (channel_color, 48, 64);
pixelrow_init (&channel_color,
tag_new (tag_precision (gimage_tag (gimage)),
FORMAT_RGB,
ALPHA_NO),
channel_color_data,
1);
palette_get_white (&channel_color);
options->color_panel = color_panel_new (&channel_color, 48, 64);
/* the dialog */
options->query_box = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (options->query_box), "new_channel_options", "Gimp");
gtk_window_set_title (GTK_WINDOW (options->query_box), "New Channel Options");
gtk_window_position (GTK_WINDOW (options->query_box), GTK_WIN_POS_MOUSE);
@@ -1797,6 +1884,7 @@ struct _EditChannelOptions {
GtkWidget *name_entry;
ChannelWidget *channel_widget;
int gimage_id;
ColorPanel *color_panel;
double opacity;
};
@@ -1807,38 +1895,39 @@ edit_channel_query_ok_callback (GtkWidget *w,
{
EditChannelOptions *options;
Channel *channel;
int opacity;
gfloat opacity;
int update = FALSE;
int i;
options = (EditChannelOptions *) client_data;
channel = options->channel_widget->channel;
opacity = (int) (255 * options->opacity) / 100;
opacity = options->opacity / 100.0;
/* Set the new channel name */
if (GIMP_DRAWABLE(channel)->name)
g_free (GIMP_DRAWABLE(channel)->name);
GIMP_DRAWABLE(channel)->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (options->name_entry)));
gtk_label_set (GTK_LABEL (options->channel_widget->label), GIMP_DRAWABLE(channel)->name);
if (channel->opacity != opacity)
{
channel->opacity = opacity;
update = TRUE;
}
for (i = 0; i < 3; i++)
if (options->color_panel->color[i] != channel->col[i])
if (gimage_get_ID (options->gimage_id)) {
/* Set the new channel name */
if (GIMP_DRAWABLE(channel)->name)
g_free (GIMP_DRAWABLE(channel)->name);
GIMP_DRAWABLE(channel)->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (options->name_entry)));
gtk_label_set (GTK_LABEL (options->channel_widget->label), GIMP_DRAWABLE(channel)->name);
if (channel->opacity != opacity)
{
channel->col[i] = options->color_panel->color[i];
channel->opacity = opacity;
update = TRUE;
}
if (update)
{
drawable_update (GIMP_DRAWABLE(channel), 0, 0, GIMP_DRAWABLE(channel)->width, GIMP_DRAWABLE(channel)->height);
gdisplays_flush ();
}
copy_row (&options->color_panel->color, &channel->col);
update = TRUE;
if (update)
{
drawable_update (GIMP_DRAWABLE(channel),
0, 0,
0, 0);
gdisplays_flush ();
}
}
color_panel_free (options->color_panel);
gtk_widget_destroy (options->query_box);
g_free (options);
@@ -1864,7 +1953,7 @@ edit_channel_query_delete_callback (GtkWidget *w,
{
edit_channel_query_cancel_callback (w, client_data);
return FALSE;
return TRUE;
}
static void
@@ -1882,19 +1971,24 @@ channels_dialog_edit_channel_query (ChannelWidget *channel_widget)
GtkWidget *label;
GtkWidget *opacity_scale;
GtkObject *opacity_scale_data;
int i;
Tag channel_tag = drawable_tag (GIMP_DRAWABLE (channel_widget->channel));
Tag color_tag = tag_new (tag_precision (channel_tag), FORMAT_RGB, ALPHA_NO);
/* the new options structure */
options = (EditChannelOptions *) g_malloc (sizeof (EditChannelOptions));
options->channel_widget = channel_widget;
options->opacity = (double) channel_widget->channel->opacity / 2.55;
for (i = 0; i < 3; i++)
channel_color[i] = channel_widget->channel->col[i];
options->gimage_id = channel_widget->gimage->ID;
options->opacity = (double) channel_widget->channel->opacity * 100.0;
options->color_panel = color_panel_new (channel_color, 48, 64);
pixelrow_init (&channel_color, color_tag, channel_color_data, 1);
copy_row (&channel_widget->channel->col, &channel_color);
options->color_panel = color_panel_new (&channel_color, 48, 64);
/* the dialog */
options->query_box = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (options->query_box), "edit_channel_atributes", "Gimp");
gtk_window_set_title (GTK_WINDOW (options->query_box), "Edit Channel Attributes");
gtk_window_position (GTK_WINDOW (options->query_box), GTK_WIN_POS_MOUSE);
@@ -1933,7 +2027,7 @@ channels_dialog_edit_channel_query (ChannelWidget *channel_widget)
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
opacity_scale_data = gtk_adjustment_new (options->opacity, 0.0, 100.0, 1.0, 1.0, 1.0);
opacity_scale_data = gtk_adjustment_new (options->opacity, 0.0, 100.0, 1.0, 1.0, 0.0);
opacity_scale = gtk_hscale_new (GTK_ADJUSTMENT (opacity_scale_data));
gtk_box_pack_start (GTK_BOX (hbox), opacity_scale, TRUE, TRUE, 0);
gtk_scale_set_value_pos (GTK_SCALE (opacity_scale), GTK_POS_TOP);

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CHANNELS_DIALOG_H__
#define __CHANNELS_DIALOG_H__

View File

@@ -13,22 +13,24 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#include "appenv.h"
#include "brushes.h"
#include "drawable.h"
#include "errors.h"
#include "gdisplay.h"
#include "gimage_mask.h"
#include "interface.h"
#include "paint_funcs.h"
#include "paint_core.h"
#include "patterns.h"
#include "canvas.h"
#include "clone.h"
#include "selection.h"
#include "draw_core.h"
#include "drawable.h"
#include "gimage.h"
#include "gdisplay.h"
#include "interface.h"
#include "paint_core_16.h"
#include "paint_funcs_area.h"
#include "patterns.h"
#include "pixelarea.h"
#include "procedural_db.h"
#include "tools.h"
#define TARGET_HEIGHT 15
@@ -40,14 +42,18 @@ typedef enum
PatternClone
} CloneType;
typedef enum
{
AlignNo,
AlignYes,
AlignRegister
} AlignType;
/* forward function declarations */
static void clone_draw (Tool *);
static void clone_motion (PaintCore *, GimpDrawable *, GimpDrawable *, CloneType, int, int);
static void clone_line_image (GImage *, GImage *, GimpDrawable *, GimpDrawable *, unsigned char *,
unsigned char *, int, int, int, int);
static void clone_line_pattern (GImage *, GimpDrawable *, GPatternP, unsigned char *,
int, int, int, int);
static int clone_line_image (PaintCore *, Canvas *, GimpDrawable *, GimpDrawable *, int, int);
static int clone_line_pattern (PaintCore *, Canvas *, GimpDrawable *, GPatternP, int, int);
static Argument * clone_invoker (Argument *);
@@ -60,7 +66,7 @@ typedef struct _CloneOptions CloneOptions;
struct _CloneOptions
{
CloneType type;
int aligned;
AlignType aligned;
};
/* local variables */
@@ -77,20 +83,6 @@ static GimpDrawable * src_drawable_ = NULL; /* source drawable */
static CloneOptions *clone_options = NULL;
static void
clone_toggle_update (GtkWidget *widget,
gpointer data)
{
int *toggle_val;
toggle_val = (int *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
*toggle_val = TRUE;
else
*toggle_val = FALSE;
}
static void
clone_type_callback (GtkWidget *w,
gpointer client_data)
@@ -98,13 +90,19 @@ clone_type_callback (GtkWidget *w,
clone_options->type =(CloneType) client_data;
}
static void
align_type_callback (GtkWidget *w,
gpointer client_data)
{
clone_options->aligned =(AlignType) client_data;
}
static CloneOptions *
create_clone_options (void)
{
CloneOptions *options;
GtkWidget *vbox;
GtkWidget *label;
GtkWidget *aligned_toggle;
GtkWidget *radio_frame;
GtkWidget *radio_box;
GtkWidget *radio_button;
@@ -115,11 +113,17 @@ create_clone_options (void)
"Image Source",
"Pattern Source"
};
char *align_names[3] =
{
"Non Aligned",
"Aligned",
"Registered"
};
/* the new options structure */
options = (CloneOptions *) g_malloc (sizeof (CloneOptions));
options->type = ImageClone;
options->aligned = TRUE;
options->aligned = AlignNo;
/* the main vbox */
vbox = gtk_vbox_new (FALSE, 1);
@@ -150,22 +154,35 @@ create_clone_options (void)
gtk_widget_show (radio_box);
gtk_widget_show (radio_frame);
/* the aligned toggle button */
aligned_toggle = gtk_check_button_new_with_label ("Aligned");
gtk_box_pack_start (GTK_BOX (vbox), aligned_toggle, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (aligned_toggle), "toggled",
(GtkSignalFunc) clone_toggle_update,
&options->aligned);
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (aligned_toggle), options->aligned);
gtk_widget_show (aligned_toggle);
/* the radio frame and box */
radio_frame = gtk_frame_new ("Alignment");
gtk_box_pack_start (GTK_BOX (vbox), radio_frame, FALSE, FALSE, 0);
radio_box = gtk_vbox_new (FALSE, 1);
gtk_container_add (GTK_CONTAINER (radio_frame), radio_box);
/* the radio buttons */
group = NULL;
for (i = 0; i < 3; i++)
{
radio_button = gtk_radio_button_new_with_label (group, align_names[i]);
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button));
gtk_signal_connect (GTK_OBJECT (radio_button), "toggled",
(GtkSignalFunc) align_type_callback,
(void *)((long) i));
gtk_box_pack_start (GTK_BOX (radio_box), radio_button, FALSE, FALSE, 0);
gtk_widget_show (radio_button);
}
gtk_widget_show (radio_box);
gtk_widget_show (radio_frame);
/* Register this selection options widget with the main tools options dialog */
tools_register_options (CLONE, vbox);
return options;
}
void *
static void *
clone_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
int state)
@@ -196,17 +213,21 @@ clone_paint_func (PaintCore *paint_core,
{
dest_x = x1;
dest_y = y1;
if (first)
if (clone_options->aligned == AlignRegister)
{
offset_x = 0;
offset_y = 0;
}
else if (first)
{
offset_x = src_x - dest_x;
offset_y = src_y - dest_y;
first = FALSE;
}
else
{
src_x = dest_x + offset_x;
src_y = dest_y + offset_y;
}
src_x = dest_x + offset_x;
src_y = dest_y + offset_y;
clone_motion (paint_core, drawable, src_drawable_, clone_options->type, offset_x, offset_y);
}
@@ -223,12 +244,12 @@ clone_paint_func (PaintCore *paint_core,
src_y = paint_core->cury;
first = TRUE;
}
else if (clone_options->aligned == FALSE)
else if (clone_options->aligned == AlignNo)
first = TRUE;
if (clone_options->type == PatternClone)
if (!get_active_pattern ())
message_box ("No patterns available for this operation.", NULL, NULL);
g_message ("No patterns available for this operation.");
break;
case FINISH_PAINT :
@@ -304,224 +325,222 @@ clone_draw (Tool *tool)
}
}
static void
clone_motion (PaintCore *paint_core,
GimpDrawable *drawable,
GimpDrawable *src_drawable,
CloneType type,
int offset_x,
int offset_y)
static void
clone_motion (
PaintCore * paint_core,
GimpDrawable * drawable,
GimpDrawable * src_drawable,
CloneType type,
int offset_x,
int offset_y
)
{
GImage *gimage;
GImage *src_gimage;
unsigned char * s;
unsigned char * d;
TempBuf * orig;
TempBuf * area;
void * pr;
int y;
int x1, y1, x2, y2;
int has_alpha;
PixelRegion srcPR, destPR;
GPatternP pattern;
Canvas * painthit = paint_core_16_area (paint_core, drawable);
int rc = FALSE;
pr = NULL;
pattern = NULL;
/* Make sure we still have a source! */
if ((! (src_gimage = drawable_gimage (src_drawable)) && type == ImageClone) ||
! (gimage = drawable_gimage (drawable)))
return;
/* Get a region which can be used to paint to */
if (! (area = paint_core_get_paint_area (paint_core, drawable)))
return;
/* Determine whether the source image has an alpha channel */
has_alpha = drawable_has_alpha (src_drawable);
switch (type)
if (painthit)
{
case ImageClone:
/* Set the paint area to transparent */
memset (temp_buf_data (area), 0, area->width * area->height * area->bytes);
switch (type)
{
case ImageClone:
{
rc = clone_line_image (paint_core, painthit,
drawable, src_drawable,
paint_core->x + offset_x,
paint_core->y + offset_y);
}
break;
case PatternClone:
{
GPatternP pattern;
if ((pattern = get_active_pattern ()))
rc = clone_line_pattern (paint_core, painthit,
drawable, pattern,
paint_core->x + offset_x,
paint_core->y + offset_y);
}
break;
}
if (rc == TRUE)
paint_core_16_area_paste (paint_core, drawable,
1.0, (gfloat) get_brush_opacity (),
SOFT, CONSTANT,
get_brush_paint_mode ());
}
}
/* If the source gimage is different from the destination,
* then we should copy straight from the destination image
* to the canvas.
* Otherwise, we need a call to get_orig_image to make sure
* we get a copy of the unblemished (offset) image
*/
static int
clone_line_image (
PaintCore * paint_core,
Canvas * painthit,
GimpDrawable * drawable,
GimpDrawable * src_drawable,
int x,
int y
)
{
GImage * src_gimage = drawable_gimage (src_drawable);
GImage * gimage = drawable_gimage (drawable);
int rc = FALSE;
if (gimage && src_gimage)
{
PixelArea srcPR, destPR;
int x1, y1, x2, y2;
if (src_drawable != drawable)
{
x1 = BOUNDS (area->x + offset_x, 0, drawable_width (src_drawable));
y1 = BOUNDS (area->y + offset_y, 0, drawable_height (src_drawable));
x2 = BOUNDS (area->x + offset_x + area->width,
0, drawable_width (src_drawable));
y2 = BOUNDS (area->y + offset_y + area->height,
0, drawable_height (src_drawable));
if (!(x2 - x1) || !(y2 - y1))
return;
pixel_region_init (&srcPR, drawable_data (src_drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
}
{
x1 = BOUNDS (x,
0, drawable_width (src_drawable));
y1 = BOUNDS (y,
0, drawable_height (src_drawable));
x2 = BOUNDS (x + canvas_width (painthit),
0, drawable_width (src_drawable));
y2 = BOUNDS (y + canvas_height (painthit),
0, drawable_height (src_drawable));
if (!(x2 - x1) || !(y2 - y1))
return FALSE;
pixelarea_init (&srcPR, drawable_data (src_drawable),
x1, y1, (x2 - x1), (y2 - y1), FALSE);
}
else
{
x1 = BOUNDS (area->x + offset_x, 0, drawable_width (drawable));
y1 = BOUNDS (area->y + offset_y, 0, drawable_height (drawable));
x2 = BOUNDS (area->x + offset_x + area->width,
0, drawable_width (drawable));
y2 = BOUNDS (area->y + offset_y + area->height,
0, drawable_height (drawable));
{
Canvas * orig;
x1 = BOUNDS (x,
0, drawable_width (drawable));
y1 = BOUNDS (y,
0, drawable_height (drawable));
x2 = BOUNDS (x + canvas_width (painthit),
0, drawable_width (drawable));
y2 = BOUNDS (y + canvas_height (painthit),
0, drawable_height (drawable));
if (!(x2 - x1) || !(y2 - y1))
return FALSE;
if (!(x2 - x1) || !(y2 - y1))
return;
orig = paint_core_16_area_original (paint_core, drawable,
x1, y1, x2, y2);
pixelarea_init (&srcPR, orig,
0, 0, (x2 - x1), (y2 - y1), FALSE);
}
pixelarea_init (&destPR, painthit,
(x1 - x), (y1 - y), (x2 - x1), (y2 - y1), TRUE);
/* get the original image */
orig = paint_core_get_orig_image (paint_core, drawable, x1, y1, x2, y2);
srcPR.bytes = orig->bytes;
srcPR.x = 0; srcPR.y = 0;
srcPR.w = x2 - x1;
srcPR.h = y2 - y1;
srcPR.rowstride = srcPR.bytes * orig->width;
srcPR.data = temp_buf_data (orig);
}
offset_x = x1 - (area->x + offset_x);
offset_y = y1 - (area->y + offset_y);
/* configure the destination */
destPR.bytes = area->bytes;
destPR.x = 0; destPR.y = 0;
destPR.w = srcPR.w;
destPR.h = srcPR.h;
destPR.rowstride = destPR.bytes * area->width;
destPR.data = temp_buf_data (area) + offset_y * destPR.rowstride +
offset_x * destPR.bytes;
pr = pixel_regions_register (2, &srcPR, &destPR);
break;
case PatternClone:
pattern = get_active_pattern ();
if (!pattern)
return;
destPR.bytes = area->bytes;
destPR.x = 0; destPR.y = 0;
destPR.w = area->width;
destPR.h = area->height;
destPR.rowstride = destPR.bytes * area->width;
destPR.data = temp_buf_data (area);
pr = pixel_regions_register (1, &destPR);
break;
copy_area (&srcPR, &destPR);
rc = TRUE;
}
for (; pr != NULL; pr = pixel_regions_process (pr))
{
s = srcPR.data;
d = destPR.data;
for (y = 0; y < destPR.h; y++)
{
switch (type)
{
case ImageClone:
clone_line_image (gimage, src_gimage, drawable, src_drawable, s, d,
has_alpha, srcPR.bytes, destPR.bytes, destPR.w);
s += srcPR.rowstride;
break;
case PatternClone:
clone_line_pattern (gimage, drawable, pattern, d,
area->x + offset_x, area->y + y + offset_y,
destPR.bytes, destPR.w);
break;
}
d += destPR.rowstride;
}
}
/* paste the newly painted canvas to the gimage which is being worked on */
paint_core_paste_canvas (paint_core, drawable, OPAQUE,
(int) (get_brush_opacity () * 255),
get_brush_paint_mode (), SOFT, CONSTANT);
return rc;
}
static void
clone_line_image (GImage *dest,
GImage *src,
GimpDrawable *d_drawable,
GimpDrawable *s_drawable,
unsigned char *s,
unsigned char *d,
int has_alpha,
int src_bytes,
int dest_bytes,
int width)
static int
clone_line_pattern (
PaintCore * paint_core,
Canvas * painthit,
GimpDrawable * drawable,
GPatternP pattern,
int x,
int y
)
{
unsigned char rgb[3];
int src_alpha, dest_alpha;
src_alpha = src_bytes - 1;
dest_alpha = dest_bytes - 1;
while (width--)
GImage * gimage;
int rc = FALSE;
gimage = drawable_gimage (drawable);
if (gimage)
{
gimage_get_color (src, drawable_type (s_drawable), rgb, s);
gimage_transform_color (dest, d_drawable, rgb, d, RGB);
PixelArea painthit_area;
void * pag;
gint pattern_width = canvas_width (pattern->mask);
gint pattern_height = canvas_height (pattern->mask);
if (has_alpha)
d[dest_alpha] = s[src_alpha];
else
d[dest_alpha] = OPAQUE;
pixelarea_init (&painthit_area, painthit,
0, 0, 0, 0, TRUE);
for (pag = pixelarea_register (1, &painthit_area);
pag != NULL;
pag = pixelarea_process (pag))
{
PixelArea painthit_portion_area, pat_area;
GdkRectangle pat_rect;
GdkRectangle painthit_portion_rect;
GdkRectangle r;
gint x_pat, y_pat;
gint x_pat_start, y_pat_start;
gint x_portion, y_portion, w_portion, h_portion;
gint extra;
x_portion = pixelarea_x ( &painthit_area );
y_portion = pixelarea_y ( &painthit_area );
w_portion = pixelarea_width ( &painthit_area );
h_portion = pixelarea_height ( &painthit_area );
if (x + x_portion >= 0)
extra = (x + x_portion) % pattern_width;
else
{
extra = (x + x_portion) % pattern_width;
extra += pattern_width;
}
x_pat_start = (x + x_portion) - extra;
if (y + y_portion >= 0)
extra = (y + y_portion) % pattern_height;
else
{
extra = (y + y_portion) % pattern_height;
extra += pattern_height;
}
y_pat_start = (y + y_portion) - extra;
x_pat = x_pat_start;
y_pat = y_pat_start;
/* tile the portion with the pattern */
while (1)
{
pat_rect.x = x_pat;
pat_rect.y = y_pat;
pat_rect.width = pattern_width;
pat_rect.height = pattern_height;
s += src_bytes;
d += dest_bytes;
painthit_portion_rect.x = x + x_portion;
painthit_portion_rect.y = y + y_portion;
painthit_portion_rect.width = w_portion;
painthit_portion_rect.height = h_portion;
gdk_rectangle_intersect (&pat_rect, &painthit_portion_rect, &r);
pixelarea_init ( &painthit_portion_area, painthit,
r.x - painthit_portion_rect.x,
r.y - painthit_portion_rect.y,
r.width, r.height, TRUE);
pixelarea_init ( &pat_area, pattern->mask,
r.x - pat_rect.x, r.y - pat_rect.y,
r.width, r.height, FALSE);
copy_area (&pat_area, &painthit_portion_area);
x_pat += pattern_width;
if (x_pat >= (x + x_portion) + w_portion)
{
x_pat = x_pat_start;
y_pat += pattern_height;
if ( y_pat >= (y + y_portion) + h_portion )
break;
}
}
}
rc = TRUE;
}
return rc;
}
static void
clone_line_pattern (GImage *dest,
GimpDrawable *drawable,
GPatternP pattern,
unsigned char *d,
int x,
int y,
int bytes,
int width)
{
unsigned char *pat, *p;
int color, alpha;
int i;
/* Make sure x, y are positive */
while (x < 0)
x += pattern->mask->width;
while (y < 0)
y += pattern->mask->height;
/* Get a pointer to the appropriate scanline of the pattern buffer */
pat = temp_buf_data (pattern->mask) +
(y % pattern->mask->height) * pattern->mask->width * pattern->mask->bytes;
color = (pattern->mask->bytes == 3) ? RGB : GRAY;
alpha = bytes - 1;
for (i = 0; i < width; i++)
{
p = pat + ((i + x) % pattern->mask->width) * pattern->mask->bytes;
gimage_transform_color (dest, drawable, p, d, color);
d[alpha] = OPAQUE;
d += bytes;
}
}
static void *
clone_non_gui_paint_func (PaintCore *paint_core,

View File

@@ -13,20 +13,17 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CLONE_H__
#define __CLONE_H__
#include "paint_core.h"
#include "procedural_db.h"
#include "tools.h"
struct _tool;
struct _ProcRecord;
void * clone_paint_func (PaintCore *, GimpDrawable *, int);
Tool * tools_new_clone (void);
void tools_free_clone (Tool *);
struct _tool * tools_new_clone (void);
void tools_free_clone (struct _tool *);
/* Procedure definition and marshalling function */
extern ProcRecord clone_proc;
extern struct _ProcRecord clone_proc;
#endif /* __CLONE_H__ */

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
@@ -22,6 +22,7 @@
#include "color_select.h"
#include "colormaps.h"
#include "palette.h"
#include "pixelrow.h"
#define FORE_AREA 0
#define BACK_AREA 1
@@ -40,8 +41,13 @@ static GdkPixmap *swap_pixmap = NULL;
static ColorSelectP color_select = NULL;
static int color_select_active = 0;
static int edit_color;
static unsigned char revert_fg_r, revert_fg_g, revert_fg_b;
static unsigned char revert_bg_r, revert_bg_g, revert_bg_b;
static PixelRow revert_fg;
static guchar revert_fg_data[TAG_MAX_BYTES];
static PixelRow revert_bg;
static guchar revert_bg_data[TAG_MAX_BYTES];
/* Local functions */
static int
@@ -137,9 +143,7 @@ color_area_draw (void)
}
static void
color_area_select_callback (int r,
int g,
int b,
color_area_select_callback (PixelRow * color,
ColorSelectState state,
void *client_data)
{
@@ -152,15 +156,15 @@ color_area_select_callback (int r,
/* Fallthrough */
case COLOR_SELECT_UPDATE:
if (edit_color == FOREGROUND)
palette_set_foreground (r, g, b);
palette_set_foreground (color);
else
palette_set_background (r, g, b);
palette_set_background (color);
break;
case COLOR_SELECT_CANCEL:
color_select_hide (color_select);
color_select_active = 0;
palette_set_foreground (revert_fg_r, revert_fg_g, revert_fg_b);
palette_set_background (revert_bg_r, revert_bg_g, revert_bg_b);
palette_set_foreground (&revert_fg);
palette_set_background (&revert_bg);
}
}
}
@@ -168,34 +172,49 @@ color_area_select_callback (int r,
static void
color_area_edit (void)
{
unsigned char r, g, b;
PixelRow r;
guchar d[TAG_MAX_BYTES];
pixelrow_init (&r,
tag_new (PRECISION_FLOAT, FORMAT_RGB, ALPHA_NO),
d,
1);
if (!color_select_active)
{
palette_get_foreground (&revert_fg_r, &revert_fg_g, &revert_fg_b);
palette_get_background (&revert_bg_r, &revert_bg_g, &revert_bg_b);
pixelrow_init (&revert_fg,
tag_new (PRECISION_FLOAT, FORMAT_RGB, ALPHA_NO),
revert_fg_data,
1);
palette_get_foreground (&revert_fg);
pixelrow_init (&revert_bg,
tag_new (PRECISION_FLOAT, FORMAT_RGB, ALPHA_NO),
revert_bg_data,
1);
palette_get_background (&revert_bg);
}
if (active_color == FOREGROUND)
{
palette_get_foreground (&r, &g, &b);
palette_get_foreground (&r);
edit_color = FOREGROUND;
}
else
{
palette_get_background (&r, &g, &b);
palette_get_background (&r);
edit_color = BACKGROUND;
}
if (! color_select)
{
color_select = color_select_new (r, g, b, color_area_select_callback, NULL);
color_select = color_select_new (&r, color_area_select_callback, NULL, TRUE);
color_select_active = 1;
}
else
{
if (! color_select_active)
color_select_show (color_select);
color_select_set_color (color_select, r, g, b, 1);
color_select_set_color (color_select, &r, 1);
}
}
@@ -205,20 +224,27 @@ color_area_events (GtkWidget *widget,
{
GdkEventButton *bevent;
int target;
unsigned char fg_r, fg_g, fg_b;
unsigned char bg_r, bg_g, bg_b;
switch (event->type)
{
case GDK_EXPOSE:
if (!color_area_pixmap)
color_area_pixmap = gdk_pixmap_new (widget->window,
widget->allocation.width,
widget->allocation.height, -1);
if (!color_area_gc)
color_area_gc = gdk_gc_new (widget->window);
case GDK_CONFIGURE:
if (color_area_pixmap)
gdk_pixmap_unref (color_area_pixmap);
color_area_draw ();
color_area_pixmap = gdk_pixmap_new (widget->window,
widget->allocation.width,
widget->allocation.height, -1);
break;
case GDK_EXPOSE:
if (GTK_WIDGET_DRAWABLE (widget))
{
if (!color_area_gc)
color_area_gc = gdk_gc_new (widget->window);
color_area_draw ();
}
break;
case GDK_BUTTON_PRESS:
@@ -239,18 +265,11 @@ color_area_events (GtkWidget *widget,
}
break;
case SWAP_AREA:
palette_get_foreground (&fg_r, &fg_g, &fg_b);
palette_get_background (&bg_r, &bg_g, &bg_b);
palette_set_foreground (bg_r, bg_g, bg_b);
palette_set_background (fg_r, fg_g, fg_b);
palette_swap_colors();
color_area_draw ();
break;
case DEF_AREA:
palette_set_foreground (0, 0, 0);
palette_set_background (255, 255, 255);
palette_set_default_colors();
color_area_draw ();
break;
}

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __COLOR_AREA_H__

View File

@@ -13,23 +13,29 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "appenv.h"
#include "actionarea.h"
#include "canvas.h"
#include "color_balance.h"
#include "color_transfer.h"
#include "drawable.h"
#include "float16.h"
#include "general.h"
#include "gimage_mask.h"
#include "gdisplay.h"
#include "image_map.h"
#include "interface.h"
#include "paint_funcs_area.h"
#include "pixelarea.h"
#include "pixelrow.h"
#define TEXT_WIDTH 55
#define SQR(x) ((x) * (x))
#define SHADOWS 0
#define MIDTONES 1
@@ -43,6 +49,16 @@
#define YB_TEXT 0x20
#define ALL 0xFF
/* for lightening */
gdouble * highlights_add_ptr;
gdouble * midtones_add_ptr;
gdouble * shadows_add_ptr;
/* for darkening */
gdouble * highlights_sub_ptr;
gdouble * midtones_sub_ptr;
gdouble * shadows_sub_ptr;
typedef struct _ColorBalance ColorBalance;
struct _ColorBalance
@@ -103,102 +119,602 @@ static void color_balance_yb_text_update (GtkWidget *, gpo
static void *color_balance_options = NULL;
static ColorBalanceDialog *color_balance_dialog = NULL;
static void color_balance (PixelRegion *, PixelRegion *, void *);
static void color_balance (PixelArea *, PixelArea *, void *);
static Argument * color_balance_invoker (Argument *);
static gdouble f0_u8 (gdouble);
static gdouble f1_u8 (gdouble);
static gdouble f2_u8 (gdouble);
static gdouble f0 (gdouble);
static gdouble f1 (gdouble);
static gdouble f2 (gdouble);
static void color_balance_allocate_transfer_arrays (gint);
static void color_balance_free_transfer_arrays (void);
typedef void (*ColorBalanceInitTransfersFunc)(void);
ColorBalanceInitTransfersFunc color_balance_init_transfers;
typedef void (*ColorBalanceRowFunc)(PixelRow *, PixelRow *, double *, double *, double *, gint);
ColorBalanceRowFunc color_balance_row;
static void color_balance_funcs (Tag drawable_tag);
static void color_balance_init_transfers_u8 (void);
static void color_balance_row_u8 (PixelRow *, PixelRow *, double *, double *, double *, gint);
static void color_balance_init_transfers_u16 (void);
static void color_balance_row_u16 (PixelRow *, PixelRow *, double *, double *, double *, gint);
static void color_balance_init_transfers_float (void);
static void color_balance_row_float (PixelRow *, PixelRow *, double *, double *, double *, gint);
static void color_balance_init_transfers_float16 (void);
static void color_balance_row_float16 (PixelRow *, PixelRow *, double *, double *, double *, gint);
/* color balance machinery */
static void
color_balance_funcs (Tag drawable_tag)
{
switch (tag_precision (drawable_tag))
{
case PRECISION_U8:
color_balance_row = color_balance_row_u8;
color_balance_init_transfers = color_balance_init_transfers_u8;
break;
case PRECISION_U16:
color_balance_row = color_balance_row_u16;
color_balance_init_transfers = color_balance_init_transfers_u16;
break;
case PRECISION_FLOAT:
color_balance_row = color_balance_row_float;
color_balance_init_transfers = color_balance_init_transfers_float;
case PRECISION_FLOAT16:
color_balance_row = color_balance_row_float16;
color_balance_init_transfers = color_balance_init_transfers_float16;
break;
default:
color_balance_row = NULL;
color_balance_init_transfers = NULL;
break;
}
}
static void
color_balance (PixelRegion *srcPR,
PixelRegion *destPR,
color_balance (PixelArea *src_area,
PixelArea *dest_area,
void *user_data)
{
ColorBalanceDialog *cbd;
unsigned char *src, *s;
unsigned char *dest, *d;
int alpha;
int r, g, b;
int r_n, g_n, b_n;
int w, h;
double *cyan_red_transfer[3];
double *magenta_green_transfer[3];
double *yellow_blue_transfer[3];
cbd = (ColorBalanceDialog *) user_data;
/* Set the transfer arrays (for speed) */
cyan_red_transfer[SHADOWS] = (cbd->cyan_red[SHADOWS] > 0) ? shadows_add : shadows_sub;
cyan_red_transfer[MIDTONES] = (cbd->cyan_red[MIDTONES] > 0) ? midtones_add : midtones_sub;
cyan_red_transfer[HIGHLIGHTS] = (cbd->cyan_red[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
magenta_green_transfer[SHADOWS] = (cbd->magenta_green[SHADOWS] > 0) ? shadows_add : shadows_sub;
magenta_green_transfer[MIDTONES] = (cbd->magenta_green[MIDTONES] > 0) ? midtones_add : midtones_sub;
magenta_green_transfer[HIGHLIGHTS] = (cbd->magenta_green[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
yellow_blue_transfer[SHADOWS] = (cbd->yellow_blue[SHADOWS] > 0) ? shadows_add : shadows_sub;
yellow_blue_transfer[MIDTONES] = (cbd->yellow_blue[MIDTONES] > 0) ? midtones_add : midtones_sub;
yellow_blue_transfer[HIGHLIGHTS] = (cbd->yellow_blue[HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
h = srcPR->h;
src = srcPR->data;
dest = destPR->data;
alpha = (srcPR->bytes == 4) ? TRUE : FALSE;
PixelRow src_row, dest_row;
ColorBalanceDialog *cbd = (ColorBalanceDialog *) user_data;
int h= pixelarea_height (src_area);
while (h--)
{
w = srcPR->w;
s = src;
d = dest;
while (w--)
{
r = r_n = s[RED_PIX];
g = g_n = s[GREEN_PIX];
b = b_n = s[BLUE_PIX];
r_n += cbd->cyan_red[SHADOWS] * cyan_red_transfer[SHADOWS][r_n];
r_n = BOUNDS (r_n, 0, 255);
r_n += cbd->cyan_red[MIDTONES] * cyan_red_transfer[MIDTONES][r_n];
r_n = BOUNDS (r_n, 0, 255);
r_n += cbd->cyan_red[HIGHLIGHTS] * cyan_red_transfer[HIGHLIGHTS][r_n];
r_n = BOUNDS (r_n, 0, 255);
g_n += cbd->magenta_green[SHADOWS] * magenta_green_transfer[SHADOWS][g_n];
g_n = BOUNDS (g_n, 0, 255);
g_n += cbd->magenta_green[MIDTONES] * magenta_green_transfer[MIDTONES][g_n];
g_n = BOUNDS (g_n, 0, 255);
g_n += cbd->magenta_green[HIGHLIGHTS] * magenta_green_transfer[HIGHLIGHTS][g_n];
g_n = BOUNDS (g_n, 0, 255);
b_n += cbd->yellow_blue[SHADOWS] * yellow_blue_transfer[SHADOWS][b_n];
b_n = BOUNDS (b_n, 0, 255);
b_n += cbd->yellow_blue[MIDTONES] * yellow_blue_transfer[MIDTONES][b_n];
b_n = BOUNDS (b_n, 0, 255);
b_n += cbd->yellow_blue[HIGHLIGHTS] * yellow_blue_transfer[HIGHLIGHTS][b_n];
b_n = BOUNDS (b_n, 0, 255);
if (cbd->preserve_luminosity)
{
rgb_to_hls (&r, &g, &b);
rgb_to_hls (&r_n, &g_n, &b_n);
g_n = g;
hls_to_rgb (&r_n, &g_n, &b_n);
}
d[RED_PIX] = r_n;
d[GREEN_PIX] = g_n;
d[BLUE_PIX] = b_n;
if (alpha)
d[ALPHA_PIX] = s[ALPHA_PIX];
s += srcPR->bytes;
d += destPR->bytes;
}
src += srcPR->rowstride;
dest += destPR->rowstride;
pixelarea_getdata (src_area, &src_row, h);
pixelarea_getdata (dest_area, &dest_row, h);
(*color_balance_row) (&src_row, &dest_row,
cbd->cyan_red,
cbd->magenta_green,
cbd->yellow_blue,
cbd->preserve_luminosity);
}
}
static void
color_balance_row_u8 (
PixelRow *src_row,
PixelRow *dest_row,
double * cr,
double * mg,
double * yb,
gint preserve_luminosity
)
{
Tag src_tag = pixelrow_tag (src_row);
Tag dest_tag = pixelrow_tag (dest_row);
gint src_num_channels = tag_num_channels (src_tag);
gint dest_num_channels = tag_num_channels (dest_tag);
guint8 *s, *d;
int has_alpha;
int r, g, b;
int r_n, g_n, b_n;
double *cyan_red_transfer[3];
double *magenta_green_transfer[3];
double *yellow_blue_transfer[3];
gint w = pixelrow_width (src_row);
/* Set the transfer arrays (for speed) */
cyan_red_transfer[SHADOWS] = (cr[SHADOWS] > 0) ? shadows_add_ptr : shadows_sub_ptr;
cyan_red_transfer[MIDTONES] = (cr[MIDTONES] > 0) ? midtones_add_ptr : midtones_sub_ptr;
cyan_red_transfer[HIGHLIGHTS] = (cr[HIGHLIGHTS] > 0) ? highlights_add_ptr : highlights_sub_ptr;
magenta_green_transfer[SHADOWS] = (mg[SHADOWS] > 0) ? shadows_add_ptr : shadows_sub_ptr;
magenta_green_transfer[MIDTONES] = (mg[MIDTONES] > 0) ? midtones_add_ptr : midtones_sub_ptr;
magenta_green_transfer[HIGHLIGHTS] = (mg[HIGHLIGHTS] > 0) ? highlights_add_ptr : highlights_sub_ptr;
yellow_blue_transfer[SHADOWS] = (yb[SHADOWS] > 0) ? shadows_add_ptr : shadows_sub_ptr;
yellow_blue_transfer[MIDTONES] = (yb[MIDTONES] > 0) ? midtones_add_ptr : midtones_sub_ptr;
yellow_blue_transfer[HIGHLIGHTS] = (yb[HIGHLIGHTS] > 0) ? highlights_add_ptr : highlights_sub_ptr;
s = (guint8 *)pixelrow_data (src_row);
d = (guint8 *)pixelrow_data (dest_row);
has_alpha = tag_alpha (src_tag) == ALPHA_YES? TRUE: FALSE;
while (w--)
{
r = r_n = s[RED_PIX];
g = g_n = s[GREEN_PIX];
b = b_n = s[BLUE_PIX];
r_n += cr[SHADOWS] * cyan_red_transfer[SHADOWS][r_n];
r_n = BOUNDS (r_n, 0, 255);
r_n += cr[MIDTONES] * cyan_red_transfer[MIDTONES][r_n];
r_n = BOUNDS (r_n, 0, 255);
r_n += cr[HIGHLIGHTS] * cyan_red_transfer[HIGHLIGHTS][r_n];
r_n = BOUNDS (r_n, 0, 255);
g_n += mg[SHADOWS] * magenta_green_transfer[SHADOWS][g_n];
g_n = BOUNDS (g_n, 0, 255);
g_n += mg[MIDTONES] * magenta_green_transfer[MIDTONES][g_n];
g_n = BOUNDS (g_n, 0, 255);
g_n += mg[HIGHLIGHTS] * magenta_green_transfer[HIGHLIGHTS][g_n];
g_n = BOUNDS (g_n, 0, 255);
b_n += yb[SHADOWS] * yellow_blue_transfer[SHADOWS][b_n];
b_n = BOUNDS (b_n, 0, 255);
b_n += yb[MIDTONES] * yellow_blue_transfer[MIDTONES][b_n];
b_n = BOUNDS (b_n, 0, 255);
b_n += yb[HIGHLIGHTS] * yellow_blue_transfer[HIGHLIGHTS][b_n];
b_n = BOUNDS (b_n, 0, 255);
if (preserve_luminosity)
{
rgb_to_hls (&r, &g, &b);
rgb_to_hls (&r_n, &g_n, &b_n);
g_n = g;
hls_to_rgb (&r_n, &g_n, &b_n);
}
d[RED_PIX] = r_n;
d[GREEN_PIX] = g_n;
d[BLUE_PIX] = b_n;
if (has_alpha)
d[ALPHA_PIX] = s[ALPHA_PIX];
s += src_num_channels;
d += dest_num_channels;
}
}
static void
color_balance_row_u16 (
PixelRow *src_row,
PixelRow *dest_row,
double * cr,
double * mg,
double * yb,
gint preserve_luminosity
)
{
Tag src_tag = pixelrow_tag (src_row);
Tag dest_tag = pixelrow_tag (dest_row);
gint src_num_channels = tag_num_channels (src_tag);
gint dest_num_channels = tag_num_channels (dest_tag);
guint16 *s, *d;
int has_alpha;
int r, g, b;
int r_n, g_n, b_n;
double *cyan_red_transfer[3];
double *magenta_green_transfer[3];
double *yellow_blue_transfer[3];
gint w = pixelrow_width (src_row);
gfloat cr_shadows, cr_midtones, cr_highlights;
gfloat mg_shadows, mg_midtones, mg_highlights;
gfloat yb_shadows, yb_midtones, yb_highlights;
/* Set the transfer arrays (for speed) */
cyan_red_transfer[SHADOWS] = (cr[SHADOWS] > 0) ? shadows_add_ptr : shadows_sub_ptr;
cyan_red_transfer[MIDTONES] = (cr[MIDTONES] > 0) ? midtones_add_ptr : midtones_sub_ptr;
cyan_red_transfer[HIGHLIGHTS] = (cr[HIGHLIGHTS] > 0) ? highlights_add_ptr : highlights_sub_ptr;
magenta_green_transfer[SHADOWS] = (mg[SHADOWS] > 0) ? shadows_add_ptr : shadows_sub_ptr;
magenta_green_transfer[MIDTONES] = (mg[MIDTONES] > 0) ? midtones_add_ptr : midtones_sub_ptr;
magenta_green_transfer[HIGHLIGHTS] = (mg[HIGHLIGHTS] > 0) ? highlights_add_ptr : highlights_sub_ptr;
yellow_blue_transfer[SHADOWS] = (yb[SHADOWS] > 0) ? shadows_add_ptr : shadows_sub_ptr;
yellow_blue_transfer[MIDTONES] = (yb[MIDTONES] > 0) ? midtones_add_ptr : midtones_sub_ptr;
yellow_blue_transfer[HIGHLIGHTS] = (yb[HIGHLIGHTS] > 0) ? highlights_add_ptr : highlights_sub_ptr;
/* scale cr, mg, yb to [0-65535] */
cr_shadows = (cr[SHADOWS]/255.0) * 65535;
cr_midtones = (cr[MIDTONES]/255.0) * 65535;
cr_highlights = (cr[HIGHLIGHTS]/255.0) * 65535;
mg_shadows = (mg[SHADOWS]/255.0) * 65535;
mg_midtones = (mg[MIDTONES]/255.0) * 65535;
mg_highlights = (mg[HIGHLIGHTS]/255.0) * 65535;
yb_shadows = (yb[SHADOWS]/255.0) * 65535;
yb_midtones = (yb[MIDTONES]/255.0) * 65535;
yb_highlights = (yb[HIGHLIGHTS]/255.0) * 65535;
s = (guint16 *)pixelrow_data (src_row);
d = (guint16 *)pixelrow_data (dest_row);
has_alpha = tag_alpha (src_tag) == ALPHA_YES? TRUE: FALSE;
while (w--)
{
r = r_n = s[RED_PIX];
g = g_n = s[GREEN_PIX];
b = b_n = s[BLUE_PIX];
r_n += cr_shadows * cyan_red_transfer[SHADOWS][r_n];
r_n = BOUNDS (r_n, 0, 65535);
r_n += cr_midtones * cyan_red_transfer[MIDTONES][r_n];
r_n = BOUNDS (r_n, 0, 65535);
r_n += cr_highlights * cyan_red_transfer[HIGHLIGHTS][r_n];
r_n = BOUNDS (r_n, 0, 65535);
g_n += mg_shadows * magenta_green_transfer[SHADOWS][g_n];
g_n = BOUNDS (g_n, 0, 65535);
g_n += mg_midtones * magenta_green_transfer[MIDTONES][g_n];
g_n = BOUNDS (g_n, 0, 65535);
g_n += mg_highlights * magenta_green_transfer[HIGHLIGHTS][g_n];
g_n = BOUNDS (g_n, 0, 65535);
b_n += yb_shadows * yellow_blue_transfer[SHADOWS][b_n];
b_n = BOUNDS (b_n, 0, 65535);
b_n += yb_midtones * yellow_blue_transfer[MIDTONES][b_n];
b_n = BOUNDS (b_n, 0, 65535);
b_n += yb_highlights * yellow_blue_transfer[HIGHLIGHTS][b_n];
b_n = BOUNDS (b_n, 0, 65535);
if (preserve_luminosity)
{
#if 0
rgb_to_hls (&r, &g, &b);
rgb_to_hls (&r_n, &g_n, &b_n);
g_n = g;
hls_to_rgb (&r_n, &g_n, &b_n);
#endif
}
d[RED_PIX] = r_n;
d[GREEN_PIX] = g_n;
d[BLUE_PIX] = b_n;
if (has_alpha)
d[ALPHA_PIX] = s[ALPHA_PIX];
s += src_num_channels;
d += dest_num_channels;
}
}
static void
color_balance_row_float (
PixelRow *src_row,
PixelRow *dest_row,
double * cr,
double * mg,
double * yb,
gint preserve_luminosity
)
{
Tag src_tag = pixelrow_tag (src_row);
Tag dest_tag = pixelrow_tag (dest_row);
gint src_num_channels = tag_num_channels (src_tag);
gint dest_num_channels = tag_num_channels (dest_tag);
gfloat *s, *d;
int has_alpha;
gdouble r, g, b;
gdouble r_n, g_n, b_n;
gfloat cr_shadows, cr_midtones, cr_highlights;
gfloat mg_shadows, mg_midtones, mg_highlights;
gfloat yb_shadows, yb_midtones, yb_highlights;
gdouble (*cyan_red_transfer[3])(gdouble);
gdouble (*magenta_green_transfer[3])(gdouble);
gdouble (*yellow_blue_transfer[3])(gdouble);
gint w = pixelrow_width (src_row);
/* scale cr, mg, yb to [0-1] */
cr_shadows = cr[SHADOWS]/255.0;
cr_midtones = cr[MIDTONES]/255.0;
cr_highlights = cr[HIGHLIGHTS]/255.0;
mg_shadows = mg[SHADOWS]/255.0;
mg_midtones = mg[MIDTONES]/255.0;
mg_highlights = mg[HIGHLIGHTS]/255.0;
yb_shadows = yb[SHADOWS]/255.0;
yb_midtones = yb[MIDTONES]/255.0;
yb_highlights = yb[HIGHLIGHTS]/255.0;
/* Set the function_ptrs for the computations */
cyan_red_transfer[SHADOWS] = (cr[SHADOWS] > 0) ? f2: f0;
cyan_red_transfer[MIDTONES] = f2;
cyan_red_transfer[HIGHLIGHTS] = (cr[HIGHLIGHTS] > 0) ? f1 : f2;
magenta_green_transfer[SHADOWS] = (mg[SHADOWS] > 0) ? f2 : f0;
magenta_green_transfer[MIDTONES] = f2;
magenta_green_transfer[HIGHLIGHTS] = (mg[HIGHLIGHTS] > 0) ? f1 : f2;
yellow_blue_transfer[SHADOWS] = (yb[SHADOWS] > 0) ? f2 : f0;
yellow_blue_transfer[MIDTONES] = f2;
yellow_blue_transfer[HIGHLIGHTS] = (yb[HIGHLIGHTS] > 0) ? f1 : f2;
s = (gfloat *)pixelrow_data (src_row);
d = (gfloat *)pixelrow_data (dest_row);
has_alpha = tag_alpha (src_tag) == ALPHA_YES? TRUE: FALSE;
while (w--)
{
r = r_n = s[RED_PIX];
g = g_n = s[GREEN_PIX];
b = b_n = s[BLUE_PIX];
r_n += cr_shadows * cyan_red_transfer[SHADOWS](r_n);
r_n = BOUNDS (r_n, 0, 1.0);
r_n += cr_midtones * cyan_red_transfer[MIDTONES](r_n);
r_n = BOUNDS (r_n, 0, 1.0);
r_n += cr_highlights * cyan_red_transfer[HIGHLIGHTS](r_n);
r_n = BOUNDS (r_n, 0, 1.0);
g_n += mg_shadows * magenta_green_transfer[SHADOWS](g_n);
g_n = BOUNDS (g_n, 0, 1.0);
g_n += mg_midtones * magenta_green_transfer[MIDTONES](g_n);
g_n = BOUNDS (g_n, 0, 1.0);
g_n += mg_highlights * magenta_green_transfer[HIGHLIGHTS](g_n);
g_n = BOUNDS (g_n, 0, 1.0);
b_n += yb_shadows * yellow_blue_transfer[SHADOWS](b_n);
b_n = BOUNDS (b_n, 0, 1.0);
b_n += yb_midtones * yellow_blue_transfer[MIDTONES](b_n);
b_n = BOUNDS (b_n, 0, 1.0);
b_n += yb_highlights * yellow_blue_transfer[HIGHLIGHTS](b_n);
b_n = BOUNDS (b_n, 0, 1.0);
if (preserve_luminosity)
{
#if 0
rgb_to_hls (&r, &g, &b);
rgb_to_hls (&r_n, &g_n, &b_n);
g_n = g;
hls_to_rgb (&r_n, &g_n, &b_n);
#endif
}
d[RED_PIX] = r_n;
d[GREEN_PIX] = g_n;
d[BLUE_PIX] = b_n;
if (has_alpha)
d[ALPHA_PIX] = s[ALPHA_PIX];
s += src_num_channels;
d += dest_num_channels;
}
}
static void
color_balance_row_float16 (
PixelRow *src_row,
PixelRow *dest_row,
double * cr,
double * mg,
double * yb,
gint preserve_luminosity
)
{
Tag src_tag = pixelrow_tag (src_row);
Tag dest_tag = pixelrow_tag (dest_row);
gint src_num_channels = tag_num_channels (src_tag);
gint dest_num_channels = tag_num_channels (dest_tag);
guint16 *s, *d;
int has_alpha;
gdouble r, g, b;
gdouble r_n, g_n, b_n;
gfloat cr_shadows, cr_midtones, cr_highlights;
gfloat mg_shadows, mg_midtones, mg_highlights;
gfloat yb_shadows, yb_midtones, yb_highlights;
gdouble (*cyan_red_transfer[3])(gdouble);
gdouble (*magenta_green_transfer[3])(gdouble);
gdouble (*yellow_blue_transfer[3])(gdouble);
gint w = pixelrow_width (src_row);
ShortsFloat u;
/* scale cr, mg, yb to [0-1] */
cr_shadows = cr[SHADOWS]/255.0;
cr_midtones = cr[MIDTONES]/255.0;
cr_highlights = cr[HIGHLIGHTS]/255.0;
mg_shadows = mg[SHADOWS]/255.0;
mg_midtones = mg[MIDTONES]/255.0;
mg_highlights = mg[HIGHLIGHTS]/255.0;
yb_shadows = yb[SHADOWS]/255.0;
yb_midtones = yb[MIDTONES]/255.0;
yb_highlights = yb[HIGHLIGHTS]/255.0;
/* Set the function_ptrs for the computations */
cyan_red_transfer[SHADOWS] = (cr[SHADOWS] > 0) ? f2: f0;
cyan_red_transfer[MIDTONES] = f2;
cyan_red_transfer[HIGHLIGHTS] = (cr[HIGHLIGHTS] > 0) ? f1 : f2;
magenta_green_transfer[SHADOWS] = (mg[SHADOWS] > 0) ? f2 : f0;
magenta_green_transfer[MIDTONES] = f2;
magenta_green_transfer[HIGHLIGHTS] = (mg[HIGHLIGHTS] > 0) ? f1 : f2;
yellow_blue_transfer[SHADOWS] = (yb[SHADOWS] > 0) ? f2 : f0;
yellow_blue_transfer[MIDTONES] = f2;
yellow_blue_transfer[HIGHLIGHTS] = (yb[HIGHLIGHTS] > 0) ? f1 : f2;
s = (guint16 *)pixelrow_data (src_row);
d = (guint16 *)pixelrow_data (dest_row);
has_alpha = tag_alpha (src_tag) == ALPHA_YES? TRUE: FALSE;
while (w--)
{
r = r_n = FLT (s[RED_PIX], u);
g = g_n = FLT (s[GREEN_PIX], u);
b = b_n = FLT (s[BLUE_PIX], u);
r_n += cr_shadows * cyan_red_transfer[SHADOWS](r_n);
r_n = BOUNDS (r_n, 0, 1.0);
r_n += cr_midtones * cyan_red_transfer[MIDTONES](r_n);
r_n = BOUNDS (r_n, 0, 1.0);
r_n += cr_highlights * cyan_red_transfer[HIGHLIGHTS](r_n);
r_n = BOUNDS (r_n, 0, 1.0);
g_n += mg_shadows * magenta_green_transfer[SHADOWS](g_n);
g_n = BOUNDS (g_n, 0, 1.0);
g_n += mg_midtones * magenta_green_transfer[MIDTONES](g_n);
g_n = BOUNDS (g_n, 0, 1.0);
g_n += mg_highlights * magenta_green_transfer[HIGHLIGHTS](g_n);
g_n = BOUNDS (g_n, 0, 1.0);
b_n += yb_shadows * yellow_blue_transfer[SHADOWS](b_n);
b_n = BOUNDS (b_n, 0, 1.0);
b_n += yb_midtones * yellow_blue_transfer[MIDTONES](b_n);
b_n = BOUNDS (b_n, 0, 1.0);
b_n += yb_highlights * yellow_blue_transfer[HIGHLIGHTS](b_n);
b_n = BOUNDS (b_n, 0, 1.0);
if (preserve_luminosity)
{
#if 0
rgb_to_hls (&r, &g, &b);
rgb_to_hls (&r_n, &g_n, &b_n);
g_n = g;
hls_to_rgb (&r_n, &g_n, &b_n);
#endif
}
d[RED_PIX] = FLT16 (r_n, u);
d[GREEN_PIX] = FLT16 (g_n, u);
d[BLUE_PIX] = FLT16 (b_n, u);
if (has_alpha)
d[ALPHA_PIX] = s[ALPHA_PIX];
s += src_num_channels;
d += dest_num_channels;
}
}
static void
color_balance_allocate_transfer_arrays (gint size)
{
highlights_add_ptr = (gdouble *)g_malloc ( sizeof (gdouble) * size );
midtones_add_ptr = (gdouble *)g_malloc ( sizeof (gdouble) * size );
shadows_add_ptr = (gdouble *)g_malloc ( sizeof (gdouble) * size );
highlights_sub_ptr = (gdouble *)g_malloc ( sizeof (gdouble) * size );
midtones_sub_ptr = (gdouble *)g_malloc ( sizeof (gdouble) * size );
shadows_sub_ptr = (gdouble *)g_malloc ( sizeof (gdouble) * size );
}
static void
color_balance_free_transfer_arrays (void)
{
if (highlights_add_ptr)
g_free (highlights_add_ptr);
if (midtones_add_ptr)
g_free (midtones_add_ptr);
if (shadows_add_ptr)
g_free (shadows_add_ptr);
if (highlights_sub_ptr)
g_free (highlights_sub_ptr);
if (midtones_sub_ptr)
g_free (midtones_sub_ptr);
if (shadows_sub_ptr)
g_free (shadows_sub_ptr);
highlights_add_ptr = NULL;
midtones_add_ptr = NULL;
shadows_add_ptr = NULL;
highlights_sub_ptr = NULL;
midtones_sub_ptr = NULL;
shadows_sub_ptr = NULL;
}
static void
color_balance_init_transfers_u8 (void)
{
gint i;
color_balance_allocate_transfer_arrays (256);
for (i = 0; i < 256; i++)
{
highlights_add_ptr[i] = shadows_sub_ptr[255 - i] = f1_u8 ((double)i);
midtones_add_ptr[i] = midtones_sub_ptr[i] = f2_u8 ((double)i);
shadows_add_ptr[i] = highlights_sub_ptr[i] = f2_u8 ((double)i);
}
}
static void
color_balance_init_transfers_u16 (void)
{
gdouble x;
gint i;
color_balance_allocate_transfer_arrays (65536);
for (i = 0; i < 65536; i++)
{
x = ((double)i/65535.0);
highlights_add_ptr[i] = shadows_sub_ptr[65535 - i] = f1(x);
midtones_add_ptr[i] = midtones_sub_ptr[i] = f2(x);
shadows_add_ptr[i] = highlights_sub_ptr[i] = f2(x);
}
}
static void
color_balance_init_transfers_float (void)
{
}
static void
color_balance_init_transfers_float16 (void)
{
}
static
gdouble f0_u8(
gdouble x
)
{
return 1.075 - 1/((255.0-x)/16.0 + 1);
}
static
gdouble f1_u8(
gdouble x
)
{
return 1.075 - 1/(x/16.0 + 1);
}
static
gdouble f0(
gdouble x
)
{
return 1.075 - 1.0 /(.0625 * (1.0-x) + 1.0);
}
static
gdouble f1(
gdouble x
)
{
return 1.075 - 1.0 /(.0625 * x + 1.0);
}
/* Formula for midtones_add, midtones_sub,
shadows_add and highlights_sub arrays [0-255] based*/
static
gdouble f2_u8(
gdouble x
)
{
return 0.667 * (1 - SQR ((x - 127.0) / 127.0));
}
static
gdouble f2(
gdouble x
)
{
return .667 * (1.0 - SQR ( 2.0 * x - 1.0));
}
/* by_color select action functions */
static void
@@ -206,6 +722,10 @@ color_balance_button_press (Tool *tool,
GdkEventButton *bevent,
gpointer gdisp_ptr)
{
GDisplay *gdisp;
gdisp = gdisp_ptr;
tool->drawable = gimage_active_drawable (gdisp->gimage);
}
static void
@@ -251,7 +771,10 @@ color_balance_control (Tool *tool,
case HALT :
if (color_balance_dialog)
{
active_tool->preserve = TRUE;
image_map_abort (color_balance_dialog->image_map);
active_tool->preserve = FALSE;
color_balance_free_transfer_arrays();
color_balance_dialog->image_map = NULL;
color_balance_cancel_callback (NULL, (gpointer) color_balance_dialog);
}
@@ -283,6 +806,9 @@ tools_new_color_balance ()
tool->arrow_keys_func = standard_arrow_keys_func;
tool->cursor_update_func = color_balance_cursor_update;
tool->control_func = color_balance_control;
tool->preserve = FALSE;
tool->gdisp_ptr = NULL;
tool->drawable = NULL;
return tool;
}
@@ -296,7 +822,7 @@ tools_free_color_balance (Tool *tool)
/* Close the color select dialog */
if (color_balance_dialog)
color_balance_ok_callback (NULL, (gpointer) color_balance_dialog);
color_balance_cancel_callback (NULL, (gpointer) color_balance_dialog);
g_free (color_bal);
}
@@ -305,13 +831,14 @@ void
color_balance_initialize (void *gdisp_ptr)
{
GDisplay *gdisp;
GimpDrawable *drawable;
int i;
gdisp = (GDisplay *) gdisp_ptr;
if (! drawable_color (gimage_active_drawable (gdisp->gimage)))
{
message_box ("Color balance operates only on RGB color drawables.", NULL, NULL);
g_message ("Color balance operates only on RGB color drawables.");
return;
}
@@ -330,14 +857,22 @@ color_balance_initialize (void *gdisp_ptr)
color_balance_dialog->magenta_green[i] = 0.0;
color_balance_dialog->yellow_blue[i] = 0.0;
}
color_balance_dialog->drawable = gimage_active_drawable (gdisp->gimage);
drawable = gimage_active_drawable (gdisp->gimage);
/* Set up the function pointers for our data type */
color_balance_funcs (drawable_tag (drawable));
/* Init the transfer arrays */
(*color_balance_init_transfers) ();
color_balance_dialog->drawable = drawable;
color_balance_dialog->image_map = image_map_create (gdisp_ptr, color_balance_dialog->drawable);
color_balance_update (color_balance_dialog, ALL);
}
/****************************/
/* Select by Color dialog */
/* Color Balance dialog */
/****************************/
/* the action area structure */
@@ -347,7 +882,7 @@ static ActionAreaItem action_items[] =
{ "Cancel", color_balance_cancel_callback, NULL, NULL }
};
ColorBalanceDialog *
static ColorBalanceDialog *
color_balance_new_dialog ()
{
ColorBalanceDialog *cbd;
@@ -383,6 +918,7 @@ color_balance_new_dialog ()
/* The shell and main vbox */
cbd->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (cbd->shell), "color_balance", "Gimp");
gtk_window_set_title (GTK_WINDOW (cbd->shell), "Color Balance");
/* handle the wm close signal */
@@ -611,8 +1147,10 @@ static void
color_balance_preview (ColorBalanceDialog *cbd)
{
if (!cbd->image_map)
g_warning ("No image map");
g_message ("color_balance_preview(): No image map");
active_tool->preserve = TRUE;
image_map_apply (cbd->image_map, color_balance, (void *) cbd);
active_tool->preserve = FALSE;
}
static void
@@ -625,12 +1163,19 @@ color_balance_ok_callback (GtkWidget *widget,
if (GTK_WIDGET_VISIBLE (cbd->shell))
gtk_widget_hide (cbd->shell);
active_tool->preserve = TRUE;
if (!cbd->preview)
image_map_apply (cbd->image_map, color_balance, (void *) cbd);
if (cbd->image_map)
{
image_map_commit (cbd->image_map);
color_balance_free_transfer_arrays();
}
active_tool->preserve = FALSE;
cbd->image_map = NULL;
}
@@ -642,7 +1187,7 @@ color_balance_delete_callback (GtkWidget *w,
{
color_balance_cancel_callback (w, client_data);
return FALSE;
return TRUE;
}
static void
@@ -657,7 +1202,10 @@ color_balance_cancel_callback (GtkWidget *widget,
if (cbd->image_map)
{
active_tool->preserve = TRUE;
image_map_abort (cbd->image_map);
active_tool->preserve = FALSE;
color_balance_free_transfer_arrays();
gdisplays_flush ();
}
@@ -916,7 +1464,7 @@ ProcRecord color_balance_proc =
static Argument *
color_balance_invoker (Argument *args)
{
PixelRegion srcPR, destPR;
PixelArea src_area, dest_area;
int success = TRUE;
int int_value;
ColorBalanceDialog cbd;
@@ -953,6 +1501,10 @@ color_balance_invoker (Argument *args)
if (drawable == NULL || gimage != drawable_gimage (drawable))
success = FALSE;
}
/* make sure the drawable is not indexed color */
if (success)
success = ! drawable_indexed (drawable);
/* transfer_mode */
if (success)
{
@@ -1017,11 +1569,15 @@ color_balance_invoker (Argument *args)
/* The application should occur only within selection bounds */
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
pixel_region_init (&srcPR, drawable_data (drawable), x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, drawable_shadow (drawable), x1, y1, (x2 - x1), (y2 - y1), TRUE);
pixelarea_init (&src_area, drawable_data (drawable),
x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixelarea_init (&dest_area, drawable_shadow (drawable),
x1, y1, (x2 - x1), (y2 - y1), TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
color_balance (&srcPR, &destPR, (void *) &cbd);
for (pr = pixelarea_register (2, &src_area, &dest_area);
pr != NULL;
pr = pixelarea_process (pr))
color_balance (&src_area, &dest_area, (void *) &cbd);
drawable_merge_shadow (drawable, TRUE);
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __COLOR_BALANCE_H__
#define __COLOR_BALANCE_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <math.h>
#include <stdio.h>
@@ -22,6 +22,9 @@
#include "color_panel.h"
#include "color_select.h"
#include "colormaps.h"
#include "paint_funcs_area.h"
#include "pixelrow.h"
#define EVENT_MASK GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
@@ -38,17 +41,16 @@ struct _ColorPanelPrivate
static void color_panel_draw (ColorPanel *);
static gint color_panel_events (GtkWidget *area, GdkEvent *event);
static void color_panel_select_callback (int, int, int, ColorSelectState, void *);
static void color_panel_select_callback (PixelRow *, ColorSelectState, void *);
ColorPanel *
color_panel_new (unsigned char *initial,
int width,
int height)
color_panel_new (PixelRow * initial,
int width,
int height)
{
ColorPanel *color_panel;
ColorPanelPrivate *private;
int i;
color_panel = g_new (ColorPanel, 1);
private = g_new (ColorPanelPrivate, 1);
@@ -58,8 +60,8 @@ color_panel_new (unsigned char *initial,
color_panel->private_part = private;
/* set the initial color */
for (i = 0; i < 3; i++)
color_panel->color[i] = (initial) ? initial[i] : 0;
pixelrow_init (&color_panel->color, pixelrow_tag (initial), color_panel->color_data, 1);
copy_row (initial, &color_panel->color);
color_panel->color_panel_widget = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (color_panel->color_panel_widget), GTK_SHADOW_IN);
@@ -110,9 +112,7 @@ color_panel_draw (ColorPanel *color_panel)
fg.pixel = old_color_pixel;
store_color (&fg.pixel,
color_panel->color[0],
color_panel->color[1],
color_panel->color[2]);
&color_panel->color);
gdk_gc_set_foreground (private->gc, &fg);
gdk_draw_rectangle (widget->window, private->gc, 1, 0, 0,
@@ -146,11 +146,10 @@ color_panel_events (GtkWidget *widget,
{
if (! private->color_select)
{
private->color_select = color_select_new (color_panel->color[0],
color_panel->color[1],
color_panel->color[2],
private->color_select = color_select_new (&color_panel->color,
color_panel_select_callback,
color_panel);
color_panel,
FALSE);
private->color_select_active = 1;
}
else
@@ -158,9 +157,7 @@ color_panel_events (GtkWidget *widget,
if (! private->color_select_active)
color_select_show (private->color_select);
color_select_set_color (private->color_select,
color_panel->color[0],
color_panel->color[1],
color_panel->color[2], 1);
&color_panel->color, 1);
}
}
break;
@@ -173,9 +170,7 @@ color_panel_events (GtkWidget *widget,
}
static void
color_panel_select_callback (int r,
int g,
int b,
color_panel_select_callback (PixelRow * col,
ColorSelectState state,
void *client_data)
{
@@ -191,10 +186,7 @@ color_panel_select_callback (int r,
case COLOR_SELECT_UPDATE:
break;
case COLOR_SELECT_OK:
color_panel->color[0] = r;
color_panel->color[1] = g;
color_panel->color[2] = b;
copy_row (col, &color_panel->color);
color_panel_draw (color_panel);
/* Fallthrough */
case COLOR_SELECT_CANCEL:

View File

@@ -13,11 +13,14 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __COLOR_PANEL_H__
#define __COLOR_PANEL_H__
#include "tag.h"
#include "pixelrow.h"
typedef struct _ColorPanel ColorPanel;
struct _ColorPanel
@@ -25,16 +28,17 @@ struct _ColorPanel
/* The calling procedure is respondible for showing this widget */
GtkWidget * color_panel_widget;
/* The actual color */
unsigned char color [3];
/* the color */
PixelRow color;
guchar color_data [TAG_MAX_BYTES];
/* Don't touch this :) */
void * private_part;
};
ColorPanel * color_panel_new (unsigned char * initial,
int width,
int height);
void color_panel_free (ColorPanel * color_panel);
ColorPanel * color_panel_new (PixelRow * initial,
int width,
int height);
void color_panel_free (ColorPanel * color_panel);
#endif /* __COLOR_PANEL_H__ */

View File

@@ -13,22 +13,26 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include "appenv.h"
#include "actionarea.h"
#include "canvas.h"
#include "color_picker.h"
#include "drawable.h"
#include "float16.h"
#include "gdisplay.h"
#include "info_dialog.h"
#include "palette.h"
#include "pixelrow.h"
#include "tools.h"
/* maximum information buffer size */
#define MAX_INFO_BUF 4
#define MAX_INFO_BUF 32
/* local function prototypes */
@@ -38,18 +42,20 @@ static void color_picker_button_release (Tool *, GdkEventButton *, gpointer);
static void color_picker_motion (Tool *, GdkEventMotion *, gpointer);
static void color_picker_cursor_update (Tool *, GdkEventMotion *, gpointer);
static void color_picker_control (Tool *, int, void *);
static void color_picker_info_window_close_callback (GtkWidget *, gpointer);
static int get_color (GImage *, GimpDrawable *, int, int, int, int);
static void color_picker_info_update (Tool *, int);
static int get_color (GImage *, GimpDrawable *, int, int, int, int);
static void color_picker_info_update (Tool *, int);
static Argument *color_picker_invoker (Argument *);
/* local variables */
static int col_value [5] = { 0, 0, 0, 0, 0 };
static guchar _color [TAG_MAX_BYTES];
static PixelRow color;
static GimpDrawable * active_drawable;
static int update_type;
static int sample_type;
static InfoDialog * color_picker_info = NULL;
static char red_buf [MAX_INFO_BUF];
static char green_buf [MAX_INFO_BUF];
@@ -57,6 +63,7 @@ static char blue_buf [MAX_INFO_BUF];
static char alpha_buf [MAX_INFO_BUF];
static char index_buf [MAX_INFO_BUF];
static char gray_buf [MAX_INFO_BUF];
static char hex_buf [MAX_INFO_BUF];
typedef struct _ColorPickerOptions ColorPickerOptions;
struct _ColorPickerOptions
@@ -117,6 +124,11 @@ create_color_picker_options (void)
return options;
}
static ActionAreaItem action_items[] =
{
{ "Close", color_picker_info_window_close_callback, NULL, NULL },
};
static void
color_picker_button_press (Tool *tool,
GdkEventButton *bevent,
@@ -141,31 +153,38 @@ color_picker_button_press (Tool *tool,
active_drawable = gimage_active_drawable (gdisp->gimage);
/* if the gdisplay is for a color image, the dialog must have RGB */
switch (drawable_type (active_drawable))
switch (tag_format (drawable_tag (active_drawable)))
{
case RGB_GIMAGE: case RGBA_GIMAGE:
case FORMAT_RGB:
info_dialog_add_field (color_picker_info, "Red", red_buf);
info_dialog_add_field (color_picker_info, "Green", green_buf);
info_dialog_add_field (color_picker_info, "Blue", blue_buf);
info_dialog_add_field (color_picker_info, "Alpha", alpha_buf);
info_dialog_add_field (color_picker_info, "Hex Triplet", hex_buf);
break;
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
case FORMAT_INDEXED:
info_dialog_add_field (color_picker_info, "Index", index_buf);
info_dialog_add_field (color_picker_info, "Alpha", alpha_buf);
info_dialog_add_field (color_picker_info, "Red", red_buf);
info_dialog_add_field (color_picker_info, "Green", green_buf);
info_dialog_add_field (color_picker_info, "Blue", blue_buf);
info_dialog_add_field (color_picker_info, "Hex Triplet", hex_buf);
break;
case GRAY_GIMAGE: case GRAYA_GIMAGE:
case FORMAT_GRAY:
info_dialog_add_field (color_picker_info, "Intensity", gray_buf);
info_dialog_add_field (color_picker_info, "Alpha", alpha_buf);
info_dialog_add_field (color_picker_info, "Hex Triplet", hex_buf);
break;
default :
break;
}
/* Create the action area */
action_items[0].user_data = color_picker_info;
build_action_area (GTK_DIALOG (color_picker_info->shell), action_items, 1, 0);
}
gdk_pointer_grab (gdisp->canvas->window, FALSE,
@@ -198,6 +217,8 @@ color_picker_button_press (Tool *tool,
COLOR_UPDATE));
update_type = COLOR_UPDATE;
}
}
static void
@@ -262,107 +283,260 @@ color_picker_control (Tool *tool,
{
}
static int
get_color (GImage *gimage,
GimpDrawable *drawable,
int x,
int y,
int sample_merged,
int final)
static int
get_color (
GImage * gimage,
GimpDrawable * drawable,
int x,
int y,
int sample_merged,
int final
)
{
unsigned char *src, *cmap, alpha;
TileManager *tiles;
Tile *tile;
int offx, offy;
PixelRow pixel;
Canvas *tiles;
int width, height;
int bytes;
int index;
int has_alpha;
if (!drawable && !sample_merged)
return FALSE;
if (! sample_merged)
{
int offx, offy;
drawable_offsets (drawable, &offx, &offy);
x -= offx;
y -= offy;
width = drawable_width (drawable);
height = drawable_height (drawable);
tiles = drawable_data (drawable);
bytes = drawable_bytes (drawable);
has_alpha = drawable_has_alpha (drawable);
sample_type = drawable_type (drawable);
cmap = drawable_cmap (drawable);
pixelrow_init (&color, drawable_tag (drawable), _color, 1);
}
else
{
width = gimage->width;
height = gimage->height;
tiles = gimage_composite (gimage);
bytes = gimage_composite_bytes (gimage);
sample_type = gimage_composite_type (gimage);
has_alpha = (sample_type == RGBA_GIMAGE ||
sample_type == GRAYA_GIMAGE ||
sample_type == INDEXEDA_GIMAGE);
cmap = gimage_cmap (gimage);
tiles = gimage_projection (gimage);
pixelrow_init (&color, gimage_tag (gimage), _color, 1);
}
if (x >= 0 && y >= 0 && x < width && y < height)
{
tile = tile_manager_get_tile (tiles, x, y, 0);
tile_ref (tile);
src = tile->data + tile->bpp * (tile->ewidth * (y % TILE_HEIGHT) + (x % TILE_WIDTH));
}
else
if (x < 0 || y < 0 || x >= width || y >= height)
return FALSE;
/* if the alpha channel (if one exists) is 0, out of bounds */
if (has_alpha)
{
alpha = src[bytes - 1];
col_value [ALPHA_PIX] = alpha;
}
canvas_portion_refro (tiles, x, y);
/* If the image is color, get RGB */
switch (sample_type)
{
case RGB_GIMAGE: case RGBA_GIMAGE:
col_value [RED_PIX] = src [RED_PIX];
col_value [GREEN_PIX] = src [GREEN_PIX];
col_value [BLUE_PIX] = src [BLUE_PIX];
break;
pixelrow_init (&pixel, canvas_tag (tiles), canvas_portion_data (tiles, x, y), 1);
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
col_value [4] = src [0];
index = src [0] * 3;
col_value [RED_PIX] = cmap [index + 0];
col_value [GREEN_PIX] = cmap [index + 1];
col_value [BLUE_PIX] = cmap [index + 2];
break;
copy_row (&pixel, &color);
canvas_portion_unref (tiles, x, y);
case GRAY_GIMAGE: case GRAYA_GIMAGE:
col_value [RED_PIX] = src [GRAY_PIX];
col_value [GREEN_PIX] = src [GRAY_PIX];
col_value [BLUE_PIX] = src [GRAY_PIX];
break;
palette_set_active_color (&color, final);
default :
break;
}
tile_unref (tile, FALSE);
palette_set_active_color (col_value [RED_PIX], col_value [GREEN_PIX],
col_value [BLUE_PIX], final);
return TRUE;
}
static void
color_picker_info_update (Tool *tool,
int valid)
static void
color_picker_info_update_u8 (
void
)
{
guint8 * src = pixelrow_data (&color);
Tag sample_tag = pixelrow_tag (&color);
switch (tag_format (sample_tag))
{
case FORMAT_RGB:
sprintf (red_buf, "%d", src [0]);
sprintf (green_buf, "%d", src [1]);
sprintf (blue_buf, "%d", src [2]);
if (tag_alpha (sample_tag) == ALPHA_YES)
sprintf (alpha_buf, "%d", src [3]);
else
sprintf (alpha_buf, "N/A");
sprintf (hex_buf, "#%.2x%.2x%.2x",
src [0], src [1], src [2]);
break;
case FORMAT_INDEXED:
sprintf (index_buf, "%d", src [0]);
if (tag_alpha (sample_tag) == ALPHA_YES)
sprintf (alpha_buf, "%d", src [1]);
else
sprintf (alpha_buf, "N/A");
sprintf (red_buf, "N/A");
sprintf (green_buf, "N/A");
sprintf (blue_buf, "N/A");
sprintf (hex_buf, "N/A");
break;
case FORMAT_GRAY:
sprintf (gray_buf, "%d", src [0]);
if (tag_alpha (sample_tag) == ALPHA_YES)
sprintf (alpha_buf, "%d", src [1]);
else
sprintf (alpha_buf, "N/A");
sprintf (hex_buf, "#%.2x%.2x%.2x", src [0],
src [0], src [0]);
break;
case FORMAT_NONE:
default:
g_warning ("bad format");
break;
}
}
static void
color_picker_info_update_u16 (
void
)
{
guint16 * src = (guint16*) pixelrow_data (&color);
Tag sample_tag = pixelrow_tag (&color);
switch (tag_format (sample_tag))
{
case FORMAT_RGB:
sprintf (red_buf, "%d", src [0]);
sprintf (green_buf, "%d", src [1]);
sprintf (blue_buf, "%d", src [2]);
if (tag_alpha (sample_tag) == ALPHA_YES)
sprintf (alpha_buf, "%d", src [3]);
else
sprintf (alpha_buf, "N/A");
sprintf (hex_buf, "#%.4x %.4x %.4x",
src [0], src [1], src [2]);
break;
case FORMAT_INDEXED:
sprintf (index_buf, "%d", src [0]);
if (tag_alpha (sample_tag) == ALPHA_YES)
sprintf (alpha_buf, "%d", src [1]);
else
sprintf (alpha_buf, "N/A");
sprintf (red_buf, "N/A");
sprintf (green_buf, "N/A");
sprintf (blue_buf, "N/A");
sprintf (hex_buf, "N/A");
break;
case FORMAT_GRAY:
sprintf (gray_buf, "%d", src [0]);
if (tag_alpha (sample_tag) == ALPHA_YES)
sprintf (alpha_buf, "%d", src [1]);
else
sprintf (alpha_buf, "N/A");
sprintf (hex_buf, "#%.4x %.4x %.4x", src [0],
src [0], src [0]);
break;
case FORMAT_NONE:
default:
g_warning ("bad format");
break;
}
}
static void
color_picker_info_update_float (
void
)
{
gfloat * src = (gfloat*) pixelrow_data (&color);
Tag sample_tag = pixelrow_tag (&color);
switch (tag_format (sample_tag))
{
case FORMAT_RGB:
sprintf (red_buf, "%7.6f", src [0]);
sprintf (green_buf, "%7.6f", src [1]);
sprintf (blue_buf, "%7.6f", src [2]);
if (tag_alpha (sample_tag) == ALPHA_YES)
sprintf (alpha_buf, "%7.6f", src [3]);
else
sprintf (alpha_buf, "N/A");
sprintf (hex_buf, "N/A");
break;
case FORMAT_INDEXED:
sprintf (index_buf, "N/A");
sprintf (alpha_buf, "N/A");
sprintf (red_buf, "N/A");
sprintf (green_buf, "N/A");
sprintf (blue_buf, "N/A");
sprintf (hex_buf, "N/A");
break;
case FORMAT_GRAY:
sprintf (gray_buf, "%7.6f", src [0]);
if (tag_alpha (sample_tag) == ALPHA_YES)
sprintf (alpha_buf, "%7.6f", src [1]);
else
sprintf (alpha_buf, "N/A");
sprintf (hex_buf, "N/A");
break;
case FORMAT_NONE:
default:
g_warning ("bad format");
break;
}
}
static void
color_picker_info_update_float16 (
void
)
{
guint16 * src = (guint16*) pixelrow_data (&color);
Tag sample_tag = pixelrow_tag (&color);
ShortsFloat u;
switch (tag_format (sample_tag))
{
case FORMAT_RGB:
sprintf (red_buf, "%7.6f", FLT (src [0], u));
sprintf (green_buf, "%7.6f", FLT (src [1], u));
sprintf (blue_buf, "%7.6f", FLT (src [2], u));
if (tag_alpha (sample_tag) == ALPHA_YES)
sprintf (alpha_buf, "%7.6f", FLT (src [3], u));
else
sprintf (alpha_buf, "N/A");
sprintf (hex_buf, "N/A");
break;
case FORMAT_INDEXED:
sprintf (index_buf, "N/A");
sprintf (alpha_buf, "N/A");
sprintf (red_buf, "N/A");
sprintf (green_buf, "N/A");
sprintf (blue_buf, "N/A");
sprintf (hex_buf, "N/A");
break;
case FORMAT_GRAY:
sprintf (gray_buf, "%7.6f", FLT (src [0], u));
if (tag_alpha (sample_tag) == ALPHA_YES)
sprintf (alpha_buf, "%7.6f", FLT (src [1], u));
else
sprintf (alpha_buf, "N/A");
sprintf (hex_buf, "N/A");
break;
case FORMAT_NONE:
default:
g_warning ("bad format");
break;
}
}
static void
color_picker_info_update (
Tool * tool,
int valid
)
{
if (!valid)
{
@@ -372,39 +546,32 @@ color_picker_info_update (Tool *tool,
sprintf (alpha_buf, "N/A");
sprintf (index_buf, "N/A");
sprintf (gray_buf, "N/A");
sprintf (hex_buf, "N/A");
}
else
{
switch (sample_type)
switch (tag_precision (pixelrow_tag (&color)))
{
case RGB_GIMAGE: case RGBA_GIMAGE:
sprintf (red_buf, "%d", col_value [RED_PIX]);
sprintf (green_buf, "%d", col_value [GREEN_PIX]);
sprintf (blue_buf, "%d", col_value [BLUE_PIX]);
if (sample_type == RGBA_GIMAGE)
sprintf (alpha_buf, "%d", col_value [ALPHA_PIX]);
else
sprintf (alpha_buf, "N/A");
break;
case PRECISION_U8:
color_picker_info_update_u8 ();
break;
case INDEXED_GIMAGE: case INDEXEDA_GIMAGE:
sprintf (index_buf, "%d", col_value [4]);
if (sample_type == INDEXEDA_GIMAGE)
sprintf (alpha_buf, "%d", col_value [ALPHA_PIX]);
else
sprintf (alpha_buf, "N/A");
sprintf (red_buf, "%d", col_value [RED_PIX]);
sprintf (green_buf, "%d", col_value [GREEN_PIX]);
sprintf (blue_buf, "%d", col_value [BLUE_PIX]);
break;
case PRECISION_U16:
color_picker_info_update_u16 ();
break;
case GRAY_GIMAGE: case GRAYA_GIMAGE:
sprintf (gray_buf, "%d", col_value [GRAY_PIX]);
if (sample_type == GRAYA_GIMAGE)
sprintf (alpha_buf, "%d", col_value [ALPHA_PIX]);
else
sprintf (alpha_buf, "N/A");
break;
case PRECISION_FLOAT:
color_picker_info_update_float ();
break;
case PRECISION_FLOAT16:
color_picker_info_update_float16 ();
break;
case PRECISION_NONE:
default:
g_warning ("bad precision");
break;
}
}
@@ -412,6 +579,7 @@ color_picker_info_update (Tool *tool,
info_dialog_popup (color_picker_info);
}
Tool *
tools_new_color_picker ()
{
@@ -433,6 +601,7 @@ tools_new_color_picker ()
tool->arrow_keys_func = standard_arrow_keys_func;
tool->cursor_update_func = color_picker_cursor_update;
tool->control_func = color_picker_control;
tool->preserve = TRUE;
return tool;
}
@@ -518,7 +687,6 @@ color_picker_invoker (Argument *args)
int save_color;
int int_value;
Argument *return_args;
unsigned char *color;
drawable = NULL;
x = 0;
@@ -571,12 +739,19 @@ color_picker_invoker (Argument *args)
if (success)
{
color = (unsigned char *) g_malloc (3);
color[RED_PIX] = col_value[RED_PIX];
color[GREEN_PIX] = col_value[GREEN_PIX];
color[BLUE_PIX] = col_value[BLUE_PIX];
return_args[1].value.pdb_pointer = color;
PixelRow c;
guchar * _c = (unsigned char *) g_malloc (3);
pixelrow_init (&c, tag_new (PRECISION_U8, FORMAT_RGB, ALPHA_NO), _c, 1);
copy_row (&color, &c);
return_args[1].value.pdb_pointer = _c;
}
return return_args;
}
static void
color_picker_info_window_close_callback (GtkWidget *w,
gpointer client_data)
{
info_dialog_popdown ((InfoDialog *) client_data);
}

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __COLOR_PICKER_H__
#define __COLOR_PICKER_H__

File diff suppressed because it is too large Load Diff

View File

@@ -13,11 +13,13 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __COLOR_SELECT_H__
#define __COLOR_SELECT_H__
struct _PixelRow;
typedef enum {
COLOR_SELECT_OK,
COLOR_SELECT_CANCEL,
@@ -25,7 +27,7 @@ typedef enum {
} ColorSelectState;
typedef struct _ColorSelect _ColorSelect, *ColorSelectP;
typedef void (*ColorSelectCallback) (int, int, int, ColorSelectState, void *);
typedef void (*ColorSelectCallback) (struct _PixelRow *, ColorSelectState, void *);
struct _ColorSelect {
GtkWidget *shell;
@@ -36,20 +38,21 @@ struct _ColorSelect {
GtkWidget *toggles[6];
GtkWidget *entries[6];
GtkAdjustment *slider_data[6];
int pos[3];
int values[6];
gfloat pos[3];
gfloat values[6];
int z_color_fill;
int xy_color_fill;
int orig_values[3];
gfloat orig_values[3];
ColorSelectCallback callback;
void *client_data;
int wants_updates;
GdkGC *gc;
};
ColorSelectP color_select_new (int, int, int, ColorSelectCallback, void *);
ColorSelectP color_select_new (struct _PixelRow *, ColorSelectCallback, void *, int);
void color_select_show (ColorSelectP);
void color_select_hide (ColorSelectP);
void color_select_free (ColorSelectP);
void color_select_set_color (ColorSelectP, int, int, int, int);
void color_select_set_color (ColorSelectP, struct _PixelRow *, int);
#endif /* __COLOR_SELECT_H__ */

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __COLOR_TRANSFER_H__
#define __COLOR_TRANSFER_H__

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <math.h>
@@ -21,14 +21,16 @@
#include "app_procs.h"
#include "brushes.h"
#include "colormaps.h"
#include "displaylut.h"
#include "errors.h"
#include "general.h"
#include "gimprc.h"
#include "gradient.h"
#include "paint_funcs_area.h"
#include "palette.h"
#include "patterns.h"
#include "pixelrow.h"
#include "plug_in.h"
#include "temp_buf.h"
#include "tile_swap.h"
@@ -65,54 +67,76 @@ gulong *g_lookup_blue;
gulong *color_pixel_vals;
gulong *gray_pixel_vals;
static int reserved_entries = 10; /* extra colors aside from color cube */
static int reserved_entries = 4; /* extra colors aside from color cube */
static gulong *reserved_pixels;
static void make_color (gulong *pixel_ptr,
int red,
int green,
int blue,
int readwrite);
static void
set_app_colors ()
{
int i;
if (g_visual->depth == 8)
if ((g_visual->type == GDK_VISUAL_PSEUDO_COLOR) ||
(g_visual->type == GDK_VISUAL_GRAYSCALE))
{
g_black_pixel = reserved_pixels[0];
g_gray_pixel = reserved_pixels[1];
g_white_pixel = reserved_pixels[2];
g_color_pixel = reserved_pixels[3];
g_normal_guide_pixel = reserved_pixels[4];
g_active_guide_pixel = reserved_pixels[5];
foreground_pixel = reserved_pixels[6];
background_pixel = reserved_pixels[7];
old_color_pixel = reserved_pixels[8];
new_color_pixel = reserved_pixels[9];
foreground_pixel = reserved_pixels[0];
background_pixel = reserved_pixels[1];
old_color_pixel = reserved_pixels[2];
new_color_pixel = reserved_pixels[3];
}
else
{
cycled_marching_ants = FALSE;
}
store_color (&g_black_pixel, 0, 0, 0);
store_color (&g_gray_pixel, 127, 127, 127);
store_color (&g_white_pixel, 255, 255, 255);
store_color (&g_color_pixel, 255, 255, 0);
store_color (&g_normal_guide_pixel, 0, 127, 255);
store_color (&g_active_guide_pixel, 255, 0, 0);
store_color (&foreground_pixel, 0, 0, 0);
store_color (&background_pixel, 255, 255, 255);
store_color (&old_color_pixel, 0, 0, 0);
store_color (&new_color_pixel, 255, 255, 255);
make_color (&g_black_pixel, 0, 0, 0, FALSE);
make_color (&g_gray_pixel, 127, 127, 127, FALSE);
make_color (&g_white_pixel, 255, 255, 255, FALSE);
make_color (&g_color_pixel, 255, 255, 0, FALSE);
make_color (&g_normal_guide_pixel, 0, 127, 255, FALSE);
make_color (&g_active_guide_pixel, 255, 0, 0, FALSE);
{
PixelRow col;
guchar d[TAG_MAX_BYTES];
pixelrow_init (&col, tag_new (PRECISION_FLOAT, FORMAT_RGB, ALPHA_NO), d, 1);
palette_get_black (&col);
store_color (&foreground_pixel, &col);
store_color (&old_color_pixel, &col);
palette_get_white (&col);
store_color (&background_pixel, &col);
store_color (&new_color_pixel, &col);
}
/* marching ants pixels--if enabled */
if (cycled_marching_ants)
for (i = 0; i < 8; i++)
{
marching_ants_pixels[i] = reserved_pixels[i + reserved_entries - 8];
if (i < 4)
store_color (&marching_ants_pixels[i], 0, 0, 0);
else
store_color (&marching_ants_pixels[i], 255, 255, 255);
}
{
COLOR16_NEW (black, tag_new (PRECISION_FLOAT, FORMAT_RGB, ALPHA_NO));
COLOR16_NEW (white, tag_new (PRECISION_FLOAT, FORMAT_RGB, ALPHA_NO));
COLOR16_INIT (black);
COLOR16_INIT (white);
palette_get_black (&black);
palette_get_white (&white);
for (i = 0; i < 8; i++)
{
marching_ants_pixels[i] = reserved_pixels[i + reserved_entries - 8];
if (i < 4)
store_color (&marching_ants_pixels[i], &black);
else
store_color (&marching_ants_pixels[i], &white);
}
}
}
@@ -139,28 +163,33 @@ gamma_correct (int intensity, double gamma)
gulong
get_color (int red,
int green,
int blue)
get_color (PixelRow * col)
{
gulong pixel;
PixelRow r;
guchar d[TAG_MAX_BYTES];
if (g_visual->depth == 8)
pixel = color_pixel_vals [(red_ordered_dither[red].s[1] +
green_ordered_dither[green].s[1] +
blue_ordered_dither[blue].s[1])];
pixelrow_init (&r, tag_new (PRECISION_U8, FORMAT_RGB, ALPHA_NO), d, 1);
copy_row (col, &r);
if ((g_visual->type == GDK_VISUAL_PSEUDO_COLOR) ||
(g_visual->type == GDK_VISUAL_GRAYSCALE))
pixel = color_pixel_vals [(red_ordered_dither[d[0]].s[1] +
green_ordered_dither[d[1]].s[1] +
blue_ordered_dither[d[2]].s[1])];
else
store_color (&pixel, red, green, blue);
store_color (&pixel, col);
return pixel;
}
void
store_color (gulong *pixel_ptr,
int red,
int green,
int blue)
static void
make_color (gulong *pixel_ptr,
int red,
int green,
int blue,
int readwrite)
{
GdkColor col;
@@ -173,7 +202,8 @@ store_color (gulong *pixel_ptr,
col.blue = blue * (65535 / 255);
col.pixel = *pixel_ptr;
if (g_visual->depth == 8)
if (readwrite && ((g_visual->type == GDK_VISUAL_PSEUDO_COLOR) ||
(g_visual->type == GDK_VISUAL_GRAYSCALE)))
gdk_color_change (g_cmap, &col);
else
gdk_color_alloc (g_cmap, &col);
@@ -181,6 +211,46 @@ store_color (gulong *pixel_ptr,
*pixel_ptr = col.pixel;
}
void
store_color (gulong *pixel_ptr,
PixelRow * col)
{
PixelRow r;
guchar d[TAG_MAX_BYTES];
pixelrow_init (&r, tag_new (PRECISION_U8, FORMAT_RGB, ALPHA_NO), d, 1);
copy_row (col, &r);
make_color (pixel_ptr, d[0], d[1], d[2], TRUE);
}
void
store_display_color (gulong *pixel_ptr,
PixelRow * col)
{
PixelRow r;
guint8 d[3];
switch (tag_precision ( pixelrow_tag (col)))
{
case PRECISION_FLOAT:
{
gfloat * float_data = (gfloat *) pixelrow_data (col);
d[0] = display_u8_from_float(float_data[0]);
d[1] = display_u8_from_float(float_data[1]);
d[2] = display_u8_from_float(float_data[2]);
}
break;
case PRECISION_U8:
case PRECISION_U16:
case PRECISION_FLOAT16:
case PRECISION_NONE:
default:
g_warning ("store_display_color: bad precision\n");
break;
}
make_color (pixel_ptr, d[0], d[1], d[2], TRUE);
}
void
get_standard_colormaps ()
@@ -196,16 +266,21 @@ get_standard_colormaps ()
gtk_preview_set_install_cmap (install_cmap);
gtk_preview_set_reserved (reserved_entries);
/* so we can reinit the colormaps */
gtk_preview_reset ();
gtk_widget_set_default_visual (gtk_preview_get_visual ());
gtk_widget_set_default_colormap (gtk_preview_get_cmap ());
info = gtk_preview_get_info ();
g_visual = info->visual;
if (g_visual->depth == 8 && info->reserved_pixels == NULL) {
if (((g_visual->type == GDK_VISUAL_PSEUDO_COLOR) ||
(g_visual->type == GDK_VISUAL_GRAYSCALE)) &&
info->reserved_pixels == NULL) {
g_print("GIMP cannot get enough colormaps to boot.\n");
g_print("Try exiting other color intensive applications.\n");
swapping_free ();
g_print("Also try enabling the (install-colormap) option in gimprc.\n");
brushes_free ();
patterns_free ();
palettes_free ();

View File

@@ -13,11 +13,13 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __COLORMAPS_H__
#define __COLORMAPS_H__
struct _PixelRow;
#include "gimage.h" /* For the image types */
/* This is a macro for arranging the red, green, and blue components into
@@ -62,8 +64,9 @@ extern gulong *g_lookup_blue;
extern gulong *color_pixel_vals;
extern gulong *gray_pixel_vals;
gulong get_color (int red, int green, int blue);
void store_color (gulong *pixel, int red, int green, int blue);
gulong get_color (struct _PixelRow *);
void store_color (gulong *pixel, struct _PixelRow *);
void store_display_color (gulong *pixel, struct _PixelRow *);
void get_standard_colormaps (void);

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
@@ -54,19 +54,21 @@
#include "layers_dialog.h"
#include "layer_select.h"
#include "levels.h"
#include "paint_funcs_area.h"
#include "palette.h"
#include "patterns.h"
#include "plug_in.h"
#include "posterize.h"
#include "resize.h"
#include "scale.h"
#include "tag.h"
#include "threshold.h"
#include "tips_dialog.h"
#include "tools.h"
#include "undo.h"
/* external functions */
extern layers_dialog_layer_merge_query (GImage *, int);
extern void layers_dialog_layer_merge_query (GImage *, int);
typedef struct {
GtkWidget *dlg;
@@ -74,7 +76,8 @@ typedef struct {
GtkWidget *width_entry;
int width;
int height;
int type;
Format format;
Storage storage;
int fill_type;
} NewImageValues;
@@ -94,7 +97,8 @@ static void file_new_toggle_callback (GtkWidget *, gpointer);
/* static variables */
static int last_width = 256;
static int last_height = 256;
static int last_type = RGB;
static Format last_format = FORMAT_RGB;
static Storage last_storage = STORAGE_TILED;
static int last_fill_type = BACKGROUND_FILL;
/* preferences local functions */
@@ -111,6 +115,7 @@ static GtkWidget *prefs_dlg = NULL;
static int old_transparency_type;
static int old_transparency_size;
static int old_levels_of_undo;
static int old_marching_speed;
static int old_allow_resize_windows;
static int old_auto_save;
static int old_preview_size;
@@ -120,7 +125,8 @@ static int old_cubic_interpolation;
static int old_confirm_on_close;
static int old_default_width;
static int old_default_height;
static int old_default_type;
static Format old_default_format;
static Precision old_default_precision;
static int new_dialog_run;
static int old_stingy_memory_use;
static int old_tile_cache_size;
@@ -174,7 +180,9 @@ file_new_ok_callback (GtkWidget *widget,
GImage *gimage;
GDisplay *gdisplay;
Layer *layer;
int type;
Precision precision = PRECISION_NONE;
Format format = FORMAT_NONE;
Alpha alpha = ALPHA_NONE;
vals = data;
@@ -185,36 +193,47 @@ file_new_ok_callback (GtkWidget *widget,
last_width = vals->width;
last_height = vals->height;
last_type = vals->type;
last_format = vals->format;
last_storage = vals->storage;
last_fill_type = vals->fill_type;
switch (vals->fill_type)
{
case BACKGROUND_FILL:
case FOREGROUND_FILL:
case WHITE_FILL:
type = (vals->type == RGB) ? RGB_GIMAGE : GRAY_GIMAGE;
case NO_FILL:
format = (vals->format == FORMAT_RGB) ? FORMAT_RGB: FORMAT_GRAY;
alpha = ALPHA_NO;
break;
case TRANSPARENT_FILL:
type = (vals->type == RGB) ? RGBA_GIMAGE : GRAYA_GIMAGE;
format = (vals->format == FORMAT_RGB) ? FORMAT_RGB: FORMAT_GRAY;
alpha = ALPHA_YES;
break;
default:
type = RGB_IMAGE;
format = FORMAT_NONE;
alpha = ALPHA_NONE;
break;
}
gimage = gimage_new (vals->width, vals->height, vals->type);
precision = default_precision;
/* Make the background (or first) layer */
layer = layer_new (gimage->ID, gimage->width, gimage->height,
type, "Background", OPAQUE, NORMAL);
{
Tag tag = tag_new ( precision, format, alpha);
gimage = gimage_new (vals->width, vals->height, tag);
/* Make the background (or first) layer */
layer = layer_new (gimage->ID, gimage->width, gimage->height,
tag, vals->storage, "Background", OPAQUE_OPACITY, NORMAL);
}
if (layer) {
/* add the new layer to the gimage */
gimage_disable_undo (gimage);
gimage_add_layer (gimage, layer, 0);
gimage_enable_undo (gimage);
drawable_fill (GIMP_DRAWABLE(layer), vals->fill_type);
if (vals->fill_type != NO_FILL)
drawable_fill (GIMP_DRAWABLE(layer), vals->fill_type);
gimage_clean_all (gimage);
@@ -231,7 +250,7 @@ file_new_delete_callback (GtkWidget *widget,
{
file_new_cancel_callback (widget, data);
return FALSE;
return TRUE;
}
@@ -279,7 +298,7 @@ file_new_cmd_callback (GtkWidget *widget,
{
last_width = default_width;
last_height = default_height;
last_type = default_type;
last_format = default_format;
new_dialog_run = 1;
}
@@ -292,25 +311,27 @@ file_new_cmd_callback (GtkWidget *widget,
gdisp = NULL;
vals = g_malloc (sizeof (NewImageValues));
vals->storage = last_storage;
vals->fill_type = last_fill_type;
if (gdisp)
{
vals->width = gdisp->gimage->width;
vals->height = gdisp->gimage->height;
vals->type = gimage_base_type (gdisp->gimage);
vals->format = tag_format (gimage_tag (gdisp->gimage));
}
else
{
vals->width = last_width;
vals->height = last_height;
vals->type = last_type;
vals->format = last_format;
}
if (vals->type == INDEXED)
vals->type = RGB; /* no indexed images */
if (vals->format == FORMAT_INDEXED)
vals->format = FORMAT_RGB; /* no indexed images */
vals->dlg = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (vals->dlg), "new_image", "Gimp");
gtk_window_set_title (GTK_WINDOW (vals->dlg), "New Image");
gtk_window_position (GTK_WINDOW (vals->dlg), GTK_WIN_POS_MOUSE);
@@ -394,22 +415,65 @@ file_new_cmd_callback (GtkWidget *widget,
button = gtk_radio_button_new_with_label (NULL, "RGB");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) RGB);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) FORMAT_RGB);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->type);
if (vals->type == RGB)
&vals->format);
if (vals->format == FORMAT_RGB)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "Grayscale");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) GRAY);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) FORMAT_GRAY);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->type);
if (vals->type == GRAY)
&vals->format);
if (vals->format == FORMAT_GRAY)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
frame = gtk_frame_new ("Storage Type");
gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
gtk_widget_show (frame);
radio_box = gtk_vbox_new (FALSE, 1);
gtk_container_border_width (GTK_CONTAINER (radio_box), 2);
gtk_container_add (GTK_CONTAINER (frame), radio_box);
gtk_widget_show (radio_box);
button = gtk_radio_button_new_with_label (NULL, "Tiled");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) STORAGE_TILED);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->storage);
if (vals->storage == STORAGE_TILED)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "Flat");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) STORAGE_FLAT);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->storage);
if (vals->storage == STORAGE_FLAT)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "Shared Memory");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) STORAGE_SHM);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->storage);
if (vals->storage == STORAGE_SHM)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
@@ -456,6 +520,28 @@ file_new_cmd_callback (GtkWidget *widget,
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "Foreground");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) FOREGROUND_FILL);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->fill_type);
if (vals->fill_type == FOREGROUND_FILL)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "No Fill");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) NO_FILL);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_new_toggle_callback,
&vals->fill_type);
if (vals->fill_type == NO_FILL)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_widget_show (button);
gtk_widget_show (vals->dlg);
}
@@ -512,8 +598,8 @@ file_save_as_cmd_callback (GtkWidget *widget,
Still no settings for default-brush, default-gradient,
default-palette, default-pattern, gamma-correction, color-cube,
marching-ants-speed, show-rulers, ruler-units. No widget for
confirm-on-close although a lot of stuff is there.
show-rulers, ruler-units. No widget for confirm-on-close although
a lot of stuff is there.
No UI feedback for the fact that some settings won't take effect
until the next Gimp restart.
@@ -562,22 +648,25 @@ file_prefs_ok_callback (GtkWidget *widget,
if (levels_of_undo < 0)
{
message_box("Error: Levels of undo must be zero or greater.",
NULL, NULL);
g_message ("Error: Levels of undo must be zero or greater.");
levels_of_undo = old_levels_of_undo;
return;
}
if (marching_speed < 50)
{
g_message ("Error: Marching speed must be 50 or greater.");
marching_speed = old_marching_speed;
return;
}
if (default_width < 1)
{
message_box("Error: Default width must be one or greater.",
NULL, NULL);
g_message ("Error: Default width must be one or greater.");
default_width = old_default_width;
return;
}
if (default_height < 1)
{
message_box("Error: Default height must be one or greater.",
NULL, NULL);
g_message ("Error: Default height must be one or greater.");
default_height = old_default_height;
return;
}
@@ -608,6 +697,7 @@ file_prefs_save_callback (GtkWidget *widget,
gchar *save_palette_path;
gchar *save_plug_in_path;
gchar *save_gradient_path;
int restart_notification = FALSE;
file_prefs_ok_callback (widget, dlg);
@@ -626,6 +716,8 @@ file_prefs_save_callback (GtkWidget *widget,
if (levels_of_undo != old_levels_of_undo)
update = g_list_append (update, "undo-levels");
if (marching_speed != old_marching_speed)
update = g_list_append (update, "marching-ants-speed");
if (allow_resize_windows != old_allow_resize_windows)
update = g_list_append (update, "allow-resize-windows");
if (auto_save != old_auto_save)
@@ -650,8 +742,10 @@ file_prefs_save_callback (GtkWidget *widget,
if (default_width != old_default_width ||
default_height != old_default_height)
update = g_list_append (update, "default-image-size");
if (default_type != old_default_type)
if (default_format != old_default_format)
update = g_list_append (update, "default-image-type");
if (default_precision != old_default_precision)
update = g_list_append (update, "default-image-precision");
if (preview_size != old_preview_size)
update = g_list_append (update, "preview-size");
if (transparency_type != old_transparency_type)
@@ -662,56 +756,67 @@ file_prefs_save_callback (GtkWidget *widget,
{
update = g_list_append (update, "stingy-memory-use");
stingy_memory_use = edit_stingy_memory_use;
restart_notification = TRUE;
}
if (edit_tile_cache_size != tile_cache_size)
{
update = g_list_append (update, "tile-cache-size");
tile_cache_size = edit_tile_cache_size;
restart_notification = TRUE;
}
if (edit_install_cmap != install_cmap)
if (edit_install_cmap != old_install_cmap)
{
update = g_list_append (update, "install-colormap");
install_cmap = edit_install_cmap;
restart_notification = TRUE;
}
if (edit_cycled_marching_ants != cycled_marching_ants)
{
update = g_list_append (update, "colormap-cycling");
cycled_marching_ants = edit_cycled_marching_ants;
restart_notification = TRUE;
}
if (file_prefs_strcmp (temp_path, edit_temp_path))
{
update = g_list_append (update, "temp-path");
temp_path = edit_temp_path;
restart_notification = TRUE;
}
if (file_prefs_strcmp (swap_path, edit_swap_path))
{
update = g_list_append (update, "swap-path");
swap_path = edit_swap_path;
restart_notification = TRUE;
}
if (file_prefs_strcmp (brush_path, edit_brush_path))
{
update = g_list_append (update, "brush-path");
brush_path = edit_brush_path;
restart_notification = TRUE;
}
if (file_prefs_strcmp (pattern_path, edit_pattern_path))
{
update = g_list_append (update, "pattern-path");
pattern_path = edit_pattern_path;
restart_notification = TRUE;
}
if (file_prefs_strcmp (palette_path, edit_palette_path))
{
update = g_list_append (update, "palette-path");
palette_path = edit_palette_path;
restart_notification = TRUE;
}
if (file_prefs_strcmp (plug_in_path, edit_plug_in_path))
{
update = g_list_append (update, "plug-in-path");
plug_in_path = edit_plug_in_path;
restart_notification = TRUE;
}
if (file_prefs_strcmp (gradient_path, edit_gradient_path))
{
update = g_list_append (update, "gradient-path");
gradient_path = edit_gradient_path;
restart_notification = TRUE;
}
save_gimprc (&update, &remove);
@@ -727,6 +832,9 @@ file_prefs_save_callback (GtkWidget *widget,
palette_path = save_palette_path;
plug_in_path = save_plug_in_path;
gradient_path = save_gradient_path;
if (restart_notification)
g_message ("You will need to restart GIMP for these changes to take effect.");
g_list_free (update);
g_list_free (remove);
@@ -740,7 +848,7 @@ file_prefs_delete_callback (GtkWidget *widget,
file_prefs_cancel_callback (widget, dlg);
/* the widget is already destroyed here no need to try again */
return FALSE;
return TRUE;
}
static void
@@ -751,6 +859,7 @@ file_prefs_cancel_callback (GtkWidget *widget,
prefs_dlg = NULL;
levels_of_undo = old_levels_of_undo;
marching_speed = old_marching_speed;
allow_resize_windows = old_allow_resize_windows;
auto_save = old_auto_save;
no_cursor_updating = old_no_cursor_updating;
@@ -759,7 +868,8 @@ file_prefs_cancel_callback (GtkWidget *widget,
confirm_on_close = old_confirm_on_close;
default_width = old_default_width;
default_height = old_default_height;
default_type = old_default_type;
default_format = old_default_format;
default_precision = old_default_precision;
if (preview_size != old_preview_size)
{
lc_dialog_rebuild (old_preview_size);
@@ -810,15 +920,19 @@ file_prefs_toggle_callback (GtkWidget *widget,
cubic_interpolation = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&confirm_on_close)
confirm_on_close = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&old_stingy_memory_use)
old_stingy_memory_use = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&old_install_cmap)
old_install_cmap = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&old_cycled_marching_ants)
old_cycled_marching_ants = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&default_type)
else if (data==&edit_stingy_memory_use)
edit_stingy_memory_use = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&edit_install_cmap)
edit_install_cmap = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&edit_cycled_marching_ants)
edit_cycled_marching_ants = GTK_TOGGLE_BUTTON (widget)->active;
else if (data==&default_format)
{
default_type = (long) gtk_object_get_user_data (GTK_OBJECT (widget));
default_format = (long) gtk_object_get_user_data (GTK_OBJECT (widget));
}
else if (data==&default_precision)
{
default_precision = (Precision) gtk_object_get_user_data (GTK_OBJECT (widget));
}
else if (GTK_TOGGLE_BUTTON (widget)->active)
{
@@ -960,6 +1074,7 @@ file_pref_cmd_callback (GtkWidget *widget,
old_transparency_type = transparency_type;
old_transparency_size = transparency_size;
old_levels_of_undo = levels_of_undo;
old_marching_speed = marching_speed;
old_allow_resize_windows = allow_resize_windows;
old_auto_save = auto_save;
old_preview_size = preview_size;
@@ -969,7 +1084,8 @@ file_pref_cmd_callback (GtkWidget *widget,
old_confirm_on_close = confirm_on_close;
old_default_width = default_width;
old_default_height = default_height;
old_default_type = default_type;
old_default_format = default_format;
old_default_precision = default_precision;
old_stingy_memory_use = edit_stingy_memory_use;
old_tile_cache_size = edit_tile_cache_size;
old_install_cmap = edit_install_cmap;
@@ -983,6 +1099,7 @@ file_pref_cmd_callback (GtkWidget *widget,
file_prefs_strset (&old_gradient_path, edit_gradient_path);
prefs_dlg = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (prefs_dlg), "preferences", "Gimp");
gtk_window_set_title (GTK_WINDOW (prefs_dlg), "Preferences");
/* handle the wm close signal */
@@ -1101,27 +1218,80 @@ file_pref_cmd_callback (GtkWidget *widget,
button = gtk_radio_button_new_with_label (NULL, "RGB");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) RGB);
if (default_type == RGB)
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) FORMAT_RGB);
if (last_format == FORMAT_RGB)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&default_type);
&default_format);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "Grayscale");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) GRAY);
if (last_type == GRAY)
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) FORMAT_GRAY);
if (last_format == FORMAT_GRAY)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&default_type);
&default_format);
gtk_widget_show (button);
hbox = gtk_hbox_new (FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
gtk_widget_show (hbox);
frame = gtk_frame_new ("Image precision");
gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
gtk_widget_show (frame);
radio_box = gtk_vbox_new (FALSE, 1);
gtk_container_border_width (GTK_CONTAINER (radio_box), 2);
gtk_container_add (GTK_CONTAINER (frame), radio_box);
gtk_widget_show (radio_box);
button = gtk_radio_button_new_with_label (NULL, "U8");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) PRECISION_U8);
if (default_precision == PRECISION_U8)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&default_precision);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "U16");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) PRECISION_U16);
if (default_precision == PRECISION_U16)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&default_precision);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "FLOAT");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) PRECISION_FLOAT);
if (default_precision == PRECISION_FLOAT)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&default_precision);
gtk_widget_show (button);
button = gtk_radio_button_new_with_label (group, "FLOAT16");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
gtk_box_pack_start (GTK_BOX (radio_box), button, TRUE, TRUE, 0);
gtk_object_set_user_data (GTK_OBJECT (button), (gpointer) PRECISION_FLOAT16);
if (default_precision == PRECISION_FLOAT16)
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&default_precision);
gtk_widget_show (button);
hbox = gtk_hbox_new (FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
gtk_widget_show (hbox);
label = gtk_label_new ("Preview size:");
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
@@ -1247,14 +1417,18 @@ file_pref_cmd_callback (GtkWidget *widget,
&allow_resize_windows);
gtk_widget_show (button);
button = gtk_check_button_new_with_label("Auto save");
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button),
/* Don't show the Auto-save button until we really
have auto-saving in the gimp.
button = gtk_check_button_new_with_label("Auto save");
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button),
auto_save);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&auto_save);
gtk_widget_show (button);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&auto_save);
gtk_widget_show (button);
*/
button = gtk_check_button_new_with_label("Disable cursor updating");
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (button),
@@ -1287,6 +1461,9 @@ file_pref_cmd_callback (GtkWidget *widget,
sprintf (buffer, "%d", marching_speed);
gtk_entry_set_text (GTK_ENTRY (entry), buffer);
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (entry), "changed",
(GtkSignalFunc) file_prefs_text_callback,
&marching_speed);
gtk_widget_show (entry);
label = gtk_label_new ("Interface");
@@ -1309,7 +1486,7 @@ file_pref_cmd_callback (GtkWidget *widget,
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&old_stingy_memory_use);
&edit_stingy_memory_use);
gtk_widget_show (button);
hbox = gtk_hbox_new (FALSE, 2);
@@ -1327,7 +1504,7 @@ file_pref_cmd_callback (GtkWidget *widget,
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (entry), "changed",
(GtkSignalFunc) file_prefs_text_callback,
&old_tile_cache_size);
&edit_tile_cache_size);
gtk_widget_show (entry);
button = gtk_check_button_new_with_label("Install colormap (8-bit only)");
@@ -1335,7 +1512,7 @@ file_pref_cmd_callback (GtkWidget *widget,
install_cmap);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&old_install_cmap);
&edit_install_cmap);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
@@ -1344,8 +1521,10 @@ file_pref_cmd_callback (GtkWidget *widget,
cycled_marching_ants);
gtk_signal_connect (GTK_OBJECT (button), "toggled",
(GtkSignalFunc) file_prefs_toggle_callback,
&old_cycled_marching_ants);
&edit_cycled_marching_ants);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
if (g_visual->depth != 8)
gtk_widget_set_sensitive (GTK_WIDGET(button), FALSE);
gtk_widget_show (button);
label = gtk_label_new ("Environment");
@@ -1635,7 +1814,7 @@ select_border_cmd_callback (GtkWidget *widget,
sprintf (initial, "%d", gimage_mask_border_radius);
query_string_box ("Border Selection", "Border selection by:", initial,
gimage_mask_border_callback, gdisp->gimage);
gimage_mask_border_callback, (gpointer) gdisp->gimage->ID);
}
void
@@ -1649,7 +1828,7 @@ select_feather_cmd_callback (GtkWidget *widget,
sprintf (initial, "%f", gimage_mask_feather_radius);
query_string_box ("Feather Selection", "Feather selection by:", initial,
gimage_mask_feather_callback, gdisp->gimage);
gimage_mask_feather_callback, (gpointer) gdisp->gimage->ID);
}
void
@@ -1663,7 +1842,7 @@ select_grow_cmd_callback (GtkWidget *widget,
sprintf (initial, "%d", gimage_mask_grow_pixels);
query_string_box ("Grow Selection", "Grow selection by:", initial,
gimage_mask_grow_callback, gdisp->gimage);
gimage_mask_grow_callback, (gpointer) gdisp->gimage->ID);
}
void
@@ -1677,7 +1856,7 @@ select_shrink_cmd_callback (GtkWidget *widget,
sprintf (initial, "%d", gimage_mask_shrink_pixels);
query_string_box ("Shrink Selection", "Shrink selection by:", initial,
gimage_mask_shrink_callback, gdisp->gimage);
gimage_mask_shrink_callback, (gpointer) gdisp->gimage->ID);
}
void
@@ -1689,6 +1868,10 @@ select_by_color_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) BY_COLOR_SELECT].toolbar_position]);
by_color_select_initialize ((void *) gdisp->gimage);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -1943,6 +2126,10 @@ image_posterize_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) POSTERIZE].toolbar_position]);
posterize_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -1954,6 +2141,10 @@ image_threshold_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) THRESHOLD].toolbar_position]);
threshold_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -1965,6 +2156,11 @@ image_color_balance_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) COLOR_BALANCE].toolbar_position]);
color_balance_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -1976,6 +2172,10 @@ image_brightness_contrast_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) BRIGHTNESS_CONTRAST].toolbar_position]);
brightness_contrast_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -1987,6 +2187,10 @@ image_hue_saturation_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) HUE_SATURATION].toolbar_position]);
hue_saturation_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -1998,6 +2202,10 @@ image_curves_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) CURVES].toolbar_position]);
curves_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -2009,6 +2217,10 @@ image_levels_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) LEVELS].toolbar_position]);
levels_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -2094,6 +2306,7 @@ image_resize_cmd_callback (GtkWidget *widget,
/* the dialog */
image_resize->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (image_resize->shell), "image_resize", "Gimp");
gtk_window_set_title (GTK_WINDOW (image_resize->shell), "Image Resize");
gtk_window_set_policy (GTK_WINDOW (image_resize->shell), FALSE, FALSE, TRUE);
gtk_window_position (GTK_WINDOW (image_resize->shell), GTK_WIN_POS_MOUSE);
@@ -2140,6 +2353,7 @@ image_scale_cmd_callback (GtkWidget *widget,
/* the dialog */
image_scale->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (image_scale->shell), "image_scale", "Gimp");
gtk_window_set_title (GTK_WINDOW (image_scale->shell), "Image Scale");
gtk_window_set_policy (GTK_WINDOW (image_scale->shell), FALSE, FALSE, TRUE);
gtk_window_position (GTK_WINDOW (image_scale->shell), GTK_WIN_POS_MOUSE);
@@ -2173,6 +2387,10 @@ image_histogram_cmd_callback (GtkWidget *widget,
gdisp = gdisplay_active ();
gtk_widget_activate (tool_widgets[tool_info[(int) HISTOGRAM].toolbar_position]);
histogram_tool_initialize ((void *) gdisp);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -2259,12 +2477,44 @@ layers_mask_select_cmd_callback (GtkWidget *widget,
gdisplays_flush ();
}
void
layers_add_alpha_channel_cmd_callback (GtkWidget *widget,
gpointer client_data)
{
GDisplay * gdisp;
gdisp = gdisplay_active ();
layer_add_alpha ( gdisp->gimage->active_layer);
gdisplays_flush ();
}
void
tools_default_colors_cmd_callback (GtkWidget *widget,
gpointer client_data)
{
palette_set_default_colors ();
}
void
tools_swap_colors_cmd_callback (GtkWidget *widget,
gpointer client_data)
{
palette_swap_colors ();
}
void
tools_select_cmd_callback (GtkWidget *widget,
gpointer client_data)
{
GDisplay * gdisp;
/* Activate the approriate widget */
gtk_widget_activate (tool_widgets[tool_info[(long) client_data].toolbar_position]);
gdisp = gdisplay_active ();
active_tool->drawable = gimage_active_drawable (gdisp->gimage);
}
void
@@ -2377,7 +2627,7 @@ image_resize_callback (GtkWidget *w,
}
else
{
message_box("Resize Error: Both width and height must be greater than zero.", NULL, NULL);
g_message ("Resize Error: Both width and height must be greater than zero.");
return;
}
}
@@ -2407,7 +2657,7 @@ image_scale_callback (GtkWidget *w,
}
else
{
message_box("Scale Error: Both width and height must be greater than zero.", NULL, NULL);
g_message ("Scale Error: Both width and height must be greater than zero.");
return;
}
}
@@ -2424,7 +2674,7 @@ image_delete_callback (GtkWidget *w,
{
image_cancel_callback (w, client_data);
return FALSE;
return TRUE;
}
@@ -2449,7 +2699,9 @@ gimage_mask_feather_callback (GtkWidget *w,
GImage *gimage;
double feather_radius;
gimage = (GImage *) client_data;
if (!(gimage = gimage_get_ID ((int)client_data)))
return;
feather_radius = atof (call_data);
gimage_mask_feather (gimage, feather_radius);
@@ -2465,7 +2717,9 @@ gimage_mask_border_callback (GtkWidget *w,
GImage *gimage;
int border_radius;
gimage = (GImage *) client_data;
if (!(gimage = gimage_get_ID ((int)client_data)))
return;
border_radius = atoi (call_data);
gimage_mask_border (gimage, border_radius);
@@ -2481,7 +2735,9 @@ gimage_mask_grow_callback (GtkWidget *w,
GImage *gimage;
int grow_pixels;
gimage = (GImage *) client_data;
if (!(gimage = gimage_get_ID ((int)client_data)))
return;
grow_pixels = atoi (call_data);
gimage_mask_grow (gimage, grow_pixels);
@@ -2497,9 +2753,17 @@ gimage_mask_shrink_callback (GtkWidget *w,
GImage *gimage;
int shrink_pixels;
gimage = (GImage *) client_data;
if (!(gimage = gimage_get_ID ((int)client_data)))
return;
shrink_pixels = atoi (call_data);
gimage_mask_shrink (gimage, shrink_pixels);
gdisplays_flush ();
}

View File

@@ -77,6 +77,9 @@ void layers_merge_cmd_callback (GtkWidget *, gpointer);
void layers_flatten_cmd_callback (GtkWidget *, gpointer);
void layers_alpha_select_cmd_callback (GtkWidget *, gpointer);
void layers_mask_select_cmd_callback (GtkWidget *, gpointer);
void layers_add_alpha_channel_cmd_callback (GtkWidget *, gpointer);
void tools_default_colors_cmd_callback (GtkWidget *, gpointer);
void tools_swap_colors_cmd_callback (GtkWidget *, gpointer);
void tools_select_cmd_callback (GtkWidget *, gpointer);
void filters_repeat_cmd_callback (GtkWidget *, gpointer);
void dialogs_brushes_cmd_callback (GtkWidget *, gpointer);

View File

@@ -13,24 +13,27 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* TODO for Convert:
*
* Make GRAYSCALE->INDEXED sane again (done?)
*
* Use palette of another open INDEXED image
*
* Post-1.0 TODO:
*
* Different dither types
*
* Alpha dithering
*/
/*
* 98/04/13 - avoid a division by zero when converting an empty gray-scale
* image (who would like to do such a thing anyway??) [Sven ]
*
* 98/03/23 - fixed a longstanding fencepost - hopefully the *right*
* way, *again*. (anyone ELSE want a go? okay, just kidding... :))
* [Adam]
*
* 97/11/14 - added a proper pdb interface and support for dithering
* to custom palettes (based on a patch by Eric Hernes) [Yosh]
*
@@ -54,8 +57,10 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "appenv.h"
#include "actionarea.h"
#include "canvas.h"
#include "convert.h"
#include "drawable.h"
#include "floating_sel.h"
@@ -64,24 +69,143 @@
#include "indexed_palette.h"
#include "interface.h"
#include "undo.h"
#include "paint_funcs_area.h"
#include "palette.h"
#include "pixelarea.h"
#include "layer_pvt.h" /* ick. */
#include "drawable_pvt.h" /* ick ick. */
#include "tile_manager_pvt.h" /* ick ick ick. */
#include "layer_pvt.h"
static Argument * convert_rgb_invoker (Argument *);
static Argument * convert_grayscale_invoker (Argument *);
static Argument * convert_indexed_invoker (Argument *);
static Argument * convert_indexed_palette_invoker (Argument *);
static void convert_image (GImage *, Format, int, int, int);
void
convert_to_rgb (void *gimage_ptr)
{
GImage *gimage;
gimage = (GImage *) gimage_ptr;
convert_image (gimage, FORMAT_RGB, 0, 0, 0);
gdisplays_flush ();
}
void
convert_to_grayscale (void *gimage_ptr)
{
GImage *gimage;
gimage = (GImage *) gimage_ptr;
convert_image (gimage, FORMAT_GRAY, 0, 0, 0);
gdisplays_flush ();
}
void
convert_to_indexed (void *gimage_ptr)
{
g_message ("indexed image support has been dropped for the moment");
return;
}
static void
convert_image (GImage *gimage,
Format new_format,
int num_cols, /* used only for new_type == INDEXED */
int dither, /* used only for new_type == INDEXED */
int palette_type) /* used only for new_type == INDEXED */
{
GSList * list;
Layer * floating_layer;
undo_push_group_start (gimage, GIMAGE_MOD_UNDO);
/* Relax the floating selection */
floating_layer = gimage_floating_sel (gimage);
if (floating_layer)
floating_sel_relax (floating_layer, TRUE);
/* Push the image size to the stack */
undo_push_gimage_mod (gimage);
/* Set the new gimage tag */
gimage->tag = tag_set_format (gimage->tag, new_format);
/* Convert all layers */
for (list = gimage->layers;
list;
list = g_slist_next (list))
{
PixelArea old, new;
/* get the original layer */
Layer * layer = (Layer *) list->data;
/* get the original image buffer */
Canvas * old_tiles = drawable_data (GIMP_DRAWABLE (layer));
/* make a new image buffer */
Canvas * new_tiles = canvas_new (tag_set_format (canvas_tag (old_tiles),
new_format),
canvas_width (old_tiles),
canvas_height (old_tiles),
STORAGE_TILED);
/* convert the image data */
pixelarea_init (&old, old_tiles,
0, 0,
0, 0,
FALSE);
pixelarea_init (&new, new_tiles,
0, 0,
0, 0,
TRUE);
copy_area (&old, &new);
/* Push the layer on the undo stack */
undo_push_layer_mod (gimage, layer);
/* save the converted layer */
GIMP_DRAWABLE(layer)->tiles = new_tiles;
}
/* Make sure the projection is up to date */
gimage_projection_realloc (gimage);
/* Rigor the floating selection */
if (floating_layer)
floating_sel_rigor (floating_layer, TRUE);
undo_push_group_end (gimage);
/* shrink wrap and update all views */
layer_invalidate_previews (gimage->ID);
gimage_invalidate_preview (gimage);
gdisplays_update_title (gimage->ID);
gdisplays_update_full (gimage->ID);
}
#define MAXNUMCOLORS 256
#define NODITHER 0
#define FSDITHER 1
#define NODESTRUCTDITHER 2
/* adam's extra palette stuff */
#define MAKE_PALETTE 0
#define REUSE_PALETTE 1
#define WEB_PALETTE 2
#define MONO_PALETTE 3
#define CUSTOM_PALETTE 4
static PaletteEntriesP theCustomPalette = NULL;
#if 0
#define NODITHER 0
#define FSDITHER 1
#define NODESTRUCTDITHER 2
#define PRECISION_R 6
#define PRECISION_G 6
@@ -194,6 +318,7 @@ typedef struct
GtkWidget * shell;
void * gimage_ptr;
int gimage_ID;
int dither;
int num_cols;
int palette;
@@ -204,10 +329,6 @@ typedef struct
int reusepal_flag;
} IndexedDialog;
static Argument * convert_rgb_invoker (Argument *);
static Argument * convert_grayscale_invoker (Argument *);
static Argument * convert_indexed_invoker (Argument *);
static Argument * convert_indexed_palette_invoker (Argument *);
static void indexed_ok_callback (GtkWidget *, gpointer);
static void indexed_cancel_callback (GtkWidget *, gpointer);
@@ -216,9 +337,6 @@ static void indexed_num_cols_update (GtkWidget *, gpointer);
static void indexed_radio_update (GtkWidget *, gpointer);
static void indexed_dither_update (GtkWidget *, gpointer);
static void convert_image (GImage *, int, int, int, int);
static void rgb_converter (Layer *, TileManager *, int);
static void grayscale_converter (Layer *, TileManager *, int);
static void zero_histogram_gray (Histogram);
static void zero_histogram_rgb (Histogram);
@@ -233,27 +351,6 @@ static gboolean needs_quantize;
static GtkWidget *build_palette_menu(int *default_palette);
static void palette_entries_callback(GtkWidget *w, gpointer client_data);
static PaletteEntriesP theCustomPalette = NULL;
void
convert_to_rgb (void *gimage_ptr)
{
GImage *gimage;
gimage = (GImage *) gimage_ptr;
convert_image (gimage, RGB, 0, 0, 0);
gdisplays_flush ();
}
void
convert_to_grayscale (void *gimage_ptr)
{
GImage *gimage;
gimage = (GImage *) gimage_ptr;
convert_image (gimage, GRAY, 0, 0, 0);
gdisplays_flush ();
}
/* the action area structure */
static ActionAreaItem action_items[] =
@@ -262,6 +359,7 @@ static ActionAreaItem action_items[] =
{ "Cancel", indexed_cancel_callback, NULL, NULL }
};
void
convert_to_indexed (void *gimage_ptr)
{
@@ -279,6 +377,7 @@ convert_to_indexed (void *gimage_ptr)
gimage = (GImage *) gimage_ptr;
dialog = (IndexedDialog *) g_malloc (sizeof (IndexedDialog));
dialog->gimage_ptr = gimage_ptr;
dialog->gimage_ID = gimage->ID;
dialog->num_cols = 256;
dialog->dither = TRUE;
@@ -297,8 +396,7 @@ convert_to_indexed (void *gimage_ptr)
dialog->num_cols = 255;
if (!shown_message_already)
{
message_box ("Note: You are attempting to convert an image\nwith alpha/layers. It is recommended that you quantize\nto no more than 255 colors if you wish to make\na transparent or animated GIF from it.\n\nYou won't get this message again\nuntil the next time you run GIMP.\nHave a nice day!",
NULL, NULL);
g_message ("Note: You are attempting to convert an image\nwith alpha/layers. It is recommended that you quantize\nto no more than 255 colors if you wish to make\na transparent or animated GIF from it.\n\nYou won't get this message again\nuntil the next time you run GIMP.\nHave a nice day!");
shown_message_already = True;
}
}
@@ -308,6 +406,7 @@ convert_to_indexed (void *gimage_ptr)
dialog->monopal_flag = FALSE;
dialog->reusepal_flag = FALSE;
dialog->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (dialog->shell), "indexed_color_conversion", "Gimp");
gtk_window_set_title (GTK_WINDOW (dialog->shell), "Indexed Color Conversion");
gtk_signal_connect (GTK_OBJECT (dialog->shell), "delete_event",
GTK_SIGNAL_FUNC (indexed_delete_callback),
@@ -363,7 +462,7 @@ convert_to_indexed (void *gimage_ptr)
gtk_widget_show (text);
gtk_widget_show (hbox);
if (gimage->base_type == RGB)
if (gimage_format (gimage) == FORMAT_RGB)
{
GtkWidget *menu;
GtkWidget *palette_option_menu;
@@ -458,14 +557,14 @@ static GtkWidget *
build_palette_menu(int *default_palette){
GtkWidget *menu;
GtkWidget *menu_item;
link_ptr list;
GSList *list;
PaletteEntriesP entries;
int i;
if(!palette_entries_list) {
/* fprintf(stderr, "no palette_entries_list, building...\n");*/
palette_init_palettes();
palette_init_palettes(FALSE);
}
list = palette_entries_list;
@@ -477,17 +576,21 @@ build_palette_menu(int *default_palette){
for(i=0,list = palette_entries_list,*default_palette=-1;
list;
i++,list = next_item (list))
i++,list = g_slist_next (list))
{
entries = (PaletteEntriesP) list->data;
/* fprintf(stderr, "(palette %s)\n", entries->filename);*/
menu_item = gtk_menu_item_new_with_label (entries->name);
gtk_signal_connect( GTK_OBJECT(menu_item), "activate",
(GtkSignalFunc) palette_entries_callback,
(gpointer)entries);
gtk_container_add(GTK_CONTAINER(menu), menu_item);
gtk_widget_show(menu_item);
if (theCustomPalette == entries) *default_palette = i;
/* We can't dither to > 256 colors */
if (entries->n_colors <= 256) {
menu_item = gtk_menu_item_new_with_label (entries->name);
gtk_signal_connect( GTK_OBJECT(menu_item), "activate",
(GtkSignalFunc) palette_entries_callback,
(gpointer)entries);
gtk_container_add(GTK_CONTAINER(menu), menu_item);
gtk_widget_show(menu_item);
if (theCustomPalette == entries) *default_palette = i;
}
}
/* default to first one */
@@ -523,11 +626,16 @@ indexed_ok_callback (GtkWidget *widget,
else
palette_type = REUSE_PALETTE;
/* Convert the image to indexed color */
convert_image ((GImage *) dialog->gimage_ptr, INDEXED, dialog->num_cols, dialog->dither, palette_type);
gdisplays_flush ();
if (gimage_get_ID (dialog->gimage_ID))
{
convert_image ((GImage *) dialog->gimage_ptr, INDEXED, dialog->num_cols,
dialog->dither, palette_type);
gdisplays_flush ();
}
gtk_widget_destroy (dialog->shell);
g_free (dialog);
dialog = NULL;
}
static gint
@@ -537,7 +645,7 @@ indexed_delete_callback (GtkWidget *w,
{
indexed_cancel_callback (w, client_data);
return FALSE;
return TRUE;
}
static void
@@ -549,6 +657,7 @@ indexed_cancel_callback (GtkWidget *widget,
dialog = (IndexedDialog *) client_data;
gtk_widget_destroy (dialog->shell);
g_free (dialog);
dialog = NULL;
}
static void
@@ -588,350 +697,6 @@ indexed_dither_update (GtkWidget *w,
dialog->dither = FALSE;
}
static void
convert_image (GImage *gimage,
int new_type,
int num_cols, /* used only for new_type == INDEXED */
int dither, /* used only for new_type == INDEXED */
int palette_type) /* used only for new_type == INDEXED */
{
QuantizeObj *quantobj;
Layer *layer;
Layer *floating_layer;
int old_type;
link_ptr list;
int new_layer_type;
int new_layer_bytes;
int has_alpha;
TileManager *new_tiles;
quantobj = NULL;
new_layer_type = RGBA_GIMAGE;
new_layer_bytes = 4;
/* Get the floating layer if one exists */
floating_layer = gimage_floating_sel (gimage);
undo_push_group_start (gimage, GIMAGE_MOD_UNDO);
/* Relax the floating selection */
if (floating_layer)
floating_sel_relax (floating_layer, TRUE);
/* Push the image size to the stack */
undo_push_gimage_mod (gimage);
/* Set the new base type */
old_type = gimage->base_type;
gimage->base_type = new_type;
/* Convert to indexed? Build histogram if necessary. */
if (new_type == INDEXED)
{
int i, j;
/* don't dither if the input is grayscale and we are simply mapping every color */
if (old_type == GRAY && num_cols == 256 && palette_type == MAKE_PALETTE)
dither = FALSE;
quantobj = initialize_median_cut (old_type, num_cols, dither ? FSDITHER : NODITHER, palette_type);
if (palette_type == MAKE_PALETTE)
{
if (old_type == GRAY)
zero_histogram_gray (quantobj->histogram);
else
zero_histogram_rgb (quantobj->histogram);
/* To begin, assume that there are fewer colours in
* the image than the user actually asked for. In that
* case, we don't need to quantize or dither.
*/
needs_quantize = FALSE;
num_found_cols = 0;
/* Build the histogram */
list = gimage->layers;
while (list)
{
layer = (Layer *) list->data;
list = next_item (list);
if (old_type == GRAY)
generate_histogram_gray (quantobj->histogram, layer);
else
generate_histogram_rgb (quantobj->histogram, layer, num_cols);
/*
* Note: generate_histogram_rgb may set needs_quantize if
* the image contains more colours than the limit specified
* by the user.
*/
}
}
if (
(old_type == RGB) &&
(!needs_quantize) &&
(palette_type == MAKE_PALETTE)
)
{
/* If this is an RGB image, and the user wanted a custom-built
* generated palette, and this image has no more colours than
* the user asked for, we don't need the first pass (quantization).
*
* There's also no point in dithering, since there's no error to
* spread. So we destroy the old quantobj and make a new one
* with the remapping function set to a special LUT-based
* no-dither remapper.
*/
quantobj->delete_func (quantobj);
quantobj = initialize_median_cut (old_type, num_cols,
NODESTRUCTDITHER, palette_type);
/* We can skip the first pass (palette creation) */
quantobj->actual_number_of_colors = num_found_cols;
for (i = 0; i < num_found_cols; i++)
{
quantobj->cmap[i].red = found_cols[i][0];
quantobj->cmap[i].green = found_cols[i][1];
quantobj->cmap[i].blue = found_cols[i][2];
}
}
else
{
(* quantobj->first_pass) (quantobj);
}
if (gimage->cmap)
g_free (gimage->cmap);
gimage->cmap = (unsigned char *) g_malloc (COLORMAP_SIZE);
gimage->num_cols = quantobj->actual_number_of_colors;
for (i = 0, j = 0; i < quantobj->actual_number_of_colors; i++)
{
gimage->cmap[j++] = quantobj->cmap[i].red;
gimage->cmap[j++] = quantobj->cmap[i].green;
gimage->cmap[j++] = quantobj->cmap[i].blue;
}
}
/* Convert all layers */
list = gimage->layers;
while (list)
{
layer = (Layer *) list->data;
list = next_item (list);
has_alpha = layer_has_alpha (layer);
switch (new_type)
{
case RGB:
new_layer_type = (has_alpha) ? RGBA_GIMAGE : RGB_GIMAGE;
new_layer_bytes = (has_alpha) ? 4 : 3;
break;
case GRAY:
new_layer_type = (has_alpha) ? GRAYA_GIMAGE : GRAY_GIMAGE;
new_layer_bytes = (has_alpha) ? 2 : 1;
break;
case INDEXED:
new_layer_type = (has_alpha) ? INDEXEDA_GIMAGE : INDEXED_GIMAGE;
new_layer_bytes = (has_alpha) ? 2 : 1;
break;
default:
break;
}
new_tiles = tile_manager_new (GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, new_layer_bytes);
switch (new_type)
{
case RGB:
rgb_converter (layer, new_tiles, old_type);
break;
case GRAY:
grayscale_converter (layer, new_tiles, old_type);
break;
case INDEXED:
(* quantobj->second_pass) (quantobj, layer, new_tiles);
break;
default:
break;
}
/* Push the layer on the undo stack */
undo_push_layer_mod (gimage, layer);
GIMP_DRAWABLE(layer)->tiles = new_tiles;
GIMP_DRAWABLE(layer)->bytes = new_layer_bytes;
GIMP_DRAWABLE(layer)->type = new_layer_type;
GIMP_DRAWABLE(layer)->has_alpha = TYPE_HAS_ALPHA(new_layer_type);
}
/* Delete the quantizer object, if there is one */
if (quantobj)
quantobj->delete_func (quantobj);
/* Make sure the projection is up to date */
gimage_projection_realloc (gimage);
/* Rigor the floating selection */
if (floating_layer)
floating_sel_rigor (floating_layer, TRUE);
undo_push_group_end (gimage);
/* shrink wrap and update all views */
layer_invalidate_previews (gimage->ID);
gimage_invalidate_preview (gimage);
gdisplays_update_title (gimage->ID);
gdisplays_update_full (gimage->ID);
indexed_palette_update_image_list ();
}
static void
rgb_converter (Layer *layer,
TileManager *new_tiles,
int old_type)
{
PixelRegion srcPR, destPR;
int row, col;
int offset;
int has_alpha;
unsigned char *src, *s;
unsigned char *dest, *d;
unsigned char *cmap;
void *pr;
has_alpha = layer_has_alpha (layer);
pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE);
pixel_region_init (&destPR, new_tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
{
src = srcPR.data;
dest = destPR.data;
switch (old_type)
{
case GRAY:
for (row = 0; row < srcPR.h; row++)
{
s = src;
d = dest;
for (col = 0; col < srcPR.w; col++)
{
d[RED_PIX] = *s;
d[GREEN_PIX] = *s;
d[BLUE_PIX] = *s;
d += 3;
s++;
if (has_alpha)
*d++ = *s++;
}
src += srcPR.rowstride;
dest += destPR.rowstride;
}
break;
case INDEXED:
cmap = drawable_cmap (GIMP_DRAWABLE(layer));
for (row = 0; row < srcPR.h; row++)
{
s = src;
d = dest;
for (col = 0; col < srcPR.w; col++)
{
offset = *s++ * 3;
d[RED_PIX] = cmap[offset + 0];
d[GREEN_PIX] = cmap[offset + 1];
d[BLUE_PIX] = cmap[offset + 2];
d += 3;
if (has_alpha)
*d++ = *s++;
}
src += srcPR.rowstride;
dest += destPR.rowstride;
}
break;
default:
break;
}
}
}
static void
grayscale_converter (Layer *layer,
TileManager *new_tiles,
int old_type)
{
PixelRegion srcPR, destPR;
int row, col;
int offset, val;
int has_alpha;
unsigned char *src, *s;
unsigned char *dest, *d;
unsigned char *cmap;
void *pr;
has_alpha = layer_has_alpha (layer);
pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE);
pixel_region_init (&destPR, new_tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, TRUE);
for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr))
{
src = srcPR.data;
dest = destPR.data;
switch (old_type)
{
case RGB:
for (row = 0; row < srcPR.h; row++)
{
s = src;
d = dest;
for (col = 0; col < srcPR.w; col++)
{
val = INTENSITY (s[RED_PIX], s[GREEN_PIX], s[BLUE_PIX]);
*d++ = (unsigned char) val;
s += 3;
if (has_alpha)
*d++ = *s++;
}
src += srcPR.rowstride;
dest += destPR.rowstride;
}
break;
case INDEXED:
cmap = drawable_cmap (GIMP_DRAWABLE(layer));
for (row = 0; row < srcPR.h; row++)
{
s = src;
d = dest;
for (col = 0; col < srcPR.w; col++)
{
offset = *s++ * 3;
val = INTENSITY (cmap[offset+0], cmap[offset+1], cmap[offset+2]);
*d++ = (unsigned char) val;
if (has_alpha)
*d++ = *s++;
}
src += srcPR.rowstride;
dest += destPR.rowstride;
}
break;
default:
break;
}
}
}
/*
* Indexed color conversion machinery
@@ -1002,9 +767,12 @@ generate_histogram_rgb (Histogram histogram,
has_alpha = (gboolean) layer_has_alpha(layer);
g_print ("col_limit = %d, nfc = %d\n", col_limit, num_found_cols);
/* g_print ("col_limit = %d, nfc = %d\n", col_limit, num_found_cols);*/
pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE);
pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0,
GIMP_DRAWABLE(layer)->width,
GIMP_DRAWABLE(layer)->height,
FALSE);
for (pr = pixel_regions_register (1, &srcPR);
pr != NULL;
pr = pixel_regions_process (pr))
@@ -1057,12 +825,6 @@ generate_histogram_rgb (Histogram histogram,
* existing colours
*/
/* Remember the new colour we just found.
*/
found_cols[num_found_cols][0] = data[RED_PIX];
found_cols[num_found_cols][1] = data[GREEN_PIX];
found_cols[num_found_cols][2] = data[BLUE_PIX];
num_found_cols++;
if (num_found_cols > col_limit)
@@ -1073,9 +835,17 @@ generate_histogram_rgb (Histogram histogram,
* quantizing at a later stage.
*/
needs_quantize = TRUE;
g_print ("max colours exceeded - needs quantize.\n");
/* g_print ("\nmax colours exceeded - needs quantize.\n");*/
goto already_found;
}
else
{
/* Remember the new colour we just found.
*/
found_cols[num_found_cols-1][0] = data[RED_PIX];
found_cols[num_found_cols-1][1] = data[GREEN_PIX];
found_cols[num_found_cols-1][2] = data[BLUE_PIX];
}
}
}
already_found:
@@ -1084,7 +854,7 @@ generate_histogram_rgb (Histogram histogram,
}
}
g_print ("O: col_limit = %d, nfc = %d\n", col_limit, num_found_cols);
/* g_print ("O: col_limit = %d, nfc = %d\n", col_limit, num_found_cols);*/
}
@@ -1467,9 +1237,21 @@ compute_color_gray (QuantizeObj *quantobj,
}
}
quantobj->cmap[icolor].red = (gtotal + (total >> 1)) / total;
quantobj->cmap[icolor].green = quantobj->cmap[icolor].red;
quantobj->cmap[icolor].blue = quantobj->cmap[icolor].red;
if (total != 0)
{
quantobj->cmap[icolor].red = (gtotal + (total >> 1)) / total;
quantobj->cmap[icolor].green = quantobj->cmap[icolor].red;
quantobj->cmap[icolor].blue = quantobj->cmap[icolor].red;
}
else /* The only situation where total==0 is if the image was null or
* all-transparent. In that case we just put a dummy value in
* the colourmap.
*/
{
quantobj->cmap[icolor].red =
quantobj->cmap[icolor].green =
quantobj->cmap[icolor].blue = 0;
}
}
static void
@@ -2023,7 +1805,7 @@ static void
custompal_pass1 (QuantizeObj *quantobj)
{
int i;
link_ptr list;
GSList *list;
PaletteEntryP entry;
/* fprintf(stderr, "custompal_pass1: using (theCustomPalette %s) from (file %s)\n",
@@ -2031,7 +1813,7 @@ custompal_pass1 (QuantizeObj *quantobj)
for (i=0,list=theCustomPalette->colors;
list;
i++,list=next_item(list))
i++,list=g_slist_next(list))
{
entry=(PaletteEntryP)list->data;
quantobj->cmap[i].red = entry->color[0];
@@ -2329,7 +2111,7 @@ median_cut_pass2_fs_dither_gray (QuantizeObj *quantobj,
has_alpha = layer_has_alpha (layer);
pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE);
pixel_region_init (&destPR, new_tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, TRUE);
src_bytes = GIMP_DRAWABLE(layer)->bytes;
src_bytes = drawable_bytes (GIMP_DRAWABLE(layer));
dest_bytes = new_tiles->levels[0].bpp;
width = GIMP_DRAWABLE(layer)->width;
height = GIMP_DRAWABLE(layer)->height;
@@ -2485,7 +2267,7 @@ median_cut_pass2_fs_dither_rgb (QuantizeObj *quantobj,
has_alpha = layer_has_alpha (layer);
pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, FALSE);
pixel_region_init (&destPR, new_tiles, 0, 0, GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height, TRUE);
src_bytes = GIMP_DRAWABLE(layer)->bytes;
src_bytes = drawable_bytes (GIMP_DRAWABLE(layer));
dest_bytes = new_tiles->levels[0].bpp;
width = GIMP_DRAWABLE(layer)->width;
height = GIMP_DRAWABLE(layer)->height;
@@ -2764,6 +2546,8 @@ initialize_median_cut (int type,
return quantobj;
}
#endif
/*
* Procedure database functions and data structures
@@ -2817,10 +2601,10 @@ convert_rgb_invoker (Argument *args)
}
/* make sure the drawable is not RGB color */
if (success)
success = (gimage_base_type (gimage) != RGB);
success = (tag_format (gimage_tag (gimage)) != FORMAT_RGB);
if (success)
convert_image ((void *) gimage, RGB, 0, 0, 0);
convert_image ((void *) gimage, FORMAT_RGB, 0, 0, 0);
return procedural_db_return_args (&convert_rgb_proc, success);
}
@@ -2875,10 +2659,10 @@ convert_grayscale_invoker (Argument *args)
}
/* make sure the drawable is not GRAYSCALE color */
if (success)
success = (gimage_base_type (gimage) != GRAY);
success = (tag_format (gimage_tag (gimage)) != FORMAT_GRAY);
if (success)
convert_image ((void *) gimage, GRAY, 0, 0, 0);
convert_image ((void *) gimage, FORMAT_GRAY, 0, 0, 0);
return procedural_db_return_args (&convert_grayscale_proc, success);
}
@@ -2943,7 +2727,7 @@ convert_indexed_invoker (Argument *args)
}
/* make sure the drawable is not INDEXED color */
if (success)
success = (gimage_base_type (gimage) != INDEXED);
success = (tag_format (gimage_tag (gimage)) != FORMAT_INDEXED);
if (success)
dither = (args[1].value.pdb_int) ? TRUE : FALSE;
if (success)
@@ -2954,7 +2738,7 @@ convert_indexed_invoker (Argument *args)
}
if (success)
convert_image ((void *) gimage, INDEXED, num_cols, dither, 0);
convert_image ((void *) gimage, FORMAT_INDEXED, num_cols, dither, 0);
return procedural_db_return_args (&convert_indexed_proc, success);
}
@@ -3029,13 +2813,13 @@ convert_indexed_palette_invoker (Argument *args)
}
/* make sure the drawable is not INDEXED color */
if (success)
success = (gimage_base_type (gimage) != INDEXED);
success = (gimage_format (gimage) != FORMAT_INDEXED);
if (success)
dither = (args[1].value.pdb_int) ? TRUE : FALSE;
if (success)
{
PaletteEntriesP entries, the_palette = NULL;
link_ptr list;
GSList *list;
palette_type = args[2].value.pdb_int;
switch(palette_type) {
@@ -3053,10 +2837,10 @@ convert_indexed_palette_invoker (Argument *args)
case CUSTOM_PALETTE:
palette_name = args[4].value.pdb_pointer;
/* fprintf(stderr, "looking for palette `%s'\n", palette_name); */
if (!palette_entries_list) palette_init_palettes();
if (!palette_entries_list) palette_init_palettes(FALSE);
for(list = palette_entries_list;
list;
list = next_item(list)) {
list = g_slist_next(list)) {
entries = (PaletteEntriesP) list->data;
if (strcmp(palette_name, entries->name)==0) {
/* fprintf(stderr, "found it!\n"); */
@@ -3077,5 +2861,5 @@ convert_indexed_palette_invoker (Argument *args)
}
if (success)
convert_image ((void *) gimage, INDEXED, num_cols, dither, palette_type);
return procedural_db_return_args (&convert_indexed_proc, success);
return procedural_db_return_args (&convert_indexed_palette_proc, success);
}

View File

@@ -13,7 +13,7 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CONVERT_H__
#define __CONVERT_H__

View File

@@ -13,18 +13,21 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include "appenv.h"
#include "brushes.h"
#include "canvas.h"
#include "drawable.h"
#include "errors.h"
#include "convolve.h"
#include "gdisplay.h"
#include "paint_funcs.h"
#include "paint_core.h"
#include "paint_funcs_area.h"
#include "paint_core_16.h"
#include "palette.h"
#include "pixelarea.h"
#include "selection.h"
#include "tools.h"
@@ -37,10 +40,9 @@ typedef enum
/* forward function declarations */
static void calculate_matrix (ConvolveType, double);
static void integer_matrix (float *, int *, int);
static void copy_matrix (float *, float *, int);
static int sum_matrix (int *, int);
static gfloat sum_matrix (gfloat *, int);
static void *convolve_non_gui_paint_func (PaintCore *, GimpDrawable *, int);
static void convolve_motion (PaintCore *, GimpDrawable *);
static Argument * convolve_invoker (Argument *);
@@ -58,9 +60,9 @@ struct _ConvolveOptions
};
/* local variables */
static int matrix [25];
static gfloat matrix [25];
static int matrix_size;
static int matrix_divisor;
static gfloat matrix_divisor;
static ConvolveOptions *convolve_options = NULL;
static float custom_matrix [25] =
@@ -184,7 +186,7 @@ create_convolve_options (void)
return options;
}
void *
static void *
convolve_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,
int state)
@@ -192,7 +194,6 @@ convolve_paint_func (PaintCore *paint_core,
switch (state)
{
case INIT_PAINT:
/* calculate the matrix */
calculate_matrix (convolve_options->type, convolve_options->pressure);
break;
@@ -230,105 +231,84 @@ tools_free_convolve (Tool *tool)
paint_core_free (tool);
}
void
static void
convolve_motion (PaintCore *paint_core,
GimpDrawable *drawable)
{
GImage *gimage;
TempBuf * area;
unsigned char *temp_data;
PixelRegion srcPR, destPR, tempPR;
Tag tag = drawable_tag (drawable);
Canvas * painthit_canvas;
PixelArea src_area, painthit_area;
if (! (gimage = drawable_gimage (drawable)))
return;
/* If the image type is indexed, don't convolve */
if (drawable_type (drawable) == INDEXED_GIMAGE)
if (tag_format (tag) == FORMAT_INDEXED )
return;
painthit_canvas = paint_core_16_area (paint_core, drawable);
/* Get a region which can be used to paint to */
if (! (area = paint_core_get_paint_area (paint_core, drawable)))
return;
/* configure the pixel regions correctly */
pixel_region_init (&srcPR, drawable_data (drawable), area->x, area->y, area->width, area->height, FALSE);
destPR.bytes = area->bytes;
destPR.x = 0; destPR.y = 0;
destPR.w = area->width;
destPR.h = area->height;
destPR.rowstride = area->width * destPR.bytes;
destPR.data = temp_buf_data (area);
/* convolve the source image with the convolve mask */
if (srcPR.w >= matrix_size && srcPR.h >= matrix_size)
/* check if the area is large enough to convolve */
if (paint_core->w >= matrix_size && paint_core->h >= matrix_size)
{
/* if the source has no alpha, then add alpha pixels */
if (!drawable_has_alpha (drawable))
{
/* note: this architecture needlessly convolves the totally-
opaque alpha channel. A faster approach would be to keep
tempPR the same number of bytes as srcPR, and extend the
paint_core_replace_canvas API to handle non-alpha images. */
Canvas * temp_canvas;
PixelArea temp_area;
tempPR.bytes = srcPR.bytes + 1;
tempPR.x = 0; tempPR.y = 0;
tempPR.w = area->width;
tempPR.h = area->height;
tempPR.rowstride = tempPR.bytes * tempPR.w;
temp_data = g_malloc (tempPR.h * tempPR.rowstride);
tempPR.data = temp_data;
/* alloc a scratch space */
temp_canvas = canvas_new (tag_set_alpha (tag, ALPHA_YES),
paint_core->w, paint_core->h,
STORAGE_FLAT);
add_alpha_region (&srcPR, &tempPR);
}
else
{
tempPR.bytes = srcPR.bytes;
tempPR.x = 0; tempPR.y = 0;
tempPR.w = area->width;
tempPR.h = area->height;
tempPR.rowstride = tempPR.bytes * tempPR.w;
temp_data = g_malloc (tempPR.h * tempPR.rowstride);
tempPR.data = temp_data;
/* copy data to a flat buffer since convolve_area doesn;t like
tiled buffers */
pixelarea_init (&src_area, drawable_data (drawable),
paint_core->x, paint_core->y,
paint_core->w, paint_core->h,
FALSE);
pixelarea_init (&temp_area, temp_canvas,
0, 0,
0, 0,
TRUE);
copy_area (&src_area, &temp_area);
copy_region (&srcPR, &tempPR);
/* do the convolution */
pixelarea_init (&temp_area, temp_canvas,
0, 0,
0, 0,
FALSE);
pixelarea_init (&painthit_area, painthit_canvas,
0, 0,
0, 0,
TRUE);
convolve_area (&temp_area, &painthit_area,
custom_matrix, matrix_size, matrix_divisor, NORMAL);
tempPR.x = 0; tempPR.y = 0;
tempPR.w = area->width;
tempPR.h = area->height;
tempPR.data = temp_data;
multiply_alpha_region (&tempPR);
}
tempPR.x = 0; tempPR.y = 0;
tempPR.w = area->width;
tempPR.h = area->height;
tempPR.data = temp_data;
/* Convolve the region */
convolve_region (&tempPR, &destPR, matrix, matrix_size,
matrix_divisor, NORMAL);
if (drawable_has_alpha (drawable))
separate_alpha_region (&destPR);
/* Free the allocated temp space */
g_free (temp_data);
/* clean up the scratch space */
canvas_delete ( temp_canvas );
}
else
{
/* if the source has no alpha, then add alpha pixels, otherwise copy */
if (!drawable_has_alpha (drawable))
add_alpha_region (&srcPR, &destPR);
else
copy_region (&srcPR, &destPR);
/* the area is too small to convolve, so just copy it */
pixelarea_init (&src_area, drawable_data (drawable),
paint_core->x, paint_core->y,
paint_core->w, paint_core->h,
FALSE);
pixelarea_init (&painthit_area, painthit_canvas,
0, 0,
0, 0,
TRUE);
copy_area (&src_area, &painthit_area);
}
/* paste the newly painted canvas to the gimage which is being worked on */
paint_core_replace_canvas (paint_core, drawable, OPAQUE,
(int) (get_brush_opacity () * 255),
SOFT, INCREMENTAL);
/* Apply the painthit to the drawable */
paint_core_16_area_replace (paint_core, drawable,
1.0,
(gfloat) get_brush_opacity (),
SOFT,
INCREMENTAL);
}
static void
@@ -360,24 +340,10 @@ calculate_matrix (ConvolveType type,
break;
}
integer_matrix (custom_matrix, matrix, matrix_size);
matrix_divisor = sum_matrix (matrix, matrix_size);
matrix_divisor = sum_matrix (custom_matrix, matrix_size);
if (!matrix_divisor)
matrix_divisor = 1;
}
static void
integer_matrix (float *source,
int *dest,
int size)
{
int i;
#define PRECISION 10000
for (i = 0; i < size*size; i++)
*dest++ = (int) (*source ++ * PRECISION);
matrix_divisor = 1.0;
}
static void
@@ -391,11 +357,11 @@ copy_matrix (float *src,
*dest++ = *src++;
}
static int
sum_matrix (int *matrix,
static gfloat
sum_matrix (gfloat *matrix,
int size)
{
int sum = 0;
gfloat sum = 0;
size *= size;
@@ -405,7 +371,6 @@ sum_matrix (int *matrix,
return sum;
}
static void *
convolve_non_gui_paint_func (PaintCore *paint_core,
GimpDrawable *drawable,

View File

@@ -13,18 +13,18 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CONVOLVE_H__
#define __CONVOLVE_H__
#include "paint_core.h"
#include "procedural_db.h"
#include "tools.h"
struct _tool;
struct _ProcRecord;
void * convolve_paint_func (PaintCore *, GimpDrawable *, int);
Tool * tools_new_convolve (void);
void tools_free_convolve (Tool *);
struct _tool * tools_new_convolve (void);
void tools_free_convolve (struct _tool *);
extern struct _ProcRecord convolve_proc;
/* Procedure definition and marshalling function */
extern ProcRecord convolve_proc;

View File

@@ -13,11 +13,12 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include "appenv.h"
#include "actionarea.h"
#include "canvas.h"
#include "drawable.h"
#include "floating_sel.h"
#include "gdisplay.h"
@@ -27,14 +28,17 @@
#include "global_edit.h"
#include "interface.h"
#include "layer.h"
#include "linked.h"
#include "paint_funcs.h"
#include "paint_funcs_area.h"
#include "palette.h"
#include "pixelarea.h"
#include "pixelrow.h"
#include "tools.h"
#include "undo.h"
#include "tile_manager_pvt.h"
#include "drawable_pvt.h"
#define TileManager Canvas
#define tile_manager_destroy canvas_delete
/* The named paste dialog */
typedef struct _PasteNamedDlg PasteNamedDlg;
@@ -57,7 +61,7 @@ struct _named_buffer
/* The named buffer list */
link_ptr named_buffers = NULL;
GSList * named_buffers = NULL;
/* The global edit buffer */
TileManager * global_buf = NULL;
@@ -69,38 +73,43 @@ TileManager *
crop_buffer (TileManager *tiles,
int border)
{
PixelRegion PR;
PixelArea PR;
TileManager *new_tiles;
int bytes, alpha;
unsigned char * data;
int num_channels, alpha;
guchar * data;
int empty;
int x1, y1, x2, y2;
int x, y;
int ex, ey;
int found;
void * pr;
unsigned char black[MAX_CHANNELS] = { 0, 0, 0, 0 };
COLOR16_NEW (black_color, canvas_tag(tiles) );
COLOR16_INIT (black_color);
palette_get_black (&black_color);
bytes = tiles->levels[0].bpp;
alpha = bytes - 1;
num_channels = tag_num_channels (canvas_tag (tiles));
alpha = num_channels - 1;
/* go through and calculate the bounds */
x1 = tiles->levels[0].width;
y1 = tiles->levels[0].height;
x1 = canvas_width (tiles);
y1 = canvas_height (tiles);
x2 = 0;
y2 = 0;
pixel_region_init (&PR, tiles, 0, 0, x1, y1, FALSE);
for (pr = pixel_regions_register (1, &PR); pr != NULL; pr = pixel_regions_process (pr))
pixelarea_init (&PR, tiles,
0, 0, x1, y1, FALSE);
for (pr = pixelarea_register (1, &PR);
pr != NULL;
pr = pixelarea_process (pr))
{
data = PR.data + alpha;
ex = PR.x + PR.w;
ey = PR.y + PR.h;
data = pixelarea_data (&PR) + alpha;
ex = pixelarea_x (&PR) + pixelarea_width (&PR);
ey = pixelarea_y (&PR) + pixelarea_height (&PR);
for (y = PR.y; y < ey; y++)
for (y = pixelarea_y (&PR); y < ey; y++)
{
found = FALSE;
for (x = PR.x; x < ex; x++, data+=bytes)
for (x = pixelarea_x (&PR); x < ex; x++, data+=num_channels)
if (*data)
{
if (x < x1)
@@ -119,48 +128,56 @@ crop_buffer (TileManager *tiles,
}
}
x2 = BOUNDS (x2 + 1, 0, tiles->levels[0].width);
y2 = BOUNDS (y2 + 1, 0, tiles->levels[0].height);
x2 = BOUNDS (x2 + 1, 0, canvas_width (tiles));
y2 = BOUNDS (y2 + 1, 0, canvas_height (tiles));
empty = (x1 == tiles->levels[0].width && y1 == tiles->levels[0].height);
empty = (x1 == canvas_width (tiles) && y1 == canvas_height (tiles));
/* If there are no visible pixels, return NULL */
if (empty)
new_tiles = NULL;
/* If no cropping, return original buffer */
else if (x1 == 0 && y1 == 0 && x2 == tiles->levels[0].width &&
y2 == tiles->levels[0].height && border == 0)
else if (x1 == 0 && y1 == 0 && x2 == canvas_width (tiles) &&
y2 == canvas_height (tiles) && border == 0)
new_tiles = tiles;
/* Otherwise, crop the original area */
else
{
PixelRegion srcPR, destPR;
PixelArea srcPR, destPR;
int new_width, new_height;
new_width = (x2 - x1) + border * 2;
new_height = (y2 - y1) + border * 2;
new_tiles = tile_manager_new (new_width, new_height, bytes);
new_tiles = canvas_new (canvas_tag (tiles), new_width, new_height, STORAGE_FLAT);
/* If there is a border, make sure to clear the new tiles first */
if (border)
{
pixel_region_init (&destPR, new_tiles, 0, 0, new_width, border, TRUE);
color_region (&destPR, black);
pixel_region_init (&destPR, new_tiles, 0, border, border, (y2 - y1), TRUE);
color_region (&destPR, black);
pixel_region_init (&destPR, new_tiles, new_width - border, border, border, (y2 - y1), TRUE);
color_region (&destPR, black);
pixel_region_init (&destPR, new_tiles, 0, new_height - border, new_width, border, TRUE);
color_region (&destPR, black);
pixelarea_init (&destPR, new_tiles,
0, 0, new_width, border, TRUE);
color_area (&destPR, &black_color);
pixelarea_init (&destPR, new_tiles,
0, border, border, (y2 - y1), TRUE);
color_area (&destPR, &black_color);
pixelarea_init (&destPR, new_tiles,
new_width - border, border, border, (y2 - y1), TRUE);
color_area (&destPR, &black_color);
pixelarea_init (&destPR, new_tiles,
0, new_height - border, new_width, border, TRUE);
color_area (&destPR, &black_color);
}
pixel_region_init (&srcPR, tiles, x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixel_region_init (&destPR, new_tiles, border, border, (x2 - x1), (y2 - y1), TRUE);
pixelarea_init (&srcPR, tiles,
x1, y1, (x2 - x1), (y2 - y1), FALSE);
pixelarea_init (&destPR, new_tiles,
border, border, (x2 - x1), (y2 - y1), TRUE);
copy_region (&srcPR, &destPR);
new_tiles->x = x1;
new_tiles->y = y1;
copy_area (&srcPR, &destPR);
/*
we dont have a way of setting this in canvas....
tiles->x = x1;
tiles->y = y1;
*/
}
return new_tiles;
@@ -239,7 +256,7 @@ edit_copy (GImage *gimage,
cropped_copy = crop_buffer (copy, 0);
if (cropped_copy != copy)
tile_manager_destroy (copy);
tile_manager_destroy (copy);
}
else if (copy)
cropped_copy = copy;
@@ -271,7 +288,7 @@ edit_paste (GImage *gimage,
int cx, cy;
/* Make a new floating layer */
float_layer = layer_from_tiles (gimage, drawable, paste, "Pasted Layer", OPAQUE, NORMAL);
float_layer = layer_from_tiles (gimage, drawable, paste, "Pasted Layer", OPAQUE_OPACITY, NORMAL);
if (float_layer)
{
@@ -284,8 +301,8 @@ edit_paste (GImage *gimage,
cx += (x1 + x2) >> 1;
cy += (y1 + y2) >> 1;
GIMP_DRAWABLE(float_layer)->offset_x = cx - (GIMP_DRAWABLE(float_layer)->width >> 1);
GIMP_DRAWABLE(float_layer)->offset_y = cy - (GIMP_DRAWABLE(float_layer)->height >> 1);
GIMP_DRAWABLE(float_layer)->offset_x = cx - (drawable_width (GIMP_DRAWABLE(float_layer)) >> 1);
GIMP_DRAWABLE(float_layer)->offset_y = cy - (drawable_height (GIMP_DRAWABLE(float_layer)) >> 1);
/* If there is a selection mask clear it--
* this might not always be desired, but in general,
@@ -311,29 +328,32 @@ edit_clear (GImage *gimage,
GimpDrawable *drawable)
{
TileManager *buf_tiles;
PixelRegion bufPR;
PixelArea bufPR;
int x1, y1, x2, y2;
unsigned char col[MAX_CHANNELS];
Tag d_tag = drawable_tag (drawable);
COLOR16_NEW (background_color, d_tag);
COLOR16_INIT (background_color);
palette_get_background (&background_color);
if (!gimage || drawable == NULL)
return FALSE;
gimage_get_background (gimage, drawable, col);
if (drawable_has_alpha (drawable))
col [drawable_bytes (drawable) - 1] = OPAQUE;
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
if (!(x2 - x1) || !(y2 - y1))
return FALSE;
buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), drawable_bytes (drawable));
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
color_region (&bufPR, col);
buf_tiles = canvas_new (d_tag, (x2 - x1), (y2 - y1), STORAGE_FLAT);
pixelarea_init (&bufPR, buf_tiles,
0, 0, (x2 - x1), (y2 - y1), TRUE);
color_area (&bufPR, &background_color);
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
gimage_apply_image (gimage, drawable, &bufPR, 1, OPAQUE,
ERASE_MODE, NULL, x1, y1);
gimage_apply_painthit(gimage, drawable,
NULL, buf_tiles,
0, 0,
(x2 - x1), (y2 - y1),
1, 1.0,
ERASE_MODE, x1, y1);
/* update the image */
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
@@ -349,29 +369,31 @@ edit_fill (GImage *gimage,
GimpDrawable *drawable)
{
TileManager *buf_tiles;
PixelRegion bufPR;
PixelArea bufPR;
int x1, y1, x2, y2;
unsigned char col[MAX_CHANNELS];
Tag d_tag = drawable_tag (drawable);
COLOR16_NEW (background_color, d_tag);
COLOR16_INIT (background_color);
palette_get_background (&background_color);
if (!gimage || drawable == NULL)
return FALSE;
gimage_get_background (gimage, drawable, col);
if (drawable_has_alpha (drawable))
col [drawable_bytes (drawable) - 1] = OPAQUE;
drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
if (!(x2 - x1) || !(y2 - y1))
return FALSE;
buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), drawable_bytes (drawable));
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE);
color_region (&bufPR, col);
buf_tiles = canvas_new (d_tag, (x2 - x1), (y2 - y1), STORAGE_FLAT);
pixelarea_init (&bufPR, buf_tiles,
0, 0, (x2 - x1), (y2 - y1), TRUE);
color_area (&bufPR, &background_color);
pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE);
gimage_apply_image (gimage, drawable, &bufPR, 1, OPAQUE,
NORMAL_MODE, NULL, x1, y1);
gimage_apply_painthit (gimage, drawable,
NULL, buf_tiles,
0, 0,
(x2 - x1), (y2 - y1),
1, 1.0, NORMAL_MODE, x1, y1);
/* update the image */
drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
@@ -449,7 +471,7 @@ global_edit_free ()
static void
set_list_of_named_buffers (GtkWidget *list_widget)
{
link_ptr list;
GSList *list;
NamedBuffer *nb;
GtkWidget *list_item;
@@ -459,7 +481,7 @@ set_list_of_named_buffers (GtkWidget *list_widget)
while (list)
{
nb = (NamedBuffer *) list->data;
list = next_item (list);
list = g_slist_next (list);
list_item = gtk_list_item_new_with_label (nb->name);
gtk_container_add (GTK_CONTAINER (list_widget), list_item);
@@ -500,6 +522,9 @@ named_buffer_paste_callback (GtkWidget *w,
gtk_widget_destroy (pn_dlg->shell);
g_free (pn_dlg);
/* flush the display */
gdisplays_flush ();
}
static void
@@ -513,7 +538,7 @@ named_buffer_delete_foreach (GtkWidget *w,
{
pn_dlg = (PasteNamedDlg *) client_data;
nb = (NamedBuffer *) gtk_object_get_user_data (GTK_OBJECT (w));
named_buffers = remove_from_list (named_buffers, (void *) nb);
named_buffers = g_slist_remove (named_buffers, (void *) nb);
g_free (nb->name);
tile_manager_destroy (nb->buf);
g_free (nb);
@@ -553,7 +578,7 @@ named_buffer_dialog_delete_callback (GtkWidget *w,
{
named_buffer_cancel_callback (w, client_data);
return FALSE;
return TRUE;
}
static void
@@ -589,6 +614,7 @@ paste_named_buffer (GDisplay *gdisp)
pn_dlg->gdisp = gdisp;
pn_dlg->shell = gtk_dialog_new ();
gtk_window_set_wmclass (GTK_WINDOW (pn_dlg->shell), "paste_named_buffer", "Gimp");
gtk_window_set_title (GTK_WINDOW (pn_dlg->shell), "Paste Named Buffer");
gtk_window_position (GTK_WINDOW (pn_dlg->shell), GTK_WIN_POS_MOUSE);
@@ -635,72 +661,88 @@ paste_named_buffer (GDisplay *gdisp)
}
static void
new_named_buffer_callback (GtkWidget *w,
gpointer client_data,
gpointer call_data)
new_named_buffer (TileManager *tiles,
char *name)
{
PixelRegion srcPR, destPR;
TileManager *tiles;
PixelArea srcPR, destPR;
NamedBuffer *nb;
tiles = (TileManager *) client_data;
if (! tiles) return;
nb = (NamedBuffer *) g_malloc (sizeof (NamedBuffer));
nb->buf = tile_manager_new (tiles->levels[0].width, tiles->levels[0].height, tiles->levels[0].bpp);
pixel_region_init (&srcPR, tiles, 0, 0, tiles->levels[0].width, tiles->levels[0].height, FALSE);
pixel_region_init (&destPR, nb->buf, 0, 0, tiles->levels[0].width, tiles->levels[0].height, TRUE);
copy_region (&srcPR, &destPR);
nb->buf = canvas_new (canvas_tag (tiles),
canvas_width (tiles), canvas_height (tiles),
STORAGE_FLAT);
pixelarea_init (&srcPR, tiles,
0, 0, canvas_width (tiles), canvas_height (tiles), FALSE);
pixelarea_init (&destPR, nb->buf,
0, 0, canvas_width (tiles), canvas_height (tiles), TRUE);
copy_area (&srcPR, &destPR);
nb->name = g_strdup ((char *) call_data);
named_buffers = append_to_list (named_buffers, (void *) nb);
nb->name = g_strdup ((char *) name);
named_buffers = g_slist_append (named_buffers, (void *) nb);
}
static void
new_named_buffer (TileManager *new_tiles)
cut_named_buffer_callback (GtkWidget *w,
gpointer client_data,
gpointer call_data)
{
/* Create the dialog box to ask for a name */
query_string_box ("Named Buffer", "Enter a name for this buffer", NULL,
new_named_buffer_callback, new_tiles);
TileManager *new_tiles;
GDisplay *gdisp;
char *name;
gdisp = (GDisplay *) client_data;
name = g_strdup ((char *) call_data);
new_tiles = edit_cut (gdisp->gimage, gimage_active_drawable (gdisp->gimage));
if (new_tiles)
new_named_buffer (new_tiles, name);
gdisplays_flush ();
}
int
named_edit_cut (void *gdisp_ptr)
{
TileManager *new_tiles;
GDisplay *gdisp;
/* stop any active tool */
gdisp = (GDisplay *) gdisp_ptr;
active_tool_control (HALT, gdisp_ptr);
new_tiles = edit_cut (gdisp->gimage, gimage_active_drawable (gdisp->gimage));
query_string_box ("Cut Named", "Enter a name for this buffer", NULL,
cut_named_buffer_callback, gdisp);
return TRUE;
}
if (! new_tiles)
return FALSE;
else
{
new_named_buffer (new_tiles);
gdisplays_flush ();
return TRUE;
}
static void
copy_named_buffer_callback (GtkWidget *w,
gpointer client_data,
gpointer call_data)
{
TileManager *new_tiles;
GDisplay *gdisp;
char *name;
gdisp = (GDisplay *) client_data;
name = g_strdup ((char *) call_data);
new_tiles = edit_copy (gdisp->gimage, gimage_active_drawable (gdisp->gimage));
if (new_tiles)
new_named_buffer (new_tiles, name);
}
int
named_edit_copy (void *gdisp_ptr)
{
TileManager *new_tiles;
GDisplay *gdisp;
gdisp = (GDisplay *) gdisp_ptr;
new_tiles = edit_copy (gdisp->gimage, gimage_active_drawable (gdisp->gimage));
if (! new_tiles)
return FALSE;
else
{
new_named_buffer (new_tiles);
return TRUE;
}
query_string_box ("Copy Named", "Enter a name for this buffer", NULL,
copy_named_buffer_callback, gdisp);
return TRUE;
}
int
@@ -716,7 +758,7 @@ named_edit_paste (void *gdisp_ptr)
void
named_buffers_free ()
{
link_ptr list;
GSList *list;
NamedBuffer * nb;
list = named_buffers;
@@ -727,9 +769,9 @@ named_buffers_free ()
tile_manager_destroy (nb->buf);
g_free (nb->name);
g_free (nb);
list = next_item (list);
list = g_slist_next (list);
}
free_list (named_buffers);
g_slist_free (named_buffers);
named_buffers = NULL;
}

View File

@@ -13,12 +13,16 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GLOBAL_EDIT_H__
#define __GLOBAL_EDIT_H__
#include "gimage.h"
struct _GImage;
struct _Canvas;
#define GImage struct _GImage
#define TileManager struct _Canvas
/* The interface functions */
TileManager * crop_buffer (TileManager *, int);
@@ -38,4 +42,7 @@ int named_edit_copy (void *);
int named_edit_paste (void *);
void named_buffers_free (void);
#undef GImage
#undef TileManager
#endif /* __GLOBAL_EDIT_H__ */

View File

@@ -13,17 +13,18 @@
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __BRUSH_HEADER_H__
#define __BRUSH_HEADER_H__
typedef struct _BrushHeader BrushHeader;
#define FILE_VERSION 2
#define FILE_VERSION 3
#define GBRUSH_MAGIC (('G' << 24) + ('I' << 16) + ('M' << 8) + ('P' << 0))
#define sz_BrushHeader (sizeof (BrushHeader))
#define BRUSH_HEADER_C_2_cw
/* All field entries are MSB */
struct _BrushHeader
@@ -32,7 +33,7 @@ struct _BrushHeader
unsigned int version; /* brush file version # */
unsigned int width; /* width of brush */
unsigned int height; /* height of brush */
unsigned int bytes; /* depth of brush in bytes--always 1 */
unsigned int type; /* = bpp in version <= 2, but layer type in version >= 3*/
unsigned int magic_number;/* GIMP brush magic number */
unsigned int spacing; /* brush spacing */
};

Some files were not shown because too many files have changed in this diff Show More