Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Switched all of jpeg to iolayer functions, removed older functions an…

…d did some

clean up.
  • Loading branch information...
commit dd55acc83c6339f654a7311912c83a83efb2fbf1 1 parent ec9b9c3
Arnar Mar Hrafnkelsson authored
Showing with 220 additions and 596 deletions.
  1. +20 −31 Imager.pm
  2. +2 −57 Imager.xs
  3. +3 −5 image.h
  4. +1 −0  io.c
  5. +187 −499 jpeg.c
  6. +7 −4 t/t101jpeg.t
51 Imager.pm
View
@@ -16,17 +16,17 @@ use Imager::Font;
DSO_close
DSO_funclist
DSO_call
-
+
load_plugin
unload_plugin
-
+
i_list_formats
i_has_format
-
+
i_color_new
i_color_set
i_color_info
-
+
i_img_empty
i_img_empty_ch
i_img_exorcise
@@ -43,7 +43,7 @@ use Imager::Font;
i_box_filled
i_arc
i_circle_aa
-
+
i_bezier_multi
i_poly_aa
@@ -53,14 +53,14 @@ use Imager::Font;
i_scale_nn
i_haar
i_count_colors
-
-
+
+
i_gaussian
i_conv
-
+
i_convert
i_map
-
+
i_img_diff
i_init_fonts
@@ -77,9 +77,6 @@ use Imager::Font;
i_tt_text
i_tt_bbox
- i_readjpeg
- i_writejpeg
-
i_readjpeg_wiol
i_writejpeg_wiol
@@ -110,11 +107,11 @@ use Imager::Font;
i_postlevels
i_mosaic
i_watermark
-
+
malloc_state
list_formats
-
+
i_gifquant
newfont
@@ -122,7 +119,6 @@ use Imager::Font;
newcolour
NC
NF
-
);
@@ -460,6 +456,9 @@ sub read {
# FIXME: Find the format here if not specified
# yes the code isn't here yet - next week maybe?
+ # Next week? Are you high or something? That comment
+ # has been there for half a year dude.
+
if (!$input{type} and $input{file}) {
$input{type}=$FORMATGUESS->($input{file});
@@ -592,20 +591,16 @@ sub read {
return undef;
}
$self->{DEBUG} && print "loading a gif file\n";
+ }
-
- } elsif ( $input{type} eq 'jpeg' ) {
- if (exists $input{data}) {
- ($self->{IMG},$self->{IPTCRAW})=i_readjpeg_scalar($input{data});
- } else {
- ($self->{IMG},$self->{IPTCRAW})=i_readjpeg( $fd );
- }
- if ( !defined($self->{IMG}) ) {
- $self->{ERRSTR}='unable to read jpeg image';
+ if ( $input{type} eq 'jpeg' ) {
+ if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) {
+ $self->{ERRSTR}='unable to write jpeg image';
return undef;
}
- $self->{DEBUG} && print "loading a jpeg file\n";
+ $self->{DEBUG} && print "writing a jpeg file\n";
}
+
}
return $self;
}
@@ -741,12 +736,6 @@ sub write {
}
$self->{DEBUG} && print "writing a gif file\n";
- } elsif ( $input{type} eq 'jpeg' ) {
- $rc = i_writejpeg($self->{IMG},$fd,$input{jpegquality});
- if ( !defined($rc) ) {
- $self->{ERRSTR}='unable to write jpeg image'; return undef;
- }
- $self->{DEBUG} && print "writing a jpeg file\n";
}
}
return $self;
59 Imager.xs
View
@@ -1018,66 +1018,11 @@ i_tt_bbox(handle,point,str,len)
#ifdef HAVE_LIBJPEG
undef_int
-i_writejpeg(im,fd,qfactor)
+i_writejpeg_wiol(im, ig, qfactor)
Imager::ImgRaw im
- int fd
+ Imager::IO ig
int qfactor
-void
-i_readjpeg(fd)
- int fd
- PREINIT:
- char* iptc_itext;
- int tlength;
- i_img* rimg;
- SV* r;
- PPCODE:
- iptc_itext = NULL;
- rimg=i_readjpeg(fd,&iptc_itext,&tlength);
- if (iptc_itext == NULL) {
- r = sv_newmortal();
- EXTEND(SP,1);
- sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
- PUSHs(r);
- } else {
- r = sv_newmortal();
- EXTEND(SP,2);
- sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
- PUSHs(r);
- PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
- myfree(iptc_itext);
- }
-
-
-void
-i_readjpeg_scalar(...)
- PROTOTYPE: $
- PREINIT:
- char* data;
- unsigned int length;
- char* iptc_itext;
- int tlength;
- i_img* rimg;
- SV* r;
- PPCODE:
- iptc_itext = NULL;
- data = (char *)SvPV(ST(0), length);
- rimg=i_readjpeg_scalar(data,length,&iptc_itext,&tlength);
- mm_log((1,"i_readjpeg_scalar: 0x%08X\n",rimg));
- if (iptc_itext == NULL) {
- r = sv_newmortal();
- EXTEND(SP,1);
- sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
- PUSHs(r);
- } else {
- r = sv_newmortal();
- EXTEND(SP,2);
- sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
- PUSHs(r);
- PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
- myfree(iptc_itext);
- }
-
void
i_readjpeg_wiol(ig)
8 image.h
View
@@ -352,11 +352,9 @@ extern i_palidx *quant_translate(i_quantize *quant, i_img *img);
extern void quant_transparent(i_quantize *quant, i_palidx *indices, i_img *img, i_palidx trans_index);
#ifdef HAVE_LIBJPEG
-i_img* i_readjpeg(int fd,char** iptc_itext,int *tlength);
-i_img* i_readjpeg_scalar(char *data, int length,char** iptc_itext,int *itlength);
-i_img* i_readjpeg_wiol(io_glue *ig, int length, char** iptc_itext, int *itlength);
-i_img* i_readjpeg_extra2(int fd,char** iptc_itext);
-undef_int i_writejpeg(i_img *im,int fd,int qfactor);
+i_img *
+i_readjpeg_wiol(io_glue *ig, int length, char** iptc_itext, int *itlength);
+undef_int i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor);
#endif /* HAVE_LIBJPEG */
#ifdef HAVE_LIBTIFF
1  io.c
View
@@ -188,6 +188,7 @@ mymalloc(int size) {
void
myfree(void *p) {
+ mm_log((1, "myfree(p %p)\n", p));
free(p);
}
686 jpeg.c
View
@@ -9,63 +9,89 @@
#include "image.h"
#include "jpeglib.h"
+#define JPEG_APP13 0xED /* APP13 marker code */
+#define JPGS 1024
unsigned char fake_eoi[]={(JOCTET) 0xFF,(JOCTET) JPEG_EOI};
-/* Handlers to read from memory */
+/* Bad design right here */
-typedef struct {
- struct jpeg_source_mgr pub; /* public fields */
- char *data;
- int length;
- JOCTET * buffer; /* start of buffer */
- boolean start_of_file; /* have we gotten any data yet? */
-} scalar_source_mgr;
+static int tlength=0;
+static char **iptc_text=NULL;
-typedef scalar_source_mgr *scalar_src_ptr;
+/* Source and Destination managers */
+typedef struct {
+ struct jpeg_source_mgr pub; /* public fields */
+ io_glue *data;
+ JOCTET *buffer; /* start of buffer */
+ int length; /* Do I need this? */
+ boolean start_of_file; /* have we gotten any data yet? */
+} wiol_source_mgr;
+typedef struct {
+ struct jpeg_destination_mgr pub; /* public fields */
+ io_glue *data;
+ JOCTET *buffer; /* start of buffer */
+ boolean start_of_file; /* have we gotten any data yet? */
+} wiol_destination_mgr;
+typedef wiol_source_mgr *wiol_src_ptr;
+typedef wiol_destination_mgr *wiol_dest_ptr;
+/*
+ * Methods for io manager objects
+ *
+ * Methods for source managers:
+ *
+ * init_source (j_decompress_ptr cinfo);
+ * skip_input_data (j_decompress_ptr cinfo, long num_bytes);
+ * fill_input_buffer (j_decompress_ptr cinfo);
+ * term_source (j_decompress_ptr cinfo);
+ */
+
static void
-scalar_init_source (j_decompress_ptr cinfo) {
- scalar_src_ptr src = (scalar_src_ptr) cinfo->src;
+wiol_init_source (j_decompress_ptr cinfo) {
+ wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
- /* We reset the empty-input-file flag for each image,
- * but we don't clear the input buffer.
- * This is correct behavior for reading a series of images from one source.
+ /* We reset the empty-input-file flag for each image, but we don't clear
+ * the input buffer. This is correct behavior for reading a series of
+ * images from one source.
*/
src->start_of_file = TRUE;
}
+
+
static boolean
-scalar_fill_input_buffer (j_decompress_ptr cinfo) {
- scalar_src_ptr src = (scalar_src_ptr) cinfo->src;
- size_t nbytes;
+wiol_fill_input_buffer(j_decompress_ptr cinfo) {
+ wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
+ ssize_t nbytes; /* We assume that reads are "small" */
+
+ mm_log((1,"wiol_fill_input_buffer(cinfo 0x%p)\n"));
- if (src->start_of_file) {
- nbytes=src->length;
- src->buffer=src->data;
+ nbytes = src->data->readcb(src->data, src->buffer, JPGS);
+
+ if (nbytes <= 0) { /* Insert a fake EOI marker */
+ src->pub.next_input_byte = fake_eoi;
+ src->pub.bytes_in_buffer = 2;
} else {
- /* Insert a fake EOI marker */
- src->buffer = fake_eoi;
- nbytes = 2;
+ src->pub.next_input_byte = src->buffer;
+ src->pub.bytes_in_buffer = nbytes;
}
-
- src->pub.next_input_byte = src->buffer;
- src->pub.bytes_in_buffer = nbytes;
src->start_of_file = FALSE;
return TRUE;
}
+
static void
-scalar_skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
- scalar_src_ptr src = (scalar_src_ptr) cinfo->src;
+wiol_skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
+ wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
/* Just a dumb implementation for now. Could use fseek() except
* it doesn't work on pipes. Not clear that being smart is worth
@@ -75,7 +101,7 @@ scalar_skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
if (num_bytes > 0) {
while (num_bytes > (long) src->pub.bytes_in_buffer) {
num_bytes -= (long) src->pub.bytes_in_buffer;
- (void) scalar_fill_input_buffer(cinfo);
+ (void) wiol_fill_input_buffer(cinfo);
/* note we assume that fill_input_buffer will never return FALSE,
* so suspension need not be handled.
*/
@@ -86,155 +112,121 @@ scalar_skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
}
static void
-scalar_term_source (j_decompress_ptr cinfo) { /* no work necessary here */ }
+wiol_term_source (j_decompress_ptr cinfo) {
+ /* no work necessary here */
+ wiol_src_ptr src;
+ if (cinfo->src != NULL) {
+ src = (wiol_src_ptr) cinfo->src;
+ myfree(src->buffer);
+ }
+}
+
+
+/* Source manager Constructor */
static void
-jpeg_scalar_src(j_decompress_ptr cinfo, char *data, int length) {
- scalar_src_ptr src;
+jpeg_wiol_src(j_decompress_ptr cinfo, io_glue *ig, int length) {
+ wiol_src_ptr src;
if (cinfo->src == NULL) { /* first time for this JPEG object? */
- cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,sizeof(scalar_source_mgr));
- src = (scalar_src_ptr) cinfo->src;
+ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_PERMANENT,sizeof(wiol_source_mgr));
+ src = (wiol_src_ptr) cinfo->src;
}
+
+ /* put the request method call in here later */
+ io_glue_commit_types(ig);
- src = (scalar_src_ptr) cinfo->src;
- src->data = data;
+ src = (wiol_src_ptr) cinfo->src;
+ src->data = ig;
+ src->buffer = mymalloc( JPGS );
src->length = length;
- src->pub.init_source = scalar_init_source;
- src->pub.fill_input_buffer = scalar_fill_input_buffer;
- src->pub.skip_input_data = scalar_skip_input_data;
+
+ src->pub.init_source = wiol_init_source;
+ src->pub.fill_input_buffer = wiol_fill_input_buffer;
+ src->pub.skip_input_data = wiol_skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
- src->pub.term_source = scalar_term_source;
- src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
- src->pub.next_input_byte = NULL; /* until buffer loaded */
+ src->pub.term_source = wiol_term_source;
+ src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+ src->pub.next_input_byte = NULL; /* until buffer loaded */
}
-undef_int
-i_writejpeg(i_img *im,int fd,int qfactor) {
- struct stat stbuf;
- JSAMPLE *image_buffer;
- int quality;
-
- struct jpeg_compress_struct cinfo;
- struct jpeg_error_mgr jerr;
-
- FILE *outfile; /* target file */
- JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
- int row_stride; /* physical row width in image buffer */
+/*
+ * Methods for destination managers:
+ *
+ * init_destination (j_compress_ptr cinfo);
+ * empty_output_buffer (j_compress_ptr cinfo);
+ * term_destination (j_compress_ptr cinfo);
+ *
+ */
- mm_log((1,"i_writejpeg(0x%x,fd %d,qfactor %d)\n",im,fd,qfactor));
+static void
+wiol_init_destination (j_compress_ptr cinfo) {
+ wiol_dest_ptr dest = (wiol_dest_ptr) cinfo->dest;
- if (!(im->channels==1 || im->channels==3)) { fprintf(stderr,"Unable to write JPEG, improper colorspace.\n"); exit(3); }
- quality = qfactor;
-
- image_buffer=im->data;
-
- /* Step 1: allocate and initialize JPEG compression object */
-
- /* We have to set up the error handler first, in case the initialization
- * step fails. (Unlikely, but it could happen if you are out of memory.)
- * This routine fills in the contents of struct jerr, and returns jerr's
- * address which we place into the link field in cinfo.
+ /* We reset the empty-input-file flag for each image, but we don't clear
+ * the input buffer. This is correct behavior for reading a series of
+ * images from one source.
*/
- cinfo.err = jpeg_std_error(&jerr);
- /* Now we can initialize the JPEG compression object. */
- jpeg_create_compress(&cinfo);
+ dest->start_of_file = TRUE;
+}
- /* Step 2: specify data destination (eg, a file) */
- /* Note: steps 2 and 3 can be done in either order. */
+static boolean
+wiol_empty_output_buffer(j_compress_ptr cinfo) {
+ wiol_dest_ptr dest = (wiol_dest_ptr) cinfo->dest;
+ ssize_t nbytes = JPGS - dest->pub.free_in_buffer;
+ ssize_t rc;
- /* Here we use the library-supplied code to send compressed data to a
- * stdio stream. You can also write your own code to do something else.
- * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
- * requires it in order to write binary files.
- */
+ mm_log((1,"wiol_emtpy_output_buffer(cinfo 0x%p)\n"));
+ rc = dest->data->writecb(dest->data, dest->buffer, nbytes);
- if (fstat(fd,&stbuf)<0) { fprintf(stderr,"Unable to stat fd.\n"); exit(1); }
-
- if ((outfile = fdopen(fd,"w")) == NULL) {
- fprintf(stderr, "can't fdopen.\n");
- exit(1);
- }
-
- jpeg_stdio_dest(&cinfo, outfile);
-
- /* Step 3: set parameters for compression */
-
- /* First we supply a description of the input image.
- * Four fields of the cinfo struct must be filled in:
- */
- cinfo.image_width = im->xsize; /* image width and height, in pixels */
- cinfo.image_height = im->ysize;
-
- if (im->channels==3) {
- cinfo.input_components = 3; /* # of color components per pixel */
- cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+ if (rc != nbytes) { /* XXX: Should raise some jpeg error */
+ mm_log((1, "wiol_empty_output_buffer: Error: nbytes = %d != rc = %d\n", nbytes, rc));
}
+ dest->pub.free_in_buffer = JPGS;
+ dest->pub.next_output_byte = dest->buffer;
+ return TRUE;
+}
- if (im->channels==1) {
- cinfo.input_components = 1; /* # of color components per pixel */
- cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
- }
+static void
+wiol_term_destination (j_compress_ptr cinfo) {
+ wiol_dest_ptr dest = (wiol_dest_ptr) cinfo->dest;
+ mm_log((1, "wiol_term_destination(cinfo %p)\n", cinfo));
+ mm_log((1, "wiol_term_destination: dest %p\n", cinfo->dest));
+ if (dest != NULL) myfree(dest->buffer);
+}
- /* Now use the library's routine to set default compression parameters.
- * (You must set at least cinfo.in_color_space before calling this,
- * since the defaults depend on the source color space.)
- */
- jpeg_set_defaults(&cinfo);
- /* Now you can set any non-default parameters you wish to.
- * Here we just illustrate the use of quality (quantization table) scaling:
- */
- jpeg_set_quality(&cinfo, quality, TRUE); /* limit to baseline-JPEG values */
+/* Destination manager Constructor */
- /* Step 4: Start compressor */
+static void
+jpeg_wiol_dest(j_compress_ptr cinfo, io_glue *ig) {
+ wiol_dest_ptr dest;
- /* TRUE ensures that we will write a complete interchange-JPEG file.
- * Pass TRUE unless you are very sure of what you're doing.
- */
- jpeg_start_compress(&cinfo, TRUE);
-
- /* Step 5: while (scan lines remain to be written) */
- /* jpeg_write_scanlines(...); */
-
- /* Here we use the library's state variable cinfo.next_scanline as the
- * loop counter, so that we don't have to keep track ourselves.
- * To keep things simple, we pass one scanline per call; you can pass
- * more if you wish, though.
- */
- row_stride = im->xsize * im->channels; /* JSAMPLEs per row in image_buffer */
-
- while (cinfo.next_scanline < cinfo.image_height) {
- /* jpeg_write_scanlines expects an array of pointers to scanlines.
- * Here the array is only one element long, but you could pass
- * more than one scanline at a time if that's more convenient.
- */
- row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
- (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
+ cinfo->dest =
+ (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(wiol_destination_mgr));
}
-
- /* Step 6: Finish compression */
-
- jpeg_finish_compress(&cinfo);
- /* After finish_compress, we can close the output file. */
- fclose(outfile);
-
- /* Step 7: release JPEG compression object */
-
- /* This is an important step since it will release a good deal of memory. */
- jpeg_destroy_compress(&cinfo);
-
- return(1);
+
+ dest = (wiol_dest_ptr) cinfo->dest;
+ dest->data = ig;
+ dest->buffer = mymalloc( JPGS );
+
+ dest->pub.init_destination = wiol_init_destination;
+ dest->pub.empty_output_buffer = wiol_empty_output_buffer;
+ dest->pub.term_destination = wiol_term_destination;
+ dest->pub.free_in_buffer = JPGS;
+ dest->pub.next_output_byte = dest->buffer;
}
-static int tlength=0;
-static char **iptc_text=NULL;
-#define JPEG_APP13 0xED /* APP13 marker code */
+
LOCAL(unsigned int)
jpeg_getc (j_decompress_ptr cinfo)
@@ -268,20 +260,8 @@ APP13_handler (j_decompress_ptr cinfo) {
return TRUE;
}
-
-
-
-
-
-
-
-
-
-
-
METHODDEF(void)
-my_output_message (j_common_ptr cinfo)
-{
+my_output_message (j_common_ptr cinfo) {
char buffer[JMSG_LENGTH_MAX];
/* Create the message */
@@ -291,11 +271,6 @@ my_output_message (j_common_ptr cinfo)
mm_log((1, "%s\n", buffer));
}
-
-
-
-
-
struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
@@ -322,161 +297,23 @@ my_error_exit (j_common_ptr cinfo) {
-
i_img*
-i_readjpeg(int fd,char** iptc_itext,int *itlength) {
+i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) {
i_img *im;
struct jpeg_decompress_struct cinfo;
- /* We use our private extension JPEG error handler.
- * Note that this struct must live as long as the main JPEG parameter
- * struct, to avoid dangling-pointer problems.
- */
-
- /* struct jpeg_error_mgr jerr;*/
struct my_error_mgr jerr;
- FILE * infile; /* source file */
JSAMPARRAY buffer; /* Output row buffer */
int row_stride; /* physical row width in output buffer */
- mm_log((1,"i_readjpeg(fd %d,iptc_itext 0x%x)\n",fd,iptc_itext));
-
- iptc_text=iptc_itext;
-
- if ((infile = fdopen(fd,"r")) == NULL) {
- fprintf(stderr, "can't fdopen.\n");
- exit(1);
- }
-
- /* Step 1: allocate and initialize JPEG decompression object */
+ mm_log((1,"i_readjpeg_wiol(data 0x%p, length %d,iptc_itext 0x%p)\n", data, iptc_itext));
- /* We set up the normal JPEG error routines, then override error_exit. */
+ iptc_text = iptc_itext;
cinfo.err = jpeg_std_error(&jerr.pub);
- jerr.pub.error_exit = my_error_exit;
+ jerr.pub.error_exit = my_error_exit;
jerr.pub.output_message = my_output_message;
- /* Establish the setjmp return context for my_error_exit to use. */
- if (setjmp(jerr.setjmp_buffer)) {
- /* If we get here, the JPEG code has signaled an error.
- * We need to clean up the JPEG object, close the input file, and return.
- */
- jpeg_destroy_decompress(&cinfo);
- fclose(infile);
- *iptc_itext=NULL;
- *itlength=0;
- return NULL;
- }
-
- /* Now we can initialize the JPEG decompression object. */
- jpeg_create_decompress(&cinfo);
- jpeg_set_marker_processor(&cinfo, JPEG_APP13, APP13_handler);
- /* Step 2: specify data source (eg, a file) */
-
- jpeg_stdio_src(&cinfo, infile);
-
- /* Step 3: read file parameters with jpeg_read_header() */
-
- (void) jpeg_read_header(&cinfo, TRUE);
-
- /* We can ignore the return value from jpeg_read_header since
- * (a) suspension is not possible with the stdio data source, and
- * (b) we passed TRUE to reject a tables-only JPEG file as an error.
- * See libjpeg.doc for more info.
- */
-
- /* Step 4: set parameters for decompression */
-
- /* In this example, we don't need to change any of the defaults set by
- * jpeg_read_header(), so we do nothing here.
- */
-
- /* Step 5: Start decompressor */
-
- (void) jpeg_start_decompress(&cinfo);
- /* We can ignore the return value since suspension is not possible
- * with the stdio data source.
- */
-
- /* We may need to do some setup of our own at this point before reading
- * the data. After jpeg_start_decompress() we have the correct scaled
- * output image dimensions available, as well as the output colormap
- * if we asked for color quantization.
- * In this example, we need to make an output work buffer of the right size.
- */
-
- im=i_img_empty_ch(NULL,cinfo.output_width,cinfo.output_height,cinfo.output_components);
-
- /* fprintf(stderr,"JPEG info:\n xsize:%d\n ysize:%d\n channels:%d.\n",xsize,ysize,channels);*/
-
- /* JSAMPLEs per row in output buffer */
- row_stride = cinfo.output_width * cinfo.output_components;
- /* Make a one-row-high sample array that will go away when done with image */
- buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
-
- /* Step 6: while (scan lines remain to be read) */
- /* jpeg_read_scanlines(...); */
-
- /* Here we use the library's state variable cinfo.output_scanline as the
- * loop counter, so that we don't have to keep track ourselves.
- */
-
- while (cinfo.output_scanline < cinfo.output_height) {
- /* jpeg_read_scanlines expects an array of pointers to scanlines.
- * Here the array is only one element long, but you could ask for
- * more than one scanline at a time if that's more convenient.
- */
- (void) jpeg_read_scanlines(&cinfo, buffer, 1);
- /* Assume put_scanline_someplace wants a pointer and sample count. */
- memcpy(im->data+im->channels*im->xsize*(cinfo.output_scanline-1),buffer[0],row_stride);
- }
-
- /* Step 7: Finish decompression */
-
- (void) jpeg_finish_decompress(&cinfo);
- /* We can ignore the return value since suspension is not possible
- * with the stdio data source.
- */
-
- /* Step 8: Release JPEG decompression object */
-
- /* This is an important step since it will release a good deal of memory. */
- jpeg_destroy_decompress(&cinfo);
-
- /* After finish_decompress, we can close the input file.
- * Here we postpone it until after no more JPEG errors are possible,
- * so as to simplify the setjmp error logic above. (Actually, I don't
- * think that jpeg_destroy can do an error exit, but why assume anything...)
- */
-
-/* fclose(infile); DO NOT fclose() BECAUSE THEN close() WILL FAIL*/
-
- /* At this point you may want to check to see whether any corrupt-data
- * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
- */
-
- /* And we're done! */
-
- *itlength=tlength;
- mm_log((1,"i_readjpeg -> (0x%x)\n",im));
- return im;
-}
-
-
-i_img*
-i_readjpeg_scalar(char *data, int length,char** iptc_itext,int *itlength) {
- i_img *im;
-
- struct jpeg_decompress_struct cinfo;
- struct my_error_mgr jerr;
- JSAMPARRAY buffer; /* Output row buffer */
- int row_stride; /* physical row width in output buffer */
-
- mm_log((1,"i_readjpeg_scalar(data 0x%08x, length %d,iptc_itext 0x%x)\n",data,length,iptc_itext));
- iptc_text=iptc_itext;
-
- cinfo.err = jpeg_std_error(&jerr.pub);
- jerr.pub.error_exit = my_error_exit;
- jerr.pub.output_message = my_output_message;
+ /* Set error handler */
if (setjmp(jerr.setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo);
*iptc_itext=NULL;
@@ -486,7 +323,8 @@ i_readjpeg_scalar(char *data, int length,char** iptc_itext,int *itlength) {
jpeg_create_decompress(&cinfo);
jpeg_set_marker_processor(&cinfo, JPEG_APP13, APP13_handler);
- jpeg_scalar_src(&cinfo, data, length );
+ jpeg_wiol_src(&cinfo, data, length);
+
(void) jpeg_read_header(&cinfo, TRUE);
(void) jpeg_start_decompress(&cinfo);
im=i_img_empty_ch(NULL,cinfo.output_width,cinfo.output_height,cinfo.output_components);
@@ -499,219 +337,69 @@ i_readjpeg_scalar(char *data, int length,char** iptc_itext,int *itlength) {
(void) jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
*itlength=tlength;
- mm_log((1,"i_readjpeg_scalar -> (0x%x)\n",im));
+ mm_log((1,"i_readjpeg_wiol -> (0x%x)\n",im));
return im;
}
+undef_int
+i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
+ struct stat stbuf;
+ JSAMPLE *image_buffer;
+ int quality;
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
+ int row_stride; /* physical row width in image buffer */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#define JPGS 1024
-
-
-
-typedef struct {
- struct jpeg_source_mgr pub; /* public fields */
- io_glue *data;
- JOCTET *buffer; /* start of buffer */
- int length; /* Do I need this? */
- boolean start_of_file; /* have we gotten any data yet? */
-} wiol_source_mgr;
-
-typedef wiol_source_mgr *wiol_src_ptr;
-
-static void
-wiol_init_source (j_decompress_ptr cinfo) {
- wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
-
- /* We reset the empty-input-file flag for each image,
- * but we don't clear the input buffer.
- * This is correct behavior for reading a series of images from one source.
- */
- src->start_of_file = TRUE;
-}
-
-static boolean
-wiol_fill_input_buffer(j_decompress_ptr cinfo) {
- wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
- ssize_t nbytes; /* We assume that reads are "small" */
-
- mm_log((1,"wiol_fill_input_buffer(cinfo 0x%p)\n"));
-
- nbytes = src->data->readcb(src->data, src->buffer, JPGS);
+ mm_log((1,"i_writejpeg(im %p, ig %p, qfactor %d)\n", im, ig, qfactor));
- if (nbytes <= 0) { /* Insert a fake EOI marker */
- src->pub.next_input_byte = fake_eoi;
- src->pub.bytes_in_buffer = 2;
- } else {
- src->pub.next_input_byte = src->buffer;
- src->pub.bytes_in_buffer = nbytes;
- }
- src->start_of_file = FALSE;
- return TRUE;
-}
+ if (!(im->channels==1 || im->channels==3)) { fprintf(stderr,"Unable to write JPEG, improper colorspace.\n"); exit(3); }
+ quality = qfactor;
-static void
-wiol_skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
- wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
-
- /* Just a dumb implementation for now. Could use fseek() except
- * it doesn't work on pipes. Not clear that being smart is worth
- * any trouble anyway --- large skips are infrequent.
- */
-
- if (num_bytes > 0) {
- while (num_bytes > (long) src->pub.bytes_in_buffer) {
- num_bytes -= (long) src->pub.bytes_in_buffer;
- (void) wiol_fill_input_buffer(cinfo);
- /* note we assume that fill_input_buffer will never return FALSE,
- * so suspension need not be handled.
- */
- }
- src->pub.next_input_byte += (size_t) num_bytes;
- src->pub.bytes_in_buffer -= (size_t) num_bytes;
- }
-}
+ image_buffer = im->data;
-static void
-wiol_term_source (j_decompress_ptr cinfo) {
- /* no work necessary here */
- wiol_src_ptr src;
- if (cinfo->src != NULL) {
- src = (wiol_src_ptr) cinfo->src;
- myfree(src->buffer);
- }
-}
+ cinfo.err = jpeg_std_error(&jerr);
-static void
-jpeg_wiol_src(j_decompress_ptr cinfo, io_glue *ig, int length) {
- wiol_src_ptr src;
-
- if (cinfo->src == NULL) { /* first time for this JPEG object? */
- cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_PERMANENT,sizeof(wiol_source_mgr));
- src = (wiol_src_ptr) cinfo->src;
- }
+ jpeg_create_compress(&cinfo);
- /* put the request method call in here later */
io_glue_commit_types(ig);
-
- src = (wiol_src_ptr) cinfo->src;
- src->data = ig;
- src->buffer = mymalloc( JPGS );
- src->length = length;
-
- src->pub.init_source = wiol_init_source;
- src->pub.fill_input_buffer = wiol_fill_input_buffer;
- src->pub.skip_input_data = wiol_skip_input_data;
- src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
- src->pub.term_source = wiol_term_source;
- src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
- src->pub.next_input_byte = NULL; /* until buffer loaded */
-}
-
-
-
-
-
-
+ jpeg_wiol_dest(&cinfo, ig);
+ cinfo.image_width = im -> xsize; /* image width and height, in pixels */
+ cinfo.image_height = im -> ysize;
+ if (im->channels==3) {
+ cinfo.input_components = 3; /* # of color components per pixel */
+ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+ }
+ if (im->channels==1) {
+ cinfo.input_components = 1; /* # of color components per pixel */
+ cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
+ }
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, quality, TRUE); /* limit to baseline-JPEG values */
+ jpeg_start_compress(&cinfo, TRUE);
-i_img*
-i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) {
- i_img *im;
+ row_stride = im->xsize * im->channels; /* JSAMPLEs per row in image_buffer */
- struct jpeg_decompress_struct cinfo;
- struct my_error_mgr jerr;
- JSAMPARRAY buffer; /* Output row buffer */
- int row_stride; /* physical row width in output buffer */
+ while (cinfo.next_scanline < cinfo.image_height) {
+ row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
+ (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
- mm_log((1,"i_readjpeg_wiol(data 0x%p, length %d,iptc_itext 0x%p)\n", data, iptc_itext));
+ /* Step 6: Finish compression */
- iptc_text = iptc_itext;
- cinfo.err = jpeg_std_error(&jerr.pub);
- jerr.pub.error_exit = my_error_exit;
- jerr.pub.output_message = my_output_message;
+ jpeg_finish_compress(&cinfo);
- /* Set error handler */
- if (setjmp(jerr.setjmp_buffer)) {
- jpeg_destroy_decompress(&cinfo);
- *iptc_itext=NULL;
- *itlength=0;
- return NULL;
- }
-
- jpeg_create_decompress(&cinfo);
- jpeg_set_marker_processor(&cinfo, JPEG_APP13, APP13_handler);
- jpeg_wiol_src(&cinfo, data, length);
+ jpeg_destroy_compress(&cinfo);
- (void) jpeg_read_header(&cinfo, TRUE);
- (void) jpeg_start_decompress(&cinfo);
- im=i_img_empty_ch(NULL,cinfo.output_width,cinfo.output_height,cinfo.output_components);
- 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(im->data+im->channels*im->xsize*(cinfo.output_scanline-1),buffer[0],row_stride);
- }
- (void) jpeg_finish_decompress(&cinfo);
- jpeg_destroy_decompress(&cinfo);
- *itlength=tlength;
- mm_log((1,"i_readjpeg_wiol -> (0x%x)\n",im));
- return im;
+ return(1);
}
-
-
11 t/t101jpeg.t
View
@@ -23,17 +23,20 @@ if (!i_has_format("jpeg")) {
} else {
open(FH,">testout/t101.jpg") || die "cannot open testout/t101.jpg for writing\n";
binmode(FH);
- i_writejpeg($img,fileno(FH),30);
+ $IO = Imager::io_new_fd(fileno(FH));
+ i_writejpeg_wiol($img,$IO,30);
close(FH);
print "ok 1\n";
- open(FH,"testout/t101.jpg") || die "cannot open testout/t101.jpg\n";
+ open(FH, "testout/t101.jpg") || die "cannot open testout/t101.jpg\n";
binmode(FH);
-
- ($cmpimg,undef)=i_readjpeg(fileno(FH));
+ $IO = Imager::io_new_fd(fileno(FH));
+ ($cmpimg,undef) = i_readjpeg_wiol($IO);
close(FH);
+ print "$cmpimg\n";
+
print "# jpeg average mean square pixel difference: ",sqrt(i_img_diff($img,$cmpimg))/150*150,"\n";
print "ok 2\n";
}
Please sign in to comment.
Something went wrong with that request. Please try again.