SOL9 2.0 Class: WICBitmapFileReader

 SOL9 C++ Class Library  SOL9 Samples  SOL9 Tutorial  SOL9 FAQ  SOL9 ClassTree  SOL9 ClassList 

Source code

/******************************************************************************
 *
 * Copyright (c) 2015 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *  WICBitmapFileReader.h
 *
 *****************************************************************************/
//2016/11/20 Added the following method to read pixel data from a wchar_t fileName

//  void read(int destWidth, int destHeight, 
//        D3D12_SUBRESOURCE_DATA& subresource)
// The following three method used in the above method are based on WICTextureLoader.cpp
//  
// convertWICToDXGIFormat
// getWICNearestFormat
// wicBitsPerPixel

//--------------------------------------------------------------------------------------
// File: WICTextureLoader.cpp
//
// Function for loading a WIC image and creating a Direct3D runtime texture for it
// (auto-generating mipmaps if possible)
//
// Note: Assumes application has already called CoInitializeEx
//
// Note these functions are useful for images created as simple 2D textures. For
// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader.
// For a full-featured DDS file reader, writer, and texture processing pipeline see
// the 'Texconv' sample and the 'DirectXTex' library.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// http://go.microsoft.com/fwlink/?LinkID=615561
//--------------------------------------------------------------------------------------

// We could load multi-frame images (TIFF/GIF) into a texture array.
// For now, we just load the first frame (note: DirectXTex supports multi-frame images)


#pragma once

#include <sol/wic/WICImagingFactory.h>
#include <sol/wic/WICBitmapDecoder.h>
#include <sol/wic/WICBitmapFrameDecode.h>

#include <sol/wic/WICBitmapScaler.h>
#include <sol/wic/WICFormatConverter.h>

#include <sol/directx/Direct2D1Bitmap.h>

namespace SOL {

class WICBitmapFileReader : public WICBitmapDecoder {
private:
  IWICImagingFactory* factory;

public:
  WICBitmapFileReader(IWICImagingFactory* factory, const wchar_t* filename)
  :WICBitmapDecoder(factory, filename, NULL, GENERIC_READ, WICDecodeMetadataCacheOnDemand),
  factory(factory)
  {
    
  }

  //This will return an instance of Direct2D1Bitmap class, or NULL on failed. 
  Direct2D1Bitmap* read(ID2D1RenderTarget* renderTarget)
  {
    WICBitmapFrameDecode* frame   = NULL;

    WICFormatConverter* converter = NULL;  

    Direct2D1Bitmap* bitmap = NULL;
  
    try {
      frame = new WICBitmapFrameDecode(*this);

      converter = new WICFormatConverter(factory);  
      converter -> initialize(
                *frame,                          
                GUID_WICPixelFormat32bppPBGRA,  
                WICBitmapDitherTypeNone,        
                NULL,                         
                0.f,                             
                WICBitmapPaletteTypeCustom
                );
      bitmap = new Direct2D1Bitmap(renderTarget, 
                       *converter);
    } catch (Exception& ex) {
      ex.display();
    }
    
    delete frame;
    delete converter;
      
    return bitmap;
  }
//2016/12/05 Added #ifdef WIN10 as shown below.
#ifdef WIN10
  //2016/11/20 Experimental code. 
  void read(int destWidth, int destHeight, 
        D3D12_SUBRESOURCE_DATA& subresource)
 
