LCOV - code coverage report
Current view: top level - vcl/source/filter/jpeg - jpegc.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 101 178 56.7 %
Date: 2015-06-13 12:38:46 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 <stdlib.h>
      24             : #include <setjmp.h>
      25             : #include <jpeglib.h>
      26             : #include <jerror.h>
      27             : 
      28             : #include <com/sun/star/task/XStatusIndicator.hpp>
      29             : #include <osl/diagnose.h>
      30             : 
      31             : extern "C" {
      32             : #include "transupp.h"
      33             : }
      34             : 
      35             : #include "jpeg.h"
      36             : #include <JpegReader.hxx>
      37             : #include <JpegWriter.hxx>
      38             : #include <boost/scoped_array.hpp>
      39             : 
      40             : #ifdef _MSC_VER
      41             : #pragma warning(push, 1) /* disable to __declspec(align()) aligned warning */
      42             : #pragma warning (disable: 4324)
      43             : #endif
      44             : 
      45             : struct ErrorManagerStruct
      46             : {
      47             :     jpeg_error_mgr pub;
      48             :     jmp_buf setjmp_buffer;
      49             : };
      50             : 
      51             : #ifdef _MSC_VER
      52             : #pragma warning(pop)
      53             : #endif
      54             : 
      55           6 : extern "C" void errorExit (j_common_ptr cinfo)
      56             : {
      57           6 :     ErrorManagerStruct * error = reinterpret_cast<ErrorManagerStruct *>(cinfo->err);
      58           6 :     (*cinfo->err->output_message) (cinfo);
      59           6 :     longjmp(error->setjmp_buffer, 1);
      60             : }
      61             : 
      62          13 : extern "C" void outputMessage (j_common_ptr cinfo)
      63             : {
      64             :     char buffer[JMSG_LENGTH_MAX];
      65          13 :     (*cinfo->err->format_message) (cinfo, buffer);
      66          13 : }
      67             : 
      68         439 : void ReadJPEG( JPEGReader* pJPEGReader, void* pInputStream, long* pLines,
      69             :                Size const & previewSize )
      70             : {
      71             :     jpeg_decompress_struct          cinfo;
      72             :     ErrorManagerStruct              jerr;
      73             :     JPEGCreateBitmapParam           aCreateBitmapParam;
      74             :     unsigned char *                 pDIB;
      75             :     unsigned char *                 pTmp;
      76             :     long                            nWidth;
      77             :     long                            nHeight;
      78             :     long                            nAlignedWidth;
      79             :     JSAMPLE*                        aRangeLimit;
      80         439 :     boost::scoped_array<unsigned char> pScanLineBuffer;
      81             : 
      82         439 :     if ( setjmp( jerr.setjmp_buffer ) )
      83             :     {
      84           6 :         jpeg_destroy_decompress( &cinfo );
      85         445 :         return;
      86             :     }
      87             : 
      88         439 :     cinfo.err = jpeg_std_error( &jerr.pub );
      89         439 :     jerr.pub.error_exit = errorExit;
      90         439 :     jerr.pub.output_message = outputMessage;
      91             : 
      92         439 :     jpeg_create_decompress( &cinfo );
      93         439 :     jpeg_svstream_src( &cinfo, pInputStream );
      94         439 :     jpeg_read_header( &cinfo, TRUE );
      95             : 
      96         438 :     cinfo.scale_num = 1;
      97         438 :     cinfo.scale_denom = 1;
      98         438 :     cinfo.output_gamma = 1.0;
      99         438 :     cinfo.raw_data_out = FALSE;
     100         438 :     cinfo.quantize_colors = FALSE;
     101         438 :     if ( cinfo.jpeg_color_space == JCS_YCbCr )
     102         436 :         cinfo.out_color_space = JCS_RGB;
     103           2 :     else if ( cinfo.jpeg_color_space == JCS_YCCK )
     104           1 :         cinfo.out_color_space = JCS_CMYK;
     105             : 
     106             :     OSL_ASSERT(cinfo.out_color_space == JCS_CMYK || cinfo.out_color_space == JCS_GRAYSCALE || cinfo.out_color_space == JCS_RGB);
     107             : 
     108             :     /* change scale for preview import */
     109         438 :     long nPreviewWidth = previewSize.Width();
     110         438 :     long nPreviewHeight = previewSize.Height();
     111         438 :     if( nPreviewWidth || nPreviewHeight )
     112             :     {
     113           0 :         if( nPreviewWidth == 0 )
     114             :         {
     115           0 :             nPreviewWidth = ( cinfo.image_width * nPreviewHeight ) / cinfo.image_height;
     116           0 :             if( nPreviewWidth <= 0 )
     117             :             {
     118           0 :                 nPreviewWidth = 1;
     119             :             }
     120             :         }
     121           0 :         else if( nPreviewHeight == 0 )
     122             :         {
     123           0 :             nPreviewHeight = ( cinfo.image_height * nPreviewWidth ) / cinfo.image_width;
     124           0 :             if( nPreviewHeight <= 0 )
     125             :             {
     126           0 :                 nPreviewHeight = 1;
     127             :             }
     128             :         }
     129             : 
     130           0 :         for( cinfo.scale_denom = 1; cinfo.scale_denom < 8; cinfo.scale_denom *= 2 )
     131             :         {
     132           0 :             if( cinfo.image_width < nPreviewWidth * cinfo.scale_denom )
     133           0 :                 break;
     134           0 :             if( cinfo.image_height < nPreviewHeight * cinfo.scale_denom )
     135           0 :                 break;
     136             :         }
     137             : 
     138           0 :         if( cinfo.scale_denom > 1 )
     139             :         {
     140           0 :             cinfo.dct_method            = JDCT_FASTEST;
     141           0 :             cinfo.do_fancy_upsampling   = FALSE;
     142           0 :             cinfo.do_block_smoothing    = FALSE;
     143             :         }
     144             :     }
     145             : 
     146         438 :     jpeg_start_decompress( &cinfo );
     147             : 
     148         434 :     nWidth = cinfo.output_width;
     149         434 :     nHeight = cinfo.output_height;
     150         434 :     aCreateBitmapParam.nWidth = nWidth;
     151         434 :     aCreateBitmapParam.nHeight = nHeight;
     152             : 
     153         434 :     aCreateBitmapParam.density_unit = cinfo.density_unit;
     154         434 :     aCreateBitmapParam.X_density = cinfo.X_density;
     155         434 :     aCreateBitmapParam.Y_density = cinfo.Y_density;
     156         434 :     aCreateBitmapParam.bGray = long(cinfo.output_components == 1);
     157         434 :     pDIB = pJPEGReader->CreateBitmap( &aCreateBitmapParam );
     158         434 :     nAlignedWidth = aCreateBitmapParam.nAlignedWidth;
     159         434 :     aRangeLimit = cinfo.sample_range_limit;
     160             : 
     161         434 :     long nScanLineBufferComponents = 0;
     162         434 :     if ( cinfo.out_color_space == JCS_CMYK )
     163             :     {
     164           1 :         nScanLineBufferComponents = cinfo.output_width * 4;
     165           1 :         pScanLineBuffer.reset(new unsigned char[nScanLineBufferComponents]);
     166             :     }
     167             : 
     168         434 :     if( pDIB )
     169             :     {
     170         434 :         if( aCreateBitmapParam.bTopDown )
     171             :         {
     172         433 :             pTmp = pDIB;
     173             :         }
     174             :         else
     175             :         {
     176           1 :             pTmp = pDIB + ( nHeight - 1 ) * nAlignedWidth;
     177           1 :             nAlignedWidth = -nAlignedWidth;
     178             :         }
     179             : 
     180      179104 :         for ( *pLines = 0; *pLines < nHeight; (*pLines)++ )
     181             :         {
     182      178670 :             if (pScanLineBuffer)
     183             :             { // in other words cinfo.out_color_space == JCS_CMYK
     184             :                 int i;
     185             :                 int j;
     186         353 :                 unsigned char *pSLB = pScanLineBuffer.get();
     187         353 :                 jpeg_read_scanlines( &cinfo, reinterpret_cast<JSAMPARRAY>(&pSLB), 1 );
     188             :                 // convert CMYK to RGB
     189      414069 :                 for( i=0, j=0; i < nScanLineBufferComponents; i+=4, j+=3 )
     190             :                 {
     191      413716 :                     int color_C = 255 - pScanLineBuffer[i+0];
     192      413716 :                     int color_M = 255 - pScanLineBuffer[i+1];
     193      413716 :                     int color_Y = 255 - pScanLineBuffer[i+2];
     194      413716 :                     int color_K = 255 - pScanLineBuffer[i+3];
     195      413716 :                     pTmp[j+0] = aRangeLimit[ 255L - ( color_C + color_K ) ];
     196      413716 :                     pTmp[j+1] = aRangeLimit[ 255L - ( color_M + color_K ) ];
     197      413716 :                     pTmp[j+2] = aRangeLimit[ 255L - ( color_Y + color_K ) ];
     198             :                 }
     199             :             }
     200             :             else
     201             :             {
     202      178317 :                 jpeg_read_scanlines( &cinfo, reinterpret_cast<JSAMPARRAY>(&pTmp), 1 );
     203             :             }
     204             : 
     205             :             /* PENDING ??? */
     206      178670 :             if ( cinfo.err->msg_code == 113 )
     207           0 :                 break;
     208             : 
     209      178670 :             pTmp += nAlignedWidth;
     210             :         }
     211             :     }
     212             : 
     213         434 :     if ( pDIB )
     214             :     {
     215         434 :         jpeg_finish_decompress( &cinfo );
     216             :     }
     217             :     else
     218             :     {
     219           0 :         jpeg_abort_decompress( &cinfo );
     220             :     }
     221             : 
     222         433 :     pScanLineBuffer.reset();
     223             : 
     224         433 :     jpeg_destroy_decompress( &cinfo );
     225             : }
     226             : 
     227           1 : bool WriteJPEG( JPEGWriter* pJPEGWriter, void* pOutputStream,
     228             :                 long nWidth, long nHeight, bool bGreys,
     229             :                 long nQualityPercent, long aChromaSubsampling,
     230             :                 css::uno::Reference<css::task::XStatusIndicator> const & status )
     231             : {
     232             :     jpeg_compress_struct        cinfo;
     233             :     ErrorManagerStruct          jerr;
     234             :     void*                       pScanline;
     235             :     long                        nY;
     236             : 
     237           1 :     if ( setjmp( jerr.setjmp_buffer ) )
     238             :     {
     239           0 :         jpeg_destroy_compress( &cinfo );
     240           0 :         return false;
     241             :     }
     242             : 
     243           1 :     cinfo.err = jpeg_std_error( &jerr.pub );
     244           1 :     jerr.pub.error_exit = errorExit;
     245           1 :     jerr.pub.output_message = outputMessage;
     246             : 
     247           1 :     jpeg_create_compress( &cinfo );
     248           1 :     jpeg_svstream_dest( &cinfo, pOutputStream );
     249             : 
     250           1 :     cinfo.image_width = (JDIMENSION) nWidth;
     251           1 :     cinfo.image_height = (JDIMENSION) nHeight;
     252           1 :     if ( bGreys )
     253             :     {
     254           1 :         cinfo.input_components = 1;
     255           1 :         cinfo.in_color_space = JCS_GRAYSCALE;
     256             :     }
     257             :     else
     258             :     {
     259           0 :         cinfo.input_components = 3;
     260           0 :         cinfo.in_color_space = JCS_RGB;
     261             :     }
     262             : 
     263           1 :     jpeg_set_defaults( &cinfo );
     264           1 :     jpeg_set_quality( &cinfo, (int) nQualityPercent, FALSE );
     265             : 
     266           1 :     cinfo.density_unit = 1;
     267           1 :     cinfo.X_density = 96;
     268           1 :     cinfo.Y_density = 96;
     269             : 
     270           1 :     if ( ( nWidth > 128 ) || ( nHeight > 128 ) )
     271           0 :         jpeg_simple_progression( &cinfo );
     272             : 
     273           1 :     if (aChromaSubsampling == 1) // YUV 4:4:4
     274             :     {
     275           0 :         cinfo.comp_info[0].h_samp_factor = 1;
     276           0 :         cinfo.comp_info[0].v_samp_factor = 1;
     277             :     }
     278           1 :     else if (aChromaSubsampling == 2) // YUV 4:2:2
     279             :     {
     280           0 :         cinfo.comp_info[0].h_samp_factor = 2;
     281           0 :         cinfo.comp_info[0].v_samp_factor = 1;
     282             :     }
     283           1 :     else if (aChromaSubsampling == 3) // YUV 4:2:0
     284             :     {
     285           0 :         cinfo.comp_info[0].h_samp_factor = 2;
     286           0 :         cinfo.comp_info[0].v_samp_factor = 2;
     287             :     }
     288             : 
     289           1 :     jpeg_start_compress( &cinfo, TRUE );
     290             : 
     291         101 :     for( nY = 0; nY < nHeight; nY++ )
     292             :     {
     293         100 :         pScanline = pJPEGWriter->GetScanline( nY );
     294             : 
     295         100 :         if( pScanline )
     296             :         {
     297         100 :             jpeg_write_scanlines( &cinfo, reinterpret_cast<JSAMPARRAY>(&pScanline), 1 );
     298             :         }
     299             : 
     300         100 :         if( status.is() )
     301             :         {
     302           0 :             status->setValue( nY * 100L / nHeight );
     303             :         }
     304             :     }
     305             : 
     306           1 :     jpeg_finish_compress(&cinfo);
     307           1 :     jpeg_destroy_compress( &cinfo );
     308             : 
     309           1 :     return true;
     310             : }
     311             : 
     312           0 : long Transform(void* pInputStream, void* pOutputStream, long nAngle)
     313             : {
     314             :     jpeg_transform_info aTransformOption;
     315           0 :     JCOPY_OPTION        aCopyOption = JCOPYOPT_ALL;
     316             : 
     317             :     jpeg_decompress_struct   aSourceInfo;
     318             :     jpeg_compress_struct     aDestinationInfo;
     319             :     ErrorManagerStruct       aSourceError;
     320             :     ErrorManagerStruct       aDestinationError;
     321             : 
     322           0 :     jvirt_barray_ptr* aSourceCoefArrays      = 0;
     323           0 :     jvirt_barray_ptr* aDestinationCoefArrays = 0;
     324             : 
     325           0 :     aTransformOption.force_grayscale = FALSE;
     326           0 :     aTransformOption.trim            = FALSE;
     327           0 :     aTransformOption.perfect         = FALSE;
     328           0 :     aTransformOption.crop            = FALSE;
     329             : 
     330             :     // Angle to transform option
     331             :     // 90 Clockwise = 270 Counterclockwise
     332           0 :     switch (nAngle)
     333             :     {
     334             :         case 2700:
     335           0 :             aTransformOption.transform  = JXFORM_ROT_90;
     336           0 :             break;
     337             :         case 1800:
     338           0 :             aTransformOption.transform  = JXFORM_ROT_180;
     339           0 :             break;
     340             :         case 900:
     341           0 :             aTransformOption.transform  = JXFORM_ROT_270;
     342           0 :             break;
     343             :         default:
     344           0 :             aTransformOption.transform  = JXFORM_NONE;
     345             :     }
     346             : 
     347             :     // Decompression
     348           0 :     aSourceInfo.err                 = jpeg_std_error(&aSourceError.pub);
     349           0 :     aSourceInfo.err->error_exit     = errorExit;
     350           0 :     aSourceInfo.err->output_message = outputMessage;
     351             : 
     352             :     // Compression
     353           0 :     aDestinationInfo.err                 = jpeg_std_error(&aDestinationError.pub);
     354           0 :     aDestinationInfo.err->error_exit     = errorExit;
     355           0 :     aDestinationInfo.err->output_message = outputMessage;
     356             : 
     357           0 :     aDestinationInfo.optimize_coding = TRUE;
     358             : 
     359           0 :     if (setjmp(aSourceError.setjmp_buffer) || setjmp(aDestinationError.setjmp_buffer))
     360             :     {
     361           0 :         jpeg_destroy_decompress(&aSourceInfo);
     362           0 :         jpeg_destroy_compress(&aDestinationInfo);
     363           0 :         return 0;
     364             :     }
     365             : 
     366           0 :     jpeg_create_decompress(&aSourceInfo);
     367           0 :     jpeg_create_compress(&aDestinationInfo);
     368             : 
     369           0 :     jpeg_svstream_src (&aSourceInfo, pInputStream);
     370             : 
     371           0 :     jcopy_markers_setup(&aSourceInfo, aCopyOption);
     372           0 :     jpeg_read_header(&aSourceInfo, TRUE);
     373           0 :     jtransform_request_workspace(&aSourceInfo, &aTransformOption);
     374             : 
     375           0 :     aSourceCoefArrays = jpeg_read_coefficients(&aSourceInfo);
     376           0 :     jpeg_copy_critical_parameters(&aSourceInfo, &aDestinationInfo);
     377             : 
     378           0 :     aDestinationCoefArrays = jtransform_adjust_parameters(&aSourceInfo, &aDestinationInfo, aSourceCoefArrays, &aTransformOption);
     379           0 :     jpeg_svstream_dest (&aDestinationInfo, pOutputStream);
     380             : 
     381             :     // Compute optimal Huffman coding tables instead of precomuted tables
     382           0 :     aDestinationInfo.optimize_coding = TRUE;
     383           0 :     jpeg_write_coefficients(&aDestinationInfo, aDestinationCoefArrays);
     384           0 :     jcopy_markers_execute(&aSourceInfo, &aDestinationInfo, aCopyOption);
     385           0 :     jtransform_execute_transformation(&aSourceInfo, &aDestinationInfo, aSourceCoefArrays, &aTransformOption);
     386             : 
     387           0 :     jpeg_finish_compress(&aDestinationInfo);
     388           0 :     jpeg_destroy_compress(&aDestinationInfo);
     389             : 
     390           0 :     jpeg_finish_decompress(&aSourceInfo);
     391           0 :     jpeg_destroy_decompress(&aSourceInfo);
     392             : 
     393           0 :     return 1;
     394         801 : }
     395             : 
     396             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11