Switch out etcpack with the ZLIB licensed rg_etc1 library

This commit is contained in:
Henrik Rydgard 2013-03-29 13:53:04 +01:00
parent 8050390ac5
commit 75e9af1379
21 changed files with 2556 additions and 8190 deletions

View File

@ -16,6 +16,7 @@ LOCAL_SRC_FILES :=\
base/colorutil.cpp \
base/error_context.cpp \
base/stringutil.cpp \
ext/rg_etc1/rg_etc1.cpp \
ext/cityhash/city.cpp \
ext/sha1/sha1.cpp \
ext/stb_image/stb_image.c \
@ -51,6 +52,7 @@ LOCAL_SRC_FILES :=\
gfx/texture_atlas.cpp \
gfx/texture_gen.cpp \
image/zim_load.cpp \
image/zim_save.cpp \
image/png_load.cpp \
ui/ui.cpp \
ui/ui_context.cpp \

View File

@ -9,7 +9,7 @@ Features
* JSON read/write (two libraries that should be made more similar)
* basic OpenGL utility code, like compressed texture loading
* 2D texture atlases and drawing code
* ETC1 texture loading support
* ETC1 texture save/load support
* basic logging
* Really simple audio mixer with OGG sample support
* RIFF file read/write
@ -29,7 +29,7 @@ Licenses
This library, for my convenience, incorporates code from a variety of public domain or similarly-licensed code. This is the list:
* glew (GL extension wrangler), MIT license. TODO: should just use a submodule.
* etcpack by Ericsson, in a cleaned up form. Has strange license but not very limiting - you can only use the code for making textures for hardware supporting ETC1, or something like that. Don't think it affects the rest of the code in any way.
* rg_etc1. ZLIB license.
* sha1, public domain implementation by Dominik Reichl
* vjson in a heavily modified form, originally by Ivan Vashchaev (TODO: break out into its own repo?)
* libzip with attribution "Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner"

View File

@ -1,7 +0,0 @@
This folder contains code adapted from etcpack by ERICSSON ///.
The license comments have been left at the top of each file, but some code may have moved around.
See LICENSE.TXT for details. It says that use of the code is limited to applications using the
code to compress textures for use with a Khronos-derived API. This game engine only supports
OpenGL ES 2.0, which certainly qualifies, so there is no issue there.

View File

@ -1,418 +0,0 @@
/**
@~English
@page licensing Licensing
@section etcdec etcdec.cxx License
etcdec.cxx is made available under the terms and conditions of the following
License Agreement.
SOFTWARE LICENSE AGREEMENT
PLEASE REVIEW THE FOLLOWING TERMS AND CONDITIONS PRIOR TO USING THE
ERICSSON TEXTURE COMPRESSION CODEC SOFTWARE (THE "SOFTWARE"). THE USE
OF THE SOFTWARE IS SUBJECT TO THE TERMS AND CONDITIONS OF THE
FOLLOWING LICENSE AGREEMENT (THE "LICENSE AGREEMENT"). IF YOU DO NOT
ACCEPT SUCH TERMS AND CONDITIONS YOU MAY NOT USE THE SOFTWARE.
Under the terms and conditions of the License Agreement, Licensee
hereby, receives a non-exclusive, non transferable, limited, free of
charge, perpetual and worldwide license, to copy, use, distribute and
modify the Software, but only for the purpose of developing,
manufacturing, selling, using and distributing products including the
Software, which products are used for (i) compression and/or
decompression to create content creation tools for usage with a
Khronos API, and/or (ii) compression and/or decompression for the
purpose of usage with a middleware API that is built on top of a
Khronos API, such as JCPs based on a Khronos API (in particular
"Mobile 3D Graphics API for J2ME" and its future versions and "Java
Bindings for OpenGL ES" and its future versions), and/or (iii)
compression and/or decompression to implement a Khronos specification.
If Licensee institutes patent litigation against Ericsson or any
licensee of the Software for using the Software for making,
developing, manufacturing, selling, using and/or distributing products
within the scope of the Khronos framework, Ericsson shall have the
right to terminate this License Agreement with immediate
effect. However, should Licensee institute patent litigation against
any other licensee of the Software based on such licensee´s use of any
other software distributed together with the Software then Ericsson
shall have no right to terminate this License Agreement.
The License Agreement does not transfer to Licensee any ownership to
any Ericsson or third party intellectual property rights.
THE SOFTWARE IS PROVIDED "AS IS". ERICSSON MAKES NO REPRESENTATIONS OF
ANY KIND, EXTENDS NO WARRANTIES OF ANY KIND, EITHER EXPRESS OR
IMPLIED; INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH THE
LICENSEE. SHOULD THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE ASSUMES
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON
MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, DISTRIBUTION, LEASE, USE
OR IMPORTATION UNDER THE LICENSE AGREEMENT WILL BE FREE FROM
INFRINGEMENT OF PATENTS, COPYRIGHTS OR OTHER INTELLECTUAL PROPERTY
RIGHTS OF OTHERS, AND THE VALIDITY OF THE LICENSE AND THE LICENSE
AGREEMENT IS SUBJECT TO LICENSEE'S SOLE RESPONSIBILITY TO MAKE SUCH
DETERMINATION AND ACQUIRE SUCH LICENSES AS MAY BE NECESSARY WITH
RESPECT TO PATENTS AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES.
IN NO EVENT WILL ERICSSON BE LIABLE TO THE LICENSEE FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT
NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
LOSSES SUSTAINED BY THE LICENSEE OR THIRD PARTIES OR A FAILURE OF THE
SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR
OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Licensee acknowledges that "ERICSSON ///" is the corporate trademark
of Telefonaktiebolaget LM Ericsson and that both "Ericsson" and the
figure "///" are important features of the trade names of
Telefonaktiebolaget LM Ericsson. Nothing contained in these terms and
conditions shall be deemed to grant Licensee any right, title or
interest in the word "Ericsson" or the figure "///".
The parties agree that this License Agreement based on these terms and
conditions is governed by the laws of Sweden, and in the event of any
dispute as a result of this License Agreement, the parties submit
themselves to the exclusive jurisdiction of the Swedish Courts.
*/
#include <stdio.h>
#include <string.h>
#define CLAMP(ll,x,ul) (((x)<(ll)) ? (ll) : (((x)>(ul)) ? (ul) : (x)))
#define GETBITS(source, size, startpos) (( (source) >> ((startpos)-(size)+1) ) & ((1<<(size)) -1))
#define GETBITSHIGH(source, size, startpos) (( (source) >> (((startpos)-32)-(size)+1) ) & ((1<<(size)) -1))
#define RED(img,width,x,y) img[3*(y*width+x)+0]
#define GREEN(img,width,x,y) img[3*(y*width+x)+1]
#define BLUE(img,width,x,y) img[3*(y*width+x)+2]
typedef unsigned char uint8;
int unscramble[4] = {2, 3, 1, 0};
static const int compressParams[16][4] = {{-8, -2, 2, 8}, {-8, -2, 2, 8}, {-17, -5, 5, 17}, {-17, -5, 5, 17}, {-29, -9, 9, 29}, {-29, -9, 9, 29}, {-42, -13, 13, 42}, {-42, -13, 13, 42}, {-60, -18, 18, 60}, {-60, -18, 18, 60}, {-80, -24, 24, 80}, {-80, -24, 24, 80}, {-106, -33, 33, 106}, {-106, -33, 33, 106}, {-183, -47, 47, 183}, {-183, -47, 47, 183}};
void decompressBlockDiffFlip(unsigned int block_part1, unsigned int block_part2, uint8 *img,int width,int height,int startx,int starty)
{
uint8 avg_color[3], enc_color1[3], enc_color2[3];
char diff[3];
int table;
int index,shift;
int r,g,b;
int diffbit;
int flipbit;
unsigned int pixel_indices_MSB, pixel_indices_LSB;
int x,y;
diffbit = (GETBITSHIGH(block_part1, 1, 33));
flipbit = (GETBITSHIGH(block_part1, 1, 32));
if( !diffbit )
{
// We have diffbit = 0.
// First decode left part of block.
avg_color[0]= GETBITSHIGH(block_part1, 4, 63);
avg_color[1]= GETBITSHIGH(block_part1, 4, 55);
avg_color[2]= GETBITSHIGH(block_part1, 4, 47);
// Here, we should really multiply by 17 instead of 16. This can
// be done by just copying the four lower bits to the upper ones
// while keeping the lower bits.
avg_color[0] |= (avg_color[0] <<4);
avg_color[1] |= (avg_color[1] <<4);
avg_color[2] |= (avg_color[2] <<4);
table = GETBITSHIGH(block_part1, 3, 39) << 1;
pixel_indices_MSB = GETBITS(block_part2, 16, 31);
pixel_indices_LSB = GETBITS(block_part2, 16, 15);
if( (flipbit) == 0 )
{
// We should not flip
shift = 0;
for(x=startx; x<startx+2; x++)
{
for(y=starty; y<starty+4; y++)
{
index = ((pixel_indices_MSB >> shift) & 1) << 1;
index |= ((pixel_indices_LSB >> shift) & 1);
shift++;
index=unscramble[index];
r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255);
g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255);
b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255);
}
}
}
else
{
// We should flip
shift = 0;
for(x=startx; x<startx+4; x++)
{
for(y=starty; y<starty+2; y++)
{
index = ((pixel_indices_MSB >> shift) & 1) << 1;
index |= ((pixel_indices_LSB >> shift) & 1);
shift++;
index=unscramble[index];
r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255);
g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255);
b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255);
}
shift+=2;
}
}
// Now decode other part of block.
avg_color[0]= GETBITSHIGH(block_part1, 4, 59);
avg_color[1]= GETBITSHIGH(block_part1, 4, 51);
avg_color[2]= GETBITSHIGH(block_part1, 4, 43);
// Here, we should really multiply by 17 instead of 16. This can
// be done by just copying the four lower bits to the upper ones
// while keeping the lower bits.
avg_color[0] |= (avg_color[0] <<4);
avg_color[1] |= (avg_color[1] <<4);
avg_color[2] |= (avg_color[2] <<4);
table = GETBITSHIGH(block_part1, 3, 36) << 1;
pixel_indices_MSB = GETBITS(block_part2, 16, 31);
pixel_indices_LSB = GETBITS(block_part2, 16, 15);
if( (flipbit) == 0 )
{
// We should not flip
shift=8;
for(x=startx+2; x<startx+4; x++)
{
for(y=starty; y<starty+4; y++)
{
index = ((pixel_indices_MSB >> shift) & 1) << 1;
index |= ((pixel_indices_LSB >> shift) & 1);
shift++;
index=unscramble[index];
r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255);
g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255);
b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255);
}
}
}
else
{
// We should flip
shift=2;
for(x=startx; x<startx+4; x++)
{
for(y=starty+2; y<starty+4; y++)
{
index = ((pixel_indices_MSB >> shift) & 1) << 1;
index |= ((pixel_indices_LSB >> shift) & 1);
shift++;
index=unscramble[index];
r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255);
g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255);
b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255);
}
shift += 2;
}
}
}
else
{
// We have diffbit = 1.
// 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
// ---------------------------------------------------------------------------------------------------
// | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |diff|flip|
// | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | 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 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
// --------------------------------------------------------------------------------------------------
// | most significant pixel index bits | least significant pixel index bits |
// | p| o| n| m| l| k| j| i| h| g| f| e| d| c| b| a| p| o| n| m| l| k| j| i| h| g| f| e| d| c | b | a |
// --------------------------------------------------------------------------------------------------
// First decode left part of block.
enc_color1[0]= GETBITSHIGH(block_part1, 5, 63);
enc_color1[1]= GETBITSHIGH(block_part1, 5, 55);
enc_color1[2]= GETBITSHIGH(block_part1, 5, 47);
// Expand from 5 to 8 bits
avg_color[0] = (enc_color1[0] <<3) | (enc_color1[0] >> 2);
avg_color[1] = (enc_color1[1] <<3) | (enc_color1[1] >> 2);
avg_color[2] = (enc_color1[2] <<3) | (enc_color1[2] >> 2);
table = GETBITSHIGH(block_part1, 3, 39) << 1;
pixel_indices_MSB = GETBITS(block_part2, 16, 31);
pixel_indices_LSB = GETBITS(block_part2, 16, 15);
if( (flipbit) == 0 )
{
// We should not flip
shift = 0;
for(x=startx; x<startx+2; x++)
{
for(y=starty; y<starty+4; y++)
{
index = ((pixel_indices_MSB >> shift) & 1) << 1;
index |= ((pixel_indices_LSB >> shift) & 1);
shift++;
index=unscramble[index];
r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255);
g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255);
b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255);
}
}
}
else
{
// We should flip
shift = 0;
for(x=startx; x<startx+4; x++)
{
for(y=starty; y<starty+2; y++)
{
index = ((pixel_indices_MSB >> shift) & 1) << 1;
index |= ((pixel_indices_LSB >> shift) & 1);
shift++;
index=unscramble[index];
r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255);
g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255);
b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255);
}
shift+=2;
}
}
// Now decode right part of block.
diff[0]= GETBITSHIGH(block_part1, 3, 58);
diff[1]= GETBITSHIGH(block_part1, 3, 50);
diff[2]= GETBITSHIGH(block_part1, 3, 42);
enc_color2[0]= enc_color1[0] + diff[0];
enc_color2[1]= enc_color1[1] + diff[1];
enc_color2[2]= enc_color1[2] + diff[2];
// Extend sign bit to entire byte.
diff[0] = (diff[0] << 5);
diff[1] = (diff[1] << 5);
diff[2] = (diff[2] << 5);
diff[0] = diff[0] >> 5;
diff[1] = diff[1] >> 5;
diff[2] = diff[2] >> 5;
// Calculale second color
enc_color2[0]= enc_color1[0] + diff[0];
enc_color2[1]= enc_color1[1] + diff[1];
enc_color2[2]= enc_color1[2] + diff[2];
// Expand from 5 to 8 bits
avg_color[0] = (enc_color2[0] <<3) | (enc_color2[0] >> 2);
avg_color[1] = (enc_color2[1] <<3) | (enc_color2[1] >> 2);
avg_color[2] = (enc_color2[2] <<3) | (enc_color2[2] >> 2);
table = GETBITSHIGH(block_part1, 3, 36) << 1;
pixel_indices_MSB = GETBITS(block_part2, 16, 31);
pixel_indices_LSB = GETBITS(block_part2, 16, 15);
if( (flipbit) == 0 )
{
// We should not flip
shift=8;
for(x=startx+2; x<startx+4; x++)
{
for(y=starty; y<starty+4; y++)
{
index = ((pixel_indices_MSB >> shift) & 1) << 1;
index |= ((pixel_indices_LSB >> shift) & 1);
shift++;
index=unscramble[index];
r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255);
g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255);
b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255);
}
}
}
else
{
// We should flip
shift=2;
for(x=startx; x<startx+4; x++)
{
for(y=starty+2; y<starty+4; y++)
{
index = ((pixel_indices_MSB >> shift) & 1) << 1;
index |= ((pixel_indices_LSB >> shift) & 1);
shift++;
index=unscramble[index];
r=RED(img,width,x,y) =CLAMP(0,avg_color[0]+compressParams[table][index],255);
g=GREEN(img,width,x,y)=CLAMP(0,avg_color[1]+compressParams[table][index],255);
b=BLUE(img,width,x,y) =CLAMP(0,avg_color[2]+compressParams[table][index],255);
}
shift += 2;
}
}
}
}
static int bswap(unsigned int x) {
return ((x & 0xFF000000) >> 24) |
((x & 0x00FF0000) >> 8) |
((x & 0x0000FF00) << 8) |
((x & 0x000000FF) << 24);
}
void DecompressBlock(const uint8 *compressed, uint8 *out, int out_width, int alpha=255) {
uint8 rgb[4*4*3];
unsigned int block_part1, block_part2;
memcpy(&block_part1, compressed, 4);
memcpy(&block_part2, compressed + 4, 4);
block_part1 = bswap(block_part1);
block_part2 = bswap(block_part2);
decompressBlockDiffFlip(block_part1, block_part2, rgb, 4, 4, 0, 0);
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
out[(y * out_width + x) * 4 + 0] = rgb[(4 * y + x) * 3 + 0];
out[(y * out_width + x) * 4 + 1] = rgb[(4 * y + x) * 3 + 1];
out[(y * out_width + x) * 4 + 2] = rgb[(4 * y + x) * 3 + 2];
out[(y * out_width + x) * 4 + 3] = alpha;
}
}
}

View File

@ -1,9 +0,0 @@
#pragma once
typedef unsigned char uint8;
/* In etcdec.cxx */
void decompressBlockDiffFlip(unsigned int block_part1, unsigned int block_part2, uint8 *img,int width,int height,int startx,int starty);
// Writes RGBA output instead of RGB.
void DecompressBlock(const uint8 *compressed, uint8 *out, int out_width, int alpha=255);

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +0,0 @@
#pragma once
#define PERCEPTUAL_WEIGHT_R_SQUARED 0.299
#define PERCEPTUAL_WEIGHT_G_SQUARED 0.587
#define PERCEPTUAL_WEIGHT_B_SQUARED 0.114
typedef unsigned char uint8;
// These functions take RGB888.
void compressBlockDiffFlipSlow(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2);
void compressBlockDiffFlipMedium(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2);
void compressBlockDiffFlipFast(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2);
void compressBlockDiffFlipSlowPerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2);
void compressBlockDiffFlipMediumPerceptual(uint8 *img,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2);
void compressBlockDiffFlipFastPerceptual(uint8 *img, uint8 *imgdec,int width,int height,int startx,int starty, unsigned int &compressed1, unsigned int &compressed2);
// This one takes RGBA8888 and converts to RGB first.
// Writes 64 bits of compressed data to output[0..7].
// Quality is 0 to 5. The odd numbers use perceptual metrics.
void CompressBlock(const uint8 *in, int in_width, uint8 *output, int quality);

