Update SOIL2 to v1.31 to fix issue with GL_OES_texture_npot

Resolves issue #910

Fail over to glGetString if SOIL_GL_GetProcAddress fails

Signed-off-by: Kai Blaschke <kai.blaschke@kb-dev.net>
This commit is contained in:
Kiley Holbrook 2025-10-11 14:13:43 +02:00 committed by Kai Blaschke
parent 1050d61845
commit 3e67f6e477
No known key found for this signature in database
GPG Key ID: B014B6811527389F
31 changed files with 6405 additions and 3057 deletions

View File

@ -65,10 +65,10 @@ auto TextureManager::GetSampler(const std::string& fullName) -> std::shared_ptr<
void TextureManager::Preload()
{
// Create samplers
m_samplers.emplace(std::pair<GLint, GLint>(GL_CLAMP_TO_EDGE, GL_LINEAR), std::make_shared<Sampler>(GL_CLAMP_TO_EDGE, GL_LINEAR));
m_samplers.emplace(std::pair<GLint, GLint>(GL_CLAMP_TO_EDGE, GL_NEAREST), std::make_shared<Sampler>(GL_CLAMP_TO_EDGE, GL_NEAREST));
m_samplers.emplace(std::pair<GLint, GLint>(GL_REPEAT, GL_LINEAR), std::make_shared<Sampler>(GL_REPEAT, GL_LINEAR));
m_samplers.emplace(std::pair<GLint, GLint>(GL_REPEAT, GL_NEAREST), std::make_shared<Sampler>(GL_REPEAT, GL_NEAREST));
m_samplers.emplace(std::make_pair(GL_CLAMP_TO_EDGE, GL_LINEAR), std::make_shared<Sampler>(GL_CLAMP_TO_EDGE, GL_LINEAR));
m_samplers.emplace(std::make_pair(GL_CLAMP_TO_EDGE, GL_NEAREST), std::make_shared<Sampler>(GL_CLAMP_TO_EDGE, GL_NEAREST));
m_samplers.emplace(std::make_pair(GL_REPEAT, GL_LINEAR), std::make_shared<Sampler>(GL_REPEAT, GL_LINEAR));
m_samplers.emplace(std::make_pair(GL_REPEAT, GL_NEAREST), std::make_shared<Sampler>(GL_REPEAT, GL_NEAREST));
int width{};
int height{};
@ -78,7 +78,7 @@ void TextureManager::Preload()
M_bytes,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MULTIPLY_ALPHA, &width, &height);
SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MULTIPLY_ALPHA);
m_textures["idlem"] = std::make_shared<Texture>("idlem", tex, GL_TEXTURE_2D, width, height, false);;
@ -87,7 +87,7 @@ void TextureManager::Preload()
headphones_bytes,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MULTIPLY_ALPHA, &width, &height);
SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MULTIPLY_ALPHA);
m_textures["idleheadphones"] = std::make_shared<Texture>("idleheadphones", tex, GL_TEXTURE_2D, width, height, false);;
@ -217,7 +217,7 @@ auto TextureManager::LoadTexture(const ScannedFile& file) -> std::shared_ptr<Tex
file.filePath.c_str(),
SOIL_LOAD_RGBA,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MULTIPLY_ALPHA, &width, &height);
SOIL_FLAG_MULTIPLY_ALPHA);
if (tex == 0)
{

View File

@ -1,31 +1,34 @@
add_library(SOIL2 OBJECT
etc1_utils.c
etc1_utils.h
image_DXT.c
image_DXT.h
image_helper.c
image_helper.h
pkm_helper.h
pvr_helper.h
SOIL2.c
SOIL2.h
stb_image.h
stb_image_write.h
stbi_DDS.h
stbi_DDS_c.h
stbi_ext.h
stbi_ext_c.h
stbi_pkm.h
stbi_pkm_c.h
stbi_pvr.h
stbi_pvr_c.h
${CMAKE_CURRENT_SOURCE_DIR}/src/common/common.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/common/common.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/image_DXT.c
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/image_DXT.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/image_helper.c
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/image_helper.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/pkm_helper.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/pvr_helper.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/SOIL2.c
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/SOIL2.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stb_image.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stb_image_write.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stbi_DDS.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stbi_DDS_c.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stbi_ext.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stbi_ext_c.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stbi_pkm.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stbi_pkm_c.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stbi_pvr.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stbi_pvr_c.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stbi_qoi.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stbi_qoi_c.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/stbi_qoi_write.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/wfETC.c
${CMAKE_CURRENT_SOURCE_DIR}/src/SOIL2/wfETC.h
)
target_include_directories(SOIL2
PRIVATE
"."
PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/.."
"${CMAKE_CURRENT_SOURCE_DIR}/src"
)
target_link_libraries(SOIL2
@ -36,15 +39,21 @@ target_link_libraries(SOIL2
if(USE_GLES)
target_compile_definitions(SOIL2
PRIVATE
SOIL_GLES3
SOIL_NO_EGL
SOIL_GLES2
)
target_link_libraries(SOIL2
PUBLIC
${CMAKE_DL_LIBS}
)
endif()
if(NOT TARGET OpenGL::EGL)
target_compile_definitions(SOIL2
PRIVATE
SOIL_NO_EGL
)
endif()
set_target_properties(SOIL2 PROPERTIES
FOLDER libprojectM
FOLDER vendor/SOIL2
)

View File

@ -1,680 +0,0 @@
// 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);
}

View File

@ -1,106 +0,0 @@
// 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

View File

@ -1,123 +0,0 @@
/*
Jonathan Dummer
2007-07-31-10.32
simple DXT compression / decompression code
public domain
*/
#ifndef HEADER_IMAGE_DXT
#define HEADER_IMAGE_DXT
/**
Converts an image from an array of unsigned chars (RGB or RGBA) to
DXT1 or DXT5, then saves the converted image to disk.
\return 0 if failed, otherwise returns 1
**/
int
save_image_as_DDS
(
const char *filename,
int width, int height, int channels,
const unsigned char *const data
);
/**
take an image and convert it to DXT1 (no alpha)
**/
unsigned char*
convert_image_to_DXT1
(
const unsigned char *const uncompressed,
int width, int height, int channels,
int *out_size
);
/**
take an image and convert it to DXT5 (with alpha)
**/
unsigned char*
convert_image_to_DXT5
(
const unsigned char *const uncompressed,
int width, int height, int channels,
int *out_size
);
/** 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 ];
/* 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
#endif /* HEADER_IMAGE_DXT */

File diff suppressed because it is too large Load Diff

86
vendor/SOIL2/SOIL2.h → vendor/SOIL2/src/SOIL2/SOIL2.h vendored Normal file → Executable file
View File

@ -2,7 +2,7 @@
@mainpage SOIL2
Fork by Martin Lucas Golini
Original author Jonathan Dummer
2007-07-26-10.36
@ -24,7 +24,8 @@
- TGA load & save
- DDS load & save
- PNG load & save
- JPG load
- JPG load & save
- QOI load & save
- PSD load
- HDR load
- PIC load
@ -49,6 +50,19 @@
extern "C" {
#endif
#define SOIL_MAJOR_VERSION 1
#define SOIL_MINOR_VERSION 3
#define SOIL_PATCH_LEVEL 0
#define SOIL_VERSION_NUM( X, Y, Z ) ( (X)*1000 + (Y)*100 + ( Z ) )
#define SOIL_COMPILED_VERSION \
SOIL_VERSION_NUM( SOIL_MAJOR_VERSION, SOIL_MINOR_VERSION, SOIL_PATCH_LEVEL )
#define SOIL_VERSION_ATLEAST( X, Y, Z ) ( SOIL_COMPILED_VERSION >= SOIL_VERSION_NUM( X, Y, Z ) )
unsigned long SOIL_version();
/**
The format of images that may be loaded (force_channels).
SOIL_LOAD_AUTO leaves the image in whatever format it was found.
@ -112,7 +126,8 @@ enum
SOIL_FLAG_TEXTURE_RECTANGLE = 512,
SOIL_FLAG_PVR_LOAD_DIRECT = 1024,
SOIL_FLAG_ETC1_LOAD_DIRECT = 2048,
SOIL_FLAG_GL_MIPMAPS = 4096
SOIL_FLAG_GL_MIPMAPS = 4096,
SOIL_FLAG_SRGB_COLOR_SPACE = 8192
};
/**
@ -127,7 +142,9 @@ enum
SOIL_SAVE_TYPE_TGA = 0,
SOIL_SAVE_TYPE_BMP = 1,
SOIL_SAVE_TYPE_PNG = 2,
SOIL_SAVE_TYPE_DDS = 3
SOIL_SAVE_TYPE_DDS = 3,
SOIL_SAVE_TYPE_JPG = 4,
SOIL_SAVE_TYPE_QOI = 5
};
/**
@ -166,9 +183,8 @@ unsigned int
const char *filename,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags,
int *width,
int *height);
unsigned int flags
);
/**
Loads 6 images from disk into an OpenGL cubemap texture.
@ -245,14 +261,13 @@ unsigned int
**/
unsigned int
SOIL_load_OGL_texture_from_memory
(const unsigned char *const buffer,
unsigned int buffer_length,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags,
int * width,
int * height
);
(
const unsigned char *const buffer,
int buffer_length,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
);
/**
Loads 6 images from memory into an OpenGL cubemap texture.
@ -405,8 +420,19 @@ unsigned char*
/**
Saves an image from an array of unsigned chars (RGBA) to disk
\param quality parameter only used for SOIL_SAVE_TYPE_JPG files, values accepted between 0 and 100.
\return 0 if failed, otherwise returns 1
**/
int
SOIL_save_image_quality
(
const char *filename,
int image_type,
int width, int height, int channels,
const unsigned char *const data,
int quality
);
int
SOIL_save_image
(
@ -416,6 +442,34 @@ int
const unsigned char *const data
);
/**
Saves an image from an array of unsigned chars (RGBA) to a memory buffer in the target format.
Free the buffer with SOIL_free_image_data.
\param quality parameter only used for SOIL_SAVE_TYPE_JPG files, values accepted between 0 and 100.
\param imageSize returns the byte count of the image.
\return 0 if failed, otherwise returns 1
**/
unsigned char*
SOIL_write_image_to_memory_quality
(
int image_type,
int width, int height, int channels,
const unsigned char* const data,
int quality,
int* imageSize
);
unsigned char*
SOIL_write_image_to_memory
(
int image_type,
int width, int height, int channels,
const unsigned char* const data,
int* imageSize
);
/**
Frees the image data (note, this is just C's "free()"...this function is
present mostly so C++ programmers don't forget to use "free()" and call
@ -462,7 +516,7 @@ unsigned int SOIL_direct_load_DDS(
/** Loads the DDS texture directly to the GPU memory ( if supported ) */
unsigned int SOIL_direct_load_DDS_from_memory(
const unsigned char *const buffer,
unsigned int buffer_length,
int buffer_length,
unsigned int reuse_texture_ID,
int flags,
int loading_as_cubemap );

5
vendor/SOIL2/image_DXT.c → vendor/SOIL2/src/SOIL2/image_DXT.c vendored Normal file → Executable file
View File

@ -108,7 +108,6 @@ unsigned char* convert_image_to_DXT1(
unsigned char ublock[16*3];
unsigned char cblock[8];
int index = 0, chan_step = 1;
int block_count = 0;
/* error check */
*out_size = 0;
if( (width < 1) || (height < 1) ||
@ -167,7 +166,6 @@ unsigned char* convert_image_to_DXT1(
}
}
/* compress the block */
++block_count;
compress_DDS_color_block( 3, ublock, cblock );
/* copy the data from the block into the main block */
for( x = 0; x < 8; ++x )
@ -189,7 +187,7 @@ unsigned char* convert_image_to_DXT5(
unsigned char ublock[16*4];
unsigned char cblock[8];
int index = 0, chan_step = 1;
int block_count = 0, has_alpha;
int has_alpha;
/* error check */
*out_size = 0;
if( (width < 1) || (height < 1) ||
@ -262,7 +260,6 @@ unsigned char* convert_image_to_DXT5(
compressed[index++] = cblock[x];
}
/* then compress the color block */
++block_count;
compress_DDS_color_block( 4, ublock, cblock );
/* copy the data from the compressed color block into the main buffer */
for( x = 0; x < 8; ++x )

259
vendor/SOIL2/src/SOIL2/image_DXT.h vendored Executable file
View File

@ -0,0 +1,259 @@
/*
Jonathan Dummer
2007-07-31-10.32
simple DXT compression / decompression code
public domain
*/
#ifndef HEADER_IMAGE_DXT
#define HEADER_IMAGE_DXT
#include <stdint.h>
/**
Converts an image from an array of unsigned chars (RGB or RGBA) to
DXT1 or DXT5, then saves the converted image to disk.
\return 0 if failed, otherwise returns 1
**/
int
save_image_as_DDS
(
const char *filename,
int width, int height, int channels,
const unsigned char *const data
);
/**
take an image and convert it to DXT1 (no alpha)
**/
unsigned char*
convert_image_to_DXT1
(
const unsigned char *const uncompressed,
int width, int height, int channels,
int *out_size
);
/**
take an image and convert it to DXT5 (with alpha)
**/
unsigned char*
convert_image_to_DXT5
(
const unsigned char *const uncompressed,
int width, int height, int channels,
int *out_size
);
// A bunch of DirectDraw Surface structures and flags
typedef struct
{
uint32_t dwMagic;
uint32_t dwSize;
uint32_t dwFlags;
uint32_t dwHeight;
uint32_t dwWidth;
uint32_t dwPitchOrLinearSize;
uint32_t dwDepth;
uint32_t dwMipMapCount;
uint32_t dwReserved1[ 11 ];
/* DDPIXELFORMAT */
struct
{
uint32_t dwSize;
uint32_t dwFlags;
uint32_t dwFourCC;
uint32_t dwRGBBitCount;
uint32_t dwRBitMask;
uint32_t dwGBitMask;
uint32_t dwBBitMask;
uint32_t dwAlphaBitMask;
} sPixelFormat;
/* DDCAPS2 */
struct
{
uint32_t dwCaps1;
uint32_t dwCaps2;
uint32_t dwDDSX;
uint32_t dwReserved;
} sCaps;
unsigned int dwReserved2;
} DDS_header;
typedef enum {
DXGI_FORMAT_UNKNOWN = 0,
DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
DXGI_FORMAT_R32G32B32A32_UINT = 3,
DXGI_FORMAT_R32G32B32A32_SINT = 4,
DXGI_FORMAT_R32G32B32_TYPELESS = 5,
DXGI_FORMAT_R32G32B32_FLOAT = 6,
DXGI_FORMAT_R32G32B32_UINT = 7,
DXGI_FORMAT_R32G32B32_SINT = 8,
DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
DXGI_FORMAT_R16G16B16A16_UNORM = 11,
DXGI_FORMAT_R16G16B16A16_UINT = 12,
DXGI_FORMAT_R16G16B16A16_SNORM = 13,
DXGI_FORMAT_R16G16B16A16_SINT = 14,
DXGI_FORMAT_R32G32_TYPELESS = 15,
DXGI_FORMAT_R32G32_FLOAT = 16,
DXGI_FORMAT_R32G32_UINT = 17,
DXGI_FORMAT_R32G32_SINT = 18,
DXGI_FORMAT_R32G8X24_TYPELESS = 19,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
DXGI_FORMAT_R10G10B10A2_UNORM = 24,
DXGI_FORMAT_R10G10B10A2_UINT = 25,
DXGI_FORMAT_R11G11B10_FLOAT = 26,
DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
DXGI_FORMAT_R8G8B8A8_UNORM = 28,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
DXGI_FORMAT_R8G8B8A8_UINT = 30,
DXGI_FORMAT_R8G8B8A8_SNORM = 31,
DXGI_FORMAT_R8G8B8A8_SINT = 32,
DXGI_FORMAT_R16G16_TYPELESS = 33,
DXGI_FORMAT_R16G16_FLOAT = 34,
DXGI_FORMAT_R16G16_UNORM = 35,
DXGI_FORMAT_R16G16_UINT = 36,
DXGI_FORMAT_R16G16_SNORM = 37,
DXGI_FORMAT_R16G16_SINT = 38,
DXGI_FORMAT_R32_TYPELESS = 39,
DXGI_FORMAT_D32_FLOAT = 40,
DXGI_FORMAT_R32_FLOAT = 41,
DXGI_FORMAT_R32_UINT = 42,
DXGI_FORMAT_R32_SINT = 43,
DXGI_FORMAT_R24G8_TYPELESS = 44,
DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
DXGI_FORMAT_R8G8_TYPELESS = 48,
DXGI_FORMAT_R8G8_UNORM = 49,
DXGI_FORMAT_R8G8_UINT = 50,
DXGI_FORMAT_R8G8_SNORM = 51,
DXGI_FORMAT_R8G8_SINT = 52,
DXGI_FORMAT_R16_TYPELESS = 53,
DXGI_FORMAT_R16_FLOAT = 54,
DXGI_FORMAT_D16_UNORM = 55,
DXGI_FORMAT_R16_UNORM = 56,
DXGI_FORMAT_R16_UINT = 57,
DXGI_FORMAT_R16_SNORM = 58,
DXGI_FORMAT_R16_SINT = 59,
DXGI_FORMAT_R8_TYPELESS = 60,
DXGI_FORMAT_R8_UNORM = 61,
DXGI_FORMAT_R8_UINT = 62,
DXGI_FORMAT_R8_SNORM = 63,
DXGI_FORMAT_R8_SINT = 64,
DXGI_FORMAT_A8_UNORM = 65,
DXGI_FORMAT_R1_UNORM = 66,
DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
DXGI_FORMAT_BC1_TYPELESS = 70,
DXGI_FORMAT_BC1_UNORM = 71,
DXGI_FORMAT_BC1_UNORM_SRGB = 72,
DXGI_FORMAT_BC2_TYPELESS = 73,
DXGI_FORMAT_BC2_UNORM = 74,
DXGI_FORMAT_BC2_UNORM_SRGB = 75,
DXGI_FORMAT_BC3_TYPELESS = 76,
DXGI_FORMAT_BC3_UNORM = 77,
DXGI_FORMAT_BC3_UNORM_SRGB = 78,
DXGI_FORMAT_BC4_TYPELESS = 79,
DXGI_FORMAT_BC4_UNORM = 80,
DXGI_FORMAT_BC4_SNORM = 81,
DXGI_FORMAT_BC5_TYPELESS = 82,
DXGI_FORMAT_BC5_UNORM = 83,
DXGI_FORMAT_BC5_SNORM = 84,
DXGI_FORMAT_B5G6R5_UNORM = 85,
DXGI_FORMAT_B5G5R5A1_UNORM = 86,
DXGI_FORMAT_B8G8R8A8_UNORM = 87,
DXGI_FORMAT_B8G8R8X8_UNORM = 88,
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
DXGI_FORMAT_BC6H_TYPELESS = 94,
DXGI_FORMAT_BC6H_UF16 = 95,
DXGI_FORMAT_BC6H_SF16 = 96,
DXGI_FORMAT_BC7_TYPELESS = 97,
DXGI_FORMAT_BC7_UNORM = 98,
DXGI_FORMAT_BC7_UNORM_SRGB = 99,
DXGI_FORMAT_AYUV = 100,
DXGI_FORMAT_Y410 = 101,
DXGI_FORMAT_Y416 = 102,
DXGI_FORMAT_NV12 = 103,
DXGI_FORMAT_P010 = 104,
DXGI_FORMAT_P016 = 105,
DXGI_FORMAT_420_OPAQUE = 106,
DXGI_FORMAT_YUY2 = 107,
DXGI_FORMAT_Y210 = 108,
DXGI_FORMAT_Y216 = 109,
DXGI_FORMAT_NV11 = 110,
DXGI_FORMAT_AI44 = 111,
DXGI_FORMAT_IA44 = 112,
DXGI_FORMAT_P8 = 113,
DXGI_FORMAT_A8P8 = 114,
DXGI_FORMAT_B4G4R4A4_UNORM = 115,
DXGI_FORMAT_P208 = 130,
DXGI_FORMAT_V208 = 131,
DXGI_FORMAT_V408 = 132,
DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE,
DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE,
DXGI_FORMAT_FORCE_UINT = 0xffffffff
} DXGI_FORMAT;
typedef struct {
DXGI_FORMAT dxgiFormat;
uint32_t resourceDimension;
uint32_t miscFlag;
uint32_t arraySize;
uint32_t miscFlags2;
} DDS_HEADER_DXT10;
/* 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
#define DDPF_LUMINANCE 0x20000
/* 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
#endif /* HEADER_IMAGE_DXT */

View File

View File

File diff suppressed because it is too large Load Diff

1733
vendor/SOIL2/src/SOIL2/stb_image_write.h vendored Normal file

File diff suppressed because it is too large Load Diff

8
vendor/SOIL2/stbi_DDS.h → vendor/SOIL2/src/SOIL2/stbi_DDS.h vendored Normal file → Executable file
View File

@ -9,14 +9,14 @@
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);
extern void *stbi__dds_load_from_path (const char *filename, int *x, int *y, int *comp, int req_comp);
extern void *stbi__dds_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
extern void *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);
extern void *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);

21
vendor/SOIL2/stbi_DDS_c.h → vendor/SOIL2/src/SOIL2/stbi_DDS_c.h vendored Normal file → Executable file
View File

@ -241,8 +241,8 @@ void stbi_decode_DXT_color_block(
}
static int stbi__dds_info( stbi__context *s, int *x, int *y, int *comp, int *iscompressed ) {
unsigned int flags;
int is_compressed,has_alpha;
int is_compressed,has_alpha;
unsigned int flags;
DDS_header header={0};
if( sizeof( DDS_header ) != 128 )
@ -337,14 +337,13 @@ int stbi__dds_info_from_file(FILE *f, int *x, int *y, int *comp
}
#endif
static stbi_uc * stbi__dds_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
static void * 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;
stbi_uc block[16*4];
stbi_uc compressed[8];
unsigned int flags;
int DXT_family;
int flags, DXT_family;
int has_alpha, has_mipmap;
int is_compressed, cubemap_faces;
int block_pitch, num_blocks;
@ -360,7 +359,7 @@ static stbi_uc * stbi__dds_load(stbi__context *s, int *x, int *y, int *comp, int
if( header.dwMagic != (('D' << 0) | ('D' << 8) | ('S' << 16) | (' ' << 24)) ) return NULL;
if( header.dwSize != 124 ) return NULL;
flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
if( (header.dwFlags & flags) != flags ) return NULL;
if( (header.dwFlags & flags) != (unsigned int)flags ) return NULL;
/* According to the MSDN spec, the dwFlags should contain
DDSD_LINEARSIZE if it's compressed, or DDSD_PITCH if
uncompressed. Some DDS writers do not conform to the
@ -558,16 +557,16 @@ static stbi_uc * stbi__dds_load(stbi__context *s, int *x, int *y, int *comp, int
}
#ifndef STBI_NO_STDIO
stbi_uc *stbi__dds_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp)
void *stbi__dds_load_from_file (FILE *f, int *x, int *y, int *comp, int 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_from_path (const char *filename, int *x, int *y, int *comp, int req_comp)
void *stbi__dds_load_from_path (const char *filename, int *x, int *y, int *comp, int req_comp)
{
stbi_uc *data;
void *data;
FILE *f = fopen(filename, "rb");
if (!f) return NULL;
data = stbi__dds_load_from_file(f,x,y,comp,req_comp);
@ -576,14 +575,14 @@ stbi_uc *stbi__dds_load_from_path (const char *filename, i
}
#endif
stbi_uc *stbi__dds_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
void *stbi__dds_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__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)
void *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);

View File

@ -14,7 +14,8 @@ enum {
STBI_dds = 9,
STBI_pvr = 10,
STBI_pkm = 11,
STBI_hdr = 12
STBI_hdr = 12,
STBI_qoi = 13
};
extern int stbi_test_from_memory (stbi_uc const *buffer, int len);

View File

@ -31,6 +31,9 @@ static int stbi_test_main(stbi__context *s)
#ifndef STBI_NO_PKM
if (stbi__pkm_test(s)) return STBI_pkm;
#endif
#ifndef STBI_NO_QOI
if (stbi__qoi_test(s)) return STBI_qoi;
#endif
#ifndef STBI_NO_HDR
if (stbi__hdr_test(s)) return STBI_hdr;
#endif

View File

@ -9,14 +9,14 @@
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);
extern void *stbi__pkm_load_from_path (char const *filename, int *x, int *y, int *comp, int req_comp);
extern void *stbi__pkm_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
extern void *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);
extern void *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);

View File

@ -1,5 +1,5 @@
#include "pkm_helper.h"
#include "etc1_utils.h"
#include "wfETC.h"
static int stbi__pkm_test(stbi__context *s)
{
@ -82,7 +82,7 @@ static int stbi__pkm_info(stbi__context *s, int *x, int *y, int *comp )
stbi__getn( s, (stbi_uc*)(&header), sizeof(PKMHeader) );
if ( 0 != strcmp( header.aName, "PKM 10" ) ) {
if ( 0 != strncmp( header.aName, "PKM 10", sizeof(header.aName) ) ) {
stbi__rewind(s);
return 0;
}
@ -136,23 +136,18 @@ int stbi__pkm_info_from_file(FILE *f, int *x, int *y, int *comp
}
#endif
static stbi_uc * stbi__pkm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
static void * 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;
unsigned int compressed_size;
stbi__getn( s, (stbi_uc*)(&header), sizeof(PKMHeader) );
if ( 0 != strcmp( header.aName, "PKM 10" ) ) {
if ( 0 != strncmp( header.aName, "PKM 10", sizeof(header.aName) ) ) {
return NULL;
}
@ -161,23 +156,21 @@ static stbi_uc * stbi__pkm_load(stbi__context *s, int *x, int *y, int *comp, int
*x = s->img_x = width;
*y = s->img_y = height;
*comp = s->img_n = 3;
*comp = s->img_n = 4;
compressedSize = etc1_get_encoded_data_size(width, height);
compressed_size = (((width + 3) & ~3) * ((height + 3) & ~3)) >> 1;
pkm_data = (stbi_uc *)malloc(compressedSize);
stbi__getn( s, pkm_data, compressedSize );
pkm_data = (stbi_uc *)malloc(compressed_size);
stbi__getn( s, pkm_data, compressed_size );
bpr = ((width * 3) + align) & ~align;
size = bpr * height;
pkm_res_data = (stbi_uc *)malloc(size);
pkm_res_data = (stbi_uc *)malloc(width * height * s->img_n);
res = etc1_decode_image((const etc1_byte*)pkm_data, (etc1_byte*)pkm_res_data, width, height, 3, bpr);
wfETC1_DecodeImage(pkm_data, pkm_res_data, width, height);
free( pkm_data );
if ( 0 == res ) {
if( (req_comp <= 4) && (req_comp >= 1) ) {
if ( NULL != pkm_res_data ) {
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 );
@ -194,16 +187,16 @@ static stbi_uc * stbi__pkm_load(stbi__context *s, int *x, int *y, int *comp, int
}
#ifndef STBI_NO_STDIO
stbi_uc *stbi__pkm_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp)
void *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)
void *stbi__pkm_load_from_path (char const*filename, int *x, int *y, int *comp, int req_comp)
{
stbi_uc *data;
void *data;
FILE *f = fopen(filename, "rb");
if (!f) return NULL;
data = stbi__pkm_load_from_file(f,x,y,comp,req_comp);
@ -212,14 +205,14 @@ stbi_uc *stbi__pkm_load_from_path (char const*filename, in
}
#endif
stbi_uc *stbi__pkm_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
void *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)
void *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);

View File

@ -9,14 +9,14 @@
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);
extern void *stbi__pvr_load_from_path (char const *filename, int *x, int *y, int *comp, int req_comp);
extern void *stbi__pvr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
extern void *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);
extern void *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);

View File

@ -602,6 +602,8 @@ static void GetModulationValue(int x,
*Mod =ModVal;
}
static int DisableTwiddlingRoutine = 0;
/*!***********************************************************************
@Function TwiddleUV
@Input YSize Y dimension of the texture in pixels
@ -615,8 +617,6 @@ static void GetModulationValue(int x,
NOTE the dimensions of the texture must be a power of 2
*************************************************************************/
static int DisableTwiddlingRoutine = 0;
static U32 TwiddleUV(U32 YSize, U32 XSize, U32 YPos, U32 XPos)
{
U32 Twiddled;
@ -875,7 +875,7 @@ static void Decompress(AMTC_BLOCK_STRUCT *pCompressedData,
}
static stbi_uc * stbi__pvr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
static void * stbi__pvr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{
stbi_uc *pvr_data = NULL;
stbi_uc *pvr_res_data = NULL;
@ -968,16 +968,16 @@ static stbi_uc * stbi__pvr_load(stbi__context *s, int *x, int *y, int *comp, int
}
#ifndef STBI_NO_STDIO
stbi_uc *stbi__pvr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp)
void *stbi__pvr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp)
{
stbi__context s;
stbi__start_file(&s,f);
return stbi__pvr_load(&s,x,y,comp,req_comp);
}
stbi_uc *stbi__pvr_load_from_path (char const*filename, int *x, int *y, int *comp, int req_comp)
void *stbi__pvr_load_from_path (char const*filename, int *x, int *y, int *comp, int req_comp)
{
stbi_uc *data;
void *data;
FILE *f = fopen(filename, "rb");
if (!f) return NULL;
data = stbi__pvr_load_from_file(f,x,y,comp,req_comp);
@ -986,14 +986,14 @@ stbi_uc *stbi__pvr_load_from_path (char const*filename, in
}
#endif
stbi_uc *stbi__pvr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
void *stbi__pvr_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__pvr_load(&s,x,y,comp,req_comp);
}
stbi_uc *stbi__pvr_load_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
void *stbi__pvr_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);

35
vendor/SOIL2/src/SOIL2/stbi_qoi.h vendored Normal file
View File

@ -0,0 +1,35 @@
/*
adding QOI loading support to stbi
*/
#ifndef HEADER_STB_IMAGE_QOI_AUGMENTATION
#define HEADER_STB_IMAGE_QOI_AUGMENTATION
/* is it a QOI file? */
extern int stbi__qoi_test_memory (stbi_uc const *buffer, int len);
extern int stbi__qoi_test_callbacks (stbi_io_callbacks const *clbk, void *user);
extern void *stbi__qoi_load_from_path (char const *filename, int *x, int *y, int *comp, int req_comp);
extern void *stbi__qoi_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
extern void *stbi__qoi_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__qoi_test_filename (char const *filename);
extern int stbi__qoi_test_file (FILE *f);
extern void *stbi__qoi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
#endif
extern int stbi__qoi_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp);
extern int stbi__qoi_info_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
#ifndef STBI_NO_STDIO
extern int stbi__qoi_info_from_path (char const *filename, int *x, int *y, int *comp);
extern int stbi__qoi_info_from_file (FILE *f, int *x, int *y, int *comp);
#endif
/*
//
//// end header file /////////////////////////////////////////////////////*/
#endif /* HEADER_STB_IMAGE_QOI_AUGMENTATION */

252
vendor/SOIL2/src/SOIL2/stbi_qoi_c.h vendored Normal file
View File

@ -0,0 +1,252 @@
static int stbi__qoi_test(stbi__context *s)
{
int i;
for (i = 0; i < 4; i++) {
if (stbi__get8(s) != "qoif"[i]) {
stbi__rewind(s);
return 0;
}
}
return 1;
}
#ifndef STBI_NO_STDIO
int stbi__qoi_test_filename(char const *filename)
{
int r;
FILE *f = fopen(filename, "rb");
if (!f) return 0;
r = stbi__qoi_test_file(f);
fclose(f);
return r;
}
int stbi__qoi_test_file(FILE *f)
{
stbi__context s;
int r,n = ftell(f);
stbi__start_file(&s,f);
r = stbi__qoi_test(&s);
fseek(f,n,SEEK_SET);
return r;
}
#endif
int stbi__qoi_test_memory (stbi_uc const *buffer, int len)
{
stbi__context s;
stbi__start_mem(&s,buffer, len);
return stbi__qoi_test(&s);
}
int stbi__qoi_test_callbacks (stbi_io_callbacks const *clbk, void *user)
{
stbi__context s;
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
return stbi__qoi_test(&s);
}
static int stbi__qoi_info(stbi__context *s, int *x, int *y, int *comp)
{
stbi__uint32 length;
stbi__rewind(s);
int i;
for (i = 0; i < 4; i++) {
if (stbi__get8(s) != "qoif"[i]) {
stbi__rewind(s);
return 0;
}
}
length = stbi__get32be(s);
if (x) *x = (int)length;
length = stbi__get32be(s);
if (y) *y = (int)length;
int channels = stbi__get8(s); // 3 = RGB, 4 = RGBA
int colorspace = stbi__get8(s) != 0; // 0 = sRGB with linear alpha, 1 = all channels linear
if (comp) *comp = channels;
return 1 + colorspace;
}
int stbi__qoi_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__qoi_info( &s, x, y, comp );
}
int stbi__qoi_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__qoi_info( &s, x, y, comp );
}
#ifndef STBI_NO_STDIO
int stbi__qoi_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__qoi_info_from_file( f, x, y, comp );
fclose(f);
return res;
}
int stbi__qoi_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__qoi_info(&s, x, y, comp);
fseek(f, n, SEEK_SET);
return res;
}
#endif
static void *stbi__qoi_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
{
if (!stbi__qoi_info(s, (int*)&s->img_x, (int*)&s->img_y, &s->img_n))
return NULL;
if (req_comp == 3 || req_comp == 4)
s->img_n = req_comp;
if (x) *x = s->img_x;
if (y) *y = s->img_y;
if (comp) *comp = s->img_n;
if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0))
return stbi__errpuc("too large", "QOI too large");
stbi_uc *out = (stbi_uc *) stbi__malloc_mad3(s->img_x, s->img_y, s->img_n, 0);
if (!out)
return stbi__errpuc("outofmem", "Out of memory");
stbi_uc *dst = out;
stbi_uc *end = &dst[s->img_x * s->img_y * s->img_n];
stbi__uint32 c = 255;
stbi__uint32 recent[0x40];
memset(recent, 0, 0x40*sizeof(stbi__uint32));
while (dst < end) {
stbi_uc tag = stbi__get8(s);
if (tag == 0xfe) {
stbi__uint32 rgb =
((stbi__uint32) stbi__get8(s) << 24) |
((stbi__uint32) stbi__get8(s) << 16) |
((stbi__uint32) stbi__get8(s) << 8);
c = (c & 0xff) | rgb;
}
else if (tag == 0xff) {
c =
((stbi__uint32) stbi__get8(s) << 24) |
((stbi__uint32) stbi__get8(s) << 16) |
((stbi__uint32) stbi__get8(s) << 8) |
(stbi__uint32) stbi__get8(s);
}
else if ((tag >> 6) == 0) {
c = recent[tag];
}
else if ((tag >> 6) == 1) {
stbi_uc r = (c >> 24) + ((tag >> 4) & 3) - 2;
stbi_uc g = (c >> 16) + ((tag >> 2) & 3) - 2;
stbi_uc b = (c >> 8) + (tag & 3) - 2;
c = (c & 0xff) | ((stbi__uint32) r << 24) | ((stbi__uint32) g << 16) | ((stbi__uint32) b << 8);
}
else if ((tag >> 6) == 2) {
stbi_uc rb = stbi__get8(s);
stbi_uc dg = (tag & 0x3f) - 32;
stbi_uc r = (c >> 24) + dg + (rb >> 4) - 8;
stbi_uc g = (c >> 16) + dg;
stbi_uc b = (c >> 8) + dg + (rb & 0xf) - 8;
c = (c & 0xff) | ((stbi__uint32) r << 24) | ((stbi__uint32) g << 16) | ((stbi__uint32) b << 8);
}
else {
int run = tag & 0x3f;
if (&dst[run * s->img_n] > end)
break;
if (s->img_n == 3) {
int i;
for (i = 0; i < run; i++) {
*dst++ = c >> 24;
*dst++ = c >> 16;
*dst++ = c >> 8;
}
}
else {
int i;
for (i = 0; i < run; i++) {
*dst++ = c >> 24;
*dst++ = c >> 16;
*dst++ = c >> 8;
*dst++ = c;
}
}
}
*dst++ = c >> 24;
*dst++ = c >> 16;
*dst++ = c >> 8;
if (s->img_n != 3) *dst++ = c;
recent[0x3f & (
((c >> 24) & 0xff) * 3u +
((c >> 16) & 0xff) * 5u +
((c >> 8) & 0xff) * 7u +
(c & 0xff) * 11u
)] = c;
}
if (req_comp)
out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
return out;
}
#ifndef STBI_NO_STDIO
void *stbi__qoi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
{
stbi__context s;
stbi__result_info ri;
stbi__start_file(&s,f);
return stbi__qoi_load(&s,x,y,comp,req_comp,&ri);
}
void *stbi__qoi_load_from_path(char const*filename, int *x, int *y, int *comp, int req_comp)
{
void *data;
FILE *f = fopen(filename, "rb");
if (!f) return NULL;
data = stbi__qoi_load_from_file(f,x,y,comp,req_comp);
fclose(f);
return data;
}
#endif
void *stbi__qoi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
{
stbi__context s;
stbi__result_info ri;
stbi__start_mem(&s,buffer, len);
return stbi__qoi_load(&s,x,y,comp,req_comp,&ri);
}
void *stbi__qoi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
{
stbi__context s;
stbi__result_info ri;
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
return stbi__qoi_load(&s,x,y,comp,req_comp,&ri);
}

