vcl/inc/pdf/pdfwriter_impl.hxx    |    5 
 vcl/source/gdi/pdfwriter_impl.cxx |  210 ++++++++++++++++++++++++--------------
 2 files changed, 138 insertions(+), 77 deletions(-)

New commits:
commit 6fed871be7c444d35fcedcc037fa89e71a4b284c
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Sat Jan 25 22:02:26 2025 +0200
Commit:     Noel Grandin <noelgran...@gmail.com>
CommitDate: Sun Jan 26 12:44:57 2025 +0100

    simplify writeBitmapObject
    
    by splitting into two methods. The previous recursive nature
    and plethora of conditionals made following the logic impossible.
    
    Change-Id: I1a9a5fa592c00b65bd8308ec33ba7df5cb7fb26f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180752
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Tested-by: Jenkins

diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx
index 636973222e8d..1500ecba0e1d 100644
--- a/vcl/inc/pdf/pdfwriter_impl.hxx
+++ b/vcl/inc/pdf/pdfwriter_impl.hxx
@@ -892,7 +892,10 @@ private:
     /* writes an XObject of type image, may create
        a second for the mask
      */
-    bool writeBitmapObject( const BitmapEmit& rObject, bool bMask = false );
+    bool writeBitmapObject( const BitmapEmit& rObject );
+    /* writes an XObject of type mask image
+     */
+    bool writeBitmapMaskObject( const BitmapEmit& rObject );
 
     void writeJPG( const JPGEmit& rEmit );
     /// Writes the form XObject proxy for the image.
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index c66370c31fe5..f88de484f126 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -9190,7 +9190,7 @@ void PDFWriterImpl::writeJPG( const JPGEmit& rObject )
         if( aAlpha.hasAlpha() )
             aAlpha.Invert();
         aEmit.m_aBitmap = BitmapEx( rObject.m_aAlphaMask.GetBitmap(), aAlpha );
-        writeBitmapObject( aEmit, true );
+        writeBitmapMaskObject( aEmit );
     }
 
     writeReferenceXObject(rObject.m_aReferenceXObject);
@@ -9611,7 +9611,7 @@ void 
PDFWriterImpl::mergeAnnotationsFromExternalPage(filter::PDFObjectElement* p
 
 }
 
