Files
gimp/app/base/temp-buf.c
Sven Neumann 4f870bc132 deprecated RGB intensity functions and definitions. These coefficients do
2005-08-03  Sven Neumann  <sven@gimp.org>

	* libgimpcolor/gimprgb.[ch]: deprecated RGB intensity functions
	and definitions. These coefficients do not accurately compute
	luminance for contemporary monitors. Instead the coefficients from
	the sRGB spec should be used which have now been added.

	* libgimpcolor/gimpcolor.def: updated.

	* libgimp/gimpdrawable.c
	* libgimp/gimppixelfetcher.c
	* app/base/colorize.c
	* app/base/levels.c
	* app/base/temp-buf.c
	* app/core/gimpdrawable-blend.c
	* app/core/gimpdrawable-convert.c
	* app/core/gimpdrawable-desaturate.c
	* app/core/gimpimage-convert.c
	* app/core/gimpimage.c
	* app/gui/splash.c
	* app/widgets/gimpgradienteditor.c
	* modules/colorsel_triangle.c
	* plug-ins/common/aa.c
	* plug-ins/common/bumpmap.c
	* plug-ins/common/colorify.c
	* plug-ins/common/despeckle.c
	* plug-ins/common/displace.c
	* plug-ins/common/engrave.c
	* plug-ins/common/gradmap.c
	* plug-ins/common/grid.c
	* plug-ins/common/mng.c
	* plug-ins/common/newsprint.c
	* plug-ins/common/png.c
	* plug-ins/common/whirlpinch.c
	* plug-ins/gflare/gflare.c
	* plug-ins/gfli/gfli.c
	* plug-ins/maze/handy.c
	* plug-ins/pagecurl/pagecurl.c: use gimp_rgb_luminance() and
	friends instead of the deprecated intensity functions.
2005-08-03 00:36:41 +00:00

541 lines
12 KiB
C