219
vendor/SOIL2/src/SOIL2/stbi_qoi_write.h vendored Normal file
View File

@ -0,0 +1,219 @@
#ifndef NULL
#define NULL 0
#endif
#define QOI_SRGB 0
#define QOI_LINEAR 1
typedef struct {
unsigned int width;
unsigned int height;
unsigned char channels;
unsigned char colorspace;
} qoi_desc;
#ifndef QOI_ZEROARR
#define QOI_ZEROARR(a) memset((a),0,sizeof(a))
#endif
#define QOI_OP_INDEX 0x00 /* 00xxxxxx */
#define QOI_OP_DIFF 0x40 /* 01xxxxxx */
#define QOI_OP_LUMA 0x80 /* 10xxxxxx */
#define QOI_OP_RUN 0xc0 /* 11xxxxxx */
#define QOI_OP_RGB 0xfe /* 11111110 */
#define QOI_OP_RGBA 0xff /* 11111111 */
#define QOI_COLOR_HASH(C) (C.rgba.r*3 + C.rgba.g*5 + C.rgba.b*7 + C.rgba.a*11)
#define QOI_MAGIC \
(((unsigned int)'q') << 24 | ((unsigned int)'o') << 16 | \
((unsigned int)'i') << 8 | ((unsigned int)'f'))
#define QOI_HEADER_SIZE 14
/* 2GB is the max file size that this implementation can safely handle. We guard
against anything larger than that, assuming the worst case with 5 bytes per
pixel, rounded down to a nice clean value. 400 million pixels ought to be
enough for anybody. */
#define QOI_PIXELS_MAX ((unsigned int)400000000)
typedef union {
struct { unsigned char r, g, b, a; } rgba;
unsigned int v;
} qoi_rgba_t;
static const unsigned char qoi_padding[8] = {0,0,0,0,0,0,0,1};
static void qoi_write_32(unsigned char *bytes, int *p, unsigned int v) {
bytes[(*p)++] = (0xff000000 & v) >> 24;
bytes[(*p)++] = (0x00ff0000 & v) >> 16;
bytes[(*p)++] = (0x0000ff00 & v) >> 8;
bytes[(*p)++] = (0x000000ff & v);
}
static void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) {
int i, max_size, p, run;
int px_len, px_end, px_pos, channels;
unsigned char *bytes;
const unsigned char *pixels;
qoi_rgba_t index[64];
qoi_rgba_t px, px_prev;
if (
data == NULL || out_len == NULL || desc == NULL ||
desc->width == 0 || desc->height == 0 ||
desc->channels < 3 || desc->channels > 4 ||
desc->colorspace > 1 ||
desc->height >= QOI_PIXELS_MAX / desc->width
) {
return NULL;
}
max_size =
desc->width * desc->height * (desc->channels + 1) +
QOI_HEADER_SIZE + sizeof(qoi_padding);
p = 0;
bytes = (unsigned char *) STBIW_MALLOC(max_size);
if (!bytes) {
return NULL;
}
qoi_write_32(bytes, &p, QOI_MAGIC);
qoi_write_32(bytes, &p, desc->width);
qoi_write_32(bytes, &p, desc->height);
bytes[p++] = desc->channels;
bytes[p++] = desc->colorspace;
pixels = (const unsigned char *)data;
QOI_ZEROARR(index);
run = 0;
px_prev.rgba.r = 0;
px_prev.rgba.g = 0;
px_prev.rgba.b = 0;
px_prev.rgba.a = 255;
px = px_prev;
px_len = desc->width * desc->height * desc->channels;
px_end = px_len - desc->channels;
channels = desc->channels;
for (px_pos = 0; px_pos < px_len; px_pos += channels) {
px.rgba.r = pixels[px_pos + 0];
px.rgba.g = pixels[px_pos + 1];
px.rgba.b = pixels[px_pos + 2];
if (channels == 4) {
px.rgba.a = pixels[px_pos + 3];
}
if (px.v == px_prev.v) {
run++;
if (run == 62 || px_pos == px_end) {
bytes[p++] = QOI_OP_RUN | (run - 1);
run = 0;
}
}
else {
int index_pos;
if (run > 0) {
bytes[p++] = QOI_OP_RUN | (run - 1);
run = 0;
}
index_pos = QOI_COLOR_HASH(px) % 64;
if (index[index_pos].v == px.v) {
bytes[p++] = QOI_OP_INDEX | index_pos;
}
else {
index[index_pos] = px;
if (px.rgba.a == px_prev.rgba.a) {
signed char vr = px.rgba.r - px_prev.rgba.r;
signed char vg = px.rgba.g - px_prev.rgba.g;
signed char vb = px.rgba.b - px_prev.rgba.b;
signed char vg_r = vr - vg;
signed char vg_b = vb - vg;
if (
vr > -3 && vr < 2 &&
vg > -3 && vg < 2 &&
vb > -3 && vb < 2
) {
bytes[p++] = QOI_OP_DIFF | (vr + 2) << 4 | (vg + 2) << 2 | (vb + 2);
}
else if (
vg_r > -9 && vg_r < 8 &&
vg > -33 && vg < 32 &&
vg_b > -9 && vg_b < 8
) {
bytes[p++] = QOI_OP_LUMA | (vg + 32);
bytes[p++] = (vg_r + 8) << 4 | (vg_b + 8);
}
else {
bytes[p++] = QOI_OP_RGB;
bytes[p++] = px.rgba.r;
bytes[p++] = px.rgba.g;
bytes[p++] = px.rgba.b;
}
}
else {
bytes[p++] = QOI_OP_RGBA;
bytes[p++] = px.rgba.r;
bytes[p++] = px.rgba.g;
bytes[p++] = px.rgba.b;
bytes[p++] = px.rgba.a;
}
}
}
px_prev = px;
}
for (i = 0; i < (int)sizeof(qoi_padding); i++) {
bytes[p++] = qoi_padding[i];
}
*out_len = p;
return bytes;
}
static int stbi_write_qoi_core(stbi__write_context *s, int x, int y, int comp, const void*data)
{
if (y <= 0 || x <= 0 || data == NULL)
return 0;
qoi_desc desc;
desc.width = x;
desc.height = y;
desc.channels = comp;
desc.colorspace = QOI_LINEAR;
int out_len = 0;
void* res = qoi_encode(data, &desc, &out_len);
if (res != NULL)
s->func(s->context, res, out_len);
return res != NULL ? 1 : 0;
}
STBIWDEF int stbi_write_qoi_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
{
stbi__write_context s = { 0 };
stbi__start_write_callbacks(&s, func, context);
return stbi_write_qoi_core(&s, x, y, comp, (void *) data);
}
#ifndef STBI_WRITE_NO_STDIO
STBIWDEF int stbi_write_qoi(char const *filename, int x, int y, int comp, const void *data)
{
stbi__write_context s = { 0 };
if (stbi__start_write_file(&s,filename)) {
int r = stbi_write_qoi_core(&s, x, y, comp, (void *) data);
stbi__end_write_file(&s);
return r;
} else
return 0;
}
#endif

