gdk-pixbuf.c 4.51 KB
Newer Older
1
/* GdkPixbuf library
Arturo Espinosa's avatar
Arturo Espinosa committed
2
 *
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Copyright (C) 1999 The Free Software Foundation
 *
 * Authors: Mark Crichton <crichton@gimp.org>
 *          Miguel de Icaza <miguel@gnu.org>
 *          Federico Mena-Quintero <federico@gimp.org>
 *          Carsten Haitzler <raster@rasterman.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Arturo Espinosa's avatar
Arturo Espinosa committed
24
 */
25

Arturo Espinosa's avatar
Arturo Espinosa committed
26
#include <config.h>
Mark Crichton's avatar
Mark Crichton committed
27
#include <math.h>
28
#include <glib.h>
29
#include <libart_lgpl/art_misc.h>
30 31 32
#include <libart_lgpl/art_affine.h>
#include <libart_lgpl/art_pixbuf.h>
#include <libart_lgpl/art_rgb_pixbuf_affine.h>
33
#include <libart_lgpl/art_alphagamma.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
34 35
#include "gdk-pixbuf.h"

36

Arturo Espinosa's avatar
Arturo Espinosa committed
37

Mark Crichton's avatar
Mark Crichton committed
38
void
39
gdk_pixbuf_destroy (GdkPixbuf *pixbuf)
Arturo Espinosa's avatar
Arturo Espinosa committed
40
{
41 42 43
	art_pixbuf_free (pixbuf->art_pixbuf);
	pixbuf->art_pixbuf = NULL;
	g_free (pixbuf);
Arturo Espinosa's avatar
Arturo Espinosa committed
44 45
}

46 47
GdkPixbuf *
gdk_pixbuf_new (ArtPixBuf *art_pixbuf, GdkPixbufUnrefFunc *unref_fn)
Michael Meeks's avatar
Michael Meeks committed
48
{
49
	GdkPixbuf *pixbuf;
Michael Meeks's avatar
Michael Meeks committed
50 51 52 53

	if (!art_pixbuf)
		return NULL;

54 55 56
	pixbuf = g_new (GdkPixbuf, 1);
	pixbuf->ref_count = 1;
	pixbuf->unref_fn = unref_fn;
Michael Meeks's avatar
Michael Meeks committed
57 58 59 60 61
	pixbuf->art_pixbuf = art_pixbuf;

	return pixbuf;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
62
void
63
gdk_pixbuf_ref (GdkPixbuf *pixbuf)
Arturo Espinosa's avatar
Arturo Espinosa committed
64
{
65 66
	g_return_if_fail (pixbuf != NULL);
	g_return_if_fail (pixbuf->ref_count > 0);
67

68
	pixbuf->ref_count++;
Arturo Espinosa's avatar
Arturo Espinosa committed
69 70 71
}

void
72
gdk_pixbuf_unref (GdkPixbuf *pixbuf)
Arturo Espinosa's avatar
Arturo Espinosa committed
73
{
74 75
	g_return_if_fail (pixbuf != NULL);
	g_return_if_fail (pixbuf->ref_count > 0);
76

77
	pixbuf->ref_count--;
78

79 80
	if (pixbuf->ref_count == 0)
		gdk_pixbuf_destroy (pixbuf);
81
}
Arturo Espinosa's avatar
Arturo Espinosa committed
82

83 84
GdkPixbuf *
gdk_pixbuf_scale (const GdkPixbuf *pixbuf, gint w, gint h)
85
{
86 87 88 89 90 91
	art_u8 *pixels;
	gint rowstride;
	double affine[6];
	ArtAlphaGamma *alphagamma;
	ArtPixBuf *art_pixbuf = NULL;
	GdkPixbuf *copy = NULL;
92

93
	alphagamma = NULL;
94

95
	affine[1] = affine[2] = affine[4] = affine[5] = 0;
96

97 98
	affine[0] = w / (double)(pixbuf->art_pixbuf->width);
	affine[3] = h / (double)(pixbuf->art_pixbuf->height);
99

100 101
	/* rowstride = w * pixbuf->art_pixbuf->n_channels; */
	rowstride = w * 3;
102

103 104 105 106
	pixels = art_alloc (h * rowstride);
	art_rgb_pixbuf_affine (pixels, 0, 0, w, h, rowstride,
			       pixbuf->art_pixbuf,
			       affine, ART_FILTER_NEAREST, alphagamma);
107

108 109 110 111 112
	if (pixbuf->art_pixbuf->has_alpha)
		/* should be rgba */
		art_pixbuf = art_pixbuf_new_rgb(pixels, w, h, rowstride);
	else
		art_pixbuf = art_pixbuf_new_rgb(pixels, w, h, rowstride);
Michael Meeks's avatar
Michael Meeks committed
113

114
	copy = gdk_pixbuf_new (art_pixbuf, NULL);
Michael Meeks's avatar
Michael Meeks committed
115

116 117 118 119
	if (!copy)
		art_free (pixels);

	return copy;
Michael Meeks's avatar
Michael Meeks committed
120 121
}

122 123
GdkPixbuf *
gdk_pixbuf_duplicate (const GdkPixbuf *pixbuf)
Michael Meeks's avatar
Michael Meeks committed
124
{
125
	GdkPixbuf *copy  = g_new (GdkPixbuf, 1);
126

Michael Meeks's avatar
Michael Meeks committed
127 128 129
	copy->ref_count  = 1;
	copy->unref_fn   = pixbuf->unref_fn;
	copy->art_pixbuf = art_pixbuf_duplicate (pixbuf->art_pixbuf);
130

Michael Meeks's avatar
Michael Meeks committed
131
	return copy;
132
}
133

134 135
GdkPixbuf *
gdk_pixbuf_rotate (GdkPixbuf *pixbuf, gdouble angle)
Mark Crichton's avatar
Mark Crichton committed
136
{
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
	art_u8 *pixels;
	gint rowstride, w, h;
	gdouble rad;
	double rot[6], trans[6], affine[6];
	ArtAlphaGamma *alphagamma = NULL;
	ArtPixBuf *art_pixbuf = NULL;

	w = pixbuf->art_pixbuf->width;
	h = pixbuf->art_pixbuf->height;

	rad = (M_PI * angle / 180.0);

	rot[0] = cos(rad);
	rot[1] = sin(rad);
	rot[2] = -sin(rad);
	rot[3] = cos(rad);
	rot[4] = rot[5] = 0;

	trans[0] = trans[3] = 1;
	trans[1] = trans[2] = 0;
	trans[4] = -(double)w / 2.0;
	trans[5] = -(double)h / 2.0;

	art_affine_multiply(rot, trans, rot);

	trans[0] = trans[3] = 1;
	trans[1] = trans[2] = 0;
	trans[4] = (double)w / 2.0;
	trans[5] = (double)h / 2.0;

	art_affine_multiply(affine, rot, trans);

	g_print("Affine: %e %e %e %e %e %e\n", affine[0], affine[1], affine[2],
		affine[3], affine[4], affine[5]);

	/* rowstride = w * pixbuf->art_pixbuf->n_channels; */
	rowstride = w * 3;

	pixels = art_alloc (h * rowstride);
	art_rgb_pixbuf_affine (pixels, 0, 0, w, h, rowstride,
			       pixbuf->art_pixbuf,
			       affine, ART_FILTER_NEAREST, alphagamma);
	if (pixbuf->art_pixbuf->has_alpha)
		/* should be rgba */
		art_pixbuf = art_pixbuf_new_rgb(pixels, w, h, rowstride);
	else
		art_pixbuf = art_pixbuf_new_rgb(pixels, w, h, rowstride);

	art_pixbuf_free (pixbuf->art_pixbuf);
	pixbuf->art_pixbuf = art_pixbuf;

	return pixbuf;
Mark Crichton's avatar
Mark Crichton committed
189
}