jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) { if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (write_all_tables) jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ /* setting up scan optimisation pattern failed, disable scan optimisation */ if (cinfo->num_scans_luma == 0 || cinfo->scan_info == NULL || cinfo->num_scans == 0) cinfo->optimize_scans = FALSE; /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); /* Perform master selection of active modules */ jinit_compress_master(cinfo); /* Set up for the first pass */ (*cinfo->master->prepare_for_pass) (cinfo); /* Ready for application to drive first pass through jpeg_write_scanlines * or jpeg_write_raw_data. */ cinfo->next_scanline = 0; cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); }
static void gst_jpegenc_resync (GstJpegEnc * jpegenc) { gint width, height; gint i, j; GST_DEBUG_OBJECT (jpegenc, "resync"); jpegenc->cinfo.image_width = width = jpegenc->width; jpegenc->cinfo.image_height = height = jpegenc->height; jpegenc->cinfo.input_components = jpegenc->channels; GST_DEBUG_OBJECT (jpegenc, "width %d, height %d", width, height); GST_DEBUG_OBJECT (jpegenc, "format %d", jpegenc->format); if (gst_video_format_is_rgb (jpegenc->format)) { GST_DEBUG_OBJECT (jpegenc, "RGB"); jpegenc->cinfo.in_color_space = JCS_RGB; } else if (gst_video_format_is_gray (jpegenc->format)) { GST_DEBUG_OBJECT (jpegenc, "gray"); jpegenc->cinfo.in_color_space = JCS_GRAYSCALE; } else { GST_DEBUG_OBJECT (jpegenc, "YUV"); jpegenc->cinfo.in_color_space = JCS_YCbCr; } /* input buffer size as max output */ jpegenc->bufsize = gst_video_format_get_size (jpegenc->format, width, height); jpeg_set_defaults (&jpegenc->cinfo); jpegenc->cinfo.raw_data_in = TRUE; /* duh, libjpeg maps RGB to YUV ... and don't expect some conversion */ if (jpegenc->cinfo.in_color_space == JCS_RGB) jpeg_set_colorspace (&jpegenc->cinfo, JCS_RGB); GST_DEBUG_OBJECT (jpegenc, "h_max_samp=%d, v_max_samp=%d", jpegenc->h_max_samp, jpegenc->v_max_samp); /* image dimension info */ for (i = 0; i < jpegenc->channels; i++) { GST_DEBUG_OBJECT (jpegenc, "comp %i: h_samp=%d, v_samp=%d", i, jpegenc->h_samp[i], jpegenc->v_samp[i]); jpegenc->cinfo.comp_info[i].h_samp_factor = jpegenc->h_samp[i]; jpegenc->cinfo.comp_info[i].v_samp_factor = jpegenc->v_samp[i]; jpegenc->line[i] = g_realloc (jpegenc->line[i], jpegenc->v_max_samp * DCTSIZE * sizeof (char *)); if (!jpegenc->planar) { for (j = 0; j < jpegenc->v_max_samp * DCTSIZE; j++) { jpegenc->row[i][j] = g_realloc (jpegenc->row[i][j], width); jpegenc->line[i][j] = jpegenc->row[i][j]; } } } /* guard against a potential error in gst_jpegenc_term_destination which occurs iff bufsize % 4 < free_space_remaining */ jpegenc->bufsize = GST_ROUND_UP_4 (jpegenc->bufsize); jpeg_suppress_tables (&jpegenc->cinfo, TRUE); GST_DEBUG_OBJECT (jpegenc, "resync done"); }
GLOBAL(void)jpeg_start_compress(j_compress_ptr cinfo, boolean write_all_tables) { // DHKIM // cinfo->raw_data_in = 1; if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (write_all_tables) jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ /* (Re)initialize error mgr and destination modules */ // (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); #ifndef JPEG_ENC_OPT //bmy 04.12.29 jpeg_enc_opt + init_destination(cinfo); #endif //bmy 04.12.29 jpeg_enc_opt + /* Perform master selection of active modules */ jinit_compress_master(cinfo); /* Set up for the first pass */ prepare_for_pass(cinfo); /* Ready for application to drive first pass through jpeg_write_scanlines * or jpeg_write_raw_data. */ // cinfo->next_scanline = 0; cinfo->global_state = CSTATE_SCANNING; }
int CJpegEncoder::SetQuality(int quality) { if(setjmp(returnPoint)) { return -1; } jpeg_set_quality(&cinfo, quality, FALSE); jpeg_suppress_tables(&cinfo, FALSE); jpeg_write_tables(&cinfo); return 0; }
jpeg_write_coefficients(j_compress_ptr cinfo, jvirt_barray_ptr* coef_arrays) { if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Mark all tables to be written */ jpeg_suppress_tables(cinfo, FALSE); /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr)((j_common_ptr) cinfo); (*cinfo->dest->init_destination)(cinfo); /* Perform master selection of active modules */ transencode_master_selection(cinfo, coef_arrays); /* Wait for jpeg_finish_compress() call */ cinfo->next_scanline = 0; /* so jpeg_write_marker works */ cinfo->global_state = CSTATE_WRCOEFS; }
static void* mjpg_rgb_init(struct ng_video_fmt *out, void *priv) { struct mjpeg_compress *h; if (ng_debug > 1) fprintf(stderr,"mjpg_rgb_init\n"); h = mjpg_init(out); if (NULL == h) return NULL; h->mjpg_cinfo.input_components = 3; h->mjpg_cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&h->mjpg_cinfo); h->mjpg_cinfo.dct_method = JDCT_FASTEST; jpeg_set_quality(&h->mjpg_cinfo, ng_jpeg_quality, TRUE); jpeg_suppress_tables(&h->mjpg_cinfo, TRUE); return h; }
static void* mjpg_yuv_init(struct ng_video_fmt *out, void *priv) { struct mjpeg_compress *h; struct mjpeg_yuv_priv *c = priv; if (ng_debug > 1) fprintf(stderr,"mjpg_yuv_init\n"); h = mjpg_init(out); if (NULL == h) return NULL; h->mjpg_cinfo.input_components = 3; h->mjpg_cinfo.in_color_space = JCS_YCbCr; jpeg_set_defaults(&h->mjpg_cinfo); h->mjpg_cinfo.dct_method = JDCT_FASTEST; jpeg_set_quality(&h->mjpg_cinfo, ng_jpeg_quality, TRUE); h->mjpg_cinfo.raw_data_in = TRUE; jpeg_set_colorspace(&h->mjpg_cinfo,JCS_YCbCr); h->mjpg_ptrs[0] = malloc(h->fmt.height*sizeof(char*)); h->mjpg_ptrs[1] = malloc(h->fmt.height*sizeof(char*)); h->mjpg_ptrs[2] = malloc(h->fmt.height*sizeof(char*)); h->mjpg_cinfo.comp_info[0].h_samp_factor = c->luma_h; h->mjpg_cinfo.comp_info[0].v_samp_factor = c->luma_v; h->mjpg_cinfo.comp_info[1].h_samp_factor = 1; h->mjpg_cinfo.comp_info[1].v_samp_factor = 1; h->mjpg_cinfo.comp_info[2].h_samp_factor = 1; h->mjpg_cinfo.comp_info[2].v_samp_factor = 1; jpeg_suppress_tables(&h->mjpg_cinfo, TRUE); return h; }
/* * Class: org_apache_harmony_x_imageio_plugins_jpeg_JPEGImageWriter * Method: encode * Signature: ([BIIIIIIIZ[[IJ)Z */ JNIEXPORT jboolean JNICALL Java_org_apache_harmony_x_imageio_plugins_jpeg_JPEGImageWriter_encode(JNIEnv *env, jobject callerObj, jbyteArray arr, jint srcWidth, jint width, jint height, jint deltaX, jint in_cs, jint out_cs, jint numBands, jboolean progressive, jobjectArray dqts, jlong handle) { JSAMPROW row_pointer; struct jpeg_compress_struct * cinfo; enc_error_mgr_ptr err_mgr; int i, j; int cur_scanline; unsigned char * native_buffer; unsigned char * rowPtr; jboolean optimizeHuffman = FALSE; row_pointer = (JSAMPROW) malloc(width * numBands); if (!row_pointer) { throwNewOutOfMemoryError(env, "Unable to allocate memory for IJG structures"); return FALSE; } cinfo = (struct jpeg_compress_struct *) (IDATA)handle; err_mgr = (enc_error_mgr_ptr) cinfo->err; if (setjmp(err_mgr->jmp_buffer)) { if (!(*env)->ExceptionOccurred(env)) { char msg_buffer[JMSG_LENGTH_MAX]; cinfo->err->format_message((j_common_ptr)cinfo, msg_buffer); throwNewExceptionByName(env, "javax/imageio/IIOException", msg_buffer); } if (row_pointer) { free(row_pointer); } return FALSE; } cinfo->image_width = width; cinfo->image_height = height; cinfo->input_components = numBands; cinfo->in_color_space = in_cs; jpeg_set_defaults(cinfo); jpeg_set_colorspace(cinfo, out_cs); cinfo->optimize_coding = optimizeHuffman; //-- TRUE - for pure abbrivated images (wo tables) creation //-- if you want to write some tables set "sent_table = FALSE" after //-- this call for the table to be emitted. //jpeg_suppress_tables(&cinfo, TRUE); jpeg_suppress_tables(cinfo, FALSE); setupDQTs(env, cinfo, dqts); //-- only simple progression sequence if (progressive) { jpeg_simple_progression(cinfo); } //-- TRUE forces all "sent_table = FALSE" so all tables will be written jpeg_start_compress(cinfo, TRUE); //-- use this for tables-only files and abbrivated images. //-- If using jpeg_suppress_tables(&cinfo, TRUE): //-- Only DQT sent_table = FALSE right now -> so DQT will be written but not DHT. //-- uncomment when custom huffman tables be used. //jpeg_start_compress(&cinfo, FALSE); cur_scanline = 0; while (cinfo->next_scanline < cinfo->image_height) { (*env)->CallVoidMethod(env, callerObj, getScanlineID, cur_scanline); // checking for an exception in the java method if ((*env)->ExceptionOccurred(env)) { //c_struct->exception_in_callback = TRUE; cinfo->err->error_exit((j_common_ptr) cinfo); } native_buffer = (JOCTET*) (*env)->GetPrimitiveArrayCritical(env, arr, NULL); // subsampling and copying to internal array rowPtr = row_pointer; for (i = 0; i < srcWidth * numBands; i += numBands * deltaX) { for (j = 0; j < numBands; j++) { *rowPtr++ = native_buffer[i + j]; } } (*env)->ReleasePrimitiveArrayCritical(env, arr, native_buffer, 0); jpeg_write_scanlines(cinfo, &row_pointer, 1); cur_scanline++; } jpeg_finish_compress(cinfo); free(row_pointer); return TRUE; }
int ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes) { JPEGENCODERSTATE* context = (JPEGENCODERSTATE*) state->context; int ok; if (setjmp(context->error.setjmp_buffer)) { /* JPEG error handler */ jpeg_destroy_compress(&context->cinfo); state->errcode = IMAGING_CODEC_BROKEN; return -1; } if (!state->state) { /* Setup compression context (very similar to the decoder) */ context->cinfo.err = jpeg_std_error(&context->error.pub); context->error.pub.error_exit = error; jpeg_create_compress(&context->cinfo); jpeg_buffer_dest(&context->cinfo, &context->destination); context->extra_offset = 0; /* Ready to encode */ state->state = 1; } /* Load the destination buffer */ context->destination.pub.next_output_byte = buf; context->destination.pub.free_in_buffer = bytes; switch (state->state) { case 1: context->cinfo.image_width = state->xsize; context->cinfo.image_height = state->ysize; switch (state->bits) { case 8: context->cinfo.input_components = 1; context->cinfo.in_color_space = JCS_GRAYSCALE; break; case 24: context->cinfo.input_components = 3; if (strcmp(im->mode, "YCbCr") == 0) context->cinfo.in_color_space = JCS_YCbCr; else context->cinfo.in_color_space = JCS_RGB; break; case 32: context->cinfo.input_components = 4; context->cinfo.in_color_space = JCS_CMYK; break; default: state->errcode = IMAGING_CODEC_CONFIG; return -1; } /* Compressor configuration */ jpeg_set_defaults(&context->cinfo); /* Use custom quantization tables */ if (context->qtables) { int i; int quality = 100; if (context->quality > 0) { quality = context->quality; } for (i = 0; i < sizeof(context->qtables)/sizeof(unsigned int); i++) { // TODO: Should add support for none baseline jpeg_add_quant_table(&context->cinfo, i, context->qtables[i], quality, TRUE); } } else if (context->quality > 0) { jpeg_set_quality(&context->cinfo, context->quality, 1); } /* Set subsampling options */ switch (context->subsampling) { case 0: /* 1x1 1x1 1x1 (4:4:4) : None */ { context->cinfo.comp_info[0].h_samp_factor = 1; context->cinfo.comp_info[0].v_samp_factor = 1; context->cinfo.comp_info[1].h_samp_factor = 1; context->cinfo.comp_info[1].v_samp_factor = 1; context->cinfo.comp_info[2].h_samp_factor = 1; context->cinfo.comp_info[2].v_samp_factor = 1; break; } case 1: /* 2x1, 1x1, 1x1 (4:2:2) : Medium */ { context->cinfo.comp_info[0].h_samp_factor = 2; context->cinfo.comp_info[0].v_samp_factor = 1; context->cinfo.comp_info[1].h_samp_factor = 1; context->cinfo.comp_info[1].v_samp_factor = 1; context->cinfo.comp_info[2].h_samp_factor = 1; context->cinfo.comp_info[2].v_samp_factor = 1; break; } case 2: /* 2x2, 1x1, 1x1 (4:1:1) : High */ { context->cinfo.comp_info[0].h_samp_factor = 2; context->cinfo.comp_info[0].v_samp_factor = 2; context->cinfo.comp_info[1].h_samp_factor = 1; context->cinfo.comp_info[1].v_samp_factor = 1; context->cinfo.comp_info[2].h_samp_factor = 1; context->cinfo.comp_info[2].v_samp_factor = 1; break; } default: { /* Use the lib's default */ break; } } if (context->progressive) jpeg_simple_progression(&context->cinfo); context->cinfo.smoothing_factor = context->smooth; context->cinfo.optimize_coding = (boolean) context->optimize; if (context->xdpi > 0 && context->ydpi > 0) { context->cinfo.density_unit = 1; /* dots per inch */ context->cinfo.X_density = context->xdpi; context->cinfo.Y_density = context->ydpi; } switch (context->streamtype) { case 1: /* tables only -- not yet implemented */ state->errcode = IMAGING_CODEC_CONFIG; return -1; case 2: /* image only */ jpeg_suppress_tables(&context->cinfo, TRUE); jpeg_start_compress(&context->cinfo, FALSE); /* suppress extra section */ context->extra_offset = context->extra_size; //add exif header if (context->rawExifLen > 0) jpeg_write_marker(&context->cinfo, JPEG_APP0+1, (unsigned char*)context->rawExif, context->rawExifLen); break; default: /* interchange stream */ jpeg_start_compress(&context->cinfo, TRUE); //add exif header if (context->rawExifLen > 0) jpeg_write_marker(&context->cinfo, JPEG_APP0+1, (unsigned char*)context->rawExif, context->rawExifLen); break; } state->state++; /* fall through */ case 2: if (context->extra) { /* copy extra buffer to output buffer */ unsigned int n = context->extra_size - context->extra_offset; if (n > context->destination.pub.free_in_buffer) n = context->destination.pub.free_in_buffer; memcpy(context->destination.pub.next_output_byte, context->extra + context->extra_offset, n); context->destination.pub.next_output_byte += n; context->destination.pub.free_in_buffer -= n; context->extra_offset += n; if (context->extra_offset >= context->extra_size) state->state++; else break; } else state->state++; case 3: ok = 1; while (state->y < state->ysize) { state->shuffle(state->buffer, (UINT8*) im->image[state->y + state->yoff] + state->xoff * im->pixelsize, state->xsize); ok = jpeg_write_scanlines(&context->cinfo, &state->buffer, 1); if (ok != 1) break; state->y++; } if (ok != 1) break; state->state++; /* fall through */ case 4: /* Finish compression */ if (context->destination.pub.free_in_buffer < 100) break; jpeg_finish_compress(&context->cinfo); /* Clean up */ if (context->extra) free(context->extra); jpeg_destroy_compress(&context->cinfo); /* if (jerr.pub.num_warnings) return BROKEN; */ state->errcode = IMAGING_CODEC_END; break; } /* Return number of bytes in output buffer */ return context->destination.pub.next_output_byte - buf; }
void ModeJpeg::jpegCompressForJetReady() { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; jmp_buf setjmp_buffer; // Use the modified Mojave CSC table hp_rgb_ycc_setup (1); compressedsize = 0; memset (compressBuf, 0xFF, m_max_file_size); cinfo.err = jpeg_std_error (&jerr); jerr.error_exit = HPJpeg_error; if (setjmp (setjmp_buffer)) { jpeg_destroy_compress (&cinfo); return; } jpeg_create_compress (&cinfo); cinfo.in_color_space = (m_iColorMode == 0) ? JCS_RGB : JCS_GRAYSCALE; jpeg_set_defaults (&cinfo); cinfo.image_width = m_iRowWidth / 3; cinfo.image_height = m_iBandHeight; cinfo.input_components = (m_iColorMode == 0) ? 3 : 1; cinfo.data_precision = 8; // Create a static quant table here. static unsigned int mojave_quant_table1[64] = { 2,3,4,5,5,5,5,5, 3,6,5,8,5,8,5,8, 4,5,5,5,5,5,5,5, 5,8,5,8,5,8,5,8, 5,5,5,5,5,5,5,5, 5,8,5,8,5,8,5,8, 5,5,5,5,5,5,5,5, 5,8,5,8,5,8,5,8 }; // // JetReady specific Q-Tables will be added here. We do the following: // 1. Add three Q-Tables. // 2. Scale the Q-Table elemets with the given scale factor. // 3. Check to see if any of the element in the table is greater than 255 // reset that elemet to 255. // 5. There is a specific scaling needed to be done to the first 6 // elements in the matrix. This is required to achieve better // compression ratio. // 4. Check to see if any the of the recently modified element is // greater than 255, reset that to 255. // // Please refer to sRGBLaserHostBasedSoftwareERS.doc v9.0 section 5.2.5.3.1.1 // for more details. // // [NOTE] These loop needs to be further optimized. // for (int i = 0; i < 3; i++) { // Adding Q-Table. jpeg_add_quant_table(&cinfo, i, mojave_quant_table1, 0, FALSE ); // // Scaling the Q-Table elements. // Reset the element to 255, if it is greater than 255. // for(int j = 1; j < 64; j++) { cinfo.quant_tbl_ptrs[i]->quantval[j] = (UINT16)((mojave_quant_table1[j] * m_pQTableInfo->qFactor) & 0xFF); } // for (int j = 1; j < 64; j++) // // Special scaling for first 6 elements in the table. // Reset the specially scaled elements 255, if it is greater than 255. // // // 1st component in the table. Unchanged, I need not change anything here. // cinfo.quant_tbl_ptrs[i]->quantval[0] = (UINT16)mojave_quant_table1[0]; // // 2nd and 3rd components in the zig zag order // // The following dTemp is being used to ceil the vales: e.g 28.5 to 29 // double dTemp = mojave_quant_table1[1] * (1 + 0.25 * (m_pQTableInfo->qFactor - 1)) + 0.5; cinfo.quant_tbl_ptrs[i]->quantval[1] = (UINT16)dTemp & 0xFF; dTemp = mojave_quant_table1[8] * (1 + 0.25 * (m_pQTableInfo->qFactor - 1)) + 0.5; cinfo.quant_tbl_ptrs[i]->quantval[8] = (UINT16)dTemp & 0xFF; // // 4th, 5th and 6th components in the zig zag order // dTemp = mojave_quant_table1[16] * (1 + 0.50 * (m_pQTableInfo->qFactor - 1)) + 0.5; cinfo.quant_tbl_ptrs[i]->quantval[16] = (UINT16)dTemp & 0xFF; dTemp = mojave_quant_table1[9] * (1 + 0.50 * (m_pQTableInfo->qFactor - 1)) + 0.5; cinfo.quant_tbl_ptrs[i]->quantval[9] = (UINT16)dTemp & 0xFF; dTemp = mojave_quant_table1[2] * (1 + 0.50 * (m_pQTableInfo->qFactor - 1)) + 0.5; cinfo.quant_tbl_ptrs[i]->quantval[2] = (UINT16)dTemp & 0xFF; } // for (i = 0; i < 3; i++) // Hard code to use sampling mode 4:4:4 cinfo.comp_info[0].h_samp_factor = 1; cinfo.comp_info[0].v_samp_factor = 1; jpeg_buffer_dest (&cinfo, (JOCTET *) this, (void *) (output_buffer_callback)); int row_width = m_iRowWidth; if (m_iColorMode != 0) { row_width = m_iRowWidth / 3; cinfo.write_JFIF_header = FALSE; cinfo.write_Adobe_marker = FALSE; jpeg_suppress_tables(&cinfo, TRUE); } jpeg_start_compress (&cinfo, TRUE); JSAMPROW pRowArray[1]; BYTE *pScanLine = m_pbyInputBuffer; int i; for (i = 0; i < m_iBandHeight; i++) { pRowArray[0] = (JSAMPROW) pScanLine; jpeg_write_scanlines (&cinfo, pRowArray, 1); pScanLine += (row_width); } jpeg_finish_compress (&cinfo); // Read the quantization table used for this compression if (cinfo.quant_tbl_ptrs[0] != NULL) { // memcpy(m_pQTableInfo->qtable0, cinfo.quant_tbl_ptrs[0]->quantval, QTABLE_SIZE); for (i = 0; i < QTABLE_SIZE; i++) { m_pQTableInfo->qtable0[i] = cinfo.quant_tbl_ptrs[0]->quantval[i]; } } if (cinfo.quant_tbl_ptrs[1] != NULL) { // memcpy(m_pQTableInfo->qtable1, cinfo.quant_tbl_ptrs[1]->quantval, QTABLE_SIZE); for (i = 0; i < QTABLE_SIZE; i++) { m_pQTableInfo->qtable1[i] = cinfo.quant_tbl_ptrs[1]->quantval[i]; } } if (cinfo.quant_tbl_ptrs[2] != NULL) { // memcpy(m_pQTableInfo->qtable2, cinfo.quant_tbl_ptrs[2]->quantval, QTABLE_SIZE); for (i = 0; i < QTABLE_SIZE; i++) { m_pQTableInfo->qtable2[i] = cinfo.quant_tbl_ptrs[2]->quantval[i]; } } jpeg_destroy_compress (&cinfo); if (m_iColorMode != 0) { unsigned int l = 0; while (l < compressedsize) { if (compressBuf[l] == 0xFF && compressBuf[l+1] == 0xDA) break; l++; } if (l != compressedsize) { m_uiGrayscaleOffset = l + 10; } } }