Advertisement
Guest User

Untitled

a guest
Dec 14th, 2019
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.00 KB | None | 0 0
  1. #include "Source.h"
  2.  
  3. #define FIRST_PATH_BUTTON_ID 1001
  4. #define SECOND_PATH_BUTTON_ID 1002
  5. #define FIND_DUPLICATES_BUTTON_ID 1003
  6. #define EXTENSION_CHECKBOX_ID 1004
  7. #define MAX_LOADSTRING 100
  8. #define FONT_SIZE 12
  9. #define MAX_PATH_LENGTH 60
  10.  
  11. HINSTANCE hInst;
  12. WCHAR title[MAX_LOADSTRING] = L"OSaSP2";
  13. WCHAR windowClass[MAX_LOADSTRING] = L"OSaSP2Class";
  14.  
  15. wstring firstSelectedPath;
  16. wstring secondSelectedPath;
  17.  
  18. wstring reducedFirstPath;
  19. wstring reducedSecondPath;
  20.  
  21. const int buttonWidth = 130;
  22. const int buttonHeight = 30;
  23. const int xMargin = 15;
  24. const int yMargin = 10;
  25.  
  26. vector<vector<filesystem::path>*>* images = new vector<vector<filesystem::path>*>;
  27. const set<string> extensions{ ".jpg", ".png", ".bmp", ".tiff", ".jpeg", ".icon", ".gif", ".exif", ".wmf", ".emf" };
  28. RECT rect;
  29. OPENFILENAME ofn;
  30.  
  31. WCHAR fileName[MAX_PATH];
  32.  
  33. ATOM                MyRegisterClass(HINSTANCE hInstance);
  34. BOOL                InitInstance(HINSTANCE, int);
  35. LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
  36.  
  37. void                pathClick(HWND hWnd, wstring& path, wstring& reducedPath);
  38. LPWSTR              getPath(HWND hwnd);
  39. wstring             reducePath(wstring path);
  40. void                saveToFile();
  41.  
  42. bool                check_extension(const filesystem::path& file);
  43. string              to_lower(string str);
  44. void                get_files(const filesystem::path& path, vector<vector<filesystem::path>*>* files);
  45. bool                compare_files(const filesystem::path file1, filesystem::path file2);
  46. void                find_duplicates(vector<vector<filesystem::path>*>* files);
  47.  
  48. Image* get_gray_scale_version(Image* image);
  49. Image* resize(Image* image);
  50. void                array_destroyer(::byte** ary, unsigned int dim1);
  51. ::byte** array_generator(unsigned int dim1, unsigned int dim2);
  52. FLOAT               start_comparing(Image* firstImage, Image* secondImage, ::byte threshold);
  53.  
  54. int CALLBACK wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
  55. {
  56.     GdiplusStartupInput gdiplusStartupInput;
  57.     ULONG_PTR           gdiplusToken;
  58.  
  59.     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
  60.  
  61.     MyRegisterClass(hInstance);
  62.  
  63.     if (!InitInstance(hInstance, nCmdShow))
  64.     {
  65.         return FALSE;
  66.     }
  67.  
  68.     MSG msg;
  69.     while (GetMessage(&msg, nullptr, 0, 0))
  70.     {
  71.         TranslateMessage(&msg);
  72.         DispatchMessage(&msg);
  73.     }
  74.  
  75.     GdiplusShutdown(gdiplusToken);
  76.     return (int)msg.wParam;
  77. }
  78.  
  79. ATOM MyRegisterClass(HINSTANCE hInstance)
  80. {
  81.     WNDCLASSEX wcex;
  82.  
  83.     wcex.cbSize = sizeof(WNDCLASSEX);
  84.     wcex.cbClsExtra = 0;
  85.     wcex.cbWndExtra = 0;
  86.     wcex.style = CS_HREDRAW | CS_VREDRAW;
  87.     wcex.lpfnWndProc = WndProc;
  88.     wcex.hInstance = hInstance;
  89.     wcex.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
  90.     wcex.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
  91.     wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
  92.     wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  93.     wcex.lpszMenuName = nullptr;
  94.     wcex.lpszClassName = windowClass;
  95.  
  96.     return RegisterClassEx(&wcex);
  97. }
  98.  
  99. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  100. {
  101.     hInst = hInstance;
  102.  
  103.     HWND hWnd = CreateWindowW(windowClass, title, WS_OVERLAPPEDWINDOW,
  104.         CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
  105.  
  106.     if (!hWnd)
  107.         return FALSE;
  108.  
  109.     ShowWindow(hWnd, nCmdShow);
  110.     UpdateWindow(hWnd);
  111.  
  112.     return TRUE;
  113. }
  114.  
  115. void saveToFile()
  116. {
  117.     std::ofstream fout("C:\\Users\\evgeny\\Desktop\\123.txt");
  118.  
  119.     int i = 0;
  120.     fout << "Duplicates" << endl << endl;
  121.     for (auto iter1 = images->begin(); iter1 != images->end(); ++iter1)
  122.     {
  123.         if ((*iter1)->size() < 2)
  124.         {
  125.             continue;
  126.         }
  127.         fout << ++i << ":" << endl;
  128.         for (auto iter2 = (*iter1)->begin(); iter2 != (*iter1)->end(); ++iter2)
  129.         {
  130.             fout << (*iter2).string() << endl;
  131.         }
  132.         fout << endl;
  133.         fout << endl;
  134.     }
  135.     fout.close();
  136. }
  137.  
  138. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  139. {
  140.     static HWND firstImgButton;
  141.     static HWND secondImgButton;
  142.     static HWND calculateButton;
  143.     static HWND extensionCheckbox;
  144.     Font font(L"Arial", FONT_SIZE, FontStyleBold);
  145.  
  146.     GetClientRect(hWnd, &rect);
  147.     switch (message)
  148.     {
  149.         case WM_COMMAND:
  150.         {
  151.             int wmId = LOWORD(wParam);
  152.             switch (wmId)
  153.             {
  154.                 case FIRST_PATH_BUTTON_ID:
  155.                     pathClick(hWnd, firstSelectedPath, reducedFirstPath);
  156.                     break;
  157.                 case SECOND_PATH_BUTTON_ID:
  158.                     pathClick(hWnd, secondSelectedPath, reducedSecondPath);
  159.                     break;
  160.                 case FIND_DUPLICATES_BUTTON_ID:
  161.                     delete images;
  162.                     images = new vector<vector<filesystem::path>*>;
  163.                     get_files(firstSelectedPath, images);
  164.                     get_files(secondSelectedPath, images);
  165.                     find_duplicates(images);
  166.                     saveToFile();
  167.                     break;
  168.                 case EXTENSION_CHECKBOX_ID:
  169.                 {
  170.                     BOOL checked = IsDlgButtonChecked(hWnd, EXTENSION_CHECKBOX_ID);
  171.                     if (checked) {
  172.                         CheckDlgButton(hWnd, EXTENSION_CHECKBOX_ID, BST_UNCHECKED);
  173.                     }
  174.                     else {
  175.                         CheckDlgButton(hWnd, EXTENSION_CHECKBOX_ID, BST_CHECKED);
  176.                     }
  177.                 }
  178.                     break;
  179.                 default:
  180.                     return DefWindowProc(hWnd, message, wParam, lParam);
  181.             }
  182.         }
  183.         break;
  184.        
  185.         case WM_PAINT:
  186.         {
  187.             PAINTSTRUCT ps;
  188.             SolidBrush brush(Color::Black);
  189.             HDC hdc = BeginPaint(hWnd, &ps);
  190.             if(!reducedFirstPath.empty())
  191.             {
  192.                 Graphics graphics(hdc);
  193.                 PointF origin(xMargin * 2 + buttonWidth, yMargin + FONT_SIZE / 2);
  194.                 graphics.DrawString(reducedFirstPath.c_str(), reducedFirstPath.length(), &font, origin, &brush);
  195.             }
  196.             if (!reducedSecondPath.empty())
  197.             {
  198.                 Graphics graphics(hdc);
  199.                 PointF origin(xMargin * 2 + buttonWidth, yMargin * 2 + buttonHeight + FONT_SIZE / 2);
  200.                 graphics.DrawString(reducedSecondPath.c_str(), reducedSecondPath.length(), &font, origin, &brush);
  201.             }
  202.             EndPaint(hWnd, &ps);
  203.         }
  204.  
  205.         case WM_KEYDOWN:
  206.             switch (wParam)
  207.             {
  208.             case VK_F1:
  209.  
  210.                 break;
  211.             }
  212.             break;
  213.         case WM_CREATE:
  214.             if (GetWindowRect(hWnd, &rect))
  215.             {
  216.                 int width = rect.right - rect.left;
  217.                 int height = rect.bottom - rect.top;
  218.                 firstImgButton = CreateWindow(L"button", L"Get first path",
  219.                     WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
  220.                     xMargin, yMargin,
  221.                     buttonWidth, buttonHeight,
  222.                     hWnd, (HMENU)FIRST_PATH_BUTTON_ID,
  223.                     hInst, NULL);
  224.  
  225.                 secondImgButton = CreateWindow(L"button", L"Get second path",
  226.                     WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
  227.                     xMargin, buttonHeight + yMargin * 2,
  228.                     buttonWidth, buttonHeight,
  229.                     hWnd, (HMENU)SECOND_PATH_BUTTON_ID,
  230.                     hInst, NULL);
  231.  
  232.                 extensionCheckbox = CreateWindow(L"button", L"Check extension",
  233.                     WS_CHILD | WS_VISIBLE | BS_CHECKBOX,
  234.                     xMargin, buttonHeight * 2 + yMargin * 3,
  235.                     buttonWidth, buttonHeight,
  236.                     hWnd, (HMENU)EXTENSION_CHECKBOX_ID,
  237.                     hInst, NULL);
  238.  
  239.                 calculateButton = CreateWindow(L"button", L"Find duplicates",
  240.                     WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
  241.                     xMargin, buttonHeight * 3 + yMargin * 4,
  242.                     buttonWidth, buttonHeight,
  243.                     hWnd, (HMENU)FIND_DUPLICATES_BUTTON_ID,
  244.                     hInst, NULL);
  245.  
  246.             }
  247.             break;
  248.         case WM_DESTROY:
  249.             PostQuitMessage(0);
  250.             break;
  251.         default:
  252.             return DefWindowProc(hWnd, message, wParam, lParam);
  253.     }
  254.     return 0;
  255. }
  256.  
  257. void pathClick(HWND hWnd, wstring& path, wstring& reducedPath)
  258. {
  259.     const LPWSTR selectedPath = getPath(hWnd);
  260.     if (selectedPath != nullptr)
  261.     {
  262.         path = selectedPath;
  263.         reducedPath = reducePath(selectedPath);
  264.     }
  265.     InvalidateRect(hWnd, 0, TRUE);
  266. }
  267.  
  268. LPWSTR getPath(HWND hWnd)
  269. {
  270.     LPWSTR file = new WCHAR[1024];
  271.     ZeroMemory(&ofn, sizeof(ofn));
  272.     ofn.lStructSize = sizeof(ofn);
  273.     ofn.hwndOwner = nullptr;
  274.     file[0] = '\0';
  275.     ofn.lpstrFile = file;
  276.     ofn.nMaxFile = 1024;
  277.     ofn.lpstrFilter = L"Pictures (*.ICON;*.png; *.GIF; *.JPEG; *.Exif; *.PNG; *.TIFF; *.WMF; *.EMF; *.BMP; *.JPG)\0*.ICON;*.png; *.GIF; *.JPEG; *.Exif; *.PNG; *.TIFF; *.WMF; *.EMF; *.BMP; *.JPG\0All Files (*.*)\0*.*\0";
  278.     ofn.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOVALIDATE;
  279.     if (GetOpenFileName(&ofn))
  280.         return ofn.lpstrFile;
  281.  
  282.     //MessageBoxA(hWnd, "Can't open file", "Caption", NULL);
  283.     return nullptr;
  284. }
  285.  
  286. wstring reducePath(wstring path)
  287. {
  288.     if(path.length() > MAX_PATH_LENGTH)
  289.     {
  290.         const wstring file(path.begin() + path.find_last_of(L'\\') + 1, path.end());
  291.         if(file.length() > MAX_PATH_LENGTH - 4)
  292.         {
  293.             return file.substr(0, MAX_PATH_LENGTH / 2 - 3).append(L"...")
  294.                 .append(file.substr(file.length() - MAX_PATH_LENGTH / 2 + 3, file.length()));
  295.         }
  296.         return path.substr(0, MAX_PATH_LENGTH - 4 - file.length()).append(L"...\\").append(file);
  297.     }
  298.     return path;
  299. }
  300.  
  301. string to_lower(string str)
  302. {
  303.     std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c)
  304.     { return std::tolower(c); });
  305.     return str;
  306. }
  307.  
  308. bool check_extension(const filesystem::path& file)
  309. {
  310.     const string extension = to_lower(file.extension().string());
  311.     return extensions.count(extension);
  312. }
  313.  
  314. void get_files(const filesystem::path& path, vector<vector<filesystem::path>*>* files)
  315. {
  316.     if (!is_directory(path))
  317.     {
  318.         files->push_back(new vector<filesystem::path>);
  319.         files->back()->push_back(path);
  320.     }
  321.     else
  322.     {
  323.         for (const auto& p : std::filesystem::recursive_directory_iterator(path))
  324.         {
  325.             if (!is_directory(p) && check_extension(p.path()))
  326.             {
  327.                 files->push_back(new vector<filesystem::path>);
  328.                 files->back()->push_back(p.path());
  329.             }
  330.         }
  331.     }
  332. }
  333.  
  334. bool compare_files(const filesystem::path file1, const filesystem::path file2)
  335. {
  336.     if (file1.extension() == file2.extension() && file_size(file1) == file_size(file2))
  337.     {
  338.         return start_comparing(new Image(file1.c_str()), new Image(file2.c_str()), 4) == 0;
  339.     }
  340.     return false;
  341. }
  342.  
  343. void find_duplicates(vector<vector<filesystem::path>*>* files)
  344. {
  345.     for (auto i = 0; i < files->size(); i++)
  346.     {
  347.         for (auto iterator = files->begin() + i + 1; iterator != files->end(); ++iterator)
  348.         {
  349.             if (compare_files(files->at(i)->front(), (*iterator)->front()))
  350.             {
  351.                 files->at(i)->push_back((*iterator)->front());
  352.                 iterator = files->erase(iterator);
  353.                 --iterator;
  354.             }
  355.         }
  356.     }
  357. }
  358.  
  359. FLOAT start_comparing(Image* firstImage, Image* secondImage, ::byte threshold)
  360. {
  361.     Image* smallImage1 = resize(firstImage);
  362.     Image* smallImage2 = resize(secondImage);
  363.     Bitmap* thisOne = (Bitmap*)(get_gray_scale_version(resize(get_gray_scale_version(smallImage1))));
  364.     Bitmap* theOtherOne = (Bitmap*)get_gray_scale_version(resize(get_gray_scale_version(smallImage2)));
  365.  
  366.     int size = 16;
  367.     ::byte** differences = array_generator(size, size);
  368.  
  369.     ::byte** firstGrayScale = array_generator(size, size);//new ::byte[size, size];
  370.     ::byte** secondGrayScale = array_generator(size, size); //new ::byte[size, size];
  371.  
  372.     Color pixelColor;
  373.     for (int x = 0; x < 16; x++)
  374.     {
  375.         for (int y = 0; y < 16; y++)
  376.         {
  377.  
  378.             thisOne->GetPixel(x, y, &pixelColor);
  379.             //int j = 8;
  380.             firstGrayScale[x][y] = (::byte)abs(pixelColor.GetRed());
  381.             //firstGrayScale[x][y] = resultPixels[x][y];
  382.         }
  383.     }
  384.  
  385.     for (int x = 0; x < 16; x++)
  386.     {
  387.  
  388.         for (int y = 0; y < 16; y++)
  389.         {
  390.             //Color pixelColor;
  391.             theOtherOne->GetPixel(x, y, &pixelColor);
  392.             secondGrayScale[x][y] = abs(pixelColor.GetRed());
  393.             //secondGrayScale[x][y] = resultPixels1[x][y];
  394.         }
  395.     }
  396.  
  397.     for (int x = 0; x < 16; x++)
  398.     {
  399.         for (int y = 0; y < 16; y++)
  400.         {
  401.             differences[x][y] = (::byte)abs(firstGrayScale[x][y] - secondGrayScale[x][y]);
  402.         }
  403.     }
  404.  
  405.     int diffPixels = 0;
  406.  
  407.     for (int i = 0; i < 16; i++)
  408.     {
  409.         for (int j = 0; j < 16; j++)
  410.         {
  411.             if (differences[i][j] > threshold)
  412.                 diffPixels++;
  413.         }
  414.     }
  415.  
  416.     array_destroyer(differences, 16);
  417.     array_destroyer(firstGrayScale, 16);
  418.     array_destroyer(secondGrayScale, 16);
  419.  
  420.     float result = static_cast<float>(diffPixels) / 256; //diffPixels / 256f;
  421.  
  422.     return result;
  423. }
  424.  
  425. Image* resize(Image* image)
  426. {
  427.     Image* smallImage1 = new Bitmap(16, 16);
  428.  
  429.     // Resize images   
  430.     Graphics gr1(smallImage1);
  431.     gr1.SetSmoothingMode(SmoothingModeHighQuality);
  432.     gr1.SetInterpolationMode(InterpolationModeHighQualityBicubic);
  433.     gr1.SetPixelOffsetMode(PixelOffsetModeHighQuality);
  434.     gr1.DrawImage(image, 0, 0, 16, 16);
  435.  
  436.     return smallImage1;
  437. }
  438.  
  439. //Converts an image to grayscale
  440. Image* get_gray_scale_version(Image* image)
  441. {
  442.  
  443.     //create a blank bitmap the same size as original
  444.     INT width = image->GetWidth();
  445.     INT height = image->GetHeight();
  446.  
  447.     Image* newImage = new Bitmap(width, height);
  448.  
  449.     Graphics grayGraphics(newImage);
  450.  
  451.     ColorMatrix colorMatrix = {
  452.         0.3f, 0.3f, 0.3f, 0.0f, 0.0f,
  453.         0.59f, 0.59f, 0.59f, 0.0f, 0.0f,
  454.         0.11f, 0.11f, 0.11f, 0.0f, 0.0f,
  455.         0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
  456.         0.0f, 0.0f, 0.0f, 0.0f, 1.0f
  457.     };
  458.  
  459.     //create some image attributes
  460.     ImageAttributes imageAttributes;
  461.     //set the color matrix attribute
  462.     imageAttributes.SetColorMatrix(&colorMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap);
  463.  
  464.     //draw the original image on the new image
  465.     //using the grayscale color matrix
  466.  
  467.     grayGraphics.DrawImage(image, Rect(0, 0, width, height), 0, 0, width, height,
  468.         UnitPixel, &imageAttributes);
  469.     //delete &grayGraphics;
  470.  
  471.     return newImage;
  472. }
  473.  
  474. void array_destroyer(::byte** ary, unsigned int dim1) {
  475.     for (int i = 0; i < dim1; i++) {
  476.         delete[] ary[i];
  477.     }
  478.     delete[] ary;
  479. }
  480.  
  481. ::byte** array_generator(unsigned int dim1, unsigned int dim2) {
  482.     ::byte** ptrary = new ::byte * [dim1];
  483.     for (int i = 0; i < dim1; i++) {
  484.         ptrary[i] = new ::byte[dim2];
  485.     }
  486.     return ptrary;
  487. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement