jpegutils.c

来自「Motion JPEG编解码器源代码」· C语言 代码 · 共 1,145 行 · 第 1/3 页

C
1,145
字号
   /* 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. */      jpeg_destroy_decompress (&dinfo);      return -1;   }   jpeg_create_decompress (&dinfo);   jpeg_buffer_src (&dinfo, jpeg_data, len);   /* Read header, make some checks and try to figure out what the      user really wants */   jpeg_read_header (&dinfo, TRUE);   dinfo.raw_data_out = TRUE;   dinfo.out_color_space = JCS_GRAYSCALE;   dinfo.dct_method = JDCT_IFAST;   if (dinfo.jpeg_color_space != JCS_GRAYSCALE)      {       mjpeg_error( "FATAL: Expected grayscale colorspace for JPEG raw decoding");       goto ERR_EXIT;     }   guarantee_huff_tables(&dinfo);   jpeg_start_decompress (&dinfo);   hsf[0] = 1; hsf[1] = 1; hsf[2] = 1;   vsf[0]= 1; vsf[1] = 1; vsf[2] = 1;   /* Height match image height or be exact twice the image height */   if (dinfo.output_height == height) {      numfields = 1;   } else if (2 * dinfo.output_height == height) {      numfields = 2;   } else {      mjpeg_error(               "Read JPEG: requested height = %d, height of image = %d",               height, dinfo.output_height);      goto ERR_EXIT;   }   /* Width is more flexible */   if (dinfo.output_width > MAX_LUMA_WIDTH) {      mjpeg_error( "Image width of %d exceeds max",               dinfo.output_width);      goto ERR_EXIT;   }   if (width < 2 * dinfo.output_width / 3) {      /* Downsample 2:1 */      hdown = 1;      if (2 * width < dinfo.output_width)         xsl = (dinfo.output_width - 2 * width) / 2;      else         xsl = 0;   } else if (width == 2 * dinfo.output_width / 3) {      /* special case of 3:2 downsampling */      hdown = 2;      xsl = 0;   } else {      /* No downsampling */      hdown = 0;      if (width < dinfo.output_width)         xsl = (dinfo.output_width - width) / 2;      else         xsl = 0;   }   /* Make xsl even, calculate xsc */   xsl = xsl & ~1;   xsc = xsl / 2;   yl = yc = 0;   for (field = 0; field < numfields; field++) {      if (field > 0) {         jpeg_read_header (&dinfo, TRUE);         dinfo.raw_data_out = TRUE;         dinfo.out_color_space = JCS_GRAYSCALE;         dinfo.dct_method = JDCT_IFAST;         jpeg_start_decompress (&dinfo);      }      if (numfields == 2) {         switch (itype) {         case LAV_INTER_TOP_FIRST:            yl = yc = field;            break;         case LAV_INTER_BOTTOM_FIRST:            yl = yc = (1 - field);            break;         default:            mjpeg_error(                     "Input is interlaced but no interlacing set");            goto ERR_EXIT;         }      } else         yl = yc = 0;      while (dinfo.output_scanline < dinfo.output_height) {         jpeg_read_raw_data (&dinfo, scanarray, 16);         for (y = 0; y < 8 * vsf[0]; yl += numfields, y++) {            xd = yl * width;            xs = xsl;            if (hdown == 0) // no horiz downsampling               for (x = 0; x < width; x++)                  raw0[xd++] = row0[y][xs++];            else if (hdown == 1) // half the res               for (x = 0; x < width; x++, xs += 2)                  raw0[xd++] = (row0[y][xs] + row0[y][xs + 1]) >> 1;            else // 2:3 downsampling               for (x = 0; x < width / 2; x++, xd += 2, xs += 3) {                  raw0[xd] = (2 * row0[y][xs] + row0[y][xs + 1]) / 3;                  raw0[xd + 1] =                      (2 * row0[y][xs + 2] + row0[y][xs + 1]) / 3;               }         }         //mjpeg_info("/* Horizontal downsampling of chroma - in Grayscale, all this is ZERO ! */");         for (y = 0; y < 8; y++) {            xs = xsc;            if (hdown == 0)               for (x = 0; x < width / 2; x++, xs++) {		 chr1[y][x] = 0; //row1[y][xs];		 chr2[y][x] = 0; //row2[y][xs];            } else if (hdown == 1)               for (x = 0; x < width / 2; x++, xs += 2) {		 chr1[y][x] = 0; //(row1[y][xs] + row1[y][xs + 1]) >> 1;		 chr2[y][x] = 0; //(row2[y][xs] + row2[y][xs + 1]) >> 1;            } else               for (x = 0; x < width / 2; x += 2, xs += 3) {		 chr1[y][x] = 0; //(2 * row1[y][xs] + row1[y][xs + 1]) / 3;		 chr1[y][x + 1] = 0;		 //(2 * row1[y][xs + 2] + row1[y][xs + 1]) / 3;		 chr2[y][x] = 0; // (2 * row2[y][xs] + row2[y][xs + 1]) / 3;		 chr2[y][x + 1] = 0;		 //(2 * row2[y][xs + 2] + row2[y][xs + 1]) / 3;               }         }         //mjpeg_info("/* Vertical downsampling of chroma, line %d, max %d */", dinfo.output_scanline, dinfo.output_height);	 switch (ctype) {	 case CHROMA422:	   if (vsf[0] == 1) {	     /* Just copy */	     for (y = 0; y < 8 /*&& yc < height */; y++, yc += numfields) {	       xd = yc * width / 2;	       for (x = 0; x < width / 2; x++, xd++) {		 raw1[xd] = 127; //chr1[y][x];		 raw2[xd] = 127; //chr2[y][x];	       }	     }	   } else {	     /* upsample */	     for (y = 0; y < 8 /*&& yc < height */; y++) {	       xd = yc * width / 2;	       for (x = 0; x < width / 2; x++, xd++) {		 raw1[xd] = 127; //chr1[y][x];		 raw2[xd] = 127; //chr2[y][x];	       }	       yc += numfields;	       xd = yc * width / 2;	       for (x = 0; x < width / 2; x++, xd++) {		 raw1[xd] = 127; //chr1[y][x];		 raw2[xd] = 127; //chr2[y][x];	       }	       yc += numfields;	     }	   }	   break;	 default:	 /* should be case CHROMA420: but use default: for compatibility of liblavjpeg.so */	   if (vsf[0] == 1) {	     /* Really downsample */	     for (y = 0; y < 8; y += 2, yc += numfields) {	       xd = yc * width / 2;	       for (x = 0; x < width / 2; x++, xd++) {		 raw1[xd] = 127; //(chr1[y][x] + chr1[y + 1][x]) >> 1;		 raw2[xd] = 127; //(chr2[y][x] + chr2[y + 1][x]) >> 1;	       }	     }	   } else {	     /* Just copy */	     for (y = 0; y < 8; y++, yc += numfields) {	       xd = yc * width / 2;	       for (x = 0; x < width / 2; x++, xd++) {		 raw1[xd] = 127; //chr1[y][x];		 raw2[xd] = 127; //chr2[y][x];	       }	     }	   }	   break;	 }      }      (void) jpeg_finish_decompress (&dinfo);      if (field == 0 && numfields > 1)         jpeg_skip_ff (&dinfo);   }   jpeg_destroy_decompress (&dinfo);   return 0; ERR_EXIT:   jpeg_destroy_decompress (&dinfo);   return -1;}/******************************************************************* *                                                                 * *    encode_jpeg_data: Compress raw YCbCr data (output JPEG       * *                      may be interlaced                          * *                                                                 * *******************************************************************/  /* * jpeg_data:       Buffer to hold output jpeg * len:             Length of buffer * itype:           0: Not interlaced *                  1: Interlaced, Top field first *                  2: Interlaced, Bottom field first * ctype            Chroma format for decompression. *                  Currently only CHROMA420 and CHROMA422 are available */int encode_jpeg_raw (unsigned char *jpeg_data, int len, int quality,                     int itype, int ctype, int width, int height,                     unsigned char *raw0, unsigned char *raw1,                     unsigned char *raw2){   int numfields, field, yl, yc, y, i;   JSAMPROW row0[16] = { buf0[0], buf0[1], buf0[2], buf0[3],      buf0[4], buf0[5], buf0[6], buf0[7],      buf0[8], buf0[9], buf0[10], buf0[11],      buf0[12], buf0[13], buf0[14], buf0[15]   };   JSAMPROW row1[8] = { buf1[0], buf1[1], buf1[2], buf1[3],      buf1[4], buf1[5], buf1[6], buf1[7]   };   JSAMPROW row2[8] = { buf2[0], buf2[1], buf2[2], buf2[3],      buf2[4], buf2[5], buf2[6], buf2[7]   };   JSAMPARRAY scanarray[3] = { row0, row1, row2 };   struct jpeg_compress_struct cinfo;   struct my_error_mgr jerr;   /* We set up the normal JPEG error routines, then override error_exit. */   cinfo.err = jpeg_std_error (&jerr.pub);   jerr.pub.error_exit = my_error_exit;   /* 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. */      jpeg_destroy_compress (&cinfo);      return -1;   }   jpeg_create_compress (&cinfo);   jpeg_buffer_dest(&cinfo, jpeg_data, len);   /* Set some jpeg header fields */   cinfo.input_components = 3;   jpeg_set_defaults (&cinfo);   jpeg_set_quality  (&cinfo, quality, FALSE);   cinfo.raw_data_in = TRUE;   cinfo.in_color_space = JCS_YCbCr;   cinfo.dct_method = JDCT_IFAST;   cinfo.input_gamma = 1.0;   cinfo.comp_info[0].h_samp_factor = 2;   cinfo.comp_info[0].v_samp_factor = 1;	/*1||2 */   cinfo.comp_info[1].h_samp_factor = 1;   cinfo.comp_info[1].v_samp_factor = 1;   cinfo.comp_info[2].h_samp_factor = 1;	/*1||2 */   cinfo.comp_info[2].v_samp_factor = 1;   if ((width>4096)||(height>4096)) {      mjpeg_error( "Image dimensions (%dx%d) exceed lavtools' max (4096x4096)", width, height);      goto ERR_EXIT;   }   if ((width%16)||(height%16)) {      mjpeg_error( "Image dimensions (%dx%d) not multiples of 16", width, height);      goto ERR_EXIT;   }   cinfo.image_width = width;   switch (itype) {   case LAV_INTER_TOP_FIRST:   case LAV_INTER_BOTTOM_FIRST: /* interlaced */      numfields = 2;      break;   default:      numfields = 1;      if (height > 2048) {         mjpeg_error( "Image height (%d) exceeds lavtools max for non-interlaced frames", height);         goto ERR_EXIT;      }   }   cinfo.image_height = height/numfields;   yl = yc = 0;                 /* y luma, chroma */   for (field = 0; field < numfields; field++) {      jpeg_start_compress (&cinfo, FALSE);            if (numfields == 2) {         static const JOCTET marker0[40];	 jpeg_write_marker(&cinfo, JPEG_APP0,   marker0, 14);	 jpeg_write_marker(&cinfo, JPEG_APP0+1, marker0, 40);         switch (itype) {         case LAV_INTER_TOP_FIRST: /* top field first */            yl = yc = field;            break;         case LAV_INTER_BOTTOM_FIRST: /* bottom field first */            yl = yc = (1 - field);            break;         default:            mjpeg_error(                     "Input is interlaced but no interlacing set");            goto ERR_EXIT;         }      } else         yl = yc = 0;      while (cinfo.next_scanline < cinfo.image_height) {         for (y = 0; y < 8 * cinfo.comp_info[0].v_samp_factor;              yl += numfields, y++) {            row0[y] = &raw0[yl * width];         }         for (y = 0; y < 8; y++) {            row1[y] = &raw1[yc * width / 2];            row2[y] = &raw2[yc * width / 2];            if ((ctype == CHROMA422) || (y%2))               yc += numfields;         }         jpeg_write_raw_data (&cinfo, scanarray,                              8 * cinfo.comp_info[0].v_samp_factor);      }      (void) jpeg_finish_compress (&cinfo);   }      /* FIXME */   i = len - cinfo.dest->free_in_buffer;   jpeg_destroy_compress (&cinfo);   return i;   /* size of jpeg */ ERR_EXIT:   jpeg_destroy_compress (&cinfo);   return -1;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?