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 + -
显示快捷键?