228
vendor/SOIL2/src/SOIL2/wfETC.c vendored Normal file
View File

@ -0,0 +1,228 @@
#include "wfETC.h"
// specification: http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt
#ifdef WF_LITTLE_ENDIAN
#define WF_ETC1_COLOR_OFFSET( offset ) ( (64-(offset)) - (4-((offset)%8))*2 )
#define WF_ETC1_PIXEL_OFFSET( offset ) ( (32-(offset)) - (4-((offset)%8))*2 )
#else
#define WF_ETC1_COLOR_OFFSET( offset ) (offset-32)
#define WF_ETC1_PIXEL_OFFSET( offset ) offset
#endif
#define WF_INLINE
#define WF_ASSUME( expr )
#ifndef WF_EXPECT
#if defined __GNUC__ && __GNUC__
#define WF_EXPECT( expr, val ) __builtin_expect( expr, val )
#else
#define WF_EXPECT( expr, val ) expr
#endif
#endif
// this table is rearranged from the specification so we do not have to add any logic to index into it
const int32_t wfETC_IntensityTables[8][4] =
{
{ 2, 8, -2, -8 },
{ 5, 17, -5, -17 },
{ 9, 29, -9, -29 },
{ 13, 42, -13, -42 },
{ 18, 60, -18, -60 },
{ 24, 80, -24, -80 },
{ 33, 106, -33, -106 },
{ 47, 183, -47, -183 }
};
WF_INLINE
int32_t wfETC_ClampColor( const int32_t x )
{
if( x < 0 ) { return 0; }
if( x > 255 ) { return 255; }
return x;
}
#define WF_ETC1_BUILD_COLOR( dst, blockIdx, colorIdx, intensityTable, baseColor ) \
dst[ blockIdx ][ colorIdx ] = WF_ETC_RGBA( \
wfETC_ClampColor( intensityTable[ blockIdx ][ colorIdx ] + baseColor[ blockIdx ][ 0 ] ), \
wfETC_ClampColor( intensityTable[ blockIdx ][ colorIdx ] + baseColor[ blockIdx ][ 1 ] ), \
wfETC_ClampColor( intensityTable[ blockIdx ][ colorIdx ] + baseColor[ blockIdx ][ 2 ] ), \
255 \
);
typedef struct _wfETC1_Block
{
int32_t baseColorsAndFlags;
int32_t pixels;
} wfETC1_Block;
#define WF_ETC1_CHECK_DIFF_BIT( block ) ( block->baseColorsAndFlags & (1<<WF_ETC1_COLOR_OFFSET(33)) )
#define WF_ETC1_CHECK_FLIP_BIT( block ) ( block->baseColorsAndFlags & (1<<WF_ETC1_COLOR_OFFSET(32)) )
WF_INLINE
int32_t wfETC1_ReadColor4( const wfETC1_Block* block, const uint32_t offset )
{
const uint32_t bitOffset = WF_ETC1_COLOR_OFFSET(offset);
const int32_t color = ( block->baseColorsAndFlags >> bitOffset ) & 0xf;
return color | (color<<4);
}
const int32_t wfETC1_Color3IdxLUT[] = { 0, 1, 2, 3, -4, -3, -2, -1 };
WF_INLINE
void wfETC1_ReadColor53( const wfETC1_Block* block, const uint32_t offset3, int32_t* WF_RESTRICT dst5, int32_t* WF_RESTRICT dst3 )
{
// read the 5 bit color and expand to 8 bit
{
const uint32_t bitOffset = WF_ETC1_COLOR_OFFSET((offset3+3));
const int32_t color = ( block->baseColorsAndFlags >> (bitOffset-3) ) & 0xf8;
*dst5 = color | (color>>5);
}
// read the 3 bit color and expand to 8 bit
{
const uint32_t bitOffset = WF_ETC1_COLOR_OFFSET(offset3);
const int32_t offset = wfETC1_Color3IdxLUT[ ( block->baseColorsAndFlags >> bitOffset ) & 0x7 ];
int32_t color = (*dst5>>3) + offset;
color <<= 3;
color |= (color>>5) & 0x7;
*dst3 = color;
}
}
WF_INLINE
int32_t wfETC1_ReadPixel( const wfETC1_Block* block, const uint32_t offset )
{
return
( (block->pixels>>WF_ETC1_PIXEL_OFFSET(offset)) & 0x1 )
|
( ( (block->pixels>>WF_ETC1_PIXEL_OFFSET(16+offset)) & 0x1 ) << 1 )
;
}
void wfETC1_DecodeBlock( const void* WF_RESTRICT src, void* WF_RESTRICT pDst, const uint32_t dstStride )
{
const wfETC1_Block* WF_RESTRICT block = ( wfETC1_Block* )src;
int32_t* WF_RESTRICT dst = (int32_t*)pDst;
int32_t baseColors[2][3]; // [sub-block][r,g,b]
int32_t colors[2][4]; // [sub-block][colorIdx]
// individual mode
if( WF_ETC1_CHECK_DIFF_BIT( block ) == 0 )
{
baseColors[0][0] = wfETC1_ReadColor4( block, 60 );
baseColors[0][1] = wfETC1_ReadColor4( block, 52 );
baseColors[0][2] = wfETC1_ReadColor4( block, 44 );
baseColors[1][0] = wfETC1_ReadColor4( block, 56 );
baseColors[1][1] = wfETC1_ReadColor4( block, 48 );
baseColors[1][2] = wfETC1_ReadColor4( block, 40 );
}
// differential mode
else
{
wfETC1_ReadColor53( block, 56, &baseColors[0][0], &baseColors[1][0] );
wfETC1_ReadColor53( block, 48, &baseColors[0][1], &baseColors[1][1] );
wfETC1_ReadColor53( block, 40, &baseColors[0][2], &baseColors[1][2] );
}
// build color tables
{
const int32_t* intensityTable[2] = // [sub-block]
{
wfETC_IntensityTables[ ( block->baseColorsAndFlags >> WF_ETC1_COLOR_OFFSET(37) ) & 0x7 ],
wfETC_IntensityTables[ ( block->baseColorsAndFlags >> WF_ETC1_COLOR_OFFSET(34) ) & 0x7 ]
};
WF_ETC1_BUILD_COLOR( colors, 0, 0, intensityTable, baseColors );
WF_ETC1_BUILD_COLOR( colors, 0, 1, intensityTable, baseColors );
WF_ETC1_BUILD_COLOR( colors, 0, 2, intensityTable, baseColors );
WF_ETC1_BUILD_COLOR( colors, 0, 3, intensityTable, baseColors );
WF_ETC1_BUILD_COLOR( colors, 1, 0, intensityTable, baseColors );
WF_ETC1_BUILD_COLOR( colors, 1, 1, intensityTable, baseColors );
WF_ETC1_BUILD_COLOR( colors, 1, 2, intensityTable, baseColors );
WF_ETC1_BUILD_COLOR( colors, 1, 3, intensityTable, baseColors );
}
// vertical split
if( WF_ETC1_CHECK_FLIP_BIT( block ) == 0 )
{
// row 0
dst[0] = colors[0][ wfETC1_ReadPixel( block, 0 ) ];
dst[1] = colors[0][ wfETC1_ReadPixel( block, 4 ) ];
dst[2] = colors[1][ wfETC1_ReadPixel( block, 8 ) ];
dst[3] = colors[1][ wfETC1_ReadPixel( block, 12 ) ];
dst += dstStride;
// row 1
dst[0] = colors[0][ wfETC1_ReadPixel( block, 1 ) ];
dst[1] = colors[0][ wfETC1_ReadPixel( block, 5 ) ];
dst[2] = colors[1][ wfETC1_ReadPixel( block, 9 ) ];
dst[3] = colors[1][ wfETC1_ReadPixel( block, 13 ) ];
dst += dstStride;
// row 2
dst[0] = colors[0][ wfETC1_ReadPixel( block, 2 ) ];
dst[1] = colors[0][ wfETC1_ReadPixel( block, 6 ) ];
dst[2] = colors[1][ wfETC1_ReadPixel( block, 10 ) ];
dst[3] = colors[1][ wfETC1_ReadPixel( block, 14 ) ];
dst += dstStride;
// row 3
dst[0] = colors[0][ wfETC1_ReadPixel( block, 3 ) ];
dst[1] = colors[0][ wfETC1_ReadPixel( block, 7 ) ];
dst[2] = colors[1][ wfETC1_ReadPixel( block, 11 ) ];
dst[3] = colors[1][ wfETC1_ReadPixel( block, 15 ) ];
//dst += dstStride;
}
// horizontal split
else
{
// row 0
dst[0] = colors[0][ wfETC1_ReadPixel( block, 0 ) ];
dst[1] = colors[0][ wfETC1_ReadPixel( block, 4 ) ];
dst[2] = colors[0][ wfETC1_ReadPixel( block, 8 ) ];
dst[3] = colors[0][ wfETC1_ReadPixel( block, 12 ) ];
dst += dstStride;
// row 1
dst[0] = colors[0][ wfETC1_ReadPixel( block, 1 ) ];
dst[1] = colors[0][ wfETC1_ReadPixel( block, 5 ) ];
dst[2] = colors[0][ wfETC1_ReadPixel( block, 9 ) ];
dst[3] = colors[0][ wfETC1_ReadPixel( block, 13 ) ];
dst += dstStride;
// row 2
dst[0] = colors[1][ wfETC1_ReadPixel( block, 2 ) ];
dst[1] = colors[1][ wfETC1_ReadPixel( block, 6 ) ];
dst[2] = colors[1][ wfETC1_ReadPixel( block, 10 ) ];
dst[3] = colors[1][ wfETC1_ReadPixel( block, 14 ) ];
dst += dstStride;
// row 3
dst[0] = colors[1][ wfETC1_ReadPixel( block, 3 ) ];
dst[1] = colors[1][ wfETC1_ReadPixel( block, 7 ) ];
dst[2] = colors[1][ wfETC1_ReadPixel( block, 11 ) ];
dst[3] = colors[1][ wfETC1_ReadPixel( block, 15 ) ];
//dst += dstStride;
}
}
void wfETC1_DecodeImage( const void* WF_RESTRICT pSrc, void* WF_RESTRICT pDst, const uint32_t width, const uint32_t height )
{
const uint8_t* WF_RESTRICT src = (uint8_t*)pSrc;
uint8_t* WF_RESTRICT dst = (uint8_t*)pDst;
const uint32_t widthBlocks = width/4;
const uint32_t heightBlocks = height/4;
uint32_t x, y;
for( y = 0; y != heightBlocks; ++y )
{
for( x = 0; x != widthBlocks; ++x )
{
wfETC1_DecodeBlock( src, dst, width );
src += 8;
dst += 16;
}
dst += width*4*3;
}
}