  {
      WICBitmapScaler*      scaler  = NULL;
      
    WICBitmapFrameDecode* frame   = NULL;

    WICFormatConverter* converter = NULL;  
  
    try {
      frame = new WICBitmapFrameDecode(*this);

      getDestinationSize(frame, (UINT&)destWidth, (UINT&)destHeight);
      scaler = new WICBitmapScaler(factory);
      
      scaler -> initialize(*frame, destWidth, destHeight, WICBitmapInterpolationModeCubic);
        
      WICPixelFormatGUID pixelFormat;
      frame -> getPixelFormat( &pixelFormat );

      WICPixelFormatGUID convertGUID;
      memcpy( &convertGUID, &pixelFormat, sizeof(pixelFormat) );

      size_t bitsPerPixel = 0;
      
      DXGI_FORMAT format = convertWICToDXGIFormat(pixelFormat);
      if (format == DXGI_FORMAT_UNKNOWN) {
        getWICNearestFormat(pixelFormat, convertGUID, format, bitsPerPixel);
      }
      else {
        bitsPerPixel = wicBitsPerPixel(pixelFormat);
      }
            
      converter = new WICFormatConverter(factory);  
      converter -> initialize(
                *scaler,                          
                GUID_WICPixelFormat32bppPRGBA, 
                WICBitmapDitherTypeErrorDiffusion,        
                NULL, 
                0.0f, 
                WICBitmapPaletteTypeCustom
                );
      UINT twidth       = destWidth;
      UINT theight      = destHeight;

      size_t rowPitch  = ( twidth * bitsPerPixel + 7 ) / 8;
     
      size_t imageSize = rowPitch * theight;
      
      uint8_t* image = new uint8_t[imageSize];
      
      converter -> copyPixels( 0, rowPitch, imageSize , image );  
      
      subresource.pData      = image;
      subresource.RowPitch   = rowPitch;
      subresource.SlicePitch = imageSize;
      
    } catch (Exception& ex) {
      ex.display();
    }
    delete scaler;
    delete frame;
    delete converter;
      
  }
#endif  
  //This will return an instance of Direct2D1Bitmap class, or NULL on failed. 
  Direct2D1Bitmap* read(ID2D1RenderTarget* renderTarget, UINT destWidth, UINT destHeight)
  {
      WICBitmapScaler*      scaler  = NULL;
      
    WICBitmapFrameDecode* frame   = NULL;

    WICFormatConverter* converter = NULL;  

    Direct2D1Bitmap* bitmap = NULL;
  
    try {
      frame = new WICBitmapFrameDecode(*this);

      getDestinationSize(frame, destWidth, destHeight);
      scaler = new WICBitmapScaler(factory);
      scaler -> initialize(*frame, destWidth, destHeight, WICBitmapInterpolationModeCubic);
        
      converter = new WICFormatConverter(factory);  
      converter -> initialize(
                *scaler,                          
                GUID_WICPixelFormat32bppPBGRA,  
                WICBitmapDitherTypeNone,        
                NULL,                         
                0.f,                             
                WICBitmapPaletteTypeCustom
                );
      bitmap = new Direct2D1Bitmap(renderTarget, 
                       *converter);
    } catch (Exception& ex) {
      ex.display();
    }
    delete scaler;
    delete frame;
    delete converter;
      
    return bitmap;
  }

  
  void getDestinationSize(WICBitmapSource* source, __inout UINT& destWidth, __inout UINT& destHeight)
  {
     UINT width  = 0;
     UINT height = 0;
     source -> getSize(width, height);
 
    if (destWidth > 0 || destHeight > 0) {
      if (destWidth == 0) {
          float scaler = (float)destHeight / (float)height;
          destWidth = (UINT) (scaler * (float)width);
      } else if (destHeight == 0) {
        float scaler = (float)destWidth / (float)width;
        destHeight = (UINT)(scaler * (float)height);
     }
    }
  }

#ifdef WIN10  
  //-------------------------------------------------------------------------------------
  // WIC Pixel Format Translation Data
  //-------------------------------------------------------------------------------------
  DXGI_FORMAT convertWICToDXGIFormat(const GUID& guid)
  {
    struct WICTranslate {
      GUID                wic;
      DXGI_FORMAT         format;
    };

    const WICTranslate wicFormats[] =
    {
      { GUID_WICPixelFormat128bppRGBAFloat,       DXGI_FORMAT_R32G32B32A32_FLOAT },

      { GUID_WICPixelFormat64bppRGBAHalf,         DXGI_FORMAT_R16G16B16A16_FLOAT },
      { GUID_WICPixelFormat64bppRGBA,             DXGI_FORMAT_R16G16B16A16_UNORM },

      { GUID_WICPixelFormat32bppRGBA,             DXGI_FORMAT_R8G8B8A8_UNORM },
      { GUID_WICPixelFormat32bppBGRA,             DXGI_FORMAT_B8G8R8A8_UNORM },
      { GUID_WICPixelFormat32bppBGR,              DXGI_FORMAT_B8G8R8X8_UNORM },

      { GUID_WICPixelFormat32bppRGBA1010102XR,    DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM },
      { GUID_WICPixelFormat32bppRGBA1010102,      DXGI_FORMAT_R10G10B10A2_UNORM },

      { GUID_WICPixelFormat16bppBGRA5551,         DXGI_FORMAT_B5G5R5A1_UNORM },
      { GUID_WICPixelFormat16bppBGR565,           DXGI_FORMAT_B5G6R5_UNORM },

      { GUID_WICPixelFormat32bppGrayFloat,        DXGI_FORMAT_R32_FLOAT },
      { GUID_WICPixelFormat16bppGrayHalf,         DXGI_FORMAT_R16_FLOAT },
      { GUID_WICPixelFormat16bppGray,             DXGI_FORMAT_R16_UNORM },
      { GUID_WICPixelFormat8bppGray,              DXGI_FORMAT_R8_UNORM },

      { GUID_WICPixelFormat8bppAlpha,             DXGI_FORMAT_A8_UNORM },

      { GUID_WICPixelFormat96bppRGBFloat,         DXGI_FORMAT_R32G32B32_FLOAT },
    };

    for (size_t i = 0; i < _countof(wicFormats); ++i) {
      if (memcmp(&wicFormats[i].wic, &guid, sizeof(GUID)) == 0)
        return wicFormats[i].format;
    }

    return DXGI_FORMAT_UNKNOWN;
  }



