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