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