53
vendor/SOIL2/src/SOIL2/wfETC.h vendored Normal file
View File

@ -0,0 +1,53 @@
#ifndef WF_ETC_H
#define WF_ETC_H
#define WF_LITTLE_ENDIAN
// Qt ordering
#define WF_ETC_RGBA( r, g, b, a ) ( ((a)<<24) | ((r)<<16) | ((g)<<8) | (b) ) // colors have been clamped by the time we hit here, so there should be no need to mask
#ifdef _MSC_VER
#if _MSC_VER < 1300
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
#else
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
#endif
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
#ifndef WF_RESTRICT
#if defined MSC_VER
#define WF_RESTRICT __restrict
#elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
#define WF_RESTRICT restrict
#else
#define WF_RESTRICT
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
extern void wfETC1_DecodeBlock( const void* WF_RESTRICT src, void* WF_RESTRICT dst, const uint32_t dstStride /*=4*/ ); //!< stride in pixels; must be a multiple of four
extern void wfETC1_DecodeImage( const void* WF_RESTRICT src, void* WF_RESTRICT dst, const uint32_t width, const uint32_t height ); //!< width/height in pixels; must be multiples of four
#ifdef __cplusplus
}
#endif
#endif // WF_ETC_H

138
vendor/SOIL2/src/common/common.cpp vendored Normal file
View File

