Files
Webcam/include/modules/pict_io_jpeglib/pict_jpeglib_codec.cpp

153 lines
4.1 KiB
C++

/* -----------------------------------------------------------------------------
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 <void *> 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 <char> 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;
}
//------------------------------------------------------------------------------