png support

This commit is contained in:
aap 2020-07-23 15:06:03 +02:00
parent 4946235d49
commit 49ca300b88
10 changed files with 8566 additions and 46 deletions

View File

@ -10,11 +10,6 @@
#include "rwobjects.h"
#include "rwengine.h"
#ifdef _WIN32
/* srsly? */
#define strdup _strdup
#endif
#define PLUGIN_ID 0
namespace rw {

View File

@ -283,6 +283,7 @@ Engine::start(void)
// Register some image formats. Or should we leave that to the user?
Image::registerFileFormat("tga", readTGA, writeTGA);
Image::registerFileFormat("bmp", readBMP, writeBMP);
Image::registerFileFormat("png", readPNG, writePNG);
Engine::state = Started;
return 1;

6410
src/lodepng/lodepng.cpp Normal file

File diff suppressed because it is too large Load Diff

1945
src/lodepng/lodepng.h Normal file

File diff suppressed because it is too large Load Diff

149
src/png.cpp Normal file
View File

@ -0,0 +1,149 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "rwbase.h"
#include "rwerror.h"
#include "rwplg.h"
#include "rwpipeline.h"
#include "rwobjects.h"
#include "rwengine.h"
#include "lodepng/lodepng.h"
#ifdef _WIN32
/* srsly? */
#define strdup _strdup
#endif
#define PLUGIN_ID 0
namespace rw {
Image*
readPNG(const char *filename)
{
Image *image;
uint32 length;
uint8 *data = getFileContents(filename, &length);
assert(data != nil);
lodepng::State state;
std::vector<uint8> raw;
uint32 w, h;
// First try: decode without conversion to see if we understand the format
state.decoder.color_convert = 0;
uint32 error = lodepng::decode(raw, w, h, state, data, length);
if(error){
RWERROR((ERR_GENERAL, lodepng_error_text(error)));
return nil;
}
if(state.info_raw.bitdepth == 4 && state.info_raw.colortype == LCT_PALETTE){
image = Image::create(w, h, 4);
image->allocate();
memcpy(image->palette, state.info_raw.palette, state.info_raw.palettesize*4);
expandPal4_BE(image->pixels, image->stride, &raw[0], w/2, w, h);
}else if(state.info_raw.bitdepth == 8){
switch(state.info_raw.colortype){
case LCT_PALETTE:
image = Image::create(w, h, state.info_raw.palettesize <= 16 ? 4 : 8);
image->allocate();
memcpy(image->palette, state.info_raw.palette, state.info_raw.palettesize*4);
memcpy(image->pixels, &raw[0], w*h);
break;
case LCT_RGB:
image = Image::create(w, h, 24);
image->allocate();
memcpy(image->pixels, &raw[0], w*h*3);
break;
default:
// Second try: just load as 32 bit
lodepng_state_init(&state);
error = lodepng::decode(raw, w, h, state, data, length);
if(error){
RWERROR((ERR_GENERAL, lodepng_error_text(error)));
return nil;
}
// fall through
case LCT_RGBA:
image = Image::create(w, h, 32);
image->allocate();
memcpy(image->pixels, &raw[0], w*h*4);
break;
}
}
return image;
}
void
writePNG(Image *image, const char *filename)
{
int32 i;
StreamFile file;
if(!file.open(filename, "wb")){
RWERROR((ERR_FILE, filename));
return;
}
std::vector<uint8> raw;
uint8 *pixels;
lodepng::State state;
pixels = image->pixels;
switch(image->depth){
case 4:
state.info_raw.bitdepth = 4;
state.info_raw.colortype = LCT_PALETTE;
state.info_png.color.bitdepth = 4;
state.info_png.color.colortype = LCT_PALETTE;
state.encoder.auto_convert = 0;
for(i = 0; i < (1<<image->depth); i++){
uint8 *col = &image->palette[i*4];
lodepng_palette_add(&state.info_png.color, col[0], col[1], col[2], col[3]);
lodepng_palette_add(&state.info_raw, col[0], col[1], col[2], col[3]);
}
pixels = rwNewT(uint8, image->width/2*image->height, ID_IMAGE | MEMDUR_FUNCTION);
compressPal4_BE(pixels, image->width/2, image->pixels, image->width, image->width, image->height);
break;
case 8:
state.info_raw.colortype = LCT_PALETTE;
state.info_png.color.colortype = LCT_PALETTE;
state.encoder.auto_convert = 0;
for(i = 0; i < (1<<image->depth); i++){
uint8 *col = &image->palette[i*4];
lodepng_palette_add(&state.info_png.color, col[0], col[1], col[2], col[3]);
lodepng_palette_add(&state.info_raw, col[0], col[1], col[2], col[3]);
}
break;
case 16:
// Don't think we can have 16 bits with PNG
// TODO: don't change original image
image->convertTo32();
break;
case 24:
state.info_raw.colortype = LCT_RGB;
state.info_png.color.colortype = LCT_RGB;
state.encoder.auto_convert = 0;
break;
case 32:
// already done
break;
}
uint32 error = lodepng::encode(raw, pixels, image->width, image->height, state);
if(error){
RWERROR((ERR_GENERAL, lodepng_error_text(error)));
return;
}
if(pixels != image->pixels)
rwFree(pixels);
file.write8(&raw[0], raw.size());
file.close();
}
}

View File

@ -1565,34 +1565,6 @@ rasterUnlockPalette(Raster *raster)
raster->privateFlags &= ~(PS2LOCK_READ_PALETTE|PS2LOCK_WRITE_PALETTE);
}
void
expandPSMT4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w/2; x++){
dst[y*dststride + x*2 + 0] = src[y*srcstride + x] & 0xF;
dst[y*dststride + x*2 + 1] = src[y*srcstride + x] >> 4;
}
}
void
compressPSMT4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w/2; x++)
dst[y*dststride + x] = src[y*srcstride + x*2 + 0] | src[y*srcstride + x*2 + 1] << 4;
}
void
copyPSMT8(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w; x++)
dst[y*dststride + x] = src[y*srcstride + x];
}
// Almost the same as d3d9 and gl3 function
bool32
imageFindRasterFormat(Image *img, int32 type,
@ -1694,9 +1666,9 @@ rasterFromImage(Raster *raster, Image *image)
uint8 *src = image->pixels;
out = raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
if(image->depth == 4){
compressPSMT4(out, tw/2, src, image->stride, image->width, image->height);
compressPal4(out, tw/2, src, image->stride, image->width, image->height);
}else if(image->depth == 8){
copyPSMT8(out, tw, src, image->stride, image->width, image->height);
copyPal8(out, tw, src, image->stride, image->width, image->height);
}else{
for(int32 y = 0; y < image->height; y++){
in = src;
@ -1795,9 +1767,9 @@ rasterToImage(Raster *raster)
uint8 *dst = image->pixels;
in = raster->lock(0, Raster::LOCKREAD);
if(depth == 4){
expandPSMT4(dst, image->stride, in, tw/2, raster->width, raster->height);
expandPal4(dst, image->stride, in, tw/2, raster->width, raster->height);
}else if(depth == 8){
copyPSMT8(dst, image->stride, in, tw, raster->width, raster->height);
copyPal8(dst, image->stride, in, tw, raster->width, raster->height);
}else{
for(int32 y = 0; y < image->height; y++){
out = dst;

View File

@ -223,9 +223,5 @@ Texture *readNativeTexture(Stream *stream);
void writeNativeTexture(Texture *tex, Stream *stream);
uint32 getSizeNativeTexture(Texture *tex);
void expandPSMT4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
void compressPSMT4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
void copyPSMT8(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
}
}

View File

@ -283,4 +283,52 @@ conv_ABGR1555_from_ARGB1555(uint8 *out, uint8 *in)
out[0] = in[0]&0xE0 | r;
}
void
expandPal4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w/2; x++){
dst[y*dststride + x*2 + 0] = src[y*srcstride + x] & 0xF;
dst[y*dststride + x*2 + 1] = src[y*srcstride + x] >> 4;
}
}
void
compressPal4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w/2; x++)
dst[y*dststride + x] = src[y*srcstride + x*2 + 0] | src[y*srcstride + x*2 + 1] << 4;
}
void
expandPal4_BE(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w/2; x++){
dst[y*dststride + x*2 + 1] = src[y*srcstride + x] & 0xF;
dst[y*dststride + x*2 + 0] = src[y*srcstride + x] >> 4;
}
}
void
compressPal4_BE(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w/2; x++)
dst[y*dststride + x] = src[y*srcstride + x*2 + 1] | src[y*srcstride + x*2 + 0] << 4;
}
void
copyPal8(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h)
{
int32 x, y;
for(y = 0; y < h; y++)
for(x = 0; x < w; x++)
dst[y*dststride + x] = src[y*srcstride + x];
}
}

View File

@ -170,6 +170,8 @@ Image *readTGA(const char *filename);
void writeTGA(Image *image, const char *filename);
Image *readBMP(const char *filename);
void writeBMP(Image *image, const char *filename);
Image *readPNG(const char *filename);
void writePNG(Image *image, const char *filename);
enum { QUANTDEPTH = 8 };
@ -310,6 +312,13 @@ void conv_RGBA8888_from_ARGB1555(uint8 *out, uint8 *in);
void conv_ABGR1555_from_ARGB1555(uint8 *out, uint8 *in);
inline void conv_ARGB1555_from_ABGR1555(uint8 *out, uint8 *in) { conv_ABGR1555_from_ARGB1555(out, in); }
void expandPal4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
void compressPal4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
void expandPal4_BE(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
void compressPal4_BE(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
void copyPal8(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
#define IGNORERASTERIMP 0

View File

@ -10,11 +10,6 @@
#include "rwobjects.h"
#include "rwengine.h"
#ifdef _WIN32
/* srsly? */
#define strdup _strdup
#endif
#define PLUGIN_ID 0
namespace rw {