PageRenderTime 51ms CodeModel.GetById 13ms app.highlight 32ms RepoModel.GetById 2ms app.codeStats 0ms

/project/jni/sdl_image/IMG_webp.c

https://github.com/aichunyu/FFPlayer
C | 296 lines | 215 code | 45 blank | 36 comment | 55 complexity | f51d8bb628ef27458181e20b18ce54b0 MD5 | raw file
  1/*
  2  SDL_image:  An example image loading library for use with SDL
  3  Copyright (C) 1997-2012 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/* This is a WEBP image file loading framework */
 23
 24#include <stdlib.h>
 25#include <stdio.h>
 26
 27#include "SDL_image.h"
 28
 29#ifdef LOAD_WEBP
 30
 31/*=============================================================================
 32        File: SDL_webp.c
 33     Purpose: A WEBP loader for the SDL library      
 34    Revision: 
 35  Created by: Michael Bonfils (Murlock) (26 November 2011)
 36              murlock42@gmail.com
 37
 38=============================================================================*/
 39
 40#include "SDL_endian.h"
 41
 42#ifdef macintosh
 43#define MACOS
 44#endif
 45#include <webp/decode.h>
 46
 47static struct {
 48	int loaded;
 49	void *handle;
 50	int/*VP8StatuCode*/ (*webp_get_features_internal) (const uint8_t *data, uint32_t data_size, WebPBitstreamFeatures* const features, int decoder_abi_version);
 51	uint8_t*	(*webp_decode_rgb_into) (const uint8_t* data, uint32_t data_size, uint8_t* output_buffer, int output_buffer_size, int output_stride);
 52	uint8_t*	(*webp_decode_rgba_into) (const uint8_t* data, uint32_t data_size, uint8_t* output_buffer, int output_buffer_size, int output_stride);
 53} lib;
 54
 55#ifdef LOAD_WEBP_DYNAMIC
 56int IMG_InitWEBP()
 57{
 58	if ( lib.loaded == 0 ) {
 59		lib.handle = SDL_LoadObject(LOAD_WEBP_DYNAMIC);
 60		if ( lib.handle == NULL ) {
 61			return -1;
 62		}
 63		lib.webp_get_features_internal = 
 64			( int (*) (const uint8_t *, uint32_t, WebPBitstreamFeatures* const, int) )
 65			SDL_LoadFunction(lib.handle, "WebPGetFeaturesInternal" );
 66		if ( lib.webp_get_features_internal == NULL ) {
 67			SDL_UnloadObject(lib.handle);
 68			return -1;
 69		}
 70
 71		lib.webp_decode_rgb_into = 
 72			( uint8_t* (*) (const uint8_t*, uint32_t, uint8_t*, int, int ) )
 73			SDL_LoadFunction(lib.handle, "WebPDecodeRGBInto" );
 74		if ( lib.webp_decode_rgb_into == NULL ) {
 75			SDL_UnloadObject(lib.handle);
 76			return -1;
 77		}
 78
 79		lib.webp_decode_rgba_into = 
 80			( uint8_t* (*) (const uint8_t*, uint32_t, uint8_t*, int, int ) )
 81			SDL_LoadFunction(lib.handle, "WebPDecodeRGBInto" );
 82		if ( lib.webp_decode_rgba_into == NULL ) {
 83			SDL_UnloadObject(lib.handle);
 84			return -1;
 85		}
 86	}
 87	++lib.loaded;
 88
 89	return 0;
 90}
 91void IMG_QuitWEBP()
 92{
 93	if ( lib.loaded == 0 ) {
 94		return;
 95	}
 96	if ( lib.loaded == 1 ) {
 97		SDL_UnloadObject(lib.handle);
 98	}
 99	--lib.loaded;
100}
101#else
102int IMG_InitWEBP()
103{
104	if ( lib.loaded == 0 ) {
105		lib.webp_get_features_internal = WebPGetFeaturesInternal;
106		lib.webp_decode_rgb_into = WebPDecodeRGBInto;
107		lib.webp_decode_rgba_into = WebPDecodeRGBAInto;
108	}
109	++lib.loaded;
110
111	return 0;
112}
113void IMG_QuitWEBP()
114{
115	if ( lib.loaded == 0 ) {
116		return;
117	}
118	if ( lib.loaded == 1 ) {
119	}
120	--lib.loaded;
121}
122#endif /* LOAD_WEBP_DYNAMIC */
123
124static int webp_getinfo( SDL_RWops *src, int *datasize ) {
125	int start;
126	int is_WEBP;
127	int data;
128	Uint8 magic[20];
129
130	if ( !src )
131		return 0;
132	start = SDL_RWtell(src);
133	is_WEBP = 0;
134	if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
135		if ( magic[ 0] == 'R' &&
136                     magic[ 1] == 'I' &&
137                     magic[ 2] == 'F' &&
138                     magic[ 3] == 'F' &&
139										 magic[ 8] == 'W' &&
140										 magic[ 9] == 'E' &&
141										 magic[10] == 'B' &&
142										 magic[11] == 'P' &&
143										 magic[12] == 'V' &&
144										 magic[13] == 'P' &&
145										 magic[14] == '8' &&
146										 magic[15] == ' '  ) {
147			is_WEBP = 1;
148			data = magic[16] | magic[17]<<8 | magic[18]<<16 | magic[19]<<24;
149			if ( datasize )
150				*datasize = data;
151		}
152	}
153	SDL_RWseek(src, start, RW_SEEK_SET);
154	return(is_WEBP);
155}
156
157/* See if an image is contained in a data source */
158int IMG_isWEBP(SDL_RWops *src)
159{
160	return webp_getinfo( src, NULL );
161}
162
163SDL_Surface *IMG_LoadWEBP_RW(SDL_RWops *src)
164{
165	int start;
166	const char *error = NULL;
167	SDL_Surface *volatile surface = NULL;
168	Uint32 Rmask;
169	Uint32 Gmask;
170	Uint32 Bmask;
171	Uint32 Amask;
172	WebPBitstreamFeatures features;
173	int raw_data_size;
174	uint8_t *raw_data;
175	int r;
176	uint8_t *ret;
177
178	if ( !src ) {
179		/* The error message has been set in SDL_RWFromFile */
180		return NULL;
181	}
182
183	start = SDL_RWtell(src);
184
185	if ( !IMG_Init(IMG_INIT_WEBP) ) {
186		goto error;
187	}
188
189
190	raw_data_size = -1;
191	if ( !webp_getinfo( src, &raw_data_size ) ) {
192		error = "Invalid WEBP";
193		goto error;
194	}
195
196	// skip header
197	SDL_RWseek(src, start+20, RW_SEEK_SET );
198
199	raw_data = (uint8_t*) malloc( raw_data_size );
200	if ( raw_data == NULL ) {
201		error = "Failed to allocate enought buffer for WEBP";
202		goto error;
203	}
204
205	r = SDL_RWread(src, raw_data, 1, raw_data_size );
206	if ( r != raw_data_size ) {
207		error = "Failed to read WEBP";
208		goto error;
209	}
210	
211#if 0
212	// extract size of picture, not interesting since we don't know about alpha channel
213	int width = -1, height = -1;
214	if ( !WebPGetInfo( raw_data, raw_data_size, &width, &height ) ) {
215		printf("WebPGetInfo has failed\n" );
216		return NULL;
217	}
218#endif
219
220	if ( lib.webp_get_features_internal( raw_data, raw_data_size, &features, WEBP_DECODER_ABI_VERSION ) != VP8_STATUS_OK ) {
221		error = "WebPGetFeatures has failed";
222		return NULL;
223	}
224
225	/* Check if it's ok !*/
226	Rmask = 0x000000FF;
227	Gmask = 0x0000FF00;
228	Bmask = 0x00FF0000;
229	Amask = features.has_alpha?0xFF000001:0;
230
231	surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
232            features.width, features.height,
233			features.has_alpha?32:24, Rmask,Gmask,Bmask,Amask);
234
235	if ( surface == NULL ) {
236		error = "Failed to allocate SDL_Surface";
237		goto error;
238	}
239
240	if ( features.has_alpha ) {
241		ret = lib.webp_decode_rgba_into( raw_data, raw_data_size, surface->pixels, surface->pitch * surface->h,  surface->pitch );
242	} else {
243		ret = lib.webp_decode_rgb_into( raw_data, raw_data_size, surface->pixels, surface->pitch * surface->h,  surface->pitch );
244	}
245
246	if ( !ret ) {
247		error = "Failed to decode WEBP";
248		goto error;
249	}
250
251	return surface;
252
253
254error:
255
256	if ( surface ) {
257		SDL_FreeSurface( surface );
258	}
259
260	if ( raw_data ) {
261		free( raw_data );
262	}
263
264	if ( error ) {
265		IMG_SetError( error );
266	}
267
268	SDL_RWseek(src, start, RW_SEEK_SET);
269	return(NULL);
270}
271
272#else
273
274int IMG_InitWEBP()
275{
276	IMG_SetError("WEBP images are not supported");
277	return(-1);
278}
279
280void IMG_QuitWEBP()
281{
282}
283
284/* See if an image is contained in a data source */
285int IMG_isWEBP(SDL_RWops *src)
286{
287	return(0);
288}
289
290/* Load a WEBP type image from an SDL datasource */
291SDL_Surface *IMG_LoadWEBP_RW(SDL_RWops *src)
292{
293	return(NULL);
294}
295
296#endif /* LOAD_WEBP */