forked from old/legacy-imlib2
jpeg and png should do the right thing with quality _or_ compression now
SVN revision: 3789
This commit is contained in:
parent
490383f4d7
commit
2e758a7c94
|
@ -13,25 +13,26 @@
|
||||||
|
|
||||||
struct ImLib_JPEG_error_mgr
|
struct ImLib_JPEG_error_mgr
|
||||||
{
|
{
|
||||||
struct jpeg_error_mgr pub;
|
struct jpeg_error_mgr pub;
|
||||||
sigjmp_buf setjmp_buffer;
|
sigjmp_buf setjmp_buffer;
|
||||||
};
|
};
|
||||||
typedef struct ImLib_JPEG_error_mgr *emptr;
|
typedef struct ImLib_JPEG_error_mgr *emptr;
|
||||||
|
|
||||||
void _JPEGFatalErrorHandler(j_common_ptr cinfo);
|
void _JPEGFatalErrorHandler(j_common_ptr cinfo);
|
||||||
void _JPEGErrorHandler(j_common_ptr cinfo);
|
void _JPEGErrorHandler(j_common_ptr cinfo);
|
||||||
void _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level);
|
void _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level);
|
||||||
char load (ImlibImage *im, ImlibProgressFunction progress,
|
char load(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
char progress_granularity, char immediate_load);
|
char progress_granularity, char immediate_load);
|
||||||
char save (ImlibImage *im, ImlibProgressFunction progress,
|
char save(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
char progress_granularity);
|
|
||||||
void formats (ImlibLoader *l);
|
char progress_granularity);
|
||||||
|
void formats(ImlibLoader * l);
|
||||||
|
|
||||||
void
|
void
|
||||||
_JPEGFatalErrorHandler(j_common_ptr cinfo)
|
_JPEGFatalErrorHandler(j_common_ptr cinfo)
|
||||||
{
|
{
|
||||||
emptr errmgr;
|
emptr errmgr;
|
||||||
|
|
||||||
errmgr = (emptr) cinfo->err;
|
errmgr = (emptr) cinfo->err;
|
||||||
/* cinfo->err->output_message(cinfo);*/
|
/* cinfo->err->output_message(cinfo);*/
|
||||||
siglongjmp(errmgr->setjmp_buffer, 1);
|
siglongjmp(errmgr->setjmp_buffer, 1);
|
||||||
|
@ -41,8 +42,8 @@ _JPEGFatalErrorHandler(j_common_ptr cinfo)
|
||||||
void
|
void
|
||||||
_JPEGErrorHandler(j_common_ptr cinfo)
|
_JPEGErrorHandler(j_common_ptr cinfo)
|
||||||
{
|
{
|
||||||
emptr errmgr;
|
emptr errmgr;
|
||||||
|
|
||||||
errmgr = (emptr) cinfo->err;
|
errmgr = (emptr) cinfo->err;
|
||||||
/* cinfo->err->output_message(cinfo);*/
|
/* cinfo->err->output_message(cinfo);*/
|
||||||
/* siglongjmp(errmgr->setjmp_buffer, 1);*/
|
/* siglongjmp(errmgr->setjmp_buffer, 1);*/
|
||||||
|
@ -52,8 +53,8 @@ _JPEGErrorHandler(j_common_ptr cinfo)
|
||||||
void
|
void
|
||||||
_JPEGErrorHandler2(j_common_ptr cinfo, int msg_level)
|
_JPEGErrorHandler2(j_common_ptr cinfo, int msg_level)
|
||||||
{
|
{
|
||||||
emptr errmgr;
|
emptr errmgr;
|
||||||
|
|
||||||
errmgr = (emptr) cinfo->err;
|
errmgr = (emptr) cinfo->err;
|
||||||
/* cinfo->err->output_message(cinfo);*/
|
/* cinfo->err->output_message(cinfo);*/
|
||||||
/* siglongjmp(errmgr->setjmp_buffer, 1);*/
|
/* siglongjmp(errmgr->setjmp_buffer, 1);*/
|
||||||
|
@ -61,15 +62,15 @@ _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level)
|
||||||
msg_level = 0;
|
msg_level = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char
|
char
|
||||||
load (ImlibImage *im, ImlibProgressFunction progress,
|
load(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
char progress_granularity, char immediate_load)
|
char progress_granularity, char immediate_load)
|
||||||
{
|
{
|
||||||
int w, h;
|
int w, h;
|
||||||
struct jpeg_decompress_struct cinfo;
|
struct jpeg_decompress_struct cinfo;
|
||||||
struct ImLib_JPEG_error_mgr jerr;
|
struct ImLib_JPEG_error_mgr jerr;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
if (im->data)
|
if (im->data)
|
||||||
return 0;
|
return 0;
|
||||||
f = fopen(im->file, "rb");
|
f = fopen(im->file, "rb");
|
||||||
|
@ -80,11 +81,11 @@ load (ImlibImage *im, ImlibProgressFunction progress,
|
||||||
jerr.pub.emit_message = _JPEGErrorHandler2;
|
jerr.pub.emit_message = _JPEGErrorHandler2;
|
||||||
jerr.pub.output_message = _JPEGErrorHandler;
|
jerr.pub.output_message = _JPEGErrorHandler;
|
||||||
if (sigsetjmp(jerr.setjmp_buffer, 1))
|
if (sigsetjmp(jerr.setjmp_buffer, 1))
|
||||||
{
|
{
|
||||||
jpeg_destroy_decompress(&cinfo);
|
jpeg_destroy_decompress(&cinfo);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
jpeg_create_decompress(&cinfo);
|
jpeg_create_decompress(&cinfo);
|
||||||
jpeg_stdio_src(&cinfo, f);
|
jpeg_stdio_src(&cinfo, f);
|
||||||
jpeg_read_header(&cinfo, TRUE);
|
jpeg_read_header(&cinfo, TRUE);
|
||||||
|
@ -92,158 +93,156 @@ load (ImlibImage *im, ImlibProgressFunction progress,
|
||||||
cinfo.do_block_smoothing = FALSE;
|
cinfo.do_block_smoothing = FALSE;
|
||||||
jpeg_start_decompress(&cinfo);
|
jpeg_start_decompress(&cinfo);
|
||||||
if ((!im->loader) && (!im->data))
|
if ((!im->loader) && (!im->data))
|
||||||
{
|
{
|
||||||
im->w = w = cinfo.output_width;
|
im->w = w = cinfo.output_width;
|
||||||
im->h = h = cinfo.output_height;
|
im->h = h = cinfo.output_height;
|
||||||
UNSET_FLAG(im->flags, F_HAS_ALPHA);
|
UNSET_FLAG(im->flags, F_HAS_ALPHA);
|
||||||
im->format = strdup("jpeg");
|
im->format = strdup("jpeg");
|
||||||
}
|
}
|
||||||
if (((!im->data) && (im->loader)) || (immediate_load) || (progress))
|
if (((!im->data) && (im->loader)) || (immediate_load) || (progress))
|
||||||
{
|
{
|
||||||
DATA8 *ptr, *line[16], *data;
|
DATA8 *ptr, *line[16], *data;
|
||||||
DATA32 *ptr2;
|
DATA32 *ptr2;
|
||||||
int x, y, l, i, scans, count, prevy;
|
int x, y, l, i, scans, count, prevy;
|
||||||
|
|
||||||
im->w = w = cinfo.output_width;
|
im->w = w = cinfo.output_width;
|
||||||
im->h = h = cinfo.output_height;
|
im->h = h = cinfo.output_height;
|
||||||
|
|
||||||
if (cinfo.rec_outbuf_height > 16)
|
if (cinfo.rec_outbuf_height > 16)
|
||||||
{
|
{
|
||||||
jpeg_destroy_decompress(&cinfo);
|
jpeg_destroy_decompress(&cinfo);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
data = malloc(w * 16 * 3);
|
data = malloc(w * 16 * 3);
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
jpeg_destroy_decompress(&cinfo);
|
jpeg_destroy_decompress(&cinfo);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* must set the im->data member before callign progress function */
|
/* must set the im->data member before callign progress function */
|
||||||
ptr2 = im->data = malloc(w * h * sizeof(DATA32));
|
ptr2 = im->data = malloc(w * h * sizeof(DATA32));
|
||||||
if (!im->data)
|
if (!im->data)
|
||||||
{
|
{
|
||||||
free(data);
|
free(data);
|
||||||
jpeg_destroy_decompress(&cinfo);
|
jpeg_destroy_decompress(&cinfo);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
count = 0;
|
count = 0;
|
||||||
prevy = 0;
|
prevy = 0;
|
||||||
if (cinfo.output_components == 3)
|
if (cinfo.output_components == 3)
|
||||||
{
|
{
|
||||||
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
||||||
line[i] = data + (i * w * 3);
|
line[i] = data + (i * w * 3);
|
||||||
for (l = 0; l < h; l += cinfo.rec_outbuf_height)
|
for (l = 0; l < h; l += cinfo.rec_outbuf_height)
|
||||||
{
|
{
|
||||||
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
||||||
scans = cinfo.rec_outbuf_height;
|
scans = cinfo.rec_outbuf_height;
|
||||||
if ((h - l) < scans)
|
if ((h - l) < scans)
|
||||||
scans = h - l;
|
scans = h - l;
|
||||||
ptr = data;
|
ptr = data;
|
||||||
for (y = 0; y < scans; y++)
|
for (y = 0; y < scans; y++)
|
||||||
{
|
{
|
||||||
for (x = 0; x < w; x++)
|
for (x = 0; x < w; x++)
|
||||||
{
|
{
|
||||||
*ptr2 = (0xff000000) |
|
*ptr2 =
|
||||||
((ptr[0]) << 16) |
|
(0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) |
|
||||||
((ptr[1]) << 8) |
|
(ptr[2]);
|
||||||
(ptr[2]);
|
ptr += 3;
|
||||||
ptr += 3;
|
ptr2++;
|
||||||
ptr2 ++;
|
}
|
||||||
}
|
}
|
||||||
}
|
if (progress)
|
||||||
if (progress)
|
{
|
||||||
{
|
int per;
|
||||||
int per;
|
|
||||||
|
per = (l * 100) / h;
|
||||||
per = (l * 100) / h;
|
if (((per - count) >= progress_granularity)
|
||||||
if (((per - count) >= progress_granularity) ||
|
|| ((h - l) <= cinfo.rec_outbuf_height))
|
||||||
((h - l) <= cinfo.rec_outbuf_height))
|
{
|
||||||
{
|
count = per;
|
||||||
count = per;
|
if (!progress(im, per, 0, prevy, w, scans + l - prevy))
|
||||||
if(!progress(im, per, 0, prevy, w, scans + l - prevy))
|
{
|
||||||
{
|
free(data);
|
||||||
free(data);
|
jpeg_finish_decompress(&cinfo);
|
||||||
jpeg_finish_decompress(&cinfo);
|
jpeg_destroy_decompress(&cinfo);
|
||||||
jpeg_destroy_decompress(&cinfo);
|
fclose(f);
|
||||||
fclose(f);
|
return 2;
|
||||||
return 2;
|
}
|
||||||
}
|
prevy = l + scans;
|
||||||
prevy = l + scans;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (cinfo.output_components == 1)
|
||||||
else if (cinfo.output_components == 1)
|
{
|
||||||
{
|
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
||||||
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
line[i] = data + (i * w);
|
||||||
line[i] = data + (i * w);
|
for (l = 0; l < h; l += cinfo.rec_outbuf_height)
|
||||||
for (l = 0; l < h; l += cinfo.rec_outbuf_height)
|
{
|
||||||
{
|
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
||||||
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
scans = cinfo.rec_outbuf_height;
|
||||||
scans = cinfo.rec_outbuf_height;
|
if ((h - l) < scans)
|
||||||
if ((h - l) < scans)
|
scans = h - l;
|
||||||
scans = h - l;
|
ptr = data;
|
||||||
ptr = data;
|
for (y = 0; y < scans; y++)
|
||||||
for (y = 0; y < scans; y++)
|
{
|
||||||
{
|
for (x = 0; x < w; x++)
|
||||||
for (x = 0; x < w; x++)
|
{
|
||||||
{
|
*ptr2 =
|
||||||
*ptr2 = (0xff000000) |
|
(0xff000000) | ((ptr[0]) << 16) | ((ptr[0]) << 8) |
|
||||||
((ptr[0]) << 16) |
|
(ptr[0]);
|
||||||
((ptr[0]) << 8) |
|
ptr++;
|
||||||
(ptr[0]);
|
ptr2++;
|
||||||
ptr ++;
|
}
|
||||||
ptr2 ++;
|
}
|
||||||
}
|
if (progress)
|
||||||
}
|
{
|
||||||
if (progress)
|
int per;
|
||||||
{
|
|
||||||
int per;
|
per = (l * 100) / h;
|
||||||
|
if (((per - count) >= progress_granularity)
|
||||||
per = (l * 100) / h;
|
|| ((h - l) <= cinfo.rec_outbuf_height))
|
||||||
if (((per - count) >= progress_granularity) ||
|
{
|
||||||
((h - l) <= cinfo.rec_outbuf_height))
|
count = per;
|
||||||
{
|
if (!progress(im, per, 0, prevy, w, l + scans - prevy))
|
||||||
count = per;
|
{
|
||||||
if(!progress(im, per, 0, prevy, w, l + scans - prevy))
|
free(data);
|
||||||
{
|
jpeg_finish_decompress(&cinfo);
|
||||||
free(data);
|
jpeg_destroy_decompress(&cinfo);
|
||||||
jpeg_finish_decompress(&cinfo);
|
fclose(f);
|
||||||
jpeg_destroy_decompress(&cinfo);
|
return 2;
|
||||||
fclose(f);
|
}
|
||||||
return 2;
|
prevy = l + scans;
|
||||||
}
|
}
|
||||||
prevy = l + scans;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
free(data);
|
||||||
}
|
}
|
||||||
free(data);
|
|
||||||
}
|
|
||||||
jpeg_finish_decompress(&cinfo);
|
jpeg_finish_decompress(&cinfo);
|
||||||
jpeg_destroy_decompress(&cinfo);
|
jpeg_destroy_decompress(&cinfo);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char
|
char
|
||||||
save (ImlibImage *im, ImlibProgressFunction progress,
|
save(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
char progress_granularity)
|
char progress_granularity)
|
||||||
{
|
{
|
||||||
struct jpeg_compress_struct cinfo;
|
struct jpeg_compress_struct cinfo;
|
||||||
struct ImLib_JPEG_error_mgr jerr;
|
struct ImLib_JPEG_error_mgr jerr;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
DATA8 *buf;
|
DATA8 *buf;
|
||||||
DATA32 *ptr;
|
DATA32 *ptr;
|
||||||
JSAMPROW *jbuf;
|
JSAMPROW *jbuf;
|
||||||
int y = 0, quality = 75;
|
int y = 0, quality = 75, compression = 2;
|
||||||
ImlibImageTag *tag;
|
ImlibImageTag *tag;
|
||||||
int i, j, pl = 0;
|
int i, j, pl = 0;
|
||||||
char pper = 0;
|
char pper = 0;
|
||||||
|
|
||||||
|
|
||||||
/* no image data? abort */
|
/* no image data? abort */
|
||||||
if (!im->data)
|
if (!im->data)
|
||||||
|
@ -254,33 +253,48 @@ save (ImlibImage *im, ImlibProgressFunction progress,
|
||||||
return 0;
|
return 0;
|
||||||
f = fopen(im->file, "wb");
|
f = fopen(im->file, "wb");
|
||||||
if (!f)
|
if (!f)
|
||||||
{
|
{
|
||||||
free(buf);
|
free(buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* set up error handling */
|
/* set up error handling */
|
||||||
jerr.pub.error_exit = _JPEGFatalErrorHandler;
|
jerr.pub.error_exit = _JPEGFatalErrorHandler;
|
||||||
jerr.pub.emit_message = _JPEGErrorHandler2;
|
jerr.pub.emit_message = _JPEGErrorHandler2;
|
||||||
jerr.pub.output_message = _JPEGErrorHandler;
|
jerr.pub.output_message = _JPEGErrorHandler;
|
||||||
cinfo.err = jpeg_std_error(&(jerr.pub));
|
cinfo.err = jpeg_std_error(&(jerr.pub));
|
||||||
if (sigsetjmp(jerr.setjmp_buffer, 1))
|
if (sigsetjmp(jerr.setjmp_buffer, 1))
|
||||||
{
|
{
|
||||||
jpeg_destroy_compress(&cinfo);
|
jpeg_destroy_compress(&cinfo);
|
||||||
free(buf);
|
free(buf);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* setup compress params */
|
/* setup compress params */
|
||||||
jpeg_create_compress(&cinfo);
|
jpeg_create_compress(&cinfo);
|
||||||
jpeg_stdio_dest(&cinfo, f);
|
jpeg_stdio_dest(&cinfo, f);
|
||||||
cinfo.image_width = im->w;
|
cinfo.image_width = im->w;
|
||||||
cinfo.image_height = im->h;
|
cinfo.image_height = im->h;
|
||||||
cinfo.input_components = 3;
|
cinfo.input_components = 3;
|
||||||
cinfo.in_color_space = JCS_RGB;
|
cinfo.in_color_space = JCS_RGB;
|
||||||
|
|
||||||
/* look for tags attached to image to get extra parameters liek quality */
|
/* look for tags attached to image to get extra parameters liek quality */
|
||||||
/* settigns etc. - thsi si the "api" to hint for extra information for */
|
/* settigns etc. - thsi si the "api" to hint for extra information for */
|
||||||
/* saver modules */
|
/* saver modules */
|
||||||
|
|
||||||
|
/* compression */
|
||||||
|
tag = __imlib_GetTag(im, "compression");
|
||||||
|
if (tag)
|
||||||
|
{
|
||||||
|
compression = tag->val;
|
||||||
|
if (compression < 0)
|
||||||
|
compression = 0;
|
||||||
|
if (compression > 9)
|
||||||
|
compression = 9;
|
||||||
|
}
|
||||||
|
/* convert to quality */
|
||||||
|
quality = (9 - compression) * 10;
|
||||||
|
quality = quality * 10 / 9;
|
||||||
|
/* quality */
|
||||||
tag = __imlib_GetTag(im, "quality");
|
tag = __imlib_GetTag(im, "quality");
|
||||||
if (tag)
|
if (tag)
|
||||||
quality = tag->val;
|
quality = tag->val;
|
||||||
|
@ -297,62 +311,60 @@ save (ImlibImage *im, ImlibProgressFunction progress,
|
||||||
ptr = im->data;
|
ptr = im->data;
|
||||||
/* go one scanline at a time... and save */
|
/* go one scanline at a time... and save */
|
||||||
while (cinfo.next_scanline < cinfo.image_height)
|
while (cinfo.next_scanline < cinfo.image_height)
|
||||||
{
|
{
|
||||||
/* convcert scaline from ARGB to RGB packed */
|
/* convcert scaline from ARGB to RGB packed */
|
||||||
for (j = 0, i = 0; i < im->w; i++)
|
for (j = 0, i = 0; i < im->w; i++)
|
||||||
{
|
{
|
||||||
buf[j++] = ((*ptr) >> 16) & 0xff;
|
buf[j++] = ((*ptr) >> 16) & 0xff;
|
||||||
buf[j++] = ((*ptr) >> 8 ) & 0xff;
|
buf[j++] = ((*ptr) >> 8) & 0xff;
|
||||||
buf[j++] = ((*ptr) ) & 0xff;
|
buf[j++] = ((*ptr)) & 0xff;
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
/* write scanline */
|
/* write scanline */
|
||||||
jbuf = (JSAMPROW *)(&buf);
|
jbuf = (JSAMPROW *) (&buf);
|
||||||
jpeg_write_scanlines(&cinfo, jbuf, 1);
|
jpeg_write_scanlines(&cinfo, jbuf, 1);
|
||||||
y++;
|
y++;
|
||||||
if (progress)
|
if (progress)
|
||||||
{
|
{
|
||||||
char per;
|
char per;
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
per = (char)((100 * y) / im->h);
|
per = (char) ((100 * y) / im->h);
|
||||||
if (((per - pper) >= progress_granularity) ||
|
if (((per - pper) >= progress_granularity) || (y == (im->h - 1)))
|
||||||
(y == (im->h - 1)))
|
{
|
||||||
{
|
l = y - pl;
|
||||||
l = y - pl;
|
if (!progress(im, per, 0, (y - l), im->w, l))
|
||||||
if(!progress(im, per, 0, (y - l), im->w, l))
|
{
|
||||||
{
|
jpeg_finish_compress(&cinfo);
|
||||||
jpeg_finish_compress(&cinfo);
|
free(buf);
|
||||||
free(buf);
|
fclose(f);
|
||||||
fclose(f);
|
return 2;
|
||||||
return 2;
|
}
|
||||||
}
|
pper = per;
|
||||||
pper = per;
|
pl = y;
|
||||||
pl = y;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/* finish off */
|
/* finish off */
|
||||||
jpeg_finish_compress(&cinfo);
|
jpeg_finish_compress(&cinfo);
|
||||||
free(buf);
|
free(buf);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 1;
|
return 1;
|
||||||
progress = NULL;
|
progress = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
formats (ImlibLoader *l)
|
formats(ImlibLoader * l)
|
||||||
{
|
{
|
||||||
char *list_formats[] =
|
char *list_formats[] = { "jpg", "jpeg", "jfif", "jfi" };
|
||||||
{ "jpg", "jpeg", "jfif", "jfi" };
|
|
||||||
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
l->num_formats = (sizeof(list_formats) / sizeof (char *));
|
l->num_formats = (sizeof(list_formats) / sizeof(char *));
|
||||||
l->formats = malloc(sizeof(char *) * l->num_formats);
|
l->formats = malloc(sizeof(char *) * l->num_formats);
|
||||||
for (i = 0; i < l->num_formats; i++)
|
|
||||||
l->formats[i] = strdup(list_formats[i]);
|
for (i = 0; i < l->num_formats; i++)
|
||||||
}
|
l->formats[i] = strdup(list_formats[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,24 +15,25 @@
|
||||||
/* PNG stuff */
|
/* PNG stuff */
|
||||||
#define PNG_BYTES_TO_CHECK 4
|
#define PNG_BYTES_TO_CHECK 4
|
||||||
|
|
||||||
char load (ImlibImage *im, ImlibProgressFunction progress,
|
char load(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
char progress_granularity, char immediate_load);
|
char progress_granularity, char immediate_load);
|
||||||
char save (ImlibImage *im, ImlibProgressFunction progress,
|
char save(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
char progress_granularity);
|
|
||||||
void formats (ImlibLoader *l);
|
|
||||||
|
|
||||||
char
|
char progress_granularity);
|
||||||
load (ImlibImage *im, ImlibProgressFunction progress,
|
void formats(ImlibLoader * l);
|
||||||
char progress_granularity, char immediate_load)
|
|
||||||
|
char
|
||||||
|
load(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
|
char progress_granularity, char immediate_load)
|
||||||
{
|
{
|
||||||
png_uint_32 w32, h32;
|
png_uint_32 w32, h32;
|
||||||
int w, h;
|
int w, h;
|
||||||
char hasa = 0, hasg = 0;
|
char hasa = 0, hasg = 0;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
png_structp png_ptr = NULL;
|
png_structp png_ptr = NULL;
|
||||||
png_infop info_ptr = NULL;
|
png_infop info_ptr = NULL;
|
||||||
int bit_depth, color_type, interlace_type;
|
int bit_depth, color_type, interlace_type;
|
||||||
|
|
||||||
/* if immediate_load is 1, then dont delay image laoding as below, or */
|
/* if immediate_load is 1, then dont delay image laoding as below, or */
|
||||||
/* already data in this image - dont load it again */
|
/* already data in this image - dont load it again */
|
||||||
if (im->data)
|
if (im->data)
|
||||||
|
@ -42,303 +43,315 @@ load (ImlibImage *im, ImlibProgressFunction progress,
|
||||||
return 0;
|
return 0;
|
||||||
/* read header */
|
/* read header */
|
||||||
if (!im->data)
|
if (!im->data)
|
||||||
{
|
{
|
||||||
unsigned char buf[PNG_BYTES_TO_CHECK];
|
unsigned char buf[PNG_BYTES_TO_CHECK];
|
||||||
|
|
||||||
/* if we havent read the header before, set the header data */
|
/* if we havent read the header before, set the header data */
|
||||||
fread(buf, 1, PNG_BYTES_TO_CHECK, f);
|
fread(buf, 1, PNG_BYTES_TO_CHECK, f);
|
||||||
if (!png_check_sig(buf, PNG_BYTES_TO_CHECK))
|
if (!png_check_sig(buf, PNG_BYTES_TO_CHECK))
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
rewind(f);
|
rewind(f);
|
||||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL,
|
png_ptr =
|
||||||
NULL);
|
png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
if (!png_ptr)
|
if (!png_ptr)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
info_ptr = png_create_info_struct(png_ptr);
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
if (!info_ptr)
|
if (!info_ptr)
|
||||||
{
|
{
|
||||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (setjmp(png_ptr->jmpbuf))
|
if (setjmp(png_ptr->jmpbuf))
|
||||||
{
|
{
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
png_init_io(png_ptr, f);
|
png_init_io(png_ptr, f);
|
||||||
png_read_info(png_ptr, info_ptr);
|
png_read_info(png_ptr, info_ptr);
|
||||||
png_get_IHDR(png_ptr, info_ptr,
|
png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32),
|
||||||
(png_uint_32 *)(&w32), (png_uint_32 *)(&h32),
|
(png_uint_32 *) (&h32), &bit_depth, &color_type,
|
||||||
&bit_depth, &color_type, &interlace_type, NULL, NULL);
|
&interlace_type, NULL, NULL);
|
||||||
im->w = (int)w32;
|
im->w = (int) w32;
|
||||||
im->h = (int)h32;
|
im->h = (int) h32;
|
||||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||||
png_set_expand(png_ptr);
|
png_set_expand(png_ptr);
|
||||||
if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||||
hasa = 1;
|
hasa = 1;
|
||||||
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||||
{
|
{
|
||||||
hasa = 1;
|
hasa = 1;
|
||||||
hasg = 1;
|
hasg = 1;
|
||||||
}
|
}
|
||||||
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)
|
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)
|
||||||
hasg = 1;
|
hasg = 1;
|
||||||
if (hasa)
|
if (hasa)
|
||||||
SET_FLAG(im->flags, F_HAS_ALPHA);
|
SET_FLAG(im->flags, F_HAS_ALPHA);
|
||||||
else
|
else
|
||||||
UNSET_FLAG(im->flags, F_HAS_ALPHA);
|
UNSET_FLAG(im->flags, F_HAS_ALPHA);
|
||||||
/* set the format string member to the lower-case full extension */
|
/* set the format string member to the lower-case full extension */
|
||||||
/* name for the format - so example names would be: */
|
/* name for the format - so example names would be: */
|
||||||
/* "png", "jpeg", "tiff", "ppm", "pgm", "pbm", "gif", "xpm" ... */
|
/* "png", "jpeg", "tiff", "ppm", "pgm", "pbm", "gif", "xpm" ... */
|
||||||
if (!im->loader)
|
if (!im->loader)
|
||||||
im->format = strdup("png");
|
im->format = strdup("png");
|
||||||
}
|
}
|
||||||
/* if its the second phase load OR its immediate load or a progress */
|
/* if its the second phase load OR its immediate load or a progress */
|
||||||
/* callback is set then load the data */
|
/* callback is set then load the data */
|
||||||
if ((im->loader) || (immediate_load) || (progress))
|
if ((im->loader) || (immediate_load) || (progress))
|
||||||
{
|
{
|
||||||
unsigned char **lines;
|
unsigned char **lines;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
w = im->w;
|
w = im->w;
|
||||||
h = im->h;
|
h = im->h;
|
||||||
if (hasa)
|
if (hasa)
|
||||||
png_set_expand(png_ptr);
|
png_set_expand(png_ptr);
|
||||||
/* we want ARGB */
|
/* we want ARGB */
|
||||||
/* note form raster: */
|
/* note form raster: */
|
||||||
/* thanks to mustapha for helping debug this on PPC Linux remotely by */
|
/* thanks to mustapha for helping debug this on PPC Linux remotely by */
|
||||||
/* sending across screenshots all the tiem and me figuring out form them */
|
/* sending across screenshots all the tiem and me figuring out form them */
|
||||||
/* what the hell was up with the colors */
|
/* what the hell was up with the colors */
|
||||||
/* now png loading shoudl work on big endian machines nicely */
|
/* now png loading shoudl work on big endian machines nicely */
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
png_set_swap_alpha(png_ptr);
|
png_set_swap_alpha(png_ptr);
|
||||||
png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
|
png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
|
||||||
#else
|
#else
|
||||||
png_set_bgr(png_ptr);
|
png_set_bgr(png_ptr);
|
||||||
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
|
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
|
||||||
#endif
|
#endif
|
||||||
/* 16bit color -> 8bit color */
|
/* 16bit color -> 8bit color */
|
||||||
png_set_strip_16(png_ptr);
|
png_set_strip_16(png_ptr);
|
||||||
/* pack all pixels to byte boundaires */
|
/* pack all pixels to byte boundaires */
|
||||||
png_set_packing(png_ptr);
|
png_set_packing(png_ptr);
|
||||||
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||||
png_set_expand(png_ptr);
|
png_set_expand(png_ptr);
|
||||||
if (im->data)
|
if (im->data)
|
||||||
free(im->data);
|
free(im->data);
|
||||||
im->data = malloc(w * h * sizeof(DATA32));
|
im->data = malloc(w * h * sizeof(DATA32));
|
||||||
if (!im->data)
|
if (!im->data)
|
||||||
{
|
{
|
||||||
png_read_end(png_ptr, info_ptr);
|
png_read_end(png_ptr, info_ptr);
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
lines = (unsigned char **)malloc(h * sizeof(unsigned char *));
|
lines = (unsigned char **) malloc(h * sizeof(unsigned char *));
|
||||||
if (!lines)
|
|
||||||
{
|
if (!lines)
|
||||||
free(im->data);
|
{
|
||||||
im->data = NULL;
|
free(im->data);
|
||||||
png_read_end(png_ptr, info_ptr);
|
im->data = NULL;
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
png_read_end(png_ptr, info_ptr);
|
||||||
fclose(f);
|
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
|
||||||
return 0;
|
fclose(f);
|
||||||
}
|
return 0;
|
||||||
if (hasg)
|
}
|
||||||
{
|
if (hasg)
|
||||||
DATA8 *line;
|
{
|
||||||
int y, count, prevy, pass, number_passes, per, nrows = 1;
|
DATA8 *line;
|
||||||
|
int y, count, prevy, pass, number_passes, per, nrows = 1;
|
||||||
line = malloc(w * 2);
|
|
||||||
if (!line)
|
line = malloc(w * 2);
|
||||||
{
|
if (!line)
|
||||||
free(lines);
|
{
|
||||||
im->data = NULL;
|
free(lines);
|
||||||
png_read_end(png_ptr, info_ptr);
|
im->data = NULL;
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
png_read_end(png_ptr, info_ptr);
|
||||||
fclose(f);
|
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
|
||||||
return 0;
|
fclose(f);
|
||||||
}
|
return 0;
|
||||||
count = 0;
|
}
|
||||||
number_passes = png_set_interlace_handling(png_ptr);
|
count = 0;
|
||||||
for (pass = 0; pass < number_passes; pass++)
|
number_passes = png_set_interlace_handling(png_ptr);
|
||||||
{
|
for (pass = 0; pass < number_passes; pass++)
|
||||||
prevy = 0;
|
{
|
||||||
per = 0;
|
prevy = 0;
|
||||||
for (y = 0; y < h; y += nrows)
|
per = 0;
|
||||||
{
|
for (y = 0; y < h; y += nrows)
|
||||||
DATA32 *ptr;
|
{
|
||||||
|
DATA32 *ptr;
|
||||||
lines[0] = line;
|
|
||||||
png_read_rows(png_ptr, &lines[0], NULL, nrows);
|
lines[0] = line;
|
||||||
ptr = im->data + (y * w);
|
png_read_rows(png_ptr, &lines[0], NULL, nrows);
|
||||||
for (i = 0; i < w; i++)
|
ptr = im->data + (y * w);
|
||||||
{
|
for (i = 0; i < w; i++)
|
||||||
ptr[0] =
|
{
|
||||||
(line[i << 1] << 16) |
|
ptr[0] =
|
||||||
(line[i << 1] << 8) |
|
(line[i << 1] << 16) | (line[i << 1] << 8) |
|
||||||
(line[i << 1]) |
|
(line[i << 1]) | (line[(i << 1) + 1] << 24);
|
||||||
(line[(i << 1) + 1] << 24);
|
ptr++;
|
||||||
ptr++;
|
}
|
||||||
}
|
if (progress)
|
||||||
if (progress)
|
{
|
||||||
{
|
per = (((pass * h) + y) * 100) / (h * number_passes);
|
||||||
per = (((pass * h) + y) * 100) / (h * number_passes);
|
if ((per - count) >= progress_granularity)
|
||||||
if ((per - count) >= progress_granularity)
|
|
||||||
{
|
|
||||||
count = per;
|
|
||||||
progress(im, per, 0, prevy, w, y - prevy + 1);
|
|
||||||
prevy = y + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((progress) && (!progress(im, per, 0, prevy, w, y - prevy + 1)))
|
|
||||||
{
|
{
|
||||||
free(lines);
|
count = per;
|
||||||
png_read_end(png_ptr, info_ptr);
|
progress(im, per, 0, prevy, w, y - prevy + 1);
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
prevy = y + 1;
|
||||||
fclose(f);
|
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(line);
|
}
|
||||||
}
|
if ((progress)
|
||||||
else
|
&& (!progress(im, per, 0, prevy, w, y - prevy + 1)))
|
||||||
{
|
{
|
||||||
for (i = 0; i < h; i++)
|
free(lines);
|
||||||
lines[i] = ((unsigned char *)(im->data)) + (i * w * sizeof(DATA32));
|
png_read_end(png_ptr, info_ptr);
|
||||||
if (progress)
|
png_destroy_read_struct(&png_ptr, &info_ptr,
|
||||||
{
|
(png_infopp) NULL);
|
||||||
int y, count, prevy, pass, number_passes, per, nrows = 1;
|
fclose(f);
|
||||||
|
return 2;
|
||||||
count = 0;
|
}
|
||||||
number_passes = png_set_interlace_handling(png_ptr);
|
}
|
||||||
for (pass = 0; pass < number_passes; pass++)
|
free(line);
|
||||||
{
|
}
|
||||||
prevy = 0;
|
else
|
||||||
per = 0;
|
{
|
||||||
for (y = 0; y < h; y += nrows)
|
for (i = 0; i < h; i++)
|
||||||
{
|
lines[i] =
|
||||||
png_read_rows(png_ptr, &lines[y], NULL, nrows);
|
((unsigned char *) (im->data)) + (i * w * sizeof(DATA32));
|
||||||
|
if (progress)
|
||||||
per = (((pass * h) + y) * 100) / (h * number_passes);
|
{
|
||||||
if ((per - count) >= progress_granularity)
|
int y, count, prevy, pass, number_passes, per, nrows = 1;
|
||||||
{
|
|
||||||
count = per;
|
count = 0;
|
||||||
if(!progress(im, per, 0, prevy, w, y - prevy + 1))
|
number_passes = png_set_interlace_handling(png_ptr);
|
||||||
{
|
for (pass = 0; pass < number_passes; pass++)
|
||||||
free(lines);
|
{
|
||||||
png_read_end(png_ptr, info_ptr);
|
prevy = 0;
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
per = 0;
|
||||||
fclose(f);
|
for (y = 0; y < h; y += nrows)
|
||||||
return 2;
|
{
|
||||||
}
|
png_read_rows(png_ptr, &lines[y], NULL, nrows);
|
||||||
prevy = y + 1;
|
|
||||||
}
|
per = (((pass * h) + y) * 100) / (h * number_passes);
|
||||||
}
|
if ((per - count) >= progress_granularity)
|
||||||
if(!progress(im, per, 0, prevy, w, y - prevy + 1))
|
{
|
||||||
{
|
count = per;
|
||||||
free(lines);
|
if (!progress(im, per, 0, prevy, w, y - prevy + 1))
|
||||||
png_read_end(png_ptr, info_ptr);
|
{
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
free(lines);
|
||||||
fclose(f);
|
png_read_end(png_ptr, info_ptr);
|
||||||
return 2;
|
png_destroy_read_struct(&png_ptr, &info_ptr,
|
||||||
}
|
(png_infopp) NULL);
|
||||||
}
|
fclose(f);
|
||||||
}
|
return 2;
|
||||||
else
|
}
|
||||||
png_read_image(png_ptr, lines);
|
prevy = y + 1;
|
||||||
}
|
}
|
||||||
free(lines);
|
}
|
||||||
png_read_end(png_ptr, info_ptr);
|
if (!progress(im, per, 0, prevy, w, y - prevy + 1))
|
||||||
}
|
{
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
free(lines);
|
||||||
|
png_read_end(png_ptr, info_ptr);
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr,
|
||||||
|
(png_infopp) NULL);
|
||||||
|
fclose(f);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
png_read_image(png_ptr, lines);
|
||||||
|
}
|
||||||
|
free(lines);
|
||||||
|
png_read_end(png_ptr, info_ptr);
|
||||||
|
}
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char
|
char
|
||||||
save (ImlibImage *im, ImlibProgressFunction progress,
|
save(ImlibImage * im, ImlibProgressFunction progress,
|
||||||
char progress_granularity)
|
char progress_granularity)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
png_structp png_ptr;
|
png_structp png_ptr;
|
||||||
png_infop info_ptr;
|
png_infop info_ptr;
|
||||||
DATA32 *ptr;
|
DATA32 *ptr;
|
||||||
int x, y, j;
|
int x, y, j;
|
||||||
png_bytep row_ptr, data = NULL;
|
png_bytep row_ptr, data = NULL;
|
||||||
png_color_8 sig_bit;
|
png_color_8 sig_bit;
|
||||||
int pl = 0;
|
int pl = 0;
|
||||||
char pper = 0;
|
char pper = 0;
|
||||||
ImlibImageTag *tag;
|
ImlibImageTag *tag;
|
||||||
int quality = 75, compression;
|
int quality = 75, compression = 3;
|
||||||
|
|
||||||
f = fopen(im->file, "wb");
|
f = fopen(im->file, "wb");
|
||||||
if (!f)
|
if (!f)
|
||||||
return 0;
|
return 0;
|
||||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
NULL, NULL, NULL);
|
|
||||||
if (!png_ptr)
|
if (!png_ptr)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
info_ptr = png_create_info_struct(png_ptr);
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
if (info_ptr == NULL)
|
if (info_ptr == NULL)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
|
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (setjmp(png_ptr->jmpbuf))
|
if (setjmp(png_ptr->jmpbuf))
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
|
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
png_init_io(png_ptr, f);
|
png_init_io(png_ptr, f);
|
||||||
if (im->flags & F_HAS_ALPHA)
|
if (im->flags & F_HAS_ALPHA)
|
||||||
{
|
{
|
||||||
png_set_IHDR(png_ptr, info_ptr, im->w, im->h, 8,
|
png_set_IHDR(png_ptr, info_ptr, im->w, im->h, 8,
|
||||||
PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
|
PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
|
||||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
png_set_swap_alpha(png_ptr);
|
png_set_swap_alpha(png_ptr);
|
||||||
#else
|
#else
|
||||||
png_set_bgr(png_ptr);
|
png_set_bgr(png_ptr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
png_set_IHDR(png_ptr, info_ptr, im->w, im->h, 8,
|
png_set_IHDR(png_ptr, info_ptr, im->w, im->h, 8, PNG_COLOR_TYPE_RGB,
|
||||||
PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
|
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
|
||||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
PNG_FILTER_TYPE_BASE);
|
||||||
data = malloc(im->w * 3 * sizeof(char));
|
data = malloc(im->w * 3 * sizeof(char));
|
||||||
}
|
}
|
||||||
sig_bit.red = 8;
|
sig_bit.red = 8;
|
||||||
sig_bit.green = 8;
|
sig_bit.green = 8;
|
||||||
sig_bit.blue = 8;
|
sig_bit.blue = 8;
|
||||||
sig_bit.alpha = 8;
|
sig_bit.alpha = 8;
|
||||||
png_set_sBIT(png_ptr, info_ptr, &sig_bit);
|
png_set_sBIT(png_ptr, info_ptr, &sig_bit);
|
||||||
/* compression */
|
/* quality */
|
||||||
tag = __imlib_GetTag(im, "quality");
|
tag = __imlib_GetTag(im, "quality");
|
||||||
if (tag)
|
if (tag)
|
||||||
|
{
|
||||||
quality = tag->val;
|
quality = tag->val;
|
||||||
if (quality < 10)
|
if (quality < 1)
|
||||||
quality = 10;
|
quality = 1;
|
||||||
if (quality > 99)
|
if (quality > 99)
|
||||||
quality = 99;
|
quality = 99;
|
||||||
/* translate to png-relevant value */
|
}
|
||||||
|
/* convert to compression */
|
||||||
quality = quality / 10;
|
quality = quality / 10;
|
||||||
compression = 10 - quality;
|
compression = 9 - quality;
|
||||||
/* should be 1-9 now */
|
/* compression */
|
||||||
|
tag = __imlib_GetTag(im, "compression");
|
||||||
|
if (tag)
|
||||||
|
compression = tag->val;
|
||||||
|
if (compression < 0)
|
||||||
|
compression = 0;
|
||||||
|
if (compression > 9)
|
||||||
|
compression = 9;
|
||||||
png_set_compression_level(png_ptr, compression);
|
png_set_compression_level(png_ptr, compression);
|
||||||
png_write_info(png_ptr, info_ptr);
|
png_write_info(png_ptr, info_ptr);
|
||||||
png_set_shift(png_ptr, &sig_bit);
|
png_set_shift(png_ptr, &sig_bit);
|
||||||
|
@ -346,49 +359,49 @@ save (ImlibImage *im, ImlibProgressFunction progress,
|
||||||
|
|
||||||
ptr = im->data;
|
ptr = im->data;
|
||||||
for (y = 0; y < im->h; y++)
|
for (y = 0; y < im->h; y++)
|
||||||
{
|
{
|
||||||
if (im->flags & F_HAS_ALPHA)
|
if (im->flags & F_HAS_ALPHA)
|
||||||
row_ptr = (png_bytep)ptr;
|
row_ptr = (png_bytep) ptr;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (j = 0, x = 0; x < im->w; x++)
|
for (j = 0, x = 0; x < im->w; x++)
|
||||||
{
|
{
|
||||||
data[j++] = (ptr[x] >> 16) & 0xff;
|
data[j++] = (ptr[x] >> 16) & 0xff;
|
||||||
data[j++] = (ptr[x] >> 8 ) & 0xff;
|
data[j++] = (ptr[x] >> 8) & 0xff;
|
||||||
data[j++] = (ptr[x] ) & 0xff;
|
data[j++] = (ptr[x]) & 0xff;
|
||||||
}
|
}
|
||||||
row_ptr = (png_bytep)data;
|
row_ptr = (png_bytep) data;
|
||||||
}
|
}
|
||||||
png_write_rows(png_ptr, &row_ptr, 1);
|
png_write_rows(png_ptr, &row_ptr, 1);
|
||||||
if (progress)
|
if (progress)
|
||||||
{
|
{
|
||||||
char per;
|
char per;
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
per = (char)((100 * y) / im->h);
|
per = (char) ((100 * y) / im->h);
|
||||||
if ((per - pper) >= progress_granularity)
|
if ((per - pper) >= progress_granularity)
|
||||||
{
|
{
|
||||||
l = y - pl;
|
l = y - pl;
|
||||||
if(!progress(im, per, 0, (y - l), im->w, l))
|
if (!progress(im, per, 0, (y - l), im->w, l))
|
||||||
{
|
{
|
||||||
if (data)
|
if (data)
|
||||||
free(data);
|
free(data);
|
||||||
png_write_end(png_ptr, info_ptr);
|
png_write_end(png_ptr, info_ptr);
|
||||||
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
|
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
pper = per;
|
pper = per;
|
||||||
pl = y;
|
pl = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptr += im->w;
|
ptr += im->w;
|
||||||
}
|
}
|
||||||
if (data)
|
if (data)
|
||||||
free(data);
|
free(data);
|
||||||
png_write_end(png_ptr, info_ptr);
|
png_write_end(png_ptr, info_ptr);
|
||||||
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
|
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -400,22 +413,21 @@ save (ImlibImage *im, ImlibProgressFunction progress,
|
||||||
/* your laoder CAN load more than one format if it likes - like: */
|
/* your laoder CAN load more than one format if it likes - like: */
|
||||||
/* loader->formats = { "gif", "png", "jpeg", "jpg"} */
|
/* loader->formats = { "gif", "png", "jpeg", "jpg"} */
|
||||||
/* if it can load those formats. */
|
/* if it can load those formats. */
|
||||||
void
|
void
|
||||||
formats (ImlibLoader *l)
|
formats(ImlibLoader * l)
|
||||||
{
|
{
|
||||||
/* this is the only bit you have to change... */
|
/* this is the only bit you have to change... */
|
||||||
char *list_formats[] =
|
char *list_formats[] = { "png" };
|
||||||
{ "png" };
|
|
||||||
|
|
||||||
/* don't bother changing any of this - it just reads this in and sets */
|
/* don't bother changing any of this - it just reads this in and sets */
|
||||||
/* the struct values and makes copies */
|
/* the struct values and makes copies */
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
l->num_formats = (sizeof(list_formats) / sizeof (char *));
|
|
||||||
l->formats = malloc(sizeof(char *) * l->num_formats);
|
|
||||||
for (i = 0; i < l->num_formats; i++)
|
|
||||||
l->formats[i] = strdup(list_formats[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
l->num_formats = (sizeof(list_formats) / sizeof(char *));
|
||||||
|
l->formats = malloc(sizeof(char *) * l->num_formats);
|
||||||
|
|
||||||
|
for (i = 0; i < l->num_formats; i++)
|
||||||
|
l->formats[i] = strdup(list_formats[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue