mirror of
https://github.com/projectM-visualizer/projectm.git
synced 2026-02-22 00:55:38 +00:00
upgrading soil to soil2
This commit is contained in:
@ -1,10 +1,9 @@
|
||||
project(Renderer)
|
||||
|
||||
SET(SOIL_SOURCES
|
||||
SOIL/image_DXT.c
|
||||
SOIL/image_helper.c
|
||||
SOIL/SOIL.c
|
||||
SOIL/stb_image_aug.c
|
||||
SOIL2/image_DXT.c
|
||||
SOIL2/image_helper.c
|
||||
SOIL2/SOIL2.c
|
||||
)
|
||||
|
||||
SET(Renderer_SOURCES
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,354 +0,0 @@
|
||||
/* stbi-1.16 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c
|
||||
when you control the images you're loading
|
||||
|
||||
QUICK NOTES:
|
||||
Primarily of interest to game developers and other people who can
|
||||
avoid problematic images and only need the trivial interface
|
||||
|
||||
JPEG baseline (no JPEG progressive, no oddball channel decimations)
|
||||
PNG non-interlaced
|
||||
BMP non-1bpp, non-RLE
|
||||
TGA (not sure what subset, if a subset)
|
||||
PSD (composited view only, no extra channels)
|
||||
HDR (radiance rgbE format)
|
||||
writes BMP,TGA (define STBI_NO_WRITE to remove code)
|
||||
decoded from memory or through stdio FILE (define STBI_NO_STDIO to remove code)
|
||||
supports installable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD)
|
||||
|
||||
TODO:
|
||||
stbi_info_*
|
||||
|
||||
history:
|
||||
1.16 major bugfix - convert_format converted one too many pixels
|
||||
1.15 initialize some fields for thread safety
|
||||
1.14 fix threadsafe conversion bug; header-file-only version (#define STBI_HEADER_FILE_ONLY before including)
|
||||
1.13 threadsafe
|
||||
1.12 const qualifiers in the API
|
||||
1.11 Support installable IDCT, colorspace conversion routines
|
||||
1.10 Fixes for 64-bit (don't use "unsigned long")
|
||||
optimized upsampling by Fabian "ryg" Giesen
|
||||
1.09 Fix format-conversion for PSD code (bad global variables!)
|
||||
1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz
|
||||
1.07 attempt to fix C++ warning/errors again
|
||||
1.06 attempt to fix C++ warning/errors again
|
||||
1.05 fix TGA loading to return correct *comp and use good luminance calc
|
||||
1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free
|
||||
1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR
|
||||
1.02 support for (subset of) HDR files, float interface for preferred access to them
|
||||
1.01 fix bug: possible bug in handling right-side up bmps... not sure
|
||||
fix bug: the stbi_bmp_load() and stbi_tga_load() functions didn't work at all
|
||||
1.00 interface to zlib that skips zlib header
|
||||
0.99 correct handling of alpha in palette
|
||||
0.98 TGA loader by lonesock; dynamically add loaders (untested)
|
||||
0.97 jpeg errors on too large a file; also catch another malloc failure
|
||||
0.96 fix detection of invalid v value - particleman@mollyrocket forum
|
||||
0.95 during header scan, seek to markers in case of padding
|
||||
0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same
|
||||
0.93 handle jpegtran output; verbose errors
|
||||
0.92 read 4,8,16,24,32-bit BMP files of several formats
|
||||
0.91 output 24-bit Windows 3.0 BMP files
|
||||
0.90 fix a few more warnings; bump version number to approach 1.0
|
||||
0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd
|
||||
0.60 fix compiling as c++
|
||||
0.59 fix warnings: merge Dave Moore's -Wall fixes
|
||||
0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian
|
||||
0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less
|
||||
than 16 available
|
||||
0.56 fix bug: zlib uncompressed mode len vs. nlen
|
||||
0.55 fix bug: restart_interval not initialized to 0
|
||||
0.54 allow NULL for 'int *comp'
|
||||
0.53 fix bug in png 3->4; speedup png decoding
|
||||
0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments
|
||||
0.51 obey req_comp requests, 1-component jpegs return as 1-component,
|
||||
on 'test' only check type, not whether we support this variant
|
||||
*/
|
||||
|
||||
#ifndef HEADER_STB_IMAGE_AUGMENTED
|
||||
#define HEADER_STB_IMAGE_AUGMENTED
|
||||
|
||||
//// begin header file ////////////////////////////////////////////////////
|
||||
//
|
||||
// Limitations:
|
||||
// - no progressive/interlaced support (jpeg, png)
|
||||
// - 8-bit samples only (jpeg, png)
|
||||
// - not threadsafe
|
||||
// - channel subsampling of at most 2 in each dimension (jpeg)
|
||||
// - no delayed line count (jpeg) -- IJG doesn't support either
|
||||
//
|
||||
// Basic usage (see HDR discussion below):
|
||||
// int x,y,n;
|
||||
// unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
|
||||
// // ... process data if not NULL ...
|
||||
// // ... x = width, y = height, n = # 8-bit components per pixel ...
|
||||
// // ... replace '0' with '1'..'4' to force that many components per pixel
|
||||
// stbi_image_free(data)
|
||||
//
|
||||
// Standard parameters:
|
||||
// int *x -- outputs image width in pixels
|
||||
// int *y -- outputs image height in pixels
|
||||
// int *comp -- outputs # of image components in image file
|
||||
// int req_comp -- if non-zero, # of image components requested in result
|
||||
//
|
||||
// The return value from an image loader is an 'unsigned char *' which points
|
||||
// to the pixel data. The pixel data consists of *y scanlines of *x pixels,
|
||||
// with each pixel consisting of N interleaved 8-bit components; the first
|
||||
// pixel pointed to is top-left-most in the image. There is no padding between
|
||||
// image scanlines or between pixels, regardless of format. The number of
|
||||
// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise.
|
||||
// If req_comp is non-zero, *comp has the number of components that _would_
|
||||
// have been output otherwise. E.g. if you set req_comp to 4, you will always
|
||||
// get RGBA output, but you can check *comp to easily see if it's opaque.
|
||||
//
|
||||
// An output image with N components has the following components interleaved
|
||||
// in this order in each pixel:
|
||||
//
|
||||
// N=#comp components
|
||||
// 1 grey
|
||||
// 2 grey, alpha
|
||||
// 3 red, green, blue
|
||||
// 4 red, green, blue, alpha
|
||||
//
|
||||
// If image loading fails for any reason, the return value will be NULL,
|
||||
// and *x, *y, *comp will be unchanged. The function stbi_failure_reason()
|
||||
// can be queried for an extremely brief, end-user unfriendly explanation
|
||||
// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid
|
||||
// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
|
||||
// more user-friendly ones.
|
||||
//
|
||||
// Paletted PNG and BMP images are automatically depalettized.
|
||||
//
|
||||
//
|
||||
// ===========================================================================
|
||||
//
|
||||
// HDR image support (disable by defining STBI_NO_HDR)
|
||||
//
|
||||
// stb_image now supports loading HDR images in general, and currently
|
||||
// the Radiance .HDR file format, although the support is provided
|
||||
// generically. You can still load any file through the existing interface;
|
||||
// if you attempt to load an HDR file, it will be automatically remapped to
|
||||
// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
|
||||
// both of these constants can be reconfigured through this interface:
|
||||
//
|
||||
// stbi_hdr_to_ldr_gamma(2.2f);
|
||||
// stbi_hdr_to_ldr_scale(1.0f);
|
||||
//
|
||||
// (note, do not use _inverse_ constants; stbi_image will invert them
|
||||
// appropriately).
|
||||
//
|
||||
// Additionally, there is a new, parallel interface for loading files as
|
||||
// (linear) floats to preserve the full dynamic range:
|
||||
//
|
||||
// float *data = stbi_loadf(filename, &x, &y, &n, 0);
|
||||
//
|
||||
// If you load LDR images through this interface, those images will
|
||||
// be promoted to floating point values, run through the inverse of
|
||||
// constants corresponding to the above:
|
||||
//
|
||||
// stbi_ldr_to_hdr_scale(1.0f);
|
||||
// stbi_ldr_to_hdr_gamma(2.2f);
|
||||
//
|
||||
// Finally, given a filename (or an open file or memory block--see header
|
||||
// file for details) containing image data, you can query for the "most
|
||||
// appropriate" interface to use (that is, whether the image is HDR or
|
||||
// not), using:
|
||||
//
|
||||
// stbi_is_hdr(char *filename);
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#define STBI_VERSION 1
|
||||
|
||||
enum
|
||||
{
|
||||
STBI_default = 0, // only used for req_comp
|
||||
|
||||
STBI_grey = 1,
|
||||
STBI_grey_alpha = 2,
|
||||
STBI_rgb = 3,
|
||||
STBI_rgb_alpha = 4,
|
||||
};
|
||||
|
||||
typedef unsigned char stbi_uc;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// WRITING API
|
||||
|
||||
#if !defined(STBI_NO_WRITE) && !defined(STBI_NO_STDIO)
|
||||
// write a BMP/TGA file given tightly packed 'comp' channels (no padding, nor bmp-stride-padding)
|
||||
// (you must include the appropriate extension in the filename).
|
||||
// returns TRUE on success, FALSE if couldn't open file, error writing file
|
||||
extern int stbi_write_bmp (char const *filename, int x, int y, int comp, void *data);
|
||||
extern int stbi_write_tga (char const *filename, int x, int y, int comp, void *data);
|
||||
#endif
|
||||
|
||||
// PRIMARY API - works on images of any type
|
||||
|
||||
// load image by filename, open file, or memory buffer
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp);
|
||||
#endif
|
||||
extern stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
// for stbi_load_from_file, file pointer is left pointing immediately after image
|
||||
|
||||
#ifndef STBI_NO_HDR
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
#endif
|
||||
extern float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
|
||||
extern void stbi_hdr_to_ldr_gamma(float gamma);
|
||||
extern void stbi_hdr_to_ldr_scale(float scale);
|
||||
|
||||
extern void stbi_ldr_to_hdr_gamma(float gamma);
|
||||
extern void stbi_ldr_to_hdr_scale(float scale);
|
||||
|
||||
#endif // STBI_NO_HDR
|
||||
|
||||
// get a VERY brief reason for failure
|
||||
// NOT THREADSAFE
|
||||
extern char *stbi_failure_reason (void);
|
||||
|
||||
// free the loaded image -- this is just free()
|
||||
extern void stbi_image_free (void *retval_from_stbi_load);
|
||||
|
||||
// get image dimensions & components without fully decoding
|
||||
extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
|
||||
extern int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi_info (char const *filename, int *x, int *y, int *comp);
|
||||
extern int stbi_is_hdr (char const *filename);
|
||||
extern int stbi_is_hdr_from_file(FILE *f);
|
||||
#endif
|
||||
|
||||
// ZLIB client - used by PNG, available for other purposes
|
||||
|
||||
extern char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
|
||||
extern char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
|
||||
extern int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
|
||||
|
||||
extern char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
|
||||
extern int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
|
||||
|
||||
// TYPE-SPECIFIC ACCESS
|
||||
|
||||
// is it a jpeg?
|
||||
extern int stbi_jpeg_test_memory (stbi_uc const *buffer, int len);
|
||||
extern stbi_uc *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern stbi_uc *stbi_jpeg_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern int stbi_jpeg_test_file (FILE *f);
|
||||
extern stbi_uc *stbi_jpeg_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
|
||||
extern int stbi_jpeg_info (char const *filename, int *x, int *y, int *comp);
|
||||
extern int stbi_jpeg_info_from_file (FILE *f, int *x, int *y, int *comp);
|
||||
#endif
|
||||
|
||||
// is it a png?
|
||||
extern int stbi_png_test_memory (stbi_uc const *buffer, int len);
|
||||
extern stbi_uc *stbi_png_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
extern int stbi_png_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp);
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern stbi_uc *stbi_png_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern int stbi_png_info (char const *filename, int *x, int *y, int *comp);
|
||||
extern int stbi_png_test_file (FILE *f);
|
||||
extern stbi_uc *stbi_png_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
extern int stbi_png_info_from_file (FILE *f, int *x, int *y, int *comp);
|
||||
#endif
|
||||
|
||||
// is it a bmp?
|
||||
extern int stbi_bmp_test_memory (stbi_uc const *buffer, int len);
|
||||
|
||||
extern stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi_bmp_test_file (FILE *f);
|
||||
extern stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
#endif
|
||||
|
||||
// is it a tga?
|
||||
extern int stbi_tga_test_memory (stbi_uc const *buffer, int len);
|
||||
|
||||
extern stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi_tga_test_file (FILE *f);
|
||||
extern stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
#endif
|
||||
|
||||
// is it a psd?
|
||||
extern int stbi_psd_test_memory (stbi_uc const *buffer, int len);
|
||||
|
||||
extern stbi_uc *stbi_psd_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi_psd_test_file (FILE *f);
|
||||
extern stbi_uc *stbi_psd_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
#endif
|
||||
|
||||
// is it an hdr?
|
||||
extern int stbi_hdr_test_memory (stbi_uc const *buffer, int len);
|
||||
|
||||
extern float * stbi_hdr_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi_hdr_load_rgbe (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi_hdr_test_file (FILE *f);
|
||||
extern float * stbi_hdr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi_hdr_load_rgbe_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
#endif
|
||||
|
||||
// define new loaders
|
||||
typedef struct
|
||||
{
|
||||
int (*test_memory)(stbi_uc const *buffer, int len);
|
||||
stbi_uc * (*load_from_memory)(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
#ifndef STBI_NO_STDIO
|
||||
int (*test_file)(FILE *f);
|
||||
stbi_uc * (*load_from_file)(FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
#endif
|
||||
} stbi_loader;
|
||||
|
||||
// register a loader by filling out the above structure (you must defined ALL functions)
|
||||
// returns 1 if added or already added, 0 if not added (too many loaders)
|
||||
// NOT THREADSAFE
|
||||
extern int stbi_register_loader(stbi_loader *loader);
|
||||
|
||||
// define faster low-level operations (typically SIMD support)
|
||||
#if STBI_SIMD
|
||||
typedef void (*stbi_idct_8x8)(uint8 *out, int out_stride, short data[64], unsigned short *dequantize);
|
||||
// compute an integer IDCT on "input"
|
||||
// input[x] = data[x] * dequantize[x]
|
||||
// write results to 'out': 64 samples, each run of 8 spaced by 'out_stride'
|
||||
// CLAMP results to 0..255
|
||||
typedef void (*stbi_YCbCr_to_RGB_run)(uint8 *output, uint8 const *y, uint8 const *cb, uint8 const *cr, int count, int step);
|
||||
// compute a conversion from YCbCr to RGB
|
||||
// 'count' pixels
|
||||
// write pixels to 'output'; each pixel is 'step' bytes (either 3 or 4; if 4, write '255' as 4th), order R,G,B
|
||||
// y: Y input channel
|
||||
// cb: Cb input channel; scale/biased to be 0..255
|
||||
// cr: Cr input channel; scale/biased to be 0..255
|
||||
|
||||
extern void stbi_install_idct(stbi_idct_8x8 func);
|
||||
extern void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func);
|
||||
#endif // STBI_SIMD
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
//
|
||||
//// end header file /////////////////////////////////////////////////////
|
||||
#endif // STBI_INCLUDE_STB_IMAGE_H
|
||||
@ -1,21 +0,0 @@
|
||||
/*
|
||||
adding DDS loading support to stbi
|
||||
*/
|
||||
|
||||
#ifndef HEADER_STB_IMAGE_DDS_AUGMENTATION
|
||||
#define HEADER_STB_IMAGE_DDS_AUGMENTATION
|
||||
|
||||
// is it a DDS file?
|
||||
extern int stbi_dds_test_memory (stbi_uc const *buffer, int len);
|
||||
|
||||
extern stbi_uc *stbi_dds_load (char *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi_dds_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi_dds_test_file (FILE *f);
|
||||
extern stbi_uc *stbi_dds_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
#endif
|
||||
|
||||
//
|
||||
//
|
||||
//// end header file /////////////////////////////////////////////////////
|
||||
#endif // HEADER_STB_IMAGE_DDS_AUGMENTATION
|
||||
File diff suppressed because it is too large
Load Diff
96
src/libprojectM/Renderer/SOIL/SOIL.h → src/libprojectM/Renderer/SOIL2/SOIL2.h
Normal file → Executable file
96
src/libprojectM/Renderer/SOIL/SOIL.h → src/libprojectM/Renderer/SOIL2/SOIL2.h
Normal file → Executable file
@ -1,10 +1,12 @@
|
||||
/**
|
||||
@mainpage SOIL
|
||||
@mainpage SOIL2
|
||||
|
||||
Jonathan Dummer
|
||||
Fork by Martin Lucas Golini
|
||||
|
||||
Original author Jonathan Dummer
|
||||
2007-07-26-10.36
|
||||
|
||||
Simple OpenGL Image Library
|
||||
Simple OpenGL Image Library 2
|
||||
|
||||
A tiny c library for uploading images as
|
||||
textures into OpenGL. Also saving and
|
||||
@ -21,8 +23,11 @@
|
||||
- BMP load & save
|
||||
- TGA load & save
|
||||
- DDS load & save
|
||||
- PNG load
|
||||
- PNG load & save
|
||||
- JPG load
|
||||
- PSD load
|
||||
- HDR load
|
||||
- PIC load
|
||||
|
||||
OpenGL Texture Features:
|
||||
- resample to power-of-two sizes
|
||||
@ -87,10 +92,11 @@ enum
|
||||
SOIL_FLAG_MULTIPLY_ALPHA: for using (GL_ONE,GL_ONE_MINUS_SRC_ALPHA) blending
|
||||
SOIL_FLAG_INVERT_Y: flip the image vertically
|
||||
SOIL_FLAG_COMPRESS_TO_DXT: if the card can display them, will convert RGB to DXT1, RGBA to DXT5
|
||||
SOIL_FLAG_DDS_LOAD_DIRECT: will load DDS files directly without _ANY_ additional processing
|
||||
SOIL_FLAG_DDS_LOAD_DIRECT: will load DDS files directly without _ANY_ additional processing ( if supported )
|
||||
SOIL_FLAG_NTSC_SAFE_RGB: clamps RGB components to the range [16,235]
|
||||
SOIL_FLAG_CoCg_Y: Google YCoCg; RGB=>CoYCg, RGBA=>CoCgAY
|
||||
SOIL_FLAG_TEXTURE_RECTANGE: uses ARB_texture_rectangle ; pixel indexed & no repeat or MIPmaps or cubemaps
|
||||
SOIL_FLAG_PVR_LOAD_DIRECT: will load PVR files directly without _ANY_ additional processing ( if supported )
|
||||
**/
|
||||
enum
|
||||
{
|
||||
@ -103,7 +109,10 @@ enum
|
||||
SOIL_FLAG_DDS_LOAD_DIRECT = 64,
|
||||
SOIL_FLAG_NTSC_SAFE_RGB = 128,
|
||||
SOIL_FLAG_CoCg_Y = 256,
|
||||
SOIL_FLAG_TEXTURE_RECTANGLE = 512
|
||||
SOIL_FLAG_TEXTURE_RECTANGLE = 512,
|
||||
SOIL_FLAG_PVR_LOAD_DIRECT = 1024,
|
||||
SOIL_FLAG_ETC1_LOAD_DIRECT = 2048,
|
||||
SOIL_FLAG_GL_MIPMAPS = 4096
|
||||
};
|
||||
|
||||
/**
|
||||
@ -111,12 +120,14 @@ enum
|
||||
(TGA supports uncompressed RGB / RGBA)
|
||||
(BMP supports uncompressed RGB)
|
||||
(DDS supports DXT1 and DXT5)
|
||||
(PNG supports RGB / RGBA)
|
||||
**/
|
||||
enum
|
||||
{
|
||||
SOIL_SAVE_TYPE_TGA = 0,
|
||||
SOIL_SAVE_TYPE_BMP = 1,
|
||||
SOIL_SAVE_TYPE_DDS = 2
|
||||
SOIL_SAVE_TYPE_PNG = 2,
|
||||
SOIL_SAVE_TYPE_DDS = 3
|
||||
};
|
||||
|
||||
/**
|
||||
@ -158,17 +169,6 @@ unsigned int
|
||||
unsigned int flags
|
||||
);
|
||||
|
||||
unsigned int
|
||||
SOIL_load_OGL_texture_size
|
||||
(
|
||||
const char *filename,
|
||||
int force_channels,
|
||||
unsigned int reuse_texture_ID,
|
||||
unsigned int flags,
|
||||
int *width,
|
||||
int *height
|
||||
);
|
||||
|
||||
/**
|
||||
Loads 6 images from disk into an OpenGL cubemap texture.
|
||||
\param x_pos_file the name of the file to upload as the +x cube face
|
||||
@ -316,8 +316,8 @@ unsigned int
|
||||
Creates a 2D OpenGL texture from raw image data. Note that the raw data is
|
||||
_NOT_ freed after the upload (so the user can load various versions).
|
||||
\param data the raw data to be uploaded as an OpenGL texture
|
||||
\param width the width of the image in pixels
|
||||
\param height the height of the image in pixels
|
||||
\param width the pointer of the width of the image in pixels ( if the texture size change, width will be overrided with the new width )
|
||||
\param height the pointer of the height of the image in pixels ( if the texture size change, height will be overrided with the new height )
|
||||
\param channels the number of channels: 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
|
||||
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
|
||||
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT
|
||||
@ -327,7 +327,7 @@ unsigned int
|
||||
SOIL_create_OGL_texture
|
||||
(
|
||||
const unsigned char *const data,
|
||||
int width, int height, int channels,
|
||||
int *width, int *height, int channels,
|
||||
unsigned int reuse_texture_ID,
|
||||
unsigned int flags
|
||||
);
|
||||
@ -436,6 +436,60 @@ const char*
|
||||
void
|
||||
);
|
||||
|
||||
/** @return The address of the GL function proc, or NULL if the function is not found. */
|
||||
void *
|
||||
SOIL_GL_GetProcAddress
|
||||
(
|
||||
const char *proc
|
||||
);
|
||||
|
||||
/** @return 1 if an OpenGL extension is supported for the current context, 0 otherwise. */
|
||||
int
|
||||
SOIL_GL_ExtensionSupported
|
||||
(
|
||||
const char *extension
|
||||
);
|
||||
|
||||
/** Loads the DDS texture directly to the GPU memory ( if supported ) */
|
||||
unsigned int SOIL_direct_load_DDS(
|
||||
const char *filename,
|
||||
unsigned int reuse_texture_ID,
|
||||
int flags,
|
||||
int loading_as_cubemap );
|
||||
|
||||
/** Loads the DDS texture directly to the GPU memory ( if supported ) */
|
||||
unsigned int SOIL_direct_load_DDS_from_memory(
|
||||
const unsigned char *const buffer,
|
||||
int buffer_length,
|
||||
unsigned int reuse_texture_ID,
|
||||
int flags,
|
||||
int loading_as_cubemap );
|
||||
|
||||
/** Loads the PVR texture directly to the GPU memory ( if supported ) */
|
||||
unsigned int SOIL_direct_load_PVR(
|
||||
const char *filename,
|
||||
unsigned int reuse_texture_ID,
|
||||
int flags,
|
||||
int loading_as_cubemap );
|
||||
|
||||
/** Loads the PVR texture directly to the GPU memory ( if supported ) */
|
||||
unsigned int SOIL_direct_load_PVR_from_memory(
|
||||
const unsigned char *const buffer,
|
||||
int buffer_length,
|
||||
unsigned int reuse_texture_ID,
|
||||
int flags,
|
||||
int loading_as_cubemap );
|
||||
|
||||
/** Loads the PVR texture directly to the GPU memory ( if supported ) */
|
||||
unsigned int SOIL_direct_load_ETC1(const char *filename,
|
||||
unsigned int reuse_texture_ID,
|
||||
int flags );
|
||||
|
||||
/** Loads the PVR texture directly to the GPU memory ( if supported ) */
|
||||
unsigned int SOIL_direct_load_ETC1_from_memory(const unsigned char *const buffer,
|
||||
int buffer_length,
|
||||
unsigned int reuse_texture_ID,
|
||||
int flags );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
680
src/libprojectM/Renderer/SOIL2/etc1_utils.c
Normal file
680
src/libprojectM/Renderer/SOIL2/etc1_utils.c
Normal file
@ -0,0 +1,680 @@
|
||||
// Copyright 2009 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "etc1_utils.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* From http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt
|
||||
|
||||
The number of bits that represent a 4x4 texel block is 64 bits if
|
||||
<internalformat> is given by ETC1_RGB8_OES.
|
||||
|
||||
The data for a block is a number of bytes,
|
||||
|
||||
{q0, q1, q2, q3, q4, q5, q6, q7}
|
||||
|
||||
where byte q0 is located at the lowest memory address and q7 at
|
||||
the highest. The 64 bits specifying the block is then represented
|
||||
by the following 64 bit integer:
|
||||
|
||||
int64bit = 256*(256*(256*(256*(256*(256*(256*q0+q1)+q2)+q3)+q4)+q5)+q6)+q7;
|
||||
|
||||
ETC1_RGB8_OES:
|
||||
|
||||
a) bit layout in bits 63 through 32 if diffbit = 0
|
||||
|
||||
63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48
|
||||
-----------------------------------------------
|
||||
| base col1 | base col2 | base col1 | base col2 |
|
||||
| R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)|
|
||||
-----------------------------------------------
|
||||
|
||||
47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
|
||||
---------------------------------------------------
|
||||
| base col1 | base col2 | table | table |diff|flip|
|
||||
| B1 (4bits)| B2 (4bits)| cw 1 | cw 2 |bit |bit |
|
||||
---------------------------------------------------
|
||||
|
||||
|
||||
b) bit layout in bits 63 through 32 if diffbit = 1
|
||||
|
||||
63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48
|
||||
-----------------------------------------------
|
||||
| base col1 | dcol 2 | base col1 | dcol 2 |
|
||||
| R1' (5 bits) | dR2 | G1' (5 bits) | dG2 |
|
||||
-----------------------------------------------
|
||||
|
||||
47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
|
||||
---------------------------------------------------
|
||||
| base col 1 | dcol 2 | table | table |diff|flip|
|
||||
| B1' (5 bits) | dB2 | cw 1 | cw 2 |bit |bit |
|
||||
---------------------------------------------------
|
||||
|
||||
|
||||
c) bit layout in bits 31 through 0 (in both cases)
|
||||
|
||||
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
|
||||
-----------------------------------------------
|
||||
| most significant pixel index bits |
|
||||
| p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a|
|
||||
-----------------------------------------------
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
--------------------------------------------------
|
||||
| least significant pixel index bits |
|
||||
| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
|
||||
--------------------------------------------------
|
||||
|
||||
|
||||
Add table 3.17.2: Intensity modifier sets for ETC1 compressed textures:
|
||||
|
||||
table codeword modifier table
|
||||
------------------ ----------------------
|
||||
0 -8 -2 2 8
|
||||
1 -17 -5 5 17
|
||||
2 -29 -9 9 29
|
||||
3 -42 -13 13 42
|
||||
4 -60 -18 18 60
|
||||
5 -80 -24 24 80
|
||||
6 -106 -33 33 106
|
||||
7 -183 -47 47 183
|
||||
|
||||
|
||||
Add table 3.17.3 Mapping from pixel index values to modifier values for
|
||||
ETC1 compressed textures:
|
||||
|
||||
pixel index value
|
||||
---------------
|
||||
msb lsb resulting modifier value
|
||||
----- ----- -------------------------
|
||||
1 1 -b (large negative value)
|
||||
1 0 -a (small negative value)
|
||||
0 0 a (small positive value)
|
||||
0 1 b (large positive value)
|
||||
|
||||
|
||||
*/
|
||||
|
||||
static const int kModifierTable[] = {
|
||||
/* 0 */2, 8, -2, -8,
|
||||
/* 1 */5, 17, -5, -17,
|
||||
/* 2 */9, 29, -9, -29,
|
||||
/* 3 */13, 42, -13, -42,
|
||||
/* 4 */18, 60, -18, -60,
|
||||
/* 5 */24, 80, -24, -80,
|
||||
/* 6 */33, 106, -33, -106,
|
||||
/* 7 */47, 183, -47, -183 };
|
||||
|
||||
static const int kLookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 };
|
||||
|
||||
static inline etc1_byte clamp(int x) {
|
||||
return (etc1_byte) (x >= 0 ? (x < 255 ? x : 255) : 0);
|
||||
}
|
||||
|
||||
static
|
||||
inline int convert4To8(int b) {
|
||||
int c = b & 0xf;
|
||||
return (c << 4) | c;
|
||||
}
|
||||
|
||||
static
|
||||
inline int convert5To8(int b) {
|
||||
int c = b & 0x1f;
|
||||
return (c << 3) | (c >> 2);
|
||||
}
|
||||
|
||||
static
|
||||
inline int convert6To8(int b) {
|
||||
int c = b & 0x3f;
|
||||
return (c << 2) | (c >> 4);
|
||||
}
|
||||
|
||||
static
|
||||
inline int divideBy255(int d) {
|
||||
return (d + 128 + (d >> 8)) >> 8;
|
||||
}
|
||||
|
||||
static
|
||||
inline int convert8To4(int b) {
|
||||
//int c = b & 0xff;
|
||||
return divideBy255(b * 15);
|
||||
}
|
||||
|
||||
static
|
||||
inline int convert8To5(int b) {
|
||||
//int c = b & 0xff;
|
||||
return divideBy255(b * 31);
|
||||
}
|
||||
|
||||
static
|
||||
inline int convertDiff(int base, int diff) {
|
||||
return convert5To8((0x1f & base) + kLookup[0x7 & diff]);
|
||||
}
|
||||
|
||||
static
|
||||
void decode_subblock(etc1_byte* pOut, int r, int g, int b, const int* table,
|
||||
etc1_uint32 low, etc1_bool second, etc1_bool flipped) {
|
||||
int baseX = 0;
|
||||
int baseY = 0;
|
||||
int i;
|
||||
|
||||
if (second) {
|
||||
if (flipped) {
|
||||
baseY = 2;
|
||||
} else {
|
||||
baseX = 2;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
int x, y;
|
||||
if (flipped) {
|
||||
x = baseX + (i >> 1);
|
||||
y = baseY + (i & 1);
|
||||
} else {
|
||||
x = baseX + (i >> 2);
|
||||
y = baseY + (i & 3);
|
||||
}
|
||||
int k = y + (x * 4);
|
||||
int offset = ((low >> k) & 1) | ((low >> (k + 15)) & 2);
|
||||
int delta = table[offset];
|
||||
etc1_byte* q = pOut + 3 * (x + 4 * y);
|
||||
*q++ = clamp(r + delta);
|
||||
*q++ = clamp(g + delta);
|
||||
*q++ = clamp(b + delta);
|
||||
}
|
||||
}
|
||||
|
||||
// Input is an ETC1 compressed version of the data.
|
||||
// Output is a 4 x 4 square of 3-byte pixels in form R, G, B
|
||||
|
||||
void etc1_decode_block(const etc1_byte* pIn, etc1_byte* pOut) {
|
||||
etc1_uint32 high = (pIn[0] << 24) | (pIn[1] << 16) | (pIn[2] << 8) | pIn[3];
|
||||
etc1_uint32 low = (pIn[4] << 24) | (pIn[5] << 16) | (pIn[6] << 8) | pIn[7];
|
||||
int r1, r2, g1, g2, b1, b2;
|
||||
if (high & 2) {
|
||||
// differential
|
||||
int rBase = high >> 27;
|
||||
int gBase = high >> 19;
|
||||
int bBase = high >> 11;
|
||||
r1 = convert5To8(rBase);
|
||||
r2 = convertDiff(rBase, high >> 24);
|
||||
g1 = convert5To8(gBase);
|
||||
g2 = convertDiff(gBase, high >> 16);
|
||||
b1 = convert5To8(bBase);
|
||||
b2 = convertDiff(bBase, high >> 8);
|
||||
} else {
|
||||
// not differential
|
||||
r1 = convert4To8(high >> 28);
|
||||
r2 = convert4To8(high >> 24);
|
||||
g1 = convert4To8(high >> 20);
|
||||
g2 = convert4To8(high >> 16);
|
||||
b1 = convert4To8(high >> 12);
|
||||
b2 = convert4To8(high >> 8);
|
||||
}
|
||||
int tableIndexA = 7 & (high >> 5);
|
||||
int tableIndexB = 7 & (high >> 2);
|
||||
const int* tableA = kModifierTable + tableIndexA * 4;
|
||||
const int* tableB = kModifierTable + tableIndexB * 4;
|
||||
etc1_bool flipped = (high & 1) != 0;
|
||||
decode_subblock(pOut, r1, g1, b1, tableA, low, 0, flipped);
|
||||
decode_subblock(pOut, r2, g2, b2, tableB, low, 1, flipped);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
etc1_uint32 high;
|
||||
etc1_uint32 low;
|
||||
etc1_uint32 score; // Lower is more accurate
|
||||
} etc_compressed;
|
||||
|
||||
static
|
||||
inline void take_best(etc_compressed* a, const etc_compressed* b) {
|
||||
if (a->score > b->score) {
|
||||
*a = *b;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void etc_average_colors_subblock(const etc1_byte* pIn, etc1_uint32 inMask,
|
||||
etc1_byte* pColors, etc1_bool flipped, etc1_bool second) {
|
||||
int r = 0;
|
||||
int g = 0;
|
||||
int b = 0;
|
||||
int y, x;
|
||||
|
||||
if (flipped) {
|
||||
int by = 0;
|
||||
if (second) {
|
||||
by = 2;
|
||||
}
|
||||
for ( y = 0; y < 2; y++) {
|
||||
int yy = by + y;
|
||||
for ( x = 0; x < 4; x++) {
|
||||
int i = x + 4 * yy;
|
||||
if (inMask & (1 << i)) {
|
||||
const etc1_byte* p = pIn + i * 3;
|
||||
r += *(p++);
|
||||
g += *(p++);
|
||||
b += *(p++);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int bx = 0;
|
||||
if (second) {
|
||||
bx = 2;
|
||||
}
|
||||
for ( y = 0; y < 4; y++) {
|
||||
for ( x = 0; x < 2; x++) {
|
||||
int xx = bx + x;
|
||||
int i = xx + 4 * y;
|
||||
if (inMask & (1 << i)) {
|
||||
const etc1_byte* p = pIn + i * 3;
|
||||
r += *(p++);
|
||||
g += *(p++);
|
||||
b += *(p++);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pColors[0] = (etc1_byte)((r + 4) >> 3);
|
||||
pColors[1] = (etc1_byte)((g + 4) >> 3);
|
||||
pColors[2] = (etc1_byte)((b + 4) >> 3);
|
||||
}
|
||||
|
||||
static
|
||||
inline int square(int x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
static etc1_uint32 chooseModifier(const etc1_byte* pBaseColors,
|
||||
const etc1_byte* pIn, etc1_uint32 *pLow, int bitIndex,
|
||||
const int* pModifierTable) {
|
||||
etc1_uint32 bestScore = ~0;
|
||||
int bestIndex = 0;
|
||||
int pixelR = pIn[0];
|
||||
int pixelG = pIn[1];
|
||||
int pixelB = pIn[2];
|
||||
int r = pBaseColors[0];
|
||||
int g = pBaseColors[1];
|
||||
int b = pBaseColors[2];
|
||||
int i;
|
||||
for ( i = 0; i < 4; i++) {
|
||||
int modifier = pModifierTable[i];
|
||||
int decodedG = clamp(g + modifier);
|
||||
etc1_uint32 score = (etc1_uint32) (6 * square(decodedG - pixelG));
|
||||
if (score >= bestScore) {
|
||||
continue;
|
||||
}
|
||||
int decodedR = clamp(r + modifier);
|
||||
score += (etc1_uint32) (3 * square(decodedR - pixelR));
|
||||
if (score >= bestScore) {
|
||||
continue;
|
||||
}
|
||||
int decodedB = clamp(b + modifier);
|
||||
score += (etc1_uint32) square(decodedB - pixelB);
|
||||
if (score < bestScore) {
|
||||
bestScore = score;
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
etc1_uint32 lowMask = (((bestIndex >> 1) << 16) | (bestIndex & 1))
|
||||
<< bitIndex;
|
||||
*pLow |= lowMask;
|
||||
return bestScore;
|
||||
}
|
||||
|
||||
static
|
||||
void etc_encode_subblock_helper(const etc1_byte* pIn, etc1_uint32 inMask,
|
||||
etc_compressed* pCompressed, etc1_bool flipped, etc1_bool second,
|
||||
const etc1_byte* pBaseColors, const int* pModifierTable) {
|
||||
int score = pCompressed->score;
|
||||
int y, x;
|
||||
if (flipped) {
|
||||
int by = 0;
|
||||
if (second) {
|
||||
by = 2;
|
||||
}
|
||||
for ( y = 0; y < 2; y++) {
|
||||
int yy = by + y;
|
||||
for ( x = 0; x < 4; x++) {
|
||||
int i = x + 4 * yy;
|
||||
if (inMask & (1 << i)) {
|
||||
score += chooseModifier(pBaseColors, pIn + i * 3,
|
||||
&pCompressed->low, yy + x * 4, pModifierTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int bx = 0;
|
||||
if (second) {
|
||||
bx = 2;
|
||||
}
|
||||
for ( y = 0; y < 4; y++) {
|
||||
for ( x = 0; x < 2; x++) {
|
||||
int xx = bx + x;
|
||||
int i = xx + 4 * y;
|
||||
if (inMask & (1 << i)) {
|
||||
score += chooseModifier(pBaseColors, pIn + i * 3,
|
||||
&pCompressed->low, y + xx * 4, pModifierTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pCompressed->score = score;
|
||||
}
|
||||
|
||||
static etc1_bool inRange4bitSigned(int color) {
|
||||
return color >= -4 && color <= 3;
|
||||
}
|
||||
|
||||
static void etc_encodeBaseColors(etc1_byte* pBaseColors,
|
||||
const etc1_byte* pColors, etc_compressed* pCompressed) {
|
||||
int r1, g1, b1, r2 = 0, g2 = 0, b2 = 0; // 8 bit base colors for sub-blocks
|
||||
etc1_bool differential;
|
||||
{
|
||||
int r51 = convert8To5(pColors[0]);
|
||||
int g51 = convert8To5(pColors[1]);
|
||||
int b51 = convert8To5(pColors[2]);
|
||||
int r52 = convert8To5(pColors[3]);
|
||||
int g52 = convert8To5(pColors[4]);
|
||||
int b52 = convert8To5(pColors[5]);
|
||||
|
||||
r1 = convert5To8(r51);
|
||||
g1 = convert5To8(g51);
|
||||
b1 = convert5To8(b51);
|
||||
|
||||
int dr = r52 - r51;
|
||||
int dg = g52 - g51;
|
||||
int db = b52 - b51;
|
||||
|
||||
differential = inRange4bitSigned(dr) && inRange4bitSigned(dg)
|
||||
&& inRange4bitSigned(db);
|
||||
if (differential) {
|
||||
r2 = convert5To8(r51 + dr);
|
||||
g2 = convert5To8(g51 + dg);
|
||||
b2 = convert5To8(b51 + db);
|
||||
pCompressed->high |= (r51 << 27) | ((7 & dr) << 24) | (g51 << 19)
|
||||
| ((7 & dg) << 16) | (b51 << 11) | ((7 & db) << 8) | 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!differential) {
|
||||
int r41 = convert8To4(pColors[0]);
|
||||
int g41 = convert8To4(pColors[1]);
|
||||
int b41 = convert8To4(pColors[2]);
|
||||
int r42 = convert8To4(pColors[3]);
|
||||
int g42 = convert8To4(pColors[4]);
|
||||
int b42 = convert8To4(pColors[5]);
|
||||
r1 = convert4To8(r41);
|
||||
g1 = convert4To8(g41);
|
||||
b1 = convert4To8(b41);
|
||||
r2 = convert4To8(r42);
|
||||
g2 = convert4To8(g42);
|
||||
b2 = convert4To8(b42);
|
||||
pCompressed->high |= (r41 << 28) | (r42 << 24) | (g41 << 20) | (g42
|
||||
<< 16) | (b41 << 12) | (b42 << 8);
|
||||
}
|
||||
pBaseColors[0] = r1;
|
||||
pBaseColors[1] = g1;
|
||||
pBaseColors[2] = b1;
|
||||
pBaseColors[3] = r2;
|
||||
pBaseColors[4] = g2;
|
||||
pBaseColors[5] = b2;
|
||||
}
|
||||
|
||||
static
|
||||
void etc_encode_block_helper(const etc1_byte* pIn, etc1_uint32 inMask,
|
||||
const etc1_byte* pColors, etc_compressed* pCompressed, etc1_bool flipped) {
|
||||
int i;
|
||||
|
||||
pCompressed->score = ~0;
|
||||
pCompressed->high = (flipped ? 1 : 0);
|
||||
pCompressed->low = 0;
|
||||
|
||||
etc1_byte pBaseColors[6];
|
||||
|
||||
etc_encodeBaseColors(pBaseColors, pColors, pCompressed);
|
||||
|
||||
int originalHigh = pCompressed->high;
|
||||
|
||||
const int* pModifierTable = kModifierTable;
|
||||
for ( i = 0; i < 8; i++, pModifierTable += 4) {
|
||||
etc_compressed temp;
|
||||
temp.score = 0;
|
||||
temp.high = originalHigh | (i << 5);
|
||||
temp.low = 0;
|
||||
etc_encode_subblock_helper(pIn, inMask, &temp, flipped, 0,
|
||||
pBaseColors, pModifierTable);
|
||||
take_best(pCompressed, &temp);
|
||||
}
|
||||
pModifierTable = kModifierTable;
|
||||
etc_compressed firstHalf = *pCompressed;
|
||||
for ( i = 0; i < 8; i++, pModifierTable += 4) {
|
||||
etc_compressed temp;
|
||||
temp.score = firstHalf.score;
|
||||
temp.high = firstHalf.high | (i << 2);
|
||||
temp.low = firstHalf.low;
|
||||
etc_encode_subblock_helper(pIn, inMask, &temp, flipped, 1,
|
||||
pBaseColors + 3, pModifierTable);
|
||||
if (i == 0) {
|
||||
*pCompressed = temp;
|
||||
} else {
|
||||
take_best(pCompressed, &temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void writeBigEndian(etc1_byte* pOut, etc1_uint32 d) {
|
||||
pOut[0] = (etc1_byte)(d >> 24);
|
||||
pOut[1] = (etc1_byte)(d >> 16);
|
||||
pOut[2] = (etc1_byte)(d >> 8);
|
||||
pOut[3] = (etc1_byte) d;
|
||||
}
|
||||
|
||||
// Input is a 4 x 4 square of 3-byte pixels in form R, G, B
|
||||
// inmask is a 16-bit mask where bit (1 << (x + y * 4)) tells whether the corresponding (x,y)
|
||||
// pixel is valid or not. Invalid pixel color values are ignored when compressing.
|
||||
// Output is an ETC1 compressed version of the data.
|
||||
|
||||
void etc1_encode_block(const etc1_byte* pIn, etc1_uint32 inMask,
|
||||
etc1_byte* pOut) {
|
||||
etc1_byte colors[6];
|
||||
etc1_byte flippedColors[6];
|
||||
etc_average_colors_subblock(pIn, inMask, colors, 0, 0);
|
||||
etc_average_colors_subblock(pIn, inMask, colors + 3, 0, 1);
|
||||
etc_average_colors_subblock(pIn, inMask, flippedColors, 1, 0);
|
||||
etc_average_colors_subblock(pIn, inMask, flippedColors + 3, 1, 1);
|
||||
|
||||
etc_compressed a, b;
|
||||
etc_encode_block_helper(pIn, inMask, colors, &a, 0);
|
||||
etc_encode_block_helper(pIn, inMask, flippedColors, &b, 1);
|
||||
take_best(&a, &b);
|
||||
writeBigEndian(pOut, a.high);
|
||||
writeBigEndian(pOut + 4, a.low);
|
||||
}
|
||||
|
||||
// Return the size of the encoded image data (does not include size of PKM header).
|
||||
|
||||
etc1_uint32 etc1_get_encoded_data_size(etc1_uint32 width, etc1_uint32 height) {
|
||||
return (((width + 3) & ~3) * ((height + 3) & ~3)) >> 1;
|
||||
}
|
||||
|
||||
// Encode an entire image.
|
||||
// pIn - pointer to the image data. Formatted such that the Red component of
|
||||
// pixel (x,y) is at pIn + pixelSize * x + stride * y + redOffset;
|
||||
// pOut - pointer to encoded data. Must be large enough to store entire encoded image.
|
||||
|
||||
int etc1_encode_image(const etc1_byte* pIn, etc1_uint32 width, etc1_uint32 height,
|
||||
etc1_uint32 pixelSize, etc1_uint32 stride, etc1_byte* pOut) {
|
||||
if (pixelSize < 2 || pixelSize > 3) {
|
||||
return -1;
|
||||
}
|
||||
static const unsigned short kYMask[] = { 0x0, 0xf, 0xff, 0xfff, 0xffff };
|
||||
static const unsigned short kXMask[] = { 0x0, 0x1111, 0x3333, 0x7777,
|
||||
0xffff };
|
||||
etc1_byte block[ETC1_DECODED_BLOCK_SIZE];
|
||||
etc1_byte encoded[ETC1_ENCODED_BLOCK_SIZE];
|
||||
etc1_uint32 y, x, cy, cx;
|
||||
|
||||
etc1_uint32 encodedWidth = (width + 3) & ~3;
|
||||
etc1_uint32 encodedHeight = (height + 3) & ~3;
|
||||
|
||||
for ( y = 0; y < encodedHeight; y += 4) {
|
||||
etc1_uint32 yEnd = height - y;
|
||||
if (yEnd > 4) {
|
||||
yEnd = 4;
|
||||
}
|
||||
int ymask = kYMask[yEnd];
|
||||
for ( x = 0; x < encodedWidth; x += 4) {
|
||||
etc1_uint32 xEnd = width - x;
|
||||
if (xEnd > 4) {
|
||||
xEnd = 4;
|
||||
}
|
||||
int mask = ymask & kXMask[xEnd];
|
||||
for ( cy = 0; cy < yEnd; cy++) {
|
||||
etc1_byte* q = block + (cy * 4) * 3;
|
||||
const etc1_byte* p = pIn + pixelSize * x + stride * (y + cy);
|
||||
if (pixelSize == 3) {
|
||||
memcpy(q, p, xEnd * 3);
|
||||
} else {
|
||||
for ( cx = 0; cx < xEnd; cx++) {
|
||||
int pixel = (p[1] << 8) | p[0];
|
||||
*q++ = convert5To8(pixel >> 11);
|
||||
*q++ = convert6To8(pixel >> 5);
|
||||
*q++ = convert5To8(pixel);
|
||||
p += pixelSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
etc1_encode_block(block, mask, encoded);
|
||||
memcpy(pOut, encoded, sizeof(encoded));
|
||||
pOut += sizeof(encoded);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Decode an entire image.
|
||||
// pIn - pointer to encoded data.
|
||||
// pOut - pointer to the image data. Will be written such that the Red component of
|
||||
// pixel (x,y) is at pIn + pixelSize * x + stride * y + redOffset. Must be
|
||||
// large enough to store entire image.
|
||||
|
||||
|
||||
int etc1_decode_image(const etc1_byte* pIn, etc1_byte* pOut,
|
||||
etc1_uint32 width, etc1_uint32 height,
|
||||
etc1_uint32 pixelSize, etc1_uint32 stride) {
|
||||
if (pixelSize < 2 || pixelSize > 3) {
|
||||
return -1;
|
||||
}
|
||||
etc1_byte block[ETC1_DECODED_BLOCK_SIZE];
|
||||
|
||||
etc1_uint32 encodedWidth = (width + 3) & ~3;
|
||||
etc1_uint32 encodedHeight = (height + 3) & ~3;
|
||||
|
||||
etc1_uint32 y, x, cy, cx;
|
||||
|
||||
for ( y = 0; y < encodedHeight; y += 4) {
|
||||
etc1_uint32 yEnd = height - y;
|
||||
if (yEnd > 4) {
|
||||
yEnd = 4;
|
||||
}
|
||||
for ( x = 0; x < encodedWidth; x += 4) {
|
||||
etc1_uint32 xEnd = width - x;
|
||||
if (xEnd > 4) {
|
||||
xEnd = 4;
|
||||
}
|
||||
etc1_decode_block(pIn, block);
|
||||
pIn += ETC1_ENCODED_BLOCK_SIZE;
|
||||
for ( cy = 0; cy < yEnd; cy++) {
|
||||
const etc1_byte* q = block + (cy * 4) * 3;
|
||||
etc1_byte* p = pOut + pixelSize * x + stride * (y + cy);
|
||||
if (pixelSize == 3) {
|
||||
memcpy(p, q, xEnd * 3);
|
||||
} else {
|
||||
for ( cx = 0; cx < xEnd; cx++) {
|
||||
etc1_byte r = *q++;
|
||||
etc1_byte g = *q++;
|
||||
etc1_byte b = *q++;
|
||||
etc1_uint32 pixel = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
|
||||
*p++ = (etc1_byte) pixel;
|
||||
*p++ = (etc1_byte) (pixel >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char kMagic[] = { 'P', 'K', 'M', ' ', '1', '0' };
|
||||
|
||||
static const etc1_uint32 ETC1_PKM_FORMAT_OFFSET = 6;
|
||||
static const etc1_uint32 ETC1_PKM_ENCODED_WIDTH_OFFSET = 8;
|
||||
static const etc1_uint32 ETC1_PKM_ENCODED_HEIGHT_OFFSET = 10;
|
||||
static const etc1_uint32 ETC1_PKM_WIDTH_OFFSET = 12;
|
||||
static const etc1_uint32 ETC1_PKM_HEIGHT_OFFSET = 14;
|
||||
|
||||
static const etc1_uint32 ETC1_RGB_NO_MIPMAPS = 0;
|
||||
|
||||
static void writeBEUint16(etc1_byte* pOut, etc1_uint32 data) {
|
||||
pOut[0] = (etc1_byte) (data >> 8);
|
||||
pOut[1] = (etc1_byte) data;
|
||||
}
|
||||
|
||||
static etc1_uint32 readBEUint16(const etc1_byte* pIn) {
|
||||
return (pIn[0] << 8) | pIn[1];
|
||||
}
|
||||
|
||||
// Format a PKM header
|
||||
|
||||
void etc1_pkm_format_header(etc1_byte* pHeader, etc1_uint32 width, etc1_uint32 height) {
|
||||
memcpy(pHeader, kMagic, sizeof(kMagic));
|
||||
etc1_uint32 encodedWidth = (width + 3) & ~3;
|
||||
etc1_uint32 encodedHeight = (height + 3) & ~3;
|
||||
writeBEUint16(pHeader + ETC1_PKM_FORMAT_OFFSET, ETC1_RGB_NO_MIPMAPS);
|
||||
writeBEUint16(pHeader + ETC1_PKM_ENCODED_WIDTH_OFFSET, encodedWidth);
|
||||
writeBEUint16(pHeader + ETC1_PKM_ENCODED_HEIGHT_OFFSET, encodedHeight);
|
||||
writeBEUint16(pHeader + ETC1_PKM_WIDTH_OFFSET, width);
|
||||
writeBEUint16(pHeader + ETC1_PKM_HEIGHT_OFFSET, height);
|
||||
}
|
||||
|
||||
// Check if a PKM header is correctly formatted.
|
||||
|
||||
etc1_bool etc1_pkm_is_valid(const etc1_byte* pHeader) {
|
||||
if (memcmp(pHeader, kMagic, sizeof(kMagic))) {
|
||||
return 0;
|
||||
}
|
||||
etc1_uint32 format = readBEUint16(pHeader + ETC1_PKM_FORMAT_OFFSET);
|
||||
etc1_uint32 encodedWidth = readBEUint16(pHeader + ETC1_PKM_ENCODED_WIDTH_OFFSET);
|
||||
etc1_uint32 encodedHeight = readBEUint16(pHeader + ETC1_PKM_ENCODED_HEIGHT_OFFSET);
|
||||
etc1_uint32 width = readBEUint16(pHeader + ETC1_PKM_WIDTH_OFFSET);
|
||||
etc1_uint32 height = readBEUint16(pHeader + ETC1_PKM_HEIGHT_OFFSET);
|
||||
return format == ETC1_RGB_NO_MIPMAPS &&
|
||||
encodedWidth >= width && encodedWidth - width < 4 &&
|
||||
encodedHeight >= height && encodedHeight - height < 4;
|
||||
}
|
||||
|
||||
// Read the image width from a PKM header
|
||||
|
||||
etc1_uint32 etc1_pkm_get_width(const etc1_byte* pHeader) {
|
||||
return readBEUint16(pHeader + ETC1_PKM_WIDTH_OFFSET);
|
||||
}
|
||||
|
||||
// Read the image height from a PKM header
|
||||
|
||||
etc1_uint32 etc1_pkm_get_height(const etc1_byte* pHeader){
|
||||
return readBEUint16(pHeader + ETC1_PKM_HEIGHT_OFFSET);
|
||||
}
|
||||
106
src/libprojectM/Renderer/SOIL2/etc1_utils.h
Normal file
106
src/libprojectM/Renderer/SOIL2/etc1_utils.h
Normal file
@ -0,0 +1,106 @@
|
||||
// Copyright 2009 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __etc1_h__
|
||||
#define __etc1_h__
|
||||
|
||||
#define ETC1_ENCODED_BLOCK_SIZE 8
|
||||
#define ETC1_DECODED_BLOCK_SIZE 48
|
||||
|
||||
#ifndef ETC1_RGB8_OES
|
||||
#define ETC1_RGB8_OES 0x8D64
|
||||
#endif
|
||||
|
||||
typedef unsigned char etc1_byte;
|
||||
typedef int etc1_bool;
|
||||
typedef unsigned int etc1_uint32;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Encode a block of pixels.
|
||||
//
|
||||
// pIn is a pointer to a ETC_DECODED_BLOCK_SIZE array of bytes that represent a
|
||||
// 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R
|
||||
// value of pixel (x, y).
|
||||
//
|
||||
// validPixelMask is a 16-bit mask where bit (1 << (x + y * 4)) indicates whether
|
||||
// the corresponding (x,y) pixel is valid. Invalid pixel color values are ignored when compressing.
|
||||
//
|
||||
// pOut is an ETC1 compressed version of the data.
|
||||
|
||||
void etc1_encode_block(const etc1_byte* pIn, etc1_uint32 validPixelMask, etc1_byte* pOut);
|
||||
|
||||
// Decode a block of pixels.
|
||||
//
|
||||
// pIn is an ETC1 compressed version of the data.
|
||||
//
|
||||
// pOut is a pointer to a ETC_DECODED_BLOCK_SIZE array of bytes that represent a
|
||||
// 4 x 4 square of 3-byte pixels in form R, G, B. Byte (3 * (x + 4 * y) is the R
|
||||
// value of pixel (x, y).
|
||||
|
||||
void etc1_decode_block(const etc1_byte* pIn, etc1_byte* pOut);
|
||||
|
||||
// Return the size of the encoded image data (does not include size of PKM header).
|
||||
|
||||
etc1_uint32 etc1_get_encoded_data_size(etc1_uint32 width, etc1_uint32 height);
|
||||
|
||||
// Encode an entire image.
|
||||
// pIn - pointer to the image data. Formatted such that
|
||||
// pixel (x,y) is at pIn + pixelSize * x + stride * y;
|
||||
// pOut - pointer to encoded data. Must be large enough to store entire encoded image.
|
||||
// pixelSize can be 2 or 3. 2 is an GL_UNSIGNED_SHORT_5_6_5 image, 3 is a GL_BYTE RGB image.
|
||||
// returns non-zero if there is an error.
|
||||
|
||||
int etc1_encode_image(const etc1_byte* pIn, etc1_uint32 width, etc1_uint32 height,
|
||||
etc1_uint32 pixelSize, etc1_uint32 stride, etc1_byte* pOut);
|
||||
|
||||
// Decode an entire image.
|
||||
// pIn - pointer to encoded data.
|
||||
// pOut - pointer to the image data. Will be written such that
|
||||
// pixel (x,y) is at pIn + pixelSize * x + stride * y. Must be
|
||||
// large enough to store entire image.
|
||||
// pixelSize can be 2 or 3. 2 is an GL_UNSIGNED_SHORT_5_6_5 image, 3 is a GL_BYTE RGB image.
|
||||
// returns non-zero if there is an error.
|
||||
|
||||
int etc1_decode_image(const etc1_byte* pIn, etc1_byte* pOut,
|
||||
etc1_uint32 width, etc1_uint32 height,
|
||||
etc1_uint32 pixelSize, etc1_uint32 stride);
|
||||
|
||||
// Size of a PKM header, in bytes.
|
||||
|
||||
#define ETC_PKM_HEADER_SIZE 16
|
||||
|
||||
// Format a PKM header
|
||||
|
||||
void etc1_pkm_format_header(etc1_byte* pHeader, etc1_uint32 width, etc1_uint32 height);
|
||||
|
||||
// Check if a PKM header is correctly formatted.
|
||||
|
||||
etc1_bool etc1_pkm_is_valid(const etc1_byte* pHeader);
|
||||
|
||||
// Read the image width from a PKM header
|
||||
|
||||
etc1_uint32 etc1_pkm_get_width(const etc1_byte* pHeader);
|
||||
|
||||
// Read the image height from a PKM header
|
||||
|
||||
etc1_uint32 etc1_pkm_get_height(const etc1_byte* pHeader);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
0
src/libprojectM/Renderer/SOIL/image_DXT.c → src/libprojectM/Renderer/SOIL2/image_DXT.c
Normal file → Executable file
0
src/libprojectM/Renderer/SOIL/image_DXT.c → src/libprojectM/Renderer/SOIL2/image_DXT.c
Normal file → Executable file
0
src/libprojectM/Renderer/SOIL/image_DXT.h → src/libprojectM/Renderer/SOIL2/image_DXT.h
Normal file → Executable file
0
src/libprojectM/Renderer/SOIL/image_DXT.h → src/libprojectM/Renderer/SOIL2/image_DXT.h
Normal file → Executable file
10
src/libprojectM/Renderer/SOIL/image_helper.c → src/libprojectM/Renderer/SOIL2/image_helper.c
Normal file → Executable file
10
src/libprojectM/Renderer/SOIL/image_helper.c → src/libprojectM/Renderer/SOIL2/image_helper.c
Normal file → Executable file
@ -322,7 +322,7 @@ find_max_RGBE
|
||||
for( i = width * height; i > 0; --i )
|
||||
{
|
||||
/* float scale = powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
|
||||
float scale = ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
|
||||
float scale = (float)ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
|
||||
for( j = 0; j < 3; ++j )
|
||||
{
|
||||
if( img[j] * scale > max_val )
|
||||
@ -363,14 +363,14 @@ RGBE_to_RGBdivA
|
||||
/* decode this pixel, and find the max */
|
||||
float r,g,b,e, m;
|
||||
/* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
|
||||
e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
|
||||
e = scale * (float)ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
|
||||
r = e * img[0];
|
||||
g = e * img[1];
|
||||
b = e * img[2];
|
||||
m = (r > g) ? r : g;
|
||||
m = (b > m) ? b : m;
|
||||
/* and encode it into RGBdivA */
|
||||
iv = (m != 0.0f) ? (int)(255.0f / m) : 1.0f;
|
||||
iv = (m != 0.0f) ? (int)(255.0f / m) : 1;
|
||||
iv = (iv < 1) ? 1 : iv;
|
||||
img[3] = (iv > 255) ? 255 : iv;
|
||||
iv = (int)(img[3] * r + 0.5f);
|
||||
@ -412,14 +412,14 @@ RGBE_to_RGBdivA2
|
||||
/* decode this pixel, and find the max */
|
||||
float r,g,b,e, m;
|
||||
/* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
|
||||
e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
|
||||
e = scale * (float)ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
|
||||
r = e * img[0];
|
||||
g = e * img[1];
|
||||
b = e * img[2];
|
||||
m = (r > g) ? r : g;
|
||||
m = (b > m) ? b : m;
|
||||
/* and encode it into RGBdivA */
|
||||
iv = (m != 0.0f) ? (int)sqrtf( 255.0f * 255.0f / m ) : 1.0f;
|
||||
iv = (m != 0.0f) ? (int)sqrtf( 255.0f * 255.0f / m ) : 1;
|
||||
iv = (iv < 1) ? 1 : iv;
|
||||
img[3] = (iv > 255) ? 255 : iv;
|
||||
iv = (int)(img[3] * img[3] * r / 255.0f + 0.5f);
|
||||
0
src/libprojectM/Renderer/SOIL/image_helper.h → src/libprojectM/Renderer/SOIL2/image_helper.h
Normal file → Executable file
0
src/libprojectM/Renderer/SOIL/image_helper.h → src/libprojectM/Renderer/SOIL2/image_helper.h
Normal file → Executable file
19
src/libprojectM/Renderer/SOIL2/pkm_helper.h
Normal file
19
src/libprojectM/Renderer/SOIL2/pkm_helper.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef PKM_HELPER_H
|
||||
#define PKM_HELPER_H
|
||||
|
||||
typedef struct {
|
||||
char aName[6];
|
||||
unsigned short iBlank;
|
||||
unsigned char iPaddedWidthMSB;
|
||||
unsigned char iPaddedWidthLSB;
|
||||
unsigned char iPaddedHeightMSB;
|
||||
unsigned char iPaddedHeightLSB;
|
||||
unsigned char iWidthMSB;
|
||||
unsigned char iWidthLSB;
|
||||
unsigned char iHeightMSB;
|
||||
unsigned char iHeightLSB;
|
||||
} PKMHeader;
|
||||
|
||||
#define PKM_HEADER_SIZE 16
|
||||
|
||||
#endif
|
||||
264
src/libprojectM/Renderer/SOIL2/pvr_helper.h
Normal file
264
src/libprojectM/Renderer/SOIL2/pvr_helper.h
Normal file
@ -0,0 +1,264 @@
|
||||
#ifndef PVR_HELPER_H
|
||||
#define PVR_HELPER_H
|
||||
|
||||
// Taken from PowerVR SDK
|
||||
|
||||
/*!***************************************************************************
|
||||
Describes the header of a PVR header-texture
|
||||
*****************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int dwHeaderSize; /*!< size of the structure */
|
||||
unsigned int dwHeight; /*!< height of surface to be created */
|
||||
unsigned int dwWidth; /*!< width of input surface */
|
||||
unsigned int dwMipMapCount; /*!< number of mip-map levels requested */
|
||||
unsigned int dwpfFlags; /*!< pixel format flags */
|
||||
unsigned int dwTextureDataSize; /*!< Total size in bytes */
|
||||
unsigned int dwBitCount; /*!< number of bits per pixel */
|
||||
unsigned int dwRBitMask; /*!< mask for red bit */
|
||||
unsigned int dwGBitMask; /*!< mask for green bits */
|
||||
unsigned int dwBBitMask; /*!< mask for blue bits */
|
||||
unsigned int dwAlphaBitMask; /*!< mask for alpha channel */
|
||||
unsigned int dwPVR; /*!< magic number identifying pvr file */
|
||||
unsigned int dwNumSurfs; /*!< the number of surfaces present in the pvr */
|
||||
} PVR_Texture_Header;
|
||||
|
||||
/*****************************************************************************
|
||||
* ENUMS
|
||||
*****************************************************************************/
|
||||
|
||||
enum PixelType
|
||||
{
|
||||
MGLPT_ARGB_4444 = 0x00,
|
||||
MGLPT_ARGB_1555,
|
||||
MGLPT_RGB_565,
|
||||
MGLPT_RGB_555,
|
||||
MGLPT_RGB_888,
|
||||
MGLPT_ARGB_8888,
|
||||
MGLPT_ARGB_8332,
|
||||
MGLPT_I_8,
|
||||
MGLPT_AI_88,
|
||||
MGLPT_1_BPP,
|
||||
MGLPT_VY1UY0,
|
||||
MGLPT_Y1VY0U,
|
||||
MGLPT_PVRTC2,
|
||||
MGLPT_PVRTC4,
|
||||
MGLPT_PVRTC2_2,
|
||||
MGLPT_PVRTC2_4,
|
||||
|
||||
OGL_RGBA_4444= 0x10,
|
||||
OGL_RGBA_5551,
|
||||
OGL_RGBA_8888,
|
||||
OGL_RGB_565,
|
||||
OGL_RGB_555,
|
||||
OGL_RGB_888,
|
||||
OGL_I_8,
|
||||
OGL_AI_88,
|
||||
OGL_PVRTC2,
|
||||
OGL_PVRTC4,
|
||||
|
||||
// OGL_BGRA_8888 extension
|
||||
OGL_BGRA_8888,
|
||||
|
||||
D3D_DXT1 = 0x20,
|
||||
D3D_DXT2,
|
||||
D3D_DXT3,
|
||||
D3D_DXT4,
|
||||
D3D_DXT5,
|
||||
|
||||
D3D_RGB_332,
|
||||
D3D_AI_44,
|
||||
D3D_LVU_655,
|
||||
D3D_XLVU_8888,
|
||||
D3D_QWVU_8888,
|
||||
|
||||
//10 bits per channel
|
||||
D3D_ABGR_2101010,
|
||||
D3D_ARGB_2101010,
|
||||
D3D_AWVU_2101010,
|
||||
|
||||
//16 bits per channel
|
||||
D3D_GR_1616,
|
||||
D3D_VU_1616,
|
||||
D3D_ABGR_16161616,
|
||||
|
||||
//HDR formats
|
||||
D3D_R16F,
|
||||
D3D_GR_1616F,
|
||||
D3D_ABGR_16161616F,
|
||||
|
||||
//32 bits per channel
|
||||
D3D_R32F,
|
||||
D3D_GR_3232F,
|
||||
D3D_ABGR_32323232F,
|
||||
|
||||
// Ericsson
|
||||
ETC_RGB_4BPP,
|
||||
ETC_RGBA_EXPLICIT,
|
||||
ETC_RGBA_INTERPOLATED,
|
||||
|
||||
// DX10
|
||||
|
||||
|
||||
ePT_DX10_R32G32B32A32_FLOAT= 0x50,
|
||||
ePT_DX10_R32G32B32A32_UINT ,
|
||||
ePT_DX10_R32G32B32A32_SINT,
|
||||
|
||||
ePT_DX10_R32G32B32_FLOAT,
|
||||
ePT_DX10_R32G32B32_UINT,
|
||||
ePT_DX10_R32G32B32_SINT,
|
||||
|
||||
ePT_DX10_R16G16B16A16_FLOAT ,
|
||||
ePT_DX10_R16G16B16A16_UNORM,
|
||||
ePT_DX10_R16G16B16A16_UINT ,
|
||||
ePT_DX10_R16G16B16A16_SNORM ,
|
||||
ePT_DX10_R16G16B16A16_SINT ,
|
||||
|
||||
ePT_DX10_R32G32_FLOAT ,
|
||||
ePT_DX10_R32G32_UINT ,
|
||||
ePT_DX10_R32G32_SINT ,
|
||||
|
||||
ePT_DX10_R10G10B10A2_UNORM ,
|
||||
ePT_DX10_R10G10B10A2_UINT ,
|
||||
|
||||
ePT_DX10_R11G11B10_FLOAT ,
|
||||
|
||||
ePT_DX10_R8G8B8A8_UNORM ,
|
||||
ePT_DX10_R8G8B8A8_UNORM_SRGB ,
|
||||
ePT_DX10_R8G8B8A8_UINT ,
|
||||
ePT_DX10_R8G8B8A8_SNORM ,
|
||||
ePT_DX10_R8G8B8A8_SINT ,
|
||||
|
||||
ePT_DX10_R16G16_FLOAT ,
|
||||
ePT_DX10_R16G16_UNORM ,
|
||||
ePT_DX10_R16G16_UINT ,
|
||||
ePT_DX10_R16G16_SNORM ,
|
||||
ePT_DX10_R16G16_SINT ,
|
||||
|
||||
ePT_DX10_R32_FLOAT ,
|
||||
ePT_DX10_R32_UINT ,
|
||||
ePT_DX10_R32_SINT ,
|
||||
|
||||
ePT_DX10_R8G8_UNORM ,
|
||||
ePT_DX10_R8G8_UINT ,
|
||||
ePT_DX10_R8G8_SNORM ,
|
||||
ePT_DX10_R8G8_SINT ,
|
||||
|
||||
ePT_DX10_R16_FLOAT ,
|
||||
ePT_DX10_R16_UNORM ,
|
||||
ePT_DX10_R16_UINT ,
|
||||
ePT_DX10_R16_SNORM ,
|
||||
ePT_DX10_R16_SINT ,
|
||||
|
||||
ePT_DX10_R8_UNORM,
|
||||
ePT_DX10_R8_UINT,
|
||||
ePT_DX10_R8_SNORM,
|
||||
ePT_DX10_R8_SINT,
|
||||
|
||||
ePT_DX10_A8_UNORM,
|
||||
ePT_DX10_R1_UNORM,
|
||||
ePT_DX10_R9G9B9E5_SHAREDEXP,
|
||||
ePT_DX10_R8G8_B8G8_UNORM,
|
||||
ePT_DX10_G8R8_G8B8_UNORM,
|
||||
|
||||
ePT_DX10_BC1_UNORM,
|
||||
ePT_DX10_BC1_UNORM_SRGB,
|
||||
|
||||
ePT_DX10_BC2_UNORM,
|
||||
ePT_DX10_BC2_UNORM_SRGB,
|
||||
|
||||
ePT_DX10_BC3_UNORM,
|
||||
ePT_DX10_BC3_UNORM_SRGB,
|
||||
|
||||
ePT_DX10_BC4_UNORM,
|
||||
ePT_DX10_BC4_SNORM,
|
||||
|
||||
ePT_DX10_BC5_UNORM,
|
||||
ePT_DX10_BC5_SNORM,
|
||||
|
||||
//ePT_DX10_B5G6R5_UNORM, // defined but obsolete - won't actually load in DX10
|
||||
//ePT_DX10_B5G5R5A1_UNORM,
|
||||
//ePT_DX10_B8G8R8A8_UNORM,
|
||||
//ePT_DX10_B8G8R8X8_UNORM,
|
||||
|
||||
// OpenVG
|
||||
|
||||
/* RGB{A,X} channel ordering */
|
||||
ePT_VG_sRGBX_8888 = 0x90,
|
||||
ePT_VG_sRGBA_8888,
|
||||
ePT_VG_sRGBA_8888_PRE,
|
||||
ePT_VG_sRGB_565,
|
||||
ePT_VG_sRGBA_5551,
|
||||
ePT_VG_sRGBA_4444,
|
||||
ePT_VG_sL_8,
|
||||
ePT_VG_lRGBX_8888,
|
||||
ePT_VG_lRGBA_8888,
|
||||
ePT_VG_lRGBA_8888_PRE,
|
||||
ePT_VG_lL_8,
|
||||
ePT_VG_A_8,
|
||||
ePT_VG_BW_1,
|
||||
|
||||
/* {A,X}RGB channel ordering */
|
||||
ePT_VG_sXRGB_8888,
|
||||
ePT_VG_sARGB_8888,
|
||||
ePT_VG_sARGB_8888_PRE,
|
||||
ePT_VG_sARGB_1555,
|
||||
ePT_VG_sARGB_4444,
|
||||
ePT_VG_lXRGB_8888,
|
||||
ePT_VG_lARGB_8888,
|
||||
ePT_VG_lARGB_8888_PRE,
|
||||
|
||||
/* BGR{A,X} channel ordering */
|
||||
ePT_VG_sBGRX_8888,
|
||||
ePT_VG_sBGRA_8888,
|
||||
ePT_VG_sBGRA_8888_PRE,
|
||||
ePT_VG_sBGR_565,
|
||||
ePT_VG_sBGRA_5551,
|
||||
ePT_VG_sBGRA_4444,
|
||||
ePT_VG_lBGRX_8888,
|
||||
ePT_VG_lBGRA_8888,
|
||||
ePT_VG_lBGRA_8888_PRE,
|
||||
|
||||
/* {A,X}BGR channel ordering */
|
||||
ePT_VG_sXBGR_8888,
|
||||
ePT_VG_sABGR_8888 ,
|
||||
ePT_VG_sABGR_8888_PRE,
|
||||
ePT_VG_sABGR_1555,
|
||||
ePT_VG_sABGR_4444,
|
||||
ePT_VG_lXBGR_8888,
|
||||
ePT_VG_lABGR_8888,
|
||||
ePT_VG_lABGR_8888_PRE,
|
||||
|
||||
// max cap for iterating
|
||||
END_OF_PIXEL_TYPES,
|
||||
|
||||
MGLPT_NOTYPE = 0xff
|
||||
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* constants
|
||||
*****************************************************************************/
|
||||
|
||||
#define PVRTEX_MIPMAP (1<<8) // has mip map levels
|
||||
#define PVRTEX_TWIDDLE (1<<9) // is twiddled
|
||||
#define PVRTEX_BUMPMAP (1<<10) // has normals encoded for a bump map
|
||||
#define PVRTEX_TILING (1<<11) // is bordered for tiled pvr
|
||||
#define PVRTEX_CUBEMAP (1<<12) // is a cubemap/skybox
|
||||
#define PVRTEX_FALSEMIPCOL (1<<13) //
|
||||
#define PVRTEX_VOLUME (1<<14)
|
||||
#define PVRTEX_PIXELTYPE 0xff // pixel type is always in the last 16bits of the flags
|
||||
#define PVRTEX_IDENTIFIER 0x21525650 // the pvr identifier is the characters 'P','V','R'
|
||||
|
||||
#define PVRTEX_V1_HEADER_SIZE 44 // old header size was 44 for identification purposes
|
||||
|
||||
#define PVRTC2_MIN_TEXWIDTH 16
|
||||
#define PVRTC2_MIN_TEXHEIGHT 8
|
||||
#define PVRTC4_MIN_TEXWIDTH 8
|
||||
#define PVRTC4_MIN_TEXHEIGHT 8
|
||||
#define ETC_MIN_TEXWIDTH 4
|
||||
#define ETC_MIN_TEXHEIGHT 4
|
||||
#define DXT_MIN_TEXWIDTH 4
|
||||
#define DXT_MIN_TEXHEIGHT 4
|
||||
|
||||
#endif
|
||||
6506
src/libprojectM/Renderer/SOIL2/stb_image.h
Normal file
6506
src/libprojectM/Renderer/SOIL2/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
730
src/libprojectM/Renderer/SOIL2/stb_image_write.h
Normal file
730
src/libprojectM/Renderer/SOIL2/stb_image_write.h
Normal file
@ -0,0 +1,730 @@
|
||||
/* stb_image_write - v0.98 - public domain - http://nothings.org/stb/stb_image_write.h
|
||||
writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
|
||||
Before #including,
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
in the file that you want to have the implementation.
|
||||
|
||||
Will probably not work correctly with strict-aliasing optimizations.
|
||||
|
||||
ABOUT:
|
||||
|
||||
This header file is a library for writing images to C stdio. It could be
|
||||
adapted to write to memory or a general streaming interface; let me know.
|
||||
|
||||
The PNG output is not optimal; it is 20-50% larger than the file
|
||||
written by a decent optimizing implementation. This library is designed
|
||||
for source code compactness and simplicitly, not optimal image file size
|
||||
or run-time performance.
|
||||
|
||||
BUILDING:
|
||||
|
||||
You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
|
||||
You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
|
||||
malloc,realloc,free.
|
||||
You can define STBIW_MEMMOVE() to replace memmove()
|
||||
|
||||
USAGE:
|
||||
|
||||
There are four functions, one for each image file format:
|
||||
|
||||
int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
|
||||
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
|
||||
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
|
||||
int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data);
|
||||
|
||||
Each function returns 0 on failure and non-0 on success.
|
||||
|
||||
The functions create an image file defined by the parameters. The image
|
||||
is a rectangle of pixels stored from left-to-right, top-to-bottom.
|
||||
Each pixel contains 'comp' channels of data stored interleaved with 8-bits
|
||||
per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
|
||||
monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
|
||||
The *data pointer points to the first byte of the top-left-most pixel.
|
||||
For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
|
||||
a row of pixels to the first byte of the next row of pixels.
|
||||
|
||||
PNG creates output files with the same number of components as the input.
|
||||
The BMP format expands Y to RGB in the file format and does not
|
||||
output alpha.
|
||||
|
||||
PNG supports writing rectangles of data even when the bytes storing rows of
|
||||
data are not consecutive in memory (e.g. sub-rectangles of a larger image),
|
||||
by supplying the stride between the beginning of adjacent rows. The other
|
||||
formats do not. (Thus you cannot write a native-format BMP through the BMP
|
||||
writer, both because it is in BGR order and because it may have padding
|
||||
at the end of the line.)
|
||||
|
||||
HDR expects linear float data. Since the format is always 32-bit rgb(e)
|
||||
data, alpha (if provided) is discarded, and for monochrome data it is
|
||||
replicated across all three channels.
|
||||
|
||||
CREDITS:
|
||||
|
||||
PNG/BMP/TGA
|
||||
Sean Barrett
|
||||
HDR
|
||||
Baldur Karlsson
|
||||
TGA monochrome:
|
||||
Jean-Sebastien Guay
|
||||
misc enhancements:
|
||||
Tim Kelsey
|
||||
bugfixes:
|
||||
github:Chribba
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_STB_IMAGE_WRITE_H
|
||||
#define INCLUDE_STB_IMAGE_WRITE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
|
||||
extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
|
||||
extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
|
||||
extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif//INCLUDE_STB_IMAGE_WRITE_H
|
||||
|
||||
#ifdef STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC)
|
||||
// ok
|
||||
#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC)
|
||||
// ok
|
||||
#else
|
||||
#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC."
|
||||
#endif
|
||||
|
||||
#ifndef STBIW_MALLOC
|
||||
#define STBIW_MALLOC(sz) malloc(sz)
|
||||
#define STBIW_REALLOC(p,sz) realloc(p,sz)
|
||||
#define STBIW_FREE(p) free(p)
|
||||
#endif
|
||||
#ifndef STBIW_MEMMOVE
|
||||
#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef STBIW_ASSERT
|
||||
#include <assert.h>
|
||||
#define STBIW_ASSERT(x) assert(x)
|
||||
#endif
|
||||
|
||||
typedef unsigned int stbiw_uint32;
|
||||
typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
|
||||
|
||||
static void writefv(FILE *f, const char *fmt, va_list v)
|
||||
{
|
||||
while (*fmt) {
|
||||
switch (*fmt++) {
|
||||
case ' ': break;
|
||||
case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; }
|
||||
case '2': { int x = va_arg(v,int); unsigned char b[2];
|
||||
b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8);
|
||||
fwrite(b,2,1,f); break; }
|
||||
case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4];
|
||||
b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8);
|
||||
b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
|
||||
fwrite(b,4,1,f); break; }
|
||||
default:
|
||||
STBIW_ASSERT(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c)
|
||||
{
|
||||
unsigned char arr[3];
|
||||
arr[0] = a, arr[1] = b, arr[2] = c;
|
||||
fwrite(arr, 3, 1, f);
|
||||
}
|
||||
|
||||
static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
|
||||
{
|
||||
unsigned char bg[3] = { 255, 0, 255}, px[3];
|
||||
stbiw_uint32 zero = 0;
|
||||
int i,j,k, j_end;
|
||||
|
||||
if (y <= 0)
|
||||
return;
|
||||
|
||||
if (vdir < 0)
|
||||
j_end = -1, j = y-1;
|
||||
else
|
||||
j_end = y, j = 0;
|
||||
|
||||
for (; j != j_end; j += vdir) {
|
||||
for (i=0; i < x; ++i) {
|
||||
unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
|
||||
if (write_alpha < 0)
|
||||
fwrite(&d[comp-1], 1, 1, f);
|
||||
switch (comp) {
|
||||
case 1: fwrite(d, 1, 1, f);
|
||||
break;
|
||||
case 2: if (expand_mono)
|
||||
write3(f, d[0],d[0],d[0]); // monochrome bmp
|
||||
else
|
||||
fwrite(d, 1, 1, f); // monochrome TGA
|
||||
break;
|
||||
case 4:
|
||||
if (!write_alpha) {
|
||||
// composite against pink background
|
||||
for (k=0; k < 3; ++k)
|
||||
px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255;
|
||||
write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 3:
|
||||
write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]);
|
||||
break;
|
||||
}
|
||||
if (write_alpha > 0)
|
||||
fwrite(&d[comp-1], 1, 1, f);
|
||||
}
|
||||
fwrite(&zero,scanline_pad,1,f);
|
||||
}
|
||||
}
|
||||
|
||||
static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...)
|
||||
{
|
||||
FILE *f;
|
||||
if (y < 0 || x < 0) return 0;
|
||||
f = fopen(filename, "wb");
|
||||
if (f) {
|
||||
va_list v;
|
||||
va_start(v, fmt);
|
||||
writefv(f, fmt, v);
|
||||
va_end(v);
|
||||
write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad,expand_mono);
|
||||
fclose(f);
|
||||
}
|
||||
return f != NULL;
|
||||
}
|
||||
|
||||
int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
|
||||
{
|
||||
int pad = (-x*3) & 3;
|
||||
return outfile(filename,-1,-1,x,y,comp,1,(void *) data,0,pad,
|
||||
"11 4 22 4" "4 44 22 444444",
|
||||
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
|
||||
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
|
||||
}
|
||||
|
||||
int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
|
||||
{
|
||||
int has_alpha = (comp == 2 || comp == 4);
|
||||
int colorbytes = has_alpha ? comp-1 : comp;
|
||||
int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
|
||||
return outfile(filename, -1,-1, x, y, comp, 0, (void *) data, has_alpha, 0,
|
||||
"111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, (colorbytes+has_alpha)*8, has_alpha*8);
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// Radiance RGBE HDR writer
|
||||
// by Baldur Karlsson
|
||||
#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
|
||||
{
|
||||
int exponent;
|
||||
float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
|
||||
|
||||
if (maxcomp < 1e-32) {
|
||||
rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
|
||||
} else {
|
||||
float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
|
||||
|
||||
rgbe[0] = (unsigned char)(linear[0] * normalize);
|
||||
rgbe[1] = (unsigned char)(linear[1] * normalize);
|
||||
rgbe[2] = (unsigned char)(linear[2] * normalize);
|
||||
rgbe[3] = (unsigned char)(exponent + 128);
|
||||
}
|
||||
}
|
||||
|
||||
void stbiw__write_run_data(FILE *f, int length, unsigned char databyte)
|
||||
{
|
||||
unsigned char lengthbyte = (unsigned char) (length+128);
|
||||
STBIW_ASSERT(length+128 <= 255);
|
||||
fwrite(&lengthbyte, 1, 1, f);
|
||||
fwrite(&databyte, 1, 1, f);
|
||||
}
|
||||
|
||||
void stbiw__write_dump_data(FILE *f, int length, unsigned char *data)
|
||||
{
|
||||
unsigned char lengthbyte = (unsigned char )(length & 0xff);
|
||||
STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
|
||||
fwrite(&lengthbyte, 1, 1, f);
|
||||
fwrite(data, length, 1, f);
|
||||
}
|
||||
|
||||
void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scratch, const float *scanline)
|
||||
{
|
||||
unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
|
||||
unsigned char rgbe[4];
|
||||
float linear[3];
|
||||
int x;
|
||||
|
||||
scanlineheader[2] = (width&0xff00)>>8;
|
||||
scanlineheader[3] = (width&0x00ff);
|
||||
|
||||
/* skip RLE for images too small or large */
|
||||
if (width < 8 || width >= 32768) {
|
||||
for (x=0; x < width; x++) {
|
||||
switch (comp) {
|
||||
case 4: /* fallthrough */
|
||||
case 3: linear[2] = scanline[x*comp + 2];
|
||||
linear[1] = scanline[x*comp + 1];
|
||||
linear[0] = scanline[x*comp + 0];
|
||||
break;
|
||||
case 2: /* fallthrough */
|
||||
case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
|
||||
break;
|
||||
}
|
||||
stbiw__linear_to_rgbe(rgbe, linear);
|
||||
fwrite(rgbe, 4, 1, f);
|
||||
}
|
||||
} else {
|
||||
int c,r;
|
||||
/* encode into scratch buffer */
|
||||
for (x=0; x < width; x++) {
|
||||
switch(comp) {
|
||||
case 4: /* fallthrough */
|
||||
case 3: linear[2] = scanline[x*comp + 2];
|
||||
linear[1] = scanline[x*comp + 1];
|
||||
linear[0] = scanline[x*comp + 0];
|
||||
break;
|
||||
case 2: /* fallthrough */
|
||||
case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
|
||||
break;
|
||||
}
|
||||
stbiw__linear_to_rgbe(rgbe, linear);
|
||||
scratch[x + width*0] = rgbe[0];
|
||||
scratch[x + width*1] = rgbe[1];
|
||||
scratch[x + width*2] = rgbe[2];
|
||||
scratch[x + width*3] = rgbe[3];
|
||||
}
|
||||
|
||||
fwrite(scanlineheader, 4, 1, f);
|
||||
|
||||
/* RLE each component separately */
|
||||
for (c=0; c < 4; c++) {
|
||||
unsigned char *comp = &scratch[width*c];
|
||||
|
||||
x = 0;
|
||||
while (x < width) {
|
||||
// find first run
|
||||
r = x;
|
||||
while (r+2 < width) {
|
||||
if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
|
||||
break;
|
||||
++r;
|
||||
}
|
||||
if (r+2 >= width)
|
||||
r = width;
|
||||
// dump up to first run
|
||||
while (x < r) {
|
||||
int len = r-x;
|
||||
if (len > 128) len = 128;
|
||||
stbiw__write_dump_data(f, len, &comp[x]);
|
||||
x += len;
|
||||
}
|
||||
// if there's a run, output it
|
||||
if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd
|
||||
// find next byte after run
|
||||
while (r < width && comp[r] == comp[x])
|
||||
++r;
|
||||
// output run up to r
|
||||
while (x < r) {
|
||||
int len = r-x;
|
||||
if (len > 127) len = 127;
|
||||
stbiw__write_run_data(f, len, comp[x]);
|
||||
x += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
|
||||
{
|
||||
int i;
|
||||
FILE *f;
|
||||
if (y <= 0 || x <= 0 || data == NULL) return 0;
|
||||
f = fopen(filename, "wb");
|
||||
if (f) {
|
||||
/* Each component is stored separately. Allocate scratch space for full output scanline. */
|
||||
unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
|
||||
fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n" );
|
||||
fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" , y, x);
|
||||
for(i=0; i < y; i++)
|
||||
stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x);
|
||||
STBIW_FREE(scratch);
|
||||
fclose(f);
|
||||
}
|
||||
return f != NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// PNG
|
||||
|
||||
// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
|
||||
#define stbiw__sbraw(a) ((int *) (a) - 2)
|
||||
#define stbiw__sbm(a) stbiw__sbraw(a)[0]
|
||||
#define stbiw__sbn(a) stbiw__sbraw(a)[1]
|
||||
|
||||
#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
|
||||
#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
|
||||
#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
|
||||
|
||||
#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
|
||||
#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
|
||||
#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
|
||||
|
||||
static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
|
||||
{
|
||||
int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
|
||||
void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
|
||||
STBIW_ASSERT(p);
|
||||
if (p) {
|
||||
if (!*arr) ((int *) p)[1] = 0;
|
||||
*arr = (void *) ((int *) p + 2);
|
||||
stbiw__sbm(*arr) = m;
|
||||
}
|
||||
return *arr;
|
||||
}
|
||||
|
||||
static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
|
||||
{
|
||||
while (*bitcount >= 8) {
|
||||
stbiw__sbpush(data, (unsigned char) *bitbuffer);
|
||||
*bitbuffer >>= 8;
|
||||
*bitcount -= 8;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static int stbiw__zlib_bitrev(int code, int codebits)
|
||||
{
|
||||
int res=0;
|
||||
while (codebits--) {
|
||||
res = (res << 1) | (code & 1);
|
||||
code >>= 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < limit && i < 258; ++i)
|
||||
if (a[i] != b[i]) break;
|
||||
return i;
|
||||
}
|
||||
|
||||
static unsigned int stbiw__zhash(unsigned char *data)
|
||||
{
|
||||
stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
return hash;
|
||||
}
|
||||
|
||||
#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
|
||||
#define stbiw__zlib_add(code,codebits) \
|
||||
(bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
|
||||
#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
|
||||
// default huffman tables
|
||||
#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
|
||||
#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
|
||||
#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
|
||||
#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
|
||||
#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n))
|
||||
#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
|
||||
|
||||
#define stbiw__ZHASH 16384
|
||||
|
||||
unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
|
||||
{
|
||||
static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 };
|
||||
static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 };
|
||||
static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 };
|
||||
static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 };
|
||||
unsigned int bitbuf=0;
|
||||
int i,j, bitcount=0;
|
||||
unsigned char *out = NULL;
|
||||
unsigned char **hash_table[stbiw__ZHASH]; // 64KB on the stack!
|
||||
if (quality < 5) quality = 5;
|
||||
|
||||
stbiw__sbpush(out, 0x78); // DEFLATE 32K window
|
||||
stbiw__sbpush(out, 0x5e); // FLEVEL = 1
|
||||
stbiw__zlib_add(1,1); // BFINAL = 1
|
||||
stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman
|
||||
|
||||
for (i=0; i < stbiw__ZHASH; ++i)
|
||||
hash_table[i] = NULL;
|
||||
|
||||
i=0;
|
||||
while (i < data_len-3) {
|
||||
// hash next 3 bytes of data to be compressed
|
||||
int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
|
||||
unsigned char *bestloc = 0;
|
||||
unsigned char **hlist = hash_table[h];
|
||||
int n = stbiw__sbcount(hlist);
|
||||
for (j=0; j < n; ++j) {
|
||||
if (hlist[j]-data > i-32768) { // if entry lies within window
|
||||
int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
|
||||
if (d >= best) best=d,bestloc=hlist[j];
|
||||
}
|
||||
}
|
||||
// when hash table entry is too long, delete half the entries
|
||||
if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
|
||||
STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
|
||||
stbiw__sbn(hash_table[h]) = quality;
|
||||
}
|
||||
stbiw__sbpush(hash_table[h],data+i);
|
||||
|
||||
if (bestloc) {
|
||||
// "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
|
||||
h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
|
||||
hlist = hash_table[h];
|
||||
n = stbiw__sbcount(hlist);
|
||||
for (j=0; j < n; ++j) {
|
||||
if (hlist[j]-data > i-32767) {
|
||||
int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
|
||||
if (e > best) { // if next match is better, bail on current match
|
||||
bestloc = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestloc) {
|
||||
int d = (int) (data+i - bestloc); // distance back
|
||||
STBIW_ASSERT(d <= 32767 && best <= 258);
|
||||
for (j=0; best > lengthc[j+1]-1; ++j);
|
||||
stbiw__zlib_huff(j+257);
|
||||
if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
|
||||
for (j=0; d > distc[j+1]-1; ++j);
|
||||
stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
|
||||
if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
|
||||
i += best;
|
||||
} else {
|
||||
stbiw__zlib_huffb(data[i]);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
// write out final bytes
|
||||
for (;i < data_len; ++i)
|
||||
stbiw__zlib_huffb(data[i]);
|
||||
stbiw__zlib_huff(256); // end of block
|
||||
// pad with 0 bits to byte boundary
|
||||
while (bitcount)
|
||||
stbiw__zlib_add(0,1);
|
||||
|
||||
for (i=0; i < stbiw__ZHASH; ++i)
|
||||
(void) stbiw__sbfree(hash_table[i]);
|
||||
|
||||
{
|
||||
// compute adler32 on input
|
||||
unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552;
|
||||
int j=0;
|
||||
while (j < data_len) {
|
||||
for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
|
||||
s1 %= 65521, s2 %= 65521;
|
||||
j += blocklen;
|
||||
blocklen = 5552;
|
||||
}
|
||||
stbiw__sbpush(out, (unsigned char) (s2 >> 8));
|
||||
stbiw__sbpush(out, (unsigned char) s2);
|
||||
stbiw__sbpush(out, (unsigned char) (s1 >> 8));
|
||||
stbiw__sbpush(out, (unsigned char) s1);
|
||||
}
|
||||
*out_len = stbiw__sbn(out);
|
||||
// make returned pointer freeable
|
||||
STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
|
||||
return (unsigned char *) stbiw__sbraw(out);
|
||||
}
|
||||
|
||||
unsigned int stbiw__crc32(unsigned char *buffer, int len)
|
||||
{
|
||||
static unsigned int crc_table[256];
|
||||
unsigned int crc = ~0u;
|
||||
int i,j;
|
||||
if (crc_table[1] == 0)
|
||||
for(i=0; i < 256; i++)
|
||||
for (crc_table[i]=i, j=0; j < 8; ++j)
|
||||
crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0);
|
||||
for (i=0; i < len; ++i)
|
||||
crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=(unsigned char)(a),(o)[1]=(unsigned char)(b),(o)[2]=(unsigned char)(c),(o)[3]=(unsigned char)(d),(o)+=4)
|
||||
#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
|
||||
#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
|
||||
|
||||
static void stbiw__wpcrc(unsigned char **data, int len)
|
||||
{
|
||||
unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
|
||||
stbiw__wp32(*data, crc);
|
||||
}
|
||||
|
||||
static unsigned char stbiw__paeth(int a, int b, int c)
|
||||
{
|
||||
int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
|
||||
if (pa <= pb && pa <= pc) return (unsigned char) a;
|
||||
if (pb <= pc) return (unsigned char) b;
|
||||
return (unsigned char) c;
|
||||
}
|
||||
|
||||
unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
|
||||
{
|
||||
int ctype[5] = { -1, 0, 4, 2, 6 };
|
||||
unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
|
||||
unsigned char *out,*o, *filt, *zlib;
|
||||
signed char *line_buffer;
|
||||
int i,j,k,p,zlen;
|
||||
|
||||
if (stride_bytes == 0)
|
||||
stride_bytes = x * n;
|
||||
|
||||
filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
|
||||
line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
|
||||
for (j=0; j < y; ++j) {
|
||||
static int mapping[] = { 0,1,2,3,4 };
|
||||
static int firstmap[] = { 0,1,0,5,6 };
|
||||
int *mymap = j ? mapping : firstmap;
|
||||
int best = 0, bestval = 0x7fffffff;
|
||||
for (p=0; p < 2; ++p) {
|
||||
for (k= p?best:0; k < 5; ++k) {
|
||||
int type = mymap[k],est=0;
|
||||
unsigned char *z = pixels + stride_bytes*j;
|
||||
for (i=0; i < n; ++i)
|
||||
switch (type) {
|
||||
case 0: line_buffer[i] = z[i]; break;
|
||||
case 1: line_buffer[i] = z[i]; break;
|
||||
case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
|
||||
case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
|
||||
case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break;
|
||||
case 5: line_buffer[i] = z[i]; break;
|
||||
case 6: line_buffer[i] = z[i]; break;
|
||||
}
|
||||
for (i=n; i < x*n; ++i) {
|
||||
switch (type) {
|
||||
case 0: line_buffer[i] = z[i]; break;
|
||||
case 1: line_buffer[i] = z[i] - z[i-n]; break;
|
||||
case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
|
||||
case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
|
||||
case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
|
||||
case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
|
||||
case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
|
||||
}
|
||||
}
|
||||
if (p) break;
|
||||
for (i=0; i < x*n; ++i)
|
||||
est += abs((signed char) line_buffer[i]);
|
||||
if (est < bestval) { bestval = est; best = k; }
|
||||
}
|
||||
}
|
||||
// when we get here, best contains the filter type, and line_buffer contains the data
|
||||
filt[j*(x*n+1)] = (unsigned char) best;
|
||||
STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
|
||||
}
|
||||
STBIW_FREE(line_buffer);
|
||||
zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
|
||||
STBIW_FREE(filt);
|
||||
if (!zlib) return 0;
|
||||
|
||||
// each tag requires 12 bytes of overhead
|
||||
out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
|
||||
if (!out) return 0;
|
||||
*out_len = 8 + 12+13 + 12+zlen + 12;
|
||||
|
||||
o=out;
|
||||
STBIW_MEMMOVE(o,sig,8); o+= 8;
|
||||
stbiw__wp32(o, 13); // header length
|
||||
stbiw__wptag(o, "IHDR");
|
||||
stbiw__wp32(o, x);
|
||||
stbiw__wp32(o, y);
|
||||
*o++ = 8;
|
||||
*o++ = (unsigned char) ctype[n];
|
||||
*o++ = 0;
|
||||
*o++ = 0;
|
||||
*o++ = 0;
|
||||
stbiw__wpcrc(&o,13);
|
||||
|
||||
stbiw__wp32(o, zlen);
|
||||
stbiw__wptag(o, "IDAT");
|
||||
STBIW_MEMMOVE(o, zlib, zlen);
|
||||
o += zlen;
|
||||
STBIW_FREE(zlib);
|
||||
stbiw__wpcrc(&o, zlen);
|
||||
|
||||
stbiw__wp32(o,0);
|
||||
stbiw__wptag(o, "IEND");
|
||||
stbiw__wpcrc(&o,0);
|
||||
|
||||
STBIW_ASSERT(o == out + *out_len);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
|
||||
{
|
||||
FILE *f;
|
||||
int len;
|
||||
unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
|
||||
if (!png) return 0;
|
||||
f = fopen(filename, "wb");
|
||||
if (!f) { STBIW_FREE(png); return 0; }
|
||||
fwrite(png, 1, len, f);
|
||||
fclose(f);
|
||||
STBIW_FREE(png);
|
||||
return 1;
|
||||
}
|
||||
#endif // STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
/* Revision history
|
||||
0.98 (2015-04-08)
|
||||
added STBIW_MALLOC, STBIW_ASSERT etc
|
||||
0.97 (2015-01-18)
|
||||
fixed HDR asserts, rewrote HDR rle logic
|
||||
0.96 (2015-01-17)
|
||||
add HDR output
|
||||
fix monochrome BMP
|
||||
0.95 (2014-08-17)
|
||||
add monochrome TGA output
|
||||
0.94 (2014-05-31)
|
||||
rename private functions to avoid conflicts with stb_image.h
|
||||
0.93 (2014-05-27)
|
||||
warning fixes
|
||||
0.92 (2010-08-01)
|
||||
casts to unsigned char to fix warnings
|
||||
0.91 (2010-07-17)
|
||||
first public release
|
||||
0.90 first internal release
|
||||
*/
|
||||
34
src/libprojectM/Renderer/SOIL2/stbi_DDS.h
Executable file
34
src/libprojectM/Renderer/SOIL2/stbi_DDS.h
Executable file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
adding DDS loading support to stbi
|
||||
*/
|
||||
|
||||
#ifndef HEADER_STB_IMAGE_DDS_AUGMENTATION
|
||||
#define HEADER_STB_IMAGE_DDS_AUGMENTATION
|
||||
|
||||
/* is it a DDS file? */
|
||||
extern int stbi__dds_test_memory (stbi_uc const *buffer, int len);
|
||||
extern int stbi__dds_test_callbacks (stbi_io_callbacks const *clbk, void *user);
|
||||
|
||||
extern stbi_uc *stbi__dds_load_from_path (const char *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi__dds_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi__dds_load_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp);
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi__dds_test_filename (char const *filename);
|
||||
extern int stbi__dds_test_file (FILE *f);
|
||||
extern stbi_uc *stbi__dds_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
#endif
|
||||
|
||||
extern int stbi__dds_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int *iscompressed);
|
||||
extern int stbi__dds_info_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int *iscompressed);
|
||||
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi__dds_info_from_path (char const *filename, int *x, int *y, int *comp, int *iscompressed);
|
||||
extern int stbi__dds_info_from_file (FILE *f, int *x, int *y, int *comp, int *iscompressed);
|
||||
#endif
|
||||
|
||||
/*
|
||||
//
|
||||
//// end header file /////////////////////////////////////////////////////*/
|
||||
#endif /* HEADER_STB_IMAGE_DDS_AUGMENTATION */
|
||||
302
src/libprojectM/Renderer/SOIL/stbi_DDS_aug_c.h → src/libprojectM/Renderer/SOIL2/stbi_DDS_c.h
Normal file → Executable file
302
src/libprojectM/Renderer/SOIL/stbi_DDS_aug_c.h → src/libprojectM/Renderer/SOIL2/stbi_DDS_c.h
Normal file → Executable file
@ -2,103 +2,77 @@
|
||||
/// DDS file support, does decoding, _not_ direct uploading
|
||||
/// (use SOIL for that ;-)
|
||||
|
||||
/// A bunch of DirectDraw Surface structures and flags
|
||||
typedef struct {
|
||||
unsigned int dwMagic;
|
||||
unsigned int dwSize;
|
||||
unsigned int dwFlags;
|
||||
unsigned int dwHeight;
|
||||
unsigned int dwWidth;
|
||||
unsigned int dwPitchOrLinearSize;
|
||||
unsigned int dwDepth;
|
||||
unsigned int dwMipMapCount;
|
||||
unsigned int dwReserved1[ 11 ];
|
||||
#include "image_DXT.h"
|
||||
|
||||
// DDPIXELFORMAT
|
||||
struct {
|
||||
unsigned int dwSize;
|
||||
unsigned int dwFlags;
|
||||
unsigned int dwFourCC;
|
||||
unsigned int dwRGBBitCount;
|
||||
unsigned int dwRBitMask;
|
||||
unsigned int dwGBitMask;
|
||||
unsigned int dwBBitMask;
|
||||
unsigned int dwAlphaBitMask;
|
||||
} sPixelFormat;
|
||||
|
||||
// DDCAPS2
|
||||
struct {
|
||||
unsigned int dwCaps1;
|
||||
unsigned int dwCaps2;
|
||||
unsigned int dwDDSX;
|
||||
unsigned int dwReserved;
|
||||
} sCaps;
|
||||
unsigned int dwReserved2;
|
||||
} DDS_header ;
|
||||
|
||||
// the following constants were copied directly off the MSDN website
|
||||
|
||||
// The dwFlags member of the original DDSURFACEDESC2 structure
|
||||
// can be set to one or more of the following values.
|
||||
#define DDSD_CAPS 0x00000001
|
||||
#define DDSD_HEIGHT 0x00000002
|
||||
#define DDSD_WIDTH 0x00000004
|
||||
#define DDSD_PITCH 0x00000008
|
||||
#define DDSD_PIXELFORMAT 0x00001000
|
||||
#define DDSD_MIPMAPCOUNT 0x00020000
|
||||
#define DDSD_LINEARSIZE 0x00080000
|
||||
#define DDSD_DEPTH 0x00800000
|
||||
|
||||
// DirectDraw Pixel Format
|
||||
#define DDPF_ALPHAPIXELS 0x00000001
|
||||
#define DDPF_FOURCC 0x00000004
|
||||
#define DDPF_RGB 0x00000040
|
||||
|
||||
// The dwCaps1 member of the DDSCAPS2 structure can be
|
||||
// set to one or more of the following values.
|
||||
#define DDSCAPS_COMPLEX 0x00000008
|
||||
#define DDSCAPS_TEXTURE 0x00001000
|
||||
#define DDSCAPS_MIPMAP 0x00400000
|
||||
|
||||
// The dwCaps2 member of the DDSCAPS2 structure can be
|
||||
// set to one or more of the following values.
|
||||
#define DDSCAPS2_CUBEMAP 0x00000200
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
|
||||
#define DDSCAPS2_VOLUME 0x00200000
|
||||
|
||||
static int dds_test(stbi *s)
|
||||
static int stbi__dds_test(stbi__context *s)
|
||||
{
|
||||
// check the magic number
|
||||
if (get8(s) != 'D') return 0;
|
||||
if (get8(s) != 'D') return 0;
|
||||
if (get8(s) != 'S') return 0;
|
||||
if (get8(s) != ' ') return 0;
|
||||
if (stbi__get8(s) != 'D') {
|
||||
stbi__rewind(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stbi__get8(s) != 'D') {
|
||||
stbi__rewind(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stbi__get8(s) != 'S') {
|
||||
stbi__rewind(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stbi__get8(s) != ' ') {
|
||||
stbi__rewind(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check header size
|
||||
if (get32le(s) != 124) return 0;
|
||||
if (stbi__get32le(s) != 124) {
|
||||
stbi__rewind(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Also rewind because the loader needs to read the header
|
||||
stbi__rewind(s);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#ifndef STBI_NO_STDIO
|
||||
int stbi_dds_test_file (FILE *f)
|
||||
|
||||
int stbi__dds_test_filename (char const *filename)
|
||||
{
|
||||
stbi s;
|
||||
int r;
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if (!f) return 0;
|
||||
r = stbi__dds_test_file(f);
|
||||
fclose(f);
|
||||
return r;
|
||||
}
|
||||
|
||||
int stbi__dds_test_file (FILE *f)
|
||||
{
|
||||
stbi__context s;
|
||||
int r,n = ftell(f);
|
||||
start_file(&s,f);
|
||||
r = dds_test(&s);
|
||||
stbi__start_file(&s,f);
|
||||
r = stbi__dds_test(&s);
|
||||
fseek(f,n,SEEK_SET);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
int stbi_dds_test_memory (stbi_uc const *buffer, int len)
|
||||
int stbi__dds_test_memory (stbi_uc const *buffer, int len)
|
||||
{
|
||||
stbi s;
|
||||
start_mem(&s,buffer, len);
|
||||
return dds_test(&s);
|
||||
stbi__context s;
|
||||
stbi__start_mem(&s,buffer, len);
|
||||
return stbi__dds_test(&s);
|
||||
}
|
||||
|
||||
int stbi__dds_test_callbacks (stbi_io_callbacks const *clbk, void *user)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
|
||||
return stbi__dds_test(&s);
|
||||
}
|
||||
|
||||
// helper functions
|
||||
@ -265,7 +239,104 @@ void stbi_decode_DXT_color_block(
|
||||
}
|
||||
// done
|
||||
}
|
||||
static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
||||
|
||||
static int stbi__dds_info( stbi__context *s, int *x, int *y, int *comp, int *iscompressed ) {
|
||||
int flags,is_compressed,has_alpha;
|
||||
DDS_header header={0};
|
||||
|
||||
if( sizeof( DDS_header ) != 128 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
stbi__getn( s, (stbi_uc*)(&header), 128 );
|
||||
|
||||
if( header.dwMagic != (('D' << 0) | ('D' << 8) | ('S' << 16) | (' ' << 24)) ) {
|
||||
stbi__rewind( s );
|
||||
return 0;
|
||||
}
|
||||
if( header.dwSize != 124 ) {
|
||||
stbi__rewind( s );
|
||||
return 0;
|
||||
}
|
||||
flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
|
||||
if( (header.dwFlags & flags) != flags ) {
|
||||
stbi__rewind( s );
|
||||
return 0;
|
||||
}
|
||||
if( header.sPixelFormat.dwSize != 32 ) {
|
||||
stbi__rewind( s );
|
||||
return 0;
|
||||
}
|
||||
flags = DDPF_FOURCC | DDPF_RGB;
|
||||
if( (header.sPixelFormat.dwFlags & flags) == 0 ) {
|
||||
stbi__rewind( s );
|
||||
return 0;
|
||||
}
|
||||
if( (header.sCaps.dwCaps1 & DDSCAPS_TEXTURE) == 0 ) {
|
||||
stbi__rewind( s );
|
||||
return 0;
|
||||
}
|
||||
|
||||
is_compressed = (header.sPixelFormat.dwFlags & DDPF_FOURCC) / DDPF_FOURCC;
|
||||
has_alpha = (header.sPixelFormat.dwFlags & DDPF_ALPHAPIXELS) / DDPF_ALPHAPIXELS;
|
||||
|
||||
*x = header.dwWidth;
|
||||
*y = header.dwHeight;
|
||||
|
||||
if ( !is_compressed ) {
|
||||
*comp = 3;
|
||||
|
||||
if ( has_alpha )
|
||||
*comp = 4;
|
||||
}
|
||||
else
|
||||
*comp = 4;
|
||||
|
||||
if ( iscompressed )
|
||||
*iscompressed = is_compressed;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int stbi__dds_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int *iscompressed)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_mem(&s,buffer, len);
|
||||
return stbi__dds_info( &s, x, y, comp, iscompressed );
|
||||
}
|
||||
|
||||
int stbi__dds_info_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int *iscompressed)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
|
||||
return stbi__dds_info( &s, x, y, comp, iscompressed );
|
||||
}
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
int stbi__dds_info_from_path(char const *filename, int *x, int *y, int *comp, int *iscompressed)
|
||||
{
|
||||
int res;
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if (!f) return 0;
|
||||
res = stbi__dds_info_from_file( f, x, y, comp, iscompressed );
|
||||
fclose(f);
|
||||
return res;
|
||||
}
|
||||
|
||||
int stbi__dds_info_from_file(FILE *f, int *x, int *y, int *comp, int *iscompressed)
|
||||
{
|
||||
stbi__context s;
|
||||
int res;
|
||||
long n = ftell(f);
|
||||
stbi__start_file(&s, f);
|
||||
res = stbi__dds_info(&s, x, y, comp, iscompressed);
|
||||
fseek(f, n, SEEK_SET);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
static stbi_uc * stbi__dds_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
// all variables go up front
|
||||
stbi_uc *dds_data = NULL;
|
||||
@ -275,14 +346,14 @@ static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
||||
int has_alpha, has_mipmap;
|
||||
int is_compressed, cubemap_faces;
|
||||
int block_pitch, num_blocks;
|
||||
DDS_header header;
|
||||
DDS_header header={0};
|
||||
int i, sz, cf;
|
||||
// load the header
|
||||
if( sizeof( DDS_header ) != 128 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
getn( s, (stbi_uc*)(&header), 128 );
|
||||
stbi__getn( s, (stbi_uc*)(&header), 128 );
|
||||
// and do some checking
|
||||
if( header.dwMagic != (('D' << 0) | ('D' << 8) | ('S' << 16) | (' ' << 24)) ) return NULL;
|
||||
if( header.dwSize != 124 ) return NULL;
|
||||
@ -341,29 +412,29 @@ static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
||||
if( DXT_family == 1 )
|
||||
{
|
||||
// DXT1
|
||||
getn( s, compressed, 8 );
|
||||
stbi__getn( s, compressed, 8 );
|
||||
stbi_decode_DXT1_block( block, compressed );
|
||||
} else if( DXT_family < 4 )
|
||||
{
|
||||
// DXT2/3
|
||||
getn( s, compressed, 8 );
|
||||
stbi__getn( s, compressed, 8 );
|
||||
stbi_decode_DXT23_alpha_block ( block, compressed );
|
||||
getn( s, compressed, 8 );
|
||||
stbi__getn( s, compressed, 8 );
|
||||
stbi_decode_DXT_color_block ( block, compressed );
|
||||
} else
|
||||
{
|
||||
// DXT4/5
|
||||
getn( s, compressed, 8 );
|
||||
stbi__getn( s, compressed, 8 );
|
||||
stbi_decode_DXT45_alpha_block ( block, compressed );
|
||||
getn( s, compressed, 8 );
|
||||
stbi__getn( s, compressed, 8 );
|
||||
stbi_decode_DXT_color_block ( block, compressed );
|
||||
}
|
||||
// is this a partial block?
|
||||
if( ref_x + 4 > s->img_x )
|
||||
if( ref_x + 4 > (int)s->img_x )
|
||||
{
|
||||
bw = s->img_x - ref_x;
|
||||
}
|
||||
if( ref_y + 4 > s->img_y )
|
||||
if( ref_y + 4 > (int)s->img_y )
|
||||
{
|
||||
bh = s->img_y - ref_y;
|
||||
}
|
||||
@ -379,7 +450,7 @@ static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
||||
}
|
||||
}
|
||||
/* done reading and decoding the main image...
|
||||
skip MIPmaps if present */
|
||||
stbi__skip MIPmaps if present */
|
||||
if( has_mipmap )
|
||||
{
|
||||
int block_size = 16;
|
||||
@ -387,7 +458,7 @@ static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
block_size = 8;
|
||||
}
|
||||
for( i = 1; i < header.dwMipMapCount; ++i )
|
||||
for( i = 1; i < (int)header.dwMipMapCount; ++i )
|
||||
{
|
||||
int mx = s->img_x >> (i + 2);
|
||||
int my = s->img_y >> (i + 2);
|
||||
@ -399,7 +470,7 @@ static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
my = 1;
|
||||
}
|
||||
skip( s, mx*my*block_size );
|
||||
stbi__skip( s, mx*my*block_size );
|
||||
}
|
||||
}
|
||||
}/* per cubemap face */
|
||||
@ -419,12 +490,12 @@ static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
||||
for( cf = 0; cf < cubemap_faces; ++ cf )
|
||||
{
|
||||
/* read the main image for this face */
|
||||
getn( s, &dds_data[cf*s->img_x*s->img_y*s->img_n], s->img_x*s->img_y*s->img_n );
|
||||
stbi__getn( s, &dds_data[cf*s->img_x*s->img_y*s->img_n], s->img_x*s->img_y*s->img_n );
|
||||
/* done reading and decoding the main image...
|
||||
skip MIPmaps if present */
|
||||
stbi__skip MIPmaps if present */
|
||||
if( has_mipmap )
|
||||
{
|
||||
for( i = 1; i < header.dwMipMapCount; ++i )
|
||||
for( i = 1; i < (int)header.dwMipMapCount; ++i )
|
||||
{
|
||||
int mx = s->img_x >> i;
|
||||
int my = s->img_y >> i;
|
||||
@ -436,7 +507,7 @@ static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
my = 1;
|
||||
}
|
||||
skip( s, mx*my*s->img_n );
|
||||
stbi__skip( s, mx*my*s->img_n );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -468,15 +539,15 @@ static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
||||
// user has some requirements, meet them
|
||||
if( req_comp != s->img_n )
|
||||
{
|
||||
dds_data = convert_format( dds_data, s->img_n, req_comp, s->img_x, s->img_y );
|
||||
*comp = s->img_n;
|
||||
dds_data = stbi__convert_format( dds_data, s->img_n, req_comp, s->img_x, s->img_y );
|
||||
*comp = req_comp;
|
||||
}
|
||||
} else
|
||||
{
|
||||
// user had no requirements, only drop to RGB is no alpha
|
||||
if( (has_alpha == 0) && (s->img_n == 4) )
|
||||
{
|
||||
dds_data = convert_format( dds_data, 4, 3, s->img_x, s->img_y );
|
||||
dds_data = stbi__convert_format( dds_data, 4, 3, s->img_x, s->img_y );
|
||||
*comp = 3;
|
||||
}
|
||||
}
|
||||
@ -485,27 +556,34 @@ static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
||||
}
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
stbi_uc *stbi_dds_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp)
|
||||
stbi_uc *stbi__dds_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
stbi s;
|
||||
start_file(&s,f);
|
||||
return dds_load(&s,x,y,comp,req_comp);
|
||||
stbi__context s;
|
||||
stbi__start_file(&s,f);
|
||||
return stbi__dds_load(&s,x,y,comp,req_comp);
|
||||
}
|
||||
|
||||
stbi_uc *stbi_dds_load (char *filename, int *x, int *y, int *comp, int req_comp)
|
||||
stbi_uc *stbi__dds_load_from_path (const char *filename, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
stbi_uc *data;
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if (!f) return NULL;
|
||||
data = stbi_dds_load_from_file(f,x,y,comp,req_comp);
|
||||
data = stbi__dds_load_from_file(f,x,y,comp,req_comp);
|
||||
fclose(f);
|
||||
return data;
|
||||
}
|
||||
#endif
|
||||
|
||||
stbi_uc *stbi_dds_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
|
||||
stbi_uc *stbi__dds_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
stbi s;
|
||||
start_mem(&s,buffer, len);
|
||||
return dds_load(&s,x,y,comp,req_comp);
|
||||
stbi__context s;
|
||||
stbi__start_mem(&s,buffer, len);
|
||||
return stbi__dds_load(&s,x,y,comp,req_comp);
|
||||
}
|
||||
|
||||
stbi_uc *stbi__dds_load_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
|
||||
return stbi__dds_load(&s,x,y,comp,req_comp);
|
||||
}
|
||||
28
src/libprojectM/Renderer/SOIL2/stbi_ext.h
Normal file
28
src/libprojectM/Renderer/SOIL2/stbi_ext.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef HEADER_STB_IMAGE_EXT
|
||||
#define HEADER_STB_IMAGE_EXT
|
||||
|
||||
enum {
|
||||
STBI_unknown= 0,
|
||||
STBI_jpeg = 1,
|
||||
STBI_png = 2,
|
||||
STBI_bmp = 3,
|
||||
STBI_gif = 4,
|
||||
STBI_tga = 5,
|
||||
STBI_psd = 6,
|
||||
STBI_pic = 7,
|
||||
STBI_pnm = 8,
|
||||
STBI_dds = 9,
|
||||
STBI_pvr = 10,
|
||||
STBI_pkm = 11,
|
||||
STBI_hdr = 12
|
||||
};
|
||||
|
||||
extern int stbi_test_from_memory (stbi_uc const *buffer, int len);
|
||||
extern int stbi_test_from_callbacks (stbi_io_callbacks const *clbk, void *user);
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi_test (char const *filename);
|
||||
extern int stbi_test_from_file (FILE *f);
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_STB_IMAGE_EXT */
|
||||
74
src/libprojectM/Renderer/SOIL2/stbi_ext_c.h
Normal file
74
src/libprojectM/Renderer/SOIL2/stbi_ext_c.h
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
static int stbi_test_main(stbi__context *s)
|
||||
{
|
||||
#ifndef STBI_NO_JPEG
|
||||
if (stbi__jpeg_test(s)) return STBI_jpeg;
|
||||
#endif
|
||||
#ifndef STBI_NO_PNG
|
||||
if (stbi__png_test(s)) return STBI_png;
|
||||
#endif
|
||||
#ifndef STBI_NO_BMP
|
||||
if (stbi__bmp_test(s)) return STBI_bmp;
|
||||
#endif
|
||||
#ifndef STBI_NO_GIF
|
||||
if (stbi__gif_test(s)) return STBI_gif;
|
||||
#endif
|
||||
#ifndef STBI_NO_PSD
|
||||
if (stbi__psd_test(s)) return STBI_psd;
|
||||
#endif
|
||||
#ifndef STBI_NO_PIC
|
||||
if (stbi__pic_test(s)) return STBI_pic;
|
||||
#endif
|
||||
#ifndef STBI_NO_PNM
|
||||
if (stbi__pnm_test(s)) return STBI_pnm;
|
||||
#endif
|
||||
#ifndef STBI_NO_DDS
|
||||
if (stbi__dds_test(s)) return STBI_dds;
|
||||
#endif
|
||||
#ifndef STBI_NO_PVR
|
||||
if (stbi__pvr_test(s)) return STBI_pvr;
|
||||
#endif
|
||||
#ifndef STBI_NO_PKM
|
||||
if (stbi__pkm_test(s)) return STBI_pkm;
|
||||
#endif
|
||||
#ifndef STBI_NO_HDR
|
||||
if (stbi__hdr_test(s)) return STBI_hdr;
|
||||
#endif
|
||||
#ifndef STBI_NO_TGA
|
||||
if (stbi__tga_test(s)) return STBI_tga;
|
||||
#endif
|
||||
return STBI_unknown;
|
||||
}
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
int stbi_test_from_file(FILE *f)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_file(&s,f);
|
||||
return stbi_test_main(&s);
|
||||
}
|
||||
|
||||
int stbi_test(char const *filename)
|
||||
{
|
||||
FILE *f = fopen(filename, "rb");
|
||||
int result;
|
||||
if (!f) return STBI_unknown;
|
||||
result = stbi_test_from_file(f);
|
||||
fclose(f);
|
||||
return result;
|
||||
}
|
||||
#endif //!STBI_NO_STDIO
|
||||
|
||||
int stbi_test_from_memory(stbi_uc const *buffer, int len)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_mem(&s,buffer,len);
|
||||
return stbi_test_main(&s);
|
||||
}
|
||||
|
||||
int stbi_test_from_callbacks(stbi_io_callbacks const *clbk, void *user)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
|
||||
return stbi_test_main(&s);
|
||||
}
|
||||
34
src/libprojectM/Renderer/SOIL2/stbi_pkm.h
Normal file
34
src/libprojectM/Renderer/SOIL2/stbi_pkm.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
adding PKM loading support to stbi
|
||||
*/
|
||||
|
||||
#ifndef HEADER_STB_IMAGE_PKM_AUGMENTATION
|
||||
#define HEADER_STB_IMAGE_PKM_AUGMENTATION
|
||||
|
||||
/* is it a PKM file? */
|
||||
extern int stbi__pkm_test_memory (stbi_uc const *buffer, int len);
|
||||
extern int stbi__pkm_test_callbacks (stbi_io_callbacks const *clbk, void *user);
|
||||
|
||||
extern stbi_uc *stbi__pkm_load_from_path (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi__pkm_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi__pkm_load_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp);
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi__pkm_test_filename (char const *filename);
|
||||
extern int stbi__pkm_test_file (FILE *f);
|
||||
extern stbi_uc *stbi__pkm_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
#endif
|
||||
|
||||
extern int stbi__pkm_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp);
|
||||
extern int stbi__pkm_info_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
|
||||
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi__pkm_info_from_path (char const *filename, int *x, int *y, int *comp);
|
||||
extern int stbi__pkm_info_from_file (FILE *f, int *x, int *y, int *comp);
|
||||
#endif
|
||||
|
||||
/*
|
||||
//
|
||||
//// end header file /////////////////////////////////////////////////////*/
|
||||
#endif /* HEADER_STB_IMAGE_PKM_AUGMENTATION */
|
||||
227
src/libprojectM/Renderer/SOIL2/stbi_pkm_c.h
Normal file
227
src/libprojectM/Renderer/SOIL2/stbi_pkm_c.h
Normal file
@ -0,0 +1,227 @@
|
||||
#include "pkm_helper.h"
|
||||
#include "etc1_utils.h"
|
||||
|
||||
static int stbi__pkm_test(stbi__context *s)
|
||||
{
|
||||
// check the magic number
|
||||
if (stbi__get8(s) != 'P') {
|
||||
stbi__rewind(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stbi__get8(s) != 'K') {
|
||||
stbi__rewind(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stbi__get8(s) != 'M') {
|
||||
stbi__rewind(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stbi__get8(s) != ' ') {
|
||||
stbi__rewind(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stbi__get8(s) != '1') {
|
||||
stbi__rewind(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stbi__get8(s) != '0') {
|
||||
stbi__rewind(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
stbi__rewind(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
|
||||
int stbi__pkm_test_filename (char const *filename)
|
||||
{
|
||||
int r;
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if (!f) return 0;
|
||||
r = stbi__pkm_test_file(f);
|
||||
fclose(f);
|
||||
return r;
|
||||
}
|
||||
|
||||
int stbi__pkm_test_file (FILE *f)
|
||||
{
|
||||
stbi__context s;
|
||||
int r,n = ftell(f);
|
||||
stbi__start_file(&s,f);
|
||||
r = stbi__pkm_test(&s);
|
||||
fseek(f,n,SEEK_SET);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
int stbi__pkm_test_memory (stbi_uc const *buffer, int len)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_mem(&s,buffer, len);
|
||||
return stbi__pkm_test(&s);
|
||||
}
|
||||
|
||||
int stbi__pkm_test_callbacks (stbi_io_callbacks const *clbk, void *user)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
|
||||
return stbi__pkm_test(&s);
|
||||
}
|
||||
|
||||
static int stbi__pkm_info(stbi__context *s, int *x, int *y, int *comp )
|
||||
{
|
||||
PKMHeader header;
|
||||
unsigned int width, height;
|
||||
|
||||
stbi__getn( s, (stbi_uc*)(&header), sizeof(PKMHeader) );
|
||||
|
||||
if ( 0 != strcmp( header.aName, "PKM 10" ) ) {
|
||||
stbi__rewind(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
width = (header.iWidthMSB << 8) | header.iWidthLSB;
|
||||
height = (header.iHeightMSB << 8) | header.iHeightLSB;
|
||||
|
||||
*x = s->img_x = width;
|
||||
*y = s->img_y = height;
|
||||
*comp = s->img_n = 3;
|
||||
|
||||
stbi__rewind(s);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int stbi__pkm_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp )
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_mem(&s,buffer, len);
|
||||
return stbi__pkm_info( &s, x, y, comp );
|
||||
}
|
||||
|
||||
int stbi__pkm_info_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
|
||||
return stbi__pkm_info( &s, x, y, comp );
|
||||
}
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
int stbi__pkm_info_from_path(char const *filename, int *x, int *y, int *comp)
|
||||
{
|
||||
int res;
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if (!f) return 0;
|
||||
res = stbi__pkm_info_from_file( f, x, y, comp );
|
||||
fclose(f);
|
||||
return res;
|
||||
}
|
||||
|
||||
int stbi__pkm_info_from_file(FILE *f, int *x, int *y, int *comp)
|
||||
{
|
||||
stbi__context s;
|
||||
int res;
|
||||
long n = ftell(f);
|
||||
stbi__start_file(&s, f);
|
||||
res = stbi__pkm_info(&s, x, y, comp);
|
||||
fseek(f, n, SEEK_SET);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
static stbi_uc * stbi__pkm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
stbi_uc *pkm_data = NULL;
|
||||
stbi_uc *pkm_res_data = NULL;
|
||||
PKMHeader header;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int align = 0;
|
||||
unsigned int bpr;
|
||||
unsigned int size;
|
||||
unsigned int compressedSize;
|
||||
|
||||
int res;
|
||||
|
||||
stbi__getn( s, (stbi_uc*)(&header), sizeof(PKMHeader) );
|
||||
|
||||
if ( 0 != strcmp( header.aName, "PKM 10" ) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
width = (header.iWidthMSB << 8) | header.iWidthLSB;
|
||||
height = (header.iHeightMSB << 8) | header.iHeightLSB;
|
||||
|
||||
*x = s->img_x = width;
|
||||
*y = s->img_y = height;
|
||||
*comp = s->img_n = 3;
|
||||
|
||||
compressedSize = etc1_get_encoded_data_size(width, height);
|
||||
|
||||
pkm_data = (stbi_uc *)malloc(compressedSize);
|
||||
stbi__getn( s, pkm_data, compressedSize );
|
||||
|
||||
bpr = ((width * 3) + align) & ~align;
|
||||
size = bpr * height;
|
||||
pkm_res_data = (stbi_uc *)malloc(size);
|
||||
|
||||
res = etc1_decode_image((const etc1_byte*)pkm_data, (etc1_byte*)pkm_res_data, width, height, 3, bpr);
|
||||
|
||||
free( pkm_data );
|
||||
|
||||
if ( 0 == res ) {
|
||||
if( (req_comp <= 4) && (req_comp >= 1) ) {
|
||||
// user has some requirements, meet them
|
||||
if( req_comp != s->img_n ) {
|
||||
pkm_res_data = stbi__convert_format( pkm_res_data, s->img_n, req_comp, s->img_x, s->img_y );
|
||||
*comp = req_comp;
|
||||
}
|
||||
}
|
||||
|
||||
return (stbi_uc *)pkm_res_data;
|
||||
} else {
|
||||
free( pkm_res_data );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
stbi_uc *stbi__pkm_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_file(&s,f);
|
||||
return stbi__pkm_load(&s,x,y,comp,req_comp);
|
||||
}
|
||||
|
||||
stbi_uc *stbi__pkm_load_from_path (char const*filename, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
stbi_uc *data;
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if (!f) return NULL;
|
||||
data = stbi__pkm_load_from_file(f,x,y,comp,req_comp);
|
||||
fclose(f);
|
||||
return data;
|
||||
}
|
||||
#endif
|
||||
|
||||
stbi_uc *stbi__pkm_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_mem(&s,buffer, len);
|
||||
return stbi__pkm_load(&s,x,y,comp,req_comp);
|
||||
}
|
||||
|
||||
stbi_uc *stbi__pkm_load_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
stbi__context s;
|
||||
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
|
||||
return stbi__pkm_load(&s,x,y,comp,req_comp);
|
||||
}
|
||||
34
src/libprojectM/Renderer/SOIL2/stbi_pvr.h
Normal file
34
src/libprojectM/Renderer/SOIL2/stbi_pvr.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
adding PVR loading support to stbi
|
||||
*/
|
||||
|
||||
#ifndef HEADER_STB_IMAGE_PVR_AUGMENTATION
|
||||
#define HEADER_STB_IMAGE_PVR_AUGMENTATION
|
||||
|
||||
/* is it a PVR file? */
|
||||
extern int stbi__pvr_test_memory (stbi_uc const *buffer, int len);
|
||||
extern int stbi__pvr_test_callbacks (stbi_io_callbacks const *clbk, void *user);
|
||||
|
||||
extern stbi_uc *stbi__pvr_load_from_path (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi__pvr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||
extern stbi_uc *stbi__pvr_load_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp);
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi__pvr_test_filename (char const *filename);
|
||||
extern int stbi__pvr_test_file (FILE *f);
|
||||
extern stbi_uc *stbi__pvr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||
#endif
|
||||
|
||||
extern int stbi__pvr_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int *iscompressed);
|
||||
extern int stbi__pvr_info_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int *iscompressed);
|
||||
|
||||
|
||||
#ifndef STBI_NO_STDIO
|
||||
extern int stbi__pvr_info_from_path (char const *filename, int *x, int *y, int *comp, int *iscompressed);
|
||||
extern int stbi__pvr_info_from_file (FILE *f, int *x, int *y, int *comp, int *iscompressed);
|
||||
#endif
|
||||
|
||||
/*
|
||||
//
|
||||
//// end header file /////////////////////////////////////////////////////*/
|
||||
#endif /* HEADER_STB_IMAGE_PVR_AUGMENTATION */
|
||||
1001
src/libprojectM/Renderer/SOIL2/stbi_pvr_c.h
Normal file
1001
src/libprojectM/Renderer/SOIL2/stbi_pvr_c.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@
|
||||
#ifdef USE_DEVIL
|
||||
#include <IL/ilut.h>
|
||||
#else
|
||||
#include "SOIL/SOIL.h"
|
||||
#include "SOIL2/SOIL2.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
@ -179,7 +179,7 @@ GLuint TextureManager::getTextureFullpath(const std::string filename, const std:
|
||||
#else
|
||||
int width, height;
|
||||
|
||||
unsigned int tex = SOIL_load_OGL_texture_size(
|
||||
unsigned int tex = SOIL_load_OGL_texture(
|
||||
imageURL.c_str(),
|
||||
SOIL_LOAD_AUTO,
|
||||
SOIL_CREATE_NEW_ID,
|
||||
@ -189,7 +189,8 @@ GLuint TextureManager::getTextureFullpath(const std::string filename, const std:
|
||||
SOIL_FLAG_MULTIPLY_ALPHA
|
||||
//| SOIL_FLAG_COMPRESS_TO_DXT
|
||||
//| SOIL_FLAG_DDS_LOAD_DIRECT
|
||||
,&width,&height);
|
||||
//,&width,&height);
|
||||
);
|
||||
|
||||
#endif
|
||||
textures[filename]=tex;
|
||||
|
||||
Reference in New Issue
Block a user