1 /*
2 This file is part of darktable,
3 Copyright (C) 2014-2020 darktable developers.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <math.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 #if defined(__SSE__)
22 #include <xmmintrin.h>
23 #endif
24 #include <assert.h>
25 #include <stdlib.h>
26
27 #include "common/colorspaces_inline_conversions.h"
28 #include "common/darktable.h"
29 #include "common/histogram.h"
30 #include "develop/imageop.h"
31
32 #define S(V, params) ((params->mul) * ((float)V))
33 #define P(V, params) (CLAMP((V), 0, (params->bins_count - 1)))
34 #define PU(V, params) (MIN((V), (params->bins_count - 1)))
35 #define PS(V, params) (P(S(V, params), params))
36
37 //------------------------------------------------------------------------------
38
histogram_helper_cs_RAW_helper_process_pixel_float(const dt_dev_histogram_collection_params_t * const histogram_params,const float * pixel,uint32_t * histogram)39 inline static void histogram_helper_cs_RAW_helper_process_pixel_float(
40 const dt_dev_histogram_collection_params_t *const histogram_params, const float *pixel, uint32_t *histogram)
41 {
42 const uint32_t i = PS(*pixel, histogram_params);
43 histogram[4 * i]++;
44 }
45
histogram_helper_cs_RAW(const dt_dev_histogram_collection_params_t * const histogram_params,const void * pixel,uint32_t * histogram,int j,const dt_iop_order_iccprofile_info_t * const profile_info)46 inline static void histogram_helper_cs_RAW(const dt_dev_histogram_collection_params_t *const histogram_params,
47 const void *pixel, uint32_t *histogram, int j,
48 const dt_iop_order_iccprofile_info_t *const profile_info)
49 {
50 const dt_histogram_roi_t *roi = histogram_params->roi;
51 const float *input = (float *)pixel + roi->width * j + roi->crop_x;
52 for(int i = 0; i < roi->width - roi->crop_width - roi->crop_x; i++, input++)
53 {
54 histogram_helper_cs_RAW_helper_process_pixel_float(histogram_params, input, histogram);
55 }
56 }
57
58 //------------------------------------------------------------------------------
59
60 // WARNING: you must ensure that bins_count is big enough
histogram_helper_cs_RAW_helper_process_pixel_uint16(const dt_dev_histogram_collection_params_t * const histogram_params,const uint16_t * pixel,uint32_t * histogram)61 inline static void histogram_helper_cs_RAW_helper_process_pixel_uint16(
62 const dt_dev_histogram_collection_params_t *const histogram_params, const uint16_t *pixel, uint32_t *histogram)
63 {
64 const uint16_t i = PU(*pixel, histogram_params);
65 histogram[4 * i]++;
66 }
67
dt_histogram_helper_cs_RAW_uint16(const dt_dev_histogram_collection_params_t * const histogram_params,const void * pixel,uint32_t * histogram,int j,const dt_iop_order_iccprofile_info_t * const profile_info)68 inline void dt_histogram_helper_cs_RAW_uint16(const dt_dev_histogram_collection_params_t *const histogram_params,
69 const void *pixel, uint32_t *histogram, int j,
70 const dt_iop_order_iccprofile_info_t *const profile_info)
71 {
72 const dt_histogram_roi_t *roi = histogram_params->roi;
73 uint16_t *in = (uint16_t *)pixel + roi->width * j + roi->crop_x;
74
75 // process pixels
76 for(int i = 0; i < roi->width - roi->crop_width - roi->crop_x; i++, in++)
77 histogram_helper_cs_RAW_helper_process_pixel_uint16(histogram_params, in, histogram);
78 }
79
80 //------------------------------------------------------------------------------
81
histogram_helper_cs_rgb_helper_process_pixel_float(const dt_dev_histogram_collection_params_t * const histogram_params,const float * pixel,uint32_t * histogram)82 inline static void __attribute__((__unused__)) histogram_helper_cs_rgb_helper_process_pixel_float(
83 const dt_dev_histogram_collection_params_t *const histogram_params, const float *pixel, uint32_t *histogram)
84 {
85 const uint32_t R = PS(pixel[0], histogram_params);
86 const uint32_t G = PS(pixel[1], histogram_params);
87 const uint32_t B = PS(pixel[2], histogram_params);
88 histogram[4 * R]++;
89 histogram[4 * G + 1]++;
90 histogram[4 * B + 2]++;
91 }
92
histogram_helper_cs_rgb_helper_process_pixel_float_compensated(const dt_dev_histogram_collection_params_t * const histogram_params,const float * pixel,uint32_t * histogram,const dt_iop_order_iccprofile_info_t * const profile_info)93 inline static void __attribute__((__unused__)) histogram_helper_cs_rgb_helper_process_pixel_float_compensated(
94 const dt_dev_histogram_collection_params_t *const histogram_params, const float *pixel, uint32_t *histogram,
95 const dt_iop_order_iccprofile_info_t *const profile_info)
96 {
97 const float rgb[3] = { dt_ioppr_compensate_middle_grey(pixel[0], profile_info),
98 dt_ioppr_compensate_middle_grey(pixel[1], profile_info),
99 dt_ioppr_compensate_middle_grey(pixel[2], profile_info) };
100 const uint32_t R = PS(rgb[0], histogram_params);
101 const uint32_t G = PS(rgb[1], histogram_params);
102 const uint32_t B = PS(rgb[2], histogram_params);
103 histogram[4 * R]++;
104 histogram[4 * G + 1]++;
105 histogram[4 * B + 2]++;
106 }
107
108 #if defined(__SSE2__)
histogram_helper_cs_rgb_helper_process_pixel_m128(const dt_dev_histogram_collection_params_t * const histogram_params,const float * pixel,uint32_t * histogram)109 inline static void histogram_helper_cs_rgb_helper_process_pixel_m128(
110 const dt_dev_histogram_collection_params_t *const histogram_params, const float *pixel, uint32_t *histogram)
111 {
112 const __m128 scale = _mm_set1_ps(histogram_params->mul);
113 const __m128 val_min = _mm_setzero_ps();
114 const __m128 val_max = _mm_set1_ps(histogram_params->bins_count - 1);
115
116 assert(dt_is_aligned(pixel, 16));
117 const __m128 input = _mm_load_ps(pixel);
118 const __m128 scaled = _mm_mul_ps(input, scale);
119 const __m128 clamped = _mm_max_ps(_mm_min_ps(scaled, val_max), val_min);
120
121 const __m128i indexes = _mm_cvtps_epi32(clamped);
122
123 __m128i values __attribute__((aligned(16)));
124 _mm_store_si128(&values, indexes);
125
126 const uint32_t *valuesi = (uint32_t *)(&values);
127
128 histogram[4 * valuesi[0]]++;
129 histogram[4 * valuesi[1] + 1]++;
130 histogram[4 * valuesi[2] + 2]++;
131 }
132
histogram_helper_cs_rgb_helper_process_pixel_m128_compensated(const dt_dev_histogram_collection_params_t * const histogram_params,const float * pixel,uint32_t * histogram,const dt_iop_order_iccprofile_info_t * const profile_info)133 inline static void histogram_helper_cs_rgb_helper_process_pixel_m128_compensated(
134 const dt_dev_histogram_collection_params_t *const histogram_params, const float *pixel, uint32_t *histogram,
135 const dt_iop_order_iccprofile_info_t *const profile_info)
136 {
137 const __m128 rgb = { dt_ioppr_compensate_middle_grey(pixel[0], profile_info),
138 dt_ioppr_compensate_middle_grey(pixel[1], profile_info),
139 dt_ioppr_compensate_middle_grey(pixel[2], profile_info), 1.f };
140 const __m128 scale = _mm_set1_ps(histogram_params->mul);
141 const __m128 val_min = _mm_setzero_ps();
142 const __m128 val_max = _mm_set1_ps(histogram_params->bins_count - 1);
143
144 assert(dt_is_aligned(pixel, 16));
145 const __m128 input = rgb;
146 const __m128 scaled = _mm_mul_ps(input, scale);
147 const __m128 clamped = _mm_max_ps(_mm_min_ps(scaled, val_max), val_min);
148
149 const __m128i indexes = _mm_cvtps_epi32(clamped);
150
151 __m128i values __attribute__((aligned(16)));
152 _mm_store_si128(&values, indexes);
153
154 const uint32_t *valuesi = (uint32_t *)(&values);
155
156 histogram[4 * valuesi[0]]++;
157 histogram[4 * valuesi[1] + 1]++;
158 histogram[4 * valuesi[2] + 2]++;
159 }
160 #endif
161
histogram_helper_cs_rgb(const dt_dev_histogram_collection_params_t * const histogram_params,const void * pixel,uint32_t * histogram,int j,const dt_iop_order_iccprofile_info_t * const profile_info)162 inline static void histogram_helper_cs_rgb(const dt_dev_histogram_collection_params_t *const histogram_params,
163 const void *pixel, uint32_t *histogram, int j,
164 const dt_iop_order_iccprofile_info_t *const profile_info)
165 {
166 const dt_histogram_roi_t *roi = histogram_params->roi;
167 float *in = (float *)pixel + 4 * (roi->width * j + roi->crop_x);
168
169 // process aligned pixels with SSE
170 for(int i = 0; i < roi->width - roi->crop_width - roi->crop_x; i++, in += 4)
171 {
172 if(darktable.codepath.OPENMP_SIMD)
173 histogram_helper_cs_rgb_helper_process_pixel_float(histogram_params, in, histogram);
174 #if defined(__SSE2__)
175 else if(darktable.codepath.SSE2)
176 histogram_helper_cs_rgb_helper_process_pixel_m128(histogram_params, in, histogram);
177 #endif
178 else
179 dt_unreachable_codepath();
180 }
181 }
182
histogram_helper_cs_rgb_compensated(const dt_dev_histogram_collection_params_t * const histogram_params,const void * pixel,uint32_t * histogram,int j,const dt_iop_order_iccprofile_info_t * const profile_info)183 inline static void histogram_helper_cs_rgb_compensated(const dt_dev_histogram_collection_params_t *const histogram_params,
184 const void *pixel, uint32_t *histogram, int j,
185 const dt_iop_order_iccprofile_info_t *const profile_info)
186 {
187 const dt_histogram_roi_t *roi = histogram_params->roi;
188 float *in = (float *)pixel + 4 * (roi->width * j + roi->crop_x);
189
190 // process aligned pixels with SSE
191 for(int i = 0; i < roi->width - roi->crop_width - roi->crop_x; i++, in += 4)
192 {
193 if(darktable.codepath.OPENMP_SIMD)
194 histogram_helper_cs_rgb_helper_process_pixel_float_compensated(histogram_params, in, histogram, profile_info);
195 #if defined(__SSE2__)
196 else if(darktable.codepath.SSE2)
197 histogram_helper_cs_rgb_helper_process_pixel_m128_compensated(histogram_params, in, histogram, profile_info);
198 #endif
199 else
200 dt_unreachable_codepath();
201 }
202 }
203
204 //------------------------------------------------------------------------------
205
histogram_helper_cs_Lab_helper_process_pixel_float(const dt_dev_histogram_collection_params_t * const histogram_params,const float * pixel,uint32_t * histogram)206 inline static void __attribute__((__unused__)) histogram_helper_cs_Lab_helper_process_pixel_float(
207 const dt_dev_histogram_collection_params_t *const histogram_params, const float *pixel, uint32_t *histogram)
208 {
209 const float Lv = pixel[0];
210 const float av = pixel[1];
211 const float bv = pixel[2];
212 const float max = histogram_params->bins_count - 1;
213 const uint32_t L = CLAMP(histogram_params->mul / 100.0f * (Lv), 0, max);
214 const uint32_t a = CLAMP(histogram_params->mul / 256.0f * (av + 128.0f), 0, max);
215 const uint32_t b = CLAMP(histogram_params->mul / 256.0f * (bv + 128.0f), 0, max);
216 histogram[4 * L]++;
217 histogram[4 * a + 1]++;
218 histogram[4 * b + 2]++;
219 }
220
221 #if defined(__SSE2__)
histogram_helper_cs_Lab_helper_process_pixel_m128(const dt_dev_histogram_collection_params_t * const histogram_params,const float * pixel,uint32_t * histogram)222 inline static void histogram_helper_cs_Lab_helper_process_pixel_m128(
223 const dt_dev_histogram_collection_params_t *const histogram_params, const float *pixel, uint32_t *histogram)
224 {
225 const float fscale = histogram_params->mul;
226
227 const __m128 shift = _mm_set_ps(0.0f, 128.0f, 128.0f, 0.0f);
228 const __m128 scale = _mm_set_ps(fscale / 1.0f, fscale / 256.0f, fscale / 256.0f, fscale / 100.0f);
229 const __m128 val_min = _mm_setzero_ps();
230 const __m128 val_max = _mm_set1_ps(histogram_params->bins_count - 1);
231
232 assert(dt_is_aligned(pixel, 16));
233 const __m128 input = _mm_load_ps(pixel);
234 const __m128 shifted = _mm_add_ps(input, shift);
235 const __m128 scaled = _mm_mul_ps(shifted, scale);
236 const __m128 clamped = _mm_max_ps(_mm_min_ps(scaled, val_max), val_min);
237
238 const __m128i indexes = _mm_cvtps_epi32(clamped);
239
240 __m128i values __attribute__((aligned(16)));
241 _mm_store_si128(&values, indexes);
242
243 const uint32_t *valuesi = (uint32_t *)(&values);
244
245 histogram[4 * valuesi[0]]++;
246 histogram[4 * valuesi[1] + 1]++;
247 histogram[4 * valuesi[2] + 2]++;
248 }
249 #endif
250
histogram_helper_cs_Lab(const dt_dev_histogram_collection_params_t * const histogram_params,const void * pixel,uint32_t * histogram,int j,const dt_iop_order_iccprofile_info_t * const profile_info)251 inline static void histogram_helper_cs_Lab(const dt_dev_histogram_collection_params_t *const histogram_params,
252 const void *pixel, uint32_t *histogram, int j,
253 const dt_iop_order_iccprofile_info_t *const profile_info)
254 {
255 const dt_histogram_roi_t *roi = histogram_params->roi;
256 float *in = (float *)pixel + 4 * (roi->width * j + roi->crop_x);
257
258 // process aligned pixels with SSE
259 for(int i = 0; i < roi->width - roi->crop_width - roi->crop_x; i++, in += 4)
260 {
261 if(darktable.codepath.OPENMP_SIMD)
262 histogram_helper_cs_Lab_helper_process_pixel_float(histogram_params, in, histogram);
263 #if defined(__SSE2__)
264 else if(darktable.codepath.SSE2)
265 histogram_helper_cs_Lab_helper_process_pixel_m128(histogram_params, in, histogram);
266 #endif
267 else
268 dt_unreachable_codepath();
269 }
270 }
271
histogram_helper_cs_Lab_LCh_helper_process_pixel_float(const dt_dev_histogram_collection_params_t * const histogram_params,const float * pixel,uint32_t * histogram)272 inline static void __attribute__((__unused__)) histogram_helper_cs_Lab_LCh_helper_process_pixel_float(
273 const dt_dev_histogram_collection_params_t *const histogram_params, const float *pixel, uint32_t *histogram)
274 {
275 float LCh[3];
276 dt_Lab_2_LCH(pixel, LCh);
277 const uint32_t L = PS((LCh[0] / 100.f), histogram_params);
278 const uint32_t C = PS((LCh[1] / (128.0f * sqrtf(2.0f))), histogram_params);
279 const uint32_t h = PS(LCh[2], histogram_params);
280 histogram[4 * L]++;
281 histogram[4 * C + 1]++;
282 histogram[4 * h + 2]++;
283 }
284
histogram_helper_cs_Lab_LCh(const dt_dev_histogram_collection_params_t * const histogram_params,const void * pixel,uint32_t * histogram,int j,const dt_iop_order_iccprofile_info_t * const profile_info)285 inline static void histogram_helper_cs_Lab_LCh(const dt_dev_histogram_collection_params_t *const histogram_params,
286 const void *pixel, uint32_t *histogram, int j,
287 const dt_iop_order_iccprofile_info_t *const profile_info)
288 {
289 const dt_histogram_roi_t *roi = histogram_params->roi;
290 float *in = (float *)pixel + 4 * (roi->width * j + roi->crop_x);
291
292 // TODO: process aligned pixels with SSE
293 for(int i = 0; i < roi->width - roi->crop_width - roi->crop_x; i++, in += 4)
294 {
295 // if(darktable.codepath.OPENMP_SIMD)
296 histogram_helper_cs_Lab_LCh_helper_process_pixel_float(histogram_params, in, histogram);
297 //#if defined(__SSE2__)
298 // else if(darktable.codepath.SSE2)
299 // histogram_helper_cs_Lab_helper_process_pixel_m128(histogram_params, in, histogram);
300 //#endif
301 // else
302 // dt_unreachable_codepath();
303 }
304 }
305
306 //==============================================================================
307
dt_histogram_worker(dt_dev_histogram_collection_params_t * const histogram_params,dt_dev_histogram_stats_t * histogram_stats,const void * const pixel,uint32_t ** histogram,const dt_worker Worker,const dt_iop_order_iccprofile_info_t * const profile_info)308 void dt_histogram_worker(dt_dev_histogram_collection_params_t *const histogram_params,
309 dt_dev_histogram_stats_t *histogram_stats, const void *const pixel,
310 uint32_t **histogram, const dt_worker Worker,
311 const dt_iop_order_iccprofile_info_t *const profile_info)
312 {
313 const int nthreads = omp_get_max_threads();
314
315 const size_t bins_total = (size_t)4 * histogram_params->bins_count;
316 const size_t buf_size = bins_total * sizeof(uint32_t);
317 void *partial_hists = calloc(nthreads, buf_size);
318
319 if(histogram_params->mul == 0) histogram_params->mul = (double)(histogram_params->bins_count - 1);
320
321 const dt_histogram_roi_t *const roi = histogram_params->roi;
322
323 #ifdef _OPENMP
324 #pragma omp parallel for default(none) \
325 dt_omp_firstprivate(histogram_params, pixel, Worker, profile_info, bins_total, roi) \
326 shared(partial_hists) \
327 schedule(static)
328 #endif
329 for(int j = roi->crop_y; j < roi->height - roi->crop_height; j++)
330 {
331 uint32_t *thread_hist = (uint32_t *)partial_hists + bins_total * omp_get_thread_num();
332 Worker(histogram_params, pixel, thread_hist, j, profile_info);
333 }
334
335 #ifdef _OPENMP
336 *histogram = realloc(*histogram, buf_size);
337 memset(*histogram, 0, buf_size);
338 uint32_t *hist = *histogram;
339
340 #pragma omp parallel for default(none) \
341 dt_omp_firstprivate(nthreads, bins_total) \
342 shared(hist, partial_hists) \
343 schedule(static)
344 for(size_t k = 0; k < bins_total; k++)
345 {
346 for(size_t n = 0; n < nthreads; n++)
347 {
348 const uint32_t *thread_hist = (uint32_t *)partial_hists + bins_total * n;
349 hist[k] += thread_hist[k];
350 }
351 }
352 #else
353 *histogram = realloc(*histogram, buf_size);
354 memmove(*histogram, partial_hists, buf_size);
355 #endif
356 free(partial_hists);
357
358 histogram_stats->bins_count = histogram_params->bins_count;
359 histogram_stats->pixels = (roi->width - roi->crop_width - roi->crop_x)
360 * (roi->height - roi->crop_height - roi->crop_y);
361 }
362
363 //------------------------------------------------------------------------------
364
dt_histogram_helper(dt_dev_histogram_collection_params_t * histogram_params,dt_dev_histogram_stats_t * histogram_stats,const dt_iop_colorspace_type_t cst,const dt_iop_colorspace_type_t cst_to,const void * pixel,uint32_t ** histogram,const int compensate_middle_grey,const dt_iop_order_iccprofile_info_t * const profile_info)365 void dt_histogram_helper(dt_dev_histogram_collection_params_t *histogram_params,
366 dt_dev_histogram_stats_t *histogram_stats, const dt_iop_colorspace_type_t cst,
367 const dt_iop_colorspace_type_t cst_to, const void *pixel, uint32_t **histogram,
368 const int compensate_middle_grey, const dt_iop_order_iccprofile_info_t *const profile_info)
369 {
370 switch(cst)
371 {
372 case iop_cs_RAW:
373 dt_histogram_worker(histogram_params, histogram_stats, pixel, histogram, histogram_helper_cs_RAW, profile_info);
374 histogram_stats->ch = 1u;
375 break;
376
377 case iop_cs_rgb:
378 if(compensate_middle_grey && profile_info)
379 dt_histogram_worker(histogram_params, histogram_stats, pixel, histogram, histogram_helper_cs_rgb_compensated, profile_info);
380 else
381 dt_histogram_worker(histogram_params, histogram_stats, pixel, histogram, histogram_helper_cs_rgb, profile_info);
382 histogram_stats->ch = 3u;
383 break;
384
385 case iop_cs_Lab:
386 default:
387 if(cst_to != iop_cs_LCh)
388 dt_histogram_worker(histogram_params, histogram_stats, pixel, histogram, histogram_helper_cs_Lab, profile_info);
389 else
390 dt_histogram_worker(histogram_params, histogram_stats, pixel, histogram, histogram_helper_cs_Lab_LCh, profile_info);
391 histogram_stats->ch = 3u;
392 break;
393 }
394 }
395
dt_histogram_max_helper(const dt_dev_histogram_stats_t * const histogram_stats,const dt_iop_colorspace_type_t cst,const dt_iop_colorspace_type_t cst_to,uint32_t ** histogram,uint32_t * histogram_max)396 void dt_histogram_max_helper(const dt_dev_histogram_stats_t *const histogram_stats,
397 const dt_iop_colorspace_type_t cst, const dt_iop_colorspace_type_t cst_to,
398 uint32_t **histogram, uint32_t *histogram_max)
399 {
400 if(*histogram == NULL) return;
401 histogram_max[0] = histogram_max[1] = histogram_max[2] = histogram_max[3] = 0;
402 uint32_t *hist = *histogram;
403 switch(cst)
404 {
405 case iop_cs_RAW:
406 for(int k = 0; k < 4 * histogram_stats->bins_count; k += 4)
407 histogram_max[0] = histogram_max[0] > hist[k] ? histogram_max[0] : hist[k];
408 break;
409
410 case iop_cs_rgb:
411 // don't count <= 0 pixels
412 for(int k = 4; k < 4 * histogram_stats->bins_count; k += 4)
413 histogram_max[0] = histogram_max[0] > hist[k] ? histogram_max[0] : hist[k];
414 for(int k = 5; k < 4 * histogram_stats->bins_count; k += 4)
415 histogram_max[1] = histogram_max[1] > hist[k] ? histogram_max[1] : hist[k];
416 for(int k = 6; k < 4 * histogram_stats->bins_count; k += 4)
417 histogram_max[2] = histogram_max[2] > hist[k] ? histogram_max[2] : hist[k];
418 for(int k = 7; k < 4 * histogram_stats->bins_count; k += 4)
419 histogram_max[3] = histogram_max[3] > hist[k] ? histogram_max[3] : hist[k];
420 break;
421
422 case iop_cs_Lab:
423 default:
424 if(cst_to == iop_cs_LCh)
425 {
426 // don't count <= 0 pixels
427 for(int k = 4; k < 4 * histogram_stats->bins_count; k += 4)
428 histogram_max[0] = histogram_max[0] > hist[k] ? histogram_max[0] : hist[k];
429 for(int k = 5; k < 4 * histogram_stats->bins_count; k += 4)
430 histogram_max[1] = histogram_max[1] > hist[k] ? histogram_max[1] : hist[k];
431 for(int k = 6; k < 4 * histogram_stats->bins_count; k += 4)
432 histogram_max[2] = histogram_max[2] > hist[k] ? histogram_max[2] : hist[k];
433 for(int k = 7; k < 4 * histogram_stats->bins_count; k += 4)
434 histogram_max[3] = histogram_max[3] > hist[k] ? histogram_max[3] : hist[k];
435 }
436 else
437 {
438 // don't count <= 0 pixels in L
439 for(int k = 4; k < 4 * histogram_stats->bins_count; k += 4)
440 histogram_max[0] = histogram_max[0] > hist[k] ? histogram_max[0] : hist[k];
441
442 // don't count <= -128 and >= +128 pixels in a and b
443 for(int k = 5; k < 4 * (histogram_stats->bins_count - 1); k += 4)
444 histogram_max[1] = histogram_max[1] > hist[k] ? histogram_max[1] : hist[k];
445 for(int k = 6; k < 4 * (histogram_stats->bins_count - 1); k += 4)
446 histogram_max[2] = histogram_max[2] > hist[k] ? histogram_max[2] : hist[k];
447 }
448 break;
449 }
450 }
451
452 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
453 // vim: shiftwidth=2 expandtab tabstop=2 cindent
454 // kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
455