1 // Copyright 2017 Google Inc. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the COPYING file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 // -----------------------------------------------------------------------------
9 //
10 //  Simple WebP-to-SDL wrapper. Useful for emscripten.
11 //
12 // Author: James Zern (jzern@google.com)
13 
14 #ifdef HAVE_CONFIG_H
15 #include "src/webp/config.h"
16 #endif
17 
18 #if defined(WEBP_HAVE_SDL)
19 
20 #include "webp_to_sdl.h"
21 
22 #include <stdio.h>
23 #include "src/webp/decode.h"
24 
25 #if defined(WEBP_HAVE_JUST_SDL_H)
26 #include <SDL.h>
27 #else
28 #include <SDL/SDL.h>
29 #endif
30 
31 static int init_ok = 0;
WebpToSDL(const char * data,unsigned int data_size)32 int WebpToSDL(const char* data, unsigned int data_size) {
33   int ok = 0;
34   VP8StatusCode status;
35   WebPDecoderConfig config;
36   WebPBitstreamFeatures* const input = &config.input;
37   WebPDecBuffer* const output = &config.output;
38   SDL_Surface* screen = NULL;
39   SDL_Surface* surface = NULL;
40 
41   if (!WebPInitDecoderConfig(&config)) {
42     fprintf(stderr, "Library version mismatch!\n");
43     return 0;
44   }
45 
46   if (!init_ok) {
47     SDL_Init(SDL_INIT_VIDEO);
48     init_ok = 1;
49   }
50 
51   status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &config.input);
52   if (status != VP8_STATUS_OK) goto Error;
53 
54   screen = SDL_SetVideoMode(input->width, input->height, 32, SDL_SWSURFACE);
55   if (screen == NULL) {
56     fprintf(stderr, "Unable to set video mode (32bpp %dx%d)!\n",
57             input->width, input->height);
58     goto Error;
59   }
60 
61   surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
62                                  input->width, input->height, 32,
63                                  0x000000ffu,   // R mask
64                                  0x0000ff00u,   // G mask
65                                  0x00ff0000u,   // B mask
66                                  0xff000000u);  // A mask
67 
68   if (surface == NULL) {
69     fprintf(stderr, "Unable to create %dx%d RGBA surface!\n",
70             input->width, input->height);
71     goto Error;
72   }
73   if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface);
74 
75 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
76   output->colorspace = MODE_BGRA;
77 #else
78   output->colorspace = MODE_RGBA;
79 #endif
80   output->width  = surface->w;
81   output->height = surface->h;
82   output->u.RGBA.rgba   = surface->pixels;
83   output->u.RGBA.stride = surface->pitch;
84   output->u.RGBA.size   = surface->pitch * surface->h;
85   output->is_external_memory = 1;
86 
87   status = WebPDecode((const uint8_t*)data, (size_t)data_size, &config);
88   if (status != VP8_STATUS_OK) {
89     fprintf(stderr, "Error decoding image (%d)\n", status);
90     goto Error;
91   }
92 
93   if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);
94   if (SDL_BlitSurface(surface, NULL, screen, NULL) ||
95       SDL_Flip(screen)) {
96     goto Error;
97   }
98 
99   ok = 1;
100 
101  Error:
102   SDL_FreeSurface(surface);
103   SDL_FreeSurface(screen);
104   WebPFreeDecBuffer(output);
105   return ok;
106 }
107 
108 //------------------------------------------------------------------------------
109 
110 #endif  // WEBP_HAVE_SDL
111