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