@ -0,0 +1,138 @@
#include "common.hpp"
#include <string>
#include <cmath>
#include <climits>
#include <limits>
#include <vector>
#if defined( __APPLE_CC__ ) || defined ( __APPLE__ )
#define PLATFORM_OSX
#include <CoreFoundation/CoreFoundation.h>
#elif defined( __WIN32__ ) || defined( _WIN32 ) || defined( _WIN64 )
#define PLATFORM_WIN32
#include <windows.h>
#if defined(_MSC_VER) && defined( UNICODE )
static std::string wcharToString(TCHAR* text) {
std::vector<char> buffer;
int size = WideCharToMultiByte(CP_UTF8, 0, text, -1, NULL, 0, NULL, NULL);
if (size > 0) {
buffer.resize(size);
WideCharToMultiByte(CP_UTF8, 0, text, -1, reinterpret_cast<LPSTR>(&buffer[0]), buffer.size(), NULL, NULL);
}
return std::string(&buffer[0]);
}
#endif
#elif defined ( linux ) || defined( __linux__ )
#define PLATFORM_LINUX
#include <libgen.h>
#include <unistd.h>
#elif defined( __HAIKU__ ) || defined( __BEOS__ )
#define PLATFORM_HAIKU
#include <kernel/OS.h>
#include <kernel/image.h>
#elif defined( __SVR4 )
#define PLATFORM_SOLARIS
#include <stdlib.h>
#elif defined( __FreeBSD__ ) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined( __DragonFly__ )
#define PLATFORM_BSD
#include <sys/sysctl.h>
#endif
std::string FileRemoveFileName( const std::string& filepath ) {
return filepath.substr( 0, filepath.find_last_of("/\\") + 1 );
}
static std::string GetProcessPath() {
#if defined( PLATFORM_OSX )
char exe_file[PATH_MAX + 1];
CFBundleRef mainBundle = CFBundleGetMainBundle();
if (mainBundle) {
CFURLRef mainURL = CFBundleCopyBundleURL(mainBundle);
if (mainURL) {
int ok = CFURLGetFileSystemRepresentation ( mainURL, (Boolean) true, (UInt8*)exe_file, PATH_MAX );
if (ok) {
return std::string(exe_file) + "/";
}
}
}
return "./";
#elif defined( PLATFORM_LINUX )
char exe_file[PATH_MAX + 1];
int size;
size = readlink("/proc/self/exe", exe_file, PATH_MAX);
if (size < 0) {
return "./";
} else {
exe_file[size] = '\0';
return std::string(dirname(exe_file)) + "/";
}
#elif defined( PLATFORM_WIN32 )
#ifdef UNICODE
// Get path to executable:
TCHAR szDllName[_MAX_PATH];
TCHAR szDrive[_MAX_DRIVE];
TCHAR szDir[_MAX_DIR];
TCHAR szFilename[_MAX_DIR];
TCHAR szExt[_MAX_DIR];
GetModuleFileName(0, szDllName, _MAX_PATH);
#if ( defined( _MSCVER ) || defined( _MSC_VER ) )
_wsplitpath_s(szDllName, szDrive, _MAX_DRIVE, szDir, _MAX_DIR, szFilename, _MAX_DIR, szExt, _MAX_DIR);
#else
_splitpath(szDllName, szDrive, szDir, szFilename, szExt);
#endif
return wcharToString(szDrive) + wcharToString(szDir);
#else
// Get path to executable:
TCHAR szDllName[_MAX_PATH];
TCHAR szDrive[_MAX_DRIVE];
TCHAR szDir[_MAX_DIR];
TCHAR szFilename[_MAX_DIR];
TCHAR szExt[_MAX_DIR];
GetModuleFileName(0, szDllName, _MAX_PATH);
#if ( defined( _MSCVER ) || defined( _MSC_VER ) )
_splitpath_s(szDllName, szDrive, _MAX_DRIVE, szDir, _MAX_DIR, szFilename, _MAX_DIR, szExt, _MAX_DIR);
#else
_splitpath(szDllName, szDrive, szDir, szFilename, szExt);
#endif
return std::string(szDrive) + std::string(szDir);
#endif
#elif defined( PLATFORM_BSD )
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
char buf[1024];
size_t cb = sizeof(buf);
sysctl(mib, 4, buf, &cb, NULL, 0);
return FileRemoveFileName( std::string( buf ) );
#elif defined( PLATFORM_SOLARIS )
return FileRemoveFileName( std::string( getexecname() ) );
#elif defined( PLATFORM_HAIKU )
image_info info;
int32 cookie = 0;
while ( B_OK == get_next_image_info( 0, &cookie, &info ) ) {
if ( info.type == B_APP_IMAGE )
break;
}
return FileRemoveFileName( std::string( info.name ) );
#else
#warning GetProcessPath() not implemented on this platform. ( will return "./" )
return "./";
#endif
}
std::string ResourcePath(std::string fileName) {
return GetProcessPath() + fileName;
}

3
vendor/SOIL2/src/common/common.hpp vendored Normal file
View File

@ -0,0 +1,3 @@
#include <string>
std::string ResourcePath(std::string fileName);

View File

@ -1,730 +0,0 @@
/* 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 *comp2 = &scratch[width*c];
x = 0;
while (x < width) {
// find first run
r = x;
while (r+2 < width) {
if (comp2[r] == comp2[r+1] && comp2[r] == comp2[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, &comp2[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 && comp2[r] == comp2[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, comp2[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 i2=0, s1=1, s2=0, blocklen = data_len % 5552;
int j2=0;
while (j2 < data_len) {
for (i2=0; i2 < blocklen; ++i2) s1 += data[j2+i2], s2 += s1;
s1 %= 65521, s2 %= 65521;
j2 += 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
*/