/* --*- c -*-- * Copyright (C) 2016 Enrico Scholz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include "bayer2rgb.h" #include "bayer2rgb-internal.h" static inline unsigned int avg1(unsigned int max, int sft, unsigned int a) { unsigned int res = a; if (sft) { res += (1u << (sft-1)); res >>= sft; } if (sft && res > max) res = max; return res; } static inline unsigned int avg2(bool do_round, unsigned int max, int sft, unsigned int a) { unsigned int res; if (!do_round) res = a / 2; else res = (a + 1) / 2; if (sft) { res += (1u << (sft-1)); res >>= sft; } if ((sft || do_round) && res > max) res = max; return res; } static inline unsigned int avg4(bool do_round, unsigned int max, int sft, unsigned int a) { unsigned int res; if (!do_round) res = a / 4; else res = (a + 2) / 4; if (sft) { res += (1u << (sft-1)); res >>= sft; } if ((sft || do_round) && res > max) res = max; return res; } static inline uint32_t get_row32(void const *addr) { return *(uint32_t*)addr; } static inline uint64_t get_row64(void const *addr) { return *(uint32_t*)addr; } #define read_row(_dst, _addr) do { \ switch (sizeof *(_dst)) { \ case 4: *(_dst) = get_row32(_addr); break; \ case 8: *(_dst) = get_row64(_addr); break; \ default: abort(); \ } \ } while (0) #if __BYTE_ORDER == __LITTLE_ENDIAN # define get_col(_row, _col) \ (((_row) >> ((_col) * (sizeof(_row)/4 * 8))) & \ ((1u << (sizeof(_row)/4 * 8)) - 1u)) #else # define get_col(_row, _col) \ (((_row) >> ((3 - (_col)) * (sizeof(_row)/4 * 8))) & \ ((1u << (sizeof(_row)/4 * 8)) - 1u)) #endif #if 1 # define do_prefetch(_addr, _lvl) do { } while (0) #else # define do_prefetch(_addr, _lvl) do { \ __builtin_prefetch(((void const *)(_addr)) + 128, 0, (_lvl)); \ } while (0) #endif void bayer2rgb_convert_c_opt(struct image_in const *input, struct image_out const *output, struct image_conversion_info *info) { static unsigned int const border = 2; int handled = -1; #define CONVERT_BODY "convert-c-opt_0.inc.h" switch (input->type) { case BAYER_GBRG: #include "convert-c-body-outer.inc.h" break; case BAYER_RGGB: case BAYER_GRBG: case BAYER_BGGR: set_fallback_reason(info, "c-opt: unsupported input format"); handled = 0; break; default: abort(); } if (!handled) bayer2rgb_convert_dumb(input, output, info); }