Merge pull request #27242 from mshabunin:fix-uwp-build

Looks like UWP builds were broken on 5.x:
```
C:\GHA-OCV-6\_work\opencv\opencv\opencv\modules\videoio\src\cap_winrt_capture.hpp(65,33): error C3646: 'size': unknown override specifier (compiling source file C:\GHA-OCV-6\_work\opencv\opencv\opencv\modules\videoio\src\cap_winrt_capture.cpp) [C:\GHA-OCV-6\_work\opencv\opencv\build\modules\videoio\opencv_videoio.vcxproj]
C:\GHA-OCV-6\_work\opencv\opencv\opencv\modules\videoio\src\cap_winrt_capture.hpp(65,37): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int (compiling source file C:\GHA-OCV-6\_work\opencv\opencv\opencv\modules\videoio\src\cap_winrt_capture.cpp) [C:\GHA-OCV-6\_work\opencv\opencv\build\modules\videoio\opencv_videoio.vcxproj]
C:\GHA-OCV-6\_work\opencv\opencv\opencv\modules\videoio\src\cap_winrt_capture.hpp(65,33): error C3646: 'size': unknown override specifier (compiling source file C:\GHA-OCV-6\_work\opencv\opencv\opencv\modules\videoio\src\videoio_registry.cpp) [C:\GHA-OCV-6\_work\opencv\opencv\build\modules\videoio\opencv_videoio.vcxproj]
C:\GHA-OCV-6\_work\opencv\opencv\opencv\modules\videoio\src\cap_winrt_capture.hpp(65,37): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int (compiling source file C:\GHA-OCV-6\_work\opencv\opencv\opencv\modules\videoio\src\videoio_registry.cpp) [C:\GHA-OCV-6\_work\opencv\opencv\build\modules\videoio\opencv_videoio.vcxproj]
C:\GHA-OCV-6\_work\opencv\opencv\opencv\modules\videoio\src\cap_winrt_capture.hpp(65,33): error C3646: 'size': unknown override specifier (compiling source file C:\GHA-OCV-6\_work\opencv\opencv\opencv\modules\videoio\src\cap_winrt_bridge.cpp) [C:\GHA-OCV-6\_work\opencv\opencv\build\modules\videoio\opencv_videoio.vcxproj]
C:\GHA-OCV-6\_work\opencv\opencv\opencv\modules\videoio\src\cap_winrt_capture.hpp(65,37): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int (compiling source file C:\GHA-OCV-6\_work\opencv\opencv\opencv\modules\videoio\src\cap_winrt_bridge.cpp) [C:\GHA-OCV-6\_work\opencv\opencv\build\modules\videoio\opencv_videoio.vcxproj]
C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\XamlCompiler\Microsoft.Windows.UI.Xaml.Common.targets(486,5): error MSB4181: The "CompileXaml" task returned false but did not log an error. [C:\GHA-OCV-6\_work\opencv\opencv\build\modules\videoio\opencv_videoio.vcxproj]
```

Notes:

- Pipeline passes even though there are errors in the build
- I decided to remove _highgui_ WinRT backend, because it uses C-API which is has been removed in 5.x. I believe nobody uses it anyway.
- Change in anneal library is caused by the issue in WinAPI header - it does not declare two functions for UWP, even though documentation states compatibility. See also https://github.com/openssl/openssl/pull/18311
  https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtuallock

  > Minimum supported client	Windows XP [desktop apps | UWP apps]
  > Minimum supported server	Windows Server 2003 [desktop apps | UWP apps]
This commit is contained in:
Maksim Shabunin 2025-05-16 12:45:40 +03:00 committed by GitHub
parent cb87f05e4b
commit 349b44a485
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 25 additions and 936 deletions

View File

