int DecompressJpegRect(int x, int y, int w, int h) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; int compressedLen; CARD8 *compressedData; CARD16 *pixelPtr; JSAMPROW rowPointer[1]; int dx, dy; compressedLen = (int)ReadCompactLen(); if (compressedLen <= 0) { fprintf(stderr, "Incorrect data received from the server.\n"); return 0; } compressedData = malloc(compressedLen); if (compressedData == NULL) { fprintf(stderr, "Memory allocation error.\n"); return 0; } if (!read_from_rfb_server(sock, (char*)compressedData, compressedLen)) { free(compressedData); return 0; } cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); JpegSetSrcManager(&cinfo, compressedData, compressedLen); jpeg_read_header(&cinfo, TRUE); cinfo.out_color_space = JCS_RGB; jpeg_start_decompress(&cinfo); if (cinfo.output_width != w || cinfo.output_height != h || cinfo.output_components != 3) { fprintf(stderr, "Tight Encoding: Wrong JPEG data received.\n"); jpeg_destroy_decompress(&cinfo); free(compressedData); return 0; } rowPointer[0] = (JSAMPROW)buffer; dy = 0; while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, rowPointer, 1); if (jpegError) { break; } /* FIXME 16 bpp hardcoded */ /* Fill the second half of our global buffer with the uncompressed data */ pixelPtr = (CARD16 *)&buffer[BUFFER_SIZE / 2]; for (dx = 0; dx < w; dx++) { *pixelPtr++ = RGB24_TO_PIXEL(16, buffer[dx*3], buffer[dx*3+1], buffer[dx*3+2]); } /* write scanline to screen */ dfb_write_data_to_screen(x, y + dy, w, 1, &buffer[BUFFER_SIZE/2]); dy++; } if (!jpegError) jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); free(compressedData); return !jpegError; }
void ClientConnection::DecompressJpegRect(BYTE *src, int srclen, BYTE *dst, int dst_size,int w, int h,rfbPixelFormat m_remoteformat) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; int pixelsize; BYTE *dstBuf=NULL; bool dstBufIsTemp = false; // Set up JPEG decompression cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); JpegSetSrcManager(&cinfo, (char*)src, srclen); jpeg_read_header(&cinfo, TRUE); cinfo.out_color_space = JCS_RGB; pixelsize = 3; #ifdef JCS_EXTENSIONS // Try to have libjpeg output directly to 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; } // libjpeg can only handle some "standard" formats if(redShift == 0 && greenShift == 8 && blueShift == 16) cinfo.out_color_space = JCS_EXT_RGBX; if(redShift == 16 && greenShift == 8 && blueShift == 0) cinfo.out_color_space = JCS_EXT_BGRX; if(redShift == 24 && greenShift == 16 && blueShift == 8) cinfo.out_color_space = JCS_EXT_XBGR; if(redShift == 8 && greenShift == 16 && blueShift == 24) cinfo.out_color_space = JCS_EXT_XRGB; if (cinfo.out_color_space != JCS_RGB) { dstBuf = dst; pixelsize = 4; } } #endif if (cinfo.out_color_space == JCS_RGB) { dstBuf = new BYTE[w * h * pixelsize]; dstBufIsTemp = true; } JSAMPROW *rowPointer = new JSAMPROW[h]; for (int dy = 0; dy < h; dy++) rowPointer[dy] = (JSAMPROW)(&dstBuf[dy * w * pixelsize]); jpeg_start_decompress(&cinfo); if (cinfo.output_width != (unsigned)w || cinfo.output_height != (unsigned)h || cinfo.output_components != pixelsize) { jpeg_destroy_decompress(&cinfo); return; } while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, &rowPointer[cinfo.output_scanline], cinfo.output_height - cinfo.output_scanline); if (jpegError) { break; } } delete [] rowPointer; if (!jpegError) { jpeg_finish_decompress(&cinfo); } jpeg_destroy_decompress(&cinfo); if (dstBufIsTemp) delete [] dstBuf; return ; }