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 22 OpcodeListBuilder::OpcodeListBuilder() : mCount(0), mOpList(), mEndianOut(&mOpList, BIG) { 23 if(mEndianOut.open() != OK) { 24 ALOGE("%s: Open failed.", __FUNCTION__); 25 } 26 } 27 28 OpcodeListBuilder::~OpcodeListBuilder() { 29 if(mEndianOut.close() != OK) { 30 ALOGE("%s: Close failed.", __FUNCTION__); 31 } 32 } 33 34 size_t OpcodeListBuilder::getSize() const { 35 return mOpList.getSize() + sizeof(mCount); 36 } 37 38 uint32_t OpcodeListBuilder::getCount() const { 39 return mCount; 40 } 41 42 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 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 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