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 <vcl/graph.hxx>
31 : : #include <vcl/bmpacc.hxx>
32 : : #include <svtools/fltcall.hxx>
33 : :
34 : : //============================ PBMReader ==================================
35 : :
36 : : class PBMReader {
37 : :
38 : : private:
39 : :
40 : : SvStream& mrPBM; // Die einzulesende PBM-Datei
41 : :
42 : : sal_Bool mbStatus;
43 : : sal_Bool mbRemark; // sal_False wenn sich stream in einem Kommentar befindet
44 : : sal_Bool mbRaw; // RAW/ASCII MODE
45 : : sal_uLong mnMode; // 0->PBM, 1->PGM, 2->PPM
46 : : Bitmap maBmp;
47 : : BitmapWriteAccess* mpAcc;
48 : : sal_uLong mnWidth, mnHeight; // Bildausmass in Pixeln
49 : : sal_uLong mnCol;
50 : : sal_uLong mnMaxVal; // maximaler wert in den
51 : : sal_Bool ImplCallback( sal_uInt16 nPercent );
52 : : sal_Bool ImplReadBody();
53 : : sal_Bool ImplReadHeader();
54 : :
55 : : public:
56 : : PBMReader(SvStream & rPBM);
57 : : ~PBMReader();
58 : : sal_Bool ReadPBM(Graphic & rGraphic );
59 : : };
60 : :
61 : : //=================== Methoden von PBMReader ==============================
62 : :
63 : 0 : PBMReader::PBMReader(SvStream & rPBM)
64 : : : mrPBM( rPBM )
65 : : , mbStatus( sal_True )
66 : : , mbRemark( sal_False )
67 : : , mbRaw( sal_True )
68 : 0 : , mpAcc( NULL )
69 : : {
70 : 0 : }
71 : :
72 : 0 : PBMReader::~PBMReader()
73 : : {
74 : 0 : }
75 : :
76 : 0 : sal_Bool PBMReader::ImplCallback( sal_uInt16 /*nPercent*/ )
77 : : {
78 : : /*
79 : : if ( pCallback != NULL )
80 : : {
81 : : if ( ( (*pCallback)( pCallerData, nPercent ) ) == sal_True )
82 : : {
83 : : mrPBM.SetError( SVSTREAM_FILEFORMAT_ERROR );
84 : : return sal_True;
85 : : }
86 : : }
87 : : */
88 : 0 : return sal_False;
89 : : }
90 : :
91 : 0 : sal_Bool PBMReader::ReadPBM(Graphic & rGraphic )
92 : : {
93 : : sal_uInt16 i;
94 : :
95 : 0 : if ( mrPBM.GetError() )
96 : 0 : return sal_False;
97 : :
98 : 0 : mrPBM.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
99 : :
100 : : // Kopf einlesen:
101 : :
102 : 0 : if ( ( mbStatus = ImplReadHeader() ) == sal_False )
103 : 0 : return sal_False;
104 : :
105 : 0 : if ( ( mnMaxVal == 0 ) || ( mnWidth == 0 ) || ( mnHeight == 0 ) )
106 : 0 : return sal_False;
107 : :
108 : : // 0->PBM, 1->PGM, 2->PPM
109 : 0 : switch ( mnMode )
110 : : {
111 : : case 0 :
112 : 0 : maBmp = Bitmap( Size( mnWidth, mnHeight ), 1 );
113 : 0 : if ( ( mpAcc = maBmp.AcquireWriteAccess() ) == sal_False )
114 : 0 : return sal_False;
115 : 0 : mpAcc->SetPaletteEntryCount( 2 );
116 : 0 : mpAcc->SetPaletteColor( 0, BitmapColor( 0xff, 0xff, 0xff ) );
117 : 0 : mpAcc->SetPaletteColor( 1, BitmapColor( 0x00, 0x00, 0x00 ) );
118 : 0 : break;
119 : :
120 : : case 1 :
121 : 0 : if ( mnMaxVal <= 1 )
122 : 0 : maBmp = Bitmap( Size( mnWidth, mnHeight ), 1);
123 : 0 : else if ( mnMaxVal <= 15 )
124 : 0 : maBmp = Bitmap( Size( mnWidth, mnHeight ), 4);
125 : : else
126 : 0 : maBmp = Bitmap( Size( mnWidth, mnHeight ), 8);
127 : :
128 : 0 : if ( ( mpAcc = maBmp.AcquireWriteAccess() ) == sal_False )
129 : 0 : return sal_False;
130 : 0 : mnCol = (sal_uInt16)mnMaxVal + 1;
131 : 0 : if ( mnCol > 256 )
132 : 0 : mnCol = 256;
133 : :
134 : 0 : mpAcc->SetPaletteEntryCount( 256 );
135 : 0 : for ( i = 0; i < mnCol; i++ )
136 : : {
137 : 0 : sal_uLong nCount = 255 * i / mnCol;
138 : 0 : mpAcc->SetPaletteColor( i, BitmapColor( (sal_uInt8)nCount, (sal_uInt8)nCount, (sal_uInt8)nCount ) );
139 : : }
140 : 0 : break;
141 : : case 2 :
142 : 0 : maBmp = Bitmap( Size( mnWidth, mnHeight ), 24 );
143 : 0 : if ( ( mpAcc = maBmp.AcquireWriteAccess() ) == sal_False )
144 : 0 : return sal_False;
145 : 0 : break;
146 : : }
147 : :
148 : : // Bitmap-Daten einlesen
149 : 0 : mbStatus = ImplReadBody();
150 : :
151 : 0 : if ( mpAcc )
152 : : {
153 : 0 : maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
154 : : }
155 : 0 : if ( mbStatus )
156 : 0 : rGraphic = maBmp;
157 : :
158 : 0 : return mbStatus;
159 : : }
160 : :
161 : 0 : sal_Bool PBMReader::ImplReadHeader()
162 : : {
163 : : sal_uInt8 nID[ 2 ];
164 : : sal_uInt8 nDat;
165 : 0 : sal_uInt8 nMax, nCount = 0;
166 : 0 : sal_Bool bFinished = sal_False;
167 : :
168 : 0 : mrPBM >> nID[ 0 ] >> nID[ 1 ];
169 : 0 : if ( nID[ 0 ] != 'P' )
170 : 0 : return sal_False;
171 : 0 : mnMaxVal = mnWidth = mnHeight = 0;
172 : 0 : switch ( nID[ 1 ] )
173 : : {
174 : : case '1' :
175 : 0 : mbRaw = sal_False;
176 : : case '4' :
177 : 0 : mnMode = 0;
178 : 0 : nMax = 2; // number of parameters in Header
179 : 0 : mnMaxVal = 1;
180 : 0 : break;
181 : : case '2' :
182 : 0 : mbRaw = sal_False;
183 : : case '5' :
184 : 0 : mnMode = 1;
185 : 0 : nMax = 3;
186 : 0 : break;
187 : : case '3' :
188 : 0 : mbRaw = sal_False;
189 : : case '6' :
190 : 0 : mnMode = 2;
191 : 0 : nMax = 3;
192 : 0 : break;
193 : : default:
194 : 0 : return sal_False;
195 : : }
196 : 0 : while ( bFinished == sal_False )
197 : : {
198 : 0 : if ( mrPBM.GetError() )
199 : 0 : return sal_False;
200 : :
201 : 0 : mrPBM >> nDat;
202 : :
203 : 0 : if ( nDat == '#' )
204 : : {
205 : 0 : mbRemark = sal_True;
206 : 0 : continue;
207 : : }
208 : 0 : else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
209 : : {
210 : 0 : mbRemark = sal_False;
211 : 0 : nDat = 0x20;
212 : : }
213 : 0 : if ( mbRemark )
214 : 0 : continue;
215 : :
216 : 0 : if ( ( nDat == 0x20 ) || ( nDat == 0x09 ) )
217 : : {
218 : 0 : if ( ( nCount == 0 ) && mnWidth )
219 : 0 : nCount++;
220 : 0 : else if ( ( nCount == 1 ) && mnHeight )
221 : : {
222 : 0 : if ( ++nCount == nMax )
223 : 0 : bFinished = sal_True;
224 : : }
225 : 0 : else if ( ( nCount == 2 ) && mnMaxVal )
226 : : {
227 : 0 : bFinished = sal_True;
228 : : }
229 : 0 : continue;
230 : : }
231 : 0 : if ( ( nDat >= '0' ) && ( nDat <= '9' ) )
232 : : {
233 : 0 : nDat -= '0';
234 : 0 : if ( nCount == 0 )
235 : : {
236 : 0 : mnWidth *= 10;
237 : 0 : mnWidth += nDat;
238 : : }
239 : 0 : else if ( nCount == 1 )
240 : : {
241 : 0 : mnHeight *= 10;
242 : 0 : mnHeight += nDat;
243 : : }
244 : 0 : else if ( nCount == 2 )
245 : : {
246 : 0 : mnMaxVal *= 10;
247 : 0 : mnMaxVal += nDat;
248 : : }
249 : : }
250 : : else
251 : 0 : return sal_False;
252 : : }
253 : 0 : return mbStatus;
254 : : }
255 : :
256 : 0 : sal_Bool PBMReader::ImplReadBody()
257 : : {
258 : 0 : sal_Bool bPara, bFinished = sal_False;
259 : 0 : sal_uInt8 nDat = 0, nCount;
260 : : sal_uLong nGrey, nRGB[3];
261 : 0 : sal_uLong nWidth = 0;
262 : 0 : sal_uLong nHeight = 0;
263 : :
264 : 0 : if ( mbRaw )
265 : : {
266 : 0 : signed char nShift = 0;
267 : 0 : switch ( mnMode )
268 : : {
269 : :
270 : : // PBM
271 : : case 0 :
272 : 0 : while ( nHeight != mnHeight )
273 : : {
274 : 0 : if ( mrPBM.IsEof() || mrPBM.GetError() )
275 : 0 : return sal_False;
276 : :
277 : 0 : if ( --nShift < 0 )
278 : : {
279 : 0 : mrPBM >> nDat;
280 : 0 : nShift = 7;
281 : : }
282 : 0 : mpAcc->SetPixel( nHeight, nWidth, nDat >> nShift );
283 : 0 : if ( ++nWidth == mnWidth )
284 : : {
285 : 0 : nShift = 0;
286 : 0 : nWidth = 0;
287 : 0 : nHeight++;
288 : 0 : ImplCallback( (sal_uInt16)( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
289 : : }
290 : : }
291 : 0 : break;
292 : :
293 : : // PGM
294 : : case 1 :
295 : 0 : while ( nHeight != mnHeight )
296 : : {
297 : 0 : if ( mrPBM.IsEof() || mrPBM.GetError() )
298 : 0 : return sal_False;
299 : :
300 : 0 : mrPBM >> nDat;
301 : 0 : mpAcc->SetPixel( nHeight, nWidth++, nDat);
302 : :
303 : 0 : if ( nWidth == mnWidth )
304 : : {
305 : 0 : nWidth = 0;
306 : 0 : nHeight++;
307 : 0 : ImplCallback( (sal_uInt16)( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
308 : : }
309 : : }
310 : 0 : break;
311 : :
312 : : // PPM
313 : : case 2 :
314 : 0 : while ( nHeight != mnHeight )
315 : : {
316 : 0 : if ( mrPBM.IsEof() || mrPBM.GetError() )
317 : 0 : return sal_False;
318 : :
319 : : sal_uInt8 nR, nG, nB;
320 : : sal_uLong nRed, nGreen, nBlue;
321 : 0 : mrPBM >> nR >> nG >> nB;
322 : 0 : nRed = 255 * nR / mnMaxVal;
323 : 0 : nGreen = 255 * nG / mnMaxVal;
324 : 0 : nBlue = 255 * nB / mnMaxVal;
325 : 0 : mpAcc->SetPixel( nHeight, nWidth++, BitmapColor( (sal_uInt8)nRed, (sal_uInt8)nGreen, (sal_uInt8)nBlue ) );
326 : 0 : if ( nWidth == mnWidth )
327 : : {
328 : 0 : nWidth = 0;
329 : 0 : nHeight++;
330 : 0 : ImplCallback( (sal_uInt16) ( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
331 : : }
332 : : }
333 : 0 : break;
334 : : }
335 : : }
336 : 0 : else switch ( mnMode )
337 : : {
338 : : // PBM
339 : : case 0 :
340 : 0 : while ( bFinished == sal_False )
341 : : {
342 : 0 : if ( mrPBM.IsEof() || mrPBM.GetError() )
343 : 0 : return sal_False;
344 : :
345 : 0 : mrPBM >> nDat;
346 : :
347 : 0 : if ( nDat == '#' )
348 : : {
349 : 0 : mbRemark = sal_True;
350 : 0 : continue;
351 : : }
352 : 0 : else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
353 : : {
354 : 0 : mbRemark = sal_False;
355 : 0 : continue;
356 : : }
357 : 0 : if ( mbRemark || nDat == 0x20 || nDat == 0x09 )
358 : 0 : continue;
359 : :
360 : 0 : if ( nDat == '0' || nDat == '1' )
361 : : {
362 : 0 : mpAcc->SetPixel( nHeight, nWidth, (sal_uInt8)nDat-'0' );
363 : 0 : nWidth++;
364 : 0 : if ( nWidth == mnWidth )
365 : : {
366 : 0 : nWidth = 0;
367 : 0 : if ( ++nHeight == mnHeight )
368 : 0 : bFinished = sal_True;
369 : 0 : ImplCallback( (sal_uInt16) ( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
370 : : }
371 : : }
372 : : else
373 : 0 : return sal_False;
374 : : }
375 : 0 : break;
376 : :
377 : : // PGM
378 : : case 1 :
379 : :
380 : 0 : bPara = sal_False;
381 : 0 : nCount = 0;
382 : 0 : nGrey = 0;
383 : :
384 : 0 : while ( bFinished == sal_False )
385 : : {
386 : 0 : if ( nCount )
387 : : {
388 : 0 : nCount--;
389 : 0 : if ( nGrey <= mnMaxVal )
390 : 0 : nGrey = 255 * nGrey / mnMaxVal;
391 : 0 : mpAcc->SetPixel( nHeight, nWidth++, (sal_uInt8)nGrey );
392 : 0 : nGrey = 0;
393 : 0 : if ( nWidth == mnWidth )
394 : : {
395 : 0 : nWidth = 0;
396 : 0 : if ( ++nHeight == mnHeight )
397 : 0 : bFinished = sal_True;
398 : 0 : ImplCallback( (sal_uInt16) ( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
399 : : }
400 : 0 : continue;
401 : : }
402 : :
403 : 0 : if ( mrPBM.IsEof() || mrPBM.GetError() )
404 : 0 : return sal_False;
405 : :
406 : 0 : mrPBM >> nDat;
407 : :
408 : 0 : if ( nDat == '#' )
409 : : {
410 : 0 : mbRemark = sal_True;
411 : 0 : if ( bPara )
412 : : {
413 : 0 : bPara = sal_False;
414 : 0 : nCount++;
415 : : }
416 : 0 : continue;
417 : : }
418 : 0 : else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
419 : : {
420 : 0 : mbRemark = sal_False;
421 : 0 : if ( bPara )
422 : : {
423 : 0 : bPara = sal_False;
424 : 0 : nCount++;
425 : : }
426 : 0 : continue;
427 : : }
428 : :
429 : 0 : if ( nDat == 0x20 || nDat == 0x09 )
430 : : {
431 : 0 : if ( bPara )
432 : : {
433 : 0 : bPara = sal_False;
434 : 0 : nCount++;
435 : : }
436 : 0 : continue;
437 : : }
438 : 0 : if ( nDat >= '0' && nDat <= '9' )
439 : : {
440 : 0 : bPara = sal_True;
441 : 0 : nGrey *= 10;
442 : 0 : nGrey += nDat-'0';
443 : 0 : continue;
444 : : }
445 : : else
446 : 0 : return sal_False;
447 : : }
448 : 0 : break;
449 : :
450 : :
451 : :
452 : : // PPM
453 : : case 2 :
454 : :
455 : 0 : bPara = sal_False;
456 : 0 : nCount = 0;
457 : 0 : nRGB[ 0 ] = nRGB[ 1 ] = nRGB[ 2 ] = 0;
458 : :
459 : 0 : while ( bFinished == sal_False )
460 : : {
461 : 0 : if ( nCount == 3 )
462 : : {
463 : 0 : nCount = 0;
464 : 0 : mpAcc->SetPixel( nHeight, nWidth++, BitmapColor( static_cast< sal_uInt8 >( ( nRGB[ 0 ] * 255 ) / mnMaxVal ),
465 : 0 : static_cast< sal_uInt8 >( ( nRGB[ 1 ] * 255 ) / mnMaxVal ),
466 : 0 : static_cast< sal_uInt8 >( ( nRGB[ 2 ] * 255 ) / mnMaxVal ) ) );
467 : 0 : nCount = 0;
468 : 0 : nRGB[ 0 ] = nRGB[ 1 ] = nRGB[ 2 ] = 0;
469 : 0 : if ( nWidth == mnWidth )
470 : : {
471 : 0 : nWidth = 0;
472 : 0 : if ( ++nHeight == mnHeight )
473 : 0 : bFinished = sal_True;
474 : 0 : ImplCallback( (sal_uInt16) ( ( 100 * nHeight ) / mnHeight ) ); // processing output in percent
475 : : }
476 : 0 : continue;
477 : : }
478 : :
479 : 0 : if ( mrPBM.IsEof() || mrPBM.GetError() )
480 : 0 : return sal_False;
481 : :
482 : 0 : mrPBM >> nDat;
483 : :
484 : 0 : if ( nDat == '#' )
485 : : {
486 : 0 : mbRemark = sal_True;
487 : 0 : if ( bPara )
488 : : {
489 : 0 : bPara = sal_False;
490 : 0 : nCount++;
491 : : }
492 : 0 : continue;
493 : : }
494 : 0 : else if ( ( nDat == 0x0d ) || ( nDat == 0x0a ) )
495 : : {
496 : 0 : mbRemark = sal_False;
497 : 0 : if ( bPara )
498 : : {
499 : 0 : bPara = sal_False;
500 : 0 : nCount++;
501 : : }
502 : 0 : continue;
503 : : }
504 : :
505 : 0 : if ( nDat == 0x20 || nDat == 0x09 )
506 : : {
507 : 0 : if ( bPara )
508 : : {
509 : 0 : bPara = sal_False;
510 : 0 : nCount++;
511 : : }
512 : 0 : continue;
513 : : }
514 : 0 : if ( nDat >= '0' && nDat <= '9' )
515 : : {
516 : 0 : bPara = sal_True;
517 : 0 : nRGB[ nCount ] *= 10;
518 : 0 : nRGB[ nCount ] += nDat-'0';
519 : 0 : continue;
520 : : }
521 : : else
522 : 0 : return sal_False;
523 : : }
524 : 0 : break;
525 : : }
526 : 0 : return mbStatus;
527 : : }
528 : :
529 : : //================== GraphicImport - die exportierte Funktion ================
530 : :
531 : : extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool __LOADONCALLAPI
532 : 0 : GraphicImport(SvStream & rStream, Graphic & rGraphic, FilterConfigItem*, sal_Bool)
533 : : {
534 : 0 : PBMReader aPBMReader(rStream);
535 : :
536 : 0 : return aPBMReader.ReadPBM(rGraphic );
537 : : }
538 : :
539 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|