void loadImageFromSensor()

in source/isp/CameraIsp.h [766:834]


  void loadImageFromSensor(const std::vector<T>& inputImage) {
    // - sanity check config
    CHECK_NE(sensorWidth, 0);
    CHECK_NE(sensorHeight, 0);
    CHECK_EQ(sensorWidth % 2, 0);
    CHECK_EQ(sensorHeight % 2, 0);
    CHECK_EQ(inputImage.size(), sensorWidth * sensorHeight);
    CHECK_EQ(sensorBitsPerPixel, 8 * sizeof(T));

    cv::Mat_<T> intermediateImage(sensorHeight, sensorWidth);

    // - load directly if there's nothing to do
    if (!isPlanar && isLittleEndian == folly::kIsLittleEndian && isRowMajor) {
      memcpy(intermediateImage.data, inputImage.data(), sensorWidth * sensorHeight * sizeof(T));
      loadImage(intermediateImage);
      return;
    }

    // - setup problem dimensions and channel mappings
    int planeWidth = sensorWidth / 2;
    int planeHeight = sensorHeight / 2;
    int numPixelsPerPlane = planeWidth * planeHeight;
    std::array<int, 4> inputChannelOrderToBayerOrder = {
        {0, 1, 2, 3}}; // no-op for interleaved input
    if (isPlanar) {
      inputChannelOrderToBayerOrder = getPlaneOrderToBayerOrder();
    }

    // - inner loop helpers to byte swap, interleave, and re-index as needed
    //   - converts from linear index to a representation-independent (channel, row, column)
    //     pixel index
    auto pixelIndexFromInputLinearIndex = [=](int linearIndex) {
      int channel, row, col;
      if (isPlanar) {
        channel = linearIndex / numPixelsPerPlane;
        int linearIndexInPlane = linearIndex - channel * numPixelsPerPlane;
        std::tie(row, col) =
            math_util::linearToMatrixIndex(linearIndexInPlane, planeHeight, planeWidth, isRowMajor);
      } else {
        std::tie(row, col) =
            math_util::linearToMatrixIndex(linearIndex, sensorHeight, sensorWidth, isRowMajor);
        // Bayer pattern is always specified in row major, so compute the channel index accordingly
        channel = math_util::matrixToLinearIndex(std::make_tuple(row % 2, col % 2), 2, 2);
        row /= 2;
        col /= 2;
      }
      return std::make_tuple(channel, row, col);
    };

    //   - converts representation-independent (channel, row, column) pixel index to (row, column)
    //     matrix index in interleaved image
    auto outputInterleavedRawIndexFromPixelIndex = [=](std::tuple<int, int, int> pixelIndex) {
      int channel, row, col, bayerRow, bayerCol;
      std::tie(channel, row, col) = pixelIndex;
      channel = inputChannelOrderToBayerOrder[channel];
      std::tie(bayerRow, bayerCol) = math_util::linearToMatrixIndex(channel, 2, 2);
      return std::make_pair(2 * row + bayerRow, 2 * col + bayerCol);
    };

    auto byteSwap = isLittleEndian ? folly::Endian::little<T> : folly::Endian::big<T>;

    // - reorder and load image
    for (int k = 0; k < sensorWidth * sensorHeight; ++k) {
      auto pixelIndex = pixelIndexFromInputLinearIndex(k);
      auto rawIndex = outputInterleavedRawIndexFromPixelIndex(pixelIndex);
      intermediateImage(std::get<0>(rawIndex), std::get<1>(rawIndex)) = byteSwap(inputImage[k]);
    }
    loadImage(intermediateImage);
  }