| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svtools.hxx" |
| |
| #include <cstdio> |
| #include <csignal> |
| #include <vector> |
| #include <set> |
| #include <map> |
| #include <rtl/crc.h> |
| #include <tools/stream.hxx> |
| #include <tools/fsys.hxx> |
| #include <vcl/svapp.hxx> |
| #include <vcl/bitmap.hxx> |
| #include <vcl/bmpacc.hxx> |
| #include <vcl/pngread.hxx> |
| #include <vcl/dibtools.hxx> |
| #include "svl/solar.hrc" |
| |
| #define EXIT_NOERROR 0x00000000 |
| #define EXIT_INVALIDFILE 0x00000001 |
| #define EXIT_COMMONERROR 0x80000000 |
| |
| // ---------- |
| // - BmpSum - |
| // ---------- |
| |
| class BmpSum |
| { |
| private: |
| |
| sal_uInt32 cExitCode; |
| |
| sal_Bool GetCommandOption( const ::std::vector< String >& rArgs, const String& rSwitch, String& rSwitchParam ); |
| sal_Bool GetCommandOptions( const ::std::vector< String >& rArgs, const String& rSwitch, ::std::vector< String >& rSwitchParams ); |
| |
| void SetExitCode( sal_uInt8 cExit ) |
| { |
| if( ( EXIT_NOERROR == cExitCode ) || ( cExit != EXIT_NOERROR ) ) |
| cExitCode = cExit; |
| } |
| void ShowUsage(); |
| void Message( const String& rText, sal_uInt8 cExitCode ); |
| |
| sal_uInt64 GetCRC( const BitmapEx& rBmpEx ); |
| |
| void ProcessFile( const String& rBmpFileName ); |
| void ProcessFileList( const String& rInFileList, const String& rOutFileList, const String& rOutPath ); |
| |
| public: |
| // |
| BmpSum(); |
| ~BmpSum(); |
| |
| int Start( const ::std::vector< String >& rArgs ); |
| }; |
| |
| // ----------------------------------------------------------------------------- |
| |
| BmpSum::BmpSum() |
| { |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| BmpSum::~BmpSum() |
| { |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool BmpSum::GetCommandOption( const ::std::vector< String >& rArgs, const String& rSwitch, String& rParam ) |
| { |
| sal_Bool bRet = sal_False; |
| |
| for( int i = 0, nCount = rArgs.size(); ( i < nCount ) && !bRet; i++ ) |
| { |
| String aTestStr( '-' ); |
| |
| for( int n = 0; ( n < 2 ) && !bRet; n++ ) |
| { |
| aTestStr += rSwitch; |
| |
| if( aTestStr.CompareIgnoreCaseToAscii( rArgs[ i ] ) == COMPARE_EQUAL ) |
| { |
| bRet = sal_True; |
| |
| if( i < ( nCount - 1 ) ) |
| rParam = rArgs[ i + 1 ]; |
| else |
| rParam = String(); |
| } |
| |
| if( 0 == n ) |
| aTestStr = '/'; |
| } |
| } |
| |
| return bRet; |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| sal_Bool BmpSum::GetCommandOptions( const ::std::vector< String >& rArgs, const String& rSwitch, ::std::vector< String >& rParams ) |
| { |
| sal_Bool bRet = sal_False; |
| |
| for( int i = 0, nCount = rArgs.size(); ( i < nCount ); i++ ) |
| { |
| String aTestStr( '-' ); |
| |
| for( int n = 0; ( n < 2 ) && !bRet; n++ ) |
| { |
| aTestStr += rSwitch; |
| |
| if( aTestStr.CompareIgnoreCaseToAscii( rArgs[ i ] ) == COMPARE_EQUAL ) |
| { |
| if( i < ( nCount - 1 ) ) |
| rParams.push_back( rArgs[ i + 1 ] ); |
| else |
| rParams.push_back( String() ); |
| |
| break; |
| } |
| |
| if( 0 == n ) |
| aTestStr = '/'; |
| } |
| } |
| |
| return( rParams.size() > 0 ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| void BmpSum::Message( const String& rText, sal_uInt8 nExitCode ) |
| { |
| if( EXIT_NOERROR != nExitCode ) |
| SetExitCode( nExitCode ); |
| |
| ByteString aText( rText, RTL_TEXTENCODING_UTF8 ); |
| aText.Append( "\r\n" ); |
| fprintf( stderr, aText.GetBuffer() ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void BmpSum::ShowUsage() |
| { |
| Message( String( RTL_CONSTASCII_USTRINGPARAM( "Usage:" ) ), EXIT_NOERROR ); |
| Message( String( RTL_CONSTASCII_USTRINGPARAM( " bmpsum bmp_inputfile" ) ), EXIT_NOERROR ); |
| Message( String( RTL_CONSTASCII_USTRINGPARAM( " bmpsum -i input_filelist -o output_filelist [-p path_for_copied_bitmaps]" ) ), EXIT_NOERROR ); |
| Message( String( RTL_CONSTASCII_USTRINGPARAM( "Options:" ) ), EXIT_NOERROR ); |
| Message( String( RTL_CONSTASCII_USTRINGPARAM( "Examples:" ) ), EXIT_NOERROR ); |
| Message( String( RTL_CONSTASCII_USTRINGPARAM( " bmpsum /home/test.bmp" ) ), EXIT_NOERROR ); |
| Message( String( RTL_CONSTASCII_USTRINGPARAM( " bmpsum -i /home/inlist.txt -o /home/outlist.txt" ) ), EXIT_NOERROR ); |
| Message( String( RTL_CONSTASCII_USTRINGPARAM( " bmpsum -i /home/inlist.txt -o /home/outlist.txt -p /home/outpath" ) ), EXIT_NOERROR ); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| int BmpSum::Start( const ::std::vector< String >& rArgs ) |
| { |
| cExitCode = EXIT_NOERROR; |
| |
| if( rArgs.size() >= 1 ) |
| { |
| String aInFileList, aOutFileList, aOutPath; |
| |
| if( GetCommandOption( rArgs, 'i', aInFileList ) && |
| GetCommandOption( rArgs, 'o', aOutFileList ) ) |
| { |
| GetCommandOption( rArgs, 'p', aOutPath ); |
| ProcessFileList( aInFileList, aOutFileList, aOutPath ); |
| } |
| else |
| { |
| ProcessFile( rArgs[ 0 ] ); |
| } |
| } |
| else |
| { |
| ShowUsage(); |
| cExitCode = EXIT_COMMONERROR; |
| } |
| |
| return cExitCode; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| sal_uInt64 BmpSum::GetCRC( const BitmapEx& rBmpEx ) |
| { |
| Bitmap aBmp( rBmpEx.GetBitmap() ); |
| BitmapReadAccess* pRAcc = aBmp.AcquireReadAccess(); |
| AlphaMask aAlpha; |
| BitmapReadAccess* pAAcc = NULL; |
| sal_uInt64 nRet = 0; |
| sal_uInt32 nCrc = 0; |
| |
| if( rBmpEx.IsTransparent() ) |
| { |
| aAlpha = rBmpEx.GetAlpha(); |
| pAAcc = aAlpha.AcquireReadAccess(); |
| } |
| |
| if( pRAcc && pRAcc->Width() && pRAcc->Height() ) |
| { |
| SVBT32 aBT32; |
| |
| for( long nY = 0; nY < pRAcc->Height(); ++nY ) |
| { |
| for( long nX = 0; nX < pRAcc->Width(); ++nX ) |
| { |
| const BitmapColor aCol( pRAcc->GetColor( nY, nX ) ); |
| |
| UInt32ToSVBT32( aCol.GetRed(), aBT32 ); |
| nCrc = rtl_crc32( nCrc, aBT32, 4 ); |
| |
| UInt32ToSVBT32( aCol.GetGreen(), aBT32 ); |
| nCrc = rtl_crc32( nCrc, aBT32, 4 ); |
| |
| UInt32ToSVBT32( aCol.GetBlue(), aBT32 ); |
| nCrc = rtl_crc32( nCrc, aBT32, 4 ); |
| |
| if( pAAcc ) |
| { |
| const BitmapColor aMaskCol( pAAcc->GetColor( nY, nX ) ); |
| |
| UInt32ToSVBT32( aMaskCol.GetRed(), aBT32 ); |
| nCrc = rtl_crc32( nCrc, aBT32, 4 ); |
| |
| UInt32ToSVBT32( aMaskCol.GetGreen(), aBT32 ); |
| nCrc = rtl_crc32( nCrc, aBT32, 4 ); |
| |
| UInt32ToSVBT32( aMaskCol.GetBlue(), aBT32 ); |
| nCrc = rtl_crc32( nCrc, aBT32, 4 ); |
| } |
| } |
| } |
| |
| nRet = ( ( (sal_uInt64) pRAcc->Width() ) << 48 ) | |
| ( ( (sal_uInt64) pRAcc->Height() ) << 32 ) | |
| ( (sal_uInt64) nCrc ); |
| } |
| |
| if( pAAcc ) |
| aAlpha.ReleaseAccess( pAAcc); |
| |
| aBmp.ReleaseAccess( pRAcc ); |
| |
| return nRet; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void BmpSum::ProcessFile( const String& rBmpFileName ) |
| { |
| SvFileStream aIStm( rBmpFileName, STREAM_READ ); |
| |
| if( aIStm.IsOpen() ) |
| { |
| BitmapEx aBmpEx; |
| |
| ReadDIBBitmapEx(aBmpEx, aIStm); |
| |
| if( !aBmpEx.IsEmpty() ) |
| { |
| fprintf( stdout, "%" SAL_PRIuUINT64 "\r\n", GetCRC( aBmpEx ) ); |
| } |
| else |
| { |
| aIStm.ResetError(); |
| aIStm.Seek( 0 ); |
| |
| ::vcl::PNGReader aPngReader( aIStm ); |
| |
| aBmpEx = aPngReader.Read(); |
| |
| if( !aBmpEx.IsEmpty() ) |
| { |
| fprintf( stdout, "%" SAL_PRIuUINT64 "\r\n", GetCRC( aBmpEx ) ); |
| } |
| else |
| Message( String( RTL_CONSTASCII_USTRINGPARAM( "file not valid" ) ), EXIT_INVALIDFILE ); |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| void BmpSum::ProcessFileList( const String& rInFileList, |
| const String& rOutFileList, |
| const String& rOutPath ) |
| { |
| SvFileStream aIStm( rInFileList, STREAM_READ ); |
| SvFileStream aOStm( rOutFileList, STREAM_WRITE | STREAM_TRUNC ); |
| const DirEntry aBaseDir( rOutPath ); |
| |
| if( rOutPath.Len() ) |
| aBaseDir.MakeDir(); |
| |
| if( aIStm.IsOpen() && aOStm.IsOpen() ) |
| { |
| ByteString aReadLine; |
| ::std::set< ByteString > aFileNameSet; |
| |
| while( aIStm.ReadLine( aReadLine ) ) |
| { |
| if( aReadLine.Len() ) |
| aFileNameSet.insert( aReadLine ); |
| |
| if( aReadLine.Search( "enus" ) != STRING_NOTFOUND ) |
| { |
| static const char* aLanguages[] = |
| { |
| "chinsim", |
| "chintrad", |
| "dtch", |
| "enus", |
| "fren", |
| "hebrew" |
| "ital", |
| "japn", |
| "korean", |
| "pol", |
| "poln", |
| "port", |
| "russ", |
| "span", |
| "turk" |
| }; |
| |
| for( sal_uInt32 n = 0; n < 14; ++n ) |
| { |
| ByteString aLangPath( aReadLine ); |
| |
| aLangPath.SearchAndReplace( "enus", aLanguages[ n ] ); |
| |
| DirEntry aTestFile( aLangPath ); |
| |
| if( aTestFile.Exists() ) |
| aFileNameSet.insert( aLangPath ); |
| } |
| } |
| |
| aReadLine.Erase(); |
| } |
| |
| aIStm.Close(); |
| |
| ::std::set< ByteString >::iterator aIter( aFileNameSet.begin() ); |
| ::std::map< sal_uInt64, ::std::vector< ByteString > > aFileNameMap; |
| |
| while( aIter != aFileNameSet.end() ) |
| { |
| ByteString aStr( *aIter++ ); |
| SvFileStream aBmpStm( String( aStr.GetBuffer(), RTL_TEXTENCODING_ASCII_US ), STREAM_READ ); |
| sal_uInt64 nCRC = 0; |
| |
| if( aBmpStm.IsOpen() ) |
| { |
| BitmapEx aBmpEx; |
| |
| ReadDIBBitmapEx(aBmpEx, aBmpStm); |
| |
| if( !aBmpEx.IsEmpty() ) |
| nCRC = GetCRC( aBmpEx ); |
| else |
| { |
| aBmpStm.ResetError(); |
| aBmpStm.Seek( 0 ); |
| |
| ::vcl::PNGReader aPngReader( aBmpStm ); |
| |
| aBmpEx = aPngReader.Read(); |
| |
| if( !aBmpEx.IsEmpty() ) |
| nCRC = GetCRC( aBmpEx ); |
| |
| else |
| fprintf( stderr, "%s could not be opened\n", aStr.GetBuffer() ); |
| } |
| |
| aBmpStm.Close(); |
| } |
| |
| if( nCRC ) |
| { |
| ::std::map< sal_uInt64, ::std::vector< ByteString > >::iterator aFound( aFileNameMap.find( nCRC ) ); |
| |
| if( aFound != aFileNameMap.end() ) |
| (*aFound).second.push_back( aStr ); |
| else |
| { |
| ::std::vector< ByteString > aVector( 1, aStr ); |
| aFileNameMap[ nCRC ] = aVector; |
| } |
| |
| } |
| else |
| { |
| ::std::vector< ByteString > aVector( 1, aStr ); |
| aFileNameMap[ nCRC ] = aVector; |
| } |
| } |
| |
| ::std::map< sal_uInt64, ::std::vector< ByteString > >::iterator aMapIter( aFileNameMap.begin() ); |
| sal_uInt32 nFileCount = 0; |
| |
| while( aMapIter != aFileNameMap.end() ) |
| { |
| ::std::pair< const sal_uInt64, ::std::vector< ByteString > > aPair( *aMapIter++ ); |
| ::std::vector< ByteString > aFileNameVector( aPair.second ); |
| |
| // write new entries |
| for( sal_uInt32 i = 0; i < aFileNameVector.size(); ++i ) |
| { |
| ByteString aStr( ByteString::CreateFromInt64( aPair.first ) ); |
| ByteString aFileName( aFileNameVector[ i ] ); |
| DirEntry aSrcFile( aFileName ); |
| |
| aStr += '\t'; |
| aStr += aFileName; |
| |
| aOStm.WriteLine( aStr ); |
| |
| // copy bitmap |
| if( rOutPath.Len() ) |
| { |
| if( aFileName.Search( ":\\" ) != STRING_NOTFOUND ) |
| aFileName.Erase( 0, aFileName.Search( ":\\" ) + 2 ); |
| |
| aFileName.SearchAndReplaceAll( '\\', '/' ); |
| |
| sal_uInt16 nTokenCount = aFileName.GetTokenCount( '/' ); |
| DirEntry aNewDir( aBaseDir ); |
| |
| for( sal_uInt16 n = 0; ( n < nTokenCount - 1 ); n++ ) |
| { |
| aNewDir += DirEntry( aFileName.GetToken( n, '/' ) ); |
| aNewDir.MakeDir(); |
| } |
| |
| aNewDir += DirEntry( aFileName.GetToken( nTokenCount - 1, '/' ) ); |
| aSrcFile.CopyTo( aNewDir, FSYS_ACTION_COPYFILE ); |
| } |
| } |
| |
| ++nFileCount; |
| } |
| |
| fprintf( |
| stdout, "unique file count: %lu", |
| sal::static_int_cast< unsigned long >(nFileCount) ); |
| } |
| } |
| |
| // -------- |
| // - Main - |
| // -------- |
| |
| int main( int nArgCount, char* ppArgs[] ) |
| { |
| #ifdef UNX |
| static char aDisplayVar[ 1024 ]; |
| |
| strcpy( aDisplayVar, "DISPLAY=" ); |
| putenv( aDisplayVar ); |
| #endif |
| |
| ::std::vector< String > aArgs; |
| BmpSum aBmpSum; |
| |
| InitVCL( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >() ); |
| |
| for( int i = 1; i < nArgCount; i++ ) |
| aArgs.push_back( String( ppArgs[ i ], RTL_TEXTENCODING_ASCII_US ) ); |
| |
| return aBmpSum.Start( aArgs ); |
| } |