www.pudn.com > QRAPPuie.rar > QRapi.cpp
/******************************************************************************** * QRAPI.cpp * * Source file for QR code image processing API. Provides * function realization for QR image processing * *AUTHOR: Song Shaojing * *DATE: 2005.12.06 * ********************************************************************************/ #include "stdafx.h" #include "QRapi.h" #include#include #include //#include //#include #include #include #include #include #include HGLOBAL hIndexData=NULL; HGLOBAL hMaskImg=NULL; HGLOBAL hMarkImage=NULL; HGLOBAL hOriginalCode=NULL; HGLOBAL hDecodeData=NULL; // local use macro ORIENTATIONCENTER TopLeft={0,0}; ORIENTATIONCENTER TopRight={0,0}; ORIENTATIONCENTER BottomLeft={0,0}; unsigned char ReviseImgPos[8];//[5] is the number of coordinate. // The following kernel definitions are for convolution filtering. // Kernel entries are specified with a divisor to get around the // requirement for floating point numbers in the low pass filters. QRKERNEL QRHP1 = { // HP filter #1 {-1, -1, -1, -1, 9, -1, -1, -1, -1}, 1 // Divisor = 1 }; QRKERNEL QRHP2 = { // HP filter #2 { 0, -1, 0, -1, 5, -1, 0, -1, 0}, 1 // Divisor = 1 }; QRKERNEL QRHP3 = { // HP filter #3 { 1, -2, 1, -2, 5, -2, 1, -2, 1}, 1 // Divisor = 1 }; QRKERNEL QRLP1 = { // LP filter #1 { 1, 1, 1, 1, 1, 1, 1, 1, 1}, 9 // Divisor = 9 }; QRKERNEL QRLP2 = { // LP filter #2 { 1, 1, 1, 1, 2, 1, 1, 1, 1}, 10 // Divisor = 10 }; QRKERNEL QRLP3 = { // LP filter #3 { 1, 2, 1, 2, 4, 2, 1, 2, 1}, 16 // Divisor = 16 }; QRKERNEL QRVertEdge = { // Vertical edge { 0, 0, 0, -1, 1, 0, 0, 0, 0}, 1 // Divisor = 1 }; QRKERNEL QRHorzEdge = { // Horizontal edge { 0, -1, 0, 0, 1, 0, 0, 0, 0}, 1 // Divisor = 1 }; QRKERNEL QRVertHorzEdge = { // Vertical Horizontal edge { -1, 0, 0, 0, 1, 0, 0, 0, 0}, 1 // Divisor = 1 }; QRKERNEL QREdgeNorth = { // North gradient { 1, 1, 1, 1, -2, 1, -1, -1, -1}, 1 // Divisor = 1 }; QRKERNEL QREdgeNorthEast = { // North East gradient { 1, 1, 1, -1, -2, 1, -1, -1, 1}, 1 // Divisor = 1 }; QRKERNEL QREdgeEast = { // East gradient {-1, 1, 1, -1, -2, 1, -1, 1, 1}, 1 // Divisor = 1 }; QRKERNEL QREdgeSouthEast = { // South East gradient {-1, -1, 1, -1, -2, 1, 1, 1, 1}, 1 // Divisor = 1 }; QRKERNEL QREdgeSouth = { // South gadient {-1, -1, -1, 1, -2, 1, 1, 1, 1}, 1 // Divisor = 1 }; QRKERNEL QREdgeSouthWest = { // South West gradient { 1, -1, -1, 1, -2, -1, 1, 1, 1}, 1 // Divisor = 1 }; QRKERNEL QREdgeWest = { // West gradient { 1, 1, -1, 1, -2, -1, 1, 1, -1}, 1 // Divisor = 1 }; QRKERNEL QREdgeNorthWest = { // North West gradient { 1, 1, 1, 1, -2, -1, 1, -1, -1}, 1 // Divisor = 1 }; QRKERNEL QRLap1 = { // Laplace filter 1 { 0, 1, 0, 1, -4, 1, 0, 1, 0}, 1 // Divisor = 1 }; QRKERNEL QRLap2 = { // Laplace filter 2 { -1, -1, -1, -1, 8, -1, -1, -1, -1}, 1 // Divisor = 1 }; QRKERNEL QRLap3 = { // Laplace filter 3 { -1, -1, -1, -1, 9, -1, -1, -1, -1}, 1 // Divisor = 1 }; QRKERNEL QRLap4 = { // Laplace filter 4 { 1, -2, 1, -2, 4, -2, 1, -2, 1}, 1 // Divisor = 1 }; QRKERNEL QRSobel[4] = { { // Sobel1 {-1, 0, 1, -2, 0, 2, -1, 0, 1}, 1 // Divisor = 1 }, { // Sobel2 {-1, -2, -1, 0, 0, 0, 1, 2, 1}, 1 // Divisor = 1 }, { // Sobel3 {-2, -1, 0, -1, 0, 1, 0, 1, 2}, 1 // Divisor = 1 }, { // Sobel4 {0, -1, -2, 1, 0, -1, 2, 1, 0}, 1 // Divisor = 1 } }; QRKERNEL QRHough[4] = { { // Hough1 {-1, 0, 1, -1, 0, 1, -1, 0, 1}, 1 // Divisor = 1 }, { // Hough2 {-1, -1, 0, -1, 0, 1, 0, 1, 1}, 1 // Divisor = 1 }, { // Hough3 {-1, -1, -1, 0, 0, 0, 1, 1, 1}, 1 // Divisor = 1 }, { // Hough4 {0, -1, -1, 1, 0, -1, 1, 1, 0}, 1 // Divisor = 1 } }; // function body /************************************************************************* * * HighPassDIB() * * Parameters: * * HQRIMG hDib - objective DIB handle * int nAlgorithm - specify the filter to use * int Strength - operation strength set to the convolute * * Return Value: * * BOOL - True is success, else False * * Description: * * High pass filtering to sharp DIB * ************************************************************************/ BOOL HighPassQR(HQRIMG hDib, int Strength, int nAlgorithm) { switch (nAlgorithm) { case QRFILTER1: return ConvoluteQR(hDib, &QRHP1, Strength); case QRFILTER2: return ConvoluteQR(hDib, &QRHP2, Strength); case QRFILTER3: return ConvoluteQR(hDib, &QRHP3, Strength); } return FALSE; } /************************************************************************* * * LowPassDIB() * * Parameters: * * HQRIMG hDib - objective DIB handle * int nAlgorithm - specify the filter to use * int Strength - operation strength set to the convolute * * Return Value: * * BOOL - True is success, else False * * Description: * * Low pass filtering to blur DIB * ************************************************************************/ BOOL LowPassQR(HQRIMG hDib, int Strength, int nAlgorithm) { switch (nAlgorithm) { case QRFILTER1: return ConvoluteQR(hDib, &QRLP1, Strength); case QRFILTER2: return ConvoluteQR(hDib, &QRLP2, Strength); case QRFILTER3: return ConvoluteQR(hDib, &QRLP3, Strength); } return FALSE; } /************************************************************************* * * EdgeEnhanceDIB() * * Parameters: * * HQRIMG hDib - objective DIB handle * int nAlgorithm - specify the filter to use * int Strength - operation strength set to the convolute * * Return Value: * * BOOL - True is success, else False * * Description: * * Edge enhance DIB * ************************************************************************/ BOOL EdgeEnhanceQR(HQRIMG hDib, int Strength, int nAlgorithm) { switch (nAlgorithm) { case QRVERT: return ConvoluteQR(hDib, &QRVertEdge, Strength); case QRHORZ: return ConvoluteQR(hDib, &QRHorzEdge, Strength); case QRVERTHORZ: return ConvoluteQR(hDib, &QRVertHorzEdge, Strength); case QRNORTH: return ConvoluteQR(hDib, &QREdgeNorth, Strength); case QRNORTHEAST: return ConvoluteQR(hDib, &QREdgeNorthEast, Strength); case QREAST: return ConvoluteQR(hDib, &QREdgeEast, Strength); case QRSOUTH: return ConvoluteQR(hDib, &QREdgeSouth, Strength); case QRSOUTHEAST: return ConvoluteQR(hDib, &QREdgeSouthEast, Strength); case QRSOUTHWEST: return ConvoluteQR(hDib, &QREdgeSouthWest, Strength); case QRWEST: return ConvoluteQR(hDib, &QREdgeWest, Strength); case QRNORTHWEST: return ConvoluteQR(hDib, &QREdgeNorthWest, Strength); case QRLAP1: return ConvoluteQR(hDib, &QRLap1, Strength); case QRLAP2: return ConvoluteQR(hDib, &QRLap2, Strength); case QRLAP3: return ConvoluteQR(hDib, &QRLap3, Strength); case QRLAP4: return ConvoluteQR(hDib, &QRLap4, Strength); case QRSOBEL: return ConvoluteQR(hDib, QRSobel, Strength, 4); case QRHOUGH: return ConvoluteQR(hDib, QRHough, Strength, 4); } return FALSE; } /************************************************************************* * * MedianFilterDIB() * * Parameters: * * HQRIMG hDib - objective DIB handle * * Return Value: * * BOOL - True is success, else False * * Description: * * This is the media filtering function to DIB * ************************************************************************/ BOOL MedianFilterQR(HQRIMG hDib) { QRWaitCursorBegin(); HQRIMG hNewDib = NULL; // we only convolute 24bpp DIB, so first convert DIB to 24bpp WORD wBitCount = QRBitCount(hDib); if (wBitCount != 24) return FALSE; //hNewDib = ConvertDIBFormat(hDib, 24, NULL); else hNewDib = CopyQRHandle(hDib); if (! hNewDib) { QRWaitCursorEnd(); return FALSE; } // new DIB attributes WORD wDIBWidth = (WORD)QRWidth(hNewDib); WORD wDIBHeight = (WORD)QRHeight(hNewDib); WORD wBytesPerLine = (WORD)QRBytesPerLine(hNewDib); DWORD dwImageSize = wBytesPerLine * wDIBHeight; // Allocate and lock memory for filtered image data HGLOBAL hFilteredBits = GlobalAlloc(GHND, dwImageSize); if (!hFilteredBits) { QRWaitCursorEnd(); return FALSE; } LPBYTE lpDestImage = (LPBYTE)GlobalLock(hFilteredBits); // get bits address in DIB LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib); LPBYTE lpDIBits = FindQRBits(lpDIB); // convolute... for (int i=1; i red) red = r; if (g > green) green = g; if (b > blue) blue = b; //red += r; green += g; blue += b; } // original RGB value in center pixel (j, i) LONG lOffset= PIXEL_OFFSET(i,j, wBytesPerLine); BYTE OldB = *(lpDIBits + lOffset++); BYTE OldG = *(lpDIBits + lOffset++); BYTE OldR = *(lpDIBits + lOffset); // When we get here, red, green and blue have the new RGB value. if (Strength != 10) { // Interpolate pixel data red = OldR + (((red - OldR) * Strength) / 10); green = OldG + (((green - OldG) * Strength) / 10); blue = OldB + (((blue - OldB) * Strength) / 10); } lOffset= PIXEL_OFFSET(i,j, wBytesPerLine); *(lpDestImage + lOffset++) = QRBOUND(blue, 0, 255); *(lpDestImage + lOffset++) = QRBOUND(green, 0, 255); *(lpDestImage + lOffset) = QRBOUND(red, 0, 255); } // a filtered image is available in lpDestImage // copy it to DIB bits memcpy(lpDIBits, lpDestImage, dwImageSize); // cleanup temp buffers GlobalUnlock(hFilteredBits); GlobalFree(hFilteredBits); GlobalUnlock(hNewDib); // rebuild hDib HQRIMG hTmp = NULL; if (wBitCount != 24) //if image is not 24bpp ,return return FALSE; //hTmp = ConvertDIBFormat(hNewDib, wBitCount, NULL); else hTmp = CopyQRHandle(hNewDib); GlobalFree(hNewDib); DWORD dwSize = GlobalSize(hTmp); memcpy((LPBYTE)GlobalLock(hDib), (LPBYTE)GlobalLock(hTmp), dwSize); GlobalUnlock(hTmp); GlobalFree(hTmp); GlobalUnlock(hDib); QRWaitCursorEnd(); return TRUE; } // local function: perform convolution to DIB with a kernel void DoConvoluteQR(int *red, int *green, int *blue, int i, int j, WORD wBytesPerLine, LPBYTE lpDIBits, QRKERNEL *lpKernel) { BYTE b[9], g[9], r[9]; LONG lOffset; lOffset= PIXEL_OFFSET(i-1,j-1, wBytesPerLine); b[0] = *(lpDIBits + lOffset++); g[0] = *(lpDIBits + lOffset++); r[0] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i-1,j, wBytesPerLine); b[1] = *(lpDIBits + lOffset++); g[1] = *(lpDIBits + lOffset++); r[1] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i-1,j+1, wBytesPerLine); b[2] = *(lpDIBits + lOffset++); g[2] = *(lpDIBits + lOffset++); r[2] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i,j-1, wBytesPerLine); b[3] = *(lpDIBits + lOffset++); g[3] = *(lpDIBits + lOffset++); r[3] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i,j, wBytesPerLine); b[4] = *(lpDIBits + lOffset++); g[4] = *(lpDIBits + lOffset++); r[4] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i,j+1, wBytesPerLine); b[5] = *(lpDIBits + lOffset++); g[5] = *(lpDIBits + lOffset++); r[5] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i+1,j-1, wBytesPerLine); b[6] = *(lpDIBits + lOffset++); g[6] = *(lpDIBits + lOffset++); r[6] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i+1,j, wBytesPerLine); b[7] = *(lpDIBits + lOffset++); g[7] = *(lpDIBits + lOffset++); r[7] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i+1,j+1, wBytesPerLine); b[8] = *(lpDIBits + lOffset++); g[8] = *(lpDIBits + lOffset++); r[8] = *(lpDIBits + lOffset); *red = *green = *blue = 0; for (int k=0; k<8; ++k) { *red += lpKernel->Element[k]*r[k]; *green += lpKernel->Element[k]*g[k]; *blue += lpKernel->Element[k]*b[k]; } if (lpKernel->Divisor != 1) { *red /= lpKernel->Divisor; *green /= lpKernel->Divisor; *blue /= lpKernel->Divisor; } } // function used to sort in the call of qsort int QRcompare(const void *e1, const void *e2) { if (*(BYTE *)e1 < *(BYTE *)e2) return -1; if (*(BYTE *)e1 > *(BYTE *)e2) return 1; return 0; } WORD QRBitCount(LPBYTE lpDIB) { if (IS_WIN30_QR(lpDIB)) return ((LPBITMAPINFOHEADER)lpDIB)->biBitCount; else return ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount; } WORD QRBitCount(HQRIMG hDIB) { LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); WORD wSize = QRBitCount(lpDIB); GlobalUnlock(hDIB); return wSize; } /************************************************************************* * * CopyHandle() * * Parameters: * * HANDLE h - source handle * * Return Value: * * HANDLE - duplicated handle * * Description: * * Copy memory handle to another ************************************************************************/ HANDLE CopyQRHandle(HANDLE h) { if (h == NULL) return NULL; DWORD dwLen = GlobalSize((HGLOBAL)h); HANDLE hCopy = GlobalAlloc(GHND, dwLen); if (hCopy == NULL) return NULL; void* lpCopy = GlobalLock((HGLOBAL) hCopy); void* lp = GlobalLock((HGLOBAL) h); CopyMemory(lpCopy, lp, dwLen); GlobalUnlock(hCopy); GlobalUnlock(h); return hCopy; } /************************************************************************* * * DIBWidth() * * Parameter: * * LPBYTE lpDIB - pointer to packed-DIB memory block * * Return Value: * * DWORD - width of the DIB * * Description: * * This function gets the width of the DIB from the BITMAPINFOHEADER * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER * width field if it is an OS/2-style DIB. * ************************************************************************/ DWORD QRWidth(LPBYTE lpDIB) { LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB LPBITMAPCOREHEADER lpbmc; // pointer to an OS/2-style DIB // point to the header (whether Win 3.0 and OS/2) lpbmi = (LPBITMAPINFOHEADER)lpDIB; lpbmc = (LPBITMAPCOREHEADER)lpDIB; // return the DIB width if it is a Win 3.0 DIB if (lpbmi->biSize == sizeof(BITMAPINFOHEADER)) return lpbmi->biWidth; else // it is an OS/2 DIB, so return its width return (DWORD)lpbmc->bcWidth; } DWORD QRWidth(HQRIMG hDIB) { LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); DWORD dw = QRWidth(lpDIB); GlobalUnlock(hDIB); return dw; } /************************************************************************* * * DIBHeight() * * Parameter: * * LPBYTE lpDIB - pointer to packed-DIB memory block * * Return Value: * * DWORD - height of the DIB * * Description: * * This function gets the height of the DIB from the BITMAPINFOHEADER * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER * height field if it is an OS/2-style DIB. * ************************************************************************/ DWORD QRHeight(LPBYTE lpDIB) { LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB LPBITMAPCOREHEADER lpbmc; // pointer to an OS/2-style DIB // point to the header (whether OS/2 or Win 3.0 lpbmi = (LPBITMAPINFOHEADER)lpDIB; lpbmc = (LPBITMAPCOREHEADER)lpDIB; // return the DIB height if it is a Win 3.0 DIB if (lpbmi->biSize == sizeof(BITMAPINFOHEADER)) return lpbmi->biHeight; else // it is an OS/2 DIB, so return its height return (DWORD)lpbmc->bcHeight; } DWORD QRHeight(HQRIMG hDIB) { LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); DWORD dw = QRHeight(lpDIB); GlobalUnlock(hDIB); return dw; } /**************************************************************************** * * FUNCTION: BytesPerLine * * PURPOSE: Calculates the number of bytes in one scan line. * * PARAMS: LPBYTE lpDIB - pointer to the BITMAPINFOHEADER that begins the CF_DIB block * * RETURNS: DWORD - number of bytes in one scan line (DWORD aligned) * \****************************************************************************/ DWORD QRBytesPerLine(LPBYTE lpDIB) { return QRWIDTHBYTES(((LPBITMAPINFOHEADER)lpDIB)->biWidth * ((LPBITMAPINFOHEADER)lpDIB)->biPlanes * ((LPBITMAPINFOHEADER)lpDIB)->biBitCount); } DWORD QRBytesPerLine(HQRIMG hDIB) { LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); DWORD dw = QRBytesPerLine(lpDIB); GlobalUnlock(hDIB); return dw; } /************************************************************************* * * FindDIBBits() * * Parameter: * * LPBYTE lpDIB - pointer to packed-DIB memory block * * Return Value: * * LPBYTE - pointer to the DIB bits * * Description: * * This function calculates the address of the DIB's bits and returns a * pointer to the DIB bits. * ************************************************************************/ LPBYTE FindQRBits(LPBYTE lpDIB) { return (lpDIB + *(LPDWORD)lpDIB + QRPaletteSize(lpDIB)); } /************************************************************************* * * PaletteSize() * * Parameter: * * LPBYTE lpDIB - pointer to packed-DIB memory block * * Return Value: * * WORD - size of the color palette of the DIB * * Description: * * This function gets the size required to store the DIB's palette by * multiplying the number of colors by the size of an RGBQUAD (for a * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an OS/2- * style DIB). * ************************************************************************/ WORD QRPaletteSize(LPBYTE lpDIB) { // calculate the size required by the palette if (IS_WIN30_QR (lpDIB)) return (QRNumColors(lpDIB) * sizeof(RGBQUAD)); else return (QRNumColors(lpDIB) * sizeof(RGBTRIPLE)); } WORD QRPaletteSize(HQRIMG hDIB) { LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); WORD wSize = QRPaletteSize(lpDIB); GlobalUnlock(hDIB); return wSize; } /************************************************************************* * * DIBNumColors() * * Parameter: * * LPBYTE lpDIB - pointer to packed-DIB memory block * * Return Value: * * WORD - number of colors in the color table * * Description: * * This function calculates the number of colors in the DIB's color table * by finding the bits per pixel for the DIB (whether Win3.0 or OS/2-style * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256, * if 24, no colors in color table. * ************************************************************************/ WORD QRNumColors(LPBYTE lpDIB) { WORD wBitCount; // DIB bit count // If this is a Windows-style DIB, the number of colors in the // color table can be less than the number of bits per pixel // allows for (i.e. lpbi->biClrUsed can be set to some value). // If this is the case, return the appropriate value. if (IS_WIN30_QR(lpDIB)) { DWORD dwClrUsed; dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed; if (dwClrUsed) return (WORD)dwClrUsed; } // Calculate the number of colors in the color table based on // the number of bits per pixel for the DIB. if (IS_WIN30_QR(lpDIB)) wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount; else wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount; // return number of colors based on bits per pixel switch (wBitCount) { case 1: return 2; case 4: return 16; case 8: return 256; default: return 0; } } WORD QRNumColors(HQRIMG hDIB) { LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); WORD wSize = QRNumColors(lpDIB); GlobalUnlock(hDIB); return wSize; } /**************************************************************************** * * FUNCTION: QRBlockSize * * PURPOSE: Calculates the number of bytes in one scan line. * * PARAMS: LPBYTE lpDIB - pointer to the BITMAPINFOHEADER that begins the CF_DIB block * * RETURNS: DWORD - DIB block size * \****************************************************************************/ DWORD QRBlockSize(LPBYTE lpDIB) { if (((LPBITMAPINFOHEADER)lpDIB)->biSizeImage == 0) ((LPBITMAPINFOHEADER)lpDIB)->biSizeImage = QRBytesPerLine(lpDIB) * ((LPBITMAPINFOHEADER)lpDIB)->biHeight; return ((LPBITMAPINFOHEADER)lpDIB)->biSize + QRPaletteSize(lpDIB) + ((LPBITMAPINFOHEADER)lpDIB)->biSizeImage; } DWORD QRBlockSize(HQRIMG hDIB) { LPBYTE lpDIB = (LPBYTE)GlobalLock(hDIB); DWORD dw = QRBlockSize(lpDIB); GlobalUnlock(hDIB); return dw; } /******************************************************************** * * void Histogram(long *Graytable) * *Parameters: * * long *Graytable - pointer to an array for the statistic data of every gray level * *Discription: * This function calculate the histogram of the gray QR image * ********************************************************************/ void Histogram(HQRIMG hDib,long * GrayTable,long *DifGrayTable) { DWORD BufSize,LineBytes,BitCounts; LPBITMAPINFOHEADER lpImgData,SrcBi; LPSTR lpPtr; int x,y,m,n; int grayindex; // HQRIMG hDifImg=NULL; int TempValue,TempGray,Center; int MaxValue=0; for(grayindex=0;grayindex<256;grayindex++) { GrayTable[grayindex]=0; DifGrayTable[grayindex]=0; } BufSize=QRBlockSize(hDib); BitCounts=QRBitCount(hDib); SrcBi=(LPBITMAPINFOHEADER)GlobalLock(hDib); LineBytes=(DWORD)QRWIDTHBYTES(SrcBi->biWidth*BitCounts); // hDifImg=CopyQRHandle(hDib); lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hDib); //lpDifImgData=(LPBITMAPINFOHEADER)GlobalLock(hDifImg); for(y=0;y biHeight;y++) { lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes); for(x=0;x biWidth;x++) { //to get histogram data of the differential image if(0 biWidth-1 && 0 biHeight-1) { Center=(unsigned char)*lpPtr; for(m=0;m<3;m++) for(n=0;n<3;n++) { TempValue=(unsigned char)*(lpPtr+(m-1)*LineBytes+n); TempGray=QRABS(Center,TempValue); if(TempGray>MaxValue) MaxValue=TempGray; } DifGrayTable[MaxValue]++; } grayindex=(unsigned char)*(lpPtr++); GrayTable[grayindex]++; } } GlobalUnlock(hDib); // GlobalUnlock(hDifImg); } // to get the differential image data and get the Histogram data of differential image /* for(y=1;y biHeight-1;y++) { lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes); lpDifPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes); for(x=1;x biWidth-1;x++) { for(m=0;m<3;m++) for(n=0;n<3;n++) { } TempValue=DoDifferential(lpPtr++,LineBytes); DifGrayTable[TempValue]++; } } */ /* unsigned char DoDifferential(LPSTR lpPtr,DWORD LineBytes) { unsigned char TemValue; unsigned char MaxValue=0; int x,y; for(x=0;x<3;x++) for(y=0;y<3;y++) { TemValue=QRABS((lpPtr+(x-1)*LineBytes+y),lpPtr); if(TemValue>MaxValue) MaxValue=TemValue; } return MaxValue; } */ int QRABS(int str1,int str2) { int Value; if(str1>=str2) Value=str1-str2; else Value=str2-str1; return Value; } /******************************************************************** * * int Erzhihua() * *Parameters: * * HQRIMG hDib - handle of the QR image * *Discription: * This function calculate the histogram of the gray QR image and get the adaptive * threshold value by OTSU algorithm * ********************************************************************/ BOOL Erzhihua(HQRIMG hDib) { DWORD BufSize,LineBytes,BitCounts; LPBITMAPINFOHEADER lpImgData,SrcBi; LPSTR lpPtr; int thresholdValue=1; // 阈值 int GrayTable[256]; // 图像直方图,256个点 int n, n1, n2; double m1, m2, sum, csum, fmax, sb; int x,y,k,grayindex; BufSize=QRBlockSize(hDib); BitCounts=QRBitCount(hDib); if(BitCounts!=8) return FALSE; SrcBi=(LPBITMAPINFOHEADER)GlobalLock(hDib); LineBytes=(DWORD)QRWIDTHBYTES(SrcBi->biWidth*BitCounts); // hDifImg=CopyQRHandle(hDib); lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hDib); // 对直方图置零... memset(GrayTable, 0, sizeof(GrayTable)); //to costruct the histogram of QR gray scale image; for(y=0;y biHeight;y++) { lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes); for(x=0;x biWidth;x++) { grayindex=(unsigned char)*(lpPtr++); GrayTable[grayindex]++; } } // set up everything sum = csum = 0.0; n = 0; for (k = 0; k < 256; k++) { sum += (double) k * (double) GrayTable[k]; /* x*f(x) 质量矩*/ n += GrayTable[k]; /* f(x) 质量 */ } if (!n) { return (128); } // do the otsu global thresholding method fmax = -1.0; n1 = 0; for (k = 0; k < 256; k++) { n1 += GrayTable[k]; if (!n1) { continue; } n2 = n - n1; if (n2 == 0) { break; } csum += (double) k *GrayTable[k]; m1 = csum / n1; m2 = (sum - csum) / n2; sb = (double) n1 *(double) n2 *(m1 - m2) * (m1 - m2); /* bbg: note: can be optimized. */ if (sb > fmax) { fmax = sb; thresholdValue = k; } } for(y=0;y biHeight;y++) { lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes); for(x=0;x biWidth;x++) { grayindex=(unsigned char)*(lpPtr); if(grayindex>thresholdValue) *(lpPtr)=255; else *(lpPtr)=0; lpPtr++; } } GlobalUnlock(hDib); return TRUE;; } /************************************************************************* * * ConvertQRToGrayscale() * * Parameters: * * HQRIMG hDIB - handle to global memory with a DIB spec * in it followed by the DIB bits * * int nMethod - method used to convert color to grayscale * * double fRedWeight - weight of Red * * double fGreenWeight - weight of Green * * double fBlueWeight - weight of Blue * * Return Value: * * HPALETTE - handle of result grayscale palette * * Description: * Change QR image color table from color to grayscale * ************************************************************************/ HPALETTE ConvertQRToGrayscale(HQRIMG hDib, int nMethod, double fRedWeight, double fGreenWeight, double fBlueWeight) { DWORD SrcBufSize,DstBufSize,LineBytes,DstLineBytes; HGLOBAL hTempImgData; LPBITMAPINFOHEADER lpImgData; LPBITMAPINFOHEADER lpTempImgData; LPSTR lpPtr,lpTempPtr; long x,y; // BITMAPFILEHEADER DstBf; // LPBITMAPFILEHEADER SrcBf; BITMAPINFOHEADER DstBi; LPBITMAPINFOHEADER SrcBi; DWORD NumColors,NewNumColors; WORD BitCounts,NewBitCounts; LOGPALETTE *pPal; // HPALETTE hPrevPalette; HGLOBAL hPal; float Y; DWORD i; HPALETTE hQRPalette=NULL; unsigned char Red,Green,Blue,Gray; if (hDib == NULL) return NULL; QRWaitCursorBegin(); NumColors=QRNumColors(hDib); NewNumColors=NumColors; BitCounts=QRBitCount(hDib); NewBitCounts=BitCounts; if(NumColors==0) { NewNumColors=256; NewBitCounts=8; } SrcBi=(LPBITMAPINFOHEADER)GlobalLock(hDib); LineBytes=(DWORD)QRWIDTHBYTES(SrcBi->biWidth*BitCounts); DstLineBytes=(DWORD)QRWIDTHBYTES(SrcBi->biWidth*NewBitCounts); DstBufSize=(DWORD)(sizeof(BITMAPINFOHEADER)+NewNumColors*sizeof(RGBQUAD)+(DWORD)DstLineBytes*SrcBi->biHeight); memcpy((char *)&DstBi,(char *)SrcBi,sizeof(BITMAPINFOHEADER)); /* memcpy((char *)&DstBf,(char *)SrcBf,sizeof(BITMAPFILEHEADER)); DstBf.bfSize=DstBufSize+sizeof(BITMAPFILEHEADER); DstBf.bfOffBits=(DWORD)(NewNumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER) +sizeof(BITMAPINFOHEADER)); */ memcpy((char *)&DstBi,(char *)SrcBi,sizeof(BITMAPINFOHEADER)); DstBi.biClrUsed=0; DstBi.biBitCount=NewBitCounts; DstBi.biSizeImage=(DWORD)DstLineBytes*SrcBi->biHeight; SrcBufSize=QRBlockSize(hDib); if((hTempImgData=GlobalAlloc(GHND,DstBufSize))==NULL) return FALSE; //Realize the Palette lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hDib); lpTempImgData=(LPBITMAPINFOHEADER)GlobalLock(hTempImgData); //copy image data memcpy(lpTempImgData,lpImgData,DstBufSize); //overwrite bitmapinfoheader with the new one memcpy(lpTempImgData,(char *)&DstBi,sizeof(BITMAPINFOHEADER)); lpPtr=(char *)lpImgData+sizeof(BITMAPINFOHEADER); lpTempPtr=(char *)lpTempImgData+sizeof(BITMAPINFOHEADER); hPal=GlobalAlloc(GHND,sizeof(LOGPALETTE) + NewNumColors* sizeof(PALETTEENTRY)); pPal =(LOGPALETTE *)GlobalLock(hPal); pPal->palNumEntries =(WORD) NewNumColors; pPal->palVersion = QRPALVERSION; if(NumColors==0) //true color for (i = 0; i < 256; i++) { pPal->palPalEntry[i].peRed=(BYTE)i; pPal->palPalEntry[i].peGreen=(BYTE)i; pPal->palPalEntry[i].peBlue=(BYTE)i; pPal->palPalEntry[i].peFlags=(BYTE)0; *(lpTempPtr++)=(unsigned char)i; *(lpTempPtr++)=(unsigned char)i; *(lpTempPtr++)=(unsigned char)i; *(lpTempPtr++)=0; } else for (i = 0; i < NewNumColors; i++) { Blue=(unsigned char )(*lpPtr++); Green=(unsigned char )(*lpPtr++); Red=(unsigned char )(*lpPtr++); Y=(float)(Red*0.299+Green*0.587+Blue*0.114); Gray=(BYTE)Y; lpPtr++; pPal->palPalEntry[i].peRed=Gray; pPal->palPalEntry[i].peGreen=Gray; pPal->palPalEntry[i].peBlue=Gray; pPal->palPalEntry[i].peFlags=0; *(lpTempPtr++)=(unsigned char)Gray; *(lpTempPtr++)=(unsigned char)Gray; *(lpTempPtr++)=(unsigned char)Gray; *(lpTempPtr++)=0; } if(hQRPalette!=NULL) DeleteObject(hQRPalette); hQRPalette=CreatePalette(pPal); GlobalUnlock(hPal); GlobalFree(hPal); //lpPtr=(char *)lpImgData+sizeof(BITMAPINFOHEADER); //lpTempPtr=(unsigned char *)lpTempImgData+sizeof(BITMAPINFOHEADER); BYTE GrayValue = 0; switch(nMethod) { case QRMAXIMUM_GRAY: if(NumColors==0) for(y=0;y biHeight;y++) { lpPtr=(char *)lpImgData+(SrcBufSize-LineBytes-y*LineBytes); lpTempPtr=(char *)lpTempImgData+(DstBufSize-DstLineBytes-y*DstLineBytes); for(x=0;x biWidth;x++) { Blue=(unsigned char )(*lpPtr++); Green=(unsigned char )(*lpPtr++); Red=(unsigned char )(*lpPtr++); GrayValue=max(Blue,Green,Red); *(lpTempPtr++)=(unsigned char)GrayValue; } } break; case QRMEAN_GRAY: if(NumColors==0) for(y=0;y biHeight;y++) { lpPtr=(char *)lpImgData+(SrcBufSize-LineBytes-y*LineBytes); lpTempPtr=(char *)lpTempImgData+(DstBufSize-DstLineBytes-y*DstLineBytes); for(x=0;x biWidth;x++) { Blue=(unsigned char )(*lpPtr++); Green=(unsigned char )(*lpPtr++); Red=(unsigned char )(*lpPtr++); GrayValue=min(255,(unsigned char)(Blue/3+Green/3+Red/3)); *(lpTempPtr++)=(unsigned char)GrayValue; } } break; case QRWEIGHT_GRAY: if(NumColors==0) for(y=0;y biHeight;y++) { lpPtr=(char *)lpImgData+(SrcBufSize-LineBytes-y*LineBytes); lpTempPtr=(char *)lpTempImgData+(DstBufSize-DstLineBytes-y*DstLineBytes); for(x=0;x biWidth;x++) { Blue=(unsigned char )(*lpPtr++); Green=(unsigned char )(*lpPtr++); Red=(unsigned char )(*lpPtr++); GrayValue=min(255,(BYTE)(Blue*fBlueWeight+Green*fGreenWeight+Red*fRedWeight)); *(lpTempPtr++)=(unsigned char)GrayValue; } } break; } //copy the grayscale data (BITMAPINFOHEADER+PALETTE+PIXEL DATA)to the original image area if(NumColors==0) { GlobalUnlock(hDib); hDib=GlobalReAlloc(hDib,DstBufSize,0); lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hDib); memcpy(lpImgData,lpTempImgData,DstBufSize); } if(hTempImgData!=NULL) { GlobalUnlock(hTempImgData); GlobalFree(hTempImgData); } GlobalUnlock(hDib); QRWaitCursorEnd(); return hQRPalette; } /************************************************************************* * * FindOrientationImage() * * Parameters: * * HQRIMG hDIB - handle to global memory with a DIB spec * in it followed by the DIB bits * * ORIENTATIONCENTER topleft - the coordinates of the top left orientation image * * ORIENTATIONCENTER topright - the coordinates of the top right orientation image * * ORIENTATIONCENTER bottomleft - the coordinates of the bottom left orientation image * * Return Value: * * if Find the three orientation image coordinates return TRue,otherwise FALSE * * Description: * * This function to get the coordinates of the three orientation image. * the width and the height of the QR image must be the multiple of 4 ************************************************************************/ BOOL PositionDetectImage(HQRIMG hDib,int * dim) { LPBITMAPINFOHEADER SrcBi; // LPBITMAPINFOHEADER lpImage; // BITMAPINFOHEADER bHeader; // BITMAPFILEHEADER bBitFile; // HFILE hf; long Width,Height; int x,y; int dims[2]; // int start,end; LPBYTE lpImageData; // ORIENTATIONCENTER Tmptopleft,Tmptopright,Tmpbottomleft,Tmpbottomright; bool bTopleft=false; bool bBottomright=false; bool bTopright=false; bool bBottomleft=false; // int Blockx,Blocky; // WORD BitCounts; //DWORD LineBytes,SrcBufSize; int index=0; HGLOBAL hStatistic,hLine; HGLOBAL hTmpIndex,hTmpStatistic; int *lpStatistic; int tmp;//datatmp; int *lpTmpStatistic; // int lpTmpSta[LINE_MAX]; int *lpLine; bool bWB=false; //HGLOBAL hIndex; if(hDib==NULL) return FALSE; SrcBi=(LPBITMAPINFOHEADER)GlobalLock(hDib); Width=SrcBi->biWidth; Height=SrcBi->biHeight; //LineBytes=(DWORD)QRWIDTHBYTES(SrcBi->biWidth*SrcBi->biBitCount); if( (Width%4!=0) && (Height%4!=0)) return FALSE; //lpImage=(LPBITMAPINFOHEADER)GlobalLock(hDib); //hIndex=CopyQRHandle(hDib); GlobalUnlock(hDib); LPBYTE lpImage=(LPBYTE)GlobalLock(hDib); lpImageData=FindQRBits(lpImage); //SrcBufSize=QRBlockSize(hDib); //to find four corner coordinates of the QR image /* for(y=0;y -1;x--) { //top left pixel if((unsigned char)*(lpImageData+x)==0 &&!bTopleft) { Tmptopleft.x=x; Tmptopleft.y=y; bTopleft=true; } } if(bTopleft ) break; } for(y=0;y -1;x--) { //top left pixel if((unsigned char)*(lpImageData++)==0 &&!bBottomright) { Tmpbottomright.x=x; Tmpbottomright.y=y; bBottomright=true; } } if(bBottomright) break; } for(x=0;x -1;x--) { for(y=Height-1;y>-1;y--) { //top left pixel lpImageData=(LPBYTE)lpImage+(SrcBufSize-LineBytes-y*LineBytes); if((unsigned char)*(lpImageData+x)==0 &&!bBottomleft) { Tmpbottomleft.x=x; Tmpbottomleft.y=y; bBottomleft=true; } } if(bBottomleft) break; } for(y=0;y =0) (*(lpTmpStatistic+tmp))++; } *(lpLine+y)=index; } //to get the statistic of the most high frequency data; int max=0; int unitminbak=Width; for(int i=0;i max) { max=*(lpTmpStatistic+i); unitminbak=i; } } // if the unitmin is unequal to the unitminbak if(unitminbak>unitmin) { // if(unitminbak%unitmin!=0) if(((*(lpTmpStatistic+unitminbak))/(*(lpTmpStatistic+unitmin)))>10) unitmin=unitminbak; } // to find the start pixel and the end pixel ORIENTATIONCENTER START,END; y=0; while((*(lpLine+y))<3) y++; START.y=y; while((*(lpLine+y))>2) y++; END.y=y; x=0; while((unsigned char)*(lpImageData+START.y*Width+x)!=0) x++; int temx1=x; x=0; while((unsigned char)*(lpImageData+(END.y-1)*Width+x)!=0) x++; int temx2=x; START.x=min(temx1,temx2); x=Width-1; while((unsigned char)*(lpImageData+START.y*Width+x)!=0) x--; temx1=x; x=Width-1; while((unsigned char)*(lpImageData+(END.y-1)*Width+x)!=0) x--; temx2=x; END.x=max(temx1,temx2)+1; //to construct the index image int Indexnum=max((END.x-START.x),(END.y-START.y))/unitmin; int Indexsum=0; int row=0; int column=0; if((hIndexData=GlobalAlloc(GHND,Indexnum*Indexnum*sizeof(char)))==NULL) return FALSE; LPBYTE lpIndexData=(LPBYTE)GlobalLock(hIndexData); for(y=START.y; y 128) *(lpIndexData+column*Indexnum+row)=255; else *(lpIndexData+column*Indexnum+row)=0; row++; } column++; } dims[0]=row; dims[1]=column; *(dim)=row; *(dim+1)=column; // to get the three orientation image coordinates and make the image to the standard position Rotate RotateAngle=NOACTION; bool bRotate=false; BYTE POSITIONPATTERN[7][7]={ { 0 , 0 , 0 , 0 , 0 , 0 , 0 }, { 0 ,255,255,255,255,255, 0 }, { 0 ,255, 0, 0 , 0 ,255, 0}, { 0 ,255, 0 , 0 , 0 ,255, 0}, { 0 ,255, 0 , 0 , 0 ,255, 0}, { 0 ,255,255,255,255,255, 0}, { 0 , 0 , 0 , 0 , 0 , 0 , 0} }; for(y=0;y<7;y++) { for(x=0;x<7;x++) if((*(lpIndexData+y*Indexnum+x))^POSITIONPATTERN[y][x]) { RotateAngle=ANTICLOCKWISE; bRotate=true; break; } if(bRotate) break; } if(!bRotate) { for(y=0;y<7;y++) { for(x=0;x<7;x++) if((*(lpIndexData+(column-1-y)*Indexnum+x))^POSITIONPATTERN[y][x]) { RotateAngle=HALFCIRCLE; bRotate=true; break; } if(bRotate) break; } } if(!bRotate) { for(y=0;y<7;y++) { for(x=0;x<7;x++) if((*(lpIndexData+(column-1-y)*Indexnum+(row-1-x)))^POSITIONPATTERN[y][x]) { RotateAngle=CLOCKWISE; bRotate=true; break; } if(bRotate) break; } } GlobalUnlock(hIndexData); if(bRotate) { if(!RotateIndexImage(hIndexData,RotateAngle,row,column)) return FALSE; } lpIndexData=(LPBYTE)GlobalLock(hIndexData); if((hTmpIndex=GlobalAlloc(GHND,row*column*sizeof(BYTE)))==NULL) return FALSE; LPBYTE lpTmpIndex=(LPBYTE)GlobalLock(hTmpIndex); for(y=0;y bmiHeader.biHeight=row; lpIndexHdr->bmiHeader.biWidth=column; //lpIndexHdr->biPlanes=0; lpIndexHdr->bmiHeader.biSizeImage=0;//row*column*sizeof(char); LPBYTE lpdata=(LPBYTE)GlobalLock(hIndextmp); //memcpy(lpdata+sizeof(BITMAPINFOHEADER),lpImage+sizeof(BITMAPINFOHEADER),256*sizeof(RGBQUAD)); memcpy(lpdata+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD),lpIndexData,row*column*sizeof(BYTE));//; //LPBYTE lpbit=(LPBYTE)GlobalLock(hIndex); bBitFile.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD); bBitFile.bfType=0x4d42; bBitFile.bfReserved1=0; bBitFile.bfReserved2=0; bBitFile.bfSize=sizeof(BITMAPFILEHEADER)+destbuf; HANDLE hFile; DWORD dwWritten; if ((hFile = CreateFile("c:\\gray.bmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL)) != INVALID_HANDLE_VALUE) { WriteFile(hFile,(LPBYTE)&bBitFile,sizeof(BITMAPFILEHEADER),&dwWritten,NULL); //WriteFile(hFile,(LPBYTE)lpIndexHdr,sizeof(BITMAPINFOHEADER),&dwWritten,NULL); //WriteFile(hFile,(LPBYTE)(lpImage+sizeof(BITMAPINFOHEADER)),256*sizeof(RGBQUAD),&dwWritten,NULL); //WriteFile(hFile,(LPBYTE)lpIndexData,row*column,&dwWritten,NULL); WriteFile(hFile,(LPBYTE)lpdata,destbuf,&dwWritten,NULL); } CloseHandle(hFile); */ if(hTmpIndex!=NULL) { GlobalUnlock(hTmpIndex); GlobalFree(hTmpIndex); } if(hStatistic!=NULL) { GlobalUnlock(hStatistic); GlobalFree(hStatistic); } if(hLine!=NULL) { GlobalUnlock(hLine); GlobalFree(hLine); } if(hTmpStatistic!=NULL) { GlobalUnlock(hTmpStatistic); GlobalFree(hTmpStatistic); } // lpTmpSat=(int *)GlobalLock(hTmpSat); // if(hTmpStatistic!=NULL) // { // GlobalUnlock(hTmpStatistic); // GlobalFree(hTmpStatistic); // DWORD fff=GetLastError(); // } ////////////////////////////////////////////////////////////////////////////////// /* unsigned char VersionNum=VersionNumberInfo( hIndexData,row, column); unsigned char Format=FormatInfo(hIndexData,row,column); if(!MaskImg(Format,VersionNum)) return FALSE; unsigned char CorrectPos=ReviseimagePos(VersionNum); if(!UnmaskIndexImage(hIndexData,hMaskImg,VersionNum)) return FALSE; HGLOBAL OriginalCode=GetOriginalCode(hIndexData,VersionNum,Format); */ // HGLOBAL DecoderCode=QRDecoder(OriginalCode,VersionNum,Format); /////////////////////////////////////////////////////////////////////////////////// return TRUE; } /******************************************************************* * *RotateIndexImage() * *Parameters: * *HGLOBAL hIndexData - the handle of the index image data; * *Rotate RotateAngle - the angle that the index image need to roate * *int row - the width of the index image; * *int column - the height of the index image; * *RETURN value: * * TRUE or FALSE * *REMARKS: * *This function is to rotate the index image to standard position, There is not position detection *image at the bottom right corner of the index image.If the rotate success return TRUE, *otherwise return FALSE; * ******************************************************************/ BOOL RotateIndexImage(HGLOBAL hIndexData,Rotate RotateAngle,int row,int column) { HGLOBAL hTmpIndex; LPBYTE lpIndexData,lpTmpData; int x,y; if(hIndexData==NULL) return FALSE; lpIndexData=(LPBYTE)GlobalLock(hIndexData); if((hTmpIndex=GlobalAlloc(GHND,row*column*sizeof(BYTE)))==NULL) return FALSE; lpTmpData=(LPBYTE)GlobalLock(hTmpIndex); switch(RotateAngle) { case CLOCKWISE: for(y=0;y >10); else return FALSE; } /************************************************************************** * *VersionNumberInfo() * *Parameters: * *HGLOBAL hIndexData - the handle of the index image data; * *int row - the width of the index image; * *int column - the height of the index image; * *RETURN value: * * unsigned char -low six bits is the version number * *REMARKS: * *This function is to get the Version number as the return value show; * *************************************************************************/ unsigned char VersionNumberInfo(HGLOBAL hIndexData,int row,int column) { LPBYTE lpIndexData; unsigned int VersionNum=0U; unsigned int VersionBak=0U; unsigned int VersionFlag=1U; int m,n; if(hIndexData==NULL) return FALSE; lpIndexData=(LPBYTE)GlobalLock(hIndexData); if(row<45) return (row-21)/4+1; //to read the top right version number for(m=0;m<6;m++) for(n=0;n<3;n++) { if(*(lpIndexData+(5-m)*row+(column-9-n))==0) VersionNum=VersionNum|(VersionFlag<<(17-m*3-n)); } //to read the bottom left version number for(m=0;m<6;m++) for(n=0;n<3;n++) { if(*(lpIndexData+(row-9-n)*row+(5-m))==0) VersionBak=VersionBak|(VersionFlag<<(17-m*3-n)); } if(VersionNum==VersionBak) return (unsigned char)(VersionNum>>12); else return FALSE; } /************************************************************************** * *MaskImg() * *Parameters: * *unsigned char FormatNum - the format information of the QR index image,including the mask * reference and the correction level; * *unsigned char VersionNum - the version number information of the QR index image * * *RETURN value: * * if the function runs properply,it returns TRUE. otherwise returns FALSE; * *REMARKS: * * This function is to make the mask image according to format information and version * number infromation; * *************************************************************************/ BOOL MaskImg(unsigned char FormatNum,unsigned char VersionNum) { unsigned char dimension=0; unsigned char maskref=0; unsigned char * lpMaskData; dimension=21+(VersionNum-1)*4; maskref=FormatNum&7; int i,j; if((hMaskImg=GlobalAlloc(GHND,dimension*dimension*sizeof(BYTE)))==NULL) return FALSE; lpMaskData=(unsigned char *)GlobalLock(hMaskImg); switch(maskref) { case 0: for(i=0;i 6) { for(y=0;y<6;y++) for(x=0;x<3;x++) *(lpMarkImgData+y*dimension+(dimension-11+x))=128; //to mark the bottom left version number area for(y=0;y<3;y++) for(x=0;x<6;x++) *(lpMarkImgData+(dimension-11+y)*dimension+x)=128; } //to mark the orientation image for(x=0;x >3; switch(VersionNum) { case 1: switch(CorrectLevel) { case LEVEL_L: //Level L CorrectCode[0]=26; CorrectCode[1]=19; CorrectCode[2]=2; CorrectCode[3]=1; CorrectCode[4]=0; return TRUE; case LEVEL_M: //Level M CorrectCode[0]=26;//sum of all code CorrectCode[1]=16;//sum of data CorrectCode[2]=4;// capacity of correction CorrectCode[3]=1; CorrectCode[4]=0; return TRUE; case LEVEL_Q: //Level Q CorrectCode[0]=26; CorrectCode[1]=13; CorrectCode[2]=6; CorrectCode[3]=1; CorrectCode[4]=0; return TRUE; case LEVEL_H: //Level H CorrectCode[0]=26; CorrectCode[1]=9; CorrectCode[2]=8; CorrectCode[3]=1; CorrectCode[4]=0; return TRUE; } case 2: switch(CorrectLevel) { case LEVEL_L: //Level L CorrectCode[0]=44; CorrectCode[1]=34; CorrectCode[2]=4; CorrectCode[3]=1; CorrectCode[4]=0; return TRUE; case LEVEL_M: //Level M CorrectCode[0]=44;//sum of all code CorrectCode[1]=28;//sum of data CorrectCode[2]=8;// capacity of correction CorrectCode[3]=1; CorrectCode[4]=0; return TRUE; case LEVEL_Q: //Level Q CorrectCode[0]=44; CorrectCode[1]=22; CorrectCode[2]=11; CorrectCode[3]=1; CorrectCode[4]=0; return TRUE; case LEVEL_H: //Level H CorrectCode[0]=44; CorrectCode[1]=16; CorrectCode[2]=14; CorrectCode[3]=1; CorrectCode[4]=0; return TRUE; } case 3: switch(CorrectLevel) { case LEVEL_L: //Level L CorrectCode[0]=70; CorrectCode[1]=55; CorrectCode[2]=7; CorrectCode[3]=1; CorrectCode[4]=0; return TRUE; case LEVEL_M: //Level M CorrectCode[0]=70;//sum of all code CorrectCode[1]=44;//sum of data CorrectCode[2]=13;// capacity of correction CorrectCode[3]=1; CorrectCode[4]=0; return TRUE; case LEVEL_Q: //Level Q CorrectCode[0]=35; CorrectCode[1]=17; CorrectCode[2]=9; CorrectCode[3]=2; CorrectCode[4]=0; return TRUE; case LEVEL_H: //Level H CorrectCode[0]=35; CorrectCode[1]=13; CorrectCode[2]=11; CorrectCode[3]=2; CorrectCode[4]=0; return TRUE; } case 4: switch(CorrectLevel) { case LEVEL_L: //Level L CorrectCode[0]=100; CorrectCode[1]=80; CorrectCode[2]=10; CorrectCode[3]=1; CorrectCode[4]=0; return TRUE; case LEVEL_M: //Level M CorrectCode[0]=50;//sum of all code CorrectCode[1]=32;//sum of data CorrectCode[2]=9;// capacity of correction CorrectCode[3]=2; CorrectCode[4]=0; return TRUE; case LEVEL_Q: //Level Q CorrectCode[0]=50; CorrectCode[1]=24; CorrectCode[2]=13; CorrectCode[3]=2; CorrectCode[4]=0; return TRUE; case LEVEL_H: //Level H CorrectCode[0]=25; CorrectCode[1]=9; CorrectCode[2]=8; CorrectCode[3]=4; CorrectCode[4]=0; return TRUE; } case 5: switch(CorrectLevel) { case LEVEL_L: //Level L CorrectCode[0]=134; CorrectCode[1]=108; CorrectCode[2]=13; CorrectCode[3]=1; CorrectCode[4]=0; return TRUE; case LEVEL_M: //Level M CorrectCode[0]=67;//sum of all code CorrectCode[1]=43;//sum of data CorrectCode[2]=12;// capacity of correction CorrectCode[3]=2; CorrectCode[4]=0; return TRUE; case LEVEL_Q: //Level Q CorrectCode[0]=33; CorrectCode[1]=15; CorrectCode[2]=9; CorrectCode[3]=2; CorrectCode[4]=2; return TRUE; case LEVEL_H: //Level H CorrectCode[0]=33; CorrectCode[1]=11; CorrectCode[2]=11; CorrectCode[3]=2; CorrectCode[4]=2; return TRUE; } case 6: switch(CorrectLevel) { case LEVEL_L: //Level L CorrectCode[0]=86; CorrectCode[1]=68; CorrectCode[2]=9; CorrectCode[3]=2; CorrectCode[4]=0; return TRUE; case LEVEL_M: //Level M CorrectCode[0]=43;//sum of all code CorrectCode[1]=27;//sum of data CorrectCode[2]=8;// capacity of correction CorrectCode[3]=4; CorrectCode[4]=0; return TRUE; case LEVEL_Q: //Level Q CorrectCode[0]=43; CorrectCode[1]=19; CorrectCode[2]=12; CorrectCode[3]=4; CorrectCode[4]=0; return TRUE; case LEVEL_H: //Level H CorrectCode[0]=43; CorrectCode[1]=15; CorrectCode[2]=14; CorrectCode[3]=4; CorrectCode[4]=0; return TRUE; } case 7: switch(CorrectLevel) { case LEVEL_L: //Level L CorrectCode[0]=98; CorrectCode[1]=78; CorrectCode[2]=10; CorrectCode[3]=2; CorrectCode[4]=0; return TRUE; case LEVEL_M: //Level M CorrectCode[0]=49;//sum of all code CorrectCode[1]=31;//sum of data CorrectCode[2]=9;// capacity of correction CorrectCode[3]=4; CorrectCode[4]=0; return TRUE; case LEVEL_Q: //Level Q CorrectCode[0]=32; CorrectCode[1]=14; CorrectCode[2]=9; CorrectCode[3]=2; CorrectCode[4]=4; return TRUE; case LEVEL_H: //Level H CorrectCode[0]=39; CorrectCode[1]=13; CorrectCode[2]=13; CorrectCode[3]=4; CorrectCode[4]=1; return TRUE; } case 8: switch(CorrectLevel) { case LEVEL_L: //Level L CorrectCode[0]=121; CorrectCode[1]=97; CorrectCode[2]=12; CorrectCode[3]=2; CorrectCode[4]=0; return TRUE; case LEVEL_M: //Level M CorrectCode[0]=60;//sum of all code CorrectCode[1]=38;//sum of data CorrectCode[2]=11;// capacity of correction CorrectCode[3]=2; CorrectCode[4]=2; return TRUE; case LEVEL_Q: //Level Q CorrectCode[0]=40; CorrectCode[1]=18; CorrectCode[2]=11; CorrectCode[3]=4; CorrectCode[4]=2; return TRUE; case LEVEL_H: //Level H CorrectCode[0]=40; CorrectCode[1]=14; CorrectCode[2]=13; CorrectCode[3]=4; CorrectCode[4]=2; return TRUE; } case 9: switch(CorrectLevel) { case LEVEL_L: //Level L CorrectCode[0]=146; CorrectCode[1]=116; CorrectCode[2]=15; CorrectCode[3]=2; CorrectCode[4]=0; return TRUE; case LEVEL_M: //Level M CorrectCode[0]=58;//sum of all code CorrectCode[1]=36;//sum of data CorrectCode[2]=11;// capacity of correction CorrectCode[3]=3; CorrectCode[4]=2; return TRUE; case LEVEL_Q: //Level Q CorrectCode[0]=36; CorrectCode[1]=16; CorrectCode[2]=10; CorrectCode[3]=4; CorrectCode[4]=4; return TRUE; case LEVEL_H: //Level H CorrectCode[0]=36; CorrectCode[1]=12; CorrectCode[2]=12; CorrectCode[3]=4; CorrectCode[4]=4; return TRUE; } case 10: switch(CorrectLevel) { case LEVEL_L: //Level L CorrectCode[0]=86; CorrectCode[1]=68; CorrectCode[2]=9; CorrectCode[3]=2; CorrectCode[4]=2; return TRUE; case LEVEL_M: //Level M CorrectCode[0]=69;//sum of all code CorrectCode[1]=43;//sum of data CorrectCode[2]=13;// capacity of correction CorrectCode[3]=4; CorrectCode[4]=1; return TRUE; case LEVEL_Q: //Level Q CorrectCode[0]=43; CorrectCode[1]=19; CorrectCode[2]=12; CorrectCode[3]=6; CorrectCode[4]=2; return TRUE; case LEVEL_H: //Level H CorrectCode[0]=43; CorrectCode[1]=15; CorrectCode[2]=14; CorrectCode[3]=6; CorrectCode[4]=2; return TRUE; } default: return FALSE; } } /************************************************************************** * *GetOriginalCode() * *Parameters: * *unsigned char VersionNum - the version number information of the QR index image * *unsigned char Format - the Format information of the QR index image * *HGLOBAL hIndexData - the handle of unmasked index image data * *RETURN value: * * if this function gets original code properply,it returns the handle of original code * otherwise it will return NULL; * *REMARKS: * * This function is to get the original code including data code and correction code * *************************************************************************/ HGLOBAL GetOriginalCode(HGLOBAL hIndexData,unsigned char VersionNum,unsigned char Format) { HGLOBAL hTmpCode=NULL; unsigned char READFLAG=1U; unsigned char count=0U; unsigned char row,column,dimension; unsigned char tmpcode=0; unsigned short codesum; unsigned short alreadyread=0; unsigned char * lpIndexData; unsigned char * lpOriginalCode; unsigned char * lpTmpCode; unsigned char CorrectCode[5]; BOOL ORDERFLAG=TRUE; BOOL bFinished=TRUE; BOOL bUpDown=TRUE; int i,j; // BOOL bOneByte=TRUE; if(hIndexData==NULL) return NULL; dimension=21+(VersionNum-1)*4; lpIndexData=(unsigned char *)GlobalLock(hIndexData); //to get the amount of correct module and correction code //for(i=0;i<5;i++) //CorrectCode[i]=0; memset(CorrectCode,0,sizeof(CorrectCode)); if(!GetCorrectionCode(VersionNum,Format,CorrectCode)) return NULL; //to allocate memory for reading original code codesum=(unsigned short)(CorrectCode[0]*CorrectCode[3]+(CorrectCode[0]+1)*CorrectCode[4]); if((hOriginalCode=GlobalAlloc(GHND,codesum*sizeof(unsigned char)))==NULL) return NULL; lpOriginalCode=(unsigned char *)GlobalLock(hOriginalCode); //start to read original code row=column=0; while(bFinished) { if(bUpDown) { row=row+1; if(column==0) column=column+1; else column=column+2; if(column==dimension-6) column=column+1; while(bUpDown) { if(ORDERFLAG) { if(*(lpIndexData+(dimension-row)*dimension+(dimension-column))==255)//0 { tmpcode=tmpcode|READFLAG<<(7-count); count++; } else if(*(lpIndexData+(dimension-row)*dimension+(dimension-column))==0)//255 { count++; } column++; ORDERFLAG=FALSE; } else { if(*(lpIndexData+(dimension-row)*dimension+(dimension-column))==255)//0 { tmpcode=tmpcode|READFLAG<<(7-count); count++; } else if(*(lpIndexData+(dimension-row)*dimension+(dimension-column))==0)//255 { count++; } row++; column--; ORDERFLAG=TRUE; } if(count==8) { count=0; if(alreadyread =dimension && column>=dimension) bFinished=FALSE; if(row>dimension||column>dimension-1) bUpDown=FALSE; } }//bUp else { row=row-1; column=column+2; if(column==dimension-6) column=column+1; while(!bUpDown) { if(ORDERFLAG) { if(*(lpIndexData+(dimension-row)*dimension+(dimension-column))==255)//0 { tmpcode=tmpcode|READFLAG<<(7-count); count++; } else if(*(lpIndexData+(dimension-row)*dimension+(dimension-column))==0)//255 { count++; } column++; ORDERFLAG=FALSE; } else { if(*(lpIndexData+(dimension-row)*dimension+(dimension-column))==255)//0 { tmpcode=tmpcode|READFLAG<<(7-count); count++; } else if(*(lpIndexData+(dimension-row)*dimension+(dimension-column))==0)//255 { count++; } row--; column--; ORDERFLAG=TRUE; } if(count==8) { count=0; if(alreadyread =dimension && column>=dimension) bFinished=FALSE; if(row>dimension || row<1||column>dimension) bUpDown=TRUE; } }//bDown }//bFinished if((hTmpCode=GlobalAlloc(GHND,codesum*sizeof(unsigned char)))==NULL) return NULL; lpTmpCode=(unsigned char *)GlobalLock(hTmpCode); int SumCorrect=CorrectCode[3]+CorrectCode[4]; if(SumCorrect>1) { // to construct the sequence data code for(i=0;i >4; else { mode=(((*(lpOriginalCode+shang))< >4; mode=mode|(*(lpOriginalCode+shang+1)>>(12-yushu)); } //mode=((*lpOriginalCode+shang)&0xF0)>>4; //to get the code amount of segment 1 CountBit=GetModeCountBit(VersionNum,mode); switch(mode) { case 0x01: if(yushu<5) { TmpData=*(lpOriginalCode+shang); CharacterAmount=((TmpData<<(yushu+4))&0x00FF)<<(CountBit-8); if(CountBit+yushu-4<=8) { TmpData=*(lpOriginalCode+shang+1); CharacterAmount=CharacterAmount|(TmpData>>(12-CountBit-yushu)); } else { TmpData=*(lpOriginalCode+shang+1); CharacterAmount=CharacterAmount|(TmpData<<(yushu+CountBit-12)); TmpData=*(lpOriginalCode+shang+2); CharacterAmount=CharacterAmount|(TmpData>>(20-CountBit-yushu)); } } else { TmpData=*(lpOriginalCode+shang+1); CharacterAmount=(TmpData<<((yushu-4))&0x00FF)<<(CountBit-8); if(CountBit+yushu-12<=8) { TmpData=*(lpOriginalCode+shang+2); CharacterAmount=CharacterAmount|(TmpData>>(20-CountBit-yushu)); } else { TmpData=*(lpOriginalCode+shang+2); CharacterAmount=CharacterAmount|(TmpData<<(yushu+CountBit-20)); TmpData=*(lpOriginalCode+shang+3); CharacterAmount=CharacterAmount|(TmpData>>(28-CountBit-yushu)); } } break; case 0x02: if(yushu<5) { TmpData=*(lpOriginalCode+shang); CharacterAmount=((TmpData<<(yushu+4))&0x00FF)<<(CountBit-8); if(CountBit+yushu-4<=8) { TmpData=*(lpOriginalCode+shang+1); CharacterAmount=CharacterAmount|(TmpData>>(12-CountBit-yushu)); } else { TmpData=*(lpOriginalCode+shang+1); CharacterAmount=CharacterAmount|(TmpData<<(yushu+CountBit-12)); TmpData=*(lpOriginalCode+shang+2); CharacterAmount=CharacterAmount|(TmpData>>(20-CountBit-yushu)); } } else { TmpData=*(lpOriginalCode+shang+1); CharacterAmount=(TmpData<<((yushu-4))&0x00FF)<<(CountBit-8); if(CountBit+yushu-12<=8) { TmpData=*(lpOriginalCode+shang+2); CharacterAmount=CharacterAmount|(TmpData>>(20-CountBit-yushu)); } else { TmpData=*(lpOriginalCode+shang+2); CharacterAmount=CharacterAmount|(TmpData<<(yushu+CountBit-20)); TmpData=*(lpOriginalCode+shang+3); CharacterAmount=CharacterAmount|(TmpData>>(28-CountBit-yushu)); } } break; case 0x04: if(yushu<5) { TmpData=*(lpOriginalCode+shang); CharacterAmount=((TmpData<<(yushu+4))&0x00FF)<<(CountBit-8); if(CountBit+yushu-4<=8) { TmpData=*(lpOriginalCode+shang+1); CharacterAmount=CharacterAmount|(TmpData>>(12-CountBit-yushu)); } else { TmpData=*(lpOriginalCode+shang+1); CharacterAmount=CharacterAmount|(TmpData<<(yushu+CountBit-12)); TmpData=*(lpOriginalCode+shang+2); CharacterAmount=CharacterAmount|(TmpData>>(20-CountBit-yushu)); } } else { TmpData=*(lpOriginalCode+shang+1); CharacterAmount=(TmpData<<((yushu-4))&0x00FF)<<(CountBit-8); if(CountBit+yushu-12<=8) { TmpData=*(lpOriginalCode+shang+2); CharacterAmount=CharacterAmount|(TmpData>>(20-CountBit-yushu)); } else { TmpData=*(lpOriginalCode+shang+2); CharacterAmount=CharacterAmount|(TmpData<<(yushu+CountBit-20)); TmpData=*(lpOriginalCode+shang+3); CharacterAmount=CharacterAmount|(TmpData>>(28-CountBit-yushu)); } } break; case 0x0D: if(yushu<5) { TmpData=*(lpOriginalCode+shang+1); CharacterAmount=((TmpData< >(16-CountBit-yushu)); } else { // TmpData=*(lpOriginalCode+shang+2); // CharacterAmount=CharacterAmount|(TmpData<<(yushu+CountBit-16)); // TmpData=*(lpOriginalCode+shang+3); // CharacterAmount=CharacterAmount|(TmpData>>(24-CountBit-yushu)); } } else { TmpData=*(lpOriginalCode+shang+1); CharacterAmount=((TmpData< >(16-CountBit-yushu)); } else { TmpData=*(lpOriginalCode+shang+2); CharacterAmount=CharacterAmount|(TmpData<<(yushu+CountBit-16)); TmpData=*(lpOriginalCode+shang+3); CharacterAmount=CharacterAmount|(TmpData>>(24-CountBit-yushu)); } } break; default: break; } //to calculate the bit amount of segment 1; switch(mode) { case 0x01: if(CharacterAmount%3==0) BitSum=4+CountBit+10*(CharacterAmount/3); else if(CharacterAmount%3==1) BitSum=4+CountBit+10*(CharacterAmount/3)+4; else if(CharacterAmount%3==2) BitSum=4+CountBit+10*(CharacterAmount/3)+7; break; case 0x02: BitSum=4+CountBit+11*(CharacterAmount/2)+6*(CharacterAmount%2); break; case 0x04: BitSum=4+CountBit+8*CharacterAmount; break; case 0x0D: BitSum=4+4+CountBit+13*CharacterAmount; break; default: break; } BitAmount=BitAmount+BitSum; if(BitAmount>=DataSum*8||mode==0) bRead=FALSE; else { ModeIndex[SegmentNum]=mode; Character[SegmentNum]=CharacterAmount; Segment[SegmentNum++]=BitSum; } } CharacterAmount=0; for(i=0;i Character[i]) { bRead=FALSE; break; } if(yushu==0) shang++; if(yushu<=6) { TmpData=*(lpOriginalCode+shang); ReadData=((TmpData< >(6-yushu)); if(yushu==6) { yushu=0; // shang++; } else yushu=(yushu+10)%8; } else { TmpData=*(lpOriginalCode+shang); ReadData=((TmpData< >yushu); yushu=(yushu+10)%8; } *(lpDecodeData+ReadNum++)=((0xA3B0+ReadData/100))>>8; *(lpDecodeData+ReadNum++)=(0xA3B0+ReadData/100); *(lpDecodeData+ReadNum++)=((0xA3B0+(ReadData%100)/10))>>8; *(lpDecodeData+ReadNum++)=(0xA3B0+(ReadData%100)/10); *(lpDecodeData+ReadNum++)=((0xA3B0+(ReadData%100)%10))>>8; *(lpDecodeData+ReadNum++)=(0xA3B0+(ReadData%100)%10); } if(Character[i]%3==1) { if(yushu==0) shang++; TmpData=*(lpOriginalCode+shang); if(yushu<5) { ReadData=((TmpData< >4; if(yushu==4) { yushu=(yushu+4)%8; // shang++; } else yushu=(yushu+4)%8; } else { ReadData=((TmpData< >4; shang++; TmpData=*(lpOriginalCode+shang); ReadData=ReadData|TmpData>>(12-yushu); yushu=yushu-4; } *(lpDecodeData+ReadNum++)=(0xA3B0+ReadData)>>8; *(lpDecodeData+ReadNum++)=0xA3B0+ReadData; } else if(Character[i]%3==2) { if(yushu==0) shang++; TmpData=*(lpOriginalCode+shang); if(yushu<2) { ReadData=((TmpData< >1; if(yushu==1) { yushu=(yushu+7)%8; // shang++; } else yushu=1; } else { ReadData=((TmpData< >1; shang++; TmpData=*(lpOriginalCode+shang); ReadData=ReadData|TmpData>>(9-yushu); yushu=yushu-1; } *(lpDecodeData+ReadNum++)=(0xA3B0+ReadData/10)>>8; *(lpDecodeData+ReadNum++)=0xA3B0+ReadData/10; *(lpDecodeData+ReadNum++)=(0xA3B0+ReadData%10)>>8; *(lpDecodeData+ReadNum++)=0xA3B0+ReadData%10; } break; case 0x02: bRead=TRUE; CharacterAmount=0; CountBit=GetModeCountBit(VersionNum,ModeIndex[i]); yushu=(BitAmount+4+CountBit)%8; shang=(BitAmount+4+CountBit)/8; BitAmount=BitAmount+Segment[i]; while(bRead) { TmpData=0; CharacterAmount=CharacterAmount+2; if(CharacterAmount>Character[i]) { bRead=FALSE; break; } if(yushu==0) shang++; if(yushu<6) { TmpData=*(lpOriginalCode+shang); ReadData=((TmpData< >(5-yushu)); if(yushu==5) { yushu=0; // shang++; } else yushu=(yushu+11)%8; } else { TmpData=*(lpOriginalCode+shang); ReadData=((TmpData< >(13-yushu)); yushu=(yushu+11)%8; } first=ReadData/45; second=ReadData%45; ReadData=TranslateChaNum(first); *(lpDecodeData+ReadNum++)=ReadData>>8; *(lpDecodeData+ReadNum++)=ReadData; ReadData=TranslateChaNum(second); *(lpDecodeData+ReadNum++)=ReadData>>8; *(lpDecodeData+ReadNum++)=ReadData; } if(Character[i]%2==1) { if(yushu==0) shang++; TmpData=*(lpOriginalCode+shang); if(yushu<3) { ReadData=((TmpData< >2; if(yushu==2) { yushu=0; // shang++; } else yushu=(yushu+6)%8; } else { ReadData=((TmpData< >2; shang++; TmpData=*(lpOriginalCode+shang); ReadData=ReadData|TmpData>>(10-yushu); yushu=yushu-2; } second=ReadData%45; ReadData=TranslateChaNum(second); *(lpDecodeData+ReadNum++)=ReadData>>8; *(lpDecodeData+ReadNum++)=ReadData; } break; case 0x04: bRead=TRUE; CharacterAmount=0; CountBit=GetModeCountBit(VersionNum,ModeIndex[i]); yushu=(BitAmount+4+CountBit)%8; shang=(BitAmount+4+CountBit)/8; BitAmount=BitAmount+Segment[i]; while(bRead) { TmpData=0; CharacterAmount++; if(CharacterAmount>Character[i]) { bRead=FALSE; break; } if(yushu==0) { shang++; ReadData=*(lpOriginalCode+shang); } else { TmpData=*(lpOriginalCode+shang); ReadData=((TmpData< >(8-yushu)); } if(ReadNum<2) *(lpDecodeData+ReadNum++)=ReadData; else { *(lpDecodeData+ReadNum++)=(ReadData+0xA380)>>8; *(lpDecodeData+ReadNum++)=ReadData+0xA380; } } break; case 0x0D: bRead=TRUE; CharacterAmount=0; CountBit=GetModeCountBit(VersionNum,ModeIndex[i]); yushu=(BitAmount+8+CountBit)%8; shang=(BitAmount+8+CountBit)/8; if(yushu==0) shang--; BitAmount=BitAmount+Segment[i]; while(bRead) { TmpData=0; CharacterAmount++; if(CharacterAmount>Character[i]) { bRead=FALSE; break; } if(yushu==0) shang++; if(yushu<=3) { TmpData=*(lpOriginalCode+shang); ReadData=((TmpData< >(3-yushu)); if(yushu==3) { yushu=0; // shang++; } else yushu=(yushu+13)%8; } else { TmpData=*(lpOriginalCode+shang); ReadData=((TmpData< >(11-yushu)); yushu=(yushu+13)%8; } first=ReadData/0x60; if(first<0x0A) first=first+0xA1; else first=first+0xA6; *(lpDecodeData+ReadNum++)=first; *(lpDecodeData+ReadNum++)=(ReadData%0x60)+0xA1; } break; default: break; } } *(lpDecodeData+ReadNum)='\0'; if(hOriginalCode!=NULL) { GlobalUnlock(hOriginalCode); GlobalFree(hOriginalCode); } GlobalUnlock(hDecodeData); return CharacterSum-1; } /************************************************************************** * *GetModeCountBit() * *Parameters: * *unsigned char VersionNum - the version number information of the QR index image * *unsigned char mode - the code mode. 0x01 - digital mode;0x02 - character-number mode 0x04 - 8 bit byte mode;0x0D - Chinese mode * *RETURN value: * * if this function runs properply,it returns bit digit of character counter of every mode * *************************************************************************/ unsigned char GetModeCountBit(unsigned char VersionNum,unsigned char mode) { switch(mode) { case 0x01: if(VersionNum>0&&VersionNum<10) return 10; if(VersionNum>9&&VersionNum<27) return 12; if(VersionNum>26&&VersionNum<41) return 14; case 0x02: if(VersionNum>0&&VersionNum<10) return 9; if(VersionNum>9&&VersionNum<27) return 11; if(VersionNum>26&&VersionNum<41) return 13; case 0x04: if(VersionNum>0&&VersionNum<10) return 8; if(VersionNum>9&&VersionNum<27) return 16; if(VersionNum>26&&VersionNum<41) return 16; case 0x0D: if(VersionNum>0&&VersionNum<10) return 8; if(VersionNum>9&&VersionNum<27) return 10; if(VersionNum>26&&VersionNum<41) return 12; default: return 0; } } unsigned short TranslateChaNum(unsigned char chanum) { unsigned short GBCha; if(chanum<10) GBCha=0xA3B0+chanum; else if(chanum<36) GBCha=0xA3B7+chanum; else if(chanum==36) GBCha=0xA3A0; else if(chanum==37) GBCha=0xA3A4; else if(chanum==38) GBCha=0xA3A5; else if(chanum==39) GBCha=0xA3AA; else if(chanum==40) GBCha=0xA3AB; else if(chanum>40 && chanum<44) GBCha=0xA384+chanum; else if(chanum==44) GBCha=0xA3BA; return GBCha; } HGLOBAL GetDecodeData(unsigned short * codenum,unsigned char VersionNum,unsigned char Format) { HGLOBAL OriginalCode=GetOriginalCode(hIndexData,VersionNum,Format); *(codenum)=QRDecoder(OriginalCode,VersionNum,Format); return hDecodeData; } HGLOBAL GetIndexImage() { return hIndexData; } HGLOBAL GetMaskImg() { return hMaskImg; }