[Libreoffice-commits] core.git: vcl/source

Stephan Bergmann sbergman at redhat.com
Wed Oct 18 22:04:23 UTC 2017


 vcl/source/filter/jpeg/jpegc.cxx |  607 ++++++++++++++++++++-------------------
 1 file changed, 321 insertions(+), 286 deletions(-)

New commits:
commit cfbb8b5090537e79ba70e250ddee86d53facbe15
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Wed Oct 18 13:02:28 2017 +0200

    Avoid throwing C++ exception across libjpeg C frames
    
    It causes trouble at least for (non-debug) 32-bit ARM Flatpak builds, where
    CppunitTest_vcl_filters_test aborts with an uncaught css::uno::RuntimeException.
    
    This is a partial revert of 6889fa826eef6bd1074d77507818e71dfe8ba152 "rework
    jpeg error handling to throw rather than setjmp to avoid leaks", switching back
    to setjmp/longjmp but trying to keep the leaks fixed by introducing any relevant
    local variables before the setjmps.
    
    Change-Id: Ia5984528ea98be1c89a21aee800b247120f88a89
    Reviewed-on: https://gerrit.libreoffice.org/43494
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>

diff --git a/vcl/source/filter/jpeg/jpegc.cxx b/vcl/source/filter/jpeg/jpegc.cxx
index 4305f065ed54..86dd30b71c7e 100644
--- a/vcl/source/filter/jpeg/jpegc.cxx
+++ b/vcl/source/filter/jpeg/jpegc.cxx
@@ -21,6 +21,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <setjmp.h>
 #include <jpeglib.h>
 #include <jerror.h>
 