/* 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 "config.h"
#include <string.h>
#include <glib-object.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpcolor/gimpcolor.h"
#include "base-types.h"
#include "pixel-region.h"
#include "temp-buf.h"
#include "paint-funcs/paint-funcs.h"
static guchar * temp_buf_allocate (guint size);
static void temp_buf_to_color (TempBuf *src_buf,
TempBuf *dest_buf);
static void temp_buf_to_gray (TempBuf *src_buf,
TempBuf *dest_buf);
/* Memory management */
static guchar *
temp_buf_allocate (guint size)
{
return g_new (guchar, size);
}
/* The conversion routines */
static void
temp_buf_to_color (TempBuf *src_buf,
TempBuf *dest_buf)
{
guchar *src;
guchar *dest;
glong num_pixels;
src = temp_buf_data (src_buf);
dest = temp_buf_data (dest_buf);
num_pixels = src_buf->width * src_buf->height;
switch (dest_buf->bytes)
{
case 3:
g_return_if_fail (src_buf->bytes == 1);
while (num_pixels--)
{
guchar tmpch;
*dest++ = tmpch = *src++;
*dest++ = tmpch;
*dest++ = tmpch;
}
break;
case 4:
g_return_if_fail (src_buf->bytes == 2);
while (num_pixels--)
{
guchar tmpch;
*dest++ = tmpch = *src++;
*dest++ = tmpch;
*dest++ = tmpch;
*dest++ = *src++; /* alpha channel */
}
break;
default:
g_return_if_reached ();
break;
}
}
static void
temp_buf_to_gray (TempBuf *src_buf,
TempBuf *dest_buf)
{
guchar *src;
guchar *dest;
glong num_pixels;
gfloat pix;
src = temp_buf_data (src_buf);
dest = temp_buf_data (dest_buf);
num_pixels = src_buf->width * src_buf->height;
switch (dest_buf->bytes)
{
case 1:
g_return_if_fail (src_buf->bytes == 3);
while (num_pixels--)
{
pix = GIMP_RGB_LUMINANCE (src[0], src[1], src[2]) + 0.5;
*dest++ = (guchar) pix;
src += 3;
}
break;
case 2:
g_return_if_fail (src_buf->bytes == 4);
while (num_pixels--)
{
pix = GIMP_RGB_LUMINANCE (src[0], src[1], src[2]) + 0.5;
*dest++ = (guchar) pix;
*dest++ = src[3]; /* alpha channel */
src += 4;
}
break;
default:
g_return_if_reached ();
break;
}
}
TempBuf *
temp_buf_new (gint width,
gint height,
gint bytes,
gint x,
gint y,
guchar *col)
{
glong i;
guchar *data;
TempBuf *temp;
g_return_val_if_fail (width > 0 && height > 0, NULL);
g_return_val_if_fail (bytes > 0, NULL);
temp = g_new (TempBuf, 1);
temp->width = width;
temp->height = height;
temp->bytes = bytes;
temp->x = x;
temp->y = y;
temp->data = data = temp_buf_allocate (width * height * bytes);
/* initialize the data */
if (col)
{
/* First check if we can save a lot of work */
for (i = 1; i < bytes; i++)
{
if (col[0] != col[i])
break;
}
if (i == bytes)
{
memset (data, *col, width * height * bytes);
}
else /* No, we cannot */
{
guchar *dptr = data;
/* Fill the first row */
for (i = width - 1; i >= 0; --i)
{
guchar *init = col;
gint j = bytes;
while (j--)
*dptr++ = *init++;
}
/* Now copy from it (we set bytes to bytes-per-row now) */
bytes *= width;
while (--height)
{
memcpy (dptr, data, bytes);
dptr += bytes;
}
}
}
return temp;
}
/* This function simply renders a checkerboard with the given
parameters into a newly allocated RGB tempbuf */
TempBuf *
temp_buf_new_check (gint width,
gint height,
GimpCheckType check_type,
GimpCheckSize check_size)
{
TempBuf *newbuf;
guchar *data;
guchar check_shift = 0;
guchar check_mod = 0;
guchar check_light = 0;
guchar check_dark = 0;
gint x, y;
g_return_val_if_fail (width > 0 && height > 0, NULL);
switch (check_size)
{
case GIMP_CHECK_SIZE_SMALL_CHECKS:
check_mod = 0x3;
check_shift = 2;
break;
case GIMP_CHECK_SIZE_MEDIUM_CHECKS:
check_mod = 0x7;
check_shift = 3;
break;
case GIMP_CHECK_SIZE_LARGE_CHECKS:
check_mod = 0xf;
check_shift = 4;
break;
}
gimp_checks_get_shades (check_type, &check_light, &check_dark);
newbuf = temp_buf_new (width, height, 3, 0, 0, NULL);
data = temp_buf_data (newbuf);
for (y = 0; y < height; y++)
{
guchar check_dark = y >> check_shift;
guchar color = (check_dark & 0x1) ? check_light : check_dark;
for (x = 0; x < width; x++)
{
*data++ = color;
*data++ = color;
*data++ = color;
if (((x + 1) & check_mod) == 0)
{
check_dark += 1;
color = (check_dark & 0x1) ? check_light : check_dark;
}
}
}
return newbuf;
}
TempBuf *
temp_buf_copy (TempBuf *src,
TempBuf *dest)
{
glong length;
g_return_val_if_fail (src != NULL, NULL);
g_return_val_if_fail (! dest || (dest->width == src->width &&
dest->height == src->height), NULL);
if (! dest)
{
dest = temp_buf_new (src->width, src->height, src->bytes, 0, 0, NULL);
}
if (src->bytes != dest->bytes)
{
if (src->bytes == 4 && dest->bytes == 2) /* RGBA -> GRAYA */
temp_buf_to_gray (src, dest);
else if (src->bytes == 3 && dest->bytes == 1) /* RGB -> GRAY */
temp_buf_to_gray (src, dest);
else if (src->bytes == 2 && dest->bytes == 4) /* GRAYA -> RGBA */
temp_buf_to_color (src, dest);
else if (src->bytes == 1 && dest->bytes == 3) /* GRAY -> RGB */
temp_buf_to_color (src, dest);
else
g_warning ("temp_buf_copy(): unimplemented color conversion");
}
else
{
/* make the copy */
length = src->width * src->height * src->bytes;
memcpy (temp_buf_data (dest), temp_buf_data (src), length);
}
return dest;
}
TempBuf *
temp_buf_resize (TempBuf *buf,
gint bytes,
gint x,
gint y,
gint width,
gint height)
{
gint size;
g_return_val_if_fail (width > 0 && height > 0, NULL);
/* calculate the requested size */
size = width * height * bytes;
/* First, configure the canvas buffer */
if (!buf)
{
buf = temp_buf_new (width, height, bytes, x, y, NULL);
}
else
{
if (size != (buf->width * buf->height * buf->bytes))
{
buf->data = g_renew (guchar, buf->data, size);
}
/* Make sure the temp buf fields are valid */
buf->x = x;
buf->y = y;
buf->width = width;
buf->height = height;
buf->bytes = bytes;
}
return buf;
}
TempBuf *
temp_buf_scale (TempBuf *src,
gint new_width,
gint new_height)
{
gint loop1;
gint loop2;
gdouble x_ratio;
gdouble y_ratio;
guchar *src_data;
guchar *dest_data;
TempBuf *dest;
g_return_val_if_fail (src != NULL, NULL);
g_return_val_if_fail (new_width > 0 && new_height > 0, NULL);
dest = temp_buf_new (new_width,
new_height,
src->bytes,
0, 0, NULL);
src_data = temp_buf_data (src);
dest_data = temp_buf_data (dest);
x_ratio = (gdouble) src->width / (gdouble) new_width;
y_ratio = (gdouble) src->height / (gdouble) new_height;
for (loop1 = 0 ; loop1 < new_height ; loop1++)
{
for (loop2 = 0 ; loop2 < new_width ; loop2++)
{
gint i;
guchar *src_pixel;
guchar *dest_pixel;
src_pixel = src_data +
(gint) (loop2 * x_ratio) * src->bytes +
(gint) (loop1 * y_ratio) * src->bytes * src->width;
dest_pixel = dest_data +
(loop2 + loop1 * new_width) * src->bytes;
for (i = 0 ; i < src->bytes; i++)
*dest_pixel++ = *src_pixel++;
}
}
return dest;
}
TempBuf *
temp_buf_copy_area (TempBuf *src,
TempBuf *dest,
gint x,
gint y,
gint width,
gint height,
gint dest_x,
gint dest_y)
{
TempBuf *new;
PixelRegion srcPR = { 0, };
PixelRegion destPR = { 0, };
guchar empty[MAX_CHANNELS] = { 0, 0, 0, 0 };
gint x1, y1, x2, y2;
g_return_val_if_fail (src != NULL, dest);
g_return_val_if_fail (!dest || dest->bytes == src->bytes, dest);
g_return_val_if_fail (width + dest_x > 0, dest);
g_return_val_if_fail (height + dest_y > 0, dest);
g_return_val_if_fail (!dest || dest->width >= width + dest_x, dest);
g_return_val_if_fail (!dest || dest->height >= height + dest_y, dest);
/* some bounds checking */
x1 = CLAMP (x, 0, src->width - 1);
y1 = CLAMP (y, 0, src->height - 1);
x2 = CLAMP (x + width - 1, 0, src->width - 1);
y2 = CLAMP (y + height - 1, 0, src->height - 1);
if (!(x2 - x1) || !(y2 - y1))
return dest;
width = x2 - x1 + 1;
height = y2 - y1 + 1;
if (! dest)
{
new = temp_buf_new (width + dest_x,
height + dest_y,
src->bytes,
0, 0,
empty);
}
else
{
new = dest;
}
/* Copy the region */
srcPR.bytes = src->bytes;
srcPR.w = width;
srcPR.h = height;
srcPR.rowstride = src->bytes * src->width;
srcPR.data = temp_buf_data (src) + (y1 * srcPR.rowstride +
x1 * srcPR.bytes);
destPR.bytes = dest->bytes;
destPR.rowstride = new->bytes * new->width;
destPR.data = temp_buf_data (new) + (dest_y * destPR.rowstride +
dest_x * destPR.bytes);
copy_region (&srcPR, &destPR);
return new;
}
void
temp_buf_free (TempBuf *temp_buf)
{
g_return_if_fail (temp_buf != NULL);
if (temp_buf->data)
g_free (temp_buf->data);
g_free (temp_buf);
}
guchar *
temp_buf_data (TempBuf *temp_buf)
{
return temp_buf->data;
}
guchar *
temp_buf_data_clear (TempBuf *temp_buf)
{
g_return_val_if_fail (temp_buf != NULL, NULL);
memset (temp_buf->data, 0,
temp_buf->height * temp_buf->width * temp_buf->bytes);
return temp_buf->data;
}
gsize
temp_buf_get_memsize (TempBuf *temp_buf)
{
gsize memsize = 0;
g_return_val_if_fail (temp_buf != NULL, 0);
memsize += (sizeof (TempBuf)
+ (gsize) temp_buf->bytes * temp_buf->width * temp_buf->height);
return memsize;
}
/******************************************************************
* Mask buffer functions *
******************************************************************/
MaskBuf *
mask_buf_new (gint width,
gint height)
{
static guchar empty = 0;
return temp_buf_new (width, height, 1, 0, 0, &empty);
}
void
mask_buf_free (MaskBuf *mask)
{
temp_buf_free ((TempBuf *) mask);
}
guchar *
mask_buf_data (MaskBuf *mask_buf)
{
return temp_buf_data ((TempBuf *) mask_buf);
}
guchar *
mask_buf_data_clear (MaskBuf *mask_buf)
{
return temp_buf_data_clear ((TempBuf *) mask_buf);
}