~ubuntu-branches/ubuntu/saucy/digikam/saucy

« back to all changes in this revision

Viewing changes to core/libs/3rdparty/lqr/lqr_energy.c

  • Committer: Package Import Robot
  • Author(s): Felix Geyer, Rohan Garg, Philip Muškovac, Felix Geyer
  • Date: 2011-09-23 18:18:55 UTC
  • mfrom: (1.2.36 upstream)
  • Revision ID: package-import@ubuntu.com-20110923181855-ifs67wxkugshev9k
Tags: 2:2.1.1-0ubuntu1
[ Rohan Garg ]
* New upstream release (LP: #834190)
  - debian/control
    + Build with libqtwebkit-dev
 - debian/kipi-plugins-common
    + Install libkvkontakte required by kipi-plugins
 - debian/digikam
    + Install panoramagui

[ Philip Muškovac ]
* New upstream release
  - debian/control:
    + Add libcv-dev, libcvaux-dev, libhighgui-dev, libboost-graph1.46-dev,
      libksane-dev, libxml2-dev, libxslt-dev, libqt4-opengl-dev, libqjson-dev,
      libgpod-dev and libqca2-dev to build-deps
    + Add packages for kipi-plugins, libmediawiki, libkface, libkgeomap and
      libkvkontakte
  - debian/rules:
    + Don't build with gphoto2 since it doesn't build with it.
  - Add kubuntu_fix_test_linking.diff to fix linking of the dngconverter test
  - update install files
  - update kubuntu_01_mysqld_executable_name.diff for new cmake layout
    and rename to kubuntu_mysqld_executable_name.diff
* Fix typo in digikam-data description (LP: #804894)
* Fix Vcs links

[ Felix Geyer ]
* Move library data files to the new packages libkface-data, libkgeomap-data
  and libkvkontakte-data.
* Override version of the embedded library packages to 1.0~digikam<version>.
* Exclude the library packages from digikam-dbg to prevent file conflicts in
  the future.
* Call dh_install with --list-missing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* LiquidRescaling Library
 
2
 * Copyright (C) 2007-2009 Carlo Baldassi (the "Author") <carlobaldassi@gmail.com>.
 
3
 * All Rights Reserved.
 
4
 *
 
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
 
9
 *
 
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.
 
13
 
 
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.
 
18
 
 
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/>
 
21
 */
 
22
 
 
23
#ifdef HAVE_CONFIG_H
 
24
#  include <config.h>
 
25
#endif
 
26
 
 
27
#include <glib.h>
 
28
#include <math.h>
 
29
#include <lqr/lqr_base.h>
 
30
#include <lqr/lqr_gradient.h>
 
31
#include <lqr/lqr_rwindow.h>
 
32
#include <lqr/lqr_energy.h>
 
33
#include <lqr/lqr_progress_pub.h>
 
34
#include <lqr/lqr_cursor_pub.h>
 
35
#include <lqr/lqr_vmap.h>
 
36
#include <lqr/lqr_vmap_list.h>
 
37
#include <lqr/lqr_carver_list.h>
 
38
#include <lqr/lqr_carver.h>
 
39
 
 
40
#ifdef __LQR_DEBUG__
 
41
#include <stdio.h>
 
42
#include <assert.h>
 
43
#endif /* __LQR_DEBUG__ */
 
44
 
 
45
/* read normalised pixel value from
 
46
 * rgb buffer at the given index */
 
47
inline gdouble
 
48
lqr_pixel_get_norm(void *rgb, gint rgb_ind, LqrColDepth col_depth)
 
49
{
 
50
    switch (col_depth) {
 
51
        case LQR_COLDEPTH_8I:
 
52
            return (gdouble) AS_8I(rgb)[rgb_ind] / 0xFF;
 
53
        case LQR_COLDEPTH_16I:
 
54
            return (gdouble) AS_16I(rgb)[rgb_ind] / 0xFFFF;
 
55
        case LQR_COLDEPTH_32F:
 
56
            return (gdouble) AS_32F(rgb)[rgb_ind];
 
57
        case LQR_COLDEPTH_64F:
 
58
            return (gdouble) AS_64F(rgb)[rgb_ind];
 
59
        default:
 
60
#ifdef __LQR_DEBUG__
 
61
            assert(0);
 
62
#endif /* __LQR_DEBUG__ */
 
63
            return 0;
 
64
    }
 
65
}
 
66
 
 
67
/* write pixel from normalised value
 
68
 * in rgb buffer at the given index */
 
69
inline void
 
70
lqr_pixel_set_norm(gdouble val, void *rgb, gint rgb_ind, LqrColDepth col_depth)
 
71
{
 
72
    switch (col_depth) {
 
73
        case LQR_COLDEPTH_8I:
 
74
            AS_8I(rgb)[rgb_ind] = AS0_8I(val * 0xFF);
 
75
            return;
 
76
        case LQR_COLDEPTH_16I:
 
77
            AS_16I(rgb)[rgb_ind] = AS0_16I(val * 0xFFFF);
 
78
            return;
 
79
        case LQR_COLDEPTH_32F:
 
80
            AS_32F(rgb)[rgb_ind] = AS0_32F(val);
 
81
            return;
 
82
        case LQR_COLDEPTH_64F:
 
83
            AS_64F(rgb)[rgb_ind] = AS0_64F(val);
 
84
            return;
 
85
        default:
 
86
#ifdef __LQR_DEBUG__
 
87
            assert(0);
 
88
#endif /* __LQR_DEBUG__ */
 
89
            return;
 
90
    }
 
91
}
 
92
 
 
93
inline gdouble
 
94
lqr_pixel_get_rgbcol(void *rgb, gint rgb_ind, LqrColDepth col_depth, LqrImageType image_type, gint channel)
 
95
{
 
96
    gdouble black_fact = 0;
 
97
 
 
98
    switch (image_type) {
 
99
        case LQR_RGB_IMAGE:
 
100
        case LQR_RGBA_IMAGE:
 
101
            return lqr_pixel_get_norm(rgb, rgb_ind + channel, col_depth);
 
102
        case LQR_CMY_IMAGE:
 
103
            return 1. - lqr_pixel_get_norm(rgb, rgb_ind + channel, col_depth);
 
104
        case LQR_CMYK_IMAGE:
 
105
        case LQR_CMYKA_IMAGE:
 
106
            black_fact = 1 - lqr_pixel_get_norm(rgb, rgb_ind + 3, col_depth);
 
107
            return black_fact * (1. - (lqr_pixel_get_norm(rgb, rgb_ind + channel, col_depth)));
 
108
        case LQR_CUSTOM_IMAGE:
 
109
            return 0;
 
110
        default:
 
111
#ifdef __LQR_DEBUG__
 
112
            assert(0);
 
113
#endif /* __LQR_DEBUG__ */
 
114
            return 0;
 
115
    }
 
116
}
 
117
 
 
118
inline gdouble
 
119
lqr_carver_read_brightness_grey(LqrCarver *r, gint x, gint y)
 
120
{
 
121
    gint now = r->raw[y][x];
 
122
    gint rgb_ind = now * r->channels;
 
123
    return lqr_pixel_get_norm(r->rgb, rgb_ind, r->col_depth);
 
124
}
 
125
 
 
126
inline gdouble
 
127
lqr_carver_read_brightness_std(LqrCarver *r, gint x, gint y)
 
128
{
 
129
    gdouble red, green, blue;
 
130
    gint now = r->raw[y][x];
 
131
    gint rgb_ind = now * r->channels;
 
132
 
 
133
    red = lqr_pixel_get_rgbcol(r->rgb, rgb_ind, r->col_depth, r->image_type, 0);
 
134
    green = lqr_pixel_get_rgbcol(r->rgb, rgb_ind, r->col_depth, r->image_type, 1);
 
135
    blue = lqr_pixel_get_rgbcol(r->rgb, rgb_ind, r->col_depth, r->image_type, 2);
 
136
    return (red + green + blue) / 3;
 
137
}
 
138
 
 
139
gdouble
 
140
lqr_carver_read_brightness_custom(LqrCarver *r, gint x, gint y)
 
141
{
 
142
    gdouble sum = 0;
 
143
    gint k;
 
144
    gint has_alpha = (r->alpha_channel >= 0 ? 1 : 0);
 
145
    gint has_black = (r->black_channel >= 0 ? 1 : 0);
 
146
    guint col_channels = r->channels - has_alpha - has_black;
 
147
 
 
148
    gdouble black_fact = 0;
 
149
 
 
150
    gint now = r->raw[y][x];
 
151
 
 
152
    if (has_black) {
 
153
        black_fact = lqr_pixel_get_norm(r->rgb, now * r->channels + r->black_channel, r->col_depth);
 
154
    }
 
155
 
 
156
    for (k = 0; k < r->channels; k++) {
 
157
        if ((k != r->alpha_channel) && (k != r->black_channel)) {
 
158
            gdouble col = lqr_pixel_get_norm(r->rgb, now * r->channels + k, r->col_depth);
 
159
            sum += 1. - (1. - col) * (1. - black_fact);
 
160
        }
 
161
    }
 
162
 
 
163
    sum /= col_channels;
 
164
 
 
165
    if (has_black) {
 
166
        sum = 1 - sum;
 
167
    }
 
168
 
 
169
    return sum;
 
170
}
 
171
 
 
172
/* read average pixel value at x, y
 
173
 * for energy computation */
 
174
gdouble
 
175
lqr_carver_read_brightness(LqrCarver *r, gint x, gint y)
 
176
{
 
177
    gint has_alpha = (r->alpha_channel >= 0 ? 1 : 0);
 
178
    gdouble alpha_fact = 1;
 
179
 
 
180
    gint now = r->raw[y][x];
 
181
 
 
182
    gdouble bright = 0;
 
183
 
 
184
    switch (r->image_type) {
 
185
        case LQR_GREY_IMAGE:
 
186
        case LQR_GREYA_IMAGE:
 
187
            bright = lqr_carver_read_brightness_grey(r, x, y);
 
188
            break;
 
189
        case LQR_RGB_IMAGE:
 
190
        case LQR_RGBA_IMAGE:
 
191
        case LQR_CMY_IMAGE:
 
192
        case LQR_CMYK_IMAGE:
 
193
        case LQR_CMYKA_IMAGE:
 
194
            bright = lqr_carver_read_brightness_std(r, x, y);
 
195
            break;
 
196
        case LQR_CUSTOM_IMAGE:
 
197
            bright = lqr_carver_read_brightness_custom(r, x, y);
 
198
            break;
 
199
    }
 
200
 
 
201
    if (has_alpha) {
 
202
        alpha_fact = lqr_pixel_get_norm(r->rgb, now * r->channels + r->alpha_channel, r->col_depth);
 
203
    }
 
204
 
 
205
    return bright * alpha_fact;
 
206
}
 
207
 
 
208
inline gdouble
 
209
lqr_carver_read_luma_std(LqrCarver *r, gint x, gint y)
 
210
{
 
211
    gdouble red, green, blue;
 
212
    gint now = r->raw[y][x];
 
213
    gint rgb_ind = now * r->channels;
 
214
 
 
215
    red = lqr_pixel_get_rgbcol(r->rgb, rgb_ind, r->col_depth, r->image_type, 0);
 
216
    green = lqr_pixel_get_rgbcol(r->rgb, rgb_ind, r->col_depth, r->image_type, 1);
 
217
    blue = lqr_pixel_get_rgbcol(r->rgb, rgb_ind, r->col_depth, r->image_type, 2);
 
218
    return 0.2126 * red + 0.7152 * green + 0.0722 * blue;
 
219
}
 
220
 
 
221
gdouble
 
222
lqr_carver_read_luma(LqrCarver *r, gint x, gint y)
 
223
{
 
224
    gint has_alpha = (r->alpha_channel >= 0 ? 1 : 0);
 
225
    gdouble alpha_fact = 1;
 
226
 
 
227
    gint now = r->raw[y][x];
 
228
 
 
229
    gdouble bright = 0;
 
230
 
 
231
    switch (r->image_type) {
 
232
        case LQR_GREY_IMAGE:
 
233
        case LQR_GREYA_IMAGE:
 
234
            bright = lqr_carver_read_brightness_grey(r, x, y);
 
235
            break;
 
236
        case LQR_RGB_IMAGE:
 
237
        case LQR_RGBA_IMAGE:
 
238
        case LQR_CMY_IMAGE:
 
239
        case LQR_CMYK_IMAGE:
 
240
        case LQR_CMYKA_IMAGE:
 
241
            bright = lqr_carver_read_luma_std(r, x, y);
 
242
            break;
 
243
        case LQR_CUSTOM_IMAGE:
 
244
            bright = lqr_carver_read_brightness_custom(r, x, y);
 
245
            break;
 
246
    }
 
247
 
 
248
    if (has_alpha) {
 
249
        alpha_fact = lqr_pixel_get_norm(r->rgb, now * r->channels + r->alpha_channel, r->col_depth);
 
250
    }
 
251
 
 
252
    return bright * alpha_fact;
 
253
}
 
254
 
 
255
gdouble
 
256
lqr_carver_read_rgba(LqrCarver *r, gint x, gint y, gint channel)
 
257
{
 
258
    gint has_alpha = (r->alpha_channel >= 0 ? 1 : 0);
 
259
 
 
260
    gint now = r->raw[y][x];
 
261
 
 
262
#ifdef __LQR_DEBUG__
 
263
    assert(channel >= 0 && channel < 4);
 
264
#endif /* __LQR_DEBUG__ */
 
265
 
 
266
    if (channel < 3) {
 
267
        switch (r->image_type) {
 
268
            case LQR_GREY_IMAGE:
 
269
            case LQR_GREYA_IMAGE:
 
270
                return lqr_carver_read_brightness_grey(r, x, y);
 
271
            case LQR_RGB_IMAGE:
 
272
            case LQR_RGBA_IMAGE:
 
273
            case LQR_CMY_IMAGE:
 
274
            case LQR_CMYK_IMAGE:
 
275
            case LQR_CMYKA_IMAGE:
 
276
                return lqr_pixel_get_rgbcol(r->rgb, now * r->channels, r->col_depth, r->image_type, channel);
 
277
            case LQR_CUSTOM_IMAGE:
 
278
                return 0;
 
279
            default:
 
280
#ifdef __LQR_DEBUG__
 
281
                assert(0);
 
282
#endif /* __LQR_DEBUG__ */
 
283
                return 0;
 
284
        }
 
285
    } else if (has_alpha) {
 
286
        return lqr_pixel_get_norm(r->rgb, now * r->channels + r->alpha_channel, r->col_depth);
 
287
    } else {
 
288
        return 1;
 
289
    }
 
290
}
 
291
 
 
292
gdouble
 
293
lqr_carver_read_custom(LqrCarver *r, gint x, gint y, gint channel)
 
294
{
 
295
    gint now = r->raw[y][x];
 
296
 
 
297
    return lqr_pixel_get_norm(r->rgb, now * r->channels + channel, r->col_depth);
 
298
}
 
299
 
 
300
gdouble
 
301
lqr_carver_read_cached_std(LqrCarver *r, gint x, gint y)
 
302
{
 
303
    gint z0 = r->raw[y][x];
 
304
 
 
305
    return r->rcache[z0];
 
306
}
 
307
 
 
308
gdouble
 
309
lqr_carver_read_cached_rgba(LqrCarver *r, gint x, gint y, gint channel)
 
310
{
 
311
    gint z0 = r->raw[y][x];
 
312
 
 
313
    return r->rcache[z0 * 4 + channel];
 
314
}
 
315
 
 
316
gdouble
 
317
lqr_carver_read_cached_custom(LqrCarver *r, gint x, gint y, gint channel)
 
318
{
 
319
    gint z0 = r->raw[y][x];
 
320
 
 
321
    return r->rcache[z0 * r->channels + channel];
 
322
}
 
323
 
 
324
gfloat
 
325
lqr_energy_builtin_grad_all(gint x, gint y, gint img_width, gint img_height, LqrReadingWindow *rwindow, LqrGradFunc gf)
 
326
{
 
327
    gdouble gx, gy;
 
328
 
 
329
    gdouble (*bread_func) (LqrReadingWindow *, gint, gint);
 
330
 
 
331
    switch (lqr_rwindow_get_read_t(rwindow)) {
 
332
        case LQR_ER_BRIGHTNESS:
 
333
            bread_func = lqr_rwindow_read_bright;
 
334
            break;
 
335
        case LQR_ER_LUMA:
 
336
            bread_func = lqr_rwindow_read_luma;
 
337
            break;
 
338
        default:
 
339
#ifdef __LQR_DEBUG__
 
340
            assert(0);
 
341
#endif /* __LQR_DEBUG__ */
 
342
            return 0;
 
343
    }
 
344
 
 
345
    if (y == 0) {
 
346
        gy = bread_func(rwindow, 0, 1) - bread_func(rwindow, 0, 0);
 
347
    } else if (y < img_height - 1) {
 
348
        gy = (bread_func(rwindow, 0, 1) - bread_func(rwindow, 0, -1)) / 2;
 
349
    } else {
 
350
        gy = bread_func(rwindow, 0, 0) - bread_func(rwindow, 0, -1);
 
351
    }
 
352
 
 
353
    if (x == 0) {
 
354
        gx = bread_func(rwindow, 1, 0) - bread_func(rwindow, 0, 0);
 
355
    } else if (x < img_width - 1) {
 
356
        gx = (bread_func(rwindow, 1, 0) - bread_func(rwindow, -1, 0)) / 2;
 
357
    } else {
 
358
        gx = bread_func(rwindow, 0, 0) - bread_func(rwindow, -1, 0);
 
359
    }
 
360
 
 
361
    return gf(gx, gy);
 
362
}
 
363
 
 
364
gfloat
 
365
lqr_energy_builtin_grad_norm(gint x, gint y, gint img_width, gint img_height, LqrReadingWindow *rwindow,
 
366
                             gpointer extra_data)
 
367
{
 
368
    return lqr_energy_builtin_grad_all(x, y, img_width, img_height, rwindow, lqr_grad_norm);
 
369
}
 
370
 
 
371
gfloat
 
372
lqr_energy_builtin_grad_sumabs(gint x, gint y, gint img_width, gint img_height, LqrReadingWindow *rwindow,
 
373
                               gpointer extra_data)
 
374
{
 
375
    return lqr_energy_builtin_grad_all(x, y, img_width, img_height, rwindow, lqr_grad_sumabs);
 
376
}
 
377
 
 
378
gfloat
 
379
lqr_energy_builtin_grad_xabs(gint x, gint y, gint img_width, gint img_height, LqrReadingWindow *rwindow,
 
380
                             gpointer extra_data)
 
381
{
 
382
    return lqr_energy_builtin_grad_all(x, y, img_width, img_height, rwindow, lqr_grad_xabs);
 
383
}
 
384
 
 
385
gfloat
 
386
lqr_energy_builtin_null(gint x, gint y, gint img_width, gint img_height, LqrReadingWindow *rwindow, gpointer extra_data)
 
387
{
 
388
    return 0;
 
389
}
 
390
 
 
391
/* LQR_PUBLIC */
 
392
LqrRetVal
 
393
lqr_carver_set_energy_function_builtin(LqrCarver *r, LqrEnergyFuncBuiltinType ef_ind)
 
394
{
 
395
    switch (ef_ind) {
 
396
        case LQR_EF_GRAD_NORM:
 
397
            LQR_CATCH(lqr_carver_set_energy_function(r, lqr_energy_builtin_grad_norm, 1, LQR_ER_BRIGHTNESS, NULL));
 
398
            break;
 
399
        case LQR_EF_GRAD_SUMABS:
 
400
            LQR_CATCH(lqr_carver_set_energy_function(r, lqr_energy_builtin_grad_sumabs, 1, LQR_ER_BRIGHTNESS, NULL));
 
401
            break;
 
402
        case LQR_EF_GRAD_XABS:
 
403
            LQR_CATCH(lqr_carver_set_energy_function(r, lqr_energy_builtin_grad_xabs, 1, LQR_ER_BRIGHTNESS, NULL));
 
404
            break;
 
405
        case LQR_EF_LUMA_GRAD_NORM:
 
406
            LQR_CATCH(lqr_carver_set_energy_function(r, lqr_energy_builtin_grad_norm, 1, LQR_ER_LUMA, NULL));
 
407
            break;
 
408
        case LQR_EF_LUMA_GRAD_SUMABS:
 
409
            LQR_CATCH(lqr_carver_set_energy_function(r, lqr_energy_builtin_grad_sumabs, 1, LQR_ER_LUMA, NULL));
 
410
            break;
 
411
        case LQR_EF_LUMA_GRAD_XABS:
 
412
            LQR_CATCH(lqr_carver_set_energy_function(r, lqr_energy_builtin_grad_xabs, 1, LQR_ER_LUMA, NULL));
 
413
            break;
 
414
        case LQR_EF_NULL:
 
415
            LQR_CATCH(lqr_carver_set_energy_function(r, lqr_energy_builtin_null, 0, LQR_ER_BRIGHTNESS, NULL));
 
416
            break;
 
417
        default:
 
418
            return LQR_ERROR;
 
419
    }
 
420
 
 
421
    return LQR_OK;
 
422
}
 
423
 
 
424
/* LQR_PUBLIC */
 
425
LqrRetVal
 
426
lqr_carver_set_energy_function(LqrCarver *r, LqrEnergyFunc en_func, gint radius,
 
427
                               LqrEnergyReaderType reader_type, gpointer extra_data)
 
428
{
 
429
    LQR_CATCH_F(r->root == NULL);
 
430
 
 
431
    r->nrg = en_func;
 
432
    r->nrg_radius = radius;
 
433
    r->nrg_read_t = reader_type;
 
434
    r->nrg_extra_data = extra_data;
 
435
 
 
436
    g_free(r->rcache);
 
437
    r->rcache = NULL;
 
438
    r->nrg_uptodate = FALSE;
 
439
 
 
440
    lqr_rwindow_destroy(r->rwindow);
 
441
 
 
442
    if (reader_type == LQR_ER_CUSTOM) {
 
443
        LQR_CATCH_MEM(r->rwindow = lqr_rwindow_new_custom(radius, r->use_rcache, r->channels));
 
444
    } else {
 
445
        LQR_CATCH_MEM(r->rwindow = lqr_rwindow_new(radius, reader_type, r->use_rcache));
 
446
    }
 
447
 
 
448
    return LQR_OK;
 
449
}
 
450
 
 
451
gdouble *
 
452
lqr_carver_generate_rcache_bright(LqrCarver *r)
 
453
{
 
454
    gdouble *buffer;
 
455
    gint x, y;
 
456
    gint z0;
 
457
 
 
458
    LQR_TRY_N_N(buffer = g_try_new(gdouble, r->w0 * r->h0));
 
459
 
 
460
    for (y = 0; y < r->h; y++) {
 
461
        for (x = 0; x < r->w; x++) {
 
462
            z0 = r->raw[y][x];
 
463
            buffer[z0] = lqr_carver_read_brightness(r, x, y);
 
464
        }
 
465
    }
 
466
 
 
467
    return buffer;
 
468
}
 
469
 
 
470
gdouble *
 
471
lqr_carver_generate_rcache_luma(LqrCarver *r)
 
472
{
 
473
    gdouble *buffer;
 
474
    gint x, y;
 
475
    gint z0;
 
476
 
 
477
    LQR_TRY_N_N(buffer = g_try_new(gdouble, r->w0 * r->h0));
 
478
 
 
479
    for (y = 0; y < r->h; y++) {
 
480
        for (x = 0; x < r->w; x++) {
 
481
            z0 = r->raw[y][x];
 
482
            buffer[z0] = lqr_carver_read_luma(r, x, y);
 
483
        }
 
484
    }
 
485
 
 
486
    return buffer;
 
487
}
 
488
 
 
489
gdouble *
 
490
lqr_carver_generate_rcache_rgba(LqrCarver *r)
 
491
{
 
492
    gdouble *buffer;
 
493
    gint x, y, k;
 
494
    gint z0;
 
495
 
 
496
    LQR_TRY_N_N(buffer = g_try_new(gdouble, r->w0 * r->h0 * 4));
 
497
 
 
498
    for (y = 0; y < r->h; y++) {
 
499
        for (x = 0; x < r->w; x++) {
 
500
            z0 = r->raw[y][x];
 
501
            for (k = 0; k < 4; k++) {
 
502
                buffer[z0 * 4 + k] = lqr_carver_read_rgba(r, x, y, k);
 
503
            }
 
504
        }
 
505
    }
 
506
 
 
507
    return buffer;
 
508
}
 
509
 
 
510
gdouble *
 
511
lqr_carver_generate_rcache_custom(LqrCarver *r)
 
512
{
 
513
    gdouble *buffer;
 
514
    gint x, y, k;
 
515
    gint z0;
 
516
 
 
517
    LQR_TRY_N_N(buffer = g_try_new(gdouble, r->w0 * r->h0 * r->channels));
 
518
 
 
519
    for (y = 0; y < r->h; y++) {
 
520
        for (x = 0; x < r->w; x++) {
 
521
            z0 = r->raw[y][x];
 
522
            for (k = 0; k < r->channels; k++) {
 
523
                buffer[z0 * r->channels + k] = lqr_carver_read_custom(r, x, y, k);
 
524
            }
 
525
        }
 
526
    }
 
527
 
 
528
    return buffer;
 
529
}
 
530
 
 
531
gdouble *
 
532
lqr_carver_generate_rcache(LqrCarver *r)
 
533
{
 
534
#ifdef __LQR_DEBUG__
 
535
    assert(r->w == r->w_start - r->max_level + 1);
 
536
#endif /* __LQR_DEBUG__ */
 
537
 
 
538
    switch (r->nrg_read_t) {
 
539
        case LQR_ER_BRIGHTNESS:
 
540
            return lqr_carver_generate_rcache_bright(r);
 
541
        case LQR_ER_LUMA:
 
542
            return lqr_carver_generate_rcache_luma(r);
 
543
        case LQR_ER_RGBA:
 
544
            return lqr_carver_generate_rcache_rgba(r);
 
545
        case LQR_ER_CUSTOM:
 
546
            return lqr_carver_generate_rcache_custom(r);
 
547
        default:
 
548
#ifdef __LQR_DEBUG__
 
549
            assert(0);
 
550
#endif /* __LQR_DEBUG__ */
 
551
            return NULL;
 
552
    }
 
553
}
 
554
 
 
555
/* LQR_PUBLIC */
 
556
LqrRetVal
 
557
lqr_carver_get_energy(LqrCarver *r, gfloat *buffer, gint orientation)
 
558
{
 
559
    gint x, y;
 
560
    gint z0 = 0;
 
561
    gint w, h;
 
562
    gint buf_size;
 
563
    gint data;
 
564
    gfloat nrg;
 
565
    gfloat nrg_min = G_MAXFLOAT;
 
566
    gfloat nrg_max = 0;
 
567
 
 
568
    LQR_CATCH_F(orientation == 0 || orientation == 1);
 
569
    LQR_CATCH_CANC(r);
 
570
    LQR_CATCH_F(buffer != NULL);
 
571
 
 
572
    if (r->nrg_active == FALSE) {
 
573
        LQR_CATCH(lqr_carver_init_energy_related(r));
 
574
    }
 
575
 
 
576
    if (r->w != r->w_start - r->max_level + 1) {
 
577
#ifdef __LQR_DEBUG__
 
578
        assert(r->active);
 
579
#endif /* __LQR_DEBUG__ */
 
580
        LQR_CATCH(lqr_carver_flatten(r));
 
581
    }
 
582
 
 
583
    buf_size = r->w * r->h;
 
584
 
 
585
    if (orientation != lqr_carver_get_orientation(r)) {
 
586
        LQR_CATCH(lqr_carver_transpose(r));
 
587
    }
 
588
    LQR_CATCH(lqr_carver_build_emap(r));
 
589
 
 
590
    w = lqr_carver_get_width(r);
 
591
    h = lqr_carver_get_height(r);
 
592
 
 
593
    for (y = 0; y < h; y++) {
 
594
        for (x = 0; x < w; x++) {
 
595
            data = orientation == 0 ? r->raw[y][x] : r->raw[x][y];
 
596
            /* nrg = tanhf(r->en[data]); */
 
597
            nrg = LQR_SATURATE(r->en[data]);
 
598
            nrg_max = MAX(nrg_max, nrg);
 
599
            nrg_min = MIN(nrg_min, nrg);
 
600
            buffer[z0++] = nrg;
 
601
        }
 
602
    }
 
603
 
 
604
    if (nrg_max > nrg_min) {
 
605
        for (z0 = 0; z0 < buf_size; z0++) {
 
606
            buffer[z0] = (buffer[z0] - nrg_min) / (nrg_max - nrg_min);
 
607
        }
 
608
    }
 
609
 
 
610
    return LQR_OK;
 
611
}
 
612
 
 
613
/* LQR_PUBLIC */
 
614
LqrRetVal
 
615
lqr_carver_get_true_energy(LqrCarver *r, gfloat *buffer, gint orientation)
 
616
{
 
617
    gint x, y;
 
618
    gint z0 = 0;
 
619
    gint w, h;
 
620
    gint buf_size;
 
621
    gint data;
 
622
 
 
623
    LQR_CATCH_F(orientation == 0 || orientation == 1);
 
624
    LQR_CATCH_CANC(r);
 
625
    LQR_CATCH_F(buffer != NULL);
 
626
 
 
627
    if (r->nrg_active == FALSE) {
 
628
        LQR_CATCH(lqr_carver_init_energy_related(r));
 
629
    }
 
630
 
 
631
    if (r->w != r->w_start - r->max_level + 1) {
 
632
#ifdef __LQR_DEBUG__
 
633
        assert(r->active);
 
634
#endif /* __LQR_DEBUG__ */
 
635
        LQR_CATCH(lqr_carver_flatten(r));
 
636
    }
 
637
 
 
638
    buf_size = r->w * r->h;
 
639
 
 
640
    if (orientation != lqr_carver_get_orientation(r)) {
 
641
        LQR_CATCH(lqr_carver_transpose(r));
 
642
    }
 
643
    LQR_CATCH(lqr_carver_build_emap(r));
 
644
 
 
645
    w = lqr_carver_get_width(r);
 
646
    h = lqr_carver_get_height(r);
 
647
 
 
648
    for (y = 0; y < h; y++) {
 
649
        for (x = 0; x < w; x++) {
 
650
            data = orientation == 0 ? r->raw[y][x] : r->raw[x][y];
 
651
            /* nrg = tanhf(r->en[data]); */
 
652
            buffer[z0++] = r->en[data];
 
653
        }
 
654
    }
 
655
 
 
656
    return LQR_OK;
 
657
}
 
658
 
 
659
/* LQR_PUBLIC */
 
660
LqrRetVal
 
661
lqr_carver_get_energy_image(LqrCarver *r, void *buffer, gint orientation, LqrColDepth col_depth,
 
662
                            LqrImageType image_type)
 
663
{
 
664
    gint x, y;
 
665
    gint z0 = 0;
 
666
    gint w, h;
 
667
    gint buf_size;
 
668
    gint data;
 
669
    gfloat nrg;
 
670
    gfloat nrg_min = G_MAXFLOAT;
 
671
    gfloat nrg_max = 0;
 
672
    gfloat *aux_buffer;
 
673
    gint k;
 
674
    gint channels;
 
675
    gint alpha_channel, black_channel;
 
676
    gboolean has_alpha, has_black, col_model_is_additive;
 
677
 
 
678
    LQR_CATCH_F(orientation == 0 || orientation == 1);
 
679
    LQR_CATCH_CANC(r);
 
680
    LQR_CATCH_F(buffer != NULL);
 
681
 
 
682
    switch (image_type) {
 
683
        case LQR_GREY_IMAGE:
 
684
            channels = 1;
 
685
            alpha_channel = -1;
 
686
            black_channel = -1;
 
687
            col_model_is_additive = TRUE;
 
688
            break;
 
689
        case LQR_GREYA_IMAGE:
 
690
            channels = 2;
 
691
            alpha_channel = 1;
 
692
            black_channel = -1;
 
693
            col_model_is_additive = TRUE;
 
694
            break;
 
695
        case LQR_RGB_IMAGE:
 
696
            channels = 3;
 
697
            alpha_channel = -1;
 
698
            black_channel = -1;
 
699
            col_model_is_additive = TRUE;
 
700
            break;
 
701
        case LQR_RGBA_IMAGE:
 
702
            channels = 4;
 
703
            alpha_channel = 3;
 
704
            black_channel = -1;
 
705
            col_model_is_additive = TRUE;
 
706
            break;
 
707
        case LQR_CMY_IMAGE:
 
708
            channels = 3;
 
709
            alpha_channel = -1;
 
710
            black_channel = -1;
 
711
            col_model_is_additive = FALSE;
 
712
            break;
 
713
        case LQR_CMYK_IMAGE:
 
714
            channels = 4;
 
715
            alpha_channel = -1;
 
716
            black_channel = 3;
 
717
            col_model_is_additive = FALSE;
 
718
            break;
 
719
        case LQR_CMYKA_IMAGE:
 
720
            channels = 5;
 
721
            alpha_channel = 4;
 
722
            black_channel = 3;
 
723
            col_model_is_additive = FALSE;
 
724
            break;
 
725
        case LQR_CUSTOM_IMAGE:
 
726
        default:
 
727
            return LQR_ERROR;
 
728
    }
 
729
 
 
730
    has_alpha = (alpha_channel >= 0 ? TRUE : FALSE);
 
731
    has_black = (black_channel >= 0 ? TRUE : FALSE);
 
732
 
 
733
    if (r->nrg_active == FALSE) {
 
734
        LQR_CATCH(lqr_carver_init_energy_related(r));
 
735
    }
 
736
 
 
737
    if (r->w != r->w_start - r->max_level + 1) {
 
738
#ifdef __LQR_DEBUG__
 
739
        assert(r->active);
 
740
#endif /* __LQR_DEBUG__ */
 
741
        LQR_CATCH(lqr_carver_flatten(r));
 
742
    }
 
743
 
 
744
    buf_size = r->w * r->h;
 
745
 
 
746
    LQR_CATCH_MEM(aux_buffer = g_try_new(gfloat, buf_size));
 
747
 
 
748
    if (orientation != lqr_carver_get_orientation(r)) {
 
749
        LQR_CATCH(lqr_carver_transpose(r));
 
750
    }
 
751
    LQR_CATCH(lqr_carver_build_emap(r));
 
752
 
 
753
    w = lqr_carver_get_width(r);
 
754
    h = lqr_carver_get_height(r);
 
755
 
 
756
    for (y = 0; y < h; y++) {
 
757
        for (x = 0; x < w; x++) {
 
758
            data = orientation == 0 ? r->raw[y][x] : r->raw[x][y];
 
759
            /* nrg = tanhf(r->en[data]); */
 
760
            nrg = LQR_SATURATE(r->en[data]);
 
761
            nrg_max = MAX(nrg_max, nrg);
 
762
            nrg_min = MIN(nrg_min, nrg);
 
763
            aux_buffer[z0++] = nrg;
 
764
        }
 
765
    }
 
766
 
 
767
    for (z0 = 0; z0 < buf_size; z0++) {
 
768
        if (nrg_max > nrg_min) {
 
769
            nrg = (aux_buffer[z0] - nrg_min) / (nrg_max - nrg_min);
 
770
        } else {
 
771
            nrg = 0;
 
772
        }
 
773
        if (col_model_is_additive) {
 
774
            for (k = 0; k < channels; k++) {
 
775
                if (k != alpha_channel) {
 
776
                    lqr_pixel_set_norm(nrg, buffer, z0 * channels + k, col_depth);
 
777
                }
 
778
            }
 
779
        } else {
 
780
            nrg = 1 - nrg;
 
781
            if (has_black) {
 
782
                lqr_pixel_set_norm(nrg, buffer, z0 * channels + black_channel, col_depth);
 
783
                for (k = 0; k < channels; k++) {
 
784
                    if ((k != alpha_channel) && (k != black_channel)) {
 
785
                        lqr_pixel_set_norm(0.0, buffer, z0 * channels + k, col_depth);
 
786
                    }
 
787
                }
 
788
            } else {
 
789
                for (k = 0; k < channels; k++) {
 
790
                    if ((k != alpha_channel) && (k != black_channel)) {
 
791
                        lqr_pixel_set_norm(nrg, buffer, z0 * channels + k, col_depth);
 
792
                    }
 
793
                }
 
794
            }
 
795
        }
 
796
        if (has_alpha) {
 
797
            lqr_pixel_set_norm(1.0, buffer, z0 * channels + alpha_channel, col_depth);
 
798
        }
 
799
    }
 
800
 
 
801
    g_free(aux_buffer);
 
802
 
 
803
    return LQR_OK;
 
804
}