xref: /aoo4110/main/svtools/bmpmaker/bmpsum.cxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_svtools.hxx"
24 
25 #include <cstdio>
26 #include <csignal>
27 #include <vector>
28 #include <set>
29 #include <map>
30 #include <rtl/crc.h>
31 #include <tools/stream.hxx>
32 #include <tools/fsys.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/bitmap.hxx>
35 #include <vcl/bmpacc.hxx>
36 #include <vcl/pngread.hxx>
37 #include <vcl/dibtools.hxx>
38 #include "svl/solar.hrc"
39 
40 #define EXIT_NOERROR        0x00000000
41 #define EXIT_INVALIDFILE    0x00000001
42 #define EXIT_COMMONERROR    0x80000000
43 
44 // ----------
45 // - BmpSum -
46 // ----------
47 
48 class BmpSum
49 {
50 private:
51 
52 	sal_uInt32      cExitCode;
53 
54 	sal_Bool	        GetCommandOption( const ::std::vector< String >& rArgs, const String& rSwitch, String& rSwitchParam );
55 	sal_Bool	        GetCommandOptions( const ::std::vector< String >& rArgs, const String& rSwitch, ::std::vector< String >& rSwitchParams );
56 
SetExitCode(sal_uInt8 cExit)57     void	        SetExitCode( sal_uInt8 cExit )
58 			        {
59 			        	if( ( EXIT_NOERROR == cExitCode ) || ( cExit != EXIT_NOERROR ) )
60 			        		cExitCode = cExit;
61 			        }
62     void            ShowUsage();
63     void            Message( const String& rText, sal_uInt8 cExitCode );
64 
65     sal_uInt64      GetCRC( const BitmapEx& rBmpEx );
66 
67     void            ProcessFile( const String& rBmpFileName );
68     void            ProcessFileList( const String& rInFileList, const String& rOutFileList, const String& rOutPath );
69 
70 public:
71 //
72                     BmpSum();
73                     ~BmpSum();
74 
75     int             Start( const ::std::vector< String >& rArgs );
76 };
77 
78 // -----------------------------------------------------------------------------
79 
BmpSum()80 BmpSum::BmpSum()
81 {
82 }
83 
84 // -----------------------------------------------------------------------------
85 
~BmpSum()86 BmpSum::~BmpSum()
87 {
88 }
89 
90 // -----------------------------------------------------------------------
91 
GetCommandOption(const::std::vector<String> & rArgs,const String & rSwitch,String & rParam)92 sal_Bool BmpSum::GetCommandOption( const ::std::vector< String >& rArgs, const String& rSwitch, String& rParam )
93 {
94 	sal_Bool bRet = sal_False;
95 
96 	for( int i = 0, nCount = rArgs.size(); ( i < nCount ) && !bRet; i++ )
97 	{
98 		String	aTestStr( '-' );
99 
100 		for( int n = 0; ( n < 2 ) && !bRet; n++ )
101 		{
102 			aTestStr += rSwitch;
103 
104 			if( aTestStr.CompareIgnoreCaseToAscii( rArgs[ i ] ) == COMPARE_EQUAL )
105 			{
106 				bRet = sal_True;
107 
108 				if( i < ( nCount - 1 ) )
109 					rParam = rArgs[ i + 1 ];
110 				else
111 					rParam = String();
112 			}
113 
114 			if( 0 == n )
115 				aTestStr = '/';
116 		}
117 	}
118 
119 	return bRet;
120 }
121 
122 // -----------------------------------------------------------------------
123 
GetCommandOptions(const::std::vector<String> & rArgs,const String & rSwitch,::std::vector<String> & rParams)124 sal_Bool BmpSum::GetCommandOptions( const ::std::vector< String >& rArgs, const String& rSwitch, ::std::vector< String >& rParams )
125 {
126 	sal_Bool bRet = sal_False;
127 
128 	for( int i = 0, nCount = rArgs.size(); ( i < nCount ); i++ )
129 	{
130 		String	aTestStr( '-' );
131 
132 		for( int n = 0; ( n < 2 ) && !bRet; n++ )
133 		{
134 			aTestStr += rSwitch;
135 
136 			if( aTestStr.CompareIgnoreCaseToAscii( rArgs[ i ] ) == COMPARE_EQUAL )
137 			{
138 				if( i < ( nCount - 1 ) )
139 					rParams.push_back( rArgs[ i + 1 ] );
140 				else
141 					rParams.push_back( String() );
142 
143 			    break;
144 			}
145 
146 			if( 0 == n )
147 				aTestStr = '/';
148 		}
149 	}
150 
151 	return( rParams.size() > 0 );
152 }
153 
154 // -----------------------------------------------------------------------
155 
Message(const String & rText,sal_uInt8 nExitCode)156 void BmpSum::Message( const String& rText, sal_uInt8 nExitCode )
157 {
158 	if( EXIT_NOERROR != nExitCode )
159 		SetExitCode( nExitCode );
160 
161 	ByteString aText( rText, RTL_TEXTENCODING_UTF8 );
162 	aText.Append( "\r\n" );
163 	fprintf( stderr, aText.GetBuffer() );
164 }
165 
166 // -----------------------------------------------------------------------------
167 
ShowUsage()168 void BmpSum::ShowUsage()
169 {
170     Message( String( RTL_CONSTASCII_USTRINGPARAM( "Usage:" ) ), EXIT_NOERROR );
171     Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum bmp_inputfile" ) ), EXIT_NOERROR );
172     Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum -i input_filelist -o output_filelist [-p path_for_copied_bitmaps]" ) ), EXIT_NOERROR );
173     Message( String( RTL_CONSTASCII_USTRINGPARAM( "Options:" ) ), EXIT_NOERROR );
174     Message( String( RTL_CONSTASCII_USTRINGPARAM( "Examples:" ) ), EXIT_NOERROR );
175     Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum /home/test.bmp" ) ), EXIT_NOERROR );
176     Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum -i /home/inlist.txt -o /home/outlist.txt" ) ), EXIT_NOERROR );
177     Message( String( RTL_CONSTASCII_USTRINGPARAM( "    bmpsum -i /home/inlist.txt -o /home/outlist.txt -p /home/outpath" ) ), EXIT_NOERROR );
178 }
179 
180 // -----------------------------------------------------------------------------
181 
Start(const::std::vector<String> & rArgs)182 int BmpSum::Start( const ::std::vector< String >& rArgs )
183 {
184 	cExitCode = EXIT_NOERROR;
185 
186 	if( rArgs.size() >= 1 )
187 	{
188 	    String  aInFileList, aOutFileList, aOutPath;
189 
190 	    if( GetCommandOption( rArgs, 'i', aInFileList ) &&
191 	        GetCommandOption( rArgs, 'o', aOutFileList ) )
192 	    {
193             GetCommandOption( rArgs, 'p', aOutPath );
194 	        ProcessFileList( aInFileList, aOutFileList, aOutPath );
195 	    }
196 	    else
197 	    {
198 	        ProcessFile( rArgs[ 0 ] );
199 	    }
200 	}
201     else
202     {
203         ShowUsage();
204         cExitCode = EXIT_COMMONERROR;
205     }
206 
207     return cExitCode;
208 }
209 
210 // -----------------------------------------------------------------------------
211 
GetCRC(const BitmapEx & rBmpEx)212 sal_uInt64 BmpSum::GetCRC( const BitmapEx& rBmpEx )
213 {
214     Bitmap              aBmp( rBmpEx.GetBitmap() );
215     BitmapReadAccess*   pRAcc = aBmp.AcquireReadAccess();
216     AlphaMask           aAlpha;
217     BitmapReadAccess*   pAAcc = NULL;
218     sal_uInt64          nRet = 0;
219     sal_uInt32          nCrc = 0;
220 
221     if( rBmpEx.IsTransparent() )
222     {
223         aAlpha = rBmpEx.GetAlpha();
224         pAAcc = aAlpha.AcquireReadAccess();
225     }
226 
227 	if( pRAcc && pRAcc->Width() && pRAcc->Height() )
228 	{
229 		SVBT32 aBT32;
230 
231 		for( long nY = 0; nY < pRAcc->Height(); ++nY )
232 		{
233     		for( long nX = 0; nX < pRAcc->Width(); ++nX )
234     		{
235     		    const BitmapColor aCol( pRAcc->GetColor( nY, nX ) );
236 
237         		UInt32ToSVBT32( aCol.GetRed(), aBT32 );
238 		        nCrc = rtl_crc32( nCrc, aBT32, 4 );
239 
240         		UInt32ToSVBT32( aCol.GetGreen(), aBT32 );
241 		        nCrc = rtl_crc32( nCrc, aBT32, 4 );
242 
243         		UInt32ToSVBT32( aCol.GetBlue(), aBT32 );
244 		        nCrc = rtl_crc32( nCrc, aBT32, 4 );
245 
246                 if( pAAcc )
247                 {
248                     const BitmapColor aMaskCol( pAAcc->GetColor( nY, nX ) );
249 
250                     UInt32ToSVBT32( aMaskCol.GetRed(), aBT32 );
251                     nCrc = rtl_crc32( nCrc, aBT32, 4 );
252 
253                     UInt32ToSVBT32( aMaskCol.GetGreen(), aBT32 );
254                     nCrc = rtl_crc32( nCrc, aBT32, 4 );
255 
256                     UInt32ToSVBT32( aMaskCol.GetBlue(), aBT32 );
257                     nCrc = rtl_crc32( nCrc, aBT32, 4 );
258                 }
259     		}
260 		}
261 
262 		nRet = ( ( (sal_uInt64) pRAcc->Width() ) << 48 ) |
263 		       ( ( (sal_uInt64) pRAcc->Height() ) << 32 ) |
264 		       ( (sal_uInt64) nCrc );
265 	}
266 
267     if( pAAcc )
268         aAlpha.ReleaseAccess( pAAcc);
269 
270     aBmp.ReleaseAccess( pRAcc );
271 
272     return nRet;
273 }
274 
275 // -----------------------------------------------------------------------------
276 
ProcessFile(const String & rBmpFileName)277 void BmpSum::ProcessFile( const String& rBmpFileName )
278 {
279     SvFileStream aIStm( rBmpFileName, STREAM_READ );
280 
281     if( aIStm.IsOpen() )
282     {
283         BitmapEx aBmpEx;
284 
285         ReadDIBBitmapEx(aBmpEx, aIStm);
286 
287 	    if( !aBmpEx.IsEmpty() )
288 	    {
289             fprintf( stdout, "%" SAL_PRIuUINT64 "\r\n", GetCRC( aBmpEx ) );
290         }
291 	    else
292         {
293             aIStm.ResetError();
294             aIStm.Seek( 0 );
295 
296        		::vcl::PNGReader aPngReader( aIStm );
297 
298             aBmpEx = aPngReader.Read();
299 
300       	    if( !aBmpEx.IsEmpty() )
301             {
302     	        fprintf( stdout, "%" SAL_PRIuUINT64 "\r\n", GetCRC( aBmpEx ) );
303             }
304             else
305                 Message( String( RTL_CONSTASCII_USTRINGPARAM( "file not valid" ) ), EXIT_INVALIDFILE );
306         }
307     }
308 }
309 
310 // -----------------------------------------------------------------------------
311 
ProcessFileList(const String & rInFileList,const String & rOutFileList,const String & rOutPath)312 void BmpSum::ProcessFileList( const String& rInFileList,
313                               const String& rOutFileList,
314                               const String& rOutPath )
315 {
316     SvFileStream    aIStm( rInFileList, STREAM_READ );
317     SvFileStream    aOStm( rOutFileList, STREAM_WRITE | STREAM_TRUNC );
318     const DirEntry  aBaseDir( rOutPath );
319 
320     if( rOutPath.Len() )
321         aBaseDir.MakeDir();
322 
323     if( aIStm.IsOpen() && aOStm.IsOpen() )
324     {
325         ByteString                  aReadLine;
326         ::std::set< ByteString >    aFileNameSet;
327 
328         while( aIStm.ReadLine( aReadLine ) )
329         {
330             if( aReadLine.Len() )
331                 aFileNameSet.insert( aReadLine );
332 
333             if( aReadLine.Search( "enus" ) != STRING_NOTFOUND )
334             {
335                 static const char* aLanguages[] =
336                 {
337                     "chinsim",
338                     "chintrad",
339                     "dtch",
340                     "enus",
341                     "fren",
342                     "hebrew"
343                     "ital",
344                     "japn",
345                     "korean",
346                     "pol",
347                     "poln",
348                     "port",
349                     "russ",
350                     "span",
351                     "turk"
352                 };
353 
354                 for( sal_uInt32 n = 0; n < 14; ++n )
355                 {
356                     ByteString aLangPath( aReadLine );
357 
358                     aLangPath.SearchAndReplace( "enus", aLanguages[ n ] );
359 
360                     DirEntry aTestFile( aLangPath );
361 
362                     if( aTestFile.Exists() )
363                         aFileNameSet.insert( aLangPath );
364                 }
365             }
366 
367             aReadLine.Erase();
368         }
369 
370         aIStm.Close();
371 
372         ::std::set< ByteString >::iterator aIter( aFileNameSet.begin() );
373         ::std::map< sal_uInt64, ::std::vector< ByteString > > aFileNameMap;
374 
375         while( aIter != aFileNameSet.end() )
376         {
377             ByteString      aStr( *aIter++ );
378             SvFileStream    aBmpStm( String( aStr.GetBuffer(), RTL_TEXTENCODING_ASCII_US ), STREAM_READ );
379             sal_uInt64      nCRC = 0;
380 
381             if( aBmpStm.IsOpen() )
382             {
383                 BitmapEx aBmpEx;
384 
385                 ReadDIBBitmapEx(aBmpEx, aBmpStm);
386 
387 	            if( !aBmpEx.IsEmpty() )
388 	                nCRC = GetCRC( aBmpEx );
389                 else
390                 {
391                     aBmpStm.ResetError();
392                     aBmpStm.Seek( 0 );
393 
394                		::vcl::PNGReader aPngReader( aBmpStm );
395 
396                     aBmpEx = aPngReader.Read();
397 
398               	    if( !aBmpEx.IsEmpty() )
399        	                nCRC = GetCRC( aBmpEx );
400 
401                     else
402                         fprintf( stderr, "%s could not be opened\n", aStr.GetBuffer() );
403                }
404 
405                 aBmpStm.Close();
406             }
407 
408             if( nCRC )
409             {
410                 ::std::map< sal_uInt64, ::std::vector< ByteString > >::iterator aFound( aFileNameMap.find( nCRC ) );
411 
412                 if( aFound != aFileNameMap.end() )
413                     (*aFound).second.push_back( aStr );
414                 else
415                 {
416                     ::std::vector< ByteString > aVector( 1, aStr );
417                     aFileNameMap[ nCRC ]  = aVector;
418                 }
419 
420             }
421             else
422             {
423                 ::std::vector< ByteString > aVector( 1, aStr );
424                 aFileNameMap[ nCRC ]  = aVector;
425             }
426         }
427 
428         ::std::map< sal_uInt64, ::std::vector< ByteString > >::iterator aMapIter( aFileNameMap.begin() );
429         sal_uInt32 nFileCount = 0;
430 
431         while( aMapIter != aFileNameMap.end() )
432         {
433             ::std::pair< const sal_uInt64, ::std::vector< ByteString > > aPair( *aMapIter++ );
434             ::std::vector< ByteString > aFileNameVector( aPair.second );
435 
436             // write new entries
437             for( sal_uInt32 i = 0; i < aFileNameVector.size(); ++i )
438             {
439                 ByteString  aStr( ByteString::CreateFromInt64( aPair.first ) );
440                 ByteString  aFileName( aFileNameVector[ i ] );
441                 DirEntry    aSrcFile( aFileName );
442 
443                 aStr += '\t';
444                 aStr += aFileName;
445 
446                 aOStm.WriteLine( aStr );
447 
448                 // copy bitmap
449                 if( rOutPath.Len() )
450                 {
451                     if( aFileName.Search( ":\\" ) != STRING_NOTFOUND )
452                         aFileName.Erase( 0, aFileName.Search( ":\\" ) + 2 );
453 
454                     aFileName.SearchAndReplaceAll( '\\', '/' );
455 
456                     sal_uInt16  nTokenCount = aFileName.GetTokenCount( '/' );
457                     DirEntry    aNewDir( aBaseDir );
458 
459                     for( sal_uInt16 n = 0; ( n < nTokenCount - 1 ); n++ )
460                     {
461                         aNewDir += DirEntry( aFileName.GetToken( n, '/' ) );
462                         aNewDir.MakeDir();
463                     }
464 
465                     aNewDir += DirEntry( aFileName.GetToken( nTokenCount - 1, '/' ) );
466                     aSrcFile.CopyTo( aNewDir, FSYS_ACTION_COPYFILE );
467                 }
468             }
469 
470             ++nFileCount;
471         }
472 
473         fprintf(
474             stdout, "unique file count: %lu",
475             sal::static_int_cast< unsigned long >(nFileCount) );
476     }
477 }
478 
479 // --------
480 // - Main -
481 // --------
482 
main(int nArgCount,char * ppArgs[])483 int main( int nArgCount, char* ppArgs[] )
484 {
485 #ifdef UNX
486     static char aDisplayVar[ 1024 ];
487 
488     strcpy( aDisplayVar, "DISPLAY=" );
489     putenv( aDisplayVar );
490 #endif
491 
492     ::std::vector< String > aArgs;
493     BmpSum                  aBmpSum;
494 
495     InitVCL( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >() );
496 
497     for( int i = 1; i < nArgCount; i++ )
498         aArgs.push_back( String( ppArgs[ i ], RTL_TEXTENCODING_ASCII_US ) );
499 
500     return aBmpSum.Start( aArgs );
501 }
502