LCOV - code coverage report
Current view: top level - libreoffice/svtools/source/filter/jpeg - jpeg.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 147 334 44.0 %
Date: 2012-12-27 Functions: 14 27 51.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <tools/solar.h>
      22             : 
      23             : extern "C"
      24             : {
      25             :     #include "stdio.h"
      26             :     #include "jpeg.h"
      27             :     #include "jpeglib.h"
      28             :     #include "jerror.h"
      29             : }
      30             : 
      31             : #define _JPEGPRIVATE
      32             : #include <vcl/bmpacc.hxx>
      33             : #include "jpeg.hxx"
      34             : #include <svtools/FilterConfigItem.hxx>
      35             : #include <svtools/filter.hxx>
      36             : 
      37             : // -----------
      38             : // - Defines -
      39             : // -----------
      40             : 
      41             : using namespace ::com::sun::star;
      42             : 
      43             : #define JPEGMINREAD 512
      44             : 
      45             : // -------------
      46             : // - (C-Calls) -
      47             : // -------------
      48             : 
      49             : // ------------------------------------------------------------------------
      50             : 
      51           5 : extern "C" void* CreateBitmap( void* pJPEGReader, void* pJPEGCreateBitmapParam )
      52             : {
      53           5 :     return ( (JPEGReader*) pJPEGReader )->CreateBitmap( pJPEGCreateBitmapParam );
      54             : }
      55             : 
      56             : // ------------------------------------------------------------------------
      57             : 
      58           0 : extern "C" void* GetScanline( void* pJPEGWriter, long nY )
      59             : {
      60           0 :     return ( (JPEGWriter*) pJPEGWriter )->GetScanline( nY );
      61             : }
      62             : 
      63             : // ------------------------------------------------------------------------
      64             : 
      65           0 : struct JPEGCallbackStruct
      66             : {
      67             :     uno::Reference< task::XStatusIndicator > xStatusIndicator;
      68             : };
      69             : 
      70           0 : extern "C" long JPEGCallback( void* pCallbackData, long nPercent )
      71             : {
      72           0 :     JPEGCallbackStruct* pS = (JPEGCallbackStruct*)pCallbackData;
      73           0 :     if ( pS && pS->xStatusIndicator.is() )
      74             :     {
      75           0 :         pS->xStatusIndicator->setValue( nPercent );
      76             :     }
      77           0 :     return 0L;
      78             : }
      79             : 
      80             : #define BUF_SIZE  4096
      81             : 
      82             : typedef struct
      83             : {
      84             :   struct jpeg_destination_mgr pub;  /* public fields */
      85             : 
      86             :   SvStream* outfile;                /* target stream */
      87             :   JOCTET * buffer;                  /* start of buffer */
      88             : } my_destination_mgr;
      89             : 
      90             : typedef my_destination_mgr * my_dest_ptr;
      91             : 
      92           0 : extern "C" void init_destination (j_compress_ptr cinfo)
      93             : {
      94           0 :   my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
      95             : 
      96             :   /* Allocate the output buffer --- it will be released when done with image */
      97             :   dest->buffer = (JOCTET *)
      98             :       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
      99           0 :                                   BUF_SIZE * sizeof(JOCTET));
     100             : 
     101           0 :   dest->pub.next_output_byte = dest->buffer;
     102           0 :   dest->pub.free_in_buffer = BUF_SIZE;
     103           0 : }
     104             : 
     105           0 : extern "C" boolean empty_output_buffer (j_compress_ptr cinfo)
     106             : {
     107           0 :   my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
     108             : 
     109           0 :   if (dest->outfile->Write(dest->buffer, BUF_SIZE) !=
     110             :       (size_t) BUF_SIZE)
     111           0 :     ERREXIT(cinfo, JERR_FILE_WRITE);
     112             : 
     113           0 :   dest->pub.next_output_byte = dest->buffer;
     114           0 :   dest->pub.free_in_buffer = BUF_SIZE;
     115             : 
     116           0 :   return sal_True;
     117             : }
     118             : 
     119           0 : extern "C" void term_destination (j_compress_ptr cinfo)
     120             : {
     121           0 :   my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
     122           0 :   size_t datacount = BUF_SIZE - dest->pub.free_in_buffer;
     123             : 
     124             :   /* Write any data remaining in the buffer */
     125           0 :   if (datacount > 0) {
     126           0 :     if (dest->outfile->Write(dest->buffer, datacount) != datacount)
     127           0 :       ERREXIT(cinfo, JERR_FILE_WRITE);
     128             :   }
     129           0 : }
     130             : 
     131           0 : extern "C" void jpeg_svstream_dest (j_compress_ptr cinfo, void* out)
     132             : {
     133           0 :   SvStream * outfile = (SvStream*)out;
     134             :   my_dest_ptr dest;
     135             : 
     136             :   /* The destination object is made permanent so that multiple JPEG images
     137             :    * can be written to the same file without re-executing jpeg_svstream_dest.
     138             :    * This makes it dangerous to use this manager and a different destination
     139             :    * manager serially with the same JPEG object, because their private object
     140             :    * sizes may be different.  Caveat programmer.
     141             :    */
     142           0 :   if (cinfo->dest == NULL) {    /* first time for this JPEG object? */
     143             :     cinfo->dest = (struct jpeg_destination_mgr *)
     144             :       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
     145           0 :                                   sizeof(my_destination_mgr));
     146             :   }
     147             : 
     148           0 :   dest = (my_dest_ptr) cinfo->dest;
     149           0 :   dest->pub.init_destination = init_destination;
     150           0 :   dest->pub.empty_output_buffer = empty_output_buffer;
     151           0 :   dest->pub.term_destination = term_destination;
     152           0 :   dest->outfile = outfile;
     153           0 : }
     154             : 
     155             : /* Expanded data source object for stdio input */
     156             : 
     157             : typedef struct {
     158             :   struct jpeg_source_mgr pub;   /* public fields */
     159             : 
     160             :   SvStream * infile;            /* source stream */
     161             :   JOCTET * buffer;              /* start of buffer */
     162             :   boolean start_of_file;        /* have we gotten any data yet? */
     163             : } my_source_mgr;
     164             : 
     165             : typedef my_source_mgr * my_src_ptr;
     166             : 
     167             : /*
     168             :  * Initialize source --- called by jpeg_read_header
     169             :  * before any data is actually read.
     170             :  */
     171             : 
     172           8 : extern "C" void init_source (j_decompress_ptr cinfo)
     173             : {
     174           8 :   my_src_ptr src = (my_src_ptr) cinfo->src;
     175             : 
     176             :   /* We reset the empty-input-file flag for each image,
     177             :    * but we don't clear the input buffer.
     178             :    * This is correct behavior for reading a series of images from one source.
     179             :    */
     180           8 :   src->start_of_file = sal_True;
     181           8 : }
     182             : 
     183          10 : long StreamRead( SvStream* pSvStm, void* pBuffer, long nBufferSize )
     184             : {
     185          10 :         long            nRead = 0;
     186             : 
     187          10 :         if( pSvStm->GetError() != ERRCODE_IO_PENDING )
     188             :         {
     189          10 :                 long nActPos = pSvStm->Tell();
     190             : 
     191          10 :                 nRead = (long) pSvStm->Read( pBuffer, nBufferSize );
     192             : 
     193          10 :                 if( pSvStm->GetError() == ERRCODE_IO_PENDING )
     194             :                 {
     195             :                         // Damit wir wieder an die alte Position
     196             :                         // seeken koennen, setzen wir den Error temp.zurueck
     197           0 :                         pSvStm->ResetError();
     198           0 :                         pSvStm->Seek( nActPos );
     199           0 :                         pSvStm->SetError( ERRCODE_IO_PENDING );
     200             :                 }
     201             :         }
     202             : 
     203          10 :         return nRead;
     204             : }
     205             : 
     206          10 : extern "C" boolean fill_input_buffer (j_decompress_ptr cinfo)
     207             : {
     208          10 :   my_src_ptr src = (my_src_ptr) cinfo->src;
     209             :   size_t nbytes;
     210             : 
     211          10 :   nbytes = StreamRead(src->infile, src->buffer, BUF_SIZE);
     212             : 
     213          10 :   if (!nbytes) {
     214           0 :     if (src->start_of_file)     /* Treat empty input file as fatal error */
     215           0 :       ERREXIT(cinfo, JERR_INPUT_EMPTY);
     216           0 :     WARNMS(cinfo, JWRN_JPEG_EOF);
     217             :     /* Insert a fake EOI marker */
     218           0 :     src->buffer[0] = (JOCTET) 0xFF;
     219           0 :     src->buffer[1] = (JOCTET) JPEG_EOI;
     220           0 :     nbytes = 2;
     221             :   }
     222             : 
     223          10 :   src->pub.next_input_byte = src->buffer;
     224          10 :   src->pub.bytes_in_buffer = nbytes;
     225          10 :   src->start_of_file = sal_False;
     226             : 
     227          10 :   return sal_True;
     228             : }
     229             : 
     230           5 : extern "C" void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
     231             : {
     232           5 :   my_src_ptr src = (my_src_ptr) cinfo->src;
     233             : 
     234             :   /* Just a dumb implementation for now.  Could use fseek() except
     235             :    * it doesn't work on pipes.  Not clear that being smart is worth
     236             :    * any trouble anyway --- large skips are infrequent.
     237             :    */
     238           5 :   if (num_bytes > 0) {
     239          12 :     while (num_bytes > (long) src->pub.bytes_in_buffer) {
     240           2 :       num_bytes -= (long) src->pub.bytes_in_buffer;
     241           2 :       (void) fill_input_buffer(cinfo);
     242             :       /* note we assume that fill_input_buffer will never return sal_False,
     243             :        * so suspension need not be handled.
     244             :        */
     245             :     }
     246           5 :     src->pub.next_input_byte += (size_t) num_bytes;
     247           5 :     src->pub.bytes_in_buffer -= (size_t) num_bytes;
     248             :   }
     249           5 : }
     250             : 
     251           4 : extern "C" void term_source (j_decompress_ptr)
     252             : {
     253             :   /* no work necessary here */
     254           4 : }
     255             : 
     256           8 : extern "C" void jpeg_svstream_src (j_decompress_ptr cinfo, void * in)
     257             : {
     258             :   my_src_ptr src;
     259           8 :   SvStream * infile = (SvStream*)in;
     260             : 
     261             :   /* The source object and input buffer are made permanent so that a series
     262             :    * of JPEG images can be read from the same file by calling jpeg_stdio_src
     263             :    * only before the first one.  (If we discarded the buffer at the end of
     264             :    * one image, we'd likely lose the start of the next one.)
     265             :    * This makes it unsafe to use this manager and a different source
     266             :    * manager serially with the same JPEG object.  Caveat programmer.
     267             :    */
     268           8 :   if (cinfo->src == NULL) {     /* first time for this JPEG object? */
     269             :     cinfo->src = (struct jpeg_source_mgr *)
     270             :       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
     271           8 :                                   sizeof(my_source_mgr));
     272           8 :     src = (my_src_ptr) cinfo->src;
     273             :     src->buffer = (JOCTET *)
     274             :       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
     275           8 :                                   BUF_SIZE * sizeof(JOCTET));
     276             :   }
     277             : 
     278           8 :   src = (my_src_ptr) cinfo->src;
     279           8 :   src->pub.init_source = init_source;
     280           8 :   src->pub.fill_input_buffer = fill_input_buffer;
     281           8 :   src->pub.skip_input_data = skip_input_data;
     282           8 :   src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
     283           8 :   src->pub.term_source = term_source;
     284           8 :   src->infile = infile;
     285           8 :   src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
     286           8 :   src->pub.next_input_byte = NULL; /* until buffer loaded */
     287           8 : }
     288             : 
     289             : // --------------
     290             : // - JPEGReader -
     291             : // --------------
     292             : 
     293           8 : JPEGReader::JPEGReader( SvStream& rStm, void* /*pCallData*/, sal_Bool bSetLS ) :
     294             :         rIStm           ( rStm ),
     295             :         pAcc            ( NULL ),
     296             :         pAcc1           ( NULL ),
     297             :         pBuffer         ( NULL ),
     298           8 :         nLastPos        ( rStm.Tell() ),
     299             :         nLastLines      ( 0 ),
     300          16 :         bSetLogSize     ( bSetLS )
     301             : {
     302           8 :     maUpperName = rtl::OUString("SVIJPEG");
     303           8 :     nFormerPos = nLastPos;
     304           8 : }
     305             : 
     306             : // ------------------------------------------------------------------------
     307             : 
     308          24 : JPEGReader::~JPEGReader()
     309             : {
     310           8 :     if( pBuffer )
     311           0 :         rtl_freeMemory( pBuffer );
     312             : 
     313           8 :     if( pAcc )
     314           0 :         aBmp.ReleaseAccess( pAcc );
     315             : 
     316           8 :     if( pAcc1 )
     317           0 :         aBmp1.ReleaseAccess( pAcc1 );
     318          16 : }
     319             : 
     320             : // ------------------------------------------------------------------------
     321             : 
     322           5 : void* JPEGReader::CreateBitmap( void* _pParam )
     323             : {
     324           5 :     JPEGCreateBitmapParam *pParam = (JPEGCreateBitmapParam *) _pParam;
     325             : 
     326           5 :     if (pParam->nWidth > SAL_MAX_INT32/8 || pParam->nHeight > SAL_MAX_INT32/8)
     327           0 :         return NULL; // avoid overflows later
     328             : 
     329           5 :     Size        aSize( pParam->nWidth, pParam->nHeight );
     330           5 :     sal_Bool    bGray = pParam->bGray != 0;
     331             : 
     332           5 :     void* pBmpBuf = NULL;
     333             : 
     334           5 :     if( pAcc )
     335           0 :         aBmp.ReleaseAccess( pAcc );
     336             : 
     337           5 :     sal_uInt64 nSize = aSize.Width();
     338           5 :     nSize *= aSize.Height();
     339           5 :     if (nSize > SAL_MAX_INT32 / 24)
     340           0 :         return NULL;
     341             : 
     342           5 :     if( bGray )
     343             :     {
     344           0 :         BitmapPalette aGrayPal( 256 );
     345             : 
     346           0 :         for( sal_uInt16 n = 0; n < 256; n++ )
     347             :         {
     348           0 :             const sal_uInt8 cGray = (sal_uInt8) n;
     349           0 :             aGrayPal[ n ] = BitmapColor( cGray, cGray, cGray );
     350             :         }
     351             : 
     352           0 :         aBmp = Bitmap( aSize, 8, &aGrayPal );
     353             :     }
     354             :     else
     355           5 :         aBmp = Bitmap( aSize, 24 );
     356             : 
     357           5 :     if ( bSetLogSize )
     358             :     {
     359           5 :         unsigned long nUnit = ((JPEGCreateBitmapParam*)pParam)->density_unit;
     360             : 
     361           5 :         if( ( ( 1 == nUnit ) || ( 2 == nUnit ) ) &&
     362             :             pParam->X_density && pParam->Y_density )
     363             :         {
     364           3 :             Point       aEmptyPoint;
     365           3 :             Fraction    aFractX( 1, pParam->X_density );
     366           3 :             Fraction    aFractY( 1, pParam->Y_density );
     367           3 :             MapMode     aMapMode( nUnit == 1 ? MAP_INCH : MAP_CM, aEmptyPoint, aFractX, aFractY );
     368           3 :             Size        aPrefSize = OutputDevice::LogicToLogic( aSize, aMapMode, MAP_100TH_MM );
     369             : 
     370           3 :             aBmp.SetPrefSize( aPrefSize );
     371           3 :             aBmp.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
     372             :         }
     373             :     }
     374             : 
     375           5 :     pAcc = aBmp.AcquireWriteAccess();
     376             : 
     377           5 :     if( pAcc )
     378             :     {
     379           5 :         const sal_uLong nFormat = pAcc->GetScanlineFormat();
     380             : 
     381           5 :         if(
     382             :             ( bGray && ( BMP_FORMAT_8BIT_PAL == nFormat ) ) ||
     383             :             ( !bGray && ( BMP_FORMAT_24BIT_TC_RGB == nFormat ) )
     384             :           )
     385             :         {
     386           0 :             pBmpBuf = pAcc->GetBuffer();
     387           0 :             pParam->nAlignedWidth = pAcc->GetScanlineSize();
     388           0 :             pParam->bTopDown = pAcc->IsTopDown();
     389             :         }
     390             :         else
     391             :         {
     392           5 :             pParam->nAlignedWidth = AlignedWidth4Bytes( aSize.Width() * ( bGray ? 8 : 24 ) );
     393           5 :             pParam->bTopDown = sal_True;
     394           5 :             pBmpBuf = pBuffer = rtl_allocateMemory( pParam->nAlignedWidth * aSize.Height() );
     395             :         }
     396             :     }
     397             : 
     398             :     // clean up, if no Bitmap buffer can be provided.
     399           5 :     if ( !pBmpBuf )
     400             :     {
     401           0 :         aBmp.ReleaseAccess( pAcc );
     402           0 :         pAcc = NULL;
     403             :     }
     404             : 
     405           5 :     return pBmpBuf;
     406             : }
     407             : 
     408             : // ------------------------------------------------------------------------
     409             : 
     410           5 : void JPEGReader::FillBitmap()
     411             : {
     412           5 :     if( pBuffer && pAcc )
     413             :     {
     414             :         HPBYTE      pTmp;
     415           5 :         BitmapColor aColor;
     416             :         long        nAlignedWidth;
     417           5 :         long        nWidth = pAcc->Width();
     418           5 :         long        nHeight = pAcc->Height();
     419             : 
     420           5 :         if( pAcc->GetBitCount() == 8 )
     421             :         {
     422           0 :             BitmapColor* pCols = new BitmapColor[ 256 ];
     423             : 
     424           0 :             for( sal_uInt16 n = 0; n < 256; n++ )
     425             :             {
     426           0 :                 const sal_uInt8 cGray = (sal_uInt8) n;
     427           0 :                 pCols[ n ] = pAcc->GetBestMatchingColor( BitmapColor( cGray, cGray, cGray ) );
     428             :             }
     429             : 
     430           0 :             nAlignedWidth = AlignedWidth4Bytes( pAcc->Width() * 8L );
     431             : 
     432           0 :             for( long nY = 0L; nY < nHeight; nY++ )
     433             :             {
     434           0 :                 pTmp = (sal_uInt8*) pBuffer + nY * nAlignedWidth;
     435             : 
     436           0 :                 for( long nX = 0L; nX < nWidth; nX++ )
     437           0 :                     pAcc->SetPixel( nY, nX, pCols[ *pTmp++ ] );
     438             :             }
     439             : 
     440           0 :             delete[] pCols;
     441             :         }
     442             :         else
     443             :         {
     444           5 :             nAlignedWidth = AlignedWidth4Bytes( pAcc->Width() * 24L );
     445             : 
     446         233 :             for( long nY = 0L; nY < nHeight; nY++ )
     447             :             {
     448         228 :                 pTmp = (sal_uInt8*) pBuffer + nY * nAlignedWidth;
     449             : 
     450       25786 :                 for( long nX = 0L; nX < nWidth; nX++ )
     451             :                 {
     452       25558 :                     aColor.SetRed( *pTmp++ );
     453       25558 :                     aColor.SetGreen( *pTmp++ );
     454       25558 :                     aColor.SetBlue( *pTmp++ );
     455       25558 :                     pAcc->SetPixel( nY, nX, aColor );
     456             :                 }
     457             :             }
     458           5 :         }
     459             :     }
     460           5 : }
     461             : 
     462             : // ------------------------------------------------------------------------
     463             : 
     464           0 : Graphic JPEGReader::CreateIntermediateGraphic( const Bitmap& rBitmap, long nLines )
     465             : {
     466           0 :     Graphic     aGraphic;
     467           0 :     const Size  aSizePix( rBitmap.GetSizePixel() );
     468             : 
     469           0 :     if( !nLastLines )
     470             :     {
     471           0 :         if( pAcc1 )
     472           0 :             aBmp1.ReleaseAccess( pAcc1 );
     473             : 
     474           0 :         aBmp1 = Bitmap( rBitmap.GetSizePixel(), 1 );
     475           0 :         aBmp1.Erase( Color( COL_WHITE ) );
     476           0 :         pAcc1 = aBmp1.AcquireWriteAccess();
     477             :     }
     478             : 
     479           0 :     if( nLines && ( nLines < aSizePix.Height() ) )
     480             :     {
     481           0 :         if( pAcc1 )
     482             :         {
     483           0 :             const long nNewLines = nLines - nLastLines;
     484             : 
     485           0 :             if( nNewLines )
     486             :             {
     487           0 :                 pAcc1->SetFillColor( Color( COL_BLACK ) );
     488             :                 pAcc1->FillRect( Rectangle( Point( 0, nLastLines ),
     489           0 :                                             Size( pAcc1->Width(), nNewLines ) ) );
     490             :             }
     491             : 
     492           0 :             aBmp1.ReleaseAccess( pAcc1 );
     493           0 :             aGraphic = BitmapEx( rBitmap, aBmp1 );
     494           0 :             pAcc1 = aBmp1.AcquireWriteAccess();
     495             :         }
     496             :         else
     497           0 :             aGraphic = rBitmap;
     498             :     }
     499             :     else
     500           0 :         aGraphic = rBitmap;
     501             : 
     502           0 :     nLastLines = nLines;
     503             : 
     504           0 :     return aGraphic;
     505             : }
     506             : 
     507             : // ------------------------------------------------------------------------
     508             : 
     509           8 : ReadState JPEGReader::Read( Graphic& rGraphic )
     510             : {
     511             :     long        nEndPos;
     512             :     long        nLines;
     513             :     ReadState   eReadState;
     514           8 :     sal_Bool        bRet = sal_False;
     515             :     sal_uInt8       cDummy;
     516             : 
     517             : #if 1 // TODO: is it possible to get rid of this seek to the end?
     518             :     // check if the stream's end is already available
     519           8 :     rIStm.Seek( STREAM_SEEK_TO_END );
     520           8 :     rIStm >> cDummy;
     521           8 :     nEndPos = rIStm.Tell();
     522             : 
     523             :     // else check if at least JPEGMINREAD bytes can be read
     524           8 :     if( rIStm.GetError() == ERRCODE_IO_PENDING )
     525             :     {
     526           0 :         rIStm.ResetError();
     527           0 :         if( ( nEndPos  - nFormerPos ) < JPEGMINREAD )
     528             :         {
     529           0 :             rIStm.Seek( nLastPos );
     530           0 :             return JPEGREAD_NEED_MORE;
     531             :         }
     532             :     }
     533             : 
     534             :     // seek back to the original position
     535           8 :     rIStm.Seek( nLastPos );
     536             : #endif
     537             : 
     538           8 :     Size aPreviewSize = GetPreviewSize();
     539           8 :     SetJpegPreviewSizeHint( aPreviewSize.Width(), aPreviewSize.Height() );
     540             : 
     541             :     // read the (partial) image
     542           8 :     ReadJPEG( this, &rIStm, &nLines );
     543             : 
     544           8 :     if( pAcc )
     545             :     {
     546           5 :         if( pBuffer )
     547             :         {
     548           5 :             FillBitmap();
     549           5 :             rtl_freeMemory( pBuffer );
     550           5 :             pBuffer = NULL;
     551             :         }
     552             : 
     553           5 :         aBmp.ReleaseAccess( pAcc );
     554           5 :         pAcc = NULL;
     555             : 
     556           5 :         if( rIStm.GetError() == ERRCODE_IO_PENDING )
     557           0 :             rGraphic = CreateIntermediateGraphic( aBmp, nLines );
     558             :         else
     559           5 :             rGraphic = aBmp;
     560             : 
     561           5 :         bRet = sal_True;
     562             :     }
     563           3 :     else if( rIStm.GetError() == ERRCODE_IO_PENDING )
     564           0 :         bRet = sal_True;
     565             : 
     566             :     // Status setzen ( Pending hat immer Vorrang )
     567           8 :     if( rIStm.GetError() == ERRCODE_IO_PENDING )
     568             :     {
     569           0 :         eReadState = JPEGREAD_NEED_MORE;
     570           0 :         rIStm.ResetError();
     571           0 :         nFormerPos = rIStm.Tell();
     572             :     }
     573             :     else
     574             :     {
     575           8 :         if( bRet )
     576           5 :             eReadState = JPEGREAD_OK;
     577             :         else
     578           3 :             eReadState = JPEGREAD_ERROR;
     579             :     }
     580             : 
     581           8 :     return eReadState;
     582             : }
     583             : 
     584             : 
     585             : // --------------
     586             : // - JPEGWriter -
     587             : // --------------
     588             : 
     589           0 : JPEGWriter::JPEGWriter( SvStream& rStm, const uno::Sequence< beans::PropertyValue >* pFilterData, bool* pExportWasGrey ) :
     590             :         rOStm       ( rStm ),
     591             :         pAcc        ( NULL ),
     592             :         pBuffer     ( NULL ),
     593           0 :         pExpWasGrey ( pExportWasGrey )
     594             : {
     595           0 :     FilterConfigItem aConfigItem( (uno::Sequence< beans::PropertyValue >*)pFilterData );
     596           0 :     bGreys = aConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "ColorMode" ) ), 0 ) != 0;
     597           0 :     nQuality = aConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Quality" ) ), 75 );
     598             : 
     599           0 :     if ( pFilterData )
     600             :     {
     601           0 :         int nArgs = pFilterData->getLength();
     602           0 :         const beans::PropertyValue* pValues = pFilterData->getConstArray();
     603           0 :         while( nArgs-- )
     604             :         {
     605           0 :             if ( pValues->Name == "StatusIndicator" )
     606             :             {
     607           0 :                 pValues->Value >>= xStatusIndicator;
     608             :             }
     609           0 :             pValues++;
     610             :         }
     611           0 :     }
     612           0 : }
     613             : 
     614             : // ------------------------------------------------------------------------
     615             : 
     616           0 : void* JPEGWriter::GetScanline( long nY )
     617             : {
     618           0 :     void* pScanline = NULL;
     619             : 
     620           0 :     if( pAcc )
     621             :     {
     622           0 :         if( bNative )
     623           0 :             pScanline = pAcc->GetScanline( nY );
     624           0 :         else if( pBuffer )
     625             :         {
     626           0 :             BitmapColor aColor;
     627           0 :             long        nWidth = pAcc->Width();
     628           0 :             sal_uInt8*      pTmp = pBuffer;
     629             : 
     630           0 :             if( pAcc->HasPalette() )
     631             :             {
     632           0 :                 for( long nX = 0L; nX < nWidth; nX++ )
     633             :                 {
     634           0 :                     aColor = pAcc->GetPaletteColor( (sal_uInt8) pAcc->GetPixel( nY, nX ) );
     635           0 :                     *pTmp++ = aColor.GetRed();
     636           0 :                     if ( bGreys )
     637           0 :                         continue;
     638           0 :                     *pTmp++ = aColor.GetGreen();
     639           0 :                     *pTmp++ = aColor.GetBlue();
     640             :                 }
     641             :             }
     642             :             else
     643             :             {
     644           0 :                 for( long nX = 0L; nX < nWidth; nX++ )
     645             :                 {
     646           0 :                     aColor = pAcc->GetPixel( nY, nX );
     647           0 :                     *pTmp++ = aColor.GetRed();
     648           0 :                     if ( bGreys )
     649           0 :                         continue;
     650           0 :                     *pTmp++ = aColor.GetGreen();
     651           0 :                     *pTmp++ = aColor.GetBlue();
     652             :                 }
     653             :             }
     654             : 
     655           0 :             pScanline = pBuffer;
     656             :         }
     657             :     }
     658             : 
     659           0 :     return pScanline;
     660             : }
     661             : 
     662             : // ------------------------------------------------------------------------
     663             : 
     664           0 : sal_Bool JPEGWriter::Write( const Graphic& rGraphic )
     665             : {
     666           0 :     sal_Bool bRet = sal_False;
     667             : 
     668           0 :     if ( xStatusIndicator.is() )
     669             :     {
     670           0 :         rtl::OUString aMsg;
     671           0 :         xStatusIndicator->start( aMsg, 100 );
     672             :     }
     673             : 
     674           0 :     Bitmap aGraphicBmp( rGraphic.GetBitmap() );
     675             : 
     676           0 :     if ( bGreys )
     677             :     {
     678           0 :         if ( !aGraphicBmp.Convert( BMP_CONVERSION_8BIT_GREYS ) )
     679           0 :             aGraphicBmp = rGraphic.GetBitmap();
     680             :     }
     681             : 
     682           0 :     pAcc = aGraphicBmp.AcquireReadAccess();
     683             : 
     684           0 :     if ( !bGreys )  // bitmap was not explicitly converted into greyscale,
     685             :     {               // check if source is greyscale only
     686             : 
     687           0 :         sal_Bool bIsGrey = sal_True;
     688             : 
     689           0 :         long nWidth = pAcc->Width();
     690           0 :         for ( long nY = 0; bIsGrey && ( nY < pAcc->Height() ); nY++ )
     691             :         {
     692           0 :             BitmapColor aColor;
     693           0 :             for( long nX = 0L; bIsGrey && ( nX < nWidth ); nX++ )
     694             :             {
     695           0 :                 aColor = pAcc->HasPalette() ? pAcc->GetPaletteColor( (sal_uInt8) pAcc->GetPixel( nY, nX ) )
     696           0 :                                             : pAcc->GetPixel( nY, nX );
     697           0 :                 bIsGrey = ( aColor.GetRed() == aColor.GetGreen() ) && ( aColor.GetRed() == aColor.GetBlue() );
     698             :             }
     699           0 :         }
     700           0 :         if ( bIsGrey )
     701           0 :             bGreys = sal_True;
     702             :     }
     703             : 
     704           0 :     if( pExpWasGrey )
     705           0 :         *pExpWasGrey = bGreys;
     706             : 
     707           0 :     if( pAcc )
     708             :     {
     709           0 :         bNative = ( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB );
     710             : 
     711           0 :         if( !bNative )
     712           0 :             pBuffer = new sal_uInt8[ AlignedWidth4Bytes( bGreys ? pAcc->Width() * 8L : pAcc->Width() * 24L ) ];
     713             : 
     714           0 :         JPEGCallbackStruct aCallbackData;
     715           0 :         aCallbackData.xStatusIndicator = xStatusIndicator;
     716           0 :         bRet = (sal_Bool) WriteJPEG( this, &rOStm, pAcc->Width(), pAcc->Height(), bGreys, nQuality, &aCallbackData );
     717             : 
     718           0 :         delete[] pBuffer;
     719           0 :         pBuffer = NULL;
     720             : 
     721           0 :         aGraphicBmp.ReleaseAccess( pAcc );
     722           0 :         pAcc = NULL;
     723             :     }
     724           0 :     if ( xStatusIndicator.is() )
     725           0 :         xStatusIndicator->end();
     726             : 
     727           0 :     return bRet;
     728             : }
     729             : 
     730             : // --------------
     731             : // - ImportJPEG -
     732             : // --------------
     733             : 
     734           8 : sal_Bool ImportJPEG( SvStream& rStm, Graphic& rGraphic, void* pCallerData, sal_Int32 nImportFlags )
     735             : {
     736           8 :     JPEGReader* pJPEGReader = (JPEGReader*) rGraphic.GetContext();
     737             :     ReadState   eReadState;
     738           8 :     sal_Bool        bRet = sal_True;
     739             : 
     740           8 :     if( !pJPEGReader )
     741           8 :         pJPEGReader = new JPEGReader( rStm, pCallerData, ( nImportFlags & GRFILTER_I_FLAGS_SET_LOGSIZE_FOR_JPEG ) != 0 );
     742             : 
     743           8 :     if( nImportFlags & GRFILTER_I_FLAGS_FOR_PREVIEW )
     744           0 :         pJPEGReader->SetPreviewSize( Size(128,128) );
     745             :     else
     746           8 :         pJPEGReader->DisablePreviewMode();
     747             : 
     748           8 :     rGraphic.SetContext( NULL );
     749           8 :     eReadState = pJPEGReader->Read( rGraphic );
     750             : 
     751           8 :     if( eReadState == JPEGREAD_ERROR )
     752             :     {
     753           3 :         bRet = sal_False;
     754           3 :         delete pJPEGReader;
     755             :     }
     756           5 :     else if( eReadState == JPEGREAD_OK )
     757           5 :         delete pJPEGReader;
     758             :     else
     759           0 :         rGraphic.SetContext( pJPEGReader );
     760             : 
     761           8 :     return bRet;
     762             : }
     763             : 
     764             : //  --------------
     765             : //  - ExportJPEG -
     766             : //  --------------
     767             : 
     768           0 : sal_Bool ExportJPEG( SvStream& rOStm, const Graphic& rGraphic,
     769             :                  const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData,
     770             :                  bool* pExportWasGrey
     771             :                 )
     772             : {
     773           0 :     JPEGWriter aJPEGWriter( rOStm, pFilterData, pExportWasGrey );
     774           0 :     return aJPEGWriter.Write( rGraphic );
     775             : }
     776             : 
     777             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10