160 lines
4.1 KiB
C++
160 lines
4.1 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <setjmp.h>
|
|
#include <string.h>
|
|
|
|
#include <jpeglib.h>
|
|
#include "pic_private.h"
|
|
#include "pic.h"
|
|
|
|
// ----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
struct my_error_mgr
|
|
{
|
|
struct jpeg_error_mgr pub;
|
|
jmp_buf setjmp_buffer;
|
|
};
|
|
typedef struct my_error_mgr * my_error_ptr;
|
|
|
|
// ----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
static unsigned char error;
|
|
|
|
// ----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
void my_error_exit(j_common_ptr cinfo)
|
|
{
|
|
my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
|
error=1;
|
|
longjmp(myerr->setjmp_buffer, 1);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
unsigned long Pic_JPG_Read(const char *FileName, char **ppPal, char **ppDatas, unsigned long *w, unsigned long *h)
|
|
{
|
|
struct jpeg_decompress_struct cinfo;
|
|
struct my_error_mgr jerr;
|
|
FILE *file;
|
|
JSAMPARRAY buffer;
|
|
int row_stride,i;
|
|
char *pDatas,*pPal;
|
|
unsigned long ptr;
|
|
|
|
error=0;
|
|
ptr=0;
|
|
file=fopen(FileName, "rb");
|
|
if (!file)
|
|
{
|
|
Pic_SetError("JPG_Read, unable to open %s",FileName);
|
|
return(0);
|
|
}
|
|
cinfo.err = jpeg_std_error(&jerr.pub);
|
|
jerr.pub.error_exit = my_error_exit;
|
|
setjmp(jerr.setjmp_buffer);
|
|
if (error)
|
|
{
|
|
Pic_SetError("JPG_Read, internal decompression error");
|
|
jpeg_destroy_decompress(&cinfo);
|
|
return(0);
|
|
}
|
|
jpeg_create_decompress(&cinfo);
|
|
jpeg_stdio_src(&cinfo, file);
|
|
(void) jpeg_read_header(&cinfo, TRUE);
|
|
*w=cinfo.image_width;
|
|
*h=cinfo.image_height;
|
|
if (!ppPal)
|
|
{
|
|
pDatas=(char*)Pic_calloc(1,(*w)*(*h)*3);
|
|
}
|
|
else
|
|
{
|
|
pDatas=(char*)Pic_calloc(1,(*w)*(*h));
|
|
pPal=(char*)Pic_calloc(1,256*3);
|
|
if (!pPal)
|
|
{
|
|
Pic_SetError("JPG_Read, not enough memory for palette");
|
|
return(0);
|
|
}
|
|
cinfo.desired_number_of_colors = 256;
|
|
cinfo.quantize_colors = TRUE;
|
|
cinfo.dither_mode = JDITHER_ORDERED;
|
|
}
|
|
if (!pDatas)
|
|
{
|
|
Pic_SetError("JPG_Read, not enough memory for pic");
|
|
return(0);
|
|
}
|
|
(void) jpeg_start_decompress(&cinfo);
|
|
row_stride = cinfo.output_width * cinfo.output_components;
|
|
buffer = (*cinfo.mem->alloc_sarray)
|
|
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
|
while (cinfo.output_scanline < cinfo.output_height)
|
|
{
|
|
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
|
|
memcpy(&pDatas[ptr],buffer[0],row_stride);
|
|
ptr+=row_stride;
|
|
}
|
|
*ppDatas=pDatas;
|
|
if (ppPal)
|
|
{
|
|
for(i=0 ; i<256 ; i++)
|
|
{
|
|
pPal[i*3+0]=cinfo.colormap[2][i];
|
|
pPal[i*3+1]=cinfo.colormap[1][i];
|
|
pPal[i*3+2]=cinfo.colormap[0][i];
|
|
}
|
|
*ppPal=pPal;
|
|
}
|
|
(void) jpeg_finish_decompress(&cinfo);
|
|
jpeg_destroy_decompress(&cinfo);
|
|
fclose(file);
|
|
return(1);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
unsigned long Pic_JPG_Write(const char *FileName, unsigned long Qual, char *pDatas, unsigned long w, unsigned long h)
|
|
{
|
|
struct jpeg_compress_struct cinfo;
|
|
struct my_error_mgr jerr;
|
|
FILE *file;
|
|
JSAMPROW row_pointer[1];
|
|
int row_stride;
|
|
|
|
error=0;
|
|
file=fopen(FileName,"wb");
|
|
if (!file)
|
|
{
|
|
Pic_SetError("JPG_Write, unable to open %s",FileName);
|
|
return(0);
|
|
}
|
|
jpeg_create_compress(&cinfo);
|
|
cinfo.err = jpeg_std_error(&jerr.pub);
|
|
jerr.pub.error_exit = my_error_exit;
|
|
setjmp(jerr.setjmp_buffer);
|
|
if (error)
|
|
{
|
|
Pic_SetError("JPG_Write, internal compression error");
|
|
jpeg_destroy_compress(&cinfo);
|
|
return(0);
|
|
}
|
|
jpeg_stdio_dest(&cinfo, file);
|
|
cinfo.image_width = w;
|
|
cinfo.image_height = h;
|
|
cinfo.input_components = 3;
|
|
cinfo.in_color_space = JCS_RGB;
|
|
jpeg_set_defaults(&cinfo);
|
|
jpeg_set_quality(&cinfo, Qual, TRUE);
|
|
jpeg_start_compress(&cinfo, TRUE);
|
|
row_stride = w * 3;
|
|
while(cinfo.next_scanline<cinfo.image_height)
|
|
{
|
|
row_pointer[0] = (JSAMPROW)& pDatas[cinfo.next_scanline * row_stride];
|
|
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
|
|
}
|
|
jpeg_finish_compress(&cinfo);
|
|
fclose(file);
|
|
jpeg_destroy_compress(&cinfo);
|
|
return(1);
|
|
}
|