view jpg.c @ 11:8fadd7877f6b default tip

build only minimon per default
author Peter Meerwald <pmeerw@pmeerw.net>
date Sun, 15 May 2011 18:58:44 +0200
parents 078dc69945ad
children
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 my_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;
}

#ifdef HAVE_LIBJPEG_TURBO
jpg_buf_t build_jpg_from_fb(unsigned char *fb_mem, int fb_width, int fb_height, int bits_per_pixel, int mon_width, int mon_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;

  my_jpeg_mem_dest(&cinfo, &jpg_buf.ptr, &jpg_buf.size);

  cinfo.image_width = mon_width;
  cinfo.image_height = mon_height;
  cinfo.input_components = 4;
  cinfo.in_color_space = JCS_EXT_BGRX;
  jpeg_set_defaults(&cinfo);
  cinfo.dct_method = JDCT_FASTEST;
  jpeg_set_quality(&cinfo, 70, TRUE);
  
  jpeg_start_compress(&cinfo, TRUE);

  unsigned char buf[mon_width * 4];
  JSAMPROW row_ptr[1] = {buf};
  memset(buf, 0, mon_width*4);
  if (fb_width >= mon_width)
    for (scanline = 0; scanline < MIN(fb_height, mon_height); scanline++) {
      row_ptr[0] = &fb_mem[scanline * fb_width * 4];
      jpeg_write_scanlines(&cinfo, row_ptr, 1);
    }
  else {
    for (scanline = 0; scanline < MIN(fb_height, mon_height); scanline++) {
      memcpy(buf, &fb_mem[scanline * fb_width * 4], fb_width * 4);
      jpeg_write_scanlines(&cinfo, row_ptr, 1);
    }
  }
  memset(buf, 0, mon_width*4);
  for (scanline = fb_height; scanline < mon_height; scanline++) {
    jpeg_write_scanlines(&cinfo, row_ptr, 1);
  }

  jpeg_finish_compress(&cinfo);

  jpeg_destroy_compress(&cinfo);

  return jpg_buf;
}
#else
static void convert_rgba_to_rgb(unsigned char *buf, unsigned char *fb_mem, int width) {
  int i;
  for (i = 0; i < width; i++) {
// BGRX
    unsigned int x = *(unsigned int *)fb_mem;
    *buf++ = (x >> 16) & 0xff;
    *buf++ = (x >> 8) & 0xff;
    *buf++ = (x) & 0xff;
    fb_mem += 4;
  }
}

jpg_buf_t build_jpg_from_fb(unsigned char *fb_mem, int fb_width, int fb_height, int bits_per_pixel, int mon_width, int mon_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;

  my_jpeg_mem_dest(&cinfo, &jpg_buf.ptr, &jpg_buf.size);

  cinfo.image_width = mon_width;
  cinfo.image_height = mon_height;
  cinfo.input_components = 3;
  cinfo.in_color_space = JCS_RGB;
  jpeg_set_defaults(&cinfo);
  cinfo.dct_method = JDCT_FASTEST;
  jpeg_set_quality(&cinfo, 70, TRUE);
  
  jpeg_start_compress(&cinfo, TRUE);

  JSAMPLE buf[mon_width * 3];
  JSAMPROW row_ptr[1] = {buf};
  memset(buf, 0, mon_width*3);
  for (scanline = 0; scanline < MIN(fb_height, mon_height); scanline++) {
    convert_rgba_to_rgb(buf, &fb_mem[scanline * fb_width * 4], mon_width);
    jpeg_write_scanlines(&cinfo, row_ptr, 1);
  }
  memset(buf, 0, mon_width*3);
  for (scanline = fb_height; scanline < mon_height; scanline++) {
    jpeg_write_scanlines(&cinfo, row_ptr, 1);
  }

  jpeg_finish_compress(&cinfo);

  jpeg_destroy_compress(&cinfo);

  return jpg_buf;
}
#endif

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