int main(int, char**)
{
	// Open the default camera
	VideoCapture cap(0);
	if (!cap.isOpened())
		return -1;

	const char *windowName = "BarcodeReader";
	namedWindow(windowName, 1);

	// Initialize Dynamsoft Barcode Reader
	CBarcodeReader reader;
	reader.InitLicense("38B9B94D8B0E2B41660D13B593BE6EF9");
	__int64 llFormat = (OneD | QR_CODE | PDF417 | DATAMATRIX);
	int iMaxCount = 0x7FFFFFFF;
	ReaderOptions ro = { 0 };
	ro.llBarcodeFormat = llFormat;
	ro.iMaxBarcodesNumPerPage = iMaxCount;
	reader.SetReaderOptions(ro);

	Mat frame;
	for (;;)
	{
		cap >> frame; // Get a new frame from camera
		imshow(windowName, frame); // Display the new frame

		read(frame, reader);

		if (waitKey(30) >= 0)
			break;
	}

	return 0;
}
int main(int argc, const char* argv[])
{
	// Parse command
	__int64 llFormat = (OneD|QR_CODE);
	const char * pszImageFile = NULL;
	int iMaxCount = 0x7FFFFFFF;
	int iIndex = 0;
	ReaderOptions ro = {0};
	int iRet = -1;
	char * pszTemp = NULL;
	char * pszTemp1 = NULL;
	unsigned __int64 ullTimeBegin = 0;
	unsigned __int64 ullTimeEnd = 0;
	
	if (argc <= 1)
	{
		PrintHelp();
		return 1;
	}

	for (iIndex = 1; iIndex < argc; iIndex ++)
	{
		if (strcmpi(argv[iIndex], "-help") == 0)
		{
			PrintHelp();
			return 0;
		}

		if (strcmpi(argv[iIndex], "-f") == 0)
		{// parse format
			iIndex ++;
			if (iIndex >= argc)
			{
				printf("The syntax of the command is incorrect.\r\n");
				return 1;
			}
			llFormat = GetFormat(argv[iIndex]);
			if (llFormat == 0)
			{
				printf("The syntax of the command is incorrect.\r\n");
				return 1;
			}
			continue;
		}

		if (strcmpi(argv[iIndex], "-n") == 0)
		{// parse format
			iIndex ++;
			if (iIndex >= argc)
			{
				printf("The syntax of the command is incorrect.\r\n");
				return 1;
			}
			iMaxCount = atoi(argv[iIndex]);
			continue;
		}

		if (NULL == pszImageFile)
			pszImageFile = argv[iIndex];
	}

	if (NULL == pszImageFile)
	{
		printf("The syntax of the command is incorrect.\r\n");
		return 1;
	}

	// Set license
	CBarcodeReader reader;
	reader.InitLicense("<Put your license key here>");

	// Read barcode
	ullTimeBegin = GetTickCount();
	ro.llBarcodeFormat = llFormat;
	ro.iMaxBarcodesNumPerPage = iMaxCount;
	reader.SetReaderOptions(ro);
	iRet = reader.DecodeFile(pszImageFile);
	ullTimeEnd = GetTickCount();
		
	// Output barcode result
	pszTemp = (char*)malloc(4096);
	if (iRet != DBR_OK)
	{
		sprintf(pszTemp, "Failed to read barcode: %s\r\n", DBR_GetErrorString(iRet));
		printf(pszTemp);
		free(pszTemp);
		return 1;
	}

	pBarcodeResultArray paryResult = NULL;
	reader.GetBarcodes(&paryResult);
	
	if (paryResult->iBarcodeCount == 0)
	{
		sprintf(pszTemp, "No barcode found. Total time spent: %.3f seconds.\r\n", ((float)(ullTimeEnd - ullTimeBegin)/1000));
		printf(pszTemp);
		free(pszTemp);
		reader.FreeBarcodeResults(&paryResult);
		return 0;
	}
	
	sprintf(pszTemp, "Total barcode(s) found: %d. Total time spent: %.3f seconds\r\n\r\n", paryResult->iBarcodeCount, ((float)(ullTimeEnd - ullTimeBegin)/1000));
	printf(pszTemp);
	for (iIndex = 0; iIndex < paryResult->iBarcodeCount; iIndex++)
	{
		sprintf(pszTemp, "Barcode %d:\r\n", iIndex + 1);
		printf(pszTemp);
		sprintf(pszTemp, "    Page: %d\r\n", paryResult->ppBarcodes[iIndex]->iPageNum);
		printf(pszTemp);
		sprintf(pszTemp, "    Type: %s\r\n", GetFormatStr(paryResult->ppBarcodes[iIndex]->llFormat));
		printf(pszTemp);
		pszTemp1 = (char*)malloc(paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
		memset(pszTemp1, 0, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
		memcpy(pszTemp1, paryResult->ppBarcodes[iIndex]->pBarcodeData, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength);
		sprintf(pszTemp, "    Value: %s\r\n", pszTemp1);
		printf(pszTemp);
		free(pszTemp1);
		sprintf(pszTemp, "    Region: {Left: %d, Top: %d, Width: %d, Height: %d}\r\n\r\n", 
			paryResult->ppBarcodes[iIndex]->iLeft, paryResult->ppBarcodes[iIndex]->iTop, 
			paryResult->ppBarcodes[iIndex]->iWidth, paryResult->ppBarcodes[iIndex]->iHeight);
		printf(pszTemp);
	}	

	free(pszTemp);
	reader.FreeBarcodeResults(&paryResult);

	return 0;
}
void read(Mat &image, CBarcodeReader &reader)
{
	int elemSize = image.elemSize();
	int size = image.total() * elemSize;
	// Get image data
	char *imageData = (char *)image.data;

	// Combine header info and image data
	int width = image.cols, height = image.rows;
	char *total = (char *)malloc(size + 40);
	if (!total)
	{
		printf("Failed to allocate memory");
		return;
	}
	memset(total, 0, size + 40);
	BITMAPINFOHEADER bitmap_info = { 40, width, height, 0, 24, 0, size, 0, 0, 0, 0 };
	memcpy(total, &bitmap_info, 40);

	char *data = total + 40;
	// Reverse the image buffer from bottom to top
	width *= 3;

	for (int i = 1; i <= height; i++)
	{
		memcpy(data, imageData + width * (height - i), width);
		data += width;
	}

	// Read barcode
	unsigned __int64 ullTimeBegin = 0;
	unsigned __int64 ullTimeEnd = 0;
	ullTimeBegin = GetTickCount();
	int iRet = reader.DecodeBuffer((unsigned char*)total, size + 40);
	ullTimeEnd = GetTickCount();
	//printf("time cost: %lld\n", (ullTimeEnd - ullTimeBegin));

	// Output barcode result
	char * pszTemp = (char*)malloc(4096);
	if (iRet != DBR_OK && iRet != DBRERR_LICENSE_EXPIRED && iRet != DBRERR_QR_LICENSE_INVALID &&
		iRet != DBRERR_1D_LICENSE_INVALID && iRet != DBRERR_PDF417_LICENSE_INVALID && iRet != DBRERR_DATAMATRIX_LICENSE_INVALID)
	{
		sprintf(pszTemp, "Failed to read barcode: %s\r\n", DBR_GetErrorString(iRet));
		printf(pszTemp);
		free(pszTemp);
		free(total);
		return;
	}

	pBarcodeResultArray paryResult = NULL;
	reader.GetBarcodes(&paryResult);

	if (paryResult->iBarcodeCount > 0)
	{
		for (int iIndex = 0; iIndex < paryResult->iBarcodeCount; iIndex++)
		{
			sprintf(pszTemp, "Barcode %d:\r\n", iIndex + 1);
			printf(pszTemp);
			sprintf(pszTemp, "    Page: %d\r\n", paryResult->ppBarcodes[iIndex]->iPageNum);
			printf(pszTemp);
			sprintf(pszTemp, "    Type: %s\r\n", GetFormatStr(paryResult->ppBarcodes[iIndex]->llFormat));
			printf(pszTemp);
			char *pszTemp1 = (char*)malloc(paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
			memset(pszTemp1, 0, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
			memcpy(pszTemp1, paryResult->ppBarcodes[iIndex]->pBarcodeData, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength);
			sprintf(pszTemp, "    Value: %s\r\n", pszTemp1);
			printf(pszTemp);
			free(pszTemp1);
			sprintf(pszTemp, "    Region: {Left: %d, Top: %d, Width: %d, Height: %d}\r\n\r\n",
				paryResult->ppBarcodes[iIndex]->iLeft, paryResult->ppBarcodes[iIndex]->iTop,
				paryResult->ppBarcodes[iIndex]->iWidth, paryResult->ppBarcodes[iIndex]->iHeight);
			printf(pszTemp);
		}
	}

	free(pszTemp);
	reader.FreeBarcodeResults(&paryResult);
	free(total);
}