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