0

Scenario: Load a TIFF image and extract the frames of tiff image and save it locally. Combine the extracted frames to the output TIFF image. When i try to combine the frames, the size of the output tiff image is increasing drastically. For example if my input size if 40 MB , the output is increased to 300 MB. Below is the code which explains the scenario,

    void readTiff()
    {
        HRESULT hr;
        IWICBitmapFrameDecode *frameDecode = NULL;
        IWICFormatConverter *formatConverter = NULL;
        IWICBitmapEncoder *encoder = NULL;
        IWICStream *pOutStream = NULL;
        IWICBitmapFrameEncode *frameEncode = NULL;
        IWICImagingFactory* m_pWICFactory;


        hr = CoCreateInstance(
            CLSID_WICImagingFactory,
            NULL,
            CLSCTX_INPROC_SERVER,
            IID_PPV_ARGS(&m_pWICFactory)
            );

        IWICBitmapDecoder *pIDecoder = NULL;

        hr = m_pWICFactory->CreateDecoderFromFilename(
            L"D:\\test28\\Multitiff_files\\300dpiTIFF40MB_WATER.tif",                  // Image to be decoded
            NULL,                           // Do not prefer a particular vendor
            GENERIC_READ,                   // Desired read access to the file
            WICDecodeMetadataCacheOnDemand, // Cache metadata when needed
            &pIDecoder                      // Pointer to the decoder
            );


        UINT frameCount = 0;
        pIDecoder->GetFrameCount(&frameCount);

        for (int i = 0; i < frameCount; i++)
        {
            wchar_t temp[200];
            int j = i;
            swprintf_s(temp, 200, L"D:\\test28\\Multitiff_files\\out\\filename_png%d.jpeg", i);

            if (SUCCEEDED(hr))
                hr = m_pWICFactory->CreateStream(&pOutStream);
            if (SUCCEEDED(hr))
                hr = pOutStream->InitializeFromFilename(temp, GENERIC_WRITE);

            if (SUCCEEDED(hr))
                hr = m_pWICFactory->CreateEncoder(GUID_ContainerFormatJpeg, NULL, &encoder);
            if (SUCCEEDED(hr))
                hr = encoder->Initialize(pOutStream, WICBitmapEncoderNoCache);

            hr = pIDecoder->GetFrame(i, &frameDecode);      

            if (SUCCEEDED(hr))
                hr = m_pWICFactory->CreateFormatConverter(&formatConverter);

            hr = formatConverter->Initialize(
                frameDecode,                     // Source frame to convert
                GUID_WICPixelFormat8bppIndexed,     // The desired pixel format
                WICBitmapDitherTypeNone,         // The desired dither pattern
                NULL,                            // The desired palette 
                0.f,                             // The desired alpha threshold
                WICBitmapPaletteTypeMedianCut       // Palette translation type
                );
            IPropertyBag2 *pPropertybag = NULL;
            //Create a new frame..
            hr = encoder->CreateNewFrame(&frameEncode, &pPropertybag);
            //PROPBAG2 option = { 0 };
            //option.pstrName = L"ImageQuality";
            //VARIANT varValue;
            //VariantInit(&varValue);
            //varValue.vt = VT_R4;
            //varValue.fltVal = 0.01f;
            //hr = pPropertybag->Write(
            //  1, // number of properties being set
            //  &option,
            //  &varValue);

            WICPixelFormatGUID pixelFormat;
            hr = frameEncode->Initialize(pPropertybag);

            //pixelFormat = GUID_WICPixelFormat8bppIndexed;

            frameDecode->GetPixelFormat(&pixelFormat);
            hr = frameEncode->SetPixelFormat(&pixelFormat);

            hr = frameEncode->WriteSource(formatConverter, NULL);
            frameEncode->Commit();
            encoder->Commit();

            if (formatConverter)
                formatConverter->Release();

            if (frameDecode)
                frameDecode->Release();

            if (frameEncode)
                frameEncode->Release();

            if (pOutStream)
                pOutStream->Release();

            if (encoder)
                encoder->Release();     
        }
        if (m_pWICFactory)
            m_pWICFactory->Release();

        pIDecoder->Release();
    }

