KSquare Utilities
ScannerFile3BitEncoded.cpp
Go to the documentation of this file.
1 #include "FirstIncludes.h"
2 #include <stdio.h>
3 #include <errno.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <iostream>
7 #include <fstream>
8 #include <map>
9 #include <vector>
10 #include "MemoryDebug.h"
11 
12 using namespace std;
13 
14 #include "GlobalGoalKeeper.h"
15 #include "KKBaseTypes.h"
16 #include "OSservices.h"
17 #include "RunLog.h"
18 #include "KKStr.h"
19 using namespace KKB;
20 
21 
22 #include "ScannerFile.h"
23 #include "Variables.h"
25 using namespace KKLSC;
26 
27 
29 {
31  ushort endOfTextBlock : 1; /**< Last text block in message. If a message requires more than *
32  * 4096 bytes it will be written in multiple text blocks with *
33  * the last one having this flag set to '1'. */
34  ushort length : 12; /**< Text Block length. */
35 }; /* OpRecTextBlock */
36 
37 
39 {
41  ushort eol :1;
46 }; /* OpRec4RawPixels */
47 
48 
49 struct ScannerFile3BitEncoded::OpRecSpaces // OpCode = 2
50 {
52  ushort eol :1;
54 }; /* OpRecSpaces */
55 
56 
57 
59 {
61  ushort eol :1;
63 }; /* OpRecBlackOuts */
64 
65 
66 
67 struct ScannerFile3BitEncoded::OpRecRunLen // OpCode = 4
68 {
70  ushort eol :1;
72  ushort pix :3;
73 }; /* OpRecBlackOuts */
74 
75 
76 
77 
78 
80 {
81  OpRecTextBlock textBlock; // OpCode = 0
82  OpRec4RawPixels rawPixels; // OpCode = 1
83  OpRecSpaces spaces; // OpCode = 2
84  OpRecBlackOuts blackOuts; // OpCode = 3
86 }; /* OpRec */
87 
88 
89 //#pragma pack(show)
90 
91 
92 uchar* ScannerFile3BitEncoded::convTable3BitTo8Bit = NULL;
93 uchar* ScannerFile3BitEncoded::convTable8BitTo3Bit = NULL;
94 uchar* ScannerFile3BitEncoded::compensationTable = NULL;
95 
96 
98  RunLog& _log
99  ):
100  ScannerFile (_fileName, _log),
101  outputBuff (NULL),
102  outputBuffLen (0),
103  workLine (NULL),
104  workLineLen (0)
105 
106 {
107  BuildConversionTables ();
108  AllocateWorkLineAndOutputBuf ();
109  memset (fourSpaces, 0, sizeof (fourSpaces));
110  memset (fourBlackOuts, 7, sizeof (fourBlackOuts)); // In 3bit world '7' = 255
111 }
112 
113 
114 
116  kkuint32 _pixelsPerScanLine,
117  kkuint32 _frameHeight,
118  RunLog& _log
119  ):
120  ScannerFile (_fileName, _pixelsPerScanLine, _frameHeight, _log),
121  outputBuff (NULL),
122  outputBuffLen (0),
123  workLine (NULL),
124  workLineLen (0)
125 
126 {
127  BuildConversionTables ();
128  AllocateWorkLineAndOutputBuf ();
129  memset (fourSpaces, 0, sizeof (fourSpaces));
130  memset (fourBlackOuts, 7, sizeof (fourBlackOuts));
131 }
132 
133 
134 
136 {
137  if (opened)
138  Close ();
139  delete outputBuff; outputBuff = NULL;
140  delete workLine; workLine = NULL;
141 }
142 
143 
144 
145 void ScannerFile3BitEncoded::BuildConversionTables ()
146 {
148 
149  if (!convTable3BitTo8Bit)
150  {
151  kkint32 x = 0;
152  kkint32 y = 0;
153  float inc = 255.0f / 8.0f;
154  convTable3BitTo8Bit = new uchar[8];
155  convTable8BitTo3Bit = new uchar[256];
156  for (x = 0; x < 8; ++x)
157  {
158  kkint32 this8Bit = (kkint32)(0.5f + (float)x * inc);
159  kkint32 next8Bit = (kkint32)(0.5f + (float)(x + 1) * inc);
160 
161  kkint32 threeBitTo8BitNum = (kkint32)(this8Bit + (x / 7.0f) * (next8Bit - this8Bit));
162 
163  convTable3BitTo8Bit[x] = (uchar)threeBitTo8BitNum;
164  for (y = this8Bit; y <= next8Bit; ++y)
165  convTable8BitTo3Bit[y] = x;
166  }
167 
168  compensationTable = new uchar[256];
169  for (kkint16 pv = 0; pv < 256; ++pv)
170  {
171  uchar encodedValue = convTable8BitTo3Bit[pv];
172  compensationTable[pv] = convTable3BitTo8Bit[encodedValue];
173  }
174 
175  atexit (ScannerFile3BitEncoded::ExitCleanUp);
176  }
177 
179 } /* BuildConversionTables */
180 
181 
182 
184 {
186  if (!compensationTable)
187  BuildConversionTables ();
189 
190  return compensationTable;
191 }
192 
193 
194 
195 void ScannerFile3BitEncoded::ExitCleanUp ()
196 {
198  delete convTable3BitTo8Bit; convTable3BitTo8Bit = NULL;
199  delete convTable8BitTo3Bit; convTable8BitTo3Bit = NULL;
200  delete compensationTable; compensationTable = NULL;
202 }
203 
204 
205 
206 
207 void ScannerFile3BitEncoded::AllocateWorkLineAndOutputBuf ()
208 {
209  delete outputBuff; outputBuff = NULL;
210  delete workLine; workLine = NULL;
211 
212  workLineLen = Max (1024U, pixelsPerScanLine);
213  workLine = new uchar[workLineLen];
214 
215  outputBuffLen = workLineLen / 4 + 10;
216  outputBuff = new OpRec[outputBuffLen];
217 } /* AllocateWorkLineAndOutputBuf */
218 
219 
220 
221 
222 void ScannerFile3BitEncoded::ScanRate (float _scanRate)
223 {
224  ScannerFile::ScanRate (_scanRate);
225 }
226 
227 
228 
229 
231 {
232  frameBufferLen = 0;
234  if (feof (file) != 0)
235  {
236  memset (frameBuffer, 0, frameBufferSize);
237  return 0;
238  }
239 
241  kkuint32 numScanLinesReadThisFrameBuffer = 0;
242  uchar* buffPtr = frameBuffer;
243 
244  while ((feof (file) == 0) && (numScanLinesReadThisFrameBuffer < frameHeight))
245  {
246  GetNextScanLine (buffPtr, pixelsPerScanLine);
247  frameBufferLen += pixelsPerScanLine;
248  buffPtr += pixelsPerScanLine;
249  ++numScanLinesReadThisFrameBuffer;
250  }
251 
252  bool endOfFileFound = (feof (file) != 0);
253  if (endOfFileFound)
254  cerr << "end of file was found." << endl;
255 
258  return numScanLinesReadThisFrameBuffer;
259 } /* ReadBufferFrame */
260 
261 
262 
264 {
265  uchar* scanLine = new uchar[pixelsPerScanLine];
266 
267  kkuint32 numScanLinesReadThisFrameBuffer = 0;
268  while ((feof (file) == 0) && (numScanLinesReadThisFrameBuffer < frameHeight))
269  {
270  GetNextScanLine (scanLine, pixelsPerScanLine);
271  ++numScanLinesReadThisFrameBuffer;
272  }
273 
274  delete[] scanLine;
275  scanLine = NULL;
276 
277  if (feof (file) != 0)
278  return -1;
279  else
280  return osFTELL (file);
281 } /* SkipToNextFrame */
282 
283 
284 
285 void ScannerFile3BitEncoded::GetNextScanLine (uchar* lineBuff,
286  kkuint32 lineBuffSize
287  )
288 {
289  bool eol = false;
290  uchar opCode = 0;
291  OpRec rec;
292  kkuint32 recsRead = 0;
293 
294  kkuint32 lineSize = 0;
295 
296  char* textMsg = NULL;
297  kkuint32 textMsgLen = 0;
298 
299  do
300  {
301  recsRead = fread (&rec, sizeof (rec), 1, file);
302  if (recsRead == 0)
303  {
304  break;
305  }
306 
307  opCode = rec.textBlock.opCode;
308 
309  switch (opCode)
310  {
311  case 0:
312  {
313  // textBlock
314  kkuint32 numTextBytes = rec.textBlock.length;
315  bool endOfTextBlock = rec.textBlock.endOfTextBlock;
316 
317 
318  if (numTextBytes < 1)
319  {
320  // Invalid Text Block ?????
321  /**@todo ScannerFile3BitEncoded::GetNextScanLine How do we get invalid text blocks */
322  break;
323  }
324 
325  char* textMsgPtr = NULL;
326 
327  if (!textMsg)
328  {
329  textMsg = new char[numTextBytes];
330  textMsgLen = numTextBytes;
331  textMsgPtr = textMsg;
332  }
333  else
334  {
335  kkint32 newTextMsgLen = textMsgLen + numTextBytes;
336  char* newTextMsg = new char[newTextMsgLen];
337  memcpy (newTextMsg, textMsg, textMsgLen);
338  textMsgPtr = newTextMsg + textMsgLen;
339  delete textMsg;
340  textMsg = newTextMsg;
341  newTextMsg = NULL;
342  textMsgLen = newTextMsgLen;
343  }
344 
345  recsRead = fread (textMsgPtr, 1, numTextBytes, file);
346  if (recsRead < numTextBytes)
347  {
348  eol = true;
349  }
350  if (endOfTextBlock)
351  {
352  ReportTextMsg (textMsg, textMsgLen);
353  delete[] textMsg; textMsg = NULL;
354  textMsgLen = 0;
355  }
356  }
357  break;
358 
359 
360  case 1:
361  {
362  eol = (rec.rawPixels.eol == 1);
363  if (lineSize >= (lineBuffSize - 4))
364  {
365  // We are going to exceed the length of the provided buffer.
366  lineSize = lineBuffSize;
367  }
368  else
369  {
370  uchar pix0 = convTable3BitTo8Bit[rec.rawPixels.pix0];
371  uchar pix1 = convTable3BitTo8Bit[rec.rawPixels.pix1];
372  uchar pix2 = convTable3BitTo8Bit[rec.rawPixels.pix2];
373  uchar pix3 = convTable3BitTo8Bit[rec.rawPixels.pix3];
374 
375  lineBuff[lineSize] = pix0;
376  lineSize++;
377 
378  lineBuff[lineSize] = pix1;
379  lineSize++;
380 
381  lineBuff[lineSize] = pix2;
382  lineSize++;
383 
384  lineBuff[lineSize] = pix3;
385  lineSize++;
386  }
387  }
388  break;
389 
390  case 2:
391  {
392  eol = (rec.spaces.eol == 1);
393  kkuint32 numSpaces = 4 * rec.spaces.num4Spaces;
394  kkuint32 newLineSize = lineSize + numSpaces;
395  if (newLineSize >= lineBuffSize)
396  {
397  numSpaces = lineBuffSize - lineSize;
398  newLineSize = lineBuffSize;
399  }
400 
401  memset (&(lineBuff[lineSize]), 0, numSpaces);
402  lineSize = newLineSize;
403  }
404  break;
405 
406 
407  case 3:
408  {
409  eol = (rec.blackOuts.eol == 1);
410  kkuint32 numBlackOuts = 4 * (kkuint32)(rec.blackOuts.num4BlackOuts);
411  kkuint32 newLineSize = lineSize + numBlackOuts;
412  if (newLineSize >= lineBuffSize)
413  {
414  if (lineSize > lineBuffSize)
415  cout << endl << "How Can This Happen !!!!" << endl << endl;
416 
417  numBlackOuts = lineBuffSize - lineSize;
418  newLineSize = lineBuffSize;
419  }
420 
421  memset (&(lineBuff[lineSize]), 255, numBlackOuts);
422  lineSize = newLineSize;
423  }
424  break;
425 
426  case 4:
427  {
428  eol = (rec.runLen.eol == 1);
429  kkuint32 runLen = rec.runLen.runLen;
430  uchar pixelValue = convTable3BitTo8Bit[rec.runLen.pix];
431 
432  kkuint32 newLineSize = lineSize + runLen;
433  if (newLineSize >= lineBuffSize)
434  {
435  runLen = lineBuffSize - lineSize;
436  newLineSize = lineBuffSize;
437  }
438 
439  memset (&(lineBuff[lineSize]), pixelValue, runLen);
440  lineSize = newLineSize;
441  }
442  break;
443  }
444  } while (!eol);
445 
446 
447  if (textMsg)
448  {
449  ReportTextMsg (textMsg, textMsgLen);
450  delete[] textMsg; textMsg = NULL;
451  textMsgLen = 0;
452  }
453 } /* GetNextScanLine */
454 
455 
456 
457 
459 {
461  //nextScanLineOffset = osFTELL (file);
462 
463  kkuint32 frameRow = 0;
464  uchar* framePtr = frameBuffer;
465  while (frameRow < frameBufferNextLine)
466  {
467  WriteNextScanLine (framePtr, pixelsPerScanLine);
468  framePtr += pixelsPerScanLine;
469  ++frameRow;
470  }
471 
472  #if defined(OS_WINDOWS)
474  #else
475  /**
476  *@todo We need to implement a 64 bit ftell function for non windows; this will involve
477  * implementation of '#define _FILE_OFFSET_BITS 64' and ftell; probably thru macros
478  * in the "FirstIncludes.h" file.
479  */
480  #endif
481 
483 } /* WriteBufferFrame*/
484 
485 
486 
487 void ScannerFile3BitEncoded::Write4Spaces (OpRecPtr& outputBuffPtr,
488  kkint32& outputBuffUsed,
489  kkint32& num4SpacesInARow,
490  ushort eol
491  )
492 {
493  if (num4SpacesInARow > 0)
494  {
495  outputBuffPtr->spaces.opCode = 2; // Spaces Code.
496  outputBuffPtr->spaces.eol = eol;
497  outputBuffPtr->spaces.num4Spaces = num4SpacesInARow;
498  ++outputBuffPtr;
499  ++outputBuffUsed;
500  num4SpacesInARow = 0;
501  }
502 } /* Write4Spaces */
503 
504 
505 
506 void ScannerFile3BitEncoded::Write4BlackOuts (OpRecPtr& outputBuffPtr,
507  kkint32& outputBuffUsed,
508  kkint32& num4BlackOutsInARow,
509  ushort eol
510  )
511 {
512  if (num4BlackOutsInARow > 0)
513  {
514  outputBuffPtr->blackOuts.opCode = 3; // Spaces Code.
515  outputBuffPtr->blackOuts.eol = eol;
516  outputBuffPtr->blackOuts.num4BlackOuts = num4BlackOutsInARow;
517  ++outputBuffPtr;
518  ++outputBuffUsed;
519  num4BlackOutsInARow = 0;
520  }
521 } /* Write4BlackOuts */
522 
523 
524 
525 void ScannerFile3BitEncoded::WriteNextScanLine (const uchar* buffer,
526  kkuint32 bufferLen
527  )
528 {
529  kkuint32 x = 0;
530 
531  if (bufferLen > workLineLen)
532  {
533  // the buffer line being passed in is larger than the current workLine so we need to expand workLine.
534  delete workLine;
535  workLine = new uchar[bufferLen];
536  workLineLen = bufferLen;
537  }
538 
539  for (x = 0; x < bufferLen; ++x)
540  workLine[x] = convTable8BitTo3Bit[buffer[x]];
541 
542  kkint32 outputBuffUsed = 0;
543  kkint32 num4SpacesInARow = 0;
544  kkint32 num4BlackOutsInARow = 0;
545  x = 0;
546  uchar* workLinePtr = workLine;
547  OpRecPtr outputBuffPtr = outputBuff;
548 
549  while (x < (bufferLen - 3))
550  {
551  if (memcmp (workLinePtr, fourSpaces, sizeof (fourSpaces)) == 0)
552  {
553  Write4BlackOuts (outputBuffPtr, outputBuffUsed, num4BlackOutsInARow, 0);
554  ++num4SpacesInARow;
555  x += 4;
556  workLinePtr += 4;
557  }
558 
559  else if (memcmp (workLinePtr, fourBlackOuts, sizeof (fourBlackOuts)) == 0)
560  {
561  Write4Spaces (outputBuffPtr, outputBuffUsed, num4SpacesInARow, 0);
562  ++num4BlackOutsInARow;
563  x += 4;
564  workLinePtr += 4;
565  }
566 
567  else
568  {
569  Write4Spaces (outputBuffPtr, outputBuffUsed, num4SpacesInARow, 0);
570  Write4BlackOuts (outputBuffPtr, outputBuffUsed, num4BlackOutsInARow, 0);
571 
572  outputBuffPtr->rawPixels.opCode = 1;
573  outputBuffPtr->rawPixels.eol = 0;
574  outputBuffPtr->rawPixels.pix0 = workLine[x]; ++x;
575  outputBuffPtr->rawPixels.pix1 = workLine[x]; ++x;
576  outputBuffPtr->rawPixels.pix2 = workLine[x]; ++x;
577  outputBuffPtr->rawPixels.pix3 = workLine[x]; ++x;
578  ++outputBuffPtr;
579  ++outputBuffUsed;
580  workLinePtr += 4;
581  }
582  }
583 
584  if (num4SpacesInARow > 0)
585  Write4Spaces (outputBuffPtr, outputBuffUsed, num4SpacesInARow, 1);
586 
587  else if (num4BlackOutsInARow > 0)
588  Write4BlackOuts (outputBuffPtr, outputBuffUsed, num4BlackOutsInARow, 1);
589 
590 
591  outputBuff[outputBuffUsed - 1].spaces.eol = 1; // Set the EOL flag
592 
593  fwrite (outputBuff, sizeof (OpRec), outputBuffUsed, file);
594 
596 } /* WriteNextScanLine */
597 
598 
599 
600 
601 
602 void ScannerFile3BitEncoded::WriteNextScanLine2 (const uchar* buffer,
603  kkuint32 bufferLen
604  )
605 {
606  kkuint32 x = 0;
607 
608  if (bufferLen > workLineLen)
609  {
610  // the buffer line being passed in is larger than the current workLine so we need to expand workLine.
611  delete workLine;
612  workLine = new uchar[bufferLen];
613  workLineLen = bufferLen;
614  }
615 
616  for (x = 0; x < bufferLen; ++x)
617  workLine[x] = convTable8BitTo3Bit[buffer[x]];
618 
619  curCompStatus = csNull;
620 
621  kkint32 outputBuffUsed = 0;
622  kkint32 num4SpacesInARow = 0;
623  kkint32 num4BlackOutsInARow = 0;
624  x = 0;
625  uchar* workLinePtr = workLine;
626  OpRecPtr outputBuffPtr = outputBuff;
627 
628  while (x < (bufferLen - 3))
629  {
630  if (memcmp (workLinePtr, fourSpaces, sizeof (fourSpaces)) == 0)
631  {
632  Write4BlackOuts (outputBuffPtr, outputBuffUsed, num4BlackOutsInARow, 0);
633  ++num4SpacesInARow;
634  x += 4;
635  workLinePtr += 4;
636  }
637 
638  else if (memcmp (workLinePtr, fourBlackOuts, sizeof (fourBlackOuts)) == 0)
639  {
640  Write4Spaces (outputBuffPtr, outputBuffUsed, num4SpacesInARow, 0);
641  ++num4BlackOutsInARow;
642  x += 4;
643  workLinePtr += 4;
644  }
645 
646  else
647  {
648  Write4Spaces (outputBuffPtr, outputBuffUsed, num4SpacesInARow, 0);
649  Write4BlackOuts (outputBuffPtr, outputBuffUsed, num4BlackOutsInARow, 0);
650 
651  outputBuffPtr->rawPixels.opCode = 1;
652  outputBuffPtr->rawPixels.eol = 0;
653 
654  outputBuffPtr->rawPixels.pix0 = workLine[x]; ++x;
655  outputBuffPtr->rawPixels.pix1 = workLine[x]; ++x;
656  outputBuffPtr->rawPixels.pix2 = workLine[x]; ++x;
657  outputBuffPtr->rawPixels.pix3 = workLine[x]; ++x;
658  ++outputBuffPtr;
659  ++outputBuffUsed;
660  workLinePtr += 4;
661  }
662  }
663 
664  if (num4SpacesInARow > 0)
665  Write4Spaces (outputBuffPtr, outputBuffUsed, num4SpacesInARow, 1);
666 
667  else if (num4BlackOutsInARow > 0)
668  Write4BlackOuts (outputBuffPtr, outputBuffUsed, num4BlackOutsInARow, 1);
669 
670 
671  outputBuff[outputBuffUsed - 1].spaces.eol = 1; // Set the EOL flag
672 
673  fwrite (outputBuff, sizeof (OpRec), outputBuffUsed, file);
674 
676 } /* WriteNextScanLine2 */
677 
678 
679 
680 
681 
682 
684  kkuint32 txtBlockLen
685  )
686 {
687  kkint32 charsLeft = txtBlockLen;
688  const uchar* txtBlockPtr = txtBlock;
689  while (charsLeft > 0)
690  {
691  kkint32 charsToWrite = Min (4096, charsLeft);
692  OpRec rec;
693  rec.textBlock.opCode = 0;
694  rec.textBlock.endOfTextBlock = (charsToWrite < charsLeft) ? 0 : 1;
695  rec.textBlock.length = charsToWrite;
696  fwrite (&rec, sizeof (rec), 1, file);
697  fwrite (txtBlockPtr, 1, charsToWrite, file);
698  charsLeft -= charsToWrite;
699  txtBlockPtr += charsToWrite;
700  }
701 
702  //nextScanLineOffset = osFTELL (file);
704 } /* WriteTextBlock */
__int16 kkint16
16 bit signed integer.
Definition: KKBaseTypes.h:85
kkint64 frameBufferFileOffsetLast
Definition: ScannerFile.h:427
kkint64 frameBufferFileOffsetNext
Definition: ScannerFile.h:429
kkint64 fileSizeInBytes
Definition: ScannerFile.h:396
__int32 kkint32
Definition: KKBaseTypes.h:88
kkint64 osFTELL(FILE *f)
Calls the appropriate 64 bit function for operating system.
Definition: OSservices.cpp:93
kkuint32 frameBufferLen
Definition: ScannerFile.h:435
unsigned __int32 kkuint32
Definition: KKBaseTypes.h:89
__int64 kkint64
Definition: KKBaseTypes.h:90
KKTHread * KKTHreadPtr
virtual void ScanRate(float _scanRate)
unsigned char uchar
Unsigned character.
Definition: KKBaseTypes.h:77
static KKStr Concat(const std::vector< std::string > &values)
Concatenates the list of &#39;std::string&#39; strings.
Definition: KKStr.cpp:1082
virtual kkint64 SkipToNextFrame()
Skip to start of next frame returning back byte offset of that frame.
Contains Classes that are specific to Cameras physical characteristics.
kkuint32 ReadBufferFrame()
Read on one Scanner File Frame.
unsigned short ushort
Unsigned short.
Definition: KKBaseTypes.h:79
ScannerFile3BitEncoded(const KKStr &_fileName, kkuint32 _pixelsPerScanLine, kkuint32 _frameHeight, RunLog &_log)
Implements a 3 bit Encoded format.
static const uchar * CompensationTable()
kkuint32 frameBufferNextLine
Definition: ScannerFile.h:441
#define OS_WINDOWS
Definition: FirstIncludes.h:11
kkuint32 pixelsPerScanLine
Definition: ScannerFile.h:407
Used for logging messages.
Definition: RunLog.h:49
virtual void WriteTextBlock(const uchar *txtBlock, kkuint32 txtBlockLen)
virtual void WriteBufferFrame()
Write the contents of &#39;frameBuffer&#39; to he end of the scanner file.
ScannerFile(const KKStr &_fileName, kkuint32 _pixelsPerScanLine, kkuint32 _frameHeight, RunLog &_log)
Maintains one instance of a GoalKeeper object that can be used anywhere in the application.
ScannerFile3BitEncoded(const KKStr &_fileName, RunLog &_log)
ScannerFile(const KKStr &_fileName, RunLog &_log)
Definition: ScannerFile.cpp:40