LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/vcl/source/filter/jpeg - JpegWriter.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 92 116 79.3 %
Date: 2013-07-09 Functions: 12 13 92.3 %
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             : extern "C"
      21             : {
      22             :     #include "stdio.h"
      23             :     #include "jpeg.h"
      24             :     #include <jpeglib.h>
      25             :     #include <jerror.h>
      26             : }
      27             : 
      28             : #include <tools/solar.h>
      29             : #include <vcl/bmpacc.hxx>
      30             : #include <vcl/FilterConfigItem.hxx>
      31             : #include <vcl/graphicfilter.hxx>
      32             : #include "JpegWriter.hxx"
      33             : 
      34             : #define BUFFER_SIZE  4096
      35             : 
      36         100 : extern "C" void* GetScanline( void* pJPEGWriter, long nY )
      37             : {
      38         100 :     return ( (JPEGWriter*) pJPEGWriter )->GetScanline( nY );
      39             : }
      40             : 
      41           2 : struct JPEGCallbackStruct
      42             : {
      43             :     css::uno::Reference< css::task::XStatusIndicator > xStatusIndicator;
      44             : };
      45             : 
      46         100 : extern "C" long JPEGCallback( void* pCallbackData, long nPercent )
      47             : {
      48         100 :     JPEGCallbackStruct* pCallbackStruct = (JPEGCallbackStruct*)pCallbackData;
      49         100 :     if ( pCallbackStruct && pCallbackStruct->xStatusIndicator.is() )
      50             :     {
      51           0 :         pCallbackStruct->xStatusIndicator->setValue( nPercent );
      52             :     }
      53         100 :     return 0L;
      54             : }
      55             : 
      56             : typedef struct
      57             : {
      58             :     struct jpeg_destination_mgr pub;  /* public fields */
      59             :     SvStream* stream;                 /* target stream */
      60             :     JOCTET * buffer;                  /* start of buffer */
      61             : } DestinationManagerStruct;
      62             : 
      63             : typedef DestinationManagerStruct* DestinationManagerStructPointer;
      64             : 
      65           1 : extern "C" void init_destination (j_compress_ptr cinfo)
      66             : {
      67           1 :     DestinationManagerStructPointer destination = (DestinationManagerStructPointer) cinfo->dest;
      68             : 
      69             :     /* Allocate the output buffer -- it will be released when done with image */
      70             :     destination->buffer = (JOCTET *)
      71           1 :         (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, BUFFER_SIZE * sizeof(JOCTET));
      72             : 
      73           1 :     destination->pub.next_output_byte = destination->buffer;
      74           1 :     destination->pub.free_in_buffer = BUFFER_SIZE;
      75           1 : }
      76             : 
      77           0 : extern "C" boolean empty_output_buffer (j_compress_ptr cinfo)
      78             : {
      79           0 :     DestinationManagerStructPointer destination = (DestinationManagerStructPointer) cinfo->dest;
      80             : 
      81           0 :     if (destination->stream->Write(destination->buffer, BUFFER_SIZE) != (size_t) BUFFER_SIZE)
      82             :     {
      83           0 :         ERREXIT(cinfo, JERR_FILE_WRITE);
      84             :     }
      85             : 
      86           0 :     destination->pub.next_output_byte = destination->buffer;
      87           0 :     destination->pub.free_in_buffer = BUFFER_SIZE;
      88             : 
      89           0 :     return sal_True;
      90             : }
      91             : 
      92           1 : extern "C" void term_destination (j_compress_ptr cinfo)
      93             : {
      94           1 :     DestinationManagerStructPointer destination = (DestinationManagerStructPointer) cinfo->dest;
      95           1 :     size_t datacount = BUFFER_SIZE - destination->pub.free_in_buffer;
      96             : 
      97             :     /* Write any data remaining in the buffer */
      98           1 :     if (datacount > 0)
      99             :     {
     100           1 :         if (destination->stream->Write(destination->buffer, datacount) != datacount)
     101             :         {
     102           0 :             ERREXIT(cinfo, JERR_FILE_WRITE);
     103             :         }
     104             :     }
     105           1 : }
     106             : 
     107           1 : extern "C" void jpeg_svstream_dest (j_compress_ptr cinfo, void* output)
     108             : {
     109           1 :     SvStream* stream = (SvStream*) output;
     110             :     DestinationManagerStructPointer destination;
     111             : 
     112             :     /* The destination object is made permanent so that multiple JPEG images
     113             :      * can be written to the same file without re-executing jpeg_svstream_dest.
     114             :      * This makes it dangerous to use this manager and a different destination
     115             :      * manager serially with the same JPEG object, because their private object
     116             :      * sizes may be different.  Caveat programmer.
     117             :      */
     118           1 :     if (cinfo->dest == NULL)
     119             :     {    /* first time for this JPEG object? */
     120             :         cinfo->dest = (struct jpeg_destination_mgr*)
     121           1 :         (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(DestinationManagerStruct));
     122             :     }
     123             : 
     124           1 :     destination = (DestinationManagerStructPointer) cinfo->dest;
     125           1 :     destination->pub.init_destination = init_destination;
     126           1 :     destination->pub.empty_output_buffer = empty_output_buffer;
     127           1 :     destination->pub.term_destination = term_destination;
     128           1 :     destination->stream = stream;
     129           1 : }
     130             : 
     131           1 : JPEGWriter::JPEGWriter( SvStream& rStream, const css::uno::Sequence< css::beans::PropertyValue >* pFilterData, bool* pExportWasGrey ) :
     132             :     mrStream     ( rStream ),
     133             :     mpReadAccess ( NULL ),
     134             :     mpBuffer     ( NULL ),
     135           1 :     mpExpWasGrey ( pExportWasGrey )
     136             : {
     137           1 :     FilterConfigItem aConfigItem( (css::uno::Sequence< css::beans::PropertyValue >*) pFilterData );
     138           1 :     mbGreys = aConfigItem.ReadInt32( "ColorMode", 0 ) != 0;
     139           1 :     mnQuality = aConfigItem.ReadInt32( "Quality", 75 );
     140           1 :     maChromaSubsampling = aConfigItem.ReadInt32( "ChromaSubsamplingMode", 0 );
     141             : 
     142           1 :     if ( pFilterData )
     143             :     {
     144           1 :         int nArgs = pFilterData->getLength();
     145           1 :         const css::beans::PropertyValue* pValues = pFilterData->getConstArray();
     146           5 :         while( nArgs-- )
     147             :         {
     148           3 :             if ( pValues->Name == "StatusIndicator" )
     149             :             {
     150           0 :                 pValues->Value >>= mxStatusIndicator;
     151             :             }
     152           3 :             pValues++;
     153             :         }
     154           1 :     }
     155           1 : }
     156             : 
     157         100 : void* JPEGWriter::GetScanline( long nY )
     158             : {
     159         100 :     void* pScanline = NULL;
     160             : 
     161         100 :     if( mpReadAccess )
     162             :     {
     163         100 :         if( mbNative )
     164             :         {
     165           0 :             pScanline = mpReadAccess->GetScanline( nY );
     166             :         }
     167         100 :         else if( mpBuffer )
     168             :         {
     169         100 :             BitmapColor aColor;
     170         100 :             long        nWidth = mpReadAccess->Width();
     171         100 :             sal_uInt8*  pTmp = mpBuffer;
     172             : 
     173         100 :             if( mpReadAccess->HasPalette() )
     174             :             {
     175           0 :                 for( long nX = 0L; nX < nWidth; nX++ )
     176             :                 {
     177           0 :                     aColor = mpReadAccess->GetPaletteColor( mpReadAccess->GetPixelIndex( nY, nX ) );
     178           0 :                     *pTmp++ = aColor.GetRed();
     179           0 :                     if ( !mbGreys )
     180             :                     {
     181           0 :                         *pTmp++ = aColor.GetGreen();
     182           0 :                         *pTmp++ = aColor.GetBlue();
     183             :                     }
     184             :                 }
     185             :             }
     186             :             else
     187             :             {
     188       10100 :                 for( long nX = 0L; nX < nWidth; nX++ )
     189             :                 {
     190       10000 :                     aColor = mpReadAccess->GetPixel( nY, nX );
     191       10000 :                     *pTmp++ = aColor.GetRed();
     192       10000 :                     if ( !mbGreys )
     193             :                     {
     194           0 :                         *pTmp++ = aColor.GetGreen();
     195           0 :                         *pTmp++ = aColor.GetBlue();
     196             :                     }
     197             :                 }
     198             :             }
     199             : 
     200         100 :             pScanline = mpBuffer;
     201             :         }
     202             :     }
     203             : 
     204         100 :     return pScanline;
     205             : }
     206             : 
     207           1 : sal_Bool JPEGWriter::Write( const Graphic& rGraphic )
     208             : {
     209           1 :     sal_Bool bRet = sal_False;
     210             : 
     211           1 :     if ( mxStatusIndicator.is() )
     212             :     {
     213           0 :         OUString aMsg;
     214           0 :         mxStatusIndicator->start( aMsg, 100 );
     215             :     }
     216             : 
     217           1 :     Bitmap aGraphicBmp( rGraphic.GetBitmap() );
     218             : 
     219           1 :     if ( mbGreys )
     220             :     {
     221           0 :         if ( !aGraphicBmp.Convert( BMP_CONVERSION_8BIT_GREYS ) )
     222           0 :             aGraphicBmp = rGraphic.GetBitmap();
     223             :     }
     224             : 
     225           1 :     mpReadAccess = aGraphicBmp.AcquireReadAccess();
     226             : 
     227           1 :     if ( !mbGreys )  // bitmap was not explicitly converted into greyscale,
     228             :     {                // check if source is greyscale only
     229             : 
     230           1 :         bool bIsGrey = true;
     231             : 
     232           1 :         long nWidth = mpReadAccess->Width();
     233         101 :         for ( long nY = 0; bIsGrey && ( nY < mpReadAccess->Height() ); nY++ )
     234             :         {
     235         100 :             BitmapColor aColor;
     236       10100 :             for( long nX = 0L; bIsGrey && ( nX < nWidth ); nX++ )
     237             :             {
     238       20000 :                 aColor = mpReadAccess->HasPalette() ? mpReadAccess->GetPaletteColor( mpReadAccess->GetPixelIndex( nY, nX ) )
     239       10000 :                                             : mpReadAccess->GetPixel( nY, nX );
     240       10000 :                 bIsGrey = ( aColor.GetRed() == aColor.GetGreen() ) && ( aColor.GetRed() == aColor.GetBlue() );
     241             :             }
     242         100 :         }
     243           1 :         if ( bIsGrey )
     244           1 :             mbGreys = sal_True;
     245             :     }
     246             : 
     247           1 :     if( mpExpWasGrey )
     248           1 :         *mpExpWasGrey = mbGreys;
     249             : 
     250           1 :     if( mpReadAccess )
     251             :     {
     252           1 :         mbNative = ( mpReadAccess->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB );
     253             : 
     254           1 :         if( !mbNative )
     255           1 :             mpBuffer = new sal_uInt8[ AlignedWidth4Bytes( mbGreys ? mpReadAccess->Width() * 8L : mpReadAccess->Width() * 24L ) ];
     256             : 
     257           1 :         JPEGCallbackStruct aCallbackData;
     258           1 :         aCallbackData.xStatusIndicator = mxStatusIndicator;
     259           1 :         bRet = (sal_Bool) WriteJPEG( this, &mrStream, mpReadAccess->Width(), mpReadAccess->Height(), mbGreys, mnQuality, maChromaSubsampling, &aCallbackData );
     260             : 
     261           1 :         delete[] mpBuffer;
     262           1 :         mpBuffer = NULL;
     263             : 
     264           1 :         aGraphicBmp.ReleaseAccess( mpReadAccess );
     265           1 :         mpReadAccess = NULL;
     266             :     }
     267           1 :     if ( mxStatusIndicator.is() )
     268           0 :         mxStatusIndicator->end();
     269             : 
     270           1 :     return bRet;
     271         465 : }
     272             : 
     273             : 
     274             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10