/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ------------------------------------------------------------------------------*/ #include "pict_io_jpeglib/pict_jpeglib_codec.h" #include "picture/pict.h" #include "container/narray.h" using namespace GS; #if 1 extern "C" { int JpgLoad_ansic(void *buf, int len, char **output, unsigned int *width, unsigned int *height); int JpgSave_ansic(char *dst, int dst_len, int *size, int qual, char *buf, unsigned int w, unsigned int h); void JpgFree_ansic(char **p); }; //------------------------------------------------------------------------------ void FetchHCoef(char *bf, int w, int /*h*/, int x, int y, float *cf) { bf += y * w * 3; for ( int p = (x - 2); p < (x + 2); p++ ) { int op = p; if ( op < 0 ) op = 0; else if ( op >= w ) op = w - 1; *cf++ = (float)((unsigned char)bf[op * 3]); } } float Spline4Inter(float t, float *cf) { float v = cf[1]+0.5f*t*(cf[2]-cf[0]+t*(cf[2]+cf[1]*(-2.0f)+cf[0]+t*((cf[2]-cf[1])*9.0f+(cf[0]-cf[3])*3.f+t*((cf[1]-cf[2])*15.f+(cf[3]-cf[0])*5.f+t*((cf[2]-cf[1])*6.f+(cf[0]-cf[3])*2.f))))); if ( v < 0.f ) v = 0.f; else if ( v > 255.f ) v = 255.f; return v; } char *RgbResize(char *rgb, int ow, int oh, int w, int h) { char *nr = new char[w * h * 3], *pr; int x, y, c, v; float hc[4], vc[4]; float px, py, dx, dy; dx = (float)ow / (float)w; dy = (float)oh / (float)h; py = 0.f; pr = nr; for ( y = 0; y < h; y++ ) { px = 0.f; for ( x = 0; x < w; x++ ) { for ( c = 0; c < 3; c++ ) { float *pvc = vc; for ( v = -2; v < 2; v++ ) { int sy = v + (int)py; if ( sy < 0 ) sy = 0; if ( sy >= oh ) sy = oh - 1; FetchHCoef(rgb + c, ow, oh, (int)px, sy, hc); *pvc++ = Spline4Inter(px - ((int)px), hc); } *pr++ = (unsigned char)Spline4Inter(py - ((int)py), vc); } px += dx; } py += dy; } return nr; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void JpeglibCppInterfaceFree(char **p) { JpgFree_ansic(p); } int JpeglibCppInterfaceLoad(void *f, int l, char **o, unsigned int *w, unsigned int *h) { return JpgLoad_ansic(f, l, o, w, h); } int JpeglibCppInterfaceSave(char *dst, int dst_len, int *size, int q, char *b, unsigned int w, unsigned int h) { return JpgSave_ansic(dst, dst_len, size, q, b, w, h); } //------------------------------------------------------------------------------ #endif //------------------------------------------------------------------------------ bool PictureJpeglibCodec::Load(IO::Handle &handle, Picture &picture) { uchar header[2]; handle.Rewind(); if (handle.Read(header, 2) != 2) return false; if ((header[0] != 0xff) || (header[1] != 0xd8)) return false; // SOI marker found, good to go. size_t size = handle.GetSize(); Array buffer((uint)size); if (!buffer) return false; handle.Rewind(); handle.Read(buffer, size); uint width, height; char *c_data = NULL; if (JpeglibCppInterfaceLoad(buffer, (int)size, &c_data, &width, &height)) { // Transfer C data to a C++ allocation. picture.AllocAs(width, height); if (uchar *data = picture.GetData()) { uchar *j_data = (uchar *)c_data; for (uint h = 0; h < height; ++h) for (uint w = 0; w < width; ++w) { data[0] = j_data[2]; data[1] = j_data[1]; data[2] = j_data[0]; data[3] = j_data[3]; j_data += 4; data += 4; } } // Drop C data. JpeglibCppInterfaceFree(&c_data); } return asbool(picture.GetData()); } bool PictureJpeglibCodec::Save(IO::Handle &handle, const Picture &picture) { // FIXME this is stupid. Array dst(5000000); if (!dst) return false; int size = 0; if (!JpeglibCppInterfaceSave(&dst[0], (uint)dst.GetSize(), &size, 100, (char *)picture.GetData(), picture.GetWidth(), picture.GetHeight())) return false; return handle.Write(dst, size) == (size_t)size; } //------------------------------------------------------------------------------