Skip to content

SGProcessingManager/src/datasplitter/ImageSplitter.cpp

Namespaces

Name
sgns
sgns::sgprocessing

Defines

Name
STB_IMAGE_IMPLEMENTATION
STB_IMAGE_WRITE_IMPLEMENTATION

Macros Documentation

define STB_IMAGE_IMPLEMENTATION

#define STB_IMAGE_IMPLEMENTATION 

define STB_IMAGE_WRITE_IMPLEMENTATION

#define STB_IMAGE_WRITE_IMPLEMENTATION 

Source code

#include <datasplitter/ImageSplitter.hpp>
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <openssl/sha.h> // For SHA256_DIGEST_LENGTH
#include <gsl/span>

namespace sgns::sgprocessing
{
    ImageSplitter::ImageSplitter( const std::vector<uint8_t> &buffer,
                                  uint64_t                    blockstride,
                                  uint64_t                    blocklinestride,
                                  uint64_t                    blocklen,
                                  int                         channels ) :
        blockstride_( blockstride ), blocklinestride_( blocklinestride ), blocklen_( blocklen ), channels_( channels )
    {
        // Set inputImage and imageSize from the provided buffer
        //inputImage = reinterpret_cast<const unsigned char*>(buffer.data());

        inputImage = reinterpret_cast<const unsigned char *>( buffer.data() );
        imageSize  = buffer.size();
        SplitImageData();
    }

    std::vector<uint8_t> ImageSplitter::GetPart( int part )
    {
        return splitparts_.at( part );
    }

    size_t ImageSplitter::GetPartByCid( const std::vector<uint8_t> &cid ) const
    {
        //Find the index of cid in cids_
        auto it = std::find( cids_.begin(), cids_.end(), cid );
        if ( it == cids_.end() )
        {
            //CID not found
            return -1;
        }

        //Find index in splitparts_ corresponding to cid
        size_t index = std::distance( cids_.begin(), it );

        //Return the data
        if ( index < splitparts_.size() )
        {
            return index;
        }
        //Index out of range
        return -1;
    }

    void ImageSplitter::SplitImageData()
    {
        // Check if imageSize is evenly divisible by blocklen_
        if ( imageSize % blocklen_ != 0 )
        {
            throw std::invalid_argument( "Image size is not evenly divisible by block length" );
        }

        for ( uint64_t i = 0; i < imageSize; i += blocklen_ )
        {
            std::vector<uint8_t> chunkBuffer( blocklen_ );
            int      rowsdone      = ( i / ( blocklen_ * ( ( blockstride_ + blocklinestride_ ) / blockstride_ ) ) );
            uint32_t bufferoffset  = 0 + ( i / blocklen_ * blockstride_ );
            bufferoffset          -= ( blockstride_ + blocklinestride_ ) * rowsdone;
            bufferoffset          += rowsdone * ( blocklen_ * ( ( blockstride_ + blocklinestride_ ) / blockstride_ ) );
            //std::cout << "buffer offset:  " << bufferoffset << std::endl;
            for ( uint64_t size = 0; size < blocklen_; size += blockstride_ )
            {
                auto chunkData = inputImage + bufferoffset;
                std::memcpy( chunkBuffer.data() + ( size ), chunkData, blockstride_ );
                bufferoffset += blockstride_ + blocklinestride_;
            }
            //std::string filename = "chunk_" + std::to_string(i) + ".png";
            //int result = stbi_write_png(filename.c_str(), blockstride_ / 4, blocklen_ / blockstride_, 4, chunkBuffer.data(), blockstride_);
            //if (!result) {
            //    std::cerr << "Error writing PNG file: " << filename << "\n";
            //}
            splitparts_.push_back( chunkBuffer );
            chunkWidthActual_.push_back( blockstride_ / channels_ );
            chunkHeightActual_.push_back( blocklen_ / blockstride_ );
            gsl::span<const uint8_t> byte_span( chunkBuffer );
            std::vector<uint8_t>     shahash( SHA256_DIGEST_LENGTH );
            unsigned int             digest_len = 0;

            EVP_MD_CTX *ctx = EVP_MD_CTX_new();
            EVP_DigestInit_ex( ctx, EVP_sha256(), NULL );
            EVP_DigestUpdate( ctx, chunkBuffer.data(), chunkBuffer.size() );
            EVP_DigestFinal_ex( ctx, shahash.data(), &digest_len );
            EVP_MD_CTX_free( ctx );

            cids_.emplace_back( shahash );
        }
    }

    uint32_t ImageSplitter::GetPartSize( int part ) const
    {
        return splitparts_.at( part ).size();
    }

    uint32_t ImageSplitter::GetPartStride( int part ) const
    {
        return chunkWidthActual_.at( part );
    }

    int ImageSplitter::GetPartWidthActual( int part ) const
    {
        return chunkWidthActual_.at( part );
    }

    int ImageSplitter::GetPartHeightActual( int part ) const
    {
        return chunkHeightActual_.at( part );
    }

    size_t ImageSplitter::GetPartCount() const
    {
        return splitparts_.size();
    }

    size_t ImageSplitter::GetImageSize() const
    {
        return imageSize;
    }

    std::vector<uint8_t> ImageSplitter::GetPartCID( int part ) const
    {
        return cids_.at( part );
    }
}

Updated on 2026-03-04 at 13:10:44 -0800