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

Generated by: LCOV version 1.10