File diff suppressed because it is too large Load Diff

View File

@ -1,212 +0,0 @@
// image.cxx
//
// NO WARRANTY
//
// BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, ERICSSON MAKES NO
// REPRESENTATIONS OF ANY KIND, EXTENDS NO WARRANTIES OF ANY KIND; EITHER
// EXPRESS OR IMPLIED; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
// PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
// THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON
// MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, LEASE, USE OR
// IMPORTATION WILL BE FREE FROM INFRINGEMENT OF PATENTS, COPYRIGHTS OR
// OTHER INTELLECTUAL PROPERTY RIGHTS OF OTHERS, AND IT SHALL BE THE SOLE
// RESPONSIBILITY OF THE LICENSEE TO MAKE SUCH DETERMINATION AS IS
// NECESSARY WITH RESPECT TO THE ACQUISITION OF LICENSES UNDER PATENTS
// AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES;
//
// IN NO EVENT WILL ERICSSON, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
// GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
// THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO
// LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
// YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
// OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGES.
//
// (C) Ericsson AB 2005. All Rights Reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "image.h"
// Removes comments in a .ppm file
// (i.e., lines starting with #)
//
// Written by Jacob Strom
//
void removeComments(FILE *f1)
{
int c;
while((c = getc(f1)) == '#')
{
char line[1024];
fgets(line, 1024, f1);
}
ungetc(c, f1);
}
// Removes white spaces in a .ppm file
//
// Written by Jacob Strom
//
void removeSpaces(FILE *f1)
{
int c;
c = getc(f1);
while(c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r')
{
c = getc(f1);
}
ungetc(c, f1);
}
// fReadPPM
//
// Written by Jacob Strom
//
// reads a ppm file with P6 header (meaning binary, as opposed to P5, which is ascII)
// and returns the image in pixels.
//
// The header must look like this:
//
// P6
// # Comments (not necessary)
// width height
// 255
//
// after that follows RGBRGBRGB...
//
bool fReadPPM(const char *filename, int &width, int &height, unsigned char *&pixels, bool reverse_y)
{
FILE *f1;
int mustbe255;
f1 = fopen(filename, "rb");
if(f1)
{
char line[255];
removeSpaces(f1);
removeComments(f1);
removeSpaces(f1);
fscanf(f1, "%s", line);
if(strcmp(line, "P6")!=0)
{
printf("Error: %s is not binary\n", filename);
printf("(Binary .ppm files start with P6).\n");
fclose(f1);
return false;
}
removeSpaces(f1);
removeComments(f1);
removeSpaces(f1);
fscanf(f1, "%d %d", &width, &height);
if( width<=0 || height <=0)
{
printf("Error: width or height negative. File: %s\n",filename);
fclose(f1);
return false;
}
removeSpaces(f1);
removeComments(f1);
removeSpaces(f1);
fscanf(f1, "%d", &mustbe255);
if( mustbe255!= 255 )
{
printf("Error: Color resolution must be 255. File: %s\n",filename);
fclose(f1);
return false;
}
// We need to remove the newline.
char c = 0;
while(c != '\n')
fscanf(f1, "%c", &c);
pixels = (unsigned char*) malloc(3*width*height);
if(!pixels)
{
printf("Error: Could not allocate memory for image. File: %s\n", filename);
fclose(f1);
return false;
}
if(reverse_y)
{
for(int yy = 0; yy<height; yy++)
{
if(fread(&pixels[(height-yy-1)*width*3], 3*width, 1, f1) != 1)
{
printf("Error: Could not read all pixels. File: %s\n", filename);
free(pixels);
fclose(f1);
return false;
}
}
}
else
{
if(fread(pixels, 3*width*height, 1, f1) != 1)
{
printf("Error: Could not read all pixels. File: %s\n", filename);
free(pixels);
fclose(f1);
return false;
}
}
// If we have reached this point, we have successfully loaded the image.
fclose(f1);
return true;
}
else
{
printf("Error: Coult not open file %s\n", filename);
return false;
}
}
// Write PPM --- Written by Jacob Strom
bool fWritePPM(const char *filename, int width, int height, unsigned char *pixels, bool reverse_y)
{
FILE *fsave;
fsave = fopen(filename, "wb");
if(fsave)
{
int q;
fprintf(fsave, "P6\n%d %d\n255\n", width, height);
for(q = 0; q< height; q++)
{
unsigned char *adr;
if(reverse_y)
adr = pixels+3*width*(height-1-q);
else
adr = pixels+3*width*q;
fwrite(adr, 3*width, 1, fsave);
}
fclose(fsave);
return true;
}
else
{
printf("Error: Could not open the file %s.\n",filename);
return(false);
}
}

View File

@ -1,33 +0,0 @@
// NO WARRANTY
//
// BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, ERICSSON MAKES NO
// REPRESENTATIONS OF ANY KIND, EXTENDS NO WARRANTIES OF ANY KIND; EITHER
// EXPRESS OR IMPLIED; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
// PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
// THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON
// MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, LEASE, USE OR
// IMPORTATION WILL BE FREE FROM INFRINGEMENT OF PATENTS, COPYRIGHTS OR
// OTHER INTELLECTUAL PROPERTY RIGHTS OF OTHERS, AND IT SHALL BE THE SOLE
// RESPONSIBILITY OF THE LICENSEE TO MAKE SUCH DETERMINATION AS IS
// NECESSARY WITH RESPECT TO THE ACQUISITION OF LICENSES UNDER PATENTS
// AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES;
//
// IN NO EVENT WILL ERICSSON, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
// GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
// THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO
// LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
// YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
// OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGES.
//
// (C) Ericsson AB 2005. All Rights Reserved.
//
#ifndef IMAGE_H
#define IMAGE_H
bool fReadPPM(const char *filename, int &width, int &height, unsigned char *&pixels,bool reverse_y);
bool fWritePPM(const char *filename, int width, int height, unsigned char *pixels,bool reverse_y);
#endif

View File

@ -1,69 +0,0 @@
SOFTWARE LICENSE AGREEMENT
PLEASE REVIEW THE FOLLOWING TERMS AND CONDITIONS PRIOR TO USING THE
ERICSSON TEXTURE COMPRESSION CODEC SOFTWARE (THE "SOFTWARE"). THE USE
OF THE SOFTWARE IS SUBJECT TO THE TERMS AND CONDITIONS OF THE
FOLLOWING LICENSE AGREEMENT (THE "LICENSE AGREEMENT"). IF YOU DO NOT
ACCEPT SUCH TERMS AND CONDITIONS YOU MAY NOT USE THE SOFTWARE.
Under the terms and conditions of the License Agreement, Licensee
hereby, receives a non-exclusive, non transferable, limited, free of
charge, perpetual and worldwide license, to copy, use, distribute and
modify the Software, but only for the purpose of developing,
manufacturing, selling, using and distributing products including the
Software, which products are used for (i) compression and/or
decompression to create content creation tools for usage with a
Khronos API, and/or (ii) compression and/or decompression for the
purpose of usage with a middleware API that is built on top of a
Khronos API, such as JCPs based on a Khronos API (in particular
"Mobile 3D Graphics API for J2ME" and its future versions and "Java
Bindings for OpenGL ES" and its future versions), and/or (iii)
compression and/or decompression to implement a Khronos API.
If Licensee institutes patent litigation against Ericsson or any
licensee of the Software for using the Software for making,
developing, manufacturing, selling, using and/or distributing products
within the scope of the Khronos framework, Ericsson shall have the
right to terminate this License Agreement with immediate
effect. However, should Licensee institute patent litigation against
any other licensee of the Software based on such licensee´s use of any
other software distributed together with the Software then Ericsson
shall have no right to terminate this License Agreement.
The License Agreement does not transfer to Licensee any ownership to
any Ericsson or third party intellectual property rights.
THE SOFTWARE IS PROVIDED "AS IS". ERICSSON MAKES NO REPRESENTATIONS OF
ANY KIND, EXTENDS NO WARRANTIES OF ANY KIND, EITHER EXPRESS OR
IMPLIED; INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH THE
LICENSEE. SHOULD THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE ASSUMES
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ERICSSON
MAKES NO WARRANTY THAT THE MANUFACTURE, SALE, DISTRIBUTION, LEASE, USE
OR IMPORTATION UNDER THE LICENSE AGREEMENT WILL BE FREE FROM
INFRINGEMENT OF PATENTS, COPYRIGHTS OR OTHER INTELLECTUAL PROPERTY
RIGHTS OF OTHERS, AND THE VALIDITY OF THE LICENSE AND THE LICENSE
AGREEMENT IS SUBJECT TO LICENSEE'S SOLE RESPONSIBILITY TO MAKE SUCH
DETERMINATION AND ACQUIRE SUCH LICENSES AS MAY BE NECESSARY WITH
RESPECT TO PATENTS AND OTHER INTELLECTUAL PROPERTY OF THIRD PARTIES.
IN NO EVENT WILL ERICSSON BE LIABLE TO THE LICENSEE FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT
NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
LOSSES SUSTAINED BY THE LICENSEE OR THIRD PARTIES OR A FAILURE OF THE
SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR
OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Licensee acknowledges that "ERICSSON ///" is the corporate trademark
of Telefonaktiebolaget LM Ericsson and that both "Ericsson" and the
figure "///" are important features of the trade names of
Telefonaktiebolaget LM Ericsson. Nothing contained in these terms and
conditions shall be deemed to grant Licensee any right, title or
interest in the word "Ericsson" or the figure "///".
The parties agree that this License Agreement based on these terms and
conditions is governed by the laws of Sweden, and in the event of any
dispute as a result of this License Agreement, the parties submit
themselves to the exclusive jurisdiction of the Swedish Courts.

View File

@ -1,49 +0,0 @@
ETCPACK v1.06
--------------------------------------------------------------------------
Changes in v1.06 against v1.05:
1. Updated this file so it has the correct version number.
--------------------------------------------------------------------------
Changes in v1.05 against v1.04:
1. Updated license agreement to include item (iii) inside
files. Removed old license text.
--------------------------------------------------------------------------
Changes in v1.04 against v1.03:
1. Updated license agreement to include item (iii).
--------------------------------------------------------------------------
Changes in v1.03 against v1.02:
1. Partinioned code in unpacking (etcdec.cxx) and the rest.
2. Also made changes so that PSNR values are calculated using double
internally.
--------------------------------------------------------------------------
Changes in v1.02 against v1.01:
Added possibility to flip images vertically. Default is to have the first
pixel (first three bytes in the .ppm file) ending up in s=0, t=0.
--------------------------------------------------------------------------
Changes in v1.01 against v1.00:
Four bugs fixed:
1. In method uncompressFile, after memory is allocated the newimg
pointer, the code checked whether the img pointer, not the newimg
pointer is NULL. This has been fixed.
2. In method compressFile the array srcimg is never
deleted/freed. This has been fixed.
3. When compressing smaller images than 4*4 (Mipmaps) with
fast/nonperceptual the application sometimes crashes. This has been
fixed.
4. Memory leak --- missing free(imgdec) in the end of
compressImageFile() inserted, and thus the bug has been fixed.
--------------------------------------------------------------------------

2442
ext/rg_etc1/rg_etc1.cpp Normal file

File diff suppressed because it is too large Load Diff

76
ext/rg_etc1/rg_etc1.h Normal file
View File

@ -0,0 +1,76 @@
// File: rg_etc1.h - Fast, high quality ETC1 block packer/unpacker - Rich Geldreich <richgel99@gmail.com>
// Please see ZLIB license at the end of this file.
#pragma once
namespace rg_etc1
{
// Unpacks an 8-byte ETC1 compressed block to a block of 4x4 32bpp RGBA pixels.
// Returns false if the block is invalid. Invalid blocks will still be unpacked with clamping.
// This function is thread safe, and does not dynamically allocate any memory.
// If preserve_alpha is true, the alpha channel of the destination pixels will not be overwritten. Otherwise, alpha will be set to 255.
bool unpack_etc1_block(const void *pETC1_block, unsigned int* pDst_pixels_rgba, int stride, bool preserve_alpha = false);
// Quality setting = the higher the quality, the slower.
// To pack large textures, it is highly recommended to call pack_etc1_block() in parallel, on different blocks, from multiple threads (particularly when using cHighQuality).
enum etc1_quality
{
cLowQuality,
cMediumQuality,
cHighQuality,
};
struct etc1_pack_params
{
etc1_quality m_quality;
bool m_dithering;
inline etc1_pack_params()
{
clear();
}
void clear()
{
m_quality = cHighQuality;
m_dithering = false;
}
};
// Important: pack_etc1_block_init() must be called before calling pack_etc1_block().
void pack_etc1_block_init();
// Packs a 4x4 block of 32bpp RGBA pixels to an 8-byte ETC1 block.
// 32-bit RGBA pixels must always be arranged as (R,G,B,A) (R first, A last) in memory, independent of platform endianness. A should always be 255.
// Returns squared error of result.
// This function is thread safe, and does not dynamically allocate any memory.
// pack_etc1_block() does not currently support "perceptual" colorspace metrics - it primarily optimizes for RGB RMSE.
unsigned int pack_etc1_block(void* pETC1_block, const unsigned int* pSrc_pixels_rgba, etc1_pack_params& pack_params);
} // namespace rg_etc1
//------------------------------------------------------------------------------
//
// rg_etc1 uses the ZLIB license:
// http://opensource.org/licenses/Zlib
//
// Copyright (c) 2012 Rich Geldreich
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
//------------------------------------------------------------------------------

View File

@ -4,7 +4,7 @@
#if !defined(USING_GLES2)
#include "image/png_load.h"
#include "ext/etcpack/etcdec.h"
#include "ext/rg_etc1/rg_etc1.h"
#endif
#include "image/zim_load.h"
@ -183,8 +183,8 @@ uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) {
memset(rgba, 0xFF, width * height * 4);
for (int y = 0; y < height; y += 4) {
for (int x = 0; x < width; x += 4) {
DecompressBlock(etc1 + ((y / 4) * width/4 + (x / 4)) * 8,
rgba + (y * width + x) * 4, width, 255);
rg_etc1::unpack_etc1_block(etc1 + ((y / 4) * width/4 + (x / 4)) * 8,
(uint32_t *)rgba + (y * width + x), width, false);
}
}
return rgba;

View File

@ -33,6 +33,10 @@ enum {
ZIM_DITHER = 64, // If set, dithers during save if color reduction is necessary.
ZIM_CLAMP = 128, // Texture should default to clamp instead of wrap.
ZIM_ZLIB_COMPRESSED = 256,
ZIM_ETC1_LOW = 512,
ZIM_ETC1_MEDIUM = 1024,
ZIM_ETC1_HIGH = 0, // default
ZIM_ETC1_DITHER = 2048,
};
// ZIM will only ever support up to 12 levels (4096x4096 max).

View File

@ -2,7 +2,7 @@
#include <string.h>
#include <math.h>
#include "base/logging.h"
#include "ext/etcpack/etcpack.h"
#include "ext/rg_etc1/rg_etc1.h"
#include "image/zim_save.h"
#include "zlib.h"
@ -101,6 +101,17 @@ void Convert(const uint8_t *image_data, int width, int height, int pitch, int fl
break;
}
case ZIM_ETC1: {
rg_etc1::pack_etc1_block_init();
rg_etc1::etc1_pack_params params;
params.m_dithering = false; //(flags & ZIM_ETC1_DITHER) != 0;
if (flags & ZIM_ETC1_LOW) {
params.m_quality = rg_etc1::cLowQuality;
} else if (flags & ZIM_ETC1_MEDIUM) {
params.m_quality = rg_etc1::cMediumQuality;
} else {
params.m_quality = rg_etc1::cHighQuality;
}
// Check for power of 2
if (!ispowerof2(width) || !ispowerof2(height)) {
FLOG("Image must have power of 2 dimensions, %ix%i just isn't that.", width, height);
@ -113,8 +124,11 @@ void Convert(const uint8_t *image_data, int width, int height, int pitch, int fl
#pragma omp parallel for
for (int y = 0; y < blockh; y++) {
for (int x = 0; x < blockw; x++) {
CompressBlock(image_data + ((y * 4) * (pitch/4) + x * 4) * 4, width,
(*data) + (blockw * y + x) * 8, 1);
uint32_t block[16];
for (int iy = 0; iy < 4; iy++) {
memcpy(block + 4 * iy, image_data + ((y * 4 + iy) * (pitch/4) + x * 4) * 4, 16);
}
rg_etc1::pack_etc1_block((*data) + (blockw * y + x) * 8, block, params);
}
}
width = blockw * 4;

View File

@ -201,8 +201,7 @@
<ClInclude Include="data\listable.h" />
<ClInclude Include="ext\cityhash\city.h" />
<ClInclude Include="ext\cityhash\citycrc.h" />
<ClInclude Include="ext\etcpack\etcdec.h" />
<ClInclude Include="ext\etcpack\etcpack.h" />
<ClInclude Include="ext\rg_etc1\rg_etc1.h" />
<ClInclude Include="ext\sha1\sha1.h" />
<ClInclude Include="ext\stb_image\stb_image.h" />
<ClInclude Include="ext\stb_vorbis\stb_vorbis.h" />
@ -294,8 +293,7 @@
<ClCompile Include="base\threadutil.cpp" />
<ClCompile Include="base\timeutil.cpp" />
<ClCompile Include="ext\cityhash\city.cpp" />
<ClCompile Include="ext\etcpack\etcdec.cpp" />
<ClCompile Include="ext\etcpack\etcpack.cpp" />
<ClCompile Include="ext\rg_etc1\rg_etc1.cpp" />
<ClCompile Include="ext\sha1\sha1.cpp" />
<ClCompile Include="ext\stb_image\stb_image.c" />
<ClCompile Include="ext\stb_vorbis\stb_vorbis.c" />

View File

@ -53,9 +53,6 @@
<ClInclude Include="gfx_es2\glsl_program.h">
<Filter>gfx</Filter>
</ClInclude>
<ClInclude Include="ext\etcpack\etcdec.h">
<Filter>ext</Filter>
</ClInclude>
<ClInclude Include="audio\wav_read.h">
<Filter>audio</Filter>
</ClInclude>
@ -98,9 +95,6 @@
<ClInclude Include="math\math_util.h">
<Filter>math</Filter>
</ClInclude>
<ClInclude Include="ext\etcpack\etcpack.h">
<Filter>ext</Filter>
</ClInclude>
<ClInclude Include="base\timeutil.h">
<Filter>base</Filter>
</ClInclude>
@ -242,6 +236,9 @@
<ClInclude Include="ext\cityhash\citycrc.h">
<Filter>ext</Filter>
</ClInclude>
<ClInclude Include="ext\rg_etc1\rg_etc1.h">
<Filter>ext</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="gfx\gl_debug_log.cpp">
@ -274,9 +271,6 @@
<ClCompile Include="gfx_es2\glsl_program.cpp">
<Filter>gfx</Filter>
</ClCompile>
<ClCompile Include="ext\etcpack\etcdec.cpp">
<Filter>ext</Filter>
</ClCompile>
<ClCompile Include="audio\wav_read.cpp">
<Filter>audio</Filter>
</ClCompile>
@ -301,9 +295,6 @@
<ClCompile Include="gfx\texture_atlas.cpp">
<Filter>gfx</Filter>
</ClCompile>
<ClCompile Include="ext\etcpack\etcpack.cpp">
<Filter>ext</Filter>
</ClCompile>
<ClCompile Include="base\timeutil.cpp">
<Filter>base</Filter>
</ClCompile>
@ -429,6 +420,9 @@
<ClCompile Include="ext\cityhash\city.cpp">
<Filter>ext</Filter>
</ClCompile>
<ClCompile Include="ext\rg_etc1\rg_etc1.cpp">
<Filter>ext</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="gfx">

View File

@ -70,6 +70,8 @@ int main(int argc, char **argv) {
break;
}
}
// TODO: make setting?
flags |= ZIM_ETC1_MEDIUM;
if ((flags & ZIM_FORMAT_MASK) == ZIM_ETC1) {
if (flags & ZIM_GEN_MIPS) {
fprintf(stderr, "WARNING: Cannot generate ETC1 mips at runtime\n");