"Fossies" - the Fresh Open Source Software Archive

Member "motion-Release-4.3.0/src/jpegutils.c" (14 Jan 2020, 23384 Bytes) of package /linux/misc/motion-Release-4.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "jpegutils.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  *  jpegutils.c: Some Utility programs for dealing with JPEG encoded images
    3  *
    4  *  Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
    5  *  Copyright (C) 2001 pHilipp Zabel  <pzabel@gmx.de>
    6  *  Copyright (C) 2008 Angel Carpintero <motiondevelop@gmail.com>
    7  *
    8  *  based on jdatasrc.c and jdatadst.c from the Independent
    9  *  JPEG Group's software by Thomas G. Lane
   10  *
   11  *  This program is free software; you can redistribute it and/or
   12  *  modify it under the terms of the GNU General Public License
   13  *  as published by the Free Software Foundation; either version 2
   14  *  of the License, or (at your option) any later version.
   15  *
   16  *  This program is distributed in the hope that it will be useful,
   17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19  *  GNU General Public License for more details.
   20  *
   21  *  You should have received a copy of the GNU General Public License
   22  *  along with this program; if not, write to the Free Software
   23  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   24  */
   25 
   26  /*
   27  * jpegutils.c
   28  *  Purpose:
   29  *    Decompress jpeg data into images for use in other parts of program.
   30  *    Currently this module only decompresses and it is only called from
   31  *    the vid_mjpegtoyuv420p function
   32  *  Functional Prefixes
   33  *    All functions within the module will use the prefix "jpgutl" for identification
   34  *  Module Level Variables:
   35  *    EOI_data    Constant value to indicate the end of an image.
   36  *  Module Level Structures:
   37  *    jpgutl_error_mgr  Used by the JPEG libraries as the error manager to catch/trap messages from library.
   38  *  Static Functions:
   39  *    The following functions are required by the JPEG library to decompress images.
   40  *      jpgutl_init_source
   41  *      jpgutl_fill_input_buffer
   42  *      jpgutl_skip_data
   43  *      jpgutl_term_source
   44  *      jpgutl_buffer_src
   45  *      jpgutl_error_exit
   46  *      jpgutl_emit_message
   47  *  Exposed Functions
   48  *    jpgutl_decode_jpeg
   49  */
   50 
   51 #include "translate.h"
   52 #include "config.h"
   53 #include "motion.h"
   54 #include "jpegutils.h"
   55 #include "picture.h"    /* For the prepare_exif */
   56 #include <setjmp.h>
   57 
   58 
   59 /* This is a workaround regarding these defines.  The config.h file defines
   60  * HAVE_STDLIB_H as 1 whereas the jpeglib.h just defines it without a value.
   61  * this causes massive warnings/error on mis-matched definitions.  We do not
   62  * control either of these so we have to suffer through this workaround hack
   63 */
   64 #if (HAVE_STDLIB_H == 1)
   65     #undef HAVE_STDLIB_H
   66     #define HAVE_STDLIB_H_ORIG 1
   67 #endif
   68 
   69 #include <jpeglib.h>
   70 
   71 #ifdef HAVE_STDLIB_H
   72   #ifdef HAVE_STDLIB_H_ORIG
   73     #undef HAVE_STDLIB_H
   74     #undef HAVE_STDLIB_H_ORIG
   75     #define HAVE_STDLIB_H 1
   76   #else
   77     #undef HAVE_STDLIB_H
   78   #endif
   79 #endif
   80 
   81 
   82 
   83 #include <jerror.h>
   84 #include <assert.h>
   85 
   86 static const uint8_t EOI_data[2] = { 0xFF, 0xD9 };
   87 
   88 struct jpgutl_error_mgr {
   89     struct jpeg_error_mgr pub;   /* "public" fields */
   90     jmp_buf setjmp_buffer;       /* For return to caller */
   91 
   92     /* Original emit_message method. */
   93     JMETHOD(void, original_emit_message, (j_common_ptr cinfo, int msg_level));
   94     /* Was a corrupt-data warning seen. */
   95     int warning_seen;
   96 };
   97 
   98 /*  These huffman tables are required by the old jpeg libs included with 14.04 */
   99 static void add_huff_table(j_decompress_ptr dinfo, JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val){
  100 /* Define a Huffman table */
  101     int nsymbols, len;
  102 
  103     if (*htblptr == NULL)
  104         *htblptr = jpeg_alloc_huff_table((j_common_ptr) dinfo);
  105 
  106     /* Copy the number-of-symbols-of-each-code-length counts. */
  107     memcpy((*htblptr)->bits, bits, sizeof((*htblptr)->bits));
  108 
  109     /*
  110      * Validate the counts.  We do this here mainly so we can copy the right
  111      * number of symbols from the val[] array, without risking marching off
  112      * the end of memory.  jchuff.c will do a more thorough test later.
  113      */
  114     nsymbols = 0;
  115 
  116     for (len = 1; len <= 16; len++)
  117         nsymbols += bits[len];
  118 
  119     if (nsymbols < 1 || nsymbols > 256)
  120         MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, _("%s: Given jpeg buffer was too small"));
  121 
  122     memcpy((*htblptr)->huffval, val, nsymbols * sizeof(UINT8));
  123 }
  124 
  125 static void std_huff_tables (j_decompress_ptr dinfo){
  126 /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
  127 /* IMPORTANT: these are only valid for 8-bit data precision! */
  128 
  129     static const UINT8 bits_dc_luminance[17] =
  130     { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
  131     static const UINT8 val_dc_luminance[] =
  132     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
  133 
  134     static const UINT8 bits_dc_chrominance[17] =
  135     { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
  136     static const UINT8 val_dc_chrominance[] =
  137     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
  138 
  139     static const UINT8 bits_ac_luminance[17] =
  140     { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
  141     static const UINT8 val_ac_luminance[] =
  142     { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
  143       0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
  144       0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
  145       0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
  146       0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
  147       0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
  148       0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
  149       0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
  150       0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
  151       0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
  152       0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
  153       0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
  154       0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
  155       0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
  156       0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
  157       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
  158       0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
  159       0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
  160       0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
  161       0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
  162       0xf9, 0xfa };
  163 
  164     static const UINT8 bits_ac_chrominance[17] =
  165     { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
  166     static const UINT8 val_ac_chrominance[] =
  167     { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
  168       0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
  169       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
  170       0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
  171       0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
  172       0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
  173       0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
  174       0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
  175       0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
  176       0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
  177       0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
  178       0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
  179       0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
  180       0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
  181       0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
  182       0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
  183       0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
  184       0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
  185       0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
  186       0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
  187       0xf9, 0xfa };
  188 
  189     add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[0],
  190                    bits_dc_luminance, val_dc_luminance);
  191     add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[0],
  192                    bits_ac_luminance, val_ac_luminance);
  193     add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[1],
  194                    bits_dc_chrominance, val_dc_chrominance);
  195     add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[1],
  196                    bits_ac_chrominance, val_ac_chrominance);
  197 }
  198 
  199 static void guarantee_huff_tables(j_decompress_ptr dinfo)
  200 {
  201     if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) &&
  202         (dinfo->dc_huff_tbl_ptrs[1] == NULL) &&
  203         (dinfo->ac_huff_tbl_ptrs[0] == NULL) &&
  204         (dinfo->ac_huff_tbl_ptrs[1] == NULL)) {
  205         std_huff_tables(dinfo);
  206     }
  207 }
  208 
  209 /*
  210  * Initialize source --- called by jpeg_read_header
  211  * before any data is actually read.
  212  */
  213 static void jpgutl_init_source(j_decompress_ptr cinfo ATTRIBUTE_UNUSED)
  214 {
  215     /* No work necessary here */
  216 }
  217 
  218 /*
  219  * Fill the input buffer --- called whenever buffer is emptied.
  220  *
  221  * Should never be called since all data should be already provided.
  222  * Is nevertheless sometimes called - sets the input buffer to data
  223  * which is the JPEG EOI marker;
  224  *
  225  */
  226 static boolean jpgutl_fill_input_buffer(j_decompress_ptr cinfo)
  227 {
  228     cinfo->src->next_input_byte = EOI_data;
  229     cinfo->src->bytes_in_buffer = 2;
  230     return TRUE;
  231 }
  232 
  233 /*
  234  * Skip data --- used to skip over a potentially large amount of
  235  * uninteresting data (such as an APPn marker).
  236  *
  237  */
  238 static void jpgutl_skip_data(j_decompress_ptr cinfo, long num_bytes)
  239 {
  240     if (num_bytes > 0) {
  241         if (num_bytes > (long) cinfo->src->bytes_in_buffer)
  242             num_bytes = (long) cinfo->src->bytes_in_buffer;
  243         cinfo->src->next_input_byte += (size_t) num_bytes;
  244         cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
  245     }
  246 }
  247 
  248 /*
  249  * Terminate source --- called by jpeg_finish_decompress
  250  * after all data has been read.  Often a no-op.
  251  */
  252 static void jpgutl_term_source(j_decompress_ptr cinfo ATTRIBUTE_UNUSED)
  253 {
  254     /* No work necessary here */
  255 }
  256 
  257 /*
  258  * The source object and input buffer are made permanent so that a series
  259  * of JPEG images can be read from the same buffer by calling jpgutl_buffer_src
  260  * only before the first one.  (If we discarded the buffer at the end of
  261  * one image, we'd likely lose the start of the next one.)
  262  * This makes it unsafe to use this manager and a different source
  263  * manager serially with the same JPEG object.  Caveat programmer.
  264  */
  265 /**
  266  * jpgutl_buffer_src
  267  *  Purpose:
  268  *    Establish the input buffer source for the JPEG libary and associated helper functions.
  269  *  Parameters:
  270  *    cinfo      The jpeg library compression/decompression information
  271  *    buffer     The buffer of JPEG data to decompress.
  272  *    buffer_len The length of the buffer.
  273  *  Return values:
  274  *    None
  275  */
  276 static void jpgutl_buffer_src(j_decompress_ptr cinfo, unsigned char *buffer, long buffer_len)
  277 {
  278 
  279     if (cinfo->src == NULL) {    /* First time for this JPEG object? */
  280         cinfo->src = (struct jpeg_source_mgr *)
  281                      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
  282                      sizeof (struct jpeg_source_mgr));
  283     }
  284 
  285     cinfo->src->init_source = jpgutl_init_source;
  286     cinfo->src->fill_input_buffer = jpgutl_fill_input_buffer;
  287     cinfo->src->skip_input_data = jpgutl_skip_data;
  288     cinfo->src->resync_to_restart = jpeg_resync_to_restart;    /* Use default method */
  289     cinfo->src->term_source = jpgutl_term_source;
  290     cinfo->src->bytes_in_buffer = buffer_len;
  291     cinfo->src->next_input_byte = (JOCTET *) buffer;
  292 
  293 
  294 }
  295 
  296 /**
  297  * jpgutl_error_exit
  298  *  Purpose:
  299  *    Exit routine for errors thrown by JPEG library.
  300  *  Parameters:
  301  *    cinfo      The jpeg library compression/decompression information
  302  *  Return values:
  303  *    None
  304  */
  305 static void jpgutl_error_exit(j_common_ptr cinfo)
  306 {
  307     char buffer[JMSG_LENGTH_MAX];
  308 
  309     /* cinfo->err really points to a jpgutl_error_mgr struct, so coerce pointer. */
  310     struct jpgutl_error_mgr *myerr = (struct jpgutl_error_mgr *) cinfo->err;
  311 
  312     /*
  313      * Always display the message.
  314      * We could postpone this until after returning, if we chose.
  315      */
  316     (*cinfo->err->format_message) (cinfo, buffer);
  317 
  318     MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "%s", buffer);
  319 
  320     /* Return control to the setjmp point. */
  321     longjmp (myerr->setjmp_buffer, 1);
  322 }
  323 
  324 /**
  325  * jpgutl_emit_message
  326  *  Purpose:
  327  *    Process the messages thrown by the JPEG library
  328  *  Parameters:
  329  *    cinfo      The jpeg library compression/decompression information
  330  *    msg_level  Integer indicating the severity of the message.
  331  *  Return values:
  332  *    None
  333  */
  334 static void jpgutl_emit_message(j_common_ptr cinfo, int msg_level)
  335 {
  336     char buffer[JMSG_LENGTH_MAX];
  337     /* cinfo->err really points to a jpgutl_error_mgr struct, so coerce pointer. */
  338     struct jpgutl_error_mgr *myerr = (struct jpgutl_error_mgr *) cinfo->err;
  339     /*
  340      *  The JWRN_EXTRANEOUS_DATA is sent a lot without any particular negative effect.
  341      *  There are some messages above zero but they are just informational and not something
  342      *  that we are interested in.
  343     */
  344     if ((cinfo->err->msg_code != JWRN_EXTRANEOUS_DATA) && (msg_level < 0) ) {
  345         myerr->warning_seen++ ;
  346         (*cinfo->err->format_message) (cinfo, buffer);
  347             MOTION_LOG(DBG, TYPE_VIDEO, NO_ERRNO, "msg_level: %d, %s", msg_level, buffer);
  348     }
  349 
  350 }
  351 
  352 /*
  353  * The following declarations and 5 functions are jpeg related
  354  * functions used by put_jpeg_grey_memory and put_jpeg_yuv420p_memory.
  355  */
  356 typedef struct {
  357     struct jpeg_destination_mgr pub;
  358     JOCTET *buf;
  359     size_t bufsize;
  360     size_t jpegsize;
  361 } mem_destination_mgr;
  362 
  363 typedef mem_destination_mgr *mem_dest_ptr;
  364 
  365 
  366 METHODDEF(void) init_destination(j_compress_ptr cinfo)
  367 {
  368     mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
  369     dest->pub.next_output_byte = dest->buf;
  370     dest->pub.free_in_buffer = dest->bufsize;
  371     dest->jpegsize = 0;
  372 }
  373 
  374 METHODDEF(boolean) empty_output_buffer(j_compress_ptr cinfo)
  375 {
  376     mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
  377     dest->pub.next_output_byte = dest->buf;
  378     dest->pub.free_in_buffer = dest->bufsize;
  379 
  380     return FALSE;
  381     ERREXIT(cinfo, JERR_BUFFER_SIZE);
  382 }
  383 
  384 METHODDEF(void) term_destination(j_compress_ptr cinfo)
  385 {
  386     mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
  387     dest->jpegsize = dest->bufsize - dest->pub.free_in_buffer;
  388 }
  389 
  390 static GLOBAL(void) _jpeg_mem_dest(j_compress_ptr cinfo, JOCTET* buf, size_t bufsize)
  391 {
  392     mem_dest_ptr dest;
  393 
  394     if (cinfo->dest == NULL) {
  395         cinfo->dest = (struct jpeg_destination_mgr *)
  396                       (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT,
  397                        sizeof(mem_destination_mgr));
  398     }
  399 
  400     dest = (mem_dest_ptr) cinfo->dest;
  401 
  402     dest->pub.init_destination    = init_destination;
  403     dest->pub.empty_output_buffer = empty_output_buffer;
  404     dest->pub.term_destination    = term_destination;
  405 
  406     dest->buf      = buf;
  407     dest->bufsize  = bufsize;
  408     dest->jpegsize = 0;
  409 }
  410 
  411 static GLOBAL(int) _jpeg_mem_size(j_compress_ptr cinfo)
  412 {
  413     mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
  414     return dest->jpegsize;
  415 }
  416 
  417 /*
  418  * put_jpeg_exif writes the EXIF APP1 chunk to the jpeg file.
  419  * It must be called after jpeg_start_compress() but before
  420  * any image data is written by jpeg_write_scanlines().
  421  */
  422 static void put_jpeg_exif(j_compress_ptr cinfo,
  423               const struct context *cnt,
  424               const struct timeval *tv1,
  425               const struct coord *box)
  426 {
  427     unsigned char *exif = NULL;
  428     unsigned exif_len = prepare_exif(&exif, cnt, tv1, box);
  429 
  430     if(exif_len > 0) {
  431         /* EXIF data lives in a JPEG APP1 marker */
  432         jpeg_write_marker(cinfo, JPEG_APP0 + 1, exif, exif_len);
  433         free(exif);
  434     }
  435 }
  436 
  437 
  438 /**
  439  * jpgutl_decode_jpeg
  440  *  Purpose:  Decompress the jpeg data_in into the img_out buffer.
  441  *
  442  *  Parameters:
  443  *  jpeg_data_in     The jpeg data sent in
  444  *  jpeg_data_len    The length of the jpeg data
  445  *  width            The width of the image
  446  *  height           The height of the image
  447  *  img_out          Pointer to the image output
  448  *
  449  *  Return Values
  450  *    Success 0, Failure -1
  451  */
  452 int jpgutl_decode_jpeg (unsigned char *jpeg_data_in, int jpeg_data_len,
  453                      unsigned int width, unsigned int height, unsigned char *volatile img_out)
  454 {
  455     JSAMPARRAY      line;           /* Array of decomp data lines */
  456     unsigned char  *wline;          /* Will point to line[0] */
  457     unsigned int    i;
  458     unsigned char  *img_y, *img_cb, *img_cr;
  459     unsigned char   offset_y;
  460 
  461     struct jpeg_decompress_struct dinfo;
  462     struct jpgutl_error_mgr jerr;
  463 
  464     /* We set up the normal JPEG error routines, then override error_exit. */
  465     dinfo.err = jpeg_std_error (&jerr.pub);
  466     jerr.pub.error_exit = jpgutl_error_exit;
  467     /* Also hook the emit_message routine to note corrupt-data warnings. */
  468     jerr.original_emit_message = jerr.pub.emit_message;
  469     jerr.pub.emit_message = jpgutl_emit_message;
  470     jerr.warning_seen = 0;
  471 
  472     jpeg_create_decompress (&dinfo);
  473 
  474     /* Establish the setjmp return context for jpgutl_error_exit to use. */
  475     if (setjmp (jerr.setjmp_buffer)) {
  476         /* If we get here, the JPEG code has signaled an error. */
  477         jpeg_destroy_decompress (&dinfo);
  478         return -1;
  479     }
  480 
  481     jpgutl_buffer_src (&dinfo, jpeg_data_in, jpeg_data_len);
  482 
  483     jpeg_read_header (&dinfo, TRUE);
  484 
  485     //420 sampling is the default for YCbCr so no need to override.
  486     dinfo.out_color_space = JCS_YCbCr;
  487     dinfo.dct_method = JDCT_DEFAULT;
  488     guarantee_huff_tables(&dinfo);  /* Required by older versions of the jpeg libs */
  489     jpeg_start_decompress (&dinfo);
  490 
  491     if ((dinfo.output_width == 0) || (dinfo.output_height == 0)) {
  492         MOTION_LOG(WRN, TYPE_VIDEO, NO_ERRNO,_("Invalid JPEG image dimensions"));
  493         jpeg_destroy_decompress(&dinfo);
  494         return -1;
  495     }
  496 
  497     if ((dinfo.output_width != width) || (dinfo.output_height != height)) {
  498         MOTION_LOG(WRN, TYPE_VIDEO, NO_ERRNO
  499             ,_("JPEG image size %dx%d, JPEG was %dx%d")
  500             ,width, height, dinfo.output_width, dinfo.output_height);
  501         jpeg_destroy_decompress(&dinfo);
  502         return -1;
  503     }
  504 
  505     img_y  = img_out;
  506     img_cb = img_y + dinfo.output_width * dinfo.output_height;
  507     img_cr = img_cb + (dinfo.output_width * dinfo.output_height) / 4;
  508 
  509     /* Allocate space for one line. */
  510     line = (*dinfo.mem->alloc_sarray)((j_common_ptr) &dinfo, JPOOL_IMAGE,
  511                                        dinfo.output_width * dinfo.output_components, 1);
  512 
  513     wline = line[0];
  514     offset_y = 0;
  515 
  516     while (dinfo.output_scanline < dinfo.output_height) {
  517         jpeg_read_scanlines(&dinfo, line, 1);
  518 
  519         for (i = 0; i < (dinfo.output_width * 3); i += 3) {
  520             img_y[i / 3] = wline[i];
  521             if (i & 1) {
  522                 img_cb[(i / 3) / 2] = wline[i + 1];
  523                 img_cr[(i / 3) / 2] = wline[i + 2];
  524             }
  525         }
  526 
  527         img_y += dinfo.output_width;
  528 
  529         if (offset_y++ & 1) {
  530             img_cb += dinfo.output_width / 2;
  531             img_cr += dinfo.output_width / 2;
  532         }
  533     }
  534 
  535     jpeg_finish_decompress(&dinfo);
  536     jpeg_destroy_decompress(&dinfo);
  537 
  538     /*
  539      * If there are too many warnings, this means that
  540      * only a partial image could be returned which would
  541      * trigger many false positive motion detections
  542     */
  543     if (jerr.warning_seen > 2) return -1;
  544 
  545     return 0;
  546 
  547 }
  548 
  549 int jpgutl_put_yuv420p(unsigned char *dest_image, int image_size,
  550                    unsigned char *input_image, int width, int height, int quality,
  551                    struct context *cnt, struct timeval *tv1, struct coord *box)
  552 
  553 {
  554     int i, j, jpeg_image_size;
  555 
  556     JSAMPROW y[16],cb[16],cr[16]; // y[2][5] = color sample of row 2 and pixel column 5; (one plane)
  557     JSAMPARRAY data[3]; // t[0][2][5] = color sample 0 of row 2 and column 5
  558 
  559     struct jpeg_compress_struct cinfo;
  560     struct jpgutl_error_mgr jerr;
  561 
  562     data[0] = y;
  563     data[1] = cb;
  564     data[2] = cr;
  565 
  566     cinfo.err = jpeg_std_error (&jerr.pub);
  567     jerr.pub.error_exit = jpgutl_error_exit;
  568     /* Also hook the emit_message routine to note corrupt-data warnings. */
  569     jerr.original_emit_message = jerr.pub.emit_message;
  570     jerr.pub.emit_message = jpgutl_emit_message;
  571     jerr.warning_seen = 0;
  572 
  573     jpeg_create_compress(&cinfo);
  574 
  575     /* Establish the setjmp return context for jpgutl_error_exit to use. */
  576     if (setjmp (jerr.setjmp_buffer)) {
  577         /* If we get here, the JPEG code has signaled an error. */
  578         jpeg_destroy_compress (&cinfo);
  579         return -1;
  580     }
  581 
  582     cinfo.image_width = width;
  583     cinfo.image_height = height;
  584     cinfo.input_components = 3;
  585     jpeg_set_defaults(&cinfo);
  586 
  587     jpeg_set_colorspace(&cinfo, JCS_YCbCr);
  588 
  589     cinfo.raw_data_in = TRUE; // Supply downsampled data
  590 #if JPEG_LIB_VERSION >= 70
  591     cinfo.do_fancy_downsampling = FALSE;  // Fix segfault with v7
  592 #endif
  593     cinfo.comp_info[0].h_samp_factor = 2;
  594     cinfo.comp_info[0].v_samp_factor = 2;
  595     cinfo.comp_info[1].h_samp_factor = 1;
  596     cinfo.comp_info[1].v_samp_factor = 1;
  597     cinfo.comp_info[2].h_samp_factor = 1;
  598     cinfo.comp_info[2].v_samp_factor = 1;
  599 
  600     jpeg_set_quality(&cinfo, quality, TRUE);
  601     cinfo.dct_method = JDCT_FASTEST;
  602 
  603     _jpeg_mem_dest(&cinfo, dest_image, image_size);  // Data written to mem
  604 
  605 
  606     jpeg_start_compress(&cinfo, TRUE);
  607 
  608     put_jpeg_exif(&cinfo, cnt, tv1, box);
  609 
  610     /* If the image is not a multiple of 16, this overruns the buffers
  611      * we'll just pad those last bytes with zeros
  612      */
  613     for (j = 0; j < height; j += 16) {
  614         for (i = 0; i < 16; i++) {
  615             if ((width * (i + j)) < (width * height)) {
  616                 y[i] = input_image + width * (i + j);
  617                 if (i % 2 == 0) {
  618                     cb[i / 2] = input_image + width * height + width / 2 * ((i + j) /2);
  619                     cr[i / 2] = input_image + width * height + width * height / 4 + width / 2 * ((i + j) / 2);
  620                 }
  621             } else {
  622                 y[i] = 0x00;
  623                 cb[i] = 0x00;
  624                 cr[i] = 0x00;
  625             }
  626         }
  627         jpeg_write_raw_data(&cinfo, data, 16);
  628     }
  629 
  630     jpeg_finish_compress(&cinfo);
  631     jpeg_image_size = _jpeg_mem_size(&cinfo);
  632     jpeg_destroy_compress(&cinfo);
  633 
  634     return jpeg_image_size;
  635 }
  636 
  637 
  638 int jpgutl_put_grey(unsigned char *dest_image, int image_size,
  639                    unsigned char *input_image, int width, int height, int quality,
  640                    struct context *cnt, struct timeval *tv1, struct coord *box)
  641 {
  642     int y, dest_image_size;
  643     JSAMPROW row_ptr[1];
  644     struct jpeg_compress_struct cjpeg;
  645     struct jpgutl_error_mgr jerr;
  646 
  647     cjpeg.err = jpeg_std_error (&jerr.pub);
  648     jerr.pub.error_exit = jpgutl_error_exit;
  649     /* Also hook the emit_message routine to note corrupt-data warnings. */
  650     jerr.original_emit_message = jerr.pub.emit_message;
  651     jerr.pub.emit_message = jpgutl_emit_message;
  652     jerr.warning_seen = 0;
  653 
  654     jpeg_create_compress(&cjpeg);
  655 
  656     /* Establish the setjmp return context for jpgutl_error_exit to use. */
  657     if (setjmp (jerr.setjmp_buffer)) {
  658         /* If we get here, the JPEG code has signaled an error. */
  659         jpeg_destroy_compress (&cjpeg);
  660         return -1;
  661     }
  662 
  663     cjpeg.image_width = width;
  664     cjpeg.image_height = height;
  665     cjpeg.input_components = 1; /* One colour component */
  666     cjpeg.in_color_space = JCS_GRAYSCALE;
  667 
  668     jpeg_set_defaults(&cjpeg);
  669 
  670     jpeg_set_quality(&cjpeg, quality, TRUE);
  671     cjpeg.dct_method = JDCT_FASTEST;
  672     _jpeg_mem_dest(&cjpeg, dest_image, image_size);  // Data written to mem
  673 
  674     jpeg_start_compress (&cjpeg, TRUE);
  675 
  676     put_jpeg_exif(&cjpeg, cnt, tv1, box);
  677 
  678     row_ptr[0] = input_image;
  679 
  680     for (y = 0; y < height; y++) {
  681         jpeg_write_scanlines(&cjpeg, row_ptr, 1);
  682         row_ptr[0] += width;
  683     }
  684 
  685     jpeg_finish_compress(&cjpeg);
  686     dest_image_size = _jpeg_mem_size(&cjpeg);
  687     jpeg_destroy_compress(&cjpeg);
  688 
  689     return dest_image_size;
  690 }
  691