Advertisement
Guest User

Untitled

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