@@ -37,12 +38,28 @@ extern "C" {
 #include <vcl/bitmapaccess.hxx>
 #include <vcl/graphicfilter.hxx>
 
+#ifdef _MSC_VER
+#pragma warning(push, 1) /* disable to __declspec(align()) aligned warning */
+#pragma warning (disable: 4324)
+#endif
+
+struct ErrorManagerStruct
+{
+    jpeg_error_mgr pub;
+    jmp_buf setjmp_buffer;
+};
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
 extern "C" void errorExit (j_common_ptr cinfo)
 {
     char buffer[JMSG_LENGTH_MAX];
     (*cinfo->err->format_message) (cinfo, buffer);
     SAL_WARN("vcl.filter", "fatal failure reading JPEG: " << buffer);
-    throw css::uno::RuntimeException(OUString(buffer, strlen(buffer), RTL_TEXTENCODING_ASCII_US));
+    ErrorManagerStruct * error = reinterpret_cast<ErrorManagerStruct *>(cinfo->err);
+    longjmp(error->setjmp_buffer, 1);
 }
 
 extern "C" void outputMessage (j_common_ptr cinfo)
@@ -55,226 +72,239 @@ extern "C" void outputMessage (j_common_ptr cinfo)
 class JpegDecompressOwner
 {
 public:
-    JpegDecompressOwner(jpeg_decompress_struct &cinfo) : m_cinfo(cinfo)
+    void set(jpeg_decompress_struct *cinfo)
     {
+        m_cinfo = cinfo;
     }
     ~JpegDecompressOwner()
     {
-        jpeg_destroy_decompress(&m_cinfo);
+        if (m_cinfo != nullptr)
+        {
+            jpeg_destroy_decompress(m_cinfo);
+        }
     }
 private:
-    jpeg_decompress_struct &m_cinfo;
+    jpeg_decompress_struct *m_cinfo = nullptr;
 };
 
 class JpegCompressOwner
 {
 public:
-    JpegCompressOwner(jpeg_compress_struct &cinfo) : m_cinfo(cinfo)
+    void set(jpeg_compress_struct *cinfo)
     {
+        m_cinfo = cinfo;
     }
     ~JpegCompressOwner()
     {
-        jpeg_destroy_compress(&m_cinfo);
+        if (m_cinfo != nullptr)
+        {
+            jpeg_destroy_compress(m_cinfo);
+        }
     }
 private:
-    jpeg_compress_struct &m_cinfo;
+    jpeg_compress_struct *m_cinfo = nullptr;
 };
 
 void ReadJPEG( JPEGReader* pJPEGReader, void* pInputStream, long* pLines,
                Size const & previewSize, GraphicFilterImportFlags nImportFlags,
                Bitmap::ScopedWriteAccess* ppAccess )
 {
-    try
+    jpeg_decompress_struct cinfo;
+    ErrorManagerStruct jerr;
+
+    JpegDecompressOwner aOwner;
+    std::unique_ptr<Bitmap::ScopedWriteAccess> pScopedAccess;
+    std::vector<sal_uInt8> pScanLineBuffer;
+    std::vector<sal_uInt8> pCYMKBuffer;
+
+    if ( setjmp( jerr.setjmp_buffer ) )
+    {
+        return;
+    }
+
+    cinfo.err = jpeg_std_error( &jerr.pub );
+    jerr.pub.error_exit = errorExit;
+    jerr.pub.output_message = outputMessage;
+
+    jpeg_create_decompress( &cinfo );
+    aOwner.set(&cinfo);
+    jpeg_svstream_src( &cinfo, pInputStream );
+    SourceManagerStruct *source = reinterpret_cast<SourceManagerStruct*>(cinfo.src);
+    jpeg_read_header( &cinfo, TRUE );
+
+    cinfo.scale_num = 1;
+    cinfo.scale_denom = 1;
+    cinfo.output_gamma = 1.0;
+    cinfo.raw_data_out = FALSE;
+    cinfo.quantize_colors = FALSE;
+
+    /* change scale for preview import */
+    long nPreviewWidth = previewSize.Width();
+    long nPreviewHeight = previewSize.Height();
+    if( nPreviewWidth || nPreviewHeight )
     {
-        jpeg_decompress_struct cinfo;
-        jpeg_error_mgr jerr;
-
-        cinfo.err = jpeg_std_error( &jerr );
-        jerr.error_exit = errorExit;
-        jerr.output_message = outputMessage;
-
-        jpeg_create_decompress( &cinfo );
-        JpegDecompressOwner aOwner(cinfo);
-        jpeg_svstream_src( &cinfo, pInputStream );
-        SourceManagerStruct *source = reinterpret_cast<SourceManagerStruct*>(cinfo.src);
-        jpeg_read_header( &cinfo, TRUE );
-
-        cinfo.scale_num = 1;
-        cinfo.scale_denom = 1;
-        cinfo.output_gamma = 1.0;
-        cinfo.raw_data_out = FALSE;
-        cinfo.quantize_colors = FALSE;
-
-        /* change scale for preview import */
-        long nPreviewWidth = previewSize.Width();
-        long nPreviewHeight = previewSize.Height();
-        if( nPreviewWidth || nPreviewHeight )
+        if( nPreviewWidth == 0 )
         {
-            if( nPreviewWidth == 0 )
+            nPreviewWidth = ( cinfo.image_width * nPreviewHeight ) / cinfo.image_height;
+            if( nPreviewWidth <= 0 )
             {
-                nPreviewWidth = ( cinfo.image_width * nPreviewHeight ) / cinfo.image_height;
-                if( nPreviewWidth <= 0 )
-                {
-                    nPreviewWidth = 1;
-                }
+                nPreviewWidth = 1;
             }
-            else if( nPreviewHeight == 0 )
+        }
+        else if( nPreviewHeight == 0 )
+        {
+            nPreviewHeight = ( cinfo.image_height * nPreviewWidth ) / cinfo.image_width;
+            if( nPreviewHeight <= 0 )
             {
-                nPreviewHeight = ( cinfo.image_height * nPreviewWidth ) / cinfo.image_width;
-                if( nPreviewHeight <= 0 )
-                {
-                    nPreviewHeight = 1;
-                }
+                nPreviewHeight = 1;
             }
+        }
 
-            for( cinfo.scale_denom = 1; cinfo.scale_denom < 8; cinfo.scale_denom *= 2 )
-            {
-                if( cinfo.image_width < nPreviewWidth * cinfo.scale_denom )
-                    break;
-                if( cinfo.image_height < nPreviewHeight * cinfo.scale_denom )
-                    break;
-            }
+        for( cinfo.scale_denom = 1; cinfo.scale_denom < 8; cinfo.scale_denom *= 2 )
+        {
+            if( cinfo.image_width < nPreviewWidth * cinfo.scale_denom )
+                break;
+            if( cinfo.image_height < nPreviewHeight * cinfo.scale_denom )
+                break;
+        }
 
-            if( cinfo.scale_denom > 1 )
-            {
-                cinfo.dct_method            = JDCT_FASTEST;
-                cinfo.do_fancy_upsampling   = FALSE;
-                cinfo.do_block_smoothing    = FALSE;
-            }
+        if( cinfo.scale_denom > 1 )
+        {
+            cinfo.dct_method            = JDCT_FASTEST;
+            cinfo.do_fancy_upsampling   = FALSE;
+            cinfo.do_block_smoothing    = FALSE;
         }
+    }
 
-        jpeg_calc_output_dimensions(&cinfo);
+    jpeg_calc_output_dimensions(&cinfo);
 
-        long nWidth = cinfo.output_width;
-        long nHeight = cinfo.output_height;
+    long nWidth = cinfo.output_width;
+    long nHeight = cinfo.output_height;
 
-        bool bGray = (cinfo.output_components == 1);
+    bool bGray = (cinfo.output_components == 1);
 
-        JPEGCreateBitmapParam aCreateBitmapParam;
+    JPEGCreateBitmapParam aCreateBitmapParam;
 
-        aCreateBitmapParam.nWidth = nWidth;
-        aCreateBitmapParam.nHeight = nHeight;
+    aCreateBitmapParam.nWidth = nWidth;
+    aCreateBitmapParam.nHeight = nHeight;
 
-        aCreateBitmapParam.density_unit = cinfo.density_unit;
-        aCreateBitmapParam.X_density = cinfo.X_density;
-        aCreateBitmapParam.Y_density = cinfo.Y_density;
-        aCreateBitmapParam.bGray = bGray;
+    aCreateBitmapParam.density_unit = cinfo.density_unit;
+    aCreateBitmapParam.X_density = cinfo.X_density;
+    aCreateBitmapParam.Y_density = cinfo.Y_density;
+    aCreateBitmapParam.bGray = bGray;
 
-        const auto bOnlyCreateBitmap = static_cast<bool>(nImportFlags & GraphicFilterImportFlags::OnlyCreateBitmap);
-        const auto bUseExistingBitmap = static_cast<bool>(nImportFlags & GraphicFilterImportFlags::UseExistingBitmap);
-        bool bBitmapCreated = bUseExistingBitmap;
-        if (!bBitmapCreated)
-            bBitmapCreated = pJPEGReader->CreateBitmap(aCreateBitmapParam);
+    const auto bOnlyCreateBitmap = static_cast<bool>(nImportFlags & GraphicFilterImportFlags::OnlyCreateBitmap);
+    const auto bUseExistingBitmap = static_cast<bool>(nImportFlags & GraphicFilterImportFlags::UseExistingBitmap);
+    bool bBitmapCreated = bUseExistingBitmap;
+    if (!bBitmapCreated)
+        bBitmapCreated = pJPEGReader->CreateBitmap(aCreateBitmapParam);
 
-        if (bBitmapCreated && !bOnlyCreateBitmap)
-        {
-            std::unique_ptr<Bitmap::ScopedWriteAccess> pScopedAccess;
+    if (bBitmapCreated && !bOnlyCreateBitmap)
+    {
+        if (nImportFlags & GraphicFilterImportFlags::UseExistingBitmap)
+            // ppAccess must be set if this flag is used.
+            assert(ppAccess);
+        else
+            pScopedAccess.reset(new Bitmap::ScopedWriteAccess(pJPEGReader->GetBitmap()));
 
-            if (nImportFlags & GraphicFilterImportFlags::UseExistingBitmap)
-                // ppAccess must be set if this flag is used.
-                assert(ppAccess);
-            else
-                pScopedAccess.reset(new Bitmap::ScopedWriteAccess(pJPEGReader->GetBitmap()));
+        Bitmap::ScopedWriteAccess& pAccess = bUseExistingBitmap ? *ppAccess : *pScopedAccess.get();
 
-            Bitmap::ScopedWriteAccess& pAccess = bUseExistingBitmap ? *ppAccess : *pScopedAccess.get();
+        if (pAccess)
+        {
+            int nPixelSize = 3;
+            J_COLOR_SPACE best_out_color_space = JCS_RGB;
+            ScanlineFormat eScanlineFormat = ScanlineFormat::N24BitTcRgb;
+            ScanlineFormat eFinalFormat = pAccess->GetScanlineFormat();
 
-            if (pAccess)
+            if (bGray)
+            {
+                best_out_color_space = JCS_GRAYSCALE;
+                eScanlineFormat = ScanlineFormat::N8BitPal;
+                nPixelSize = 1;
+            }
+            else if (eFinalFormat == ScanlineFormat::N32BitTcBgra)
+            {
+                best_out_color_space = JCS_EXT_BGRA;
+                eScanlineFormat = eFinalFormat;
+                nPixelSize = 4;
+            }
+            else if (eFinalFormat == ScanlineFormat::N32BitTcRgba)
+            {
+                best_out_color_space = JCS_EXT_RGBA;
+                eScanlineFormat = eFinalFormat;
+                nPixelSize = 4;
+            }
+            else if (eFinalFormat == ScanlineFormat::N32BitTcArgb)
             {
-                int nPixelSize = 3;
-                J_COLOR_SPACE best_out_color_space = JCS_RGB;
-                ScanlineFormat eScanlineFormat = ScanlineFormat::N24BitTcRgb;
-                ScanlineFormat eFinalFormat = pAccess->GetScanlineFormat();
+                best_out_color_space = JCS_EXT_ARGB;
+                eScanlineFormat = eFinalFormat;
+                nPixelSize = 4;
+            }
 
-                if (bGray)
-                {
-                    best_out_color_space = JCS_GRAYSCALE;
-                    eScanlineFormat = ScanlineFormat::N8BitPal;
-                    nPixelSize = 1;
-                }
-                else if (eFinalFormat == ScanlineFormat::N32BitTcBgra)
-                {
-                    best_out_color_space = JCS_EXT_BGRA;
-                    eScanlineFormat = eFinalFormat;
-                    nPixelSize = 4;
-                }
-                else if (eFinalFormat == ScanlineFormat::N32BitTcRgba)
-                {
-                    best_out_color_space = JCS_EXT_RGBA;
-                    eScanlineFormat = eFinalFormat;
-                    nPixelSize = 4;
-                }
-                else if (eFinalFormat == ScanlineFormat::N32BitTcArgb)
-                {
-                    best_out_color_space = JCS_EXT_ARGB;
-                    eScanlineFormat = eFinalFormat;
-                    nPixelSize = 4;
-                }
+            if (cinfo.jpeg_color_space == JCS_YCCK)
+                cinfo.out_color_space = JCS_CMYK;
 
-                if (cinfo.jpeg_color_space == JCS_YCCK)
-                    cinfo.out_color_space = JCS_CMYK;
+            if (cinfo.out_color_space != JCS_CMYK)
+                cinfo.out_color_space = best_out_color_space;
 
-                if (cinfo.out_color_space != JCS_CMYK)
-                    cinfo.out_color_space = best_out_color_space;
+            jpeg_start_decompress(&cinfo);
 
-                jpeg_start_decompress(&cinfo);
+            JSAMPLE* aRangeLimit = cinfo.sample_range_limit;
 
-                JSAMPLE* aRangeLimit = cinfo.sample_range_limit;
+            pScanLineBuffer.resize(nWidth * nPixelSize);
 
-                std::vector<sal_uInt8> pScanLineBuffer(nWidth * nPixelSize);
-                std::vector<sal_uInt8> pCYMKBuffer;
+            if (cinfo.out_color_space == JCS_CMYK)
+            {
+                pCYMKBuffer.resize(nWidth * 4);
+            }
 
-                if (cinfo.out_color_space == JCS_CMYK)
-                {
-                    pCYMKBuffer.resize(nWidth * 4);
-                }
+            for (*pLines = 0; *pLines < nHeight && !source->no_data_available; (*pLines)++)
+            {
+                size_t yIndex = *pLines;
+
+                sal_uInt8* p = (cinfo.out_color_space == JCS_CMYK) ? pCYMKBuffer.data() : pScanLineBuffer.data();
+                jpeg_read_scanlines(&cinfo, reinterpret_cast<JSAMPARRAY>(&p), 1);
 
-                for (*pLines = 0; *pLines < nHeight && !source->no_data_available; (*pLines)++)
+                if (cinfo.out_color_space == JCS_CMYK)
                 {
-                    size_t yIndex = *pLines;
+                    // convert CMYK to RGB
+                    for (long cmyk = 0, x = 0; cmyk < nWidth * 4; cmyk += 4, ++x)
+                    {
+                        int color_C = 255 - pCYMKBuffer[cmyk + 0];
+                        int color_M = 255 - pCYMKBuffer[cmyk + 1];
+                        int color_Y = 255 - pCYMKBuffer[cmyk + 2];
+                        int color_K = 255 - pCYMKBuffer[cmyk + 3];
 
-                    sal_uInt8* p = (cinfo.out_color_space == JCS_CMYK) ? pCYMKBuffer.data() : pScanLineBuffer.data();
-                    jpeg_read_scanlines(&cinfo, reinterpret_cast<JSAMPARRAY>(&p), 1);
+                        sal_uInt8 cRed = aRangeLimit[255L - (color_C + color_K)];
+                        sal_uInt8 cGreen = aRangeLimit[255L - (color_M + color_K)];
+                        sal_uInt8 cBlue = aRangeLimit[255L - (color_Y + color_K)];
 
-                    if (cinfo.out_color_space == JCS_CMYK)
-                    {
-                        // convert CMYK to RGB
-                        for (long cmyk = 0, x = 0; cmyk < nWidth * 4; cmyk += 4, ++x)
-                        {
-                            int color_C = 255 - pCYMKBuffer[cmyk + 0];
-                            int color_M = 255 - pCYMKBuffer[cmyk + 1];
-                            int color_Y = 255 - pCYMKBuffer[cmyk + 2];
-                            int color_K = 255 - pCYMKBuffer[cmyk + 3];
-
-                            sal_uInt8 cRed = aRangeLimit[255L - (color_C + color_K)];
-                            sal_uInt8 cGreen = aRangeLimit[255L - (color_M + color_K)];
-                            sal_uInt8 cBlue = aRangeLimit[255L - (color_Y + color_K)];
-
-                            pAccess->SetPixel(yIndex, x, BitmapColor(cRed, cGreen, cBlue));
-                        }
-                    }
-                    else
-                    {
-                        pAccess->CopyScanline(yIndex, pScanLineBuffer.data(), eScanlineFormat, pScanLineBuffer.size());
+                        pAccess->SetPixel(yIndex, x, BitmapColor(cRed, cGreen, cBlue));
                     }
-
-                    /* PENDING ??? */
-                    if (cinfo.err->msg_code == 113)
-                        break;
                 }
+                else
+                {
+                    pAccess->CopyScanline(yIndex, pScanLineBuffer.data(), eScanlineFormat, pScanLineBuffer.size());
+                }
+
+                /* PENDING ??? */
+                if (cinfo.err->msg_code == 113)
+                    break;
             }
-        }
 
-        if (bBitmapCreated && !bOnlyCreateBitmap)
-        {
-            jpeg_finish_decompress( &cinfo );
-        }
-        else
-        {
-            jpeg_abort_decompress( &cinfo );
+            pScanLineBuffer.clear();
+            pCYMKBuffer.clear();
         }
+        pScopedAccess.reset();
     }
-    catch (const css::uno::RuntimeException&)
+
+    if (bBitmapCreated && !bOnlyCreateBitmap)
     {
+        jpeg_finish_decompress( &cinfo );
+    }
+    else
+    {
+        jpeg_abort_decompress( &cinfo );
     }
 }
 
@@ -283,165 +313,170 @@ bool WriteJPEG( JPEGWriter* pJPEGWriter, void* pOutputStream,
                 long nQualityPercent, long aChromaSubsampling,
                 css::uno::Reference<css::task::XStatusIndicator> const & status )
 {
-    try
-    {
-        jpeg_compress_struct        cinfo;
-        jpeg_error_mgr              jerr;
-        void*                       pScanline;
-        long                        nY;
-
-        cinfo.err = jpeg_std_error( &jerr );
-        jerr.error_exit = errorExit;
-        jerr.output_message = outputMessage;
-
-        jpeg_create_compress( &cinfo );
-        JpegCompressOwner aOwner(cinfo);
-        jpeg_svstream_dest( &cinfo, pOutputStream );
-
-        cinfo.image_width = (JDIMENSION) nWidth;
-        cinfo.image_height = (JDIMENSION) nHeight;
-        if ( bGreys )
-        {
-            cinfo.input_components = 1;
-            cinfo.in_color_space = JCS_GRAYSCALE;
-        }
-        else
-        {
-            cinfo.input_components = 3;
-            cinfo.in_color_space = JCS_RGB;
-        }
+    jpeg_compress_struct        cinfo;
+    ErrorManagerStruct          jerr;
+    void*                       pScanline;
+    long                        nY;
 
-        jpeg_set_defaults( &cinfo );
-        jpeg_set_quality( &cinfo, (int) nQualityPercent, FALSE );
+    JpegCompressOwner aOwner;
 
-        cinfo.density_unit = 1;
-        cinfo.X_density = rPPI.getX();
-        cinfo.Y_density = rPPI.getY();
+    if ( setjmp( jerr.setjmp_buffer ) )
+    {
+        return false;
+    }
 
-        if ( ( nWidth > 128 ) || ( nHeight > 128 ) )
-            jpeg_simple_progression( &cinfo );
+    cinfo.err = jpeg_std_error( &jerr.pub );
+    jerr.pub.error_exit = errorExit;
+    jerr.pub.output_message = outputMessage;
 
-        if (aChromaSubsampling == 1) // YUV 4:4:4
-        {
-            cinfo.comp_info[0].h_samp_factor = 1;
-            cinfo.comp_info[0].v_samp_factor = 1;
-        }
-        else if (aChromaSubsampling == 2) // YUV 4:2:2
-        {
-            cinfo.comp_info[0].h_samp_factor = 2;
-            cinfo.comp_info[0].v_samp_factor = 1;
-        }
-        else if (aChromaSubsampling == 3) // YUV 4:2:0
-        {
-            cinfo.comp_info[0].h_samp_factor = 2;
-            cinfo.comp_info[0].v_samp_factor = 2;
-        }
+    jpeg_create_compress( &cinfo );
+    aOwner.set(&cinfo);
+    jpeg_svstream_dest( &cinfo, pOutputStream );
 
-        jpeg_start_compress( &cinfo, TRUE );
+    cinfo.image_width = (JDIMENSION) nWidth;
+    cinfo.image_height = (JDIMENSION) nHeight;
+    if ( bGreys )
+    {
+        cinfo.input_components = 1;
+        cinfo.in_color_space = JCS_GRAYSCALE;
+    }
+    else
+    {
+        cinfo.input_components = 3;
+        cinfo.in_color_space = JCS_RGB;
+    }
 
-        for( nY = 0; nY < nHeight; nY++ )
-        {
-            pScanline = pJPEGWriter->GetScanline( nY );
+    jpeg_set_defaults( &cinfo );
+    jpeg_set_quality( &cinfo, (int) nQualityPercent, FALSE );
 
-            if( pScanline )
-            {
-                jpeg_write_scanlines( &cinfo, reinterpret_cast<JSAMPARRAY>(&pScanline), 1 );
-            }
+    cinfo.density_unit = 1;
+    cinfo.X_density = rPPI.getX();
+    cinfo.Y_density = rPPI.getY();
 
-            if( status.is() )
-            {
-                status->setValue( nY * 100L / nHeight );
-            }
-        }
+    if ( ( nWidth > 128 ) || ( nHeight > 128 ) )
+        jpeg_simple_progression( &cinfo );
 
-        jpeg_finish_compress(&cinfo);
+    if (aChromaSubsampling == 1) // YUV 4:4:4
+    {
+        cinfo.comp_info[0].h_samp_factor = 1;
+        cinfo.comp_info[0].v_samp_factor = 1;
     }
-    catch (const css::uno::RuntimeException&)
+    else if (aChromaSubsampling == 2) // YUV 4:2:2
     {
-        return false;
+        cinfo.comp_info[0].h_samp_factor = 2;
+        cinfo.comp_info[0].v_samp_factor = 1;
     }
-    return true;
-}
-
-void Transform(void* pInputStream, void* pOutputStream, long nAngle)
-{
-    try
+    else if (aChromaSubsampling == 3) // YUV 4:2:0
     {
-        jpeg_transform_info aTransformOption;
-        JCOPY_OPTION        aCopyOption = JCOPYOPT_ALL;
+        cinfo.comp_info[0].h_samp_factor = 2;
+        cinfo.comp_info[0].v_samp_factor = 2;
+    }
 
-        jpeg_decompress_struct   aSourceInfo;
-        jpeg_compress_struct     aDestinationInfo;
-        jpeg_error_mgr           aSourceError;
-        jpeg_error_mgr           aDestinationError;
+    jpeg_start_compress( &cinfo, TRUE );
 
-        jvirt_barray_ptr* aSourceCoefArrays      = nullptr;
-        jvirt_barray_ptr* aDestinationCoefArrays = nullptr;
+    for( nY = 0; nY < nHeight; nY++ )
+    {
+        pScanline = pJPEGWriter->GetScanline( nY );
 
-        aTransformOption.force_grayscale = FALSE;
-        aTransformOption.trim            = FALSE;
-        aTransformOption.perfect         = FALSE;
-        aTransformOption.crop            = FALSE;
+        if( pScanline )
+        {
+            jpeg_write_scanlines( &cinfo, reinterpret_cast<JSAMPARRAY>(&pScanline), 1 );
+        }
 
-        // Angle to transform option
-        // 90 Clockwise = 270 Counterclockwise
-        switch (nAngle)
+        if( status.is() )
         {
-            case 2700:
-                aTransformOption.transform  = JXFORM_ROT_90;
-                break;
-            case 1800:
-                aTransformOption.transform  = JXFORM_ROT_180;
-                break;
-            case 900:
-                aTransformOption.transform  = JXFORM_ROT_270;
-                break;
-            default:
-                aTransformOption.transform  = JXFORM_NONE;
+            status->setValue( nY * 100L / nHeight );
         }
+    }
 
-        // Decompression
-        aSourceInfo.err                 = jpeg_std_error(&aSourceError);
-        aSourceInfo.err->error_exit     = errorExit;
-        aSourceInfo.err->output_message = outputMessage;
+    jpeg_finish_compress(&cinfo);
 
-        // Compression
-        aDestinationInfo.err                 = jpeg_std_error(&aDestinationError);
-        aDestinationInfo.err->error_exit     = errorExit;
-        aDestinationInfo.err->output_message = outputMessage;
+    return true;
+}
+
+void Transform(void* pInputStream, void* pOutputStream, long nAngle)
+{
+    jpeg_transform_info aTransformOption;
+    JCOPY_OPTION        aCopyOption = JCOPYOPT_ALL;
 
-        aDestinationInfo.optimize_coding = TRUE;
+    jpeg_decompress_struct   aSourceInfo;
+    jpeg_compress_struct     aDestinationInfo;
+    ErrorManagerStruct       aSourceError;
+    ErrorManagerStruct       aDestinationError;
 
-        jpeg_create_decompress(&aSourceInfo);
-        JpegDecompressOwner aDecompressOwner(aSourceInfo);
-        jpeg_create_compress(&aDestinationInfo);
-        JpegCompressOwner aCompressOwner(aDestinationInfo);
+    jvirt_barray_ptr* aSourceCoefArrays      = nullptr;
+    jvirt_barray_ptr* aDestinationCoefArrays = nullptr;
 
-        jpeg_svstream_src (&aSourceInfo, pInputStream);
+    aTransformOption.force_grayscale = FALSE;
+    aTransformOption.trim            = FALSE;
+    aTransformOption.perfect         = FALSE;
+    aTransformOption.crop            = FALSE;
 
-        jcopy_markers_setup(&aSourceInfo, aCopyOption);
-        jpeg_read_header(&aSourceInfo, TRUE);
-        jtransform_request_workspace(&aSourceInfo, &aTransformOption);
+    // Angle to transform option
+    // 90 Clockwise = 270 Counterclockwise
+    switch (nAngle)
+    {
+        case 2700:
+            aTransformOption.transform  = JXFORM_ROT_90;
+            break;
+        case 1800:
+            aTransformOption.transform  = JXFORM_ROT_180;
+            break;
+        case 900:
+            aTransformOption.transform  = JXFORM_ROT_270;
+            break;
+        default:
+            aTransformOption.transform  = JXFORM_NONE;
+    }
 
-        aSourceCoefArrays = jpeg_read_coefficients(&aSourceInfo);
-        jpeg_copy_critical_parameters(&aSourceInfo, &aDestinationInfo);
+    // Decompression
+    aSourceInfo.err                 = jpeg_std_error(&aSourceError.pub);
+    aSourceInfo.err->error_exit     = errorExit;
+    aSourceInfo.err->output_message = outputMessage;
 
-        aDestinationCoefArrays = jtransform_adjust_parameters(&aSourceInfo, &aDestinationInfo, aSourceCoefArrays, &aTransformOption);
-        jpeg_svstream_dest (&aDestinationInfo, pOutputStream);
+    // Compression
+    aDestinationInfo.err                 = jpeg_std_error(&aDestinationError.pub);
+    aDestinationInfo.err->error_exit     = errorExit;
+    aDestinationInfo.err->output_message = outputMessage;
 
-        // Compute optimal Huffman coding tables instead of precomputed tables
-        aDestinationInfo.optimize_coding = TRUE;
-        jpeg_write_coefficients(&aDestinationInfo, aDestinationCoefArrays);
-        jcopy_markers_execute(&aSourceInfo, &aDestinationInfo, aCopyOption);
-        jtransform_execute_transformation(&aSourceInfo, &aDestinationInfo, aSourceCoefArrays, &aTransformOption);
+    aDestinationInfo.optimize_coding = TRUE;
 
-        jpeg_finish_compress(&aDestinationInfo);
+    JpegDecompressOwner aDecompressOwner;
+    JpegCompressOwner aCompressOwner;
 
-        jpeg_finish_decompress(&aSourceInfo);
-    }
-    catch (const css::uno::RuntimeException&)
+    if (setjmp(aSourceError.setjmp_buffer) || setjmp(aDestinationError.setjmp_buffer))
     {
+        jpeg_destroy_decompress(&aSourceInfo);
+        jpeg_destroy_compress(&aDestinationInfo);
+        return;
     }
+
+    jpeg_create_decompress(&aSourceInfo);
+    aDecompressOwner.set(&aSourceInfo);
+    jpeg_create_compress(&aDestinationInfo);
+    aCompressOwner.set(&aDestinationInfo);
+
+    jpeg_svstream_src (&aSourceInfo, pInputStream);
+
+    jcopy_markers_setup(&aSourceInfo, aCopyOption);
+    jpeg_read_header(&aSourceInfo, TRUE);
+    jtransform_request_workspace(&aSourceInfo, &aTransformOption);
+
+    aSourceCoefArrays = jpeg_read_coefficients(&aSourceInfo);
+    jpeg_copy_critical_parameters(&aSourceInfo, &aDestinationInfo);
+
+    aDestinationCoefArrays = jtransform_adjust_parameters(&aSourceInfo, &aDestinationInfo, aSourceCoefArrays, &aTransformOption);
+    jpeg_svstream_dest (&aDestinationInfo, pOutputStream);
+
+    // Compute optimal Huffman coding tables instead of precomputed tables
+    aDestinationInfo.optimize_coding = TRUE;
+    jpeg_write_coefficients(&aDestinationInfo, aDestinationCoefArrays);
+    jcopy_markers_execute(&aSourceInfo, &aDestinationInfo, aCopyOption);
+    jtransform_execute_transformation(&aSourceInfo, &aDestinationInfo, aSourceCoefArrays, &aTransformOption);
+
+    jpeg_finish_compress(&aDestinationInfo);
+
+    jpeg_finish_decompress(&aSourceInfo);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list