PGF Console  6.21.2
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 
655 CleanUp:
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 }
Definition: CImage.h:58
unsigned char GetBPP() const
Definition: CImage.cpp:107
#define ImageModeBitmap
Definition: CImage.h:33
#define ImageModeIndexedColor
Definition: CImage.h:35
unsigned char * GetBits() const
Definition: CImage.cpp:97
static INT64 FileSize(char *filename)
Definition: PGF.cpp:94
static string PGFErrors[]
Definition: PGF.cpp:79
bool Create(int width, int height, int bpp)
Definition: CImage.cpp:43
#define ImageModeRGB48
Definition: CImage.h:44
static bool bQuiet
Definition: PGF.cpp:78
void SetColorTable(int firstColor, int numColors, const void *prgbColors)
Definition: CImage.cpp:167
bool Save(const char *dest)
Definition: CImage.cpp:122
int GetPitch() const
Definition: CImage.cpp:102
unsigned int GetHeight() const
Definition: CImage.cpp:112
int GetChannelDepth() const
Definition: CImage.cpp:250
void SetMaxValue(int maxValue)
Definition: CImage.cpp:319

◆ 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 
424 CleanUp:
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 }
Definition: CImage.h:58
bool Load(const char *source)
Definition: CImage.cpp:127
unsigned char GetBPP() const
Definition: CImage.cpp:107
#define ImageModeIndexedColor
Definition: CImage.h:35
unsigned char * GetBits() const
Definition: CImage.cpp:97
unsigned char GetColorType() const
Definition: CImage.cpp:178
static INT64 FileSize(char *filename)
Definition: PGF.cpp:94
static string PGFErrors[]
Definition: PGF.cpp:79
#define ImageModeRGB48
Definition: CImage.h:44
void GetColorTable(int firstColor, int numColors, void *prgbColors)
Definition: CImage.cpp:156
static bool bQuiet
Definition: PGF.cpp:78
int GetMaxColorTableEntries()
Definition: CImage.cpp:151
int GetMaxValue() const
Definition: CImage.cpp:323
int GetPitch() const
Definition: CImage.cpp:102
unsigned int GetHeight() const
Definition: CImage.cpp:112
int GetChannelDepth() const
Definition: CImage.cpp:250
unsigned int GetWidth() const
Definition: CImage.cpp:117

◆ 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 }
Definition: CImage.h:58
#define CurrentYear
Definition: PGF.cpp:28
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
static void RegisterPNM()
Definition: CImage.cpp:303
#define PGFConsoleVersion
Definition: PGF.cpp:27
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 bQuiet
Definition: PGF.cpp:78
static bool Encoding(CImage *&image, char *source, char *dest, int levels, int quality, bool roi, bool streaming, CPGFMemoryStream **memStream)
Definition: PGF.cpp:218

◆ 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 }
Definition: CImage.h:58
static void PSNR(const CImage &image1, const CImage &image2, bool roi, PGFRect &rect)
Definition: PGF.cpp:105
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 bQuiet
Definition: PGF.cpp:78
static bool Encoding(CImage *&image, char *source, char *dest, int levels, int quality, bool roi, bool streaming, CPGFMemoryStream **memStream)
Definition: PGF.cpp:218
int GetChannelDepth() const
Definition: CImage.cpp:250

◆ 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 }
unsigned char GetBPP() const
Definition: CImage.cpp:107
unsigned char * GetBits() const
Definition: CImage.cpp:97
static bool bQuiet
Definition: PGF.cpp:78
int GetMaxValue() const
Definition: CImage.cpp:323
int GetPitch() const
Definition: CImage.cpp:102
unsigned int GetHeight() const
Definition: CImage.cpp:112
int GetChannelDepth() const
Definition: CImage.cpp:250
int GetChannels() const
Definition: CImage.cpp:276
unsigned int GetWidth() const
Definition: CImage.cpp:117

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.