bump product version to 4.1.6.2
[LibreOffice.git] / filter / source / graphicfilter / ipbm / ipbm.cxx
blob4de5cefd343552c41c598b57850ef0162625f973
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <vcl/graph.hxx>
22 #include <vcl/bmpacc.hxx>
24 class FilterConfigItem;
26 //============================ PBMReader ==================================
28 class PBMReader {
30 private:
32 SvStream& mrPBM; // the PBM file to read
34 sal_Bool mbStatus;
35 sal_Bool mbRemark; // sal_False if the stream is in a comment
36 sal_Bool mbRaw; // RAW/ASCII MODE
37 sal_uLong mnMode; // 0->PBM, 1->PGM, 2->PPM
38 Bitmap maBmp;
39 BitmapWriteAccess* mpAcc;
40 sal_uLong mnWidth, mnHeight; // dimensions in pixel
41 sal_uLong mnCol;
42 sal_uLong mnMaxVal; // max value in the <missing comment>
43 sal_Bool ImplCallback( sal_uInt16 nPercent );
44 sal_Bool ImplReadBody();
45 sal_Bool ImplReadHeader();
47 public:
48 PBMReader(SvStream & rPBM);
49 ~PBMReader();
50 sal_Bool ReadPBM(Graphic & rGraphic );
53 //=================== Methods of PBMReader ==============================
55 PBMReader::PBMReader(SvStream & rPBM)
56 : mrPBM( rPBM )
57 , mbStatus( sal_True )
58 , mbRemark( sal_False )
59 , mbRaw( sal_True )
60 , mpAcc( NULL )
64 PBMReader::~PBMReader()
68 sal_Bool PBMReader::ImplCallback( sal_uInt16 /*nPercent*/ )
71 if ( pCallback != NULL )
73 if ( ( (*pCallback)( pCallerData, nPercent ) ) == sal_True )
75 mrPBM.SetError( SVSTREAM_FILEFORMAT_ERROR );
76 return sal_True;
80 return sal_False;
83 sal_Bool PBMReader::ReadPBM(Graphic & rGraphic )
85 sal_uInt16 i;
87 if ( mrPBM.GetError() )
88 return sal_False;
90 mrPBM.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
92 // read header:
94 if ( ( mbStatus = ImplReadHeader() ) == sal_False )
95 return sal_False;
97 if ( ( mnMaxVal == 0 ) || ( mnWidth == 0 ) || ( mnHeight == 0 ) )
98 return sal_False;
100 // 0->PBM, 1->PGM, 2->PPM
101 switch ( mnMode )
103 case 0 :
104 maBmp = Bitmap( Size( mnWidth, mnHeight ), 1 );
105 if ( ( mpAcc = maBmp.AcquireWriteAccess() ) == sal_False )
106 return sal_False;
107 mpAcc->SetPaletteEntryCount( 2 );
108 mpAcc->SetPaletteColor( 0, BitmapColor( 0xff, 0xff, 0xff ) );
109 mpAcc->SetPaletteColor( 1, BitmapColor( 0x00, 0x00, 0x00 ) );
110 break;
112 case 1 :
113 if ( mnMaxVal <= 1 )
114 maBmp = Bitmap( Size( mnWidth, mnHeight ), 1);
115 else if ( mnMaxVal <= 15 )
116 maBmp = Bitmap( Size( mnWidth, mnHeight ), 4);
117 else
118 maBmp = Bitmap( Size( mnWidth, mnHeight ), 8);
120 if ( ( mpAcc = maBmp.AcquireWriteAccess() ) == sal_False )
121 return sal_False;
122 mnCol = (sal_uInt16)mnMaxVal + 1;
123 if ( mnCol > 256 )
124 mnCol = 256;
126 mpAcc->SetPaletteEntryCount( 256 );
127 for ( i = 0; i < mnCol; i++ )
129 sal_uLong nCount = 255 * i / mnCol;
130 mpAcc->SetPaletteColor( i, BitmapColor( (sal_uInt8)nCount, (sal_uInt8)nCount, (sal_uInt8)nCount ) );
132 break;
133 case 2 :
134 maBmp = Bitmap( Size( mnWidth, mnHeight ), 24 );
135 if ( ( mpAcc = maBmp.AcquireWriteAccess() ) == sal_False )
136 return sal_False;
137 break;
140 // read bitmap data
141 mbStatus = ImplReadBody();
143 if ( mpAcc )
145 maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
147 if ( mbStatus )
148 rGraphic = maBmp;
150 return mbStatus;
153 sal_Bool PBMReader::ImplReadHeader()
155 sal_uInt8 nID[ 2 ];
156 sal_uInt8 nDat;
157 sal_uInt8 nMax, nCount = 0;
158 sal_Bool bFinished = sal_False;
160 mrPBM >> nID[ 0 ] >> nID[ 1 ];
161 if ( nID[ 0 ] != 'P' )
162 return sal_False;
163 mnMaxVal = mnWidth = mnHeight = 0;
164 switch ( nID[ 1 ] )
166 case '1' :
167 mbRaw = sal_False;
168 case '4' :
169 mnMode = 0;
170 nMax = 2; // number of parameters in Header
171 mnMaxVal = 1;
172 break;
173 case '2' :
174 mbRaw = sal_False;
175 case '5' :
176 mnMode = 1;
177 nMax = 3;
178 break;
179 case '3' :
180 mbRaw = sal_False;
181 case '6' :
182 mnMode = 2;
183 nMax = 3;
184 break;
185 default:
186 return sal_False;
188 while ( bFinished == sal_False )
190 if ( mrPBM.GetError() )
191 return sal_False;
193 mrPBM >> nDat;
195 if ( nDat == '#' )
197 mbRemark = sal_True;
198 continue;
200 else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
202 mbRemark = sal_False;
203 nDat = 0x20;
205 if ( mbRemark )
206 continue;
208 if ( ( nDat == 0x20 ) || ( nDat == 0x09 ) )
210 if ( ( nCount == 0 ) && mnWidth )
211 nCount++;
212 else if ( ( nCount == 1 ) && mnHeight )
214 if ( ++nCount == nMax )
215 bFinished = sal_True;
217 else if ( ( nCount == 2 ) && mnMaxVal )
219 bFinished = sal_True;
221 continue;
223 if ( ( nDat >= '0' ) && ( nDat <= '9' ) )
225 nDat -= '0';
226 if ( nCount == 0 )
228 mnWidth *= 10;
229 mnWidth += nDat;
231 else if ( nCount == 1 )
233 mnHeight *= 10;
234 mnHeight += nDat;
236 else if ( nCount == 2 )
238 mnMaxVal *= 10;
239 mnMaxVal += nDat;
242 else
243 return sal_False;
245 return mbStatus;
248 sal_Bool PBMReader::ImplReadBody()
250 sal_Bool bPara, bFinished = sal_False;
251 sal_uInt8 nDat = 0, nCount;
252 sal_uLong nGrey, nRGB[3];
253 sal_uLong nWidth = 0;
254 sal_uLong nHeight = 0;
256 if ( mbRaw )
258 signed char nShift = 0;
259 switch ( mnMode )
262 // PBM
263 case 0 :
264 while ( nHeight != mnHeight )
266 if ( mrPBM.IsEof() || mrPBM.GetError() )
267 return sal_False;
269 if ( --nShift < 0 )
271 mrPBM >> nDat;
272 nShift = 7;
274 mpAcc->SetPixelIndex( nHeight, nWidth, nDat >> nShift );
275 if ( ++nWidth == mnWidth )
277 nShift = 0;
278 nWidth = 0;
279 nHeight++;
280 ImplCallback( (sal_uInt16)( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
283 break;
285 // PGM
286 case 1 :
287 while ( nHeight != mnHeight )
289 if ( mrPBM.IsEof() || mrPBM.GetError() )
290 return sal_False;
292 mrPBM >> nDat;
293 mpAcc->SetPixelIndex( nHeight, nWidth++, nDat);
295 if ( nWidth == mnWidth )
297 nWidth = 0;
298 nHeight++;
299 ImplCallback( (sal_uInt16)( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
302 break;
304 // PPM
305 case 2 :
306 while ( nHeight != mnHeight )
308 if ( mrPBM.IsEof() || mrPBM.GetError() )
309 return sal_False;
311 sal_uInt8 nR, nG, nB;
312 sal_uLong nRed, nGreen, nBlue;
313 mrPBM >> nR >> nG >> nB;
314 nRed = 255 * nR / mnMaxVal;
315 nGreen = 255 * nG / mnMaxVal;
316 nBlue = 255 * nB / mnMaxVal;
317 mpAcc->SetPixel( nHeight, nWidth++, BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
318 if ( nWidth == mnWidth )
320 nWidth = 0;
321 nHeight++;
322 ImplCallback( (sal_uInt16) ( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
325 break;
328 else switch ( mnMode )
330 // PBM
331 case 0 :
332 while ( bFinished == sal_False )
334 if ( mrPBM.IsEof() || mrPBM.GetError() )
335 return sal_False;
337 mrPBM >> nDat;
339 if ( nDat == '#' )
341 mbRemark = sal_True;
342 continue;
344 else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
346 mbRemark = sal_False;
347 continue;
349 if ( mbRemark || nDat == 0x20 || nDat == 0x09 )
350 continue;
352 if ( nDat == '0' || nDat == '1' )
354 mpAcc->SetPixelIndex( nHeight, nWidth, static_cast<sal_uInt8>(nDat - '0') );
355 nWidth++;
356 if ( nWidth == mnWidth )
358 nWidth = 0;
359 if ( ++nHeight == mnHeight )
360 bFinished = sal_True;
361 ImplCallback( (sal_uInt16) ( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
364 else
365 return sal_False;
367 break;
369 // PGM
370 case 1 :
372 bPara = sal_False;
373 nCount = 0;
374 nGrey = 0;
376 while ( bFinished == sal_False )
378 if ( nCount )
380 nCount--;
381 if ( nGrey <= mnMaxVal )
382 nGrey = 255 * nGrey / mnMaxVal;
383 mpAcc->SetPixelIndex( nHeight, nWidth++, static_cast<sal_uInt8>(nGrey) );
384 nGrey = 0;
385 if ( nWidth == mnWidth )
387 nWidth = 0;
388 if ( ++nHeight == mnHeight )
389 bFinished = sal_True;
390 ImplCallback( (sal_uInt16) ( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
392 continue;
395 if ( mrPBM.IsEof() || mrPBM.GetError() )
396 return sal_False;
398 mrPBM >> nDat;
400 if ( nDat == '#' )
402 mbRemark = sal_True;
403 if ( bPara )
405 bPara = sal_False;
406 nCount++;
408 continue;
410 else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
412 mbRemark = sal_False;
413 if ( bPara )
415 bPara = sal_False;
416 nCount++;
418 continue;
421 if ( nDat == 0x20 || nDat == 0x09 )
423 if ( bPara )
425 bPara = sal_False;
426 nCount++;
428 continue;
430 if ( nDat >= '0' && nDat <= '9' )
432 bPara = sal_True;
433 nGrey *= 10;
434 nGrey += nDat-'0';
435 continue;
437 else
438 return sal_False;
440 break;
444 // PPM
445 case 2 :
447 bPara = sal_False;
448 nCount = 0;
449 nRGB[ 0 ] = nRGB[ 1 ] = nRGB[ 2 ] = 0;
451 while ( bFinished == sal_False )
453 if ( nCount == 3 )
455 nCount = 0;
456 mpAcc->SetPixel( nHeight, nWidth++, BitmapColor( static_cast< sal_uInt8 >( ( nRGB[ 0 ] * 255 ) / mnMaxVal ),
457 static_cast< sal_uInt8 >( ( nRGB[ 1 ] * 255 ) / mnMaxVal ),
458 static_cast< sal_uInt8 >( ( nRGB[ 2 ] * 255 ) / mnMaxVal ) ) );
459 nCount = 0;
460 nRGB[ 0 ] = nRGB[ 1 ] = nRGB[ 2 ] = 0;
461 if ( nWidth == mnWidth )
463 nWidth = 0;
464 if ( ++nHeight == mnHeight )
465 bFinished = sal_True;
466 ImplCallback( (sal_uInt16) ( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
468 continue;
471 if ( mrPBM.IsEof() || mrPBM.GetError() )
472 return sal_False;
474 mrPBM >> nDat;
476 if ( nDat == '#' )
478 mbRemark = sal_True;
479 if ( bPara )
481 bPara = sal_False;
482 nCount++;
484 continue;
486 else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
488 mbRemark = sal_False;
489 if ( bPara )
491 bPara = sal_False;
492 nCount++;
494 continue;
497 if ( nDat == 0x20 || nDat == 0x09 )
499 if ( bPara )
501 bPara = sal_False;
502 nCount++;
504 continue;
506 if ( nDat >= '0' && nDat <= '9' )
508 bPara = sal_True;
509 nRGB[ nCount ] *= 10;
510 nRGB[ nCount ] += nDat-'0';
511 continue;
513 else
514 return sal_False;
516 break;
518 return mbStatus;
521 //================== GraphicImport - the exported function ================
523 // this needs to be kept in sync with
524 // ImpFilterLibCacheEntry::GetImportFunction() from
525 // vcl/source/filter/graphicfilter.cxx
526 #if defined(DISABLE_DYNLOADING)
527 #define GraphicImport ipbGraphicImport
528 #endif
530 extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL
531 GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, sal_Bool)
533 PBMReader aPBMReader(rStream);
535 return aPBMReader.ReadPBM(rGraphic );
538 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */