[code]
/**
* @file JpeglibExtension.h
* @author cheol-dong choi <aucd29@gmail.com>
* @version 1.0
* @date April 9, 2009 13:26:31
* @section LICENSE
*
* Copyright (c) 2003-2010, cheol-dong choi, (http://www.sarangnamu.net)
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* @section DESCRIPTION
*
*
* @section CHANGE_LOG
*
*/
#ifndef __CD_JPEGLIBEXTENSION_H__
#define __CD_JPEGLIBEXTENSION_H__
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <stdio.h>
#include <string>
/* The maximum number of palette entries in palette-based images.
In the wonderful new world of gd 2.0, you can of course have
many more colors when using truecolor mode. */
#define gdMaxColors 256
extern "C"
{
#include "jpeglib.h"
}
#define MAXSIZE 2048 /* Maximum size of thumbnail */
#define MINSIZE 1 /* Minimum size of thumbnail */
#define DEFAULTSIZE 128 /* Default size of thumbnail */
#define GRAY 128
#define RSZ_AUTO 0
#define RSZ_WIDTH 1
#define RSZ_HEIGHT 2
#define RSZ_FIX 3
#ifndef byte
typedef unsigned char byte;
#endif
struct my_error_mgr
{
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;
static void my_error_exit(j_common_ptr cinfo)
{
my_error_ptr myerr = (my_error_ptr) cinfo->err;
char buf[JMSG_LENGTH_MAX];
(*cinfo->err->format_message)(cinfo,buf);
longjmp(myerr->setjmp_buffer, 1);
}
class CJpeglibExtension
{
public:
CJpeglibExtension(void);
~CJpeglibExtension(void);
public:
bool Read(const char* filename);
bool Read(const char* szPath, const char* szName);
bool Resize(int maxsize=DEFAULTSIZE, int which_dim=RSZ_AUTO);
bool Matrix(int nCount=3);
bool Write(const char *filename, int quality, bool bMatrix=false);
void FreeMemory(bool bMatrix=false);
byte* GetPalette() { return _palette; }
byte* GetReadImage() { return _readImage; }
int GetWidth() { return _width; }
int GetHeight() { return _height; }
bool IsDivide(int nDivCount, int& nX, int& nY);
protected:
byte* _readImage;
byte* _outimage; /* The current thumbnail image */
byte* _palette; /* Global palette pointer */
int _width; /* Original image width */
int _height; /* Original image height */
int _background; /* Index's background color */
int _dwEffWidth;
int _wBpp;
int _biClrUsed;
long _out_wide; /* Width of thumbnail image */
long _out_high; /* Height of thumbnail image */
std::string _szFileName;
};
#endif
[/code]
[code]
/**
* @file JpeglibExtension.cpp
* @author cheol-dong choi <aucd29@gmail.com>
* @version 1.0
* @date April 9, 2009 13:26:27
* @section LICENSE
*
* Copyright (c) 2003-2010, cheol-dong choi, (http://www.sarangnamu.net)
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* @section DESCRIPTION
*
*
* @section CHANGE_LOG
*
*/
#include "JpeglibExtension.h"
#include "RSLOGGER.H"
#if defined(_WIN32_WCE)
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
CJpeglibExtension::CJpeglibExtension(void)
{
_outimage = NULL;
_readImage = NULL;
_palette = NULL;
_width = 0; /* Original image width */
_height = 0; /* Original image height */
_background = 0; /* Index's background color */
_out_wide = 0; /* Width of thumbnail image */
_out_high = 0; /* Height of thumbnail image */
_szFileName = "";
}
CJpeglibExtension::~CJpeglibExtension(void)
{
FreeMemory();
}
// -----------------------------------------------------------
bool CJpeglibExtension::Read(const char* filename)
{
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
int f;
int row_stride;
FILE* infile;
byte* ptr;
FreeMemory();
_szFileName = filename;
#if !defined(ANDROID)
try
{
#endif
_palette = (byte*)calloc(1, 1768);
if (_palette == NULL)
{
#if !defined(ANDROID)
throw "Out of memory!!";
#else
ASSERT(0);
#endif
}
infile = fopen(filename,"rb");
if (infile == NULL)
{
#if !defined(ANDROID)
throw "File not found!!";
#else
ASSERT(0);
#endif
}
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
if (setjmp(jerr.setjmp_buffer))
{
jpeg_destroy_decompress(&cinfo);
fclose(infile);
delete[] _palette;
#if !defined(ANDROID)
throw "setjmp";
#else
ASSERT(0);
#endif
}
/* Now we can initialize the JPEG decompression object. */
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo,infile);
jpeg_read_header(&cinfo,TRUE);
/* setup parameters for decompression */
cinfo.dct_method = JDCT_ISLOW;
cinfo.quantize_colors = TRUE;
cinfo.desired_number_of_colors = 256;
cinfo.two_pass_quantize = TRUE;
/* Fix to greys if greyscale. (required to read greyscale JPEGs) */
if (cinfo.jpeg_color_space == JCS_GRAYSCALE)
{
cinfo.out_color_space = JCS_GRAYSCALE;
cinfo.desired_number_of_colors = 256;
cinfo.quantize_colors = FALSE;
cinfo.two_pass_quantize = FALSE;
for(f=0; f<256; f++)
{
_palette[f] = _palette[256 + f] = _palette[512 + f] = f;
}
}
_width = cinfo.image_width;
_height = cinfo.image_height;
_readImage = (byte*)calloc(1, _width * _height);
if (_readImage == NULL)
{
longjmp(jerr.setjmp_buffer,1);
#if !defined(ANDROID)
throw "Out of memory!!";
#else
ASSERT(0);
#endif
}
jpeg_start_decompress(&cinfo);
int wBpp = (cinfo.output_components * 8);
// Make sure bits per pixel is valid
if (wBpp <= 1)
{
_wBpp = 1;
_biClrUsed = 2;
}
else if (wBpp <= 4)
{
_wBpp = 4;
_biClrUsed = 16;
}
else if (wBpp <= 8)
{
_wBpp = 8;
_biClrUsed = 256;
}
else
{
_wBpp = 24;
_biClrUsed = 0;
}
// set the common image informations
_dwEffWidth = ((((_wBpp * _width) + 31) / 32) * 4);
/* read the palette (if greyscale, this has already been done) */
if (cinfo.jpeg_color_space != JCS_GRAYSCALE)
{
for (f=0; f<cinfo.actual_number_of_colors; f++)
{
_palette[ f] = cinfo.colormap[0][f];
_palette[256+f] = cinfo.colormap[1][f];
_palette[512+f] = cinfo.colormap[2][f];
}
}
if (cinfo.out_color_space == JCS_GRAYSCALE)
{
_biClrUsed = 256;
}
else
{
if (cinfo.quantize_colors)
{
_biClrUsed = cinfo.actual_number_of_colors;
}
else
{
_biClrUsed = 0;
}
}
ptr = _readImage;
row_stride = _width;
/* read the image */
while (cinfo.output_scanline < (unsigned int)_height)
{
jpeg_read_scanlines(&cinfo, &ptr, 1);
ptr += row_stride;
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
#if !defined(ANDROID)
}
catch (const char* e)
{
printf("Error!! %s\n", e);
return false;
}
#endif
return true;
}
//
// Read
//
bool CJpeglibExtension::Read(const char* szPath, const char* szName)
{
LOG1("JpeglibExtension::Read\n");
//
// Method description
// -------
//
//
if (szPath == NULL || szName == NULL)
{
LOG3("ERROR::CJpeglibExtension::Read <szPath == NULL || szName == NULL>\n");
return false;
}
std::string szFullPath;
size_t i;
szFullPath = szPath;
i = strlen(szPath);
if (szPath[i - 1] != '/' && szPath[i - 1] != '\\')
{
szFullPath += "/";
}
szFullPath += szName;
return Read(szFullPath.c_str());
}
bool CJpeglibExtension::Write(const char *filename, int quality, bool bMatrix/*=true*/)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *out;
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
#if !defined(ANDROID)
try
{
#endif
/* Step 1: Allocate and initialize JPEG compression object. */
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
/* Step 2: Specify data destination. */
if (filename == NULL)
{
#if !defined(ANDROID)
throw "Invalid filename";
#else
ASSERT(0);
#endif
}
if (filename)
{
out = fopen(filename, "wb");
if (out == NULL)
{
#if !defined(ANDROID)
throw "can not open files";
#else
ASSERT(0);
#endif
}
}
jpeg_stdio_dest(&cinfo,out);
/* Step 3: set parameters for compression */
cinfo.image_width = _out_wide; /* image width and height, in pix */
cinfo.image_height = _out_high;
cinfo.input_components = 3; /* # of color components per pix */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo,quality,FALSE);
/* Step 4: Start compressor */
jpeg_start_compress(&cinfo,TRUE);
/* Step 5: while (scan lines remain to be written) */
row_stride = _out_wide * 3; /* JSAMPLEs per row in image_buffer */
while (cinfo.next_scanline < cinfo.image_height)
{
row_pointer[0] = &_outimage[cinfo.next_scanline*row_stride];
jpeg_write_scanlines(&cinfo,row_pointer,1);
}
/* Step 6: Finish compression */
jpeg_finish_compress(&cinfo);
fclose(out);
/* Step 7: release JPEG compression object */
jpeg_destroy_compress(&cinfo);
#if !defined(ANDROID)
}
catch (const char* e)
{
printf("Error!! %s\n", e);
return false;
}
#endif
FreeMemory(bMatrix);
return true;
}
bool CJpeglibExtension::Resize(int maxsize, int resize_dim)
{
register int a, b, x, yp, yw;
long y, sw, sh, lastyp;
int c, pixwide, pixhigh;
int tmp, tr, tg, tb, tn;
int xypos;
#if !defined(ANDROID)
try
{
#endif
if (_readImage == NULL)
{
#if !defined(ANDROID)
throw "Please read file!!";
#else
ASSERT(0);
#endif
return false;
}
byte* palr = GetPalette();
byte* palg = GetPalette() + 256;
byte* palb = GetPalette() + 512;
/* The resize dimension wasn't provided... */
if (!resize_dim)
{
if (_width <= _height)
{
/* Picture is square or portraity */
resize_dim = RSZ_HEIGHT;
}
else
{
/* Picture is landscapey */
resize_dim = RSZ_WIDTH;
}
}
switch(resize_dim)
{
case RSZ_FIX:
sh = sw = maxsize;
break;
case RSZ_HEIGHT:
sh = maxsize;
sw = (int)( (maxsize * ((double)_width)) / ((double)_height) );
break;
case RSZ_WIDTH:
sw = maxsize;
sh = (int)( (maxsize * ((double)_height)) / ((double)_width) );
break;
default:
/* WE SHOULD NEVER GET HERE! */
sw = sh = 0;
break;
}
/* This is a kludge. */
if (sw == 0) sw += 1;
if (sh == 0) sh += 1;
_out_wide = sw;
_out_high = sh;
/* Reserve the amount of memory we will need. */
_outimage = (byte*)calloc(1, (sw * sh * 3));
if (_outimage == NULL)
{
#if !defined(ANDROID)
throw "Out of memory!!";
#else
ASSERT(0);
#endif
}
for (x=0; x<(sw * sh * 3); x++)
{
_outimage[x] = GRAY;
}
/* It has been reduced. */
if (_width > sw)
{
lastyp = -1;
pixhigh = (int)( ((float)_height) / ((float)sh) + 0.5 );
pixwide = (int)( ((float)_width) / ((float)sw) + 0.5 );
pixhigh++;
pixwide++;
for(y=0; y < _height; y++)
{
yp = (y * sh) / _height;
if (yp != lastyp)
{
yw = (y * _width);
/* we try to resample a bit. get that pentium RSN :) */
for (x=0; x < _width; x++,yw++)
{
tr = 0;
tg = 0;
tb = 0;
tn = 0;
for (b=0; (b < pixhigh) && (y+b < _height); b++)
{
for (a=0; (a < pixwide) && (x + a < _width); a++)
{
tmp = *(_readImage + yw + a + b * _width);
tr += palr[tmp];
tg += palg[tmp];
tb += palb[tmp];
tn++;
}
}
xypos = 3 * (((x * sw) / _width) + yp * sw);
tr /= tn;
tg /= tn;
tb /= tn;
_outimage[xypos] = tr;
_outimage[xypos+1] = tg;
_outimage[xypos+2] = tb;
}
lastyp = yp;
}
}
}
else
{
/* we just leave it the same size */
_out_wide = _width;
_out_high = _height;
for (y=0; y < _height; y++)
{
for (x=0; x < _width; x++)
{
c = _readImage[y * _width + x];
_outimage[3 * (y * _width + x)] = palr[c];
_outimage[3 * (y * _width + x) + 1] = palg[c];
_outimage[3 * (y * _width + x) + 2] = palb[c];
}
}
}
#if !defined(ANDROID)
}
catch (const char* e)
{
printf("Error!! %s\n", e);
return false;
}
#endif
return true;
}
//
// Matrix
//
bool CJpeglibExtension::Matrix(int nCount/*=3*/)
{
if (!_width || !_height)
return false;
std::string szExtension;
//
// Find extension
//
szExtension = strrchr(_szFileName.c_str(), '.');
//
// Checking extension
//
if (szExtension != ".jpg" && szExtension != ".jpeg")
return false;
int nWidth, nHeight;
if (!IsDivide(nCount, nWidth, nHeight))
{
ASSERT(0);
}
nWidth = static_cast<int>(_width / nCount);
nHeight = static_cast<int>(_height / nCount);
printf("resize Information Width: %d, height: %d\n", nWidth, nHeight);
register int x;
long y;
int c;
#if !defined(ANDROID)
try
{
#endif
if (_readImage == NULL)
#if !defined(ANDROID)
throw "Please read file!!";
#else
ASSERT(0);
#endif
byte* palr = GetPalette();
byte* palg = GetPalette() + 256;
byte* palb = GetPalette() + 512;
if (_outimage)
free(_outimage);
_out_wide = nWidth;
_out_high = nHeight;
_outimage = (byte*)calloc(1, (nWidth * nHeight * 3));
if (_outimage == NULL)
#if !defined(ANDROID)
throw "Out of memory!!";
#else
ASSERT(0);
#endif
int nImageCount = 1;
int nXPos = 0, nYPos = 0, nPos = 0;
//
// Matrix 형태로 이미지를 자르기 위해서 몇등분을 할지 입력값을 받은 다음
// 해당 개수 만큼 가로/세로 로 자르게 된다.
//
for (int h=1; h<=nCount; ++h)
{
for (int w=1; w<=nCount; ++w)
{
//
// Initialize Memory
//
for (x=0; x<(nWidth * nHeight * 3); x++)
{
_outimage[x] = GRAY;
}
printf("Image Filling Area(xPos:%d, yPos:%d)\n", nXPos, nYPos);
//
// Fill Memory
//
for (y=nYPos; y < (nHeight * h); ++y)
{
for (x=nXPos; x < (nWidth * w); ++x)
{
c = _readImage[y * _width + x];
nPos = (y - nYPos) * nWidth + (x - nXPos);
_outimage[3 * nPos] = palr[c];
_outimage[3 * nPos + 1] = palg[c];
_outimage[3 * nPos + 2] = palb[c];
}
}
std::string szFileName;
char szNumber[8] = {0};
//
// Name setting
//
sprintf(szNumber, "%03d", nImageCount);
szFileName = _szFileName.substr(0, _szFileName.size() - szExtension.size());
szFileName += "_split";
szFileName += szNumber;
szFileName += szExtension;
++nImageCount;
//
// Write Jpeg file
//
Write(szFileName.c_str(), 70, true);
nXPos += nWidth;
}
nXPos = 0;
nYPos += nHeight;
}
FreeMemory();
#if !defined(ANDROID)
}
catch (const char* e)
{
printf("ERROR : %s\n", e);
return false;
}
#endif
return true;
}
void CJpeglibExtension::FreeMemory(bool bMatrix/*=false*/)
{
if (bMatrix)
return ;
if (_outimage != NULL)
{
free(_outimage);
}
if (_readImage != NULL)
{
free(_readImage);
}
if (_palette != NULL)
{
free(_palette);
}
_outimage = NULL;
_readImage = NULL;
_palette = NULL;
}
//
// IsDivide
//
bool CJpeglibExtension::IsDivide(int nDivCount, int& nX, int& nY)
{
//LOG1("JpeglibExtension::IsDivide\n");
if (_width == 0 || _height == 0)
return false;
nX = _width % nDivCount;
nY = _height % nDivCount;
printf("Image Information Width: %d, Height: %d\n", _width, _height);
printf("Image Divide Value : w:%d, h:%d\n", nX, nY);
bool bRes = true;
if (nX != 0)
{
nX = (int(_width / nDivCount) + 1) * nDivCount;
printf("Image New Size Value : w:%d\n", nX);
bRes = false;
}
if (nY != 0)
{
nY = (int(_height / nDivCount) + 1) * nDivCount;
printf("Image New Size Value : h:%d\n", nY);
bRes = false;
}
return bRes;
}
[/code]
/**
* @file JpeglibExtension.h
* @author cheol-dong choi <aucd29@gmail.com>
* @version 1.0
* @date April 9, 2009 13:26:31
* @section LICENSE
*
* Copyright (c) 2003-2010, cheol-dong choi, (http://www.sarangnamu.net)
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* @section DESCRIPTION
*
*
* @section CHANGE_LOG
*
*/
#ifndef __CD_JPEGLIBEXTENSION_H__
#define __CD_JPEGLIBEXTENSION_H__
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <stdio.h>
#include <string>
/* The maximum number of palette entries in palette-based images.
In the wonderful new world of gd 2.0, you can of course have
many more colors when using truecolor mode. */
#define gdMaxColors 256
extern "C"
{
#include "jpeglib.h"
}
#define MAXSIZE 2048 /* Maximum size of thumbnail */
#define MINSIZE 1 /* Minimum size of thumbnail */
#define DEFAULTSIZE 128 /* Default size of thumbnail */
#define GRAY 128
#define RSZ_AUTO 0
#define RSZ_WIDTH 1
#define RSZ_HEIGHT 2
#define RSZ_FIX 3
#ifndef byte
typedef unsigned char byte;
#endif
struct my_error_mgr
{
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;
static void my_error_exit(j_common_ptr cinfo)
{
my_error_ptr myerr = (my_error_ptr) cinfo->err;
char buf[JMSG_LENGTH_MAX];
(*cinfo->err->format_message)(cinfo,buf);
longjmp(myerr->setjmp_buffer, 1);
}
class CJpeglibExtension
{
public:
CJpeglibExtension(void);
~CJpeglibExtension(void);
public:
bool Read(const char* filename);
bool Read(const char* szPath, const char* szName);
bool Resize(int maxsize=DEFAULTSIZE, int which_dim=RSZ_AUTO);
bool Matrix(int nCount=3);
bool Write(const char *filename, int quality, bool bMatrix=false);
void FreeMemory(bool bMatrix=false);
byte* GetPalette() { return _palette; }
byte* GetReadImage() { return _readImage; }
int GetWidth() { return _width; }
int GetHeight() { return _height; }
bool IsDivide(int nDivCount, int& nX, int& nY);
protected:
byte* _readImage;
byte* _outimage; /* The current thumbnail image */
byte* _palette; /* Global palette pointer */
int _width; /* Original image width */
int _height; /* Original image height */
int _background; /* Index's background color */
int _dwEffWidth;
int _wBpp;
int _biClrUsed;
long _out_wide; /* Width of thumbnail image */
long _out_high; /* Height of thumbnail image */
std::string _szFileName;
};
#endif
[/code]
[code]
/**
* @file JpeglibExtension.cpp
* @author cheol-dong choi <aucd29@gmail.com>
* @version 1.0
* @date April 9, 2009 13:26:27
* @section LICENSE
*
* Copyright (c) 2003-2010, cheol-dong choi, (http://www.sarangnamu.net)
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* @section DESCRIPTION
*
*
* @section CHANGE_LOG
*
*/
#include "JpeglibExtension.h"
#include "RSLOGGER.H"
#if defined(_WIN32_WCE)
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
CJpeglibExtension::CJpeglibExtension(void)
{
_outimage = NULL;
_readImage = NULL;
_palette = NULL;
_width = 0; /* Original image width */
_height = 0; /* Original image height */
_background = 0; /* Index's background color */
_out_wide = 0; /* Width of thumbnail image */
_out_high = 0; /* Height of thumbnail image */
_szFileName = "";
}
CJpeglibExtension::~CJpeglibExtension(void)
{
FreeMemory();
}
// -----------------------------------------------------------
bool CJpeglibExtension::Read(const char* filename)
{
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
int f;
int row_stride;
FILE* infile;
byte* ptr;
FreeMemory();
_szFileName = filename;
#if !defined(ANDROID)
try
{
#endif
_palette = (byte*)calloc(1, 1768);
if (_palette == NULL)
{
#if !defined(ANDROID)
throw "Out of memory!!";
#else
ASSERT(0);
#endif
}
infile = fopen(filename,"rb");
if (infile == NULL)
{
#if !defined(ANDROID)
throw "File not found!!";
#else
ASSERT(0);
#endif
}
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
if (setjmp(jerr.setjmp_buffer))
{
jpeg_destroy_decompress(&cinfo);
fclose(infile);
delete[] _palette;
#if !defined(ANDROID)
throw "setjmp";
#else
ASSERT(0);
#endif
}
/* Now we can initialize the JPEG decompression object. */
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo,infile);
jpeg_read_header(&cinfo,TRUE);
/* setup parameters for decompression */
cinfo.dct_method = JDCT_ISLOW;
cinfo.quantize_colors = TRUE;
cinfo.desired_number_of_colors = 256;
cinfo.two_pass_quantize = TRUE;
/* Fix to greys if greyscale. (required to read greyscale JPEGs) */
if (cinfo.jpeg_color_space == JCS_GRAYSCALE)
{
cinfo.out_color_space = JCS_GRAYSCALE;
cinfo.desired_number_of_colors = 256;
cinfo.quantize_colors = FALSE;
cinfo.two_pass_quantize = FALSE;
for(f=0; f<256; f++)
{
_palette[f] = _palette[256 + f] = _palette[512 + f] = f;
}
}
_width = cinfo.image_width;
_height = cinfo.image_height;
_readImage = (byte*)calloc(1, _width * _height);
if (_readImage == NULL)
{
longjmp(jerr.setjmp_buffer,1);
#if !defined(ANDROID)
throw "Out of memory!!";
#else
ASSERT(0);
#endif
}
jpeg_start_decompress(&cinfo);
int wBpp = (cinfo.output_components * 8);
// Make sure bits per pixel is valid
if (wBpp <= 1)
{
_wBpp = 1;
_biClrUsed = 2;
}
else if (wBpp <= 4)
{
_wBpp = 4;
_biClrUsed = 16;
}
else if (wBpp <= 8)
{
_wBpp = 8;
_biClrUsed = 256;
}
else
{
_wBpp = 24;
_biClrUsed = 0;
}
// set the common image informations
_dwEffWidth = ((((_wBpp * _width) + 31) / 32) * 4);
/* read the palette (if greyscale, this has already been done) */
if (cinfo.jpeg_color_space != JCS_GRAYSCALE)
{
for (f=0; f<cinfo.actual_number_of_colors; f++)
{
_palette[ f] = cinfo.colormap[0][f];
_palette[256+f] = cinfo.colormap[1][f];
_palette[512+f] = cinfo.colormap[2][f];
}
}
if (cinfo.out_color_space == JCS_GRAYSCALE)
{
_biClrUsed = 256;
}
else
{
if (cinfo.quantize_colors)
{
_biClrUsed = cinfo.actual_number_of_colors;
}
else
{
_biClrUsed = 0;
}
}
ptr = _readImage;
row_stride = _width;
/* read the image */
while (cinfo.output_scanline < (unsigned int)_height)
{
jpeg_read_scanlines(&cinfo, &ptr, 1);
ptr += row_stride;
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
#if !defined(ANDROID)
}
catch (const char* e)
{
printf("Error!! %s\n", e);
return false;
}
#endif
return true;
}
//
// Read
//
bool CJpeglibExtension::Read(const char* szPath, const char* szName)
{
LOG1("JpeglibExtension::Read\n");
//
// Method description
// -------
//
//
if (szPath == NULL || szName == NULL)
{
LOG3("ERROR::CJpeglibExtension::Read <szPath == NULL || szName == NULL>\n");
return false;
}
std::string szFullPath;
size_t i;
szFullPath = szPath;
i = strlen(szPath);
if (szPath[i - 1] != '/' && szPath[i - 1] != '\\')
{
szFullPath += "/";
}
szFullPath += szName;
return Read(szFullPath.c_str());
}
bool CJpeglibExtension::Write(const char *filename, int quality, bool bMatrix/*=true*/)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *out;
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
#if !defined(ANDROID)
try
{
#endif
/* Step 1: Allocate and initialize JPEG compression object. */
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
/* Step 2: Specify data destination. */
if (filename == NULL)
{
#if !defined(ANDROID)
throw "Invalid filename";
#else
ASSERT(0);
#endif
}
if (filename)
{
out = fopen(filename, "wb");
if (out == NULL)
{
#if !defined(ANDROID)
throw "can not open files";
#else
ASSERT(0);
#endif
}
}
jpeg_stdio_dest(&cinfo,out);
/* Step 3: set parameters for compression */
cinfo.image_width = _out_wide; /* image width and height, in pix */
cinfo.image_height = _out_high;
cinfo.input_components = 3; /* # of color components per pix */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo,quality,FALSE);
/* Step 4: Start compressor */
jpeg_start_compress(&cinfo,TRUE);
/* Step 5: while (scan lines remain to be written) */
row_stride = _out_wide * 3; /* JSAMPLEs per row in image_buffer */
while (cinfo.next_scanline < cinfo.image_height)
{
row_pointer[0] = &_outimage[cinfo.next_scanline*row_stride];
jpeg_write_scanlines(&cinfo,row_pointer,1);
}
/* Step 6: Finish compression */
jpeg_finish_compress(&cinfo);
fclose(out);
/* Step 7: release JPEG compression object */
jpeg_destroy_compress(&cinfo);
#if !defined(ANDROID)
}
catch (const char* e)
{
printf("Error!! %s\n", e);
return false;
}
#endif
FreeMemory(bMatrix);
return true;
}
bool CJpeglibExtension::Resize(int maxsize, int resize_dim)
{
register int a, b, x, yp, yw;
long y, sw, sh, lastyp;
int c, pixwide, pixhigh;
int tmp, tr, tg, tb, tn;
int xypos;
#if !defined(ANDROID)
try
{
#endif
if (_readImage == NULL)
{
#if !defined(ANDROID)
throw "Please read file!!";
#else
ASSERT(0);
#endif
return false;
}
byte* palr = GetPalette();
byte* palg = GetPalette() + 256;
byte* palb = GetPalette() + 512;
/* The resize dimension wasn't provided... */
if (!resize_dim)
{
if (_width <= _height)
{
/* Picture is square or portraity */
resize_dim = RSZ_HEIGHT;
}
else
{
/* Picture is landscapey */
resize_dim = RSZ_WIDTH;
}
}
switch(resize_dim)
{
case RSZ_FIX:
sh = sw = maxsize;
break;
case RSZ_HEIGHT:
sh = maxsize;
sw = (int)( (maxsize * ((double)_width)) / ((double)_height) );
break;
case RSZ_WIDTH:
sw = maxsize;
sh = (int)( (maxsize * ((double)_height)) / ((double)_width) );
break;
default:
/* WE SHOULD NEVER GET HERE! */
sw = sh = 0;
break;
}
/* This is a kludge. */
if (sw == 0) sw += 1;
if (sh == 0) sh += 1;
_out_wide = sw;
_out_high = sh;
/* Reserve the amount of memory we will need. */
_outimage = (byte*)calloc(1, (sw * sh * 3));
if (_outimage == NULL)
{
#if !defined(ANDROID)
throw "Out of memory!!";
#else
ASSERT(0);
#endif
}
for (x=0; x<(sw * sh * 3); x++)
{
_outimage[x] = GRAY;
}
/* It has been reduced. */
if (_width > sw)
{
lastyp = -1;
pixhigh = (int)( ((float)_height) / ((float)sh) + 0.5 );
pixwide = (int)( ((float)_width) / ((float)sw) + 0.5 );
pixhigh++;
pixwide++;
for(y=0; y < _height; y++)
{
yp = (y * sh) / _height;
if (yp != lastyp)
{
yw = (y * _width);
/* we try to resample a bit. get that pentium RSN :) */
for (x=0; x < _width; x++,yw++)
{
tr = 0;
tg = 0;
tb = 0;
tn = 0;
for (b=0; (b < pixhigh) && (y+b < _height); b++)
{
for (a=0; (a < pixwide) && (x + a < _width); a++)
{
tmp = *(_readImage + yw + a + b * _width);
tr += palr[tmp];
tg += palg[tmp];
tb += palb[tmp];
tn++;
}
}
xypos = 3 * (((x * sw) / _width) + yp * sw);
tr /= tn;
tg /= tn;
tb /= tn;
_outimage[xypos] = tr;
_outimage[xypos+1] = tg;
_outimage[xypos+2] = tb;
}
lastyp = yp;
}
}
}
else
{
/* we just leave it the same size */
_out_wide = _width;
_out_high = _height;
for (y=0; y < _height; y++)
{
for (x=0; x < _width; x++)
{
c = _readImage[y * _width + x];
_outimage[3 * (y * _width + x)] = palr[c];
_outimage[3 * (y * _width + x) + 1] = palg[c];
_outimage[3 * (y * _width + x) + 2] = palb[c];
}
}
}
#if !defined(ANDROID)
}
catch (const char* e)
{
printf("Error!! %s\n", e);
return false;
}
#endif
return true;
}
//
// Matrix
//
bool CJpeglibExtension::Matrix(int nCount/*=3*/)
{
if (!_width || !_height)
return false;
std::string szExtension;
//
// Find extension
//
szExtension = strrchr(_szFileName.c_str(), '.');
//
// Checking extension
//
if (szExtension != ".jpg" && szExtension != ".jpeg")
return false;
int nWidth, nHeight;
if (!IsDivide(nCount, nWidth, nHeight))
{
ASSERT(0);
}
nWidth = static_cast<int>(_width / nCount);
nHeight = static_cast<int>(_height / nCount);
printf("resize Information Width: %d, height: %d\n", nWidth, nHeight);
register int x;
long y;
int c;
#if !defined(ANDROID)
try
{
#endif
if (_readImage == NULL)
#if !defined(ANDROID)
throw "Please read file!!";
#else
ASSERT(0);
#endif
byte* palr = GetPalette();
byte* palg = GetPalette() + 256;
byte* palb = GetPalette() + 512;
if (_outimage)
free(_outimage);
_out_wide = nWidth;
_out_high = nHeight;
_outimage = (byte*)calloc(1, (nWidth * nHeight * 3));
if (_outimage == NULL)
#if !defined(ANDROID)
throw "Out of memory!!";
#else
ASSERT(0);
#endif
int nImageCount = 1;
int nXPos = 0, nYPos = 0, nPos = 0;
//
// Matrix 형태로 이미지를 자르기 위해서 몇등분을 할지 입력값을 받은 다음
// 해당 개수 만큼 가로/세로 로 자르게 된다.
//
for (int h=1; h<=nCount; ++h)
{
for (int w=1; w<=nCount; ++w)
{
//
// Initialize Memory
//
for (x=0; x<(nWidth * nHeight * 3); x++)
{
_outimage[x] = GRAY;
}
printf("Image Filling Area(xPos:%d, yPos:%d)\n", nXPos, nYPos);
//
// Fill Memory
//
for (y=nYPos; y < (nHeight * h); ++y)
{
for (x=nXPos; x < (nWidth * w); ++x)
{
c = _readImage[y * _width + x];
nPos = (y - nYPos) * nWidth + (x - nXPos);
_outimage[3 * nPos] = palr[c];
_outimage[3 * nPos + 1] = palg[c];
_outimage[3 * nPos + 2] = palb[c];
}
}
std::string szFileName;
char szNumber[8] = {0};
//
// Name setting
//
sprintf(szNumber, "%03d", nImageCount);
szFileName = _szFileName.substr(0, _szFileName.size() - szExtension.size());
szFileName += "_split";
szFileName += szNumber;
szFileName += szExtension;
++nImageCount;
//
// Write Jpeg file
//
Write(szFileName.c_str(), 70, true);
nXPos += nWidth;
}
nXPos = 0;
nYPos += nHeight;
}
FreeMemory();
#if !defined(ANDROID)
}
catch (const char* e)
{
printf("ERROR : %s\n", e);
return false;
}
#endif
return true;
}
void CJpeglibExtension::FreeMemory(bool bMatrix/*=false*/)
{
if (bMatrix)
return ;
if (_outimage != NULL)
{
free(_outimage);
}
if (_readImage != NULL)
{
free(_readImage);
}
if (_palette != NULL)
{
free(_palette);
}
_outimage = NULL;
_readImage = NULL;
_palette = NULL;
}
//
// IsDivide
//
bool CJpeglibExtension::IsDivide(int nDivCount, int& nX, int& nY)
{
//LOG1("JpeglibExtension::IsDivide\n");
if (_width == 0 || _height == 0)
return false;
nX = _width % nDivCount;
nY = _height % nDivCount;
printf("Image Information Width: %d, Height: %d\n", _width, _height);
printf("Image Divide Value : w:%d, h:%d\n", nX, nY);
bool bRes = true;
if (nX != 0)
{
nX = (int(_width / nDivCount) + 1) * nDivCount;
printf("Image New Size Value : w:%d\n", nX);
bRes = false;
}
if (nY != 0)
{
nY = (int(_height / nDivCount) + 1) * nDivCount;
printf("Image New Size Value : h:%d\n", nY);
bRes = false;
}
return bRes;
}
[/code]
'Native > C++' 카테고리의 다른 글
pcre (0) | 2013.10.02 |
---|---|
Visual C++ 2005 map<string, string> problem (0) | 2013.10.02 |
library 만들기 (0) | 2013.10.02 |
error msg (0) | 2013.10.02 |
mutable (0) | 2013.10.02 |