Fixed README
[liblqr.git] / lqr / lqr_carver_bias.c
blobc00534ce84e1966db89deec627b0d504f8dd06a3
1 /* LiquidRescaling Library
2 * Copyright (C) 2007-2009 Carlo Baldassi (the "Author") <carlobaldassi@gmail.com>.
3 * All Rights Reserved.
5 * This library implements the algorithm described in the paper
6 * "Seam Carving for Content-Aware Image Resizing"
7 * by Shai Avidan and Ariel Shamir
8 * which can be found at http://www.faculty.idc.ac.il/arik/imret.pdf
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; version 3 dated June, 2007.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, see <http://www.gnu.org/licenses/>
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
27 #include <lqr/lqr_all.h>
29 #ifdef __LQR_DEBUG__
30 #include <assert.h>
31 #endif
33 /**** LQR_CARVER_BIAS STRUCT FUNTIONS ****/
35 /* LQR_PUBLIC */
36 void
37 lqr_carver_bias_clear(LqrCarver *r)
39 g_free(r->bias);
40 r->bias = NULL;
41 r->nrg_uptodate = FALSE;
44 /* LQR_PUBLIC */
45 LqrRetVal
46 lqr_carver_bias_add_xy(LqrCarver *r, gdouble bias, gint x, gint y)
48 gint xt, yt;
50 if (bias == 0) {
51 return LQR_OK;
54 LQR_CATCH_CANC(r);
55 if (r->nrg_active == FALSE) {
56 LQR_CATCH(lqr_carver_init_energy_related(r));
59 if ((r->w != r->w0) || (r->w_start != r->w0) || (r->h != r->h0) || (r->h_start != r->h0)) {
60 LQR_CATCH(lqr_carver_flatten(r));
62 if (r->bias == NULL) {
63 LQR_CATCH_MEM(r->bias = g_try_new0(gfloat, r->w0 * r->h0));
66 xt = r->transposed ? y : x;
67 yt = r->transposed ? x : y;
69 r->bias[yt * r->w0 + xt] += (gfloat) bias / 2;
71 r->nrg_uptodate = FALSE;
73 return LQR_OK;
76 /* LQR_PUBLIC */
77 LqrRetVal
78 lqr_carver_bias_add_area(LqrCarver *r, gdouble *buffer, gint bias_factor, gint width, gint height, gint x_off,
79 gint y_off)
81 gint x, y;
82 gint xt, yt;
83 gint wt, ht;
84 gint x0, y0, x1, y1, x2, y2;
85 gfloat bias;
87 LQR_CATCH_CANC(r);
89 if (bias_factor == 0) {
90 return LQR_OK;
93 if ((r->w != r->w0) || (r->w_start != r->w0) || (r->h != r->h0) || (r->h_start != r->h0)) {
94 LQR_CATCH(lqr_carver_flatten(r));
97 if (r->nrg_active == FALSE) {
98 LQR_CATCH(lqr_carver_init_energy_related(r));
101 if (r->bias == NULL) {
102 LQR_CATCH_MEM(r->bias = g_try_new0(gfloat, r->w * r->h));
105 wt = r->transposed ? r->h : r->w;
106 ht = r->transposed ? r->w : r->h;
108 x0 = MIN(0, x_off);
109 y0 = MIN(0, y_off);
110 x1 = MAX(0, x_off);
111 y1 = MAX(0, y_off);
112 x2 = MIN(wt, width + x_off);
113 y2 = MIN(ht, height + y_off);
115 for (y = 0; y < y2 - y1; y++) {
116 for (x = 0; x < x2 - x1; x++) {
117 bias = (gfloat) ((gdouble) bias_factor * buffer[(y - y0) * width + (x - x0)] / 2);
119 xt = r->transposed ? y : x;
120 yt = r->transposed ? x : y;
122 r->bias[(yt + y1) * r->w0 + (xt + x1)] += bias;
126 r->nrg_uptodate = FALSE;
128 return LQR_OK;
131 /* LQR_PUBLIC */
132 LqrRetVal
133 lqr_carver_bias_add(LqrCarver *r, gdouble *buffer, gint bias_factor)
135 return lqr_carver_bias_add_area(r, buffer, bias_factor, lqr_carver_get_width(r), lqr_carver_get_height(r), 0, 0);
138 /* LQR_PUBLIC */
139 LqrRetVal
140 lqr_carver_bias_add_rgb_area(LqrCarver *r, guchar *rgb, gint bias_factor, gint channels, gint width, gint height,
141 gint x_off, gint y_off)
143 gint x, y, k, c_channels;
144 gboolean has_alpha;
145 gint xt, yt;
146 gint wt, ht;
147 gint x0, y0, x1, y1, x2, y2;
148 gint sum;
149 gdouble bias;
151 LQR_CATCH_CANC(r);
153 if ((r->w != r->w0) || (r->w_start != r->w0) || (r->h != r->h0) || (r->h_start != r->h0)) {
154 LQR_CATCH(lqr_carver_flatten(r));
157 if (r->nrg_active == FALSE) {
158 LQR_CATCH(lqr_carver_init_energy_related(r));
161 if (bias_factor == 0) {
162 return LQR_OK;
165 if (r->bias == NULL) {
166 LQR_CATCH_MEM(r->bias = g_try_new0(gfloat, r->w * r->h));
169 has_alpha = (channels == 2 || channels >= 4);
170 c_channels = channels - (has_alpha ? 1 : 0);
172 wt = r->transposed ? r->h : r->w;
173 ht = r->transposed ? r->w : r->h;
175 x0 = MIN(0, x_off);
176 y0 = MIN(0, y_off);
177 x1 = MAX(0, x_off);
178 y1 = MAX(0, y_off);
179 x2 = MIN(wt, width + x_off);
180 y2 = MIN(ht, height + y_off);
182 for (y = 0; y < y2 - y1; y++) {
183 for (x = 0; x < x2 - x1; x++) {
184 sum = 0;
185 for (k = 0; k < c_channels; k++) {
186 sum += rgb[((y - y0) * width + (x - x0)) * channels + k];
189 bias = ((gdouble) bias_factor * sum / (2 * 255 * c_channels));
190 if (has_alpha) {
191 bias *= (gdouble) rgb[((y - y0) * width + (x - x0) + 1) * channels - 1] / 255;
194 xt = r->transposed ? y : x;
195 yt = r->transposed ? x : y;
197 r->bias[(yt + y1) * r->w0 + (xt + x1)] += (gfloat) bias;
201 r->nrg_uptodate = FALSE;
203 return LQR_OK;
206 /* LQR_PUBLIC */
207 LqrRetVal
208 lqr_carver_bias_add_rgb(LqrCarver *r, guchar *rgb, gint bias_factor, gint channels)
210 return lqr_carver_bias_add_rgb_area(r, rgb, bias_factor, channels, lqr_carver_get_width(r),
211 lqr_carver_get_height(r), 0, 0);
214 /**** END OF LQR_CARVER_BIAS CLASS FUNCTIONS ****/