@@ -374,31 +374,33 @@ bool PxMDecoder::readData( Mat& img )
374
374
375
375
// ////////////////////////////////////////////////////////////////////////////////////////
376
376
377
- PxMEncoder::PxMEncoder ()
377
+ PxMEncoder::PxMEncoder (PxMMode mode) :
378
+ mode_ (mode)
378
379
{
379
- m_description = " Portable image format (*.pbm;*.pgm;*.ppm;*.pxm;*.pnm)" ;
380
+ switch (mode)
381
+ {
382
+ case PXM_TYPE_AUTO: m_description = " Portable image format - auto (*.pnm)" ; break ;
383
+ case PXM_TYPE_PBM: m_description = " Portable image format - monochrome (*.pbm)" ; break ;
384
+ case PXM_TYPE_PGM: m_description = " Portable image format - gray (*.pgm)" ; break ;
385
+ case PXM_TYPE_PPM: m_description = " Portable image format - color (*.ppm)" ; break ;
386
+ default :
387
+ CV_Error (Error::StsInternal, " " );
388
+ }
380
389
m_buf_supported = true ;
381
390
}
382
391
383
-
384
392
PxMEncoder::~PxMEncoder ()
385
393
{
386
394
}
387
395
388
-
389
- ImageEncoder PxMEncoder::newEncoder () const
390
- {
391
- return makePtr<PxMEncoder>();
392
- }
393
-
394
-
395
- bool PxMEncoder::isFormatSupported ( int depth ) const
396
+ bool PxMEncoder::isFormatSupported (int depth) const
396
397
{
398
+ if (mode_ == PXM_TYPE_PBM)
399
+ return depth == CV_8U;
397
400
return depth == CV_8U || depth == CV_16U;
398
401
}
399
402
400
-
401
- bool PxMEncoder::write ( const Mat& img, const std::vector<int >& params )
403
+ bool PxMEncoder::write (const Mat& img, const std::vector<int >& params)
402
404
{
403
405
bool isBinary = true ;
404
406
@@ -409,8 +411,29 @@ bool PxMEncoder::write( const Mat& img, const std::vector<int>& params )
409
411
int x, y;
410
412
411
413
for ( size_t i = 0 ; i < params.size (); i += 2 )
412
- if ( params[i] == CV_IMWRITE_PXM_BINARY )
414
+ {
415
+ if ( params[i] == IMWRITE_PXM_BINARY )
413
416
isBinary = params[i+1 ] != 0 ;
417
+ }
418
+
419
+ int mode = mode_;
420
+ if (mode == PXM_TYPE_AUTO)
421
+ {
422
+ mode = img.channels () == 1 ? PXM_TYPE_PGM : PXM_TYPE_PPM;
423
+ }
424
+
425
+ if (mode == PXM_TYPE_PGM && img.channels () > 1 )
426
+ {
427
+ CV_Error (Error::StsBadArg, " Portable bitmap(.pgm) expects gray image" );
428
+ }
429
+ if (mode == PXM_TYPE_PPM && img.channels () != 3 )
430
+ {
431
+ CV_Error (Error::StsBadArg, " Portable bitmap(.ppm) expects BGR image" );
432
+ }
433
+ if (mode == PXM_TYPE_PBM && img.type () != CV_8UC1)
434
+ {
435
+ CV_Error (Error::StsBadArg, " For portable bitmap(.pbm) type must be CV_8UC1" );
436
+ }
414
437
415
438
WLByteStream strm;
416
439
@@ -441,18 +464,58 @@ bool PxMEncoder::write( const Mat& img, const std::vector<int>& params )
441
464
char * buffer = _buffer;
442
465
443
466
// write header;
444
- sprintf ( buffer, " P%c\n # Generated by OpenCV %s\n %d %d\n %d\n " ,
445
- ' 2' + (channels > 1 ? 1 : 0 ) + (isBinary ? 3 : 0 ),
446
- CV_VERSION,
447
- width, height, (1 << depth) - 1 );
467
+ const int code = ((mode == PXM_TYPE_PBM) ? 1 : (mode == PXM_TYPE_PGM) ? 2 : 3 )
468
+ + (isBinary ? 3 : 0 );
469
+ const char * comment = " # Generated by OpenCV " CV_VERSION " \n " ;
470
+
471
+ int header_sz = sprintf (buffer, " P%c\n %s%d %d\n " ,
472
+ (char )(' 0' + code), comment,
473
+ width, height);
474
+ CV_Assert (header_sz > 0 );
475
+ if (mode != PXM_TYPE_PBM)
476
+ {
477
+ int sz = sprintf (&buffer[header_sz], " %d\n " , (1 << depth) - 1 );
478
+ CV_Assert (sz > 0 );
479
+ header_sz += sz;
480
+ }
448
481
449
- strm.putBytes ( buffer, ( int ) strlen (buffer) );
482
+ strm.putBytes (buffer, header_sz );
450
483
451
484
for ( y = 0 ; y < height; y++ )
452
485
{
453
486
const uchar* const data = img.ptr (y);
454
487
if ( isBinary )
455
488
{
489
+ if (mode == PXM_TYPE_PBM)
490
+ {
491
+ char * ptr = buffer;
492
+ int bcount = 7 ;
493
+ char byte = 0 ;
494
+ for (x = 0 ; x < width; x++)
495
+ {
496
+ if (bcount == 0 )
497
+ {
498
+ if (data[x] == 0 )
499
+ byte = (byte) | 1 ;
500
+ *ptr++ = byte;
501
+ bcount = 7 ;
502
+ byte = 0 ;
503
+ }
504
+ else
505
+ {
506
+ if (data[x] == 0 )
507
+ byte = (byte) | (1 << bcount);
508
+ bcount--;
509
+ }
510
+ }
511
+ if (bcount != 7 )
512
+ {
513
+ *ptr++ = byte;
514
+ }
515
+ strm.putBytes (buffer, (int )(ptr - buffer));
516
+ continue ;
517
+ }
518
+
456
519
if ( _channels == 3 )
457
520
{
458
521
if ( depth == 8 )
@@ -475,59 +538,72 @@ bool PxMEncoder::write( const Mat& img, const std::vector<int>& params )
475
538
buffer[x + 1 ] = v;
476
539
}
477
540
}
478
- strm.putBytes ( (channels > 1 || depth > 8 ) ? buffer : (const char *)data, fileStep );
541
+
542
+ strm.putBytes ( (channels > 1 || depth > 8 ) ? buffer : (const char *)data, fileStep);
479
543
}
480
544
else
481
545
{
482
546
char * ptr = buffer;
483
-
484
- if ( channels > 1 )
547
+ if (mode == PXM_TYPE_PBM)
485
548
{
486
- if ( depth == 8 )
549
+ CV_Assert (channels == 1 );
550
+ CV_Assert (depth == 8 );
551
+ for (x = 0 ; x < width; x++)
487
552
{
488
- for ( x = 0 ; x < width*channels; x += channels )
489
- {
490
- sprintf ( ptr, " % 4d" , data[x + 2 ] );
491
- ptr += 4 ;
492
- sprintf ( ptr, " % 4d" , data[x + 1 ] );
493
- ptr += 4 ;
494
- sprintf ( ptr, " % 4d" , data[x] );
495
- ptr += 4 ;
496
- *ptr++ = ' ' ;
497
- *ptr++ = ' ' ;
498
- }
499
- }
500
- else
501
- {
502
- for ( x = 0 ; x < width*channels; x += channels )
503
- {
504
- sprintf ( ptr, " % 6d" , ((const ushort *)data)[x + 2 ] );
505
- ptr += 6 ;
506
- sprintf ( ptr, " % 6d" , ((const ushort *)data)[x + 1 ] );
507
- ptr += 6 ;
508
- sprintf ( ptr, " % 6d" , ((const ushort *)data)[x] );
509
- ptr += 6 ;
510
- *ptr++ = ' ' ;
511
- *ptr++ = ' ' ;
512
- }
553
+ ptr[0 ] = data[x] ? ' 0' : ' 1' ;
554
+ ptr += 1 ;
513
555
}
514
556
}
515
557
else
516
558
{
517
- if ( depth == 8 )
559
+ if ( channels > 1 )
518
560
{
519
- for ( x = 0 ; x < width; x++ )
561
+ if ( depth == 8 )
562
+ {
563
+ for ( x = 0 ; x < width*channels; x += channels )
564
+ {
565
+ sprintf ( ptr, " % 4d" , data[x + 2 ] );
566
+ ptr += 4 ;
567
+ sprintf ( ptr, " % 4d" , data[x + 1 ] );
568
+ ptr += 4 ;
569
+ sprintf ( ptr, " % 4d" , data[x] );
570
+ ptr += 4 ;
571
+ *ptr++ = ' ' ;
572
+ *ptr++ = ' ' ;
573
+ }
574
+ }
575
+ else
520
576
{
521
- sprintf ( ptr, " % 4d" , data[x] );
522
- ptr += 4 ;
577
+ for ( x = 0 ; x < width*channels; x += channels )
578
+ {
579
+ sprintf ( ptr, " % 6d" , ((const ushort *)data)[x + 2 ] );
580
+ ptr += 6 ;
581
+ sprintf ( ptr, " % 6d" , ((const ushort *)data)[x + 1 ] );
582
+ ptr += 6 ;
583
+ sprintf ( ptr, " % 6d" , ((const ushort *)data)[x] );
584
+ ptr += 6 ;
585
+ *ptr++ = ' ' ;
586
+ *ptr++ = ' ' ;
587
+ }
523
588
}
524
589
}
525
590
else
526
591
{
527
- for ( x = 0 ; x < width; x++ )
592
+ if ( depth == 8 )
528
593
{
529
- sprintf ( ptr, " % 6d" , ((const ushort *)data)[x] );
530
- ptr += 6 ;
594
+ for ( x = 0 ; x < width; x++ )
595
+ {
596
+ sprintf ( ptr, " % 4d" , data[x] );
597
+ ptr += 4 ;
598
+ }
599
+ }
600
+ else
601
+ {
602
+ for ( x = 0 ; x < width; x++ )
603
+ {
604
+ sprintf ( ptr, " % 6d" , ((const ushort *)data)[x] );
605
+ ptr += 6 ;
606
+ }
531
607
}
532
608
}
533
609
}
0 commit comments