Real Fresh Real Fresh - 3 months ago 27
C++ Question

GDCM ImageWriter write progress

I use gdcm::ImageWriter to write multiframe image into dicom file. To do this I use next code:

gdcm::ImageWriter writer;
writer.SetFileName(m_filePath.toLatin1().data());

auto &image = writer.GetImage();
image.SetPixelFormat(m_currentFormat);
image.SetPhotometricInterpretation(gdcm::PhotometricInterpretation::MONOCHROME2);
image.SetTransferSyntax(gdcm::TransferSyntax::ExplicitVRLittleEndian);
image.SetDimension(0, m_width);
image.SetDimension(1, m_height);
image.SetDimension(2, 0);

gdcm::DataElement pixelDataElement(gdcm::Tag(0x07fe, 0x0010));
pixelDataElement.SetByteValue(m_imageData.data(), m_imageDataSize);
image.SetDataElement(pixelDataElement);

writer.GetFile().SetDataSet(m_data);
return writer.Write();


How can I extract write operation progress by using callback or something other? Also, is it possible to interrupt write operation?

Answer

I didn't found any solution to solve this problem, so I created custom std::streambuf like the next one:

class interruptable_streambuf : public std::streambuf {
public:
    // constructors, destructors, setters, getters, etc.
    ... 

    // interrupts stream write operation with exception
    void interrupt() { m_interrupted.store(true); }

    // returns is stream interrupted
    bool interrupted() const { return m_interrupted.load() }

    // returns current file write carriage position
    long offset() const { return m_offset.load(); }

protected:
    virtual std::streamsize xsputn(const char *s, std::streamsize num) {
        assert(m_fileHandle != nullptr);

        std::streamsize writeSize = 0;
        for (std::streamsize offset = 0; offset < num; ) {
            if (!m_interrupted.load()) {
                std::streamsize dataSize = std::min<long>(num - offset, m_sectorSize);
                writeSize += fwrite(s + offset, sizeof(char), dataSize, m_fileHandle);
                offset += dataSize;

                m_offset.store(ftell(m_fileHandle));
                if (fflush(m_fileHandle) == EOF) {
                    return -1;
                }
            } else {
                throw InterruptedException();
            }
        }

        return writeSize;
    }

    // other protected members and methods
    ... 

private:
    // interrupted flag
    std::atomic_bool m_interrupted;

    // current 
    std::atomic_long m_offset;
}

Before executing gdcm::ImageWriter::Write I set standard std::stream initialized with my interruptable streambuf realization, ex:

interruptable_streambuf myBuffer(file_name);
std::ostream stream(&myBuffer);

gdcm::ImageWriter writer;
writer.SetStream(stream);

// setting ImageWriter data
...

if (writer.Write() && !myBuffer.interrupted()) {
    return true;
} else {
    return false;
}

Every time after writing data by gdcm::ImageWriter::Write() I must check if my interruptable_streambuf was interrupted, because, even if it throws an exception, Write() method returns true.