c++tifflibtiffwic

BIts Per Sample / Pixel libtiff vs WIC


TIFF *TiffImage;
uint16 photo, bps, spp, fillorder;
uint32 width,height;
unsigned long stripSize;
unsigned long imageOffset, result;
int stripMax, stripCount;
unsigned char *buffer, tempbyte;
unsigned short *buffer16;
unsigned int *buffer32;
unsigned long bufferSize, count;
bool success = true;
int shiftCount = 0;


//read image to InData
const char *InFileName = fileName.c_str();

if((TiffImage = TIFFOpen(InFileName, "r")) == NULL){
    ErrMsg("Could not open incoming image\n");
    return false;
}
// Check that it is of a type that we support
if(TIFFGetField(TiffImage, TIFFTAG_BITSPERSAMPLE, &bps) == 0) {
   ErrMsg("Either undefined or unsupported number of bits per sample\n");
   return false;
}
TBitPrecision bitPrecision = (TBitPrecision)bps;

char* imageDesc = NULL;
TIFFGetField(TiffImage, TIFFTAG_IMAGEDESCRIPTION, &imageDesc);

// Get actual bit precision for CP Images
if (bps > 8 && bps <= 16)
{
    if (GetCpTiffTag(imageDesc, CP_TIFFTAG_BITPRECISION, (uint32*)&bitPrecision) == true)
    {
        shiftCount = 16 - bitPrecision;
    }
}

In my libtiff implementation I have used 12 bit per pixel image and also 10 bpp it is very easy to set this info in libtiff

I can't find a similar way to do so in WIC

uint16_t photo, bps, spp, fillorder;
uint32_t width,height;
unsigned long stripSize;
unsigned long imageOffset, result;
int stripMax, stripCount;
unsigned char *buffer, tempbyte;
unsigned short *buffer16;
unsigned int *buffer32;
unsigned long bufferSize, count;
bool success = true;
int shiftCount = 0;

 //read image to InData
const char *InFileName = fileName.c_str();
 IWICImagingFactory* piFactory = NULL;

// Create WIC factory
  HRESULT hr = CoCreateInstance(
  CLSID_WICImagingFactory,
  NULL,
  CLSCTX_INPROC_SERVER,
  IID_PPV_ARGS(&piFactory)
);
 // Create a decoder
IWICBitmapDecoder *pIDecoder = NULL;
IWICBitmapFrameDecode *pIDecoderFrame  = NULL;

std::wstring ws;
ws.assign(fileName.begin(), fileName.end());
// get temporary LPCWSTR (pretty safe)
LPCWSTR pcwstr = ws.c_str();

   hr = piFactory->CreateDecoderFromFilename(
   pcwstr,                      // 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
   );
      // Retrieve the first bitmap frame.
if (SUCCEEDED(hr))
{
    hr = pIDecoder->GetFrame(0, &pIDecoderFrame);
}
else
{
     ErrMsg("Could not open incoming image\n");
}
return true;

Am I suppose to use EXIF or XMP? how do I find the TIFFTAG's for WIC?


Solution

  • The DirectXTex library has lots of examples of using WIC from C++.

    You need something like:

    using Microsoft::WRL::ComPtr;
    
    
    ComPtr<IWICMetadataQueryReader> metareader;
    hr = pIDecoderFrame->GetMetadataQueryReader(metareader.GetAddressOf());
    if (SUCCEEDED(hr))
    {
        PROPVARIANT value;
        PropVariantInit(&value);
    
        if (SUCCEEDED(metareader->GetMetadataByName(L"/ifd/{ushort=258}", &value))
            && value.vt == VT_UI2)
        {
            // BitsPerSample is in value.uiVal
        }
    
        PropVariantClear(&value);    
    }
    

    You should get in the habit of using a smart-pointer like ComPtr rather than using raw interface pointers to keep the ref counts correct.