masterfix DEV300: #i10000# removeing moved code

This commit is contained in:
Ivo Hinkelmann 2011-03-30 15:41:12 +02:00
parent 4296c7c855
commit 87987da3c2
2 changed files with 0 additions and 1061 deletions

View file

@ -1,777 +0,0 @@
/*************************************************************************
*
* 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 );
}

View file

@ -1,284 +0,0 @@
/*************************************************************************
*
* 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;
}