char *JpegCompressData(XImage *image, int level, int *compressed_size) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; CARD8 *srcBuf; JSAMPROW rowPointer[1]; int dy, w, h; *compressed_size = 0; /* * Initialize the image stuff */ bitsPerPixel = image -> bits_per_pixel; bytesPerLine = image -> bytes_per_line; byteOrder = image -> byte_order; #ifdef TEST fprintf(stderr, "******JpegCompressData: Image byte order [%d] bitmap bit order [%d].\n", image -> byte_order, image -> bitmap_bit_order); fprintf(stderr, "******JpegCompressData: Bits per pixel [%d] bytes per line [%d].\n", bitsPerPixel, bytesPerLine); #endif redShift = FindLSB(image -> red_mask) - 1; greenShift = FindLSB(image -> green_mask) - 1; blueShift = FindLSB(image -> blue_mask) - 1; #ifdef TEST fprintf(stderr, "******JpegCompressData: Red mask [0x%lx] green mask [0x%lx] blue mask [0x%lx].\n", image -> red_mask, image -> green_mask, image -> blue_mask); fprintf(stderr, "******JpegCompressData: Red shift [%d] green shift [%d] blue shift [%d].\n", redShift, greenShift, blueShift); #endif redMax = image -> red_mask >> redShift; greenMax = image -> green_mask >> greenShift; blueMax = image -> blue_mask >> blueShift; #ifdef TEST fprintf(stderr, "******JpegCompressData: Red max [0x%x] green max [0x%x] blue max [0x%x].\n", redMax, greenMax, blueMax); #endif w = image -> width; h = image -> height; jpegBeforeBuf = image -> data; #ifdef DEBUG fprintf(stderr, "******JpegCompressData: Width [%d] height [%d] level [%d].\n", w, h, level); #endif if (bitsPerPixel == 1 || bitsPerPixel == 8) { #ifdef PANIC fprintf(stderr, "******JpegCompressData: PANIC! Invalid bits per pixel [%d].\n", bitsPerPixel); #endif return NULL; } /* * Allocate space for one line of the * resulting image, 3 bytes per pixel. */ #ifdef DEBUG fprintf(stderr, "******JpegCompressData: Allocating [%d] bytes for the scanline.\n", w * 3); #endif srcBuf = (CARD8 *) malloc(w * 3); if (srcBuf == NULL) { #ifdef PANIC fprintf(stderr, "******JpegCompressData: PANIC! Cannot allocate [%d] bytes.\n", w * 3); #endif return NULL; } rowPointer[0] = srcBuf; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); cinfo.image_width = w; cinfo.image_height = h; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, jpegQuality[level], 1); /* * Allocate memory for the destination * buffer. */ jpegCompBufSize = JPEG_DEST_SIZE(w, h); #ifdef TEST fprintf(stderr, "******JpegCompressData: Allocating [%d] bytes for the destination data.\n", jpegCompBufSize); #endif jpegCompBuf = malloc(jpegCompBufSize); if (jpegCompBuf == NULL) { #ifdef PANIC fprintf(stderr, "******JpegCompressData: PANIC! Error allocating [%d] bytes for the Jpeg data.\n", jpegCompBufSize); #endif return NULL; } JpegSetDstManager(&cinfo); jpeg_start_compress(&cinfo, 1); #ifdef DEBUG fprintf(stderr, "******JpegCompressedData: Initialization finished.\n"); #endif for (dy = 0; dy < h; dy++) { PrepareRowForJpeg(srcBuf, dy, w); jpeg_write_scanlines(&cinfo, rowPointer, 1); if (jpegError != 0) { break; } } #ifdef DEBUG fprintf(stderr, "******JpegCompressedData: Compression finished. Lines handled [%d,%d]. Error is [%d].\n", dy, h, jpegError); #endif if (jpegError == 0) { jpeg_finish_compress(&cinfo); } jpeg_destroy_compress(&cinfo); free((char *) srcBuf); if (jpegError != 0) { #ifdef PANIC fprintf(stderr, "******JpegCompressedData: PANIC! Compression failed. Error is [%d].\n", jpegError); #endif free(jpegCompBuf); return NULL; } /* * Check the size of the resulting data. */ if (jpegDstDataLen > 0) { /* * Save the image on disk to help with * the debug. */ #ifdef DEBUG int i = 0; fprintf(stderr, "******JpegCompressedData: Compressed size [%d].\n", jpegDstDataLen); jpegId++; sprintf(jpegName, "jpeg%d", jpegId); jpegFile = fopen(jpegName, "w"); for (i = 0; i < jpegDstDataLen; i++) { fprintf(jpegFile, "%c", *(jpegCompBuf + i)); } fclose(jpegFile); #endif *compressed_size = jpegDstDataLen; return jpegCompBuf; } else { #ifdef PANIC fprintf(stderr, "******JpegCompressedData: PANIC! Invalid size of the compressed data [%d].\n", jpegDstDataLen); #endif free(jpegCompBuf); return NULL; } }
int vncEncodeUltra2::SendJpegRect(BYTE *src,BYTE *dst, int dst_size, int w, int h, int quality,rfbPixelFormat m_remoteformat) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); BYTE *srcBuf=NULL; cinfo.image_width = w; cinfo.image_height = h; cinfo.in_color_space = JCS_RGB; cinfo.input_components = 3; #ifdef JCS_EXTENSIONS // Try to have libjpeg read directly from our native format if(m_remoteformat.bitsPerPixel==32) { int redShift, greenShift, blueShift; if(m_remoteformat.bigEndian) { redShift = 24 - m_remoteformat.redShift; greenShift = 24 - m_remoteformat.greenShift; blueShift = 24 - m_remoteformat.blueShift; } else { redShift = m_remoteformat.redShift; greenShift = m_remoteformat.greenShift; blueShift = m_remoteformat.blueShift; } if(redShift == 0 && greenShift == 8 && blueShift == 16) cinfo.in_color_space = JCS_EXT_RGBX; if(redShift == 16 && greenShift == 8 && blueShift == 0) cinfo.in_color_space = JCS_EXT_BGRX; if(redShift == 24 && greenShift == 16 && blueShift == 8) cinfo.in_color_space = JCS_EXT_XBGR; if(redShift == 8 && greenShift == 16 && blueShift == 24) cinfo.in_color_space = JCS_EXT_XRGB; if (cinfo.in_color_space != JCS_RGB) { srcBuf = src; cinfo.input_components = 4; } } #endif jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); if(quality >= 96) cinfo.dct_method = JDCT_ISLOW; else cinfo.dct_method = JDCT_FASTEST; cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 2; JpegSetDstManager(&cinfo, dst, dst_size); JSAMPROW *rowPointer = new JSAMPROW[h]; for (int dy = 0; dy < h; dy++) rowPointer[dy] = (JSAMPROW)(&srcBuf[dy * w * 4]); jpeg_start_compress(&cinfo, TRUE); while (cinfo.next_scanline < cinfo.image_height) { jpeg_write_scanlines(&cinfo, &rowPointer[cinfo.next_scanline], cinfo.image_height - cinfo.next_scanline); if (jpegError) break; } if (!jpegError) jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); delete[] rowPointer; if (jpegError) return 0; return jpegDstDataLen; }