19
19
#include "config.h"
24
21
#include <string.h>
25
#include <sys/types.h>
30
23
#include <glib-object.h>
33
#include <process.h> /* For _getpid() */
36
25
#include "libgimpbase/gimpbase.h"
37
26
#include "libgimpcolor/gimpcolor.h"
39
28
#include "base-types.h"
41
#include "config/gimpbaseconfig.h"
42
#include "config/gimpconfig-path.h"
30
#include "paint-funcs/paint-funcs.h"
44
32
#include "pixel-region.h"
45
33
#include "temp-buf.h"
47
#include "paint-funcs/paint-funcs.h"
50
static guchar * temp_buf_allocate (guint size);
51
static void temp_buf_to_color (TempBuf *src_buf,
53
static void temp_buf_to_gray (TempBuf *src_buf,
58
#warning FIXME: extern GimpBaseConfig *base_config;
60
extern GimpBaseConfig *base_config;
63
/* Memory management */
66
temp_buf_allocate (guint size)
68
return g_new (guchar, size);
72
/* The conversion routines */
75
temp_buf_to_color (TempBuf *src_buf,
82
src = temp_buf_data (src_buf);
83
dest = temp_buf_data (dest_buf);
85
num_pixels = src_buf->width * src_buf->height;
87
switch (dest_buf->bytes)
90
g_return_if_fail (src_buf->bytes == 1);
94
*dest++ = tmpch = *src++;
101
g_return_if_fail (src_buf->bytes == 2);
105
*dest++ = tmpch = *src++;
109
*dest++ = *src++; /* alpha channel */
114
g_return_if_reached ();
120
temp_buf_to_gray (TempBuf *src_buf,
128
src = temp_buf_data (src_buf);
129
dest = temp_buf_data (dest_buf);
131
num_pixels = src_buf->width * src_buf->height;
133
switch (dest_buf->bytes)
136
g_return_if_fail (src_buf->bytes == 3);
139
pix = GIMP_RGB_INTENSITY (src[0], src[1], src[2]) + 0.5;
140
*dest++ = (guchar) pix;
147
g_return_if_fail (src_buf->bytes == 4);
150
pix = GIMP_RGB_INTENSITY (src[0], src[1], src[2]) + 0.5;
151
*dest++ = (guchar) pix;
153
*dest++ = src[3]; /* alpha channel */
160
g_return_if_reached ();
36
static void temp_buf_to_color (TempBuf *src_buf,
38
static void temp_buf_to_gray (TempBuf *src_buf,
166
temp_buf_new (gint width,
43
temp_buf_new (gint width,
177
52
g_return_val_if_fail (width > 0 && height > 0, NULL);
536
378
g_return_val_if_fail (temp_buf != NULL, 0);
538
memsize += sizeof (TempBuf);
540
if (temp_buf->swapped)
542
memsize += strlen (temp_buf->filename) + 1;
546
memsize += ((gsize) temp_buf->bytes *
380
memsize += (sizeof (TempBuf)
381
+ (gsize) temp_buf->bytes * temp_buf->width * temp_buf->height);
555
/******************************************************************
556
* Mask buffer functions *
557
******************************************************************/
561
mask_buf_new (gint width,
564
static guchar empty = 0;
566
return temp_buf_new (width, height, 1, 0, 0, &empty);
570
mask_buf_free (MaskBuf *mask)
572
temp_buf_free ((TempBuf *) mask);
576
mask_buf_data (MaskBuf *mask_buf)
578
return temp_buf_data ((TempBuf *) mask_buf);
582
mask_buf_data_clear (MaskBuf *mask_buf)
584
return temp_buf_data_clear ((TempBuf *) mask_buf);
588
/******************************************************************
589
* temp buffer disk caching functions *
590
******************************************************************/
593
* Disk caching is setup as follows:
594
* On a call to temp_buf_swap, the TempBuf parameter is stored
595
* in a temporary variable called cached_in_memory.
596
* On the next call to temp_buf_swap, if cached_in_memory is non-null,
597
* cached_in_memory is moved to disk, and the latest TempBuf parameter
598
* is stored in cached_in_memory. This method keeps the latest TempBuf
599
* structure in memory instead of moving it directly to disk as requested.
600
* On a call to temp_buf_unswap, if cached_in_memory is non-null, it is
601
* compared against the requested TempBuf. If they are the same, nothing
602
* must be moved in from disk since it still resides in memory. However,
603
* if the two pointers are different, the requested TempBuf is retrieved
604
* from disk. In the former case, cached_in_memory is set to NULL;
605
* in the latter case, cached_in_memory is left unchanged.
606
* If temp_buf_swap_free is called, cached_in_memory must be checked
607
* against the temp buf being freed. If they are the same, then
608
* cached_in_memory must be set to NULL;
610
* In the case where memory usage is set to "stingy":
611
* temp bufs are not cached in memory at all, they go right to disk.
615
/* a static counter for generating unique filenames
617
static gint tmp_file_index = 0;
620
/* a static pointer which keeps track of the last request for
623
static TempBuf *cached_in_memory = NULL;
627
generate_unique_tmp_filename (GimpBaseConfig *config)
634
tmpdir = gimp_config_path_expand (config->temp_path, TRUE, NULL);
638
tmpfile = g_strdup_printf ("gimp%d.%d",
642
path = g_build_filename (tmpdir, tmpfile, NULL);
651
temp_buf_swap (TempBuf *buf)
657
if (!buf || buf->swapped)
660
/* Set the swapped flag */
663
if (base_config->stingy_memory_use)
669
swap = cached_in_memory;
670
cached_in_memory = buf;
673
/* For the case where there is no temp buf ready
674
* to be moved to disk, return
679
/* Get a unique filename for caching the data to a UNIX file */
680
filename = generate_unique_tmp_filename (base_config);
682
/* Check if generated filename is valid */
683
if (g_file_test (filename, G_FILE_TEST_IS_DIR))
685
g_message ("Error in temp buf caching: \"%s\" is a directory (cannot overwrite)",
686
gimp_filename_to_utf8 (filename));
691
/* Open file for overwrite */
692
if ((fp = fopen (filename, "wb")))
694
gsize blocks_written;
696
blocks_written = fwrite (swap->data,
697
swap->width * swap->height * swap->bytes, 1,
700
/* Check whether all bytes were written and fclose() was able
701
to flush its buffers */
702
if ((0 != fclose (fp)) || (1 != blocks_written))
705
perror ("Write error on temp buf");
706
g_message ("Cannot write \"%s\"",
707
gimp_filename_to_utf8 (filename));
715
perror ("Error in temp buf caching");
716
g_message ("Cannot write \"%s\"",
717
gimp_filename_to_utf8 (filename));
721
/* Finally, free the buffer's data */
725
swap->filename = filename;
729
temp_buf_unswap (TempBuf *buf)
732
gboolean succ = FALSE;
734
if (!buf || !buf->swapped)
737
/* Set the swapped flag */
738
buf->swapped = FALSE;
740
/* If the requested temp buf is still in memory, simply return */
741
if (cached_in_memory == buf)
743
cached_in_memory = NULL;
747
/* Allocate memory for the buffer's data */
748
buf->data = temp_buf_allocate (buf->width * buf->height * buf->bytes);
750
if (g_file_test (buf->filename, G_FILE_TEST_IS_REGULAR))
752
if ((fp = fopen (buf->filename, "rb")))
756
blocks_read = fread (buf->data,
757
buf->width * buf->height * buf->bytes, 1,
761
if (blocks_read != 1)
762
perror ("Read error on temp buf");
767
perror ("Error in temp buf caching");
769
/* Delete the swap file */
770
unlink (buf->filename);
774
g_message ("Error in temp buf caching: "
775
"information swapped to disk was lost!");
777
g_free (buf->filename); /* free filename */
778
buf->filename = NULL;
782
temp_buf_swap_free (TempBuf *buf)
787
/* Set the swapped flag */
788
buf->swapped = FALSE;
790
/* If the requested temp buf is cached in memory... */
791
if (cached_in_memory == buf)
793
cached_in_memory = NULL;
797
/* Find out if the filename of the swapped data is an existing file... */
798
if (g_file_test (buf->filename, G_FILE_TEST_IS_REGULAR))
800
/* Delete the swap file */
801
unlink (buf->filename);
804
g_message ("Error in temp buf disk swapping: "
805
"information swapped to disk was lost!");
808
g_free (buf->filename); /* free filename */
809
buf->filename = NULL;
815
if (cached_in_memory)
816
temp_buf_free (cached_in_memory);
387
/* The conversion routines */
390
temp_buf_to_color (TempBuf *src_buf,
397
src = temp_buf_data (src_buf);
398
dest = temp_buf_data (dest_buf);
400
num_pixels = src_buf->width * src_buf->height;
402
switch (dest_buf->bytes)
405
g_return_if_fail (src_buf->bytes == 1);
410
*dest++ = tmp = *src++;
417
g_return_if_fail (src_buf->bytes == 2);
422
*dest++ = tmp = *src++;
426
*dest++ = *src++; /* alpha channel */
431
g_return_if_reached ();
437
temp_buf_to_gray (TempBuf *src_buf,
444
src = temp_buf_data (src_buf);
445
dest = temp_buf_data (dest_buf);
447
num_pixels = src_buf->width * src_buf->height;
449
switch (dest_buf->bytes)
452
g_return_if_fail (src_buf->bytes == 3);
455
gint lum = GIMP_RGB_LUMINANCE (src[0], src[1], src[2]) + 0.5;
457
*dest++ = (guchar) lum;
464
g_return_if_fail (src_buf->bytes == 4);
467
gint lum = GIMP_RGB_LUMINANCE (src[0], src[1], src[2]) + 0.5;
469
*dest++ = (guchar) lum;
470
*dest++ = src[3]; /* alpha channel */
477
g_return_if_reached ();