Я чувствую себя почти на финише. Я работаю над проектом для считывания отпечатков пальцев, который мне нужен для работы. Это должно быть сделано к середине января, поэтому мне нужно, чтобы это работало 🙂
Я прыгал по всему интернету, чтобы найти библиотеку, которая уже берет изображение от моего читателя, и меня отослали к Грио. Долго говоря Коротко, после большого разочарования я пришел к выводу, что Грио устарел, слишком сложен для того, что он должен делать, слишком дорог и в целом слишком труден, чтобы заставить его работать должным образом.
Поэтому я решил использовать другой подход, где я использую примеры, предоставленные Microsoft, а затем использую другую библиотеку, которую я получил, чтобы позаботиться об обработке, как только я получу изображение.
Сейчас я нахожусь в точке, где я могу отсканировать отпечаток пальца и затем сделать файл BMP. Но соотношение сторон файла странное. Он выглядит очень высоким и сжатым вместе, хотя (если память служит) сканер должен иметь более высокое разрешение.
Консоль пишет, что изображение должно быть 256 x 360
но я должен разделить эту ширину на 3, чтобы изображение работало. Так получается, что 85x360
что выглядит не совсем правильно.
Итак, вот функция, которая сохраняет изображение как BMP:
bool SaveBMP(BYTE* buffer, int width, int height, long paddedsize, LPCTSTR bmpfile) {
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER info;
memset(&bmfh, 0, sizeof(BITMAPFILEHEADER));
memset(&info, 0, sizeof(BITMAPINFOHEADER));
bmfh.bfType = 0x4d42; // Don't question it. Magic Word (B and M). It's necessary. Seriously.
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
bmfh.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+paddedsize;
bmfh.bfOffBits = 0x36;
info.biSize = sizeof(BITMAPINFOHEADER);
info.biWidth = width;
info.biHeight = height;
info.biPlanes = 1;
info.biBitCount = 24;
info.biCompression = BI_RGB;
info.biSizeImage = 0;
info.biXPelsPerMeter = 0x0ec4;
info.biYPelsPerMeter = 0x0ec4;
info.biClrUsed = 0;
info.biClrImportant = 0;
HANDLE file = CreateFile(bmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
unsigned long bwritten;
if (WriteFile(file, &bmfh, sizeof(BITMAPFILEHEADER), &bwritten, NULL) == false) {
CloseHandle(file);
return false;
}
if (WriteFile(file, &info, sizeof(BITMAPINFOHEADER), &bwritten, NULL) == false) {
CloseHandle(file);
return false;
}
if (WriteFile(file, buffer, paddedsize, &bwritten, NULL) == false) {
CloseHandle(file);
return false;
}
CloseHandle(file);
return true;
}
Код, используемый для захвата отпечатка пальца:
HRESULT CaptureSample()
{
HRESULT hr = S_OK;
WINBIO_SESSION_HANDLE sessionHandle = NULL;
WINBIO_UNIT_ID unitId = 0;
WINBIO_REJECT_DETAIL rejectDetail = 0;
PWINBIO_BIR sample = NULL;
SIZE_T sampleSize = 0;
// Connect to the system pool.
hr = WinBioOpenSession(
WINBIO_TYPE_FINGERPRINT, // Service provider
WINBIO_POOL_SYSTEM, // Pool type
WINBIO_FLAG_RAW, // Access: Capture raw data
NULL, // Array of biometric unit IDs
0, // Count of biometric unit IDs
WINBIO_DB_DEFAULT, // Default database
&sessionHandle // [out] Session handle
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioOpenSession failed. hr = 0x%x\n", hr);
goto e_Exit;
}
// Capture a biometric sample.
wprintf_s(L"\n Calling WinBioCaptureSample - Swipe sensor...\n");
hr = WinBioCaptureSample(
sessionHandle,
WINBIO_NO_PURPOSE_AVAILABLE,
WINBIO_DATA_FLAG_RAW,
&unitId,
&sample,
&sampleSize,
&rejectDetail
);
if (FAILED(hr))
{
if (hr == WINBIO_E_BAD_CAPTURE)
{
wprintf_s(L"\n Bad capture; reason: %d\n", rejectDetail);
}
else
{
wprintf_s(L"\n WinBioCaptureSample failed. hr = 0x%x\n", hr);
}
goto e_Exit;
}
wprintf_s(L"\n Swipe processed - Unit ID: %d\n", unitId);
wprintf_s(L"\n Captured %d bytes.\n", sampleSize);
// Art "Messiah" Baker at Microsoft
PWINBIO_BIR_HEADER BirHeader = (PWINBIO_BIR_HEADER)(((PBYTE)sample) + sample->HeaderBlock.Offset);
PWINBIO_BDB_ANSI_381_HEADER AnsiBdbHeader = (PWINBIO_BDB_ANSI_381_HEADER)(((PBYTE)sample) + sample->StandardDataBlock.Offset);
PWINBIO_BDB_ANSI_381_RECORD AnsiBdbRecord = (PWINBIO_BDB_ANSI_381_RECORD)(((PBYTE)AnsiBdbHeader) + sizeof(WINBIO_BDB_ANSI_381_HEADER));
PBYTE firstPixel = (PBYTE)((PBYTE)AnsiBdbRecord) + sizeof(WINBIO_BDB_ANSI_381_RECORD);
int width = AnsiBdbRecord->HorizontalLineLength;
int height = AnsiBdbRecord->VerticalLineLength;
wprintf_s(L"\n ID: %d\n", AnsiBdbHeader->ProductId.Owner);
wprintf_s(L"\n Width: %d\n", AnsiBdbRecord->HorizontalLineLength);
wprintf_s(L"\n Height: %d\n", AnsiBdbRecord->VerticalLineLength);
wprintf_s(L"\n Horizontal Img. Res.: %d\n", AnsiBdbHeader->HorizontalImageResolution);
wprintf_s(L"\n Horizontal Scan Img. Res.: %d\n", AnsiBdbHeader->HorizontalScanResolution);
wprintf_s(L"\n Vertical Img. Res.: %d\n", AnsiBdbHeader->VerticalImageResolution);
wprintf_s(L"\n Vertical Scan Img. Res.: %d\n", AnsiBdbHeader->VerticalScanResolution);
wprintf_s(L"\n First Pixel: %d\n", firstPixel);
wprintf_s(L"\n Element Count: %d\n", AnsiBdbHeader->ElementCount);
bool b = SaveBMP(firstPixel, width, height, 0, L"C:\\Users\\smf\\Desktop\\fingerprint.bmp");
wprintf_s(L"\n Success: %d\n", b);
e_Exit:
if (sample != NULL)
{
WinBioFree(sample);
sample = NULL;
}
if (sessionHandle != NULL)
{
WinBioCloseSession(sessionHandle);
sessionHandle = NULL;
}
wprintf_s(L"\n Press any key to exit...");
_getch();
return hr;
}
Что я не совсем понимаю (так как я новичок в C ++ в целом, но разбираюсь в языках более высокого уровня), так это для того, чтобы эта функция работала, я должен разделить всю ширину, которую я передаю функции, на 3. Если я не надену не делайте этого, изображение получится неработающим.
В чем причина этого, и, если возможно, как заставить изображение сохранить первоначальную ширину?
AFAIK, изображение, возвращаемое WinBioCaptureSample, является растровым изображением в градациях серого, то есть использует 8 бит на пиксель.
Ваша реализация SaveBitmap записывает 24-битное растровое изображение RGB. Таким образом, ему нужно в 3 раза больше байтов, чем в исходном растровом изображении (или, как вы уже узнали, изображение будет уменьшено в 3 раза).
Таким образом, чтобы решить проблему, вам нужно утроить каждый байт в какой-то момент. Либо внутри SaveBitmap, либо перед передачей данных в него.
Других решений пока нет …