PGF Console 6.21.2
Loading...
Searching...
No Matches
PGF.cpp File Reference
#include <iostream>
#include <cmath>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctime>
#include <fcntl.h>
#include <string>
#include "PGFimage.h"
#include <windows.h>
#include "CImage.h"

Go to the source code of this file.

Macros

#define PGFConsoleVersion   "7.21.07"
 
#define CurrentYear   "2021"
 
#define __PGFROISUPPORT__
 

Functions

static INT64 FileSize (char *filename)
 
static void PSNR (const CImage &image1, const CImage &image2, bool roi, PGFRect &rect)
 
static bool Encoding (CImage *&image, char *source, char *dest, int levels, int quality, bool roi, bool streaming, CPGFMemoryStream **memStream)
 
static bool Decoding (CImage *&image, char *source, char *dest, int level, bool roi, PGFRect &rect, bool streaming, CPGFMemoryStream **memStream)
 
static bool Measurement (char *source, char *dest, char *temp, int levels, int level, int quality, bool roi, PGFRect &rect, bool streaming, bool useMemStream)
 
int main (int argc, char *argv[])
 

Variables

static bool bQuiet = false
 
static string PGFErrors []
 

Macro Definition Documentation

◆ __PGFROISUPPORT__

#define __PGFROISUPPORT__

Definition at line 33 of file PGF.cpp.

◆ CurrentYear

#define CurrentYear   "2021"

Definition at line 28 of file PGF.cpp.

◆ PGFConsoleVersion

#define PGFConsoleVersion   "7.21.07"

Definition at line 27 of file PGF.cpp.

Function Documentation

◆ Decoding()

static bool Decoding ( CImage *& image,
char * source,
char * dest,
int level,
bool roi,
PGFRect & rect,
bool streaming,
CPGFMemoryStream ** memStream )
static

Definition at line 458 of file PGF.cpp.

