xref: /AOO42X/main/filter/source/graphicfilter/ipbm/ipbm.cxx (revision b1c5455db1639c48e26c568e4fa7ee78ca5d60ee)
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