106#ifndef __PGFROISUPPORT__
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);
119 const UINT32 size = w*h;
120 const int bypp1 = image1.
GetBPP()/8;
121 const int bypp2 = image2.
GetBPP()/8;
125 double sum[MaxChannels + 1] = { 0 };
127 int cnt1 = 0, cnt2 = 0, maxValue;
130 UINT8* rgbBuff1 = (UINT8 *)image1.
GetBits();
131 UINT8* rgbBuff2 = (UINT8 *)image2.
GetBits();
134 #ifdef __PGFROISUPPORT__
138 rgbBuff1 += (image1.
GetHeight() - h - rect.top)*pitch1 + rect.left*channels1;
141 for (UINT32 j=0; j < h; j++) {
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;
154 UINT16* rgbBuff1 = (UINT16 *)image1.
GetBits();
155 UINT16* rgbBuff2 = (UINT16 *)image2.
GetBits();
157#ifdef __PNMEXSUPPORT__
165 #ifdef __PGFROISUPPORT__
169 rgbBuff1 += (image1.
GetHeight() - h - rect.top)*pitch1 + rect.left*channels1;
172 for (UINT32 j=0; j < h; j++) {
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;
188 for (
int c=0; c < channels1; c++) {
189 sum[MaxChannels] += sum[c];
194 cout << 10*log10(
double(maxValue)*maxValue*size*channels1/sum[MaxChannels]);
196 for (
int c=0; c < channels1; c++) {
197 cout <<
';' << 10*log10(
double(maxValue)*maxValue*size/sum[c]);
202 if (sum[MaxChannels] == 0) {
203 cout <<
"PSNR: lossless" << endl;
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]);
209 if (c < channels1 - 1) cout <<
", ";
218static bool Encoding(
CImage*& image,
char *source,
char *dest,
int levels,
int quality,
bool roi,
bool streaming, CPGFMemoryStream** memStream) {
219#ifndef __PGFROISUPPORT__
224 ASSERT(0 <= quality && quality <= MaxQuality);
225 bool returnValue =
true;
228 clock_t start = 0, mean = 0, end = 0;
229 UINT32 writtenBytes = 0;
230 CPGFStream *stream =
nullptr;
234#elif defined(__POSIX__)
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;
251 stream =
new CPGFFileStream(fd);
253 #elif defined(__POSIX__)
254 fd = open(dest, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
256 cout <<
"Error: Could not open destination file." << endl;
263 stream =
new CPGFFileStream(fd);
268 if (!
bQuiet) cout <<
"Encoding PGF image to memory stream (quality: " << quality <<
", levels: " << levels <<
"): " << source << endl;
270 if (!
bQuiet) cout <<
"Encoding PGF image (quality: " << quality <<
", levels: " << levels <<
"): " << source << endl;
272 if (roi || streaming) {
274 cout <<
"PGF image will support ROI." << endl;
276 cout << dest <<
" will support ROI." << endl;
287 if (!image->
Load(source)) {
290 FORMAT_MESSAGE_ALLOCATE_BUFFER |
291 FORMAT_MESSAGE_FROM_SYSTEM |
292 FORMAT_MESSAGE_IGNORE_INSERTS,
295 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
300 cerr <<
"Error: " << lpMsgBuf << endl;
305#elif defined(__POSIX__)
306 if (!image->
Load(source) ){
307 cerr <<
"Error: Could not load source file." << endl;
315 if ((bpp < 1) || (bpp > 48) || (bpp == 4)) {
316 cerr <<
"Error: Unhandled image format." << endl;
321 ASSERT((bpp >= 1) && (bpp <= 48) && (bpp != 4));
331 pgf.ConfigureEncoder(
true,
false);
335 header.nLevels = (UINT8)levels;
336 header.quality = (UINT8)quality;
338 header.bpp = header.channels = 0;
339 header.usedBitsPerChannel = 0;
343 pgf.SetHeader(header, (roi || streaming) ? PGFROI : 0);
345 char data[] =
"This is a free text annotation.";
346 pgf.SetHeader(header, (roi || streaming) ? PGFROI : 0, (UINT8 *)data,
sizeof(data));
349#ifdef __PNMEXSUPPORT__
357 UINT8* buff = (UINT8 *)image->
GetBits();
359 int map[] = { 2, 1, 0 };
363 int map[] = { 2, 1, 0 };
373 RGBQUAD* pColorTable =
new RGBQUAD[colorTableSize];
376 pgf.SetColorTable(0, colorTableSize, pColorTable);
377 delete[] pColorTable;
380 }
catch(IOException& e) {
383 if (err >= AppError) {
384 cerr <<
"Error: Importing input image failed\n(" <<
PGFErrors[err - AppError] <<
")!" << endl;
386 cerr <<
"Error: Importing input image failed (" << err <<
")!" << endl;
393 #ifdef __PGFROISUPPORT__
396 writtenBytes = pgf.WriteHeader(stream);
397 if (!
bQuiet) cout <<
"Write header [" << writtenBytes <<
" bytes]" << endl;
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;
405 #endif __PGFROISUPPORT__
408 pgf.Write(stream, &writtenBytes);
411 }
catch(IOException& e) {
413 if (err >= AppError) {
414 cerr <<
"Error: Writing PGF image failed\n(" <<
PGFErrors[err - AppError] <<
")!" << endl;
416 cerr <<
"Error: Writing PGF image failed (" << err <<
")!" << endl;
427 pgf.ResetStreamPos(
false);
431 if (fd) CloseHandle(fd);
432#elif defined(__POSIX__)
440 double destSize = (memStream) ? writtenBytes : double(
FileSize(dest));
441 double ratio = double(
FileSize(source))/destSize;
444 cout << double(end - mean)/CLOCKS_PER_SEC <<
';' << double(end - start)/CLOCKS_PER_SEC <<
';' << ratio <<
';';
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;
458static bool Decoding(
CImage*& image,
char *source,
char *dest,
int level,
bool roi, PGFRect& rect,
bool streaming, CPGFMemoryStream** memStream) {
459#ifndef __PGFROISUPPORT__
465 bool returnValue =
true;
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;
473#elif defined(__POSIX__)
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;
493 stream =
new CPGFFileStream(fd);
495 #elif defined(__POSIX__)
496 fd = open(source, O_RDONLY);
498 cout <<
"Error: Could not open source file." << endl;
505 stream =
new CPGFFileStream(fd);
510 pgf.ConfigureDecoder(
true);
513 if (!
bQuiet) cout <<
"Decoding PGF image from memory stream." << endl;
515 if (!
bQuiet) cout <<
"Decoding PGF image: " << source << endl;
521 UINT64 startpos = stream->GetPos();
523 if (!
bQuiet) cout <<
"Read header and level info [" << stream->GetPos() - startpos <<
" bytes]" << endl;
528 const UINT8 *data = pgf.GetUserData(len);
530 cout << (
char *)data << endl;
535 #ifdef __PGFROISUPPORT__
536 if (pgf.ROIisSupported()) {
538 if (!
bQuiet) cout <<
"PGF image supports ROI." << endl;
540 if (!
bQuiet) cout << source <<
" supports ROI." << endl;
542 if (!
bQuiet && roi) cout <<
"Decode ROI (" << rect.left <<
"," << rect.top <<
"," << rect.Width() <<
"," << rect.Height() <<
")"<< endl;
545 pgf.Read(rect, level);
549 for (
int i = pgf.Levels() - 1; i >= 0; i--) {
550 if (!
bQuiet) cout <<
"Read level " << i;
551 UINT64 pos = stream->GetPos();
553 if (!
bQuiet) cout <<
" [" << stream->GetPos() - pos <<
" bytes]" << endl;
558 cout <<
"PGF Console: ROI supports has been disabled." << endl;
560 if (!roi && !streaming) {
563 sourceSize = double(stream->GetPos() - startpos);
565 }
catch(IOException& e) {
567 if (err >= AppError) {
568 cerr <<
"Error: Opening and reading PGF image failed\n(" <<
PGFErrors[err - AppError] <<
")!" << endl;
570 cerr <<
"Error: Opening and reading PGF image failed (" << err <<
")!" << endl;
580#ifdef __PGFROISUPPORT__
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;
591 if (!image->
Create(pgf.Width(level), pgf.Height(level), pgf.Mode())) {
592 cerr <<
"Decoding is not supported for this PGF color format." << endl;
600 buff = (UINT8 *)image->
GetBits();
602 int map[] = { 2, 1, 0 };
606 int map[] = { 2, 1, 0 };
616 image->
SetColorTable(0, 1 << pgf.BPP(), pgf.GetColorTable());
620 bw[0].rgbGreen = 255;
630#ifdef __PNMEXSUPPORT__
638 if (image->
Save(dest)) {
639 if (!
bQuiet) cout <<
"Written image file: " << dest << endl;
641 cerr <<
"Error: Output format not supported for this color depth." << endl;
657 stream->SetPos(FSFromStart, 0);
661 if (fd) CloseHandle(fd);
662#elif defined(__POSIX__)
670 sourceSize = (double)
FileSize(source);
675 double ratio = double(
FileSize(dest))/sourceSize;
677 cout << double(mean3 - mean2 + mean - start)/CLOCKS_PER_SEC <<
';' << double(end - mean3 + mean3 - mean2 + mean - start)/CLOCKS_PER_SEC <<
';' << ratio <<
';';
680 cout <<
"Decoding time (reading PGF, decoding): " << double(mean3 - mean2 + mean - start)/CLOCKS_PER_SEC <<
" s" << endl;
682 cout <<
"Decoding time (reading PGF down to level " << level <<
", decoding): " << double(mean3 - mean2 + mean - start)/CLOCKS_PER_SEC <<
" s" << endl;
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;
693static bool Measurement(
char *source,
char *dest,
char *temp,
int levels,
int level,
int quality,
bool roi, PGFRect& rect,
bool streaming,
bool useMemStream) {
696 CImage *image1 =
nullptr, *image2 =
nullptr;
697 CPGFMemoryStream *memStream =
nullptr;
699 if (!
bQuiet) cout <<
"Measuring PSNR (quality: " << quality <<
", levels: " << levels <<
"): " << source << endl;
701 if (!
bQuiet) cout <<
"PGF image is written into memory stream." << endl;
705 if (!
bQuiet) cout << endl;
707 if (!
Encoding(image1, source, temp, levels, quality, roi, streaming, (useMemStream) ? &memStream :
nullptr)) {
712 if (!
Decoding(image2, temp, dest, level, roi, rect, streaming, (useMemStream) ? &memStream :
nullptr)) {
720 PSNR(*image1, *image2, roi, rect);
730int main(
int argc,
char* argv[]) {
734 enum Operation {Encode, Decode, Measure} op = Encode;
735 char *source=
nullptr, *dest=
nullptr, *temp=
nullptr;
736 int level = 0, levels = 0, quality = 0;
740 bool bStreaming =
false;
742 bool bMemStream =
false;
743 bool bWrongArgs = (argc < 4);
745 while (!bWrongArgs && arg < argc) {
746 if (argv[arg][0] ==
'-') {
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') {
761 temp = argv[arg]; arg++;
766 if (argv[arg][2] ==
'e') {
772 level = atoi(argv[arg]); arg++;
773 bWrongArgs = (level < 1) || (level > MaxLevel);
781 levels = atoi(argv[arg]); arg++;
782 bWrongArgs = (levels < 1) || (levels > MaxLevel);
790 quality = atoi(argv[arg]); arg++;
791 bWrongArgs = (quality < 0) || (quality > MaxQuality);
794 #ifdef __PGFROISUPPORT__
795 case 'r': bROI =
true;
796 if (argv[arg][2] ==
'e') {
799 if (arg + 4 > argc) {
802 rect = PGFRect(atoi(argv[arg]), atoi(argv[arg+1]), atoi(argv[arg+2]), atoi(argv[arg+3]));
808 if (arg == argc) bWrongArgs =
true;
811 case 's': bStreaming =
true; arg++;
break;
813 case 'v':
bQuiet =
true; arg++;
break;
814 default: arg++; bWrongArgs =
true;
break;
826 if (!
bQuiet) cout <<
"PGF Console - Copyright (c) 2001-" CurrentYear " xeraina GmbH, Switzerland" << endl <<
828 "libpgf Version : " PGFCodecVersion
", www.libpgf.org" << endl << endl;
831 cout <<
"Usage: " << endl <<
832 #ifdef __PGFROISUPPORT__
833 "- Encoding: pgfconsole -e [-l levels] [-q quality] [-r] [-s] [-v] source dest" << endl <<
835 "- Encoding: pgfconsole -e [-l levels] [-q quality] [-v] source dest" << endl <<
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 <<
856 " -v Numbers only: All text output is reduced to numbers." << endl <<
858 #ifdef __PGFROISUPPORT__
859 "- Decoding: pgfconsole -d [-lev level] [-rect left top width height] [-s] [-v] source dest" << endl <<
861 "- Decoding: pgfconsole -d [-v] source dest" << endl <<
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 <<
872 " -v Numbers only: All text output is reduced to numbers." << 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 <<
891#ifdef __PNMEXSUPPORT__
898 if (!
Encoding(image, source, dest, levels, quality, bROI, bStreaming,
nullptr)) nRetCode = 3;
901 if (!
Decoding(image, source, dest, level, bROI, rect, bStreaming,
nullptr)) nRetCode = 4;
904 if (!
Measurement(source, dest, temp, levels, level, quality, bROI, rect, bStreaming, bMemStream)) nRetCode = 5;
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)