/* put_jpeg_yv12_memory converts an input image in the YUV420P format into a jpeg image and puts * it in a memory buffer. * Inputs: * - input_image is the image in YV12 format. * - width and height are the dimensions of the image * Output: * - dest_image is a pointer to the jpeg image buffer * Returns buffer size of jpeg image */ long put_jpeg_yv12_memory(unsigned char *dest_image,unsigned char *input_image, int width, int height,int quality){ int i, j, jpeg_image_size; JSAMPROW y[16],cb[16],cr[16]; // y[2][5] = color sample of row 2 and pixel column 5; (one plane) JSAMPARRAY data[3]; // t[0][2][5] = color sample 0 of row 2 and column 5 struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; data[0] = y; data[1] = cr; data[2] = cb; cinfo.err = jpeg_std_error(&jerr); // errors get written to stderr jpeg_create_compress(&cinfo); cinfo.image_width = width; cinfo.image_height = height/16*16; cinfo.input_components = 3; jpeg_set_defaults (&cinfo); jpeg_set_colorspace(&cinfo, JCS_YCbCr); cinfo.raw_data_in = TRUE; // supply downsampled data cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 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; cinfo.comp_info[2].v_samp_factor = 1; jpeg_set_quality(&cinfo, quality, TRUE); cinfo.dct_method = JDCT_FASTEST; jpeg_mem_dest(&cinfo, dest_image, cinfo.image_width*cinfo.image_height*3/2); // data written to mem jpeg_start_compress(&cinfo, TRUE); for (j = 0; j < cinfo.image_height; j += 16) { for (i = 0; i < 16; i++) { y[i] = input_image + width * (i + j); if (i%2 == 0) { cb[i/2] = input_image + width * height + width / 2 * ((i + j) / 2); cr[i/2] = input_image + width * height + width * height / 4 + width / 2 * ((i + j) / 2); } } jpeg_write_raw_data(&cinfo, data, 16); } jpeg_finish_compress(&cinfo); jpeg_image_size = jpeg_mem_size(&cinfo); jpeg_destroy_compress(&cinfo); return jpeg_image_size; }
/** * Do the SW jpeg encoding. * * it will convert the YUV data to P411 and then do jpeg encoding. * * \param yuv_buf: the source buffer for YUV data * \return 0 if the encoding is successful. * \return -1 if the encoding fails. */ int SWJpegEncoder::doJpegEncoding(const void* yuv_buf, int format) { LOG1("@%s", __FUNCTION__); unsigned char * srcY = NULL; unsigned char * srcU = NULL; unsigned char * srcV = NULL; JSAMPROW y[16],u[16],v[16]; JSAMPARRAY data[3]; int i, j, width, height; width= mCInfo.image_width; height=mCInfo.image_height; srcY = (unsigned char *)yuv_buf; srcV = (unsigned char *)yuv_buf + width * height; srcU = (unsigned char *)yuv_buf + width * height + width * height / 4; data[0] = y; data[1] = u; data[2] = v; for (i = 0; i < height; i += 16) { for (j = 0; j < 16 && (i + j) < height; j++) { y[j] = srcY + width * (j + i); if (j % 2 == 0) { u[j / 2] = srcU + width / 2 * ((j + i) / 2); v[j / 2] = srcV + width / 2 * ((j + i) / 2); } } jpeg_write_raw_data(&mCInfo, data, 16); } jpeg_finish_compress(&mCInfo); return 0; }
static int jpeg_encode_yuv_row(u8* output, int quality, image_data_t input) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; int i = 0; int j = 0; int written = 0; u32 size = input.width * input.height; u32 quarter_size = size / 4; u32 row = 0; JSAMPROW y[16]; JSAMPROW cb[16]; JSAMPROW cr[16]; JSAMPARRAY planes[3]; planes[0] = y; planes[1] = cb; planes[2] = cr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); dest_buffer(&cinfo, output, input.width * input.height, &written); cinfo.image_width = input.width; /* image width and height, in pixels */ cinfo.image_height = input.height; cinfo.input_components = COLOR_COMPONENTS; /* # of color components per pixel */ cinfo.in_color_space = JCS_YCbCr; /* colorspace of input image */ jpeg_set_defaults(&cinfo); cinfo.raw_data_in = TRUE; // supply downsampled data cinfo.dct_method = JDCT_IFAST; cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 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; cinfo.comp_info[2].v_samp_factor = 1; jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); jpeg_start_compress(&cinfo, TRUE); for (j = 0; j < input.height; j += 16) { for (i = 0; i < 16; i++) { row = input.width * (i + j); y[i] = input.buffer + row; if (i % 2 == 0) { cb[i/2] = input.buffer + size + row/4; cr[i/2] = input.buffer + size + quarter_size + row/4; } } jpeg_write_raw_data(&cinfo, planes, 16); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); return written; }
/* put_jpeg_yuv420p_file converts an YUV420P coded image to a jpeg image and writes * it to an already open file. * Inputs: * - image is the image in YUV420P format. * - width and height are the dimensions of the image * - quality is the jpeg encoding quality 0-100% * Output: * - The jpeg is written directly to the file given by the file pointer fp * Returns nothing */ static void put_jpeg_yuv420p_file(FILE *fp, unsigned char *image, int width, int height, int quality) { int i,j; JSAMPROW y[16],cb[16],cr[16]; // y[2][5] = color sample of row 2 and pixel column 5; (one plane) JSAMPARRAY data[3]; // t[0][2][5] = color sample 0 of row 2 and column 5 struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; data[0] = y; data[1] = cb; data[2] = cr; cinfo.err = jpeg_std_error(&jerr); // errors get written to stderr jpeg_create_compress(&cinfo); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; jpeg_set_defaults(&cinfo); jpeg_set_colorspace(&cinfo, JCS_YCbCr); cinfo.raw_data_in = TRUE; // supply downsampled data #if JPEG_LIB_VERSION >= 70 #warning using JPEG_LIB_VERSION >= 70 cinfo.do_fancy_downsampling = FALSE; // fix segfaulst with v7 #endif cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 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; cinfo.comp_info[2].v_samp_factor = 1; jpeg_set_quality(&cinfo, quality, TRUE); cinfo.dct_method = JDCT_FASTEST; jpeg_stdio_dest(&cinfo, fp); // data written to file jpeg_start_compress(&cinfo, TRUE); for (j = 0; j < height; j += 16) { for (i = 0; i < 16; i++) { y[i] = image + width * (i + j); if (i % 2 == 0) { cb[i / 2] = image + width * height + width / 2 * ((i + j) / 2); cr[i / 2] = image + width * height + width * height / 4 + width / 2 * ((i + j) /2); } } jpeg_write_raw_data(&cinfo, data, 16); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); }
int CJpegEncoder::EncodeYUV420P(const unsigned char* srcBuff, int width, int height) { if(planeHeight < height || yPlane == NULL) { free(yPlane); free(uPlane); free(vPlane); yPlane = (JSAMPARRAY) malloc(sizeof(JSAMPROW)*height); uPlane = (JSAMPARRAY) malloc(sizeof(JSAMPROW)*(height/2)); vPlane = (JSAMPARRAY) malloc(sizeof(JSAMPROW)*(height/2)); planeHeight = height; } if(setjmp(returnPoint)) { free(yPlane); yPlane = NULL; free(uPlane); uPlane = NULL; free(vPlane); vPlane = NULL; return -1; } cinfo.image_width = width; cinfo.image_height = height; cinfo.comp_info[0].h_samp_factor = cinfo.comp_info[0].v_samp_factor = 2; cinfo.comp_info[1].h_samp_factor = cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = cinfo.comp_info[2].v_samp_factor = 1; for(int i = 0; i < height; i++) yPlane[i] = (JSAMPROW) &srcBuff[i * width]; for(int i = 0; i < height/2; i++) { uPlane[i] = (JSAMPROW) &srcBuff[width * height + i * (width/2)]; vPlane[i] = (JSAMPROW) &srcBuff[width * height + (width/2) * (height/2) + i * (width/2)]; } jpeg_start_compress(&cinfo, FALSE); int y = 0; int blockrow = 0; while(y < height) { JSAMPARRAY planes[3]; planes[0] = yPlane + cinfo.comp_info[0].v_samp_factor * DCTSIZE * blockrow; planes[1] = uPlane + cinfo.comp_info[1].v_samp_factor * DCTSIZE * blockrow; planes[2] = vPlane + cinfo.comp_info[2].v_samp_factor * DCTSIZE * blockrow; jpeg_write_raw_data(&cinfo, planes, cinfo.comp_info[0].v_samp_factor * DCTSIZE); y += cinfo.comp_info[0].v_samp_factor * DCTSIZE; blockrow++; } jpeg_finish_compress(&cinfo); return 0; }
static void mjpg_420_compress(struct mjpeg_compress *h) { unsigned char **mjpg_run[3]; unsigned int y; mjpg_run[0] = h->mjpg_ptrs[0]; mjpg_run[1] = h->mjpg_ptrs[1]; mjpg_run[2] = h->mjpg_ptrs[2]; jpeg_start_compress(&h->mjpg_cinfo, h->mjpg_tables); for (y = 0; y < h->mjpg_cinfo.image_height; y += 2*DCTSIZE) { jpeg_write_raw_data(&h->mjpg_cinfo, mjpg_run,2*DCTSIZE); mjpg_run[0] += 2*DCTSIZE; mjpg_run[1] += DCTSIZE; mjpg_run[2] += DCTSIZE; } jpeg_finish_compress(&h->mjpg_cinfo); }
static void mjpg_422_compress(struct mjpeg_compress *h) { unsigned char **mjpg_run[3]; unsigned int y; mjpg_run[0] = h->mjpg_ptrs[0]; mjpg_run[1] = h->mjpg_ptrs[1]; mjpg_run[2] = h->mjpg_ptrs[2]; h->mjpg_cinfo.write_JFIF_header = FALSE; jpeg_start_compress(&h->mjpg_cinfo, h->mjpg_tables); jpeg_write_marker(&h->mjpg_cinfo, JPEG_APP0, "AVI1\0\0\0\0", 8); for (y = 0; y < h->mjpg_cinfo.image_height; y += DCTSIZE) { jpeg_write_raw_data(&h->mjpg_cinfo, mjpg_run, DCTSIZE); mjpg_run[0] += DCTSIZE; mjpg_run[1] += DCTSIZE; mjpg_run[2] += DCTSIZE; } jpeg_finish_compress(&h->mjpg_cinfo); }
/* Encodes a YUV planar frame of width "d->c->width and height "d->c->height" at "src" straight * into a JPEG frame at "dst" (must be allocated y caller). "d->len" is set to the * length of the compressed JPEG frame. "d->j" contains the JPEG compressor and * must be initialised correctly by the caller */ static void jpeg_encode_yuv420(struct v4l4j_device *d, unsigned char *src, unsigned char *dst) { //Code for this function is taken from Motion //Credit to them !!! dprint(LOG_CALLS, "[CALL] Entering %s\n",__PRETTY_FUNCTION__); JSAMPROW y[16],cb[16],cr[16]; JSAMPARRAY data[3]; int i, line, rgb_size, width, height; struct jpeg_compress_struct *cinfo = d->j->cinfo; width = d->vdev->capture->width; height = d->vdev->capture->height ; data[0] = y; data[1] = cb; data[2] = cr; //init JPEG dest mgr rgb_size = width * height * 3; d->j->destmgr->next_output_byte = dst; d->j->destmgr->free_in_buffer = rgb_size; jpeg_set_quality(cinfo,d->j->jpeg_quality,TRUE); dprint(LOG_JPEG, "[JPEG] Starting compression (%d bytes)\n", d->vdev->capture->imagesize); jpeg_start_compress(cinfo, TRUE ); for (line=0; line<height; line+=16) { for (i=0; i<16; i++) { y[i] = (unsigned char *)src + width*(i+line); if (i%2 == 0) { cb[i/2] = (unsigned char *)src + width*height + width/2*((i+line)/2); cr[i/2] = (unsigned char *)src + width*height + width*height/4 + width/2*((i+line)/2); } } jpeg_write_raw_data(cinfo, data, 16); } jpeg_finish_compress(cinfo); d->len = rgb_size - cinfo->dest->free_in_buffer; dprint(LOG_JPEG, "[JPEG] Finished compression (%d bytes)\n", d->len); }
/* Encodes a YUV planar frame of width "width and height "height" at "src" straight * into a JPEG frame at "dst" (must be allocated y caller). "len" is set to the * length of the compressed JPEG frame. "j" contains the JPEG compressor and * must be initialised correctly by the caller */ static int jpeg_encode_yuv(void *src, int src_len, struct capture_device *cdev, struct jpeg *j, void *dst) { //Code for this function is taken from Motion //Credit to them !!! JSAMPROW y[16],cb[16],cr[16]; JSAMPARRAY data[3]; int i, line, rgb_size, width = cdev->width, height = cdev->height; dprint(LOG_SOURCE_JPEG, LOG_LEVEL_DEBUG2, "Encoding a %dx%d frame\n", width, height); data[0] = y; data[1] = cb; data[2] = cr; //init JPEG dest mgr rgb_size = width * height * 3; j->destmgr.next_output_byte = dst; j->destmgr.free_in_buffer = rgb_size; jpeg_set_quality(&j->cinfo, jpeg_quality,TRUE); jpeg_start_compress( &j->cinfo, TRUE ); for (line=0; line<height; line+=16) { for (i=0; i<16; i++) { y[i] = src + width*(i+line); if (i%2 == 0) { cb[i/2] = src + width*height + width/2*((i+line)/2); cr[i/2] = src + width*height + width*height/4 + width/2*((i+line)/2); } } jpeg_write_raw_data(&j->cinfo, data, 16); } jpeg_finish_compress(&j->cinfo); dprint(LOG_SOURCE_JPEG, LOG_LEVEL_DEBUG2, "Compressed %d bytes to %d bytes\n", rgb_size, (rgb_size - j->cinfo.dest->free_in_buffer)); return rgb_size - j->cinfo.dest->free_in_buffer; }
static GstFlowReturn gst_jpegenc_chain (GstPad * pad, GstBuffer * buf) { GstFlowReturn ret; GstJpegEnc *jpegenc; guchar *data; gulong size; guint height, width; guchar *base[3], *end[3]; gint i, j, k; jpegenc = GST_JPEGENC (GST_OBJECT_PARENT (pad)); if (G_UNLIKELY (jpegenc->width <= 0 || jpegenc->height <= 0)) goto not_negotiated; data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); GST_LOG_OBJECT (jpegenc, "got buffer of %lu bytes", size); ret = gst_pad_alloc_buffer_and_set_caps (jpegenc->srcpad, GST_BUFFER_OFFSET_NONE, jpegenc->bufsize, GST_PAD_CAPS (jpegenc->srcpad), &jpegenc->output_buffer); if (ret != GST_FLOW_OK) goto done; gst_buffer_copy_metadata (jpegenc->output_buffer, buf, GST_BUFFER_COPY_TIMESTAMPS); width = jpegenc->width; height = jpegenc->height; for (i = 0; i < jpegenc->channels; i++) { base[i] = data + jpegenc->offset[i]; end[i] = base[i] + jpegenc->cheight[i] * jpegenc->stride[i]; } jpegenc->jdest.next_output_byte = GST_BUFFER_DATA (jpegenc->output_buffer); jpegenc->jdest.free_in_buffer = GST_BUFFER_SIZE (jpegenc->output_buffer); /* prepare for raw input */ #if JPEG_LIB_VERSION >= 70 jpegenc->cinfo.do_fancy_downsampling = FALSE; #endif jpegenc->cinfo.smoothing_factor = jpegenc->smoothing; jpegenc->cinfo.dct_method = jpegenc->idct_method; jpeg_set_quality (&jpegenc->cinfo, jpegenc->quality, TRUE); jpeg_start_compress (&jpegenc->cinfo, TRUE); GST_LOG_OBJECT (jpegenc, "compressing"); if (jpegenc->planar) { for (i = 0; i < height; i += jpegenc->v_max_samp * DCTSIZE) { for (k = 0; k < jpegenc->channels; k++) { for (j = 0; j < jpegenc->v_samp[k] * DCTSIZE; j++) { jpegenc->line[k][j] = base[k]; if (base[k] + jpegenc->stride[k] < end[k]) base[k] += jpegenc->stride[k]; } } jpeg_write_raw_data (&jpegenc->cinfo, jpegenc->line, jpegenc->v_max_samp * DCTSIZE); } } else { for (i = 0; i < height; i += jpegenc->v_max_samp * DCTSIZE) { for (k = 0; k < jpegenc->channels; k++) { for (j = 0; j < jpegenc->v_samp[k] * DCTSIZE; j++) { guchar *src, *dst; gint l; /* ouch, copy line */ src = base[k]; dst = jpegenc->line[k][j]; for (l = jpegenc->cwidth[k]; l > 0; l--) { *dst = *src; src += jpegenc->inc[k]; dst++; } if (base[k] + jpegenc->stride[k] < end[k]) base[k] += jpegenc->stride[k]; } } jpeg_write_raw_data (&jpegenc->cinfo, jpegenc->line, jpegenc->v_max_samp * DCTSIZE); } } /* This will ensure that gst_jpegenc_term_destination is called; we push the final output buffer from there */ jpeg_finish_compress (&jpegenc->cinfo); GST_LOG_OBJECT (jpegenc, "compressing done"); done: gst_buffer_unref (buf); return ret; /* ERRORS */ not_negotiated: { GST_WARNING_OBJECT (jpegenc, "no input format set (no caps on buffer)"); ret = GST_FLOW_NOT_NEGOTIATED; goto done; } }
void poll_frame_and_output_jpg(AVFrame *frm, AVStream *st, char *path) { //H264Context *h = st->codec->priv_data; int n = 0; for (n = 0; n < 1060; n++) { AVPacket pkt; int i = av_read_frame(ifc, &pkt); // printf("read %d, pkt: size=%d index=%d\n", // i, pkt.size, pkt.stream_index); if (pkt.stream_index != st->index) continue; int got_pic; i = avcodec_decode_video2(st->codec, frm, &got_pic, &pkt); printf("decode %d, w=%d h=%d\n", i, frm->width, frm->height); if (got_pic && frm->key_frame) break; } // YUV420P printf("format=%d\n", frm->format); printf("key_frame=%d\n", frm->key_frame); printf("linesize=%d,%d,%d\n", frm->linesize[0], frm->linesize[1], frm->linesize[2]); struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; printf("write to %s\n", path); FILE *outfile = fopen(path, "wb+"); cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, outfile); cinfo.image_width = frm->width; cinfo.image_height = frm->height; cinfo.input_components = 3; cinfo.in_color_space = JCS_YCbCr; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, 90, TRUE); cinfo.raw_data_in = TRUE; cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 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; cinfo.comp_info[2].v_samp_factor = 1; printf("dct_size=%d\n", DCTSIZE); jpeg_start_compress(&cinfo, TRUE); int i, j; JSAMPROW y[16], cb[16], cr[16]; JSAMPARRAY data[3]; data[0] = y; data[2] = cb; data[1] = cr; for (j = 0; j < cinfo.image_height; j += 16) { for (i = 0; i < 16; i++) { y[i] = frm->data[0] + frm->linesize[0]*(i+j); cr[i/2] = frm->data[1] + frm->linesize[1]*((i+j)/2); cb[i/2] = frm->data[2] + frm->linesize[2]*((i+j)/2); } jpeg_write_raw_data(&cinfo, data, 16); } jpeg_finish_compress(&cinfo); fclose(outfile); jpeg_destroy_compress(&cinfo); }
int main(int argc, char *argv[]) { long quality; const char *size; char *x; int luma_width; int luma_height; int chroma_width; int chroma_height; int frame_width; int frame_height; const char *yuv_path; const char *jpg_path; FILE *yuv_fd; size_t yuv_size; unsigned char *yuv_buffer; JSAMPLE *image_buffer; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; FILE *jpg_fd; JSAMPROW yrow_pointer[16]; JSAMPROW cbrow_pointer[8]; JSAMPROW crrow_pointer[8]; JSAMPROW *plane_pointer[3]; int y; if (argc != 5) { fprintf(stderr, "Required arguments:\n"); fprintf(stderr, "1. JPEG quality value, 0-100\n"); fprintf(stderr, "2. Image size (e.g. '512x512')\n"); fprintf(stderr, "3. Path to YUV input file\n"); fprintf(stderr, "4. Path to JPG output file\n"); return 1; } errno = 0; quality = strtol(argv[1], NULL, 10); if (errno != 0 || quality < 0 || quality > 100) { fprintf(stderr, "Invalid JPEG quality value!\n"); return 1; } size = argv[2]; x = strchr(size, 'x'); if (!x && x != size && x != (x + strlen(x) - 1)) { fprintf(stderr, "Invalid image size input!\n"); return 1; } luma_width = (int)strtol(size, NULL, 10); if (errno != 0) { fprintf(stderr, "Invalid image size input!\n"); return 1; } luma_height = (int)strtol(x + 1, NULL, 10); if (errno != 0) { fprintf(stderr, "Invalid image size input!\n"); return 1; } if (luma_width <= 0 || luma_height <= 0) { fprintf(stderr, "Invalid image size input!\n"); return 1; } chroma_width = (luma_width + 1) >> 1; chroma_height = (luma_height + 1) >> 1; /* Will check these for validity when opening via 'fopen'. */ yuv_path = argv[3]; jpg_path = argv[4]; yuv_fd = fopen(yuv_path, "r"); if (!yuv_fd) { fprintf(stderr, "Invalid path to YUV file!\n"); return 1; } fseek(yuv_fd, 0, SEEK_END); yuv_size = ftell(yuv_fd); fseek(yuv_fd, 0, SEEK_SET); /* Check that the file size matches 4:2:0 yuv. */ if (yuv_size != (size_t)luma_width*luma_height + 2*chroma_width*chroma_height) { fprintf(stderr, "Unexpected input format!\n"); return 1; } yuv_buffer = malloc(yuv_size); if (!yuv_buffer) { fprintf(stderr, "Memory allocation failure!\n"); return 1; } if (fread(yuv_buffer, yuv_size, 1, yuv_fd) != 1) { fprintf(stderr, "Error reading yuv file\n"); }; fclose(yuv_fd); frame_width = (luma_width + (16 - 1)) & ~(16 - 1); frame_height = (luma_height + (16 - 1)) & ~(16 - 1); image_buffer = malloc(frame_width*frame_height + 2*(frame_width/2)*(frame_height/2)); if (!image_buffer) { fprintf(stderr, "Memory allocation failure!\n"); return 1; } extend_edge(image_buffer, frame_width, frame_height, yuv_buffer, luma_width, luma_height, chroma_width, chroma_height); free(yuv_buffer); cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpg_fd = fopen(jpg_path, "wb"); if (!jpg_fd) { fprintf(stderr, "Invalid path to JPEG file!\n"); free(image_buffer); return 1; } jpeg_stdio_dest(&cinfo, jpg_fd); cinfo.image_width = luma_width; cinfo.image_height = luma_height; cinfo.input_components = 3; cinfo.in_color_space = JCS_YCbCr; jpeg_set_defaults(&cinfo); cinfo.raw_data_in = TRUE; cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 2; cinfo.comp_info[0].dc_tbl_no = 0; cinfo.comp_info[0].ac_tbl_no = 0; cinfo.comp_info[0].quant_tbl_no = 0; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[1].dc_tbl_no = 1; cinfo.comp_info[1].ac_tbl_no = 1; cinfo.comp_info[1].quant_tbl_no = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; cinfo.comp_info[2].dc_tbl_no = 1; cinfo.comp_info[2].ac_tbl_no = 1; cinfo.comp_info[2].quant_tbl_no = 1; jpeg_set_quality(&cinfo, quality, TRUE); cinfo.optimize_coding = TRUE; jpeg_start_compress(&cinfo, TRUE); plane_pointer[0] = yrow_pointer; plane_pointer[1] = cbrow_pointer; plane_pointer[2] = crrow_pointer; while (cinfo.next_scanline < cinfo.image_height) { int scanline; scanline = cinfo.next_scanline; for (y = 0; y < 16; y++) { yrow_pointer[y] = &image_buffer[frame_width*(scanline + y)]; } for (y = 0; y < 8; y++) { cbrow_pointer[y] = &image_buffer[frame_width*frame_height + (frame_width/2)*((scanline/2) + y)]; crrow_pointer[y] = &image_buffer[frame_width*frame_height + (frame_width/2)*(frame_height/2) + (frame_width/2)*((scanline/2) + y)]; } jpeg_write_raw_data(&cinfo, plane_pointer, 16); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); free(image_buffer); fclose(jpg_fd); return 0; }
static bool_t jpeg_enc_yv12(char* buffer, int width, int height, int quality, char* filename) { char fname[128] ; static int framenum = 0; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; FILE *outfile = NULL; bool_t ret = TRUE; if(buffer == NULL || width <=0 || height <=0|| filename == NULL) return FALSE; #ifdef __MINGW32__ //sprintf(fname, "%s-%d.jpg", filename, framenum++); sprintf(fname, "%s.jpg", filename); #else sprintf(fname, "%s-%d.jpg", filename, framenum++); #endif #ifdef WIN32 if ((outfile = fopen(fname, "wb")) == NULL) { return FALSE; } #else if ((outfile = fopen(fname, "r+x")) == NULL) { return FALSE; } #endif // WIN32 cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, outfile); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_YCbCr; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); cinfo.raw_data_in = TRUE; { JSAMPARRAY pp[3]; JSAMPROW *rpY = (JSAMPROW*)malloc(sizeof(JSAMPROW) * height); JSAMPROW *rpU = (JSAMPROW*)malloc(sizeof(JSAMPROW) * height); JSAMPROW *rpV = (JSAMPROW*)malloc(sizeof(JSAMPROW) * height); int k; if(rpY == NULL && rpU == NULL && rpV == NULL) { ret = FALSE; goto exit; } cinfo.comp_info[0].h_samp_factor = cinfo.comp_info[0].v_samp_factor = 2; cinfo.comp_info[1].h_samp_factor = cinfo.comp_info[1].v_samp_factor = cinfo.comp_info[2].h_samp_factor = cinfo.comp_info[2].v_samp_factor = 1; jpeg_start_compress(&cinfo, TRUE); for (k = 0; k < height; k+=2) { rpY[k] = buffer + k*width; rpY[k+1] = buffer + (k+1)*width; rpU[k/2] = buffer+width*height + (k/2)*width/2; rpV[k/2] = buffer+width*height*5/4 + (k/2)*width/2; } for (k = 0; k < height; k+=2*DCTSIZE) { pp[0] = &rpY[k]; pp[1] = &rpU[k/2]; pp[2] = &rpV[k/2]; jpeg_write_raw_data(&cinfo, pp, 2*DCTSIZE); } jpeg_finish_compress(&cinfo); free(rpY); free(rpU); free(rpV); } exit: fclose(outfile); jpeg_destroy_compress(&cinfo); return ret; }
static void compress_and_post(Instance *pi, int width, int height, uint8_t *c1, uint8_t *c2, uint8_t *c3, Image_common *c, int compress_mode) { /* Compress input buffer. See "libjpeg.txt" in IJPEG source, and "cjpeg.c". */ CJpeg_private *priv = (CJpeg_private *)pi; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; Jpeg_buffer *jpeg_out = 0L; double t1, t2; int report_time = 0; if (0) printf("%s:%s(width=%d height=%d c1=%p c2=%p c3=%p)\n", __FILE__, __func__, width, height, c1, c2, c3); cti_getdoubletime(&t1); cinfo.err = jpeg_std_error(&jerr); /* NOTE: See ERREXIT, error_exit, this may cause the program to call exit()! */ jpeg_create_compress(&cinfo); jpeg_out = Jpeg_buffer_new(0, 0L); /* Pass 0 to let libjpeg allocate output buffer */ jpeg_out->width = width; jpeg_out->height = height; if (c->timestamp == 0.0) { jpeg_out->c.timestamp = t1; /* Save timestamp. */ } if (compress_mode == COMPRESS_Y422 || compress_mode == COMPRESS_Y420) { int w2 = (width/8)*8; int h2 = (height/8)*8; if (w2 != width) { fprintf(stderr, "warning: truncating width from %d to %d\n", width, w2); jpeg_out->width = w2; } if (h2 != height) { fprintf(stderr, "warning: truncating height from %d to %d\n", height, h2); jpeg_out->height = h2; } // jpeg_out->tv = y422p_in->tv; } jpeg_mem_dest(&cinfo, &jpeg_out->data, &jpeg_out->encoded_length); /* NOTE: It turns out there is actually no need for jinit_read_mem() [rdmem.c], just set the pointers in the encode loop! */ cinfo.image_width = jpeg_out->width; cinfo.image_height = jpeg_out->height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; /* reset below if y422p or y420p*/ jpeg_set_defaults(&cinfo); /* See "Raw (downsampled) image data" section in libjpeg.txt. */ if (compress_mode == COMPRESS_Y422) { cinfo.raw_data_in = TRUE; jpeg_set_colorspace(&cinfo, JCS_YCbCr); cinfo.do_fancy_downsampling = FALSE; // http://www.lavrsen.dk/svn/motion/trunk/picture.c cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 1; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; } else if (compress_mode == COMPRESS_Y420) { cinfo.raw_data_in = TRUE; jpeg_set_colorspace(&cinfo, JCS_YCbCr); cinfo.do_fancy_downsampling = FALSE; // http://www.lavrsen.dk/svn/motion/trunk/picture.c cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 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; cinfo.comp_info[2].v_samp_factor = 1; } /* Various options can be set here... */ //cinfo.dct_method = JDCT_FLOAT; cinfo.dct_method = priv->dct_method; /* Ah, we have to set this up here! */ jpeg_set_quality (&cinfo, priv->adjusted_quality, TRUE); jpeg_start_compress(&cinfo, TRUE); while (cinfo.next_scanline < cinfo.image_height) { if (compress_mode == COMPRESS_Y422) { int n; /* Setup necessary for raw downsampled data. */ JSAMPROW y[16]; JSAMPROW cb[16]; JSAMPROW cr[16]; for (n=0; n < 16; n++) { y[n] = c1 + ((cinfo.next_scanline+n)* width); cb[n] = c2 + ((cinfo.next_scanline+n) * width / 2); cr[n] = c3 + ((cinfo.next_scanline+n) * width / 2); } JSAMPARRAY array[3] = { y, cb, cr}; JSAMPIMAGE image = array; /* Need to pass enough lines at a time, see "(num_lines < lines_per_iMCU_row)" test in jcapistd.c */ jpeg_write_raw_data(&cinfo, image, 16); } else if (compress_mode == COMPRESS_Y420) { int n; /* Setup necessary for raw downsampled data. */ // fprintf(stderr, "420 cinfo.next_scanline=%d\n", cinfo.next_scanline); JSAMPROW y[16]; JSAMPROW cb[16]; JSAMPROW cr[16]; for (n=0; n < 16; n++) { y[n] = c1 + ((cinfo.next_scanline+n)* width); cb[n] = c2 + (((cinfo.next_scanline/2)+n) * width / 2); cr[n] = c3 + (((cinfo.next_scanline/2)+n) * width / 2); } JSAMPARRAY array[3] = { y, cb, cr}; JSAMPIMAGE image = array; /* Need to pass enough lines at a time, see "(num_lines < lines_per_iMCU_row)" test in jcapistd.c */ jpeg_write_raw_data(&cinfo, image, 16); } else { JSAMPROW row_pointer[1]; /* pointer to a single row */ row_pointer[0] = c1 + (cinfo.next_scanline * width * 3); jpeg_write_scanlines(&cinfo, row_pointer, 1); } } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); // fprintf(stderr, "jpeg_out->encoded_length=%lu\n", jpeg_out->encoded_length); if (pi->outputs[OUTPUT_JPEG].destination) { PostData(jpeg_out, pi->outputs[OUTPUT_JPEG].destination); } else { /* Discard output buffer! */ Jpeg_buffer_release(jpeg_out); } jpeg_out = 0L; /* Clear output buffer copy. */ /* Calculate compress time. */ cti_getdoubletime(&t2); double tdiff = (t2 - t1); if (pi->counter % (30) == 0) { dpf("tdiff=%.5f\n", tdiff); } if ((priv->time_limit > 0.0) && (tdiff > priv->time_limit)) { /* Compress time went over time limit, call sched_yield(), which should prevent starving other threads, most importantly video and audio capture. Frames will back up on this thread, but on systems like 1.6GHz P4 which can just barely handle 640x480@30fps, it tends to even out. */ sched_yield(); /* Turn down quality. */ if (priv->adjusted_quality > 50) { priv->adjusted_quality -= 5; } report_time = 1; } else if (priv->adjusted_quality < priv->quality) { /* Ratchet quality back up, but only by 2, we don't "ping-pong" +/- 5. */ int temp = priv->adjusted_quality + 2; priv->adjusted_quality = cti_min(temp, priv->quality); report_time = 1; } if (report_time) { dpf("* %.5f (q=%d)\n", tdiff, priv->adjusted_quality); } }
int CJpegEncoder::EncodeYUV420SP(const unsigned char* srcBuff, int width, int height) { if(width == -1 || height == -1) { width = frameWidth; height = frameHeight; } if(planeHeight < height || yPlane == NULL) { free(yPlane); free(uPlane); free(vPlane); yPlane = (JSAMPARRAY) malloc( sizeof(JSAMPROW) * height); uPlane = (JSAMPARRAY) malloc( sizeof(JSAMPROW) * (height/2) ); vPlane = (JSAMPARRAY) malloc( sizeof(JSAMPROW) * (height/2) ); planeHeight = height; } if(planeDataSize < (width/2) * (height/2) || uPlaneData == NULL) { free(uPlaneData); free(vPlaneData); planeDataSize = (width/2) * (height/2); uPlaneData = (JSAMPROW) malloc(planeDataSize); vPlaneData = (JSAMPROW) malloc(planeDataSize); } if(setjmp(returnPoint)) { free(uPlaneData); uPlaneData = NULL; free(vPlaneData); vPlaneData = NULL; free(yPlane); yPlane = NULL; free(uPlane); uPlane = NULL; free(vPlane); vPlane = NULL; return -1; } cinfo.image_width = width; cinfo.image_height = height; cinfo.comp_info[0].h_samp_factor = cinfo.comp_info[0].v_samp_factor = 2; cinfo.comp_info[1].h_samp_factor = cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = cinfo.comp_info[2].v_samp_factor = 1; // for(int i = 0; i < height; i++) yPlane[i] = (JSAMPROW) &srcBuff[i * width]; for(int i = 0; i < height/2; i++) { uPlane[i] = &uPlaneData[i * (width/2)]; vPlane[i] = &vPlaneData[i * (width/2)]; } JSAMPROW cbPtr = uPlaneData; JSAMPROW crPtr = vPlaneData; JSAMPROW inPtr = (JSAMPROW) &srcBuff[width * height]; for(int i = 0; i < planeDataSize; i++) { *cbPtr++ = inPtr[0]; *crPtr++ = inPtr[1]; inPtr += 2; } jpeg_start_compress(&cinfo, FALSE); int y = 0; int blockrow = 0; while(y < height) { JSAMPARRAY planes[3]; planes[0] = yPlane + cinfo.comp_info[0].v_samp_factor * DCTSIZE * blockrow; // planes[1] = uPlane + cinfo.comp_info[1].v_samp_factor * DCTSIZE * blockrow; // planes[2] = vPlane + cinfo.comp_info[2].v_samp_factor * DCTSIZE * blockrow; planes[1] = vPlane + cinfo.comp_info[1].v_samp_factor * DCTSIZE * blockrow; planes[2] = uPlane + cinfo.comp_info[2].v_samp_factor * DCTSIZE * blockrow; jpeg_write_raw_data(&cinfo, planes, cinfo.comp_info[0].v_samp_factor * DCTSIZE); y += cinfo.comp_info[0].v_samp_factor * DCTSIZE; blockrow++; } jpeg_finish_compress(&cinfo); return 0; }
/** * put_jpeg_yuv420p_file * Converts an YUV420P coded image to a jpeg image and writes * it to an already open file. * * Inputs: * - image is the image in YUV420P format. * - width and height are the dimensions of the image * - quality is the jpeg encoding quality 0-100% * * Output: * - The jpeg is written directly to the file given by the file pointer fp * * Returns nothing */ static void put_jpeg_yuv420p_file(FILE *fp, uint8_t *image[3], y4m_stream_info_t *si, int quality) { int i, j; JSAMPROW y[16],cb[16],cr[16]; // y[2][5] = color sample of row 2 and pixel column 5; (one plane) JSAMPARRAY data[3]; // t[0][2][5] = color sample 0 of row 2 and column 5 struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; y4m_ratio_t pixelaspect; int w,h,cw,ch; data[0] = y; data[1] = cb; data[2] = cr; // fprintf (stderr,"TRACE: put_jpeg_yuv420p_file in\n"); cinfo.err = jpeg_std_error(&jerr); // Errors get written to stderr ch = y4m_si_get_plane_height(si,0) / y4m_si_get_plane_height(si,1); cw = y4m_si_get_plane_width(si,0) / y4m_si_get_plane_width(si,1); h = y4m_si_get_plane_height(si,0); w = y4m_si_get_plane_width(si,0); jpeg_create_compress(&cinfo); cinfo.image_width = w; cinfo.image_height = h; cinfo.input_components = 3; jpeg_set_defaults(&cinfo); jpeg_set_colorspace(&cinfo, JCS_YCbCr); cinfo.raw_data_in = TRUE; // Supply downsampled data #if JPEG_LIB_VERSION >= 70 #warning using JPEG_LIB_VERSION >= 70 cinfo.do_fancy_downsampling = FALSE; // Fix segfault with v7 #endif pixelaspect = y4m_si_get_sampleaspect(si); cinfo.X_density = pixelaspect.n; cinfo.Y_density = pixelaspect.d; cinfo.comp_info[0].h_samp_factor = cw; cinfo.comp_info[0].v_samp_factor = ch; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; jpeg_set_quality(&cinfo, quality, TRUE); cinfo.dct_method = JDCT_FASTEST; jpeg_stdio_dest(&cinfo, fp); // Data written to file jpeg_start_compress(&cinfo, TRUE); // fprintf (stderr,"jpeg write for j\n"); for (j = 0; j < h; j += 16) { for (i = 0; i < 16; i++) { y[i] = image[0] + cinfo.image_width * (i + j); // need to handle other chroma subsampling if (i % ch == 0) { cb[i / ch] = image[1] + w / cw * ((i + j) / cw); cr[i / ch] = image[2] + w / cw * ((i + j) / cw); } } // fprintf (stderr,"jpeg write raw data\n"); jpeg_write_raw_data(&cinfo, data, 16); // fprintf (stderr,"jpeg write raw data finish\n"); } // fprintf (stderr,"jpeg finish compress\n"); jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); }
/* * EncodeBlock */ static block_t *EncodeBlock(encoder_t *p_enc, picture_t *p_pic) { encoder_sys_t *p_sys = p_enc->p_sys; if (unlikely(!p_pic)) { return NULL; } block_t *p_block = block_Alloc(p_sys->i_blocksize); if (p_block == NULL) { return NULL; } JSAMPIMAGE p_row_pointers = NULL; unsigned long size = p_block->i_buffer; /* libjpeg longjmp's there in case of error */ if (setjmp(p_sys->setjmp_buffer)) { goto error; } jpeg_create_compress(&p_sys->p_jpeg); jpeg_mem_dest(&p_sys->p_jpeg, &p_block->p_buffer, &size); p_sys->p_jpeg.image_width = p_enc->fmt_in.video.i_visible_width; p_sys->p_jpeg.image_height = p_enc->fmt_in.video.i_visible_height; p_sys->p_jpeg.input_components = 3; p_sys->p_jpeg.in_color_space = JCS_YCbCr; jpeg_set_defaults(&p_sys->p_jpeg); jpeg_set_colorspace(&p_sys->p_jpeg, JCS_YCbCr); p_sys->p_jpeg.raw_data_in = TRUE; #if JPEG_LIB_VERSION >= 70 p_sys->p_jpeg.do_fancy_downsampling = FALSE; #endif jpeg_set_quality(&p_sys->p_jpeg, p_sys->i_quality, TRUE); jpeg_start_compress(&p_sys->p_jpeg, TRUE); /* Encode picture */ p_row_pointers = malloc(sizeof(JSAMPARRAY) * p_pic->i_planes); if (p_row_pointers == NULL) { goto error; } for (int i = 0; i < p_pic->i_planes; i++) { p_row_pointers[i] = malloc(sizeof(JSAMPROW) * p_sys->p_jpeg.comp_info[i].v_samp_factor * DCTSIZE); } while (p_sys->p_jpeg.next_scanline < p_sys->p_jpeg.image_height) { for (int i = 0; i < p_pic->i_planes; i++) { int i_offset = p_sys->p_jpeg.next_scanline * p_sys->p_jpeg.comp_info[i].v_samp_factor / p_sys->p_jpeg.max_v_samp_factor; for (int j = 0; j < p_sys->p_jpeg.comp_info[i].v_samp_factor * DCTSIZE; j++) { p_row_pointers[i][j] = p_pic->p[i].p_pixels + p_pic->p[i].i_pitch * (i_offset + j); } } jpeg_write_raw_data(&p_sys->p_jpeg, p_row_pointers, p_sys->p_jpeg.max_v_samp_factor * DCTSIZE); } jpeg_finish_compress(&p_sys->p_jpeg); jpeg_destroy_compress(&p_sys->p_jpeg); for (int i = 0; i < p_pic->i_planes; i++) { free(p_row_pointers[i]); } free(p_row_pointers); p_block->i_buffer = size; p_block->i_dts = p_block->i_pts = p_pic->date; return p_block; error: jpeg_destroy_compress(&p_sys->p_jpeg); if (p_row_pointers != NULL) { for (int i = 0; i < p_pic->i_planes; i++) { free(p_row_pointers[i]); } } free(p_row_pointers); block_Release(p_block); return NULL; }
int V4L2Camera:: yuv420_to_jpeg(unsigned char *data, int width, int height, FILE *fp, int quality) { #if USE_HW_JPG_LIB PRINT_DEBUG_MSG; int fileSize = 0; int ret = emxx_yuv_to_jpeg(data,width,height,fp,quality,OMF_MC_JPEGD_SAMPLING22); if (ret != 0) { LOGE("yuv file convert to jpeg file failed!!!!"); } fseek(fp, 0, SEEK_END); fileSize = ftell(fp); #else PRINT_DEBUG_MSG; int fileSize = 0; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; int row_stride; JSAMPIMAGE buffer; unsigned char *pSrc,*pDst; int band,i,buf_width[3],buf_height[3]; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, fp); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE ); cinfo.raw_data_in = TRUE; cinfo.jpeg_color_space = JCS_YCbCr; cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 2; jpeg_start_compress(&cinfo, TRUE); buffer = (JSAMPIMAGE) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_IMAGE, 3 * sizeof(JSAMPARRAY)); for (band=0; band <3; band++) { buf_width[band] = cinfo.comp_info[band].width_in_blocks * DCTSIZE; buf_height[band] = cinfo.comp_info[band].v_samp_factor * DCTSIZE; buffer[band] = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, buf_width[band], buf_height[band]); } unsigned char *rawData[3]; rawData[0]=data; rawData[1]=data+width*height; rawData[2]=data+width*height*5/4; int src_width[3],src_height[3]; for (int i=0;i<3;i++){ src_width[i]=(i==0)?width:width/2; src_height[i]=(i==0)?height:height/2; } int max_line = cinfo.max_v_samp_factor*DCTSIZE; for (int counter=0; cinfo.next_scanline < cinfo.image_height; counter++) { //buffer image copy. for (band=0; band <3; band++){ int mem_size = src_width[band]; pDst = (unsigned char *) buffer[band][0]; pSrc = (unsigned char *) rawData[band] + counter*buf_height[band] * src_width[band]; for (i=0; i <buf_height[band]; i++){ memcpy(pDst, pSrc, mem_size); pSrc += src_width[band]; pDst += buf_width[band]; } } jpeg_write_raw_data(&cinfo, buffer, max_line); } jpeg_finish_compress(&cinfo); fileSize = ftell(fp); jpeg_destroy_compress(&cinfo); #endif return fileSize; }
int main (int argc, char **argv) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; #ifdef PROGRESS_REPORT struct cdjpeg_progress_mgr progress; #endif int file_index; cjpeg_source_ptr src_mgr; FILE * input_file; FILE * output_file = NULL; unsigned char *outbuffer = NULL; unsigned long outsize = 0; JDIMENSION num_scanlines; /* On Mac, fetch a command line. */ #ifdef USE_CCOMMAND argc = ccommand(&argv); #endif progname = argv[0]; if (progname == NULL || progname[0] == 0) progname = "cjpeg"; /* in case C library doesn't provide it */ /* Initialize the JPEG compression object with default error handling. */ cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); /* Add some application-specific error messages (from cderror.h) */ jerr.addon_message_table = cdjpeg_message_table; jerr.first_addon_message = JMSG_FIRSTADDONCODE; jerr.last_addon_message = JMSG_LASTADDONCODE; /* Now safe to enable signal catcher. */ #ifdef NEED_SIGNAL_CATCHER enable_signal_catcher((j_common_ptr) &cinfo); #endif /* Initialize JPEG parameters. * Much of this may be overridden later. * In particular, we don't yet know the input file's color space, * but we need to provide some value for jpeg_set_defaults() to work. */ cinfo.in_color_space = JCS_RGB; /* arbitrary guess */ cinfo.use_moz_defaults = TRUE; jpeg_set_defaults(&cinfo); /* Scan command line to find file names. * It is convenient to use just one switch-parsing routine, but the switch * values read here are ignored; we will rescan the switches after opening * the input file. */ file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); #ifdef TWO_FILE_COMMANDLINE if (!memdst) { /* Must have either -outfile switch or explicit output file name */ if (outfilename == NULL) { if (file_index != argc-2) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } outfilename = argv[file_index+1]; } else { if (file_index != argc-1) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } } } #else /* Unix style: expect zero or one file name */ if (file_index < argc-1) { fprintf(stderr, "%s: only one input file\n", progname); usage(); } #endif /* TWO_FILE_COMMANDLINE */ /* Open the input file. */ if (file_index < argc) { if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); exit(EXIT_FAILURE); } } else { /* default input file is stdin */ input_file = read_stdin(); } /* Open the output file. */ if (outfilename != NULL) { if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, outfilename); exit(EXIT_FAILURE); } } else if (!memdst) { /* default output file is stdout */ output_file = write_stdout(); } #ifdef PROGRESS_REPORT start_progress_monitor((j_common_ptr) &cinfo, &progress); #endif /* Figure out the input file format, and set up to read it. */ src_mgr = select_file_type(&cinfo, input_file); src_mgr->input_file = input_file; /* Read the input file header to obtain file size & colorspace. */ (*src_mgr->start_input) (&cinfo, src_mgr); /* Now that we know input colorspace, fix colorspace-dependent defaults */ #if JPEG_RAW_READER if (!is_jpeg) #endif jpeg_default_colorspace(&cinfo); /* Adjust default compression parameters by re-parsing the options */ file_index = parse_switches(&cinfo, argc, argv, 0, TRUE); /* Specify data destination for compression */ #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) if (memdst) jpeg_mem_dest(&cinfo, &outbuffer, &outsize); else #endif jpeg_stdio_dest(&cinfo, output_file); /* Start compressor */ jpeg_start_compress(&cinfo, TRUE); /* Copy metadata */ if (is_jpeg) { jpeg_saved_marker_ptr marker; /* In the current implementation, we don't actually need to examine the * option flag here; we just copy everything that got saved. * But to avoid confusion, we do not output JFIF and Adobe APP14 markers * if the encoder library already wrote one. */ for (marker = src_mgr->marker_list; marker != NULL; marker = marker->next) { if (cinfo.write_JFIF_header && marker->marker == JPEG_APP0 && marker->data_length >= 5 && GETJOCTET(marker->data[0]) == 0x4A && GETJOCTET(marker->data[1]) == 0x46 && GETJOCTET(marker->data[2]) == 0x49 && GETJOCTET(marker->data[3]) == 0x46 && GETJOCTET(marker->data[4]) == 0) continue; /* reject duplicate JFIF */ if (cinfo.write_Adobe_marker && marker->marker == JPEG_APP0+14 && marker->data_length >= 5 && GETJOCTET(marker->data[0]) == 0x41 && GETJOCTET(marker->data[1]) == 0x64 && GETJOCTET(marker->data[2]) == 0x6F && GETJOCTET(marker->data[3]) == 0x62 && GETJOCTET(marker->data[4]) == 0x65) continue; /* reject duplicate Adobe */ jpeg_write_marker(&cinfo, marker->marker, marker->data, marker->data_length); } } /* Process data */ while (cinfo.next_scanline < cinfo.image_height) { num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); #if JPEG_RAW_READER if (is_jpeg) (void) jpeg_write_raw_data(&cinfo, src_mgr->plane_pointer, num_scanlines); else #endif (void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines); } /* Finish compression and release memory */ (*src_mgr->finish_input) (&cinfo, src_mgr); jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); /* Close files, if we opened them */ if (input_file != stdin) fclose(input_file); if (output_file != stdout && output_file != NULL) fclose(output_file); #ifdef PROGRESS_REPORT end_progress_monitor((j_common_ptr) &cinfo); #endif if (memdst) { fprintf(stderr, "Compressed size: %lu bytes\n", outsize); if (outbuffer != NULL) free(outbuffer); } /* All done. */ exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); return 0; /* suppress no-return-value warnings */ }
// native YUV jpeg encoder code based on encode_JPEG of the quicktime4linux lib // static void write_yuv_JPEG_file(char *filename, int quality, unsigned char **input, int _width, int _height) { int i, j, k; int width = _width; int height = _height; unsigned char *base[3]; struct jpeg_compress_struct encinfo; struct jpeg_error_mgr jerr; FILE * outfile; /* target file */ jpeg_create_compress(&encinfo); encinfo.err = jpeg_std_error(&jerr); if ((outfile = fopen(filename, "wb")) == NULL) { tc_log_error(MOD_NAME, "can't open %s", filename); } jpeg_stdio_dest(&encinfo, outfile); encinfo.image_width = width; encinfo.image_height = height; encinfo.input_components = 3; jpeg_set_defaults(&encinfo); encinfo.dct_method = JDCT_FASTEST; jpeg_set_quality(&encinfo, quality, TRUE); encinfo.raw_data_in = TRUE; encinfo.in_color_space = JCS_YCbCr; encinfo.comp_info[0].h_samp_factor = 2; encinfo.comp_info[0].v_samp_factor = 2; encinfo.comp_info[1].h_samp_factor = 1; encinfo.comp_info[1].v_samp_factor = 1; encinfo.comp_info[2].h_samp_factor = 1; encinfo.comp_info[2].v_samp_factor = 1; jpeg_start_compress(&encinfo, TRUE); base[0] = input[0]; base[1] = input[1]; base[2] = input[2]; for (i = 0; i < height; i += 2*DCTSIZE) { for (j=0, k=0; j<2*DCTSIZE;j+=2, k++) { line[0][j] = base[0]; base[0] += width; line[0][j+1] = base[0]; base[0] += width; line[1][k] = base[1]; base[1] += width/2; line[2][k] = base[2]; base[2] += width/2; } jpeg_write_raw_data(&encinfo, line, 2*DCTSIZE); } jpeg_finish_compress(&encinfo); fclose(outfile); jpeg_destroy_compress(&encinfo); }