summaryrefslogtreecommitdiff
path: root/svtools/source/filter/jpeg/jpegc.c
diff options
context:
space:
mode:
Diffstat (limited to 'svtools/source/filter/jpeg/jpegc.c')
-rw-r--r--svtools/source/filter/jpeg/jpegc.c284
1 files changed, 284 insertions, 0 deletions
diff --git a/svtools/source/filter/jpeg/jpegc.c b/svtools/source/filter/jpeg/jpegc.c
new file mode 100644
index 000000000000..8d3a82a86ef3
--- /dev/null
+++ b/svtools/source/filter/jpeg/jpegc.c
@@ -0,0 +1,284 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "setjmp.h"
+#include "jpeglib.h"
+#include "jerror.h"
+#include "jpeg.h"
+#include "rtl/alloc.h"
+#include "osl/diagnose.h"
+
+struct my_error_mgr
+{
+ struct jpeg_error_mgr pub;
+ jmp_buf setjmp_buffer;
+};
+
+void jpeg_svstream_src (j_decompress_ptr cinfo, void* infile);
+void jpeg_svstream_dest (j_compress_ptr cinfo, void* outfile);
+
+METHODDEF( void )
+my_error_exit (j_common_ptr cinfo)
+{
+ my_error_ptr myerr = (my_error_ptr) cinfo->err;
+ (*cinfo->err->output_message) (cinfo);
+ longjmp(myerr->setjmp_buffer, 1);
+}
+
+
+METHODDEF( void )
+my_output_message (j_common_ptr cinfo)
+{
+ char buffer[JMSG_LENGTH_MAX];
+ (*cinfo->err->format_message) (cinfo, buffer);
+}
+
+/* TODO: when incompatible changes are possible again
+ the preview size hint should be redone */
+static int nPreviewWidth = 0;
+static int nPreviewHeight = 0;
+void SetJpegPreviewSizeHint( int nWidth, int nHeight )
+{
+ nPreviewWidth = nWidth;
+ nPreviewHeight = nHeight;
+}
+
+void ReadJPEG( void* pJPEGReader, void* pIStm, long* pLines )
+{
+ struct jpeg_decompress_struct cinfo;
+ struct my_error_mgr jerr;
+ struct JPEGCreateBitmapParam aCreateBitmapParam;
+ HPBYTE pDIB;
+ HPBYTE pTmp;
+ long nWidth;
+ long nHeight;
+ long nAlignedWidth;
+ JSAMPLE * range_limit;
+ HPBYTE pScanLineBuffer = NULL;
+ long nScanLineBufferComponents = 0;
+ // declare bDecompCreated volatile because of gcc
+ // warning: variable 'bDecompCreated' might be clobbered by `longjmp' or `vfork'
+ volatile long bDecompCreated = 0;
+
+ /* Falls der Stream nicht ausreicht (IO_PENDING)
+ wird ueber ein longjmp in der Schleife nach Exit
+ gesprungen, wir geben dann die Anzahl
+ der bisher bearbeiteten Scanlines zurueck*/
+ if ( setjmp( jerr.setjmp_buffer ) )
+ goto Exit;
+
+ cinfo.err = jpeg_std_error( &jerr.pub );
+ jerr.pub.error_exit = my_error_exit;
+ jerr.pub.output_message = my_output_message;
+
+ jpeg_create_decompress( &cinfo );
+ bDecompCreated = 1;
+ jpeg_svstream_src( &cinfo, pIStm );
+ jpeg_read_header( &cinfo, sal_True );
+
+ cinfo.scale_num = 1;
+ cinfo.scale_denom = 1;
+ cinfo.output_gamma = 1.0;
+ cinfo.raw_data_out = sal_False;
+ cinfo.quantize_colors = sal_False;
+ if ( cinfo.jpeg_color_space == JCS_YCbCr )
+ cinfo.out_color_space = JCS_RGB;
+ else if ( cinfo.jpeg_color_space == JCS_YCCK )
+ cinfo.out_color_space = JCS_CMYK;
+
+ OSL_ASSERT(cinfo.out_color_space == JCS_CMYK || cinfo.out_color_space == JCS_GRAYSCALE || cinfo.out_color_space == JCS_RGB);
+
+ /* change scale for preview import */
+ if( nPreviewWidth || nPreviewHeight )
+ {
+ if( nPreviewWidth == 0 ) {
+ nPreviewWidth = ( cinfo.image_width*nPreviewHeight )/cinfo.image_height;
+ if( nPreviewWidth <= 0 )
+ nPreviewWidth = 1;
+ } else if( nPreviewHeight == 0 ) {
+ nPreviewHeight = ( cinfo.image_height*nPreviewWidth )/cinfo.image_width;
+ if( nPreviewHeight <= 0 )
+ nPreviewHeight = 1;
+ }
+
+ for( cinfo.scale_denom = 1; cinfo.scale_denom < 8; cinfo.scale_denom *= 2 )
+ {
+ if( cinfo.image_width < nPreviewWidth * cinfo.scale_denom )
+ break;
+ if( cinfo.image_height < nPreviewHeight * cinfo.scale_denom )
+ break;
+ }
+
+ if( cinfo.scale_denom > 1 )
+ {
+ cinfo.dct_method = JDCT_FASTEST;
+ cinfo.do_fancy_upsampling = sal_False;
+ cinfo.do_block_smoothing = sal_False;
+ }
+ }
+
+ jpeg_start_decompress( &cinfo );
+
+ nWidth = cinfo.output_width;
+ nHeight = cinfo.output_height;
+ aCreateBitmapParam.nWidth = nWidth;
+ aCreateBitmapParam.nHeight = nHeight;
+
+ aCreateBitmapParam.density_unit = cinfo.density_unit;
+ aCreateBitmapParam.X_density = cinfo.X_density;
+ aCreateBitmapParam.Y_density = cinfo.Y_density;
+ aCreateBitmapParam.bGray = cinfo.output_components == 1;
+ pDIB = CreateBitmap( pJPEGReader, &aCreateBitmapParam );
+ nAlignedWidth = aCreateBitmapParam.nAlignedWidth;
+ range_limit=cinfo.sample_range_limit;
+
+ if ( cinfo.out_color_space == JCS_CMYK )
+ {
+ nScanLineBufferComponents = cinfo.output_width * 4;
+ pScanLineBuffer = rtl_allocateMemory( nScanLineBufferComponents );
+ }
+
+ if( pDIB )
+ {
+ if( aCreateBitmapParam.bTopDown )
+ pTmp = pDIB;
+ else
+ {
+ pTmp = pDIB + ( nHeight - 1 ) * nAlignedWidth;
+ nAlignedWidth = -nAlignedWidth;
+ }
+
+ for ( *pLines = 0; *pLines < nHeight; (*pLines)++ )
+ {
+ if (pScanLineBuffer!=NULL) { // in other words cinfo.out_color_space == JCS_CMYK
+ int i;
+ int j;
+ jpeg_read_scanlines( &cinfo, (JSAMPARRAY) &pScanLineBuffer, 1 );
+ // convert CMYK to RGB
+ for( i=0, j=0; i < nScanLineBufferComponents; i+=4, j+=3 )
+ {
+ int c_=255-pScanLineBuffer[i+0];
+ int m_=255-pScanLineBuffer[i+1];
+ int y_=255-pScanLineBuffer[i+2];
+ int k_=255-pScanLineBuffer[i+3];
+ pTmp[j+0]=range_limit[ 255L - ( c_ + k_ ) ];
+ pTmp[j+1]=range_limit[ 255L - ( m_ + k_ ) ];
+ pTmp[j+2]=range_limit[ 255L - ( y_ + k_ ) ];
+ }
+ } else {
+ jpeg_read_scanlines( &cinfo, (JSAMPARRAY) &pTmp, 1 );
+ }
+ /* PENDING ??? */
+ if ( cinfo.err->msg_code == 113 )
+ break;
+
+ pTmp += nAlignedWidth;
+ }
+ }
+
+ jpeg_finish_decompress( &cinfo );
+ if (pScanLineBuffer!=NULL) {
+ rtl_freeMemory( pScanLineBuffer );
+ pScanLineBuffer=NULL;
+ }
+
+Exit:
+
+ if( bDecompCreated )
+ jpeg_destroy_decompress( &cinfo );
+}
+
+long WriteJPEG( void* pJPEGWriter, void* pOStm,
+ long nWidth, long nHeight, long bGreys,
+ long nQualityPercent, void* pCallbackData )
+{
+ struct jpeg_compress_struct cinfo;
+ struct my_error_mgr jerr;
+ void* pScanline;
+ long nY;
+ // declare bCompCreated, bRet volatile because of gcc
+ // warning: variable 'bCompCreated' might be clobbered by `longjmp' or `vfork'
+ volatile long bCompCreated = 0;
+ volatile long bRet = 0;
+
+ if ( setjmp( jerr.setjmp_buffer ) )
+ goto Exit;
+
+ cinfo.err = jpeg_std_error( &jerr.pub );
+ jerr.pub.error_exit = my_error_exit;
+ jerr.pub.output_message = my_output_message;
+
+ jpeg_create_compress( &cinfo );
+ bCompCreated = 1;
+
+ jpeg_svstream_dest( &cinfo, pOStm );
+
+ cinfo.image_width = (JDIMENSION) nWidth;
+ cinfo.image_height = (JDIMENSION) nHeight;
+ if ( bGreys )
+ {
+ cinfo.input_components = 1;
+ cinfo.in_color_space = JCS_GRAYSCALE;
+ }
+ else
+ {
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+ }
+
+ jpeg_set_defaults( &cinfo );
+ jpeg_set_quality( &cinfo, (int) nQualityPercent, sal_False );
+
+ if ( ( nWidth > 128 ) || ( nHeight > 128 ) )
+ jpeg_simple_progression( &cinfo );
+
+ jpeg_start_compress( &cinfo, sal_True );
+
+ for( nY = 0; nY < nHeight; nY++ )
+ {
+ pScanline = GetScanline( pJPEGWriter, nY );
+
+ if( pScanline )
+ jpeg_write_scanlines( &cinfo, (JSAMPARRAY) &pScanline, 1 );
+
+ if( JPEGCallback( pCallbackData, nY * 100L / nHeight ) )
+ goto Exit;
+ }
+
+ bRet = 1;
+
+ jpeg_finish_compress(&cinfo);
+
+Exit:
+
+ if ( bCompCreated )
+ jpeg_destroy_compress( &cinfo );
+
+ return bRet;
+}