mirror of https://github.com/aap/librw.git
png support
This commit is contained in:
parent
4946235d49
commit
49ca300b88
|
@ -10,11 +10,6 @@
|
|||
#include "rwobjects.h"
|
||||
#include "rwengine.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
/* srsly? */
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
#define PLUGIN_ID 0
|
||||
|
||||
namespace rw {
|
||||
|
|
|
@ -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;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -10,11 +10,6 @@
|
|||
#include "rwobjects.h"
|
||||
#include "rwengine.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
/* srsly? */
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
#define PLUGIN_ID 0
|
||||
|
||||
namespace rw {
|
||||
|
|
Loading…
Reference in New Issue