Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <cstdio>
31 : : #include <csignal>
32 : : #include <vector>
33 : : #include <set>
34 : : #include <map>
35 : :
36 : : #include <comphelper/string.hxx>
37 : : #include <rtl/crc.h>
38 : : #include <rtl/strbuf.hxx>
39 : : #include <tools/stream.hxx>
40 : : #include <tools/fsys.hxx>
41 : : #include <vcl/svapp.hxx>
42 : : #include <vcl/bitmap.hxx>
43 : : #include <vcl/bmpacc.hxx>
44 : : #include <vcl/pngread.hxx>
45 : :
46 : : #include "svl/solar.hrc"
47 : :
48 : : #define EXIT_NOERROR 0x00000000
49 : : #define EXIT_INVALIDFILE 0x00000001
50 : : #define EXIT_COMMONERROR 0x80000000
51 : :
52 : : // ----------
53 : : // - BmpSum -
54 : : // ----------
55 : :
56 : : class BmpSum
57 : : {
58 : : private:
59 : :
60 : : sal_uInt32 cExitCode;
61 : :
62 : : sal_Bool GetCommandOption( const ::std::vector< String >& rArgs, const String& rSwitch, String& rSwitchParam );
63 : :
64 : 0 : void SetExitCode( sal_uInt8 cExit )
65 : : {
66 : 0 : if( ( EXIT_NOERROR == cExitCode ) || ( cExit != EXIT_NOERROR ) )
67 : 0 : cExitCode = cExit;
68 : 0 : }
69 : : void ShowUsage();
70 : : void Message( const String& rText, sal_uInt8 cExitCode );
71 : :
72 : : sal_uInt64 GetCRC( const BitmapEx& rBmpEx );
73 : :
74 : : void ProcessFile( const String& rBmpFileName );
75 : : void ProcessFileList( const String& rInFileList, const String& rOutFileList, const String& rOutPath );
76 : :
77 : : public:
78 : : //
79 : : BmpSum();
80 : : ~BmpSum();
81 : :
82 : : int Start( const ::std::vector< String >& rArgs );
83 : : };
84 : :
85 : : // -----------------------------------------------------------------------------
86 : :
87 : 0 : BmpSum::BmpSum()
88 : : {
89 : 0 : }
90 : :
91 : : // -----------------------------------------------------------------------------
92 : :
93 : 0 : BmpSum::~BmpSum()
94 : : {
95 : 0 : }
96 : :
97 : : // -----------------------------------------------------------------------
98 : :
99 : 0 : sal_Bool BmpSum::GetCommandOption( const ::std::vector< String >& rArgs, const String& rSwitch, String& rParam )
100 : : {
101 : 0 : sal_Bool bRet = sal_False;
102 : :
103 : 0 : for( int i = 0, nCount = rArgs.size(); ( i < nCount ) && !bRet; i++ )
104 : : {
105 : 0 : rtl::OUString aTestStr( '-' );
106 : :
107 : 0 : for( int n = 0; ( n < 2 ) && !bRet; n++ )
108 : : {
109 : 0 : aTestStr += rSwitch;
110 : :
111 : 0 : if( aTestStr.equalsIgnoreAsciiCase( rArgs[ i ] ) )
112 : : {
113 : 0 : bRet = sal_True;
114 : :
115 : 0 : if( i < ( nCount - 1 ) )
116 : 0 : rParam = rArgs[ i + 1 ];
117 : : else
118 : 0 : rParam = String();
119 : : }
120 : :
121 : 0 : if( 0 == n )
122 : 0 : aTestStr = rtl::OUString('/');
123 : : }
124 : 0 : }
125 : :
126 : 0 : return bRet;
127 : : }
128 : :
129 : : // -----------------------------------------------------------------------
130 : :
131 : 0 : void BmpSum::Message( const String& rText, sal_uInt8 nExitCode )
132 : : {
133 : 0 : if( EXIT_NOERROR != nExitCode )
134 : 0 : SetExitCode( nExitCode );
135 : :
136 : 0 : rtl::OStringBuffer aText(rtl::OUStringToOString(rText, RTL_TEXTENCODING_UTF8));
137 : 0 : aText.append(RTL_CONSTASCII_STRINGPARAM("\r\n"));
138 : 0 : fprintf(stderr, "%s", aText.getStr());
139 : 0 : }
140 : :
141 : : // -----------------------------------------------------------------------------
142 : :
143 : 0 : void BmpSum::ShowUsage()
144 : : {
145 : 0 : Message( String( RTL_CONSTASCII_USTRINGPARAM( "Usage:" ) ), EXIT_NOERROR );
146 : 0 : Message( String( RTL_CONSTASCII_USTRINGPARAM( " bmpsum bmp_inputfile" ) ), EXIT_NOERROR );
147 : 0 : Message( String( RTL_CONSTASCII_USTRINGPARAM( " bmpsum -i input_filelist -o output_filelist [-p path_for_copied_bitmaps]" ) ), EXIT_NOERROR );
148 : 0 : Message( String( RTL_CONSTASCII_USTRINGPARAM( "Options:" ) ), EXIT_NOERROR );
149 : 0 : Message( String( RTL_CONSTASCII_USTRINGPARAM( "Examples:" ) ), EXIT_NOERROR );
150 : 0 : Message( String( RTL_CONSTASCII_USTRINGPARAM( " bmpsum /home/test.bmp" ) ), EXIT_NOERROR );
151 : 0 : Message( String( RTL_CONSTASCII_USTRINGPARAM( " bmpsum -i /home/inlist.txt -o /home/outlist.txt" ) ), EXIT_NOERROR );
152 : 0 : Message( String( RTL_CONSTASCII_USTRINGPARAM( " bmpsum -i /home/inlist.txt -o /home/outlist.txt -p /home/outpath" ) ), EXIT_NOERROR );
153 : 0 : }
154 : :
155 : : // -----------------------------------------------------------------------------
156 : :
157 : 0 : int BmpSum::Start( const ::std::vector< String >& rArgs )
158 : : {
159 : 0 : cExitCode = EXIT_NOERROR;
160 : :
161 : 0 : if( rArgs.size() >= 1 )
162 : : {
163 : 0 : String aInFileList, aOutFileList, aOutPath;
164 : :
165 : 0 : if( GetCommandOption( rArgs, rtl::OUString('i'), aInFileList ) &&
166 : 0 : GetCommandOption( rArgs, rtl::OUString('o'), aOutFileList ) )
167 : : {
168 : 0 : GetCommandOption( rArgs, rtl::OUString('p'), aOutPath );
169 : 0 : ProcessFileList( aInFileList, aOutFileList, aOutPath );
170 : : }
171 : : else
172 : : {
173 : 0 : ProcessFile( rArgs[ 0 ] );
174 : 0 : }
175 : : }
176 : : else
177 : : {
178 : 0 : ShowUsage();
179 : 0 : cExitCode = EXIT_COMMONERROR;
180 : : }
181 : :
182 : 0 : return cExitCode;
183 : : }
184 : :
185 : : // -----------------------------------------------------------------------------
186 : :
187 : 0 : sal_uInt64 BmpSum::GetCRC( const BitmapEx& rBmpEx )
188 : : {
189 : 0 : Bitmap aBmp( rBmpEx.GetBitmap() );
190 : 0 : BitmapReadAccess* pRAcc = aBmp.AcquireReadAccess();
191 : 0 : AlphaMask aAlpha;
192 : 0 : BitmapReadAccess* pAAcc = NULL;
193 : 0 : sal_uInt64 nRet = 0;
194 : :
195 : 0 : if( rBmpEx.IsTransparent() )
196 : : {
197 : 0 : aAlpha = rBmpEx.GetAlpha();
198 : 0 : pAAcc = aAlpha.AcquireReadAccess();
199 : : }
200 : :
201 : 0 : if( pRAcc && pRAcc->Width() && pRAcc->Height() )
202 : : {
203 : : SVBT32 aBT32;
204 : 0 : sal_uInt32 nCrc = 0;
205 : :
206 : 0 : for( long nY = 0; nY < pRAcc->Height(); ++nY )
207 : : {
208 : 0 : for( long nX = 0; nX < pRAcc->Width(); ++nX )
209 : : {
210 : 0 : const BitmapColor aCol( pRAcc->GetColor( nY, nX ) );
211 : :
212 : 0 : UInt32ToSVBT32( aCol.GetRed(), aBT32 );
213 : 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
214 : :
215 : 0 : UInt32ToSVBT32( aCol.GetGreen(), aBT32 );
216 : 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
217 : :
218 : 0 : UInt32ToSVBT32( aCol.GetBlue(), aBT32 );
219 : 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
220 : :
221 : 0 : if( pAAcc )
222 : : {
223 : 0 : const BitmapColor aMaskCol( pAAcc->GetColor( nY, nX ) );
224 : :
225 : 0 : UInt32ToSVBT32( aMaskCol.GetRed(), aBT32 );
226 : 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
227 : :
228 : 0 : UInt32ToSVBT32( aMaskCol.GetGreen(), aBT32 );
229 : 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
230 : :
231 : 0 : UInt32ToSVBT32( aMaskCol.GetBlue(), aBT32 );
232 : 0 : nCrc = rtl_crc32( nCrc, aBT32, 4 );
233 : : }
234 : 0 : }
235 : : }
236 : :
237 : 0 : nRet = ( ( (sal_uInt64) pRAcc->Width() ) << 48 ) |
238 : 0 : ( ( (sal_uInt64) pRAcc->Height() ) << 32 ) |
239 : 0 : ( (sal_uInt64) nCrc );
240 : : }
241 : :
242 : 0 : if( pAAcc )
243 : 0 : aAlpha.ReleaseAccess( pAAcc);
244 : :
245 : 0 : aBmp.ReleaseAccess( pRAcc );
246 : :
247 : 0 : return nRet;
248 : : }
249 : :
250 : : // -----------------------------------------------------------------------------
251 : :
252 : 0 : void BmpSum::ProcessFile( const String& rBmpFileName )
253 : : {
254 : 0 : SvFileStream aIStm( rBmpFileName, STREAM_READ );
255 : :
256 : 0 : if( aIStm.IsOpen() )
257 : : {
258 : 0 : BitmapEx aBmpEx;
259 : :
260 : 0 : aIStm >> aBmpEx;
261 : :
262 : 0 : if( !aBmpEx.IsEmpty() )
263 : : {
264 : 0 : fprintf( stdout, "%" SAL_PRIuUINT64 "\r\n", GetCRC( aBmpEx ) );
265 : : }
266 : : else
267 : : {
268 : 0 : aIStm.ResetError();
269 : 0 : aIStm.Seek( 0 );
270 : :
271 : 0 : ::vcl::PNGReader aPngReader( aIStm );
272 : :
273 : 0 : aBmpEx = aPngReader.Read();
274 : :
275 : 0 : if( !aBmpEx.IsEmpty() )
276 : : {
277 : 0 : fprintf( stdout, "%" SAL_PRIuUINT64 "\r\n", GetCRC( aBmpEx ) );
278 : : }
279 : : else
280 : 0 : Message( String( RTL_CONSTASCII_USTRINGPARAM( "file not valid" ) ), EXIT_INVALIDFILE );
281 : 0 : }
282 : 0 : }
283 : 0 : }
284 : :
285 : : // -----------------------------------------------------------------------------
286 : :
287 : 0 : void BmpSum::ProcessFileList( const String& rInFileList,
288 : : const String& rOutFileList,
289 : : const String& rOutPath )
290 : : {
291 : 0 : SvFileStream aIStm( rInFileList, STREAM_READ );
292 : 0 : SvFileStream aOStm( rOutFileList, STREAM_WRITE | STREAM_TRUNC );
293 : 0 : const DirEntry aBaseDir( rOutPath );
294 : :
295 : 0 : if( rOutPath.Len() )
296 : 0 : aBaseDir.MakeDir();
297 : :
298 : 0 : if( aIStm.IsOpen() && aOStm.IsOpen() )
299 : : {
300 : 0 : rtl::OString aReadLine;
301 : 0 : ::std::set<rtl::OString> aFileNameSet;
302 : :
303 : 0 : while( aIStm.ReadLine( aReadLine ) )
304 : : {
305 : 0 : if( !aReadLine.isEmpty() )
306 : 0 : aFileNameSet.insert( aReadLine );
307 : :
308 : 0 : if( aReadLine.indexOfL(RTL_CONSTASCII_STRINGPARAM("enus") ) != -1 )
309 : : {
310 : : static const char* aLanguages[] =
311 : : {
312 : : "chinsim",
313 : : "chintrad",
314 : : "dtch",
315 : : "enus",
316 : : "fren",
317 : : "hebrew"
318 : : "ital",
319 : : "japn",
320 : : "korean",
321 : : "pol",
322 : : "poln",
323 : : "port",
324 : : "russ",
325 : : "span",
326 : : "turk"
327 : : };
328 : :
329 : 0 : for( sal_uInt32 n = 0; n < 14; ++n )
330 : : {
331 : : rtl::OString aLangPath(
332 : : aReadLine.replaceAll(
333 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("enus")),
334 : 0 : rtl::OString(aLanguages[n])));
335 : :
336 : 0 : DirEntry aTestFile( aLangPath );
337 : :
338 : 0 : if( aTestFile.Exists() )
339 : 0 : aFileNameSet.insert( aLangPath );
340 : 0 : }
341 : : }
342 : :
343 : 0 : aReadLine = rtl::OString();
344 : : }
345 : :
346 : 0 : aIStm.Close();
347 : :
348 : 0 : ::std::set< rtl::OString >::iterator aIter( aFileNameSet.begin() );
349 : 0 : ::std::map< sal_uInt64, ::std::vector< rtl::OString > > aFileNameMap;
350 : :
351 : 0 : while( aIter != aFileNameSet.end() )
352 : : {
353 : 0 : rtl::OString aStr( *aIter++ );
354 : 0 : SvFileStream aBmpStm(rtl::OStringToOUString(aStr, RTL_TEXTENCODING_ASCII_US), STREAM_READ);
355 : 0 : sal_uInt64 nCRC = 0;
356 : :
357 : 0 : if( aBmpStm.IsOpen() )
358 : : {
359 : 0 : BitmapEx aBmpEx;
360 : :
361 : 0 : aBmpStm >> aBmpEx;
362 : :
363 : 0 : if( !aBmpEx.IsEmpty() )
364 : 0 : nCRC = GetCRC( aBmpEx );
365 : : else
366 : : {
367 : 0 : aBmpStm.ResetError();
368 : 0 : aBmpStm.Seek( 0 );
369 : :
370 : 0 : ::vcl::PNGReader aPngReader( aBmpStm );
371 : :
372 : 0 : aBmpEx = aPngReader.Read();
373 : :
374 : 0 : if( !aBmpEx.IsEmpty() )
375 : 0 : nCRC = GetCRC( aBmpEx );
376 : :
377 : : else
378 : 0 : fprintf( stderr, "%s could not be opened\n", aStr.getStr() );
379 : : }
380 : :
381 : 0 : aBmpStm.Close();
382 : : }
383 : :
384 : 0 : if( nCRC )
385 : : {
386 : 0 : ::std::map< sal_uInt64, ::std::vector< rtl::OString > >::iterator aFound( aFileNameMap.find( nCRC ) );
387 : :
388 : 0 : if( aFound != aFileNameMap.end() )
389 : 0 : (*aFound).second.push_back( aStr );
390 : : else
391 : : {
392 : 0 : ::std::vector< rtl::OString > aVector( 1, aStr );
393 : 0 : aFileNameMap[ nCRC ] = aVector;
394 : : }
395 : :
396 : : }
397 : : else
398 : : {
399 : 0 : ::std::vector< rtl::OString > aVector( 1, aStr );
400 : 0 : aFileNameMap[ nCRC ] = aVector;
401 : : }
402 : 0 : }
403 : :
404 : 0 : ::std::map< sal_uInt64, ::std::vector< rtl::OString > >::iterator aMapIter( aFileNameMap.begin() );
405 : 0 : sal_uInt32 nFileCount = 0;
406 : :
407 : 0 : while( aMapIter != aFileNameMap.end() )
408 : : {
409 : 0 : ::std::pair< const sal_uInt64, ::std::vector< rtl::OString > > aPair( *aMapIter++ );
410 : 0 : ::std::vector< rtl::OString > aFileNameVector( aPair.second );
411 : :
412 : : // write new entries
413 : 0 : for( sal_uInt32 i = 0; i < aFileNameVector.size(); ++i )
414 : : {
415 : 0 : rtl::OString aFileName( aFileNameVector[ i ] );
416 : 0 : DirEntry aSrcFile( aFileName );
417 : :
418 : 0 : rtl::OStringBuffer aStr;
419 : 0 : aStr.append(static_cast<sal_Int64>(aPair.first))
420 : 0 : .append('\t').append(aFileName);
421 : 0 : aOStm.WriteLine( aStr.makeStringAndClear() );
422 : :
423 : : // copy bitmap
424 : 0 : if( rOutPath.Len() )
425 : : {
426 : 0 : sal_Int32 nIndex = aFileName.indexOf(":\\");
427 : 0 : if (nIndex != -1)
428 : 0 : aFileName = aFileName.copy(nIndex + 2);
429 : :
430 : 0 : aFileName = aFileName.replace('\\', '/');
431 : :
432 : 0 : sal_Int32 nTokenCount = comphelper::string::getTokenCount(aFileName, '/');
433 : 0 : DirEntry aNewDir( aBaseDir );
434 : :
435 : 0 : for (sal_Int32 n = 0; ( n < nTokenCount - 1 ); ++n)
436 : : {
437 : 0 : aNewDir += DirEntry( comphelper::string::getToken(aFileName, n, '/') );
438 : 0 : aNewDir.MakeDir();
439 : : }
440 : :
441 : 0 : aNewDir += DirEntry( comphelper::string::getToken(aFileName, nTokenCount - 1, '/') );
442 : 0 : aSrcFile.CopyTo( aNewDir, FSYS_ACTION_COPYFILE );
443 : : }
444 : 0 : }
445 : :
446 : 0 : ++nFileCount;
447 : 0 : }
448 : :
449 : : fprintf(
450 : : stdout, "unique file count: %lu",
451 : 0 : sal::static_int_cast< unsigned long >(nFileCount) );
452 : 0 : }
453 : 0 : }
454 : :
455 : : // --------
456 : : // - Main -
457 : : // --------
458 : :
459 : 0 : int main( int nArgCount, char* ppArgs[] )
460 : : {
461 : : #ifdef UNX
462 : : static char aDisplayVar[ 1024 ];
463 : :
464 : 0 : strcpy( aDisplayVar, "DISPLAY=" );
465 : 0 : putenv( aDisplayVar );
466 : : #endif
467 : :
468 : 0 : ::std::vector< String > aArgs;
469 : 0 : BmpSum aBmpSum;
470 : :
471 : 0 : InitVCL( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >() );
472 : :
473 : 0 : for( int i = 1; i < nArgCount; i++ )
474 : 0 : aArgs.push_back( String( ppArgs[ i ], RTL_TEXTENCODING_ASCII_US ) );
475 : :
476 : 0 : return aBmpSum.Start( aArgs );
477 : : }
478 : :
479 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|