1 /*
2 * Copyright 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <img_utils/DngUtils.h>
18
19 namespace android {
20 namespace img_utils {
21
OpcodeListBuilder()22 OpcodeListBuilder::OpcodeListBuilder() : mCount(0), mOpList(), mEndianOut(&mOpList, BIG) {
23 if(mEndianOut.open() != OK) {
24 ALOGE("%s: Open failed.", __FUNCTION__);
25 }
26 }
27
~OpcodeListBuilder()28 OpcodeListBuilder::~OpcodeListBuilder() {
29 if(mEndianOut.close() != OK) {
30 ALOGE("%s: Close failed.", __FUNCTION__);
31 }
32 }
33
getSize() const34 size_t OpcodeListBuilder::getSize() const {
35 return mOpList.getSize() + sizeof(mCount);
36 }
37
getCount() const38 uint32_t OpcodeListBuilder::getCount() const {
39 return mCount;
40 }
41
buildOpList(uint8_t * buf) const42 status_t OpcodeListBuilder::buildOpList(uint8_t* buf) const {
43 uint32_t count = convertToBigEndian(mCount);
44 memcpy(buf, &count, sizeof(count));
45 memcpy(buf + sizeof(count), mOpList.getArray(), mOpList.getSize());
46 return OK;
47 }
48
addGainMapsForMetadata(uint32_t lsmWidth,uint32_t lsmHeight,uint32_t activeAreaTop,uint32_t activeAreaLeft,uint32_t activeAreaBottom,uint32_t activeAreaRight,CfaLayout cfa,const float * lensShadingMap)49 status_t OpcodeListBuilder::addGainMapsForMetadata(uint32_t lsmWidth,
50 uint32_t lsmHeight,
51 uint32_t activeAreaTop,
52 uint32_t activeAreaLeft,
53 uint32_t activeAreaBottom,
54 uint32_t activeAreaRight,
55 CfaLayout cfa,
56 const float* lensShadingMap) {
57 uint32_t activeAreaWidth = activeAreaRight - activeAreaLeft;
58 uint32_t activeAreaHeight = activeAreaBottom - activeAreaTop;
59 double spacingV = 1.0 / lsmHeight;
60 double spacingH = 1.0 / lsmWidth;
61
62 float redMap[lsmWidth * lsmHeight];
63 float greenEvenMap[lsmWidth * lsmHeight];
64 float greenOddMap[lsmWidth * lsmHeight];
65 float blueMap[lsmWidth * lsmHeight];
66
67 size_t lsmMapSize = lsmWidth * lsmHeight * 4;
68
69 // Split lens shading map channels into separate arrays
70 size_t j = 0;
71 for (size_t i = 0; i < lsmMapSize; i += 4, ++j) {
72 redMap[j] = lensShadingMap[i + LSM_R_IND];
73 greenEvenMap[j] = lensShadingMap[i + LSM_GE_IND];
74 greenOddMap[j] = lensShadingMap[i + LSM_GO_IND];
75 blueMap[j] = lensShadingMap[i + LSM_B_IND];
76 }
77
78 uint32_t redTop = 0;
79 uint32_t redLeft = 0;
80 uint32_t greenEvenTop = 0;
81 uint32_t greenEvenLeft = 1;
82 uint32_t greenOddTop = 1;
83 uint32_t greenOddLeft = 0;
84 uint32_t blueTop = 1;
85 uint32_t blueLeft = 1;
86
87 switch(cfa) {
88 case CFA_RGGB:
89 redTop = 0;
90 redLeft = 0;
91 greenEvenTop = 0;
92 greenEvenLeft = 1;
93 greenOddTop = 1;
94 greenOddLeft = 0;
95 blueTop = 1;
96 blueLeft = 1;
97 break;
98 case CFA_GRBG:
99 redTop = 0;
100 redLeft = 1;
101 greenEvenTop = 0;
102 greenEvenLeft = 0;
103 greenOddTop = 1;
104 greenOddLeft = 1;
105 blueTop = 1;
106 blueLeft = 0;
107 break;
108 case CFA_GBRG:
109 redTop = 1;
110 redLeft = 0;
111 greenEvenTop = 0;
112 greenEvenLeft = 0;
113 greenOddTop = 1;
114 greenOddLeft = 1;
115 blueTop = 0;
116 blueLeft = 1;
117 break;
118 case CFA_BGGR:
119 redTop = 1;
120 redLeft = 1;
121 greenEvenTop = 0;
122 greenEvenLeft = 1;
123 greenOddTop = 1;
124 greenOddLeft = 0;
125 blueTop = 0;
126 blueLeft = 0;
127 break;
128 default:
129 ALOGE("%s: Unknown CFA layout %d", __FUNCTION__, cfa);
130 return BAD_VALUE;
131 }
132
133 status_t err = addGainMap(/*top*/redTop,
134 /*left*/redLeft,
135 /*bottom*/activeAreaHeight - 1,
136 /*right*/activeAreaWidth - 1,
137 /*plane*/0,
138 /*planes*/1,
139 /*rowPitch*/2,
140 /*colPitch*/2,
141 /*mapPointsV*/lsmHeight,
142 /*mapPointsH*/lsmWidth,
143 /*mapSpacingV*/spacingV,
144 /*mapSpacingH*/spacingH,
145 /*mapOriginV*/0,
146 /*mapOriginH*/0,
147 /*mapPlanes*/1,
148 /*mapGains*/redMap);
149 if (err != OK) return err;
150
151 err = addGainMap(/*top*/greenEvenTop,
152 /*left*/greenEvenLeft,
153 /*bottom*/activeAreaHeight - 1,
154 /*right*/activeAreaWidth - 1,
155 /*plane*/0,
156 /*planes*/1,
157 /*rowPitch*/2,
158 /*colPitch*/2,
159 /*mapPointsV*/lsmHeight,
160 /*mapPointsH*/lsmWidth,
161 /*mapSpacingV*/spacingV,
162 /*mapSpacingH*/spacingH,
163 /*mapOriginV*/0,
164 /*mapOriginH*/0,
165 /*mapPlanes*/1,
166 /*mapGains*/greenEvenMap);
167 if (err != OK) return err;
168
169 err = addGainMap(/*top*/greenOddTop,
170 /*left*/greenOddLeft,
171 /*bottom*/activeAreaHeight - 1,
172 /*right*/activeAreaWidth - 1,
173 /*plane*/0,
174 /*planes*/1,
175 /*rowPitch*/2,
176 /*colPitch*/2,
177 /*mapPointsV*/lsmHeight,
178 /*mapPointsH*/lsmWidth,
179 /*mapSpacingV*/spacingV,
180 /*mapSpacingH*/spacingH,
181 /*mapOriginV*/0,
182 /*mapOriginH*/0,
183 /*mapPlanes*/1,
184 /*mapGains*/greenOddMap);
185 if (err != OK) return err;
186
187 err = addGainMap(/*top*/blueTop,
188 /*left*/blueLeft,
189 /*bottom*/activeAreaHeight - 1,
190 /*right*/activeAreaWidth - 1,
191 /*plane*/0,
192 /*planes*/1,
193 /*rowPitch*/2,
194 /*colPitch*/2,
195 /*mapPointsV*/lsmHeight,
196 /*mapPointsH*/lsmWidth,
197 /*mapSpacingV*/spacingV,
198 /*mapSpacingH*/spacingH,
199 /*mapOriginV*/0,
200 /*mapOriginH*/0,
201 /*mapPlanes*/1,
202 /*mapGains*/blueMap);
203 return err;
204 }
205
addGainMap(uint32_t top,uint32_t left,uint32_t bottom,uint32_t right,uint32_t plane,uint32_t planes,uint32_t rowPitch,uint32_t colPitch,uint32_t mapPointsV,uint32_t mapPointsH,double mapSpacingV,double mapSpacingH,double mapOriginV,double mapOriginH,uint32_t mapPlanes,const float * mapGains)206 status_t OpcodeListBuilder::addGainMap(uint32_t top,
207 uint32_t left,
208 uint32_t bottom,
209 uint32_t right,
210 uint32_t plane,
211 uint32_t planes,
212 uint32_t rowPitch,
213 uint32_t colPitch,
214 uint32_t mapPointsV,
215 uint32_t mapPointsH,
216 double mapSpacingV,
217 double mapSpacingH,
218 double mapOriginV,
219 double mapOriginH,
220 uint32_t mapPlanes,
221 const float* mapGains) {
222
223 uint32_t opcodeId = GAIN_MAP_ID;
224
225 status_t err = mEndianOut.write(&opcodeId, 0, 1);
226 if (err != OK) return err;
227
228 uint8_t version[] = {1, 3, 0, 0};
229 err = mEndianOut.write(version, 0, NELEMS(version));
230 if (err != OK) return err;
231
232 // Do not include optional flag for preview, as this can have a large effect on the output.
233 uint32_t flags = FLAG_OPTIONAL;
234
235 err = mEndianOut.write(&flags, 0, 1);
236 if (err != OK) return err;
237
238 const uint32_t NUMBER_INT_ARGS = 11;
239 const uint32_t NUMBER_DOUBLE_ARGS = 4;
240
241 uint32_t totalSize = NUMBER_INT_ARGS * sizeof(uint32_t) + NUMBER_DOUBLE_ARGS * sizeof(double) +
242 mapPointsV * mapPointsH * mapPlanes * sizeof(float);
243
244 err = mEndianOut.write(&totalSize, 0, 1);
245 if (err != OK) return err;
246
247 // Batch writes as much as possible
248 uint32_t settings1[] = { top,
249 left,
250 bottom,
251 right,
252 plane,
253 planes,
254 rowPitch,
255 colPitch,
256 mapPointsV,
257 mapPointsH };
258
259 err = mEndianOut.write(settings1, 0, NELEMS(settings1));
260 if (err != OK) return err;
261
262 double settings2[] = { mapSpacingV,
263 mapSpacingH,
264 mapOriginV,
265 mapOriginH };
266
267 err = mEndianOut.write(settings2, 0, NELEMS(settings2));
268 if (err != OK) return err;
269
270 err = mEndianOut.write(&mapPlanes, 0, 1);
271 if (err != OK) return err;
272
273 err = mEndianOut.write(mapGains, 0, mapPointsV * mapPointsH * mapPlanes);
274 if (err != OK) return err;
275
276 mCount++;
277
278 return OK;
279 }
280
281 } /*namespace img_utils*/
282 } /*namespace android*/
283