Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

194 lines
4.6 KiB

  1. #include "common.h"
  2. #include "glyph.h"
  3. #include "score.h"
  4. #include "fugu.h"
  5. #include "volcanop.h"
  6. #include "nnet.h"
  7. #define FUGU_SEG_MAX_SPACES 32
  8. static int g_cSpaces;
  9. static FUGU_INTEGER_WEIGHTS g_aCharDetNet[FUGU_SEG_MAX_SPACES];
  10. POINT *DupPoints(POINT *pOldPoints, int nPoints);
  11. GLYPH *GlyphFromStrokes(UINT cStrokes, STROKE *pStrokes);
  12. // prepare net from pointer
  13. BOOL PrepareCharDetNet (BYTE *pb, FUGU_INTEGER_WEIGHTS *pCharDetNet)
  14. {
  15. pCharDetNet->pHeader = (FUGU_INTEGER_WEIGHTS_HEADER *) pb;
  16. pCharDetNet->pfdchMapping = (WCHAR *) (pb + sizeof(FUGU_INTEGER_WEIGHTS_HEADER));
  17. pCharDetNet->pbWeights = pb + sizeof(FUGU_INTEGER_WEIGHTS_HEADER) +
  18. sizeof(WCHAR) * pCharDetNet->pHeader->arch.nOutputs;
  19. return TRUE;
  20. }
  21. // validates the header of the brknet
  22. int CheckCharDetHeader (void *pData)
  23. {
  24. NNET_HEADER *pHeader = (NNET_HEADER *)pData;
  25. // wrong magic number
  26. ASSERT (pHeader->dwFileType == CHARDET_FILE_TYPE);
  27. if (pHeader->dwFileType != CHARDET_FILE_TYPE)
  28. {
  29. return FALSE;
  30. }
  31. // check version
  32. ASSERT(pHeader->iFileVer >= CHARDET_OLD_FILE_VERSION);
  33. ASSERT(pHeader->iMinCodeVer <= CHARDET_CUR_FILE_VERSION);
  34. ASSERT ( !memcmp ( pHeader->adwSignature,
  35. g_locRunInfo.adwSignature,
  36. sizeof (pHeader->adwSignature)
  37. )
  38. );
  39. ASSERT (pHeader->cSpace <= FUGU_SEG_MAX_SPACES);
  40. if ( pHeader->iFileVer >= CHARDET_OLD_FILE_VERSION &&
  41. pHeader->iMinCodeVer <= CHARDET_CUR_FILE_VERSION &&
  42. !memcmp ( pHeader->adwSignature,
  43. g_locRunInfo.adwSignature,
  44. sizeof (pHeader->adwSignature)
  45. ) &&
  46. pHeader->cSpace <= FUGU_SEG_MAX_SPACES
  47. )
  48. {
  49. return pHeader->cSpace;
  50. }
  51. else
  52. {
  53. return 0;
  54. }
  55. }
  56. // does the necessary preparations for a net to be used later
  57. static BOOL CharDetLoadFromPointer (BYTE *pData)
  58. {
  59. int iSpc, cSpc, iSpaceID;
  60. NNET_SPACE_HEADER *pSpaceHeader;
  61. BYTE *pPtr;
  62. if (!pData)
  63. {
  64. return FALSE;
  65. }
  66. // check the header info
  67. cSpc = CheckCharDetHeader (pData);
  68. g_cSpaces = cSpc;
  69. if (cSpc <= 0)
  70. {
  71. return FALSE;
  72. }
  73. pPtr = pData + sizeof (NNET_HEADER);
  74. for (iSpc = 0; iSpc < cSpc; iSpc++)
  75. {
  76. // point to the one and only space that we have
  77. pSpaceHeader = (NNET_SPACE_HEADER *)pPtr;
  78. pPtr += sizeof (NNET_SPACE_HEADER);
  79. // point to the actual data
  80. iSpaceID = pSpaceHeader->iSpace;
  81. ASSERT (iSpaceID >= 1 && iSpaceID <= FUGU_SEG_MAX_SPACES);
  82. if (!PrepareCharDetNet ( pData + pSpaceHeader->iDataOffset,
  83. g_aCharDetNet + iSpaceID - 1
  84. )
  85. )
  86. {
  87. return FALSE;
  88. }
  89. }
  90. return TRUE;
  91. }
  92. BOOL LoadCharDetFromFile(wchar_t *wszPath, LOAD_INFO *pLoadInfo)
  93. {
  94. wchar_t awszFileName[MAX_PATH];
  95. // memory map the file
  96. wsprintf (awszFileName, L"%s\\chardet.bin", wszPath);
  97. if (!DoOpenFile(pLoadInfo, awszFileName))
  98. {
  99. return FALSE;
  100. }
  101. return CharDetLoadFromPointer (pLoadInfo->pbMapping);
  102. }
  103. BOOL LoadCharDetFromResource (HINSTANCE hInst, int nResID, int nType)
  104. {
  105. LOAD_INFO LoadInfo;
  106. if (!DoLoadResource (&LoadInfo, hInst, nResID, nType))
  107. {
  108. return FALSE;
  109. }
  110. return CharDetLoadFromPointer (LoadInfo.pbMapping);
  111. }
  112. BOOL CharDetUnloadFile(LOAD_INFO *pInfo)
  113. {
  114. return DoCloseFile(pInfo);
  115. }
  116. int *ApplyFuguInteger(FUGU_INTEGER_WEIGHTS *pFugu, int aiInput[FUGU_INPUT_WIDTH][FUGU_INPUT_HEIGHT]);
  117. float FuguSegScore(int cStrokes, STROKE *pStrokes, LOCRUN_INFO *pLocRunInfo)
  118. {
  119. GLYPH *pGlyph = GlyphFromStrokes(cStrokes, pStrokes);
  120. int i;
  121. int aiInput[FUGU_INPUT_WIDTH][FUGU_INPUT_HEIGHT];
  122. int *piOutput = NULL;
  123. float flOutput = 0;
  124. if (cStrokes >= 1 && cStrokes <= g_cSpaces)
  125. {
  126. // First convert the ink to 29x29 input region
  127. if (!FuguRender(pGlyph, NULL, aiInput))
  128. {
  129. return -1;
  130. }
  131. // Apply the recognizer
  132. piOutput = ApplyFuguInteger(g_aCharDetNet + cStrokes - 1, aiInput);
  133. if (piOutput == NULL)
  134. {
  135. return -1;
  136. }
  137. for (i = 0; i < g_aCharDetNet[cStrokes - 1].pHeader->arch.nOutputs; i++)
  138. {
  139. wchar_t wch = g_aCharDetNet[cStrokes - 1].pfdchMapping[i];
  140. // I'm assuming every space will have "not a char" samples. Note that
  141. // there are two possible mappings for "not a char", the old one L'0'
  142. // and the new one which is simply 0.
  143. if (wch == 0 || wch == L'0')
  144. {
  145. int cRight = FUGU_ACTIVATION_SCALE - piOutput[i];
  146. if (cRight == 0)
  147. {
  148. cRight = 1;
  149. }
  150. flOutput = (float) cRight / (float) FUGU_ACTIVATION_SCALE;
  151. }
  152. }
  153. }
  154. DestroyFramesGLYPH(pGlyph);
  155. DestroyGLYPH(pGlyph);
  156. ExternFree(piOutput);
  157. return flOutput;
  158. }