void combineFile(int count)
{
    HRESULT hr;
    IWICImagingFactory *pFactory = NULL;
    IWICStream *pInStream = NULL;
    IWICBitmapDecoder *decoder = NULL;
    IWICBitmapFrameDecode *frameDecode = NULL;
    IWICFormatConverter *formatConverter = NULL;
    IWICBitmapEncoder *encoder = NULL;
    IWICStream *pOutStream = NULL;
    IWICBitmapFrameEncode *frameEncode = NULL;

    hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pFactory);

    if (!SUCCEEDED(hr)) {
        hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*)&pFactory);
    }

    if (SUCCEEDED(hr))
        hr = pFactory->CreateStream(&pOutStream);

    if (SUCCEEDED(hr))
        hr = pOutStream->InitializeFromFilename(L"D:\\test28\\Multitiff_files\\out\\out.tiff", GENERIC_WRITE);
    if (SUCCEEDED(hr))
        hr = pFactory->CreateEncoder(GUID_ContainerFormatWmp, NULL, &encoder);
    if (SUCCEEDED(hr))
        hr = encoder->Initialize(pOutStream, WICBitmapEncoderNoCache);


    for (int i = 0; i < count; i++)
    {
        wchar_t temp[200];

        swprintf_s(temp, 200, L"D:\\test28\\Multitiff_files\\out\\filename_png%d.jpeg", i);
        if (SUCCEEDED(hr))
            hr = pFactory->CreateStream(&pInStream);
        if (SUCCEEDED(hr))
            hr = pInStream->InitializeFromFilename(temp, GENERIC_READ);
        if (SUCCEEDED(hr))
            hr = pFactory->CreateDecoderFromStream(pInStream, NULL, WICDecodeMetadataCacheOnLoad, &decoder);
        if (SUCCEEDED(hr))
            hr = pFactory->CreateFormatConverter(&formatConverter);


        hr = decoder->GetFrame(0, &frameDecode);

        //hr = formatConverter->Initialize(

        //  frameDecode,                     // Source frame to convert
        //  GUID_WICPixelFormat8bppIndexed,     // The desired pixel format
        //  WICBitmapDitherTypeNone,         // The desired dither pattern
        //  NULL,                            // The desired palette 
        //  0.f,                             // The desired alpha threshold
        //  WICBitmapPaletteTypeMedianCut       // Palette translation type
        //  );

        WICPixelFormatGUID pixelFormat;
        frameDecode->GetPixelFormat(&pixelFormat);

        IPropertyBag2 *pPropertybag = NULL;
        //Create a new frame..
        hr = encoder->CreateNewFrame(&frameEncode, &pPropertybag);
        PROPBAG2 option = { 0 };
        option.pstrName = L"TiffCompressionMethod";
        VARIANT varValue;
        VariantInit(&varValue);
        varValue.vt = VT_UI1;
        varValue.bVal = WICTiffCompressionOption::WICTiffCompressionZIP;
        hr = pPropertybag->Write(1, &option, &varValue);


        hr = frameEncode->Initialize(pPropertybag);
        hr = frameEncode->SetPixelFormat(&pixelFormat);

        hr = frameEncode->WriteSource(formatConverter, NULL);
        hr = frameEncode->Commit();

        if (pInStream)
            pInStream->Release();
        if (decoder)
            decoder->Release();
        if (formatConverter)
            formatConverter->Release();
        if (frameEncode)
            frameEncode->Release();
        //if (frameDecode)
        //frameDecode->Release();
    }
    encoder->Commit();

    if (pFactory)
        pFactory->Release();

    if (encoder)
        encoder->Release();

    if (pOutStream)
        pOutStream->Release();
}
IPS
  • 81
  • 1
  • 12
  • 2
    When you put it back together, is it compressed still? Is it using the same style of compression? Do your tools have any type of "give me the details on this tiff" that you can run on the original and the re-combined version? Looking at the table here: https://en.wikipedia.org/wiki/Tagged_Image_File_Format#TIFF_Compression_Tag it looks like you may have chosen a lossless compression format - maybe originally it wasn't lossless? – xaxxon Mar 01 '16 at 06:09
  • Thanks for the information @xaxxon .I have extracted the frames of tiff to GUID_ContainerFormatJpeg and combined the frames back to tiff. Is this right? yes i have applied the compression WICTiffCompressionZIP while combining the jpeg images. – IPS Mar 01 '16 at 07:10
  • 1
    But what was the compression when you started? Was it WICTiffCompressionZIP or was it something different? If you're compressing it with a different algorithm, the size could change drastically. It's reasonably likely the original was compressed with a lossy compression and you are now using lossless. – xaxxon Mar 01 '16 at 08:33
  • The input tiff image was just an input to us. I'm unable find what compression method they have used. From the properties, i could see that compression is empty. – IPS Mar 01 '16 at 09:11
  • @xaxxon Thanks for the information. The input compression format is JPEG. But the output compression format is ZIP. I'm using WIC (Windows Imaging Component ) for creating the output Tiff image. In WIC i cant find any compression for JPEG. Can you please look this? – IPS Mar 01 '16 at 10:41

1 Answers1

1

One easy way to debug this kind of issue is to use ImageMagick which is installed on most Linux distros and is available for OSX and Windows. First use the identify utility within the suite with its verbose option to find out everything about your before and after images like this:

# Find out all we know about first image and put in file "1.txt"
identify -verbose image1.tif > 1.txt

# Find out all we know about second image and put in file "2.txt"
identify -verbose image2.tif > 2.txt

Now use your favourite file comparison tool to see the differences:

opendiff 1.txt 2.txt

enter image description here

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • Thanks for the information. The input compression format is JPEG. But the output compression format is ZIP. I'm using WIC (Windows Imaging Component ) for creating the output Tiff image. In WIC i cant find any compression for JPEG. Can you please look this? – IPS Mar 01 '16 at 10:41