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

Generated by: LCOV version 1.10