LCOV - code coverage report
Current view: top level - filter/source/graphicfilter/ipcx - ipcx.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 120 181 66.3 %
Date: 2015-06-13 12:38:46 Functions: 7 7 100.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             : 
      21             : #include <vcl/graph.hxx>
      22             : #include <vcl/bmpacc.hxx>
      23             : 
      24             : class FilterConfigItem;
      25             : 
      26             : //============================ PCXReader ==================================
      27             : 
      28             : class PCXReader {
      29             : 
      30             : private:
      31             : 
      32             :     SvStream& m_rPCX;               // the PCX file to read
      33             : 
      34             :     Bitmap              aBmp;
      35             :     sal_uInt8           nVersion;           // PCX-Version
      36             :     sal_uInt8           nEncoding;          // compression type
      37             :     sal_uLong           nBitsPerPlanePix;   // bits per plane per pixel
      38             :     sal_uLong           nPlanes;            // no of planes
      39             :     sal_uLong           nBytesPerPlaneLin;  // bytes per plane line
      40             :     sal_uInt16          nPaletteInfo;
      41             : 
      42             :     sal_uLong           nWidth, nHeight;    // dimension in pixel
      43             :     sal_uInt16          nResX, nResY;       // resolution in pixel per inch oder 0,0
      44             :     sal_uInt16          nDestBitsPerPixel;  // bits per pixel in destination bitmap 1,4,8 or 24
      45             :     sal_uInt8*          pPalette;
      46             :     bool                nStatus;            // from now on do not read status from stream ( SJ )
      47             : 
      48             : 
      49             :     void                ImplReadBody(BitmapWriteAccess * pAcc);
      50             :     void                ImplReadPalette( sal_uLong nCol );
      51             :     void                ImplReadHeader();
      52             : 
      53             : public:
      54             :                         PCXReader(SvStream &rStream);
      55             :                         ~PCXReader();
      56             :     bool                ReadPCX(Graphic & rGraphic );
      57             :                         // Reads a PCX file from the stream and fills the GDIMetaFile
      58             : };
      59             : 
      60             : //=================== methods of PCXReader ==============================
      61             : 
      62           5 : PCXReader::PCXReader(SvStream &rStream)
      63             :     : m_rPCX(rStream)
      64             :     , nVersion(0)
      65             :     , nEncoding(0)
      66             :     , nBitsPerPlanePix(0)
      67             :     , nPlanes(0)
      68             :     , nBytesPerPlaneLin(0)
      69             :     , nPaletteInfo(0)
      70             :     , nWidth(0)
      71             :     , nHeight(0)
      72             :     , nResX(0)
      73             :     , nResY(0)
      74             :     , nDestBitsPerPixel(0)
      75           5 :     , nStatus(false)
      76             : {
      77           5 :     pPalette = new sal_uInt8[ 768 ];
      78           5 : }
      79             : 
      80          10 : PCXReader::~PCXReader()
      81             : {
      82           5 :     delete[] pPalette;
      83           5 : }
      84             : 
      85           5 : bool PCXReader::ReadPCX(Graphic & rGraphic)
      86             : {
      87           5 :     if ( m_rPCX.GetError() )
      88           0 :         return false;
      89             : 
      90           5 :     m_rPCX.SetEndian(SvStreamEndian::LITTLE);
      91             : 
      92             :     // read header:
      93             : 
      94           5 :     nStatus = true;
      95             : 
      96           5 :     ImplReadHeader();
      97             : 
      98             :     // Write BMP header and conditionally (maybe invalid for now) color palette:
      99           5 :     if ( nStatus )
     100             :     {
     101           2 :         aBmp = Bitmap( Size( nWidth, nHeight ), nDestBitsPerPixel );
     102           2 :         Bitmap::ScopedWriteAccess pAcc(aBmp);
     103           2 :         if ( pAcc == 0 )
     104           0 :             return false;
     105             : 
     106           2 :         if ( nDestBitsPerPixel <= 8 )
     107             :         {
     108           1 :             sal_uInt16 nColors = 1 << nDestBitsPerPixel;
     109           1 :             sal_uInt8* pPal = pPalette;
     110           1 :             pAcc->SetPaletteEntryCount( nColors );
     111         257 :             for ( sal_uInt16 i = 0; i < nColors; i++, pPal += 3 )
     112             :             {
     113         256 :                 pAcc->SetPaletteColor( i, BitmapColor ( pPal[ 0 ], pPal[ 1 ], pPal[ 2 ] ) );
     114             :             }
     115             :         }
     116             :         // read bitmap data
     117           2 :         ImplReadBody(pAcc.get());
     118             : 
     119             :         // If an extended color palette exists at the end of the file, then read it and
     120             :         // and write again in palette:
     121           2 :         if ( nDestBitsPerPixel == 8 && nStatus )
     122             :         {
     123           0 :             sal_uInt8* pPal = pPalette;
     124           0 :             m_rPCX.SeekRel(1);
     125           0 :             ImplReadPalette(256);
     126           0 :             pAcc->SetPaletteEntryCount( 256 );
     127           0 :             for ( sal_uInt16 i = 0; i < 256; i++, pPal += 3 )
     128             :             {
     129           0 :                 pAcc->SetPaletteColor( i, BitmapColor ( pPal[ 0 ], pPal[ 1 ], pPal[ 2 ] ) );
     130             :             }
     131             :         }
     132             :     /*
     133             :         // set resolution:
     134             :         if (nResX!=0 && nResY!=0) {
     135             :             MapMode aMapMode(MAP_INCH,Point(0,0),Fraction(1,nResX),Fraction(1,nResY));
     136             :             rBitmap.SetPrefMapMode(aMapMode);
     137             :             rBitmap.SetPrefSize(Size(nWidth,nHeight));
     138             :         }
     139           2 :     */  if ( nStatus )
     140             :         {
     141           1 :             rGraphic = aBmp;
     142           1 :             return true;
     143           1 :         }
     144             :     }
     145           4 :     return false;
     146             : }
     147             : 
     148           5 : void PCXReader::ImplReadHeader()
     149             : {
     150           5 :     sal_uInt8 nbyte(0);
     151           5 :     m_rPCX.ReadUChar( nbyte ).ReadUChar( nVersion ).ReadUChar( nEncoding );
     152           5 :     if ( nbyte!=0x0a || (nVersion != 0 && nVersion != 2 && nVersion != 3 && nVersion != 5) || nEncoding > 1 )
     153             :     {
     154           0 :         nStatus = false;
     155           3 :         return;
     156             :     }
     157             : 
     158           5 :     nbyte = 0;
     159           5 :     m_rPCX.ReadUChar( nbyte ); nBitsPerPlanePix = (sal_uLong)nbyte;
     160           5 :     sal_uInt16 nMinX(0),nMinY(0),nMaxX(0),nMaxY(0);
     161           5 :     m_rPCX.ReadUInt16( nMinX ).ReadUInt16( nMinY ).ReadUInt16( nMaxX ).ReadUInt16( nMaxY );
     162             : 
     163           5 :     if ((nMinX > nMaxX) || (nMinY > nMaxY))
     164             :     {
     165           0 :         nStatus = false;
     166           0 :         return;
     167             :     }
     168             : 
     169           5 :     nWidth = nMaxX-nMinX+1;
     170           5 :     nHeight = nMaxY-nMinY+1;
     171             : 
     172           5 :     m_rPCX.ReadUInt16( nResX );
     173           5 :     m_rPCX.ReadUInt16( nResY );
     174           5 :     if ( nResX >= nWidth || nResY >= nHeight || ( nResX != nResY ) )
     175           4 :         nResX = nResY = 0;
     176             : 
     177           5 :     ImplReadPalette( 16 );
     178             : 
     179           5 :     m_rPCX.SeekRel( 1 );
     180           5 :     nbyte = 0;
     181           5 :     m_rPCX.ReadUChar( nbyte );   nPlanes = (sal_uLong)nbyte;
     182           5 :     sal_uInt16 nushort(0);
     183           5 :     m_rPCX.ReadUInt16( nushort ); nBytesPerPlaneLin = (sal_uLong)nushort;
     184           5 :     m_rPCX.ReadUInt16( nPaletteInfo );
     185             : 
     186           5 :     m_rPCX.SeekRel( 58 );
     187             : 
     188           5 :     nDestBitsPerPixel = (sal_uInt16)( nBitsPerPlanePix * nPlanes );
     189           5 :     if (nDestBitsPerPixel == 2 || nDestBitsPerPixel == 3) nDestBitsPerPixel = 4;
     190             : 
     191           5 :     if ( ( nDestBitsPerPixel != 1 && nDestBitsPerPixel != 4 && nDestBitsPerPixel != 8 && nDestBitsPerPixel != 24 )
     192           4 :         || nPlanes > 4 || nBytesPerPlaneLin < ( ( nWidth * nBitsPerPlanePix+7 ) >> 3 ) )
     193             :     {
     194           3 :         nStatus = false;
     195           3 :         return;
     196             :     }
     197             : 
     198             :     // If the bitmap has only 2 colors, the palatte is most often invalid and it is always(?)
     199             :     // a black and white image:
     200           2 :     if ( nPlanes == 1 && nBitsPerPlanePix == 1 )
     201             :     {
     202           0 :         pPalette[ 0 ] = pPalette[ 1 ] = pPalette[ 2 ] = 0x00;
     203           0 :         pPalette[ 3 ] = pPalette[ 4 ] = pPalette[ 5 ] = 0xff;
     204             :     }
     205             : }
     206             : 
     207           2 : void PCXReader::ImplReadBody(BitmapWriteAccess * pAcc)
     208             : {
     209             :     sal_uInt8   *pPlane[ 4 ], * pDest;
     210             :     sal_uLong   i, nx, ny, np, nCount, nPercent;
     211           2 :     sal_uLong   nLastPercent = 0;
     212           2 :     sal_uInt8   nDat = 0, nCol = 0;
     213             : 
     214             :     //sanity check there is enough data before trying allocation
     215           2 :     if (nBytesPerPlaneLin > m_rPCX.remainingSize() / nPlanes)
     216             :     {
     217           1 :         nStatus = false;
     218           3 :         return;
     219             :     }
     220             : 
     221           4 :     for( np = 0; np < nPlanes; np++ )
     222           3 :         pPlane[ np ] = new sal_uInt8[ nBytesPerPlaneLin ];
     223             : 
     224           1 :     nCount = 0;
     225         195 :     for ( ny = 0; ny < nHeight; ny++ )
     226             :     {
     227         194 :         if (m_rPCX.GetError() || m_rPCX.IsEof())
     228             :         {
     229           0 :             nStatus = false;
     230           0 :             break;
     231             :         }
     232         194 :         nPercent = ny * 60 / nHeight + 10;
     233         194 :         if ( ny == 0 || nLastPercent + 4 <= nPercent )
     234             :         {
     235          15 :             nLastPercent = nPercent;
     236             :         }
     237         776 :         for ( np = 0; np < nPlanes; np++)
     238             :         {
     239         582 :             if ( nEncoding == 0)
     240           0 :                 m_rPCX.Read( static_cast<void *>(pPlane[ np ]), nBytesPerPlaneLin );
     241             :             else
     242             :             {
     243         582 :                 pDest = pPlane[ np ];
     244         582 :                 nx = nBytesPerPlaneLin;
     245        1164 :                 while ( nCount > 0 && nx > 0)
     246             :                 {
     247           0 :                     *(pDest++) = nDat;
     248           0 :                     nx--;
     249           0 :                     nCount--;
     250             :                 }
     251       39402 :                 while ( nx > 0 )
     252             :                 {
     253       38286 :                     m_rPCX.ReadUChar( nDat );
     254       38286 :                     if ( ( nDat & 0xc0 ) == 0xc0 )
     255             :                     {
     256       20182 :                         nCount =( (sal_uLong)nDat ) & 0x003f;
     257       20182 :                         m_rPCX.ReadUChar( nDat );
     258       20182 :                         if ( nCount < nx )
     259             :                         {
     260       20134 :                             nx -= nCount;
     261      364578 :                             while ( nCount > 0)
     262             :                             {
     263      324310 :                                 *(pDest++) = nDat;
     264      324310 :                                 nCount--;
     265             :                             }
     266             :                         }
     267             :                         else
     268             :                         {
     269          48 :                             nCount -= nx;
     270         384 :                             do
     271             :                             {
     272         384 :                                 *(pDest++) = nDat;
     273         384 :                                 nx--;
     274             :                             }
     275             :                             while ( nx > 0 );
     276          48 :                             break;
     277             :                         }
     278             :                     }
     279             :                     else
     280             :                     {
     281       18104 :                         *(pDest++) = nDat;
     282       18104 :                         nx--;
     283             :                     }
     284             :                 }
     285             :             }
     286             :         }
     287         194 :         sal_uInt8 *pSource1 = pPlane[ 0 ];
     288         194 :         sal_uInt8 *pSource2 = pPlane[ 1 ];
     289         194 :         sal_uInt8 *pSource3 = pPlane[ 2 ];
     290         194 :         sal_uInt8 *pSource4 = pPlane[ 3 ];
     291         194 :         switch ( nBitsPerPlanePix + ( nPlanes << 8 ) )
     292             :         {
     293             :             // 2 colors
     294             :             case 0x101 :
     295           0 :                 for ( i = 0; i < nWidth; i++ )
     296             :                 {
     297           0 :                     sal_uLong nShift = ( i & 7 ) ^ 7;
     298           0 :                     if ( nShift == 0 )
     299           0 :                         pAcc->SetPixelIndex( ny, i, *(pSource1++) & 1 );
     300             :                     else
     301           0 :                         pAcc->SetPixelIndex( ny, i, (*pSource1 >> nShift ) & 1 );
     302             :                 }
     303           0 :                 break;
     304             :             // 4 colors
     305             :             case 0x102 :
     306           0 :                 for ( i = 0; i < nWidth; i++ )
     307             :                 {
     308           0 :                     switch( i & 3 )
     309             :                     {
     310             :                         case 0 :
     311           0 :                             nCol = *pSource1 >> 6;
     312           0 :                             break;
     313             :                         case 1 :
     314           0 :                             nCol = ( *pSource1 >> 4 ) & 0x03 ;
     315           0 :                             break;
     316             :                         case 2 :
     317           0 :                             nCol = ( *pSource1 >> 2 ) & 0x03;
     318           0 :                             break;
     319             :                         case 3 :
     320           0 :                             nCol = ( *pSource1++ ) & 0x03;
     321           0 :                             break;
     322             :                     }
     323           0 :                     pAcc->SetPixelIndex( ny, i, nCol );
     324             :                 }
     325           0 :                 break;
     326             :             // 256 colors
     327             :             case 0x108 :
     328           0 :                 for ( i = 0; i < nWidth; i++ )
     329             :                 {
     330           0 :                     pAcc->SetPixelIndex( ny, i, *pSource1++ );
     331             :                 }
     332           0 :                 break;
     333             :             // 8 colors
     334             :             case 0x301 :
     335           0 :                 for ( i = 0; i < nWidth; i++ )
     336             :                 {
     337           0 :                     sal_uLong nShift = ( i & 7 ) ^ 7;
     338           0 :                     if ( nShift == 0 )
     339             :                     {
     340           0 :                         nCol = ( *pSource1++ & 1) + ( ( *pSource2++ << 1 ) & 2 ) + ( ( *pSource3++ << 2 ) & 4 );
     341           0 :                         pAcc->SetPixelIndex( ny, i, nCol );
     342             :                     }
     343             :                     else
     344             :                     {
     345             :                         nCol = sal::static_int_cast< sal_uInt8 >(
     346           0 :                             ( ( *pSource1 >> nShift ) & 1)  + ( ( ( *pSource2 >> nShift ) << 1 ) & 2 ) +
     347           0 :                             ( ( ( *pSource3 >> nShift ) << 2 ) & 4 ));
     348           0 :                         pAcc->SetPixelIndex( ny, i, nCol );
     349             :                     }
     350             :                 }
     351           0 :                 break;
     352             :             // 16 colors
     353             :             case 0x401 :
     354           0 :                 for ( i = 0; i < nWidth; i++ )
     355             :                 {
     356           0 :                     sal_uLong nShift = ( i & 7 ) ^ 7;
     357           0 :                     if ( nShift == 0 )
     358             :                     {
     359           0 :                         nCol = ( *pSource1++ & 1) + ( ( *pSource2++ << 1 ) & 2 ) + ( ( *pSource3++ << 2 ) & 4 ) +
     360           0 :                             ( ( *pSource4++ << 3 ) & 8 );
     361           0 :                         pAcc->SetPixelIndex( ny, i, nCol );
     362             :                     }
     363             :                     else
     364             :                     {
     365             :                         nCol = sal::static_int_cast< sal_uInt8 >(
     366           0 :                             ( ( *pSource1 >> nShift ) & 1)  + ( ( ( *pSource2 >> nShift ) << 1 ) & 2 ) +
     367           0 :                             ( ( ( *pSource3 >> nShift ) << 2 ) & 4 ) + ( ( ( *pSource4 >> nShift ) << 3 ) & 8 ));
     368           0 :                         pAcc->SetPixelIndex( ny, i, nCol );
     369             :                     }
     370             :                 }
     371           0 :                 break;
     372             :             // 16m colors
     373             :             case 0x308 :
     374      114460 :                 for ( i = 0; i < nWidth; i++ )
     375             :                 {
     376      114266 :                     pAcc->SetPixel( ny, i, Color( *pSource1++, *pSource2++, *pSource3++ ) );
     377             : 
     378             :                 }
     379         194 :                 break;
     380             :             default :
     381           0 :                 nStatus = false;
     382           0 :                 break;
     383             :         }
     384             :     }
     385           4 :     for ( np = 0; np < nPlanes; np++ )
     386           3 :         delete[] pPlane[ np ];
     387             : }
     388             : 
     389           5 : void PCXReader::ImplReadPalette( sal_uLong nCol )
     390             : {
     391             :     sal_uInt8   r, g, b;
     392           5 :     sal_uInt8*  pPtr = pPalette;
     393          85 :     for ( sal_uLong i = 0; i < nCol; i++ )
     394             :     {
     395          80 :         m_rPCX.ReadUChar( r ).ReadUChar( g ).ReadUChar( b );
     396          80 :         *pPtr++ = r;
     397          80 :         *pPtr++ = g;
     398          80 :         *pPtr++ = b;
     399             :     }
     400           5 : }
     401             : 
     402             : //================== GraphicImport - the exported function ================
     403             : 
     404             : // this needs to be kept in sync with
     405             : // ImpFilterLibCacheEntry::GetImportFunction() from
     406             : // vcl/source/filter/graphicfilter.cxx
     407             : #if defined(DISABLE_DYNLOADING)
     408             : #define GraphicImport ipxGraphicImport
     409             : #endif
     410             : 
     411             : extern "C" SAL_DLLPUBLIC_EXPORT bool SAL_CALL
     412           5 : GraphicImport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* )
     413             : {
     414           5 :     PCXReader aPCXReader(rStream);
     415           5 :     bool nRetValue = aPCXReader.ReadPCX(rGraphic);
     416           5 :     if ( !nRetValue )
     417           4 :         rStream.SetError( SVSTREAM_FILEFORMAT_ERROR );
     418           5 :     return nRetValue;
     419             : }
     420             : 
     421             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11