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

Generated by: LCOV version 1.11