Mercurial > hg > minimon
diff jpg.c @ 2:bac8ed8d6eb9
add jpeg coding and test stuff
author | Peter Meerwald <pmeerw@pmeerw.net> |
---|---|
date | Sun, 08 May 2011 18:22:22 +0200 |
parents | |
children | e8957085fe8a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jpg.c Sun May 08 18:22:22 2011 +0200 @@ -0,0 +1,124 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "jpeglib.h" +#include "jerror.h" + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + unsigned char ** outbuffer; /* target buffer */ + unsigned long * outsize; + unsigned char * newbuffer; /* newly allocated buffer */ + JOCTET * buffer; /* start of buffer */ + size_t bufsize; +} mem_dest_mgr; + +typedef mem_dest_mgr * mem_dest_mgr_ptr; + +void init_mem_destination (j_compress_ptr cinfo) { +} + +boolean empty_mem_output_buffer(j_compress_ptr cinfo) { + size_t nextsize; + JOCTET * nextbuffer; + mem_dest_mgr_ptr dest = (mem_dest_mgr_ptr) cinfo->dest; + + /* Try to allocate new buffer with double size */ + nextsize = dest->bufsize * 2; + nextbuffer = malloc(nextsize); + + if (nextbuffer == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); + + memcpy(nextbuffer, dest->buffer, dest->bufsize); + + if (dest->newbuffer != NULL) + free(dest->newbuffer); + + dest->newbuffer = nextbuffer; + + dest->pub.next_output_byte = nextbuffer + dest->bufsize; + dest->pub.free_in_buffer = dest->bufsize; + + dest->buffer = nextbuffer; + dest->bufsize = nextsize; + + return TRUE; +} + +void term_mem_destination(j_compress_ptr cinfo) { + mem_dest_mgr_ptr dest = (mem_dest_mgr_ptr) cinfo->dest; + + *dest->outbuffer = dest->buffer; + *dest->outsize = dest->bufsize - dest->pub.free_in_buffer; +} + +void jpeg_mem_dest(j_compress_ptr cinfo, unsigned char ** outbuffer, unsigned long * outsize) { + mem_dest_mgr_ptr dest; + + if (outbuffer == NULL || outsize == NULL) /* sanity check */ + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same buffer without re-executing jpeg_mem_dest. + */ + 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(mem_dest_mgr)); + } + + dest = (mem_dest_mgr_ptr) cinfo->dest; + dest->pub.init_destination = init_mem_destination; + dest->pub.empty_output_buffer = empty_mem_output_buffer; + dest->pub.term_destination = term_mem_destination; + dest->outbuffer = outbuffer; + dest->outsize = outsize; + dest->newbuffer = NULL; + + if (*outbuffer == NULL || *outsize == 0) { + /* Allocate initial buffer */ + dest->newbuffer = *outbuffer = malloc(65536); + if (dest->newbuffer == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); + *outsize = 65536; + } + + dest->pub.next_output_byte = dest->buffer = *outbuffer; + dest->pub.free_in_buffer = dest->bufsize = *outsize; +} + + +int build_jpg(JSAMPLE *image_buf, int width, int height) { + int scanline; + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + + unsigned long out_size = 1<<20; + unsigned char *out_buf = NULL; + jpeg_mem_dest(&cinfo, &out_buf, &out_size); + + cinfo.image_width = width; + cinfo.image_height = height; + cinfo.input_components = 3; + cinfo.in_color_space = JCS_RGB; + jpeg_set_defaults(&cinfo); + + jpeg_start_compress(&cinfo, TRUE); + + for (scanline = 0; scanline < height; scanline++) { + JSAMPROW *row_ptr; + row_ptr = &image_buf[scanline * width]; + jpeg_write_scanlines(&cinfo, row_ptr, 1); + } + + jpeg_finish_compress(&cinfo); + + jpeg_destroy_compress(&cinfo); + + return 0; +}