Home | History | Annotate | Download | only in src
      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