/* 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; }
result save(void) { // Set error manager struct jpeg_compress_struct compressor; compressor.err = &error_manager; if (setjmp(catch)) { jpeg_destroy_compress(&compressor); return LibJPEG_error_message; } // Initialize compression structure unsigned long new_data_length = data_length; jpeg_create_compress(&compressor); jpeg_mem_dest(&compressor, &data_buffer, &new_data_length); LibEph5_write(&context, &compressor); jpeg_finish_compress(&compressor); data_length = new_data_length; // Clean up jpeg_destroy_compress(&compressor); return result_OK; }
// http://stackoverflow.com/a/2296662 size_t compress_rgb(uint8_t * in, uint8_t * out, int width, int height) { struct jpeg_compress_struct cinfo = { 0 }; struct jpeg_error_mgr jerr; JSAMPROW row_ptr[1]; int row_stride; unsigned long int length = 0; unsigned char * output = NULL; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo, &output, &length); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_start_compress(&cinfo, TRUE); row_stride = width * 3; while (cinfo.next_scanline < cinfo.image_height) { row_ptr[0] = &out[cinfo.next_scanline * row_stride]; jpeg_write_scanlines(&cinfo, row_ptr, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); memcpy(out, output, length); return length; }
/* * Compress RGB buffer in memory */ int RGB_2_JPEG(unsigned char *buffer, unsigned char **compressed, long unsigned int *new_len, int quality) { struct jpeg_compress_struct cinfo = {0}; struct jpeg_error_mgr jerr; JSAMPROW row_ptr[1]; int row_stride; *compressed = NULL; *new_len = 0; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo, compressed, new_len); cinfo.image_width = 640; cinfo.image_height = 480; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); jpeg_start_compress(&cinfo, TRUE); row_stride = 640 * 3; while (cinfo.next_scanline < cinfo.image_height) { row_ptr[0] = &buffer[cinfo.next_scanline * row_stride]; jpeg_write_scanlines(&cinfo, row_ptr, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); return 1; }
/* * See: http://msdn.microsoft.com/en-us/library/dd145119%28VS.85%29.aspx * This function was copied from the MSDN example. * It was then modified to send the BMP data rather than save to disk * It was then modified to conver the BMP to JPEG and send * Now its realy big. */ int bmp2jpeg(PBYTE buf, int quality, BYTE ** buf_jpeg, DWORD * buf_jpeg_size ) { // Convert to JPEG stuff struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cjpeg_source_ptr src_mgr; JDIMENSION num_scanlines; // JPEG conversion start here..' // buf is a pointer to a BMP in memory. /* Initialize JPEG parameters. * Much of this may be overridden later. * We need to provide some value for jpeg_set_defaults() to work. */ cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); cinfo.in_color_space = JCS_RGB; /* arbitrary guess */ jpeg_set_defaults(&cinfo); src_mgr = jinit_read_bmp(&cinfo); //Returns a cjpeg_source_ptr but is really bmp_source_ptr... src_mgr->input_buf = buf; src_mgr->read_offset = 0; /* Read the input file header to obtain file size & colorspace. */ start_input_bmp(&cinfo, src_mgr); jpeg_default_colorspace(&cinfo); // TODO: accept options from the command line for grayscale and quality. /* Go GRAYSCALE */ //jpeg_set_colorspace(&cinfo, JCS_GRAYSCALE); /* Quality */ jpeg_set_quality(&cinfo, quality, FALSE); // Write the compressed JPEG to memory: bug_jpeg jpeg_mem_dest(&cinfo, buf_jpeg, buf_jpeg_size); /* Start compressor */ jpeg_start_compress(&cinfo, TRUE); /* Process data */ while (cinfo.next_scanline < cinfo.image_height) { num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); (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); return 1; }
/////////////////////////////////////////////////////////////// // // JpegEncode // // XRGB to jpeg // /////////////////////////////////////////////////////////////// bool JpegEncode ( uint uiWidth, uint uiHeight, uint uiQuality, const void* pData, uint uiDataSize, CBuffer& outBuffer ) { // Validate if ( uiDataSize == 0 || uiDataSize != uiWidth * uiHeight * 4 ) return false; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); unsigned long memlen = 0; unsigned char *membuffer = NULL; jpeg_mem_dest (&cinfo,&membuffer,&memlen ); cinfo.image_width = uiWidth; /* image width and height, in pixels */ cinfo.image_height = uiHeight; cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ jpeg_set_defaults(&cinfo); jpeg_set_quality (&cinfo, uiQuality, true); cinfo.dct_method = JDCT_IFAST; /* Start compressor */ jpeg_start_compress(&cinfo, TRUE); /* Process data */ CBuffer rowBuffer; rowBuffer.SetSize ( uiWidth * 3 ); char* pRowTemp = rowBuffer.GetData (); JSAMPROW row_pointer[1]; while (cinfo.next_scanline < cinfo.image_height) { BYTE* pRowSrc = (BYTE*)pData + cinfo.next_scanline * uiWidth * 4; for ( uint i = 0 ; i < uiWidth ; i++ ) { pRowTemp[i*3+0] = pRowSrc[i*4+2]; pRowTemp[i*3+1] = pRowSrc[i*4+1]; pRowTemp[i*3+2] = pRowSrc[i*4+0]; } row_pointer[0] = (JSAMPROW)pRowTemp; (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); } /* Finish compression and release memory */ jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); // Copy out data and free memory outBuffer = CBuffer ( membuffer, memlen ); free ( membuffer ); return true; }
void VideoCompressorThread::stoppableRun() { while(!shouldStop) { // JPEG-related stuff struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer; unsigned char* jpgBuf=NULL; unsigned long jpgBufLen=0; unsigned char* data; ChunkAttrib chunkAttrib; // Get raw image from the input buffer data = inpBuf->getChunk(&chunkAttrib); // Initialize JPEG cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo, &jpgBuf, &jpgBufLen); // Set the parameters of the output file cinfo.image_width = VIDEO_WIDTH; cinfo.image_height = VIDEO_HEIGHT; cinfo.input_components = (color ? 3 : 1); cinfo.in_color_space = (color ? JCS_RGB : JCS_GRAYSCALE); // Use default compression parameters jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, jpgQuality, TRUE); // Do the compression jpeg_start_compress(&cinfo, TRUE); // write one row at a time while(cinfo.next_scanline < cinfo.image_height) { row_pointer = (data + (cinfo.next_scanline * cinfo.image_width * (color ? 3 : 1))); jpeg_write_scanlines(&cinfo, &row_pointer, 1); } // clean up after we're done compressing jpeg_finish_compress(&cinfo); // Insert compressed image into the output buffer chunkAttrib.chunkSize = jpgBufLen; outBuf->insertChunk(jpgBuf, chunkAttrib); // The output buffer needs to be explicitly freed by the libjpeg client free(jpgBuf); jpeg_destroy_compress(&cinfo); } }
ImageBuffer compress_jpeg(ImageConf imageConf, uint8_t * buffer, int out_width, int out_height) { ImageBuffer f; f.buffer = NULL; f.size = 0; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; int row_stride; unsigned long outlen = OUTPUT_BUF_SIZE; unsigned char *outbuffer = malloc(outlen); if ( !buffer ) { printf("Error buffer null\n"); return f; } cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_mem_dest (&cinfo, &outbuffer, &outlen); cinfo.image_width = out_width; cinfo.image_height = out_height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); cinfo.write_JFIF_header = TRUE; cinfo.JFIF_major_version = 1; cinfo.JFIF_minor_version = 2; cinfo.density_unit = 1; cinfo.write_Adobe_marker = TRUE; jpeg_set_quality(&cinfo, imageConf.quality, imageConf.baseline); cinfo.optimize_coding = imageConf.optimize; cinfo.smoothing_factor = imageConf.smooth; jpeg_simple_progression(&cinfo); jpeg_start_compress(&cinfo, TRUE); row_stride = out_width * 3; while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = &buffer[cinfo.next_scanline * row_stride]; (void)jpeg_write_scanlines(&cinfo, row_pointer,1); } my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo.dest; jpeg_finish_compress(&cinfo); f.buffer = outbuffer; f.size = outlen; jpeg_destroy_compress(&cinfo); return f; }
/** * Encodes an RGB-buffer to a JPEG. * * @param rgb_buffer An RGB image. * @param rgb_width Width of the image, pixels. * @param rgb_height Height of the image, pixels. * @param quality Quality: 0-100. * @param out_buffer Encoded image (JPEG) [must be freed by the called via `free`]. * @param out_size Size of the encoded image, bytes. * @param out_msg An error message, if any [must be freed by the caller via `free`]. * @return 0 if there is no error, otherwise a error code, see 'jerror.h' for details. */ int encode_jpeg(unsigned char* rgb_buffer, unsigned int rgb_width, unsigned int rgb_height, int quality, unsigned char** out_buffer, unsigned int* out_size, char** out_msg) { unsigned char* out_buffer_ret = NULL; unsigned long out_size_ret = 0; struct jpeg_compress_struct cinfo; struct basic_jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr.handler); jerr.handler.error_exit = handle_exit; if (setjmp(jerr.setjmp_buffer)) { int result = jerr.handler.msg_code; *out_msg = strdup(jerr.msg_str); jpeg_destroy_compress(&cinfo); if(out_buffer_ret) { free(out_buffer_ret); } return result; } jpeg_create_compress(&cinfo); cinfo.image_width = rgb_width; cinfo.image_height = rgb_height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); jpeg_mem_dest(&cinfo, &out_buffer_ret, &out_size_ret); jpeg_start_compress(&cinfo, TRUE); JSAMPROW row_pointer[1]; int row_stride = rgb_width * 3; while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = &rgb_buffer[cinfo.next_scanline * row_stride]; jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); *out_buffer = out_buffer_ret; *out_size = (unsigned int)out_size_ret; return 0; }
void screenshotJPEG(char *filename, qbyte *screendata, int screenwidth, int screenheight) //input is rgb NOT rgba { qbyte *buffer; vfsfile_t *outfile; jpeg_error_mgr_wrapper jerr; struct jpeg_compress_struct cinfo; JSAMPROW row_pointer[1]; if (!(outfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY))) { FS_CreatePath (filename, FS_GAME); if (!(outfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY))) { Con_Printf("Error opening %s\n", filename); return; } } cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = jpeg_error_exit; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_compress(&cinfo); VFS_CLOSE(outfile); FS_Remove(filename, FS_GAME); Con_Printf("Failed to create jpeg\n"); return; } jpeg_create_compress(&cinfo); buffer = screendata; jpeg_mem_dest(&cinfo, outfile); cinfo.image_width = screenwidth; cinfo.image_height = screenheight; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality (&cinfo, 75/*bound(0, (int) gl_image_jpeg_quality_level.value, 100)*/, true); jpeg_start_compress(&cinfo, true); while (cinfo.next_scanline < cinfo.image_height) { *row_pointer = &buffer[(cinfo.image_height - cinfo.next_scanline - 1) * cinfo.image_width * 3]; jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_finish_compress(&cinfo); VFS_CLOSE(outfile); jpeg_destroy_compress(&cinfo); }
/* --------------------------------------------------------------------------- ** convert yuyv -> jpeg ** -------------------------------------------------------------------------*/ unsigned long yuyv2jpeg(char* image_buffer, unsigned int width, unsigned int height, unsigned int quality) { struct jpeg_error_mgr jerr; struct jpeg_compress_struct cinfo; jpeg_create_compress(&cinfo); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.err = jpeg_std_error(&jerr); unsigned char* dest = NULL; unsigned long destsize = 0; jpeg_mem_dest(&cinfo, &dest, &destsize); jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); jpeg_start_compress(&cinfo, TRUE); unsigned char bufline[cinfo.image_width * 3]; while (cinfo.next_scanline < cinfo.image_height) { // convert line from YUYV -> YUV for (unsigned int i = 0; i < cinfo.image_width; i += 2) { unsigned int base = cinfo.next_scanline*cinfo.image_width * 2 ; bufline[i*3 ] = image_buffer[base + i*2 ]; bufline[i*3+1] = image_buffer[base + i*2+1]; bufline[i*3+2] = image_buffer[base + i*2+3]; bufline[i*3+3] = image_buffer[base + i*2+2]; bufline[i*3+4] = image_buffer[base + i*2+1]; bufline[i*3+5] = image_buffer[base + i*2+3]; } JSAMPROW row = bufline; jpeg_write_scanlines(&cinfo, &row, 1); } jpeg_finish_compress(&cinfo); if (dest != NULL) { if (destsize < width*height*2) { memcpy(image_buffer, dest, destsize); } else { LOG(WARN) << "Buffer to small size:" << width*height*2 << " " << destsize; } free(dest); } jpeg_destroy_compress(&cinfo); return destsize; }
/** int write_jpeg_mem(unsigned char** buf, unsigned long* len, JPEGImage jp, int qulty) jp の画像データを *bufに書き出す.*bufは要 free @param[out] buf 画像データが格納される.要 free @param[out] len buf の長さ(Byte)が格納される. @param jp 保存する JPEGデータ @param qulty 保存のクオリティ 0〜100 100が最高画質 @retval ERROR_GRAPH_OPFILE ファイルオープンエラー @retval ERROR_GRAPH_HEADER 不正ファイル(JPEGファイルでない?) @retval ERROR_GRAPH_MEMORY メモリエラー @retval ERROR_GRAPH_NODATA jp にデータが無い @retval ERROR_GRAPH_IVDARH buf が NULL, or サポート外のチャンネル数(現在の所チャンネル数は 1か 3のみをサポート) */ int write_jpeg_mem(unsigned char** buf, unsigned long* len, JPEGImage jp, int qulty) { struct jpeg_compress_struct jdat; struct jpeg_error_mgr jerr; if (buf==NULL || len==NULL) return ERROR_GRAPH_IVDARG; if (jp.col!=1 && jp.col!=3) return ERROR_GRAPH_IVDARG; if (jp.gp==NULL || jp.img==NULL) return ERROR_GRAPH_NODATA; *len = jp.xs*jp.ys*jp.col; if (*len<=0) return ERROR_GRAPH_IVDARG; if (qulty>100) qulty = 100; else if (qulty<0) qulty = 0; *buf = (unsigned char*)malloc(*len); if (*buf==NULL) { return ERROR_GRAPH_MEMORY; } jdat.err = jpeg_std_error(&jerr); jpeg_create_compress(&jdat); jpeg_mem_dest(&jdat, buf, len); jdat.image_width = jp.xs; jdat.image_height = jp.ys; jdat.input_components = jp.col; if (jp.col==1) jdat.in_color_space = JCS_GRAYSCALE; else jdat.in_color_space = JCS_RGB; jpeg_set_quality (&jdat, qulty, TRUE); jpeg_set_defaults(&jdat); jpeg_start_compress (&jdat, TRUE); jpeg_write_scanlines(&jdat, jp.img, jp.ys); jpeg_finish_compress(&jdat); jpeg_destroy_compress(&jdat); if (*len<=0) { freeNull(*buf); return ERROR_GRAPH; } return 0; }
void write_jpeg_file2(const char* filename, char* data, int w, int h) { JSAMPLE* image_buffer = reinterpret_cast<JSAMPLE*>(data); struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s] int row_stride = w * 3; // JSAMPLEs per row in image_buffer cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); uint8_t* outbuffer = nullptr; // must be 0 size_t outsize = 0; // must be 0 jpeg_mem_dest(&cinfo, &outbuffer, &outsize); cinfo.image_width = w; // image width and height, in pixels cinfo.image_height = h; cinfo.input_components = 3; // # of color components per pixel cinfo.in_color_space = JCS_RGB; // colorspace of input image jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, config.quality, TRUE); // limit to baseline-JPEG values jpeg_start_compress(&cinfo, TRUE); while (cinfo.next_scanline < cinfo.image_height) { // jpeg_write_scanlines expects an array of pointers to scanlines. // Here the array is only one element long, but you could pass // more than one scanline at a time if that's more convenient. row_pointer[0] = &image_buffer[cinfo.next_scanline * row_stride]; (void)jpeg_write_scanlines(&cinfo, row_pointer, 1); } // Finish compression jpeg_finish_compress(&cinfo); // release JPEG compression object // This is an important step since it will release a good deal of memory. jpeg_destroy_compress(&cinfo); // Write file write_file(filename, (const char*)outbuffer, outsize); // free the jpeg buffer free(outbuffer); }
// Take a buffer in RGBA format, has to skip 4th uchar int encodeJPEG(unsigned char *inputbuffer, int width, int height, unsigned char **outputbuffer, unsigned long *outputsize, int quality) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; unsigned char *buf; if (quality > 100) quality = 100; // convert RGBA to RGB buf = malloc(sizeof(unsigned char)*width*height*3); size_t i; unsigned char* p = buf; for(i=0;i<width*height*4; i++) { if (i % 4 == 0) continue; *p = inputbuffer[i]; p++; } cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo, outputbuffer, outputsize); 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); jpeg_simple_progression(&cinfo); cinfo.optimize_coding = TRUE; jpeg_start_compress(&cinfo, TRUE); while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = &buf[cinfo.next_scanline * width * 3]; jpeg_write_scanlines(&cinfo, row_pointer, 1); } free(buf); jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); return 0; }
int write_jpegmem_rgb(char * frame, unsigned short width, unsigned short height, unsigned char **outbuffer, long unsigned int *outlen, int quality) { JSAMPROW row_ptr[1]; unsigned short nbChannels = 3 ; struct jpeg_compress_struct jpeg; struct jpeg_error_mgr jerr; char *line, *image; int y, x, line_width; //*outbuffer = NULL; *outlen = 0; line =(char *) malloc((width * nbChannels) * sizeof(char)); if (!line) return 0; jpeg.err = jpeg_std_error (&jerr); jpeg_create_compress (&jpeg); jpeg.image_width = width; jpeg.image_height= height; jpeg.input_components = nbChannels; jpeg.in_color_space = JCS_RGB; jpeg_set_defaults (&jpeg); jpeg_set_quality (&jpeg, quality, TRUE); jpeg.dct_method = JDCT_FASTEST; jpeg_mem_dest(&jpeg, outbuffer, outlen); jpeg_start_compress (&jpeg, TRUE); row_ptr[0] = (JSAMPROW) line; line_width = width * nbChannels; for (y = 0; y < height; y++) { for (x = 0; x < line_width; x++) { line[x] = frame[x]; } if (!jpeg_write_scanlines (&jpeg, row_ptr, 1)) { jpeg_destroy_compress (&jpeg); free (line); return 0; } frame += line_width; } jpeg_finish_compress (&jpeg); jpeg_destroy_compress (&jpeg); free (line); return 1; }
long jpeg_compress(char *src, unsigned char *dst, int width, int height, int quality) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; long bufsize = 65000; // create jpeg data cinfo.err = jpeg_std_error( &jerr ); jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo, &dst, &bufsize); // set image parameters cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; // set jpeg compression parameters to default jpeg_set_defaults(&cinfo); // and then adjust quality setting jpeg_set_quality(&cinfo, quality, TRUE); // start compress jpeg_start_compress(&cinfo, TRUE); // feed data while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = src + cinfo.next_scanline * cinfo.image_width * cinfo.input_components; jpeg_write_scanlines(&cinfo, row_pointer, 1); } // finish compression jpeg_finish_compress(&cinfo); // destroy jpeg data jpeg_destroy_compress(&cinfo); return bufsize; }
size_t JPEGCoder::encode() { double t0 = now(); int step_w = orig_w/(capture_pixel_skip+1), step_h = orig_h/(capture_pixel_skip+1); for(int y=0;y<step_h;y++) { int img_y = y * (capture_pixel_skip+1); for(int x=0;x<step_w;x++) { int img_x = x * (capture_pixel_skip+1); unsigned char r,g,b,a; capture_img->getPixelRaw( img_x, img_y, &r,&g,&b,&a); sampary[y][x*3+0] = r; sampary[y][x*3+1] = g; sampary[y][x*3+2] = b; } } double t1 = now(); struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress( &cinfo); // jpeg_stdio_dest(&cinfo,jfp); unsigned long outsize; jpeg_mem_dest( &cinfo, &compressed, &outsize ); cinfo.image_width = step_w; cinfo.image_height = step_h; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults( &cinfo); jpeg_set_quality( &cinfo, jpeg_quality, true ); jpeg_start_compress( &cinfo, true ); jpeg_write_scanlines( &cinfo, sampary, step_h ); jpeg_finish_compress( &cinfo ); compressed_size = outsize; double t2 = now(); if((t2-t1)>0.02) print("slow jpeg compress"); if((t1-t0)>0.02) print("slow pixel copy"); // print("jpeg: time: %f, %f img:%d,%d", t1-t0, t2-t1, step_w, step_h); return outsize; }
static void init_libjpeg_cinfo(struct v4lconvert_data *data) { struct jpeg_compress_struct cinfo; unsigned char *jpeg_header = NULL; unsigned long jpeg_header_size = 0; if (data->cinfo_initialized) return; /* Setup our error handling */ jpeg_std_error(&data->jerr); data->jerr.error_exit = jerr_error_exit; data->jerr.emit_message = jerr_emit_message; /* Create a jpeg compression object with default params and write default jpeg headers to a mem buffer, so that we can use them to pre-fill a jpeg_decompress_struct with default quant and huffman tables, so that libjpeg can be used to parse [m]jpg-s with incomplete headers */ cinfo.err = &data->jerr; cinfo.client_data = data; jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo, &jpeg_header, &jpeg_header_size); cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_write_tables(&cinfo); jpeg_destroy_compress(&cinfo); /* Init the jpeg_decompress_struct */ data->cinfo.err = &data->jerr; data->cinfo.client_data = data; jpeg_create_decompress(&data->cinfo); jpeg_mem_src(&data->cinfo, jpeg_header, jpeg_header_size); jpeg_read_header(&data->cinfo, FALSE); free(jpeg_header); data->cinfo_initialized = 1; }
void encodeRGB8_to_JPEG(unsigned char *image, size_t width, size_t height, unsigned char **encoded, size_t *capacity) { #if JPEG_LIB_VERSION >= 80 /*! Compression parameters and scratch space pointers (allocated by the library). */ struct jpeg_compress_struct cinfo; /*! The library error handler. */ struct jpeg_error_mgr jerror; cinfo.err = jpeg_std_error(&jerror); /*! Initialize the JPEG compression object. */ jpeg_create_compress(&cinfo); /*! Specify the incoming image resolution, color space, and color space components. */ cinfo.image_width = width; cinfo.image_height = height; cinfo.in_color_space = JCS_RGB; cinfo.input_components = 3; /*! Fill in a sensible set of defaults. */ jpeg_set_defaults(&cinfo); /*! Set the image quality. */ jpeg_set_quality(&cinfo, 90, TRUE); /*! Specify the data source. */ jpeg_mem_dest(&cinfo, encoded, capacity); /*! Compress and write the image into the target buffer. */ compress(&cinfo, image); /*! At this point 'jerror.num_warnings' could be checked for corrupt-data warnings. */ jpeg_destroy_compress(&cinfo); #else // JPEG_LIB_VERSION throw std::runtime_error("JPEG encoding into a memory buffer requires LibJPEG 8a or higher"); #endif // JPEG_LIB_VERSION }
void encodeFrame( unsigned char *pixels, int index ) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); size_t outsz = 1024*256; unsigned char *outbuf = (unsigned char*) MALLOC(outsz); jpeg_mem_dest(&cinfo, &outbuf, &outsz ); cinfo.image_width = SCREEN_WIDTH; cinfo.image_height = SCREEN_HEIGHT; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults( &cinfo ); jpeg_set_quality( &cinfo, 75, 1 ); jpeg_start_compress( &cinfo, 1 ); JSAMPROW row_pointer; int y=0; while( cinfo.next_scanline < cinfo.image_height ) { row_pointer = pixels + y * SCREEN_WIDTH * 3; jpeg_write_scanlines( &cinfo, &row_pointer, 1 ); y++; } jpeg_finish_compress(&cinfo); printf( "outlen: %d\n", (int)outsz ); char path[100]; snprintf(path,sizeof(path), "out%02d.jpg", index ); FILE *fp = fopen( path,"w"); fwrite( outbuf, 1, outsz, fp); fclose(fp); }
static int save_jpeg(unsigned char **buf, size_t *len, int quality, unsigned char *data, int width, int height, int bpl) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; unsigned char *b = NULL; unsigned long l = 0; JSAMPROW row_pointer[1]; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo, &b, &l); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_EXT_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); jpeg_start_compress(&cinfo, TRUE); while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = (void*)&data[cinfo.next_scanline * bpl]; (void)jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_finish_compress(&cinfo); *buf = b; *len = l; jpeg_destroy_compress(&cinfo); return 0; }
static bool ipl2jpeg(IplImage *frame, unsigned char **outbuffer, long unsigned int *outlen) { unsigned char *outdata = (uchar *) frame->imageData; struct jpeg_compress_struct cinfo = {0}; struct jpeg_error_mgr jerr; JSAMPROW row_ptr[1]; int row_stride; *outbuffer = NULL; *outlen = 0; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo, outbuffer, outlen); cinfo.image_width = frame->width; cinfo.image_height = frame->height; cinfo.input_components = frame->nChannels; if ( frame->nChannels == 1 ) cinfo.in_color_space = JCS_GRAYSCALE; else cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_start_compress(&cinfo, TRUE); row_stride = frame->width * frame->nChannels; while (cinfo.next_scanline < cinfo.image_height) { row_ptr[0] = &outdata[cinfo.next_scanline * row_stride]; jpeg_write_scanlines(&cinfo, row_ptr, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); return true; }
unsigned char* LibJPEG::encode(unsigned char* imageBuffer, unsigned long buffSize, const int width, const int height, const int quality, unsigned long &destSize) { unsigned long buf_size = 0; unsigned char* buf = NULL; jpeg_mem_dest(&m_cinfo, &buf, &buf_size); m_cinfo.image_width = width; m_cinfo.image_height = height; m_cinfo.input_components = 3; m_cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&m_cinfo); m_cinfo.dct_method = JDCT_FLOAT; jpeg_set_quality(&m_cinfo, quality, true); jpeg_start_compress(&m_cinfo, TRUE); JSAMPROW row_pointer[1]; int row_stride; row_stride = m_cinfo.image_width * m_cinfo.input_components; while (m_cinfo.next_scanline < m_cinfo.image_height) { row_pointer[0] = &imageBuffer[m_cinfo.next_scanline * m_cinfo.image_width * m_cinfo.input_components]; jpeg_write_scanlines(&m_cinfo, row_pointer, 1); } jpeg_finish_compress(&m_cinfo); destSize = buf_size; return buf; }
int main(int argc, char *argv[]) { FILE *fin, *fout; uint16_t thumb[65536]; uint8_t header[16]; uint8_t jpeg_stripe[500000]; uint8_t out[5000000]; uint8_t jpeg_data[500000]; int q, width, height; int thumbnail_width, thumbnail_height; char fname[256]; char outname[256]; struct jpeg_compress_struct cinfo; struct jpeg_decompress_struct dinfo; struct jpeg_error_mgr jcerr, jderr; JOCTET *jpeg_header = NULL; unsigned long jpeg_header_size = 0; int i, x, y, x1, y1, jpeg_data_size, jpeg_data_idx, eoi, size, ret; if (argc != 2) { printf("syntax: jl2005bcd_decompress (some raw file)\n"); return 1; } fin = fopen(argv[1], "r"); if(!fin) { printf("Error opening raw file. Exiting.\n"); return 0; } if (!strchr(argv[1], 0x2e)) { fprintf(stderr, "\tIllegal input file.\n" "\tNo period in filename!\n" "\tExiting!\n"); return 0; } i = strchr(argv[1], 0x2e) - argv[1]; if (i < 4) { fprintf(stderr, "\tBasename of input file is too short!\n" "\tExiting!\n"); return 0; } /* Finally, check whether the alleged input file really claims to be * a gphoto2 raw file, at least by its name */ if (strncmp("raw_", argv[1], 4)) { fprintf(stderr, "\tThe input does not even claim to be a raw file!\n" "\tExiting!\n"); return 0; } /* To create the name(s) of the destination file(s), remove * the prefix raw_ as the first step. */ strncpy(outname, argv[1] + 4, i - 4); strcat (outname, "r"); fprintf (stderr, "Destination file will be called %s\n", outname); fread(header, 1, 16, fin); q = header[3] & 0x7f; height = header[4] * 8; width = header[5] * 8; printf("quality is %d\n", q); printf("size: %dx%d\n", width, height); switch (header[9]) { case 0xf0: thumbnail_width = 128; thumbnail_height = 120; break; case 0x60: thumbnail_width = 96; thumbnail_height = 64; break; default: thumbnail_width = 0; thumbnail_height = 0; } if(thumbnail_width) { sprintf(fname, "%s-thumb.ppm", outname); fout = fopen(fname, "w"); if (!fin || !fout) { printf("still stupid!\n"); return 1; } fread(thumb, 1, thumbnail_width * thumbnail_height * 2, fin); for (i = 0; i < thumbnail_width * thumbnail_height; i++) { thumb[i] = ntohs(thumb[i]); out[i * 3 + 0] = (thumb[i] & 0xf800) >> 8; out[i * 3 + 1] = (thumb[i] & 0x07e0) >> 3; out[i * 3 + 2] = (thumb[i] & 0x001f) << 3; } fprintf(fout, "P6\n%d %d\n255\n", thumbnail_width, thumbnail_height); fwrite(out, 1, thumbnail_width * thumbnail_height * 3, fout); fclose(fout); } /* * And the fun begins, first of all create a dummy jpeg, which we use * to get the headers from to feed to libjpeg when decompressing the * stripes. This way we can use libjpeg's quant table handling * (and built in default huffman tables). */ cinfo.err = jpeg_std_error (&jcerr); jpeg_create_compress (&cinfo); jpeg_mem_dest (&cinfo, &jpeg_header, &jpeg_header_size); cinfo.image_width = 16; cinfo.image_height = 16; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults (&cinfo); /* Make comp[0] (which will be green) 1x2 subsampled */ cinfo.comp_info[0].h_samp_factor = 1; cinfo.comp_info[0].v_samp_factor = 2; /* Make comp[1] and [2] use huffman table and quanttable 0, as all * components use luminance settings with the jl2005c/d/e */ cinfo.comp_info[1].quant_tbl_no = 0; cinfo.comp_info[1].dc_tbl_no = 0; cinfo.comp_info[1].ac_tbl_no = 0; cinfo.comp_info[2].quant_tbl_no = 0; cinfo.comp_info[2].dc_tbl_no = 0; cinfo.comp_info[2].ac_tbl_no = 0; /* Apply the quality setting from the header */ if (q <= 0) i = 5000; else if (q <= 50) i = 5000 / q; else if (q <= 100) i = 2 * (100 - q); else i = 0; jpeg_set_linear_quality(&cinfo, i, TRUE); jpeg_start_compress (&cinfo, TRUE); while( cinfo.next_scanline < cinfo.image_height ) { JOCTET row[16 * 3]; JSAMPROW row_pointer[1] = { row }; jpeg_write_scanlines (&cinfo, row_pointer, 1); } jpeg_finish_compress (&cinfo); jpeg_destroy_compress (&cinfo); JSAMPLE green[8 * 16]; JSAMPLE red[8 * 8]; JSAMPLE blue[8 * 8]; JSAMPROW green_row_pointer[16]; JSAMPROW red_row_pointer[8]; JSAMPROW blue_row_pointer[8]; for (i = 0; i < 16; i++) green_row_pointer[i] = green + i * 8; for (i = 0; i < 8; i++) { red_row_pointer[i] = red + i * 8; blue_row_pointer[i] = blue + i * 8; } JSAMPARRAY samp_image[3] = { green_row_pointer, red_row_pointer, blue_row_pointer }; memcpy(jpeg_stripe, jpeg_header, JPEG_HEADER_SIZE); jpeg_stripe[JPEG_HEIGHT_OFFSET ] = height >> 8; jpeg_stripe[JPEG_HEIGHT_OFFSET + 1] = height; jpeg_stripe[JPEG_HEIGHT_OFFSET + 2] = 0; jpeg_stripe[JPEG_HEIGHT_OFFSET + 3] = 8; free (jpeg_header); jpeg_data_size = fread(jpeg_data, 1, 500000, fin); jpeg_data_idx = 0; memset(out, 0, width * height * 3); dinfo.err = jpeg_std_error (&jderr); jpeg_create_decompress (&dinfo); for (x = 0; x < width; x += 16) { eoi = find_eoi(jpeg_data, jpeg_data_idx, jpeg_data_size); if (eoi < 0) return eoi; size = eoi - jpeg_data_idx; if ((JPEG_HEADER_SIZE + size) > sizeof(jpeg_stripe)) { printf("AAAIIIIII\n"); return 1; } memcpy (jpeg_stripe + JPEG_HEADER_SIZE, jpeg_data + jpeg_data_idx, size); jpeg_mem_src (&dinfo, jpeg_stripe, JPEG_HEADER_SIZE + size); jpeg_read_header (&dinfo, TRUE); dinfo.raw_data_out = TRUE; #if JPEG_LIB_VERSION >= 70 dinfo.do_fancy_upsampling = FALSE; #endif jpeg_start_decompress (&dinfo); for (y = 0; y < height; y += 16) { jpeg_read_raw_data (&dinfo, samp_image, 16); for (y1 = 0; y1 < 16; y1 += 2) { for (x1 = 0; x1 < 16; x1 += 2) { out[((y + y1 + 0) * width + x + x1 + 0) * 3] = red[y1 * 4 + x1 / 2]; out[((y + y1 + 0) * width + x + x1 + 1) * 3 + 1] = green[y1 * 8 + x1 / 2]; out[((y + y1 + 1) * width + x + x1 + 0) * 3 + 1] = green[y1 * 8 + 8 + x1 / 2]; out[((y + y1 + 1) * width + x + x1 + 1) * 3 + 2] = blue[y1 * 4 + x1 / 2]; } } } jpeg_finish_decompress (&dinfo); /* Set jpeg_data_idx for the next stripe */ jpeg_data_idx = (jpeg_data_idx + size + 0x0f) & ~0x0f; } jpeg_destroy_decompress(&dinfo); ret = gp_ahd_interpolate(out, width, height, BAYER_TILE_BGGR); if (ret < 0) { printf("HEUH?\n"); return ret; } white_balance (out, width*height, 1.6); sprintf(fname, "%s.ppm", outname); fout = fopen(fname, "w"); if (!fout) { printf("stupid again?\n"); return 1; } fprintf(fout, "P6\n%d %d\n255\n", width, height); fwrite(out, 1, width * height * 3, fout); fclose(fin); fclose(fout); return 0; }
prepare_for_pass (j_compress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; cinfo->trellis_passes = master->pass_number < master->pass_number_scan_opt_base; switch (master->pass_type) { case main_pass: /* Initial pass: will collect input data, and do either Huffman * optimization or data output for the first scan. */ select_scan_parameters(cinfo); per_scan_setup(cinfo); if (! cinfo->raw_data_in) { (*cinfo->cconvert->start_pass) (cinfo); (*cinfo->downsample->start_pass) (cinfo); (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); } (*cinfo->fdct->start_pass) (cinfo); (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); (*cinfo->coef->start_pass) (cinfo, (master->total_passes > 1 ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); if (cinfo->optimize_coding) { /* No immediate data output; postpone writing frame/scan headers */ master->pub.call_pass_startup = FALSE; } else { /* Will write frame/scan headers at first jpeg_write_scanlines call */ master->pub.call_pass_startup = TRUE; } break; #ifdef ENTROPY_OPT_SUPPORTED case huff_opt_pass: /* Do Huffman optimization for a scan after the first one. */ select_scan_parameters(cinfo); per_scan_setup(cinfo); if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { (*cinfo->entropy->start_pass) (cinfo, TRUE); (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); master->pub.call_pass_startup = FALSE; break; } /* Special case: Huffman DC refinement scans need no Huffman table * and therefore we can skip the optimization pass for them. */ master->pass_type = output_pass; master->pass_number++; /*FALLTHROUGH*/ #endif case output_pass: /* Do a data-output pass. */ /* We need not repeat per-scan setup if prior optimization pass did it. */ if (! cinfo->optimize_coding) { select_scan_parameters(cinfo); per_scan_setup(cinfo); } if (cinfo->optimize_scans) { master->saved_dest = cinfo->dest; cinfo->dest = NULL; master->scan_size[master->scan_number] = 0; jpeg_mem_dest(cinfo, &master->scan_buffer[master->scan_number], &master->scan_size[master->scan_number]); (*cinfo->dest->init_destination)(cinfo); } (*cinfo->entropy->start_pass) (cinfo, FALSE); (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); /* We emit frame/scan headers now */ if (master->scan_number == 0) (*cinfo->marker->write_frame_header) (cinfo); (*cinfo->marker->write_scan_header) (cinfo); master->pub.call_pass_startup = FALSE; break; case trellis_pass: if (master->pass_number%(cinfo->num_components*(cinfo->use_scans_in_trellis?4:2)) == 1 && cinfo->trellis_q_opt) { int i, j; for (i = 0; i < NUM_QUANT_TBLS; i++) { for (j = 1; j < DCTSIZE2; j++) { cinfo->norm_src[i][j] = 0.0; cinfo->norm_coef[i][j] = 0.0; } } } (*cinfo->entropy->start_pass) (cinfo, TRUE); (*cinfo->coef->start_pass) (cinfo, JBUF_REQUANT); master->pub.call_pass_startup = FALSE; break; default: ERREXIT(cinfo, JERR_NOT_COMPILED); } master->pub.is_last_pass = (master->pass_number == master->total_passes-1); /* Set up progress monitor's pass info if present */ if (cinfo->progress != NULL) { cinfo->progress->completed_passes = master->pass_number; cinfo->progress->total_passes = master->total_passes; } }
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 */ }
/* * save function * */ int libjpeg_(Main_save)(lua_State *L) { unsigned char *inmem = NULL; /* destination memory (if saving to memory) */ unsigned long inmem_size = 0; /* destination memory size (bytes) */ /* get args */ const char *filename = luaL_checkstring(L, 1); THTensor *tensor = luaT_checkudata(L, 2, torch_Tensor); THTensor *tensorc = THTensor_(newContiguous)(tensor); real *tensor_data = THTensor_(data)(tensorc); const int save_to_file = luaL_checkint(L, 3); THByteTensor* tensor_dest = NULL; if (save_to_file == 0) { tensor_dest = luaT_checkudata(L, 5, "torch.ByteTensor"); } int quality = luaL_checkint(L, 4); if (quality < 0 || quality > 100) { luaL_error(L, "quality should be between 0 and 100"); } /* jpeg struct */ struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; /* pointer to raw image */ unsigned char *raw_image = NULL; /* dimensions of the image we want to write */ int width=0, height=0, bytes_per_pixel=0; int color_space=0; if (tensorc->nDimension == 3) { bytes_per_pixel = tensorc->size[0]; height = tensorc->size[1]; width = tensorc->size[2]; if (bytes_per_pixel == 3) { color_space = JCS_RGB; } else if (bytes_per_pixel == 1) { color_space = JCS_GRAYSCALE; } else { luaL_error(L, "tensor should have 1 or 3 channels (gray or RGB)"); } } else if (tensorc->nDimension == 2) { bytes_per_pixel = 1; height = tensorc->size[0]; width = tensorc->size[1]; color_space = JCS_GRAYSCALE; } else { luaL_error(L, "supports only 1 or 3 dimension tensors"); } /* alloc raw image data */ raw_image = (unsigned char *)malloc((sizeof (unsigned char))*width*height*bytes_per_pixel); /* convert tensor to raw bytes */ int x,y,k; for (k=0; k<bytes_per_pixel; k++) { for (y=0; y<height; y++) { for (x=0; x<width; x++) { raw_image[(y*width+x)*bytes_per_pixel+k] = *tensor_data++; } } } /* this is a pointer to one row of image data */ JSAMPROW row_pointer[1]; FILE *outfile = NULL; if (save_to_file == 1) { outfile = fopen( filename, "wb" ); if ( !outfile ) { luaL_error(L, "Error opening output jpeg file %s\n!", filename ); } } cinfo.err = jpeg_std_error( &jerr ); jpeg_create_compress(&cinfo); /* specify data source (eg, a file) */ if (save_to_file == 1) { jpeg_stdio_dest(&cinfo, outfile); } else { jpeg_mem_dest(&cinfo, &inmem, &inmem_size); } /* Setting the parameters of the output file here */ cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = bytes_per_pixel; cinfo.in_color_space = color_space; /* default compression parameters, we shouldn't be worried about these */ jpeg_set_defaults( &cinfo ); jpeg_set_quality(&cinfo, quality, (boolean)0); /* Now do the compression .. */ jpeg_start_compress( &cinfo, TRUE ); /* like reading a file, this time write one row at a time */ while( cinfo.next_scanline < cinfo.image_height ) { row_pointer[0] = &raw_image[ cinfo.next_scanline * cinfo.image_width * cinfo.input_components]; jpeg_write_scanlines( &cinfo, row_pointer, 1 ); } /* similar to read file, clean up after we're done compressing */ jpeg_finish_compress( &cinfo ); jpeg_destroy_compress( &cinfo ); if (outfile != NULL) { fclose( outfile ); } if (save_to_file == 0) { THByteTensor_resize1d(tensor_dest, inmem_size); /* will fail if it's not a Byte Tensor */ unsigned char* tensor_dest_data = THByteTensor_data(tensor_dest); memcpy(tensor_dest_data, inmem, inmem_size); free(inmem); } /* some cleanup */ free(raw_image); THTensor_(free)(tensorc); /* success code is 1! */ return 1; }
void JpegEncoder::encode() { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_mem_dest(&cinfo, &jpeg, &jpeg_len); if (offset.isNull()) { cinfo.image_width = width; cinfo.image_height = height; } else { cinfo.image_width = offset.w; cinfo.image_height = offset.h; } cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); cinfo.smoothing_factor = smoothing; jpeg_start_compress(&cinfo, TRUE); unsigned char *rgb_data; switch (buf_type) { case BUF_RGBA: rgb_data = rgba_to_rgb(data, width*height*4); if (!rgb_data) throw "malloc failed in JpegEncoder::encode/rgba_to_rgb."; break; case BUF_BGRA: rgb_data = bgra_to_rgb(data, width*height*4); if (!rgb_data) throw "malloc failed in JpegEncoder::encode/bgra_to_rgb."; break; case BUF_BGR: rgb_data = bgr_to_rgb(data, width*height*3); if (!rgb_data) throw "malloc failed in JpegEncoder::encode/bgr_to_rgb."; break; case BUF_RGB: rgb_data = data; break; default: throw "Unexpected buf_type in JpegEncoder::encode"; } JSAMPROW row_pointer; int start = 0; if (!offset.isNull()) { start = offset.y*width*3 + offset.x*3; } while (cinfo.next_scanline < cinfo.image_height) { row_pointer = &rgb_data[start + cinfo.next_scanline*3*width]; jpeg_write_scanlines(&cinfo, &row_pointer, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); if (buf_type == BUF_BGR || buf_type == BUF_RGBA || buf_type == BUF_BGRA) free(rgb_data); }
int main (int argc, char **argv) { struct jpeg_decompress_struct srcinfo; struct jpeg_compress_struct dstinfo; struct jpeg_error_mgr jsrcerr, jdsterr; #ifdef PROGRESS_REPORT struct cdjpeg_progress_mgr progress; #endif jvirt_barray_ptr * src_coef_arrays; jvirt_barray_ptr * dst_coef_arrays; int file_index; /* We assume all-in-memory processing and can therefore use only a * single file pointer for sequential input and output operation. */ FILE * fp; unsigned char *inbuffer = NULL; unsigned long insize = 0; unsigned char *outbuffer = NULL; unsigned long outsize = 0; /* On Mac, fetch a command line. */ #ifdef USE_CCOMMAND argc = ccommand(&argv); #endif progname = argv[0]; if (progname == NULL || progname[0] == 0) progname = "jpegtran"; /* in case C library doesn't provide it */ /* Initialize the JPEG decompression object with default error handling. */ srcinfo.err = jpeg_std_error(&jsrcerr); jpeg_create_decompress(&srcinfo); /* Initialize the JPEG compression object with default error handling. */ dstinfo.err = jpeg_std_error(&jdsterr); jpeg_create_compress(&dstinfo); dstinfo.use_moz_defaults = TRUE; /* Scan command line to find file names. * It is convenient to use just one switch-parsing routine, but the switch * values read here are mostly ignored; we will rescan the switches after * opening the input file. Also note that most of the switches affect the * destination JPEG object, so we parse into that and then copy over what * needs to affects the source too. */ file_index = parse_switches(&dstinfo, argc, argv, 0, FALSE); jsrcerr.trace_level = jdsterr.trace_level; srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use; #ifdef TWO_FILE_COMMANDLINE /* 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 ((fp = fopen(argv[file_index], READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s for reading\n", progname, argv[file_index]); exit(EXIT_FAILURE); } } else { /* default input file is stdin */ fp = read_stdin(); } #ifdef PROGRESS_REPORT start_progress_monitor((j_common_ptr) &dstinfo, &progress); #endif /* Specify data source for decompression */ memsrc = dstinfo.use_moz_defaults; /* needed to revert to original */ #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) if (memsrc) { size_t nbytes; do { inbuffer = (unsigned char *)realloc(inbuffer, insize + INPUT_BUF_SIZE); if (inbuffer == NULL) { fprintf(stderr, "%s: memory allocation failure\n", progname); exit(EXIT_FAILURE); } nbytes = JFREAD(fp, &inbuffer[insize], INPUT_BUF_SIZE); if (nbytes < INPUT_BUF_SIZE && ferror(fp)) { if (file_index < argc) fprintf(stderr, "%s: can't read from %s\n", progname, argv[file_index]); else fprintf(stderr, "%s: can't read from stdin\n", progname); } insize += (unsigned long)nbytes; } while (nbytes == INPUT_BUF_SIZE); jpeg_mem_src(&srcinfo, inbuffer, insize); } else #endif jpeg_stdio_src(&srcinfo, fp); /* Enable saving of extra markers that we want to copy */ jcopy_markers_setup(&srcinfo, copyoption); /* Read file header */ (void) jpeg_read_header(&srcinfo, TRUE); /* Any space needed by a transform option must be requested before * jpeg_read_coefficients so that memory allocation will be done right. */ #if TRANSFORMS_SUPPORTED /* Fail right away if -perfect is given and transformation is not perfect. */ if (!jtransform_request_workspace(&srcinfo, &transformoption)) { fprintf(stderr, "%s: transformation is not perfect\n", progname); exit(EXIT_FAILURE); } #endif /* Read source file as DCT coefficients */ src_coef_arrays = jpeg_read_coefficients(&srcinfo); /* Initialize destination compression parameters from source values */ jpeg_copy_critical_parameters(&srcinfo, &dstinfo); /* Adjust destination parameters if required by transform options; * also find out which set of coefficient arrays will hold the output. */ #if TRANSFORMS_SUPPORTED dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo, src_coef_arrays, &transformoption); #else dst_coef_arrays = src_coef_arrays; #endif /* Close input file, if we opened it. * Note: we assume that jpeg_read_coefficients consumed all input * until JPEG_REACHED_EOI, and that jpeg_finish_decompress will * only consume more while (! cinfo->inputctl->eoi_reached). * We cannot call jpeg_finish_decompress here since we still need the * virtual arrays allocated from the source object for processing. */ if (fp != stdin) fclose(fp); /* Open the output file. */ if (outfilename != NULL) { if ((fp = fopen(outfilename, WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s for writing\n", progname, outfilename); exit(EXIT_FAILURE); } } else { /* default output file is stdout */ fp = write_stdout(); } /* Adjust default compression parameters by re-parsing the options */ file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE); /* Specify data destination for compression */ #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) if (dstinfo.use_moz_defaults) jpeg_mem_dest(&dstinfo, &outbuffer, &outsize); else #endif jpeg_stdio_dest(&dstinfo, fp); /* Start compressor (note no image data is actually written here) */ jpeg_write_coefficients(&dstinfo, dst_coef_arrays); /* Copy to the output file any extra markers that we want to preserve */ jcopy_markers_execute(&srcinfo, &dstinfo, copyoption); /* Execute image transformation, if any */ #if TRANSFORMS_SUPPORTED jtransform_execute_transformation(&srcinfo, &dstinfo, src_coef_arrays, &transformoption); #endif /* Finish compression and release memory */ jpeg_finish_compress(&dstinfo); if (dstinfo.use_moz_defaults) { size_t nbytes; unsigned char *buffer = outbuffer; unsigned long size = outsize; if (insize < size) { size = insize; buffer = inbuffer; } nbytes = JFWRITE(fp, buffer, size); if (nbytes < size && ferror(fp)) { if (file_index < argc) fprintf(stderr, "%s: can't write to %s\n", progname, argv[file_index]); else fprintf(stderr, "%s: can't write to stdout\n", progname); } } jpeg_destroy_compress(&dstinfo); (void) jpeg_finish_decompress(&srcinfo); jpeg_destroy_decompress(&srcinfo); /* Close output file, if we opened it */ if (fp != stdout) fclose(fp); #ifdef PROGRESS_REPORT end_progress_monitor((j_common_ptr) &dstinfo); #endif /* All done. */ exit(jsrcerr.num_warnings + jdsterr.num_warnings ?EXIT_WARNING:EXIT_SUCCESS); return 0; /* suppress no-return-value warnings */ }
bool CJpegIO::CreateThumbnailFromSurface(unsigned char* bufferin, unsigned int width, unsigned int height, unsigned int format, unsigned int pitch, const CStdString& destFile, unsigned char* &bufferout, unsigned int &bufferoutSize) { //Encode raw data from buffer, save to destbuffer struct jpeg_compress_struct cinfo; struct my_error_mgr jerr; JSAMPROW row_pointer[1]; long unsigned int outBufSize = width * height; unsigned char* src = bufferin; unsigned char* rgbbuf, *src2, *dst2; if(bufferin == NULL) { CLog::Log(LOGERROR, "JpegIO::CreateThumbnailFromSurface no buffer"); return false; } m_thumbnailbuffer = (unsigned char*) malloc(outBufSize); //Initial buffer. Grows as-needed. if (m_thumbnailbuffer == NULL) { CLog::Log(LOGERROR, "JpegIO::CreateThumbnailFromSurface error allocating memory for image buffer"); return false; } if(format == XB_FMT_RGB8) { rgbbuf = bufferin; } else if(format == XB_FMT_A8R8G8B8) { // create a copy for bgra -> rgb. rgbbuf = new unsigned char [(width * height * 3)]; unsigned char* dst = rgbbuf; for (unsigned int y = 0; y < height; y++) { dst2 = dst; src2 = src; for (unsigned int x = 0; x < width; x++, src2 += 4) { *dst2++ = src2[2]; *dst2++ = src2[1]; *dst2++ = src2[0]; } dst += width * 3; src += pitch; } } else { CLog::Log(LOGWARNING, "JpegIO::CreateThumbnailFromSurface Unsupported format"); free(m_thumbnailbuffer); return false; } cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = jpeg_error_exit; jpeg_create_compress(&cinfo); if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_compress(&cinfo); free(m_thumbnailbuffer); if(format != XB_FMT_RGB8) delete [] rgbbuf; return false; } else { #if JPEG_LIB_VERSION < 80 x_jpeg_mem_dest(&cinfo, &m_thumbnailbuffer, &outBufSize); #else jpeg_mem_dest(&cinfo, &m_thumbnailbuffer, &outBufSize); #endif 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, 90, TRUE); jpeg_start_compress(&cinfo, TRUE); while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = &rgbbuf[cinfo.next_scanline * width * 3]; jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); } if(format != XB_FMT_RGB8) delete [] rgbbuf; bufferout = m_thumbnailbuffer; bufferoutSize = outBufSize; return true; }