summaryrefslogtreecommitdiff
path: root/svtools
diff options
context:
space:
mode:
authorIvo Hinkelmann <ihi@openoffice.org>2011-03-29 18:14:38 +0200
committerIvo Hinkelmann <ihi@openoffice.org>2011-03-29 18:14:38 +0200
commit4296c7c855220334c38aaa9075287b7537ef544f (patch)
treeeb9ba12adb8cdfc75529197abbd20c9fba820069 /svtools
parent96198071f8a75ac34c49e0f8186d22df03da1ca5 (diff)
parent5164e89e3a6471c7e6be701c61071fd86725edfa (diff)
CWS-TOOLING: integrate CWS rsvglibs
Diffstat (limited to 'svtools')
-rw-r--r--svtools/source/filter.vcl/jpeg/jpeg.cxx777
-rw-r--r--svtools/source/filter.vcl/jpeg/jpegc.c284
2 files changed, 1061 insertions, 0 deletions
diff --git a/svtools/source/filter.vcl/jpeg/jpeg.cxx b/svtools/source/filter.vcl/jpeg/jpeg.cxx
new file mode 100644
index 000000000000..da1edf8449e4
--- /dev/null
+++ b/svtools/source/filter.vcl/jpeg/jpeg.cxx
@@ -0,0 +1,777 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svtools.hxx"
+
+#include <tools/solar.h>
+
+extern "C"
+{
+ #include "stdio.h"
+ #include "jpeg.h"
+ #include "jpeg/jpeglib.h"
+ #include "jpeg/jerror.h"
+}
+
+#define _JPEGPRIVATE
+#include <vcl/bmpacc.hxx>
+#include "jpeg.hxx"
+#include <svtools/FilterConfigItem.hxx>
+#include <svtools/filter.hxx>
+
+// -----------
+// - Defines -
+// -----------
+
+using namespace ::com::sun::star;
+
+#define JPEGMINREAD 512
+
+// -------------
+// - (C-Calls) -
+// -------------
+
+// ------------------------------------------------------------------------
+
+extern "C" void* CreateBitmap( void* pJPEGReader, void* pJPEGCreateBitmapParam )
+{
+ return ( (JPEGReader*) pJPEGReader )->CreateBitmap( pJPEGCreateBitmapParam );
+}
+
+// ------------------------------------------------------------------------
+
+extern "C" void* GetScanline( void* pJPEGWriter, long nY )
+{
+ return ( (JPEGWriter*) pJPEGWriter )->GetScanline( nY );
+}
+
+// ------------------------------------------------------------------------
+
+struct JPEGCallbackStruct
+{
+ uno::Reference< task::XStatusIndicator > xStatusIndicator;
+};
+
+extern "C" long JPEGCallback( void* pCallbackData, long nPercent )
+{
+ JPEGCallbackStruct* pS = (JPEGCallbackStruct*)pCallbackData;
+ if ( pS && pS->xStatusIndicator.is() )
+ {
+ pS->xStatusIndicator->setValue( nPercent );
+ }
+ return 0L;
+}
+
+#define BUF_SIZE 4096
+
+typedef struct
+{
+ struct jpeg_destination_mgr pub; /* public fields */
+
+ SvStream* outfile; /* target stream */
+ JOCTET * buffer; /* start of buffer */
+} my_destination_mgr;
+
+typedef my_destination_mgr * my_dest_ptr;
+
+extern "C" void init_destination (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+ /* Allocate the output buffer --- it will be released when done with image */
+ dest->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ BUF_SIZE * sizeof(JOCTET));
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = BUF_SIZE;
+}
+
+extern "C" int empty_output_buffer (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+ if (dest->outfile->Write(dest->buffer, BUF_SIZE) !=
+ (size_t) BUF_SIZE)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = BUF_SIZE;
+
+ return sal_True;
+}
+
+extern "C" void term_destination (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ size_t datacount = BUF_SIZE - dest->pub.free_in_buffer;
+
+ /* Write any data remaining in the buffer */
+ if (datacount > 0) {
+ if (dest->outfile->Write(dest->buffer, datacount) != datacount)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ }
+}
+
+extern "C" void jpeg_svstream_dest (j_compress_ptr cinfo, void* out)
+{
+ SvStream * outfile = (SvStream*)out;
+ my_dest_ptr dest;
+
+ /* The destination object is made permanent so that multiple JPEG images
+ * can be written to the same file without re-executing jpeg_svstream_dest.
+ * This makes it dangerous to use this manager and a different destination
+ * manager serially with the same JPEG object, because their private object
+ * sizes may be different. Caveat programmer.
+ */
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
+ cinfo->dest = (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(my_destination_mgr));
+ }
+
+ dest = (my_dest_ptr) cinfo->dest;
+ dest->pub.init_destination = init_destination;
+ dest->pub.empty_output_buffer = empty_output_buffer;
+ dest->pub.term_destination = term_destination;
+ dest->outfile = outfile;
+}
+
+/* Expanded data source object for stdio input */
+
+typedef struct {
+ struct jpeg_source_mgr pub; /* public fields */
+
+ SvStream * infile; /* source stream */
+ JOCTET * buffer; /* start of buffer */
+ boolean start_of_file; /* have we gotten any data yet? */
+} my_source_mgr;
+
+typedef my_source_mgr * my_src_ptr;
+
+/*
+ * Initialize source --- called by jpeg_read_header
+ * before any data is actually read.
+ */
+
+extern "C" void init_source (j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ /* We reset the empty-input-file flag for each image,
+ * but we don't clear the input buffer.
+ * This is correct behavior for reading a series of images from one source.
+ */
+ src->start_of_file = sal_True;
+}
+
+long StreamRead( SvStream* pSvStm, void* pBuffer, long nBufferSize )
+{
+ long nRead;
+
+ if( pSvStm->GetError() != ERRCODE_IO_PENDING )
+ {
+ long nActPos = pSvStm->Tell();
+
+ nRead = (long) pSvStm->Read( pBuffer, nBufferSize );
+
+ if( pSvStm->GetError() == ERRCODE_IO_PENDING )
+ {
+ nRead = 0;
+
+ // Damit wir wieder an die alte Position
+ // seeken koennen, setzen wir den Error temp.zurueck
+ pSvStm->ResetError();
+ pSvStm->Seek( nActPos );
+ pSvStm->SetError( ERRCODE_IO_PENDING );
+ }
+ }
+ else
+ nRead = 0;
+
+ return nRead;
+}
+
+extern "C" int fill_input_buffer (j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+ size_t nbytes;
+
+ nbytes = StreamRead(src->infile, src->buffer, BUF_SIZE);
+
+ if (nbytes <= 0) {
+ if (src->start_of_file) /* Treat empty input file as fatal error */
+ ERREXIT(cinfo, JERR_INPUT_EMPTY);
+ WARNMS(cinfo, JWRN_JPEG_EOF);
+ /* Insert a fake EOI marker */
+ src->buffer[0] = (JOCTET) 0xFF;
+ src->buffer[1] = (JOCTET) JPEG_EOI;
+ nbytes = 2;
+ }
+
+ src->pub.next_input_byte = src->buffer;
+ src->pub.bytes_in_buffer = nbytes;
+ src->start_of_file = sal_False;
+
+ return sal_True;
+}
+
+extern "C" void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ /* Just a dumb implementation for now. Could use fseek() except
+ * it doesn't work on pipes. Not clear that being smart is worth
+ * any trouble anyway --- large skips are infrequent.
+ */
+ if (num_bytes > 0) {
+ while (num_bytes > (long) src->pub.bytes_in_buffer) {
+ num_bytes -= (long) src->pub.bytes_in_buffer;
+ (void) fill_input_buffer(cinfo);
+ /* note we assume that fill_input_buffer will never return sal_False,
+ * so suspension need not be handled.
+ */
+ }
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+ }
+}
+
+extern "C" void term_source (j_decompress_ptr)
+{
+ /* no work necessary here */
+}
+
+extern "C" void jpeg_svstream_src (j_decompress_ptr cinfo, void * in)
+{
+ my_src_ptr src;
+ SvStream * infile = (SvStream*)in;
+
+ /* The source object and input buffer are made permanent so that a series
+ * of JPEG images can be read from the same file by calling jpeg_stdio_src
+ * only before the first one. (If we discarded the buffer at the end of
+ * one image, we'd likely lose the start of the next one.)
+ * This makes it unsafe to use this manager and a different source
+ * manager serially with the same JPEG object. Caveat programmer.
+ */
+ if (cinfo->src == NULL) { /* first time for this JPEG object? */
+ cinfo->src = (struct jpeg_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(my_source_mgr));
+ src = (my_src_ptr) cinfo->src;
+ src->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ BUF_SIZE * sizeof(JOCTET));
+ }
+
+ src = (my_src_ptr) cinfo->src;
+ src->pub.init_source = init_source;
+ src->pub.fill_input_buffer = fill_input_buffer;
+ src->pub.skip_input_data = skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
+ src->pub.term_source = term_source;
+ src->infile = infile;
+ src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+ src->pub.next_input_byte = NULL; /* until buffer loaded */
+}
+
+// --------------
+// - JPEGReader -
+// --------------
+
+JPEGReader::JPEGReader( SvStream& rStm, void* /*pCallData*/, sal_Bool bSetLS ) :
+ rIStm ( rStm ),
+ pAcc ( NULL ),
+ pAcc1 ( NULL ),
+ pBuffer ( NULL ),
+ nLastPos ( rStm.Tell() ),
+ nLastLines ( 0 ),
+ bSetLogSize ( bSetLS )
+{
+ maUpperName = String::CreateFromAscii( "SVIJPEG", 7 );
+ nFormerPos = nLastPos;
+}
+
+// ------------------------------------------------------------------------
+
+JPEGReader::~JPEGReader()
+{
+ if( pBuffer )
+ rtl_freeMemory( pBuffer );
+
+ if( pAcc )
+ aBmp.ReleaseAccess( pAcc );
+
+ if( pAcc1 )
+ aBmp1.ReleaseAccess( pAcc1 );
+}
+
+// ------------------------------------------------------------------------
+
+void* JPEGReader::CreateBitmap( void* pParam )
+{
+ Size aSize( ((JPEGCreateBitmapParam*)pParam)->nWidth,
+ ((JPEGCreateBitmapParam*)pParam)->nHeight );
+ sal_Bool bGray = ((JPEGCreateBitmapParam*)pParam)->bGray != 0;
+
+ void* pBmpBuf = NULL;
+
+ if( pAcc )
+ aBmp.ReleaseAccess( pAcc );
+
+ if( bGray )
+ {
+ BitmapPalette aGrayPal( 256 );
+
+ for( sal_uInt16 n = 0; n < 256; n++ )
+ {
+ const sal_uInt8 cGray = (sal_uInt8) n;
+ aGrayPal[ n ] = BitmapColor( cGray, cGray, cGray );
+ }
+
+ aBmp = Bitmap( aSize, 8, &aGrayPal );
+ }
+ else
+ aBmp = Bitmap( aSize, 24 );
+
+ if ( bSetLogSize )
+ {
+ unsigned long nUnit = ((JPEGCreateBitmapParam*)pParam)->density_unit;
+
+ if( ( ( 1 == nUnit ) || ( 2 == nUnit ) ) &&
+ ( (JPEGCreateBitmapParam*) pParam )->X_density &&
+ ( (JPEGCreateBitmapParam*) pParam )->Y_density )
+ {
+ Point aEmptyPoint;
+ Fraction aFractX( 1, ((JPEGCreateBitmapParam*)pParam)->X_density );
+ Fraction aFractY( 1, ((JPEGCreateBitmapParam*)pParam)->Y_density );
+ MapMode aMapMode( nUnit == 1 ? MAP_INCH : MAP_CM, aEmptyPoint, aFractX, aFractY );
+ Size aPrefSize = OutputDevice::LogicToLogic( aSize, aMapMode, MAP_100TH_MM );
+
+ aBmp.SetPrefSize( aPrefSize );
+ aBmp.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
+ }
+ }
+
+ pAcc = aBmp.AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ long nAlignedWidth;
+
+ const sal_uLong nFormat = pAcc->GetScanlineFormat();
+
+ if(
+ ( bGray && ( BMP_FORMAT_8BIT_PAL == nFormat ) ) ||
+ ( !bGray && ( BMP_FORMAT_24BIT_TC_RGB == nFormat ) )
+ )
+ {
+ pBmpBuf = pAcc->GetBuffer();
+ nAlignedWidth = pAcc->GetScanlineSize();
+ ((JPEGCreateBitmapParam*)pParam)->bTopDown = pAcc->IsTopDown();
+ }
+ else
+ {
+ nAlignedWidth = AlignedWidth4Bytes( aSize.Width() * ( bGray ? 8 : 24 ) );
+ ((JPEGCreateBitmapParam*)pParam)->bTopDown = sal_True;
+ pBmpBuf = pBuffer = rtl_allocateMemory( nAlignedWidth * aSize.Height() );
+ }
+ ((JPEGCreateBitmapParam*)pParam)->nAlignedWidth = nAlignedWidth;
+ }
+
+ return pBmpBuf;
+}
+
+// ------------------------------------------------------------------------
+
+void JPEGReader::FillBitmap()
+{
+ if( pBuffer && pAcc )
+ {
+ HPBYTE pTmp;
+ BitmapColor aColor;
+ long nAlignedWidth;
+ long nWidth = pAcc->Width();
+ long nHeight = pAcc->Height();
+
+ if( pAcc->GetBitCount() == 8 )
+ {
+ BitmapColor* pCols = new BitmapColor[ 256 ];
+
+ for( sal_uInt16 n = 0; n < 256; n++ )
+ {
+ const sal_uInt8 cGray = (sal_uInt8) n;
+ pCols[ n ] = pAcc->GetBestMatchingColor( BitmapColor( cGray, cGray, cGray ) );
+ }
+
+ nAlignedWidth = AlignedWidth4Bytes( pAcc->Width() * 8L );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ pTmp = (sal_uInt8*) pBuffer + nY * nAlignedWidth;
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pAcc->SetPixel( nY, nX, pCols[ *pTmp++ ] );
+ }
+
+ delete[] pCols;
+ }
+ else
+ {
+ nAlignedWidth = AlignedWidth4Bytes( pAcc->Width() * 24L );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ pTmp = (sal_uInt8*) pBuffer + nY * nAlignedWidth;
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aColor.SetRed( *pTmp++ );
+ aColor.SetGreen( *pTmp++ );
+ aColor.SetBlue( *pTmp++ );
+ pAcc->SetPixel( nY, nX, aColor );
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+Graphic JPEGReader::CreateIntermediateGraphic( const Bitmap& rBitmap, long nLines )
+{
+ Graphic aGraphic;
+ const Size aSizePix( rBitmap.GetSizePixel() );
+
+ if( !nLastLines )
+ {
+ if( pAcc1 )
+ aBmp1.ReleaseAccess( pAcc1 );
+
+ aBmp1 = Bitmap( rBitmap.GetSizePixel(), 1 );
+ aBmp1.Erase( Color( COL_WHITE ) );
+ pAcc1 = aBmp1.AcquireWriteAccess();
+ }
+
+ if( nLines && ( nLines < aSizePix.Height() ) )
+ {
+ if( pAcc1 )
+ {
+ const long nNewLines = nLines - nLastLines;
+
+ if( nNewLines )
+ {
+ pAcc1->SetFillColor( Color( COL_BLACK ) );
+ pAcc1->FillRect( Rectangle( Point( 0, nLastLines ),
+ Size( pAcc1->Width(), nNewLines ) ) );
+ }
+
+ aBmp1.ReleaseAccess( pAcc1 );
+ aGraphic = BitmapEx( rBitmap, aBmp1 );
+ pAcc1 = aBmp1.AcquireWriteAccess();
+ }
+ else
+ aGraphic = rBitmap;
+ }
+ else
+ aGraphic = rBitmap;
+
+ nLastLines = nLines;
+
+ return aGraphic;
+}
+
+// ------------------------------------------------------------------------
+
+ReadState JPEGReader::Read( Graphic& rGraphic )
+{
+ long nEndPos;
+ long nLines;
+ ReadState eReadState;
+ sal_Bool bRet = sal_False;
+ sal_uInt8 cDummy;
+
+#if 1 // TODO: is it possible to get rid of this seek to the end?
+ // check if the stream's end is already available
+ rIStm.Seek( STREAM_SEEK_TO_END );
+ rIStm >> cDummy;
+ nEndPos = rIStm.Tell();
+
+ // else check if at least JPEGMINREAD bytes can be read
+ if( rIStm.GetError() == ERRCODE_IO_PENDING )
+ {
+ rIStm.ResetError();
+ if( ( nEndPos - nFormerPos ) < JPEGMINREAD )
+ {
+ rIStm.Seek( nLastPos );
+ return JPEGREAD_NEED_MORE;
+ }
+ }
+
+ // seek back to the original position
+ rIStm.Seek( nLastPos );
+#endif
+
+ Size aPreviewSize = GetPreviewSize();
+ SetJpegPreviewSizeHint( aPreviewSize.Width(), aPreviewSize.Height() );
+
+ // read the (partial) image
+ ReadJPEG( this, &rIStm, &nLines );
+
+ if( pAcc )
+ {
+ if( pBuffer )
+ {
+ FillBitmap();
+ rtl_freeMemory( pBuffer );
+ pBuffer = NULL;
+ }
+
+ aBmp.ReleaseAccess( pAcc );
+ pAcc = NULL;
+
+ if( rIStm.GetError() == ERRCODE_IO_PENDING )
+ rGraphic = CreateIntermediateGraphic( aBmp, nLines );
+ else
+ rGraphic = aBmp;
+
+ bRet = sal_True;
+ }
+ else if( rIStm.GetError() == ERRCODE_IO_PENDING )
+ bRet = sal_True;
+
+ // Status setzen ( Pending hat immer Vorrang )
+ if( rIStm.GetError() == ERRCODE_IO_PENDING )
+ {
+ eReadState = JPEGREAD_NEED_MORE;
+ rIStm.ResetError();
+ nFormerPos = rIStm.Tell();
+ }
+ else
+ {
+ if( bRet )
+ eReadState = JPEGREAD_OK;
+ else
+ eReadState = JPEGREAD_ERROR;
+ }
+
+ return eReadState;
+}
+
+
+// --------------
+// - JPEGWriter -
+// --------------
+
+JPEGWriter::JPEGWriter( SvStream& rStm, const uno::Sequence< beans::PropertyValue >* pFilterData, bool* pExportWasGrey ) :
+ rOStm ( rStm ),
+ pAcc ( NULL ),
+ pBuffer ( NULL ),
+ pExpWasGrey ( pExportWasGrey )
+{
+ FilterConfigItem aConfigItem( (uno::Sequence< beans::PropertyValue >*)pFilterData );
+ bGreys = aConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "ColorMode" ) ), 0 ) != 0;
+ nQuality = aConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Quality" ) ), 75 );
+
+ if ( pFilterData )
+ {
+ int nArgs = pFilterData->getLength();
+ const beans::PropertyValue* pValues = pFilterData->getConstArray();
+ while( nArgs-- )
+ {
+ if( pValues->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StatusIndicator" ) ) )
+ {
+ pValues->Value >>= xStatusIndicator;
+ }
+ pValues++;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void* JPEGWriter::GetScanline( long nY )
+{
+ void* pScanline = NULL;
+
+ if( pAcc )
+ {
+ if( bNative )
+ pScanline = pAcc->GetScanline( nY );
+ else if( pBuffer )
+ {
+ BitmapColor aColor;
+ long nWidth = pAcc->Width();
+ sal_uInt8* pTmp = pBuffer;
+
+ if( pAcc->HasPalette() )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aColor = pAcc->GetPaletteColor( (sal_uInt8) pAcc->GetPixel( nY, nX ) );
+ *pTmp++ = aColor.GetRed();
+ if ( bGreys )
+ continue;
+ *pTmp++ = aColor.GetGreen();
+ *pTmp++ = aColor.GetBlue();
+ }
+ }
+ else
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aColor = pAcc->GetPixel( nY, nX );
+ *pTmp++ = aColor.GetRed();
+ if ( bGreys )
+ continue;
+ *pTmp++ = aColor.GetGreen();
+ *pTmp++ = aColor.GetBlue();
+ }
+ }
+
+ pScanline = pBuffer;
+ }
+ }
+
+ return pScanline;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool JPEGWriter::Write( const Graphic& rGraphic )
+{
+ sal_Bool bRet = sal_False;
+
+ if ( xStatusIndicator.is() )
+ {
+ rtl::OUString aMsg;
+ xStatusIndicator->start( aMsg, 100 );
+ }
+
+ Bitmap aGraphicBmp( rGraphic.GetBitmap() );
+
+ if ( bGreys )
+ {
+ if ( !aGraphicBmp.Convert( BMP_CONVERSION_8BIT_GREYS ) )
+ aGraphicBmp = rGraphic.GetBitmap();
+ }
+
+ pAcc = aGraphicBmp.AcquireReadAccess();
+
+ if ( !bGreys ) // bitmap was not explicitely converted into greyscale,
+ { // check if source is greyscale only
+
+ sal_Bool bIsGrey = sal_True;
+
+ long nWidth = pAcc->Width();
+ for ( long nY = 0; bIsGrey && ( nY < pAcc->Height() ); nY++ )
+ {
+ BitmapColor aColor;
+ for( long nX = 0L; bIsGrey && ( nX < nWidth ); nX++ )
+ {
+ aColor = pAcc->HasPalette() ? pAcc->GetPaletteColor( (sal_uInt8) pAcc->GetPixel( nY, nX ) )
+ : pAcc->GetPixel( nY, nX );
+ bIsGrey = ( aColor.GetRed() == aColor.GetGreen() ) && ( aColor.GetRed() == aColor.GetBlue() );
+ }
+ }
+ if ( bIsGrey )
+ bGreys = sal_True;
+ }
+
+ if( pExpWasGrey )
+ *pExpWasGrey = bGreys;
+
+ if( pAcc )
+ {
+ bNative = ( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB );
+
+ if( !bNative )
+ pBuffer = new sal_uInt8[ AlignedWidth4Bytes( bGreys ? pAcc->Width() * 8L : pAcc->Width() * 24L ) ];
+
+ JPEGCallbackStruct aCallbackData;
+ aCallbackData.xStatusIndicator = xStatusIndicator;
+ bRet = (sal_Bool) WriteJPEG( this, &rOStm, pAcc->Width(), pAcc->Height(), bGreys, nQuality, &aCallbackData );
+
+ delete[] pBuffer;
+ pBuffer = NULL;
+
+ aGraphicBmp.ReleaseAccess( pAcc );
+ pAcc = NULL;
+ }
+ if ( xStatusIndicator.is() )
+ xStatusIndicator->end();
+
+ return bRet;
+}
+
+// --------------
+// - ImportJPEG -
+// --------------
+
+sal_Bool ImportJPEG( SvStream& rStm, Graphic& rGraphic, void* pCallerData, sal_Int32 nImportFlags )
+{
+ JPEGReader* pJPEGReader = (JPEGReader*) rGraphic.GetContext();
+ ReadState eReadState;
+ sal_Bool bRet = sal_True;
+
+ if( !pJPEGReader )
+ pJPEGReader = new JPEGReader( rStm, pCallerData, ( nImportFlags & GRFILTER_I_FLAGS_SET_LOGSIZE_FOR_JPEG ) != 0 );
+
+ if( nImportFlags & GRFILTER_I_FLAGS_FOR_PREVIEW )
+ pJPEGReader->SetPreviewSize( Size(128,128) );
+ else
+ pJPEGReader->DisablePreviewMode();
+
+ rGraphic.SetContext( NULL );
+ eReadState = pJPEGReader->Read( rGraphic );
+
+ if( eReadState == JPEGREAD_ERROR )
+ {
+ bRet = sal_False;
+ delete pJPEGReader;
+ }
+ else if( eReadState == JPEGREAD_OK )
+ delete pJPEGReader;
+ else
+ rGraphic.SetContext( pJPEGReader );
+
+ return bRet;
+}
+
+// --------------
+// - ExportJPEG -
+// --------------
+
+sal_Bool ExportJPEG( SvStream& rOStm, const Graphic& rGraphic,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData,
+ bool* pExportWasGrey
+ )
+{
+ JPEGWriter aJPEGWriter( rOStm, pFilterData, pExportWasGrey );
+ return aJPEGWriter.Write( rGraphic );
+}
diff --git a/svtools/source/filter.vcl/jpeg/jpegc.c b/svtools/source/filter.vcl/jpeg/jpegc.c
new file mode 100644
index 000000000000..b51d37a4a163
--- /dev/null
+++ b/svtools/source/filter.vcl/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 "jpeg/jpeglib.h"
+#include "jpeg/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;
+}