@ -12,6 +12,7 @@
#include <sys/types.h>
#include <windows.h>
#include <memoryapi.h>
#include <errno.h>
#include <io.h>
@ -189,6 +190,27 @@ inline int msync(void *addr, size_t len, int /*flags*/)
return -1;
}
#pragma region Desktop Family or OneCore Family
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
WINBASEAPI
BOOL
WINAPI
VirtualLock(
_In_ LPVOID lpAddress,
_In_ SIZE_T dwSize
);
WINBASEAPI
BOOL
WINAPI
VirtualUnlock(
_In_ LPVOID lpAddress,
_In_ SIZE_T dwSize
);
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
inline int mlock(const void *addr, size_t len)
{
if (VirtualLock((LPVOID)addr, len))

View File

@ -26,10 +26,6 @@ set(highgui_srcs
# Jose Luis Blanco, 2008
# ----------------------------------------------------------------------------
if(DEFINED WINRT AND NOT DEFINED ENABLE_WINRT_MODE_NATIVE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /ZW")
endif()
if(APPLE)
ocv_include_directories(${ZLIB_INCLUDE_DIRS})
list(APPEND HIGHGUI_LIBRARIES ${ZLIB_LIBRARIES})
@ -44,9 +40,6 @@ file(GLOB highgui_ext_hdrs
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/*.hpp"
"${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/*.h")
# Removing WinRT API headers by default
list(REMOVE_ITEM highgui_ext_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/highgui_winrt.hpp")
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "")
if(WITH_FRAMEBUFFER AND HAVE_FRAMEBUFFER)
@ -149,41 +142,6 @@ elseif(HAVE_QT)
set_source_files_properties(${_RCC_OUTFILES} PROPERTIES COMPILE_FLAGS -Wno-missing-declarations)
endif()
endif()
elseif(WINRT)
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "WINRT")
if(NOT WINRT_8_0)
# Dependencies used by the implementation referenced
# below are not available on WinRT 8.0.
# Enabling it for WiRT 8.1+ only.
# WinRT 8.1+ detected. Adding WinRT API header.
message(STATUS " ${name}: WinRT detected. Adding WinRT API header")
list(APPEND highgui_ext_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${name}/highgui_winrt.hpp")
list(APPEND highgui_srcs
${CMAKE_CURRENT_LIST_DIR}/src/window_winrt.cpp
${CMAKE_CURRENT_LIST_DIR}/src/window_winrt_bridge.cpp)
list(APPEND highgui_hdrs
${CMAKE_CURRENT_LIST_DIR}/src/window_winrt_bridge.hpp)
endif()
# libraries below are neither available nor required
# on ARM devices and/or Windows Phone
if(WINRT_PHONE OR (OpenCV_ARCH STREQUAL "ARM"))
list(REMOVE_ITEM HIGHGUI_LIBRARIES "comctl32" "gdi32" "ole32" "setupapi")
if(WINRT_PHONE)
message(STATUS " ${name}: Windows Phone detected")
elseif(OpenCV_ARCH STREQUAL "ARM")
message(STATUS " ${name}: ARM detected")
if(WINRT_STORE)
list(REMOVE_ITEM HIGHGUI_LIBRARIES "ws2_32")
message(STATUS " ${name}: Removing 'ws2_32.lib'")
endif()
endif()
message(STATUS " ${name}: Removing 'comctl32.lib, gdi32.lib, ole32.lib, setupapi.lib'")
message(STATUS " ${name}: Leaving '${HIGHGUI_LIBRARIES}'")
endif()
elseif(HAVE_COCOA)
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "COCOA")
add_definitions(-DHAVE_COCOA)

View File

@ -1,6 +1,6 @@
if(PROJECT_NAME STREQUAL "OpenCV")
set(ENABLE_PLUGINS_DEFAULT ON)
if(EMSCRIPTEN OR IOS OR WINRT)
if(EMSCRIPTEN OR IOS)
set(ENABLE_PLUGINS_DEFAULT OFF)
endif()
set(HIGHGUI_PLUGIN_LIST "" CACHE STRING "List of GUI backends to be compiled as plugins (gtk, gtk2/gtk3, qt, win32 or special value 'all')")

View File

@ -87,44 +87,6 @@ It provides easy interface to:
See below the example used to generate the figure:
@include highgui_qt.cpp
@defgroup highgui_winrt WinRT support
This figure explains new functionality implemented with WinRT GUI. The new GUI provides an Image control,
and a slider panel. Slider panel holds trackbars attached to it.
Sliders are attached below the image control. Every new slider is added below the previous one.
See below the example used to generate the figure:
@code
void sample_app::MainPage::ShowWindow()
{
static cv::String windowName("sample");
cv::winrt_initContainer(this->cvContainer);
cv::namedWindow(windowName); // not required
cv::Mat image = cv::imread("Assets/sample.jpg");
cv::Mat converted = cv::Mat(image.rows, image.cols, CV_8UC4);
cv::cvtColor(image, converted, COLOR_BGR2BGRA);
cv::imshow(windowName, converted); // this will create window if it hasn't been created before
int state = 42;
cv::TrackbarCallback callback = [](int pos, void* userdata)
{
if (pos == 0) {
cv::destroyWindow(windowName);
}
};
cv::TrackbarCallback callbackTwin = [](int pos, void* userdata)
{
if (pos >= 70) {
cv::destroyAllWindows();
}
};
cv::createTrackbar("Sample trackbar", windowName, &state, 100, callback);
cv::createTrackbar("Twin brother", windowName, &state, 100, callbackTwin);
}
@endcode
@}
*/

View File

@ -121,7 +121,6 @@ void updateWindowImpl(const char* window_name);
void cvSetModeWindow_W32(const char* name, double prop_value);
void cvSetModeWindow_GTK(const char* name, double prop_value);
void cvSetModeWindow_COCOA(const char* name, double prop_value);
void cvSetModeWindow_WinRT(const char* name, double prop_value);
cv::Rect cvGetWindowRect_W32(const char* name);
cv::Rect cvGetWindowRect_GTK(const char* name);
@ -131,7 +130,6 @@ cv::Rect cvGetWindowRect_WAYLAND(const char* name);
double cvGetModeWindow_W32(const char* name);
double cvGetModeWindow_GTK(const char* name);
double cvGetModeWindow_COCOA(const char* name);
double cvGetModeWindow_WinRT(const char* name);
double cvGetPropWindowAutoSize_W32(const char* name);
double cvGetPropWindowAutoSize_GTK(const char* name);

View File

@ -230,8 +230,6 @@ void cv::setWindowProperty(const String& name, int prop_id, double prop_value)
cvSetModeWindow_GTK(name.c_str(),prop_value);
#elif defined (HAVE_COCOA)
cvSetModeWindow_COCOA(name.c_str(),prop_value);
#elif defined (WINRT)
cvSetModeWindow_WinRT(name.c_str(), prop_value);
#endif
break;
@ -314,8 +312,6 @@ double cv::getWindowProperty(const String& name, int prop_id)
return cvGetModeWindow_GTK(name.c_str());
#elif defined (HAVE_COCOA)
return cvGetModeWindow_COCOA(name.c_str());
#elif defined (WINRT)
return cvGetModeWindow_WinRT(name.c_str());
#else
return -1;
#endif
@ -1182,7 +1178,7 @@ int cv::createButton(const String&, ButtonCallback, void*, int , bool )
//========================= NO GUI fallback =========================
#if !defined (HAVE_WIN32UI) && !defined (HAVE_GTK) && !defined (HAVE_COCOA) && !defined (HAVE_QT) \
&& !defined (HAVE_WAYLAND) && !defined (WINRT) && !defined (WINRT_8_0)
&& !defined (HAVE_WAYLAND)
// No windowing system present at compile time ;-(
//

View File

@ -1,246 +0,0 @@
// highgui to XAML bridge for OpenCV
// Copyright (c) Microsoft Open Technologies, Inc.
// All rights reserved.
//
// (3 - clause BSD License)
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
// the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
// following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
// promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include "precomp.hpp"
#include <map>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <opencv2\highgui.hpp>
#include <opencv2\highgui\highgui_winrt.hpp>
#include "window_winrt_bridge.hpp"
#define CV_WINRT_NO_GUI_ERROR( funcname ) \
{ \
cvError( cv::Error::StsNotImplemented, funcname, \
"The function is not implemented. ", \
__FILE__, __LINE__ ); \
}
#ifdef CV_ERROR
#undef CV_ERROR
#define CV_ERROR( Code, Msg ) \
{ \
cvError( (Code), cvFuncName, Msg, __FILE__, __LINE__ ); \
};
#endif
/********************************** WinRT Specific API Implementation ******************************************/
// Initializes or overrides container contents with default XAML markup structure
void cv::winrt_initContainer(::Windows::UI::Xaml::Controls::Panel^ _container)
{
HighguiBridge::getInstance().setContainer(_container);
}
/********************************** API Implementation *********************************************************/
void showImageImpl(const char* name, InputArray arr)
{
__BEGIN__;
if (!name)
CV_Error(cv::Error::StsNullPtr, "NULL name");
CvWindow* window = HighguiBridge::getInstance().namedWindow(name);
if (!window || arr.empty())
return;
//TODO: use approach from window_w32.cpp or cv::Mat(.., .., CV_8UC4)
// and cvtColor(.., .., cv::COLOR_BGR2BGRA) to convert image here
// than beforehand.
window->updateImage(arr);
HighguiBridge::getInstance().showWindow(window);
__END__;
}
int namedWindowImpl(const char* name, int flags)
{
CV_UNUSED(flags);
if (!name)
CV_Error(cv::Error::StsNullPtr, "NULL name");
HighguiBridge::getInstance().namedWindow(name);
return CV_OK;
}
void destroyWindowImpl(const char* name)
{
if (!name)
CV_Error(cv::Error::StsNullPtr, "NULL name string");
HighguiBridge::getInstance().destroyWindow(name);
}
void destroyAllWindowsImpl()
{
HighguiBridge::getInstance().destroyAllWindows();
}
int createTrackbar2Impl(const char* trackbar_name, const char* window_name,
int* val, int count, CvTrackbarCallback2 on_notify, void* userdata)
{
if (!window_name || !trackbar_name)
CV_Error(cv::Error::StsNullPtr, "NULL window or trackbar name");
if (count < 0)
CV_Error(cv::Error::StsOutOfRange, "Bad trackbar max value");
CvWindow* window = HighguiBridge::getInstance().namedWindow(window_name);
if (!window)
{
CV_Error(cv::Error::StsNullPtr, "NULL window");
}
window->createSlider(trackbar_name, val, count, on_notify, userdata);
return CV_OK;
}
void setTrackbarPosImpl(const char* trackbar_name, const char* window_name, int pos)
{
CvTrackbar* trackbar = 0;
if (trackbar_name == 0 || window_name == 0)
CV_Error(cv::Error::StsNullPtr, "NULL trackbar or window name");
CvWindow* window = HighguiBridge::getInstance().findWindowByName(window_name);
if (window)
trackbar = window->findTrackbarByName(trackbar_name);
if (trackbar)
trackbar->setPosition(pos);
}
void setTrackbarMaxImpl(const char* trackbar_name, const char* window_name, int maxval)
{
if (maxval >= 0)
{
if (trackbar_name == 0 || window_name == 0)
CV_Error(cv::Error::StsNullPtr, "NULL trackbar or window name");
CvTrackbar* trackbar = HighguiBridge::getInstance().findTrackbarByName(trackbar_name, window_name);
if (trackbar)
trackbar->setMaxPosition(maxval);
}
}
void setTrackbarMinImpl(const char* trackbar_name, const char* window_name, int minval)
{
if (minval >= 0)
{
if (trackbar_name == 0 || window_name == 0)
CV_Error(cv::Error::StsNullPtr, "NULL trackbar or window name");
CvTrackbar* trackbar = HighguiBridge::getInstance().findTrackbarByName(trackbar_name, window_name);
if (trackbar)
trackbar->setMinPosition(minval);
}
}
int getTrackbarPosImpl(const char* trackbar_name, const char* window_name)
{
int pos = -1;
if (trackbar_name == 0 || window_name == 0)
CV_Error(cv::Error::StsNullPtr, "NULL trackbar or window name");
CvTrackbar* trackbar = HighguiBridge::getInstance().findTrackbarByName(trackbar_name, window_name);
if (trackbar)
pos = (int)trackbar->getPosition();
return pos;
}
/********************************** Not YET implemented API ****************************************************/
int waitKeyImpl(int delay)
{
CV_WINRT_NO_GUI_ERROR("waitKeyImpl");
// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724411(v=vs.85).aspx
//int time0 = GetTickCount64();
for (;;)
{
// CvWindow* window;
if (delay <= 0)
{
// TODO: implement appropriate logic here
}
}
}
void setMouseCallbackImpl(const char* window_name, CvMouseCallback on_mouse, void* param)
{
CV_UNUSED(on_mouse); CV_UNUSED(param);
CV_WINRT_NO_GUI_ERROR("setMouseCallbackImpl");
if (!window_name)
CV_Error(cv::Error::StsNullPtr, "NULL window name");
CvWindow* window = HighguiBridge::getInstance().findWindowByName(window_name);
if (!window)
return;
// TODO: implement appropriate logic here
}
/********************************** Disabled or not supported API **********************************************/
void moveWindowImpl(const char* name, int x, int y)
{
CV_UNUSED(name); CV_UNUSED(x); CV_UNUSED(y);
CV_WINRT_NO_GUI_ERROR("moveWindowImpl");
}
void resizeWindowImpl(const char* name, int width, int height)
{
CV_UNUSED(name); CV_UNUSED(width); CV_UNUSED(height);
CV_WINRT_NO_GUI_ERROR("resizeWindowImpl");
}
void cvSetModeWindow_WinRT(const char* name, double prop_value) {
CV_UNUSED(name); CV_UNUSED(prop_value);
CV_WINRT_NO_GUI_ERROR("cvSetModeWindow");
}
double cvGetModeWindow_WinRT(const char* name) {
CV_UNUSED(name);
CV_WINRT_NO_GUI_ERROR("cvGetModeWindow");
return cv::Error::StsNotImplemented;
}

View File

@ -1,367 +0,0 @@
// highgui to XAML bridge for OpenCV
// Copyright (c) Microsoft Open Technologies, Inc.
// All rights reserved.
//
// (3 - clause BSD License)
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
// the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
// following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
// promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include "precomp.hpp"
#include "opencv2\highgui\highgui_winrt.hpp"
#include "window_winrt_bridge.hpp"
#include <collection.h>
#include <Robuffer.h> // Windows::Storage::Streams::IBufferByteAccess
using namespace Microsoft::WRL; // ComPtr
using namespace Windows::Storage::Streams; // IBuffer
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Media::Imaging;
using namespace ::std;
/***************************** Constants ****************************************/
// Default markup for the container content allowing for proper components placement
const Platform::String^ CvWindow::markupContent =
"<Page \n" \
" xmlns = \"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n" \
" xmlns:x = \"http://schemas.microsoft.com/winfx/2006/xaml\" >\n" \
" <StackPanel Name=\"Container\" Orientation=\"Vertical\" Width=\"Auto\" Height=\"Auto\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Top\" Visibility=\"Visible\">\n" \
" <Image Name=\"cvImage\" Width=\"Auto\" Height=\"Auto\" Margin=\"10\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Top\" Visibility=\"Visible\"/>\n" \
" <StackPanel Name=\"cvTrackbar\" Height=\"Auto\" Width=\"Auto\" Orientation=\"Vertical\" Visibility=\"Visible\"/>\n" \
" <StackPanel Name=\"cvButton\" Height=\"Auto\" Width=\"Auto\" Orientation=\"Horizontal\" Visibility=\"Visible\"/>\n" \
" </StackPanel>\n" \
"</Page>";
const double CvWindow::sliderDefaultWidth = 100;
/***************************** HighguiBridge class ******************************/
HighguiBridge& HighguiBridge::getInstance()
{
static HighguiBridge instance;
return instance;
}
void HighguiBridge::setContainer(Windows::UI::Xaml::Controls::Panel^ container_)
{
this->container = container_;
}
CvWindow* HighguiBridge::findWindowByName(cv::String name)
{
auto search = windowsMap->find(name);
if (search != windowsMap->end()) {
return search->second;
}
return nullptr;
}
CvTrackbar* HighguiBridge::findTrackbarByName(cv::String trackbar_name, cv::String window_name)
{
CvWindow* window = findWindowByName(window_name);
if (window)
return window->findTrackbarByName(trackbar_name);
return nullptr;
}
Platform::String^ HighguiBridge::convertString(cv::String name)
{
auto data = name.c_str();
int bufferSize = MultiByteToWideChar(CP_UTF8, 0, data, -1, nullptr, 0);
auto wide = std::make_unique<wchar_t[]>(bufferSize);
if (0 == MultiByteToWideChar(CP_UTF8, 0, data, -1, wide.get(), bufferSize))
return nullptr;
std::wstring* stdStr = new std::wstring(wide.get());
return ref new Platform::String(stdStr->c_str());
}
void HighguiBridge::cleanContainer()
{
container->Children->Clear();
}
void HighguiBridge::showWindow(CvWindow* window)
{
currentWindow = window;
cleanContainer();
HighguiBridge::getInstance().container->Children->Append(window->getPage());
}
CvWindow* HighguiBridge::namedWindow(cv::String name) {
CvWindow* window = HighguiBridge::getInstance().findWindowByName(name.c_str());
if (!window)
{
window = createWindow(name);
}
return window;
}
void HighguiBridge::destroyWindow(cv::String name)
{
auto window = windowsMap->find(name);
if (window != windowsMap->end())
{
// Check if deleted window is the one currently displayed
// and clear container if this is the case
if (window->second == currentWindow)
{
cleanContainer();
}
windowsMap->erase(window);
}
}
void HighguiBridge::destroyAllWindows()
{
cleanContainer();
windowsMap->clear();
}
CvWindow* HighguiBridge::createWindow(cv::String name)
{
CvWindow* window = new CvWindow(name);
windowsMap->insert(std::pair<cv::String, CvWindow*>(name, window));
return window;
}
/***************************** CvTrackbar class *********************************/
CvTrackbar::CvTrackbar(cv::String name, Slider^ slider, CvWindow* parent) : name(name), slider(slider), parent(parent) {}
CvTrackbar::~CvTrackbar() {}
void CvTrackbar::setPosition(double pos)
{
if (pos < 0)
pos = 0;
if (pos > slider->Maximum)
pos = slider->Maximum;
slider->Value = pos;
}
void CvTrackbar::setMaxPosition(double pos)
{
//slider->Minimum is initialized with 0
if (pos < slider->Minimum)
pos = slider->Minimum;
slider->Maximum = pos;
}
void CvTrackbar::setMinPosition(double pos)
{
if (pos < 0)
pos = 0;
//Min is always less than Max.
if (pos > slider->Maximum)
pos = slider->Maximum;
slider->Minimum = pos;
}
void CvTrackbar::setSlider(Slider^ slider_) {
if (slider_)
this->slider = slider_;
}
double CvTrackbar::getPosition()
{
return slider->Value;
}
double CvTrackbar::getMaxPosition()
{
return slider->Maximum;
}
double CvTrackbar::getMinPosition()
{
return slider->Minimum;
}
Slider^ CvTrackbar::getSlider()
{
return slider;
}
/***************************** CvWindow class ***********************************/
CvWindow::CvWindow(cv::String name, int flags) : name(name)
{
CV_UNUSED(flags);
this->page = (Page^)Windows::UI::Xaml::Markup::XamlReader::Load(const_cast<Platform::String^>(markupContent));
this->sliderMap = new std::map<cv::String, CvTrackbar*>();
sliderPanel = (Panel^)page->FindName("cvTrackbar");
imageControl = (Image^)page->FindName("cvImage");
buttonPanel = (Panel^)page->FindName("cvButton");
// Required to adapt controls to the size of the image.
// System calculates image control width first, after that we can
// update other controls
imageControl->Loaded += ref new Windows::UI::Xaml::RoutedEventHandler(
[=](Platform::Object^ sender,
Windows::UI::Xaml::RoutedEventArgs^ e)
{
// Need to update sliders with appropriate width
for (auto iter = sliderMap->begin(); iter != sliderMap->end(); ++iter) {
iter->second->getSlider()->Width = imageControl->ActualWidth;
}
// Need to update buttons with appropriate width
// TODO: implement when adding buttons
});
}
CvWindow::~CvWindow() {}
void CvWindow::createSlider(cv::String name_, int* val, int count, CvTrackbarCallback2 on_notify, void* userdata)
{
CV_UNUSED(userdata);
CvTrackbar* trackbar = findTrackbarByName(name_);
// Creating slider if name is new or reusing the existing one
Slider^ slider = !trackbar ? ref new Slider() : trackbar->getSlider();
slider->Header = HighguiBridge::getInstance().convertString(name_);
// Making slider the same size as the image control or setting minimal size.
// This is added to cover potential edge cases because:
// 1. Fist clause will not be true until the second call to any container-updating API
// e.g. cv::createTrackbar, cv:imshow or cv::namedWindow
// 2. Second clause will work but should be immediately overridden by Image->Loaded callback,
// see CvWindow ctor.
if (this->imageControl->ActualWidth > 0) {
// One would use double.NaN for auto-stretching but there is no such constant in C++/CX
// see https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.frameworkelement.width
slider->Width = this->imageControl->ActualWidth;
} else {
// This value would never be used/seen on the screen unless there is something wrong with the image.
// Although this code actually gets called, slider width will be overridden in the callback after
// Image control is loaded. See callback implementation in CvWindow ctor.
slider->Width = sliderDefaultWidth;
}
slider->Value = val ? *val : 0;
slider->Maximum = count;
slider->Visibility = Windows::UI::Xaml::Visibility::Visible;
slider->Margin = Windows::UI::Xaml::ThicknessHelper::FromLengths(10, 10, 10, 0);
slider->HorizontalAlignment = Windows::UI::Xaml::HorizontalAlignment::Left;
if (!trackbar)
{
if (!sliderPanel) return;
// Adding slider to the list for current window
CvTrackbar* trackbar_ = new CvTrackbar(name_, slider, this);
trackbar_->callback = on_notify;
slider->ValueChanged +=
ref new Controls::Primitives::RangeBaseValueChangedEventHandler(
[=](Platform::Object^ sender,
Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e)
{
Slider^ slider = (Slider^)sender;
trackbar_->callback((int)slider->Value, nullptr);
});
this->sliderMap->insert(std::pair<cv::String, CvTrackbar*>(name_, trackbar_));
// Adding slider to the window
sliderPanel->Children->Append(slider);
}
}
CvTrackbar* CvWindow::findTrackbarByName(cv::String name_)
{
auto search = sliderMap->find(name_);
if (search != sliderMap->end()) {
return search->second;
}
return nullptr;
}
void CvWindow::updateImage(InputArray arr)
{
if (!imageControl) return;
Mat src = arr.getMat();
this->imageData = src.data;
this->imageWidth = src.size().width;
// Create the WriteableBitmap
WriteableBitmap^ bitmap = ref new WriteableBitmap(src.cols, src.rows);
// Get access to the pixels
IBuffer^ buffer = bitmap->PixelBuffer;
unsigned char* dstPixels;
// Obtain IBufferByteAccess
ComPtr<IBufferByteAccess> pBufferByteAccess;
ComPtr<IInspectable> pBuffer((IInspectable*)buffer);
pBuffer.As(&pBufferByteAccess);
// Get pointer to pixel bytes
pBufferByteAccess->Buffer(&dstPixels);
memcpy(dstPixels, src.data, CV_ELEM_SIZE(src.type) * src.cols*src.rows);
// Set the bitmap to the Image element
imageControl->Source = bitmap;
}
Page^ CvWindow::getPage()
{
return page;
}
//TODO: prototype, not in use yet
void CvWindow::createButton(cv::String name_)
{
if (!buttonPanel) return;
Button^ b = ref new Button();
b->Content = HighguiBridge::getInstance().convertString(name_);
b->Width = 260;
b->Height = 80;
b->Click += ref new Windows::UI::Xaml::RoutedEventHandler(
[=](Platform::Object^ sender,
Windows::UI::Xaml::RoutedEventArgs^ e)
{
Button^ button = (Button^)sender;
// TODO: more logic here...
});
buttonPanel->Children->Append(b);
}
// end

View File

@ -1,234 +0,0 @@
// highgui to XAML bridge for OpenCV
// Copyright (c) Microsoft Open Technologies, Inc.
// All rights reserved.
//
// (3 - clause BSD License)
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
// the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
// following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or
// promote products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#pragma once
#include <map>
#include <opencv2\core.hpp>
using namespace Windows::UI::Xaml::Controls;
class CvWindow;
class CvTrackbar;
class HighguiBridge
{
public:
/** @brief Instantiates a Highgui singleton (Meyers type).
The function Instantiates a Highgui singleton (Meyers type) and returns reference to that instance.
*/
static HighguiBridge& getInstance();
/** @brief Finds window by name and returns the reference to it.
@param name Name of the window.
The function finds window by name and returns the reference to it. Returns nullptr
if window with specified name is not found or name argument is null.
*/
CvWindow* findWindowByName(cv::String name);
/** @brief Returns reference to the trackbar(slider) registered within window with a provided name.
@param name Name of the window.
The function returns reference to the trackbar(slider) registered within window with a provided name.
Returns nullptr if trackbar with specified name is not found or window reference is nullptr.
*/
CvTrackbar* findTrackbarByName(cv::String trackbarName, cv::String windowName);
/** @brief Converts cv::String to Platform::String.
@param name String to convert.
The function converts cv::String to Platform::String.
Returns nullptr if conversion fails.
*/
Platform::String^ convertString(cv::String name);
/** @brief Creates window if there is no window with this name, otherwise returns existing window.
@param name Window name.
The function creates window if there is no window with this name, otherwise returns existing window.
*/
CvWindow* namedWindow(cv::String name);
/** @brief Shows provided window.
The function shows provided window: makes provided window current, removes current container
contents and shows current window by putting it as a container content.
*/
void showWindow(CvWindow* window);
/** @brief Destroys window if there exists window with this name, otherwise does nothing.
@param name Window name.
The function destroys window if there exists window with this name, otherwise does nothing.
If window being destroyed is the current one, it will be hidden by clearing the window container.
*/
void destroyWindow(cv::String name);
/** @brief Destroys all windows.
The function destroys all windows.
*/
void destroyAllWindows();
/** @brief Assigns container used to display windows.
@param _container Container reference.
The function assigns container used to display windows.
*/
void setContainer(Windows::UI::Xaml::Controls::Panel^ _container);
private:
// Meyers singleton
HighguiBridge(const HighguiBridge &);
HighguiBridge() {
windowsMap = new std::map<cv::String, CvWindow*>();
};
/** @brief Creates window if there is no window with this name.
@param name Window name.
The function creates window if there is no window with this name.
*/
CvWindow* createWindow(cv::String name);
/** @brief Cleans current container contents.
The function cleans current container contents.
*/
void cleanContainer();
// see https://msdn.microsoft.com/en-US/library/windows/apps/xaml/hh700103.aspx
// see https://msdn.microsoft.com/ru-ru/library/windows.foundation.collections.aspx
std::map<cv::String, CvWindow*>* windowsMap;
CvWindow* currentWindow;
// Holds current container/content to manipulate with
Windows::UI::Xaml::Controls::Panel^ container;
};
class CvTrackbar
{
public:
CvTrackbar(cv::String name, Slider^ slider, CvWindow* parent);
~CvTrackbar();
double getPosition();
void setPosition(double pos);
double getMaxPosition();
void setMaxPosition(double pos);
double getMinPosition();
void setMinPosition(double pos);
Slider^ getSlider();
void setSlider(Slider^ pos);
CvTrackbarCallback2 callback;
private:
cv::String name;
Slider^ slider;
CvWindow* parent;
};
class CvWindow
{
public:
CvWindow(cv::String name, int flag = cv::WINDOW_NORMAL);
~CvWindow();
/** @brief NOTE: prototype.
Should create button if there is no button with this name already.
*/
void createButton(cv::String name);
/** @brief Creates slider if there is no slider with this name already.
The function creates slider if there is no slider with this name already OR resets
provided values for the existing one.
*/
void createSlider(cv::String name, int* val, int count, CvTrackbarCallback2 on_notify, void* userdata);
/** @brief Updates window image.
@param src Image data object reference.
The function updates window image. If argument is null or image control is not found - does nothing.
*/
void updateImage(InputArray arr);
/** @brief Returns reference to the trackbar(slider) registered within provided window.
@param name Name of the window.
The function returns reference to the trackbar(slider) registered within provided window.
Returns nullptr if trackbar with specified name is not found or window reference is nullptr.
*/
CvTrackbar* findTrackbarByName(cv::String name);
Page^ getPage();
private:
cv::String name;
// Holds image data in CV format
CvMat* imageData;
// Map of all sliders assigned to this window
std::map<cv::String, CvTrackbar*>* sliderMap;
// Window contents holder
Page^ page;
// Image control displayed by this window
Image^ imageControl;
// Container for sliders
Panel^ sliderPanel;
// Container for buttons
// TODO: prototype, not available via API
Panel^ buttonPanel;
// Holds image width to arrange other UI elements.
// Required since imageData->width value gets recalculated when processing
int imageWidth;
// Default markup for the container content allowing for proper components placement
static const Platform::String^ markupContent;
// Default Slider size, fallback solution for unexpected edge cases
static const double sliderDefaultWidth;
};

View File

@ -62,7 +62,7 @@ namespace cv {
protected:
bool started;
CvSize size;
Size size;
int bytesPerPixel;
unsigned long frameCurrent;
std::atomic<bool> isFrameNew;