  void getWICNearestFormat(
    WICPixelFormatGUID& pixelFormat,
    WICPixelFormatGUID& convertGUID,
    DXGI_FORMAT& format,
    size_t& bpp)
  {
    //-------------------------------------------------------------------------------------
    // WIC Pixel Format nearest conversion table
    //-------------------------------------------------------------------------------------

    struct WICConvert {
      GUID        source;
      GUID        target;
    };

    const WICConvert wicConvert[] =
    {
      // Note target GUID in this conversion table must be one of those directly supported formats (above).

      { GUID_WICPixelFormatBlackWhite,            GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM

      { GUID_WICPixelFormat1bppIndexed,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
      { GUID_WICPixelFormat2bppIndexed,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
      { GUID_WICPixelFormat4bppIndexed,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
      { GUID_WICPixelFormat8bppIndexed,           GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 

      { GUID_WICPixelFormat2bppGray,              GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM 
      { GUID_WICPixelFormat4bppGray,              GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM 

      { GUID_WICPixelFormat16bppGrayFixedPoint,   GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT 
      { GUID_WICPixelFormat32bppGrayFixedPoint,   GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT 

      { GUID_WICPixelFormat16bppBGR555,           GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM

      { GUID_WICPixelFormat32bppBGR101010,        GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM

      { GUID_WICPixelFormat24bppBGR,              GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
      { GUID_WICPixelFormat24bppRGB,              GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
      { GUID_WICPixelFormat32bppPBGRA,            GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
      { GUID_WICPixelFormat32bppPRGBA,            GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 

      { GUID_WICPixelFormat48bppRGB,              GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
      { GUID_WICPixelFormat48bppBGR,              GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
      { GUID_WICPixelFormat64bppBGRA,             GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
      { GUID_WICPixelFormat64bppPRGBA,            GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
      { GUID_WICPixelFormat64bppPBGRA,            GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM

      { GUID_WICPixelFormat48bppRGBFixedPoint,    GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
      { GUID_WICPixelFormat48bppBGRFixedPoint,    GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
      { GUID_WICPixelFormat64bppRGBAFixedPoint,   GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
      { GUID_WICPixelFormat64bppBGRAFixedPoint,   GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
      { GUID_WICPixelFormat64bppRGBFixedPoint,    GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
      { GUID_WICPixelFormat64bppRGBHalf,          GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 
      { GUID_WICPixelFormat48bppRGBHalf,          GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT 

      { GUID_WICPixelFormat128bppPRGBAFloat,      GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT 
      { GUID_WICPixelFormat128bppRGBFloat,        GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT 
      { GUID_WICPixelFormat128bppRGBAFixedPoint,  GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT 
      { GUID_WICPixelFormat128bppRGBFixedPoint,   GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT 
      { GUID_WICPixelFormat32bppRGBE,             GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT 

      { GUID_WICPixelFormat32bppCMYK,             GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM 
      { GUID_WICPixelFormat64bppCMYK,             GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
      { GUID_WICPixelFormat40bppCMYKAlpha,        GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
      { GUID_WICPixelFormat80bppCMYKAlpha,        GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM

      { GUID_WICPixelFormat32bppRGB,              GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM
      { GUID_WICPixelFormat64bppRGB,              GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM
      { GUID_WICPixelFormat64bppPRGBAHalf,        GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT

      { GUID_WICPixelFormat96bppRGBFixedPoint,   GUID_WICPixelFormat96bppRGBFloat }, // DXGI_FORMAT_R32G32B32_FLOAT

                                                                                     // We don't support n-channel formats
    };

    for (size_t i = 0; i < _countof(wicConvert); ++i)
    {
      if (memcmp(&wicConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0)
      {
        memcpy(&convertGUID, &wicConvert[i].target, sizeof(WICPixelFormatGUID));

        format = convertWICToDXGIFormat(wicConvert[i].target);

        bpp = wicBitsPerPixel(convertGUID);
        break;
      }
    }

    if (format == DXGI_FORMAT_UNKNOWN) {
      throw IException("Unsupported format.");
    }
  }

  //---------------------------------------------------------------------------------
  size_t wicBitsPerPixel(REFGUID targetGuid)
  {
    UINT bpp = 0;
   // size_t bpp = 0;

    IWICComponentInfo*   cinfo = NULL;
    IWICPixelFormatInfo* pfinfo = NULL;
    try {
      if (factory->CreateComponentInfo(targetGuid, &cinfo))
        throw 0;

      WICComponentType type;
      if (cinfo->GetComponentType(&type))
        throw 0;

      if (type != WICPixelFormat)
        throw 0;

      if (FAILED(cinfo->QueryInterface(IID_PPV_ARGS(&pfinfo))))
        throw 0;

      if (FAILED(pfinfo->GetBitsPerPixel(&bpp)))
        throw 0;

    }
    catch (...) {
      //Ignore
    }

    if (cinfo)
      cinfo->Release();
    if (pfinfo)
      pfinfo->Release();

      return (size_t)bpp;
  }
#endif
};
  
}

  

Last modified: 5 May 2019

Copyright (c) 2009-2019 Antillia.com ALL RIGHTS RESERVED.