Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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");
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
/*
 * 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;
}
Exemplo n.º 9
0
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;

}
Exemplo n.º 10
0
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;
        }
    }
}