1 /*
2 Copyright 2016 Esri
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15
16 A local copy of the license and additional notices are located with the
17 source distribution at:
18
19 http://github.com/Esri/lepcc/
20
21 Contributors: Thomas Maurer
22 */
23
24 // Test_C_Api.cpp
25 //
26
27 #include <cstring>
28 #include <cmath>
29 #include <stdio.h>
30 #include <iostream>
31 #include <vector>
32 #include <algorithm>
33 #include <chrono>
34 #include "lepcc_c_api.h"
35 #include "lepcc_types.h"
36
37 using namespace std;
38 using namespace std::chrono;
39 using namespace lepcc;
40
41 // -------------------------------------------------------------------------- ;
42
43 int ReadBlobSize(lepcc_ContextHdl ctx, FILE* fp);
44
HasError(ErrCode errCode,const string & fctName)45 int HasError(ErrCode errCode, const string& fctName)
46 {
47 if (errCode != ErrCode::Ok)
48 printf("Error in main(): %s failed. Error code = %d\n", fctName.c_str(), errCode);
49 return (int)errCode;
50 }
51
52 // -------------------------------------------------------------------------- ;
53
main(int argc,char * argv[])54 int main(int argc, char* argv[])
55 {
56 {
57 // open a small test binary slpk blob which has some LEPCC blobs embedded
58
59 string fnIn = "../testData/SMALL_AUTZEN_LAS_All.slpk";
60 string fnGT = "../testData/SMALL_AUTZEN_LAS_All.bin"; // decoded ground truth stored as raw binary arrays
61 bool bWriteGT = false; // toggle between write or read the ground truth
62
63 FILE* fp = 0;
64 fp = fopen(fnIn.c_str(), "rb");
65 if (!fp)
66 {
67 printf("Error in main(): Cannot read from file %s.\n", fnIn.c_str());
68 return 0;
69 }
70
71 fseek(fp, 0, SEEK_END);
72 size_t len = ftell(fp);
73 rewind(fp);
74
75 vector<Byte> byteVec(len, 0);
76 fread(&byteVec[0], 1, len, fp);
77 fclose(fp);
78
79 FILE* fpGT = 0;
80 fpGT = fopen(fnGT.c_str(), bWriteGT ? "wb" : "rb");
81 if (!fpGT)
82 {
83 printf("Error in main(): Cannot open file %s.\n", fnGT.c_str());
84 return 0;
85 }
86
87 // search for LEPCC blobs
88
89 vector<string> magicStrings;
90 magicStrings.push_back("LEPCC ");
91 magicStrings.push_back("ClusterRGB");
92 magicStrings.push_back("Intensity ");
93
94 lepcc_ContextHdl ctx = lepcc_createContext();
95 int nInfo = lepcc_getBlobInfoSize();
96 ErrCode errCode;
97
98 size_t magicLen = 10;
99 for (size_t pos = 0; pos < len - magicLen; pos++)
100 {
101 for (size_t blobType = 0; blobType < magicStrings.size(); blobType++)
102 {
103 if (0 == memcmp(&byteVec[pos], magicStrings[blobType].c_str(), magicLen))
104 {
105 const Byte* ptr = &byteVec[pos];
106 uint32 blobSize = 0;
107 lepcc_blobType bt;
108 errCode = (ErrCode)lepcc_getBlobInfo(ctx, ptr, nInfo, &bt, &blobSize);
109 if (HasError(errCode, "lepcc_getBlobInfo()"))
110 return 0;
111
112 switch (blobType)
113 {
114 case 0:
115 {
116 uint32 nPts = 0;
117 errCode = (ErrCode)lepcc_getPointCount(ctx, ptr, len - pos, &nPts);
118 if (HasError(errCode, "lepcc_getPointCount()"))
119 return 0;
120
121 vector<Point3D> ptVec(nPts);
122 errCode = (ErrCode)lepcc_decodeXYZ(ctx, &ptr, len - pos, &nPts, (double*)(&ptVec[0]));
123 if (HasError(errCode, "lepcc_decodeXYZ()"))
124 return 0;
125
126 printf("decode xyz blob succeeded.\n");
127
128 if (bWriteGT)
129 {
130 fwrite(&nPts, 4, 1, fpGT);
131 fwrite(&ptVec[0], sizeof(Point3D), nPts, fpGT);
132 }
133 else
134 {
135 uint32 nPts2 = 0;
136 fread(&nPts2, 4, 1, fpGT);
137 if (nPts2 != nPts)
138 {
139 printf("Error in main(): mismatch in number of elements %d vs %d\n", nPts, nPts2);
140 return 0;
141 }
142 vector<Point3D> ptVec2(nPts);
143 fread(&ptVec2[0], sizeof(Point3D), nPts, fpGT);
144
145 // compare
146 double dxMax(0), dyMax(0), dzMax(0);
147 for (int i = 0; i < (int)nPts; i++)
148 {
149 const Point3D* p = &ptVec[i];
150 const Point3D* q = &ptVec2[i];
151
152 double dx = abs(q->x - p->x);
153 double dy = abs(q->y - p->y);
154 double dz = abs(q->z - p->z);
155
156 dxMax = max(dx, dxMax);
157 dyMax = max(dy, dyMax);
158 dzMax = max(dz, dzMax);
159 }
160
161 printf("number of points = %d, dxMax = %f, dyMax = %f, dzMax = %f\n", nPts, dxMax, dyMax, dzMax);
162 }
163 }
164 break;
165
166 case 1:
167 {
168 uint32 nPts = 0;
169 errCode = (ErrCode)lepcc_getRGBCount(ctx, ptr, len - pos, &nPts);
170 if (HasError(errCode, "lepcc_getRGBCount()"))
171 return 0;
172
173 vector<RGB_t> rgbVec(nPts);
174 errCode = (ErrCode)lepcc_decodeRGB(ctx, &ptr, len - pos, &nPts, (Byte*)(&rgbVec[0]));
175 if (HasError(errCode, "lepcc_decodeRGB()"))
176 return 0;
177
178 printf("decode RGB blob succeeded.\n");
179
180 if (bWriteGT)
181 {
182 fwrite(&nPts, 4, 1, fpGT);
183 fwrite(&rgbVec[0], sizeof(RGB_t), nPts, fpGT);
184 }
185 else
186 {
187 uint32 nPts2 = 0;
188 fread(&nPts2, 4, 1, fpGT);
189 if (nPts2 != nPts)
190 {
191 printf("Error in main(): mismatch in number of elements %d vs %d\n", nPts, nPts2);
192 return 0;
193 }
194 vector<RGB_t> rgbVec2(nPts);
195 fread(&rgbVec2[0], sizeof(RGB_t), nPts, fpGT);
196
197 // compare
198 double dxMax(0), dyMax(0), dzMax(0);
199 for (int i = 0; i < (int)nPts; i++)
200 {
201 const RGB_t* p = &rgbVec[i];
202 const RGB_t* q = &rgbVec2[i];
203
204 double dx = abs(q->r - p->r);
205 double dy = abs(q->g - p->g);
206 double dz = abs(q->b - p->b);
207
208 dxMax = max(dx, dxMax);
209 dyMax = max(dy, dyMax);
210 dzMax = max(dz, dzMax);
211 }
212
213 printf("number of points = %d, dxMax = %f, dyMax = %f, dzMax = %f\n", nPts, dxMax, dyMax, dzMax);
214 }
215 }
216 break;
217
218 case 2:
219 {
220 uint32 nPts = 0;
221 errCode = (ErrCode)lepcc_getIntensityCount(ctx, ptr, len - pos, &nPts);
222 if (HasError(errCode, "lepcc_getIntensityCount()"))
223 return 0;
224
225 vector<unsigned short> intensityVec(nPts);
226 errCode = (ErrCode)lepcc_decodeIntensity(ctx, &ptr, len - pos, &nPts, (unsigned short*)(&intensityVec[0]));
227 if (HasError(errCode, "lepcc_decodeIntensity()"))
228 return 0;
229
230 printf("decode intensity blob succeeded.\n");
231
232 if (bWriteGT)
233 {
234 fwrite(&nPts, 4, 1, fpGT);
235 fwrite(&intensityVec[0], sizeof(unsigned short), nPts, fpGT);
236 }
237 else
238 {
239 uint32 nPts2 = 0;
240 fread(&nPts2, 4, 1, fpGT);
241 if (nPts2 != nPts)
242 {
243 printf("Error in main(): mismatch in number of elements %d vs %d\n", nPts, nPts2);
244 return 0;
245 }
246 vector<unsigned short> intensityVec2(nPts);
247 fread(&intensityVec2[0], sizeof(unsigned short), nPts, fpGT);
248
249 // compare
250 double dxMax(0);
251 for (int i = 0; i < (int)nPts; i++)
252 {
253 int intensity0 = intensityVec[i];
254 int intensity1 = intensityVec2[i];
255 double dx = abs(intensity1 - intensity0);
256 dxMax = max(dx, dxMax);
257 }
258
259 printf("number of points = %d, dxMax = %f\n", nPts, dxMax);
260 }
261 }
262 break;
263
264 default:
265 printf("Error in main(): Test for this LEPCC blob type not implemented.\n");
266 }
267
268 pos += blobSize - 1;
269 }
270 }
271 }
272
273 fclose(fpGT);
274 return 0;
275 }
276
277 // -------------- see below for examples on how to encode and decode --------
278
279 double maxXErr = 9e-8, maxYErr = maxXErr;
280 double maxZErr = 0.01;
281
282 int mode = 0; // 0 - computeCompressedSize, 1 - encode, 2 - decode, 3 - test
283
284 bool origHasXYZ = false;
285 bool origHasRGB = false;
286 bool decodHasRGB = origHasRGB;
287 bool origHasIntensity = true;
288
289 string fn, fnOut;
290
291 if (mode != 2)
292 {
293 //fn = "tilesXYZ.bin";
294 //fn = "tilesXYZ_RGB.bin";
295 //fn = "heritage_rgb_only.bin";
296 fn = "sonoma18_intensity_only.bin";
297 fnOut = "tilesCompressed.bin";
298 }
299 else
300 {
301 fn = "tilesCompressed.bin";
302 fnOut = "tilesUncompressed.bin";
303 }
304
305 FILE* fp = 0;
306 fp = fopen( fn.c_str(), "rb");
307 if (!fp)
308 {
309 printf("Error in main(): Cannot read from file %s.\n", fn.c_str()); return 0;
310 }
311
312 FILE* fpOut = 0;
313 if (mode == 1 || mode == 2) // || mode == 0)
314 {
315 fpOut = fopen(fnOut.c_str(), "wb");
316 if (!fpOut)
317 {
318 printf("Error in main(): Cannot write to file %s.\n", fnOut.c_str()); return 0;
319 }
320 fclose(fpOut);
321 fpOut = fopen(fnOut.c_str(), "ab"); // open again in append mode
322 }
323
324 double totalNumPoints = 0, totalNumTiles = 0;
325 double minPts = 1e16, maxPts = 0;
326 double maxDecErrX = 0, maxDecErrY = 0, maxDecErrZ = 0;
327 double maxDecErrRGB = 0, totalDecErrRGB = 0;
328 double maxDecErrIntensity = 0, totalDecErrIntensity = 0;
329 int64 totalNumBytesCompressed = 0;
330
331 lepcc_ContextHdl ctx = lepcc_createContext();
332 lepcc_ContextHdl ctxDec = lepcc_createContext();
333 lepcc_status hr;
334
335 vector<Point3D> ptVec, decPtVec;
336 vector<RGB_t> rgbVec, sortedRgbVec, decRgbVec;
337 vector<Byte> byteVec;
338 vector<uint16> intensityVec, decIntensityVec;
339 vector<uint32> orderVec;
340
341 high_resolution_clock::time_point t0 = high_resolution_clock::now();
342
343 if (mode != 2) // simulate, encode, or test
344 {
345 bool done = false;
346 while (!done) // tile loop
347 {
348 int nPts = 0;
349
350 if (origHasXYZ)
351 {
352 fread(&nPts, 4, 1, fp);
353 if (nPts == 0) // eof
354 {
355 done = true;
356 continue;
357 }
358 ptVec.resize(nPts);
359 fread(&ptVec[0], sizeof(Point3D), nPts, fp);
360 }
361
362 //memset(&ptVec[0], 0, sizeof(Point3D) * nPts); // set points to all 0
363
364 if (origHasRGB)
365 {
366 int nPts2 = 0;
367 fread(&nPts2, 4, 1, fp);
368 if (nPts2 == 0) // eof
369 {
370 done = true;
371 continue;
372 }
373 if (origHasXYZ && nPts2 != nPts)
374 return 0;
375
376 nPts = nPts2;
377 rgbVec.resize(nPts);
378 fread(&rgbVec[0], sizeof(RGB_t), nPts, fp);
379 }
380
381 if (origHasIntensity)
382 {
383 int nPts2 = 0;
384 fread(&nPts2, 4, 1, fp);
385 if (nPts2 == 0) // eof
386 {
387 done = true;
388 continue;
389 }
390 if (origHasXYZ && nPts2 != nPts)
391 return 0;
392
393 nPts = nPts2;
394 intensityVec.resize(nPts);
395 fread(&intensityVec[0], sizeof(uint16), nPts, fp);
396 }
397
398 uint32 nBytesXYZ = 0;
399 if (ptVec.size() > 0)
400 {
401 orderVec.resize(nPts);
402 hr = lepcc_computeCompressedSizeXYZ(ctx, nPts, (const double*)(&ptVec[0]), maxXErr, maxYErr, maxZErr, &nBytesXYZ, (uint32*)(&orderVec[0]));
403 if (hr)
404 {
405 printf("Error in main(): lepcc_computeCompressedSizeXYZ(...) failed.\n"); return 0;
406 }
407 }
408
409 uint32 nBytesRGB = 0;
410 if (rgbVec.size() > 0)
411 {
412 if (orderVec.size() > 0) // resort the RGB values to point order
413 {
414 sortedRgbVec.resize(nPts);
415 for (int i = 0; i < nPts; i++)
416 sortedRgbVec[i] = rgbVec[orderVec[i]];
417
418 hr = lepcc_computeCompressedSizeRGB(ctx, nPts, (const Byte*)(&sortedRgbVec[0]), &nBytesRGB);
419 }
420 else
421 hr = lepcc_computeCompressedSizeRGB(ctx, nPts, (const Byte*)(&rgbVec[0]), &nBytesRGB);
422
423 if (hr)
424 {
425 printf("Error in main(): lepcc_computeCompressedSizeRGB(...) failed.\n"); return 0;
426 }
427 }
428
429 uint32 nBytesIntensity = 0;
430 if (intensityVec.size() > 0)
431 {
432 //for (int i = 0; i < (int)intensityVec.size(); i++)
433 // intensityVec[i] = 0;
434
435 hr = lepcc_computeCompressedSizeIntensity(ctx, nPts, &intensityVec[0], &nBytesIntensity);
436
437 if (hr)
438 {
439 printf("Error in main(): lepcc_computeCompressedSizeIntensity(...) failed.\n"); return 0;
440 }
441 }
442
443 int64 nBytes = nBytesXYZ + nBytesRGB + nBytesIntensity;
444
445 // stats
446 totalNumBytesCompressed += nBytes;
447 totalNumPoints += nPts;
448 totalNumTiles++;
449
450 minPts = (std::min)(minPts, (double)nPts);
451 maxPts = (std::max)(maxPts, (double)nPts);
452
453 //printf("nTiles = %d, minPtsPerTile = %d, maxPtsPerTile = %d, nPtsTotal = %d\n", (int)totalNumTiles, (int)minPts, (int)maxPts, (int)totalNumPoints);
454
455 if (mode > 0) // encode, or test
456 {
457 byteVec.resize((size_t)nBytes);
458 Byte* buffer = &byteVec[0];
459 Byte* pByte = buffer;
460
461 // encode
462 if (ptVec.size() > 0)
463 if ((hr = lepcc_encodeXYZ(ctx, &pByte, nBytesXYZ)))
464 {
465 printf("Error in main(): lepcc_encodeXYZ(...) failed.\n"); return 0;
466 }
467
468 if (rgbVec.size() > 0)
469 if ((hr = lepcc_encodeRGB(ctx, &pByte, nBytesRGB)))
470 {
471 printf("Error in main(): lepcc_encodeRGB(...) failed.\n"); return 0;
472 }
473
474 if (intensityVec.size() > 0)
475 if ((hr = lepcc_encodeIntensity(ctx, &pByte, nBytesIntensity, &intensityVec[0], nPts)))
476 {
477 printf("Error in main(): lepcc_encodeIntensity(...) failed.\n"); return 0;
478 }
479
480 if (mode == 1) // encode
481 {
482 fwrite(buffer, 1, (size_t)nBytes, fpOut); // append this byte blob to output stream
483 }
484
485 else if (mode == 3) // test mode: compare decoded points to orig for this tile right away
486 {
487 const Byte* pByte = buffer; // same buffer
488 uint32 nPts2 = 0;
489
490 if (!lepcc_getPointCount(ctxDec, pByte, nBytesXYZ, &nPts2) && nPts2 > 0)
491 {
492 decPtVec.resize(nPts2);
493 if ((hr = lepcc_decodeXYZ(ctxDec, &pByte, nBytesXYZ, &nPts2, (double*)(&decPtVec[0]))))
494 {
495 printf("Error in main(): lepcc_decodeXYZ(...) failed.\n"); return 0;
496 }
497
498 // compare
499 for (int i = 0; i < (int)nPts2; i++)
500 {
501 int k = orderVec[i];
502 const Point3D* p = &ptVec[k];
503 const Point3D* q = &decPtVec[i];
504
505 double dx = abs(q->x - p->x);
506 double dy = abs(q->y - p->y);
507 double dz = abs(q->z - p->z);
508
509 maxDecErrX = max(dx, maxDecErrX);
510 maxDecErrY = max(dy, maxDecErrY);
511 maxDecErrZ = max(dz, maxDecErrZ);
512 }
513 }
514
515 if (!lepcc_getRGBCount(ctxDec, pByte, nBytesRGB, &nPts2) && nPts2 > 0)
516 {
517 decRgbVec.resize(nPts2);
518 if ((hr = lepcc_decodeRGB(ctxDec, &pByte, nBytesRGB, &nPts2, (Byte*)(&decRgbVec[0]))))
519 {
520 printf("Error in main(): lepcc_decodeRGB(...) failed.\n"); return 0;
521 }
522
523 // compare
524 bool resortedColors = !orderVec.empty();
525
526 for (int i = 0; i < (int)nPts2; i++)
527 {
528 int k = resortedColors ? orderVec[i] : i;
529 RGB_t rgbEnc = rgbVec[k];
530 RGB_t rgbDec = decRgbVec[i];
531
532 double dx = rgbDec.r - rgbEnc.r;
533 double dy = rgbDec.g - rgbEnc.g;
534 double dz = rgbDec.b - rgbEnc.b;
535 double delta = sqrt(dx * dx + dy * dy + dz * dz);
536
537 maxDecErrRGB = max(delta, maxDecErrRGB);
538 totalDecErrRGB += delta;
539 }
540 }
541
542 if (!lepcc_getIntensityCount(ctxDec, pByte, nBytesIntensity, &nPts2) && nPts2 > 0)
543 {
544 decIntensityVec.resize(nPts2);
545 if ((hr = lepcc_decodeIntensity(ctxDec, &pByte, nBytesIntensity, &nPts2, &decIntensityVec[0])))
546 {
547 printf("Error in main(): lepcc_decodeIntensity(...) failed.\n"); return 0;
548 }
549
550 // compare
551 bool resortedColors = !orderVec.empty();
552
553 for (int i = 0; i < (int)nPts2; i++)
554 {
555 int k = resortedColors ? orderVec[i] : i;
556 uint16 intensEnc = intensityVec[k];
557 uint16 intensDec = decIntensityVec[i];
558 double delta = abs(intensDec - intensEnc);
559 maxDecErrIntensity = max(delta, maxDecErrIntensity);
560 totalDecErrIntensity += delta;
561 }
562 }
563 } // if (mode == 3)
564 } // if (mode > 0)
565 } // while (!done)
566 } // if (mode <= 1)
567
568 else if (mode == 2) // decode
569 {
570 bool done = false;
571 while (!done)
572 {
573 // get info from blob header, for XYZ blob
574 int nBytes = 0;
575 int nPts = 0;
576
577 if (origHasXYZ)
578 {
579 nBytes = ReadBlobSize(ctxDec, fp);
580
581 if (nBytes == 0)
582 {
583 done = true;
584 continue;
585 }
586 if (nBytes < 0)
587 {
588 printf("Error in main(): Read in bad num bytes for blob.\n"); return 0;
589 }
590 }
591
592 if (nBytes > 0)
593 {
594 byteVec.resize((size_t)nBytes);
595 fread(&byteVec[0], 1, (size_t)nBytes, fp); // read it from file
596
597 const Byte* pByte = &byteVec[0];
598 uint32 nPts2 = 0;
599 if ((hr = lepcc_getPointCount(ctxDec, pByte, nBytes, &nPts2)) && nPts2 > 0)
600 {
601 printf("Error in main(): lepcc_getPointCount(...) failed.\n"); return 0;
602 }
603
604 decPtVec.resize(nPts2);
605 if ((hr = lepcc_decodeXYZ(ctxDec, &pByte, nBytes, &nPts2, (double*)(&decPtVec[0]))))
606 {
607 printf("Error in main(): lepcc_decodeXYZ(...) failed.\n"); return 0;
608 }
609
610 // write out the uncompressed points
611 nPts = nPts2;
612 fwrite(&nPts2, sizeof(int), 1, fpOut);
613 fwrite(&decPtVec[0], sizeof(Point3D), nPts2, fpOut);
614 }
615
616 // get info from blob header, for RGB blob
617 nBytes = 0;
618
619 if (decodHasRGB)
620 {
621 nBytes = ReadBlobSize(ctxDec, fp);
622
623 if (nBytes == 0)
624 {
625 done = true;
626 continue;
627 }
628 if (nBytes < 0)
629 {
630 printf("Error in main(): Read in bad num bytes for blob.\n"); return 0;
631 }
632 }
633
634 if (nBytes > 0)
635 {
636 byteVec.resize((size_t)nBytes);
637 fread(&byteVec[0], 1, (size_t)nBytes, fp); // read it from file
638
639 const Byte* pByte = &byteVec[0];
640 uint32 nPts2 = 0;
641 if ((hr = lepcc_getRGBCount(ctxDec, pByte, nBytes, &nPts2)) && nPts2 > 0)
642 {
643 printf("Error in main(): lepcc_getRGBCount(...) failed.\n"); return 0;
644 }
645
646 decRgbVec.resize(nPts2);
647 if ((hr = lepcc_decodeRGB(ctxDec, &pByte, nBytes, &nPts2, (Byte*)(&decRgbVec[0]))))
648 {
649 printf("Error in main(): lepcc_decodeRGB(...) failed.\n"); return 0;
650 }
651
652 // write out the uncompressed colors
653 nPts = nPts2;
654 fwrite(&nPts2, sizeof(int), 1, fpOut);
655 fwrite(&decRgbVec[0], sizeof(RGB_t), nPts2, fpOut);
656 }
657
658 totalNumTiles++;
659 totalNumPoints += nPts;
660 }
661
662 int stopSign = 0;
663 fwrite(&stopSign, sizeof(int), 1, fpOut);
664 }
665
666 lepcc_deleteContext(&ctx);
667
668 high_resolution_clock::time_point t1 = high_resolution_clock::now();
669 auto duration = duration_cast<milliseconds>(t1 - t0).count();
670
671 double nBytesPerPt = (double)totalNumBytesCompressed / (double)totalNumPoints;
672
673 std::cout << "tiles = " << totalNumTiles << endl;
674 std::cout << "points = " << totalNumPoints << endl;
675
676 if (mode < 2)
677 {
678 std::cout << "points per tile [min, max] = [ " << minPts << ", " << maxPts << " ]" << endl;
679 std::cout << "total num bytes compressed = " << totalNumBytesCompressed << endl;
680 std::cout << "num bytes per point = " << nBytesPerPt << endl;
681 }
682 else if (mode == 3)
683 {
684 std::cout << "max decoding error in [x, y, z] = [ " << maxDecErrX << ", " << maxDecErrY << ", " << maxDecErrZ << " ]" << endl;
685 std::cout << "max decoding error in RGB = " << maxDecErrRGB << endl;
686 std::cout << "mean decoding error in RGB = " << totalDecErrRGB / totalNumPoints << endl;
687 std::cout << "max decoding error in intensity = " << maxDecErrIntensity << endl;
688 std::cout << "mean decoding error in intensity = " << totalDecErrIntensity / totalNumPoints << endl;
689 }
690
691 std::cout << "total time = " << duration << " ms" << endl;
692 std::cout << "time per tile = " << ((int)((duration / totalNumTiles) * 1000 + 0.5)) * 0.001 << " ms" << endl;
693
694 fclose(fp);
695
696 if (fpOut)
697 fclose(fpOut);
698
699 return 0;
700 }
701
702 // -------------------------------------------------------------------------- ;
703
704 // only for this little test program;
705 // a real app should keep track of the order compressed blobs are written to the stream, and their sizes;
706
ReadBlobSize(lepcc_ContextHdl ctx,FILE * fp)707 int ReadBlobSize(lepcc_ContextHdl ctx, FILE* fp)
708 {
709 Byte buffer[64];
710 int nBytes = 0;
711 int nInfo = lepcc_getBlobInfoSize();
712
713 if (nInfo == fread(buffer, 1, nInfo, fp))
714 {
715 lepcc_blobType bt;
716 uint32 blobSize = 0;
717 ErrCode errCode = (ErrCode)lepcc_getBlobInfo(ctx, buffer, nInfo, &bt, &blobSize);
718 nBytes = (errCode == ErrCode::Ok) ? (int)blobSize : -1;
719 fseek(fp, -nInfo, SEEK_CUR); // reset
720 }
721
722 return nBytes;
723 }
724
725 // -------------------------------------------------------------------------- ;
726