int64_t TiffFrame::rawABGRFrameBytes()

in src/tiffFrame.cpp [277:335]


int64_t TiffFrame::rawABGRFrameBytes(uint8_t *rawMemory,
int64_t memorySize) {
  // tiff frame data in native format is jpeg encoded.
  // uncompress and return # of bytes read.
  // return 0 if error occures.
  uint64_t abgrBufferSizeRead = 0;
  const uint64_t width = frameWidth();
  const uint64_t height = frameHeight();
  if (tiffDirectory()->isJpegCompressed() &&
       jpegUtil::decodeJpeg(width, height, jpegDecodeColorSpace(),
                            rawCompressedBytes_.get(),
                            rawCompressedBytesSize_, rawMemory, memorySize)) {
      abgrBufferSizeRead = width * height * 4;
  } else if (tiffDirectory()->isJpeg2kCompressed()) {
    // if frame is jpeg2000 decode using OpenSlide.
     openslide_t *opslide = tiffFile()->getOpenslidePtr();
    int32_t level = tiffFile()->getOpenslideLevel();
    uint32_t * buf_bytes = reinterpret_cast<uint32_t*>(rawMemory);
    int64_t levelZeroWidth;
    int64_t levelZeroHeight;
    openslide_get_level0_dimensions(opslide, &levelZeroWidth, &levelZeroHeight);
    int64_t levelZeroX = locationX() * levelZeroWidth /
                         tiffDirectory()->imageWidth();
    int64_t levelZeroY = locationY() * levelZeroHeight /
                         tiffDirectory()->imageHeight();
    openslide_read_region(opslide, buf_bytes, levelZeroX, levelZeroY,
                          level, width, height);
    if (openslide_get_error(opslide)) {
       BOOST_LOG_TRIVIAL(error) << openslide_get_error(opslide);
       throw 1;
    }
    // Uncommon, openslide C++ API premults RGB by alpha.
    // if alpha is not zero reverse transform to get RGB
    // https://openslide.org/api/openslide_8h.html
    const uint32_t size = width * height;
    for (uint32_t x = 0; x < size; ++x) {
      const uint32_t pixel = buf_bytes[x];  // Pixel value to be downsampled
      const int alpha = pixel >> 24;            // Alpha value of pixel
      if (alpha == 0) {                         // If transparent skip
        continue;
      }
      uint32_t red = (pixel >> 16) & 0xFF;  // Get RGB Bytes
      uint32_t green = (pixel >> 8) & 0xFF;
      uint32_t blue = pixel & 0xFF;
      // Uncommon, openslide C++ API premults RGB by alpha.
      // if alpha is not zero reverse transform to get RGB
      // https://openslide.org/api/openslide_8h.html
      if (alpha != 0xFF) {
        red = red * 255 / alpha;
        green = green * 255 / alpha;
        blue = blue * 255 / alpha;
      }
      // Swap red and blue channel for dicom compatiability.
      buf_bytes[x] = (alpha << 24) | (blue << 16) | (green << 8) | red;
    }
  }
  decReadCounter();
  return abgrBufferSizeRead;
}