IMG_WIC.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 26 Oct 2018 14:58:01 -0700
changeset 617 d64228a395fc
parent 575 36e9e2255178
child 638 e3e9d7430674
permissions -rw-r--r--
Fixed webp library detection when cross-compiling for Windows
     1 /*
     2   SDL_image:  An example image loading library for use with SDL
     3   Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 #if defined(SDL_IMAGE_USE_WIC_BACKEND)
    23 
    24 #include "SDL_image.h"
    25 #include <wincodec.h>
    26 
    27 extern "C" {
    28 
    29 #define SAFE_RELEASE(X) if ((X)) { (X)->Release(); }
    30 #define DONE_IF_FAILED(X) if (FAILED((X))) { goto done; }
    31 
    32 IWICImagingFactory2* wicFactory = NULL;
    33 
    34 int WIC_Init()
    35 {
    36     if (wicFactory == NULL) {
    37         HRESULT hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&wicFactory));
    38         if (FAILED(hr)) {
    39             return -1;
    40         }
    41     }
    42 
    43     return 0;
    44 }
    45 
    46 void WIC_Quit()
    47 {
    48     SAFE_RELEASE(wicFactory);
    49 }
    50 
    51 int IMG_InitPNG()
    52 {
    53     return WIC_Init();
    54 }
    55 
    56 void IMG_QuitPNG()
    57 {
    58     WIC_Quit();
    59 }
    60 
    61 int IMG_InitJPG()
    62 {
    63     return WIC_Init();
    64 }
    65 
    66 void IMG_QuitJPG()
    67 {
    68     WIC_Quit();
    69 }
    70 
    71 int IMG_InitTIF()
    72 {
    73     return WIC_Init();
    74 }
    75 
    76 void IMG_QuitTIF()
    77 {
    78     WIC_Quit();
    79 }
    80 
    81 int IMG_isPNG(SDL_RWops *src)
    82 {
    83     Sint64 start;
    84     int is_PNG;
    85     Uint8 magic[4];
    86 
    87     if ( !src ) {
    88         return 0;
    89     }
    90 
    91     start = SDL_RWtell(src);
    92     is_PNG = 0;
    93     if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
    94         if ( magic[0] == 0x89 &&
    95              magic[1] == 'P' &&
    96              magic[2] == 'N' &&
    97              magic[3] == 'G' ) {
    98             is_PNG = 1;
    99         }
   100     }
   101     SDL_RWseek(src, start, RW_SEEK_SET);
   102     return(is_PNG);
   103 }
   104 
   105 int IMG_isJPG(SDL_RWops *src)
   106 {
   107     Sint64 start;
   108     int is_JPG;
   109     int in_scan;
   110     Uint8 magic[4];
   111 
   112     /* This detection code is by Steaphan Greene <stea@cs.binghamton.edu> */
   113     /* Blame me, not Sam, if this doesn't work right. */
   114     /* And don't forget to report the problem to the the sdl list too! */
   115 
   116     if (!src)
   117         return 0;
   118     start = SDL_RWtell(src);
   119     is_JPG = 0;
   120     in_scan = 0;
   121     if (SDL_RWread(src, magic, 2, 1)) {
   122         if ((magic[0] == 0xFF) && (magic[1] == 0xD8)) {
   123             is_JPG = 1;
   124             while (is_JPG == 1) {
   125                 if (SDL_RWread(src, magic, 1, 2) != 2) {
   126                     is_JPG = 0;
   127                 }
   128                 else if ((magic[0] != 0xFF) && (in_scan == 0)) {
   129                     is_JPG = 0;
   130                 }
   131                 else if ((magic[0] != 0xFF) || (magic[1] == 0xFF)) {
   132                     /* Extra padding in JPEG (legal) */
   133                     /* or this is data and we are scanning */
   134                     SDL_RWseek(src, -1, RW_SEEK_CUR);
   135                 }
   136                 else if (magic[1] == 0xD9) {
   137                     /* Got to end of good JPEG */
   138                     break;
   139                 }
   140                 else if ((in_scan == 1) && (magic[1] == 0x00)) {
   141                     /* This is an encoded 0xFF within the data */
   142                 }
   143                 else if ((magic[1] >= 0xD0) && (magic[1] < 0xD9)) {
   144                     /* These have nothing else */
   145                 }
   146                 else if (SDL_RWread(src, magic + 2, 1, 2) != 2) {
   147                     is_JPG = 0;
   148                 }
   149                 else {
   150                     /* Yes, it's big-endian */
   151                     Sint64 innerStart;
   152                     Uint32 size;
   153                     Sint64 end;
   154                     innerStart = SDL_RWtell(src);
   155                     size = (magic[2] << 8) + magic[3];
   156                     end = SDL_RWseek(src, size - 2, RW_SEEK_CUR);
   157                     if (end != innerStart + size - 2) is_JPG = 0;
   158                     if (magic[1] == 0xDA) {
   159                         /* Now comes the actual JPEG meat */
   160 #ifdef  FAST_IS_JPEG
   161                         /* Ok, I'm convinced.  It is a JPEG. */
   162                         break;
   163 #else
   164                         /* I'm not convinced.  Prove it! */
   165                         in_scan = 1;
   166 #endif
   167                     }
   168                 }
   169             }
   170         }
   171     }
   172     SDL_RWseek(src, start, RW_SEEK_SET);
   173     return(is_JPG);
   174 }
   175 
   176 int IMG_isTIF(SDL_RWops* src)
   177 {
   178     Sint64 start;
   179     int is_TIF;
   180     Uint8 magic[4];
   181 
   182     if (!src)
   183         return 0;
   184     start = SDL_RWtell(src);
   185     is_TIF = 0;
   186     if (SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic)) {
   187         if ((magic[0] == 'I' &&
   188             magic[1] == 'I' &&
   189             magic[2] == 0x2a &&
   190             magic[3] == 0x00) ||
   191             (magic[0] == 'M' &&
   192             magic[1] == 'M' &&
   193             magic[2] == 0x00 &&
   194             magic[3] == 0x2a)) {
   195             is_TIF = 1;
   196         }
   197     }
   198     SDL_RWseek(src, start, RW_SEEK_SET);
   199     return(is_TIF);
   200 }
   201 
   202 SDL_Surface* WIC_LoadImage(SDL_RWops *src)
   203 {
   204     SDL_Surface* surface = NULL;
   205 
   206     IWICStream* stream = NULL;
   207     IWICBitmapDecoder* bitmapDecoder = NULL;
   208     IWICBitmapFrameDecode* bitmapFrame = NULL;
   209     IWICFormatConverter* formatConverter = NULL;
   210     
   211     Sint64 fileSize = SDL_RWsize(src);
   212     Uint8* memoryBuffer = (Uint8*)SDL_malloc(fileSize);
   213     if (!memoryBuffer) {
   214         SDL_OutOfMemory();
   215         return NULL;  
   216     }
   217 
   218     SDL_RWread(src, memoryBuffer, 1, fileSize);
   219 
   220     DONE_IF_FAILED(wicFactory->CreateStream(&stream));
   221     DONE_IF_FAILED(stream->InitializeFromMemory(memoryBuffer, fileSize));
   222     DONE_IF_FAILED(wicFactory->CreateDecoderFromStream(stream, NULL, WICDecodeMetadataCacheOnDemand, &bitmapDecoder));
   223     DONE_IF_FAILED(bitmapDecoder->GetFrame(0, &bitmapFrame));
   224     DONE_IF_FAILED(wicFactory->CreateFormatConverter(&formatConverter));
   225     DONE_IF_FAILED(formatConverter->Initialize(bitmapFrame, GUID_WICPixelFormat32bppPRGBA, WICBitmapDitherTypeNone, NULL, 0.0, WICBitmapPaletteTypeCustom));
   226     
   227     UINT width, height;
   228     DONE_IF_FAILED(bitmapFrame->GetSize(&width, &height));
   229     
   230     Uint32 Amask = 0xFF000000;
   231     Uint32 Rmask = 0x00FF0000;
   232     Uint32 Gmask = 0x0000FF00;
   233     Uint32 Bmask = 0x000000FF;
   234 
   235     surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, Rmask, Gmask, Bmask, Amask);
   236 
   237     formatConverter->CopyPixels(NULL, width * 4, width * height * 4, (BYTE*)surface->pixels);
   238 
   239 done:
   240     SAFE_RELEASE(formatConverter);
   241     SAFE_RELEASE(bitmapFrame);
   242     SAFE_RELEASE(bitmapDecoder);
   243     SAFE_RELEASE(stream);
   244 
   245  SDL_free(memoryBuffer);
   246 
   247  return surface;
   248 }
   249 
   250 SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
   251 {
   252     return WIC_LoadImage(src);
   253 }
   254 
   255 SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src)
   256 {
   257     return WIC_LoadImage(src);
   258 }
   259 
   260 SDL_Surface *IMG_LoadTIF_RW(SDL_RWops *src)
   261 {
   262     return WIC_LoadImage(src);
   263 }
   264 
   265 #endif /* SDL_IMAGE_USE_WIC_BACKEND */
   266