If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below. |
|
|
Thread Tools | Rate Thread | Display Modes |
#1
|
|||
|
|||
Default image size in File Explorer.
I can do this, but it seems to take a long time to
finish. If I have a folder containing 50000 images in umpteen folders of "large" size images (seemingly the default with Win10) and I change this default to "extra large" the computer grinds away for over about an hour to do it. Does all this involve tagging each individual image to open as "extra large", and does this mean any individual image carries this property with itself when transferred elsewhere? Peter |
Ads |
#2
|
|||
|
|||
Default image size in File Explorer.
Peter Jason wrote:
I can do this, but it seems to take a long time to finish. If I have a folder containing 50000 images in umpteen folders of "large" size images (seemingly the default with Win10) and I change this default to "extra large" the computer grinds away for over about an hour to do it. Does all this involve tagging each individual image to open as "extra large", and does this mean any individual image carries this property with itself when transferred elsewhere? Peter Thumbnails are put in a thumbnail database (.db). The system thumbnailer providers for JPG and TIFF are extremely fast. So fast in fact, that the system can generate a thumbnail from a given file, in about the same time it can query the .db and extract it from there. If we do 100 images a second, 50000 images is still 8 minutes. I have a program that will scan a folder tree and update the relevant .db . And it's not doing much more than File Explorer would do, except the program allows you to run the generation task at a more convenient time. If you move an image file, there's no particular reason for a thumbnail to be generated for the file in its new location. It would require an expose event in File Explorer to cause the thumbnail to be generated. I don't think Microsoft particularly cares to do "clever ****" to move the thumbnails around. It could, for example, define an alternate stream for a file, and as the file is moved from place to place, the alternate stream could come with it. But instead, they have their little .db which manages things as expose events require. If a file is not found in the .db, the provider extracts a new one. Using logic only File Explorer understands, the thumbnail .db file can be removed and regenerated whenever they feel the need. It isn't even as generous as waiting three months before zapping windows.edb (Search) and regenerating the index. Here's a program for Visual Studio to compile, which will generate thumbnails on demand for a folder tree. Requires a starting path, the extension type you want thumbnails for, plus the preferred thumbnail size (256 maybe). ******* thumnail.cpp ******* // thumnail.cpp : Defines the entry point for the console application. // // This program needs "Visual C++ Redistributable for Visual Studio 2015" Version140 // https://www.microsoft.com/en-gb/down....aspx?id=48145 // // Loads: mfc140u.dll , msvcp140.dll , vcruntime140.dll // The MFC might be superfluous but I can't be bothered to remove the code. // I have no plan to distribute EXE and DLLs as such. // // ******* // // thumnail.exe is a command line program which scans a folder tree for // files to add to the thumbnail cache. In doing so, it might cache // thumbnails not currently in view as such. The thumbnail cache has // finite size, and Windows can choose to delete the cache at any time. // This means that excessive thumbnail generation (for extra large icons) // could potentially be self defeating. // // Thumbnails are stored here on Win10 (the intended target for this program). // They can be removed by using Cleanmgr.exe. This program does not directly // manipulate these files. But if the files become too large, the OS deletes // them and starts over. // // C:\Users\User Name\AppData\Local\Microsoft\Windows\Explorer // // Program arguments: // // Path: "C:\users\user name\Downloads\PDF10" --- use double quotes!!! // Extension: pdf --- also jpg ot tif // Size: 256 --- varies :-) // // You can verify the pixel size required, by using SnippingTool and taking a screenshot // of a window that normally contains your thumbnails. My extra large icons had // outer dimensions larger than 256, but the inner dimension (white part) is 256. // On Hi-DPI monitors, it's possible Windows will have chosen different dimensions. // This program does not have any logic to "sniff" this and automate it. if the user // erased the thumbnails using CleanMgr.exe, there would be no information to sniff // any more. So it's not worth trying to add such a feature. // // The thumbnail handlers invoked, vary in efficiency. The Microsoft handlers are pretty // fast. It's almost as fast to extract a JPG thumbnail from scratch, as to get it // from the cache. However, Adobe Acrobat shell extension thumbnail handler is quite // slow. For any significant collection of PDF files, it could take all night. // // The C++ library has two interfaces. The one used in this program, is slow. // There is a "stream" interface, but it serves a different purpose. It pulls // the bitmap from the cache, so a developer can show a picture on the screen of // the icon for themselves. Whereas the interface used in this program, can "test" // whether an entry already exists in the cache, or like this program, the interface // can also cause a thumbnail entry to be added/updated. // // This code was constructed using mostly time-tested "Copy/Paste" techniques, from the // well-known helpful websites. Hardly any of this code is original. #include "stdafx.h" #include "thumnail.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // The one and only application object CWinApp theApp; #include string #include vector #include stack #include iostream #include algorithm #include sstream #include windows.h #include shobjIdl.h #include Shlwapi.h #include thumbcache.h using namespace std; // This copy/pasted code descends a file tree bool ListFiles(wstring path, wstring mask, vectorwstring& files) { HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA ffd; wstring spec; stackwstring directories; directories.push(path); files.clear(); while (!directories.empty()) { path = directories.top(); spec = path + L"\\" + mask; directories.pop(); hFind = FindFirstFile(spec.c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { return false; } do { if (wcscmp(ffd.cFileName, L".") != 0 && wcscmp(ffd.cFileName, L"..") != 0) { if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { directories.push(path + L"\\" + ffd.cFileName); } else { files.push_back(path + L"\\" + ffd.cFileName); } } } while (FindNextFile(hFind, &ffd) != 0); if (GetLastError() != ERROR_NO_MORE_FILES) { FindClose(hFind); return false; } FindClose(hFind); hFind = INVALID_HANDLE_VALUE; } return true; } int wmain(__in int argc, __in_ecount(argc) WCHAR **argv) { // Some of the first lines of code are "boilerplate", pasted by Visual Studio. int nRetCode = 0; HMODULE hModule = ::GetModuleHandle(nullptr); // Compute total runtime. Since the method is rubbish (counting steamboats does not match), // I decided to use a second time stamp too :-) __int64 time1 = 0, time2 = 0, freq = 0; QueryPerformanceCounter((LARGE_INTEGER *)&time1); QueryPerformanceFrequency((LARGE_INTEGER *)&freq); int thour, tmin, tsec; struct tm local; time_t secs = time(0); localtime_s(&local, &secs); thour = local.tm_hour; tmin = local.tm_min; tsec = local.tm_sec; wprintf(L"\nStart at %02d:%02d:%02d\n", thour, tmin, tsec); if (hModule != nullptr) { // initialize MFC and print an error on failure if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs wprintf(L"Fatal Error: MFC initialization failed\n"); nRetCode = 1; } else { // TODO: code your application's behavior here. if (argc != 4) { // Check that three parameters plus program name exist. wprintf(L"\nUsage: %s path_in_double_quotes file_extension_jpg_tif_pdf thumbnail_size_256\n", argv[0]); wprintf(L"Usage: %s \"C:\\users\\user name\\Downloads\\PDF10\" pdf 256\n", argv[0]); return 1; } else { PCWSTR pszDir = argv[1]; vectorwstring files; wchar_t* ext; int thumsize; wprintf(L"Called with %s and %s and %s for argc of %d\n\n", pszDir, argv[2], argv[3], argc); // Convert thumbnail size (square) pixel dimension, string to integer conversion for 256. wistringstream wiss( argv[3] ); if (!(wiss thumsize) || !wiss.eof()) { wprintf(L"Could not convert third (integer) argument to a thumbnail size number for %s\n", argv[3] ); return 1; } // Fire up the COM engine CoInitialize(NULL); IThumbnailCache *cache; HRESULT hr = CoCreateInstance(CLSID_LocalThumbnailCache, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&cache)); if (SUCCEEDED(hr)) { if (ListFiles(pszDir, L"*", files)) { //Scan for files int count = 0; for (vectorwstring::iterator it = files.begin(); it != files.end(); ++it) { // .PDF -- pdf , make it lower case, remove the period ext = PathFindExtension(it-c_str()); wchar_t* ext_tmp = new wchar_t[wcslen(ext) + 1]; ext_tmp[0] = L'\0'; if (wcslen(ext) 0) { for (size_t k = 1; k wcslen(ext); k++) ext_tmp[k - 1] = towlower(ext[k]); ext_tmp[wcslen(ext) - 1] = L'\0'; } if (!wcscmp(ext_tmp, argv[2])) { // Get a ShellItem for the matching file type we found PIDLIST_ABSOLUTE pidl; IBindCtx *pbc = NULL; HRESULT hresult = SHParseDisplayName(it-c_str(), pbc, &pidl, 0, 0); if (SUCCEEDED(hresult)) { IShellItem *psi; hresult = SHCreateShellItem(NULL, NULL, pidl, &psi); if (SUCCEEDED(hresult)) { // Call for thumbnail // // If no Acrobat Reader shell extension is installed for PDF, will fail. // Need a suitable unhelpful error message. hresult = cache-GetThumbnail(psi, thumsize, WTS_EXTRACT, NULL, NULL, NULL); if (SUCCEEDED(hresult)) { wcout ext_tmp " number " count " is " it-c_str() endl; } else { wcout "cache-GetThumbnail failed (Missing Handler???) for " it-c_str() endl; } // cache-Release() --- Moved outside loop ILFree(pidl); count++; } } else { wcout "Failed to get ShellID for " it-c_str() endl; } } delete[] ext_tmp; } // for } //Listfiles cache-Release(); } //SUCCEEDED else { wprintf(L"Problem starting COM engine, bailing\n"); return 1; } } secs = time(0); localtime_s(&local, &secs); thour = local.tm_hour; tmin = local.tm_min; tsec = local.tm_sec; wprintf(L"\nStopping at %02d:%02d:%02d\n", thour, tmin, tsec); QueryPerformanceCounter((LARGE_INTEGER *)&time2); wprintf(L"Total run time t=%010.6f pseudo-seconds\n", (float)(time2 - time1) / freq); return 0; } } else { // TODO: change error code to suit your needs wprintf(L"Fatal Error: GetModuleHandle failed\n"); nRetCode = 1; } return nRetCode; } ******* end thumnail.cpp ******* Paul |
#3
|
|||
|
|||
Default image size in File Explorer.
On Thu, 24 May 2018 18:54:55 -0400, Paul
wrote: Peter Jason wrote: I can do this, but it seems to take a long time to finish. If I have a folder containing 50000 images in umpteen folders of "large" size images (seemingly the default with Win10) and I change this default to "extra large" the computer grinds away for over about an hour to do it. Does all this involve tagging each individual image to open as "extra large", and does this mean any individual image carries this property with itself when transferred elsewhere? Peter Thumbnails are put in a thumbnail database (.db). The system thumbnailer providers for JPG and TIFF are extremely fast. So fast in fact, that the system can generate a thumbnail from a given file, in about the same time it can query the .db and extract it from there. If we do 100 images a second, 50000 images is still 8 minutes. I have a program that will scan a folder tree and update the relevant .db . And it's not doing much more than File Explorer would do, except the program allows you to run the generation task at a more convenient time. If you move an image file, there's no particular reason for a thumbnail to be generated for the file in its new location. It would require an expose event in File Explorer to cause the thumbnail to be generated. I don't think Microsoft particularly cares to do "clever ****" to move the thumbnails around. It could, for example, define an alternate stream for a file, and as the file is moved from place to place, the alternate stream could come with it. But instead, they have their little .db which manages things as expose events require. If a file is not found in the .db, the provider extracts a new one. Using logic only File Explorer understands, the thumbnail .db file can be removed and regenerated whenever they feel the need. It isn't even as generous as waiting three months before zapping windows.edb (Search) and regenerating the index. Here's a program for Visual Studio to compile, which will generate thumbnails on demand for a folder tree. Requires a starting path, the extension type you want thumbnails for, plus the preferred thumbnail size (256 maybe). ******* thumnail.cpp ******* // thumnail.cpp : Defines the entry point for the console application. // // This program needs "Visual C++ Redistributable for Visual Studio 2015" Version140 // https://www.microsoft.com/en-gb/down....aspx?id=48145 // // Loads: mfc140u.dll , msvcp140.dll , vcruntime140.dll // The MFC might be superfluous but I can't be bothered to remove the code. // I have no plan to distribute EXE and DLLs as such. // // ******* // // thumnail.exe is a command line program which scans a folder tree for // files to add to the thumbnail cache. In doing so, it might cache // thumbnails not currently in view as such. The thumbnail cache has // finite size, and Windows can choose to delete the cache at any time. // This means that excessive thumbnail generation (for extra large icons) // could potentially be self defeating. // // Thumbnails are stored here on Win10 (the intended target for this program). // They can be removed by using Cleanmgr.exe. This program does not directly // manipulate these files. But if the files become too large, the OS deletes // them and starts over. // // C:\Users\User Name\AppData\Local\Microsoft\Windows\Explorer // // Program arguments: // // Path: "C:\users\user name\Downloads\PDF10" --- use double quotes!!! // Extension: pdf --- also jpg ot tif // Size: 256 --- varies :-) // // You can verify the pixel size required, by using SnippingTool and taking a screenshot // of a window that normally contains your thumbnails. My extra large icons had // outer dimensions larger than 256, but the inner dimension (white part) is 256. // On Hi-DPI monitors, it's possible Windows will have chosen different dimensions. // This program does not have any logic to "sniff" this and automate it. if the user // erased the thumbnails using CleanMgr.exe, there would be no information to sniff // any more. So it's not worth trying to add such a feature. // // The thumbnail handlers invoked, vary in efficiency. The Microsoft handlers are pretty // fast. It's almost as fast to extract a JPG thumbnail from scratch, as to get it // from the cache. However, Adobe Acrobat shell extension thumbnail handler is quite // slow. For any significant collection of PDF files, it could take all night. // // The C++ library has two interfaces. The one used in this program, is slow. // There is a "stream" interface, but it serves a different purpose. It pulls // the bitmap from the cache, so a developer can show a picture on the screen of // the icon for themselves. Whereas the interface used in this program, can "test" // whether an entry already exists in the cache, or like this program, the interface // can also cause a thumbnail entry to be added/updated. // // This code was constructed using mostly time-tested "Copy/Paste" techniques, from the // well-known helpful websites. Hardly any of this code is original. #include "stdafx.h" #include "thumnail.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // The one and only application object CWinApp theApp; #include string #include vector #include stack #include iostream #include algorithm #include sstream #include windows.h #include shobjIdl.h #include Shlwapi.h #include thumbcache.h using namespace std; // This copy/pasted code descends a file tree bool ListFiles(wstring path, wstring mask, vectorwstring& files) { HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA ffd; wstring spec; stackwstring directories; directories.push(path); files.clear(); while (!directories.empty()) { path = directories.top(); spec = path + L"\\" + mask; directories.pop(); hFind = FindFirstFile(spec.c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { return false; } do { if (wcscmp(ffd.cFileName, L".") != 0 && wcscmp(ffd.cFileName, L"..") != 0) { if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { directories.push(path + L"\\" + ffd.cFileName); } else { files.push_back(path + L"\\" + ffd.cFileName); } } } while (FindNextFile(hFind, &ffd) != 0); if (GetLastError() != ERROR_NO_MORE_FILES) { FindClose(hFind); return false; } FindClose(hFind); hFind = INVALID_HANDLE_VALUE; } return true; } int wmain(__in int argc, __in_ecount(argc) WCHAR **argv) { // Some of the first lines of code are "boilerplate", pasted by Visual Studio. int nRetCode = 0; HMODULE hModule = ::GetModuleHandle(nullptr); // Compute total runtime. Since the method is rubbish (counting steamboats does not match), // I decided to use a second time stamp too :-) __int64 time1 = 0, time2 = 0, freq = 0; QueryPerformanceCounter((LARGE_INTEGER *)&time1); QueryPerformanceFrequency((LARGE_INTEGER *)&freq); int thour, tmin, tsec; struct tm local; time_t secs = time(0); localtime_s(&local, &secs); thour = local.tm_hour; tmin = local.tm_min; tsec = local.tm_sec; wprintf(L"\nStart at %02d:%02d:%02d\n", thour, tmin, tsec); if (hModule != nullptr) { // initialize MFC and print an error on failure if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs wprintf(L"Fatal Error: MFC initialization failed\n"); nRetCode = 1; } else { // TODO: code your application's behavior here. if (argc != 4) { // Check that three parameters plus program name exist. wprintf(L"\nUsage: %s path_in_double_quotes file_extension_jpg_tif_pdf thumbnail_size_256\n", argv[0]); wprintf(L"Usage: %s \"C:\\users\\user name\\Downloads\\PDF10\" pdf 256\n", argv[0]); return 1; } else { PCWSTR pszDir = argv[1]; vectorwstring files; wchar_t* ext; int thumsize; wprintf(L"Called with %s and %s and %s for argc of %d\n\n", pszDir, argv[2], argv[3], argc); // Convert thumbnail size (square) pixel dimension, string to integer conversion for 256. wistringstream wiss( argv[3] ); if (!(wiss thumsize) || !wiss.eof()) { wprintf(L"Could not convert third (integer) argument to a thumbnail size number for %s\n", argv[3] ); return 1; } // Fire up the COM engine CoInitialize(NULL); IThumbnailCache *cache; HRESULT hr = CoCreateInstance(CLSID_LocalThumbnailCache, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&cache)); if (SUCCEEDED(hr)) { if (ListFiles(pszDir, L"*", files)) { //Scan for files int count = 0; for (vectorwstring::iterator it = files.begin(); it != files.end(); ++it) { // .PDF -- pdf , make it lower case, remove the period ext = PathFindExtension(it-c_str()); wchar_t* ext_tmp = new wchar_t[wcslen(ext) + 1]; ext_tmp[0] = L'\0'; if (wcslen(ext) 0) { for (size_t k = 1; k wcslen(ext); k++) ext_tmp[k - 1] = towlower(ext[k]); ext_tmp[wcslen(ext) - 1] = L'\0'; } if (!wcscmp(ext_tmp, argv[2])) { // Get a ShellItem for the matching file type we found PIDLIST_ABSOLUTE pidl; IBindCtx *pbc = NULL; HRESULT hresult = SHParseDisplayName(it-c_str(), pbc, &pidl, 0, 0); if (SUCCEEDED(hresult)) { IShellItem *psi; hresult = SHCreateShellItem(NULL, NULL, pidl, &psi); if (SUCCEEDED(hresult)) { // Call for thumbnail // // If no Acrobat Reader shell extension is installed for PDF, will fail. // Need a suitable unhelpful error message. hresult = cache-GetThumbnail(psi, thumsize, WTS_EXTRACT, NULL, NULL, NULL); if (SUCCEEDED(hresult)) { wcout ext_tmp " number " count " is " it-c_str() endl; } else { wcout "cache-GetThumbnail failed (Missing Handler???) for " it-c_str() endl; } // cache-Release() --- Moved outside loop ILFree(pidl); count++; } } else { wcout "Failed to get ShellID for " it-c_str() endl; } } delete[] ext_tmp; } // for } //Listfiles cache-Release(); } //SUCCEEDED else { wprintf(L"Problem starting COM engine, bailing\n"); return 1; } } secs = time(0); localtime_s(&local, &secs); thour = local.tm_hour; tmin = local.tm_min; tsec = local.tm_sec; wprintf(L"\nStopping at %02d:%02d:%02d\n", thour, tmin, tsec); QueryPerformanceCounter((LARGE_INTEGER *)&time2); wprintf(L"Total run time t=%010.6f pseudo-seconds\n", (float)(time2 - time1) / freq); return 0; } } else { // TODO: change error code to suit your needs wprintf(L"Fatal Error: GetModuleHandle failed\n"); nRetCode = 1; } return nRetCode; } ******* end thumnail.cpp ******* Paul Thanks Paul. |
#4
|
|||
|
|||
Default image size in File Explorer.
Peter Jason wrote:
On Thu, 24 May 2018 18:54:55 -0400, Paul wrote: Peter Jason wrote: I can do this, but it seems to take a long time to finish. If I have a folder containing 50000 images in umpteen folders of "large" size images (seemingly the default with Win10) and I change this default to "extra large" the computer grinds away for over about an hour to do it. Does all this involve tagging each individual image to open as "extra large", and does this mean any individual image carries this property with itself when transferred elsewhere? Peter Thumbnails are put in a thumbnail database (.db). The system thumbnailer providers for JPG and TIFF are extremely fast. So fast in fact, that the system can generate a thumbnail from a given file, in about the same time it can query the .db and extract it from there. If we do 100 images a second, 50000 images is still 8 minutes. I have a program that will scan a folder tree and update the relevant .db . And it's not doing much more than File Explorer would do, except the program allows you to run the generation task at a more convenient time. If you move an image file, there's no particular reason for a thumbnail to be generated for the file in its new location. It would require an expose event in File Explorer to cause the thumbnail to be generated. I don't think Microsoft particularly cares to do "clever ****" to move the thumbnails around. It could, for example, define an alternate stream for a file, and as the file is moved from place to place, the alternate stream could come with it. But instead, they have their little .db which manages things as expose events require. If a file is not found in the .db, the provider extracts a new one. Using logic only File Explorer understands, the thumbnail .db file can be removed and regenerated whenever they feel the need. It isn't even as generous as waiting three months before zapping windows.edb (Search) and regenerating the index. Here's a program for Visual Studio to compile, which will generate thumbnails on demand for a folder tree. Requires a starting path, the extension type you want thumbnails for, plus the preferred thumbnail size (256 maybe). ******* thumnail.cpp ******* // thumnail.cpp : Defines the entry point for the console application. // // This program needs "Visual C++ Redistributable for Visual Studio 2015" Version140 // https://www.microsoft.com/en-gb/down....aspx?id=48145 // // Loads: mfc140u.dll , msvcp140.dll , vcruntime140.dll // The MFC might be superfluous but I can't be bothered to remove the code. // I have no plan to distribute EXE and DLLs as such. // // ******* // // thumnail.exe is a command line program which scans a folder tree for // files to add to the thumbnail cache. In doing so, it might cache // thumbnails not currently in view as such. The thumbnail cache has // finite size, and Windows can choose to delete the cache at any time. // This means that excessive thumbnail generation (for extra large icons) // could potentially be self defeating. // // Thumbnails are stored here on Win10 (the intended target for this program). // They can be removed by using Cleanmgr.exe. This program does not directly // manipulate these files. But if the files become too large, the OS deletes // them and starts over. // // C:\Users\User Name\AppData\Local\Microsoft\Windows\Explorer // // Program arguments: // // Path: "C:\users\user name\Downloads\PDF10" --- use double quotes!!! // Extension: pdf --- also jpg ot tif // Size: 256 --- varies :-) // // You can verify the pixel size required, by using SnippingTool and taking a screenshot // of a window that normally contains your thumbnails. My extra large icons had // outer dimensions larger than 256, but the inner dimension (white part) is 256. // On Hi-DPI monitors, it's possible Windows will have chosen different dimensions. // This program does not have any logic to "sniff" this and automate it. if the user // erased the thumbnails using CleanMgr.exe, there would be no information to sniff // any more. So it's not worth trying to add such a feature. // // The thumbnail handlers invoked, vary in efficiency. The Microsoft handlers are pretty // fast. It's almost as fast to extract a JPG thumbnail from scratch, as to get it // from the cache. However, Adobe Acrobat shell extension thumbnail handler is quite // slow. For any significant collection of PDF files, it could take all night. // // The C++ library has two interfaces. The one used in this program, is slow. // There is a "stream" interface, but it serves a different purpose. It pulls // the bitmap from the cache, so a developer can show a picture on the screen of // the icon for themselves. Whereas the interface used in this program, can "test" // whether an entry already exists in the cache, or like this program, the interface // can also cause a thumbnail entry to be added/updated. // // This code was constructed using mostly time-tested "Copy/Paste" techniques, from the // well-known helpful websites. Hardly any of this code is original. #include "stdafx.h" #include "thumnail.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // The one and only application object CWinApp theApp; #include string #include vector #include stack #include iostream #include algorithm #include sstream #include windows.h #include shobjIdl.h #include Shlwapi.h #include thumbcache.h using namespace std; // This copy/pasted code descends a file tree bool ListFiles(wstring path, wstring mask, vectorwstring& files) { HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA ffd; wstring spec; stackwstring directories; directories.push(path); files.clear(); while (!directories.empty()) { path = directories.top(); spec = path + L"\\" + mask; directories.pop(); hFind = FindFirstFile(spec.c_str(), &ffd); if (hFind == INVALID_HANDLE_VALUE) { return false; } do { if (wcscmp(ffd.cFileName, L".") != 0 && wcscmp(ffd.cFileName, L"..") != 0) { if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { directories.push(path + L"\\" + ffd.cFileName); } else { files.push_back(path + L"\\" + ffd.cFileName); } } } while (FindNextFile(hFind, &ffd) != 0); if (GetLastError() != ERROR_NO_MORE_FILES) { FindClose(hFind); return false; } FindClose(hFind); hFind = INVALID_HANDLE_VALUE; } return true; } int wmain(__in int argc, __in_ecount(argc) WCHAR **argv) { // Some of the first lines of code are "boilerplate", pasted by Visual Studio. int nRetCode = 0; HMODULE hModule = ::GetModuleHandle(nullptr); // Compute total runtime. Since the method is rubbish (counting steamboats does not match), // I decided to use a second time stamp too :-) __int64 time1 = 0, time2 = 0, freq = 0; QueryPerformanceCounter((LARGE_INTEGER *)&time1); QueryPerformanceFrequency((LARGE_INTEGER *)&freq); int thour, tmin, tsec; struct tm local; time_t secs = time(0); localtime_s(&local, &secs); thour = local.tm_hour; tmin = local.tm_min; tsec = local.tm_sec; wprintf(L"\nStart at %02d:%02d:%02d\n", thour, tmin, tsec); if (hModule != nullptr) { // initialize MFC and print an error on failure if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs wprintf(L"Fatal Error: MFC initialization failed\n"); nRetCode = 1; } else { // TODO: code your application's behavior here. if (argc != 4) { // Check that three parameters plus program name exist. wprintf(L"\nUsage: %s path_in_double_quotes file_extension_jpg_tif_pdf thumbnail_size_256\n", argv[0]); wprintf(L"Usage: %s \"C:\\users\\user name\\Downloads\\PDF10\" pdf 256\n", argv[0]); return 1; } else { PCWSTR pszDir = argv[1]; vectorwstring files; wchar_t* ext; int thumsize; wprintf(L"Called with %s and %s and %s for argc of %d\n\n", pszDir, argv[2], argv[3], argc); // Convert thumbnail size (square) pixel dimension, string to integer conversion for 256. wistringstream wiss( argv[3] ); if (!(wiss thumsize) || !wiss.eof()) { wprintf(L"Could not convert third (integer) argument to a thumbnail size number for %s\n", argv[3] ); return 1; } // Fire up the COM engine CoInitialize(NULL); IThumbnailCache *cache; HRESULT hr = CoCreateInstance(CLSID_LocalThumbnailCache, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&cache)); if (SUCCEEDED(hr)) { if (ListFiles(pszDir, L"*", files)) { //Scan for files int count = 0; for (vectorwstring::iterator it = files.begin(); it != files.end(); ++it) { // .PDF -- pdf , make it lower case, remove the period ext = PathFindExtension(it-c_str()); wchar_t* ext_tmp = new wchar_t[wcslen(ext) + 1]; ext_tmp[0] = L'\0'; if (wcslen(ext) 0) { for (size_t k = 1; k wcslen(ext); k++) ext_tmp[k - 1] = towlower(ext[k]); ext_tmp[wcslen(ext) - 1] = L'\0'; } if (!wcscmp(ext_tmp, argv[2])) { // Get a ShellItem for the matching file type we found PIDLIST_ABSOLUTE pidl; IBindCtx *pbc = NULL; HRESULT hresult = SHParseDisplayName(it-c_str(), pbc, &pidl, 0, 0); if (SUCCEEDED(hresult)) { IShellItem *psi; hresult = SHCreateShellItem(NULL, NULL, pidl, &psi); if (SUCCEEDED(hresult)) { // Call for thumbnail // // If no Acrobat Reader shell extension is installed for PDF, will fail. // Need a suitable unhelpful error message. hresult = cache-GetThumbnail(psi, thumsize, WTS_EXTRACT, NULL, NULL, NULL); if (SUCCEEDED(hresult)) { wcout ext_tmp " number " count " is " it-c_str() endl; } else { wcout "cache-GetThumbnail failed (Missing Handler???) for " it-c_str() endl; } // cache-Release() --- Moved outside loop ILFree(pidl); count++; } } else { wcout "Failed to get ShellID for " it-c_str() endl; } } delete[] ext_tmp; } // for } //Listfiles cache-Release(); } //SUCCEEDED else { wprintf(L"Problem starting COM engine, bailing\n"); return 1; } } secs = time(0); localtime_s(&local, &secs); thour = local.tm_hour; tmin = local.tm_min; tsec = local.tm_sec; wprintf(L"\nStopping at %02d:%02d:%02d\n", thour, tmin, tsec); QueryPerformanceCounter((LARGE_INTEGER *)&time2); wprintf(L"Total run time t=%010.6f pseudo-seconds\n", (float)(time2 - time1) / freq); return 0; } } else { // TODO: change error code to suit your needs wprintf(L"Fatal Error: GetModuleHandle failed\n"); nRetCode = 1; } return nRetCode; } ******* end thumnail.cpp ******* Paul Thanks Paul. I regret that I don't have a server to host that on (in binary form). I'd do it that way if I had a choice. And using Visual Studio isn't my preference either, as MinGW is potentially a smaller download for someone building from source. But the libraries that uses, probably aren't all available in MinGW. I'm guessing that code is C++, but using the C subset of it (as I'm not an object oriented person and it would be a bore doing "private" and "public" sections, operator overloading and the like). The program more or less uses basic C constructs. Paul |
Thread Tools | |
Display Modes | Rate This Thread |
|
|