void DcmFileDraft::write()

in src/dcmFileDraft.cpp [131:273]


void DcmFileDraft::write(DcmOutputStream* outStream) {
  std::unique_ptr<DcmPixelData> pixelData =
      std::make_unique<DcmPixelData>(DCM_PixelData);
  DcmOffsetList offsetList;
  std::unique_ptr<DcmPixelSequence> compressedPixelSequence =
      std::make_unique<DcmPixelSequence>(DCM_PixelSequenceTag);
  std::unique_ptr<DcmPixelItem> offsetTable =
      std::make_unique<DcmPixelItem>(DcmTag(DCM_Item, EVR_OB));
  compressedPixelSequence->insert(offsetTable.release());
  DcmtkImgDataInfo imgInfo;
  std::vector<uint8_t> frames;

  // What channel components in represent.
  // Values = RGB or YBR_FULL_422.
  // value determined by compression JPEG2000 & RAW = RGB
  // Jpeg compressed = YBR_FULL_422
  // TiffFrame jpeg compressed = RGB or YBR_FULL_422 value
  // dependent on encoding of jpeg.
  std::string framePhotoMetrIntrp = "";

  // Text description of rough image processing which generated frames.
  std::string derivationDescription = "";

  // Actual size of imaging for frames writen in dicom file.
  // Summed across frames.  Used to calculate imaging compression ratio.
  int64_t imagingSizeBytes = 0;

  const int64_t  frameDataSize = framesData_.size();
  // get general state from first frame.
  if (frameDataSize > 0) {
    const int firstFrameNumber = 0;
    while (!framesData_[firstFrameNumber]->isDone()) {
      boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
    }
    Frame *frame = framesData_[firstFrameNumber].get();
    framePhotoMetrIntrp =
                    std::move(static_cast<std::string>(frame->photoMetrInt()));
    derivationDescription = sourceImageDescription_ +
                            frame->derivationDescription();
    // maximum length of derivationDescription vr type is 1024 chars
    // subtracting 1 to allow for null.
    derivationDescription = std::move(derivationDescription.substr(0, 1023));
  }

  // if image is encoded as raw compute total size of all frames and reserve
  // memory to speed addition of data to raw write buffer.
  uint64_t totalFrameByteSize = 0;
  for (size_t frameNumber = 0; frameNumber < frameDataSize; ++frameNumber) {
    while (!framesData_[frameNumber]->isDone()) {
      boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
    }
    Frame *frame = framesData_[frameNumber].get();
    if (frame->hasDcmPixelItem()) {
      break;  // Jpeg or JPeg2000 encoded data.
    } else {
      totalFrameByteSize += frame->dicomFrameBytesSize();
    }
  }
  if (totalFrameByteSize > 0) {
    frames.reserve(totalFrameByteSize);
  }

  for (size_t frameNumber = 0; frameNumber < frameDataSize; ++frameNumber) {
    while (!framesData_[frameNumber]->isDone()) {
      boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
    }
    Frame *frame = framesData_[frameNumber].get();
    if (frame->hasDcmPixelItem()) {  // Jpeg or JPeg2000 encoded data.
      // if currentSize is odd this will be fixed by dcmtk during
      // DcmOtherByteOtherWord::write()
      // passing ownership of frame pointer to dcmtk.
      compressedPixelSequence->insert(frame->dcmPixelItem());
      // 8 bytes extra for header
      Uint32 currentSize = frame->dicomFrameBytesSize() + 8;
      // odd frame size requires padding, i.e. last fragment uses odd
      // length pixel item
      if (currentSize & 1) {
        currentSize++;
      }
      offsetList.push_back(currentSize);
    } else {
      frames.insert(frames.end(), frame->dicomFrameBytes(),
                    frame->dicomFrameBytes() + frame->dicomFrameBytesSize());
      frame->clearDicomMem();  // memory copied clear.
    }
    imagingSizeBytes += frame->dicomFrameBytesSize();
  }
  if (imagingSizeBytes > 0) {
    // compute uncompressed size realtive to frames written in file. Possible
    // to split frames across multiple files.
    const double uncompressed = static_cast<double>(3 * frameWidth_ *
                                                frameHeight_ * frameDataSize);
    const double storedImageSize = static_cast<double>(imagingSizeBytes);
    const double compression_ratio = uncompressed / storedImageSize;
    imgInfo.compressionRatio = std::to_string(compression_ratio);
    imgInfo.derivationDescription = derivationDescription;
  } else {
    imgInfo.compressionRatio = "";
    imgInfo.derivationDescription = "";
  }

  switch (compression_) {
    case JPEG:
      imgInfo.transSyn = EXS_JPEGProcess1;

      imgInfo.photoMetrInt = (framePhotoMetrIntrp.empty()) ?
                                  "YBR_FULL_422" : framePhotoMetrIntrp.c_str();
      pixelData->putOriginalRepresentation(imgInfo.transSyn, nullptr,
                                           compressedPixelSequence.release());
      break;
    case JPEG2000:
      imgInfo.transSyn = EXS_JPEG2000LosslessOnly;
      imgInfo.photoMetrInt = (framePhotoMetrIntrp.empty()) ?
                                           "RGB" : framePhotoMetrIntrp.c_str();
      pixelData->putOriginalRepresentation(imgInfo.transSyn, nullptr,
                                           compressedPixelSequence.release());
      break;
    default:
      imgInfo.transSyn = EXS_LittleEndianExplicit;
      imgInfo.photoMetrInt = (framePhotoMetrIntrp.empty()) ?
                                           "RGB" : framePhotoMetrIntrp.c_str();
      pixelData->putUint8Array(&frames[0], frames.size());
  }
  imgInfo.samplesPerPixel = 3;
  imgInfo.planConf = 0;
  imgInfo.rows = frameHeight_;
  imgInfo.cols = frameWidth_;
  imgInfo.bitsAlloc = 8;
  imgInfo.bitsStored = 8;
  imgInfo.highBit = 7;
  imgInfo.pixelRepr = 0;
  const int64_t batchSize = fileFrameCount();
  const int64_t numberOfFrames = batchSize + prior_batch_frames_;
  uint32_t rowSize = 1 + ((imageWidth_ - 1) / frameWidth_);
  uint32_t totalNumberOfFrames =
      rowSize * (1 + ((imageHeight_ - 1) / frameHeight_));
  DcmtkUtils::startConversion(
      imageHeight_, imageWidth_, rowSize, studyId_, seriesId_, imageName_,
      std::move(pixelData), imgInfo, batchSize, row_, column_, instanceNumber_,
      downsample_, batchNumber_, numberOfFrames - batchSize,
      totalNumberOfFrames, tiled_, additionalTags_, firstLevelWidthMm_,
      firstLevelHeightMm_, outStream);
}