-bool PDFWriterImpl::writeBitmapObject( const BitmapEmit& rObject, bool bMask )
+bool PDFWriterImpl::writeBitmapObject( const BitmapEmit& rObject )
 {
     if (rObject.m_aReferenceXObject.hasExternalPDFData() && 
!m_aContext.UseReferenceXObject)
     {
@@ -9622,35 +9622,13 @@ bool PDFWriterImpl::writeBitmapObject( const 
BitmapEmit& rObject, bool bMask )
     if (!updateObject(rObject.m_nObject))
         return false;
 
-    Bitmap  aBitmap;
     bool    bWriteMask = false;
-    if( ! bMask )
+    Bitmap  aBitmap = rObject.m_aBitmap.GetBitmap();
+    if( rObject.m_aBitmap.IsAlpha() )
     {
-        aBitmap = rObject.m_aBitmap.GetBitmap();
-        if( rObject.m_aBitmap.IsAlpha() )
-        {
-            if( m_aContext.Version >= PDFWriter::PDFVersion::PDF_1_4 )
-                bWriteMask = true;
-            // else draw without alpha channel
-        }
-    }
-    else
-    {
-        if( m_aContext.Version < PDFWriter::PDFVersion::PDF_1_4 || ! 
rObject.m_aBitmap.IsAlpha() )
-        {
-            if( rObject.m_aBitmap.IsAlpha() )
-            {
-                aBitmap = rObject.m_aBitmap.GetAlphaMask().GetBitmap();
-                aBitmap.Convert( BmpConversion::N1BitThreshold );
-                SAL_WARN_IF(aBitmap.getPixelFormat() != 
vcl::PixelFormat::N8_BPP, "vcl.pdfwriter", "mask conversion failed" );
-            }
-        }
-        else if (aBitmap.getPixelFormat() != vcl::PixelFormat::N8_BPP)
-        {
-            aBitmap = rObject.m_aBitmap.GetAlphaMask().GetBitmap();
-            aBitmap.Convert( BmpConversion::N8BitGreys );
-            SAL_WARN_IF(aBitmap.getPixelFormat() != vcl::PixelFormat::N8_BPP, 
"vcl.pdfwriter", "alpha mask conversion failed" );
-        }
+        if( m_aContext.Version >= PDFWriter::PDFVersion::PDF_1_4 )
+            bWriteMask = true;
+        // else draw without alpha channel
     }
 
     BitmapScopedReadAccess pAccess(aBitmap);
@@ -9705,64 +9683,53 @@ bool PDFWriterImpl::writeBitmapObject( const 
BitmapEmit& rObject, bool bMask )
             aLine.append( ">>
" );
         }
     }
-    if( ! bMask )
+    aLine.append( "/ColorSpace" );
+    if( bTrueColor )
+        aLine.append( "/DeviceRGB
" );
+    else
     {
-        aLine.append( "/ColorSpace" );
-        if( bTrueColor )
-            aLine.append( "/DeviceRGB
" );
-        else
-        {
-            aLine.append( "[ /Indexed/DeviceRGB " );
-            aLine.append( 
static_cast<sal_Int32>(pAccess->GetPaletteEntryCount()-1) );
-            aLine.append( "
<" );
-            if (m_aContext.Encryption.canEncrypt())
+        aLine.append( "[ /Indexed/DeviceRGB " );
+        aLine.append( 
static_cast<sal_Int32>(pAccess->GetPaletteEntryCount()-1) );
+        aLine.append( "
<" );
+        if (m_aContext.Encryption.canEncrypt())
+        {
+            enableStringEncryption(rObject.m_nObject);
+            //check encryption buffer size
+            m_vEncryptionBuffer.resize(pAccess->GetPaletteEntryCount()*3);
+            int nChar = 0;
+            //fill the encryption buffer
+            for( sal_uInt16 i = 0; i < pAccess->GetPaletteEntryCount(); i++ )
             {
-                enableStringEncryption(rObject.m_nObject);
-                //check encryption buffer size
-                m_vEncryptionBuffer.resize(pAccess->GetPaletteEntryCount()*3);
-                int nChar = 0;
-                //fill the encryption buffer
-                for( sal_uInt16 i = 0; i < pAccess->GetPaletteEntryCount(); 
i++ )
-                {
-                    const BitmapColor& rColor = pAccess->GetPaletteColor( i );
-                    m_vEncryptionBuffer[nChar++] = rColor.GetRed();
-                    m_vEncryptionBuffer[nChar++] = rColor.GetGreen();
-                    m_vEncryptionBuffer[nChar++] = rColor.GetBlue();
-                }
-                //encrypt the colorspace lookup table
-                std::vector<sal_uInt8> aOutputBuffer(nChar);
-                m_pPDFEncryptor->encrypt(m_vEncryptionBuffer.data(), nChar, 
aOutputBuffer, nChar);
-                //now queue the data for output
-                COSWriter::appendHexArray(aOutputBuffer.data(), 
aOutputBuffer.size(), aLine);
+                const BitmapColor& rColor = pAccess->GetPaletteColor( i );
+                m_vEncryptionBuffer[nChar++] = rColor.GetRed();
+                m_vEncryptionBuffer[nChar++] = rColor.GetGreen();
+                m_vEncryptionBuffer[nChar++] = rColor.GetBlue();
             }
-            else //no encryption requested (PDF/A-1a program flow drops here)
+            //encrypt the colorspace lookup table
+            std::vector<sal_uInt8> aOutputBuffer(nChar);
+            m_pPDFEncryptor->encrypt(m_vEncryptionBuffer.data(), nChar, 
aOutputBuffer, nChar);
+            //now queue the data for output
+            COSWriter::appendHexArray(aOutputBuffer.data(), 
aOutputBuffer.size(), aLine);
+        }
+        else //no encryption requested (PDF/A-1a program flow drops here)
+        {
+            for( sal_uInt16 i = 0; i < pAccess->GetPaletteEntryCount(); i++ )
             {
-                for( sal_uInt16 i = 0; i < pAccess->GetPaletteEntryCount(); 
i++ )
-                {
-                    const BitmapColor& rColor = pAccess->GetPaletteColor( i );
-                    COSWriter::appendHex( rColor.GetRed(), aLine );
-                    COSWriter::appendHex( rColor.GetGreen(), aLine );
-                    COSWriter::appendHex( rColor.GetBlue(), aLine );
-                }
+                const BitmapColor& rColor = pAccess->GetPaletteColor( i );
+                COSWriter::appendHex( rColor.GetRed(), aLine );
+                COSWriter::appendHex( rColor.GetGreen(), aLine );
+                COSWriter::appendHex( rColor.GetBlue(), aLine );
             }
-            aLine.append( ">
]
" );
         }
-    }
-    else
-    {
-        aLine.append( "/ColorSpace/DeviceGray
"
-                      "/Decode [ 1 0 ]
" );
+        aLine.append( ">
]
" );
     }
 
-    if (!bMask && !m_bIsPDF_A1)
+    if (!m_bIsPDF_A1)
     {
         if( bWriteMask )
         {
             nMaskObject = createObject();
-            if (rObject.m_aBitmap.IsAlpha())
-                aLine.append( "/SMask " );
-            else
-                aLine.append( "/Mask " );
+            aLine.append( "/SMask " );
             aLine.append( nMaskObject );
             aLine.append( " 0 R
" );
         }
@@ -9836,8 +9803,99 @@ bool PDFWriterImpl::writeBitmapObject( const BitmapEmit& 
rObject, bool bMask )
         BitmapEmit aEmit;
         aEmit.m_nObject             = nMaskObject;
         aEmit.m_aBitmap             = rObject.m_aBitmap;
-        return writeBitmapObject( aEmit, true );
+        return writeBitmapMaskObject( aEmit );
+    }
+
+    writeReferenceXObject(rObject.m_aReferenceXObject);
+
+    return true;
+}
+
+bool PDFWriterImpl::writeBitmapMaskObject( const BitmapEmit& rObject )
+{
+    assert( rObject.m_aBitmap.IsAlpha() );
+    assert( rObject.m_aBitmap.GetAlphaMask().GetBitmap().getPixelFormat() == 
vcl::PixelFormat::N8_BPP );
+
+    if (rObject.m_aReferenceXObject.hasExternalPDFData() && 
!m_aContext.UseReferenceXObject)
+    {
+        writeReferenceXObject(rObject.m_aReferenceXObject);
+        return true;
+    }
+
+    if (!updateObject(rObject.m_nObject))
+        return false;
+
+    Bitmap  aBitmap;
+    if( m_aContext.Version < PDFWriter::PDFVersion::PDF_1_4 )
+    {
+        aBitmap = rObject.m_aBitmap.GetAlphaMask().GetBitmap();
+        aBitmap.Convert( BmpConversion::N1BitThreshold );
+    }
+    else
+    {
+        aBitmap = rObject.m_aBitmap.GetAlphaMask().GetBitmap();
+    }
+
+    const sal_Int32 nBitsPerComponent = 8;
+
+    sal_Int32 nStreamLengthObject   = createObject();
+
+    if (g_bDebugDisableCompression)
+    {
+        emitComment( "PDFWriterImpl::writeBitmapObject" );
+    }
+    OStringBuffer aLine(1024);
+    aLine.append( rObject.m_nObject );
+    aLine.append( " 0 obj
"
+                  "<</Type/XObject/Subtype/Image/Width " );
+    aLine.append( static_cast<sal_Int32>(aBitmap.GetSizePixel().Width()) );
+    aLine.append( "/Height " );
+    aLine.append( static_cast<sal_Int32>(aBitmap.GetSizePixel().Height()) );
+    aLine.append( "/BitsPerComponent " );
+    aLine.append( nBitsPerComponent );
+    aLine.append( "/Length " );
+    aLine.append( nStreamLengthObject );
+    aLine.append( " 0 R
" );
+    if (!g_bDebugDisableCompression)
+    {
+        aLine.append( "/Filter/FlateDecode" );
+    }
+    aLine.append( "/ColorSpace/DeviceGray
"
+                  "/Decode [ 1 0 ]
" );
+
+    aLine.append( ">>
"
+                  "stream
" );
+    if (!writeBuffer(aLine)) return false;
+    sal_uInt64 nStartPos = 0;
+    if (osl::File::E_None != m_aFile.getPos(nStartPos))
+        return false;
+
+    checkAndEnableStreamEncryption( rObject.m_nObject );
+    beginCompression();
+    BitmapScopedReadAccess pAccess(aBitmap);
+    //With PDF bitmaps, each row is padded to a BYTE boundary (multiple of 8 
bits).
+    const int nScanLineBytes = ((pAccess->GetBitCount() * pAccess->Width()) + 
7U) / 8U;
+    for( tools::Long i = 0; i < pAccess->Height(); i++ )
+    {
+        if (!writeBufferBytes(pAccess->GetScanline(i), nScanLineBytes))
+            return false;
     }
+    endCompression();
+    disableStreamEncryption();
+
+    sal_uInt64 nEndPos = 0;
+    if (osl::File::E_None != m_aFile.getPos(nEndPos))
+        return false;
+    aLine.setLength( 0 );
+    aLine.append( "
endstream
endobj

" );
+    if (!writeBuffer(aLine)) return false;
+    if (!updateObject(nStreamLengthObject)) return false;
+    aLine.setLength( 0 );
+    aLine.append( nStreamLengthObject );
+    aLine.append( " 0 obj
" );
+    aLine.append( static_cast<sal_Int64>(nEndPos-nStartPos) );
+    aLine.append( "
endobj

" );
+    if (!writeBuffer(aLine)) return false;
 
     writeReferenceXObject(rObject.m_aReferenceXObject);
 

Reply via email to