458 {
459#ifndef __PGFROISUPPORT__
460 ASSERT(!roi);
461 ASSERT(!streaming);
462 rect;
463#endif
464 ASSERT(dest);
465 bool returnValue = true;
466 CPGFImage pgf;
467 clock_t start = 0, mean = 0, mean2 = 0, mean3 = 0, end = 0;
468 CPGFStream *stream = nullptr;
469 UINT8* buff = nullptr;
470 double sourceSize = 0;
471#ifdef WIN32
472 HANDLE fd = nullptr;
473#elif defined(__POSIX__)
474 int fd = 0;
475#endif
476
477 if (memStream) {
478 // use memory stream
479 stream = *memStream;
480 } else {
481 ASSERT(source);
482 #ifdef WIN32
483 // no other choice to get a "HANDLE"
484 fd = CreateFile(source, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
485 if (fd == INVALID_HANDLE_VALUE) {
486 cerr << "Error: Could not open source file." << endl;
487 fd = nullptr;
488 returnValue = false;
489 goto CleanUp;
490 }
491
492 // create stream object
493 stream = new CPGFFileStream(fd);
494
495 #elif defined(__POSIX__)
496 fd = open(source, O_RDONLY);
497 if (fd == -1){
498 cout << "Error: Could not open source file." << endl;
499 fd = 0;
500 returnValue = false;
501 goto CleanUp;
502 }
503
504 // create stream object
505 stream = new CPGFFileStream(fd);
506 #endif
507 }
508
509 // optional PGF encoder configuration
510 pgf.ConfigureDecoder(true); // true: use openMP (if codec is compiled with openMP)
511
512 if (memStream) {
513 if (!bQuiet) cout << "Decoding PGF image from memory stream." << endl;
514 } else {
515 if (!bQuiet) cout << "Decoding PGF image: " << source << endl;
516 }
517
518 start = clock();
519 try {
520 // open pgf image
521 UINT64 startpos = stream->GetPos();
522 pgf.Open(stream);
523 if (!bQuiet) cout << "Read header and level info [" << stream->GetPos() - startpos << " bytes]" << endl;
524
525 // read annotations
526 if (!bQuiet) {
527 UINT32 len = 0;
528 const UINT8 *data = pgf.GetUserData(len);
529 if (data && len) {
530 cout << (char *)data << endl;
531 }
532 }
533
534 // read pgf image
535 #ifdef __PGFROISUPPORT__
536 if (pgf.ROIisSupported()) {
537 if (memStream) {
538 if (!bQuiet) cout << "PGF image supports ROI." << endl;
539 } else {
540 if (!bQuiet) cout << source << " supports ROI." << endl;
541 }
542 if (!bQuiet && roi) cout << "Decode ROI (" << rect.left << "," << rect.top << "," << rect.Width() << "," << rect.Height() << ")"<< endl;
543 }
544 if (roi) {
545 pgf.Read(rect, level); // ROI test
546 } else {
547 if (streaming) {
548 // decode each level separately
549 for (int i = pgf.Levels() - 1; i >= 0; i--) {
550 if (!bQuiet) cout << "Read level " << i;
551 UINT64 pos = stream->GetPos();
552 pgf.Read(i);
553 if (!bQuiet) cout << " [" << stream->GetPos() - pos << " bytes]" << endl;
554 }
555 }
556 }
557 #else
558 cout << "PGF Console: ROI supports has been disabled." << endl;
559 #endif
560 if (!roi && !streaming) {
561 pgf.Read(level);
562 }
563 sourceSize = double(stream->GetPos() - startpos);
564
565 } catch(IOException& e) {
566 int err = e.error;
567 if (err >= AppError) {
568 cerr << "Error: Opening and reading PGF image failed\n(" << PGFErrors[err - AppError] << ")!" << endl;
569 } else {
570 cerr << "Error: Opening and reading PGF image failed (" << err << ")!" << endl;
571 }
572
573 returnValue = false;
574 goto CleanUp;
575 }
576 mean = clock();
577
578 // create image
579 image = new CImage();
580#ifdef __PGFROISUPPORT__
581 if (roi) {
582 const PGFRect r = pgf.ComputeLevelROI();
583 if (!image->Create(r.Width(), r.Height(), pgf.Mode())) {
584 cerr << "Decoding is not supported for this PGF color format." << endl;
585 returnValue = false;
586 goto CleanUp;
587 }
588 } else
589#endif
590 {
591 if (!image->Create(pgf.Width(level), pgf.Height(level), pgf.Mode())) {
592 cerr << "Decoding is not supported for this PGF color format." << endl;
593 returnValue = false;
594 goto CleanUp;
595 }
596 }
597
598 // copy bits
599 mean2 = clock();
600 buff = (UINT8 *)image->GetBits();
601 if (pgf.Mode() == ImageModeRGB48) {
602 int map[] = { 2, 1, 0 };
603 pgf.GetBitmap(-image->GetPitch(), &(buff[(image->GetHeight() - 1) * image->GetPitch()]), image->GetBPP(), map);
604 } else {
605#ifdef __BIG_ENDIAN__
606 int map[] = { 2, 1, 0 };
607 pgf.GetBitmap(-image->GetPitch(), &(buff[(image->GetHeight() - 1) * image->GetPitch()]), image->GetBPP(), map);
608#else
609 pgf.GetBitmap(-image->GetPitch(), &(buff[(image->GetHeight() - 1) * image->GetPitch()]), image->GetBPP());
610#endif
611 }
612
613 // update color table if image is indexed or bitmap
614 if ((pgf.Mode() == ImageModeIndexedColor)) {
615 // cannot get number of color table entries directly, so use 2^bitdepth
616 image->SetColorTable(0, 1 << pgf.BPP(), pgf.GetColorTable());
617 } else if (pgf.Mode() == ImageModeBitmap) {
618 RGBQUAD bw[2];
619 bw[0].rgbRed = 255;
620 bw[0].rgbGreen = 255;
621 bw[0].rgbBlue = 255;
622 bw[1].rgbRed = 0;
623 bw[1].rgbGreen = 0;
624 bw[1].rgbBlue = 0;
625 image->SetColorTable(0, 2, bw);
626 }
627
628 mean3 = clock();
629
630#ifdef __PNMEXSUPPORT__
631 if (image->GetChannelDepth() > 8) {
632 // set maximum value
633 image->SetMaxValue(pgf.GetMaxValue());
634 }
635#endif
636
637 // save image
638 if (image->Save(dest)) {
639 if (!bQuiet) cout << "Written image file: " << dest << endl;
640 } else {
641 cerr << "Error: Output format not supported for this color depth." << endl;
642 return false;
643 }
644
645 end = clock();
646
647 // example of how to make a second read (with a different ROI) after resetting stream position to data
648 //pgf.ResetStreamPos(true);
649 //pgf.Read(rect);
650
651 // less efficient variant:
652 //pgf.ResetStreamPos(false); pgf.Open(stream);
653 //pgf.Read(rect);
654
655CleanUp:
656 if (memStream) {
657 stream->SetPos(FSFromStart, 0);
658 } else {
659 // close file
660#ifdef WIN32
661 if (fd) CloseHandle(fd);
662#elif defined(__POSIX__)
663 if (fd) close(fd);
664#endif
665 delete stream;
666 }
667
668 if (!memStream) {
669 // source has to be closed before FileSize
670 sourceSize = (double)FileSize(source);
671 }
672
673 if (returnValue) {
674 // output
675 double ratio = double(FileSize(dest))/sourceSize;
676 if (bQuiet) {
677 cout << double(mean3 - mean2 + mean - start)/CLOCKS_PER_SEC << ';' << double(end - mean3 + mean3 - mean2 + mean - start)/CLOCKS_PER_SEC << ';' << ratio << ';';
678 } else {
679 if (level == 0) {
680 cout << "Decoding time (reading PGF, decoding): " << double(mean3 - mean2 + mean - start)/CLOCKS_PER_SEC << " s" << endl;
681 } else {
682 cout << "Decoding time (reading PGF down to level " << level << ", decoding): " << double(mean3 - mean2 + mean - start)/CLOCKS_PER_SEC << " s" << endl;
683 }
684 cout << "Total time (reading PGF, decoding, writing destination): " << double(end - mean3 + mean3 - mean2 + mean - start)/CLOCKS_PER_SEC << " s" << endl;
685 cout << "Compression ratio: " << ratio << endl;
686 cout << endl;
687 }
688 }
689 return returnValue;
690}
#define ImageModeBitmap
Definition CImage.h:33
#define ImageModeRGB48
Definition CImage.h:44
#define ImageModeIndexedColor
Definition CImage.h:35
static INT64 FileSize(char *filename)
Definition PGF.cpp:94
static string PGFErrors[]
Definition PGF.cpp:79
static bool bQuiet
Definition PGF.cpp:78
bool Create(int width, int height, int bpp)
Definition CImage.cpp:43
unsigned char * GetBits() const
Definition CImage.cpp:97
void SetMaxValue(int maxValue)
Definition CImage.cpp:319
void SetColorTable(int firstColor, int numColors, const void *prgbColors)
Definition CImage.cpp:167
int GetPitch() const
Definition CImage.cpp:102
unsigned int GetHeight() const
Definition CImage.cpp:112
unsigned char GetBPP() const
Definition CImage.cpp:107
bool Save(const char *dest)
Definition CImage.cpp:122
int GetChannelDepth() const
Definition CImage.cpp:250

◆ Encoding()

static bool Encoding ( CImage *& image,
char * source,
char * dest,
int levels,
int quality,
bool roi,
bool streaming,
CPGFMemoryStream ** memStream )
static

Definition at line 218 of file PGF.cpp.

218 {
219#ifndef __PGFROISUPPORT__
220 ASSERT(!roi);
221 ASSERT(!streaming);
222#endif
223 ASSERT(source);
224 ASSERT(0 <= quality && quality <= MaxQuality);
225 bool returnValue = true;
226 CPGFImage pgf;
227 PGFHeader header;
228 clock_t start = 0, mean = 0, end = 0;
229 UINT32 writtenBytes = 0;
230 CPGFStream *stream = nullptr;
231 UINT8 bpp = 0;
232#ifdef WIN32
233 HANDLE fd = nullptr;
234#elif defined(__POSIX__)
235 int fd = 0;
236#endif
237
238 if (!memStream) {
239 ASSERT(dest);
240 #ifdef WIN32
241 // no other choice to get a "HANDLE"
242 fd = CreateFile(dest, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
243 if (fd == INVALID_HANDLE_VALUE) {
244 cerr << "Error: Could not open destination file." << endl;
245 fd = nullptr;
246 returnValue = false;
247 goto CleanUp;
248 }
249
250 // create stream object
251 stream = new CPGFFileStream(fd);
252
253 #elif defined(__POSIX__)
254 fd = open(dest, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
255 if (fd == -1) {
256 cout << "Error: Could not open destination file." << endl;
257 fd = 0;
258 returnValue = false;
259 goto CleanUp;
260 }
261
262 // create stream object
263 stream = new CPGFFileStream(fd);
264 #endif
265 }
266
267 if (memStream) {
268 if (!bQuiet) cout << "Encoding PGF image to memory stream (quality: " << quality << ", levels: " << levels << "): " << source << endl;
269 } else {
270 if (!bQuiet) cout << "Encoding PGF image (quality: " << quality << ", levels: " << levels << "): " << source << endl;
271 }
272 if (roi || streaming) {
273 if (memStream) {
274 cout << "PGF image will support ROI." << endl;
275 } else {
276 cout << dest << " will support ROI." << endl;
277 }
278 }
279
280 start = clock();
281
282 // create new image object
283 image = new CImage();
284
285 // load image
286#ifdef WIN32
287 if (!image->Load(source)) {
288 LPTSTR lpMsgBuf;
289 FormatMessage(
290 FORMAT_MESSAGE_ALLOCATE_BUFFER |
291 FORMAT_MESSAGE_FROM_SYSTEM |
292 FORMAT_MESSAGE_IGNORE_INSERTS,
293 nullptr,
294 GetLastError(),
295 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
296 (LPTSTR)&lpMsgBuf,
297 0,
298 nullptr
299 );
300 cerr << "Error: " << lpMsgBuf << endl;
301 LocalFree(lpMsgBuf);
302 returnValue = false;
303 goto CleanUp;
304 }
305#elif defined(__POSIX__)
306 if (!image->Load(source) ){
307 cerr << "Error: Could not load source file." << endl;
308 returnValue = false;
309 goto CleanUp;
310 }
311#endif
312
313 bpp = image->GetBPP();
314 // minimum: 1-bit bitmap, maximum: 48-bit RGB (16-bit per channel)
315 if ((bpp < 1) || (bpp > 48) || (bpp == 4)) {
316 cerr << "Error: Unhandled image format." << endl;
317 returnValue = false;
318 goto CleanUp;
319 }
320
321 ASSERT((bpp >= 1) && (bpp <= 48) && (bpp != 4));
322
323 if (memStream) {
324 *memStream = new CPGFMemoryStream(abs(image->GetPitch())*image->GetHeight());
325 stream = *memStream;
326 }
327
328 mean = clock();
329
330 // optional PGF encoder configuration
331 pgf.ConfigureEncoder(true, false); // true: use openMP (if codec is compiled with openMP), false: favorSpeedOverSize
332
333 header.width = image->GetWidth();
334 header.height = image->GetHeight();
335 header.nLevels = (UINT8)levels;
336 header.quality = (UINT8)quality;
337 header.mode = image->GetColorType();
338 header.bpp = header.channels = 0; // depend on mode and will be set automatically
339 header.usedBitsPerChannel = 0; // depend on mode and bpp and will be set automatically
340
341 try {
342 if (bQuiet) {
343 pgf.SetHeader(header, (roi || streaming) ? PGFROI : 0);
344 } else {
345 char data[] = "This is a free text annotation.";
346 pgf.SetHeader(header, (roi || streaming) ? PGFROI : 0, (UINT8 *)data, sizeof(data));
347 }
348
349#ifdef __PNMEXSUPPORT__
350 if (image->GetChannelDepth() > 8) {
351 // set maximum value
352 pgf.SetMaxValue(image->GetMaxValue());
353 }
354#endif
355
356 // copy bits
357 UINT8* buff = (UINT8 *)image->GetBits();
358 if (pgf.Mode() == ImageModeRGB48) {
359 int map[] = { 2, 1, 0 };
360 pgf.ImportBitmap(-image->GetPitch(), &(buff[(image->GetHeight() - 1)*image->GetPitch()]), bpp, map);
361 } else {
362#ifdef __BIG_ENDIAN__
363 int map[] = { 2, 1, 0 };
364 pgf.ImportBitmap(-image->GetPitch(), &(buff[(image->GetHeight() - 1)*image->GetPitch()]), bpp, map);
365#else
366 pgf.ImportBitmap(-image->GetPitch(), &(buff[(image->GetHeight() - 1)*image->GetPitch()]), bpp);
367#endif
368 }
369
370 // update color table if image is indexed
371 if ((pgf.Mode() == ImageModeIndexedColor)) {
372 int colorTableSize = image->GetMaxColorTableEntries();
373 RGBQUAD* pColorTable = new RGBQUAD[colorTableSize];
374
375 image->GetColorTable(0, colorTableSize, pColorTable);
376 pgf.SetColorTable(0, colorTableSize, pColorTable);
377 delete[] pColorTable;
378 }
379
380 } catch(IOException& e) {
381 int err = e.error;
382
383 if (err >= AppError) {
384 cerr << "Error: Importing input image failed\n(" << PGFErrors[err - AppError] << ")!" << endl;
385 } else {
386 cerr << "Error: Importing input image failed (" << err << ")!" << endl;
387 }
388 returnValue = false;
389 goto CleanUp;
390 }
391
392 try {
393 #ifdef __PGFROISUPPORT__
394 if (streaming) {
395 // process and write header
396 writtenBytes = pgf.WriteHeader(stream);
397 if (!bQuiet) cout << "Write header [" << writtenBytes << " bytes]" << endl;
398 // encode each level separately
399 for(int i = pgf.Levels() - 1; i >= 0; i--) {
400 UINT32 size = pgf.Write(i);
401 if (!bQuiet) cout << "Write level " << i << " [" << size << " bytes]" << endl;
402 writtenBytes += size;
403 }
404 } else
405 #endif __PGFROISUPPORT__
406 {
407 // write image to pgf-file
408 pgf.Write(stream, &writtenBytes);
409 }
410
411 } catch(IOException& e) {
412 int err = e.error;
413 if (err >= AppError) {
414 cerr << "Error: Writing PGF image failed\n(" << PGFErrors[err - AppError] << ")!" << endl;
415 } else {
416 cerr << "Error: Writing PGF image failed (" << err << ")!" << endl;
417 }
418 returnValue = false;
419 goto CleanUp;
420 }
421
422 end = clock();
423
424CleanUp:
425 if (memStream) {
426 // reset stream position
427 pgf.ResetStreamPos(false);
428 } else {
429 // close file
430#ifdef WIN32
431 if (fd) CloseHandle(fd);
432#elif defined(__POSIX__)
433 if (fd) close(fd);
434#endif
435 delete stream;
436 }
437
438 if (returnValue) {
439 // output: output file has to be closed before FileSize
440 double destSize = (memStream) ? writtenBytes : double(FileSize(dest));
441 double ratio = double(FileSize(source))/destSize;
442
443 if (bQuiet) {
444 cout << double(end - mean)/CLOCKS_PER_SEC << ';' << double(end - start)/CLOCKS_PER_SEC << ';' << ratio << ';';
445 } else {
446 cout << "Written bytes: " << writtenBytes << endl;
447 cout << "Encoding time (encoding, writing PGF): " << double(end - mean)/CLOCKS_PER_SEC << " s" << endl;
448 cout << "Total time (reading source, encoding, writing PGF): " << double(end - start)/CLOCKS_PER_SEC << " s" << endl;
449 cout << "Compression ratio: " << ratio << endl;
450 cout << endl;
451 }
452 }
453
454 return returnValue;
455}
unsigned int GetWidth() const
Definition CImage.cpp:117
int GetMaxValue() const
Definition CImage.cpp:323
int GetMaxColorTableEntries()
Definition CImage.cpp:151
bool Load(const char *source)
Definition CImage.cpp:127
void GetColorTable(int firstColor, int numColors, void *prgbColors)
Definition CImage.cpp:156
unsigned char GetColorType() const
Definition CImage.cpp:178

◆ FileSize()

static INT64 FileSize ( char * filename)
static

Definition at line 94 of file PGF.cpp.

94 {
95 struct __stat64 data;
96
97 if (_stat64(filename, &data) != -1) {
98 return data.st_size;
99 } else {
100 return 0;
101 }
102}

◆ main()

int main ( int argc,
char * argv[] )

Definition at line 730 of file PGF.cpp.

730 {
731 int nRetCode = 0;
732
733 // parse arguments
734 enum Operation {Encode, Decode, Measure} op = Encode;
735 char *source=nullptr, *dest=nullptr, *temp=nullptr;
736 int level = 0, levels = 0, quality = 0;
737 PGFRect rect;
738 int arg = 1; // argument 0 = pgf
739 bool bSource = true; // true: bSource, false: dest
740 bool bStreaming = false;// true: level wise writing/reading is used
741 bool bROI = false; // true: ROI is used
742 bool bMemStream = false;// true: use a memory stream during measuring
743 bool bWrongArgs = (argc < 4);
744
745 while (!bWrongArgs && arg < argc) {
746 if (argv[arg][0] == '-') {
747 // options
748 switch(argv[arg][1]) {
749 case 'e': op = Encode; arg++; break;
750 case 'd': op = Decode; arg++; break;
751 case 'm': op = Measure;
752 if (argv[arg][2] == 'm') {
753 // -mm
754 bMemStream = true;
755 arg++;
756 } else {
757 arg++;
758 if (arg == argc) {
759 bWrongArgs = true;
760 } else {
761 temp = argv[arg]; arg++;
762 }
763 }
764 break;
765 case 'l':
766 if (argv[arg][2] == 'e') {
767 // -le[v]
768 arg++;
769 if (arg == argc) {
770 bWrongArgs = true;
771 } else {
772 level = atoi(argv[arg]); arg++;
773 bWrongArgs = (level < 1) || (level > MaxLevel);
774 }
775 } else {
776 // -l
777 arg++;
778 if (arg == argc) {
779 bWrongArgs = true;
780 } else {
781 levels = atoi(argv[arg]); arg++;
782 bWrongArgs = (levels < 1) || (levels > MaxLevel);
783 }
784 }
785 break;
786 case 'q': arg++;
787 if (arg == argc) {
788 bWrongArgs = true;
789 } else {
790 quality = atoi(argv[arg]); arg++;
791 bWrongArgs = (quality < 0) || (quality > MaxQuality);
792 }
793 break;
794 #ifdef __PGFROISUPPORT__
795 case 'r': bROI = true;
796 if (argv[arg][2] == 'e') {
797 // -re[ct]
798 arg++;
799 if (arg + 4 > argc) {
800 bWrongArgs = true;
801 } else {
802 rect = PGFRect(atoi(argv[arg]), atoi(argv[arg+1]), atoi(argv[arg+2]), atoi(argv[arg+3]));
803 arg += 4;
804 }
805 } else {
806 // -r
807 arg++;
808 if (arg == argc) bWrongArgs = true;
809 }
810 break;
811 case 's': bStreaming = true; arg++; break;
812 #endif // __PGFROISUPPORT__
813 case 'v': bQuiet = true; arg++; break;
814 default: arg++; bWrongArgs = true; break;
815 }
816 } else {
817 if (bSource) {
818 source = argv[arg];
819 bSource = false;
820 } else {
821 dest = argv[arg];
822 }
823 arg++;
824 }
825 }
826 if (!bQuiet) cout << "PGF Console - Copyright (c) 2001-" CurrentYear " xeraina GmbH, Switzerland" << endl <<
827 "Console Version: " PGFConsoleVersion ", www.xeraina.ch" << endl <<
828 "libpgf Version : " PGFCodecVersion ", www.libpgf.org" << endl << endl;
829 if (bWrongArgs) {
830 if (!bQuiet) {
831 cout << "Usage: " << endl <<
832 #ifdef __PGFROISUPPORT__
833 "- Encoding: pgfconsole -e [-l levels] [-q quality] [-r] [-s] [-v] source dest" << endl <<
834 #else
835 "- Encoding: pgfconsole -e [-l levels] [-q quality] [-v] source dest" << endl <<
836 #endif
837 " Create from a source file a PGF image (dest)." << endl <<
838 " The most popular image file formats with the following image" << endl <<
839 " types are supported:" << endl <<
840 " - bitmap (1 bit)" << endl <<
841 " - grayscale (8 and 16 bit)" << endl <<
842 " - indexed color (8 bit)" << endl <<
843 " - RGB (16 [565], 24, 32, and 48 bit)" << endl <<
844 " - RGBA (32 bit)" << endl <<
845 " Options:" << endl <<
846 " -l levels Number of hierarchical levels [1.." << MaxLevel << "]. Default is 0." << endl <<
847 " 0 means the number of levels are automatically set." << endl <<
848 " -q quality Quality [0.." << MaxQuality << "]. Default is 0." << endl <<
849 " 0 means perfect quality (lossless compression)," << endl <<
850 " " << MaxQuality << " means maximum compression." << endl <<
851 #ifdef __PGFROISUPPORT__
852 " -r Region of interest (ROI) encoding scheme is used." << endl <<
853 " This encoding scheme has a slightly worse compression ratio." << endl <<
854 " -s Level wise encoding in separate writing calls." << endl <<
855 #endif
856 " -v Numbers only: All text output is reduced to numbers." << endl <<
857 endl <<
858 #ifdef __PGFROISUPPORT__
859 "- Decoding: pgfconsole -d [-lev level] [-rect left top width height] [-s] [-v] source dest" << endl <<
860 #else
861 "- Decoding: pgfconsole -d [-v] source dest" << endl <<
862 #endif
863 " Create from a PGF image (source) a new image (dest)." << endl <<
864 " Options:" << endl <<
865 " -lev level The image level of the resulting image. Default is 0." << endl <<
866 #ifdef __PGFROISUPPORT__
867 " -rect rect Read a rectangular region of a PGF image supporting Region of" << endl <<
868 " interests (ROI). The rectangle is defined by 4 blank-separated" << endl <<
869 " positive parameters: left top width height" << endl <<
870 " -s Level wise decoding in separate reading calls." << endl <<
871 #endif
872 " -v Numbers only: All text output is reduced to numbers." << endl <<
873 endl <<
874 "- Measuring: pgfconsole -m temp-file [...] source destination" << endl <<
875 " Measure quality between source and destination bitmap." << endl <<
876 " Encode from an input image (source) a PGF image" << endl <<
877 " (temp-file) and decode from the temp-file a new output" << endl <<
878 " (destination image)." << endl <<
879 " Options:" << endl <<
880 " -mm Instead of using the option -m temp-file you can use " << endl <<
881 " the option -mm (without temp-file). The latter writes the PGF" << endl <<
882 " image into a memory stream instead of a file stream." << endl <<
883 " In both cases all encoding and decoding options are valid." << endl <<
884 endl <<
885 endl;
886 }
887 nRetCode = 2;
888 } else {
889 CImage *image = 0;
890
891#ifdef __PNMEXSUPPORT__
892 // register new PNM plugin
894#endif
895
896 switch(op) {
897 case Encode:
898 if (!Encoding(image, source, dest, levels, quality, bROI, bStreaming, nullptr)) nRetCode = 3;
899 break;
900 case Decode:
901 if (!Decoding(image, source, dest, level, bROI, rect, bStreaming, nullptr)) nRetCode = 4;
902 break;
903 case Measure:
904 if (!Measurement(source, dest, temp, levels, level, quality, bROI, rect, bStreaming, bMemStream)) nRetCode = 5;
905 break;
906 default:
907 nRetCode = 6;
908 ASSERT(false); // unhandled operation
909 }
910 if (bQuiet) cout << endl;
911
912 delete image;
913 }
914 return nRetCode;
915}
static bool Encoding(CImage *&image, char *source, char *dest, int levels, int quality, bool roi, bool streaming, CPGFMemoryStream **memStream)
Definition PGF.cpp:218
#define CurrentYear
Definition PGF.cpp:28
static bool Decoding(CImage *&image, char *source, char *dest, int level, bool roi, PGFRect &rect, bool streaming, CPGFMemoryStream **memStream)
Definition PGF.cpp:458
static bool Measurement(char *source, char *dest, char *temp, int levels, int level, int quality, bool roi, PGFRect &rect, bool streaming, bool useMemStream)
Definition PGF.cpp:693
#define PGFConsoleVersion
Definition PGF.cpp:27
static void RegisterPNM()
Definition CImage.cpp:303

◆ Measurement()

static bool Measurement ( char * source,
char * dest,
char * temp,
int levels,
int level,
int quality,
bool roi,
PGFRect & rect,
bool streaming,
bool useMemStream )
static

Definition at line 693 of file PGF.cpp.

693 {
694 ASSERT(source);
695 ASSERT(dest);
696 CImage *image1 = nullptr, *image2 = nullptr;
697 CPGFMemoryStream *memStream = nullptr;
698
699 if (!bQuiet) cout << "Measuring PSNR (quality: " << quality << ", levels: " << levels << "): " << source << endl;
700 if (useMemStream) {
701 if (!bQuiet) cout << "PGF image is written into memory stream." << endl;
702 } else {
703 ASSERT(temp);
704 }
705 if (!bQuiet) cout << endl;
706
707 if (!Encoding(image1, source, temp, levels, quality, roi, streaming, (useMemStream) ? &memStream : nullptr)) {
708 delete image1;
709 delete memStream;
710 return false;
711 }
712 if (!Decoding(image2, temp, dest, level, roi, rect, streaming, (useMemStream) ? &memStream : nullptr)) {
713 delete image2;
714 delete memStream;
715 return false;
716 }
717
718 if (image1->GetChannelDepth() == 8 || image1->GetChannelDepth() == 16) {
719 // output psnr
720 PSNR(*image1, *image2, roi, rect);
721 }
722
723 delete image1;
724 delete image2;
725 delete memStream;
726 return true;
727}
static void PSNR(const CImage &image1, const CImage &image2, bool roi, PGFRect &rect)
Definition PGF.cpp:105

◆ PSNR()

static void PSNR ( const CImage & image1,
const CImage & image2,
bool roi,
PGFRect & rect )
static

Definition at line 105 of file PGF.cpp.

105 {
106#ifndef __PGFROISUPPORT__
107 roi;
108 rect;
109#endif
110 ASSERT(image1.GetChannelDepth() == image2.GetChannelDepth());
111 ASSERT(image1.GetChannelDepth() == 8 || image1.GetChannelDepth() == 16);
112
113 const int channels1 = image1.GetChannels(); ASSERT(channels1 <= MaxChannels);
114 #pragma warning(disable: 4189)
115 const int channels2 = image2.GetChannels(); ASSERT(channels2 <= MaxChannels);
116 ASSERT(channels1 == channels2);
117 const UINT32 w = image2.GetWidth();
118 const UINT32 h = image2.GetHeight();
119 const UINT32 size = w*h;
120 const int bypp1 = image1.GetBPP()/8; // RGB mode has 3 channels but can use 24 or 32 bits per pixel
121 const int bypp2 = image2.GetBPP()/8;
122
123 int pitch1 = image1.GetPitch();
124 int pitch2 = image2.GetPitch();
125 double sum[MaxChannels + 1] = { 0 };
126 int tmp;
127 int cnt1 = 0, cnt2 = 0, maxValue;
128
129 if (image1.GetChannelDepth() == 8) {
130 UINT8* rgbBuff1 = (UINT8 *)image1.GetBits();
131 UINT8* rgbBuff2 = (UINT8 *)image2.GetBits();
132 maxValue = 255;
133
134 #ifdef __PGFROISUPPORT__
135 if (roi) {
136 ASSERT(w <= image1.GetWidth());
137 ASSERT(h <= image1.GetHeight());
138 rgbBuff1 += (image1.GetHeight() - h - rect.top)*pitch1 + rect.left*channels1;
139 }
140 #endif
141 for (UINT32 j=0; j < h; j++) {
142 cnt1 = cnt2 = 0;
143 for (UINT32 i=0; i < w; i++) {
144 for (int c=0; c < channels1; c++) {
145 tmp = rgbBuff2[cnt2 + c] - rgbBuff1[cnt1 + c]; sum[c] += tmp*tmp;
146 }
147 cnt1 += bypp1;
148 cnt2 += bypp2;
149 }
150 rgbBuff1 += pitch1;
151 rgbBuff2 += pitch2;
152 }
153 } else if (image1.GetChannelDepth() == 16) {
154 UINT16* rgbBuff1 = (UINT16 *)image1.GetBits();
155 UINT16* rgbBuff2 = (UINT16 *)image2.GetBits();
156
157#ifdef __PNMEXSUPPORT__
158 maxValue = image1.GetMaxValue();
159#else
160 maxValue = 65535;
161#endif
162 pitch1 /= 2;
163 pitch2 /= 2;
164
165 #ifdef __PGFROISUPPORT__
166 if (roi) {
167 ASSERT(w <= image1.GetWidth());
168 ASSERT(h <= image1.GetHeight());
169 rgbBuff1 += (image1.GetHeight() - h - rect.top)*pitch1 + rect.left*channels1;
170 }
171 #endif
172 for (UINT32 j=0; j < h; j++) {
173 cnt1 = cnt2 = 0;
174 for (UINT32 i=0; i < w; i++) {
175 for (int c=0; c < channels1; c++) {
176 tmp = rgbBuff2[cnt2 + c] - rgbBuff1[cnt1 + c]; sum[c] += tmp*tmp;
177 }
178 cnt1 += bypp1;
179 cnt2 += bypp2;
180 }
181 rgbBuff1 += pitch1;
182 rgbBuff2 += pitch2;
183 }
184 } else {
185 return;
186 }
187
188 for (int c=0; c < channels1; c++) {
189 sum[MaxChannels] += sum[c];
190 }
191
192 // output
193 if (bQuiet) {
194 cout << 10*log10(double(maxValue)*maxValue*size*channels1/sum[MaxChannels]);
195// cout << ((sum[MaxChannels] != 0) ? 10*log10(double(maxValue)*maxValue*size*channels1/sum[MaxChannels]) : 100);
196 for (int c=0; c < channels1; c++) {
197 cout << ';' << 10*log10(double(maxValue)*maxValue*size/sum[c]);
198 //cout << ';' << ((sum[c] != 0) ? 10*log10(double(maxValue)*maxValue*size/sum[c]) : 100);
199 }
200 cout << ';';
201 } else {
202 if (sum[MaxChannels] == 0) {
203 cout << "PSNR: lossless" << endl;
204 } else {
205 cout << "PSNR: " << 10*log10(double(maxValue)*maxValue*size*channels1/sum[MaxChannels]) << " (";
206 for (int c=0; c < channels1; c++) {
207 cout << 'c' << c << ": " << 10*log10(double(maxValue)*maxValue*size/sum[c]);
208 //cout << 'c' << c << ": " << ((sum[c] != 0) ? 10*log10(double(maxValue)*maxValue*size/sum[c]) : 100);
209 if (c < channels1 - 1) cout << ", ";
210 }
211 cout << ')' << endl;
212 }
213 cout << endl;
214 }
215}
int GetChannels() const
Definition CImage.cpp:276

Variable Documentation

◆ bQuiet

bool bQuiet = false
static

Definition at line 78 of file PGF.cpp.

◆ PGFErrors

string PGFErrors[]
static
Initial value:
= {
"no error",
"memory allocation was not successfull",
"invalid memory stream position",
"user break by ESC",
"wrong pgf version",
"wrong data file format",
"image is too small",
"error in zlib functions",
"errors related to color table size",
"errors in png functions",
"expected data cannot be read",
}

Definition at line 79 of file PGF.cpp.

79 {
80 "no error",
81 "memory allocation was not successfull",
82 "invalid memory stream position",
83 "user break by ESC",
84 "wrong pgf version",
85 "wrong data file format",
86 "image is too small",
87 "error in zlib functions",
88 "errors related to color table size",
89 "errors in png functions",
90 "expected data cannot be read",
91};