view jpg.c @ 4:5ff6a67e1421

missing
author Peter Meerwald <pmeerw@pmeerw.net>
date Mon, 09 May 2011 23:32:51 +0200
parents e8957085fe8a
children 3819ecaf0f14
line wrap: on
line source

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "jpeglib.h"
#include "jerror.h"

#include "common.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;

static void init_mem_destination (j_compress_ptr cinfo) {
}

static 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;
}

static 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;
}

static 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;
}



jpg_buf_t build_jpg_from_fb(int fb, 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);

  jpg_buf_t jpg_buf;
  jpg_buf.size = 1 << 20;
  jpg_buf.ptr = NULL;

  jpeg_mem_dest(&cinfo, &jpg_buf.ptr, &jpg_buf.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);

  JSAMPLE *buf = malloc(width * 4);
  JSAMPROW row_ptr[1];
  row_ptr[0] = buf;
  for (scanline = 0; scanline < height; scanline++) {
    read(fb, buf, width*4);
    jpeg_write_scanlines(&cinfo, row_ptr, 1);
  }
  free(buf);

  jpeg_finish_compress(&cinfo);

  jpeg_destroy_compress(&cinfo);

  return jpg_buf;
}

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.