/src/libraw/src/preprocessing/subtract_black.cpp
Line | Count | Source |
1 | | /* -*- C++ -*- |
2 | | * Copyright 2019-2025 LibRaw LLC (info@libraw.org) |
3 | | * |
4 | | |
5 | | LibRaw is free software; you can redistribute it and/or modify |
6 | | it under the terms of the one of two licenses as you choose: |
7 | | |
8 | | 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 |
9 | | (See file LICENSE.LGPL provided in LibRaw distribution archive for details). |
10 | | |
11 | | 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 |
12 | | (See file LICENSE.CDDL provided in LibRaw distribution archive for details). |
13 | | |
14 | | */ |
15 | | |
16 | | #include "../../internal/libraw_cxx_defs.h" |
17 | | |
18 | | int LibRaw::subtract_black() |
19 | 0 | { |
20 | 0 | adjust_bl(); |
21 | 0 | return subtract_black_internal(); |
22 | 0 | } |
23 | | |
24 | | int LibRaw::subtract_black_internal() |
25 | 7.80k | { |
26 | 7.80k | CHECK_ORDER_LOW(LIBRAW_PROGRESS_RAW2_IMAGE); |
27 | | |
28 | 7.80k | try |
29 | 7.80k | { |
30 | 7.80k | if (!is_phaseone_compressed() && |
31 | 7.06k | (C.cblack[0] || C.cblack[1] || C.cblack[2] || C.cblack[3] || |
32 | 2.74k | (C.cblack[4] && C.cblack[5]))) |
33 | 4.43k | { |
34 | 4.43k | int cblk[4], i; |
35 | 22.1k | for (i = 0; i < 4; i++) |
36 | 17.7k | cblk[i] = C.cblack[i]; |
37 | | |
38 | 4.43k | int size = S.iheight * S.iwidth; |
39 | 4.43k | int dmax = 0; |
40 | 4.43k | if (C.cblack[4] && C.cblack[5]) |
41 | 1.89k | { |
42 | 77.4M | for (unsigned q = 0; q < (unsigned)size; q++) |
43 | 77.4M | { |
44 | 387M | for (unsigned c = 0; c < 4; c++) |
45 | 309M | { |
46 | 309M | int val = imgdata.image[q][c]; |
47 | 309M | val -= C.cblack[6 + q / S.iwidth % C.cblack[4] * C.cblack[5] + |
48 | 309M | q % S.iwidth % C.cblack[5]]; |
49 | 309M | val -= cblk[c]; |
50 | 309M | imgdata.image[q][c] = CLIP(val); |
51 | 309M | if (dmax < val) dmax = val; |
52 | 309M | } |
53 | 77.4M | } |
54 | 1.89k | } |
55 | 2.54k | else |
56 | 2.54k | { |
57 | 142M | for (unsigned q = 0; q < (unsigned)size; q++) |
58 | 142M | { |
59 | 712M | for (unsigned c = 0; c < 4; c++) |
60 | 569M | { |
61 | 569M | int val = imgdata.image[q][c]; |
62 | 569M | val -= cblk[c]; |
63 | 569M | imgdata.image[q][c] = CLIP(val); |
64 | 569M | if (dmax < val) dmax = val; |
65 | 569M | } |
66 | 142M | } |
67 | 2.54k | } |
68 | 4.43k | C.data_maximum = dmax & 0xffff; |
69 | 4.43k | C.maximum -= C.black; |
70 | 4.43k | ZERO(C.cblack); // Yeah, we used cblack[6+] values too! |
71 | 4.43k | C.black = 0; |
72 | 4.43k | } |
73 | 3.36k | else |
74 | 3.36k | { |
75 | | // Nothing to Do, maximum is already calculated, black level is 0, so no |
76 | | // change only calculate channel maximum; |
77 | 3.36k | int idx; |
78 | 3.36k | ushort *p = (ushort *)imgdata.image; |
79 | 3.36k | int dmax = 0; |
80 | 412M | for (idx = 0; idx < S.iheight * S.iwidth * 4; idx++) |
81 | 412M | if (dmax < p[idx]) |
82 | 10.4k | dmax = p[idx]; |
83 | 3.36k | C.data_maximum = dmax; |
84 | 3.36k | } |
85 | 7.80k | return 0; |
86 | 7.80k | } |
87 | 7.80k | catch (const LibRaw_exceptions& err) |
88 | 7.80k | { |
89 | 0 | EXCEPTION_HANDLER(err); |
90 | 0 | } |
91 | 7.80k | } |