diff --git a/Vimba_6_0/Documentation/ReleaseNotes.txt b/Vimba_6_0/Documentation/ReleaseNotes.txt new file mode 100644 index 0000000..f1b8f2c --- /dev/null +++ b/Vimba_6_0/Documentation/ReleaseNotes.txt @@ -0,0 +1,605 @@ +=========================================================================== + + Vimba for Linux ARMv8 64-bit - Release Notes + + Version: 6.0 + Date: January 2022 +=========================================================================== + +-------------------------------- +Components and Version Reference +-------------------------------- + +Vimba GenICam Transport Layer modules +------------------------------------- + CSI Transport Layer (VimbaCSITL.cti) 1.0.1* + GigE Transport Layer (VimbaGigETL.cti) 1.9.0 + USB Transport Layer (VimbaUSBTL.cti) 1.4.1* + +APIs +---- + Vimba C API (libVimbaC.so) 1.9.1* + Vimba C++ API (libVimbaCPP.so) 1.9.0 + Vimba Python API 1.2.1* + Image Transform Library (libVimbaImageTransform.so) 1.6.0 + +Tools +----- + Vimba Viewer (VimbaViewer) 2.5.0 + Vimba Class Generator (VimbaClassGenerator) 1.0.6 + Vimba Firmware Updater (VimbaFirmwareUpdater.exe) 1.2.0 + Vimba Firmware Updater Console (FWUpdaterConsole.exe) 1.2.0 + +Third Party Libraries +--------------------- + TinyXML (not shipped with Vimba) 2.6.2 + Qt 4.8.5 + Qwt 6.1.3 + libTIFF 4.0.7 + OpenCV 3.0.0 + +* Changed in this release of Vimba + + +--------------------- +Hardware Requirements +--------------------- +ARM board with ARMv8-compatible 64-bit processor + +Allied Vision GigE cameras require a built-in Gigabit Ethernet network interface +or at least one Gigabit Ethernet network card. + + Note for IP configuration: + By default, IP Configuration Mode is set to DHCP. + You can also select LLA (link-local address) if you connect just one camera. + If multiple cameras are connected at the same time, we recommend using + DHCP or Persistent IP Address to enable discovery of all cameras. + + +Allied Vision USB cameras require a built-in USB 3.0 controller for PCI Express bus. + +------------------------ +Tested Operating Systems +------------------------ +Vimba was tested on NVIDIA Xavier NX with: + - JetPack 4.6 (L4T 32.6.1) - GigE and USB cameras + - JetPack 4.5.1 (L4T 32.5.1) - CSI-2 cameras + +------------------------------------ +Prerequisites for CSI-2 camera users +------------------------------------ +The driver for Allied Vision CSI-2 is not included in the Linux kernel provided +by the manufacturer of the board. +Before installing Vimba, please install the driver, see: +https://github.com/alliedvision + +-------------------------------------- +Supported CSI-2 cameras and ARM boards +-------------------------------------- +Supported CSI-2 camera models and ARM boards are listed in this document: +https://alliedvision.com/fileadmin/content/documents/products/software/software/embedded/Getting_started_with_GenICam_for_CSI.pdf + +------------ +Installation +------------ +Allied Vision Vimba comes as a tarball. In order to set up Vimba, follow these steps: + + - Uncompress the archive with the command tar -xf ./Vimba.tgz to a + directory you have writing privileges for like /opt. Under this directory + Vimba will be installed in its own folder. In the following, we will refer + to this path as [InstallDir]. + - Go to [InstallDir]/VimbaGigETL and/or [InstallDir]/VimbaUSBTL and execute the shell + script Install.sh with super user privileges (e.g., sudo ./Install.sh). This + registers the GENICAM_GENTL32_PATH and/or the GENICAM_GENTL64_PATH environment + variable through a startup script in /etc/profile.d so that every GenICam GenTL + consumer (such as the examples that ship with Allied Vision Vimba) can access the + Allied Vision Gigabit Ethernet and USB Transport Layers. Please note that this is a + per-user setting. If transport layers are not found, follow the instructions in this document: + https://alliedvision.com/fileadmin/content/documents/products/software/software/Vimba/appnote/Vimba_installation_under_Linux.pdf + - Reboot computer + +Vimba Viewer: +Vimba Viewer can be found in, for example, [InstallDir]/Tools/Viewer/Bin/x86_64bit/. +This program allows you to configure your Allied Vision cameras and capture images. +Ubuntu 18.04 LTS: + - To build Vimba Viewer, install the libcanberra-gtk-module + apt-get install libcanberra-gtk-module + +Vimba includes many precompiled examples that can be found in +Vimba/VimbaC/Examples/Bin and Vimba/VimbaCPP/Examples/Bin. +If you want to compile these examples yourself, please refer to the user manual +for instructions and required packages. + +For uninstalling Vimba, remove the startup scripts by running the shell scripts +Uninstall.sh as super user. This prevents any GenTL consumer from loading the +Vimba and USB Transport Layers. Then simply remove the +installation directory. + + +------------ +Known Issues +------------ + - When experiencing trouble with image acquisition, try to increase the priority + of your application with "sudo -E nice -n -20 ". + +GigE Transport Layer: + - A change of the available camera access modes cannot be reported for cameras + in different subnets or with malconfigured IP addresses. These cameras can + be accessed in configuration mode from different hosts simultaneously. + - Not all ARM boards come with a GigE network interface. When acquiring images + with only 100 Mbit/s, make sure to set the "StreamBytesPerSecond" feature to + a reasonable small value (12 400 000). This adjustment is done automatically + when the camera is connected directly to a 100 Mbit/s interface. + +Tranport layers not found (Error -16): + - Please follow the instructions in this document: + https://alliedvision.com/fileadmin/content/documents/products/software/software/Vimba/appnote/Vimba_installation_under_Linux.pdf + + - Vimba Firmware Updater and FWUpdaterConsole.exe: + Mako-U cameras are not detected after updating the firmware. + To detect the camera, please reboot the board. + +Camera detection: + - If multiple IP addresses are configured on one physical Ethernet adapter, + then Vimba sends GVCP discovery requests only to the last added IP address. + Therefore, the camera is detected only if its IP address was added last. + +Vimba Viewer: + - If a GigE camera was opened and then closed with Vimba Viewer, + it is displayed as locked and Vimba Viewer does not open it again. + Workaround: Close and open Vimba Viewer. + - When multiple opened GigE cameras are disconnected at the same time + while no other camera stays connected to the very same NIC, + the Vimba Viewer's camera windows stay open. + - qt error: please install libpng12 if it is missing. See: + https://cdn.alliedvision.com/fileadmin/content/documents/products/software/software/Vimba/appnote/libpng-installation.pdf + - After streaming several hours, the displayed image is not updated. + Changing camera settings results in a black image. Stopping and starting image acquisition + updates the displayed image. The issue affects only the displayed image, not the image itself. + +Vimba code examples + - qt error: please install libpng12 if it is missing. See: + https://cdn.alliedvision.com/fileadmin/content/documents/products/software/software/Vimba/appnote/libpng-installation.pdf + +Vimba Documentation: + - Some apps and browsers currently don't support relative links from one + document to another document. We have successfully tested relative links + with Adobe Acrobat. + +Vimba APIs: + - When API startup and shutdown is performed excessively within the same process, + camera initialization may fail sporadically, which may cause exceptions. + We recommend to have only one API session during one process. + +CSI-2: + - Please use “alloc and announce” for best performance, see the AsynchrounousGrab example. + (C++: Program.Config.h, optional parameter /x, C: Program.c, optional parameter /x, Python: + optional parameter /x). + - Switching the camera from GenICam for CSI-2 to V4L2 or vice versa requires rebooting the board + - Exposure times greater than approx. 1 second: Stopping acquisition may cause an error. Please + close and open the camera to start streaming again. + - Executing the Device Reset GenICam command leads to camera communication failures. + - Not all ROIs work when Mono8 is applied. + - When a ROI or a different pixel format is applied and the camera is closed and opened again, image + acquisition doesn’t start in some cases. To enable image acquisition again, open the camera with + Vimba Viewer (even if you set the ROI with a third-party viewer). In some cases, rebooting + the board is necessary. + - Issues that may occur occasionally: + - AGX Xavier: Camera stays in locked state after camera handle is closed + +--------------------------- +Changes and release history +--------------------------- + +Changes in Vimba 6.0.0: +----------------------- + +VimbaC + - Fixed: Issue with null terminator for zipped XML files + +CSITL + - First release (supported camera models and ARM boards and known issues: see above) + +USBTL + - Bug fix (relevant for Windows only) + +VimbaPython: + - Less restrictive C API version check + + +Changes in Vimba 5.1.0: +----------------------- +VimbaC + - New feature: Support for Alloc And Announce frame allocation mode + - Feature endianess related fixes (corresponding to GigE TL) + +VimbaCPP + - New feature: Supports Alloc And Announce frame allocation mode + +VimbaPython + - New feature: Supports Alloc And Announce frame allocation mode + +Vimba Viewer + - Supports Alloc And Announce frame allocation mode + - Chinese localization + - Supports changes of GigE TL and VimbaC + - Fixed: IP labels not updated after changing the IP via GevCameraForceAddressSend + - Fixed: Auto ROI tab always resets ROI at startup + +Firmware Updater + - Supports Git hash representation + +Firmware Updater Console + - Supports Git hash representation + +GigETL + - Changed behaviour of endianess handling (values must match host endianness in little-endian), + for better compatibility with third-party software. + Affected features that now have a changed byte order: + - Config Mode + - IP-related features including MulticastIPAddress + - Action Commands + - New feature DeviceUpdateTimeout (only applicable if GigE discovery is switched to Broadcast) + - New GVSPMaxLookBack default value (0 instead of 1) for improved packet resend handling + - Fixed: High memory usage during performance bottleneck (Nonpaged pool growing with multiple GigE cameras) + - Fixed: Action commands caused an error message in the console log + - Fixed: Multicast IP address range, better compatibility with third-party software + +USB TL +- Updated 3rd-party libraries + + +Changes in Vimba 5.0.0: +----------------------- + +GigETL + - New feature: GVSPHostReceiveBufferSize (SO_RCVBUF) replaces GVSPHostReceiveBuffers + (which is still usable in existing applications). + - Fixed for 5 GigE cameras: + - Fixed limitations of certain GVSPPacketSize values + +VimbaC + - Fixed: Callbacks after stopping image acquisition caused exceptions + in the Python API. + - Fixed: ListAncillaryDataFeatures example (error "Could not queue frame") + +Vimba Firmware Updater + - Prepared for CSI-2 support + +Vimba Firmware Updater Console + - Prepared for CSI-2 support + +Vimba Viewer + - Prepared for CSI-2 support + + +Changes in Vimba 4.3.0: +----------------------- + +GigETL + - Prepared for use with 5 GigE Vision cameras + +VimbaC + - Prepared for use with 5 GigE Vision cameras + +VimbaCPP + - Preparations for use with 5 GigE Vision cameras in the underlying VimbaC API + +Vimba Python + - Updated for use with new VimbaC version + - Fixed: read_memory now returns all 0_bytes + +Vimba Firmware Updater + - Preparations for use with 5 GigE Vision cameras + +Vimba Firmware Updater Console + - Preparations for use with 5 GigE Vision cameras + +Vimba Viewer + - Preparations for use with 5 GigE Vision cameras + + + +Changes in Vimba 4.2.0: +----------------------- +Vimba C + - Standard-compliant ForceIP features instead of Allied Vision custom features, + Updated VimbaC ForceIP example to use the standard-compliant ForceIP features + +Vimba Python + - Redirected the used Vimba version to the one delivered in this package. + - Install.sh suggests compatible Python interpreter versions only + - Install.sh and Uninstall.sh: Added support of virtual environments, Added debug flag + +GigETL + - Standard-compliant ForceIP features instead of Allied Vision custom features (see also Vimba C) + - Prepared for use with extended IDs + +USBTL + - Increased default MaxTransferSize value for better performance with current Linux versions + - Improved camera detection on Linux systems (plugin event handling) + +Vimba Viewer + - Added a dialog for enforcing IP settings to a GigE Vision camera + + +Changes in Vimba 4.1.0: +----------------------- + +USBTL + - Solved conflicts between customers' boost version and the internally used version + - Other internal bug fixes + + +Changes in Vimba 4.0.0: +----------------------- +Vimba C + - Bug fixes + +Vimba C++ + - Bug fixes + +Vimba Python + - New API + +GigETL + - Improved resend handling + - By default, packet resends are enabled + - Other bug fixes + +USBTL + - Improved visibility of USB camera status + - Other bug fixes + +Vimba GigE Filter Driver + - Bug fixes + +Vimba Viewer + - Bug fixes + + +Changes in Vimba 3.1.0: +----------------------- +Vimba C + - Updated for use with GenTL 1.5 + +Vimba C++ + - Updated for use with GenTL 1.5 + +GigETL + - GenTL 1.5 support + +USBTL + - GenTL 1.5 support + +Vimba Viewer + - Bug fixes + + +Changes in Vimba 3.0: +----------------------- +Vimba C + - Bug fixes + +Vimba C++ + - Bug fixes + +Vimba Viewer + - Supports Alvium USB cameras + - Fixed handling of float increments + - Fixed occasional crashes with high frame rates + - Several minor bug fixes + +GigETL + - Fixed: GVSPPacketSize now updates as expected + +USBTL + - Bug fixes + +Changes in Vimba 2.1.3: +--------------------- + +Vimba C + - Added ActionCommands programming example + - Vimba C Manual: Updated documentation of Action Commands + - Prepared the API for use with GenTL 1.5 + - Bug fixes + +Vimba C++ + - Added ActionCommands programming example + - Vimba CPP Manual: Updated documentation of Action Commands + - Prepared the underlying C API for use with GenTL 1.5 + - Vimba CPP Manual: Added chapter Asynchronous image acquisition - overview + - Bug fixes + +Vimba Viewer + - New plugin architecture + +Vima Setup + - Removed Vimba Class Generator desktop symbol + +Vimba Manual + - Integrated Vimba Features Manual + + +Changes in Vimba 2.1: +--------------------- +Vimba C + - Added functionality for Action Commands. + - Bug fixes + +Vimba C++ + - Added functionality for Action Commands. + - Bug fixes + +Vimba Image Transform Library + - Support for conversion from 10-bit raw source formats to 16-bit color target formats. + - Support for conversion from 12-bit raw source formats to 16-bit color target formats. + - Support for conversion from 14-bit raw source formats to 16-bit color target formats. + - Support for conversion from 10-bit mono source formats to 16-bit mono target formats. + - Support for conversion from 12-bit mono source formats to 16-bit mono target formats. + - Support for conversion from 14-bit mono source formats to 16-bit mono target formats. + +Vimba Viewer + - Allows now saving of 12-bit and 16-bit images (12-bit images are saved in 16-bit containers). + - Added functionality for Action Commands. + - Camera list shows the IP address of each device. + - Bug fixes + +GigE Transport Layer + - The parameter BUFFER_INFO_DELIVERED_IMAGEHEIGHT is filled correctly. + - Added functionality of Action Commands. + - Bug fixes + + +Changes in Vimba 2.0: +--------------------- +Vimba Setup + - Added Vimba Viewer Guide document + - Improved documents, new layout + +Vimba C + - Added functionality of loading and saving camera settings from / to XML + - Bug fixes + +Vimba C++ + - Added functionality of loading and saving camera settings from / to XML + - Bug fixes + +Vimba Image Transform Library + - Support for conversion from BayerXX10,12 formats to 2 byte output formats (RGB[A], BGR[A]) + - Added interface functions VmbSetImageInfoFromInputParameters and VmbSetImageInfoFromInputImage + +Vimba Viewer + - Enabled making use of load / save settings functionality + - Added tabsheet widgets for Brightness, ROI, Autofunction ROI, Trigger IO, Color + - Bug fixes + +USB Transport Layer + - Minor bug fixes + +GigE Transport Layer + - Reworked and improved filter driver + +Vimba Class Generator + - Changes for Camera Link support (affects Windows only) + +Changes in Vimba 1.4.1: +----------------------- +Package for ARMv7 + - Support of USB Transport Layer + +Package for other Linux systems + - Support of USB Transport Layer + - Improved documentation + +Vimba C + - Extended camera support (e.g. float increments) + - Stability improvements + - Improved some examples + - Bug fixes + +Vimba C++ + - Extended camera support (e.g. float increments, needs Vimba C 1.4) + - Improved error handling + - Improved some examples + - Added and improved examples + - Bug fixes + +Vimba Image Transform Library + - Added support for PFNC 10p and 12p formats + - Improved the documentation + +GigE Transport Layer + - Improved stability on high traffic networks + - Bug fixes for multi-camera usage and incomplete cleanup + - Fixed range of GevHeartbeatInterval and GevHeartbeatTimeout + +Vimba Viewer + - Added open camera by ID + - Added endianness switch in direct register dialog + - Many bug fixes + +Vimba Class Generator + - Small improvements + +Changes in Vimba 1.3.0: +----------------------- +Package for ARMv7 (new) + - Support of Vimba C API + - Support of Vimba C++ API + - Support of GigE Transport Layer + +Package for other Linux systems + - Added a Vimba Tour document and a Vimba Quickstart Guide + - Improved the other documents + - Added examples for Vimba C and C++ + - Added an OpenMP version of the Vimba Image Transform Library + +Vimba C 1.3.0 + - Fixed feature access for ancillary data + - Made device discovery blocking + - Added system feature GeVDiscoveryAllDuration for adjustable waiting time + - Fixed issues with mixed feature names + - Bug-fixes for improving stability + +Vimba C++ 1.3.0 + - Fixed feature access for ancillary data + - Changes caused by bug fixes in Vimba C + +Vimba Image Transform Library 1.2.0 + - Allowed more input for VmbSetImageInfoFromString + - Corrected return codes + - Removed transformations to Mono10/12/14 and big-endian data + +Vimba Viewer 1.1.3 + - Improved handling for GigE camera list changes + - Fixed issues around saving images + - GUI usage improvements + +GigE Transport Layer 1.3.1 + - Fixed GenTL compliance: Changed the Device ID from the serial number + to a MAC-based ID. This changes the way all APIs (C, C++ and .Net) + identify the cameras + - Added a document for GigE camera features + - Changed the supported GenTL version to 1.3 (e.g. new feature categories + BufferHandlingMode and StreamInformation) + - Separate features for heartbeat timeout and heartbeat interval + - Adjustable device discovery waiting time + - Fixed issues with similar serial numbers + - Fixed issues with many network interfaces + +Vimba Class Generator + - Minor changes to appearance and documentation + +Changes in Vimba 1.2.0: +----------------------- +Vimba C 1.2.0 + - Version 1.2.0 is only compatible to AVT GigE TL Version 1.2.0 onwards + - Name independent search for AVT transport layers + - Made EnumEntries' "pIsImplemented" condition equivalent to "pIsAvailable" + to mimic the behavior of GenICam reference implementation + +Vimba C++ 1.2.0 + - Fix for opening camera by IP address + +Vimba .NET 1.2.0 + - Fix for 64bit version attempting to load 32bit transport layers + - Fix for opening camera by IP address + +Vimba Viewer 1.1.1 + - SFNC Features directly beneath the root category get listed + - Many new pixel formats available for histogram support + +GigE Transport Layer 1.2.0 + - Improved performance in case of many events + - Restriction to eight cameras removed + - Corrected Heartbeat feature + - Fixed support for small packets + + +---------------------------------------- +Allied Vision Technical Support +---------------------------------------- +Contact us: +https://www.alliedvision.com/contact diff --git a/Vimba_6_0/Documentation/Terms_and_Conditions_Vimba_Downloads-EN_1.0.1.pdf b/Vimba_6_0/Documentation/Terms_and_Conditions_Vimba_Downloads-EN_1.0.1.pdf new file mode 100644 index 0000000..fb9a547 Binary files /dev/null and b/Vimba_6_0/Documentation/Terms_and_Conditions_Vimba_Downloads-EN_1.0.1.pdf differ diff --git a/Vimba_6_0/Documentation/Vimba Manual.pdf b/Vimba_6_0/Documentation/Vimba Manual.pdf new file mode 100644 index 0000000..679cf24 Binary files /dev/null and b/Vimba_6_0/Documentation/Vimba Manual.pdf differ diff --git a/Vimba_6_0/Documentation/Vimba Quickstart Guide.pdf b/Vimba_6_0/Documentation/Vimba Quickstart Guide.pdf new file mode 100644 index 0000000..913cb1f Binary files /dev/null and b/Vimba_6_0/Documentation/Vimba Quickstart Guide.pdf differ diff --git a/Vimba_6_0/Documentation/Vimba Tour.pdf b/Vimba_6_0/Documentation/Vimba Tour.pdf new file mode 100644 index 0000000..afe8029 Binary files /dev/null and b/Vimba_6_0/Documentation/Vimba Tour.pdf differ diff --git a/Vimba_6_0/Documentation/Vimba Viewer Guide.pdf b/Vimba_6_0/Documentation/Vimba Viewer Guide.pdf new file mode 100644 index 0000000..e874363 Binary files /dev/null and b/Vimba_6_0/Documentation/Vimba Viewer Guide.pdf differ diff --git a/Vimba_6_0/Documentation/open-source-licenses.txt b/Vimba_6_0/Documentation/open-source-licenses.txt new file mode 100644 index 0000000..3146c89 --- /dev/null +++ b/Vimba_6_0/Documentation/open-source-licenses.txt @@ -0,0 +1,1783 @@ +This product contains software developed by the boost project. + +http://www.boost.org/LICENSE_1_0.txt + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- + +This product contains software developed by the Qt project. + +GNU Lesser General Public License (LGPL) + +The Qt GUI Toolkit is Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +Contact: Nokia Corporation (qt-info@nokia.com) + +Qt is available under the LGPL. + + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + [This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your + freedom to share and change it. By contrast, the GNU General Public + Licenses are intended to guarantee your freedom to share and change + free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some + specially designated software packages--typically libraries--of the + Free Software Foundation and other authors who decide to use it. You + can use it too, but we suggest you first think carefully about whether + this license or the ordinary General Public License is the better + strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, + not price. Our General Public Licenses are designed to make sure that + you have the freedom to distribute copies of free software (and charge + for this service if you wish); that you receive source code or can get + it if you want it; that you can change the software and use pieces of + it in new free programs; and that you are informed that you can do + these things. + + To protect your rights, we need to make restrictions that forbid + distributors to deny you these rights or to ask you to surrender these + rights. These restrictions translate to certain responsibilities for + you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis + or for a fee, you must give the recipients all the rights that we gave + you. You must make sure that they, too, receive or can get the source + code. If you link other code with the library, you must provide + complete object files to the recipients, so that they can relink them + with the library after making changes to the library and recompiling + it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the + library, and (2) we offer you this license, which gives you legal + permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that + there is no warranty for the free library. Also, if the library is + modified by someone else and passed on, the recipients should know + that what they have is not the original version, so that the original + author's reputation will not be affected by problems that might be + introduced by others. + + Finally, software patents pose a constant threat to the existence of + any free program. We wish to make sure that a company cannot + effectively restrict the users of a free program by obtaining a + restrictive license from a patent holder. Therefore, we insist that + any patent license obtained for a version of the library must be + consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the + ordinary GNU General Public License. This license, the GNU Lesser + General Public License, applies to certain designated libraries, and + is quite different from the ordinary General Public License. We use + this license for certain libraries in order to permit linking those + libraries into non-free programs. + + When a program is linked with a library, whether statically or using + a shared library, the combination of the two is legally speaking a + combined work, a derivative of the original library. The ordinary + General Public License therefore permits such linking only if the + entire combination fits its criteria of freedom. The Lesser General + Public License permits more lax criteria for linking other code with + the library. + + We call this license the "Lesser" General Public License because it + does Less to protect the user's freedom than the ordinary General + Public License. It also provides other free software developers Less + of an advantage over competing non-free programs. These disadvantages + are the reason we use the ordinary General Public License for many + libraries. However, the Lesser license provides advantages in certain + special circumstances. + + For example, on rare occasions, there may be a special need to + encourage the widest possible use of a certain library, so that it becomes + a de-facto standard. To achieve this, non-free programs must be + allowed to use the library. A more frequent case is that a free + library does the same job as widely used non-free libraries. In this + case, there is little to gain by limiting the free library to free + software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free + programs enables a greater number of people to use a large body of + free software. For example, permission to use the GNU C Library in + non-free programs enables many more people to use the whole GNU + operating system, as well as its variant, the GNU/Linux operating + system. + + Although the Lesser General Public License is Less protective of the + users' freedom, it does ensure that the user of a program that is + linked with the Library has the freedom and the wherewithal to run + that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and + modification follow. Pay close attention to the difference between a + "work based on the library" and a "work that uses the library". The + former contains code derived from the library, whereas the latter must + be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other + program which contains a notice placed by the copyright holder or + other authorized party saying it may be distributed under the terms of + this Lesser General Public License (also called "this License"). + Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data + prepared so as to be conveniently linked with application programs + (which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" means either the Library or any derivative work under + copyright law: that is to say, a work containing the Library or a + portion of it, either verbatim or with modifications and/or translated + straightforwardly into another language. (Hereinafter, translation is + included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for + making modifications to it. For a library, complete source code means + all the source code for all modules it contains, plus any associated + interface definition files, plus the scripts used to control compilation + and installation of the library. + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of + running a program using the Library is not restricted, and output from + such a program is covered only if its contents constitute a work based + on the Library (independent of the use of the Library in a tool for + writing it). Whether that is true depends on what the Library does + and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's + complete source code as you receive it, in any medium, provided that + you conspicuously and appropriately publish on each copy an + appropriate copyright notice and disclaimer of warranty; keep intact + all the notices that refer to this License and to the absence of any + warranty; and distribute a copy of this License along with the + Library. + + You may charge a fee for the physical act of transferring a copy, + and you may at your option offer warranty protection in exchange for a + fee. + + 2. You may modify your copy or copies of the Library or any portion + of it, thus forming a work based on the Library, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Library, + and can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work based + on the Library, the distribution of the whole must be on the terms of + this License, whose permissions for other licensees extend to the + entire whole, and thus to each and every part regardless of who wrote + it. + + Thus, it is not the intent of this section to claim rights or contest + your rights to work written entirely by you; rather, the intent is to + exercise the right to control the distribution of derivative or + collective works based on the Library. + + In addition, mere aggregation of another work not based on the Library + with the Library (or with a work based on the Library) on a volume of + a storage or distribution medium does not bring the other work under + the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public + License instead of this License to a given copy of the Library. To do + this, you must alter all the notices that refer to this License, so + that they refer to the ordinary GNU General Public License, version 2, + instead of to this License. (If a newer version than version 2 of the + ordinary GNU General Public License has appeared, then you can specify + that version instead if you wish.) Do not make any other change in + these notices. + + Once this change is made in a given copy, it is irreversible for + that copy, so the ordinary GNU General Public License applies to all + subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of + the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or + derivative of it, under Section 2) in object code or executable form + under the terms of Sections 1 and 2 above provided that you accompany + it with the complete corresponding machine-readable source code, which + must be distributed under the terms of Sections 1 and 2 above on a + medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy + from a designated place, then offering equivalent access to copy the + source code from the same place satisfies the requirement to + distribute the source code, even though third parties are not + compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the + Library, but is designed to work with the Library by being compiled or + linked with it, is called a "work that uses the Library". Such a + work, in isolation, is not a derivative work of the Library, and + therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because it + contains portions of the Library), rather than a "work that uses the + library". The executable is therefore covered by this License. + Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file + that is part of the Library, the object code for the work may be a + derivative work of the Library even though the source code is not. + Whether this is true is especially significant if the work can be + linked without the Library, or if the work is itself a library. The + threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data + structure layouts and accessors, and small macros and small inline + functions (ten lines or less in length), then the use of the object + file is unrestricted, regardless of whether it is legally a derivative + work. (Executables containing this object code plus portions of the + Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may + distribute the object code for the work under the terms of Section 6. + Any executables containing that work also fall under Section 6, + whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or + link a "work that uses the Library" with the Library to produce a + work containing portions of the Library, and distribute that work + under terms of your choice, provided that the terms permit + modification of the work for the customer's own use and reverse + engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the + Library is used in it and that the Library and its use are covered by + this License. You must supply a copy of this License. If the work + during execution displays copyright notices, you must include the + copyright notice for the Library among them, as well as a reference + directing the user to the copy of this License. Also, you must do one + of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the + Library" must include any data and utility programs needed for + reproducing the executable from it. However, as a special exception, + the materials to be distributed need not include anything that is + normally distributed (in either source or binary form) with the major + components (compiler, kernel, and so on) of the operating system on + which the executable runs, unless that component itself accompanies + the executable. + + It may happen that this requirement contradicts the license + restrictions of other proprietary libraries that do not normally + accompany the operating system. Such a contradiction means you cannot + use both them and the Library together in an executable that you + distribute. + + 7. You may place library facilities that are a work based on the + Library side-by-side in a single library together with other library + facilities not covered by this License, and distribute such a combined + library, provided that the separate distribution of the work based on + the Library and of the other library facilities is otherwise + permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute + the Library except as expressly provided under this License. Any + attempt otherwise to copy, modify, sublicense, link with, or + distribute the Library is void, and will automatically terminate your + rights under this License. However, parties who have received copies, + or rights, from you under this License will not have their licenses + terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify or + distribute the Library or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Library (or any work based on the + Library), you indicate your acceptance of this License to do so, and + all its terms and conditions for copying, distributing or modifying + the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the + Library), the recipient automatically receives a license from the + original licensor to copy, distribute, link with or modify the Library + subject to these terms and conditions. You may not impose any further + restrictions on the recipients' exercise of the rights granted herein. + You are not responsible for enforcing compliance by third parties with + this License. + + 11. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot + distribute so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you + may not distribute the Library at all. For example, if a patent + license would not permit royalty-free redistribution of the Library by + all those who receive copies directly or indirectly through you, then + the only way you could satisfy both it and this License would be to + refrain entirely from distribution of the Library. + + If any portion of this section is held invalid or unenforceable under any + particular circumstance, the balance of the section is intended to apply, + and the section as a whole is intended to apply in other circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is willing + to distribute software through any other system and a licensee cannot + impose that choice. + + This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Library under this License may add + an explicit geographical distribution limitation excluding those countries, + so that distribution is permitted only in or among countries not thus + excluded. In such case, this License incorporates the limitation as if + written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new + versions of the Lesser General Public License from time to time. + Such new versions will be similar in spirit to the present version, + but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Library + specifies a version number of this License which applies to it and + "any later version", you have the option of following the terms and + conditions either of that version or of any later version published by + the Free Software Foundation. If the Library does not specify a + license version number, you may choose any version ever published by + the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free + programs whose distribution conditions are incompatible with these, + write to the author to ask for permission. For software which is + copyrighted by the Free Software Foundation, write to the Free + Software Foundation; we sometimes make exceptions for this. Our + decision will be guided by the two goals of preserving the free status + of all derivatives of our free software and of promoting the sharing + and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO + WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. + EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR + OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE + LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME + THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY + AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU + FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE + LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING + RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A + FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF + SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + DAMAGES. + +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- + +This product contains software developed by the Qt project. + +The Qt GUI Toolkit is Copyright (C) 2015 The Qt Company Ltd. +Contact: http://www.qt.io/licensing/ + +Qt is available under the LGPL. + +http://doc.qt.io/qt-4.8/licensing.html + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +0the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- + +This product contains software developed by the CryptoPP project. + +https://www.cryptopp.com/License.txt + + +Compilation Copyright (c) 1995-2013 by Wei Dai. All rights reserved. +This copyright applies only to this software distribution package +as a compilation, and does not imply a copyright on any particular +file in the package. + +All individual files in this compilation are placed in the public domain by +Wei Dai and other contributors. + +I would like to thank the following authors for placing their works into +the public domain: + +Joan Daemen - 3way.cpp +Leonard Janke - cast.cpp, seal.cpp +Steve Reid - cast.cpp +Phil Karn - des.cpp +Andrew M. Kuchling - md2.cpp, md4.cpp +Colin Plumb - md5.cpp +Seal Woods - rc6.cpp +Chris Morgan - rijndael.cpp +Paulo Baretto - rijndael.cpp, skipjack.cpp, square.cpp +Richard De Moliner - safer.cpp +Matthew Skala - twofish.cpp +Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp +Ronny Van Keer - sha3.cpp + +The Crypto++ Library (as a compilation) is currently licensed under the Boost +Software License 1.0 (http://www.boost.org/users/license.html). + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- + +This product contains software developed by the libUSB project. + +https://github.com/libusb/libusb/wiki/FAQ#What_is_the_libusb_license + +GNU LESSER GENERAL PUBLIC LICENSE + +Version 2.1, February 1999 + +Copyright (C) 1991, 1999 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. + +This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. + +When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. + +To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. + +For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. + +We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. + +To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. + +Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. + +Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. + +When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. + +We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. + +For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. + +In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. + +Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. + +The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". + +A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. + +The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) + +"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. + +1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. + c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. + d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. + + (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. + +Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. + +This option is useful when you wish to copy part of the code of the Library into a program that is not a library. + +4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. + +If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. + +5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. + +However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. + +When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. + +If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) + +Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. + +6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. + +You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: + + a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) + b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. + c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. + d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. + e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. + +For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. + +7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. + b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. + +8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. + +10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. + +11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. + +14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- + +This product contains software developed by the miniz project. + +https://github.com/tfussell/miniz-cpp/blob/master/LICENSE + +The MIT License (MIT) + +Copyright (c) 2014 Thomas Fussell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- + +This product contains software developed by the TinyXML project. + +TinyXML is released under the zlib license: + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors +be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, +and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + + +3. This notice may not be removed or altered from any source distribution. + + +TinyXML: + +http://www.grinninglizard.com/tinyxmldocs/index.html + +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- + +This product contains software developed by the Uriparser project. + +http://uriparser.sourceforge.net/ + +uriparser - RFC 3986 URI parsing library + +Copyright (C) 2007, Weijia Song +Copyright (C) 2007, Sebastian Pipping +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * 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. + + * Neither the name of the 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 OWNER 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. + +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- + +This product contains software developed by the puff project. + +https://github.com/madler/zlib/blob/master/contrib/puff/puff.h + + Copyright (C) 2002-2013 Mark Adler, all rights reserved + version 2.3, 21 Jan 2013 + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + Mark Adler madler@alumni.caltech.edu + +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- + +This product contains software developed by the Qwt project. + +http://qwt.sourceforge.net/qwtlicense.html + + Qwt License + Version 1.0, January 1, 2003 +The Qwt library and included programs are provided under the terms +of the GNU LESSER GENERAL PUBLIC LICENSE (LGPL) with the following +exceptions: + 1. Widgets that are subclassed from Qwt widgets do not + constitute a derivative work. + 2. Static linking of applications and widgets to the + Qwt library does not constitute a derivative work + and does not require the author to provide source + code for the application or widget, use the shared + Qwt libraries, or link their applications or + widgets against a user-supplied version of Qwt. + If you link the application or widget to a modified + version of Qwt, then the changes to Qwt must be + provided under the terms of the LGPL in sections + 1, 2, and 4. + 3. You do not have to provide a copy of the Qwt license + with programs that are linked to the Qwt library, nor + do you have to identify the Qwt license in your + program or documentation as required by section 6 + of the LGPL. + However, programs must still identify their use of Qwt. + The following example statement can be included in user + documentation to satisfy this requirement: + [program/widget] is based in part on the work of + the Qwt project (http://qwt.sf.net). +---------------------------------------------------------------------- + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + Preamble + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + a) The modified work must itself be a software library. + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + NO WARRANTY + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- + +This product contains software developed by the libTIFF project. + +http://www.libtiff.org/misc.html + +Copyright (c) 1988-1997 Sam Leffler +Copyright (c) 1991-1997 Silicon Graphics, Inc. + +Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that (i) the above copyright notices and this permission notice appear in all copies of the software and related documentation, and (ii) the names of Sam Leffler and Silicon Graphics may not be used in any advertising or publicity relating to the software without the specific, prior written permission of Sam Leffler and Silicon Graphics. + +THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- + +This product contains software developed by the OpenCV project. + +http://opencv.org/license.html + +By downloading, copying, installing or using the software you agree to this license. +If you do not agree to this license, do not download, install, +copy or use the software. + + License Agreement + For Open Source Computer Vision Library + (3-clause BSD License) + +Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +Copyright (C) 2015, OpenCV Foundation, all rights reserved. +Copyright (C) 2015, Itseez Inc., all rights reserved. +Third party copyrights are property of their respective owners. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * 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. + + * Neither the names of the copyright holders nor the names of the 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 copyright holders 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. \ No newline at end of file diff --git a/Vimba_6_0/Tools/FirmwareUpdater/Bin/arm_64bit/FWUpdaterConsole b/Vimba_6_0/Tools/FirmwareUpdater/Bin/arm_64bit/FWUpdaterConsole new file mode 100755 index 0000000..b25cad5 Binary files /dev/null and b/Vimba_6_0/Tools/FirmwareUpdater/Bin/arm_64bit/FWUpdaterConsole differ diff --git a/Vimba_6_0/Tools/FirmwareUpdater/Bin/arm_64bit/VimbaFirmwareUpdater b/Vimba_6_0/Tools/FirmwareUpdater/Bin/arm_64bit/VimbaFirmwareUpdater new file mode 100755 index 0000000..89d1694 Binary files /dev/null and b/Vimba_6_0/Tools/FirmwareUpdater/Bin/arm_64bit/VimbaFirmwareUpdater differ diff --git a/Vimba_6_0/Tools/Viewer/Bin/arm_64bit/VimbaViewer b/Vimba_6_0/Tools/Viewer/Bin/arm_64bit/VimbaViewer new file mode 100755 index 0000000..b47f854 Binary files /dev/null and b/Vimba_6_0/Tools/Viewer/Bin/arm_64bit/VimbaViewer differ diff --git a/Vimba_6_0/Tools/Viewer/Bin/arm_64bit/VimbaViewer_zh.qm b/Vimba_6_0/Tools/Viewer/Bin/arm_64bit/VimbaViewer_zh.qm new file mode 100644 index 0000000..9072831 Binary files /dev/null and b/Vimba_6_0/Tools/Viewer/Bin/arm_64bit/VimbaViewer_zh.qm differ diff --git a/Vimba_6_0/Tools/VimbaClassGenerator/Bin/arm_64bit/Templates/CppTemplate.cpp b/Vimba_6_0/Tools/VimbaClassGenerator/Bin/arm_64bit/Templates/CppTemplate.cpp new file mode 100644 index 0000000..00bb47b --- /dev/null +++ b/Vimba_6_0/Tools/VimbaClassGenerator/Bin/arm_64bit/Templates/CppTemplate.cpp @@ -0,0 +1,28 @@ +/*============================================================================= +This file was generated by the VimbaClassGenerator +=============================================================================*/ + +#include "### HEADER_FILE_NAME ###" + +### CLASS_NAME ###::### CLASS_NAME ### ( + const char *pCameraID, + const char *pCameraName, + const char *pCameraModel, + const char *pCameraSerialNumber, + const char *pInterfaceID, + VmbInterfaceType interfaceType, + const char *pInterfaceName, + const char *pInterfaceSerialNumber, + VmbAccessModeType interfacePermittedAccess + ) + : Camera ( + pCameraID, + pCameraName, + pCameraModel, + pCameraSerialNumber, + pInterfaceID, + interfaceType) +{ +} + +### METHOD_IMPLEMENTATIONS ### diff --git a/Vimba_6_0/Tools/VimbaClassGenerator/Bin/arm_64bit/Templates/CppTemplate.h b/Vimba_6_0/Tools/VimbaClassGenerator/Bin/arm_64bit/Templates/CppTemplate.h new file mode 100644 index 0000000..7eed999 --- /dev/null +++ b/Vimba_6_0/Tools/VimbaClassGenerator/Bin/arm_64bit/Templates/CppTemplate.h @@ -0,0 +1,34 @@ +/*============================================================================= +This file was generated by the VimbaClassGenerator +=============================================================================*/ + +#ifndef ### HEADER_FILE_MACRO_NAME ### +#define ### HEADER_FILE_MACRO_NAME ### + +#include "VimbaCPP/Include/VimbaCPP.h" + +class ### CLASS_NAME ### : public AVT::VmbAPI::Camera +{ + public: + typedef SP_DECL( ### CLASS_NAME ### ) Ptr; + + ### ENUM_DECLARATIONS ### + + ### CLASS_NAME ### ( + const char *pCameraID, + const char *pCameraName, + const char *pCameraModel, + const char *pCameraSerialNumber, + const char *pInterfaceID, + VmbInterfaceType interfaceType, + const char *pInterfaceName, + const char *pInterfaceSerialNumber, + VmbAccessModeType interfacePermittedAccess ); + + ### METHOD_DECLARATIONS ### + + private: + ### VARIABLE_DECLARATIONS ### +}; + +#endif \ No newline at end of file diff --git a/Vimba_6_0/Tools/VimbaClassGenerator/Bin/arm_64bit/VimbaClassGenerator b/Vimba_6_0/Tools/VimbaClassGenerator/Bin/arm_64bit/VimbaClassGenerator new file mode 100755 index 0000000..ce6ead1 Binary files /dev/null and b/Vimba_6_0/Tools/VimbaClassGenerator/Bin/arm_64bit/VimbaClassGenerator differ diff --git a/Vimba_6_0/VimbaC/Documentation/Vimba C Manual.pdf b/Vimba_6_0/VimbaC/Documentation/Vimba C Manual.pdf new file mode 100644 index 0000000..51513de Binary files /dev/null and b/Vimba_6_0/VimbaC/Documentation/Vimba C Manual.pdf differ diff --git a/Vimba_6_0/VimbaC/DynamicLib/arm_64bit/VimbaC.xml b/Vimba_6_0/VimbaC/DynamicLib/arm_64bit/VimbaC.xml new file mode 100644 index 0000000..2c7ef8b --- /dev/null +++ b/Vimba_6_0/VimbaC/DynamicLib/arm_64bit/VimbaC.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/Vimba_6_0/VimbaC/Examples/ActionCommands/Build/Make/Makefile b/Vimba_6_0/VimbaC/Examples/ActionCommands/Build/Make/Makefile new file mode 100644 index 0000000..1411528 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ActionCommands/Build/Make/Makefile @@ -0,0 +1,58 @@ +PROJECT_NAME = ActionCommands + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaC.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +COMMON_DIR = $(EXAMPLES_DIR)/Common + +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBAC_LIBS) + +DEFINES = -D_LITTLE_ENDIAN + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBAC_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ActionCommands.o \ + $(OBJ_DIR)/program.o \ + $(OBJ_DIR)/PrintVimbaVersion.o \ + $(OBJ_DIR)/ErrorCodeToMessage.o \ + $(OBJ_DIR)/DiscoverGigECameras.o + +DEPENDENCIES = VimbaC + +$(OBJ_DIR)/%.o: $(COMMON_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaC/Examples/ActionCommands/Source/ActionCommands.c b/Vimba_6_0/VimbaC/Examples/ActionCommands/Source/ActionCommands.c new file mode 100644 index 0000000..8dfd586 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ActionCommands/Source/ActionCommands.c @@ -0,0 +1,912 @@ +/*============================================================================= + Copyright (C) 2021 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ActionCommands.cpp + + Description: see header file for description + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#include + +// socket library to check IP addresses +#ifdef _WIN32 + #include + #include +#else + #include +#endif + +// number of frame buffers to be used by example +#define NUM_FRAMES 3 + +// +// Frame callback, which will be called when Vimba receives a frame from the camera +// +// Parameters: +// [in] aCamera Camera handle +// [in] aFrame Received frame +// +void VMB_CALL FrameCallback( const VmbHandle_t aCamera, VmbFrame_t* aFrame ) +{ + VmbError_t lError = VmbErrorSuccess; + + // proceed only if given pointer are valid + if( (NULL != aCamera) && (NULL != aFrame) ) + { + // check if received frame is complete + if( VmbFrameStatusComplete == aFrame->receiveStatus ) + { + printf( "......Frame has been received\n" ); + } + + // re-queue received frame (buffer) to the capture queue (output buffer queue of GigE TL) + lError = VmbCaptureFrameQueue( aCamera, aFrame, &FrameCallback ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not re-queue received buffer\n" ); + } + } +} + +// +// Called when any failure occurs within the example. +// Ensures to close camera and shutdown Vimba +// +// Parameters: +// [in] aCamera Camera handle +// +void FailureShutdown( VmbHandle_t aCamera ) +{ + VmbError_t lError = VmbErrorSuccess; + + // close camera + lError = VmbCameraClose( aCamera ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not close camera. Reason: %i", lError ); + } + + printf( "......Camera has been closed\n" ); + + // shutdown Vimba + VmbShutdown(); + + printf( "......Vimba has been stopped\n" ); +} + +// +// Convert given string to IP address, +// using respective socket library (Winsock/Arpa) +// +// Parameters: +// [in] aString String to be converted +// [out] aIPAddress Decimal representation of given IP address string +// +VmbError_t ConvertStringToIPAddress( const char* aString, VmbUint32_t* aIPAddress ) +{ + VmbError_t lError = VmbErrorSuccess; + VmbUint32_t lIP = 0; + + // check parameter + if( (NULL == aString) || (NULL == aIPAddress) ) + { + printf( "[F]...Invalid parameter given.\n" ); + return VmbErrorBadParameter; + } + + // convert given string to IP struct + lIP = inet_addr( aString ); + if( -1 == lIP ) + { + lError = VmbErrorInvalidValue; + } + else + { + + #ifdef _LITTLE_ENDIAN + lIP = ntohl( lIP ); + #endif + + *aIPAddress = lIP; + } + + return lError; +} + +// +// Start Vimba and open camera with given string +// +// Parameters: +// [in] aCamera The ID or IP address of the camera to work with +// [out] aHandle Handle to camera, if opened successfully +// +VmbError_t PrepareCamera( const char* aCamera, VmbHandle_t* aHandle ) +{ + VmbError_t lError = VmbErrorSuccess; + VmbHandle_t lCameraHandle = NULL; + + // check parameter + if( (NULL == aCamera) || (NULL == aHandle) ) + { + printf( "[F]...Invalid parameter given.\n" ); + return VmbErrorBadParameter; + } + + // start Vimba + lError = VmbStartup(); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not start Vimba API. Reason: %i\n", lError ); + return lError; + } + + printf( "......Vimba has been started\n" ); + + // -check if GigE TL is present + // -set API waiting time for discovery response to 250ms + // -send discovery packet once, to all connected cameras + lError = DiscoverGigECameras(); + if( VmbErrorSuccess != lError ) + { + VmbShutdown(); + return lError; + } + + printf( "......GigE Devices have been discovered\n" ); + + // open camera with given string (could be device ID or IP address) + lError = VmbCameraOpen( aCamera, VmbAccessModeFull, &lCameraHandle ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not open camera '%s'. Reason: %i\n", aCamera, lError ); + VmbShutdown(); + return lError; + } + + printf( "......Camera has been opened (%s)\n", aCamera ); + + // return camera handle + *aHandle = lCameraHandle; + + return lError; +} + +// +// Close camera and shutdown Vimba +// +// Parameters: +// [in] aHandle Handle to camera +// +VmbError_t StopCamera( VmbHandle_t aHandle ) +{ + VmbError_t lError = VmbErrorSuccess; + + // close camera + lError = VmbCameraClose( aHandle ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not close camera. Reason: %i\n", lError ); + FailureShutdown( aHandle ); + return lError; + } + + printf( "......Camera has been closed\n" ); + + // shutdown Vimba + VmbShutdown(); + + printf( "......Vimba has been stopped\n" ); + + return lError; +} + +// +// Prepare trigger settings for given camera +// +// Parameters: +// [in] aHandle Handle to camera +// +VmbError_t PrepareTrigger( VmbHandle_t aHandle ) +{ + VmbError_t lError = VmbErrorSuccess; + + // check parameter + if( NULL == aHandle ) + { + printf( "[F]...Invalid parameter given.\n" ); + return VmbErrorBadParameter; + } + + // select FrameStart trigger via TriggerSelector feature + lError = VmbFeatureEnumSet( aHandle, "TriggerSelector", "FrameStart" ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not set TriggerSelector to FrameStart. Reason: %i", lError ); + FailureShutdown( aHandle ); + return lError; + } + + // set trigger source to Action0 + lError = VmbFeatureEnumSet( aHandle, "TriggerSource", "Action0" ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not set TriggerSource to 'Action0'. Reason: %i\nProbably this camera does not support Action Commands.\n", lError ); + FailureShutdown( aHandle ); + return lError; + } + + // enable trigger + lError = VmbFeatureEnumSet( aHandle, "TriggerMode", "On" ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not enable TriggerMode for FrameStart. Reason: %i", lError ); + FailureShutdown( aHandle ); + return lError; + } + + printf( "......Trigger FrameStart has been activated and set to Action0\n" ); + + return lError; +} + +// +// Set Action Command information to given handle. +// This could be a handle to Vimba system, interface +// or a camera handle +// +// Parameters: +// [in] aHandle Handle to either Vimba system, interface or camera +// [in] aCommand Action Command struct (device key, group key, group mask) +// +VmbError_t PrepareActionCommand( VmbHandle_t aHandle, tActionCommand* aCommand ) +{ + VmbError_t lError = VmbErrorSuccess; + + // check parameter + if( (NULL == aHandle) || (NULL == aCommand) ) + { + printf( "[F]...Invalid parameter given.\n" ); + return VmbErrorBadParameter; + } + + // set device key + lError = VmbFeatureIntSet( aHandle, "ActionDeviceKey", aCommand->mDeviceKey ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not set ActionDeviceKey. Reason: %i\n", lError ); + FailureShutdown( aHandle ); + return lError; + } + + // set group key + lError = VmbFeatureIntSet( aHandle, "ActionGroupKey", aCommand->mGroupKey ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not set ActionGroupKey. Reason: %i\n", lError ); + FailureShutdown( aHandle ); + return lError; + } + + // set group mask + lError = VmbFeatureIntSet( aHandle, "ActionGroupMask", aCommand->mGroupMask ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not set ActionGroupMask. Reason: %i\n", lError ); + FailureShutdown( aHandle ); + return lError; + } + + printf( "......Action Command has been set (%i,%i,%i)\n", aCommand->mDeviceKey, aCommand->mGroupKey, aCommand->mGroupMask ); + + return lError; +} + +// +// Prepare streaming settings in the camera, +// like allocating the buffers, start capture engine, etc. +// +// Parameters: +// [in] aHandle Handle to camera +// [in] aFrameArray Array of frames to be used for streaming +// +VmbError_t PrepareStreaming( VmbHandle_t aHandle, VmbFrame_t* aFrameArray ) +{ + VmbError_t lError = VmbErrorSuccess; + VmbBool_t lFlag = VmbBoolFalse; + VmbInt64_t lGVSPSize = 0; + VmbInt64_t lPayloadSize = 0; + int lIter = 0; + + // check parameter + if( NULL == aHandle ) + { + printf( "[F]...Invalid parameter given.\n" ); + return VmbErrorBadParameter; + } + + // set GVSP packet size to max value (MTU) + // and wait until command is done + lError = VmbFeatureCommandRun( aHandle, "GVSPAdjustPacketSize" ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not set GVSP packet size. Reason: %i\n", lError ); + FailureShutdown( aHandle ); + return lError; + } + else + { + do + { + // check if operation is done + lError = VmbFeatureCommandIsDone( aHandle, "GVSPAdjustPacketSize", &lFlag ); + if( VmbErrorSuccess != lError ) + { + break; + } + + } while( VmbBoolFalse == lFlag ); + } + + // get GVSP packet size, which was actually set in the camera + lError = VmbFeatureIntGet( aHandle, "GVSPPacketSize", &lGVSPSize ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not get GVSP packet size. Reason: %i\n", lError ); + } + + printf( "......GVSP packet size has been set to maximum (%i)\n", (int)lGVSPSize ); + + // get camera payload size (necessary for allocating the buffer memory) + lError = VmbFeatureIntGet( aHandle, "PayloadSize", &lPayloadSize ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not get payload size. Reason: %i", lError ); + FailureShutdown( aHandle ); + return lError; + } + + printf( "......Camera has payload size of '%i'\n", (int)lPayloadSize ); + + // initialize frame array with 0 + memset( aFrameArray, 0, sizeof(aFrameArray) ); + + // allocate buffer memory for each frame + for( lIter = 0; lIter < NUM_FRAMES; ++lIter ) + { + // allocate buffer + aFrameArray[lIter].buffer = (unsigned char*)malloc((VmbUint32_t)lPayloadSize); + if( NULL == aFrameArray[lIter].buffer ) + { + lError = VmbErrorResources; + break; + } + + // set buffer size + aFrameArray[lIter].bufferSize = (VmbUint32_t)lPayloadSize; + } + + // in case any failure occured, free allocated space + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Failure during memory allocation for buffers (%i/%i). Reason: %i", lIter, NUM_FRAMES, lError ); + + for( lIter = 0; lIter < NUM_FRAMES; ++lIter ) + { + free( aFrameArray[lIter].buffer ); + memset( aFrameArray, 0, sizeof(aFrameArray) ); + } + + FailureShutdown( aHandle ); + return lError; + } + + printf( "......Allocated memory for frame buffers\n" ); + + // announce frame buffers (move them to buffer input pool of GigE TL) + for( lIter = 0; lIter < NUM_FRAMES; ++lIter ) + { + lError = VmbFrameAnnounce( aHandle, &aFrameArray[lIter], sizeof(VmbFrame_t) ); + if( VmbErrorSuccess != lError ) + { + break; + } + } + + // in case any failure occured, revoke all announced frames + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Failure during announcing frame buffers (%i/%i). Reason: %i", lIter, NUM_FRAMES, lError ); + + lError = VmbFrameRevokeAll( aHandle ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not revoke all frame buffers. Reason: %i", lError ); + } + + FailureShutdown( aHandle ); + return lError; + } + + printf( "......Buffers have been announced and moved to input pool\n" ); + + // start capture engine + lError = VmbCaptureStart( aHandle ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not start capture engine. Reason: %i", lError ); + FailureShutdown( aHandle ); + return lError; + } + + printf( "......Capture engine has been started\n" ); + + // move announced frames to output buffer queue + for( lIter = 0; lIter < NUM_FRAMES; ++lIter ) + { + lError = VmbCaptureFrameQueue( aHandle, &aFrameArray[lIter], &FrameCallback ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not queue frame to output buffer queue. Reason: %i\n", lError ); + FailureShutdown( aHandle ); + return lError; + } + } + + printf( "......Buffers have been moved to output queue\n" ); + + // start acquisition in the camera + lError = VmbFeatureCommandRun( aHandle, "AcquisitionStart" ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not start camera acquisition. Reason: %i\n", lError ); + FailureShutdown( aHandle ); + return lError; + } + + printf( "......Camera acquisition has been started\n" ); + + return lError; +} + +// +// End streaming +// +// Parameters: +// [in] aHandle Handle to camera +// [in] aFrameArray Array of frames to be used for streaming +// +VmbError_t StopStreaming( VmbHandle_t aHandle, VmbFrame_t* aFrameArray ) +{ + VmbError_t lError = VmbErrorSuccess; + int lIter = 0; + + // call acquisition stop feature in camera + lError = VmbFeatureCommandRun( aHandle, "AcquisitionStop" ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not run AcquisitionStop feature. Reason: %i\n", lError ); + FailureShutdown( aHandle ); + return lError; + } + + // stop capture engine + lError = VmbCaptureEnd( aHandle ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not stop capture engine. Reason: %i\n", lError ); + FailureShutdown( aHandle ); + return lError; + } + + // flush buffer output queue + lError = VmbCaptureQueueFlush( aHandle ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not flush output buffer queue. Reason: %i\n", lError ); + FailureShutdown( aHandle ); + return lError; + } + + // revoke all announced buffers + lError = VmbFrameRevokeAll( aHandle ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not flush input buffer pool. Reason: %i\n", lError ); + FailureShutdown( aHandle ); + return lError; + } + + // free allocated space for buffers + for( lIter = 0; lIter < NUM_FRAMES; ++lIter ) + { + free( aFrameArray[lIter].buffer ); + memset( aFrameArray, 0, sizeof(aFrameArray) ); + } + + return lError; +} + +// +// Send Action Command on system level. +// This command will be broadcasted on all network interfaces. +// +// Parameters: +// [in] aCamera The ID or IP address of the camera to work with +// [in] aCommand Action Command to be set in the camera +// +VmbError_t SendActionCommandOnAllInterfaces( const char* aCamera, tActionCommand aCommand ) +{ + VmbError_t lError = VmbErrorSuccess; + VmbBool_t lFlag = VmbBoolFalse; + VmbHandle_t lCameraHandle = NULL; + VmbUint32_t lIP = 0; + int lKey = 0; + VmbFrame_t lFrames[NUM_FRAMES]; + + // check parameter + if( NULL == aCamera ) + { + printf( "[F]...Invalid parameter given!\n" ); + return VmbErrorBadParameter; + } + + // -start Vimba + // -discover GigE devices + // -open camera in full access mode and get handle + lError = PrepareCamera( aCamera, &lCameraHandle ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // -select FrameStart trigger feature + // -set source to Action0 + // -enable trigger + lError = PrepareTrigger( lCameraHandle ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // Set Action Command to camera + // -set device key + // -set group key + // -set group mask + lError = PrepareActionCommand( lCameraHandle, &aCommand ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // -adjust GVSP packet size + // -get payload size + // -allocate memory for frame buffers + // -announce frames and move them to buffer input pool + // -start capture engine + // -move frames to capture queue (buffer output queue) + // -call start acquisition feature in the camera + lError = PrepareStreaming( lCameraHandle, lFrames ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // determine if Action Command shall be send as uni- or broadcast + // if IP address was given, send it as unicast + lError = ConvertStringToIPAddress( aCamera, &lIP ); + if( VmbErrorSuccess == lError ) + { + // set IP address to Vimba + lError = VmbFeatureIntSet( gVimbaHandle, "GevActionDestinationIPAddress", lIP ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not set IP address '%s' to Vimba. Reason: %i\n", aCamera, lError ); + } + + printf( "......Action Command will be send as unicast to IP '%s (%i)'\n", aCamera, lIP ); + } + + // set Action Command to Vimba system + // -device key + // -group key + // -group mask + lError = PrepareActionCommand( gVimbaHandle, &aCommand ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not prepare Action Command. Reason: %i\n", lError ); + } + + #ifdef _WIN32 + printf( "\n<< Please hit 'a' to send prepared Action Command. To stop example hit 'q' >>\n\n" ); + #else + printf( "\n<< Please enter 'a' and return to send prepared Action Command. To stop example enter 'q' and return >>\n\n" ); + #endif + + // repeat this until user hits ESC + do + { + // wait for user input + #ifdef _WIN32 + lKey = _getch(); + #else + lKey = getchar(); + #endif + + if( 97 == lKey ) + { + + // send Action Command by calling command feature + lError = VmbFeatureCommandRun( gVimbaHandle, "ActionCommand" ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not send Action Command. Reason: %i\n", lError ); + FailureShutdown( lCameraHandle ); + return lError; + } + + printf( "......Action Command has been sent\n" ); + + } + + } while( 113 != lKey ); + + // stop streaming + lError = StopStreaming( lCameraHandle, lFrames ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // -close camera + // -shutdown Vimba + lError = StopCamera( lCameraHandle ); + + return lError; +} + +// +// Send Action Command on interface level. +// This command will be broadcasted on given network interface. +// +// Parameters: +// [in] aCamera The ID or IP address of the camera to work with +// [in] aInterface The network interface on which the Action Command +// will be sent out +// [in] aCommand Action Command to be used by Vimba and camera +// +VmbError_t SendActionCommandOnInterface( const char* aCamera, const char* aInterface, tActionCommand aCommand ) +{ + VmbError_t lError = VmbErrorSuccess; + VmbHandle_t lCameraHandle = NULL; + VmbInterfaceInfo_t* lInterfaces = NULL; + VmbUint32_t lCount = 0; + VmbHandle_t lInterfaceHandle = NULL; + VmbBool_t lFound = VmbBoolFalse; + int lInterfaceIndex = 0; + VmbUint32_t lIP = 0; + int lKey = 0; + VmbFrame_t lFrames[NUM_FRAMES]; + int lIter = 0; + + // check parameter + if( NULL == aCamera || NULL == aInterface ) + { + printf( "[F]...Invalid parameter given!\n" ); + return VmbErrorBadParameter; + } + + // -start Vimba + // -discover GigE devices + // -open camera in full access mode and get handle + lError = PrepareCamera( aCamera, &lCameraHandle ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // -select FrameStart trigger feature + // -set source to Action0 + // -enable trigger + lError = PrepareTrigger( lCameraHandle ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // Set Action Command to camera + // -set device key + // -set group key + // -set group mask + lError = PrepareActionCommand( lCameraHandle, &aCommand ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // -adjust GVSP packet size + // -get payload size + // -allocate memory for frame buffers + // -announce frames and move them to buffer input pool + // -start capture engine + // -move frames to capture queue (buffer output queue) + // -call start acquisition feature in the camera + lError = PrepareStreaming( lCameraHandle, lFrames ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // get number of available interfaces + lError = VmbInterfacesList( NULL, lCount, &lCount, 0 ); + if( (VmbErrorSuccess != lError) || (0 == lCount) ) + { + printf( "[F]...Could not retrieve number of interfaces. Reason: %i\n", lError ); + FailureShutdown( lCameraHandle ); + return lError; + } + + // allocate space for interface info list + lInterfaces = (VmbInterfaceInfo_t*)malloc( lCount * sizeof(VmbInterfaceInfo_t) ); + if( NULL == lInterfaces ) + { + printf( "[F]...Could not allocate space for interface info list.\n" ); + FailureShutdown( lCameraHandle ); + return lError; + } + + // get interface info list + lError = VmbInterfacesList( lInterfaces, lCount, &lCount, sizeof(*lInterfaces) ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not retrieve interface info list. Reason: %i\n", lError ); + FailureShutdown( lCameraHandle ); + return lError; + } + + // print interface list + printf( "......following interfaces were found:\n" ); + for( lIter = 0; lIter>\n\n" ); + #else + printf( "\n<< Please enter 'a' and return to send prepared Action Command. To stop example enter 'q' and return >>\n\n" ); + #endif + + // repeat this until user hits ESC + do + { + // wait for user input + #ifdef _WIN32 + lKey = _getch(); + #else + lKey = getchar(); + #endif + + if( 97 == lKey ) + { + + // send Action Command by calling command feature + lError = VmbFeatureCommandRun( lInterfaceHandle, "ActionCommand" ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not send Action Command. Reason: %i\n", lError ); + FailureShutdown( lCameraHandle ); + return lError; + } + + printf( "......Action Command has been sent\n" ); + + } + + } while( 113 != lKey ); + + // close interface + lError = VmbInterfaceClose( lInterfaceHandle ); + if( VmbErrorSuccess != lError ) + { + printf( "[F]...Could not close interface. Reason: %i\n", lError ); + FailureShutdown( lCameraHandle ); + return lError; + } + + // stop streaming + lError = StopStreaming( lCameraHandle, lFrames ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // -close camera + // -shutdown Vimba + lError = StopCamera( lCameraHandle ); + + return lError; +} diff --git a/Vimba_6_0/VimbaC/Examples/ActionCommands/Source/ActionCommands.h b/Vimba_6_0/VimbaC/Examples/ActionCommands/Source/ActionCommands.h new file mode 100644 index 0000000..91d2293 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ActionCommands/Source/ActionCommands.h @@ -0,0 +1,145 @@ +/*============================================================================= + Copyright (C) 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ActionCommands.h + + Description: This example will create an Action Command and send it to any + camera, given by parameter. The following can be set up with + parameters as well: + -send Action Command as broadcast on specific network interface + -send Action Command as broadcast to all network interfaces + -send Action Command to specific IP address (unicast) + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef ACTION_COMMANDS_H_ +#define ACTION_COMMANDS_H_ + +#include +#include <../../Common/DiscoverGigECameras.h> + +// struct representing an Action Command +typedef struct tActionCommand +{ + VmbUint32_t mDeviceKey; + VmbUint32_t mGroupKey; + VmbUint32_t mGroupMask; + +} tActionCommand; + +// +// Called when any failure occurs within the example. +// Ensures to close camera and shutdown Vimba +// +// Parameters: +// [in] aCamera Camera handle +// +void FailureShutdown( VmbHandle_t aCamera ); + +// +// Convert given string to IP address, +// using respective socket library (Winsock/Arpa) +// +// Parameters: +// [in] aString String to be converted +// [out] aIPAddress Decimal representation of given IP address string +// +VmbError_t ConvertStringToIPAddress( const char* aString, VmbUint32_t* aIPAddress ); + +// +// Start Vimba and open camera with given string +// +// Parameters: +// [in] aCamera The ID or IP address of the camera to work with +// [out] aHandle Handle to camera, if opened successfully +// +VmbError_t PrepareCamera( const char* aCamera, VmbHandle_t* aHandle ); + +// +// Close camera and shutdown Vimba +// +// Parameters: +// [in] aHandle Handle to camera +// +VmbError_t StopCamera( VmbHandle_t aHandle ); + +// +// Prepare trigger settings for given camera +// +// Parameters: +// [in] aHandle Handle to camera +// +VmbError_t PrepareTrigger( VmbHandle_t aHandle ); + +// +// Set Action Command information to given handle. +// This could be a handle to Vimba system, interface +// or a camera handle +// +// Parameters: +// [in] aHandle Handle to either Vimba system, interface or camera +// [in] aCommand Action Command struct (device key, group key, group mask) +// +VmbError_t PrepareActionCommand( VmbHandle_t aHandle, tActionCommand* aCommand ); + +// +// Prepare streaming settings in Vimba and the camera, +// like allocating the buffers, start capture engine, etc. +// +// Parameters: +// [in] aHandle Handle to camera +// [in] aFrameArray Array of frames to be used for streaming +// +VmbError_t PrepareStreaming( VmbHandle_t aHandle, VmbFrame_t* aFrameArray ); + +// +// End streaming +// +// Parameters: +// [in] aHandle Handle to camera +// [in] aFrameArray Array of frames to be used for streaming +// +VmbError_t StopStreaming( VmbHandle_t aHandle, VmbFrame_t* aFrameArray ); + +// +// Send Action Command on system level. +// This command will be broadcasted on all network interfaces. +// +// Parameters: +// [in] aCamera The ID or IP address of the camera to work with +// [in] aCommand Action Command to be used by Vimba and camera +// +VmbError_t SendActionCommandOnAllInterfaces( const char* aCamera, tActionCommand aCommand ); + +// +// Send Action Command on interface level. +// This command will be broadcasted on given network interface. +// +// Parameters: +// [in] aCamera The ID or IP address of the camera to work with +// [in] aInterface The network interface on which the Action Command +// will be send out +// [in] aCommand Action Command to be used by Vimba and camera +// +VmbError_t SendActionCommandOnInterface( const char* aCamera, const char* aIndex, tActionCommand aCommand ); + +#endif diff --git a/Vimba_6_0/VimbaC/Examples/ActionCommands/Source/program.c b/Vimba_6_0/VimbaC/Examples/ActionCommands/Source/program.c new file mode 100644 index 0000000..6e154e8 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ActionCommands/Source/program.c @@ -0,0 +1,101 @@ +/*============================================================================= + Copyright (C) 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: Main entry point of ActionCommands example of VimbaC. + + annotations: + -local variables are prefixed with 'l' for local + -function parameter are prefixed with 'a' for 'argument' + -structs are prefixed with 't' for 'type' + -global variables are prefixed with 'g' for 'global' + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#include +#include <../../Common/PrintVimbaVersion.h> + +#include + +// function to print out help how to use this example application +void PrintHelp() +{ + printf( "Usage: ActionCommands \n\n" ); + printf( "Parameters: CameraID ID of the camera to be used\n" ); + printf( " IPAddress IP address of camera to react on Action Command\n" ); + printf( " InterfaceID ID of network interface to send out Action Command\n" ); + printf( " 'ALL' enables broadcast on all interfaces\n\n" ); +} + +int main( int argc, char* argv[] ) +{ + VmbError_t lError = VmbErrorSuccess; + VmbUint32_t lIPAddress = 0; + tActionCommand lActionCommand; + + printf( "\n" ); + printf( "/////////////////////////////////////////\n" ); + printf( "/// Vimba API Action Commands Example ///\n" ); + printf( "/////////////////////////////////////////\n" ); + printf( "\n" ); + + // show Vimba API version + PrintVimbaVersion(); + + printf( "\n" ); + + // check number of arguments + if( 3 == argc ) + { + // define Action Command to be set in the camera + // and used by either Vimba system or interface module + lActionCommand.mDeviceKey = 1; + lActionCommand.mGroupKey = 1; + lActionCommand.mGroupMask = 1; + + // check if interface index is '-1' to send out Action Command on all interfaces + // if not, send Action Command via given network interface + if( 0 == strcmp("ALL", argv[2]) ) + { + lError = SendActionCommandOnAllInterfaces( argv[1], lActionCommand ); + } + else + { + lError = SendActionCommandOnInterface( argv[1], argv[2], lActionCommand ); + } + + } + else + { + lError = VmbErrorBadParameter; + printf( "[F]...Invalid number of parameters given!\n\n" ); + PrintHelp(); + } + + printf( "\n" ); + + return lError; +} diff --git a/Vimba_6_0/VimbaC/Examples/AsynchronousGrab/Build/Make/Makefile b/Vimba_6_0/VimbaC/Examples/AsynchronousGrab/Build/Make/Makefile new file mode 100644 index 0000000..bc925e9 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/AsynchronousGrab/Build/Make/Makefile @@ -0,0 +1,65 @@ +PROJECT_NAME = AsynchronousGrab + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaC.mk + +include $(MAKE_INCLUDE_DIR)/VimbaImageTransform.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +COMMON_DIR = $(EXAMPLES_DIR)/Common + +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBAC_LIBS) \ + $(VIMBAIMAGETRANSFORM_LIBS) \ + -lrt + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBAC_CFLAGS) \ + $(VIMBAIMAGETRANSFORM_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/AsynchronousGrab.o \ + $(OBJ_DIR)/program.o \ + $(OBJ_DIR)/PrintVimbaVersion.o \ + $(OBJ_DIR)/ErrorCodeToMessage.o \ + $(OBJ_DIR)/DiscoverGigECameras.o + +DEPENDENCIES = VimbaC \ + VimbaImageTransform + + +$(OBJ_DIR)/%.o: $(COMMON_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) diff --git a/Vimba_6_0/VimbaC/Examples/AsynchronousGrab/Source/AsynchronousGrab.c b/Vimba_6_0/VimbaC/Examples/AsynchronousGrab/Source/AsynchronousGrab.c new file mode 100644 index 0000000..5a90e33 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/AsynchronousGrab/Source/AsynchronousGrab.c @@ -0,0 +1,648 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: AsynchronousGrab.c + + Description: The AsynchronousGrab example will grab images asynchronously + using VimbaC. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#ifdef WIN32 + #include +#else + #include + #include + #include +#endif + +#include + +#include "VmbTransform.h" + +#include +#include "Common/PrintVimbaVersion.h" +#include "Common/DiscoverGigECameras.h" + + +enum +{ + NUM_FRAMES = 3 +}; + +VmbBool_t g_bVimbaStarted = VmbBoolFalse; // Remember if Vimba is started +VmbBool_t g_bStreaming = VmbBoolFalse; // Remember if Vimba is streaming +VmbBool_t g_bAcquiring = VmbBoolFalse; // Remember if Vimba is acquiring +VmbHandle_t g_CameraHandle = NULL; // A handle to our camera +VmbFrame_t g_Frames[NUM_FRAMES]; // The frames we capture into +FrameInfos g_eFrameInfos = FrameInfos_Off; // Remember if we should print out frame infos +VmbBool_t g_bRGBValue = VmbBoolFalse; // Show RGB values +VmbBool_t g_bEnableColorProcessing = VmbBoolFalse; // Enables color processing for frames +VmbBool_t g_bUseAllocAndAnnouce = VmbBoolFalse; // Enables frame alloc and announce mode +double g_dFrameTime = 0.0; // Timestamp of last frame +VmbBool_t g_bFrameTimeValid = VmbBoolFalse; // Remember if there was a last timestamp +VmbUint64_t g_nFrameID = 0; // ID of last frame +VmbBool_t g_bFrameIDValid = VmbBoolFalse; // Remember if there was a last ID +#ifdef WIN32 +double g_dFrequency = 0.0; //Frequency of tick counter in Win32 +#else +#endif + + + +#ifdef WIN32 + HANDLE g_hMutex = INVALID_HANDLE_VALUE; + + VmbBool_t CreateApiLock() + { + if( INVALID_HANDLE_VALUE != g_hMutex) + { + DestroyApiLock(); + } + g_hMutex = CreateMutex( NULL, FALSE, NULL ); + return INVALID_HANDLE_VALUE != g_hMutex; + } + void DestroyApiLock() + { + if( INVALID_HANDLE_VALUE != g_hMutex) + { + CloseHandle( g_hMutex ); + } + } + VmbBool_t AquireApiLock() + { + if( WAIT_OBJECT_0 == WaitForSingleObject( g_hMutex, INFINITE ) ) + { + return VmbBoolTrue; + } + return VmbBoolFalse; + } + void ReleaseApiLock() + { + ReleaseMutex( g_hMutex ); + } +#else + pthread_mutex_t g_Mutex = PTHREAD_MUTEX_INITIALIZER; + VmbBool_t CreateApiLock() + { + return VmbBoolTrue; + } + void DestroyApiLock() + { + } + VmbBool_t AquireApiLock() + { + if(0 == pthread_mutex_lock( &g_Mutex ) ) + { + return VmbBoolTrue; + } + return VmbBoolFalse; + } + void ReleaseApiLock() + { + pthread_mutex_unlock( &g_Mutex ); + } +#endif + + +// +// Method: ProcessFrame +// +// Purpose: convert frames to RGB24 format and apply color processing if desired +// +// Parameters: +// [in] pFrame frame to process data might be destroyed dependent on transform function used +// +VmbError_t ProcessFrame( VmbFrame_t * pFrame) +{ + VmbError_t Result = VmbErrorSuccess; // result of function + VmbUint32_t Width = 0; // will later hold the frame width + VmbUint32_t Height = 0; // will later hold the frame height + VmbImage SourceImage; // source image struct to pass to image transform + VmbImage DestinationImage; // destination image struct to pass to image transform + VmbRGB8_t* DestinationBuffer = NULL; // destination image buffer + VmbTransformInfo TransformInfo; // if desired the transform information is constructed here + VmbUint32_t TransformInfoCount = 0; // if color processing is desired this will be set + // check if we can get data + if( NULL == pFrame || NULL == pFrame->buffer ) + { + printf("%s error invalid frame\n", __FUNCTION__); + return VmbErrorBadParameter; + } + // init local variables for frame width and height + Width = pFrame->width; + Height = pFrame->height; + if( g_bEnableColorProcessing == VmbBoolTrue ) // if color processing is desired set the transform matrix + { + const static VmbFloat_t matrix[9] = { 0.0, 0.0, 1.0, // matrix to swap red and blue component + 0.0, 1.0, 0.0, + 1.0, 0.0, 0.0 }; + Result = VmbSetColorCorrectionMatrix3x3(matrix, &TransformInfo); // initialize transform info + if( VmbErrorSuccess != Result) + { + printf("%s error could not set transform matrix; Error: %d\n", __FUNCTION__, Result); + return Result; + } + TransformInfoCount = 1; + } + // set the struct size to image + SourceImage.Size = sizeof( SourceImage ); + // set the image information from the frames pixel format and size + Result = VmbSetImageInfoFromPixelFormat( pFrame->pixelFormat, Width, Height, &SourceImage ); + if( VmbErrorSuccess != Result) + { + printf( "%s error could not set source image info; Error: %d\n", __FUNCTION__, Result); + return Result; + } + // the frame buffer will be the images data buffer + SourceImage.Data = pFrame->buffer; + // set size for destination image + DestinationImage.Size = sizeof( DestinationImage ); + // set destination image info from frame size and string for RGB8 (rgb24) + Result = VmbSetImageInfoFromString( "RGB8", 4, Width, Height, &DestinationImage ); + if( VmbErrorSuccess != Result) + { + printf("%s error could not set destination image info; Error: %d\n", __FUNCTION__, Result); + return Result; + } + // allocate buffer for destination image size is width * height * size of rgb pixel + DestinationBuffer = (VmbRGB8_t*) malloc( Width*Height*sizeof( VmbRGB8_t) ); + if( NULL == DestinationBuffer) + { + printf("%s error could not allocate rgb buffer for width: %d and height: %d\n", __FUNCTION__, Width, Height); + return VmbErrorResources; + } + // set the destination buffer to the data buffer of the image + DestinationImage.Data = DestinationBuffer; + // transform source to destination if color processing was enabled TransformInfoCount is 1 otherwise TransformInfo will be ignored + Result = VmbImageTransform( &SourceImage, &DestinationImage, &TransformInfo, TransformInfoCount ); + // print first rgb pixel + printf("R: %d\tG: %d\tB: %d\n", DestinationBuffer->R, DestinationBuffer->G, DestinationBuffer->B); + // clean image buffer + free( DestinationBuffer ); + return -Result; +} + +// +// Method: GetTime +// +// Purpose: get time indicator +// +// Returns: time indicator in seconds for differential measurements +double GetTime() +{ +#ifdef WIN32 + LARGE_INTEGER nCounter; + QueryPerformanceCounter( &nCounter ); + return ( (double)nCounter.QuadPart ) / g_dFrequency; +#else + struct timespec now; + clock_gettime( CLOCK_REALTIME, &now ); + return ( (double)now.tv_sec ) + ( (double)now.tv_nsec ) / 1000000000.0; +#endif //WIN32 +} + +// +// Method: FrameCallback +// +// Purpose: called from Vimba if a frame is ready for user processing +// +// Parameters: +// +// [in] handle to camera that supplied the frame +// [in] pointer to frame structure that can hold valid data +// +void VMB_CALL FrameCallback( const VmbHandle_t cameraHandle, VmbFrame_t* pFrame ) +{ + // + // from here on the frame is under user control until returned to Vimba by re queuing it + // if you want to have smooth streaming keep the time you hold the frame short + // + VmbBool_t bShowFrameInfos = VmbBoolFalse; // showing frame infos + double dFPS = 0.0; // frames per second calculated + VmbBool_t bFPSValid = VmbBoolFalse; // indicator if fps calculation was valid + double dFrameTime = 0.0; // reference time for frames + double dTimeDiff = 0.0; // time difference between frames + VmbUint64_t nFramesMissing = 0; // number of missing frames + + // Ensure that a frame callback is not interrupted by a VmbFrameRevoke during shutdown + AquireApiLock(); + + if( FrameInfos_Off != g_eFrameInfos ) + { + if( FrameInfos_Show == g_eFrameInfos ) + { + bShowFrameInfos = VmbBoolTrue; + } + + if( VmbFrameFlagsFrameID & pFrame->receiveFlags ) + { + if( g_bFrameIDValid ) + { + if( pFrame->frameID != ( g_nFrameID + 1 ) ) + { + // get difference between current frame and last received frame to calculate missing frames + nFramesMissing = pFrame->frameID - g_nFrameID - 1; + if( 1 == nFramesMissing ) + { + printf("%s 1 missing frame detected\n", __FUNCTION__); + } + else + { + printf("%s error %llu missing frames detected\n",__FUNCTION__, nFramesMissing); + } + } + } + g_nFrameID = pFrame->frameID; // store current frame id to calculate missing frames in the next calls + g_bFrameIDValid = VmbBoolTrue; + + dFrameTime = GetTime(); // get current time to calculate frames per second + if( ( g_bFrameTimeValid ) // only if the last time was valid + && ( 0 == nFramesMissing ) ) // and the frame is not missing + { + dTimeDiff = dFrameTime - g_dFrameTime; // build time difference with last frames time + if( dTimeDiff > 0.0 ) + { + dFPS = 1.0 / dTimeDiff; + bFPSValid = VmbBoolTrue; + } + else + { + bShowFrameInfos = VmbBoolTrue; + } + } + // store time for fps calculation in the next call + g_dFrameTime = dFrameTime; + g_bFrameTimeValid = VmbBoolTrue; + } + else + { + bShowFrameInfos = VmbBoolTrue; + g_bFrameIDValid = VmbBoolFalse; + g_bFrameTimeValid = VmbBoolFalse; + } + // test if the frame is complete + if( VmbFrameStatusComplete != pFrame->receiveStatus ) + { + bShowFrameInfos = VmbBoolTrue; + } + } + + if( bShowFrameInfos ) + { + printf("Frame ID:"); + if( VmbFrameFlagsFrameID & pFrame->receiveFlags ) + { + printf( "%llu", pFrame->frameID ); + } + else + { + printf( "?" ); + } + + printf( " Status:" ); + switch( pFrame->receiveStatus ) + { + case VmbFrameStatusComplete: + printf( "Complete" ); + break; + + case VmbFrameStatusIncomplete: + printf( "Incomplete" ); + break; + + case VmbFrameStatusTooSmall: + printf( "Too small" ); + break; + + case VmbFrameStatusInvalid: + printf( "Invalid" ); + break; + + default: + printf( "?" ); + break; + } + + printf( " Size:" ); + if( VmbFrameFlagsDimension & pFrame->receiveFlags ) + { + printf( "%ux%u", pFrame->width, pFrame->height ); + } + else + { + printf( "?x?" ); + } + + printf( " Format:0x%08X", pFrame->pixelFormat ); + + printf( " FPS:" ); + if( bFPSValid ) + { + printf( "%.2f", dFPS ); + } + else + { + printf( "?" ); + } + + printf( "\n" ); + } + + if ( g_bRGBValue ) + { + // goto image processing + ProcessFrame( pFrame); + } + else if ( FrameInfos_Show != g_eFrameInfos ) + { + // Print a dot every frame + printf( "." ); + } + + fflush( stdout ); + // requeue the frame so it can be filled again + VmbCaptureFrameQueue( cameraHandle, pFrame, &FrameCallback ); + + ReleaseApiLock(); +} + +// +// Method StartContinuousImageAcquisition +// +// Purpose: starts image acquisition on a given camera +// +// Parameters: +// +// [in] pCameraId zero terminated C string with the camera id for the camera to be used +// [in] eFrameInfos enumeration value for the frame infos to show for received frames +// [in] bEnableColorProcessing toggle for enabling image processing, in this case just swapping red with blue +// [in] bUseAllocAndAnnounce toggle for enabling AllocAndAnnouce +// +// Note: Vimba has to be uninitialized and the camera has to allow access mode full +// +VmbError_t StartContinuousImageAcquisition( const char* pCameraID, FrameInfos eFrameInfos, VmbBool_t bEnableColorProcessing, VmbBool_t bRGBValue, VmbBool_t bUseAllocAndAnnounce ) +{ + VmbError_t err = VmbErrorSuccess; // The function result + VmbCameraInfo_t *pCameras = NULL; // A list of camera details + VmbUint32_t nCount = 0; // Number of found cameras + VmbUint32_t nFoundCount = 0; // Change of found cameras + VmbAccessMode_t cameraAccessMode = VmbAccessModeFull; // We open the camera with full access + VmbBool_t bIsCommandDone = VmbBoolFalse; // Has a command finished execution + VmbInt64_t nPayloadSize = 0; // The size of one frame + int i = 0; // Counting variable +#ifdef WIN32 + LARGE_INTEGER nFrequency; +#endif //WIN32 + + if( !g_bVimbaStarted ) + { + // initialize global state + g_bStreaming = VmbBoolFalse; + g_bAcquiring = VmbBoolFalse; + g_CameraHandle = NULL; + memset( g_Frames, 0, sizeof( g_Frames )); + g_dFrameTime = 0.0; + g_bFrameTimeValid = VmbBoolFalse; + g_nFrameID = 0; + g_bFrameIDValid = VmbBoolFalse; + g_eFrameInfos = eFrameInfos; + g_bRGBValue = bRGBValue; + g_bEnableColorProcessing = bEnableColorProcessing; + g_bUseAllocAndAnnouce = bUseAllocAndAnnounce; + +#ifdef WIN32 + QueryPerformanceFrequency( &nFrequency ); + g_dFrequency = (double)nFrequency.QuadPart; +#endif //WIN32 + // Startup Vimba + err = VmbStartup(); + // Print the version of Vimba + PrintVimbaVersion(); + if ( VmbErrorSuccess == err ) + { + g_bVimbaStarted = VmbBoolTrue; + + // Is Vimba connected to a GigE transport layer? + DiscoverGigECameras(); + + // If no camera ID was provided use the first camera found + if ( NULL == pCameraID ) + { + // Get the amount of known cameras + err = VmbCamerasList( NULL, 0, &nCount, sizeof *pCameras ); + if ( VmbErrorSuccess == err + && 0 != nCount ) + { + pCameras = (VmbCameraInfo_t*)malloc( nCount * sizeof( *pCameras )); + if ( NULL != pCameras ) + { + // Actually query all static details of all known cameras without having to open the cameras + // If a new camera was connected since we queried the amount of cameras (nFoundCount > nCount) we can ignore that one + err = VmbCamerasList( pCameras, nCount, &nFoundCount, sizeof *pCameras ); + if ( VmbErrorSuccess != err + && VmbErrorMoreData != err ) + { + printf( "%s Could not list cameras. Error code: %d\n", __FUNCTION__, err ); + } + else + { + // Use the first camera + if( nFoundCount != 0) + { + pCameraID = pCameras[0].cameraIdString; + } + else + { + err = VmbErrorNotFound; + printf( "%s camera lost. Error code: %d\n", __FUNCTION__, err ); + pCameraID = NULL; + } + } + + free( pCameras ); + pCameras = NULL; + } + else + { + printf( "%s Could not allocate camera list.\n", __FUNCTION__ ); + } + } + else + { + printf( "%s Could not list cameras or no cameras present. Error code: %d\n", __FUNCTION__, err ); + } + } + + if ( NULL != pCameraID ) + { + // Open camera + err = VmbCameraOpen( pCameraID, cameraAccessMode, &g_CameraHandle ); + if ( VmbErrorSuccess == err ) + { + printf("Opening camera with ID: %s\n", pCameraID); + + // Set the GeV packet size to the highest possible value + // (In this example we do not test whether this cam actually is a GigE cam) + if ( VmbErrorSuccess == VmbFeatureCommandRun( g_CameraHandle, "GVSPAdjustPacketSize" )) + { + do + { + if ( VmbErrorSuccess != VmbFeatureCommandIsDone( g_CameraHandle, + "GVSPAdjustPacketSize", + &bIsCommandDone )) + { + break; + } + } while ( VmbBoolFalse == bIsCommandDone ); + } + + if ( VmbErrorSuccess == err ) + { + // Evaluate frame size + err = VmbFeatureIntGet( g_CameraHandle, "PayloadSize", &nPayloadSize ); + if ( VmbErrorSuccess == err ) + { + for(i = 0; i < NUM_FRAMES; i++) + { + g_Frames[i].buffer = ( g_bUseAllocAndAnnouce ) ? NULL : (unsigned char*)malloc( (VmbUint32_t)nPayloadSize ); + g_Frames[i].bufferSize = (VmbUint32_t)nPayloadSize; + + // Announce Frame + err = VmbFrameAnnounce( g_CameraHandle, &g_Frames[i], (VmbUint32_t)sizeof( VmbFrame_t )); + if ( VmbErrorSuccess != err ) + { + free( g_Frames[i].buffer ); + memset( &g_Frames[i], 0, sizeof( VmbFrame_t )); + break; + } + } + + if ( VmbErrorSuccess == err ) + { + // Start Capture Engine + err = VmbCaptureStart( g_CameraHandle ); + if ( VmbErrorSuccess == err ) + { + g_bStreaming = VmbBoolTrue; + for( i = 0; i < NUM_FRAMES; i++ ) + { + // Queue Frame + err = VmbCaptureFrameQueue( g_CameraHandle, &g_Frames[i], &FrameCallback ); + if ( VmbErrorSuccess != err ) + { + break; + } + } + + if ( VmbErrorSuccess == err ) + { + // Start Acquisition + err = VmbFeatureCommandRun( g_CameraHandle,"AcquisitionStart" ); + if ( VmbErrorSuccess == err ) + { + g_bAcquiring = VmbBoolTrue; + } + } + } + } + } + } + } + } + + if( VmbErrorSuccess != err ) + { + StopContinuousImageAcquisition(); + } + } + } + else + { + err = VmbErrorOther; + } + + return err; +} + +// +// Method: StopContinuousImageAcquisition +// +// Purpose: stops image acquisition that was started with StartContinuousImageAcquisition +// +void StopContinuousImageAcquisition() +{ + int i = 0; + + if( g_bVimbaStarted ) + { + if( NULL != g_CameraHandle ) + { + if( g_bAcquiring ) + { + // Stop Acquisition + VmbFeatureCommandRun( g_CameraHandle, "AcquisitionStop" ); + g_bAcquiring = VmbBoolFalse; + } + + if( g_bStreaming ) + { + // Stop Capture Engine + VmbCaptureEnd( g_CameraHandle ); + g_bStreaming = VmbBoolFalse; + } + + // Flush the capture queue + VmbCaptureQueueFlush( g_CameraHandle ); + + // Ensure that revoking is not interrupted by a dangling frame callback + AquireApiLock(); + for( i = 0; i < NUM_FRAMES; i++ ) + { + if( NULL != g_Frames[i].buffer ) + { + VmbFrameRevoke( g_CameraHandle, &g_Frames[i] ); + if ( !g_bUseAllocAndAnnouce ) + { + free( g_Frames[i].buffer ); + memset( &g_Frames[i], 0, sizeof( VmbFrame_t )); + } + } + } + ReleaseApiLock(); + // Close camera + VmbCameraClose ( g_CameraHandle ); + g_CameraHandle = NULL; + } + VmbShutdown(); + g_bVimbaStarted = VmbBoolFalse; +#ifdef WIN32 + CloseHandle( g_hMutex ); +#else + pthread_mutex_destroy(&g_Mutex); +#endif + } +} + diff --git a/Vimba_6_0/VimbaC/Examples/AsynchronousGrab/Source/AsynchronousGrab.h b/Vimba_6_0/VimbaC/Examples/AsynchronousGrab/Source/AsynchronousGrab.h new file mode 100644 index 0000000..7c4da64 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/AsynchronousGrab/Source/AsynchronousGrab.h @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (C) 2012 - 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: AsynchronousGrab.h + + Description: The AsynchronousGrab example will grab images asynchronously + using VimbaC. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef ASYNCHRONOUS_GRAB_H_ +#define ASYNCHRONOUS_GRAB_H_ + +#include + +typedef enum FrameInfos +{ + FrameInfos_Off, + FrameInfos_Show, + FrameInfos_Automatic +} FrameInfos; + +VmbError_t StartContinuousImageAcquisition( const char* pCameraID, FrameInfos eFrameInfos, VmbBool_t bEnableColorProcessing, VmbBool_t bRGBValue, VmbBool_t bUseAllocAndAnnounce ); +void StopContinuousImageAcquisition(); + +VmbBool_t CreateApiLock(); +void DestroyApiLock(); +VmbBool_t AquireApiLock(); +void ReleaseApiLock(); + + +#endif diff --git a/Vimba_6_0/VimbaC/Examples/AsynchronousGrab/Source/program.c b/Vimba_6_0/VimbaC/Examples/AsynchronousGrab/Source/program.c new file mode 100644 index 0000000..1f1edb7 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/AsynchronousGrab/Source/program.c @@ -0,0 +1,214 @@ +/*============================================================================= + Copyright (C) 2013 - 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.c + + Description: Implementation of main entry point of AsynchronousGrab example + of VimbaC. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include + +#include +#include "Common/ErrorCodeToMessage.h" + +#ifdef WIN32 +#include +BOOL WINAPI consoleHandler( DWORD signal) +{ + switch( signal) + { + case CTRL_C_EVENT: + case CTRL_CLOSE_EVENT: + AquireApiLock(); + VmbShutdown(); + ReleaseApiLock(); + } + return TRUE; +} + +#endif + +int main( int argc, char* argv[] ) +{ + VmbError_t err = VmbErrorSuccess; + + char* pCameraID = NULL; // The ID of the camera to use + FrameInfos eFrameInfos = FrameInfos_Off; // Show frame infos + VmbBool_t bRGBValue = VmbBoolFalse; // Show RGB values + VmbBool_t bEnableColorProcessing = VmbBoolFalse; // Enables color processing of frames + VmbBool_t bUseAllocAndAnnounce = VmbBoolFalse; // Enables use of AllocAndAnnounce + unsigned char bPrintHelp = 0; // Output help? + int i = 0; // Counter for some iteration + char* pParameter = NULL; // The command line parameter + CreateApiLock(); +#ifdef WIN32 + SetConsoleCtrlHandler(consoleHandler,TRUE); +#endif + + printf( "///////////////////////////////////////////\n" ); + printf( "/// Vimba API Asynchronous Grab Example ///\n" ); + printf( "///////////////////////////////////////////\n\n" ); + + ////////////////////// + //Parse command line// + ////////////////////// + + for( i = 1; i < argc; ++i ) + { + pParameter = argv[i]; + if( 0 > strlen( pParameter )) + { + err = VmbErrorBadParameter; + break; + } + + if( '/' == pParameter[0] ) + { + if( 0 == strcmp( pParameter, "/i" )) + { + if( ( FrameInfos_Off != eFrameInfos ) + || ( bPrintHelp )) + { + err = VmbErrorBadParameter; + break; + } + + eFrameInfos = FrameInfos_Show; + } + else if( 0 == strcmp( pParameter, "/r" )) + { + if( bPrintHelp ) + { + err = VmbErrorBadParameter; + break; + } + + bRGBValue = VmbBoolTrue; + } + else if( 0 == strcmp( pParameter, "/c" )) + { + if ( bPrintHelp ) + { + err = VmbErrorBadParameter; + break; + } + + bEnableColorProcessing = VmbBoolTrue; + bRGBValue = VmbBoolTrue; + } + else if( 0 == strcmp( pParameter, "/a" )) + { + if( ( FrameInfos_Off != eFrameInfos ) + || ( bPrintHelp )) + { + err = VmbErrorBadParameter; + break; + } + + eFrameInfos = FrameInfos_Automatic; + } + else if( 0 == strcmp( pParameter, "/x" )) + { + if ( bPrintHelp ) + { + err = VmbErrorBadParameter; + break; + } + + bUseAllocAndAnnounce = VmbBoolTrue; + } + else if( 0 == strcmp( pParameter, "/h" )) + { + if( ( NULL != pCameraID ) + || ( bPrintHelp ) + || ( VmbBoolFalse != bEnableColorProcessing ) + || ( VmbBoolFalse != bRGBValue ) + || ( FrameInfos_Off != eFrameInfos )) + { + err = VmbErrorBadParameter; + break; + } + + bPrintHelp = 1; + } + else + { + err = VmbErrorBadParameter; + break; + } + } + else + { + if( NULL != pCameraID ) + { + err = VmbErrorBadParameter; + break; + } + + pCameraID = pParameter; + } + } + + //Write out an error if we could not parse the command line + if ( VmbErrorBadParameter == err ) + { + printf( "Invalid parameters!\n\n" ); + bPrintHelp = 1; + } + + //Print out help and end program + if ( bPrintHelp ) + { + printf( "Usage: AsynchronousGrab [CameraID] [/i] [/h]\n" ); + printf( "Parameters: CameraID ID of the camera to use (using first camera if not specified)\n" ); + printf( " /r Convert to RGB and show RGB values\n" ); + printf( " /c Enable color processing (includes /r)\n" ); + printf( " /i Show frame infos\n" ); + printf( " /a Automatically only show frame infos of corrupt frames\n" ); + printf( " /x Use AllocAndAnnounceFrame instead of AnnounceFrame\n" ); + printf( " /h Print out help\n" ); + } + else + { + err = StartContinuousImageAcquisition( pCameraID, eFrameInfos, bEnableColorProcessing, bRGBValue , bUseAllocAndAnnounce); + if ( VmbErrorSuccess == err ) + { + printf( "Press to stop acquisition...\n" ); + getchar(); + + StopContinuousImageAcquisition(); + } + + if ( VmbErrorSuccess == err ) + { + printf( "\nAcquisition stopped.\n" ); + } + else + { + printf( "\nAn error occurred: %s\n", ErrorCodeToMessage( err ) ); + } + } + ReleaseApiLock(); + return err; +} diff --git a/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ActionCommands b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ActionCommands new file mode 100755 index 0000000..a690de3 Binary files /dev/null and b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ActionCommands differ diff --git a/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/AsynchronousGrab b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/AsynchronousGrab new file mode 100755 index 0000000..d4d4575 Binary files /dev/null and b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/AsynchronousGrab differ diff --git a/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ForceIP b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ForceIP new file mode 100755 index 0000000..e0ff84e Binary files /dev/null and b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ForceIP differ diff --git a/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ListAncillaryDataFeatures b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ListAncillaryDataFeatures new file mode 100755 index 0000000..33ab94a Binary files /dev/null and b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ListAncillaryDataFeatures differ diff --git a/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ListCameras b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ListCameras new file mode 100755 index 0000000..c80f141 Binary files /dev/null and b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ListCameras differ diff --git a/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ListFeatures b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ListFeatures new file mode 100755 index 0000000..3a670cb Binary files /dev/null and b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/ListFeatures differ diff --git a/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/LoadSaveSettings b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/LoadSaveSettings new file mode 100755 index 0000000..2fcc83f Binary files /dev/null and b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/LoadSaveSettings differ diff --git a/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/SynchronousGrab b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/SynchronousGrab new file mode 100755 index 0000000..a079173 Binary files /dev/null and b/Vimba_6_0/VimbaC/Examples/Bin/arm_64bit/SynchronousGrab differ diff --git a/Vimba_6_0/VimbaC/Examples/Build/Make/Common.mk b/Vimba_6_0/VimbaC/Examples/Build/Make/Common.mk new file mode 100644 index 0000000..a727c58 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/Build/Make/Common.mk @@ -0,0 +1,100 @@ +UNAME = $(shell uname -m) + +ifeq ($(UNAME),i386) +ARCH = x86 +AUTOWORDSIZE = 32 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),i486) +ARCH = x86 +AUTOWORDSIZE = 32 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),i586) +ARCH = x86 +AUTOWORDSIZE = 32 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),i686) +ARCH = x86 +AUTOWORDSIZE = 32 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),x86_64) +ARCH = x86 +AUTOWORDSIZE = 64 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),amd64) +ARCH = x86 +AUTOWORDSIZE = 64 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),armv6l) +ARCH = arm +AUTOWORDSIZE = 32 +AUTOFLOATABI = soft +endif +ifeq ($(UNAME),armv7l) +ARCH = arm +AUTOWORDSIZE = 32 +AUTOFLOATABI = soft +endif +ifeq ($(UNAME),aarch64) +ARCH = arm +AUTOWORDSIZE = 64 +AUTOFLOATABI = hard +endif + +#Possible word sizes: 32, 64 +WORDSIZE = $(AUTOWORDSIZE) +#Possible float abis: soft, hard +FLOATABI = $(AUTOFLOATABI) + +ifneq ($(WORDSIZE),32) +ifneq ($(WORDSIZE),64) +$(error Invalid word size set) +endif +endif + +ifneq ($(FLOATABI),soft) +ifneq ($(FLOATABI),hard) +ifneq ($(FLOATABI),ignore) +$(error Invalid float abi set) +endif +endif +endif + +#Common tools +PKGCFG = pkg-config +MKDIR = mkdir +RM = rm +CXX = g++ +MAKE = make +CP = cp + +#Set word size on x86 +ifeq ($(ARCH),x86) +ARCH_CFLAGS = -m$(WORDSIZE) +endif + +#Configure compiler and linker for soft or hard-float build on ARM +ifeq ($(ARCH),arm) +ifeq ($(FLOATABI),soft) +ARCH_CFLAGS = -marm -mfloat-abi=soft -march=armv4t +else ifeq ($(FLOATABI),hard) +ifeq ($(WORDSIZE),32) +ARCH_CFLAGS = -mthumb -mfloat-abi=hard -march=armv7 +else ifeq ($(WORDSIZE),64) +ARCH_CFLAGS = -march=armv8-a +endif +endif +endif + +ifeq ($(CONFIG),Debug) + CONFIG_CFLAGS = -O0 -g +else + CONFIG_CFLAGS = -O3 +endif + +COMMON_CFLAGS = $(CONFIG_CFLAGS) $(ARCH_CFLAGS) -fPIC diff --git a/Vimba_6_0/VimbaC/Examples/Build/Make/Makefile b/Vimba_6_0/VimbaC/Examples/Build/Make/Makefile new file mode 100644 index 0000000..0d6473c --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/Build/Make/Makefile @@ -0,0 +1,23 @@ +EXAMPLES_DIR = ../.. +MAKE_INCLUDE_DIR = $(CURDIR) + +include $(MAKE_INCLUDE_DIR)/Common.mk + +EXAMPLES = ActionCommands \ + AsynchronousGrab \ + ForceIP \ + ListCameras \ + ListFeatures \ + ListAncillaryDataFeatures \ + SynchronousGrab \ + LoadSaveSettings + +make_%: $(EXAMPLES_DIR)/%/Build/Make/Makefile + $(MAKE) -C $(EXAMPLES_DIR)/$*/Build/Make + +clean_%: $(EXAMPLES_DIR)/%/Build/Make/Makefile + $(MAKE) -C $(EXAMPLES_DIR)/$*/Build/Make clean + +all: $(foreach example,$(EXAMPLES),make_$(example)) + +clean: $(foreach example,$(EXAMPLES),clean_$(example)) diff --git a/Vimba_6_0/VimbaC/Examples/Build/Make/VimbaC.mk b/Vimba_6_0/VimbaC/Examples/Build/Make/VimbaC.mk new file mode 100644 index 0000000..d8bdb00 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/Build/Make/VimbaC.mk @@ -0,0 +1,14 @@ +include $(MAKE_INCLUDE_DIR)/Common.mk + +#Compile options needed for VimbaC +VIMBAC_CFLAGS = -I$(VIMBASDK_DIR) + +#Linker options needed for VimbaC +VIMBAC_LIBS = -L$(BIN_DIR) -lVimbaC + +#By default we copy libVimbaC.so next to the binary +$(BIN_DIR)/libVimbaC.so: $(BIN_DIR) + $(CP) $(VIMBASDK_DIR)/VimbaC/DynamicLib/$(ARCH)_$(WORDSIZE)bit/libVimbaC.so $(BIN_DIR)/ + +#Operations we have to do in order to prepare VimbaC +VimbaC: $(BIN_DIR)/libVimbaC.so diff --git a/Vimba_6_0/VimbaC/Examples/Build/Make/VimbaImageTransform.mk b/Vimba_6_0/VimbaC/Examples/Build/Make/VimbaImageTransform.mk new file mode 100644 index 0000000..42ab9e6 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/Build/Make/VimbaImageTransform.mk @@ -0,0 +1,14 @@ +include $(MAKE_INCLUDE_DIR)/Common.mk + +#Compile options needed for VimbaImageTransform +VIMBAIMAGETRANSFORM_CFLAGS = -I$(VIMBASDK_DIR)/VimbaImageTransform/Include + +#Compile options needed for VimbaImageTransform +VIMBAIMAGETRANSFORM_LIBS = -L$(BIN_DIR) -lVimbaImageTransform -Wl,-rpath-link,$(BIN_DIR) + +#By default we copy libVimbaImageTransform.so next to the binary +$(BIN_DIR)/libVimbaImageTransform.so: $(BIN_DIR) + $(CP) $(VIMBASDK_DIR)/VimbaImageTransform/DynamicLib/$(ARCH)_$(WORDSIZE)bit/libVimbaImageTransform.so $(BIN_DIR)/ + +#Operations we have to do in order to prepare VimbaImageTransform +VimbaImageTransform: $(BIN_DIR)/libVimbaImageTransform.so diff --git a/Vimba_6_0/VimbaC/Examples/Common/DiscoverGigECameras.c b/Vimba_6_0/VimbaC/Examples/Common/DiscoverGigECameras.c new file mode 100644 index 0000000..3abce96 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/Common/DiscoverGigECameras.c @@ -0,0 +1,73 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: DiscoverGigECameras.c + + Description: Discover GigE cameras if GigE TL is present. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#ifdef WIN32 +#include +#else +#include +#endif + +#include + +#include "DiscoverGigECameras.h" + + +// Purpose: Discovers GigE cameras if GigE TL is present. +// Discovery is switched on only once so that the API can detect all currently connected cameras. +VmbError_t DiscoverGigECameras() +{ + VmbError_t err = VmbErrorSuccess; + VmbBool_t isGigE = VmbBoolFalse; + + err = VmbFeatureBoolGet( gVimbaHandle, "GeVTLIsPresent", &isGigE ); // Is Vimba connected to a GigE transport layer? + if ( VmbErrorSuccess == err ) + { + if( VmbBoolTrue == isGigE ) + { + err = VmbFeatureIntSet( gVimbaHandle, "GeVDiscoveryAllDuration", 250 ); // Set the waiting duration for discovery packets to return. If not set the default of 150 ms is used. + if( VmbErrorSuccess == err ) + { + err = VmbFeatureCommandRun( gVimbaHandle, "GeVDiscoveryAllOnce" ); // Send discovery packets to GigE cameras and wait 250 ms until they are answered + if( VmbErrorSuccess != err ) + { + printf( "Could not ping GigE cameras over the network. Reason: %d\n", err ); + } + } + else + { + printf( "Could not set the discovery waiting duration. Reason: %d\n", err ); + } + } + } + else + { + printf( "Could not query Vimba for the presence of a GigE transport layer. Reason: %d\n\n", err ); + } + + return err; +} diff --git a/Vimba_6_0/VimbaC/Examples/Common/DiscoverGigECameras.h b/Vimba_6_0/VimbaC/Examples/Common/DiscoverGigECameras.h new file mode 100644 index 0000000..f26225f --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/Common/DiscoverGigECameras.h @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: DiscoverGigECameras.h + + Description: Discover GigE cameras if GigE TL is present. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef DISCOVER_GIGE_CAMERAS_H_ +#define DISCOVER_GIGE_CAMERAS_H_ + +#include + +// Purpose: Discovers GigE cameras if GigE TL is present. +// Discovery is switched on only once so that the API can detect all currently connected cameras. +VmbError_t DiscoverGigECameras(); + +#endif diff --git a/Vimba_6_0/VimbaC/Examples/Common/ErrorCodeToMessage.c b/Vimba_6_0/VimbaC/Examples/Common/ErrorCodeToMessage.c new file mode 100644 index 0000000..0919e23 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/Common/ErrorCodeToMessage.c @@ -0,0 +1,66 @@ +/*============================================================================= + Copyright (C) 2014 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ErrorCodeToMessage.h + + Description: Convert the error codes to a self-explanatory message. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 "ErrorCodeToMessage.h" + +// +// Translates Vimba error codes to readable error messages +// +// Parameters: +// [in] eError The error code to be converted to string +// +// Returns: +// A descriptive string representation of the error code +// +const char* ErrorCodeToMessage( VmbError_t eError ) +{ + + switch(eError) + { + case VmbErrorSuccess: return "Success."; + case VmbErrorInternalFault: return "Unexpected fault in VmbApi or driver."; + case VmbErrorApiNotStarted: return "API not started."; + case VmbErrorNotFound: return "Not found."; + case VmbErrorBadHandle: return "Invalid handle "; + case VmbErrorDeviceNotOpen: return "Device not open."; + case VmbErrorInvalidAccess: return "Invalid access."; + case VmbErrorBadParameter: return "Bad parameter."; + case VmbErrorStructSize: return "Wrong DLL version."; + case VmbErrorMoreData: return "More data returned than memory provided."; + case VmbErrorWrongType: return "Wrong type."; + case VmbErrorInvalidValue: return "Invalid value."; + case VmbErrorTimeout: return "Timeout."; + case VmbErrorOther: return "TL error."; + case VmbErrorResources: return "Resource not available."; + case VmbErrorInvalidCall: return "Invalid call."; + case VmbErrorNoTL: return "TL not loaded."; + case VmbErrorNotImplemented: return "Not implemented."; + case VmbErrorNotSupported: return "Not supported."; + default: return "Unknown"; + } +} + diff --git a/Vimba_6_0/VimbaC/Examples/Common/ErrorCodeToMessage.h b/Vimba_6_0/VimbaC/Examples/Common/ErrorCodeToMessage.h new file mode 100644 index 0000000..95c5a86 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/Common/ErrorCodeToMessage.h @@ -0,0 +1,44 @@ +/*============================================================================= + Copyright (C) 2014 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ErrorCodeToMessage.h + + Description: Convert the error codes to a self-explanatory message. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef ERROR_CODE_TO_MESSAGE_H_ +#define ERROR_CODE_TO_MESSAGE_H_ + +#include "VimbaC/Include/VimbaC.h" + +// +// Translates Vimba error codes to readable error messages +// +// Parameters: +// [in] eError The error code to be converted to string +// +// Returns: +// A descriptive string representation of the error code +// +const char* ErrorCodeToMessage( VmbError_t eError ); + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaC/Examples/Common/PrintVimbaVersion.c b/Vimba_6_0/VimbaC/Examples/Common/PrintVimbaVersion.c new file mode 100644 index 0000000..9627ece --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/Common/PrintVimbaVersion.c @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (C) 2014 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: PrintVimbaVersion.h + + Description: Print Vimba version. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 "PrintVimbaVersion.h" +#include +#include + +// +// Prints out the version of the Vimba API +// +void PrintVimbaVersion() +{ + VmbVersionInfo_t version_info; + VmbError_t result = VmbVersionQuery( &version_info, sizeof( version_info )); + if( VmbErrorSuccess == result) + { + printf( "Vimba Version Major: %u Minor: %u Patch: %u\n", version_info.major, version_info.minor,version_info.patch ); + } + else + { + printf( "VmbVersionQuery failed with Reason: %x\n", result ); + } +} + + diff --git a/Vimba_6_0/VimbaC/Examples/Common/PrintVimbaVersion.h b/Vimba_6_0/VimbaC/Examples/Common/PrintVimbaVersion.h new file mode 100644 index 0000000..a348211 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/Common/PrintVimbaVersion.h @@ -0,0 +1,36 @@ +/*============================================================================= + Copyright (C) 2014 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: PrintVimbaVersion.h + + Description: Print Vimba version. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef PRINT_VIMBA_VERSION_H_ +#define PRINT_VIMBA_VERSION_H_ + +// +// Prints out the version of the Vimba API +// +void PrintVimbaVersion(); + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaC/Examples/ForceIP/Build/Make/Makefile b/Vimba_6_0/VimbaC/Examples/ForceIP/Build/Make/Makefile new file mode 100644 index 0000000..d5c3069 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ForceIP/Build/Make/Makefile @@ -0,0 +1,58 @@ +PROJECT_NAME = ForceIP + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaC.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +COMMON_DIR = $(EXAMPLES_DIR)/Common + +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBAC_LIBS) + +DEFINES = -D_LITTLE_ENDIAN + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBAC_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ForceIP.o \ + $(OBJ_DIR)/program.o \ + $(OBJ_DIR)/PrintVimbaVersion.o \ + $(OBJ_DIR)/ErrorCodeToMessage.o \ + $(OBJ_DIR)/DiscoverGigECameras.o + +DEPENDENCIES = VimbaC + +$(OBJ_DIR)/%.o: $(COMMON_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) diff --git a/Vimba_6_0/VimbaC/Examples/ForceIP/Source/ForceIP.c b/Vimba_6_0/VimbaC/Examples/ForceIP/Source/ForceIP.c new file mode 100644 index 0000000..14a91d0 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ForceIP/Source/ForceIP.c @@ -0,0 +1,232 @@ +/*============================================================================= + Copyright (C) 2013 - 2020 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ForceIP.h + + Description: The ForceIP example will assign an IP address to a camera + that is identified by its MAC address. It utilizes only + GenTL features. This approach is useful when a camera has + an invalid IP configuration and cannot be accessed through + the network anymore. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include + +#ifdef WIN32 + #include +#else + #include + #include +#endif + +#include + +#include +#include "../../Common/PrintVimbaVersion.h" + +// +// Converts a hexadecimal MAC address into its decimal representation. +// Leaves decimal addresses untouched. +// +// Parameters: +// [in] strMAC The hexadecimal (with preceding 0x) or decimal MAC +// address to be converted to decimal. As string. +// +// Returns: +// 0 in case of error +// The decimal representation of the MAC address on success as integer +// +unsigned long long mac_addr( const char* strMAC ) +{ + unsigned long long nMAC; + + if ( sscanf( strMAC, "0x%llx", &nMAC ) + || sscanf( strMAC, "%lld", &nMAC )) + { + return nMAC; + } + else + { + return 0; + } +} + +// Converts a IP address string into its decimal representation. +// +// Parameters: +// [in] strIP The string representation of the IP +// +// Returns: +// The decimal representation of the IP address as integer. +// +unsigned int ip_addr( const char* strIP ) +{ + unsigned long ip = inet_addr( strIP ); + + #ifdef _LITTLE_ENDIAN + ip = ntohl( ip ); + #endif + + return ip; +} + +// Sleeps for the given seconds. +// +// Parameters: +// [in] seconds The number of seconds to sleep +// +void SleepForSeconds( const unsigned int seconds) +{ + #ifdef WIN32 + Sleep(1000 * seconds); + #else + sleep(seconds); + #endif +} + + +// +// Starts Vimba API +// Seeks a GigE camera by its MAC address on the network +// Sets the found camera's +// - IP address +// - subnet mask +// - gateway +// +// Parameters: +// [in] strMAC The MAC address of the camera to work on in decimal +// or hex (with preceding 0x) representation +// [in] strIP The desired IP address for the camera +// [in] strSubnet The desired subnet mask of the IP address +// [in] strGateway The desired gateway. Optional, can be 0 +// +void ForceIP( char* strMAC, char* strIP, char* strSubnet, char* strGateway ) +{ + VmbError_t err = VmbErrorSuccess; + VmbBool_t bIsGigE = 0; + VmbHandle_t hCam = NULL; + unsigned long long nMAC = 0; + unsigned long nIP = 0; + unsigned long nSubnet = 0; + unsigned long nGateway = 0; + + err = VmbStartup(); // Initialize the Vimba API + PrintVimbaVersion(); // Print Vimba Version + nMAC = mac_addr( strMAC ); // The MAC address of the camera + nIP = ip_addr( strIP ); // The future IP address of the camera + nSubnet = ip_addr( strSubnet ); // The future subnet mask of the camera + nGateway = strGateway != NULL ? ip_addr( strGateway ) : 0; // A possible gateway + + if ( VmbErrorSuccess == err ) + { + err = VmbFeatureBoolGet( gVimbaHandle, "GeVTLIsPresent", &bIsGigE ); // Is Vimba connected to a GigE transport layer? + if ( VmbErrorSuccess == err ) + { + if( bIsGigE ) + { + if ( 0 != nMAC ) + { + err = VmbFeatureIntSet( gVimbaHandle, "GevDeviceForceMACAddress", nMAC ); // Send MAC address to TL + if ( VmbErrorSuccess == err ) + { + err = VmbFeatureIntSet( gVimbaHandle, "GevDeviceForceIPAddress", nIP ); // Send new IP address to TL + if ( VmbErrorSuccess == err ) + { + err = VmbFeatureIntSet( gVimbaHandle, "GevDeviceForceSubnetMask", nSubnet ); // Send new subnet mask to TL + if ( VmbErrorSuccess == err ) + { + if( 0 != nGateway ) + { + err = VmbFeatureIntSet( gVimbaHandle, "GevDeviceForceGateway", nGateway ); // Send gateway address to TL + if ( VmbErrorSuccess != err ) + { + printf( "Could not prepare the gateway settings. Reason: %d\n\n", err ); + } + } + + if ( VmbErrorSuccess == err ) + { + err = VmbFeatureCommandRun( gVimbaHandle, "GevDeviceForceIP" ); // Finally execute the command to write all settings to cam + if ( VmbErrorSuccess == err ) + { + VmbBool_t isDone = 0; + unsigned int retryCount = 0; + do + { + SleepForSeconds(1); + err = VmbFeatureCommandIsDone( gVimbaHandle, "GevDeviceForceIP", &isDone); // Check if the command is accepted by the camera + } + while(retryCount++, isDone == VmbBoolFalse && err == VmbErrorSuccess && retryCount < 5); + + if( isDone == VmbBoolTrue) + { + printf("ForceIP command sent successfully to the camera\n"); + } + else + { + printf("ForceIP command could not be completed\n"); + } + } + else + { + printf( "Could not set a new IP address. Reason: %d\n\n", err ); + } + } + } + else + { + printf( "Could not prepare the subnet settings. Reason: %d\n\n", err ); + } + } + else + { + printf( "Could not prepare the IP address settings. Reason: %d\n\n", err ); + } + } + else + { + printf( "Could not prepare the MAC address settings. Reason: %d\n\n", err ); + } + } + else + { + printf( "Malformed MAC address.\n\n" ); + } + } + else + { + printf( "No GigE transport layer present.\n\n" ); + } + } + else + { + printf( "Could not query Vimba for the presence of a GigE transport layer. Reason: %d\n\n", err ); + } + + VmbShutdown(); // Close Vimba + } + else + { + printf( "Could not start system. Error code: %d\n\n", err ); + } +} diff --git a/Vimba_6_0/VimbaC/Examples/ForceIP/Source/ForceIP.h b/Vimba_6_0/VimbaC/Examples/ForceIP/Source/ForceIP.h new file mode 100644 index 0000000..7f2f391 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ForceIP/Source/ForceIP.h @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (C) 2013 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ForceIP.h + + Description: The ForceIP example will assign an IP address to a camera + that is identified by its MAC address. It utilizes only + GenTL features. This approach is useful when a camera has + an invalid IP configuration and cannot be accessed through + the network anymore. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef FORCE_IP_H_ +#define FORCE_IP_H_ + +// +// Starts Vimba API +// Seeks a GigE camera by its MAC address on the network +// Sets the found camera's +// - IP address +// - subnet mask +// - gateway +// +// Parameters: +// [in] strMAC The MAC address of the camera to work on in decimal +// or hex (with preceding 0x) representation +// [in] strIP The desired IP address for the camera +// [in] strSubnet The desired subnet mask of the IP address +// [in] strGateway The desired gateway. Optional, can be 0 +// +void ForceIP( char* strMAC, char* strIP, char* strSubnet, char* strGateway ); + +#endif diff --git a/Vimba_6_0/VimbaC/Examples/ForceIP/Source/program.c b/Vimba_6_0/VimbaC/Examples/ForceIP/Source/program.c new file mode 100644 index 0000000..5b1be7e --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ForceIP/Source/program.c @@ -0,0 +1,67 @@ +/*============================================================================= + Copyright (C) 2020 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: Main entry point of ForceIP example of VimbaC. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#ifndef WIN32 + #include +#else + #include +#endif + +#include + +int main( int argc, char* argv[] ) +{ + printf( "\n//////////////////////////////////\n" ); + printf( "/// Vimba API Force IP Example ///\n" ); + printf( "//////////////////////////////////\n\n" ); + + if( 4 > argc + || 5 < argc ) + { + printf( "Usage: ForceIP MAC IP Subnet [Gateway]\n\n" ); + printf( "Parameters:\n" ); + printf( "MAC The MAC address of the camera whose IP address shall be changed.\n" ); + printf( " Either hexadecimal with preceding 0x or decimal.\n" ); + printf( "IP The new IPv4 address of the camera in numbers and dots notation.\n" ); + printf( "Subnet The new network mask of the camera in numbers and dots notation.\n" ); + printf( "Gateway The address of a possible gateway if the camera is not connected\n" ); + printf( " to the host PC directly.\n\n" ); + printf( "For example to change the IP address of a camera with the MAC address 0x0F3101D540\nto 169.254.1.1 in a class B network call:\n\n" ); + printf( "ForceIP 0x0F3101D540 169.254.1.1 255.255.0.0\n\n" ); +#ifndef WIN32 + printf( "To alter cameras in foreign subnets run the program with sudo -E / su -m. \n\n" ); +#endif + } + else + { + ForceIP( argv[1], argv[2], argv[3], argc == 5 ? argv[4] : NULL ); + } + + return 0; +} diff --git a/Vimba_6_0/VimbaC/Examples/ListAncillaryDataFeatures/Build/Make/Makefile b/Vimba_6_0/VimbaC/Examples/ListAncillaryDataFeatures/Build/Make/Makefile new file mode 100644 index 0000000..2e5d1d1 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ListAncillaryDataFeatures/Build/Make/Makefile @@ -0,0 +1,58 @@ +PROJECT_NAME = ListAncillaryDataFeatures + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaC.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +COMMON_DIR = $(EXAMPLES_DIR)/Common + +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBAC_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBAC_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ListAncillaryDataFeatures.o \ + $(OBJ_DIR)/program.o \ + $(OBJ_DIR)/PrintVimbaVersion.o \ + $(OBJ_DIR)/ErrorCodeToMessage.o \ + $(OBJ_DIR)/DiscoverGigECameras.o + +DEPENDENCIES = VimbaC + +$(OBJ_DIR)/%.o: $(COMMON_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaC/Examples/ListAncillaryDataFeatures/Source/ListAncillaryDataFeatures.c b/Vimba_6_0/VimbaC/Examples/ListAncillaryDataFeatures/Source/ListAncillaryDataFeatures.c new file mode 100644 index 0000000..1153ec0 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ListAncillaryDataFeatures/Source/ListAncillaryDataFeatures.c @@ -0,0 +1,389 @@ +/*============================================================================= + Copyright (C) 2014 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ListAncillaryDataFeatures.c + + Description: The ListAncillaryDataFeatures example will list all available + features of the ancillary data that are found by VimbaC. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#ifdef WIN32 + #include +#else + #include +#endif + +#include + +#include +#include <../../Common/PrintVimbaVersion.h> +#include <../../Common/DiscoverGigECameras.h> + +// Purpose: Fetches features from the ancillary data. Ancillary data is part of a frame, +// therefore we need to capture a single frame beforehand. +// If no camera ID string was passed we use the first camera found. +// +// Parameter: +// [in ] const char* pStrID The ID of the camera to use. May be NULL. +void ListAncillaryDataFeatures( const char* pStrID ) +{ + VmbError_t err = VmbErrorSuccess; + VmbHandle_t cameraHandle = NULL; // A handle to our camera + VmbHandle_t ancillaryDataHandle = NULL; // A handle to ancillary data + VmbCameraInfo_t* pCameras = NULL; // A list of camera infos + VmbUint32_t count = 0; // The number of found cameras + VmbFeatureInfo_t* pFeatures = NULL; // A list of ancillary data features + VmbFrame_t frame; // A single frame + VmbInt64_t pls = 0; // The payload size of a frame + VmbCameraInfo_t info; // The name and other information of our camera + VmbBool_t bIsCommandDone = VmbBoolFalse; // Has a command finished execution + // The volatile value of a feature + double doubleValue = 0.0; // A float value + char* pStringValue = NULL; // A string value + VmbBool_t boolValue = VmbBoolFalse; // A bool value + VmbInt64_t intValue = 0; // An int value + VmbUint32_t i = 0; + + err = VmbStartup(); // Initialize the Vimba API + PrintVimbaVersion(); // Print Vimba Version + if (VmbErrorSuccess == err) + { + DiscoverGigECameras(); // Seek for GigE cameras on the network + + if( NULL == pStrID ) // If no ID was provided use the first camera + { + err = VmbCamerasList ( NULL, // Get the amount of known cameras + 0, + &count, + sizeof *pCameras ); + if( VmbErrorSuccess == err + && 0 < count ) + { + pCameras = (VmbCameraInfo_t*)malloc( count * sizeof *pCameras ); + if( NULL != pCameras ) + { + err = VmbCamerasList( pCameras, // Get all known cameras + count, + &count, + sizeof *pCameras ); + if( VmbErrorSuccess == err + || VmbErrorMoreData == err ) // If a new camera was connected since we queried + { // for the amount of cameras, we can ignore that one + if( 0 < count ) + { + info = pCameras[0]; // Copy the camera info of the camera we will use + err = VmbCameraOpen( pCameras[0].cameraIdString, // Finally open the first one + VmbAccessModeFull, + &cameraHandle ); + } + else + { + printf( "Camera lost. Error code: %d\n", err ); + } + } + else + { + printf( "Could not list cameras. Error code: %d\n", err ); + } + + free( pCameras ); + pCameras = NULL; + } + else + { + printf( "Could not allocate camera list.\n" ); + } + } + else + { + printf( "Could not list cameras or no cameras present. Error code: %d\n", err ); + } + } + else + { + err = VmbCameraOpen( pStrID, // Open the camera with the given ID + VmbAccessModeFull, + &cameraHandle ); + } + + if ( NULL != cameraHandle ) + { + if( VmbErrorSuccess == err ) + { + if ( NULL != pStrID ) + { + err = VmbCameraInfoQuery( pStrID, &info, sizeof( VmbCameraInfo_t ) ); // If we haven't queried the camera info yet, we do it now to display the camera name + } + + if ( VmbErrorSuccess == err ) + { + printf( "Using camera %s\n", info.cameraName ); + + err = VmbFeatureBoolSet( cameraHandle, "ChunkModeActive", VmbBoolTrue ); // Enable ancillary data + if( VmbErrorSuccess == err ) + { + // Set the GeV packet size to the highest possible value + // (In this example we do not test whether this cam actually is a GigE cam) + if ( VmbErrorSuccess == VmbFeatureCommandRun( cameraHandle, "GVSPAdjustPacketSize" )) + { + printf( "Adjusting packet size " ); // Set the highest possible packet size + do + { + if ( VmbErrorSuccess != VmbFeatureCommandIsDone( cameraHandle, + "GVSPAdjustPacketSize", + &bIsCommandDone )) + { + break; + } +#ifdef WIN32 + Sleep(200); +#else + usleep(200000); +#endif + printf( "." ); + } while ( VmbBoolFalse == bIsCommandDone ); + } + + printf( "\nCapture a single frame\n" ); // In order to fill the ancillary data we need to fill a frame + + err = VmbFeatureIntGet( cameraHandle, "PayloadSize", &pls ); + if( VmbErrorSuccess == err ) + { + frame.bufferSize = (VmbUint32_t)pls; + frame.buffer = malloc( (VmbUint32_t)pls * sizeof(unsigned char) ); + if ( NULL != frame.buffer ) + { + err = VmbFrameAnnounce( cameraHandle, &frame, sizeof(VmbFrame_t)); + if( VmbErrorSuccess == err) + { + err = VmbCaptureStart ( cameraHandle ); + if( VmbErrorSuccess == err ) + { + err = VmbCaptureFrameQueue( cameraHandle, &frame, NULL ); + if( VmbErrorSuccess == err ) + { + err = VmbFeatureCommandRun( cameraHandle, "AcquisitionStart" ); + if( VmbErrorSuccess == err ) + { + err = VmbCaptureFrameWait( cameraHandle, &frame, 1000 ); + if( VmbErrorSuccess == err ) + { + if( VmbFrameStatusComplete == frame.receiveStatus ) + { + err = VmbAncillaryDataOpen( &frame, &ancillaryDataHandle ); + if( VmbErrorSuccess == err ) + { + // Query all static details as well as the value of all fetched ancillary data features and print them out. + err = VmbFeaturesList( ancillaryDataHandle, // Get the amount of features + NULL, + 0, + &count, + sizeof *pFeatures ); + if ( VmbErrorSuccess == err + && 0 < count ) + { + pFeatures = (VmbFeatureInfo_t *)malloc( count * sizeof *pFeatures ); + if( NULL != pFeatures ) + { + err = VmbFeaturesList( ancillaryDataHandle, // Get the features + pFeatures, + count, + &count, + sizeof *pFeatures ); + if( VmbErrorSuccess == err ) + { + for( i=0; i + +#include + +int main( int argc, char* argv[] ) +{ + printf( "\n" ); + printf( "//////////////////////////////////////////////////////\n" ); + printf( "/// Vimba API List Ancillary Data Features Example ///\n" ); + printf( "//////////////////////////////////////////////////////\n" ); + printf( "\n" ); + + if( 2 < argc ) + { + printf( "Usage: ListAncillaryDataFeatures [CameraID]\n\n" ); + printf( "Parameters: CameraID ID of the camera to use (using first camera if not specified)\n" ); + } + else if( 2 == argc ) + { + ListAncillaryDataFeatures( (const char*)argv[1] ); + } + else + { + ListAncillaryDataFeatures( NULL ); + } + + printf( "\n" ); +} diff --git a/Vimba_6_0/VimbaC/Examples/ListCameras/Build/Make/Makefile b/Vimba_6_0/VimbaC/Examples/ListCameras/Build/Make/Makefile new file mode 100644 index 0000000..b0352ed --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ListCameras/Build/Make/Makefile @@ -0,0 +1,58 @@ +PROJECT_NAME = ListCameras + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaC.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +COMMON_DIR = $(EXAMPLES_DIR)/Common + +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBAC_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBAC_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ListCameras.o \ + $(OBJ_DIR)/program.o \ + $(OBJ_DIR)/PrintVimbaVersion.o \ + $(OBJ_DIR)/ErrorCodeToMessage.o \ + $(OBJ_DIR)/DiscoverGigECameras.o + +DEPENDENCIES = VimbaC + +$(OBJ_DIR)/%.o: $(COMMON_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaC/Examples/ListCameras/Source/ListCameras.c b/Vimba_6_0/VimbaC/Examples/ListCameras/Source/ListCameras.c new file mode 100644 index 0000000..864899c --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ListCameras/Source/ListCameras.c @@ -0,0 +1,109 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ListCameras.c + + Description: The ListCameras example will list all available cameras that + are found by VimbaC. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include + +#include + +#include +#include <../../Common/PrintVimbaVersion.h> +#include <../../Common/DiscoverGigECameras.h> + +// +// Starts Vimba +// Gets all connected cameras +// And prints out information about the camera name, model name, serial number, ID and the corresponding interface ID +// +void ListCameras() +{ + VmbError_t err = VmbErrorSuccess; + VmbCameraInfo_t * pCameras = NULL; + VmbUint32_t i = 0; + VmbUint32_t nCount = 0; + VmbUint32_t nFoundCount = 0; + + err = VmbStartup(); // Initialize the Vimba API + PrintVimbaVersion(); // Print Vimba Version + + if ( VmbErrorSuccess == err ) + { + DiscoverGigECameras(); + + err = VmbCamerasList( NULL, 0, &nCount, sizeof *pCameras ); // Get the amount of known cameras + if ( VmbErrorSuccess == err + && nCount != 0 ) + { + printf( "Cameras found: %d\n\n", nCount ); + + pCameras = (VmbCameraInfo_t*)malloc( sizeof *pCameras * nCount ); + if ( NULL != pCameras ) + { + err = VmbCamerasList( pCameras, nCount, &nFoundCount, sizeof *pCameras ); // Query all static details of all known cameras + // Without having to open the cameras + if( VmbErrorSuccess == err + || VmbErrorMoreData == err ) + { + if( nFoundCount < nCount) // If a new camera was connected since we queried + { // the amount of cameras, we can ignore that one + nCount = nFoundCount; + } + for ( i=0; i + +#include + +int main( int argc, char* argv[] ) +{ + printf( "//////////////////////////////////////\n" ); + printf( "/// Vimba API List Cameras Example ///\n" ); + printf( "//////////////////////////////////////\n\n" ); + + if ( 1 < argc ) + { + printf( "No parameters expected. Execution will not be affected by the provided parameter(s).\n\n" ); + } + + ListCameras(); + + return 0; +} diff --git a/Vimba_6_0/VimbaC/Examples/ListFeatures/Build/Make/Makefile b/Vimba_6_0/VimbaC/Examples/ListFeatures/Build/Make/Makefile new file mode 100644 index 0000000..b3645fc --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ListFeatures/Build/Make/Makefile @@ -0,0 +1,58 @@ +PROJECT_NAME = ListFeatures + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaC.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +COMMON_DIR = $(EXAMPLES_DIR)/Common + +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBAC_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBAC_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ListFeatures.o \ + $(OBJ_DIR)/program.o \ + $(OBJ_DIR)/PrintVimbaVersion.o \ + $(OBJ_DIR)/ErrorCodeToMessage.o \ + $(OBJ_DIR)/DiscoverGigECameras.o + +DEPENDENCIES = VimbaC + +$(OBJ_DIR)/%.o: $(COMMON_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaC/Examples/ListFeatures/Source/ListFeatures.c b/Vimba_6_0/VimbaC/Examples/ListFeatures/Source/ListFeatures.c new file mode 100644 index 0000000..ca9220a --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/ListFeatures/Source/ListFeatures.c @@ -0,0 +1,250 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ListFeatures.cpp + + Description: The ListFeatures example will list all available features of a + camera that are found by VimbaC. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include + +#include + +#include +#include <../../Common/PrintVimbaVersion.h> +#include <../../Common/DiscoverGigECameras.h> + +// +// Prints out all features and their values and details of a given camera. +// If no camera ID is provided, the first camera will be used. +// Starts and stops the API +// Opens and closes the camera +// +// Parameters: +// [in] pStrID The ID of the camera to work +// +void ListFeatures( const char *pStrID ) +{ + VmbError_t err = VmbErrorSuccess; + VmbHandle_t hCamera = NULL; // A handle to our camera + VmbCameraInfo_t* pCameras = NULL; // A list of camera infos + VmbUint32_t nCount = 0; // The number of found cameras + VmbFeatureInfo_t *pFeatures = NULL; // A list of static details of camera features + // The changeable value of a feature + VmbInt64_t nValue = 0; // An int value + double fValue = 0.0; // A float value + char *pStrValue = NULL; // A string value + VmbBool_t bValue = VmbBoolFalse; // A bool value + VmbUint32_t i = 0; + + err = VmbStartup(); // Initialize the Vimba API + PrintVimbaVersion(); // Print Vimba Version + if ( VmbErrorSuccess == err ) + { + DiscoverGigECameras(); + + if ( NULL == pStrID ) // If no ID was provided use the first camera + { + err = VmbCamerasList( NULL, // Get the amount of known cameras + 0, + &nCount, + sizeof *pCameras ); + if ( VmbErrorSuccess == err + && 0 < nCount ) + { + pCameras = (VmbCameraInfo_t*)malloc( nCount * sizeof *pCameras ); + if ( NULL != pCameras ) + { + err = VmbCamerasList( pCameras, // Get all known cameras + nCount, + &nCount, + sizeof *pCameras ); + if ( VmbErrorSuccess == err + || VmbErrorMoreData == err ) // If a new camera was connected since we queried + { // for the amount of cameras, we can ignore that one + if( 0 < nCount ) + { + err = VmbCameraOpen( pCameras[0].cameraIdString, // Finally open the first one + VmbAccessModeFull, + &hCamera ); + } + else + { + printf( "Camera lost.\n" ); + } + } + else + { + printf( "Could not list cameras. Error code: %d\n", err ); + } + + free( pCameras ); + pCameras = NULL; + } + else + { + printf( "Could not allocate camera list.\n" ); + } + } + else + { + printf( "Could not list cameras or no cameras present. Error code: %d\n", err ); + } + } + else + { + err = VmbCameraOpen( pStrID, // Open the camera with the given ID + VmbAccessModeFull, + &hCamera ); + } + + // Query all static details as well as the value of all fetched features and print them out. + if ( VmbErrorSuccess == err ) + { + err = VmbFeaturesList( hCamera, // Get the amount of features + NULL, + 0, + &nCount, + sizeof *pFeatures ); + if ( VmbErrorSuccess == err + && 0 < nCount ) + { + pFeatures = (VmbFeatureInfo_t *)malloc( nCount * sizeof *pFeatures ); + if ( NULL != pFeatures ) + { + err = VmbFeaturesList( hCamera, // Get the features + pFeatures, + nCount, + &nCount, + sizeof *pFeatures ); + if ( VmbErrorSuccess == err ) + { + for ( i=0; i + +#include + +int main( int argc, char* argv[] ) +{ + printf( "\n" ); + printf( "///////////////////////////////////////\n" ); + printf( "/// Vimba API List Features Example ///\n" ); + printf( "///////////////////////////////////////\n" ); + printf( "\n" ); + + if( 2 < argc ) + { + printf( "Usage: ListFeatures [CameraID]\n\n" ); + printf( "Parameters: CameraID ID of the camera to use (using first camera if not specified)\n" ); + } + else if ( 2 == argc ) + { + ListFeatures( (const char*)argv[1] ); + } + else + { + ListFeatures( NULL ); + } + + printf( "\n" ); +} diff --git a/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Build/Make/Makefile b/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Build/Make/Makefile new file mode 100644 index 0000000..b1a3277 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Build/Make/Makefile @@ -0,0 +1,56 @@ +PROJECT_NAME = LoadSaveSettings + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaC.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +COMMON_DIR = $(EXAMPLES_DIR)/Common + +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBAC_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBAC_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/program.o \ + $(OBJ_DIR)/PrintVimbaVersion.o \ + $(OBJ_DIR)/DiscoverGigECameras.o + +DEPENDENCIES = VimbaC + +$(OBJ_DIR)/%.o: $(COMMON_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/DiscoverGigECameras.c b/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/DiscoverGigECameras.c new file mode 100644 index 0000000..3abce96 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/DiscoverGigECameras.c @@ -0,0 +1,73 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: DiscoverGigECameras.c + + Description: Discover GigE cameras if GigE TL is present. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#ifdef WIN32 +#include +#else +#include +#endif + +#include + +#include "DiscoverGigECameras.h" + + +// Purpose: Discovers GigE cameras if GigE TL is present. +// Discovery is switched on only once so that the API can detect all currently connected cameras. +VmbError_t DiscoverGigECameras() +{ + VmbError_t err = VmbErrorSuccess; + VmbBool_t isGigE = VmbBoolFalse; + + err = VmbFeatureBoolGet( gVimbaHandle, "GeVTLIsPresent", &isGigE ); // Is Vimba connected to a GigE transport layer? + if ( VmbErrorSuccess == err ) + { + if( VmbBoolTrue == isGigE ) + { + err = VmbFeatureIntSet( gVimbaHandle, "GeVDiscoveryAllDuration", 250 ); // Set the waiting duration for discovery packets to return. If not set the default of 150 ms is used. + if( VmbErrorSuccess == err ) + { + err = VmbFeatureCommandRun( gVimbaHandle, "GeVDiscoveryAllOnce" ); // Send discovery packets to GigE cameras and wait 250 ms until they are answered + if( VmbErrorSuccess != err ) + { + printf( "Could not ping GigE cameras over the network. Reason: %d\n", err ); + } + } + else + { + printf( "Could not set the discovery waiting duration. Reason: %d\n", err ); + } + } + } + else + { + printf( "Could not query Vimba for the presence of a GigE transport layer. Reason: %d\n\n", err ); + } + + return err; +} diff --git a/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/DiscoverGigECameras.h b/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/DiscoverGigECameras.h new file mode 100644 index 0000000..44faed6 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/DiscoverGigECameras.h @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: DiscoverGigECameras.h + + Description: Discover GigE cameras if GigE TL is present. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef DISCOVER_GIGE_CAMERAS_H_ +#define DISCOVER_GIGE_CAMERAS_H_ + +#include + +// Purpose: Discovers GigE cameras if GigE TL is present. +// Discovery is switched on only once so that the API can detect all currently connected cameras. +VmbError_t DiscoverGigECameras(); + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/PrintVimbaVersion.c b/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/PrintVimbaVersion.c new file mode 100644 index 0000000..c1dda1a --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/PrintVimbaVersion.c @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: PrintVimbaVersion.h + + Description: Print Vimba version. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 "PrintVimbaVersion.h" +#include +#include + +// Purpose: Prints the Vimba version information. +void PrintVimbaVersion() +{ + VmbVersionInfo_t version_info; + VmbError_t result = VmbVersionQuery( &version_info, sizeof( version_info )); + if( VmbErrorSuccess == result) + { + printf( "Vimba Version Major: %u Minor: %u Patch: %u\n", version_info.major, version_info.minor,version_info.patch ); + } + else + { + printf( "VmbVersionQuery failed with Reason: %x", result ); + } +} + + diff --git a/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/PrintVimbaVersion.h b/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/PrintVimbaVersion.h new file mode 100644 index 0000000..faeb3aa --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/PrintVimbaVersion.h @@ -0,0 +1,34 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: PrintVimbaVersion.h + + Description: Print Vimba version. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef PRINT_VIMBA_VERSION_H_ +#define PRINT_VIMBA_VERSION_H_ + +// Purpose: Prints the Vimba version information. +void PrintVimbaVersion(); + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/program.c b/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/program.c new file mode 100644 index 0000000..5c854a7 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/LoadSaveSettings/Source/program.c @@ -0,0 +1,213 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.c + + Description: Main entry point of LoadSaveSettings example of VimbaC. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include +#include + +int main( int argc, char *argv[] ) +{ + VmbError_t err = VmbErrorSuccess; + VmbUint32_t nCount = 0; + VmbCameraInfo_t *pCameras = NULL; + VmbHandle_t handle = NULL; + const char *fileName = "current_settings.xml"; + const char *cameraId = NULL; + +// prepare settings struct to determine behaviour +// during loading or saving operation +// (This is optional. Passing NULL triggers default settings) + VmbFeaturePersistSettings_t settings; + settings.loggingLevel = 4; // full loggin details (trace, debug, warning, error and info messages) + settings.maxIterations = 5; // how many iterations during loading shall be performed at max + // (comparing desired with device value. in case of difference new iteration will be executed) + settings.persistType = VmbFeaturePersistNoLUT; // determines which features shall be considered + // NoLUT means: all features except for lookUp table features + + printf( "\n" ); + printf( "////////////////////////////////////////////\n" ); + printf( "/// Vimba API Load/Save Settings Example ///\n" ); + printf( "////////////////////////////////////////////\n" ); + printf( "\n" ); + +// start VimbaC API + err = VmbStartup(); + if( VmbErrorSuccess != err ) + { + printf( "Could not start Vimba [error code: %i]\n", err ); + return err; + } + + printf( "--> VimbaC has been started\n" ); + +// check for GigE cameras + err = DiscoverGigECameras(); + if( VmbErrorSuccess != err ) + { + VmbShutdown(); + printf( "Could discover GigE cameras [error code: %i]\n", err ); + return err; + } + +// get amount of connected cameras + err = VmbCamerasList( NULL, 0, &nCount, sizeof(*pCameras) ); + if( VmbErrorSuccess != err ) + { + VmbShutdown(); + printf( "Could not retrieve number of cameras [error code: %i]\n", err ); + return err; + } + +// in case no camera is connected + if( 0 == nCount ) + { + VmbShutdown(); + printf( "No Camera found [error code: %i]\n", err ); + return err; + } + +// allocate space for camera list + pCameras = (VmbCameraInfo_t *) malloc( nCount * sizeof(*pCameras) ); + if( NULL == pCameras ) + { + VmbShutdown(); + printf( "No Camera found [error code: %i]\n", err ); + return VmbErrorOther; + } + +// retrieve camera list from Vimba + err = VmbCamerasList( pCameras, nCount, &nCount, sizeof(*pCameras) ); + if( VmbErrorSuccess != err ) + { + VmbShutdown(); + printf( "Could not retrieve info pointers for connected cameras [error code: %i]\n", err ); + return err; + } + +// get camera id string + cameraId = pCameras[0].cameraIdString; + if( NULL == cameraId ) + { + VmbShutdown(); + printf( "Could not retrieve camera id [error code: %i]\n", VmbErrorOther ); + return err; + } + +// open camera (first in list) + err = VmbCameraOpen( cameraId, VmbAccessModeFull, &handle ); + if( VmbErrorSuccess != err ) + { + VmbShutdown(); + printf( "Could not open camera in Full Access mode [error code: %i]\n", err ); + return err; + } + + printf( "--> Camera with id '%s' has been opened\n", cameraId ); + + +// save current camera feature values + err = VmbCameraSettingsSave( handle, fileName, NULL, 0 ); + if( VmbErrorSuccess != err ) + { + printf( "Could not save feature values to given XML file '%s' [error code: %i]\n", fileName, err ); + err = VmbCameraClose( handle ); + if( VmbErrorSuccess != err ) + { + printf( "Could not close camera [error code: %i]\n", err ); + } + VmbShutdown(); + return err; + } + + printf( "--> Camera settings have been saved\n" ); + +// set all feature values to factory default + err = VmbFeatureEnumSet( handle, "UserSetSelector", "Default" ); + if( VmbErrorSuccess != err ) + { + printf( "Could not set feature value 'UserSetSelector' to 'Default' [error code: %i]\n", err ); + err = VmbCameraClose( handle ); + if( VmbErrorSuccess != err ) + { + printf( "Could not close camera [error code: %i]\n", err ); + } + VmbShutdown(); + return err; + } + err = VmbFeatureCommandRun( handle, "UserSetLoad" ); + if( VmbErrorSuccess != err ) + { + printf( "Could not run 'UserSetLoad' command [error code: %i]\n", err ); + err = VmbCameraClose( handle ); + if( VmbErrorSuccess != err ) + { + printf( "Could not close camera [error code: %i]\n", err ); + } + VmbShutdown(); + return err; + } + + printf( "--> All feature values have been restored to default\n" ); + +// load feature values to selected camera from xml file + err = VmbCameraSettingsLoad( handle, fileName, &settings, sizeof(settings) ); + if( VmbErrorSuccess != err ) + { + printf( "Could not load feature values from given XML file '%s' [error code: %i]\n", fileName, err ); + err = VmbCameraClose( handle ); + if( VmbErrorSuccess != err ) + { + printf( "Could not close camera [error code: %i]\n", err ); + } + VmbShutdown(); + return err; + } + + printf( "--> Feature values have been loaded from given XML file\n" ); + +// close camera + err = VmbCameraClose( handle ); + if( VmbErrorSuccess != err ) + { + printf( "Could not close camera [error code: %i]\n", err ); + VmbShutdown(); + return err; + } + + printf( "--> Camera has been closed\n" ); + +// shutdown VimbaC API + VmbShutdown(); + printf( "--> VimbaC has been stopped\n" ); + +// free allocated space for camera list + free( pCameras ); + pCameras = NULL; + + return 0; +} diff --git a/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Build/Make/Makefile b/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Build/Make/Makefile new file mode 100644 index 0000000..ec620c2 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Build/Make/Makefile @@ -0,0 +1,59 @@ +PROJECT_NAME = SynchronousGrab + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaC.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +COMMON_DIR = $(EXAMPLES_DIR)/Common + +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBAC_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBAC_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/Bitmap.o \ + $(OBJ_DIR)/SynchronousGrab.o \ + $(OBJ_DIR)/program.o \ + $(OBJ_DIR)/PrintVimbaVersion.o \ + $(OBJ_DIR)/ErrorCodeToMessage.o \ + $(OBJ_DIR)/DiscoverGigECameras.o + +DEPENDENCIES = VimbaC + +$(OBJ_DIR)/%.o: $(COMMON_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.c $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/Bitmap.c b/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/Bitmap.c new file mode 100644 index 0000000..c03fe7d --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/Bitmap.c @@ -0,0 +1,267 @@ +/*============================================================================= + Copyright (C) 2013 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: Bitmap.c + + Description: The bitmap class represents a MS(R) Windows(TM) bitmap version 3 + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#include + +#define THREE_CHANNEL 0xC +#define BMP_HEADER_SIZE 54 +#define ALIGNMENT_SIZE 4 + +// +// Creates a MS Windows bitmap with header and color palette. +// Fills it with the content of the given byte buffer +// +// Parameters: +// [out] pBitmap A pointer to an AVTBitmap that will get filled +// [in] pBuffer The buffer that will be used to fill the created bitmap +// +// Returns: +// 0 in case of error +// 1 in case of success +// +unsigned char AVTCreateBitmap( AVTBitmap * const pBitmap, const void* pBuffer ) +{ + unsigned char nNumColors = 0; // Number of colors of our image + unsigned char nPadLength = 0; // The padding we need to align the bitmap ALIGNMENT_SIZE + unsigned long nPaletteSize = 0; // The size of the bitmap's palette + unsigned long nHeaderSize = 0; // The size of the bitmap's header + unsigned long nFileSize = 0; // The size of the bitmap file + unsigned char* pBitmapBuffer = 0; // A buffer we use for creating the bitmap + unsigned char* pCurBitmapBuf = 0; // A cursor to move over "pBitmapBuffer" + unsigned char* pCurSrc = 0; // A cursor to move over the given buffer "pBuffer" + unsigned long px = 0; // A single pixel for storing transformed color information + unsigned long x = 0; // The horizontal position within our image + unsigned long y = 0; // The vertical position within our image + unsigned long i = 0; // Counter for some iteration + + // The bitmap header + char fileHeader[14] = { 'B','M', // Default + 0,0,0,0, // File size + 0,0,0,0, // Reserved + 0,0,0,0 }; // Offset to image content + char infoHeader[40] = { 40,0,0,0, // Size of info header + 0,0,0,0, // Width + 0,0,0,0, // Height + 1,0, // Default + 0, 0 }; // bpp + + if ( NULL == pBitmap + || 0 == pBitmap->bufferSize + || 0 == pBitmap->width + || 0 == pBitmap->height ) + { + return 0; + } + + if ( pBitmap->colorCode == ( pBitmap->colorCode & THREE_CHANNEL )) + { + nNumColors = 3; + } + else + { + nNumColors = 1; + } + + // Bitmap padding always is a multiple of four Bytes. If data is not we need to pad with zeros. + nPadLength = ( pBitmap->width * nNumColors ) % ALIGNMENT_SIZE; + if ( 0 != nPadLength ) + { + nPadLength = ALIGNMENT_SIZE - nPadLength; + } + + if ( ColorCodeRGB24 != pBitmap->colorCode ) + { + nPaletteSize = 256; + } + + nHeaderSize = BMP_HEADER_SIZE + nPaletteSize * 4; + pBitmapBuffer = (unsigned char*)malloc( nHeaderSize + pBitmap->bufferSize + (nPadLength * pBitmap->height )); + nFileSize = nHeaderSize + pBitmap->bufferSize + ( nPadLength * pBitmap->height ); + + // File size + fileHeader[ 2] = (char)( nFileSize ); + fileHeader[ 3] = (char)( nFileSize >> 8 ); + fileHeader[ 4] = (char)( nFileSize >> 16 ); + fileHeader[ 5] = (char)( nFileSize >> 24 ); + // Offset to image content + fileHeader[10] = (char)( nHeaderSize ); + fileHeader[11] = (char)( nHeaderSize >> 8 ); + fileHeader[12] = (char)( nHeaderSize >> 16 ); + fileHeader[13] = (char)( nHeaderSize >> 24 ); + + // Width + infoHeader[ 4] = (char)( pBitmap->width ); + infoHeader[ 5] = (char)( pBitmap->width >> 8 ); + infoHeader[ 6] = (char)( pBitmap->width >> 16 ); + infoHeader[ 7] = (char)( pBitmap->width >> 24 ); + // Height (has to be negative for a top down image) + infoHeader[ 8] = (char)( -(long)pBitmap->height ); + infoHeader[ 9] = (char)( -(long)pBitmap->height >> 8 ); + infoHeader[10] = (char)( -(long)pBitmap->height >> 16 ); + infoHeader[11] = (char)( -(long)pBitmap->height >> 24 ); + // bpp + infoHeader[14] = 8 * nNumColors; + // Image size + infoHeader[20] = (char)( pBitmap->bufferSize ); + infoHeader[21] = (char)( pBitmap->bufferSize >> 8 ); + infoHeader[22] = (char)( pBitmap->bufferSize >> 16 ); + infoHeader[23] = (char)( pBitmap->bufferSize >> 24 ); + // Palette size + infoHeader[32] = (char)( nPaletteSize ); + infoHeader[33] = (char)( nPaletteSize >> 8 ); + infoHeader[34] = (char)( nPaletteSize >> 16 ); + infoHeader[35] = (char)( nPaletteSize >> 24 ); + // Used colors + infoHeader[36] = (char)( nPaletteSize ); + infoHeader[37] = (char)( nPaletteSize >> 8 ); + infoHeader[38] = (char)( nPaletteSize >> 16 ); + infoHeader[39] = (char)( nPaletteSize >> 24 ); + + // Write header + pCurBitmapBuf = pBitmapBuffer; + memcpy( pCurBitmapBuf, fileHeader, 14 ); + pCurBitmapBuf += 14; + memcpy( pCurBitmapBuf, infoHeader, 40 ); + pCurBitmapBuf += 40; + for( i = 0; i < nPaletteSize; ++i ) + { + pCurBitmapBuf[0] = (char)(i); + pCurBitmapBuf[1] = (char)(i); + pCurBitmapBuf[2] = (char)(i); + pCurBitmapBuf[3] = 0; + pCurBitmapBuf += 4; + } + + // RGB -> BGR (a Windows bitmap is BGR) + if ( ColorCodeRGB24 == pBitmap->colorCode ) + { + pCurSrc = (unsigned char*)pBuffer; + for ( y=0; yheight; ++y, pCurBitmapBuf+=nPadLength ) + { + for ( x = 0; + x < pBitmap->width; + ++x, + pCurSrc += 3, + pCurBitmapBuf += 3 ) + { + px = 0; + // Create a 4 Byte structure to store ARGB (we don't use A) + px = px | ( pCurSrc[0] << 16 ) | ( pCurSrc[1] << 8 ) | pCurSrc[2]; + // Due to endianess ARGB is stored as BGRA + // and we only have to write the first three Bytes + memcpy( pCurBitmapBuf, &px, 3 ); + } + // Add padding at the end of each row + memset( pCurBitmapBuf, 0, nPadLength ); + } + pBitmap->colorCode = ColorCodeBGR24; + } + // Mono8 + else + { + if ( 0 == nPadLength ) + { + memcpy( pCurBitmapBuf, pBuffer, pBitmap->bufferSize ); + } + else + { + pCurSrc = (unsigned char*)pBuffer; + for ( y=0; + yheight; + ++y, + pCurSrc += pBitmap->width * nNumColors ) + { + // Write a single row of colored pixels + memcpy( pCurBitmapBuf, pCurSrc, pBitmap->width * nNumColors ); + pCurBitmapBuf += pBitmap->width * nNumColors; + // Write padding pixels + memset( pCurBitmapBuf, 0, nPadLength ); + pCurBitmapBuf += nPadLength; + } + } + } + + pBitmap->buffer = pBitmapBuffer; + pBitmap->bufferSize = nFileSize; + return 1; +} + +// +// Releases (frees) a given bitmap +// +// Parameters: +// [in, out] pBitmap The bitmap whose memory will be freed +// +// Returns: +// 0 in case of error +// 1 in case of success +// +unsigned char AVTReleaseBitmap( AVTBitmap * const pBitmap ) +{ + if ( NULL != pBitmap + && NULL != pBitmap->buffer + && 0 < pBitmap->bufferSize ) + { + free( pBitmap->buffer ); + pBitmap->buffer = NULL; + return 1; + } + + return 0; +} + +// +// Writes a given bitmap to file +// +// Parameters: +// [in] pBitmap The AVTBitmap to write to file +// [in] pFileName The destination (complete path) where to write the bitmap to +// +// Returns: +// 0 in case of error +// 1 in case of success +// +unsigned char AVTWriteBitmapToFile( AVTBitmap const * const pBitmap, char const * const pFileName ) +{ + FILE *file; + if ( NULL != pBitmap + && NULL != pBitmap->buffer + && NULL != pFileName ) + { + file = fopen( pFileName, "wb" ); + fwrite( pBitmap->buffer, 1, pBitmap->bufferSize, file ); + fclose( file ); + + return 1; + } + + return 0; +} diff --git a/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/Bitmap.h b/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/Bitmap.h new file mode 100644 index 0000000..5121419 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/Bitmap.h @@ -0,0 +1,87 @@ +/*============================================================================= + Copyright (C) 2013 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: Bitmap.h + + Description: The bitmap class represents a MS(R) Windows(TM) bitmap version 3 + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_BITMAP_H_ +#define AVT_BITMAP_H_ + +typedef enum +{ + ColorCodeMono8 = 1, + ColorCodeMono16 = 2, + ColorCodeBGR24 = 4, + ColorCodeRGB24 = 8 +} ColorCode; + +typedef struct +{ + void* buffer; + unsigned long bufferSize; + unsigned long width; + unsigned long height; + ColorCode colorCode; +} AVTBitmap; + +// +// Creates a MS Windows bitmap with header and color palette. +// Fills it with the content of the given byte buffer +// +// Parameters: +// [out] pBitmap A pointer to an AVTBitmap that will get filled +// [in] pBuffer The buffer that will be used to fill the created bitmap +// +// Returns: +// 0 in case of error +// 1 in case of success +// +unsigned char AVTCreateBitmap( AVTBitmap * const pBitmap, const void* pBuffer ); + +// +// Releases (frees) a given bitmap +// +// Parameters: +// [in, out] pBitmap The bitmap whose memory will be freed +// +// Returns: +// 0 in case of error +// 1 in case of success +// +unsigned char AVTReleaseBitmap( AVTBitmap * const pBitmap ); + +// +// Writes a given bitmap to file +// +// Parameters: +// [in] pBitmap The AVTBitmap to write to file +// [in] pFileName The destination (complete path) where to write the bitmap to +// +// Returns: +// 0 in case of error +// 1 in case of success +// +unsigned char AVTWriteBitmapToFile( AVTBitmap const * const pBitmap, char const * const pFileName ); + +#endif diff --git a/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/SynchronousGrab.c b/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/SynchronousGrab.c new file mode 100644 index 0000000..74600f6 --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/SynchronousGrab.c @@ -0,0 +1,318 @@ +/*============================================================================= + Copyright (C) 2012 - 2013 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: SynchronousGrab.cpp + + Description: The SynchronousGrab example will grab a single image + synchronously and save it to a file using VimbaC. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#ifdef WIN32 + #include +#else + #include +#endif + +#include +#include "../../Common/PrintVimbaVersion.h" +#include "../../Common/DiscoverGigECameras.h" +#include +#include + +// +// Starts Vimba API +// Opens the given camera, if no camera ID was provided, the first camera found will be used +// Sets the maximum possible Ethernet packet size +// Adjusts the image format +// Acquires one image synchronously +// Writes the image as bitmap to file +// Closes the camera in case of failure +// +// Parameters: +// [in] pCameraID The ID of the camera to work on. Can be NULL. +// [in] pFileName The path of the bitmap where the image is saved to +// +// Returns: +// An API status code +// +VmbError_t SynchronousGrab( const char* pCameraID, const char* pFileName ) +{ + VmbError_t err = VmbStartup(); // Initialize the Vimba API + VmbCameraInfo_t *pCameras = NULL; // A list of camera details + VmbUint32_t nCount = 0; // Number of found cameras + VmbUint32_t nFoundCount = 0; // Change of found cameras + const VmbUint32_t nTimeout = 2000; // Timeout for Grab + VmbAccessMode_t cameraAccessMode = VmbAccessModeFull;// We open the camera with full access + VmbHandle_t cameraHandle = NULL; // A handle to our camera + VmbBool_t bIsCommandDone = VmbBoolFalse; // Has a command finished execution + VmbFrame_t frame; // The frame we capture + const char* pPixelFormat = NULL; // The pixel format we use for acquisition + VmbInt64_t nPayloadSize = 0; // The size of one frame + AVTBitmap bitmap; // The bitmap we create + + PrintVimbaVersion(); + + if ( VmbErrorSuccess == err ) + { + // Is Vimba connected to a GigE transport layer? + DiscoverGigECameras(); + + // If no camera ID was provided use the first camera found + if ( NULL == pCameraID ) + { + // Get the amount of known cameras + err = VmbCamerasList( NULL, 0, &nCount, sizeof *pCameras ); + if ( VmbErrorSuccess == err + && 0 < nCount ) + { + pCameras = (VmbCameraInfo_t*)malloc( nCount * sizeof( *pCameras )); + if ( NULL != pCameras ) + { + // Actually query all static details of all known cameras without having to open the cameras + // If a new camera was connected since we queried the amount of cameras (nFoundCount > nCount) we can ignore that one + err = VmbCamerasList( pCameras, nCount, &nFoundCount, sizeof *pCameras ); + if ( VmbErrorSuccess != err + && VmbErrorMoreData != err ) + { + printf( "Could not list cameras. Error code: %d\n", err ); + } + else + { + // Use the first camera + if( nFoundCount != 0) + { + pCameraID = pCameras[0].cameraIdString; + } + else + { + pCameraID = NULL; + err = VmbErrorNotFound; + printf( "Camera lost.\n" ); + } + } + + free( pCameras ); + pCameras = NULL; + } + else + { + printf( "Could not allocate camera list.\n" ); + } + } + else + { + printf( "Could not list cameras or no cameras present. Error code: %d\n", err ); + } + } + + if ( NULL != pCameraID ) + { + // Open camera + err = VmbCameraOpen( pCameraID, cameraAccessMode, &cameraHandle ); + if ( VmbErrorSuccess == err ) + { + printf( "Camera ID: %s\n\n", pCameraID ); + + // Set the GeV packet size to the highest possible value + // (In this example we do not test whether this cam actually is a GigE cam) + if ( VmbErrorSuccess == VmbFeatureCommandRun( cameraHandle, "GVSPAdjustPacketSize" )) + { + do + { + if ( VmbErrorSuccess != VmbFeatureCommandIsDone( cameraHandle, + "GVSPAdjustPacketSize", + &bIsCommandDone )) + { + break; + } + } while ( VmbBoolFalse == bIsCommandDone ); + } + + if ( VmbErrorSuccess == err ) + { + // Set pixel format. For the sake of simplicity we only support Mono and RGB in this example. + err = VmbFeatureEnumSet( cameraHandle, "PixelFormat", "RGB8Packed" ); + if ( VmbErrorSuccess != err ) + { + // Fall back to Mono + err = VmbFeatureEnumSet( cameraHandle, "PixelFormat", "Mono8" ); + } + // Read back pixel format + VmbFeatureEnumGet( cameraHandle, "PixelFormat", &pPixelFormat ); + + if ( VmbErrorSuccess == err ) + { + // Evaluate frame size + err = VmbFeatureIntGet( cameraHandle, "PayloadSize", &nPayloadSize ); + if ( VmbErrorSuccess == err ) + { + frame.buffer = (unsigned char*)malloc( (VmbUint32_t)nPayloadSize ); + frame.bufferSize = (VmbUint32_t)nPayloadSize; + + // Announce Frame + err = VmbFrameAnnounce( cameraHandle, &frame, (VmbUint32_t)sizeof( VmbFrame_t )); + if ( VmbErrorSuccess == err ) + { + // Start Capture Engine + err = VmbCaptureStart( cameraHandle ); + if ( VmbErrorSuccess == err ) + { + // Queue Frame + err = VmbCaptureFrameQueue( cameraHandle, &frame, NULL ); + if ( VmbErrorSuccess == err ) + { + // Start Acquisition + err = VmbFeatureCommandRun( cameraHandle,"AcquisitionStart" ); + if ( VmbErrorSuccess == err ) + { + // Capture one frame synchronously + err = VmbCaptureFrameWait( cameraHandle, &frame, nTimeout ); + if ( VmbErrorSuccess == err ) + { + // Convert the captured frame to a bitmap and save to disk + if ( VmbFrameStatusComplete == frame.receiveStatus ) + { + bitmap.bufferSize = frame.imageSize; + bitmap.width = frame.width; + bitmap.height = frame.height; + // We only support Mono and RGB in this example + if ( 0 == strcmp( "RGB8Packed", pPixelFormat )) + { + bitmap.colorCode = ColorCodeRGB24; + } + else + { + bitmap.colorCode = ColorCodeMono8; + } + + // Create the bitmap + if ( 0 == AVTCreateBitmap( &bitmap, frame.buffer )) + { + printf( "Could not create bitmap.\n" ); + } + else + { + // Save the bitmap + if ( 0 == AVTWriteBitmapToFile( &bitmap, pFileName )) + { + printf( "Could not write bitmap to file.\n" ); + } + else + { + printf( "Bitmap successfully written to file \"%s\"\n", pFileName ); + // Release the bitmap's buffer + if ( 0 == AVTReleaseBitmap( &bitmap )) + { + printf( "Could not release the bitmap.\n" ); + } + } + } + } + else + { + printf( "Frame not successfully received. Error code: %d\n", frame.receiveStatus ); + } + } + else + { + printf( "Could not capture frame. Error code: %d\n", err ); + } + + // Stop Acquisition + err = VmbFeatureCommandRun( cameraHandle,"AcquisitionStop" ); + if ( VmbErrorSuccess != err ) + { + printf( "Could not stop acquisition. Error code: %d\n", err ); + } + } + else + { + printf( "Could not start acquisition. Error code: %d\n", err ); + } + } + else + { + printf( "Could not queue frame. Error code: %d\n", err ); + } + + // Stop Capture Engine + err = VmbCaptureEnd( cameraHandle ); + if ( VmbErrorSuccess != err ) + { + printf( "Could not end capture. Error code: %d\n", err ); + } + } + else + { + printf( "Could not start capture. Error code: %d\n", err ); + } + + // Revoke frame + err = VmbFrameRevoke( cameraHandle, &frame ); + if ( VmbErrorSuccess != err ) + { + printf( "Could not revoke frame. Error code: %d\n", err ); + } + } + else + { + printf( "Could not announce frame. Error code: %d\n", err ); + } + + free( frame.buffer ); + frame.buffer = NULL; + } + } + else + { + printf( "Could not set pixel format to either RGB or Mono. Error code: %d\n", err ); + } + } + else + { + printf( "Could not adjust packet size. Error code: %d\n", err ); + } + + err = VmbCameraClose ( cameraHandle ); + if ( VmbErrorSuccess != err ) + { + printf( "Could not close camera. Error code: %d\n", err ); + } + } + else + { + printf( "Could not open camera. Error code: %d\n", err ); + } + } + VmbShutdown(); + } + else + { + printf( "Could not start system. Error code: %d\n", err ); + } + + return err; +} diff --git a/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/SynchronousGrab.h b/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/SynchronousGrab.h new file mode 100644 index 0000000..6b7450b --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/SynchronousGrab.h @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: SynchronousGrab.h + + Description: The SynchronousGrab example will grab a single image + synchronously and save it to a file using VimbaC. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef SYNCHRONOUS_GRAB_H_ +#define SYNCHRONOUS_GRAB_H_ + +#include + +// +// Starts Vimba API +// Opens the given camera, if no camera ID was provided, the first camera found will be used +// Sets the maximum possible Ethernet packet size +// Adjusts the image format +// Acquires one image synchronously +// Writes the image as bitmap to file +// Closes the camera in case of failure +// +// Parameters: +// [in] pCameraID The ID of the camera to work on. Can be NULL. +// [in] pFileName The path of the bitmap where the image is saved to +// +// Returns: +// An API status code +// +VmbError_t SynchronousGrab ( const char* pCameraID, const char* pFileName ); + +#endif diff --git a/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/program.c b/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/program.c new file mode 100644 index 0000000..d4e222a --- /dev/null +++ b/Vimba_6_0/VimbaC/Examples/SynchronousGrab/Source/program.c @@ -0,0 +1,159 @@ +/*============================================================================= + Copyright (C) 2012 - 2013 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: Implementation of main entry point of SynchronousGrab example of + VimbaC. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include + +#include + +unsigned char StartsWith(const char *pString, const char *pStart) +{ + if(NULL == pString) + { + return 0; + } + if(NULL == pStart) + { + return 0; + } + + if(strlen(pString) < strlen(pStart)) + { + return 0; + } + + if(memcmp(pString, pStart, strlen(pStart)) != 0) + { + return 0; + } + + return 1; +} + +int main( int argc, char* argv[] ) +{ + VmbError_t err = VmbErrorSuccess; + + char* pCameraID = NULL; // The ID of the camera to use + const char* pFileName = NULL; // The filename for the bitmap to save + unsigned char bPrintHelp = 0; // Output help? + int i = 0; // Counter for some iteration + char* pParameter = 0; // The command line parameter + + printf( "//////////////////////////////////////////\n" ); + printf( "/// Vimba API Synchronous Grab Example ///\n" ); + printf( "//////////////////////////////////////////\n\n" ); + + ////////////////////// + //Parse command line// + ////////////////////// + + for( i = 1; i < argc; ++i ) + { + pParameter = argv[i]; + if( 0 > strlen( pParameter )) + { + err = VmbErrorBadParameter; + break; + } + + if( '/' == pParameter[0] ) + { + if( StartsWith( pParameter, "/f:" )) + { + if( NULL != pFileName ) + { + err = VmbErrorBadParameter; + break; + } + + pFileName = pParameter + 3; + if( 0 >= strlen( pFileName )) + { + err = VmbErrorBadParameter; + break; + } + } + else if( 0 == strcmp( pParameter, "/h" )) + { + if( ( NULL != pCameraID ) + || ( NULL != pFileName ) + || ( bPrintHelp )) + { + err = VmbErrorBadParameter; + break; + } + + bPrintHelp = 1; + } + else + { + err = VmbErrorBadParameter; + break; + } + } + else + { + if( NULL != pCameraID ) + { + err = VmbErrorBadParameter; + break; + } + + pCameraID = pParameter; + } + } + + //Write out an error if we could not parse the command line + if ( VmbErrorBadParameter == err ) + { + printf( "Invalid parameters!\n\n" ); + bPrintHelp = 1; + } + + //Print out help and end program + if ( bPrintHelp ) + { + printf( "Usage: SynchronousGrab [CameraID] [/h] [/f:FileName]\n" ); + printf( "Parameters: CameraID ID of the camera to use (using first camera if not specified)\n" ); + printf( " /h Print out help\n" ); + printf( " /f:FileName File name for operation\n" ); + printf( " (default \"SynchronousGrab.bmp/.dat\" if not specified)\n" ); + } + else + { + if ( NULL == pFileName ) + { + pFileName = "SynchronousGrab.bmp"; + } + + err = SynchronousGrab( pCameraID, pFileName ); + } + + return err; +} diff --git a/Vimba_6_0/VimbaC/Include/VimbaC.h b/Vimba_6_0/VimbaC/Include/VimbaC.h new file mode 100644 index 0000000..a942706 --- /dev/null +++ b/Vimba_6_0/VimbaC/Include/VimbaC.h @@ -0,0 +1,1954 @@ +/*============================================================================= + Copyright (C) 2012 - 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this header file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: VimbaC.h + + Description: Main header file for the VimbaC API. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef VIMBAC_H_INCLUDE_ +#define VIMBAC_H_INCLUDE_ + +// This file describes all necessary definitions for using Allied Vision's +// VimbaC API. These type definitions are designed to be portable from other +// languages and other operating systems. +// +// General conventions: +// - Method names are composed in the following manner: +// - Vmb"Action" example: VmbStartup() +// - Vmb"Entity""Action" or Vmb"ActionTarget""Action" example: VmbInterfaceOpen() +// - Vmb"Entity""SubEntity/ActionTarget""Action" example: VmbFeatureCommandRun() +// - Methods dealing with features, memory or registers accept a handle from the following +// entity list as first parameter: System, Camera, Interface and AncillaryData. +// All other methods taking handles accept only a specific handle. +// - Strings (generally declared as "const char *") are assumed to have a trailing 0 character +// - All pointer parameters should of course be valid, except if stated otherwise. +// - To ensure compatibility with older programs linked against a former version of the API, +// all struct* parameters have an accompanying sizeofstruct parameter. +// - Functions returning lists are usually called twice: once with a zero buffer +// to get the length of the list, and then again with a buffer of the correct length. + +//===== #DEFINES ============================================================== + +#if defined (_WIN32) + #if defined AVT_VMBAPI_C_EXPORTS // DLL exports + #define IMEXPORTC /*__declspec(dllexport) HINT: We export via the .def file */ + #elif defined AVT_VMBAPI_C_LIB // static LIB + #define IMEXPORTC + #else // import + #define IMEXPORTC __declspec(dllimport) + #endif + + #ifndef _WIN64 + // Calling convention + #define VMB_CALL __stdcall + #else + // Calling convention + #define VMB_CALL + #endif +#elif defined (__GNUC__) && (__GNUC__ >= 4) && defined (__ELF__) + // SO exports (requires compiler option -fvisibility=hidden) + #ifdef AVT_VMBAPI_C_EXPORTS + #define IMEXPORTC __attribute__((visibility("default"))) + #else + #define IMEXPORTC + #endif + + #ifdef __i386__ + // Calling convention + #define VMB_CALL __attribute__((stdcall)) + #else + // Calling convention + #define VMB_CALL + #endif +#elif defined (__APPLE__) + #define IMEXPORTC __attribute__((visibility("default"))) + // Calling convention + #define VMB_CALL +#else + #error Unknown platform, file needs adaption +#endif + +//===== TYPES ============================================================== +#include "VmbCommonTypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Timeout parameter signaling a blocking call +#define VMBINFINITE 0xFFFFFFFF + +// Constant for the Vimba handle to be able to access Vimba system features +static const VmbHandle_t gVimbaHandle = (VmbHandle_t)1; + +// +// Camera interface type (for instance FireWire, Ethernet); +// +typedef enum VmbInterfaceType +{ + VmbInterfaceUnknown = 0, // Interface is not known to this version of the API + VmbInterfaceFirewire = 1, // 1394 + VmbInterfaceEthernet = 2, // GigE + VmbInterfaceUsb = 3, // USB 3.0 + VmbInterfaceCL = 4, // Camera Link + VmbInterfaceCSI2 = 5, // CSI-2 +} VmbInterfaceType; +typedef VmbUint32_t VmbInterface_t; // Type for an Interface; for values see VmbInterfaceType + +// +// Access mode for configurable devices (interfaces, cameras). +// Used in VmbCameraInfo_t, VmbInterfaceInfo_t as flags, so multiple modes can be +// announced, while in VmbCameraOpen(), no combination must be used. +// +typedef enum VmbAccessModeType +{ + VmbAccessModeNone = 0, // No access + VmbAccessModeFull = 1, // Read and write access + VmbAccessModeRead = 2, // Read-only access + VmbAccessModeConfig = 4, // Configuration access (GeV) + VmbAccessModeLite = 8, // Read and write access without feature access (only addresses) +} VmbAccessModeType; +typedef VmbUint32_t VmbAccessMode_t; // Type for an AccessMode; for values see VmbAccessModeType + +// +// Interface information. +// Holds read-only information about an interface. +// +typedef struct +{ + const char* interfaceIdString; // Unique identifier for each interface + VmbInterface_t interfaceType; // Interface type, see VmbInterfaceType + const char* interfaceName; // Interface name, given by the transport layer + const char* serialString; // Serial number + VmbAccessMode_t permittedAccess; // Used access mode, see VmbAccessModeType +} VmbInterfaceInfo_t; + +// +// Camera information. +// Holds read-only information about a camera. +// +typedef struct +{ + const char* cameraIdString; // Unique identifier for each camera + const char* cameraName; // Name of the camera + const char* modelName; // Model name + const char* serialString; // Serial number + VmbAccessMode_t permittedAccess; // Used access mode, see VmbAccessModeType + const char* interfaceIdString; // Unique value for each interface or bus +} VmbCameraInfo_t; + +// +// Supported feature data types +// +typedef enum VmbFeatureDataType +{ + VmbFeatureDataUnknown = 0, // Unknown feature type + VmbFeatureDataInt = 1, // 64 bit integer feature + VmbFeatureDataFloat = 2, // 64 bit floating point feature + VmbFeatureDataEnum = 3, // Enumeration feature + VmbFeatureDataString = 4, // String feature + VmbFeatureDataBool = 5, // Boolean feature + VmbFeatureDataCommand = 6, // Command feature + VmbFeatureDataRaw = 7, // Raw (direct register access) feature + VmbFeatureDataNone = 8, // Feature with no data +} VmbFeatureDataType; +typedef VmbUint32_t VmbFeatureData_t; // Data type for a Feature; for values see VmbFeatureDataType + +// +// Feature visibility +// +typedef enum VmbFeatureVisibilityType +{ + VmbFeatureVisibilityUnknown = 0, // Feature visibility is not known + VmbFeatureVisibilityBeginner = 1, // Feature is visible in feature list (beginner level) + VmbFeatureVisibilityExpert = 2, // Feature is visible in feature list (expert level) + VmbFeatureVisibilityGuru = 3, // Feature is visible in feature list (guru level) + VmbFeatureVisibilityInvisible = 4, // Feature is not visible in feature list +} VmbFeatureVisibilityType; +typedef VmbUint32_t VmbFeatureVisibility_t; // Type for Feature visibility; for values see VmbFeatureVisibilityType + +// +// Feature flags +// +typedef enum VmbFeatureFlagsType +{ + VmbFeatureFlagsNone = 0, // No additional information is provided + VmbFeatureFlagsRead = 1, // Static info about read access. Current status depends on access mode, check with VmbFeachtureAccessQuery() + VmbFeatureFlagsWrite = 2, // Static info about write access. Current status depends on access mode, check with VmbFeachtureAccessQuery() + VmbFeatureFlagsVolatile = 8, // Value may change at any time + VmbFeatureFlagsModifyWrite = 16, // Value may change after a write +} VmbFeatureFlagsType; +typedef VmbUint32_t VmbFeatureFlags_t; // Type for Feature flags; for values see VmbFeatureFlagsType + +// +// Feature information. +// Holds read-only information about a feature. +// +typedef struct VmbFeatureInfo +{ + const char* name; // Name used in the API + VmbFeatureData_t featureDataType; // Data type of this feature + VmbFeatureFlags_t featureFlags; // Access flags for this feature + const char* category; // Category this feature can be found in + const char* displayName; // Feature name to be used in GUIs + VmbUint32_t pollingTime; // Predefined polling time for volatile features + const char* unit; // Measuring unit as given in the XML file + const char* representation; // Representation of a numeric feature + VmbFeatureVisibility_t visibility; // GUI visibility + const char* tooltip; // Short description, e.g. for a tooltip + const char* description; // Longer description + const char* sfncNamespace; // Namespace this feature resides in + VmbBool_t isStreamable; // Indicates if a feature can be stored to / loaded from a file + VmbBool_t hasAffectedFeatures; // Indicates if the feature potentially affects other features + VmbBool_t hasSelectedFeatures; // Indicates if the feature selects other features +} VmbFeatureInfo_t; + +// +// Info about possible entries of an enumeration feature +// +typedef struct VmbFeatureEnumEntry +{ + const char* name; // Name used in the API + const char* displayName; // Enumeration entry name to be used in GUIs + VmbFeatureVisibility_t visibility; // GUI visibility + const char* tooltip; // Short description, e.g. for a tooltip + const char* description; // Longer description + const char* sfncNamespace; // Namespace this feature resides in + VmbInt64_t intValue; // Integer value of this enumeration entry +} VmbFeatureEnumEntry_t; + +// +// Status of a frame transfer +// +typedef enum VmbFrameStatusType +{ + VmbFrameStatusComplete = 0, // Frame has been completed without errors + VmbFrameStatusIncomplete = -1, // Frame could not be filled to the end + VmbFrameStatusTooSmall = -2, // Frame buffer was too small + VmbFrameStatusInvalid = -3, // Frame buffer was invalid +} VmbFrameStatusType; +typedef VmbInt32_t VmbFrameStatus_t; // Type for the frame status; for values see VmbFrameStatusType + +// +// Frame flags +// +typedef enum VmbFrameFlagsType +{ + VmbFrameFlagsNone = 0, // No additional information is provided + VmbFrameFlagsDimension = 1, // Frame's dimension is provided + VmbFrameFlagsOffset = 2, // Frame's offset is provided (ROI) + VmbFrameFlagsFrameID = 4, // Frame's ID is provided + VmbFrameFlagsTimestamp = 8, // Frame's timestamp is provided +} VmbFrameFlagsType; +typedef VmbUint32_t VmbFrameFlags_t; // Type for Frame flags; for values see VmbFrameFlagsType + +// +// Frame delivered by the camera +// +typedef struct +{ + //----- In ----- + void* buffer; // Comprises image and ancillary data + VmbUint32_t bufferSize; // Size of the data buffer + + void* context[4]; // 4 void pointers that can be employed by the user (e.g. for storing handles) + + //----- Out ----- + VmbFrameStatus_t receiveStatus; // Resulting status of the receive operation + VmbFrameFlags_t receiveFlags; // Flags indicating which additional frame information is available + + VmbUint32_t imageSize; // Size of the image data inside the data buffer + VmbUint32_t ancillarySize; // Size of the ancillary data inside the data buffer + + VmbPixelFormat_t pixelFormat; // Pixel format of the image + + VmbUint32_t width; // Width of an image + VmbUint32_t height; // Height of an image + VmbUint32_t offsetX; // Horizontal offset of an image + VmbUint32_t offsetY; // Vertical offset of an image + + VmbUint64_t frameID; // Unique ID of this frame in this stream + VmbUint64_t timestamp; // Timestamp set by the camera +} VmbFrame_t; + +// +// Type of features that are to be saved (persisted) to the XML file when using VmbCameraSettingsSave +// +typedef enum VmbFeaturePersistType +{ + VmbFeaturePersistAll = 0, // Save all features to XML, including look-up tables + VmbFeaturePersistStreamable = 1, // Save only features marked as streamable, excluding look-up tables + VmbFeaturePersistNoLUT = 2 // Save all features except look-up tables (default) +} VmbFeaturePersistType; +typedef VmbUint32_t VmbFeaturePersist_t; // Type for feature persistence; for values see VmbFeaturePersistType + +// +// Parameters determining the operation mode of VmbCameraSettingsSave and VmbCameraSettingsLoad +// +typedef struct +{ + VmbFeaturePersist_t persistType; // Type of features that are to be saved + VmbUint32_t maxIterations; // Number of iterations when loading settings + VmbUint32_t loggingLevel; // Determines level of detail for load/save settings logging +} VmbFeaturePersistSettings_t; + + +// ----- Callbacks ------------------------------------------------------------ + +// +// Name: VmbInvalidationCallback +// +// Purpose: Invalidation Callback type for a function that gets called in a separate thread +// and has been registered with VmbFeatureInvalidationRegister() +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [in ] void* pUserContext Pointer to the user context, see VmbFeatureInvalidationRegister +// +// Details: While the callback is run, all feature data is atomic. After the +// callback finishes, the feature data might be updated with new values. +// +// Note: Do not spend too much time in this thread; it will prevent the feature values +// from being updated from any other thread or the lower-level drivers. +// +typedef void (VMB_CALL *VmbInvalidationCallback)( const VmbHandle_t handle, const char* name, void* pUserContext ); + +// +// Name: VmbFrameCallback +// +// Purpose: Frame Callback type for a function that gets called in a separate thread +// if a frame has been queued with VmbCaptureFrameQueue() +// +// Parameters: +// +// [in ] const VmbHandle_t cameraHandle Handle of the camera +// [out] VmbFrame_t* pFrame Frame completed +// +typedef void (VMB_CALL *VmbFrameCallback)( const VmbHandle_t cameraHandle, VmbFrame_t* pFrame ); + + +//===== FUNCTION PROTOTYPES =================================================== + +//----- API Version ----------------------------------------------------------- + +// +// Method: VmbVersionQuery() +// +// Purpose: Retrieve the version number of VimbaC. +// +// Parameters: +// +// [out] VmbVersionInfo_t* pVersionInfo Pointer to the struct where version information +// is copied +// [in ] VmbUint32_t sizeofVersionInfo Size of structure in bytes +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorStructSize: The given struct size is not valid for this version of the API +// - VmbErrorBadParameter: If "pVersionInfo" is NULL. +// +// Details: This function can be called at anytime, even before the API is +// initialized. All other version numbers may be queried via feature access. +// +IMEXPORTC VmbError_t VMB_CALL VmbVersionQuery ( VmbVersionInfo_t* pVersionInfo, + VmbUint32_t sizeofVersionInfo ); + + +//----- API Initialization ---------------------------------------------------- + +// +// Method: VmbStartup() +// +// Purpose: Initialize the VimbaC API. +// +// Parameters: +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorInternalFault: An internal fault occurred +// +// Details: On successful return, the API is initialized; this is a necessary call. +// +// Note: This method must be called before any VimbaC function other than VmbVersionQuery() is run. +// +IMEXPORTC VmbError_t VMB_CALL VmbStartup ( void ); + +// +// Method: VmbShutdown() +// +// Purpose: Perform a shutdown on the API. +// +// Parameters: none +// +// Returns: none +// +// Details: This will free some resources and deallocate all physical resources if applicable. +// +IMEXPORTC void VMB_CALL VmbShutdown ( void ); + + +//----- Camera Enumeration & Information -------------------------------------- + +// +// Method: VmbCamerasList() +// +// Purpose: Retrieve a list of all cameras. +// +// Parameters: +// +// [out] VmbCameraInfo_t* pCameraInfo Array of VmbCameraInfo_t, allocated by +// the caller. The camera list is +// copied here. May be NULL if pNumFound is used for size query. +// [in ] VmbUint32_t listLength Number of VmbCameraInfo_t elements provided +// [out] VmbUint32_t* pNumFound Number of VmbCameraInfo_t elements found. +// [in ] VmbUint32_t sizeofCameraInfo Size of the structure (if pCameraInfo == NULL this parameter is ignored) +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorStructSize: The given struct size is not valid for this API version +// - VmbErrorMoreData: The given list length was insufficient to hold all available entries +// - VmbErrorBadParameter: If "pNumFound" was NULL +// +// Details: Camera detection is started with the registration of the "DiscoveryCameraEvent" +// event or the first call of VmbCamerasList(), which may be delayed if no +// "DiscoveryCameraEvent" event is registered (see examples). +// VmbCamerasList() is usually called twice: once with an empty array to query the +// list length, and then again with an array of the correct length. If camera +// lists change between the calls, pNumFound may deviate from the query return. +// +IMEXPORTC VmbError_t VMB_CALL VmbCamerasList ( VmbCameraInfo_t* pCameraInfo, + VmbUint32_t listLength, + VmbUint32_t* pNumFound, + VmbUint32_t sizeofCameraInfo ); + +// +// Method: VmbCameraInfoQuery() +// +// Purpose: Retrieve information on a camera given by an ID. +// +// Parameters: +// +// [in ] const char* idString ID of the camera +// [out] VmbCameraInfo_t* pInfo Structure where information will be copied. May be NULL. +// [in ] VmbUint32_t sizeofCameraInfo Size of the structure +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorNotFound: The designated camera cannot be found +// - VmbErrorStructSize: The given struct size is not valid for this API version +// - VmbErrorBadParameter: If "idString" was NULL +// +// Details: May be called if a camera has not been opened by the application yet. +// Examples for "idString": +// "DEV_81237473991" for an ID given by a transport layer, +// "169.254.12.13" for an IP address, +// "000F314C4BE5" for a MAC address or +// "DEV_1234567890" for an ID as reported by Vimba +// +IMEXPORTC VmbError_t VMB_CALL VmbCameraInfoQuery ( const char* idString, + VmbCameraInfo_t* pInfo, + VmbUint32_t sizeofCameraInfo ); + +// +// Method: VmbCameraOpen() +// +// Purpose: Open the specified camera. +// +// Parameters: +// +// [in ] const char* idString ID of the camera +// [in ] VmbAccessMode_t accessMode Determines the level of control you have on the camera +// [out] VmbHandle_t* pCameraHandle A camera handle +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorNotFound: The designated camera cannot be found +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorInvalidCall: If called from frame callback +// - VmbErrorBadParameter: If "idString" or "pCameraHandle" is NULL +// +// Details: A camera may be opened in a specific access mode, which determines +// the level of control you have on a camera. +// Examples for "idString": +// "DEV_81237473991" for an ID given by a transport layer, +// "169.254.12.13" for an IP address, +// "000F314C4BE5" for a MAC address or +// "DEV_1234567890" for an ID as reported by Vimba +// +IMEXPORTC VmbError_t VMB_CALL VmbCameraOpen ( const char* idString, + VmbAccessMode_t accessMode, + VmbHandle_t* pCameraHandle ); + +// +// Method: VmbCameraClose() +// +// Purpose: Close the specified camera. +// +// Parameters: +// +// [in ] const VmbHandle_t cameraHandle A valid camera handle +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorInvalidCall: If called from frame callback +// +// Details: Depending on the access mode this camera was opened with, events are killed, +// callbacks are unregistered, and camera control is released. +// +IMEXPORTC VmbError_t VMB_CALL VmbCameraClose ( const VmbHandle_t cameraHandle ); + + +//----- Features ---------------------------------------------------------- + +// +// Method: VmbFeaturesList() +// +// Purpose: List all the features for this entity. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [out] VmbFeatureInfo_t* pFeatureInfoList An array of VmbFeatureInfo_t to be filled by the API. May be NULL if pNumFund is used for size query. +// [in ] VmbUint32_t listLength Number of VmbFeatureInfo_t elements provided +// [out] VmbUint32_t* pNumFound Number of VmbFeatureInfo_t elements found. May be NULL if pFeatureInfoList is not NULL. +// [in ] VmbUint32_t sizeofFeatureInfo Size of a VmbFeatureInfo_t entry +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorStructSize: The given struct size of VmbFeatureInfo_t is not valid for this version of the API +// - VmbErrorMoreData: The given list length was insufficient to hold all available entries +// +// Details: This method lists all implemented features, whether they are currently available or not. +// The list of features does not change as long as the camera/interface is connected. +// "pNumFound" returns the number of VmbFeatureInfo elements. +// This function is usually called twice: once with an empty list to query the length +// of the list, and then again with an list of the correct length. +// +// +IMEXPORTC VmbError_t VMB_CALL VmbFeaturesList ( const VmbHandle_t handle, + VmbFeatureInfo_t* pFeatureInfoList, + VmbUint32_t listLength, + VmbUint32_t* pNumFound, + VmbUint32_t sizeofFeatureInfo ); + +// +// Method: VmbFeatureInfoQuery() +// +// Purpose: Query information about the constant properties of a feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [out] VmbFeatureInfo_t* pFeatureInfo The feature info to query +// [in ] VmbUint32_t sizeofFeatureInfo Size of the structure +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorStructSize: The given struct size is not valid for this version of the API +// +// Details: Users provide a pointer to VmbFeatureInfo_t, which is then set to the internal representation. +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureInfoQuery ( const VmbHandle_t handle, + const char* name, + VmbFeatureInfo_t* pFeatureInfo, + VmbUint32_t sizeofFeatureInfo ); + +// +// Method: VmbFeatureListAffected() +// +// Purpose: List all the features that might be affected by changes to this feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [out] VmbFeatureInfo_t* pFeatureInfoList An array of VmbFeatureInfo_t to be filled by the API. May be NULL if pNumFound is used for size query. +// [in ] VmbUint32_t listLength Number of VmbFeatureInfo_t elements provided +// [out] VmbUint32_t* pNumFound Number of VmbFeatureInfo_t elements found. May be NULL is pFeatureInfoList is not NULL. +// [in ] VmbUint32_t sizeofFeatureInfo Size of a VmbFeatureInfo_t entry +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorStructSize: The given struct size of VmbFeatureInfo_t is not valid for this version of the API +// - VmbErrorMoreData: The given list length was insufficient to hold all available entries +// +// Details: This method lists all affected features, whether they are currently available or not. +// The value of affected features depends directly or indirectly on this feature +// (including all selected features). +// The list of features does not change as long as the camera/interface is connected. +// This function is usually called twice: once with an empty array to query the length +// of the list, and then again with an array of the correct length. +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureListAffected ( const VmbHandle_t handle, + const char* name, + VmbFeatureInfo_t* pFeatureInfoList, + VmbUint32_t listLength, + VmbUint32_t* pNumFound, + VmbUint32_t sizeofFeatureInfo ); + +// +// Method: VmbFeatureListSelected() +// +// Purpose: List all the features selected by a given feature for this module. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [out] VmbFeatureInfo_t* pFeatureInfoList An array of VmbFeatureInfo_t to be filled by the API. May be NULL if pNumFound is used for size query. +// [in ] VmbUint32_t listLength Number of VmbFeatureInfo_t elements provided +// [out] VmbUint32_t* pNumFound Number of VmbFeatureInfo_t elements found. May be NULL if pFeatureInfoList is not NULL. +// [in ] VmbUint32_t sizeofFeatureInfo Size of a VmbFeatureInfo_t entry +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorStructSize: The given struct size is not valid for this version of the API +// - VmbErrorMoreData: The given list length was insufficient to hold all available entries +// +// Details: This method lists all selected features, whether they are currently available or not. +// Features with selected features ("selectors") have no direct impact on the camera, +// but only influence the register address that selected features point to. +// The list of features does not change while the camera/interface is connected. +// This function is usually called twice: once with an empty array to query the length +// of the list, and then again with an array of the correct length. +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureListSelected ( const VmbHandle_t handle, + const char* name, + VmbFeatureInfo_t* pFeatureInfoList, + VmbUint32_t listLength, + VmbUint32_t* pNumFound, + VmbUint32_t sizeofFeatureInfo ); + +// +// Method: VmbFeatureAccessQuery() +// +// Purpose: Return the dynamic read and write capabilities of this feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features. +// [in ] const char * name Name of the feature. +// [out] VmbBool_t * pIsReadable Indicates if this feature is readable. May be NULL. +// [out] VmbBool_t * pIsWriteable Indicates if this feature is writable. May be NULL. +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorBadParameter: If "pIsReadable" and "pIsWriteable" were both NULL +// - VmbErrorNotFound: The feature was not found +// +// Details: The access mode of a feature may change. For example, if "PacketSize" +// is locked while image data is streamed, it is only readable. +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureAccessQuery ( const VmbHandle_t handle, + const char* name, + VmbBool_t * pIsReadable, + VmbBool_t * pIsWriteable ); + + +//-----Integer -------- + +// +// Method: VmbFeatureIntGet() +// +// Purpose: Get the value of an integer feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [out] VmbInt64_t* pValue Value to get +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Integer +// - VmbErrorNotFound: The feature was not found +// - VmbErrorBadParameter: If "name" or "pValue" is NULL +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureIntGet ( const VmbHandle_t handle, + const char* name, + VmbInt64_t* pValue ); + +// +// Method: VmbFeatureIntSet() +// +// Purpose: Set the value of an integer feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [in ] VmbInt64_t value Value to set +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Integer +// - VmbErrorInvalidValue: If "value" is either out of bounds or not an increment of the minimum +// - VmbErrorBadParameter: If "name" is NULL +// - VmbErrorNotFound: If the feature was not found +// - VmbErrorInvalidCall: If called from frame callback +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureIntSet ( const VmbHandle_t handle, + const char* name, + VmbInt64_t value ); + +// +// Method: VmbFeatureIntRangeQuery() +// +// Purpose: Query the range of an integer feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [out] VmbInt64_t* pMin Minimum value to be returned. May be NULL. +// [out] VmbInt64_t* pMax Maximum value to be returned. May be NULL. +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorBadParameter: If "name" is NULL or "pMin" and "pMax" are NULL +// - VmbErrorWrongType: The type of feature "name" is not Integer +// - VmbErrorNotFound: If the feature was not found +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureIntRangeQuery ( const VmbHandle_t handle, + const char* name, + VmbInt64_t* pMin, + VmbInt64_t* pMax ); + +// +// Method: VmbFeatureIntIncrementQuery() +// +// Purpose: Query the increment of an integer feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [out] VmbInt64_t* pValue Value of the increment to get. +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Integer +// - VmbErrorNotFound: The feature was not found +// VmbErrorBadParameter: If "name" or "pValue" is NULL +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureIntIncrementQuery ( const VmbHandle_t handle, + const char* name, + VmbInt64_t* pValue ); + +//-----Float -------- + +// +// Method: VmbFeatureFloatGet() +// +// Purpose: Get the value of a float feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [out] double* pValue Value to get +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Float +// - VmbErrorBadParameter: If "name" or "pValue" is NULL +// - VmbErrorNotFound: The feature was not found +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureFloatGet ( const VmbHandle_t handle, + const char* name, + double* pValue ); + +// +// Method: VmbFeatureFloatSet() +// +// Purpose: Set the value of a float feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [in ] double value Value to set +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Float +// - VmbErrorInvalidValue: If "value" is not within valid bounds +// - VmbErrorNotFound: The feature was not found +// - VmbErrorBadParameter: If "name" is NULL +// - VmbErrorInvalidCall: If called from frame callback +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureFloatSet ( const VmbHandle_t handle, + const char* name, + double value ); + +// +// Method: VmbFeatureFloatRangeQuery() +// +// Purpose: Query the range of a float feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [out] double* pMin Minimum value to be returned. May be NULL. +// [out] double* pMax Maximum value to be returned. May be NULL. +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Float +// - VmbErrorNotFound: The feature was not found +// - VmbBadParameter: If "name" is NULL or "pMin" and "pMax" are NULL +// +// Details: Only one of the values may be queried if the other parameter is set to NULL, +// but if both parameters are NULL, an error is returned. +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureFloatRangeQuery ( const VmbHandle_t handle, + const char* name, + double* pMin, + double* pMax ); + +// +// Method: VmbFeatureFloatIncrementQuery() +// +// Purpose: Query the increment of an float feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [out] VmbBool_t * pHasIncrement "true" if this float feature has an increment. +// [out] double* pValue Value of the increment to get. +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Integer +// - VmbErrorNotFound: The feature was not found +// VmbErrorBadParameter: If "name" or "pValue" is NULL +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureFloatIncrementQuery ( const VmbHandle_t handle, + const char* name, + VmbBool_t* pHasIncrement, + double* pValue ); +//-----Enum -------- + +// +// Method: VmbFeatureEnumGet() +// +// Purpose: Get the value of an enumeration feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [out] const char** pValue The current enumeration value. The returned value +// is a reference to the API value +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Enumeration +// - VmbErrorNotFound: The feature was not found +// - VmbErrorBadParameter: If "name" or "pValue" is NULL +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureEnumGet ( const VmbHandle_t handle, + const char* name, + const char** pValue ); + +// +// Method: VmbFeatureEnumSet() +// +// Purpose: Set the value of an enumeration feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [in ] const char* value Value to set +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Enumeration +// - VmbErrorInvalidValue: If "value" is not within valid bounds +// - VmbErrorNotFound: The feature was not found +// - VmbErrorBadParameter: If "name" ore "value" is NULL +// - VmbErrorInvalidCall: If called from frame callback +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureEnumSet ( const VmbHandle_t handle, + const char* name, + const char* value ); + +// +// Method: VmbFeatureEnumRangeQuery() +// +// Purpose: Query the value range of an enumeration feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [out] const char** pNameArray An array of enumeration value names; may be NULL if pNumFilled is used for size query +// [in ] VmbUint32_t arrayLength Number of elements in the array +// [out] VmbUint32_t * pNumFilled Number of filled elements; may be NULL if pNameArray is not NULL +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorMoreData: The given array length was insufficient to hold all available entries +// - VmbErrorWrongType: The type of feature "name" is not Enumeration +// - VmbErrorNotFound: The feature was not found +// - VmbErrorBadParameter: If "name" is NULL or "pNameArray" and "pNumFilled" are NULL +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureEnumRangeQuery ( const VmbHandle_t handle, + const char* name, + const char** pNameArray, + VmbUint32_t arrayLength, + VmbUint32_t* pNumFilled ); + +// +// Method: VmbFeatureEnumIsAvailable() +// +// Purpose: Check if a certain value of an enumeration is available. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [in ] const char* value Value to check +// [out] VmbBool_t * pIsAvailable Indicates if the given enumeration value is available +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Enumeration +// - VmbErrorNotFound: The feature was not found +// - VmbErrorBadParameter: If "name" or "value" or "pIsAvailable" is NULL +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureEnumIsAvailable ( const VmbHandle_t handle, + const char* name, + const char* value, + VmbBool_t * pIsAvailable ); + +// +// Method: VmbFeatureEnumAsInt() +// +// Purpose: Get the integer value for a given enumeration string value. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [in ] const char* value The enumeration value to get the integer value for +// [out] VmbInt64_t* pIntVal The integer value for this enumeration entry +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Enumeration +// - VmbErrorNotFound: The feature was not found +// - VmbErrorBadParameter: If "name" or "value" or "pIntVal" is NULL +// +// Details: Converts a name of an enum member into an int value ("Mono12Packed" to 0x10C0006) +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureEnumAsInt ( const VmbHandle_t handle, + const char* name, + const char* value, + VmbInt64_t* pIntVal ); + +// +// Method: VmbFeatureEnumAsString() +// +// Purpose: Get the enumeration string value for a given integer value. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the feature +// [in ] VmbInt64_t intValue The numeric value +// [out] const char** pStringValue The string value for the numeric value +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Enumeration +// - VmbErrorNotFound: The feature was not found +// - VmbErrorBadParameter: If "name" or "pStringValue" is NULL +// +// Details: Converts an int value to a name of an enum member (e.g. 0x10C0006 to "Mono12Packed") +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureEnumAsString ( const VmbHandle_t handle, + const char* name, + VmbInt64_t intValue, + const char** pStringValue ); + +// +// Method: VmbFeatureEnumEntryGet() +// +// Purpose: Get infos about an entry of an enumeration feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* featureName Name of the feature +// [in ] const char* entryName Name of the enum entry of that feature +// [out] VmbFeatureEnumEntry_t* pFeatureEnumEntry Infos about that entry returned by the API +// [in] VmbUint32_t sizeofFeatureEnumEntry Size of the structure +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorStructSize Size of VmbFeatureEnumEntry_t is not compatible with the API version +// - VmbErrorWrongType: The type of feature "name" is not Enumeration +// - VmbErrorNotFound: The feature was not found +// - VmbErrorBadParameter: If "featureName" or "entryName" or "pFeatureEnumEntry" is NULL +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureEnumEntryGet ( const VmbHandle_t handle, + const char* featureName, + const char* entryName, + VmbFeatureEnumEntry_t* pFeatureEnumEntry, + VmbUint32_t sizeofFeatureEnumEntry ); + +//-----String -------- + +// +// Method: VmbFeatureStringGet() +// +// Purpose: Get the value of a string feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the string feature +// [out] char* buffer String buffer to fill. May be NULL if pSizeFilled is used for size query. +// [in ] VmbUint32_t bufferSize Size of the input buffer +// [out] VmbUint32_t* pSizeFilled Size actually filled. May be NULL if buffer is not NULL. +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorMoreData: The given buffer size was too small +// - VmbErrorNotFound: The feature was not found +// - VmbErrorWrongType: The type of feature "name" is not String +// +// Details: This function is usually called twice: once with an empty buffer to query the length +// of the string, and then again with a buffer of the correct length. + +IMEXPORTC VmbError_t VMB_CALL VmbFeatureStringGet ( const VmbHandle_t handle, + const char* name, + char* buffer, + VmbUint32_t bufferSize, + VmbUint32_t* pSizeFilled ); + +// +// Method: VmbFeatureStringSet() +// +// Purpose: Set the value of a string feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the string feature +// [in ] const char* value Value to set +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorNotFound: The feature was not found +// - VmbErrorWrongType: The type of feature "name" is not String +// - VmbErrorInvalidValue: If length of "value" exceeded the maximum length +// - VmbErrorBadParameter: If "name" or "value" is NULL +// - VmbErrorInvalidCall: If called from frame callback +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureStringSet ( const VmbHandle_t handle, + const char* name, + const char* value ); + +// +// Method: VmbFeatureStringMaxlengthQuery() +// +// Purpose: Get the maximum length of a string feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the string feature +// [out] VmbUint32_t* pMaxLength Maximum length of this string feature +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not String +// - VmbErrorBadParameter: If "name" or "pMaxLength" is NULL +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureStringMaxlengthQuery ( const VmbHandle_t handle, + const char* name, + VmbUint32_t* pMaxLength ); + +//-----Boolean -------- + +// +// Method: VmbFeatureBoolGet() +// +// Purpose: Get the value of a boolean feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the boolean feature +// [out] VmbBool_t * pValue Value to be read +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Boolean +// - VmbErrorNotFound: If feature is not found +// - VmbErrorBadParameter: If "name" or "pValue" is NULL +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureBoolGet ( const VmbHandle_t handle, + const char* name, + VmbBool_t * pValue ); + +// +// Method: VmbFeatureBoolSet() +// +// Purpose: Set the value of a boolean feature. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the boolean feature +// [in ] VmbBool_t value Value to write +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Boolean +// - VmbErrorInvalidValue: If "value" is not within valid bounds +// - VmbErrorNotFound: If the feature is not found +// - VmbErrorBadParameter: If "name" is NULL +// - VmbErrorInvalidCall: If called from frame callback +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureBoolSet ( const VmbHandle_t handle, + const char* name, + VmbBool_t value ); + +//-----Command ------ + +// +// Method: VmbFeatureCommandRun() +// +// Purpose: Run a feature command. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the command feature +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Command +// - VmbErrorNotFound: Feature was not found +// - VmbErrorBadParameter: If "name" is NULL +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureCommandRun ( const VmbHandle_t handle, + const char* name ); + +// +// Method: VmbFeatureCommandIsDone() +// +// Purpose: Check if a feature command is done. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the command feature +// [out] VmbBool_t * pIsDone State of the command. +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Command +// - VmbErrorNotFound: Feature was not found +// - VmbErrorBadParameter: If "name" or "pIsDone" is NULL +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureCommandIsDone ( const VmbHandle_t handle, + const char* name, + VmbBool_t * pIsDone ); + +//-----Raw -------- + +// +// Method: VmbFeatureRawGet() +// +// Purpose: Read the memory contents of an area given by a feature name. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the raw feature +// [out] char* pBuffer Buffer to fill +// [in ] VmbUint32_t bufferSize Size of the buffer to be filled +// [out] VmbUint32_t* pSizeFilled Number of bytes actually filled +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Register +// - VmbErrorNotFound: Feature was not found +// - VmbErrorBadParameter: If "name" or "pBuffer" or "pSizeFilled" is NULL +// +// Details: This feature type corresponds to a top-level "Register" feature in GenICam. +// Data transfer is split up by the transport layer if the feature length is too large. +// You can get the size of the memory area addressed by the feature "name" by VmbFeatureRawLengthQuery(). +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureRawGet ( const VmbHandle_t handle, + const char* name, + char* pBuffer, + VmbUint32_t bufferSize, + VmbUint32_t* pSizeFilled ); + +// +// Method: VmbFeatureRawSet() +// +// Purpose: Write to a memory area given by a feature name. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the raw feature +// [in ] const char* pBuffer Data buffer to use +// [in ] VmbUint32_t bufferSize Size of the buffer +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Register +// - VmbErrorNotFound: Feature was not found +// - VmbErrorBadParameter: If "name" or "pBuffer" is NULL +// - VmbErrorInvalidCall: If called from frame callback +// +// Details: This feature type corresponds to a first-level "Register" node in the XML file. +// Data transfer is split up by the transport layer if the feature length is too large. +// You can get the size of the memory area addressed by the feature "name" by VmbFeatureRawLengthQuery(). +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureRawSet ( const VmbHandle_t handle, + const char* name, + const char* pBuffer, + VmbUint32_t bufferSize ); + +// +// Method: VmbFeatureRawLengthQuery() +// +// Purpose: Get the length of a raw feature for memory transfers. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that exposes features +// [in ] const char* name Name of the raw feature +// [out] VmbUint32_t* pLength Length of the raw feature area (in bytes) +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorWrongType: The type of feature "name" is not Register +// - VmbErrorNotFound: Feature not found +// - VmbErrorBadParameter: If "name" or "pLength" is NULL +// +// Details: This feature type corresponds to a first-level "Register" node in the XML file. +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureRawLengthQuery ( const VmbHandle_t handle, + const char* name, + VmbUint32_t* pLength ); + +//----- Feature invalidation -------------------------------------------------------- + +// +// Method: VmbFeatureInvalidationRegister() +// +// Purpose: Register a VmbInvalidationCallback callback for feature invalidation signaling. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that emits events +// [in ] const char* name Name of the event +// [in ] VmbInvalidationCallback callback Callback to be run, when invalidation occurs +// [in ] void* pUserContext User context passed to function +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// +// Details: Any feature change, either of its value or of its access state, may be tracked +// by registering an invalidation callback. +// Registering multiple callbacks for one feature invalidation event is possible because +// only the combination of handle, name, and callback is used as key. If the same +// combination of handle, name, and callback is registered a second time, it overwrites +// the previous one. +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureInvalidationRegister ( const VmbHandle_t handle, + const char* name, + VmbInvalidationCallback callback, + void* pUserContext ); + +// +// Method: VmbFeatureInvalidationUnregister() +// +// Purpose: Unregister a previously registered feature invalidation callback. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that emits events +// [in ] const char* name Name of the event +// [in ] VmbInvalidationCallback callback Callback to be removed +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// +// Details: Since multiple callbacks may be registered for a feature invalidation event, +// a combination of handle, name, and callback is needed for unregistering, too. +// +IMEXPORTC VmbError_t VMB_CALL VmbFeatureInvalidationUnregister ( const VmbHandle_t handle, + const char* name, + VmbInvalidationCallback callback ); + + +//----- Image preparation and acquisition --------------------------------------------------- + +// +// Method: VmbFrameAnnounce() +// +// Purpose: Announce frames to the API that may be queued for frame capturing later. +// +// Parameters: +// +// [in ] const VmbHandle_t cameraHandle Handle for a camera +// [in ] const VmbFrame_t* pFrame Frame buffer to announce +// [in ] VmbUint32_t sizeofFrame Size of the frame structure +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given camera handle is not valid +// - VmbErrorBadParameter: The given frame pointer is not valid or "sizeofFrame" is 0 +// - VmbErrorStructSize: The given struct size is not valid for this version of the API +// +// Details: Allows some preparation for frames like DMA preparation depending on the transport layer. +// The order in which the frames are announced is not taken into consideration by the API. +// The method can be used to annouce a previously allocated frame buffer to the transport layer. +// Alternatively, in case "pFrame->buffer" points to NULL, the method will allocate and announce +// a new buffer. In this case "pFrame->buffer" contains the allocated buffer address on return. +// +IMEXPORTC VmbError_t VMB_CALL VmbFrameAnnounce ( const VmbHandle_t cameraHandle, + const VmbFrame_t* pFrame, + VmbUint32_t sizeofFrame ); + + +// +// Method: VmbFrameRevoke() +// +// Purpose: Revoke a frame from the API. +// +// Parameters: +// +// [in ] const VmbHandle_t cameraHandle Handle for a camera +// [in ] const VmbFrame_t* pFrame Frame buffer to be removed from the list of announced frames +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given camera handle is not valid +// - VmbErrorBadParameter: The given frame pointer is not valid +// - VmbErrorStructSize: The given struct size is not valid for this version of the API +// +// Details: The referenced frame is removed from the pool of frames for capturing images. +// +IMEXPORTC VmbError_t VMB_CALL VmbFrameRevoke ( const VmbHandle_t cameraHandle, + const VmbFrame_t* pFrame ); + + +// +// Method: VmbFrameRevokeAll() +// +// Purpose: Revoke all frames assigned to a certain camera. +// +// Parameters: +// +// [in ] const VmbHandle_t cameraHandle Handle for a camera +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given camera handle is not valid +// +IMEXPORTC VmbError_t VMB_CALL VmbFrameRevokeAll ( const VmbHandle_t cameraHandle ); + + +// +// Method: VmbCaptureStart() +// +// Purpose: Prepare the API for incoming frames. +// +// Parameters: +// +// [in ] const VmbHandle_t cameraHandle Handle for a camera +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorDeviceNotOpen: Camera was not opened for usage +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// +IMEXPORTC VmbError_t VMB_CALL VmbCaptureStart ( const VmbHandle_t cameraHandle ); + + +// +// Method: VmbCaptureEnd() +// +// Purpose: Stop the API from being able to receive frames. +// +// Parameters: +// +// [in ] const VmbHandle_t cameraHandle Handle for a camera +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// +// Details: Consequences of VmbCaptureEnd(): +// - The frame callback will not be called anymore +// +IMEXPORTC VmbError_t VMB_CALL VmbCaptureEnd ( const VmbHandle_t cameraHandle ); + + +// +// Method: VmbCaptureFrameQueue() +// +// Purpose: Queue frames that may be filled during frame capturing. +// +// Parameters: +// +// [in ] const VmbHandle_t cameraHandle Handle of the camera +// [in ] const VmbFrame_t* pFrame Pointer to an already announced frame +// [in ] VmbFrameCallback callback Callback to be run when the frame is complete. NULL is Ok. +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given frame is not valid +// - VmbErrorStructSize: The given struct size is not valid for this version of the API +// +// Details: The given frame is put into a queue that will be filled sequentially. +// The order in which the frames are filled is determined by the order in which they are queued. +// If the frame was announced with VmbFrameAnnounce() before, the application +// has to ensure that the frame is also revoked by calling VmbFrameRevoke() or +// VmbFrameRevokeAll() when cleaning up. +// +IMEXPORTC VmbError_t VMB_CALL VmbCaptureFrameQueue ( const VmbHandle_t cameraHandle, + const VmbFrame_t* pFrame, + VmbFrameCallback callback ); + + +// +// Method: VmbCaptureFrameWait() +// +// Purpose: Wait for a queued frame to be filled (or dequeued). +// +// Parameters: +// +// [in ] const VmbHandle_t cameraHandle Handle of the camera +// [in ] const VmbFrame_t* pFrame Pointer to an already announced & queued frame +// [in ] VmbUint32_t timeout Timeout (in milliseconds) +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorTimeout: Call timed out +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// +IMEXPORTC VmbError_t VMB_CALL VmbCaptureFrameWait ( const VmbHandle_t cameraHandle, + const VmbFrame_t* pFrame, + VmbUint32_t timeout); + + +// +// Method: VmbCaptureQueueFlush() +// +// Purpose: Flush the capture queue. +// +// Parameters: +// +// [in ] const VmbHandle_t cameraHandle Handle of the camera to flush +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// +// Details: Control of all the currently queued frames will be returned to the user, +// leaving no frames in the capture queue. +// After this call, no frame notification will occur until frames are queued again. +// +IMEXPORTC VmbError_t VMB_CALL VmbCaptureQueueFlush ( const VmbHandle_t cameraHandle ); + + +//----- Interface Enumeration & Information -------------------------------------- + +// +// Method: VmbInterfacesList() +// +// Purpose: List all the interfaces currently visible to VimbaC. +// +// Parameters: +// +// [out] VmbInterfaceInfo_t* pInterfaceInfo Array of VmbInterfaceInfo_t, allocated by the caller. +// The interface list is copied here. May be NULL. +// [in ] VmbUint32_t listLength Number of entries in the caller's pList array +// [out] VmbUint32_t* pNumFound Number of interfaces found (may be more than +// listLength!) returned here. +// [in ] VmbUint32_t sizeofInterfaceInfo Size of one VmbInterfaceInfo_t entry +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorStructSize: The given struct size is not valid for this API version +// - VmbErrorMoreData: The given list length was insufficient to hold all available entries +// - VmbErrorBadParameter: If "pNumFound" was NULL +// +// Details: All the interfaces known via GenICam TransportLayers are listed by this +// command and filled into the provided array. Interfaces may correspond to +// adapter cards or frame grabber cards or, in the case of FireWire to the +// whole 1394 infrastructure, for instance. +// This function is usually called twice: once with an empty array to query the length +// of the list, and then again with an array of the correct length. +// +IMEXPORTC VmbError_t VMB_CALL VmbInterfacesList ( VmbInterfaceInfo_t* pInterfaceInfo, + VmbUint32_t listLength, + VmbUint32_t* pNumFound, + VmbUint32_t sizeofInterfaceInfo ); + +// +// Method: VmbInterfaceOpen() +// +// Purpose: Open an interface handle for feature access. +// +// Parameters: +// +// [in ] const char* idString The ID of the interface to get the handle for +// (returned by VmbInterfacesList()) +// [out] VmbHandle_t* pInterfaceHandle The handle for this interface. +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorNotFound: The designated interface cannot be found +// - VmbErrorBadParameter: If "pInterfaceHandle" was NULL +// +// Details: An interface can be opened if interface-specific control or information +// is required, e.g. the number of devices attached to a specific interface. +// Access is then possible via feature access methods. +// +IMEXPORTC VmbError_t VMB_CALL VmbInterfaceOpen ( const char* idString, + VmbHandle_t* pInterfaceHandle ); + +// +// Method: VmbInterfaceClose() +// +// Purpose: Close an interface. +// +// Parameters: +// +// [in ] const VmbHandle_t interfaceHandle The handle of the interface to close. +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// +// Details: After configuration of the interface, close it by calling this function. +// +IMEXPORTC VmbError_t VMB_CALL VmbInterfaceClose ( const VmbHandle_t interfaceHandle ); + + +//----- Ancillary data -------------------------------------------------------- + +// +// Method: VmbAncillaryDataOpen() +// +// Purpose: Get a working handle to allow access to the elements of the ancillary data via feature access. +// +// Parameters: +// +// [in ] VmbFrame_t* pFrame Pointer to a filled frame +// [out] VmbHandle_t* pAncillaryDataHandle Handle to the ancillary data inside the frame +// +// Returns: +// +// - VmbErrorSuccess: No error +// - VmbErrorBadHandle: Chunk mode of the camera was not activated. See feature ChunkModeActive +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// +// Details: This function can only succeed if the given frame has been filled by the API. +// +IMEXPORTC VmbError_t VMB_CALL VmbAncillaryDataOpen ( VmbFrame_t* pFrame, + VmbHandle_t* pAncillaryDataHandle ); + +// +// Method: VmbAncillaryDataClose() +// +// Purpose: Destroy the working handle to the ancillary data inside a frame. +// +// Parameters: +// +// [in ] VmbHandle_t ancillaryDataHandle Handle to ancillary frame data +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// +// Details: After reading the ancillary data and before re-queuing the frame, ancillary data +// must be closed. +// +IMEXPORTC VmbError_t VMB_CALL VmbAncillaryDataClose ( VmbHandle_t ancillaryDataHandle ); + + +//----- Memory/Register access -------------------------------------------- +//----- Memory/Register access -------------------------------------------- + +// +// Method: VmbMemoryRead() +// +// Purpose: Read an array of bytes. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that allows memory access +// [in ] VmbUint64_t address Address to be used for this read operation +// [in ] VmbUint32_t bufferSize Size of the data buffer to read +// [out] char* dataBuffer Buffer to be filled +// [out] VmbUint32_t* pSizeComplete Size of the data actually read +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// +IMEXPORTC VmbError_t VMB_CALL VmbMemoryRead ( const VmbHandle_t handle, + VmbUint64_t address, + VmbUint32_t bufferSize, + char* dataBuffer, + VmbUint32_t* pSizeComplete ); + +// +// Method: VmbMemoryWrite() +// +// Purpose: Write an array of bytes. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that allows memory access +// [in ] VmbUint64_t address Address to be used for this read operation +// [in ] VmbUint32_t bufferSize Size of the data buffer to write +// [in ] const char* dataBuffer Data to write +// [out] VmbUint32_t* pSizeComplete Number of bytes successfully written; if an +// error occurs this is less than bufferSize +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorMoreData: Not all data were written; see pSizeComplete value for the number of bytes written +// +IMEXPORTC VmbError_t VMB_CALL VmbMemoryWrite ( const VmbHandle_t handle, + VmbUint64_t address, + VmbUint32_t bufferSize, + const char* dataBuffer, + VmbUint32_t* pSizeComplete ); + +// +// Method: VmbRegistersRead() +// +// Purpose: Read an array of registers. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that allows register access +// [in ] VmbUint32_t readCount Number of registers to be read +// [in ] const VmbUint64_t* pAddressArray Array of addresses to be used for this read operation +// [out] VmbUint64_t* pDataArray Array of registers to be used for this read operation +// [out] VmbUint32_t* pNumCompleteReads Number of reads completed +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorIncomplete: Not all the requested reads could be completed +// +// Details: Two arrays of data must be provided: an array of register addresses and one +// for corresponding values to be read. The registers are read consecutively +// until an error occurs or all registers are written successfully. +// +IMEXPORTC VmbError_t VMB_CALL VmbRegistersRead ( const VmbHandle_t handle, + VmbUint32_t readCount, + const VmbUint64_t* pAddressArray, + VmbUint64_t* pDataArray, + VmbUint32_t* pNumCompleteReads ); + +// +// Method: VmbRegistersWrite() +// +// Purpose: Write an array of registers. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that allows register access +// [in ] VmbUint32_t writeCount Number of registers to be written +// [in ] const VmbUint64_t* pAddressArray Array of addresses to be used for this write operation +// [in ] const VmbUint64_t* pDataArray Array of reads to be used for this write operation +// [out] VmbUint32_t* pNumCompleteWrites Number of writes completed +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorIncomplete: Not all the requested writes could be completed +// +// Details: Two arrays of data must be provided: an array of register addresses and one with the +// corresponding values to be written to these addresses. The registers are written +// consecutively until an error occurs or all registers are written successfully. +// +IMEXPORTC VmbError_t VMB_CALL VmbRegistersWrite ( const VmbHandle_t handle, + VmbUint32_t writeCount, + const VmbUint64_t* pAddressArray, + const VmbUint64_t* pDataArray, + VmbUint32_t* pNumCompleteWrites ); + +// +// Method: VmbCameraSettingsSave() +// +// Purpose: Saves all feature values to XML file. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that allows register access +// [in ] const char* fileName Name of XML file to save settings +// [in ] VmbFeaturePersistSettings_t* pSettings Settings struct +// [in ] VmbUint32_t sizeofSettings Size of settings struct +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorBadParameter: If "fileName" is NULL +// +// Details: Camera must be opened beforehand and function needs corresponding handle. +// With given filename parameter path and name of XML file can be determined. +// Additionally behaviour of function can be set with providing 'persistent struct'. +// +IMEXPORTC VmbError_t VMB_CALL VmbCameraSettingsSave ( const VmbHandle_t handle, + const char * fileName, + VmbFeaturePersistSettings_t * pSettings, + VmbUint32_t sizeofSettings ); + +// +// Method: VmbCameraSettingsLoad() +// +// Purpose: Load all feature values from XML file to device. +// +// Parameters: +// +// [in ] const VmbHandle_t handle Handle for an entity that allows register access +// [in ] const char* fileName Name of XML file to save settings +// [in ] VmbFeaturePersistSettings_t* pSettings Settings struct +// [in ] VmbUint32_t sizeofSettings Size of settings struct +// +// Returns: +// +// - VmbErrorSuccess: If no error +// - VmbErrorApiNotStarted: VmbStartup() was not called before the current command +// - VmbErrorBadHandle: The given handle is not valid +// - VmbErrorInvalidAccess: Operation is invalid with the current access mode +// - VmbErrorBadParameter: If "fileName" is NULL +// +// Details: Camera must be opened beforehand and function needs corresponding handle. +// With given filename parameter path and name of XML file can be determined. +// Additionally behaviour of function can be set with providing 'settings struct'. +// +IMEXPORTC VmbError_t VMB_CALL VmbCameraSettingsLoad ( const VmbHandle_t handle, + const char * fileName, + VmbFeaturePersistSettings_t * pSettings, + VmbUint32_t sizeofSettings ); + +#ifdef __cplusplus +} +#endif + +#endif // VIMBAC_H_INCLUDE_ diff --git a/Vimba_6_0/VimbaC/Include/VmbCommonTypes.h b/Vimba_6_0/VimbaC/Include/VmbCommonTypes.h new file mode 100644 index 0000000..d16dd69 --- /dev/null +++ b/Vimba_6_0/VimbaC/Include/VmbCommonTypes.h @@ -0,0 +1,251 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this header file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: VmbCommonTypes.h + + Description: Main header file for the common types of the Vimba APIs. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef VMBCOMMONTYPES_H_INCLUDE_ +#define VMBCOMMONTYPES_H_INCLUDE_ + +#ifdef __cplusplus +extern "C" { +#endif + +// This file describes all necessary definitions for types used within +// Allied Vision's Vimba APIs. These type definitions are designed to be +// portable from other languages and other operating systems. + +#if defined (_MSC_VER) + + // 8 bit signed integer on Microsoft systems + typedef __int8 VmbInt8_t; + // 8 bit unsigned integer on Microsoft systems + typedef unsigned __int8 VmbUint8_t; + // 16 bit signed integer on Microsoft systems + typedef __int16 VmbInt16_t; + // 16 bit unsigned integer on Microsoft systems + typedef unsigned __int16 VmbUint16_t; + // 32 bit signed integer on Microsoft systems + typedef __int32 VmbInt32_t; + // 32 bit unsigned integer on Microsoft systems + typedef unsigned __int32 VmbUint32_t; + // 64 bit signed integer on Microsoft systems + typedef __int64 VmbInt64_t; + // 64 bit unsigned integer on Microsoft systems + typedef unsigned __int64 VmbUint64_t; + +#else // for non MS or GNU compilers without any warranty for the size + + //#pragma message("Compatibility warning: typedefs in " __FILE__ " may not have the correct number of bits") + + // 8 bit signed integer on non-Microsoft systems + typedef signed char VmbInt8_t; + // 8 bit unsigned integer on non-Microsoft systems + typedef unsigned char VmbUint8_t; + // 16 bit signed integer on non-Microsoft systems + typedef short VmbInt16_t; + // 16 bit unsigned integer on non-Microsoft systems + typedef unsigned short VmbUint16_t; + // 32 bit signed integer on non-Microsoft systems + typedef int VmbInt32_t; + // 32 bit signed integer on non-Microsoft systems + typedef unsigned int VmbUint32_t; + // 64 bit signed integer on non-Microsoft systems + typedef long long VmbInt64_t; + // 64 bit unsigned integer on non-Microsoft systems + typedef unsigned long long VmbUint64_t; + +#endif + + // Handle; e.g. for a camera + typedef void* VmbHandle_t; + +// Standard type for boolean values +#if defined(__cplusplus) || defined(__bool_true_false_are_defined) + typedef bool VmbBool_t; +#else + // Boolean type (equivalent to char) + typedef char VmbBool_t; // 1 means true and 0 means false +#endif + // + // enum for bool values + // + typedef enum VmbBoolVal + { + VmbBoolTrue = 1, + VmbBoolFalse = 0, + } VmbBoolVal; + + // char type + typedef unsigned char VmbUchar_t; + + // + // Error codes, returned by most functions: (not yet complete) + // + typedef enum VmbErrorType + { + VmbErrorSuccess = 0, // No error + VmbErrorInternalFault = -1, // Unexpected fault in VimbaC or driver + VmbErrorApiNotStarted = -2, // VmbStartup() was not called before the current command + VmbErrorNotFound = -3, // The designated instance (camera, feature etc.) cannot be found + VmbErrorBadHandle = -4, // The given handle is not valid + VmbErrorDeviceNotOpen = -5, // Device was not opened for usage + VmbErrorInvalidAccess = -6, // Operation is invalid with the current access mode + VmbErrorBadParameter = -7, // One of the parameters is invalid (usually an illegal pointer) + VmbErrorStructSize = -8, // The given struct size is not valid for this version of the API + VmbErrorMoreData = -9, // More data available in a string/list than space is provided + VmbErrorWrongType = -10, // Wrong feature type for this access function + VmbErrorInvalidValue = -11, // The value is not valid; either out of bounds or not an increment of the minimum + VmbErrorTimeout = -12, // Timeout during wait + VmbErrorOther = -13, // Other error + VmbErrorResources = -14, // Resources not available (e.g. memory) + VmbErrorInvalidCall = -15, // Call is invalid in the current context (e.g. callback) + VmbErrorNoTL = -16, // No transport layers are found + VmbErrorNotImplemented = -17, // API feature is not implemented + VmbErrorNotSupported = -18, // API feature is not supported + VmbErrorIncomplete = -19, // The current operation was not completed (e.g. a multiple registers read or write) + VmbErrorIO = -20, // Low level IO error in transport layer + } VmbErrorType; + typedef VmbInt32_t VmbError_t; // Type for an error returned by API methods; for values see VmbErrorType + + // + // Version information + // + typedef struct + { + VmbUint32_t major; // Major version number + VmbUint32_t minor; // Minor version number + VmbUint32_t patch; // Patch version number + + } VmbVersionInfo_t; + + // + // Indicate if pixel is monochrome or RGB. + // + typedef enum VmbPixelType + { + VmbPixelMono = 0x01000000, // Monochrome pixel + VmbPixelColor = 0x02000000 // Pixel bearing color information + } VmbPixelType; + + // + // Indicate number of bits for a pixel. Needed for building values of VmbPixelFormatType + // + typedef enum VmbPixelOccupyType + { + VmbPixelOccupy8Bit = 0x00080000, // Pixel effectively occupies 8 bits + VmbPixelOccupy10Bit = 0x000A0000, // Pixel effectively occupies 10 bits + VmbPixelOccupy12Bit = 0x000C0000, // Pixel effectively occupies 12 bits + VmbPixelOccupy14Bit = 0x000E0000, // Pixel effectively occupies 14 bits + VmbPixelOccupy16Bit = 0x00100000, // Pixel effectively occupies 16 bits + VmbPixelOccupy24Bit = 0x00180000, // Pixel effectively occupies 24 bits + VmbPixelOccupy32Bit = 0x00200000, // Pixel effectively occupies 32 bits + VmbPixelOccupy48Bit = 0x00300000, // Pixel effectively occupies 48 bits + VmbPixelOccupy64Bit = 0x00400000, // Pixel effectively occupies 48 bits + } VmbPixelOccupyType; + + // + // Pixel format types. + // As far as possible, the Pixel Format Naming Convention (PFNC) has been followed, allowing a few deviations. + // If data spans more than one byte, it is always LSB aligned, except if stated differently. + // + typedef enum VmbPixelFormatType + { + // Mono formats + VmbPixelFormatMono8 = VmbPixelMono | VmbPixelOccupy8Bit | 0x0001, // Monochrome, 8 bits (PFNC:Mono8) + VmbPixelFormatMono10 = VmbPixelMono | VmbPixelOccupy16Bit | 0x0003, // Monochrome, 10 bits in 16 bits (PFNC:Mono10) + VmbPixelFormatMono10p = VmbPixelMono | VmbPixelOccupy10Bit | 0x0046, // Monochrome, 4x10 bits continuously packed in 40 bits (PFNC:Mono10p) + VmbPixelFormatMono12 = VmbPixelMono | VmbPixelOccupy16Bit | 0x0005, // Monochrome, 12 bits in 16 bits (PFNC:Mono12) + VmbPixelFormatMono12Packed = VmbPixelMono | VmbPixelOccupy12Bit | 0x0006, // Monochrome, 2x12 bits in 24 bits (GEV:Mono12Packed) + VmbPixelFormatMono12p = VmbPixelMono | VmbPixelOccupy12Bit | 0x0047, // Monochrome, 2x12 bits continuously packed in 24 bits (PFNC:Mono12p) + VmbPixelFormatMono14 = VmbPixelMono | VmbPixelOccupy16Bit | 0x0025, // Monochrome, 14 bits in 16 bits (PFNC:Mono14) + VmbPixelFormatMono16 = VmbPixelMono | VmbPixelOccupy16Bit | 0x0007, // Monochrome, 16 bits (PFNC:Mono16) + // Bayer formats + VmbPixelFormatBayerGR8 = VmbPixelMono | VmbPixelOccupy8Bit | 0x0008, // Bayer-color, 8 bits, starting with GR line (PFNC:BayerGR8) + VmbPixelFormatBayerRG8 = VmbPixelMono | VmbPixelOccupy8Bit | 0x0009, // Bayer-color, 8 bits, starting with RG line (PFNC:BayerRG8) + VmbPixelFormatBayerGB8 = VmbPixelMono | VmbPixelOccupy8Bit | 0x000A, // Bayer-color, 8 bits, starting with GB line (PFNC:BayerGB8) + VmbPixelFormatBayerBG8 = VmbPixelMono | VmbPixelOccupy8Bit | 0x000B, // Bayer-color, 8 bits, starting with BG line (PFNC:BayerBG8) + VmbPixelFormatBayerGR10 = VmbPixelMono | VmbPixelOccupy16Bit | 0x000C, // Bayer-color, 10 bits in 16 bits, starting with GR line (PFNC:BayerGR10) + VmbPixelFormatBayerRG10 = VmbPixelMono | VmbPixelOccupy16Bit | 0x000D, // Bayer-color, 10 bits in 16 bits, starting with RG line (PFNC:BayerRG10) + VmbPixelFormatBayerGB10 = VmbPixelMono | VmbPixelOccupy16Bit | 0x000E, // Bayer-color, 10 bits in 16 bits, starting with GB line (PFNC:BayerGB10) + VmbPixelFormatBayerBG10 = VmbPixelMono | VmbPixelOccupy16Bit | 0x000F, // Bayer-color, 10 bits in 16 bits, starting with BG line (PFNC:BayerBG10) + VmbPixelFormatBayerGR12 = VmbPixelMono | VmbPixelOccupy16Bit | 0x0010, // Bayer-color, 12 bits in 16 bits, starting with GR line (PFNC:BayerGR12) + VmbPixelFormatBayerRG12 = VmbPixelMono | VmbPixelOccupy16Bit | 0x0011, // Bayer-color, 12 bits in 16 bits, starting with RG line (PFNC:BayerRG12) + VmbPixelFormatBayerGB12 = VmbPixelMono | VmbPixelOccupy16Bit | 0x0012, // Bayer-color, 12 bits in 16 bits, starting with GB line (PFNC:BayerGB12) + VmbPixelFormatBayerBG12 = VmbPixelMono | VmbPixelOccupy16Bit | 0x0013, // Bayer-color, 12 bits in 16 bits, starting with BG line (PFNC:BayerBG12) + VmbPixelFormatBayerGR12Packed = VmbPixelMono | VmbPixelOccupy12Bit | 0x002A, // Bayer-color, 2x12 bits in 24 bits, starting with GR line (GEV:BayerGR12Packed) + VmbPixelFormatBayerRG12Packed = VmbPixelMono | VmbPixelOccupy12Bit | 0x002B, // Bayer-color, 2x12 bits in 24 bits, starting with RG line (GEV:BayerRG12Packed) + VmbPixelFormatBayerGB12Packed = VmbPixelMono | VmbPixelOccupy12Bit | 0x002C, // Bayer-color, 2x12 bits in 24 bits, starting with GB line (GEV:BayerGB12Packed) + VmbPixelFormatBayerBG12Packed = VmbPixelMono | VmbPixelOccupy12Bit | 0x002D, // Bayer-color, 2x12 bits in 24 bits, starting with BG line (GEV:BayerBG12Packed) + VmbPixelFormatBayerGR10p = VmbPixelMono | VmbPixelOccupy10Bit | 0x0056, // Bayer-color, 4x10 bits continuously packed in 40 bits, starting with GR line (PFNC:BayerGR10p) + VmbPixelFormatBayerRG10p = VmbPixelMono | VmbPixelOccupy10Bit | 0x0058, // Bayer-color, 4x10 bits continuously packed in 40 bits, starting with RG line (PFNC:BayerRG10p) + VmbPixelFormatBayerGB10p = VmbPixelMono | VmbPixelOccupy10Bit | 0x0054, // Bayer-color, 4x10 bits continuously packed in 40 bits, starting with GB line (PFNC:BayerGB10p) + VmbPixelFormatBayerBG10p = VmbPixelMono | VmbPixelOccupy10Bit | 0x0052, // Bayer-color, 4x10 bits continuously packed in 40 bits, starting with BG line (PFNC:BayerBG10p) + VmbPixelFormatBayerGR12p = VmbPixelMono | VmbPixelOccupy12Bit | 0x0057, // Bayer-color, 2x12 bits continuously packed in 24 bits, starting with GR line (PFNC:BayerGR12p) + VmbPixelFormatBayerRG12p = VmbPixelMono | VmbPixelOccupy12Bit | 0x0059, // Bayer-color, 2x12 bits continuously packed in 24 bits, starting with RG line (PFNC:BayerRG12p) + VmbPixelFormatBayerGB12p = VmbPixelMono | VmbPixelOccupy12Bit | 0x0055, // Bayer-color, 2x12 bits continuously packed in 24 bits, starting with GB line (PFNC:BayerGB12p) + VmbPixelFormatBayerBG12p = VmbPixelMono | VmbPixelOccupy12Bit | 0x0053, // Bayer-color, 2x12 bits continuously packed in 24 bits, starting with BG line (PFNC:BayerBG12p) + VmbPixelFormatBayerGR16 = VmbPixelMono | VmbPixelOccupy16Bit | 0x002E, // Bayer-color, 16 bits, starting with GR line (PFNC:BayerGR16) + VmbPixelFormatBayerRG16 = VmbPixelMono | VmbPixelOccupy16Bit | 0x002F, // Bayer-color, 16 bits, starting with RG line (PFNC:BayerRG16) + VmbPixelFormatBayerGB16 = VmbPixelMono | VmbPixelOccupy16Bit | 0x0030, // Bayer-color, 16 bits, starting with GB line (PFNC:BayerGB16) + VmbPixelFormatBayerBG16 = VmbPixelMono | VmbPixelOccupy16Bit | 0x0031, // Bayer-color, 16 bits, starting with BG line (PFNC:BayerBG16) + // RGB formats + VmbPixelFormatRgb8 = VmbPixelColor | VmbPixelOccupy24Bit | 0x0014, // RGB, 8 bits x 3 (PFNC:RGB8) + VmbPixelFormatBgr8 = VmbPixelColor | VmbPixelOccupy24Bit | 0x0015, // BGR, 8 bits x 3 (PFNC:Bgr8) + VmbPixelFormatRgb10 = VmbPixelColor | VmbPixelOccupy48Bit | 0x0018, // RGB, 10 bits in 16 bits x 3 (PFNC:RGB10) + VmbPixelFormatBgr10 = VmbPixelColor | VmbPixelOccupy48Bit | 0x0019, // BGR, 10 bits in 16 bits x 3 (PFNC:BGR10) + VmbPixelFormatRgb12 = VmbPixelColor | VmbPixelOccupy48Bit | 0x001A, // RGB, 12 bits in 16 bits x 3 (PFNC:RGB12) + VmbPixelFormatBgr12 = VmbPixelColor | VmbPixelOccupy48Bit | 0x001B, // BGR, 12 bits in 16 bits x 3 (PFNC:BGR12) + VmbPixelFormatRgb14 = VmbPixelColor | VmbPixelOccupy48Bit | 0x005E, // RGB, 14 bits in 16 bits x 3 (PFNC:RGB14) + VmbPixelFormatBgr14 = VmbPixelColor | VmbPixelOccupy48Bit | 0x004A, // BGR, 14 bits in 16 bits x 3 (PFNC:BGR14) + VmbPixelFormatRgb16 = VmbPixelColor | VmbPixelOccupy48Bit | 0x0033, // RGB, 16 bits x 3 (PFNC:RGB16) + VmbPixelFormatBgr16 = VmbPixelColor | VmbPixelOccupy48Bit | 0x004B, // BGR, 16 bits x 3 (PFNC:BGR16) + // RGBA formats + VmbPixelFormatArgb8 = VmbPixelColor | VmbPixelOccupy32Bit | 0x0016, // ARGB, 8 bits x 4 (PFNC:RGBa8) + VmbPixelFormatRgba8 = VmbPixelFormatArgb8, // RGBA, 8 bits x 4, legacy name + VmbPixelFormatBgra8 = VmbPixelColor | VmbPixelOccupy32Bit | 0x0017, // BGRA, 8 bits x 4 (PFNC:BGRa8) + VmbPixelFormatRgba10 = VmbPixelColor | VmbPixelOccupy64Bit | 0x005F, // RGBA, 10 bits in 16 bits x 4 + VmbPixelFormatBgra10 = VmbPixelColor | VmbPixelOccupy64Bit | 0x004C, // BGRA, 10 bits in 16 bits x 4 + VmbPixelFormatRgba12 = VmbPixelColor | VmbPixelOccupy64Bit | 0x0061, // RGBA, 12 bits in 16 bits x 4 + VmbPixelFormatBgra12 = VmbPixelColor | VmbPixelOccupy64Bit | 0x004E, // BGRA, 12 bits in 16 bits x 4 + VmbPixelFormatRgba14 = VmbPixelColor | VmbPixelOccupy64Bit | 0x0063, // RGBA, 14 bits in 16 bits x 4 + VmbPixelFormatBgra14 = VmbPixelColor | VmbPixelOccupy64Bit | 0x0050, // BGRA, 14 bits in 16 bits x 4 + VmbPixelFormatRgba16 = VmbPixelColor | VmbPixelOccupy64Bit | 0x0064, // RGBA, 16 bits x 4 + VmbPixelFormatBgra16 = VmbPixelColor | VmbPixelOccupy64Bit | 0x0051, // BGRA, 16 bits x 4 + // YUV/YCbCr formats + VmbPixelFormatYuv411 = VmbPixelColor | VmbPixelOccupy12Bit | 0x001E, // YUV 411 with 8 bits (GEV:YUV411Packed) + VmbPixelFormatYuv422 = VmbPixelColor | VmbPixelOccupy16Bit | 0x001F, // YUV 422 with 8 bits (GEV:YUV422Packed) + VmbPixelFormatYuv444 = VmbPixelColor | VmbPixelOccupy24Bit | 0x0020, // YUV 444 with 8 bits (GEV:YUV444Packed) + VmbPixelFormatYCbCr411_8_CbYYCrYY = VmbPixelColor | VmbPixelOccupy12Bit | 0x003C, // YCbCr 411 with 8 bits (PFNC:YCbCr411_8_CbYYCrYY) - identical to VmbPixelFormatYuv411 + VmbPixelFormatYCbCr422_8_CbYCrY = VmbPixelColor | VmbPixelOccupy16Bit | 0x0043, // YCbCr 422 with 8 bits (PFNC:YCbCr422_8_CbYCrY) - identical to VmbPixelFormatYuv422 + VmbPixelFormatYCbCr8_CbYCr = VmbPixelColor | VmbPixelOccupy24Bit | 0x003A, // YCbCr 444 with 8 bits (PFNC:YCbCr8_CbYCr) - identical to VmbPixelFormatYuv444 + VmbPixelFormatLast, + } VmbPixelFormatType; + typedef VmbUint32_t VmbPixelFormat_t; // Type for the pixel format; for values see VmbPixelFormatType + +#ifdef __cplusplus +} +#endif + +#endif // VMBCOMMONTYPES_H_INCLUDE_ diff --git a/Vimba_6_0/VimbaCPP/Build/Make/Common.mk b/Vimba_6_0/VimbaCPP/Build/Make/Common.mk new file mode 100644 index 0000000..a727c58 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Build/Make/Common.mk @@ -0,0 +1,100 @@ +UNAME = $(shell uname -m) + +ifeq ($(UNAME),i386) +ARCH = x86 +AUTOWORDSIZE = 32 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),i486) +ARCH = x86 +AUTOWORDSIZE = 32 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),i586) +ARCH = x86 +AUTOWORDSIZE = 32 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),i686) +ARCH = x86 +AUTOWORDSIZE = 32 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),x86_64) +ARCH = x86 +AUTOWORDSIZE = 64 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),amd64) +ARCH = x86 +AUTOWORDSIZE = 64 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),armv6l) +ARCH = arm +AUTOWORDSIZE = 32 +AUTOFLOATABI = soft +endif +ifeq ($(UNAME),armv7l) +ARCH = arm +AUTOWORDSIZE = 32 +AUTOFLOATABI = soft +endif +ifeq ($(UNAME),aarch64) +ARCH = arm +AUTOWORDSIZE = 64 +AUTOFLOATABI = hard +endif + +#Possible word sizes: 32, 64 +WORDSIZE = $(AUTOWORDSIZE) +#Possible float abis: soft, hard +FLOATABI = $(AUTOFLOATABI) + +ifneq ($(WORDSIZE),32) +ifneq ($(WORDSIZE),64) +$(error Invalid word size set) +endif +endif + +ifneq ($(FLOATABI),soft) +ifneq ($(FLOATABI),hard) +ifneq ($(FLOATABI),ignore) +$(error Invalid float abi set) +endif +endif +endif + +#Common tools +PKGCFG = pkg-config +MKDIR = mkdir +RM = rm +CXX = g++ +MAKE = make +CP = cp + +#Set word size on x86 +ifeq ($(ARCH),x86) +ARCH_CFLAGS = -m$(WORDSIZE) +endif + +#Configure compiler and linker for soft or hard-float build on ARM +ifeq ($(ARCH),arm) +ifeq ($(FLOATABI),soft) +ARCH_CFLAGS = -marm -mfloat-abi=soft -march=armv4t +else ifeq ($(FLOATABI),hard) +ifeq ($(WORDSIZE),32) +ARCH_CFLAGS = -mthumb -mfloat-abi=hard -march=armv7 +else ifeq ($(WORDSIZE),64) +ARCH_CFLAGS = -march=armv8-a +endif +endif +endif + +ifeq ($(CONFIG),Debug) + CONFIG_CFLAGS = -O0 -g +else + CONFIG_CFLAGS = -O3 +endif + +COMMON_CFLAGS = $(CONFIG_CFLAGS) $(ARCH_CFLAGS) -fPIC diff --git a/Vimba_6_0/VimbaCPP/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Build/Make/Makefile new file mode 100644 index 0000000..2e67600 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Build/Make/Makefile @@ -0,0 +1,73 @@ +PROJECT_NAME = VimbaCPP + +PROJECT_DIR = ../.. +VIMBASDK_DIR = $(PROJECT_DIR)/.. +MAKE_INCLUDE_DIR = $(CURDIR) + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = lib$(PROJECT_NAME).so +BIN_DIR = dynamic/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaC.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(PROJECT_DIR)/.. + +LIBS = $(VIMBAC_LIBS) \ + -lpthread + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBAC_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/AncillaryData.o \ + $(OBJ_DIR)/BaseFeature.o \ + $(OBJ_DIR)/BasicLockable.o \ + $(OBJ_DIR)/BoolFeature.o \ + $(OBJ_DIR)/Camera.o \ + $(OBJ_DIR)/Clock.o \ + $(OBJ_DIR)/CommandFeature.o \ + $(OBJ_DIR)/Condition.o \ + $(OBJ_DIR)/ConditionHelper.o \ + $(OBJ_DIR)/DefaultCameraFactory.o \ + $(OBJ_DIR)/EnumEntry.o \ + $(OBJ_DIR)/EnumFeature.o \ + $(OBJ_DIR)/FeatureContainer.o \ + $(OBJ_DIR)/Feature.o \ + $(OBJ_DIR)/FileLogger.o \ + $(OBJ_DIR)/FloatFeature.o \ + $(OBJ_DIR)/Frame.o \ + $(OBJ_DIR)/FrameHandler.o \ + $(OBJ_DIR)/Interface.o \ + $(OBJ_DIR)/IntFeature.o \ + $(OBJ_DIR)/Mutex.o \ + $(OBJ_DIR)/MutexGuard.o \ + $(OBJ_DIR)/RawFeature.o \ + $(OBJ_DIR)/Semaphore.o \ + $(OBJ_DIR)/StringFeature.o \ + $(OBJ_DIR)/VimbaSystem.o + +DEPENDENCIES = VimbaC + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) -shared $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) dynamic -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) diff --git a/Vimba_6_0/VimbaCPP/Build/Make/VimbaC.mk b/Vimba_6_0/VimbaCPP/Build/Make/VimbaC.mk new file mode 100644 index 0000000..d8bdb00 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Build/Make/VimbaC.mk @@ -0,0 +1,14 @@ +include $(MAKE_INCLUDE_DIR)/Common.mk + +#Compile options needed for VimbaC +VIMBAC_CFLAGS = -I$(VIMBASDK_DIR) + +#Linker options needed for VimbaC +VIMBAC_LIBS = -L$(BIN_DIR) -lVimbaC + +#By default we copy libVimbaC.so next to the binary +$(BIN_DIR)/libVimbaC.so: $(BIN_DIR) + $(CP) $(VIMBASDK_DIR)/VimbaC/DynamicLib/$(ARCH)_$(WORDSIZE)bit/libVimbaC.so $(BIN_DIR)/ + +#Operations we have to do in order to prepare VimbaC +VimbaC: $(BIN_DIR)/libVimbaC.so diff --git a/Vimba_6_0/VimbaCPP/Documentation/Vimba CPP Manual.pdf b/Vimba_6_0/VimbaCPP/Documentation/Vimba CPP Manual.pdf new file mode 100644 index 0000000..508dc03 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Documentation/Vimba CPP Manual.pdf differ diff --git a/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Build/Make/Makefile new file mode 100644 index 0000000..b0ef96c --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Build/Make/Makefile @@ -0,0 +1,51 @@ +PROJECT_NAME = ActionCommands + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBACPP_LIBS) + +DEFINES = -D_LITTLE_ENDIAN + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ActionCommands.o \ + $(OBJ_DIR)/FrameObserver.o \ + $(OBJ_DIR)/program.o + +DEPENDENCIES = VimbaCPP + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/ActionCommands.cpp b/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/ActionCommands.cpp new file mode 100644 index 0000000..271a154 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/ActionCommands.cpp @@ -0,0 +1,985 @@ +/*============================================================================= + Copyright (C) 2021 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ActionCommands.cpp + + Description: see header file for description + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include + +#include + +// socket library to check IP addresses +#ifdef _WIN32 + #include + #include +#else + #include +#endif + +// number of frame buffers to be used by example +#define NUM_FRAMES 3 + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// +// Constructor +// +cActionCommands::cActionCommands() + : mSystem( VimbaSystem::GetInstance() ) + , mFrameObserver( NULL ) + , mSystemFlag( false ) + , mInterfaceFlag( false ) + , mCameraFlag( false ) + , mStreamingFlag( false ) +{ +} + +// +// Destructor +// +cActionCommands::~cActionCommands() +{ +} + +// +// Helper method to read feature values of any type +// +// Parameters: +// [in] aName Feature name +// [in] aOwner Feature owner, like Vimba system, interface or camera +// [out] aType Feature data type +// [in/out] aValue Buffer for feature value +// [in/out] aSize Size of buffer +// +VmbErrorType cActionCommands::GetFeatureValue( const char* aName, tFeatureOwner aOwner, VmbFeatureDataType* aType, void* aValue, size_t* aSize ) +{ + VmbErrorType lError = VmbErrorSuccess; + + // check parameter + if( (NULL == aName) || (NULL == aValue) ) + { + return VmbErrorBadParameter; + } + + // get feature pointer + FeaturePtr lFeature; + switch( aOwner ) + { + case eFeatureOwnerSystem: + { + lError = this->mSystem.GetFeatureByName( aName, lFeature ); + break; + } + case eFeatureOwnerInterface: + { + lError = this->mInterface->GetFeatureByName( aName, lFeature ); + break; + } + case eFeatureOwnerCamera: + { + lError = this->mCamera->GetFeatureByName( aName, lFeature ); + break; + } + default: + { + lError = VmbErrorBadParameter; + break; + } + } + + // get feature data type + VmbFeatureDataType lType = VmbFeatureDataUnknown; + lError = lFeature->GetDataType( lType ); + if( (VmbErrorSuccess == lError) && (NULL != aType) ) + { + *aType = lType; + } + + // proceed in case of no error + if( VmbErrorSuccess == lError ) + { + // set feature value + switch( lType ) + { + case VmbFeatureDataInt: + { + // get value + VmbInt64_t lValue = 0; + lError = lFeature->GetValue( lValue ); + if( VmbErrorSuccess == lError ) + { + memcpy( aValue, &lValue, sizeof(VmbInt64_t) ); + } + + // set buffer size + if( NULL != aSize ) + { + *aSize = sizeof(VmbInt64_t); + } + + break; + } + default: + { + lError = VmbErrorBadParameter; + break; + } + } + } + + return lError; +} + +// +// Helper method to write feature values of any type +// +// Parameters: +// [in] aName Feature name +// [in] aOwner Feature owner, like Vimba system, interface or camera +// [in] aType Feature data type +// [in] aValue Buffer for feature value +// [in] aSize Size of buffer +// +VmbErrorType cActionCommands::SetFeatureValue( const char* aName, tFeatureOwner aOwner, VmbFeatureDataType aType, void* aValue, size_t aSize ) +{ + VmbErrorType lError = VmbErrorSuccess; + + // check parameter + if( (NULL == aName) || (NULL == aValue) ) + { + return VmbErrorBadParameter; + } + + // get feature pointer + FeaturePtr lFeature; + switch( aOwner ) + { + case eFeatureOwnerSystem: + { + lError = this->mSystem.GetFeatureByName( aName, lFeature ); + break; + } + case eFeatureOwnerInterface: + { + lError = this->mInterface->GetFeatureByName( aName, lFeature ); + break; + } + case eFeatureOwnerCamera: + { + lError = this->mCamera->GetFeatureByName( aName, lFeature ); + break; + } + default: + { + lError = VmbErrorBadParameter; + break; + } + } + + // check feature data type + VmbFeatureDataType lType = VmbFeatureDataUnknown; + lFeature->GetDataType( lType ); + if( lType != aType ) + { + return VmbErrorBadParameter; + } + + // proceed in case of no error + if( VmbErrorSuccess == lError ) + { + // set feature value + switch( aType ) + { + case VmbFeatureDataInt: + { + // check size + if( sizeof(VmbInt64_t) >= aSize ) + { + // set value + VmbInt64_t lValue = (VmbInt64_t)aValue; + lError = lFeature->SetValue( lValue ); + } + + break; + } + case VmbFeatureDataEnum: + { + // set value + const char* lValue = (char*)aValue; + lError = lFeature->SetValue( lValue ); + + break; + } + default: + { + lError = VmbErrorBadParameter; + break; + } + } + } + + return lError; +} + +// +// Helper method to run a Command Feature +// +// Parameters: +// [in] aName Feature name +// [in] aOwner Feature owner, like Vimba system, interface or camera +// +VmbErrorType cActionCommands::RunCommand( const char* aName, tFeatureOwner aOwner ) +{ + VmbErrorType lError = VmbErrorSuccess; + + // get feature pointer + FeaturePtr lFeature; + switch( aOwner ) + { + case eFeatureOwnerSystem: + { + lError = this->mSystem.GetFeatureByName( aName, lFeature ); + break; + } + case eFeatureOwnerInterface: + { + lError = this->mInterface->GetFeatureByName( aName, lFeature ); + break; + } + case eFeatureOwnerCamera: + { + lError = this->mCamera->GetFeatureByName( aName, lFeature ); + break; + } + default: + lError = VmbErrorBadParameter; + } + + if( VmbErrorSuccess == lError ) + { + lError = lFeature->RunCommand(); + } + + return lError; +} + +// +// Called when any failure occurs within the example. +// Ensures to stop streaming, close interface, close camera and shutdown Vimba +// +void cActionCommands::FailureShutdown() +{ + VmbErrorType lError = VmbErrorSuccess; + + // stop streaming + if( true == this->mStreamingFlag ) + { + lError = this->mCamera->StopContinuousImageAcquisition(); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not stop camera acquisition. Reason: " << lError << std::endl; + } + + std::cout << "......Streaming has been stopped." << std::endl; + } + + // close camera + if( true == this->mCameraFlag ) + { + lError = this->mCamera->Close(); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not close camera. Reason: " << lError << std::endl; + } + + std::cout << "......Camera has been closed." << std::endl; + } + + // close interface + if( true == this->mInterfaceFlag ) + { + lError = this->mInterface->Close(); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not close interface. Reason: " << lError << std::endl; + } + + std::cout << "......Interface has been closed." << std::endl; + } + + // shutdown Vimba + if( true == this->mSystemFlag ) + { + lError = this->mSystem.Shutdown(); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not shutdown Vimba. Reason: " << lError << std::endl; + } + + std::cout << "......Vimba has been stooped." << std::endl; + } +} + +// +// Convert given string to IP address, +// using respective socket library (Winsock/Arpa) +// +// Parameters: +// [in] aString String to be converted +// [out] aIPAddress Decimal representation of given IP address string +// +VmbErrorType cActionCommands::ConvertStringToIPAddress( std::string aString, VmbUint32_t* aIPAddress ) +{ + VmbErrorType lError = VmbErrorSuccess; + VmbUint32_t lIP = 0; + + // check parameter + if( (true == aString.empty()) || (NULL == aIPAddress) ) + { + std::cout << "[F]...Invalid parameter given" << std::endl; + return VmbErrorBadParameter; + } + + // convert given string to IP struct + lIP = inet_addr( aString.c_str() ); + if( -1 == lIP ) + { + lError = VmbErrorInvalidValue; + } + else + { + + #ifdef _LITTLE_ENDIAN + lIP = ntohl( lIP ); + #endif + + *aIPAddress = lIP; + } + + return lError; +} + +// +// Start Vimba and open camera with given string +// +// Parameters: +// [in] aCamera The ID or IP address of the camera to work with +// +VmbErrorType cActionCommands::PrepareCamera( std::string aCamera ) +{ + VmbErrorType lError = VmbErrorSuccess; + + // check parameter + if( true == aCamera.empty() ) + { + std::cout << "[F]...Invalid device ID or IP address given." << std::endl; + return VmbErrorBadParameter; + } + + // start Vimba + lError = this->mSystem.Startup(); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not start Vimba API. Reason: " << lError << std::endl; + return lError; + } + + this->mSystemFlag = true; + std::cout << "......Vimba has been started." << std::endl; + + // open camera with given string (could be device ID or IP address) + lError = this->mSystem.OpenCameraByID( aCamera.c_str(), VmbAccessModeFull, this->mCamera ); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not open camera " << aCamera << ". Reason: " << lError << std::endl; + this->FailureShutdown(); + return lError; + } + + this->mCameraFlag = true; + std::cout << "......Camera has been opened (" << aCamera << ")." << std::endl; + + return lError; +} + +// +// Close camera and shutdown Vimba +// +VmbErrorType cActionCommands::StopCamera() +{ + VmbErrorType lError = VmbErrorSuccess; + + if( true == this->mCameraFlag ) + { + // close camera + lError = this->mCamera->Close(); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not close camera. Reason: " << lError << std::endl; + } + + this->mCameraFlag = false; + std::cout << "......Camera has been closed." << std::endl; + } + + if( true == this->mSystemFlag ) + { + // shutdown Vimba + lError = this->mSystem.Shutdown(); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not stop Vimba. Reason: " << lError << std::endl; + } + + this->mSystemFlag = false; + std::cout << "......Vimba has been stopped." << std::endl; + } + + return lError; +} + +// +// Prepare trigger settings for given camera +// +VmbErrorType cActionCommands::PrepareTrigger() +{ + VmbErrorType lError = VmbErrorSuccess; + FeaturePtr lFeature; + char* lTemp = "";; + + // select FrameStart trigger via TriggerSelector feature + lTemp = "FrameStart"; + lError = this->SetFeatureValue( "TriggerSelector", eFeatureOwnerCamera, VmbFeatureDataEnum, lTemp, sizeof(lTemp) ); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not set TriggerSelector to FrameStart. Reason: " << lError << std::endl; + FailureShutdown(); + return lError; + } + + // set trigger source to Action0 + lTemp = "Action0"; + lError = this->SetFeatureValue( "TriggerSource", eFeatureOwnerCamera, VmbFeatureDataEnum, lTemp, sizeof(lTemp) ); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not set TriggerSource to 'Action0'. Reason: " << lError << ". Probably this camera does not support Action Commands." << std::endl; + FailureShutdown(); + return lError; + } + + // enable trigger + lTemp = "On"; + lError = this->SetFeatureValue( "TriggerMode", eFeatureOwnerCamera, VmbFeatureDataEnum, lTemp, sizeof(lTemp) ); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not enable TriggerMode for FrameStart. Reason: " << lError << std::endl; + FailureShutdown(); + return lError; + } + + std::cout << "......Trigger FrameStart has been activated and set to Action0" << std::endl; + + return lError; +} + +// +// Set Action Command information to given feature owner. +// This could be Vimba system, interface or the camera +// +// Parameters: +// [in] aOwner Feature owner, like System, Interface or Camera +// [in] aCommand Action Command struct (device key, group key, group mask) +// +VmbErrorType cActionCommands::PrepareActionCommand( tFeatureOwner aOwner, tActionCommand* aCommand ) +{ + VmbErrorType lError = VmbErrorSuccess; + + // check parameter + if( NULL == aCommand ) + { + std::cout << "[F]...Invalid Action Command given." << std::endl; + FailureShutdown(); + return VmbErrorBadParameter; + } + + // set device key + lError = this->SetFeatureValue( "ActionDeviceKey", aOwner, VmbFeatureDataInt, (void*)(aCommand->mDeviceKey), sizeof(aCommand->mDeviceKey) ); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not set ActionDeviceKey. Reason: " << lError << std::endl; + FailureShutdown(); + return lError; + } + + // set group key + lError = this->SetFeatureValue( "ActionGroupKey", aOwner, VmbFeatureDataInt, (void*)(aCommand->mGroupKey), sizeof(aCommand->mGroupKey) ); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not set ActionGroupKey. Reason: " << lError << std::endl; + FailureShutdown(); + return lError; + } + + // set group mask + lError = this->SetFeatureValue( "ActionGroupMask", aOwner, VmbFeatureDataInt, (void*)(aCommand->mGroupMask), sizeof(aCommand->mGroupMask) ); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not set ActionGroupMask. Reason: " << lError << std::endl; + FailureShutdown(); + return lError; + } + + std::cout << "......Action Command has been set (" << aCommand->mDeviceKey << ", " << aCommand->mGroupKey << ", " << aCommand->mGroupMask << ")" << std::endl; + + return lError; +} + +// +// Prepare streaming settings in Vimba and the camera, +// like allocating the buffers, start capture engine, etc. +// +VmbErrorType cActionCommands::PrepareStreaming() +{ + VmbErrorType lError = VmbErrorSuccess; + FeaturePtr lFeature; + + // set GVSP packet size to max value (MTU) + // and wait until command is done + lError = this->mCamera->GetFeatureByName( "GVSPAdjustPacketSize", lFeature ); + if( VmbErrorSuccess == lError ) + { + lError = lFeature->RunCommand(); + } + + // check if any failure occurred + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not set GVSP packet size. Reason: " << lError << std::endl; + FailureShutdown(); + return lError; + } + + // check if operation is done + bool lFlag = false; + do + { + lError = lFeature->IsCommandDone( lFlag ); + if( VmbErrorSuccess != lError ) + { + break; + } + + } while( VmbBoolFalse == lFlag ); + + // get GVSP packet size, which was actually set in the camera + VmbInt64_t lGVSPSize = 0; + lError = this->GetFeatureValue( "GVSPPacketSize", eFeatureOwnerCamera, NULL, &lGVSPSize, NULL ); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not get GVSP packet size. Reason: " << lError << std::endl; + } + + std::cout << "......GVSP packet size has been set to maximum (" << lGVSPSize << ")" << std::endl; + + // create new frame observer + this->mFrameObserver = new cFrameObserver( this->mCamera ); + + // start continuous image acquisition + lError = this->mCamera->StartContinuousImageAcquisition( NUM_FRAMES, IFrameObserverPtr(this->mFrameObserver) ); + if( VmbErrorSuccess != lError ) + { + FailureShutdown(); + std::cout << "[F]...Could not start continuous image acquisition. Reason: " << lError << std::endl; + return lError; + } + + this->mStreamingFlag = true; + std::cout << "......Camera acquisition has been started." << std::endl; + + return lError; +} + +// +// End streaming +// +VmbErrorType cActionCommands::StopStreaming() +{ + VmbErrorType lError = VmbErrorSuccess; + + // stop continuous image acquisition + lError = this->mCamera->StopContinuousImageAcquisition(); + if( VmbErrorSuccess != lError ) + { + FailureShutdown(); + std::cout << "[F]...Could not stop streaming. Reason: " << lError << std::endl; + return lError; + } + + this->mStreamingFlag = false; + std::cout << "......Camera acquisition has been stopped." << std::endl; + + return lError; +} + +// +// Send Action Command on system level. +// This command will be broadcasted on all network interfaces. +// +// Parameters: +// [in] aCamera The ID or IP address of the camera to work with +// [in] aCommand Action Command to be used by Vimba and camera +// +VmbErrorType cActionCommands::SendActionCommandOnAllInterfaces( std::string aCamera, tActionCommand aCommand ) +{ + VmbErrorType lError = VmbErrorSuccess; + + // -start Vimba + // -open camera in full access mode and get handle + lError = PrepareCamera( aCamera ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // -select FrameStart trigger feature + // -set source to Action0 + // -enable trigger + lError = PrepareTrigger(); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // Set Action Command to camera + // -set device key + // -set group key + // -set group mask + lError = PrepareActionCommand( eFeatureOwnerCamera, &aCommand ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // -adjust GVSP packet size + // -get payload size + // -allocate memory for frame buffers + // -announce frames and move them to buffer input pool + // -start capture engine + // -move frames to capture queue (buffer output queue) + // -call start acquisition feature in the camera + lError = PrepareStreaming(); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // determine if Action Command shall be send as uni- or broadcast + // if IP address was given, send it as unicast + VmbUint32_t lIP = 0; + lError = ConvertStringToIPAddress( aCamera, &lIP ); + if( VmbErrorSuccess == lError ) + { + // set IP address to Vimba + lError = this->SetFeatureValue( "GevActionDestinationIPAddress", eFeatureOwnerSystem, VmbFeatureDataInt, (void*)lIP, sizeof(lIP) ); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not set IP address '" << aCamera << "' to Vimba. Reason: " << lError << std::endl; + } + + std::cout << "......Action Command will be send as unicast to IP '" << aCamera << "' (" << lIP << ")" << std::endl; + } + + // set Action Command to Vimba system + // -device key + // -group key + // -group mask + lError = PrepareActionCommand(eFeatureOwnerSystem, &aCommand); + if (VmbErrorSuccess != lError) + { + std::cout << "[F]...Could not prepare Action Command. Reason: " << lError << std::endl; + } + + #ifdef _WIN32 + std::cout << "\n<< Please hit 'a' to send prepared Action Command. To stop example hit 'q' >>\n\n"; + #else + std::cout << "\n<< Please enter 'a' and return to send prepared Action Command. To stop example enter 'q' and return >>\n\n"; + #endif + + // repeat this until user hits ESC + int lKey = 0; + do + { + // wait for user input + #ifdef _WIN32 + lKey = _getch(); + #else + lKey = getchar(); + #endif + + if( 97 == lKey ) + { + + // send Action Command by calling command feature + lError = RunCommand( "ActionCommand", eFeatureOwnerSystem ); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not send Action Command. Reason: " << lError << std::endl; + FailureShutdown(); + return lError; + } + + std::cout << "......Action Command has been sent." << std::endl; + + } + + } while( 113 != lKey ); + + // stop streaming + lError = StopStreaming(); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // -close camera + // -shutdown Vimba + lError = StopCamera(); + + return lError; +} + +// +// Send Action Command on interface level. +// This command will be broadcasted on given network interface. +// +// Parameters: +// [in] aCamera The ID or IP address of the camera to work with +// [in] aInterface The network interface on which the Action Command +// will be sent out +// [in] aCommand Action Command to be used by Vimba and camera +// +VmbErrorType cActionCommands::SendActionCommandOnInterface( std::string aCamera, std::string aInterface, tActionCommand aCommand ) +{ + VmbErrorType lError = VmbErrorSuccess; + + // -start Vimba + // -open camera in full access mode and get handle + lError = PrepareCamera( aCamera ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // -select FrameStart trigger feature + // -set source to Action0 + // -enable trigger + lError = PrepareTrigger(); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // Set Action Command to camera + // -set device key + // -set group key + // -set group mask + lError = PrepareActionCommand( eFeatureOwnerCamera, &aCommand ); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // -adjust GVSP packet size + // -get payload size + // -allocate memory for frame buffers + // -announce frames and move them to buffer input pool + // -start capture engine + // -move frames to capture queue (buffer output queue) + // -call start acquisition feature in the camera + lError = PrepareStreaming(); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // get available interfaces + InterfacePtrVector lInterfaces; + lError = this->mSystem.GetInterfaces( lInterfaces ); + if( (VmbErrorSuccess != lError) || (0 == lInterfaces.size()) ) + { + std::cout << "[F]...Could not retrieve interfaces" << std::endl; + FailureShutdown(); + return lError; + } + + // print interface list + bool lFound = false; + int lIndex = 0; + for( int i=0; iGetID( lInterfaceID ); + if( VmbErrorSuccess == lError ) + { + std::cout << ".........[" << i << "] " << lInterfaceID << std::endl; + + // compare given interface ID with current one + if( 0 == lInterfaceID.compare( aInterface ) ) + { + // if interface ID matches, keep index + lFound = true; + lIndex = i; + } + } + } + + // if no interface with given ID was found, return + if( false == lFound ) + { + std::cout << "[F]...Given interface with ID '" << aInterface << "' was not found!" << std::endl; + FailureShutdown( ); + return VmbErrorBadParameter; + } + + // get interface pointer + this->mInterface = lInterfaces.at( lIndex ); + if( true == SP_ISNULL(this->mInterface) ) + { + std::cout << "[F]...No valid interface pointer with given index found" << std::endl; + FailureShutdown(); + return VmbErrorBadParameter; + } + + // check interface type + VmbInterfaceType lInterfaceType = VmbInterfaceUnknown; + lError = this->mInterface->GetType( lInterfaceType ); + if( (VmbErrorSuccess != lError) || (VmbInterfaceEthernet != lInterfaceType) ) + { + printf( "[F]...Selected interface is non-GigE interface!\n" ); + FailureShutdown(); + return VmbErrorBadParameter; + } + + // open interface + lError = this->mInterface->Open(); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not open interface" << std::endl; + FailureShutdown(); + return lError; + } + + this->mInterfaceFlag = true; + std::cout << "......Interface has been opened." << std::endl; + + // determine if Action Command shall be send as uni- or broadcast + // if IP address was given, send it as unicast + VmbUint32_t lIP = 0; + lError = ConvertStringToIPAddress( aCamera, &lIP ); + if( VmbErrorSuccess == lError ) + { + // set IP address to the selected interface + lError = this->SetFeatureValue( "GevActionDestinationIPAddress", eFeatureOwnerInterface, VmbFeatureDataInt, (void*)lIP, sizeof(lIP) ); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not set IP address '" << aCamera << "' to Vimba. Reason: " << lError << std::endl; + } + + std::cout << "......Action Command will be send as unicast to IP '" << aCamera << "' (" << lIP << ")" << std::endl; + } + + // set Action Command to the selected interface + // -device key + // -group key + // -group mask + lError = PrepareActionCommand(eFeatureOwnerInterface, &aCommand); + if (VmbErrorSuccess != lError) + { + std::cout << "[F]...Could not prepare Action Command. Reason: " << lError << std::endl; + } + + #ifdef _WIN32 + std::cout << "\n<< Please hit 'a' to send prepared Action Command. To stop example hit 'q' >>\n\n"; + #else + std::cout << "\n<< Please enter 'a' and return to send prepared Action Command. To stop example enter 'q' and return >>\n\n"; + #endif + + // repeat this until user hits ESC + int lKey = 0; + do + { + // wait for user input + #ifdef _WIN32 + lKey = _getch(); + #else + lKey = getchar(); + #endif + + if( 97 == lKey ) + { + + // send Action Command by calling command feature + lError = RunCommand( "ActionCommand", eFeatureOwnerInterface ); + if( VmbErrorSuccess != lError ) + { + std::cout << "[F]...Could not send Action Command. Reason: " << lError << std::endl; + FailureShutdown(); + return lError; + } + + std::cout << "......Action Command has been sent." << std::endl; + + } + + } while( 113 != lKey ); + + // close interface + lError = this->mInterface->Close(); + if( VmbErrorSuccess != lError ) + { + std::cout << "Could not close interface. Reason: " << lError << std::endl; + } + + this->mInterfaceFlag = false; + std::cout << "......Interface has been closed." << std::endl; + + // stop streaming + lError = StopStreaming(); + if( VmbErrorSuccess != lError ) + { + return lError; + } + + // -close camera + // -shutdown Vimba + lError = StopCamera(); + + return lError; +} + +}}} // namespace AVT::VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/ActionCommands.h b/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/ActionCommands.h new file mode 100644 index 0000000..301e449 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/ActionCommands.h @@ -0,0 +1,200 @@ +/*============================================================================= + Copyright (C) 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ActionCommands.h + + Description: This example will create an Action Command and send it to any + camera, given by parameter. The following can be set up with + parameters as well: + -send Action Command as broadcast on specific network interface + -send Action Command as broadcast to all network interfaces + -send Action Command to specific IP address (unicast) + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_ACTION_COMMANDS +#define AVT_VMBAPI_EXAMPLES_ACTION_COMMANDS + +#include "VimbaCPP/Include/VimbaCPP.h" + +#include "FrameObserver.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// struct representing an Action Command +typedef struct tActionCommand +{ + VmbUint32_t mDeviceKey; + VmbUint32_t mGroupKey; + VmbUint32_t mGroupMask; + +} tActionCommand; + +typedef enum tFeatureOwner +{ + eFeatureOwnerUnknown = 0, + eFeatureOwnerSystem = 1, + eFeatureOwnerInterface = 2, + eFeatureOwnerCamera = 3 + +} tFeatureOwner; + +class cActionCommands +{ + private: + VimbaSystem& mSystem; + InterfacePtr mInterface; + CameraPtr mCamera; + + cFrameObserver* mFrameObserver; + + bool mSystemFlag; + bool mInterfaceFlag; + bool mCameraFlag; + bool mStreamingFlag; + + public: + // + // Constructor + // + cActionCommands(); + + // + // Destructor + // + ~cActionCommands(); + + // + // Helper method to read feature values of any type + // + // Parameters: + // [in] aName Feature name + // [in] aOwner Feature owner, like Vimba system, interface or camera + // [out] aType Feature data type + // [in/out] aValue Buffer for feature value + // [in/out] aSize Size of buffer + // + VmbErrorType GetFeatureValue( const char* aName, tFeatureOwner aOwner, VmbFeatureDataType* aType, void* aValue, size_t* aSize ); + + // + // Helper method to write feature values of any type + // + // Parameters: + // [in] aName Feature name + // [in] aOwner Feature owner, like Vimba system, interface or camera + // [in] aType Feature data type + // [in] aValue Buffer for feature value + // [in] aSize Size of buffer + // + VmbErrorType SetFeatureValue( const char* aName, tFeatureOwner aOwner, VmbFeatureDataType aType, void* aValue, size_t aSize ); + + // + // Helper method to run a Command Feature + // + // Parameters: + // [in] aName Feature name + // [in] aOwner Feature owner, like Vimba system, interface or camera + // + VmbErrorType RunCommand( const char* aName, tFeatureOwner aOwner ); + + // + // Called when any failure occurs within the example. + // Ensures to stop streaming, close interface, close camera and shutdown Vimba + // + void FailureShutdown(); + + // + // Convert given string to IP address, + // using respective socket library (Winsock/Arpa) + // + // Parameters: + // [in] aString String to be converted + // [out] aIPAddress Decimal representation of given IP address string + // + VmbErrorType ConvertStringToIPAddress( std::string aString, VmbUint32_t* aIPAddress ); + + // + // Start Vimba and open camera with given string + // + // Parameters: + // [in] aCamera The ID or IP address of the camera to work with + // + VmbErrorType PrepareCamera( std::string aCamera ); + + // + // Close camera and shutdown Vimba + // + VmbErrorType StopCamera(); + + // + // Prepare trigger settings for given camera + // + VmbErrorType PrepareTrigger(); + + // + // Set Action Command information to given feature owner. + // This could be Vimba system, interface or the camera + // + // Parameters: + // [in] aOwner Feature owner, like System, Interface or Camera + // [in] aCommand Action Command struct (device key, group key, group mask) + // + VmbErrorType PrepareActionCommand( tFeatureOwner aOwner, tActionCommand* aCommand ); + + // + // Prepare streaming settings in Vimba and the camera, + // like allocating the buffers, start capture engine, etc. + // + VmbErrorType PrepareStreaming(); + + // + // End streaming + // + VmbErrorType StopStreaming(); + + // + // Send Action Command on system level. + // This command will be broadcasted on all network interfaces. + // + // Parameters: + // [in] aCamera The ID or IP address of the camera to work with + // [in] aCommand Action Command to be used by Vimba and camera + // + VmbErrorType SendActionCommandOnAllInterfaces( std::string aCamera, tActionCommand aCommand ); + + // + // Send Action Command on interface level. + // This command will be broadcasted on given network interface. + // + // Parameters: + // [in] aCamera The ID or IP address of the camera to work with + // [in] aInterface The network interface on which the Action Command + // will be sent out + // [in] aCommand Action Command to be used by Vimba and camera + // + VmbErrorType SendActionCommandOnInterface( std::string aCamera, std::string aInterface, tActionCommand aCommand ); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/FrameObserver.cpp b/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/FrameObserver.cpp new file mode 100644 index 0000000..448c575 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/FrameObserver.cpp @@ -0,0 +1,76 @@ +/*============================================================================= + Copyright (C) 2013 - 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: FrameObserver.cpp + + Description: The frame observer that is used for notifications from VimbaCPP + regarding the arrival of a newly acquired frame. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +#include "FrameObserver.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// +// We pass the camera that will deliver the frames to the constructor +// +// Parameters: +// [in] pCamera The camera the frame was queued at +// [in] eFrameInfos Indicates how the frame will be displayed +// [in] eColorProcessing Indicates how color processing is applied +// +cFrameObserver::cFrameObserver( CameraPtr aCamera ) + : IFrameObserver( aCamera ) +{ + this->mCamera = aCamera; +} + +// +// This is our callback routine that will be executed on every received frame. +// Triggered by the API. +// +// Parameters: +// [in] pFrame The frame returned from the API +// +void cFrameObserver::FrameReceived( const FramePtr pFrame ) +{ + if(false == SP_ISNULL( pFrame ) ) + { + VmbErrorType lError = VmbErrorSuccess; + VmbFrameStatusType lStatus; + + lError = SP_ACCESS( pFrame)->GetReceiveStatus( lStatus); + if( (VmbErrorSuccess == lError) && (VmbFrameStatusComplete == lStatus)) + { + std::cout << "......Frame has been received" << std::endl; + } + + // requeue frame + this->mCamera->QueueFrame( pFrame ); + } +} + +}}} // namespace AVT::VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/FrameObserver.h b/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/FrameObserver.h new file mode 100644 index 0000000..c15c331 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/FrameObserver.h @@ -0,0 +1,65 @@ +/*============================================================================= + Copyright (C) 2013 - 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: FrameObserver.h + + Description: The frame observer that is used for notifications from VimbaCPP + regarding the arrival of a newly acquired frame. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_FRAMEOBSERVER +#define AVT_VMBAPI_EXAMPLES_FRAMEOBSERVER + +#include "VimbaCPP/Include/VimbaCPP.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + + +class cFrameObserver : virtual public IFrameObserver +{ + private: + CameraPtr mCamera; + + public: + // + // We pass the camera that will deliver the frames to the constructor + // + // Parameters: + // [in] pCamera The camera the frame was queued at + // + cFrameObserver( CameraPtr aCamera ); + + // + // This is our callback routine that will be executed on every received frame. + // Triggered by the API. + // + // Parameters: + // [in] pFrame The frame returned from the API + // + virtual void FrameReceived( const FramePtr aFrame ); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/program.cpp b/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/program.cpp new file mode 100644 index 0000000..8a3dbd9 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ActionCommands/Source/program.cpp @@ -0,0 +1,98 @@ +/*============================================================================= + Copyright (C) 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: Main entry point of ActionCommands example of VimbaCPP. + + annotations: + -local variables are prefixed with 'l' for local + -function parameter are prefixed with 'a' for 'argument' + -structs are prefixed with 't' for 'type' + -classes are prefixed with 'c' for 'class' + -class attributes and struct members are prefixed with 'm' for members + -enum literals are prefixed with 'e' for 'enumeration' + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include + +#include "VimbaCPP/Include/VimbaCPP.h" + +#include "ActionCommands.h" + +// function to print out help how to use this example application +void PrintHelp() +{ + printf( "Usage: ActionCommands \n\n" ); + printf( "Parameters: CameraID ID of the camera to be used\n" ); + printf( " IPAddress IP address of camera to react on Action Command\n" ); + printf( " InterfaceID ID of network interface to send out Action Command\n" ); + printf( " 'ALL' enables broadcast on all interfaces\n\n" ); +} + +int main( int argc, char* argv[] ) +{ + VmbErrorType lError = VmbErrorSuccess; + + std::cout << std::endl; + std::cout << "/////////////////////////////////////////" << std::endl; + std::cout << "/// Vimba API Action Commands Example ///" << std::endl; + std::cout << "/////////////////////////////////////////" << std::endl; + std::cout << std::endl; + + // check number of arguments + if( 3 == argc ) + { + // create Action Command example instance + AVT::VmbAPI::Examples::cActionCommands lProgram; + + // define Action Command to be set in the camera + // and used by either Vimba system or interface module + AVT::VmbAPI::Examples::tActionCommand lActionCommand; + lActionCommand.mDeviceKey = 1; + lActionCommand.mGroupKey = 1; + lActionCommand.mGroupMask = 1; + + // check if interface index is '-1' to send out Action Command on all interfaces + // if not, send Action Command via given network interface + if( 0 == strcmp("ALL", argv[2]) ) + { + lError = lProgram.SendActionCommandOnAllInterfaces( argv[1], lActionCommand ); + } + else + { + lError = lProgram.SendActionCommandOnInterface( argv[1], argv[2], lActionCommand ); + } + } + else + { + lError = VmbErrorBadParameter; + std::cout << "[F]...Invalid number of parameters given!" << std::endl; + std::cout << std::endl; + PrintHelp(); + } + + std::cout << std::endl; + + return lError; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Build/Make/Makefile new file mode 100644 index 0000000..e3a035b --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Build/Make/Makefile @@ -0,0 +1,57 @@ +PROJECT_NAME = AsynchronousGrabConsole + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/../.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk + +include $(MAKE_INCLUDE_DIR)/VimbaImageTransform.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBACPP_LIBS) \ + $(VIMBAIMAGETRANSFORM_LIBS) \ + -lrt + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) \ + $(VIMBAIMAGETRANSFORM_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ApiController.o \ + $(OBJ_DIR)/FrameObserver.o \ + $(OBJ_DIR)/program.o + +DEPENDENCIES = VimbaCPP \ + VimbaImageTransform + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/ApiController.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/ApiController.cpp new file mode 100644 index 0000000..6d04928 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/ApiController.cpp @@ -0,0 +1,245 @@ +/*============================================================================= + Copyright (C) 2013 - 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ApiController.cpp + + Description: Implementation file for the ApiController helper class that + demonstrates how to implement an asynchronous, continuous image + acquisition with VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include + +#include "ApiController.h" +#include "Common/StreamSystemInfo.h" +#include "Common/ErrorCodeToMessage.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +#define NUM_FRAMES 3 + +ApiController::ApiController() + // Get a reference to the Vimba singleton + : m_system ( VimbaSystem::GetInstance() ) +{} + +ApiController::~ApiController() +{ +} + +// +// Translates Vimba error codes to readable error messages +// +// Parameters: +// [in] eErr The error code to be converted to string +// +// Returns: +// A descriptive string representation of the error code +// +std::string ApiController::ErrorCodeToMessage( VmbErrorType eErr ) const +{ + return AVT::VmbAPI::Examples::ErrorCodeToMessage( eErr ); +} + +// +// Starts the Vimba API and loads all transport layers +// +// Returns: +// An API status code +// +VmbErrorType ApiController::StartUp() +{ + return m_system.Startup(); +} + +// +// Shuts down the API +// +void ApiController::ShutDown() +{ + // Release Vimba + m_system.Shutdown(); +} + +// +// Opens the given camera +// Sets the maximum possible Ethernet packet size +// Adjusts the image format +// Sets up the observer that will be notified on every incoming frame +// Calls the API convenience function to start image acquisition +// Closes the camera in case of failure +// +// Parameters: +// [in] Config A configuration struct including the camera ID and other settings +// +// Returns: +// An API status code +// +VmbErrorType ApiController::StartContinuousImageAcquisition( const ProgramConfig& Config ) +{ + // Open the desired camera by its ID + VmbErrorType res = m_system.OpenCameraByID( Config.getCameraID().c_str(), VmbAccessModeFull, m_pCamera ); + if ( VmbErrorSuccess == res ) + { + // Set the GeV packet size to the highest possible value + // (In this example we do not test whether this cam actually is a GigE cam) + FeaturePtr pCommandFeature; + if ( VmbErrorSuccess == m_pCamera->GetFeatureByName( "GVSPAdjustPacketSize", pCommandFeature )) + { + if ( VmbErrorSuccess == pCommandFeature->RunCommand() ) + { + bool bIsCommandDone = false; + do + { + if ( VmbErrorSuccess != pCommandFeature->IsCommandDone( bIsCommandDone )) + { + break; + } + } while ( false == bIsCommandDone ); + } + } + + if ( VmbErrorSuccess == res ) + { + // set camera so that transform algorithms will never fail + res = PrepareCamera(); + if ( VmbErrorSuccess == res ) + { + // Create a frame observer for this camera (This will be wrapped in a shared_ptr so we don't delete it) + m_pFrameObserver = new FrameObserver( m_pCamera, Config.getFrameInfos(), Config.getColorProcessing(), Config.getRGBValue() ); + // Start streaming + res = m_pCamera->StartContinuousImageAcquisition( NUM_FRAMES, IFrameObserverPtr( m_pFrameObserver ), Config.getAllocAndAnnounce() ? FrameAllocation_AllocAndAnnounceFrame : FrameAllocation_AnnounceFrame ); + } + } + if ( VmbErrorSuccess != res ) + { + // If anything fails after opening the camera we close it + m_pCamera->Close(); + } + } + + return res; +} + +/**setting a feature to maximum value that is a multiple of 2 and a multiple of the increment*/ +VmbErrorType SetIntFeatureValueModulo2( const CameraPtr &pCamera, const char* const& Name ) +{ + VmbErrorType result; + FeaturePtr feature; + VmbInt64_t value_min = 0; + VmbInt64_t value_max = 0; + VmbInt64_t value_increment = 0; + + result = SP_ACCESS( pCamera )->GetFeatureByName( Name, feature ); + if( VmbErrorSuccess != result ) + { + return result; + } + + result = SP_ACCESS( feature )->GetRange( value_min, value_max ); + if( VmbErrorSuccess != result ) + { + return result; + } + + result = SP_ACCESS( feature )->GetIncrement( value_increment ); + if( VmbErrorSuccess != result ) + { + return result; + } + + value_max = value_max - ( value_max % value_increment); + if( value_max % 2 != 0) + { + value_max -= value_increment; + } + + result = SP_ACCESS( feature )->SetValue ( value_max ); + return result; +} + +/**prepare camera so that the delivered image will not fail in image transform*/ +VmbErrorType ApiController::PrepareCamera() +{ + VmbErrorType result; + result = SetIntFeatureValueModulo2( m_pCamera, "Width" ); + if( VmbErrorSuccess != result ) + { + return result; + } + result = SetIntFeatureValueModulo2( m_pCamera, "Height" ); + if( VmbErrorSuccess != result ) + { + return result; + } + return result; +} + +// +// Calls the API convenience function to stop image acquisition +// Closes the camera +// +// Returns: +// An API status code +// +VmbErrorType ApiController::StopContinuousImageAcquisition() +{ + // Stop streaming + m_pCamera->StopContinuousImageAcquisition(); + + // Close camera + return m_pCamera->Close(); +} + +// +// Gets all cameras known to Vimba +// +// Returns: +// A vector of camera shared pointers +// +CameraPtrVector ApiController::GetCameraList() const +{ + CameraPtrVector cameras; + // Get all known cameras + if ( VmbErrorSuccess == m_system.GetCameras( cameras )) + { + // And return them + return cameras; + } + return CameraPtrVector(); +} + +// +// Gets the version of the Vimba API +// +// Returns: +// The version as string +// +std::string ApiController::GetVersion() const +{ + std::ostringstream os; + os< + +#include "VimbaCPP/Include/VimbaCPP.h" + +#include "FrameObserver.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class ApiController +{ + public: + ApiController(); + ~ApiController(); + + // + // Starts the Vimba API and loads all transport layers + // + // Returns: + // An API status code + // + VmbErrorType StartUp(); + + // + // Shuts down the API + // + void ShutDown(); + + // + // Opens the given camera + // Sets the maximum possible Ethernet packet size + // Adjusts the image format + // Sets up the observer that will be notified on every incoming frame + // Calls the API convenience function to start image acquisition + // Closes the camera in case of failure + // + // Parameters: + // [in] Config A configuration struct including the camera ID and other settings + // + // Returns: + // An API status code + // + VmbErrorType StartContinuousImageAcquisition( const ProgramConfig & ); + + // + // Calls the API convenience function to stop image acquisition + // Closes the camera + // + // Returns: + // An API status code + // + VmbErrorType StopContinuousImageAcquisition(); + + // + // Gets all cameras known to Vimba + // + // Returns: + // A vector of camera shared pointers + // + CameraPtrVector GetCameraList() const; + + // + // Translates Vimba error codes to readable error messages + // + // Parameters: + // [in] eErr The error code to be converted to string + // + // Returns: + // A descriptive string representation of the error code + // + std::string ErrorCodeToMessage( VmbErrorType eErr ) const; + + // + // Gets the version of the Vimba API + // + // Returns: + // The version as string + // + std::string GetVersion() const; + + private: + VmbErrorType PrepareCamera(); + VimbaSystem & m_system; // A reference to our Vimba singleton + CameraPtr m_pCamera; // The currently streaming camera + FrameObserver* m_pFrameObserver; // Every camera has its own frame observer +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/BaseException.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/BaseException.h new file mode 100644 index 0000000..3f9802c --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/BaseException.h @@ -0,0 +1,84 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: BaseException.h + + Description: + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef BASE_EXCEPTION_H_ +#define BASE_EXCEPTION_H_ + +#include +#include + +#include "VimbaCPP/Include/VimbaCPP.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class BaseException: public std::exception +{ + std::string m_Function; + std::string m_Message; + VmbErrorType m_Result; +public: + BaseException( const char* const &fun, const char* const& msg, VmbErrorType result ) + : m_Result ( result ) + { + try + { + if( NULL != fun) + { + m_Function = std::string( fun ); + } + } + catch(...) {} + try + { + if( NULL != msg) + { + m_Message = std::string( msg ); + } + } + catch(...) {} + } + ~BaseException() throw() + {} + const std::string& Function() const + { + return m_Function; + } + const std::string& Message() const + { + return m_Message; + } + VmbErrorType Result() const + { + return m_Result; + } +}; + +}}} + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/FrameObserver.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/FrameObserver.cpp new file mode 100644 index 0000000..8e7198c --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/FrameObserver.cpp @@ -0,0 +1,370 @@ +/*============================================================================= + Copyright (C) 2013 - 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: FrameObserver.cpp + + Description: The frame observer that is used for notifications from VimbaCPP + regarding the arrival of a newly acquired frame. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#ifdef WIN32 +#include +#else +#include +#endif //WIN32 + +#include "FrameObserver.h" + +#include "TransformImage.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// +// We pass the camera that will deliver the frames to the constructor +// +// Parameters: +// [in] pCamera The camera the frame was queued at +// [in] eFrameInfos Indicates how the frame will be displayed +// [in] eColorProcessing Indicates how color processing is applied +// +FrameObserver::FrameObserver( CameraPtr pCamera, FrameInfos eFrameInfos, ColorProcessing eColorProcessing, bool bRGBValue ) + : IFrameObserver( pCamera ) + , m_eFrameInfos( eFrameInfos ) + , m_bRGB( bRGBValue ) + , m_eColorProcessing( eColorProcessing ) +#ifdef WIN32 + , m_dFrequency( 0.0 ) +#endif //WIN32 +{ +#ifdef WIN32 + LARGE_INTEGER nFrequency; + QueryPerformanceFrequency( &nFrequency ); + m_dFrequency = (double)nFrequency.QuadPart; +#endif //WIN32 +} + +// +// Gets the current timestamp for interval measurement +// +double FrameObserver::GetTime() +{ + double dTime = 0.0; + +#ifdef WIN32 + LARGE_INTEGER nCounter; + QueryPerformanceCounter( &nCounter ); + dTime = ( (double)nCounter.QuadPart ) / m_dFrequency; +#else + //clock_t nTime = times(NULL); + //dTime = ((double)(nTime) * 10000.0) / ((double)CLOCKS_PER_SEC); + struct timespec now; + clock_gettime( CLOCK_REALTIME, &now ); + dTime = ( (double)now.tv_sec ) + ( (double)now.tv_nsec ) / 1000000000.0; +#endif //WIN32 + + return dTime; +} + +// +// Prints out frame parameters such as +// - width +// - height +// - pixel format +// +// Parameters: +// [in] pFrame The frame to work on +// +void PrintFrameInfo( const FramePtr &pFrame ) +{ + std::cout<<" Size:"; + VmbUint32_t nWidth = 0; + VmbErrorType res; + res = pFrame->GetWidth(nWidth); + if( VmbErrorSuccess == res ) + { + std::cout<GetHeight(nHeight); + if( VmbErrorSuccess == res ) + { + std::cout<< nHeight; + } + else + { + std::cout<<"?"; + } + + std::cout<<" Format:"; + VmbPixelFormatType ePixelFormat = VmbPixelFormatMono8; + res = pFrame->GetPixelFormat( ePixelFormat ); + if( VmbErrorSuccess == res ) + { + std::cout<<"0x"<GetFrameID( nFrameID ); + if( VmbErrorSuccess == res ) + { + bFrameIDValid = true; + + if( m_FrameID.IsValid() ) + { + if( nFrameID != ( m_FrameID() + 1 ) ) + { + nFramesMissing = nFrameID - m_FrameID() - 1; + if( 1 == nFramesMissing ) + { + std::cout<<"1 missing frame detected\n"; + } + else + { + std::cout< 0.0 ) + { + dFPS = 1.0 / dTimeDiff; + bFPSValid = true; + } + else + { + bShowFrameInfos = true; + } + } + + m_FrameTime( dFrameTime ); + } + else + { + bShowFrameInfos = true; + m_FrameID.Invalidate(); + m_FrameTime.Invalidate(); + } + + res = pFrame->GetReceiveStatus( eFrameStatus ); + if( VmbErrorSuccess == res ) + { + bFrameStatusValid = true; + + if( VmbFrameStatusComplete != eFrameStatus ) + { + bShowFrameInfos = true; + } + } + else + { + bShowFrameInfos = true; + } + if( bShowFrameInfos ) + { + std::cout<<"Frame ID:"; + if( bFrameIDValid ) + { + std::cout<GetReceiveStatus( status); + if( VmbErrorSuccess == Result && VmbFrameStatusComplete == status) + { + std::vector TransformedData; + if ( m_bRGB ) + { + switch( m_eColorProcessing ) + { + default: + Result = VmbErrorBadParameter; + std::cout<<"unknown color processing parameter\n"; + break; + case ColorProcessing_Off: + Result = TransformImage( pFrame, TransformedData, "RGB24" ); + break; + case ColorProcessing_Matrix: + { + std::cout<<"Color Transform\n"; + const VmbFloat_t Matrix[] = { 0.6f, 0.3f, 0.1f, + 0.6f, 0.3f, 0.1f, + 0.6f, 0.3f, 0.1f}; + Result = TransformImage( pFrame, TransformedData,"BGR24", Matrix ); + } + break; + + } + if( VmbErrorSuccess == Result && TransformedData.size() >=3 ) + { + char old_fill_char = std::cout.fill('0'); + std::cout<QueueFrame( pFrame ); +} +}}} // namespace AVT::VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/FrameObserver.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/FrameObserver.h new file mode 100644 index 0000000..9bb918a --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/FrameObserver.h @@ -0,0 +1,113 @@ +/*============================================================================= + Copyright (C) 2013 - 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: FrameObserver.h + + Description: The frame observer that is used for notifications from VimbaCPP + regarding the arrival of a newly acquired frame. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_FRAMEOBSERVER +#define AVT_VMBAPI_EXAMPLES_FRAMEOBSERVER + +#include +#include "VimbaCPP/Include/VimbaCPP.h" +#include "ProgramConfig.h" +#ifdef WIN32 +#include +#endif //WIN32 + +namespace AVT { +namespace VmbAPI { +namespace Examples { + + +class FrameObserver : virtual public IFrameObserver +{ +public: + // + // We pass the camera that will deliver the frames to the constructor + // + // Parameters: + // [in] pCamera The camera the frame was queued at + // [in] eFrameInfos Indicates how the frame will be displayed + // [in] eColorProcessing Indicates how color processing is applied + // + FrameObserver( CameraPtr pCamera, FrameInfos eFrameInfos, ColorProcessing eColorProcessing, bool bRGBValue ); + + // + // This is our callback routine that will be executed on every received frame. + // Triggered by the API. + // + // Parameters: + // [in] pFrame The frame returned from the API + // + virtual void FrameReceived( const FramePtr pFrame ); + +private: + void ShowFrameInfos( const FramePtr & ); + double GetTime(); + template + class ValueWithState + { + private: + T m_Value; + bool m_State; + public: + ValueWithState() + : m_State( false ) + {} + ValueWithState( T &value ) + : m_Value ( value ) + , m_State( true ) + {} + const T& operator()() const + { + return m_Value; + } + void operator()( const T &value ) + { + m_Value = value; + m_State = true; + } + bool IsValid() const + { + return m_State; + } + void Invalidate() + { + m_State = false; + } + }; + const FrameInfos m_eFrameInfos; + const bool m_bRGB; + const ColorProcessing m_eColorProcessing; + ValueWithState m_FrameTime; + ValueWithState m_FrameID; +#ifdef WIN32 + double m_dFrequency; +#endif //WIN32 +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/ProgramConfig.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/ProgramConfig.h new file mode 100644 index 0000000..f820f10 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/ProgramConfig.h @@ -0,0 +1,246 @@ +/*============================================================================= + Copyright (C) 2014 - 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ProgrammConfig.h + + Description: + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef PROGRAM_CONFIG_H_ +#define PROGRAM_CONFIG_H_ + +#include + +#include "BaseException.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class ProgramConfigException: public BaseException +{ +public: + ProgramConfigException( const char* const &fun, const char* const& msg, VmbErrorType result = VmbErrorOther ) + : BaseException( fun, msg, result ) + { + } + ~ProgramConfigException() throw() + {} +}; + +enum FrameInfos +{ + FrameInfos_Off, + FrameInfos_Show, + FrameInfos_Automatic +}; + +enum ColorProcessing +{ + ColorProcessing_Off, + ColorProcessing_Matrix, +}; + +struct ProgramConfig +{ + FrameInfos m_FrameInfos; + bool m_RGBValue; + ColorProcessing m_ColorProcessing; + std::string m_CameraID; + bool m_PrintHelp; + bool m_UseAllocAndAnnounce; +public: + ProgramConfig() + : m_FrameInfos( AVT::VmbAPI::Examples::FrameInfos_Off ) + , m_RGBValue( false ) + , m_ColorProcessing( ColorProcessing_Off ) + , m_PrintHelp( false ) + , m_UseAllocAndAnnounce( false ) + { + } + VmbErrorType ParseCommandline( int argc, char* argv[] ) + { + VmbErrorType Result = VmbErrorSuccess; + char * pParameter = NULL; // The command line parameter + for( int i = 1; i < argc; ++i ) + { + pParameter = argv[i]; + if( 0 >= std::strlen( pParameter )) + { + return VmbErrorBadParameter; + } + + if( '/' == pParameter[0] ) + { + if( 0 == std::strcmp( pParameter, "/i" )) + { + if( ( FrameInfos_Off != getFrameInfos() ) + || ( getPrintHelp() )) + { + return VmbErrorBadParameter; + } + + setFrameInfos( FrameInfos_Show ); + } + else if( 0 == std::strcmp( pParameter, "/a" )) + { + if( ( FrameInfos_Off != getFrameInfos() ) + || ( getPrintHelp() )) + { + return VmbErrorBadParameter; + } + + setFrameInfos( FrameInfos_Automatic ); + } + else if( 0 == std::strcmp( pParameter, "/h" )) + { + if( ( ! getCameraID().empty() ) + || ( getPrintHelp() ) + || ( AVT::VmbAPI::Examples::FrameInfos_Off != getFrameInfos() )) + { + return VmbErrorBadParameter; + } + + setPrintHelp( true ); + } + else if( 0 == std::strcmp( pParameter, "/r" )) + { + if( getPrintHelp() ) + { + return VmbErrorBadParameter; + } + + setRGBValue( true ); + } + else if( 0 == std::strcmp( pParameter, "/c" )) + { + if( ( ColorProcessing_Off != getColorProcessing() ) + || ( getPrintHelp() )) + { + return VmbErrorBadParameter; + } + + setColorProcessing( ColorProcessing_Matrix ); + setRGBValue( true ); + } + else if( 0 == std::strcmp( pParameter, "/x" )) + { + if( getPrintHelp() ) + { + return VmbErrorBadParameter; + } + + setAllocAndAnnounce( true ); + } + else + { + return VmbErrorBadParameter; + } + } + else + { + if( !getCameraID().empty() ) + { + return VmbErrorBadParameter; + } + + setCameraID( pParameter ); + } + } + return Result; + } + FrameInfos getFrameInfos() const + { + return m_FrameInfos; + } + void setFrameInfos( FrameInfos infos ) + { + m_FrameInfos = infos; + } + bool getRGBValue() const + { + return m_RGBValue; + } + void setRGBValue( bool RGBValue ) + { + m_RGBValue = RGBValue; + } + ColorProcessing getColorProcessing() const + { + return m_ColorProcessing; + } + void setColorProcessing( ColorProcessing processing ) + { + m_ColorProcessing = processing; + } + bool getAllocAndAnnounce() const + { + return m_UseAllocAndAnnounce; + } + void setAllocAndAnnounce( bool useAllocAndAnnounce ) + { + m_UseAllocAndAnnounce = useAllocAndAnnounce; + } + const std::string& getCameraID() const + { + return m_CameraID; + } + void setCameraID( const std::string &name ) + { + m_CameraID = name; + } + void setCameraID( const char* const&name ) + { + if( NULL != name ) + { + m_CameraID = std::string( name ); + } + else + { + throw ProgramConfigException(__FUNCTION__,"null pointer in name parameter", VmbErrorBadParameter); + } + } + bool getPrintHelp() const + { + return m_PrintHelp; + } + void setPrintHelp( bool state ) + { + m_PrintHelp = state; + } + template + static STREAM_TYPE& PrintHelp( STREAM_TYPE &s ) + { + s<<"Usage: AsynchronousGrab [CameraID] [/i] [/h]\n"; + s<<"Parameters: CameraID ID of the camera to use (using first camera if not specified)\n"; + s<<" /i Show frame infos\n"; + s<<" /a Automatically only show frame infos of corrupt frames\n"; + s<<" /h Print out help\n"; + s<<" /r Convert to RGB and show RGB values\n"; + s<<" /c Color correction (includes /r)\n"; + s<<" /x Use AllocAndAnnounceFrame instead of AnnounceFrame\n"; + return s; + } +}; + +}}} +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/TransformImage.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/TransformImage.h new file mode 100644 index 0000000..c6b2f90 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/TransformImage.h @@ -0,0 +1,163 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ImageTransform.h + + Description: Image transformation of Vimba images + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef TRANSFORM_IMAGE_H_ +#define TRANSFORM_IMAGE_H_ + +#include +#include + +#include "VmbTransform.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +VmbErrorType TransformImage( const FramePtr & SourceFrame, std::vector & DestinationData, const std::string &DestinationFormat ) +{ + if( SP_ISNULL( SourceFrame) ) + { + return VmbErrorBadParameter; + } + VmbErrorType Result; + VmbPixelFormatType InputFormat; + VmbUint32_t InputWidth,InputHeight; + Result = SP_ACCESS( SourceFrame )->GetPixelFormat( InputFormat ) ; + if( VmbErrorSuccess != Result ) + { + return Result; + } + Result = SP_ACCESS( SourceFrame )->GetWidth( InputWidth ); + if( VmbErrorSuccess != Result ) + { + return Result; + } + Result = SP_ACCESS( SourceFrame )->GetHeight( InputHeight ); + if( VmbErrorSuccess != Result ) + { + return Result; + } + // Prepare source image + VmbImage SourceImage; + SourceImage.Size = sizeof( SourceImage ); + Result = static_cast( VmbSetImageInfoFromPixelFormat( InputFormat, InputWidth, InputHeight, &SourceImage )); + if( VmbErrorSuccess != Result ) + { + return Result; + } + VmbUchar_t *DataBegin = NULL; + Result = SP_ACCESS( SourceFrame )->GetBuffer( DataBegin ); + if( VmbErrorSuccess != Result ) + { + return Result; + } + SourceImage.Data = DataBegin; + // Prepare destination image + VmbImage DestinationImage; + DestinationImage.Size = sizeof( DestinationImage ); + Result = static_cast( VmbSetImageInfoFromString( DestinationFormat.c_str(), static_cast(DestinationFormat.size()), InputWidth, InputHeight, &DestinationImage) ); + if ( VmbErrorSuccess != Result ) + { + return Result; + } + const size_t ByteCount = ( DestinationImage.ImageInfo.PixelInfo.BitsPerPixel * InputWidth* InputHeight ) / 8 ; + DestinationData.resize( ByteCount ); + DestinationImage.Data = &*DestinationData.begin(); + // Transform data + Result = static_cast( VmbImageTransform( &SourceImage, &DestinationImage, NULL , 0 )); + return Result; +} + +VmbErrorType TransformImage( const FramePtr & SourceFrame, std::vector & DestinationData, const std::string &DestinationFormat, const VmbFloat_t *Matrix ) +{ + if( SP_ISNULL( SourceFrame )) + { + return VmbErrorBadParameter; + } + if ( NULL == Matrix ) + { + return VmbErrorBadParameter; + } + VmbErrorType Result; + VmbPixelFormatType InputFormat; + VmbUint32_t InputWidth,InputHeight; + Result = SP_ACCESS( SourceFrame )->GetPixelFormat( InputFormat ) ; + if( VmbErrorSuccess != Result ) + { + return Result; + } + Result = SP_ACCESS( SourceFrame )->GetWidth( InputWidth ); + if( VmbErrorSuccess != Result ) + { + return Result; + } + Result = SP_ACCESS( SourceFrame )->GetHeight( InputHeight ); + if( VmbErrorSuccess != Result ) + { + return Result; + } + // Prepare source image + VmbImage SourceImage; + SourceImage.Size = sizeof( SourceImage ); + Result = static_cast( VmbSetImageInfoFromPixelFormat( InputFormat, InputWidth, InputHeight, &SourceImage )); + if( VmbErrorSuccess != Result) + { + return Result; + } + VmbUchar_t *DataBegin = NULL; + Result = SP_ACCESS( SourceFrame )->GetBuffer( DataBegin ); + if( VmbErrorSuccess != Result ) + { + return Result; + } + SourceImage.Data = DataBegin; + // Prepare destination image + VmbImage DestinationImage; + DestinationImage.Size = sizeof( DestinationImage ); + Result = static_cast( VmbSetImageInfoFromString( DestinationFormat.c_str(), static_cast(DestinationFormat.size()), InputWidth, InputHeight, &DestinationImage )); + if ( VmbErrorSuccess != Result ) + { + return Result; + } + const size_t ByteCount = ( DestinationImage.ImageInfo.PixelInfo.BitsPerPixel * InputWidth* InputHeight ) / 8 ; + DestinationData.resize( ByteCount ); + DestinationImage.Data = &*DestinationData.begin(); + // Setup Transform parameter + + // Transform data + VmbTransformInfo TransformInfo; + Result = static_cast( VmbSetColorCorrectionMatrix3x3( Matrix, &TransformInfo )); + if( VmbErrorSuccess != Result ) + { + return Result; + } + Result = static_cast( VmbImageTransform( &SourceImage, &DestinationImage, &TransformInfo , 1 )); + return Result; +} + +}}} +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/program.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/program.cpp new file mode 100644 index 0000000..93744f3 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Console/Source/program.cpp @@ -0,0 +1,119 @@ +/*============================================================================= + Copyright (C) 2013 - 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: Implementation of main entry point of AsynchronousGrabConsole + example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#include "VimbaCPP/Include/VimbaCPP.h" +#include "ApiController.h" + +int main( int argc, char* argv[] ) +{ + VmbErrorType err = VmbErrorSuccess; + + std::cout<<"///////////////////////////////////////////\n"; + std::cout<<"/// Vimba API Asynchronous Grab Example ///\n"; + std::cout<<"///////////////////////////////////////////\n\n"; + + ////////////////////// + //Parse command line// + ////////////////////// + AVT::VmbAPI::Examples::ProgramConfig Config; + err = Config.ParseCommandline( argc, argv); + //Write out an error if we could not parse the command line + if ( VmbErrorBadParameter == err ) + { + std::cout<< "Invalid parameters!\n\n" ; + Config.setPrintHelp( true ); + } + + //Print out help and end program + if ( Config.getPrintHelp() ) + { + Config.PrintHelp( std::cout ); + } + else + { + AVT::VmbAPI::Examples::ApiController apiController; + + // Print out version of Vimba + std::cout<<"Vimba C++ API Version "<GetID( strCameraID ); + if( VmbErrorSuccess == err ) + { + Config.setCameraID( strCameraID ); + } + } + } + if ( VmbErrorSuccess == err ) + { + std::cout<<"Opening camera with ID: "< to stop acquisition...\n" ; + getchar(); + + apiController.StopContinuousImageAcquisition(); + } + } + + apiController.ShutDown(); + } + + if ( VmbErrorSuccess == err ) + { + std::cout<<"\nAcquisition stopped.\n" ; + } + else + { + std::string strError = apiController.ErrorCodeToMessage( err ); + std::cout<<"\nAn error occurred: " << strError << "\n"; + } + } + + return err; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Build/Make/Makefile new file mode 100644 index 0000000..5c2db9e --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Build/Make/Makefile @@ -0,0 +1,84 @@ +PROJECT_NAME = AsynchronousGrabQt + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/../.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk +include $(MAKE_INCLUDE_DIR)/VimbaImageTransform.mk +include $(MAKE_INCLUDE_DIR)/Qt.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source + +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + -I$(OBJ_DIR) + +LIBS = $(VIMBACPP_LIBS) \ + $(VIMBAIMAGETRANSFORM_LIBS) \ + $(QTCORE_LIBS) \ + $(QTGUI_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) \ + $(VIMBAIMAGETRANSFORM_CFLAGS) \ + $(QTCORE_CFLAGS) \ + $(QTGUI_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ApiController.o \ + $(OBJ_DIR)/AsynchronousGrab.o \ + $(OBJ_DIR)/CameraObserver.o \ + $(OBJ_DIR)/FrameObserver.o \ + $(OBJ_DIR)/main.o \ + $(OBJ_DIR)/moc_AsynchronousGrab.o \ + $(OBJ_DIR)/moc_CameraObserver.o \ + $(OBJ_DIR)/moc_FrameObserver.o \ + $(OBJ_DIR)/qrc_AsynchronousGrab.o + +GEN_HEADERS = $(OBJ_DIR)/ui_AsynchronousGrab.h + +DEPENDENCIES = VimbaCPP \ + VimbaImageTransform \ + QtCore \ + QtGui + +$(OBJ_DIR)/moc_%.cpp: $(SOURCE_DIR)/%.h $(OBJ_DIR) + $(MOC) -o $@ $< + +$(OBJ_DIR)/ui_%.h: $(SOURCE_DIR)/res/%.ui $(OBJ_DIR) + $(UIC) -o $@ $< + +$(OBJ_DIR)/qrc_%.cpp: $(SOURCE_DIR)/res/%.qrc $(OBJ_DIR) + $(RCC) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) $(GEN_HEADERS) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(OBJ_DIR)/%.cpp $(OBJ_DIR) $(GEN_HEADERS) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/ApiController.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/ApiController.cpp new file mode 100644 index 0000000..5b6e8f9 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/ApiController.cpp @@ -0,0 +1,340 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ApiController.cpp + + Description: Implementation file for the ApiController helper class that + demonstrates how to implement an asynchronous, continuous image + acquisition with VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include +#include "Common/StreamSystemInfo.h" +#include "Common/ErrorCodeToMessage.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +enum { NUM_FRAMES=3, }; + +ApiController::ApiController() + // Get a reference to the Vimba singleton + : m_system( VimbaSystem::GetInstance() ) +{ +} + +ApiController::~ApiController() +{ +} + +// +// Translates Vimba error codes to readable error messages +// +// Parameters: +// [in] eErr The error code to be converted to string +// +// Returns: +// A descriptive string representation of the error code +// +std::string ApiController::ErrorCodeToMessage( VmbErrorType eErr ) const +{ + return AVT::VmbAPI::Examples::ErrorCodeToMessage( eErr ); +} + +// +// Starts the Vimba API and loads all transport layers +// +// Returns: +// An API status code +// +VmbErrorType ApiController::StartUp() +{ + VmbErrorType res; + + // Start Vimba + res = m_system.Startup(); + if( VmbErrorSuccess == res ) + { + // This will be wrapped in a shared_ptr so we don't delete it + SP_SET( m_pCameraObserver , new CameraObserver() ); + // Register an observer whose callback routine gets triggered whenever a camera is plugged in or out + res = m_system.RegisterCameraListObserver( m_pCameraObserver ); + } + + return res; +} + +// +// Shuts down the API +// +void ApiController::ShutDown() +{ + // Release Vimba + m_system.Shutdown(); +} +/*** helper function to set image size to a value that is dividable by modulo 2 and a multiple of the increment. +\note this is needed because VimbaImageTransform does not support odd values for some input formats +*/ +inline VmbErrorType SetValueIntMod2( const CameraPtr &camera, const std::string &featureName, VmbInt64_t &storage ) +{ + VmbErrorType res; + FeaturePtr pFeature; + VmbInt64_t minValue = 0; + VmbInt64_t maxValue = 0; + VmbInt64_t incrementValue = 0; + + res = SP_ACCESS( camera )->GetFeatureByName( featureName.c_str(), pFeature ); + if( VmbErrorSuccess != res ) + { + return res; + } + + res = SP_ACCESS( pFeature )->GetRange( minValue, maxValue ); + if( VmbErrorSuccess != res ) + { + return res; + } + + res = SP_ACCESS( pFeature )->GetIncrement( incrementValue); + if( VmbErrorSuccess != res) + { + return res; + } + + maxValue = maxValue - ( maxValue % incrementValue ); + if( maxValue % 2 != 0) + { + maxValue -= incrementValue; + } + + res = SP_ACCESS( pFeature )->SetValue( maxValue ); + if( VmbErrorSuccess != res ) + { + return res; + } + + storage = maxValue; + return res; +} + +// +// Opens the given camera +// Sets the maximum possible Ethernet packet size +// Adjusts the image format +// Sets up the observer that will be notified on every incoming frame +// Calls the API convenience function to start image acquisition +// Closes the camera in case of failure +// +// Parameters: +// [in] rStrCameraID The ID of the camera to open as reported by Vimba +// +// Returns: +// An API status code +// +VmbErrorType ApiController::StartContinuousImageAcquisition( const std::string &rStrCameraID ) +{ + // Open the desired camera by its ID + VmbErrorType res = m_system.OpenCameraByID( rStrCameraID.c_str(), VmbAccessModeFull, m_pCamera ); + if( VmbErrorSuccess == res ) + { + // Set the GeV packet size to the highest possible value + // (In this example we do not test whether this cam actually is a GigE cam) + FeaturePtr pCommandFeature; + if( VmbErrorSuccess == SP_ACCESS( m_pCamera )->GetFeatureByName( "GVSPAdjustPacketSize", pCommandFeature ) ) + { + if( VmbErrorSuccess == SP_ACCESS( pCommandFeature )->RunCommand() ) + { + bool bIsCommandDone = false; + do + { + if( VmbErrorSuccess != SP_ACCESS( pCommandFeature )->IsCommandDone( bIsCommandDone ) ) + { + break; + } + } while( false == bIsCommandDone ); + } + } + res = SetValueIntMod2( m_pCamera,"Width", m_nWidth ); + if( VmbErrorSuccess == res ) + { + res = SetValueIntMod2( m_pCamera, "Height", m_nHeight ); + if( VmbErrorSuccess == res ) + { + // Store currently selected image format + FeaturePtr pFormatFeature; + res = SP_ACCESS( m_pCamera )->GetFeatureByName( "PixelFormat", pFormatFeature ); + if( VmbErrorSuccess == res ) + { + res = SP_ACCESS( pFormatFeature )->GetValue( m_nPixelFormat ); + if ( VmbErrorSuccess == res ) + { + // Create a frame observer for this camera (This will be wrapped in a shared_ptr so we don't delete it) + SP_SET( m_pFrameObserver , new FrameObserver( m_pCamera ) ); + // Start streaming + res = SP_ACCESS( m_pCamera )->StartContinuousImageAcquisition( NUM_FRAMES, m_pFrameObserver ); + } + } + } + } + if ( VmbErrorSuccess != res ) + { + // If anything fails after opening the camera we close it + SP_ACCESS( m_pCamera )->Close(); + } + } + + return res; +} + +// +// Calls the API convenience function to stop image acquisition +// Closes the camera +// +// Returns: +// An API status code +// +VmbErrorType ApiController::StopContinuousImageAcquisition() +{ + // Stop streaming + SP_ACCESS( m_pCamera )->StopContinuousImageAcquisition(); + + // Close camera + return m_pCamera->Close(); +} + +// +// Gets all cameras known to Vimba +// +// Returns: +// A vector of camera shared pointers +// +CameraPtrVector ApiController::GetCameraList() +{ + CameraPtrVector cameras; + // Get all known cameras + if( VmbErrorSuccess == m_system.GetCameras( cameras ) ) + { + // And return them + return cameras; + } + return CameraPtrVector(); +} + +// +// Gets the width of a frame +// +// Returns: +// The width as integer +// +int ApiController::GetWidth() const +{ + return static_cast(m_nWidth); +} + +// +// Gets the height of a frame +// +// Returns: +// The height as integer +// +int ApiController::GetHeight() const +{ + return static_cast(m_nHeight); +} + +// +// Gets the pixel format of a frame +// +// Returns: +// The pixel format as enum +// +VmbPixelFormatType ApiController::GetPixelFormat() const +{ + return static_cast(m_nPixelFormat); +} + +// +// Gets the oldest frame that has not been picked up yet +// +// Returns: +// A frame shared pointer +// +FramePtr ApiController::GetFrame() +{ + return SP_DYN_CAST( m_pFrameObserver, FrameObserver )->GetFrame(); +} + +// +// Clears all remaining frames that have not been picked up +// +void ApiController::ClearFrameQueue() +{ + SP_DYN_CAST( m_pFrameObserver,FrameObserver )->ClearFrameQueue(); +} + +// +// Queues a given frame to be filled by the API +// +// Parameters: +// [in] pFrame The frame to queue +// +// Returns: +// An API status code +// +VmbErrorType ApiController::QueueFrame( FramePtr pFrame ) +{ + return SP_ACCESS( m_pCamera )->QueueFrame( pFrame ); +} + +// +// Returns the camera observer as QObject pointer to connect their signals to the view's slots +// +QObject* ApiController::GetCameraObserver() +{ + return SP_DYN_CAST( m_pCameraObserver, CameraObserver ).get(); +} + +// +// Returns the frame observer as QObject pointer to connect their signals to the view's slots +// +QObject* ApiController::GetFrameObserver() +{ + return SP_DYN_CAST( m_pFrameObserver, FrameObserver ).get(); +} + +// +// Gets the version of the Vimba API +// +// Returns: +// The version as string +// +std::string ApiController::GetVersion() const +{ + std::ostringstream os; + os << m_system; + return os.str(); +} + +}}} // namespace AVT::VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/ApiController.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/ApiController.h new file mode 100644 index 0000000..7f62375 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/ApiController.h @@ -0,0 +1,191 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ApiController.h + + Description: Implementation file for the ApiController helper class that + demonstrates how to implement an asynchronous, continuous image + acquisition with VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_APICONTROLLER +#define AVT_VMBAPI_EXAMPLES_APICONTROLLER + +#include + +#include + +#include +#include + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class ApiController +{ + public: + ApiController(); + ~ApiController(); + + // + // Starts the Vimba API and loads all transport layers + // + // Returns: + // An API status code + // + VmbErrorType StartUp(); + + // + // Shuts down the API + // + void ShutDown(); + + // + // Opens the given camera + // Sets the maximum possible Ethernet packet size + // Adjusts the image format + // Sets up the observer that will be notified on every incoming frame + // Calls the API convenience function to start image acquisition + // Closes the camera in case of failure + // + // Parameters: + // [in] rStrCameraID The ID of the camera to open as reported by Vimba + // + // Returns: + // An API status code + // + VmbErrorType StartContinuousImageAcquisition( const std::string &rStrCameraID ); + + // + // Calls the API convenience function to stop image acquisition + // Closes the camera + // + // Returns: + // An API status code + // + VmbErrorType StopContinuousImageAcquisition(); + + // + // Gets the width of a frame + // + // Returns: + // The width as integer + // + int GetWidth() const; + + // + // Gets the height of a frame + // + // Returns: + // The height as integer + // + int GetHeight() const; + + // + // Gets the pixel format of a frame + // + // Returns: + // The pixel format as enum + // + VmbPixelFormatType GetPixelFormat() const; + + // + // Gets all cameras known to Vimba + // + // Returns: + // A vector of camera shared pointers + // + CameraPtrVector GetCameraList(); + + // + // Gets the oldest frame that has not been picked up yet + // + // Returns: + // A frame shared pointer + // + FramePtr GetFrame(); + + // + // Queues a given frame to be filled by the API + // + // Parameters: + // [in] pFrame The frame to queue + // + // Returns: + // An API status code + // + VmbErrorType QueueFrame( FramePtr pFrame ); + + // + // Clears all remaining frames that have not been picked up + // + void ClearFrameQueue(); + + // + // Returns the camera observer as QObject pointer to connect their signals to the view's slots + // + QObject* GetCameraObserver(); + + // + // Returns the frame observer as QObject pointer to connect their signals to the view's slots + // + QObject* GetFrameObserver(); + + // + // Translates Vimba error codes to readable error messages + // + // Parameters: + // [in] eErr The error code to be converted to string + // + // Returns: + // A descriptive string representation of the error code + // + std::string ErrorCodeToMessage( VmbErrorType eErr ) const; + + // + // Gets the version of the Vimba API + // + // Returns: + // The version as string + // + std::string GetVersion() const; + private: + // A reference to our Vimba singleton + VimbaSystem& m_system; + // The currently streaming camera + CameraPtr m_pCamera; + // Every camera has its own frame observer + IFrameObserverPtr m_pFrameObserver; + // Our camera observer + ICameraListObserverPtr m_pCameraObserver; + // The current pixel format + VmbInt64_t m_nPixelFormat; + // The current width + VmbInt64_t m_nWidth; + // The current height + VmbInt64_t m_nHeight; +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/AsynchronousGrab.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/AsynchronousGrab.cpp new file mode 100644 index 0000000..330695c --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/AsynchronousGrab.cpp @@ -0,0 +1,354 @@ +/*============================================================================= + Copyright (C) 2012 - 2017 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: AsynchronousGrab.cpp + + Description: Qt dialog class for the GUI of the AsynchronousGrab example of + VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +#include "AsynchronousGrab.h" +#include "VmbTransform.h" +#define NUM_COLORS 3 +#define BIT_DEPTH 8 + +using AVT::VmbAPI::FramePtr; +using AVT::VmbAPI::CameraPtrVector; + +AsynchronousGrab::AsynchronousGrab( QWidget *parent, Qt::WindowFlags flags ) + : QMainWindow( parent, flags ) + , m_bIsStreaming( false ) +{ + ui.setupUi( this ); + ui.m_LabelStream->setAlignment(Qt::AlignCenter ); + // Connect GUI events with event handlers + QObject::connect( ui.m_ButtonStartStop, SIGNAL( clicked() ), this, SLOT( OnBnClickedButtonStartstop() ) ); + + // Start Vimba + VmbErrorType err = m_ApiController.StartUp(); + setWindowTitle( QString( "AsynchronousGrab (Qt version) Vimba C++ API Version " )+ QString::fromStdString( m_ApiController.GetVersion() ) ); + Log( "Starting Vimba", err ); + + if( VmbErrorSuccess == err ) + { + // Connect new camera found event with event handler + QObject::connect( m_ApiController.GetCameraObserver(), SIGNAL( CameraListChangedSignal(int) ), this, SLOT( OnCameraListChanged(int) ) ); + + // Initially get all connected cameras + UpdateCameraListBox(); + std::stringstream strMsg; + strMsg << "Cameras found..." << m_cameras.size(); + Log(strMsg.str() ); + } +} + +AsynchronousGrab::~AsynchronousGrab() +{ + // if we are streaming stop streaming + if( true == m_bIsStreaming ) + { + OnBnClickedButtonStartstop(); + } + + // Before we close the application we stop Vimba + m_ApiController.ShutDown(); +} + +void AsynchronousGrab::OnBnClickedButtonStartstop() +{ + VmbErrorType err; + int nRow = ui.m_ListBoxCameras->currentRow(); + + if( -1 < nRow ) + { + if( false == m_bIsStreaming ) + { + // Start acquisition + err = m_ApiController.StartContinuousImageAcquisition( m_cameras[nRow] ); + // Set up Qt image + if ( VmbErrorSuccess == err ) + { + m_Image = QImage( m_ApiController.GetWidth(), + m_ApiController.GetHeight(), + QImage::Format_RGB888 ); + + QObject::connect( m_ApiController.GetFrameObserver(), SIGNAL( FrameReceivedSignal(int) ), this, SLOT( OnFrameReady(int) ) ); + } + Log( "Starting Acquisition", err ); + m_bIsStreaming = VmbErrorSuccess == err; + } + else + { + m_bIsStreaming = false; + // Stop acquisition + err = m_ApiController.StopContinuousImageAcquisition(); + // Clear all frames that we have not picked up so far + m_ApiController.ClearFrameQueue(); + m_Image = QImage(); + Log( "Stopping Acquisition", err ); + } + + if( false == m_bIsStreaming ) + { + ui.m_ButtonStartStop->setText( QString( "Start Image Acquisition" ) ); + } + else + { + ui.m_ButtonStartStop->setText( QString( "Stop Image Acquisition" ) ); + } + } +} + +// +// This event handler (Qt slot) is triggered through a Qt signal posted by the frame observer +// +// Parameters: +// [in] status The frame receive status (complete, incomplete, ...) +// +void AsynchronousGrab::OnFrameReady( int status ) +{ + if( true == m_bIsStreaming ) + { + // Pick up frame + FramePtr pFrame = m_ApiController.GetFrame(); + if( SP_ISNULL( pFrame ) ) + { + Log("frame pointer is NULL, late frame ready message"); + return; + } + // See if it is not corrupt + if( VmbFrameStatusComplete == status ) + { + VmbUchar_t *pBuffer; + VmbErrorType err = SP_ACCESS( pFrame )->GetImage( pBuffer ); + if( VmbErrorSuccess == err ) + { + VmbUint32_t nSize; + err = SP_ACCESS( pFrame )->GetImageSize( nSize ); + if( VmbErrorSuccess == err ) + { + VmbPixelFormatType ePixelFormat = m_ApiController.GetPixelFormat(); + if( ! m_Image.isNull() ) + { + // Copy it + // We need that because Qt might repaint the view after we have released the frame already + if( ui.m_ColorProcessingCheckBox->checkState()== Qt::Checked ) + { + static const VmbFloat_t Matrix[] = { 8.0f, 0.1f, 0.1f, // this matrix just makes a quick color to mono conversion + 0.1f, 0.8f, 0.1f, + 0.0f, 0.0f, 1.0f }; + if( VmbErrorSuccess != CopyToImage( pBuffer,ePixelFormat, m_Image, Matrix ) ) + { + ui.m_ColorProcessingCheckBox->setChecked( false ); + } + } + else + { + CopyToImage( pBuffer,ePixelFormat, m_Image ); + } + + // Display it + const QSize s = ui.m_LabelStream->size() ; + ui.m_LabelStream->setPixmap( QPixmap::fromImage( m_Image ).scaled(s,Qt::KeepAspectRatio ) ); + } + } + } + } + else + { + // If we receive an incomplete image we do nothing but logging + Log( "Failure in receiving image", VmbErrorOther ); + } + + // And queue it to continue streaming + m_ApiController.QueueFrame( pFrame ); + } +} + +// +// This event handler (Qt slot) is triggered through a Qt signal posted by the camera observer +// +// Parameters: +// [in] reason The reason why the callback of the observer was triggered (plug-in, plug-out, ...) +// +void AsynchronousGrab::OnCameraListChanged( int reason ) +{ + bool bUpdateList = false; + + // We only react on new cameras being found and known cameras being unplugged + if( AVT::VmbAPI::UpdateTriggerPluggedIn == reason ) + { + Log( "Camera list changed. A new camera was discovered by Vimba." ); + bUpdateList = true; + } + else if( AVT::VmbAPI::UpdateTriggerPluggedOut == reason ) + { + Log( "Camera list changed. A camera was disconnected from Vimba." ); + if( true == m_bIsStreaming ) + { + OnBnClickedButtonStartstop(); + } + bUpdateList = true; + } + + if( true == bUpdateList ) + { + UpdateCameraListBox(); + } + + ui.m_ButtonStartStop->setEnabled( 0 < m_cameras.size() || m_bIsStreaming ); +} + +// +// Copies the content of a byte buffer to a Qt image with respect to the image's alignment +// +// Parameters: +// [in] pInbuffer The byte buffer as received from the cam +// [in] ePixelFormat The pixel format of the frame +// [out] OutImage The filled Qt image +// +VmbErrorType AsynchronousGrab::CopyToImage( VmbUchar_t *pInBuffer, VmbPixelFormat_t ePixelFormat, QImage &pOutImage, const float *Matrix /*= NULL */ ) +{ + const int nHeight = m_ApiController.GetHeight(); + const int nWidth = m_ApiController.GetWidth(); + + VmbImage SourceImage,DestImage; + VmbError_t Result; + SourceImage.Size = sizeof( SourceImage ); + DestImage.Size = sizeof( DestImage ); + + Result = VmbSetImageInfoFromPixelFormat( ePixelFormat, nWidth, nHeight, & SourceImage ); + if( VmbErrorSuccess != Result ) + { + Log( "Could not set source image info", static_cast( Result ) ); + return static_cast( Result ); + } + QString OutputFormat; + const int bytes_per_line = pOutImage.bytesPerLine(); + switch( pOutImage.format() ) + { + default: + Log( "unknown output format",VmbErrorBadParameter ); + return VmbErrorBadParameter; + case QImage::Format_RGB888: + if( nWidth*3 != bytes_per_line ) + { + Log( "image transform does not support stride",VmbErrorWrongType ); + return VmbErrorWrongType; + } + OutputFormat = "RGB24"; + break; + } + Result = VmbSetImageInfoFromString( OutputFormat.toStdString().c_str(), OutputFormat.length(),nWidth,nHeight, &DestImage ); + if( VmbErrorSuccess != Result ) + { + Log( "could not set output image info",static_cast( Result ) ); + return static_cast( Result ); + } + SourceImage.Data = pInBuffer; + DestImage.Data = pOutImage.bits(); + // do color processing? + if( NULL != Matrix ) + { + VmbTransformInfo TransformParameter; + Result = VmbSetColorCorrectionMatrix3x3( Matrix, &TransformParameter ); + if( VmbErrorSuccess == Result ) + { + Result = VmbImageTransform( &SourceImage, &DestImage, &TransformParameter,1 ); + } + else + { + Log( "could not set matrix t o transform info ", static_cast( Result ) ); + return static_cast( Result ); + } + } + else + { + Result = VmbImageTransform( &SourceImage, &DestImage,NULL,0 ); + } + if( VmbErrorSuccess != Result ) + { + Log( "could not transform image", static_cast( Result ) ); + return static_cast( Result ); + } + return static_cast( Result ); +} + +// +// Queries and lists all known camera +// +void AsynchronousGrab::UpdateCameraListBox() +{ + // Get all cameras currently connected to Vimba + CameraPtrVector cameras = m_ApiController.GetCameraList(); + + // Simply forget about all cameras known so far + ui.m_ListBoxCameras->clear(); + m_cameras.clear(); + + // And query the camera details again + for( CameraPtrVector::const_iterator iter = cameras.begin(); + cameras.end() != iter; + ++iter ) + { + std::string strCameraName; + std::string strCameraID; + if( VmbErrorSuccess != (*iter)->GetName( strCameraName ) ) + { + strCameraName = "[NoName]"; + } + // If for any reason we cannot get the ID of a camera we skip it + if( VmbErrorSuccess == (*iter)->GetID( strCameraID ) ) + { + ui.m_ListBoxCameras->addItem( QString::fromStdString( strCameraName + " " +strCameraID ) ); + m_cameras.push_back( strCameraID ); + } + } + + ui.m_ButtonStartStop->setEnabled( 0 < m_cameras.size() || m_bIsStreaming ); +} + +// +// Prints out a given logging string, error code and the descriptive representation of that error code +// +// Parameters: +// [in] strMsg A given message to be printed out +// [in] eErr The API status code +// +void AsynchronousGrab::Log( std::string strMsg, VmbErrorType eErr ) +{ + strMsg += "..." + m_ApiController.ErrorCodeToMessage( eErr ); + ui.m_ListLog->insertItem( 0, QString::fromStdString( strMsg ) ); +} + +// +// Prints out a given logging string +// +// Parameters: +// [in] strMsg A given message to be printed out +// +void AsynchronousGrab::Log( std::string strMsg) +{ + ui.m_ListLog->insertItem( 0, QString::fromStdString( strMsg ) ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/AsynchronousGrab.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/AsynchronousGrab.h new file mode 100644 index 0000000..e8855a6 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/AsynchronousGrab.h @@ -0,0 +1,112 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: AsynchronousGrab.h + + Description: Qt dialog class for the GUI of the AsynchronousGrab example of + VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef ASYNCHRONOUSGRABQT_H +#define ASYNCHRONOUSGRABQT_H + +#include +#include "ui_AsynchronousGrab.h" + +#include + +using AVT::VmbAPI::Examples::ApiController; + +class AsynchronousGrab : public QMainWindow +{ + Q_OBJECT + +public: + AsynchronousGrab( QWidget *parent = 0, Qt::WindowFlags flags = 0 ); + ~AsynchronousGrab(); + +private: + // The Qt GUI + Ui::AsynchronousGrabClass ui; + // Our controller that wraps API access + ApiController m_ApiController; + // A list of known camera IDs + std::vector m_cameras; + // Are we streaming? + bool m_bIsStreaming; + // Our Qt image to display + QImage m_Image; + + // + // Queries and lists all known camera + // + void UpdateCameraListBox(); + + // + // Prints out a given logging string, error code and the descriptive representation of that error code + // + // Parameters: + // [in] strMsg A given message to be printed out + // [in] eErr The API status code + // + void Log( std::string strMsg, VmbErrorType eErr ); + + // + // Prints out a given logging string + // + // Parameters: + // [in] strMsg A given message to be printed out + // + void Log( std::string strMsg); + + // + // Copies the content of a byte buffer to a Qt image with respect to the image's alignment + // + // Parameters: + // [in] pInbuffer The byte buffer as received from the cam + // [in] ePixelFormat The pixel format of the frame + // [out] OutImage The filled Qt image + // + VmbErrorType CopyToImage( VmbUchar_t *pInBuffer, VmbPixelFormat_t ePixelFormat, QImage &pOutImage, const float *Matrix = NULL ); + +private slots: + // The event handler for starting / stopping acquisition + void OnBnClickedButtonStartstop(); + + // + // This event handler (Qt slot) is triggered through a Qt signal posted by the frame observer + // + // Parameters: + // [in] status The frame receive status (complete, incomplete, ...) + // + void OnFrameReady( int status ); + + // + // This event handler (Qt slot) is triggered through a Qt signal posted by the camera observer + // + // Parameters: + // [in] reason The reason why the callback of the observer was triggered (plug-in, plug-out, ...) + // + void OnCameraListChanged( int reason ); +}; + +#endif // ASYNCHRONOUSGRABQT_H diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/CameraObserver.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/CameraObserver.cpp new file mode 100644 index 0000000..2756025 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/CameraObserver.cpp @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: CameraObserver.cpp + + Description: The camera observer that is used for notifications from VimbaCPP + regarding a change in the camera list. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// +// This is our callback routine that will be executed every time a camera was plugged in or out +// +// Parameters: +// [in] pCam The camera that triggered the callback +// [in] reason The reason why the callback was triggered +// +void CameraObserver::CameraListChanged( CameraPtr pCam, UpdateTriggerType reason ) +{ + if ( UpdateTriggerPluggedIn == reason + || UpdateTriggerPluggedOut == reason ) + { + // Emit the new camera signal + emit CameraListChangedSignal( reason ); + } +} + +}}} // namespace AVT::VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/CameraObserver.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/CameraObserver.h new file mode 100644 index 0000000..3dcb7f4 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/CameraObserver.h @@ -0,0 +1,66 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: CameraObserver.h + + Description: The camera observer that is used for notifications from VimbaCPP + regarding a change in the camera list. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_CAMERAOBSERVER +#define AVT_VMBAPI_EXAMPLES_CAMERAOBSERVER + +#include + +#include + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class CameraObserver : public QObject, public ICameraListObserver +{ + Q_OBJECT + + public: + // + // This is our callback routine that will be executed every time a camera was plugged in or out + // + // Parameters: + // [in] pCam The camera that triggered the callback + // [in] reason The reason why the callback was triggered + // + virtual void CameraListChanged( CameraPtr pCamera, UpdateTriggerType reason ); + + signals: + // + // The camera list changed event (Qt signal) that notifies about a camera change and its reason + // + // Parameters: + // [out] reason The reason why this event was fired + // + void CameraListChangedSignal( int reason ); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/FrameObserver.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/FrameObserver.cpp new file mode 100644 index 0000000..540a4ba --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/FrameObserver.cpp @@ -0,0 +1,105 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: FrameObserver.cpp + + Description: The frame observer that is used for notifications from VimbaCPP + regarding the arrival of a newly acquired frame. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// +// This is our callback routine that will be executed on every received frame. +// Triggered by the API. +// +// Parameters: +// [in] pFrame The frame returned from the API +// +void FrameObserver::FrameReceived( const FramePtr pFrame ) +{ + bool bQueueDirectly = true; + VmbFrameStatusType eReceiveStatus; + + if( 0 != receivers(SIGNAL(FrameReceivedSignal(int)) ) + && VmbErrorSuccess == pFrame->GetReceiveStatus( eReceiveStatus ) ) + { + // Lock the frame queue + m_FramesMutex.lock(); + // Add frame to queue + m_Frames.push( pFrame ); + // Unlock frame queue + m_FramesMutex.unlock(); + // Emit the frame received signal + emit FrameReceivedSignal( eReceiveStatus ); + bQueueDirectly = false; + } + + // If any error occurred we queue the frame without notification + if( true == bQueueDirectly ) + { + m_pCamera->QueueFrame( pFrame ); + } +} + +// +// After the view has been notified about a new frame it can pick it up. +// It is then removed from the internal queue +// +// Returns: +// A shared pointer to the latest frame +// +FramePtr FrameObserver::GetFrame() +{ + // Lock the frame queue + m_FramesMutex.lock(); + // Pop frame from queue + FramePtr res; + if( !m_Frames.empty() ) + { + res = m_Frames.front(); + m_Frames.pop(); + } + // Unlock frame queue + m_FramesMutex.unlock(); + return res; +} + +// +// Clears the internal (double buffering) frame queue +// +void FrameObserver::ClearFrameQueue() +{ + // Lock the frame queue + m_FramesMutex.lock(); + // Clear the frame queue and release the memory + std::queue empty; + std::swap( m_Frames, empty ); + // Unlock the frame queue + m_FramesMutex.unlock(); +} + +}}} // namespace AVT::VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/FrameObserver.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/FrameObserver.h new file mode 100644 index 0000000..3185eae --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/FrameObserver.h @@ -0,0 +1,97 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: FrameObserver.h + + Description: The frame observer that is used for notifications from VimbaCPP + regarding the arrival of a newly acquired frame. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_FRAMEOBSERVER +#define AVT_VMBAPI_EXAMPLES_FRAMEOBSERVER + +#include + +#include +#include + +#include + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class FrameObserver : public QObject, virtual public IFrameObserver +{ + Q_OBJECT + + public: + // + // We pass the camera that will deliver the frames to the constructor + // + // Parameters: + // [in] pCamera The camera the frame was queued at + // + FrameObserver( CameraPtr pCamera ) : IFrameObserver( pCamera ) {;} + + // + // This is our callback routine that will be executed on every received frame. + // Triggered by the API. + // + // Parameters: + // [in] pFrame The frame returned from the API + // + virtual void FrameReceived( const FramePtr pFrame ); + + // + // After the view has been notified about a new frame it can pick it up. + // It is then removed from the internal queue + // + // Returns: + // A shared pointer to the latest frame + // + FramePtr GetFrame(); + + // + // Clears the internal (double buffering) frame queue + // + void ClearFrameQueue(); + + private: + // Since a Qt signal cannot contain a whole frame + // the frame observer stores all FramePtr + std::queue m_Frames; + QMutex m_FramesMutex; + +signals: + // + // The frame received event (Qt signal) that notifies about a new incoming frame + // + // Parameters: + // [out] status The frame receive status + // + void FrameReceivedSignal( int status ); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/main.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/main.cpp new file mode 100644 index 0000000..2559fed --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/main.cpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: main.cpp + + Description: The main entry point of the AsynchronousGrab example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 "AsynchronousGrab.h" +#include + +int main( int argc, char *argv[] ) +{ + QApplication a( argc, argv ); + AsynchronousGrab w; + w.show(); + return a.exec(); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/res/AsynchronousGrab.png b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/res/AsynchronousGrab.png new file mode 100644 index 0000000..61642b4 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/res/AsynchronousGrab.png differ diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/res/AsynchronousGrab.qrc b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/res/AsynchronousGrab.qrc new file mode 100644 index 0000000..e9cd2c6 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/res/AsynchronousGrab.qrc @@ -0,0 +1,5 @@ + + + AsynchronousGrab.png + + diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/res/AsynchronousGrab.ui b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/res/AsynchronousGrab.ui new file mode 100644 index 0000000..7d6eab2 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousGrab/Qt/Source/res/AsynchronousGrab.ui @@ -0,0 +1,111 @@ + + + AsynchronousGrabClass + + + + 0 + 0 + 1040 + 780 + + + + + 0 + 0 + + + + + 1040 + 780 + + + + + 1040 + 780 + + + + AsynchronousGrab (Qt version) + + + + :/AsynchronousGrabQt/AsynchronousGrab.png:/AsynchronousGrabQt/AsynchronousGrab.png + + + + + + 0 + 10 + 261 + 491 + + + + + + + 0 + 580 + 1041 + 191 + + + + + + + 0 + 540 + 261 + 31 + + + + Start Image Acquisition + + + + + + 270 + 10 + 771 + 561 + + + + + 0 + 0 + + + + + + + + + + 140 + 510 + 121 + 20 + + + + ColorProcessing + + + + + + + + + + diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Build/Make/Makefile new file mode 100644 index 0000000..ef5fc85 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Build/Make/Makefile @@ -0,0 +1,95 @@ +PROJECT_NAME = AsynchronousOpenCVRecorder + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/../.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk +include $(MAKE_INCLUDE_DIR)/VimbaImageTransform.mk +include $(MAKE_INCLUDE_DIR)/Qt.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source + +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + -I$(OBJ_DIR) + + +OPENCV_CFLAGS = $(shell $(PKGCFG) --cflags opencv) + +OPENCV_LIBS = $(shell $(PKGCFG) --libs opencv) + + + +LIBS = $(VIMBACPP_LIBS) \ + $(VIMBAIMAGETRANSFORM_LIBS) \ + $(QTCORE_LIBS) \ + $(QTGUI_LIBS) \ + $(OPENCV_LIBS) + +DEFINES = + + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) \ + $(VIMBAIMAGETRANSFORM_CFLAGS) \ + $(QTCORE_CFLAGS) \ + $(QTGUI_CFLAGS) \ + $(OPENCV_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ApiController.o \ + $(OBJ_DIR)/AsynchronousOpenCVRecorder.o \ + $(OBJ_DIR)/CameraObserver.o \ + $(OBJ_DIR)/FrameObserver.o \ + $(OBJ_DIR)/main.o \ + $(OBJ_DIR)/moc_AsynchronousOpenCVRecorder.o \ + $(OBJ_DIR)/moc_CameraObserver.o \ + $(OBJ_DIR)/moc_FrameObserver.o \ + $(OBJ_DIR)/moc_OpenCVVideoRecorder.o \ + $(OBJ_DIR)/qrc_AsynchronousOpenCVRecorder.o + +GEN_HEADERS = $(OBJ_DIR)/ui_AsynchronousOpenCVRecorder.h + +DEPENDENCIES = VimbaCPP \ + VimbaImageTransform \ + QtCore \ + QtGui + +$(OBJ_DIR)/moc_%.cpp: $(SOURCE_DIR)/%.h $(OBJ_DIR) + $(MOC) -o $@ $< + +$(OBJ_DIR)/ui_%.h: $(SOURCE_DIR)/res/%.ui $(OBJ_DIR) + $(UIC) -o $@ $< + +$(OBJ_DIR)/qrc_%.cpp: $(SOURCE_DIR)/res/%.qrc $(OBJ_DIR) + $(RCC) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) $(GEN_HEADERS) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(OBJ_DIR)/%.cpp $(OBJ_DIR) $(GEN_HEADERS) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Build/Make/Readme b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Build/Make/Readme new file mode 100644 index 0000000..a9c4e86 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Build/Make/Readme @@ -0,0 +1,9 @@ +build Linux +requirements: + Installed QT 4 + OpenCV3 + - Get libopencv-dev package or download from https://github.com/opencv/opencv/archive/3.0.0.tar.gz + - Create OpenCV makefile using CMake + - Build OpenCV by calling 'make' or 'make -j' for multithreaded build + - Install OpenCV by calling 'sudo make install' + For in-depth instructions please refer to: https://docs.opencv.org/3.0.0/d7/d9f/tutorial_linux_install.html diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/ApiController.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/ApiController.cpp new file mode 100644 index 0000000..76db9d6 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/ApiController.cpp @@ -0,0 +1,339 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ApiController.cpp + + Description: Implementation file for the ApiController helper class that + demonstrates how to implement an asynchronous, continuous image + acquisition with VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include +#include "Common/StreamSystemInfo.h" +#include "Common/ErrorCodeToMessage.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +enum { NUM_FRAMES=3, }; + +ApiController::ApiController() + // Get a reference to the Vimba singleton + : m_system( VimbaSystem::GetInstance() ) +{ +} + +ApiController::~ApiController() +{ +} + +// +// Translates Vimba error codes to readable error messages +// +// Parameters: +// [in] eErr The error code to be converted to string +// +// Returns: +// A descriptive string representation of the error code +// +std::string ApiController::ErrorCodeToMessage( VmbErrorType eErr ) const +{ + return AVT::VmbAPI::Examples::ErrorCodeToMessage( eErr ); +} + +// +// Starts the Vimba API and loads all transport layers +// +// Returns: +// An API status code +// +VmbErrorType ApiController::StartUp() +{ + VmbErrorType res; + + // Start Vimba + res = m_system.Startup(); + if( VmbErrorSuccess == res ) + { + // This will be wrapped in a shared_ptr so we don't delete it + SP_SET( m_pCameraObserver , new CameraObserver() ); + // Register an observer whose callback routine gets triggered whenever a camera is plugged in or out + res = m_system.RegisterCameraListObserver( m_pCameraObserver ); + } + + return res; +} + +// +// Shuts down the API +// +void ApiController::ShutDown() +{ + // Release Vimba + m_system.Shutdown(); +} + +/*** helper function to set image size to a value that is dividable by modulo 2. +\note this is needed because VimbaImageTransform does not support odd values for some input formats +*/ +inline VmbErrorType SetValueIntMod2( const CameraPtr &camera, const std::string &featureName, VmbInt64_t &storage ) +{ + VmbErrorType res; + FeaturePtr pFeature; + res = SP_ACCESS( camera )->GetFeatureByName( featureName.c_str(), pFeature ); + if( VmbErrorSuccess == res ) + { + VmbInt64_t minValue,maxValue; + res = SP_ACCESS( pFeature )->GetRange( minValue,maxValue ); + if( VmbErrorSuccess == res ) + { + maxValue = ( maxValue>>1 )<<1; // mod 2 dividable + res = SP_ACCESS( pFeature )->SetValue( maxValue ); + if( VmbErrorSuccess == res ) + { + storage = maxValue; + } + } + } + return res; +} + +// +// Opens the given camera +// Sets the maximum possible Ethernet packet size +// Adjusts the image format +// Sets up the observer that will be notified on every incoming frame +// Calls the API convenience function to start image acquisition +// Closes the camera in case of failure +// +// Parameters: +// [in] rStrCameraID The ID of the camera to open as reported by Vimba +// +// Returns: +// An API status code +// +VmbErrorType ApiController::StartContinuousImageAcquisition( const std::string &rStrCameraID ) +{ + // Open the desired camera by its ID + VmbErrorType res = m_system.OpenCameraByID( rStrCameraID.c_str(), VmbAccessModeFull, m_pCamera ); + if( VmbErrorSuccess == res ) + { + // Set the GeV packet size to the highest possible value + // (In this example we do not test whether this cam actually is a GigE cam) + FeaturePtr pCommandFeature; + if( VmbErrorSuccess == SP_ACCESS( m_pCamera )->GetFeatureByName( "GVSPAdjustPacketSize", pCommandFeature ) ) + { + if( VmbErrorSuccess == SP_ACCESS( pCommandFeature )->RunCommand() ) + { + bool bIsCommandDone = false; + do + { + if( VmbErrorSuccess != SP_ACCESS( pCommandFeature )->IsCommandDone( bIsCommandDone ) ) + { + break; + } + } while( false == bIsCommandDone ); + } + } + res = SetValueIntMod2( m_pCamera,"Width", m_nWidth ); + if( VmbErrorSuccess == res ) + { + res = SetValueIntMod2( m_pCamera, "Height", m_nHeight ); + if( VmbErrorSuccess == res ) + { + m_FPS = 15.0; + FeaturePtr pFeatureFPS ; + res = SP_ACCESS( m_pCamera )->GetFeatureByName("AcquisitionFrameRateAbs", pFeatureFPS); + if( VmbErrorSuccess != res) + { + // lets try other + res = SP_ACCESS( m_pCamera )->GetFeatureByName("AcquisitionFrameRate", pFeatureFPS); + } + if( VmbErrorSuccess == res ) + { + res = SP_ACCESS(pFeatureFPS)->GetValue( m_FPS ); + } + // Store currently selected image format + FeaturePtr pFormatFeature; + res = SP_ACCESS( m_pCamera )->GetFeatureByName( "PixelFormat", pFormatFeature ); + if( VmbErrorSuccess == res ) + { + res = SP_ACCESS( pFormatFeature )->GetValue( m_nPixelFormat ); + if ( VmbErrorSuccess == res ) + { + // Create a frame observer for this camera (This will be wrapped in a shared_ptr so we don't delete it) + SP_SET( m_pFrameObserver , new FrameObserver( m_pCamera ) ); + // Start streaming + res = SP_ACCESS( m_pCamera )->StartContinuousImageAcquisition( NUM_FRAMES, m_pFrameObserver ); + } + } + } + } + } + + return res; +} + +// +// Calls the API convenience function to stop image acquisition +// Closes the camera +// +// Returns: +// An API status code +// +VmbErrorType ApiController::StopContinuousImageAcquisition() +{ + // Stop streaming + m_pCamera->StopContinuousImageAcquisition(); + + // Close camera + return m_pCamera->Close(); +} + +// +// Gets all cameras known to Vimba +// +// Returns: +// A vector of camera shared pointers +// +CameraPtrVector ApiController::GetCameraList() +{ + CameraPtrVector cameras; + // Get all known cameras + if( VmbErrorSuccess == m_system.GetCameras( cameras ) ) + { + // And return them + return cameras; + } + return CameraPtrVector(); +} + +// +// Gets the width of a frame +// +// Returns: +// The width as integer +// +int ApiController::GetWidth() const +{ + return static_cast(m_nWidth); +} + +// +// Gets the height of a frame +// +// Returns: +// The height as integer +// +int ApiController::GetHeight() const +{ + return static_cast(m_nHeight); +} + +// +// Gets the pixel format of a frame +// +// Returns: +// The pixel format as enum +// +VmbPixelFormatType ApiController::GetPixelFormat() const +{ + return static_cast(m_nPixelFormat); +} + +// +// Gets the current frames per second +// +// Returns: +// Frame rate in Hertz +// +double ApiController::GetFPS() const +{ + return m_FPS; +} + +// +// Gets the oldest frame that has not been picked up yet +// +// Returns: +// A frame shared pointer +// +FramePtr ApiController::GetFrame() +{ + return SP_DYN_CAST( m_pFrameObserver, FrameObserver )->GetFrame(); +} + +// +// Clears all remaining frames that have not been picked up +// +void ApiController::ClearFrameQueue() +{ + SP_DYN_CAST( m_pFrameObserver,FrameObserver )->ClearFrameQueue(); +} + +// +// Queues a given frame to be filled by the API +// +// Parameters: +// [in] pFrame The frame to queue +// +// Returns: +// An API status code +// +VmbErrorType ApiController::QueueFrame( FramePtr pFrame ) +{ + return SP_ACCESS( m_pCamera )->QueueFrame( pFrame ); +} + +// +// Returns the camera observer as QObject pointer to connect their signals to the view's slots +// +QObject* ApiController::GetCameraObserver() +{ + return SP_DYN_CAST( m_pCameraObserver, CameraObserver ).get(); +} + +// +// Returns the frame observer as QObject pointer to connect their signals to the view's slots +// +QObject* ApiController::GetFrameObserver() +{ + return SP_DYN_CAST( m_pFrameObserver, FrameObserver ).get(); +} + +// +// Gets the version of the Vimba API +// +// Returns: +// The version as string +// +std::string ApiController::GetVersion() const +{ + std::ostringstream os; + os << m_system; + return os.str(); +} + +}}} // namespace AVT::VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/ApiController.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/ApiController.h new file mode 100644 index 0000000..6d9c375 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/ApiController.h @@ -0,0 +1,201 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ApiController.h + + Description: Implementation file for the ApiController helper class that + demonstrates how to implement an asynchronous, continuous image + acquisition with VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_APICONTROLLER +#define AVT_VMBAPI_EXAMPLES_APICONTROLLER + +#include + +#include + +#include +#include + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class ApiController +{ + public: + ApiController(); + ~ApiController(); + + // + // Starts the Vimba API and loads all transport layers + // + // Returns: + // An API status code + // + VmbErrorType StartUp(); + + // + // Shuts down the API + // + void ShutDown(); + + // + // Opens the given camera + // Sets the maximum possible Ethernet packet size + // Adjusts the image format + // Sets up the observer that will be notified on every incoming frame + // Calls the API convenience function to start image acquisition + // Closes the camera in case of failure + // + // Parameters: + // [in] rStrCameraID The ID of the camera to open as reported by Vimba + // + // Returns: + // An API status code + // + VmbErrorType StartContinuousImageAcquisition( const std::string &rStrCameraID ); + + // + // Calls the API convenience function to stop image acquisition + // Closes the camera + // + // Returns: + // An API status code + // + VmbErrorType StopContinuousImageAcquisition(); + + // + // Gets the width of a frame + // + // Returns: + // The width as integer + // + int GetWidth() const; + + // + // Gets the height of a frame + // + // Returns: + // The height as integer + // + int GetHeight() const; + + // + // Gets the pixel format of a frame + // + // Returns: + // The pixel format as enum + // + VmbPixelFormatType GetPixelFormat() const; + + // + // Gets the current frames per second + // + // Returns: + // Frame rate in Hertz + // + double GetFPS() const; + + // + // Gets all cameras known to Vimba + // + // Returns: + // A vector of camera shared pointers + // + CameraPtrVector GetCameraList(); + + // + // Gets the oldest frame that has not been picked up yet + // + // Returns: + // A frame shared pointer + // + FramePtr GetFrame(); + + // + // Queues a given frame to be filled by the API + // + // Parameters: + // [in] pFrame The frame to queue + // + // Returns: + // An API status code + // + VmbErrorType QueueFrame( FramePtr pFrame ); + + // + // Clears all remaining frames that have not been picked up + // + void ClearFrameQueue(); + + // + // Returns the camera observer as QObject pointer to connect their signals to the view's slots + // + QObject* GetCameraObserver(); + + // + // Returns the frame observer as QObject pointer to connect their signals to the view's slots + // + QObject* GetFrameObserver(); + + // + // Translates Vimba error codes to readable error messages + // + // Parameters: + // [in] eErr The error code to be converted to string + // + // Returns: + // A descriptive string representation of the error code + // + std::string ErrorCodeToMessage( VmbErrorType eErr ) const; + + // + // Gets the version of the Vimba API + // + // Returns: + // The version as string + // + std::string GetVersion() const; + private: + // A reference to our Vimba singleton + VimbaSystem& m_system; + // The currently streaming camera + CameraPtr m_pCamera; + // Every camera has its own frame observer + IFrameObserverPtr m_pFrameObserver; + // Our camera observer + ICameraListObserverPtr m_pCameraObserver; + // The current pixel format + VmbInt64_t m_nPixelFormat; + // The current width + VmbInt64_t m_nWidth; + // The current height + VmbInt64_t m_nHeight; + // The current FPS + double m_FPS; +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/AsynchronousOpenCVRecorder.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/AsynchronousOpenCVRecorder.cpp new file mode 100644 index 0000000..a0bc8d3 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/AsynchronousOpenCVRecorder.cpp @@ -0,0 +1,376 @@ +/*============================================================================= + Copyright (C) 2015 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: AsynchronousOpenCVRecorder.cpp + + Description: Qt dialog class for the GUI of the AsynchronousOpenCVRecorder + example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +#include "AsynchronousOpenCVRecorder.h" +#include "VmbTransform.h" +#define NUM_COLORS 3 +#define BIT_DEPTH 8 + +using AVT::VmbAPI::FramePtr; +using AVT::VmbAPI::CameraPtrVector; + +AsynchronousOpenCVRecorder::AsynchronousOpenCVRecorder( QWidget *parent, Qt::WindowFlags flags ) + : QMainWindow( parent, flags ) + , m_bIsStreaming( false ) +{ + ui.setupUi( this ); + ui.m_LabelStream->setAlignment(Qt::AlignCenter ); + // Connect GUI events with event handlers + QObject::connect( ui.m_ButtonStartStop, SIGNAL( clicked() ), this, SLOT( OnBnClickedButtonStartstop() ) ); + + // Start Vimba + VmbErrorType err = m_ApiController.StartUp(); + setWindowTitle( QString( "Asynchronous OpenCV Recorder Vimba C++ API Version " )+ QString::fromStdString( m_ApiController.GetVersion() ) ); + Log( "Starting Vimba", err ); + + if( VmbErrorSuccess == err ) + { + // Connect new camera found event with event handler + QObject::connect( m_ApiController.GetCameraObserver(), SIGNAL( CameraListChangedSignal(int) ), this, SLOT( OnCameraListChanged(int) ) ); + + // Initially get all connected cameras + UpdateCameraListBox(); + std::stringstream strMsg; + strMsg << "Cameras found..." << m_cameras.size(); + Log(strMsg.str() ); + } +} + +AsynchronousOpenCVRecorder::~AsynchronousOpenCVRecorder() +{ + // if we are streaming stop streaming + if( true == m_bIsStreaming ) + OnBnClickedButtonStartstop(); + + // Before we close the application we stop Vimba + m_ApiController.ShutDown(); + +} + +void AsynchronousOpenCVRecorder::OnBnClickedButtonStartstop() +{ + VmbErrorType err; + int nRow = ui.m_ListBoxCameras->currentRow(); + + if( -1 < nRow ) + { + if( false == m_bIsStreaming ) + { + // Start acquisition + err = m_ApiController.StartContinuousImageAcquisition( m_cameras[nRow] ); + // Set up Qt image + if ( VmbErrorSuccess == err) + { + VmbUint32_t Width = m_ApiController.GetWidth(); + VmbUint32_t Height = m_ApiController.GetHeight(); + double FPS = m_ApiController.GetFPS(); + try + { + m_pVideoRecorder = OpenCVRecorderPtr( new OpenCVRecorder("AsynchronousOpenCVRecorder.avi", FPS, Width,Height) ); + m_pVideoRecorder->start(); + } + catch(const BaseException &bex) + { + Log( (bex.Function()+" :" + bex.Message() ).toStdString() ); + } + m_Image = QImage( Width, Height, QImage::Format_RGB888 ); + + QObject::connect( m_ApiController.GetFrameObserver(), SIGNAL( FrameReceivedSignal(int) ), this, SLOT( OnFrameReady(int) ) ); + } + Log( "Starting Acquisition", err ); + m_bIsStreaming = VmbErrorSuccess == err; + } + else + { + if( !m_pVideoRecorder.isNull() ) + { + m_pVideoRecorder->stopThread(); + if( ! m_pVideoRecorder->wait( 1000 ) ) + { + m_pVideoRecorder->terminate(); + } + m_pVideoRecorder.clear(); + } + m_bIsStreaming = false; + // Stop acquisition + err = m_ApiController.StopContinuousImageAcquisition(); + // Clear all frames that we have not picked up so far + m_ApiController.ClearFrameQueue(); + m_Image = QImage(); + Log( "Stopping Acquisition", err ); + } + + if( false == m_bIsStreaming ) + { + ui.m_ButtonStartStop->setText( QString( "Start Image Acquisition" ) ); + } + else + { + ui.m_ButtonStartStop->setText( QString( "Stop Image Acquisition" ) ); + } + } +} + +// +// This event handler (Qt slot) is triggered through a Qt signal posted by the frame observer +// +// Parameters: +// [in] status The frame receive status (complete, incomplete, ...) +// +void AsynchronousOpenCVRecorder::OnFrameReady( int status ) +{ + if( true == m_bIsStreaming ) + { + // Pick up frame + FramePtr pFrame = m_ApiController.GetFrame(); + if( SP_ISNULL( pFrame ) ) + { + Log("frame pointer is NULL, late frame ready message"); + return; + } + // See if it is not corrupt + if( VmbFrameStatusComplete == status ) + { + if(! m_pVideoRecorder.isNull() ) + { + m_pVideoRecorder->enqueueFrame( *pFrame); + } + VmbUchar_t *pBuffer; + VmbErrorType err = SP_ACCESS( pFrame )->GetImage( pBuffer ); + if( VmbErrorSuccess == err ) + { + VmbUint32_t nSize; + err = SP_ACCESS( pFrame )->GetImageSize( nSize ); + if( VmbErrorSuccess == err ) + { + VmbPixelFormatType ePixelFormat = m_ApiController.GetPixelFormat(); + if( ! m_Image.isNull() ) + { + // Copy it + // We need that because Qt might repaint the view after we have released the frame already + if( ui.m_ColorProcessingCheckBox->checkState()== Qt::Checked ) + { + static const VmbFloat_t Matrix[] = { 8.0f, 0.1f, 0.1f, // this matrix just makes a quick color to mono conversion + 0.1f, 0.8f, 0.1f, + 0.0f, 0.0f, 1.0f }; + if( VmbErrorSuccess != CopyToImage( pBuffer,ePixelFormat, m_Image, Matrix ) ) + { + ui.m_ColorProcessingCheckBox->setChecked( false ); + } + } + else + { + CopyToImage( pBuffer,ePixelFormat, m_Image ); + } + + // Display it + const QSize s = ui.m_LabelStream->size() ; + ui.m_LabelStream->setPixmap( QPixmap::fromImage( m_Image ).scaled(s,Qt::KeepAspectRatio ) ); + } + } + } + } + else + { + // If we receive an incomplete image we do nothing but logging + Log( "Failure in receiving image", VmbErrorOther ); + } + + // And queue it to continue streaming + m_ApiController.QueueFrame( pFrame ); + } +} + +// +// This event handler (Qt slot) is triggered through a Qt signal posted by the camera observer +// +// Parameters: +// [in] reason The reason why the callback of the observer was triggered (plug-in, plug-out, ...) +// +void AsynchronousOpenCVRecorder::OnCameraListChanged( int reason ) +{ + bool bUpdateList = false; + + // We only react on new cameras being found and known cameras being unplugged + if( AVT::VmbAPI::UpdateTriggerPluggedIn == reason ) + { + Log( "Camera list changed. A new camera was discovered by Vimba." ); + bUpdateList = true; + } + else if( AVT::VmbAPI::UpdateTriggerPluggedOut == reason ) + { + Log( "Camera list changed. A camera was disconnected from Vimba." ); + if( true == m_bIsStreaming ) + { + OnBnClickedButtonStartstop(); + } + bUpdateList = true; + } + + if( true == bUpdateList ) + { + UpdateCameraListBox(); + } + + ui.m_ButtonStartStop->setEnabled( 0 < m_cameras.size() || m_bIsStreaming ); +} + +// +// Copies the content of a byte buffer to a Qt image with respect to the image's alignment +// +// Parameters: +// [in] pInbuffer The byte buffer as received from the cam +// [in] ePixelFormat The pixel format of the frame +// [out] OutImage The filled Qt image +// +VmbErrorType AsynchronousOpenCVRecorder::CopyToImage( VmbUchar_t *pInBuffer, VmbPixelFormat_t ePixelFormat, QImage &pOutImage, const float *Matrix /*= NULL */ ) +{ + const int nHeight = m_ApiController.GetHeight(); + const int nWidth = m_ApiController.GetWidth(); + + VmbImage SourceImage,DestImage; + VmbError_t Result; + SourceImage.Size = sizeof( SourceImage ); + DestImage.Size = sizeof( DestImage ); + + Result = VmbSetImageInfoFromPixelFormat( ePixelFormat, nWidth, nHeight, & SourceImage ); + if( VmbErrorSuccess != Result ) + { + Log( "Could not set source image info", static_cast( Result ) ); + return static_cast( Result ); + } + QString OutputFormat; + const int bytes_per_line = pOutImage.bytesPerLine(); + switch( pOutImage.format() ) + { + default: + Log( "unknown output format",VmbErrorBadParameter ); + return VmbErrorBadParameter; + case QImage::Format_RGB888: + if( nWidth*3 != bytes_per_line ) + { + Log( "image transform does not support stride",VmbErrorWrongType ); + return VmbErrorWrongType; + } + OutputFormat = "RGB24"; + break; + } + Result = VmbSetImageInfoFromString( OutputFormat.toStdString().c_str(), OutputFormat.length(),nWidth,nHeight, &DestImage ); + if( VmbErrorSuccess != Result ) + { + Log( "could not set output image info",static_cast( Result ) ); + return static_cast( Result ); + } + SourceImage.Data = pInBuffer; + DestImage.Data = pOutImage.bits(); + // do color processing? + if( NULL != Matrix ) + { + VmbTransformInfo TransformParameter; + Result = VmbSetColorCorrectionMatrix3x3( Matrix, &TransformParameter ); + if( VmbErrorSuccess == Result ) + { + Result = VmbImageTransform( &SourceImage, &DestImage, &TransformParameter,1 ); + } + else + { + Log( "could not set matrix t o transform info ", static_cast( Result ) ); + return static_cast( Result ); + } + } + else + { + Result = VmbImageTransform( &SourceImage, &DestImage,NULL,0 ); + } + if( VmbErrorSuccess != Result ) + { + Log( "could not transform image", static_cast( Result ) ); + return static_cast( Result ); + } + return static_cast( Result ); +} + +// +// Queries and lists all known camera +// +void AsynchronousOpenCVRecorder::UpdateCameraListBox() +{ + // Get all cameras currently connected to Vimba + CameraPtrVector cameras = m_ApiController.GetCameraList(); + + // Simply forget about all cameras known so far + ui.m_ListBoxCameras->clear(); + m_cameras.clear(); + + // And query the camera details again + for( CameraPtrVector::const_iterator iter = cameras.begin(); + cameras.end() != iter; + ++iter ) + { + std::string strCameraName; + std::string strCameraID; + if( VmbErrorSuccess != (*iter)->GetName( strCameraName ) ) + { + strCameraName = "[NoName]"; + } + // If for any reason we cannot get the ID of a camera we skip it + if( VmbErrorSuccess == (*iter)->GetID( strCameraID ) ) + { + ui.m_ListBoxCameras->addItem( QString::fromStdString( strCameraName + " " +strCameraID ) ); + m_cameras.push_back( strCameraID ); + } + } + + ui.m_ButtonStartStop->setEnabled( 0 < m_cameras.size() || m_bIsStreaming ); +} + +// +// Prints out a given logging string, error code and the descriptive representation of that error code +// +// Parameters: +// [in] strMsg A given message to be printed out +// [in] eErr The API status code +// +void AsynchronousOpenCVRecorder::Log( std::string strMsg, VmbErrorType eErr ) +{ + strMsg += "..." + m_ApiController.ErrorCodeToMessage( eErr ); + ui.m_ListLog->insertItem( 0, QString::fromStdString( strMsg ) ); +} + +// +// Prints out a given logging string +// +// Parameters: +// [in] strMsg A given message to be printed out +// +void AsynchronousOpenCVRecorder::Log( std::string strMsg) +{ + ui.m_ListLog->insertItem( 0, QString::fromStdString( strMsg ) ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/AsynchronousOpenCVRecorder.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/AsynchronousOpenCVRecorder.h new file mode 100644 index 0000000..7414ba2 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/AsynchronousOpenCVRecorder.h @@ -0,0 +1,114 @@ +/*============================================================================= + Copyright (C) 2015 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: AsynchronousOpenCVRecorder.h + + Description: Qt dialog class for the GUI of the AsynchronousOpenCVRecorder + example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef ASYNCHRONOUSOPENCVRECORDER_H +#define ASYNCHRONOUSOPENCVRECORDER_H + +#include +#include "ui_AsynchronousOpenCVRecorder.h" + +#include +#include "OpenCVVideoRecorder.h" +using AVT::VmbAPI::Examples::ApiController; + +class AsynchronousOpenCVRecorder : public QMainWindow +{ + Q_OBJECT + +public: + AsynchronousOpenCVRecorder( QWidget *parent = 0, Qt::WindowFlags flags = 0 ); + ~AsynchronousOpenCVRecorder(); + +private: + typedef QSharedPointer OpenCVRecorderPtr; + OpenCVRecorderPtr m_pVideoRecorder; + // The Qt GUI + Ui::AsynchronousOpenCVRecorderClass ui; + // Our controller that wraps API access + ApiController m_ApiController; + // A list of known camera IDs + std::vector m_cameras; + // Are we streaming? + bool m_bIsStreaming; + // Our Qt image to display + QImage m_Image; + + // + // Queries and lists all known camera + // + void UpdateCameraListBox(); + + // + // Prints out a given logging string, error code and the descriptive representation of that error code + // + // Parameters: + // [in] strMsg A given message to be printed out + // [in] eErr The API status code + // + void Log( std::string strMsg, VmbErrorType eErr ); + + // + // Prints out a given logging string + // + // Parameters: + // [in] strMsg A given message to be printed out + // + void Log( std::string strMsg); + + // + // Copies the content of a byte buffer to a Qt image with respect to the image's alignment + // + // Parameters: + // [in] pInbuffer The byte buffer as received from the cam + // [in] ePixelFormat The pixel format of the frame + // [out] OutImage The filled Qt image + // + VmbErrorType CopyToImage( VmbUchar_t *pInBuffer, VmbPixelFormat_t ePixelFormat, QImage &pOutImage, const float *Matrix = NULL ); + +private slots: + // The event handler for starting / stopping acquisition + void OnBnClickedButtonStartstop(); + + // + // This event handler (Qt slot) is triggered through a Qt signal posted by the frame observer + // + // Parameters: + // [in] status The frame receive status (complete, incomplete, ...) + // + void OnFrameReady( int status ); + + // + // This event handler (Qt slot) is triggered through a Qt signal posted by the camera observer + // + // Parameters: + // [in] reason The reason why the callback of the observer was triggered (plug-in, plug-out, ...) + // + void OnCameraListChanged( int reason ); +}; + +#endif // ASYNCHRONOUSOPENCVRECORDER_H diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/CameraObserver.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/CameraObserver.cpp new file mode 100644 index 0000000..2756025 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/CameraObserver.cpp @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: CameraObserver.cpp + + Description: The camera observer that is used for notifications from VimbaCPP + regarding a change in the camera list. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// +// This is our callback routine that will be executed every time a camera was plugged in or out +// +// Parameters: +// [in] pCam The camera that triggered the callback +// [in] reason The reason why the callback was triggered +// +void CameraObserver::CameraListChanged( CameraPtr pCam, UpdateTriggerType reason ) +{ + if ( UpdateTriggerPluggedIn == reason + || UpdateTriggerPluggedOut == reason ) + { + // Emit the new camera signal + emit CameraListChangedSignal( reason ); + } +} + +}}} // namespace AVT::VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/CameraObserver.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/CameraObserver.h new file mode 100644 index 0000000..683de30 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/CameraObserver.h @@ -0,0 +1,66 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: CameraObserver.h + + Description: The camera observer that is used for notifications from VimbaCPP + regarding a change in the camera list. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_CAMERAOBSERVER +#define AVT_VMBAPI_EXAMPLES_CAMERAOBSERVER + +#include + +#include + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class CameraObserver : public QObject, public ICameraListObserver +{ + Q_OBJECT + + public: + // + // This is our callback routine that will be executed every time a camera was plugged in or out + // + // Parameters: + // [in] pCam The camera that triggered the callback + // [in] reason The reason why the callback was triggered + // + virtual void CameraListChanged( CameraPtr pCamera, UpdateTriggerType reason ); + + signals: + // + // The camera list changed event (Qt signal) that notifies about a camera change and its reason + // + // Parameters: + // [out] reason The reason why this event was fired + // + void CameraListChangedSignal( int reason ); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/FrameObserver.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/FrameObserver.cpp new file mode 100644 index 0000000..540a4ba --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/FrameObserver.cpp @@ -0,0 +1,105 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: FrameObserver.cpp + + Description: The frame observer that is used for notifications from VimbaCPP + regarding the arrival of a newly acquired frame. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// +// This is our callback routine that will be executed on every received frame. +// Triggered by the API. +// +// Parameters: +// [in] pFrame The frame returned from the API +// +void FrameObserver::FrameReceived( const FramePtr pFrame ) +{ + bool bQueueDirectly = true; + VmbFrameStatusType eReceiveStatus; + + if( 0 != receivers(SIGNAL(FrameReceivedSignal(int)) ) + && VmbErrorSuccess == pFrame->GetReceiveStatus( eReceiveStatus ) ) + { + // Lock the frame queue + m_FramesMutex.lock(); + // Add frame to queue + m_Frames.push( pFrame ); + // Unlock frame queue + m_FramesMutex.unlock(); + // Emit the frame received signal + emit FrameReceivedSignal( eReceiveStatus ); + bQueueDirectly = false; + } + + // If any error occurred we queue the frame without notification + if( true == bQueueDirectly ) + { + m_pCamera->QueueFrame( pFrame ); + } +} + +// +// After the view has been notified about a new frame it can pick it up. +// It is then removed from the internal queue +// +// Returns: +// A shared pointer to the latest frame +// +FramePtr FrameObserver::GetFrame() +{ + // Lock the frame queue + m_FramesMutex.lock(); + // Pop frame from queue + FramePtr res; + if( !m_Frames.empty() ) + { + res = m_Frames.front(); + m_Frames.pop(); + } + // Unlock frame queue + m_FramesMutex.unlock(); + return res; +} + +// +// Clears the internal (double buffering) frame queue +// +void FrameObserver::ClearFrameQueue() +{ + // Lock the frame queue + m_FramesMutex.lock(); + // Clear the frame queue and release the memory + std::queue empty; + std::swap( m_Frames, empty ); + // Unlock the frame queue + m_FramesMutex.unlock(); +} + +}}} // namespace AVT::VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/FrameObserver.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/FrameObserver.h new file mode 100644 index 0000000..f714cfb --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/FrameObserver.h @@ -0,0 +1,93 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: FrameObserver.h + + Description: The frame observer that is used for notifications from VimbaCPP + regarding the arrival of a newly acquired frame. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_FRAMEOBSERVER +#define AVT_VMBAPI_EXAMPLES_FRAMEOBSERVER + +#include + +#include +#include + +#include + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class FrameObserver : public QObject, virtual public IFrameObserver +{ + Q_OBJECT + + public: + // We pass the camera that will deliver the frames to the constructor + FrameObserver( CameraPtr pCamera ) : IFrameObserver( pCamera ) {;} + + // + // This is our callback routine that will be executed on every received frame. + // Triggered by the API. + // + // Parameters: + // [in] pFrame The frame returned from the API + // + virtual void FrameReceived( const FramePtr pFrame ); + + // + // After the view has been notified about a new frame it can pick it up. + // It is then removed from the internal queue + // + // Returns: + // A shared pointer to the latest frame + // + FramePtr GetFrame(); + + // + // Clears the internal (double buffering) frame queue + // + void ClearFrameQueue(); + + private: + // Since a Qt signal cannot contain a whole frame + // the frame observer stores all FramePtr + std::queue m_Frames; + QMutex m_FramesMutex; + + signals: + // + // The frame received event (Qt signal) that notifies about a new incoming frame + // + // Parameters: + // [out] status The frame receive status + // + void FrameReceivedSignal( int status ); + +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/OpenCVVideoRecorder.h b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/OpenCVVideoRecorder.h new file mode 100644 index 0000000..47194c8 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/OpenCVVideoRecorder.h @@ -0,0 +1,401 @@ +/*============================================================================= + Copyright (C) 2015 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: OpenCVVideoRecorder.h + + Description: class to save videos with OpenCV. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + + + +=============================================================================*/ + +/*=========================================================================== + +By downloading, copying, installing or using the software you agree to this license. +If you do not agree to this license, do not download, install, +copy or use the software. + + + License Agreement + For Open Source Computer Vision Library + (3-clause BSD License) + +Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +Copyright (C) 2015, OpenCV Foundation, all rights reserved. +Copyright (C) 2015, Itseez Inc., all rights reserved. +Third party copyrights are property of their respective owners. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * 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. + + * Neither the names of the copyright holders nor the names of the 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 copyright holders 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. + +=============================================================================*/ +#ifndef OPEN_CV_VIDEO_RECORDER_H_ +#define OPEN_CV_VIDEO_RECORDER_H_ +// open cv include +#include "opencv2/opencv.hpp" +//qt include +#include "QtCore/QSharedPointer" +#include "QtCore/QList" +#include "QtCore/QMutex" +#include "QtCore/QWaitCondition" +#include "QtCore/QThread" +// std include +#include +#include +#include +// allied vision image transform include +#include "VmbTransform.h" +#include + + +// +// Base exception +// +class BaseException: public std::exception +{ + QString m_Function; + QString m_Message; +public: + BaseException( const char*fun, const char* msg) + { + try { if( NULL != fun ) { m_Function = QString( fun );}} + catch(...) {} + try { if( NULL != msg ) { m_Message = QString( msg ); } + } catch(...) {} + } + ~BaseException() throw() {} + const QString& Function() const { return m_Function; } + const QString& Message() const { return m_Message; } +}; +// +// Exception for video recorder +class VideoRecorderException: public BaseException +{ +public: + VideoRecorderException( const char* fun, const char*msg) + : BaseException( fun, msg ) + {} + ~VideoRecorderException() throw() {} +}; +// +// Video recorder using open cv VideoWriter +// +class OpenCVRecorder: public QThread +{ + Q_OBJECT; + // + // Example FOURCC codes that can be used with the OpenCVRecorder + // + VmbUint32_t maxQueueElements() const { return 3; } + enum + { + FOURCC_USER_SELECT = CV_FOURCC_PROMPT, + FOURCC_DEFAULT = CV_FOURCC_MACRO('I','Y','U','V'), + FOURCC_MPEG1 = CV_FOURCC_MACRO('P','I','M','1'), + FOURCC_MJPEG = CV_FOURCC_MACRO('M','J','P','G'), + FOURCC_MPEG42 = CV_FOURCC_MACRO('M','P','4','2'), + FOURCC_MPEG43 = CV_FOURCC_MACRO('M','P','4','3'), + FOURCC_DIVX = CV_FOURCC_MACRO('D','I','V','X'), + FOURCC_X264 = CV_FOURCC_MACRO('X','2','6','4'), + }; + // + // frame data temporary storage + // + struct frame_store + { + private: + typedef std::vector data_vector; + data_vector m_Data; // Frame data + VmbUint32_t m_Width; // frame width + VmbUint32_t m_Height; // frame height + VmbPixelFormat_t m_PixelFormat; // frame pixel format + public: + // + // Method: frame_store() + // + // Purpose: default constructing frame store from data pointer and dimensions + // + frame_store(const VmbUchar_t *pBuffer, VmbUint32_t BufferByteSize, VmbUint32_t Width, VmbUint32_t Height, VmbPixelFormatType PixelFormat) + : m_Data ( pBuffer, pBuffer + BufferByteSize ) + , m_Width( Width ) + , m_Height( Height ) + , m_PixelFormat( PixelFormat ) + { + } + // + // Method: equal + // + // Purpose: compare frame store to frame dimensions + // + bool equal( VmbUint32_t Width, VmbUint32_t Height, VmbPixelFormat_t PixelFormat) const + { + return m_Width == Width + && m_Height == Height + && m_PixelFormat == PixelFormat; + } + // + // Method: setData + // + // Purpose: copy data into frame store from matching source + // + // Returns: false if data size not equal to internal buffer size + // + bool setData( const VmbUchar_t *Buffer, VmbUint32_t BufferSize) + { + if( BufferSize == dataSize() ) + { + std::copy( Buffer, Buffer+BufferSize, m_Data.begin() ); + return true; + } + return false; + } + // + // Methode: PixelFormat() + // + // Purpose: get pixel format of internal buffer. + // + VmbPixelFormat_t pixelFormat() const { return m_PixelFormat; } + // + // Methode: Width() + // + // Purpose: get image width. + // + VmbUint32_t width() const { return m_Width; } + // + // Methode: Height() + // + // Purpose: get image height + // + VmbUint32_t height() const { return m_Height; } + // + // Methode: dataSize() + // + // Purpose: get buffer size of internal data. + // + VmbUint32_t dataSize() const { return static_cast( m_Data.size() ); } + // + // Methode: data() + // + // Purpose: get constant internal data pointer. + // + const VmbUchar_t* data() const { return &*m_Data.begin();} + // + // Methode: data() + // + // Purpose: get internal data pointer. + // + VmbUchar_t* data() { return &*m_Data.begin();} + }; + typedef QSharedPointer FrameStorePtr; // shared pointer to frame store data + typedef QList FrameQueue; // queue of frames tore pointers + + cv::VideoWriter m_VideoWriter; // OpenCV VideoWriter + + cv::Mat m_ConvertImage; // storage for converted image, data should only be accessed inside run + // size and format are const while thread runs + + FrameQueue m_FrameQueue; // frame data queue for frames that are to be saved into video stream + bool m_StopThread; // flag to signal that the thread has to finish + QMutex m_ClassLock; // shared data lock + QWaitCondition m_FramesAvailable; // queue frame available condition + + // + // Method: run() + // + // Purpose: QThread run() implementation. + // + // Details: main thread processing function that will run while the object is alife. + // + // + void run() + { + while( ! m_StopThread ) + { + FrameStorePtr tmp; + { + // two class events unlock the queue + // first if a frame arrives enqueueFrame wakes the condition + // second if the thread is stopped we are woken up + // the while loop is necessary because a condition can be woken up by the system + QMutexLocker local_lock( &m_ClassLock ); + while(! m_StopThread && m_FrameQueue.empty() ) + { + m_FramesAvailable.wait( local_lock.mutex() ); + } + if( ! m_StopThread) + { + tmp = m_FrameQueue.front(); + m_FrameQueue.pop_front(); + } + }// scope for the lock, from now one we don't need the class lock + if( ! m_StopThread) + { + convertImage( *tmp ); + m_VideoWriter << m_ConvertImage; + } + } + } + // + // Method: convertImage() + // + // Purpose: converts frame_store data to internal openCV image for video encoding. + // + // Parameters: + // + // [in] frame internal frame_store struct from queue to convert into m_ConvertImage + // + // Note: access to m_Convert image will race the function is not thread safe and meant to be used as single writer to data. + // + bool convertImage(frame_store &frame) + { + VmbImage srcImage; + VmbImage dstImage; + srcImage.Size = sizeof( srcImage); + dstImage.Size = sizeof( dstImage); + VmbSetImageInfoFromPixelFormat( frame.pixelFormat(), frame.width(), frame.height(), & srcImage ); + VmbSetImageInfoFromPixelFormat( VmbPixelFormatBgr8, m_ConvertImage.cols, m_ConvertImage.rows, & dstImage); + srcImage.Data = frame.data(); + dstImage.Data = m_ConvertImage.data; + return VmbErrorSuccess == VmbImageTransform( &srcImage, &dstImage, NULL, 0 ); + + } +public: + OpenCVRecorder(const QString &fileName, VmbFloat_t fps, VmbUint32_t Width, VmbUint32_t Height) + : m_StopThread( false ) +#ifdef _MSC_VER // codec selection only supported by Windows + , m_VideoWriter(fileName.toStdString(), FOURCC_USER_SELECT, fps, cv::Size(Width,Height),true ) +#else + , m_VideoWriter(fileName.toStdString(), FOURCC_X264, fps, cv::Size(Width,Height),true ) +#endif + , m_ConvertImage( Height, Width, CV_8UC3) + { + if( ! m_VideoWriter.isOpened() ) + { + throw VideoRecorderException(__FUNCTION__, "could not open recorder"); + } + } + virtual ~OpenCVRecorder(){} + // + // Method: stopthread() + // + // Purpose: stops thread and ends video encoding. + // + // Details: will stop any data processing and signal that events are to be handled. + // + void stopThread() + { + QMutexLocker local_lock( &m_ClassLock); + m_StopThread = true; + m_FrameQueue.clear(); + m_FramesAvailable.wakeOne(); + } + // + // Method: enqueueFrame() + // + // Purpose: copies frame data into internal queue for processing. + // + // Parameters: + // + // [in] frame Vimba frame to add to queue, data will be copied from frame + // + // Returns: + // + // - true if frame was inserted + // - false if frame has not expected size or the insert did not succeed for other reasons + // + // Details: frame data will be added to frame queue, if the MAX_QUEUE_ELEMENTS are reached + // the oldest frame data is dropped and the new frame is enqueued. + // + // Note: after return frame is not referenced by the class. + // + bool enqueueFrame( const AVT::VmbAPI::Frame &frame) + { + VmbUint32_t Width; + VmbUint32_t Height; + VmbUint32_t BufferSize; + VmbPixelFormatType PixelFormat; + const VmbUchar_t* pBuffer(NULL); + + if( VmbErrorSuccess == frame.GetPixelFormat( PixelFormat) + && VmbErrorSuccess == frame.GetWidth( Width ) + && VmbErrorSuccess == frame.GetHeight( Height ) + && VmbErrorSuccess == frame.GetBufferSize( BufferSize ) + && VmbErrorSuccess == frame.GetBuffer( pBuffer ) ) + { + if( m_ConvertImage.cols == Width + && m_ConvertImage.rows == Height ) + { + QMutexLocker local_lock( &m_ClassLock); + FrameStorePtr pFrame; + // in case we reached the maximum number of queued frames + // take of the oldest and reuse it to store the newly arriving frame + if( m_FrameQueue.size() >= static_cast( maxQueueElements() ) ) + { + pFrame = m_FrameQueue.front(); + m_FrameQueue.pop_front(); + if ( ! pFrame->equal( Width, Height, PixelFormat ) ) + { + pFrame.clear(); + } + } + if( pFrame.isNull() ) + { + pFrame = FrameStorePtr( new frame_store( pBuffer, BufferSize, Width, Height, PixelFormat) ); + } + else + { + pFrame->setData( pBuffer, BufferSize ); + } + m_FrameQueue.push_back( pFrame ); + m_FramesAvailable.wakeOne(); + return true; + } + } + return false; + } +}; + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/main.cpp b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/main.cpp new file mode 100644 index 0000000..903b04c --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/main.cpp @@ -0,0 +1,38 @@ +/*============================================================================= + Copyright (C) 2015 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: main.cpp + + Description: The main entry point of the AsynchronousOpenCVRecorder + example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 "AsynchronousOpenCVRecorder.h" +#include + +int main( int argc, char *argv[] ) +{ + QApplication a( argc, argv ); + AsynchronousOpenCVRecorder w; + w.show(); + return a.exec(); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/res/AsynchronousOpenCVRecorder.png b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/res/AsynchronousOpenCVRecorder.png new file mode 100644 index 0000000..61642b4 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/res/AsynchronousOpenCVRecorder.png differ diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/res/AsynchronousOpenCVRecorder.qrc b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/res/AsynchronousOpenCVRecorder.qrc new file mode 100644 index 0000000..fdfacbc --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/res/AsynchronousOpenCVRecorder.qrc @@ -0,0 +1,5 @@ + + + AsynchronousOpenCVRecorder.png + + diff --git a/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/res/AsynchronousOpenCVRecorder.ui b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/res/AsynchronousOpenCVRecorder.ui new file mode 100644 index 0000000..20fc970 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/AsynchronousOpenCVRecorder/Qt/Source/res/AsynchronousOpenCVRecorder.ui @@ -0,0 +1,111 @@ + + + AsynchronousOpenCVRecorderClass + + + + 0 + 0 + 1040 + 780 + + + + + 0 + 0 + + + + + 1040 + 780 + + + + + 1040 + 780 + + + + AsynchronousOpenCVRecorder + + + + :/AsynchronousOpenCVRecorder/AsynchronousOpenCVRecorder.png:/AsynchronousOpenCVRecorder/AsynchronousOpenCVRecorder.png + + + + + + 0 + 10 + 261 + 491 + + + + + + + 0 + 580 + 1041 + 191 + + + + + + + 0 + 540 + 261 + 31 + + + + Start Image Recording ... + + + + + + 270 + 10 + 771 + 561 + + + + + 0 + 0 + + + + + + + + + + 140 + 510 + 121 + 20 + + + + ColorProcessing + + + + + + + + + + diff --git a/Vimba_6_0/VimbaCPP/Examples/BandwidthHelper/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/BandwidthHelper/Build/Make/Makefile new file mode 100644 index 0000000..bad5fb5 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/BandwidthHelper/Build/Make/Makefile @@ -0,0 +1,50 @@ +PROJECT_NAME = BandwidthHelper + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBACPP_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/BandwidthHelper.o \ + $(OBJ_DIR)/program.o + +DEPENDENCIES = VimbaCPP + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/BandwidthHelper/Source/BandwidthHelper.cpp b/Vimba_6_0/VimbaCPP/Examples/BandwidthHelper/Source/BandwidthHelper.cpp new file mode 100644 index 0000000..cc88372 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/BandwidthHelper/Source/BandwidthHelper.cpp @@ -0,0 +1,495 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: BandwidthHelper.cpp + + Description: The BandwidthHelper example demonstrates how to get and set the + bandwidth used by a camera using VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include + +#include "BandwidthHelper.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +#define PACKET_SIZE_MAX_1394_S100 1024 +#define PACKET_SIZE_MAX_1394_S200 2048 +#define PACKET_SIZE_MAX_1394_S400 4096 +#define PACKET_SIZE_MAX_1394_S800 8192 + +// +// Calculates the current bandwidth usage of a camera in relation to a free bus / network +// +// Parameters: +// [in] pCamera The camera to work on +// [out] rfBandwidth The current bandwidth usage (maximum 1) +// +// Returns: +// An API status code +// +VmbErrorType BandwidthHelper::GetBandwidthUsage( CameraPtr pCamera, double &rfBandwidth ) +{ + VmbErrorType res; + VmbInt64_t nValue; + FeaturePtr pFeature; + InterfacePtr pInterface; + VmbInterfaceType interfaceType; + std::string strInterfaceID; + VimbaSystem & system = VimbaSystem::GetInstance(); + + res = pCamera->GetInterfaceID( strInterfaceID ); + if( VmbErrorSuccess == res ) + { + res = system.GetInterfaceByID( strInterfaceID.c_str(), pInterface ); + if( VmbErrorSuccess == res ) + { + res = pInterface->GetType( interfaceType ); + if( VmbErrorSuccess == res ) + { + switch( interfaceType ) + { + case VmbInterfaceEthernet: + res = pCamera->GetFeatureByName( "StreamBytesPerSecond", pFeature ); + if ( VmbErrorSuccess == res ) + { + res = pFeature->GetValue( nValue ); + if ( VmbErrorSuccess == res ) + { + VmbInt64_t nMin, nMax; + res = pFeature->GetRange( nMin, nMax ); + if ( VmbErrorSuccess == res ) + { + rfBandwidth = (double)nValue / nMax; + } + } + } + break; + case VmbInterfaceFirewire: + res = pCamera->GetFeatureByName( "IIDCPacketSize", pFeature ); + if ( VmbErrorSuccess == res ) + { + res = pFeature->GetValue( nValue ); + if ( VmbErrorSuccess == res ) + { + res = pCamera->GetFeatureByName( "IIDCPhyspeed", pFeature ); + if ( VmbErrorSuccess == res ) + { + std::string strPhySpeed; + res = pFeature->GetValue( strPhySpeed ); + if ( VmbErrorSuccess == res ) + { + int nPhySpeed = atoi( strPhySpeed.substr( 1 ).c_str() ); + switch ( nPhySpeed ) + { + case 100 : nPhySpeed = PACKET_SIZE_MAX_1394_S100; + break; + case 200 : nPhySpeed = PACKET_SIZE_MAX_1394_S200; + break; + case 400 : nPhySpeed = PACKET_SIZE_MAX_1394_S400; + break; + case 800 : nPhySpeed = PACKET_SIZE_MAX_1394_S800; + break; + default: return VmbErrorInternalFault; + } + rfBandwidth = (double)nValue / (double)nPhySpeed; + } + } + } + } + break; + case VmbInterfaceUsb: + res = pCamera->GetFeatureByName( "DeviceLinkThroughputLimitMode", pFeature ); + if ( VmbErrorSuccess == res ) + { + std::string strMode; + res = pFeature->GetValue( strMode ); + if ( VmbErrorSuccess == res ) + { + // If link speed limit is disabled, the used bandwidth can be up to 100% + if ( !strcmp( "Off", strMode.c_str() )) + { + rfBandwidth = 1.0; + } + else + { + // If link speed limit is enabled, get its current value + res = pCamera->GetFeatureByName( "DeviceLinkThroughputLimit", pFeature ); + if ( VmbErrorSuccess == res ) + { + res = pFeature->GetValue( nValue ); + if ( VmbErrorSuccess == res ) + { + VmbInt64_t nMin, nMax; + res = pFeature->GetRange( nMin, nMax ); + if ( VmbErrorSuccess == res ) + { + rfBandwidth = (double)nValue / nMax; + } + } + } + } + } + } + break; + default: + res = VmbErrorWrongType; + break; + } + } + } + } + + return res; +} + +// +// Sets the current bandwidth usage in relation to a free bus / network +// +// Parameters: +// [in] pCamera The camera to work on +// [out] fBandwidth The bandwidth to be set (maximum 1) +// +// Returns: +// An API status code +// +VmbErrorType BandwidthHelper::SetBandwidthUsage( CameraPtr pCamera, double fBandwidth ) +{ + VmbErrorType res; + VmbInt64_t nValue; + FeaturePtr pFeature; + InterfacePtr pInterface; + VmbInterfaceType interfaceType; + std::string strInterfaceID; + VimbaSystem& system = VimbaSystem::GetInstance(); + + res = pCamera->GetInterfaceID( strInterfaceID ); + if( VmbErrorSuccess == res ) + { + res = system.GetInterfaceByID( strInterfaceID.c_str(), pInterface ); + if( VmbErrorSuccess == res ) + { + res = pInterface->GetType( interfaceType ); + if( VmbErrorSuccess == res ) + { + switch( interfaceType ) + { + case VmbInterfaceEthernet: + res = pCamera->GetFeatureByName( "StreamBytesPerSecond", pFeature ); + if ( VmbErrorSuccess == res ) + { + VmbInt64_t nMin, nMax; + res = pFeature->GetRange( nMin, nMax ); + if ( VmbErrorSuccess == res ) + { + nValue = (VmbUint64_t)(fBandwidth * nMax); + res = pFeature->SetValue( nValue ); + } + } + break; + case VmbInterfaceFirewire: + res = pCamera->GetFeatureByName( "IIDCPacketSizeAuto", pFeature ); + if ( VmbErrorSuccess == res ) + { + res = pFeature->SetValue( "Off" ); + if ( VmbErrorSuccess == res ) + { + res = pCamera->GetFeatureByName( "IIDCPhyspeed", pFeature ); + if ( VmbErrorSuccess == res ) + { + std::string strPhySpeed; + res = pFeature->GetValue( strPhySpeed ); + if ( VmbErrorSuccess == res ) + { + int nPhySpeed = atoi( strPhySpeed.substr( 1 ).c_str() ); + switch ( nPhySpeed ) + { + case 100 : nPhySpeed = PACKET_SIZE_MAX_1394_S100; + break; + case 200 : nPhySpeed = PACKET_SIZE_MAX_1394_S200; + break; + case 400 : nPhySpeed = PACKET_SIZE_MAX_1394_S400; + break; + case 800 : nPhySpeed = PACKET_SIZE_MAX_1394_S800; + break; + default: return VmbErrorInternalFault; + } + // Set size to new percentage + nValue = (VmbUint64_t)(fBandwidth * nPhySpeed); + res = pCamera->GetFeatureByName( "IIDCPacketSize", pFeature ); + if ( VmbErrorSuccess == res ) + { + // Adjust new value to fit increment + VmbInt64_t nInc; + res = pFeature->GetIncrement( nInc ); + if ( VmbErrorSuccess == res ) + { + nValue -= (nValue % nInc); + // Write new value + res = pFeature->SetValue( nValue ); + } + } + } + } + } + } + break; + case VmbInterfaceUsb: + res = pCamera->GetFeatureByName( "DeviceLinkThroughputLimitMode", pFeature ); + if ( VmbErrorSuccess == res ) + { + // Enable link speed limit + res = pFeature->SetValue( "On" ); + if ( VmbErrorSuccess == res ) + { + res = pCamera->GetFeatureByName( "DeviceLinkThroughputLimit", pFeature ); + if ( VmbErrorSuccess == res ) + { + VmbInt64_t nMin, nMax; + res = pFeature->GetRange( nMin, nMax ); + if ( VmbErrorSuccess == res ) + { + nValue = (VmbUint64_t)(fBandwidth * nMax); + // Set link speed limit + res = pFeature->SetValue( nValue ); + } + } + } + } + break; + default: + res = VmbErrorWrongType; + break; + } + } + } + } + + return res; +} + +// +// The relative minimum bandwidth usage as reported by the device +// +// Parameters: +// [in] pCamera The camera to work on +// [out rfBandwidth The ratio of minimum and maximum of either stream bytes per second or the packet size +// +// Returns: +// An API status code +// +VmbErrorType BandwidthHelper::GetMinPossibleBandwidthUsage( CameraPtr pCamera, double &rfBandwidth ) +{ + VmbErrorType res; + VmbInt64_t nMinValue; + VmbInt64_t nMaxValue; + FeaturePtr pFeature; + InterfacePtr pInterface; + VmbInterfaceType interfaceType; + std::string strInterfaceID; + VimbaSystem & system = VimbaSystem::GetInstance(); + + res = pCamera->GetInterfaceID( strInterfaceID ); + if( VmbErrorSuccess == res ) + { + res = system.GetInterfaceByID( strInterfaceID.c_str(), pInterface ); + if( VmbErrorSuccess == res ) + { + res = pInterface->GetType( interfaceType ); + if( VmbErrorSuccess == res ) + { + switch( interfaceType ) + { + case VmbInterfaceEthernet: + res = pCamera->GetFeatureByName( "StreamBytesPerSecond", pFeature ); + if ( VmbErrorSuccess == res ) + { + res = pFeature->GetRange( nMinValue, nMaxValue ); + if ( VmbErrorSuccess == res ) + { + rfBandwidth = (double)nMinValue / nMaxValue; + } + } + break; + + case VmbInterfaceFirewire: + res = pCamera->GetFeatureByName( "IIDCPacketSize", pFeature ); + if ( VmbErrorSuccess == res ) + { + res = pFeature->GetRange( nMinValue, nMaxValue ); + if ( VmbErrorSuccess == res ) + { + res = pCamera->GetFeatureByName( "IIDCPhyspeed", pFeature ); + if ( VmbErrorSuccess == res ) + { + std::string strPhySpeed; + res = pFeature->GetValue( strPhySpeed ); + if ( VmbErrorSuccess == res ) + { + int nPhySpeed = atoi( strPhySpeed.substr( 1 ).c_str() ); + switch ( nPhySpeed ) + { + case 100 : nPhySpeed = PACKET_SIZE_MAX_1394_S100; + break; + case 200 : nPhySpeed = PACKET_SIZE_MAX_1394_S200; + break; + case 400 : nPhySpeed = PACKET_SIZE_MAX_1394_S400; + break; + case 800 : nPhySpeed = PACKET_SIZE_MAX_1394_S800; + break; + default: return VmbErrorInternalFault; + } + rfBandwidth = (double)nMinValue / (double)nPhySpeed; + } + } + } + } + break; + case VmbInterfaceUsb: + res = pCamera->GetFeatureByName( "DeviceLinkThroughputLimit", pFeature ); + if ( VmbErrorSuccess == res ) + { + res = pFeature->GetRange( nMinValue, nMaxValue ); + if ( VmbErrorSuccess == res ) + { + rfBandwidth = (double)nMinValue / nMaxValue; + } + } + break; + default: + res = VmbErrorWrongType; + break; + } + } + } + } + + return res; +} + +// +// The relative maximum bandwidth usage as reported by the device +// +// Parameters: +// [in] pCamera The camera to work on +// [out rfBandwidth The ratio of maximum packet size as reported by the device and the maximum of the bus (for technologies other than fire wire always 1) +// +// Returns: +// An API status code +// +VmbErrorType BandwidthHelper::GetMaxPossibleBandwidthUsage( CameraPtr pCamera, double &rfBandwidth ) +{ + VmbErrorType res; + VmbInt64_t nMinValue; + VmbInt64_t nMaxValue; + FeaturePtr pFeature; + InterfacePtr pInterface; + VmbInterfaceType interfaceType; + std::string strInterfaceID; + VimbaSystem & system = VimbaSystem::GetInstance(); + + res = pCamera->GetInterfaceID( strInterfaceID ); + if( VmbErrorSuccess == res ) + { + res = system.GetInterfaceByID( strInterfaceID.c_str(), pInterface ); + if( VmbErrorSuccess == res ) + { + res = pInterface->GetType( interfaceType ); + if( VmbErrorSuccess == res ) + { + switch ( interfaceType ) + { + case VmbInterfaceEthernet: + rfBandwidth = 1.0; + break; + + case VmbInterfaceFirewire: + res = pCamera->GetFeatureByName( "IIDCPacketSize", pFeature ); + if ( VmbErrorSuccess == res ) + { + res = pFeature->GetRange( nMinValue, nMaxValue ); + if ( VmbErrorSuccess == res ) + { + res = pCamera->GetFeatureByName( "IIDCPhyspeed", pFeature ); + if ( VmbErrorSuccess == res ) + { + std::string strPhySpeed; + res = pFeature->GetValue( strPhySpeed ); + if ( VmbErrorSuccess == res ) + { + int nPhySpeed = atoi( strPhySpeed.substr( 1 ).c_str() ); + switch ( nPhySpeed ) + { + case 100 : nPhySpeed = PACKET_SIZE_MAX_1394_S100; + break; + case 200 : nPhySpeed = PACKET_SIZE_MAX_1394_S200; + break; + case 400 : nPhySpeed = PACKET_SIZE_MAX_1394_S400; + break; + case 800 : nPhySpeed = PACKET_SIZE_MAX_1394_S800; + break; + default: return VmbErrorInternalFault; + } + rfBandwidth = (double)nMaxValue / (double)nPhySpeed; + } + } + } + } + break; + case VmbInterfaceUsb: + rfBandwidth = 1.0; + break; + default: + res = VmbErrorWrongType; + break; + } + } + } + } + + return res; +} + +// +// Converts the interface type enum to a string representation +// +// Parameters: +// [in] interfaceType The interface enum to convert +// +// Returns: +// The string representation of the given enum +// +std::string BandwidthHelper::InterfaceToString( VmbInterfaceType interfaceType ) +{ + switch ( interfaceType ) + { + case VmbInterfaceFirewire: return "FireWire"; + case VmbInterfaceEthernet: return "GigE"; + case VmbInterfaceUsb: return "USB"; + default: return "Unknown"; + } +} + +}}} // AVT:VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/BandwidthHelper/Source/BandwidthHelper.h b/Vimba_6_0/VimbaCPP/Examples/BandwidthHelper/Source/BandwidthHelper.h new file mode 100644 index 0000000..bee33ac --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/BandwidthHelper/Source/BandwidthHelper.h @@ -0,0 +1,107 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: BandwidthHelper.h + + Description: The BandwidthHelper example demonstrates how to get and set the + bandwidth used by a camera using VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_HELPER_BANDWIDTHHELPER_H +#define AVT_VMBAPI_HELPER_BANDWIDTHHELPER_H + +#include "VimbaCPP/Include/VimbaCPP.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class BandwidthHelper +{ + public: + // + // Calculates the current bandwidth usage of a camera in relation to a free bus / network + // + // Parameters: + // [in] pCamera The camera to work on + // [out] rfBandwidth The current bandwidth usage (maximum 1) + // + // Returns: + // An API status code + // + static VmbErrorType GetBandwidthUsage( CameraPtr pCamera, double &bandwidth ); + + // + // Sets the current bandwidth usage in relation to a free bus / network + // + // Parameters: + // [in] pCamera The camera to work on + // [out] fBandwidth The bandwidth to be set (maximum 1) + // + // Returns: + // An API status code + // + static VmbErrorType SetBandwidthUsage( CameraPtr pCamera, double bandwidth ); + + // + // The relative minimum bandwidth usage as reported by the device + // + // Parameters: + // [in] pCamera The camera to work on + // [out rfBandwidth The ratio of minimum and maximum of either stream bytes per second or the packet size + // + // Returns: + // An API status code + // + static VmbErrorType GetMinPossibleBandwidthUsage( CameraPtr pCamera, double &bandwidth ); + + // + // The relative maximum bandwidth usage as reported by the device + // + // Parameters: + // [in] pCamera The camera to work on + // [out rfBandwidth The ratio of maximum packet size as reported by the device and the maximum of the bus (for technologies other than fire wire always 1) + // + // Returns: + // An API status code + // + static VmbErrorType GetMaxPossibleBandwidthUsage( CameraPtr pCamera, double &bandwidth ); + + // + // Converts the interface type enum to a string representation + // + // Parameters: + // [in] interfaceType The interface enum to convert + // + // Returns: + // The string representation of the given enum + // + static std::string InterfaceToString( VmbInterfaceType interfaceType ); + + private: + // No default ctor + BandwidthHelper(); +}; + +}}} // AVT:VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/BandwidthHelper/Source/program.cpp b/Vimba_6_0/VimbaCPP/Examples/BandwidthHelper/Source/program.cpp new file mode 100644 index 0000000..00e4cee --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/BandwidthHelper/Source/program.cpp @@ -0,0 +1,402 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: Main entry point of BandwidthHelper example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include +#include +#include +#include + +#include "BandwidthHelper.h" + +#include "Common/StreamSystemInfo.h" + +enum SettingsMode +{ + SettingsModeUnknown = 0, + SettingsModeGet = 1, + SettingsModeSet = 2, + SettingsModeGetMin = 3, + SettingsModeGetMax = 4 +}; + +bool StartsWith( const char *pString, const char *pStart ) +{ + if( NULL == pString ) + { + return false; + } + if( NULL == pStart ) + { + return false; + } + + if( std::strlen( pString ) < std::strlen( pStart ) ) + { + return false; + } + + if( std::memcmp( pString, pStart, std::strlen( pStart ) ) != 0 ) + { + return false; + } + + return true; +} + +int main( int argc, char* argv[] ) +{ + std::string cameraID, cameraName; + VmbInterfaceType cameraInterfaceType; + double fValue; + SettingsMode settingsMode = SettingsModeUnknown; + bool printHelp = false; + + std::cout << "\n"; + std::cout << "//////////////////////////////////////////\n"; + std::cout << "/// Vimba API Bandwidth Helper Example ///\n"; + std::cout << "//////////////////////////////////////////\n"; + std::cout << std::endl; + + VmbErrorType err = VmbErrorSuccess; + + ////////////////////// + //Parse command line// + ////////////////////// + + if( 4 < argc ) + { + err = VmbErrorBadParameter; + printHelp = true; + } + else + { + for( int i=1; i= std::strlen( pParameter ) ) + { + err = VmbErrorBadParameter; + break; + } + + if( pParameter[0] == '/' ) + { + // Get bandwidth usage + if( 0 == std::strcmp( pParameter, "/g" ) ) + { + if( SettingsModeUnknown != settingsMode ) + { + err = VmbErrorBadParameter; + break; + } + + settingsMode = SettingsModeGet; + } + // Set bandwidth usage + else if( true == StartsWith( pParameter, "/s:" ) ) + { + if( SettingsModeUnknown != settingsMode ) + { + err = VmbErrorBadParameter; + break; + } + + settingsMode = SettingsModeSet; + + std::string strVal = pParameter + 3; + if( 0 >= strVal.size() ) + { + err = VmbErrorBadParameter; + break; + } + fValue = atof( strVal.c_str() ) / 100; + } + else if( 0 == std::strcmp( pParameter, "/h" ) ) + { + if( true == printHelp ) + { + err = VmbErrorBadParameter; + break; + } + + printHelp = true; + } + // Get min bandwidth usage + else if( 0 == std::strcmp( pParameter, "/min" ) ) + { + if( SettingsModeUnknown != settingsMode ) + { + err = VmbErrorBadParameter; + break; + } + + settingsMode = SettingsModeGetMin; + } + // Get max bandwidth usage + else if( 0 == std::strcmp( pParameter, "/max" ) ) + { + if( SettingsModeUnknown != settingsMode ) + { + err = VmbErrorBadParameter; + break; + } + + settingsMode = SettingsModeGetMax; + } + else + { + err = VmbErrorBadParameter; + break; + } + } + else + { + if( false == cameraID.empty() ) + { + err = VmbErrorBadParameter; + break; + } + + cameraID = pParameter; + } + } + } + + // Write out an error if we could not parse the command line + if( VmbErrorBadParameter == err ) + { + std::cout << "Invalid parameter found.\n\n"; + printHelp = true; + } + + // Print out help + if( true == printHelp ) + { + std::cout << "Gets or sets the current bandwidth as percentage of the theoretically possible bandwidth.\n\n"; + std::cout << "Usage: BandwidthHelper [CameraID] [/h] [/{g|s:val|min|max}]\n"; + std::cout << "Parameters: CameraID ID of the camera to use (using first camera if not specified)\n"; + std::cout << " /h Print out help\n"; + std::cout << " /g Get bandwidth usage (default if not specified)\n"; + std::cout << " /s:val Set bandwidth usage to % of the maximum bandwidth\n"; + std::cout << " /min Get minimal possible bandwidth usage\n"; + std::cout << " /max Get maximal possible bandwidth usage\n\n"; + + return err; + } + + if( VmbErrorSuccess == err ) + { + // Get a reference to the VimbaSystem singleton + AVT::VmbAPI::VimbaSystem &rVimbaSystem = AVT::VmbAPI::VimbaSystem::GetInstance(); + + // Print out version of Vimba + std::cout << "Vimba C++ API Version " << rVimbaSystem << "\n"; + + // Startup API + err = rVimbaSystem.Startup(); + if( VmbErrorSuccess != err ) + { + std::cout << "Could not start system. Error code: " << err <<"\n"; + } + else + { + AVT::VmbAPI::CameraPtr pCamera; + // Open first available camera + if( cameraID.empty() ) + { + // Fetch all cameras known to Vimba + AVT::VmbAPI::CameraPtrVector cameras; + err = rVimbaSystem.GetCameras( cameras ); + if( VmbErrorSuccess == err ) + { + if( !cameras.empty() ) + { + for( AVT::VmbAPI::CameraPtrVector::const_iterator iter = cameras.begin(); + cameras.end() != iter; + ++iter ) + { + // Check if we can open the camera in full mode + VmbAccessModeType accessMode = VmbAccessModeNone; + err = (*iter)->GetPermittedAccess( accessMode ); + if( VmbErrorSuccess == err ) + { + if( VmbAccessModeFull & accessMode ) + { + // Now get the camera ID + err = ( *iter )->GetID( cameraID ); + if( VmbErrorSuccess == err ) + { + // Try to open the camera + err = ( *iter )->Open( VmbAccessModeFull ); + if( VmbErrorSuccess == err ) + { + pCamera = *iter; + // Get camera name and interface type + if( VmbErrorSuccess == pCamera->GetName( cameraName ) + && VmbErrorSuccess == pCamera->GetInterfaceType( cameraInterfaceType ) ) + { + std::cout << "Successfully opened " << AVT::VmbAPI::Examples::BandwidthHelper::InterfaceToString( cameraInterfaceType ) << " camera " << cameraName << " (" << cameraID << ")\n" ; + } + else + { + std::cout << "Successfully opened camera " << "(" << cameraID << ")\n"; + } + break; + } + } + } + } + } + + if( NULL == pCamera ) + { + std::cout << "Could not open any camera.\n"; + err = VmbErrorNotFound; + } + } + else + { + std::cout << "No camera available.\n"; + err = VmbErrorNotFound; + } + } + else + { + std::cout << "Could not list cameras. Error code: " << err << std::endl; + } + } + else + { + // Open specific camera + err = rVimbaSystem.OpenCameraByID( cameraID.c_str(), VmbAccessModeFull, pCamera ); + if( VmbErrorSuccess != err ) + { + std::cout << "Could not open camera. Error code: " << err <<"\n"; + } + } + + if( VmbErrorSuccess == err ) + { + switch( settingsMode ) + { + default: + case SettingsModeGet: + { + // Get bandwidth + err = AVT::VmbAPI::Examples::BandwidthHelper::GetBandwidthUsage( pCamera, fValue ); + if ( VmbErrorWrongType == err ) + { + std::cout << "The bandwidth cannot be controlled for this interface type.\n"; + } + else if ( VmbErrorSuccess != err ) + { + std::cout << "Could not get bandwidth usage. Error code: " << err <<"\n"; + } + else + { + std::cout << "Bandwidth usage: " << fValue * 100 << "%\n"; + } + } + break; + + case SettingsModeSet: + { + // Set bandwidth + err = AVT::VmbAPI::Examples::BandwidthHelper::SetBandwidthUsage( pCamera, fValue ); + if ( VmbErrorWrongType == err ) + { + std::cout << "The bandwidth cannot be controlled for this interface type.\n"; + } + else + { + if ( VmbErrorSuccess == err ) + { + // Read back written value + err = AVT::VmbAPI::Examples::BandwidthHelper::GetBandwidthUsage( pCamera, fValue ); + if ( VmbErrorSuccess == err ) + { + std::cout << "Bandwidth usage successfully set to: " << fValue * 100 << "%\n"; + } + } + if ( VmbErrorSuccess != err ) + { + std::cout << "Could not set bandwidth usage. Error code: " << err <<"\n"; + } + } + } + break; + + case SettingsModeGetMin: + { + // Get bandwidth + err = AVT::VmbAPI::Examples::BandwidthHelper::GetMinPossibleBandwidthUsage( pCamera, fValue ); + if ( VmbErrorWrongType == err ) + { + std::cout << "The bandwidth cannot be controlled for this interface type.\n"; + } + else if( VmbErrorSuccess != err ) + { + std::cout << "Could not get minimal possible bandwidth usage. Error code: " << err <<"\n"; + } + else + { + std::cout << "Minimal possible bandwidth usage: " << fValue * 100 << "%\n"; + } + } + break; + + case SettingsModeGetMax: + { + // Get bandwidth + err = AVT::VmbAPI::Examples::BandwidthHelper::GetMaxPossibleBandwidthUsage( pCamera, fValue ); + if ( VmbErrorWrongType == err ) + { + std::cout << "The bandwidth cannot be controlled for this interface type.\n"; + } + else if ( VmbErrorSuccess != err ) + { + std::cout << "Could not get maximal possible bandwidth usage. Error code: " << err <<"\n"; + } + else + { + std::cout << "Maximal possible bandwidth usage: " << fValue * 100 << "%\n"; + } + } + break; + } + // Close camera + err = pCamera->Close(); + } + // Shutdown API + rVimbaSystem.Shutdown(); + } + + return err; + } +} diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/ActionCommands b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/ActionCommands new file mode 100755 index 0000000..3123b04 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/ActionCommands differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/AsynchronousGrabConsole b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/AsynchronousGrabConsole new file mode 100755 index 0000000..c84ef4f Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/AsynchronousGrabConsole differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/AsynchronousGrabQt b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/AsynchronousGrabQt new file mode 100755 index 0000000..0c93c18 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/AsynchronousGrabQt differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/AsynchronousOpenCVRecorder b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/AsynchronousOpenCVRecorder new file mode 100755 index 0000000..924246f Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/AsynchronousOpenCVRecorder differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/BandwidthHelper b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/BandwidthHelper new file mode 100755 index 0000000..f7e4a55 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/BandwidthHelper differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/CameraFactory b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/CameraFactory new file mode 100755 index 0000000..ccb83a1 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/CameraFactory differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/EventHandling b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/EventHandling new file mode 100755 index 0000000..844f36e Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/EventHandling differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/ListAncillaryDataFeatures b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/ListAncillaryDataFeatures new file mode 100755 index 0000000..9e2f9ac Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/ListAncillaryDataFeatures differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/ListCameras b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/ListCameras new file mode 100755 index 0000000..0d4e9fe Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/ListCameras differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/ListFeatures b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/ListFeatures new file mode 100755 index 0000000..fd25ece Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/ListFeatures differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/LoadSaveSettings b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/LoadSaveSettings new file mode 100755 index 0000000..628cec5 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/LoadSaveSettings differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/LookUpTable b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/LookUpTable new file mode 100755 index 0000000..9878ecf Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/LookUpTable differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/SynchronousGrabConsole b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/SynchronousGrabConsole new file mode 100755 index 0000000..ec541b3 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/SynchronousGrabConsole differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/SynchronousGrabQt b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/SynchronousGrabQt new file mode 100755 index 0000000..f1240ce Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/SynchronousGrabQt differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/UserSet b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/UserSet new file mode 100755 index 0000000..aedf323 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/UserSet differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/VimbaViewer b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/VimbaViewer new file mode 100755 index 0000000..b47f854 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/Bin/arm_64bit/VimbaViewer differ diff --git a/Vimba_6_0/VimbaCPP/Examples/Build/Make/Common.mk b/Vimba_6_0/VimbaCPP/Examples/Build/Make/Common.mk new file mode 100644 index 0000000..a727c58 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/Build/Make/Common.mk @@ -0,0 +1,100 @@ +UNAME = $(shell uname -m) + +ifeq ($(UNAME),i386) +ARCH = x86 +AUTOWORDSIZE = 32 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),i486) +ARCH = x86 +AUTOWORDSIZE = 32 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),i586) +ARCH = x86 +AUTOWORDSIZE = 32 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),i686) +ARCH = x86 +AUTOWORDSIZE = 32 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),x86_64) +ARCH = x86 +AUTOWORDSIZE = 64 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),amd64) +ARCH = x86 +AUTOWORDSIZE = 64 +AUTOFLOATABI = ignore +endif +ifeq ($(UNAME),armv6l) +ARCH = arm +AUTOWORDSIZE = 32 +AUTOFLOATABI = soft +endif +ifeq ($(UNAME),armv7l) +ARCH = arm +AUTOWORDSIZE = 32 +AUTOFLOATABI = soft +endif +ifeq ($(UNAME),aarch64) +ARCH = arm +AUTOWORDSIZE = 64 +AUTOFLOATABI = hard +endif + +#Possible word sizes: 32, 64 +WORDSIZE = $(AUTOWORDSIZE) +#Possible float abis: soft, hard +FLOATABI = $(AUTOFLOATABI) + +ifneq ($(WORDSIZE),32) +ifneq ($(WORDSIZE),64) +$(error Invalid word size set) +endif +endif + +ifneq ($(FLOATABI),soft) +ifneq ($(FLOATABI),hard) +ifneq ($(FLOATABI),ignore) +$(error Invalid float abi set) +endif +endif +endif + +#Common tools +PKGCFG = pkg-config +MKDIR = mkdir +RM = rm +CXX = g++ +MAKE = make +CP = cp + +#Set word size on x86 +ifeq ($(ARCH),x86) +ARCH_CFLAGS = -m$(WORDSIZE) +endif + +#Configure compiler and linker for soft or hard-float build on ARM +ifeq ($(ARCH),arm) +ifeq ($(FLOATABI),soft) +ARCH_CFLAGS = -marm -mfloat-abi=soft -march=armv4t +else ifeq ($(FLOATABI),hard) +ifeq ($(WORDSIZE),32) +ARCH_CFLAGS = -mthumb -mfloat-abi=hard -march=armv7 +else ifeq ($(WORDSIZE),64) +ARCH_CFLAGS = -march=armv8-a +endif +endif +endif + +ifeq ($(CONFIG),Debug) + CONFIG_CFLAGS = -O0 -g +else + CONFIG_CFLAGS = -O3 +endif + +COMMON_CFLAGS = $(CONFIG_CFLAGS) $(ARCH_CFLAGS) -fPIC diff --git a/Vimba_6_0/VimbaCPP/Examples/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/Build/Make/Makefile new file mode 100644 index 0000000..5c6f180 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/Build/Make/Makefile @@ -0,0 +1,56 @@ +EXAMPLES_DIR = ../.. +MAKE_INCLUDE_DIR = $(CURDIR) + +include $(MAKE_INCLUDE_DIR)/Common.mk + +QT_SUPPORT = true + +ifeq ($(QT_SUPPORT),true) +QT_EXAMPLES = VimbaViewer + +QT_SUB_EXAMPLES = AsynchronousGrab \ + AsynchronousOpenCVRecorder \ + SynchronousGrab +endif + +CONSOLE_EXAMPLES = ActionCommands \ + BandwidthHelper \ + CameraFactory \ + EventHandling \ + ListCameras \ + ListFeatures \ + ListAncillaryDataFeatures \ + LoadSaveSettings \ + LookUpTable \ + UserSet + +CONSOLE_SUB_EXAMPLES = AsynchronousGrab \ + SynchronousGrab + +make_%: $(EXAMPLES_DIR)/%/Build/Make/Makefile + $(MAKE) -C $(EXAMPLES_DIR)/$*/Build/Make + +clean_%: $(EXAMPLES_DIR)/%/Build/Make/Makefile + $(MAKE) -C $(EXAMPLES_DIR)/$*/Build/Make clean + +make_%Console: $(EXAMPLES_DIR)/%/Console/Build/Make/Makefile + $(MAKE) -C $(EXAMPLES_DIR)/$*/Console/Build/Make + +clean_%Console: $(EXAMPLES_DIR)/%/Console/Build/Make/Makefile + $(MAKE) -C $(EXAMPLES_DIR)/$*/Console/Build/Make clean + +make_%Qt: $(EXAMPLES_DIR)/%/Qt/Build/Make/Makefile + $(MAKE) -C $(EXAMPLES_DIR)/$*/Qt/Build/Make + +clean_%Qt: $(EXAMPLES_DIR)/%/Qt/Build/Make/Makefile + $(MAKE) -C $(EXAMPLES_DIR)/$*/Qt/Build/Make clean + +all: $(foreach example,$(CONSOLE_EXAMPLES),make_$(example)) \ + $(foreach example,$(CONSOLE_SUB_EXAMPLES),make_$(example)Console) \ + $(foreach example,$(QT_EXAMPLES),make_$(example)) \ + $(foreach example,$(QT_SUB_EXAMPLES),make_$(example)Qt) + +clean: $(foreach example,$(CONSOLE_EXAMPLES),clean_$(example)) \ + $(foreach example,$(CONSOLE_SUB_EXAMPLES),clean_$(example)Console) \ + $(foreach example,$(QT_EXAMPLES),clean_$(example)) \ + $(foreach example,$(QT_SUB_EXAMPLES),clean_$(example)Qt) diff --git a/Vimba_6_0/VimbaCPP/Examples/Build/Make/Qt.mk b/Vimba_6_0/VimbaCPP/Examples/Build/Make/Qt.mk new file mode 100644 index 0000000..297e144 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/Build/Make/Qt.mk @@ -0,0 +1,36 @@ +include $(MAKE_INCLUDE_DIR)/Common.mk + +PKGCFG_MOC = $(shell $(PKGCFG) --variable=moc_location QtCore) +PKGCFG_UIC = $(shell $(PKGCFG) --variable=uic_location QtCore) + +#Qt tools +MOC = $(if $(PKGCFG_MOC),$(PKGCFG_MOC),moc) +UIC = $(if $(PKGCFG_UIC),$(PKGCFG_UIC),uic) +RCC = rcc + +#Compile options needed for QtCore +QTCORE_CFLAGS = $(shell $(PKGCFG) --cflags QtCore) + +#Linker options needed for QtCore +QTCORE_LIBS = $(shell $(PKGCFG) --libs QtCore) + +#Compile options needed for QtGui +QTGUI_CFLAGS = $(shell $(PKGCFG) --cflags QtGui) + +#Linker options needed for QtGui +QTGUI_LIBS = $(shell $(PKGCFG) --libs QtGui) + +#Compile options needed for QtSvg +QTSVG_CFLAGS = $(shell $(PKGCFG) --cflags QtSvg) + +#Linker options needed for QtSvg +QTSVG_LIBS = $(shell $(PKGCFG) --libs QtSvg) + +#Operations we have to do in order to prepare QtCore +QtCore: + +#Operations we have to do in order to prepare QtGui +QtGui: + +#Operations we have to do in order to prepare QtSvg +QtSvg: \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/Build/Make/VimbaC.mk b/Vimba_6_0/VimbaCPP/Examples/Build/Make/VimbaC.mk new file mode 100644 index 0000000..d8bdb00 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/Build/Make/VimbaC.mk @@ -0,0 +1,14 @@ +include $(MAKE_INCLUDE_DIR)/Common.mk + +#Compile options needed for VimbaC +VIMBAC_CFLAGS = -I$(VIMBASDK_DIR) + +#Linker options needed for VimbaC +VIMBAC_LIBS = -L$(BIN_DIR) -lVimbaC + +#By default we copy libVimbaC.so next to the binary +$(BIN_DIR)/libVimbaC.so: $(BIN_DIR) + $(CP) $(VIMBASDK_DIR)/VimbaC/DynamicLib/$(ARCH)_$(WORDSIZE)bit/libVimbaC.so $(BIN_DIR)/ + +#Operations we have to do in order to prepare VimbaC +VimbaC: $(BIN_DIR)/libVimbaC.so diff --git a/Vimba_6_0/VimbaCPP/Examples/Build/Make/VimbaCPP.mk b/Vimba_6_0/VimbaCPP/Examples/Build/Make/VimbaCPP.mk new file mode 100644 index 0000000..c4b4baf --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/Build/Make/VimbaCPP.mk @@ -0,0 +1,15 @@ +include $(MAKE_INCLUDE_DIR)/Common.mk +include $(MAKE_INCLUDE_DIR)/VimbaC.mk + +#Compile options needed for VimbaCPP +VIMBACPP_CFLAGS = -I$(VIMBASDK_DIR) $(VIMBAC_CFLAGS) + +#Linker options needed for VimbaCPP +VIMBACPP_LIBS = -L$(BIN_DIR) -lVimbaCPP $(VIMBAC_LIBS) -Wl,-rpath-link,$(BIN_DIR) + +#By default we copy libVimbaCPP.so next to the binary +$(BIN_DIR)/libVimbaCPP.so: $(BIN_DIR) VimbaC + $(CP) $(VIMBASDK_DIR)/VimbaCPP/DynamicLib/$(ARCH)_$(WORDSIZE)bit/libVimbaCPP.so $(BIN_DIR)/ + +#Operations we have to do in order to prepare VimbaCPP +VimbaCPP: $(BIN_DIR)/libVimbaCPP.so diff --git a/Vimba_6_0/VimbaCPP/Examples/Build/Make/VimbaImageTransform.mk b/Vimba_6_0/VimbaCPP/Examples/Build/Make/VimbaImageTransform.mk new file mode 100644 index 0000000..83cf6c9 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/Build/Make/VimbaImageTransform.mk @@ -0,0 +1,14 @@ +include $(MAKE_INCLUDE_DIR)/Common.mk + +#Compile options needed for VimbaImageTransform +VIMBAIMAGETRANSFORM_CFLAGS = -I$(VIMBASDK_DIR)/VimbaImageTransform/Include + +#Compile options needed for VimbaImageTransform +VIMBAIMAGETRANSFORM_LIBS = -L$(BIN_DIR) -lVimbaImageTransform -Wl,-rpath-link,$(BIN_DIR) + +#By default we copy libVimbaImageTransform.so next to the binary +$(BIN_DIR)/libVimbaImageTransform.so: $(BIN_DIR) + $(CP) $(VIMBASDK_DIR)/VimbaImageTransform/DynamicLib/$(ARCH)_$(WORDSIZE)bit/libVimbaImageTransform.so $(BIN_DIR)/ + +#Operations we have to do in order to prepare VimbaImageTransform +VimbaImageTransform: $(BIN_DIR)/libVimbaImageTransform.so diff --git a/Vimba_6_0/VimbaCPP/Examples/Build/Make/tinyxml.mk b/Vimba_6_0/VimbaCPP/Examples/Build/Make/tinyxml.mk new file mode 100644 index 0000000..16642c7 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/Build/Make/tinyxml.mk @@ -0,0 +1,12 @@ +include $(MAKE_INCLUDE_DIR)/Common.mk + +PKGCFG_TINYXML_LIBS = $(shell $(PKGCFG) --libs tinyxml) + +#Compile options needed for tinyxml +TINYXML_CFLAGS = $(shell $(PKGCFG) --cflags tinyxml) + +#Linker options needed for tinyxml +TINYXML_LIBS = $(if $(PKGCFG_TINYXML_LIBS),$(PKGCFG_TINYXML_LIBS),-ltinyxml) + +#Operations we have to do in order to prepare tinyxml +tinyxml: \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/CameraFactory/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/CameraFactory/Build/Make/Makefile new file mode 100644 index 0000000..895d769 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/CameraFactory/Build/Make/Makefile @@ -0,0 +1,51 @@ +PROJECT_NAME = CameraFactory + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBACPP_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/CameraFactory.o \ + $(OBJ_DIR)/program.o \ + $(OBJ_DIR)/FindCameras.o + +DEPENDENCIES = VimbaCPP + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/CameraFactory/Source/CameraFactory.cpp b/Vimba_6_0/VimbaCPP/Examples/CameraFactory/Source/CameraFactory.cpp new file mode 100644 index 0000000..bd3c4fc --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/CameraFactory/Source/CameraFactory.cpp @@ -0,0 +1,208 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: CameraFactory.cpp + + Description: The CameraFactory example will create a suitable object for + each known interface. The user can create his own factory and + camera classes for customization. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 "CameraFactory.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +/*============================================================================= + FirewireCamera class +=============================================================================*/ + + FirewireCamera::FirewireCamera( const char *pCameraID, + const char *pCameraName, + const char *pCameraModel, + const char *pCameraSerialNumber, + const char *pInterfaceID, + VmbInterfaceType interfaceType, + const char *pInterfaceName, + const char *pInterfaceSerialNumber, + VmbAccessModeType interfacePermittedAccess ) + : Camera( pCameraID, pCameraName, pCameraModel, + pCameraSerialNumber, pInterfaceID, interfaceType) + { + } + + // A custom camera function + void FirewireCamera::addonFireWire( std::string &info ) + { + info = "1394 interface connection detected"; + } + +/*============================================================================= + GigECamera class +=============================================================================*/ + + GigECamera::GigECamera( const char *pCameraID, + const char *pCameraName, + const char *pCameraModel, + const char *pCameraSerialNumber, + const char *pInterfaceID, + VmbInterfaceType interfaceType, + const char *pInterfaceName, + const char *pInterfaceSerialNumber, + VmbAccessModeType interfacePermittedAccess ) + : Camera( pCameraID, pCameraName, pCameraModel, + pCameraSerialNumber, pInterfaceID, interfaceType) + { + } + + // A custom camera function + void GigECamera::addonGigE( std::string &info ) + { + info = "Ethernet interface connection detected"; + } + +/*============================================================================= + USBCamera class +=============================================================================*/ + + USBCamera::USBCamera( const char *pCameraID, + const char *pCameraName, + const char *pCameraModel, + const char *pCameraSerialNumber, + const char *pInterfaceID, + VmbInterfaceType interfaceType, + const char *pInterfaceName, + const char *pInterfaceSerialNumber, + VmbAccessModeType interfacePermittedAccess ) + : Camera( pCameraID, pCameraName, pCameraModel, + pCameraSerialNumber, pInterfaceID, interfaceType) + { + } + + // A custom camera function + void USBCamera::addonUSB( std::string &info ) + { + info = "USB interface connection detected"; + } + +/*============================================================================= + CLCamera class +=============================================================================*/ + + CLCamera::CLCamera( const char *pCameraID, + const char *pCameraName, + const char *pCameraModel, + const char *pCameraSerialNumber, + const char *pInterfaceID, + VmbInterfaceType interfaceType, + const char *pInterfaceName, + const char *pInterfaceSerialNumber, + VmbAccessModeType interfacePermittedAccess ) + : Camera( pCameraID, pCameraName, pCameraModel, + pCameraSerialNumber, pInterfaceID, interfaceType) + { + } + + // A custom camera function + void CLCamera::addonCL( std::string &info ) + { + info = "CL interface connection detected"; + } + +/*============================================================================= + UserCameraFactory class +=============================================================================*/ + + CameraPtr UserCameraFactory::CreateCamera( const char *pCameraID, + const char *pCameraName, + const char *pCameraModel, + const char *pCameraSerialNumber, + const char *pInterfaceID, + VmbInterfaceType interfaceType, + const char *pInterfaceName, + const char *pInterfaceSerialNumber, + VmbAccessModeType interfacePermittedAccess) + { + // create camera class, depending on camera interface type + if ( VmbInterfaceFirewire == interfaceType ) + { + return FirewireCamera_t( new FirewireCamera( pCameraID, + pCameraName, + pCameraModel, + pCameraSerialNumber, + pInterfaceID, + interfaceType, + pInterfaceName, + pInterfaceSerialNumber, + interfacePermittedAccess)); + } + else if ( VmbInterfaceEthernet == interfaceType ) + { + return GigECamera_t( new GigECamera( pCameraID, + pCameraName, + pCameraModel, + pCameraSerialNumber, + pInterfaceID, + interfaceType, + pInterfaceName, + pInterfaceSerialNumber, + interfacePermittedAccess)); + } + else if ( VmbInterfaceUsb == interfaceType ) + { + return USBCamera_t( new USBCamera( pCameraID, + pCameraName, + pCameraModel, + pCameraSerialNumber, + pInterfaceID, + interfaceType, + pInterfaceName, + pInterfaceSerialNumber, + interfacePermittedAccess)); + } + else if ( VmbInterfaceCL == interfaceType ) + { + return CLCamera_t( new CLCamera( pCameraID, + pCameraName, + pCameraModel, + pCameraSerialNumber, + pInterfaceID, + interfaceType, + pInterfaceName, + pInterfaceSerialNumber, + interfacePermittedAccess)); + } + else // unknown camera interface + { + // use default camera class + return Camera_t( new Camera( pCameraID, + pCameraName, + pCameraModel, + pCameraSerialNumber, + pInterfaceID, + interfaceType)); + } + } + +}}} // namespace AVT::VmbAPI::Examples + diff --git a/Vimba_6_0/VimbaCPP/Examples/CameraFactory/Source/CameraFactory.h b/Vimba_6_0/VimbaCPP/Examples/CameraFactory/Source/CameraFactory.h new file mode 100644 index 0000000..bc049d9 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/CameraFactory/Source/CameraFactory.h @@ -0,0 +1,152 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: CameraFactory.h + + Description: The CameraFactory example will create a suitable object for + each known interface. The user can create his own factory and + camera classes for customization. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_CAMERAFACTORY +#define AVT_VMBAPI_EXAMPLES_CAMERAFACTORY + +#include "VimbaCPP/Include/VimbaCPP.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class UserCameraFactory; +class FirewireCamera; +class GigECamera; +class USBCamera; +class CLCamera; + +typedef SP_DECL( UserCameraFactory ) UserCameraFactory_t; +typedef SP_DECL( FirewireCamera ) FirewireCamera_t; +typedef SP_DECL( GigECamera ) GigECamera_t; +typedef SP_DECL( USBCamera ) USBCamera_t; +typedef SP_DECL( CLCamera ) CLCamera_t; +typedef SP_DECL( Camera ) Camera_t; + +// +// A class that derives from standard Vimba Camera with a function specific to fire wire +// +class FirewireCamera: + public Camera +{ +public: + FirewireCamera( const char *pCameraID, + const char *pCameraName, + const char *pCameraModel, + const char *pCameraSerialNumber, + const char *pInterfaceID, + VmbInterfaceType interfaceType, + const char *pInterfaceName, + const char *pInterfaceSerialNumber, + VmbAccessModeType interfacePermittedAccess ); + + void addonFireWire( std::string &info ); // custom camera function +}; + +// +// A class that derives from standard Vimba Camera with a function specific to GigE +// +class GigECamera: + public Camera +{ +public: + GigECamera( const char *pCameraID, + const char *pCameraName, + const char *pCameraModel, + const char *pCameraSerialNumber, + const char *pInterfaceID, + VmbInterfaceType interfaceType, + const char *pInterfaceName, + const char *pInterfaceSerialNumber, + VmbAccessModeType interfacePermittedAccess ); + + void addonGigE( std::string &info ); // custom camera function +}; + +// +// A class that derives from standard Vimba Camera with a function specific to USB +// +class USBCamera: + public Camera +{ +public: + USBCamera( const char *pCameraID, + const char *pCameraName, + const char *pCameraModel, + const char *pCameraSerialNumber, + const char *pInterfaceID, + VmbInterfaceType interfaceType, + const char *pInterfaceName, + const char *pInterfaceSerialNumber, + VmbAccessModeType interfacePermittedAccess ); + + void addonUSB( std::string &info ); // custom camera function +}; + +// +// A class that derives from standard Vimba Camera with a functions specific to CL +// +class CLCamera: + public Camera +{ +public: + CLCamera( const char *pCameraID, + const char *pCameraName, + const char *pCameraModel, + const char *pCameraSerialNumber, + const char *pInterfaceID, + VmbInterfaceType interfaceType, + const char *pInterfaceName, + const char *pInterfaceSerialNumber, + VmbAccessModeType interfacePermittedAccess ); + + void addonCL( std::string &info ); // custom camera function +}; + +// +// A class with a static factory method creating specific camera classes dependent on the interface type +// +class UserCameraFactory : + public ICameraFactory +{ + public: + CameraPtr CreateCamera( const char *pCameraID, + const char *pCameraName, + const char *pCameraModel, + const char *pCameraSerialNumber, + const char *pInterfaceID, + VmbInterfaceType interfaceType, + const char *pInterfaceName, + const char *pInterfaceSerialNumber, + VmbAccessModeType interfacePermittedAccess); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/CameraFactory/Source/FindCameras.cpp b/Vimba_6_0/VimbaCPP/Examples/CameraFactory/Source/FindCameras.cpp new file mode 100644 index 0000000..c23d16e --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/CameraFactory/Source/FindCameras.cpp @@ -0,0 +1,162 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: FindCameras.cpp + + Description: Find and print a custom string for each known customized camera. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#include "FindCameras.h" +#include "CameraFactory.h" + +#include "VimbaCPP/Include/VimbaCPP.h" +#include "Common/StreamSystemInfo.h" +#include "Common/ErrorCodeToMessage.h" +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// +// Detects all connected physical cameras and creates polymorphic classes (all inheriting from Vimba Camera class) +// depending on the camera's interface type. +// Starts up the API +// Creates the objects and prints them out +// Shuts down the API and exits +// +void FindCameras::Print() +{ + VimbaSystem& sys = VimbaSystem::GetInstance(); // Get a reference to the VimbaSystem singleton + VmbErrorType err = sys.Startup(); // Initialize the Vimba API + CameraPtrVector cameras; // A vector of std::shared_ptr objects + + std::string strName; // The name of the cam + VmbInterfaceType interfaceType; // The interface type of the cam + std::string strInfo; // The custom information + + std::stringstream strError; + + + + if( VmbErrorSuccess == err ) + { + std::cout<<"Vimba C++ API Version "<GetName( strName ); + if( VmbErrorSuccess != err ) + { + strError << "[Could not get camera name. Error code: " << err <<"("<GetInterfaceType( interfaceType ); + if( VmbErrorSuccess != err ) + { + strError << "[Could not get camera interface. Error code: " << err << "("<addonFireWire( strInfo ); + break; + } + case VmbInterfaceEthernet: + { + GigECamera_t gcam = SP_DYN_CAST( *iter, GigECamera ); + if ( gcam != NULL ) + gcam->addonGigE( strInfo ); + break; + } + case VmbInterfaceUsb: + { + USBCamera_t ucam = SP_DYN_CAST( *iter, USBCamera ); + if ( ucam != NULL ) + ucam->addonUSB( strInfo ); + break; + } + case VmbInterfaceCL: + { + CLCamera_t ccam = SP_DYN_CAST( *iter, CLCamera ); + if ( ccam != NULL ) + ccam->addonCL( strInfo ); + break; + } + default: + { + break; + } + } + } + + std::cout <<"/// Camera Name: " << strName + <<"\n/// Custom Info: " << strInfo + <<"\n\n"; + } + } + else + { + std::cout << "Could not list cameras. Error code: " << err <<"("< + +#include "FindCameras.h" + +int main( int argc, char* argv[] ) +{ + std::cout << "\n"; + std::cout << "///////////////////////////////////////\n"; + std::cout << "/// Vimba API CameraFactory Example ///\n"; + std::cout << "///////////////////////////////////////\n\n"; + + if( 1 < argc ) + { + std::cout << "No parameters expected. Execution will not be affected by the provided parameter(s).\n\n"; + } + + AVT::VmbAPI::Examples::FindCameras::Print(); + + std::cout << "\n"; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/Common/ErrorCodeToMessage.h b/Vimba_6_0/VimbaCPP/Examples/Common/ErrorCodeToMessage.h new file mode 100644 index 0000000..e4e37df --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/Common/ErrorCodeToMessage.h @@ -0,0 +1,84 @@ +/*============================================================================= + Copyright (C) 2014 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ErrorCodeToMessage.h + + Description: Convert the error codes to a self-explanatory message. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef ERROR_CODE_TO_MESSAGE_H_ +#define ERROR_CODE_TO_MESSAGE_H_ + +#include + +#include "VimbaCPP/Include/VimbaCPP.h" + +#ifdef UNICODE + typedef std::wstring string_type; + #define MAKE_STRING_LITERAL_(s) L ## s +#else + typedef std::string string_type; +#define MAKE_STRING_LITERAL_(s) s +#endif +#define MAKE_STRING_LITERAL(s) MAKE_STRING_LITERAL_(s) + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// +// Translates Vimba error codes to readable error messages +// +// Parameters: +// [in] eError The error code to be converted to string +// +// Returns: +// A descriptive string representation of the error code +// +inline string_type ErrorCodeToMessage( VmbError_t eError ) +{ + switch( eError ) + { + case VmbErrorSuccess: return string_type( MAKE_STRING_LITERAL( "Success." ) ); + case VmbErrorInternalFault: return string_type( MAKE_STRING_LITERAL( "Unexpected fault in VmbApi or driver." ) ); + case VmbErrorApiNotStarted: return string_type( MAKE_STRING_LITERAL( "API not started." ) ); + case VmbErrorNotFound: return string_type( MAKE_STRING_LITERAL( "Not found." ) ); + case VmbErrorBadHandle: return string_type( MAKE_STRING_LITERAL( "Invalid handle " ) ); + case VmbErrorDeviceNotOpen: return string_type( MAKE_STRING_LITERAL( "Device not open." ) ); + case VmbErrorInvalidAccess: return string_type( MAKE_STRING_LITERAL( "Invalid access." ) ); + case VmbErrorBadParameter: return string_type( MAKE_STRING_LITERAL( "Bad parameter." ) ); + case VmbErrorStructSize: return string_type( MAKE_STRING_LITERAL( "Wrong DLL version." ) ); + case VmbErrorMoreData: return string_type( MAKE_STRING_LITERAL( "More data returned than memory provided." ) ); + case VmbErrorWrongType: return string_type( MAKE_STRING_LITERAL( "Wrong type." ) ); + case VmbErrorInvalidValue: return string_type( MAKE_STRING_LITERAL( "Invalid value." ) ); + case VmbErrorTimeout: return string_type( MAKE_STRING_LITERAL( "Timeout." ) ); + case VmbErrorOther: return string_type( MAKE_STRING_LITERAL( "TL error." ) ); + case VmbErrorResources: return string_type( MAKE_STRING_LITERAL( "Resource not available." ) ); + case VmbErrorInvalidCall: return string_type( MAKE_STRING_LITERAL( "Invalid call." ) ); + case VmbErrorNoTL: return string_type( MAKE_STRING_LITERAL( "TL not loaded." ) ); + case VmbErrorNotImplemented: return string_type( MAKE_STRING_LITERAL( "Not implemented." ) ); + case VmbErrorNotSupported: return string_type( MAKE_STRING_LITERAL( "Not supported." ) ); + default: return string_type( MAKE_STRING_LITERAL( "Unknown" ) ); + } +} +}}} // AVT::VmbAPI::Examples +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/Common/StreamSystemInfo.h b/Vimba_6_0/VimbaCPP/Examples/Common/StreamSystemInfo.h new file mode 100644 index 0000000..6f7cc9b --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/Common/StreamSystemInfo.h @@ -0,0 +1,51 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: StreamSystemInfo.h + + Description: + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef STREAM_SYSTEM_INFO_H +#define STREAM_SYSTEM_INFO_H + +#include + +#include "VimbaCPP/Include/VimbaCPP.h" + +namespace AVT { +namespace VmbAPI { + +template +STREAM& operator<<( STREAM& os, AVT::VmbAPI::VimbaSystem &sys ) +{ + VmbVersionInfo_t info; + if (VmbErrorSuccess != sys.QueryVersion( info )) + { + throw std::exception(); + } + os << info.major << "." << info.minor << "." << info.patch; + return os; +} + +}} // Namespace AVT::VmbAPI::Examples +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/EventHandling/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/EventHandling/Build/Make/Makefile new file mode 100644 index 0000000..68f95e4 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/EventHandling/Build/Make/Makefile @@ -0,0 +1,51 @@ +PROJECT_NAME = EventHandling + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBACPP_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/EventHandling.o \ + $(OBJ_DIR)/program.o \ + $(OBJ_DIR)/EventObserver.o + +DEPENDENCIES = VimbaCPP + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/EventHandling.cpp b/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/EventHandling.cpp new file mode 100644 index 0000000..8ffef91 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/EventHandling.cpp @@ -0,0 +1,288 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: EventHandling.cpp + + Description: The EventHandling example will register observer on all + 'EventData' features and turn on camera notification for + 'AcquisitionStart' events. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include +#include +#include +#include + +#include "Common/StreamSystemInfo.h" +#include "Common/ErrorCodeToMessage.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// Purpose: Example execution. +// +// Parameter: +// [in ] std::string cameraID Use camera with this ID for the example. +void EventHandling::RunExample( std::string cameraID ) +{ + VimbaSystem& sys = VimbaSystem::GetInstance(); // Get a reference to the VimbaSystem singleton + std::cout << "Vimba C++ API Version " << sys << "\n\n"; // Print out version of Vimba + VmbErrorType err = sys.Startup(); // Initialize the Vimba API + CameraPtr pCamera = CameraPtr(); // Our camera + + if( VmbErrorSuccess == err ) + { + if( cameraID.empty() ) // If no ID was provided use the first camera + { + CameraPtrVector cameras; + err = sys.GetCameras( cameras ); + if( VmbErrorSuccess == err + && !cameras.empty() ) + { + err = cameras[0]->Open( VmbAccessModeFull ); // Open the camera + if( VmbErrorSuccess == err ) + { + pCamera = cameras[0]; + err = pCamera->GetID( cameraID ); + } + } + } + else + { + err = sys.OpenCameraByID( cameraID.c_str(), VmbAccessModeFull, pCamera ); // Open the camera + } + + if( NULL != pCamera ) + { + VmbInterfaceType interfaceType; + pCamera->GetInterfaceType( interfaceType ); + if( VmbErrorSuccess == err ) + { + switch ( interfaceType ) + { + case VmbInterfaceEthernet: + { + if( VmbErrorSuccess == err ) + { + err = DeactivateAllCameraNotifications( pCamera ); + if( VmbErrorSuccess == err ) + { + err = ActivateNotification( pCamera, "AcquisitionStart" ); + if( VmbErrorSuccess == err ) + { + err = RegisterEventObserver( pCamera ); + if( VmbErrorSuccess == err ) + { + std::cout << "Acquire image to trigger event.\n"; + std::cout << "\n----------- Events -----------\n\n"; + FramePtr pFrame; + VmbInt32_t exampleTimeoutValue = 2000; + pCamera->AcquireSingleImage( pFrame, exampleTimeoutValue ); // Trigger the event + } + } + } + } + break; + } + default: + std::cout << "Interface type of camera not supported by this example.: " << cameraID << "\n"; + } + } + else + { + std::cout << "Could not get interface type. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + pCamera->Close(); + } + else + { + std::cout << "Could not open camera or no camera available. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + sys.Shutdown(); + } + else + { + std::cout << "Could not start system. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } +} + +// Purpose: Deactivate all camera notification. +// +// Parameter: +// [in ] CameraPtr pCamera Intern camera object. +// +// Returns: +// VmbErrorSuccess in case of success otherwise an error code +VmbErrorType EventHandling::DeactivateAllCameraNotifications( CameraPtr pCamera ) +{ + std::cout << "Deactivate notifications.\n"; + FeaturePtr pFeatureEventSelector; + VmbErrorType err = pCamera->GetFeatureByName( "EventSelector", pFeatureEventSelector ); + if( VmbErrorSuccess == err ) + { + EnumEntryVector eventSelectorEntrys; + err = pFeatureEventSelector->GetEntries( eventSelectorEntrys ); + if( VmbErrorSuccess == err ) + { + FeaturePtr pFeatureEnumEntry; + for( size_t i = 0; i < eventSelectorEntrys.size(); i++ ) + { + std::string entryValue = ""; + err = eventSelectorEntrys[i].GetName( entryValue ); + if( VmbErrorSuccess == err ) + { + bool isCurrentEntryAvailable = false; + err = pFeatureEventSelector->IsValueAvailable( entryValue.c_str(), isCurrentEntryAvailable ); + if ( VmbErrorSuccess == err ) + { + if ( isCurrentEntryAvailable ) + { + err = pFeatureEventSelector->SetValue( entryValue.c_str() ); + if( VmbErrorSuccess == err ) + { + err = pCamera->GetFeatureByName( "EventNotification", pFeatureEnumEntry ); + if( VmbErrorSuccess == err ) + { + err = pFeatureEnumEntry->SetValue( "Off" ); + if( VmbErrorSuccess != err ) + { + std::cout << "Could not set notification 'Off'. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else + { + std::cout << "Could not get feature 'EventNotification'. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else + { + std::cout << "Could not set 'EventSelector' value to '" << entryValue << "'. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + } + else + { + std::cout << "Could not check if entry is currently available. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else + { + std::cout << "Could not get entry value. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + } + else + { + std::cout << "Could not get 'EventSelector' entry's. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else + { + std::cout << "Could not get feature 'EventSelector'. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + return err; +} + +// Purpose: Create for each 'Camera->EventData' feature an observer and register it. +// +// Parameter: +// [in ] CameraPtr pCamera Intern camera object. +// +// Returns: +// VmbErrorSuccess in case of success otherwise an error code +VmbErrorType EventHandling::RegisterEventObserver( CameraPtr pCamera ) +{ + FeaturePtrVector features; + VmbErrorType err = pCamera->GetFeatures( features ); + if( VmbErrorSuccess == err ) + { + for( size_t i = 0; i < features.size(); i++ ) + { + std::string category; + err = features[i]->GetCategory( category ); + if( 0 == category.compare( "/EventControl/EventData" ) && VmbErrorSuccess == err ) + { + IFeatureObserverPtr pObserver; + SP_SET( pObserver, new EventObserver( pCamera ) ); + err = features[i]->RegisterObserver( pObserver ); + if( VmbErrorSuccess != err ) + { + std::cout << "Could not register observer. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + } + } + else + { + std::cout << "Could not get features. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + return err; +} + +// Purpose: Activate camera notification. +// +// Parameter: +// [in ] CameraPtr pCamera Intern camera object. +// [in ] std::string eventName Name of event to activate. +// +// Returns: +// VmbErrorSuccess in case of success otherwise an error code +VmbErrorType EventHandling::ActivateNotification( CameraPtr pCamera, std::string eventName ) +{ + std::cout << "Activate notification for '" << eventName << "' events.\n"; + FeaturePtr feature; + VmbErrorType err = pCamera->GetFeatureByName( "EventSelector", feature ); + if( VmbErrorSuccess == err ) + { + err = feature->SetValue( eventName.c_str() ); + if( VmbErrorSuccess == err ) + { + err = pCamera->GetFeatureByName( "EventNotification", feature ); + if( VmbErrorSuccess == err ) + { + err = feature->SetValue( "On" ); + if( VmbErrorSuccess != err ) + { + std::cout << "Could not set notification 'On'. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else + { + std::cout << "Could not get feature 'EventNotification'. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else + { + std::cout << "Could not get selector '" << eventName << "'. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else + { + std::cout << "Could not get feature 'EventSelector'. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + return err; +} + +}}} // namespace AVT::VmbAPI::Examples \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/EventHandling.h b/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/EventHandling.h new file mode 100644 index 0000000..a327bc2 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/EventHandling.h @@ -0,0 +1,83 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: EventHandling.h + + Description: The EventHandling example will register observer on all + 'EventData' features and turn on camera notification for + 'AcquisitionStart' events. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_EVENT_HANDLING +#define AVT_VMBAPI_EXAMPLES_EVENT_HANDLING + +#include + +#include "VimbaCPP/Include/VimbaCPP.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class EventHandling +{ + +public: + // Purpose: Example execution. + // + // Parameter: + // [in ] std::string cameraID Use camera with this ID for the example. + void RunExample( std::string cameraID ); + +private: + // Purpose: Deactivate all camera notification. + // + // Parameter: + // [in ] CameraPtr pCamera Intern camera object. + // + // Returns: + // VmbErrorSuccess in case of success otherwise an error code + VmbErrorType DeactivateAllCameraNotifications( CameraPtr pCamera ); + + // Purpose: Create for each 'Camera->EventData' feature an observer and register it. + // + // Parameter: + // [in ] CameraPtr pCamera Intern camera object. + // + // Returns: + // VmbErrorSuccess in case of success otherwise an error code + VmbErrorType RegisterEventObserver( CameraPtr pCamera ); + + // Purpose: Activate camera notification. + // + // Parameter: + // [in ] CameraPtr pCamera Intern camera object. + // [in ] std::string eventName Name of event to activate. + // + // Returns: + // VmbErrorSuccess in case of success otherwise an error code + VmbErrorType ActivateNotification( CameraPtr pCamera, std::string eventName ); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/EventObserver.cpp b/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/EventObserver.cpp new file mode 100644 index 0000000..bc78b87 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/EventObserver.cpp @@ -0,0 +1,71 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: EventObserver.h + + Description: The EventObserver can be attached to a camera feature. On Feature + changing the function FeatureChanged() is called. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +#include "EventObserver.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +EventObserver::EventObserver( AVT::VmbAPI::CameraPtr pCam ) + : m_pCam( pCam ) +{ +} + +// Purpose: This function will be called when the observed feature is changing. +// +// Parameter: +// [in ] const AVT::VmbAPI::FeaturePtr &feature changed feature +// +void EventObserver::FeatureChanged( const AVT::VmbAPI::FeaturePtr &feature ) +{ + if( feature != NULL ) + { + std::string featureName; + if ( !feature->GetName( featureName ) ) + { + std::cout << featureName << " (Event) has changed to "; + + AVT::VmbAPI::FeaturePtr pFeature; + VmbInt64_t nID; + if ( !( m_pCam->GetFeatureByName( featureName.c_str(), pFeature ) ) + && !( pFeature->GetValue( nID ) ) ) + { + std::cout << nID << std::endl; + } + } + else + { + std::cout << "An error occurred" << std::endl; + } + } +} + +}}} // namespace AVT::VmbAPI::Examples \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/EventObserver.h b/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/EventObserver.h new file mode 100644 index 0000000..db02800 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/EventObserver.h @@ -0,0 +1,58 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: EventObserver.h + + Description: The EventObserver can be attached to a camera feature. On Feature + changing the function FeatureChanged() is called. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_EVENT_OBSERVER_H +#define AVT_VMBAPI_EXAMPLES_EVENT_OBSERVER_H + +#include + +#include "VimbaCPP/Include/VimbaCPP.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class EventObserver : public AVT::VmbAPI::IFeatureObserver +{ + +private: + AVT::VmbAPI::CameraPtr m_pCam; + +public: + // Purpose: This function will be called when the observed feature is changing. + // + // Parameter: + // [in ] const AVT::VmbAPI::FeaturePtr &feature changed feature + // + virtual void FeatureChanged( const AVT::VmbAPI::FeaturePtr &feature ); + EventObserver( AVT::VmbAPI::CameraPtr pCam ); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/program.cpp b/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/program.cpp new file mode 100644 index 0000000..9705ef5 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/EventHandling/Source/program.cpp @@ -0,0 +1,56 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: Main entry point of EventHandling example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +#include "EventHandling.h" + +int main( int argc, char* argv[] ) +{ + std::cout << "\n"; + std::cout << "////////////////////////////////////////\n"; + std::cout << "/// Vimba API Event Handling Example ///\n"; + std::cout << "////////////////////////////////////////\n\n"; + + if( 2 < argc ) + { + std::cout << "Usage: EventHandling [CameraID]\n\n"; + std::cout << "Parameters: CameraID ID of the camera to use (using first camera if not specified)\n"; + } + else if( 2 == argc ) + { + AVT::VmbAPI::Examples::EventHandling eventHandler; + eventHandler.RunExample( argv[1] ); + } + else + { + AVT::VmbAPI::Examples::EventHandling eventHandler; + eventHandler.RunExample( "" ); + } + + std::cout <<"\n"; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/ListAncillaryDataFeatures/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/ListAncillaryDataFeatures/Build/Make/Makefile new file mode 100644 index 0000000..04a7427 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ListAncillaryDataFeatures/Build/Make/Makefile @@ -0,0 +1,50 @@ +PROJECT_NAME = ListAncillaryDataFeatures + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBACPP_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ListAncillaryDataFeatures.o \ + $(OBJ_DIR)/program.o + +DEPENDENCIES = VimbaCPP + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/ListAncillaryDataFeatures/Source/ListAncillaryDataFeatures.cpp b/Vimba_6_0/VimbaCPP/Examples/ListAncillaryDataFeatures/Source/ListAncillaryDataFeatures.cpp new file mode 100644 index 0000000..2e29c1a --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ListAncillaryDataFeatures/Source/ListAncillaryDataFeatures.cpp @@ -0,0 +1,384 @@ +/*============================================================================= + Copyright (C) 2014 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ListAncillaryDataFeatures.cpp + + Description: The ListAncillaryDataFeatures example will list all available + features of a camera that are found by VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include +#include +#include + +#include "VimbaCPP/Include/VimbaCPP.h" +#include "Common/StreamSystemInfo.h" +#include "Common/ErrorCodeToMessage.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// Purpose: Uses an API feature to set the biggest packet size possible +// +// Parameter: +// [in ] CamerPtr pCamera The camera to work on +VmbErrorType AdjustPacketSize(CameraPtr pCamera) +{ + FeaturePtr pPacketSize; + VmbErrorType err; + err = SP_ACCESS( pCamera )->GetFeatureByName( "GVSPAdjustPacketSize", pPacketSize ); + if( VmbErrorSuccess == err ) + { + err = SP_ACCESS( pPacketSize )->RunCommand() ; + if( VmbErrorSuccess == err) + { + bool bIsCommandDone = false; + do + { + if( VmbErrorSuccess != SP_ACCESS( pPacketSize )->IsCommandDone( bIsCommandDone ) ) + { + break; + } + } while( false == bIsCommandDone ); + } + } + return err; +} + +enum +{ + ACQ_TIMEOUT = 1000, +}; + +// Purpose: Prints out the value of a given feature +// +// Parameter: +// [in ] const FeaturePtr& feature A reference to the feature shared pointer +void PrintFeatureValue( const FeaturePtr& pFeature ) +{ + VmbFeatureDataType featureType; + VmbErrorType err = pFeature->GetDataType( featureType ); + + if( VmbErrorSuccess != err ) + { + std::cout << "[Could not get feature Data Type. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]\n"; + } + else + { + std::cout << "/// Value : "; + switch( featureType ) + { + case VmbFeatureDataBool: + { + VmbBool_t value; + err = pFeature->GetValue( value ); + if ( VmbErrorSuccess == err ) + { + std::cout << value << "\n"; + } + } + break; + case VmbFeatureDataEnum: + { + std::string value; + err = pFeature->GetValue( value ); + if ( VmbErrorSuccess == err ) + { + std::cout << value << "\n"; + } + } + break; + case VmbFeatureDataFloat: + { + double value; + err = pFeature->GetValue( value ); + if( VmbErrorSuccess == err) + { + std::cout << value << "\n"; + } + } + break; + case VmbFeatureDataInt: + { + VmbInt64_t value; + err = pFeature->GetValue( value ); + if( VmbErrorSuccess == err) + { + std::cout << value << "\n"; + } + } + break; + case VmbFeatureDataString: + { + std::string value; + err = pFeature->GetValue( value ); + if( VmbErrorSuccess == err) + { + std::cout << value << "\n"; + } + } + break; + case VmbFeatureDataCommand: + default: + std::cout << "[None]" << "\n"; + break; + } + + if( VmbErrorSuccess == err ) + { + std::cout << "\n"; + } + else + { + std::cout << "Could not get feature value. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n\n"; + } + } +} + +// Purpose: Prints out all details of a given feature +// +// Parameter: +// [in ] const FeaturePtr& pFeature A reference to the feature shared pointer +void PrintFeature( const FeaturePtr& pFeature ) +{ + std::string name; // The name of the feature + std::string displayName; // The display name of the feature + std::string toolTip; // A short description of the feature + std::string description; // A long description of the feature + std::string category; // A category to group features + std::string sfncNamespace; // The Standard Feature Naming Convention namespace + std::string unit; // The measurement unit of the value + + std::ostringstream ErrorStream; + + VmbErrorType err = pFeature->GetName( name ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature Name. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + name = ErrorStream.str(); + } + + err = pFeature->GetDisplayName( displayName ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature Display Name. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + displayName = ErrorStream.str(); + } + + err = pFeature->GetToolTip( toolTip ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature Tooltip. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + toolTip = ErrorStream.str(); + } + + err = pFeature->GetDescription( description ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature Description. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + description = ErrorStream.str(); + } + + err = pFeature->GetCategory( category ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature Category. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + category = ErrorStream.str(); + } + + err = pFeature->GetSFNCNamespace( sfncNamespace ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature SNFC Namespace. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + sfncNamespace = ErrorStream.str(); + } + + err = pFeature->GetUnit( unit ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature Unit. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + unit = ErrorStream.str(); + } + + std::cout << "/// Feature Name : " << name << "\n"; + std::cout << "/// Display Name : " << displayName << "\n"; + std::cout << "/// Tooltip : " << toolTip << "\n"; + std::cout << "/// Description : " << description << "\n"; + std::cout << "/// SNFC Namespace : " << sfncNamespace << "\n"; + + PrintFeatureValue( pFeature ); +} + +// Purpose: Pints out features from the ancillary data. Ancillary data is part of a frame, +// therefore we need to capture a single frame beforehand. +// If no camera ID string was passed we use the first camera found. +// +// Parameter: +// [in ] string cameraID The ID of the camera to use +void ListAncillaryDataFeatures::Print( std::string cameraID ) +{ + VimbaSystem& sys = VimbaSystem::GetInstance(); // Get a reference to the VimbaSystem singleton + std::cout << "Vimba C++ API Version " << sys << "\n"; // Print out version of Vimba + VmbErrorType err = sys.Startup(); // Initialize the Vimba API + FeaturePtrVector features; // A vector of std::shared_ptr objects + CameraPtr pCamera = CameraPtr(); // Our camera + + std::stringstream errorString; + + if( VmbErrorSuccess == err ) + { + if( cameraID.empty() ) // If no ID was provided use the first camera + { + CameraPtrVector cameras; + err = sys.GetCameras( cameras ); + if( VmbErrorSuccess == err + && !cameras.empty() ) + { + pCamera = cameras[0]; // Get the camera + err = pCamera->Open( VmbAccessModeFull ); // Open the camera + if( VmbErrorSuccess == err ) + { + err = pCamera->GetID( cameraID ); + } + } + } + else + { + err = sys.OpenCameraByID( cameraID.c_str(), // Get and open the camera + VmbAccessModeFull, + pCamera ); + } + + if( !SP_ISNULL( pCamera )) + { + if ( VmbErrorSuccess == err ) + { + AdjustPacketSize( pCamera ); + std::cout << "Printing all ancillary data features of camera with ID: " << cameraID << "\n\n"; + + FeaturePtr pFeature; + err = pCamera->GetFeatureByName( "ChunkModeActive", pFeature ); + if( VmbErrorSuccess == err ) + { + err = pFeature->SetValue( true ); // Enable ancillary data + if( VmbErrorSuccess == err ) + { + std::cout << "Capture a single frame\n\n"; // In order to fill the ancillary data we need to fill a frame + + FramePtr pFrame; + err = pCamera->AcquireSingleImage( pFrame, ACQ_TIMEOUT ); + if ( VmbErrorSuccess == err ) + { + VmbFrameStatusType status; + err = pFrame->GetReceiveStatus( status ); // Check whether we received a complete frame + if( VmbErrorSuccess == err ) + { + if ( VmbFrameStatusComplete == status ) + { + AncillaryDataPtr pAncillaryData; + err = pFrame->GetAncillaryData( pAncillaryData ); // Get the ancillary data of the frame + if ( VmbErrorSuccess == err ) + { + err = pAncillaryData->Open(); + if( VmbErrorSuccess == err) + { + err = pAncillaryData->GetFeatures( features ); // Fetch all features of the ancillary data + if( VmbErrorSuccess == err ) + { + // Query all static details as well as the value of all fetched features and print them out. + std::for_each( features.begin(), features.end(), PrintFeature ); + } + else + { + std::cout << "Could not get features. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + + pAncillaryData->Close(); + } + else + { + std::cout << "Could not open ancillary data. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else + { + std::cout << "Could not get ancillary data. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else if( VmbFrameStatusIncomplete == status ) + { + std::cout << "Could not acquire complete frame. Receive status: " << err << "\n"; + } + else + { + std::cout << "Could not acquire frame. Receive status: " << err << "\n"; + } + } + else + { + std::cout << "Could not get frame receive status. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else + { + std::cout << "Could not acquire image. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else + { + std::cout << "Could not enable ancillary data. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else if( VmbErrorNotFound == err ) + { + std::cout << "The camera does not provide ancillary data. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + else + { + std::cout << "Could not query for the presence of ancillary data. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + + + pCamera->Close(); + } + else + { + std::cout << "Could not open camera. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + } + else + { + std::cout << "No camera available.\n"; + } + + sys.Shutdown(); // Finally close Vimba + } + else + { + std::cout << "Could not start system. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } +} + +}}} // namespace AVT::VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/ListAncillaryDataFeatures/Source/ListAncillaryDataFeatures.h b/Vimba_6_0/VimbaCPP/Examples/ListAncillaryDataFeatures/Source/ListAncillaryDataFeatures.h new file mode 100644 index 0000000..b7e785c --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ListAncillaryDataFeatures/Source/ListAncillaryDataFeatures.h @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ListAncillaryDataFeatures.h + + Description: The ListAncillaryDataFeatures example will list all available + features of the ancillary data. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_LISTANCILLARYDATAFEATURES +#define AVT_VMBAPI_EXAMPLES_LISTANCILLARYDATAFEATURES + +#include + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class ListAncillaryDataFeatures +{ +public: + // Purpose: Pints out features from the ancillary data. Ancillary data is part of a frame, + // therefore we need to capture a single frame beforehand. + // If no camera ID string was passed we use the first camera found. + // + // Parameter: + // [in ] string cameraID The ID of the camera to use + static void Print( std::string cameraID ); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/ListAncillaryDataFeatures/Source/program.cpp b/Vimba_6_0/VimbaCPP/Examples/ListAncillaryDataFeatures/Source/program.cpp new file mode 100644 index 0000000..f4677de --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ListAncillaryDataFeatures/Source/program.cpp @@ -0,0 +1,54 @@ +/*============================================================================= + Copyright (C) 2014 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: Main entry point of ListAncillaryDataFeatures example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +#include "ListAncillaryDataFeatures.h" + +int main( int argc, char* argv[] ) +{ + std::cout << "\n"; + std::cout << "//////////////////////////////////////////////////////\n"; + std::cout << "/// Vimba API List Ancillary Data Features Example ///\n"; + std::cout << "//////////////////////////////////////////////////////\n\n"; + + if( 2 < argc ) + { + std::cout << "Usage: ListAncillaryDataFeatures [CameraID]\n\n"; + std::cout << "Parameters: CameraID ID of the camera to use (using first camera if not specified)\n"; + } + else if( 2 == argc ) + { + AVT::VmbAPI::Examples::ListAncillaryDataFeatures::Print( argv[1] ); + } + else + { + AVT::VmbAPI::Examples::ListAncillaryDataFeatures::Print( "" ); + } + + std::cout << "\n"; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/ListCameras/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/ListCameras/Build/Make/Makefile new file mode 100644 index 0000000..a3513a5 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ListCameras/Build/Make/Makefile @@ -0,0 +1,50 @@ +PROJECT_NAME = ListCameras + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBACPP_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ListCameras.o \ + $(OBJ_DIR)/program.o + +DEPENDENCIES = VimbaCPP + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/ListCameras/Source/ListCameras.cpp b/Vimba_6_0/VimbaCPP/Examples/ListCameras/Source/ListCameras.cpp new file mode 100644 index 0000000..b60bea2 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ListCameras/Source/ListCameras.cpp @@ -0,0 +1,138 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ListCameras.cpp + + Description: The ListCameras example will list all available cameras that + are found by VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include +#include + +#include "ListCameras.h" + +#include "VimbaCPP/Include/VimbaCPP.h" +#include "Common/StreamSystemInfo.h" +#include "Common/ErrorCodeToMessage.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +/**printing camera info for a camera. +*\note this function is used with for_each and is called for each camera in range cameras.begin(), cameraas.end() +*/ +void PrintCameraInfo( const CameraPtr &camera ) +{ + std::string strID; + std::string strName; + std::string strModelName; + std::string strSerialNumber; + std::string strInterfaceID; + + std::ostringstream ErrorStream; + + VmbErrorType err = camera->GetID( strID ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get camera ID. Error code: " << err << "("<GetName( strName ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get camera name. Error code: " << err << "("<GetModel( strModelName ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get camera mode name. Error code: " << err << "("<GetSerialNumber( strSerialNumber ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get camera serial number. Error code: " << err << "("<GetInterfaceID( strInterfaceID ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get interface ID. Error code: " << err << "("< objects + + std::stringstream strError; + + if( VmbErrorSuccess == err ) + { + err = sys.GetCameras( cameras ); // Fetch all cameras known to Vimba + if( VmbErrorSuccess == err ) + { + std::cout << "Cameras found: " << cameras.size() <<"\n\n"; + + // Query all static details of all known cameras and print them out. + // We don't have to open the cameras for that. + std::for_each( cameras.begin(), cameras.end(), PrintCameraInfo ); + } + else + { + std::cout << "Could not list cameras. Error code: " << err << "("< + +#include "ListCameras.h" + +int main( int argc, char* argv[] ) +{ + std::cout << "\n"; + std::cout << "//////////////////////////////////////\n"; + std::cout << "/// Vimba API List Cameras Example ///\n"; + std::cout << "//////////////////////////////////////\n\n"; + + if( 1 < argc ) + { + std::cout << "No parameters expected. Execution will not be affected by the provided parameter(s).\n\n"; + } + + AVT::VmbAPI::Examples::ListCameras::Print(); + + std::cout << "\n"; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/ListFeatures/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/ListFeatures/Build/Make/Makefile new file mode 100644 index 0000000..9b56258 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ListFeatures/Build/Make/Makefile @@ -0,0 +1,50 @@ +PROJECT_NAME = ListFeatures + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBACPP_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ListFeatures.o \ + $(OBJ_DIR)/program.o + +DEPENDENCIES = VimbaCPP + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/ListFeatures/Source/ListFeatures.cpp b/Vimba_6_0/VimbaCPP/Examples/ListFeatures/Source/ListFeatures.cpp new file mode 100644 index 0000000..deb123f --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ListFeatures/Source/ListFeatures.cpp @@ -0,0 +1,314 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ListFeatures.cpp + + Description: The ListFeatures example will list all available features of a + camera that are found by VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include +#include +#include + +#include "VimbaCPP/Include/VimbaCPP.h" +#include "Common/StreamSystemInfo.h" +#include "Common/ErrorCodeToMessage.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// +// Prints out an error message in case a feature's value could not be queried. +// Prints nothing in case the error means success. +// +// Parameters: +// [in] err The return code indicating the error +// +// Returns: +// The error code as passed in +// +VmbErrorType PrintGetValueErrorMessage ( const VmbErrorType err ) +{ + if ( VmbErrorSuccess != err ) + { + std::cout << "Could not get feature value. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + + return err; +} + +// +// Prints out the value and the type of a given feature +// +// Parameters: +// [in] feature The feature to work on +// +void PrintFeatureValue( const FeaturePtr &feature ) +{ + VmbFeatureDataType eType; + VmbErrorType err = feature->GetDataType( eType ); + if( VmbErrorSuccess != err ) + { + std::cout << "[Could not get feature Data Type. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]\n"; + } + else + { + std::cout << "/// Value : "; + switch( eType ) + { + case VmbFeatureDataBool: + { + VmbBool_t bValue; + err = feature->GetValue( bValue ); + if ( VmbErrorSuccess == PrintGetValueErrorMessage( err ) ) + { + std::cout << bValue << "\n"; + } + std::cout << "/// Type : Boolean\n"; + } + break; + case VmbFeatureDataEnum: + { + std::string strValue; + err = feature->GetValue( strValue ); + if ( VmbErrorSuccess == PrintGetValueErrorMessage( err ) ) + { + std::cout << strValue << "\n"; + } + std::cout << "/// Type : Enumeration\n"; + } + break; + case VmbFeatureDataFloat: + { + double fValue; + double fMin, fMax; + err = feature->GetValue( fValue ); + if( VmbErrorSuccess == PrintGetValueErrorMessage( err ) ) + { + std::cout << fValue << "\n"; + } + + std::cout << "/// Minimum : "; + err = feature->GetRange( fMin, fMax ); + if( VmbErrorSuccess == PrintGetValueErrorMessage( err ) ) + { + std::cout << fMin << "\n"; + std::cout << "/// Maximum : " << fMax << "\n"; + } + std::cout << "/// Type : Double precision floating point\n"; + } + break; + case VmbFeatureDataInt: + { + VmbInt64_t nValue; + VmbInt64_t nMin, nMax; + err = feature->GetValue( nValue ); + if( VmbErrorSuccess == PrintGetValueErrorMessage( err ) ) + { + std::cout << nValue << "\n"; + } + + std::cout << "/// Minimum : "; + err = feature->GetRange( nMin, nMax ); + if( VmbErrorSuccess == PrintGetValueErrorMessage( err ) ) + { + std::cout << nMin << "\n"; + std::cout << "/// Maximum : " << nMax << "\n"; + } + std::cout << "/// Type : Long long integer\n"; + } + break; + case VmbFeatureDataString: + { + std::string strValue; + + err = feature->GetValue( strValue ); + if( VmbErrorSuccess == PrintGetValueErrorMessage( err ) ) + { + std::cout << strValue << "\n"; + } + std::cout << "/// Type : String\n"; + } + break; + case VmbFeatureDataCommand: + default: + { + std::cout << "[None]" << "\n"; + std::cout << "/// Type : Command feature\n"; + } + break; + } + + std::cout << "\n"; + } +} + +// +// Prints out all details of a feature +// +// Parameters: +// [in] feature The feature to work on +// +void PrintFeatures( const FeaturePtr &feature ) +{ + std::string strName; // The name of the feature + std::string strDisplayName; // The display name of the feature + std::string strToolTip; // A short description of the feature + std::string strDescription; // A long description of the feature + std::string strCategory; // A category to group features + std::string strSFNCNamespace; // The Standard Feature Naming Convention namespace + std::string strUnit; // The measurement unit of the value + + std::ostringstream ErrorStream; + + VmbErrorType err = feature->GetName( strName ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature Name. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + strName = ErrorStream.str(); + } + + err = feature->GetDisplayName( strDisplayName ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature Display Name. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + strDisplayName = ErrorStream.str(); + } + + err = feature->GetToolTip( strToolTip ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature Tooltip. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + strToolTip = ErrorStream.str(); + } + + err = feature->GetDescription( strDescription ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature Description. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + strDescription = ErrorStream.str(); + } + + err = feature->GetCategory( strCategory ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature Category. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + strCategory = ErrorStream.str(); + } + + err = feature->GetSFNCNamespace( strSFNCNamespace ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature SNFC Namespace. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + strSFNCNamespace = ErrorStream.str(); + } + + err = feature->GetUnit( strUnit ); + if( VmbErrorSuccess != err ) + { + ErrorStream << "[Could not get feature Unit. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "]"; + strUnit = ErrorStream.str(); + } + + std::cout << "/// Feature Name : " << strName << "\n"; + std::cout << "/// Display Name : " << strDisplayName << "\n"; + std::cout << "/// Tooltip : " << strToolTip << "\n"; + std::cout << "/// Description : " << strDescription << "\n"; + std::cout << "/// SNFC Namespace : " << strSFNCNamespace << "\n"; + std::cout << "/// Unit : " << strUnit << "\n"; + + PrintFeatureValue( feature ); +} + +// +// Prints out all features and their values and details of a given camera. +// If no camera ID is provided, the first camera will be used. +// Starts and stops the API +// Opens and closes the camera +// +// Parameters: +// [in] CameraID The ID of the camera to work +// +void ListFeatures::Print( std::string CameraID ) +{ + VimbaSystem& sys = VimbaSystem::GetInstance(); // Get a reference to the VimbaSystem singleton + std::cout << "Vimba C++ API Version " << sys << "\n"; // Print out version of Vimba + VmbErrorType err = sys.Startup(); // Initialize the Vimba API + FeaturePtrVector features; // A vector of std::shared_ptr objects + CameraPtr pCamera = CameraPtr(); // Our camera + + std::stringstream strError; + + if( VmbErrorSuccess == err ) + { + if( CameraID.empty() ) // If no ID was provided use the first camera + { + CameraPtrVector cameras; + err = sys.GetCameras( cameras ); + if( VmbErrorSuccess == err + && !cameras.empty() ) + { + err = cameras[0]->Open( VmbAccessModeFull ); // Open the camera + if( VmbErrorSuccess == err ) + { + pCamera = cameras[0]; + err = pCamera->GetID( CameraID ); + } + } + } + else + { + err = sys.OpenCameraByID( CameraID.c_str(), VmbAccessModeFull, pCamera ); // Get and open the camera + } + if( NULL != pCamera ) + { + std::cout << "Printing all features of camera with ID: " << CameraID << "\n"; + err = pCamera->GetFeatures( features ); // Fetch all features of our cam + if( VmbErrorSuccess == err ) + { + // Query all static details as well as the value of all fetched features and print them out. + std::for_each( features.begin(), features.end(), PrintFeatures ); + } + else + { + std::cout << "Could not get features. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + + pCamera->Close(); + } + else + { + std::cout << "Could not open camera or no camera available. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } + sys.Shutdown(); + } + else + { + std::cout << "Could not start system. Error code: " << err << " (" << AVT::VmbAPI::Examples::ErrorCodeToMessage( err ) << ")" << "\n"; + } +} + +}}} // namespace AVT::VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/ListFeatures/Source/ListFeatures.h b/Vimba_6_0/VimbaCPP/Examples/ListFeatures/Source/ListFeatures.h new file mode 100644 index 0000000..904baec --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ListFeatures/Source/ListFeatures.h @@ -0,0 +1,55 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ListFeatures.h + + Description: The ListFeatures example will list all available features of a + camera that are found by VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_LISTFEATURES +#define AVT_VMBAPI_EXAMPLES_LISTFEATURES + +#include + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class ListFeatures +{ +public: + // + // Prints out all features and their values and details of a given camera. + // If no camera ID is provided, the first camera will be used. + // Starts and stops the API + // Opens and closes the camera + // + // Parameters: + // [in] CameraID The ID of the camera to work + // + static void Print( std::string CameraID ); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/ListFeatures/Source/program.cpp b/Vimba_6_0/VimbaCPP/Examples/ListFeatures/Source/program.cpp new file mode 100644 index 0000000..48a3efa --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/ListFeatures/Source/program.cpp @@ -0,0 +1,54 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: Main entry point of ListFeatures example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +#include "ListFeatures.h" + +int main( int argc, char* argv[] ) +{ + std::cout << "\n"; + std::cout << "///////////////////////////////////////\n"; + std::cout << "/// Vimba API List Features Example ///\n"; + std::cout << "///////////////////////////////////////\n\n"; + + if( 2 < argc ) + { + std::cout << "Usage: ListFeatures [CameraID]\n\n"; + std::cout << "Parameters: CameraID ID of the camera to use (using first camera if not specified)\n"; + } + else if( 2 == argc ) + { + AVT::VmbAPI::Examples::ListFeatures::Print( argv[1] ); + } + else + { + AVT::VmbAPI::Examples::ListFeatures::Print( "" ); + } + + std::cout <<"\n"; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/LoadSaveSettings/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/LoadSaveSettings/Build/Make/Makefile new file mode 100644 index 0000000..b4928e5 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/LoadSaveSettings/Build/Make/Makefile @@ -0,0 +1,53 @@ +PROJECT_NAME = LoadSaveSettings + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk +include $(MAKE_INCLUDE_DIR)/tinyxml.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBACPP_LIBS) \ + $(TINYXML_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) \ + $(TINYXML_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/program.o + +DEPENDENCIES = VimbaCPP \ + tinyxml + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/LoadSaveSettings/Source/program.cpp b/Vimba_6_0/VimbaCPP/Examples/LoadSaveSettings/Source/program.cpp new file mode 100644 index 0000000..246dd34 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/LoadSaveSettings/Source/program.cpp @@ -0,0 +1,472 @@ +/*============================================================================= + Copyright (C) 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: LoadSaveSettings example of VimbaCPP. + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +int main( int argc, char* argv[] ) +{ + using namespace AVT::VmbAPI; + + VmbErrorType err = VmbErrorSuccess; + std::stringstream ss; + bool apiFlag = false; + bool cameraFlag = false; + + std::cout << std::endl; + std::cout << "////////////////////////////////////////////" << std::endl; + std::cout << "/// Vimba API Load/Save Settings Example ///" << std::endl; + std::cout << "////////////////////////////////////////////" << std::endl; + std::cout << std::endl; + +// create camera pointer +// get VimbaCPP instance singleton + CameraPtr pCam; + VimbaSystem &sys = VimbaSystem::GetInstance(); + + try + { + // start Vimba API + err = sys.Startup(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not start Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + throw std::exception(); + } + + apiFlag = true; + std::cout << "--> VimbaCPP has been started" << std::endl; + + // get connected cameras from VimbaCPP + CameraPtrVector pCameras; + err = sys.GetCameras( pCameras ); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not get connected cameras [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + throw std::exception(); + } + + // select first camera in list + pCam = pCameras[0]; + + // open camera + err = pCam->Open( VmbAccessModeFull ); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not open camera [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + + err = pCam->Close(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not close camera [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + + throw std::exception(); + } + + // get camera id + std::string cameraId; + err = pCam->GetID( cameraId ); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not get camera id [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + + err = pCam->Close(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not close camera [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + + throw std::exception(); + } + + cameraFlag = true; + ss.str( "" ); + ss << "--> Camera with id '" << cameraId << "' has been opened"; + std::cout << ss.str() << std::endl; + + // create xml file name + ss.str( "" ); + ss << cameraId << ".xml"; + std::string xmlFile = ss.str(); + + // ------------------------------------------------------------------------------------- + // setup load/save settings behaviour: + // there are three different ways in VimbaCPP to setup the behaviour for + // loading and saving feature values with load/save settings implementation. + // SaveCameraSettings() and LoadCameraSettings() can be called either with + // an created struct of type 'VmbFeaturePersistSettings_t' or not. The third + // alternative is to call LoadSaveSettingsSetup() beforehand and provide the + // same parameters as it will be done by the struct. + // + // (1) default usage: + // pCam->SaveCameraSettings( xmlFile ); + // pCam->LoadCameraSettings( xmlFile ); + // + // (2) usage with settings struct: + // VmbFeaturePersistSettings_t settingsStruct; + // settingsStruct.loggingLevel = 4; // set logging level (0:info only, 1: with errors, 2: with warnings, 3: with debug, 4: with traces) + // settingsStruct.maxIterations = 5; // since its difficult to catch all feature dependencies during loading multiple + // iterations are used (compare desired value with camera value and write it to camera) + // settingsStruct.persistType = VmbFeaturePersistNoLUT; // set which features shall be persisted (saved to XML): + // VmbFeaturePersistAll: all features shall be persisted (including LUTs). + // VmbFeaturePersistStreamable: only streamable features shall be persisted. + // VmbFeaturePersistNoLUT: all features shall be persisted except for LUT, + // which is the recommended setting, because it might be very time consuming. + // pCam->SaveCameraSettings( xmlFile, &settingsStruct ); + // pCam->LoadCameraSettings( xmlFile, &settingsStruct ); + // + // (3) usage with setup method: + // pCam->LoadSaveSettingsSetup( VmbFeaturePersistNoLUT, 5, 4 ); + // pCam->SaveCameraSettings( xmlFile ); + // pCam->LoadCameraSettings( xmlFile ); + // ------------------------------------------------------------------------------------- + + // call VimbaCPP method for saving all feature values + err = pCam->SaveCameraSettings( xmlFile ); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not save camera settings to file '" << xmlFile << "' [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + + err = pCam->Close(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not close camera [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + cameraFlag = false; + + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + apiFlag = false; + + throw std::exception(); + } + + ss.str( "" ); + ss << "--> Feature values have been saved to '" << xmlFile << "'"; + std::cout << ss.str() << std::endl; + + // get feature selector for user set + FeaturePtr feature; + err = pCam->GetFeatureByName( "UserSetSelector", feature ); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not get feature 'UserSetSelector' [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + + err = pCam->Close(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not close camera [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + cameraFlag = false; + + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + apiFlag = false; + + throw std::exception(); + } + + // set value of selector to 'Default' + err = feature->SetValue( "Default" ); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not set value of feature 'UserSetSelector' [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + + err = pCam->Close(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not close camera [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + cameraFlag = false; + + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + apiFlag = false; + + throw std::exception(); + } + + // get feature command 'UserSetLoad' + err = pCam->GetFeatureByName( "UserSetLoad", feature ); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not get feature 'UserSetLoad' [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + + err = pCam->Close(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not close camera [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + cameraFlag = false; + + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + apiFlag = false; + + throw std::exception(); + } + + // load selected user set + err = feature->RunCommand(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not run command 'UserSetLoad' [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + + err = pCam->Close(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not close camera [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + cameraFlag = false; + + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + apiFlag = false; + + throw std::exception(); + } + + std::cout << "--> All feature values have been restored to default" << std::endl; + + // create settings struct to determine behaviour during loading + VmbFeaturePersistSettings_t settingsStruct; + settingsStruct.loggingLevel = 4; + settingsStruct.maxIterations = 5; + settingsStruct.persistType = VmbFeaturePersistNoLUT; + + // re-load saved settings from file + err = pCam->LoadCameraSettings( xmlFile, &settingsStruct ); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not load camera settings to file '" << xmlFile << "' [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + + err = pCam->Close(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not close camera [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + cameraFlag = false; + + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + apiFlag = false; + + throw std::exception(); + } + + ss.str( "" ); + ss << "--> Feature values have been loaded from given XML file '" << xmlFile << "'"; + std::cout << ss.str() << std::endl; + + // close camera + err = pCam->Close(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not close camera [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + apiFlag = false; + + throw std::exception(); + } + cameraFlag = false; + + std::cout << "--> Camera has been closed" << std::endl; + + // shutdown Vimba + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + throw std::exception(); + } + apiFlag = false; + + std::cout << "--> VimbaCPP has been shut down" << std::endl; + + } + catch( std::exception &e ) + { + std::cout << "[Exception] " << e.what() << std::endl; + + if( true == cameraFlag ) + { + err = pCam->Close(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not close camera [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + } + if( true == apiFlag ) + { + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + } + + } + catch(...) + { + std::cout << "[Exception]" << std::endl; + + if( true == cameraFlag ) + { + err = pCam->Close(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not close camera [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + } + if( true == apiFlag ) + { + err = sys.Shutdown(); + if( VmbErrorSuccess != err ) + { + ss.str( "" ); + ss << "Could not shutdown Vimba [error code: " << err << "]"; + std::cout << ss.str() << std::endl; + } + } + + } + + std::cout << std::endl << "<>" << std::endl; + std::cin.get(); + return err; + +} diff --git a/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Build/Make/Makefile new file mode 100644 index 0000000..768aa6a --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Build/Make/Makefile @@ -0,0 +1,51 @@ +PROJECT_NAME = LookUpTable + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBACPP_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/LookUpTable.o \ + $(OBJ_DIR)/program.o \ + $(OBJ_DIR)/Csv.o + +DEPENDENCIES = VimbaCPP + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/Csv.cpp b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/Csv.cpp new file mode 100644 index 0000000..5ec151f --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/Csv.cpp @@ -0,0 +1,97 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: Csv.cpp + + Description: Helper to access a CSV file using VimbaCPP. + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +#include "Csv.h" + +#include "VimbaCPP/Include/VimbaCPP.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + + +// Class to write data to a CSV file +CsvSave::CsvSave( const std::string &FileName ) + :m_Stream( FileName.c_str() ) +{ } + +// Writes a single row to a CSV file. +bool CsvSave::Row( const std::string &text ) +{ + if( 0 == text.size() ) + { + return false; + } + std::string line = text + m_CsvParameter.RD() ; + m_Stream.write( line.c_str(), line.length() ); + return true; +} + +// Class to load data from CSV +CsvLoad::CsvLoad( const std::string &filename ) + : m_Stream( filename.c_str() ) +{} + +// Reads a row of data from CSV +bool CsvLoad::Row( std::vector &row ) +{ + row.clear(); + char pLineText[256]; + if( m_Stream.getline( pLineText, 256, m_CsvParameter.RD() ) ) + { + + std::string lineText = std::string( pLineText ); + if( 0 == lineText.size() ) + { + return false; + } + typedef std::string::size_type pos_type; + pos_type pos = 0; + while( pos != std::string::npos ) + { + pos_type start = pos; + pos = lineText.find( m_CsvParameter.VD(), start ); + const std::string value = lineText.substr( start, pos ); + row.push_back( value ); + if( pos != std::string::npos ) + { + pos++; + } + } + } + else + { + return false; + } + + return ( row.size() > 0 ); +} + +}}} // namespace AVT::VmbAPI::Examples \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/Csv.h b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/Csv.h new file mode 100644 index 0000000..96438b9 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/Csv.h @@ -0,0 +1,90 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: Csv.h + + Description: Helper to access a CSV file using VimbaCPP. + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_LOOKUPTABLE_CSV +#define AVT_VMBAPI_EXAMPLES_LOOKUPTABLE_CSV + +#include +#include + +#include "VimbaCPP/Include/VimbaCPP.h" + + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class Csv +{ +private: + char m_VD; + char m_RD; + bool m_bHasHeader; + +public: + //ctor + Csv() + : m_VD( ';' ) + , m_RD( '\n' ) + , m_bHasHeader( false ) + { } + char VD( ) const { return m_VD; } + void VD( char vd ) { m_VD = vd;} + char RD ( ) const { return m_RD; } + bool HasHeader() const { return m_bHasHeader; } + void HasHeader( bool bHasHeader ) { m_bHasHeader = bHasHeader; } + +}; + +class CsvLoad +{ +private: + std::ifstream m_Stream; + Csv m_CsvParameter; +public: + //ctor + CsvLoad( const std::string &filename ); + bool Row( std::vector &row ); +}; + +class CsvSave +{ +private: + std::ofstream m_Stream; + Csv m_CsvParameter; +public: + //ctor + CsvSave( const std::string &filename ); + + bool Row( const std::string &text ); +}; + + +}}} // namespace AVT::VmbAPI::Examples + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/Exception.h b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/Exception.h new file mode 100644 index 0000000..1daf5f0 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/Exception.h @@ -0,0 +1,87 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: Exception.h + + Description: Helper for exceptions. + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_EXCEPTION +#define AVT_VMBAPI_EXAMPLES_EXCEPTION + +#include "VimbaCPP/Include/VimbaCPP.h" +#include "Common/ErrorCodeToMessage.h" +using namespace std; + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class Exception: public exception +{ +private: + std::string m_sMsg; + // Vimba error code + VmbErrorType m_eError; +public: + Exception( const std::string &rsMessage, const VmbErrorType eError ) + : m_eError(eError) + { + try + { + m_sMsg = rsMessage; + } catch(...){} + } + Exception( const std::string &Fun, const std::string &rsMessage, const VmbErrorType eError ) + : m_eError(eError) + { + try + { + m_sMsg = Fun + ": " + rsMessage; + } catch(...){} + } + + virtual ~Exception() throw() + { + } + + VmbErrorType GetError() const + { + return m_eError; + } + + std::string GetMessageStr() const + { + return m_sMsg; + } + + // Translates Vimba error codes to readable error messages + std::string ErrorCodeToMessage( VmbErrorType eErr ) + { + return AVT::VmbAPI::Examples::ErrorCodeToMessage( eErr ); + } +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/LookUpTable.cpp b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/LookUpTable.cpp new file mode 100644 index 0000000..876674f --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/LookUpTable.cpp @@ -0,0 +1,569 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: LookUpTable.cpp + + Description: The LookUpTable example will demonstrate how to use + the look up table feature of the camera using VimbaCPP. + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include +#include +#include +#include + +#include "LookUpTable.h" +#include "Csv.h" +#include "Exception.h" +#include "VimbaFeatures.h" +#include "VimbaCPP/Include/VimbaCPP.h" + + + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +namespace +{ // toolset to handle network byte order, for production, use htons ntohs for int16 + static const union + { + VmbUint8_t bytes[4]; + VmbUint32_t v; + } host_byte_order = {{0,1,2,3}}; + enum + { + byte_oder_little_endian = 0x03020100ul, + byte_oder_big_endian = 0x01000302ul, + }; + + inline UcharVector ConvertToNetworkInt16( const UcharVector &d) + { + if (host_byte_order.v == byte_oder_little_endian) + { + UcharVector tmp( d ); + for( size_t i = 0 ;i < tmp.size(); i +=2) + { + VmbUint16_t *p = reinterpret_cast( &tmp[i] ); + *p = ((*p>>8) & 0xff) | ((*p<<8) & 0xff00); + } + return tmp; + } + return d; + } + inline UcharVector ConvertFromNetworkInt16( const UcharVector &d) + { + return ConvertToNetworkInt16( d ); + } +} +bool LookUpTableCollection::HasLookUpTable(CameraPtr pCamera ) +{ + return VimbaFeature::HasFeature( pCamera, "LUTSelector"); +} +LookUpTableCollection::LookUpTableCollection( CameraPtr pCamera ) + : m_pCamera( pCamera ) +{ + //Check parameters + if( NULL == m_pCamera ) + { + throw Exception( __FUNCTION__,"LookUpTableCollection failed camera pointer NULL.", VmbErrorBadParameter ); + } + + + VmbInt64_t nCount = GetCount( ); + if( 0 == nCount ) + { + throw Exception( __FUNCTION__,"LookUpTableCollection no entries.", VmbErrorNotFound ); + } + // for each lookup table create a control + for( int i = 0; i < nCount; i++ ) + { + m_tables.push_back( LookUpTableControl( m_pCamera, i )); + } +} + +//Get look up table count +VmbInt64_t LookUpTableCollection::GetCount( ) +{ + // number of LUTs is the number of enum values fo the "LUTSelector" Feature + VimbaFeatureEnum LutSelector( m_pCamera, "LUTSelector" ); + return LutSelector.ValueCount(); +} + +//Get look up table control +LookUpTableControl LookUpTableCollection::GetControl( VmbInt64_t nIndex ) +{ + VimbaFeatureEnum LutSelector( m_pCamera, "LUTSelector" ); //< get enum feature for supported LUTs + StringVector Values = LutSelector.GetValues(); //< get list of supported LUTs + if( static_cast(nIndex) >= Values.size() ) //< test index for out of range + { + throw Exception( __FUNCTION__,"selected index out of range",VmbErrorBadParameter ); + } + std::string SelectedValue = Values[ static_cast( nIndex ) ]; + if( !LutSelector.IsAvailable( SelectedValue ) ) + { + throw Exception(__FUNCTION__,"selected LUT is not available", VmbErrorBadParameter ); + } + LutSelector.SetStringValue( SelectedValue ); //< activate the LUT at nIndex + + return m_tables[ static_cast( nIndex ) ]; //< get stored LUT control +} + +//Get look up table active index +VmbInt64_t LookUpTableCollection::GetActiveIndex( ) +{ + VimbaFeatureEnum LutSelector( m_pCamera, "LUTSelector" ); //< get enum feture for supported luts + const StringVector SupportedLuts = LutSelector.GetValues(); //< get list of supported LUTs + std::string CurrentLut = LutSelector.GetStringValue( ); //< get the currently selected LUT + StringVector::const_iterator find_pos = std::find( SupportedLuts.begin(), SupportedLuts.end(), CurrentLut );//< find current vallue in list + if( SupportedLuts.end() == find_pos ) + { + throw Exception( __FUNCTION__,"could not find current selected lut index",VmbErrorNotFound ); + } + return std::distance( SupportedLuts.begin(), find_pos ); +} + +LookUpTableControl::LookUpTableControl( CameraPtr pCamera, VmbInt64_t nIndex ) + : m_pCamera( pCamera ) + , m_nIndex( nIndex ) + +{ + //Check parameters + if( NULL == m_pCamera ) + { + throw Exception( __FUNCTION__,"LookUpTableControl failed.", VmbErrorBadParameter ); + } +} + +//Enable look up table +void LookUpTableControl::Enable( VmbBool_t bEnable ) +{ + VimbaFeatureBool LutEnable( m_pCamera, "LUTEnable" ); //< create bool feature for lut enable + LutEnable( bEnable ); //< set state to feature +} + +//Is look up table enabled +VmbBool_t LookUpTableControl::IsEnabled( ) const +{ + VimbaFeatureBool LutEnable( m_pCamera,"LUTEnable" ); //< create bool feature for Lut enable + return LutEnable(); //< return current value +} + +//Get look up table index +VmbInt64_t LookUpTableControl::GetIndex( ) const +{ + VimbaFeatureInt LutIndex( m_pCamera, "LUTIndex" ); //< get feature for LUT index + return LutIndex(); // return current index +} + +//Get value count +VmbInt64_t LookUpTableControl::GetValueCount( ) const +{ + VimbaFeatureInt LutSize ( m_pCamera,"LUTSize"); //< get feature for LUT size in bytes + VimbaFeatureInt LutBitDepthOut ( m_pCamera, "LUTBitDepthOut"); //< get feature for output bits per lut values + VmbInt64_t nLUTBytePerValue = LutBitDepthOut() > 8 ? 2 : 1; //< calculate bytes used its either 2 bytes if larger than 8bits or 1 byte + + return LutSize() / nLUTBytePerValue; //< lut are elements without padding consecutive in memory +} + +//Get look up table value +VmbInt64_t LookUpTableControl::GetValue( ) const +{ + VimbaFeatureInt LutValue( m_pCamera, "LUTValue" ); //< get feature for lUT element value this depends on LUTIndex + return LutValue(); //< return current value +} + +//Set look up table value +void LookUpTableControl::SetValue( VmbInt64_t nValue ) +{ + VimbaFeatureInt LutValue( m_pCamera,"LUTValue" ); //< get feature for LUT element value this depends on LUTIndex + LutValue( nValue ); //< set new value +} + + +//Get bit depth in +VmbInt64_t LookUpTableControl::GetBitDepthIn( ) const +{ + VimbaFeatureInt LutBitDepthIn( m_pCamera, "LUTBitDepthIn" ); //< get feature for input bit depth of LUT + return LutBitDepthIn(); //< return bit depth +} + +//Get bit depth out +VmbInt64_t LookUpTableControl::GetBitDepthOut( ) const +{ + VimbaFeatureInt LutBitDepthOut( m_pCamera,"LUTBitDepthOut" ); //< get feature for output bit depth of LUT + return LutBitDepthOut(); // return bit dept +} + + +//Download look up table +void LookUpTableControl::Download() +{ + // if any kind of LUT is implemented we should find the LUTSelector feature + if( VmbBoolTrue != VimbaFeature::HasFeature( m_pCamera,"LUTSelector" ) ) + { + throw Exception( __FUNCTION__,"no LUT feature implemented",VmbErrorNotFound ); + } + // try reading LUT with FileAccess + if( VmbBoolTrue == VimbaFeature::HasFeature( m_pCamera, "FileSelector" ) ) + { + VimbaFeatureEnum LutSelector ( m_pCamera, "LUTSelector"); //< selector feature for lookup table + VimbaFeatureEnum FileSelector( m_pCamera, "FileSelector"); //< file selector + VimbaFeatureEnum FileOpenMode( m_pCamera, "FileOpenMode"); //< selector for file open mode + FileSelector.SetStringValue ( std::string("LUT") + LutSelector.GetStringValue()); //< get the lookup table name and set it to file selector + + if( VmbBoolTrue != FileOpenMode.IsAvailable( "Read" ) ) //< test if LUT feature is readable, Firewire does not support LUT read + { + throw Exception( __FUNCTION__,"camera does not support LUT download to host computer", VmbErrorNotSupported ); + } + FileOpenMode.SetStringValue( "Read" ); //< set the open mode to read + + VimbaFeatureInt LutSize( m_pCamera,"LUTSizeBytes" ); //< integer feature for bytes of lookup table + m_data.resize( static_cast( LutSize() ) ); //< get the bytes + + VimbaFeatureEnum FileOperationSelector ( m_pCamera, "FileOperationSelector"); //< file operation selector to selector the file command + VimbaFeatureCommand FileOperationExecute ( m_pCamera, "FileOperationExecute"); //< file operation command executer + VimbaFeatureRaw FileAccessBuffer ( m_pCamera, "FileAccessBuffer"); //< raw data feature to access file buffer + VimbaFeatureInt FileAccessOffset ( m_pCamera, "FileAccessOffset"); //< integer feature to get the data offset into the buffer + VimbaFeatureInt FileAccessLength ( m_pCamera, "FileAccessLength"); //< integer feature for length of file access + VimbaFeatureEnum FileOperationStatus ( m_pCamera, "FileOperationStatus"); //< enumeration value for state of file operation + VimbaFeatureInt FileOperationResult ( m_pCamera, "FileOperationResult"); //< integer for file operation result + VimbaFeatureEnum FileStatus ( m_pCamera, "FileStatus"); //< file state feature + VimbaFeatureInt FileSize ( m_pCamera, "FileSize"); //< file size feature + + + FileOperationSelector.SetStringValue( "Open" ); //< set open command for file access + FileOperationExecute.Run(); //< execute command + + //File size + VmbInt64_t nFileSize = FileSize( ); //< get lut file size + + + FileOperationSelector.SetStringValue( "Read" ); //< set file operation to read + + VmbInt64_t nFileAccessOffset = 0; //< set start offset + VmbInt64_t nFileAccessLength = min( LutSize(), FileAccessLength.Max() ); //< determine if we can read the lut in one go, or are limited by max access length + UcharVector data( static_cast( nFileAccessLength ) ); //< prepare the temporary data buffer + + do + { + FileAccessLength( nFileAccessLength ); //< set the amount of data we want to read + FileOperationExecute.Run(); //< commit the read request + + + if( FileOperationStatus.GetStringValue( ) != "Success" ) //< test if read failed + { + throw Exception( __FUNCTION__,"reading LUT failed", VmbErrorOther ); + } + + FileAccessBuffer.GetBuffer( data ); //< if read succeeded we can read the raw buffer + data = ConvertFromNetworkInt16( data ); + copy( data.begin(), data.end(), m_data.begin() + ( size_t )nFileAccessOffset ); //< copy it from temp storage to internal data buffer + + nFileAccessOffset = FileAccessOffset( ); //< get the new file offset + + nFileAccessLength = min( nFileSize - nFileAccessOffset, FileAccessLength.Max() ); //< get the next file length + } + while( nFileSize != nFileAccessOffset ); + + //Select close as file operation + FileOperationSelector.SetStringValue( "Close" ); //< set file operation to close + FileOperationExecute.Run(); //< commit the close operation + + if( FileOperationStatus.GetStringValue() != "Success" ) //< test if close succeeded + { + throw Exception( __FUNCTION__,"lut file operation failed", VmbErrorOther ); + } + } + // try reading LUT address for GigE (indicator for direct memory access) + else if( VmbBoolTrue == VimbaFeature::HasFeature( m_pCamera, "LUTAddress" ) ) + { + VimbaFeatureInt LutSize( m_pCamera,"LUTSizeBytes" ); //< get feature for lut byte size + m_data.resize( static_cast( LutSize() ) ); //< prepare storage for LUT data + + VimbaFeatureInt LutAddress (m_pCamera, "LUTAddress"); //< try to get the LUT address feature + VmbInt64_t nLUTAddress = LutAddress(); //< store address + VmbUint32_t nCompletedReads = 0; + VmbErrorType err = m_pCamera->ReadMemory( nLUTAddress, m_data, nCompletedReads ); + if( VmbErrorSuccess != err ) + { + throw Exception( __FUNCTION__,": could not read memory from camera",err ); + } + m_data = ConvertFromNetworkInt16( m_data ); + } + // if non of the buffer read features are available try to read it value by value + else + { + VimbaFeatureInt LUTIndex( m_pCamera, "LUTIndex" ); //< get the LUTIndex feature to control the index of the current value + VimbaFeatureInt LUTValue( m_pCamera, "LUTValue" ); //< get the LUTValue feature to access the current value + VimbaFeatureInt LutSize ( m_pCamera, "LUTSizeBytes" ); //< get the LUTSizeBytes feature to get LUT size info + + m_data.resize( static_cast( LutSize() ) ); //< resize storage for LUT data + + VmbInt64_t nLUTBitDepthOut = GetBitDepthOut( ); //< get bits per LUT value needed + + //Evaluate number of LUT entries + VmbInt64_t nLUTBytePerValue = ( nLUTBitDepthOut > 8 ) ? 2 : 1; //< determine what size the LUT values occupy + VmbInt64_t nLUTEntries = LutSize() / nLUTBytePerValue; //< entries are stored consecutive without padding + + //Get LUT values by iteration over indexes + int iter = 0; + for( VmbInt64_t i = 0; i < nLUTEntries ; i++ ) + { + LUTIndex( i ); //< set index + VmbInt64_t nValue = LUTValue( ); //< get current value + switch( nLUTBytePerValue ) + { + case 1: + m_data[iter++] = static_cast( nValue ); + break; + case 2: + { + VmbUint16_t * p = (VmbUint16_t*)( &m_data[iter] ); + *p = static_cast( nValue ); + iter +=2; + } + break; + } + } + } +} + +//Upload look up table +void LookUpTableControl::Upload() +{ + //Look up table raw data empty + if( m_data.empty() ) + { + throw Exception( __FUNCTION__,": lut data vector is empty", VmbErrorOther ); + } + + if( VmbBoolTrue == VimbaFeature::HasFeature( m_pCamera, "FileSelector" ) ) + { + + //Evaluate size of LUT + VimbaFeatureInt LUTSize ( m_pCamera, "LUTSizeBytes"); + //file access control + VimbaFeatureEnum FileOperationSelector ( m_pCamera, "FileOperationSelector"); + VimbaFeatureCommand FileOperationExecute ( m_pCamera, "FileOperationExecute" ); + VimbaFeatureEnum FileOpenMode ( m_pCamera, "FileOpenMode" ); + VimbaFeatureRaw FileAccessBuffer ( m_pCamera, "FileAccessBuffer" ); + VimbaFeatureInt FileAccessOffset ( m_pCamera, "FileAccessOffset" ); + VimbaFeatureInt FileAccessLength ( m_pCamera, "FileAccessLength" ); + VimbaFeatureEnum FileOperationStatus ( m_pCamera, "FileOperationStatus" ); + + VimbaFeatureInt FileOperationResult ( m_pCamera, "FileOperationResult" ); + VimbaFeatureEnum FileStatus ( m_pCamera, "FileStatus" ); + VimbaFeatureInt FileSize ( m_pCamera, "FileSize" ); + VimbaFeatureEnum FileSelector ( m_pCamera, "FileSelector" ); + VimbaFeatureEnum LUTSelector ( m_pCamera, "LUTSelector" ); + + FileSelector.SetStringValue( std::string( "LUT" )+LUTSelector.GetStringValue() ); + if( FileOpenMode.IsAvailable( "Write" ) ) + { + FileOpenMode.SetStringValue( "Write" ); + FileOperationSelector.SetStringValue( "Open" ); + FileOperationExecute.Run(); + VmbInt64_t nFileSize = FileSize( ); + if( m_data.size() != nFileSize ) + { + throw Exception( __FUNCTION__,"LUT to upload does not seam to have the correct size for this camera",VmbErrorBadParameter ); + } + //File access length + VmbInt64_t nMaxFileAccessLength = FileAccessLength.Max( ); + FileOperationSelector.SetStringValue( "Write" ); + + VmbInt64_t nFileAccessOffset = 0; + VmbInt64_t nFileAccessLength = min( nFileSize, nMaxFileAccessLength ); + UcharVector data( (size_t)nFileAccessLength ); + do + { + //Set FileAccessLength + FileAccessLength( nFileAccessLength ); + //Fill buffer + copy( &m_data[(size_t)nFileAccessOffset ], &m_data[(size_t)( nFileAccessLength+nFileAccessOffset-1 ) ], data.begin() ); + data = ConvertToNetworkInt16( data ); + FileAccessBuffer( data ); + //Execute file operation + FileOperationExecute.Run( ); + //Get file operation status + if( FileOperationStatus.GetStringValue() != "Success" ) + { + throw Exception( __FUNCTION__,"writing data failed",VmbErrorOther ); + } + nFileAccessOffset =FileAccessOffset(); + + nFileAccessLength = min( nFileSize - nFileAccessOffset, nMaxFileAccessLength ); + } + while( nFileSize != nFileAccessOffset ); + FileOperationSelector.SetStringValue( "Close" ); + FileOperationExecute.Run(); + //Get file operation status + if( FileOperationStatus.GetStringValue() != "Success" ) + { + throw Exception( __FUNCTION__,"could not close file", VmbErrorOther ); + } + } + } + else if( VmbBoolTrue == VimbaFeature::HasFeature( m_pCamera,"LUTIndex" ) ) + { + //Get LUT address for GigE (indicator for direct memory access) + VimbaFeatureInt LUTAddress( m_pCamera, "LUTAddress" ); //< get feature for lut address + VmbUint32_t nCompletedWrites = 0; + UcharVector network_data( ConvertToNetworkInt16( m_data ) ); //< expect our camera to be big endian device, so if we are intel little endian we have to swap + m_pCamera->WriteMemory( LUTAddress() , network_data, nCompletedWrites ); //< write data direct to camera + } + //Camera doesn't support direct memory access for LUT + else + { + //Used LUT index and value as indicator for GigE + VimbaFeatureInt LUTIndex( m_pCamera, "LUTIndex" ); //< get lUT index feature to set current index + VimbaFeatureInt LUTValue( m_pCamera, "LUTValue" ); //< get LUT value feature to set current value + VimbaFeatureInt LUTSize ( m_pCamera, "LUTSizeBytes"); //< get feature for size of LUT in bytes + if( m_data.size() != LUTSize() ) //< compare data size to LUT size + { + throw Exception( __FUNCTION__,"data size is not equal lut size, they are incompatible",VmbErrorBadParameter ); + } + //Evaluate number of LUT entries + VmbInt64_t nLUTBytePerValue = ( GetBitDepthOut() > 8 ) ? 2 : 1; //< determine if LUT values take one or two bytes + VmbInt64_t nLUTEntries = LUTSize() / nLUTBytePerValue; //< calculate lement count, LUT values are unpadded and consecutive in memory + //Set LUT values by iteration over indexes + int iter( 0 ); + VmbInt64_t nValue( 0 ); + for( VmbInt64_t i = 0; i < nLUTEntries ; i++ ) + { + LUTIndex( i ); //< set current index + switch( nLUTBytePerValue ) + { + case 1: + nValue = m_data[iter++]; //< copy 8bit value + break; + + case 2: + { + VmbUint16_t* p = (VmbUint16_t*)(&m_data[iter]); //< interpret data as host byte order uint 16 + nValue = *p; + iter +=2; + } + } + LUTValue( nValue ); //< write data to camera + } + } +} + +//Load look up table from Csv +void LookUpTableControl::LoadFromCsv( const std::string &FileName, int nIndex ) +{ + + //Evaluate size of LUT + VmbInt64_t nLUTBitDepthOut = GetBitDepthOut( ); //< get output bit depth of LUT + VmbInt64_t nLUTBytePerValue = nLUTBitDepthOut > 8 ? 2 : 1; //< determine if LUT values take one or two byte + // Load LUT from CSV + CsvLoad load( FileName ); //< import the LUT from CSV file + std::vector row; + while( load.Row( row ) ) //< load rows until none left + { + if( row.size() <= ( size_t )nIndex ) //< test if index in range + { + throw Exception( __FUNCTION__,"index for the csv file is out of bounds",VmbErrorBadParameter ); + } + + int nData; //< coonvert string to int + std::stringstream ss( row[nIndex] ); + ss >> nData; + + char data[2]; //< pack data for storage + if( 2 == nLUTBytePerValue ) + { + VmbUint16_t *p = ( VmbUint16_t* )( data ); + *p = static_cast( nData ); + } + else + { + data[0] = static_cast( nData&0xFF ); + } + + copy( data, data + nLUTBytePerValue, std::back_inserter( m_data ) ); //< append data to internal storage + } +} + +//Save look up table to CSV +void LookUpTableControl::SaveToCsv( const std::string &FileName ) +{ + + //Raw data empty + if( m_data.empty() ) + { + throw Exception( __FUNCTION__,"no data to write to csv file", VmbErrorOther ); + } + + //Evaluate size of LUT + VimbaFeatureInt LUTSize( m_pCamera, "LUTSizeBytes" ); //< get feature for LUT size in bytes + + VmbInt64_t nLUTBitDepthOut = GetBitDepthOut( ); //< get output bit depth of LUT + VmbInt64_t nLUTBytePerValue = nLUTBitDepthOut > 8 ? 2 : 1; //< determine if LUT values take one or two bytes + VmbInt64_t nLUTEntries = LUTSize()/nLUTBytePerValue; //< calculate LUT element count, LUT values are unpadded and consecutive + if( m_data.size() != LUTSize() ) //< if lut size and data size miss match they are not compatible + { + throw Exception( __FUNCTION__,"data does not equal the current cameras LUT",VmbErrorBadParameter ); + } + // Save LUT data to CSV + + CsvSave save( FileName ); //< create CSV file + { + for( int i = 0; i < nLUTEntries; i++ ) //< for each LUT value + { + int data ; //< unpack data to int + if( 2 == nLUTBytePerValue ) + { + data = *( ( VmbUint16_t* )( &m_data[i*2] ) ); + } + else + { + data = m_data[i]; + } + stringstream ss; //< stream int to string + ss << data; + save.Row( ss.str() ); //< write a csv row + } + } +} + +//Load look up table from flash +void LookUpTableControl::LoadFromFlash() +{ + VimbaFeatureCommand LUTLoad = CreateOneOf( m_pCamera, "LUTLoad", "LUTLoadAll" ); // there are two possible names for this feature + LUTLoad.Run(); +} + +//Save look up table to flash +void LookUpTableControl::SaveToFlash() +{ + VimbaFeatureCommand LUTSave = CreateOneOf( m_pCamera, "LUTSave", "LUTSaveAll" ); //< there are two possible names for this feature + LUTSave.Run(); +} + +}}} // namespace AVT::VmbAPI::Examples + diff --git a/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/LookUpTable.h b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/LookUpTable.h new file mode 100644 index 0000000..610cfbb --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/LookUpTable.h @@ -0,0 +1,120 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: LookUpTable.h + + Description: The LookUpTable example will demonstrate how to use + the look up table feature of the camera using VimbaCPP. + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_LOOKUPTABLE +#define AVT_VMBAPI_EXAMPLES_LOOKUPTABLE + +#include "VimbaCPP/Include/VimbaCPP.h" + + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class LookUpTableControl +{ +private: + CameraPtr m_pCamera; + VmbInt64_t m_nIndex; + UcharVector m_data; + +public: + //ctor + LookUpTableControl( CameraPtr pCamera, VmbInt64_t nIndex ); + + //Enable + void Enable( VmbBool_t bEnable ); + + //Is enabled + VmbBool_t IsEnabled() const; + + //Get index + VmbInt64_t GetIndex( ) const; + + //Get value count + VmbInt64_t GetValueCount( ) const; + + //Get Value + VmbInt64_t GetValue( ) const; + + //Set Value + void SetValue( VmbInt64_t nValue ); + + //Get bit depth in + VmbInt64_t GetBitDepthIn( ) const; + + //Get bit depth out + VmbInt64_t GetBitDepthOut( ) const; + + //Download look up table from internal memory into the camera + void Download(); + + //Upload the selected look up table into internal memory of the camera + void Upload(); + + + //Load from Csv + void LoadFromCsv( const std::string &FileName, int nIndex ); + + //Save to Csv + void SaveToCsv( const std::string &FileName ); + + //Load from flash + void LoadFromFlash(); + + //Save to flash + void SaveToFlash(); +}; + +class LookUpTableCollection +{ +private: + CameraPtr m_pCamera; + std::vector m_tables; + +public: + //ctor + LookUpTableCollection( CameraPtr pCamera ); + + // test for Lookup table support + static bool HasLookUpTable( CameraPtr pCamera); + + //Get count + VmbInt64_t GetCount( ); + + // Get control + LookUpTableControl GetControl( VmbInt64_t nIndex ); + + //Get active index + VmbInt64_t GetActiveIndex( ); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/VimbaFeatures.h b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/VimbaFeatures.h new file mode 100644 index 0000000..10f3d05 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/VimbaFeatures.h @@ -0,0 +1,849 @@ +#ifndef AVT_VIMBA_FEATURES_H_ +#define AVT_VIMBA_FEATURES_H_ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: VimbaFeatures.h + + Description: Helper for features. + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include + +#include "Exception.h" +#include "VimbaCPP/Include/VimbaCPP.h" + +namespace AVT{ +namespace VmbAPI{ +namespace Examples{ + + using AVT::VmbAPI::StringVector; + // + // basic feature. + // + class VimbaFeature + { + FeaturePtr m_Feature; + public: + + // + // Method: VimbaFeature + // + // Purpose: constructor from feature pointer. + // + // Parameters: + // + // [in] feature feature to wrap + // + VimbaFeature(const FeaturePtr &feature) + : m_Feature( feature ) + { } + // + // Method: VimbaFeature + // + // Purpose: constructor from camera and feature name. + // + // Parameters: + // + // [in] cam camera to get feature from + // [in] name name of the feature + // + VimbaFeature(const CameraPtr &cam, const std::string &name) + { + if( cam.get() == NULL ) + { + throw Exception( __FUNCTION__,"camera pointer is null",VmbErrorBadParameter); + } + VmbErrorType Result = cam->GetFeatureByName( name.c_str() , m_Feature); + if( VmbErrorSuccess != Result) + { + throw Exception( __FUNCTION__,std::string("could not get vimba feature :")+name, Result); + } + } + // + // Method: GetType + // + // Purpose: get feature data type. + // + VmbFeatureDataType GetType() const + { + VmbFeatureDataType DataType; + VmbErrorType Result = m_Feature->GetDataType( DataType); + if( VmbErrorSuccess != Result) + { + throw Exception( __FUNCTION__, "could not get feature data type", Result); + } + return DataType; + } + // + // Method: HasFeature + // + // Purpose: static test if a feature is implemented. + // + // Parameters: + // + // [in] cam camera to ask + // param[in] name feature name + // + static VmbBool_t HasFeature( const CameraPtr &cam, const std::string &name) + { + if( cam.get() == NULL ) + { + throw Exception( __FUNCTION__,"camera pointer is null",VmbErrorBadParameter); + } + FeaturePtr dummy; + VmbErrorType Result = cam->GetFeatureByName(name.c_str(), dummy); + if( VmbErrorSuccess != Result) + { + if( VmbErrorNotFound == Result) + { + return VmbBoolFalse; + } + throw Exception(__FUNCTION__,"could not get feature",Result); + } + return VmbBoolTrue; + } + // + // Method: operator() const + // + // Purpose : get the const feature pointer. + // + const FeaturePtr& operator()() const { return m_Feature; } + // + // Method: operator() + // + // Purpose:get the feature pointer. + // + FeaturePtr& operator()() { return m_Feature; } + }; + // + // integer feature + // + class VimbaFeatureInt + { + VimbaFeature m_Feature; + public: + // + // Method: VimbaFeatureInt + // + // Purpose: constructor from feature pointer. + // [in] feature feature pointer + // + VimbaFeatureInt(const FeaturePtr &feature) + : m_Feature( feature) + { + if( VmbFeatureDataInt != m_Feature.GetType() ) + { + throw Exception(__FUNCTION__,"wrong feature data type", VmbErrorWrongType); + } + } + // + // Method: VimbaFeatureInt + // + // Purpose: constructor from camera and feature name. + // + // Parameters: + // + // [in] cam camera to get feature from + // [in] name feature name + // + VimbaFeatureInt(const CameraPtr &cam, const std::string &name) + : m_Feature( cam, name) + { + if( VmbFeatureDataInt != m_Feature.GetType() ) + { + throw Exception(__FUNCTION__,"wrong feature data type", VmbErrorWrongType); + } + } + // + // Method: operator() const + // + // Purpose: get feature int value. + // + VmbInt64_t operator()() const + { + VmbInt64_t Value; + VmbErrorType Result = m_Feature()->GetValue( Value ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not get value for feature", Result); + } + return Value; + } + // + // Method: operator( VmbInt64_t) + // + // Purpose: set feature int value. + // + // Parameters: + // + // [in] Value value to set + // + void operator()( VmbInt64_t Value) + { + VmbErrorType Result = m_Feature()->SetValue( Value ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not set feature value", Result); + } + } + // + // Method: Min + // + // Purpose: get feature minimum value. + // + VmbInt64_t Min() const + { + VmbInt64_t MinValue,MaxValue; + VmbErrorType Result = m_Feature()->GetRange(MinValue,MaxValue); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not get integer feature range",Result); + } + return MinValue; + } + // + // Method: Max + // + // Purpose: get feature maximum value. + // + VmbInt64_t Max() const + { + VmbInt64_t MinValue,MaxValue; + VmbErrorType Result = m_Feature()->GetRange(MinValue,MaxValue); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not get integer feature range",Result); + } + return MaxValue; + } + // + // Method: Increment() + // + // Purpose: get the increment to advance an integer feature + // Value = Min() + n * Increment() <= Max() + // + VmbInt64_t Increment() const + { + VmbInt64_t IncValue; + VmbErrorType Result = m_Feature()->GetIncrement( IncValue ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not get integer feature increment",Result); + } + return IncValue; + } + }; + // + // Vimba bool feature. + // + class VimbaFeatureBool + { + VimbaFeature m_Feature; + public: + // + // Method: VimbaFeatureBool + // + // Purpose:constructor from feature pointer. + // + // Parameters: + // + // [in] feature feature pointer + // + VimbaFeatureBool(const FeaturePtr &feature) + : m_Feature( feature ) + { + if( VmbFeatureDataBool != m_Feature.GetType() ) + { + throw Exception(__FUNCTION__,"wrong feature data type", VmbErrorWrongType); + } + } + // + // Method: VimbaFeatureBool + // + // Purpose: constructor from camera and feature name. + // + // Parameters: + // + // [in] cam camera to get feature from + // [in] name name of the feature + // + VimbaFeatureBool(const CameraPtr &cam, const std::string &name) + : m_Feature( cam, name) + { + if( VmbFeatureDataBool != m_Feature.GetType() ) + { + throw Exception(__FUNCTION__,"wrong feature data type", VmbErrorWrongType); + } + } + // + // Method: operator() const + // + // Purpose: get feature bool value. + // + VmbBool_t operator()() const + { + VmbBool_t Value; + VmbErrorType Result = m_Feature()->GetValue( Value ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not get value for feature", Result); + } + return Value; + } + // + // Method: operator() + // + // Purpose: set feature bool value. + // + void operator()( VmbBool_t Value) + { + VmbErrorType Result = m_Feature()->SetValue( Value ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not set feature value", Result); + } + } + }; + // + // Vimba float feature + // + class VimbaFeatureFloat + { + VimbaFeature m_Feature; + public: + // + // Method: VimbaFeatureFloat + // + // Purpose:constructor from feature pointer. + // + // Parameters: + // + // [in] feature feature pointer + // + VimbaFeatureFloat(const FeaturePtr &feature) + : m_Feature( feature ) + { + if( VmbFeatureDataFloat != m_Feature.GetType() ) + { + throw Exception(__FUNCTION__,"wrong feature data type", VmbErrorWrongType); + } + } + // + // Method: VimbaFeatureFloat + // + // Purpose: constructor from camera and feature name. + // + // Parameters: + // + // [in] cam camera to get feature from + // [in] name name of the feature + // + VimbaFeatureFloat(const CameraPtr &cam, const std::string &name) + : m_Feature( cam, name) + { + if( VmbFeatureDataFloat != m_Feature.GetType() ) + { + throw Exception(__FUNCTION__,"wrong feature data type", VmbErrorWrongType); + } + } + // + // Method: operator() const + // + // Purpose: get feature float value. + // + double operator()() const + { + double Value; + VmbErrorType Result = m_Feature()->GetValue( Value ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not get value for feature", Result); + } + return Value; + } + // + // Method: operator() + // + // Purpose: set feature float value. + // + void operator()( double Value) + { + VmbErrorType Result = m_Feature()->SetValue( Value ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not set feature value", Result); + } + } + double Min() const + { + double MinValue, MaxValue; + VmbErrorType Result = m_Feature()->GetRange( MinValue, MaxValue ); + if( VmbErrorSuccess != Result) + { + throw Exception( __FUNCTION__,"could not get range for float feature", Result ); + } + return MinValue; + } + double Max() const + { + double MinValue, MaxValue; + VmbErrorType Result = m_Feature()->GetRange( MinValue, MaxValue ); + if( VmbErrorSuccess != Result) + { + throw Exception( __FUNCTION__,"could not get range for float feature", Result ); + } + return MaxValue; + } + }; + // + // feature enum. + // + class VimbaFeatureEnum + { + VimbaFeature m_Feature; + public: + // + // Method: VimbaFeatureEnum() + // + // Purpose: constructor from feature pointer. + // + // Parameters: + // + // [in] feature feature pointer + // + VimbaFeatureEnum(const FeaturePtr &feature) + : m_Feature( feature ) + { + if( VmbFeatureDataEnum != m_Feature.GetType() ) + { + throw Exception(__FUNCTION__,"wrong feature data type", VmbErrorWrongType); + } + } + // + // Method: VimbaFeatureEnum + // + // Purpose: constructor from camera and feature name. + // + // Parameters: + // + // [in] cam camera to get feature from + // [in] name feature name + // + VimbaFeatureEnum(const CameraPtr &cam, const std::string &name) + : m_Feature( cam, name ) + { + if( VmbFeatureDataEnum != m_Feature.GetType() ) + { + throw Exception(__FUNCTION__,"wrong feature data type", VmbErrorWrongType); + } + } + // + // Methods: GetValues + // + // Purpose:get all supported feature value strings. + // + AVT::VmbAPI::StringVector GetValues() const + { + StringVector Values; + VmbErrorType Result = m_Feature()->GetValues( Values ); + if( VmbErrorSuccess != Result) + { + throw Exception( __FUNCTION__,"could not get values",Result); + } + return Values; + } + // + // Method: GetEntries + // + // Purpose: get enum entries + // + EnumEntryVector GetEntries( ) const + { + EnumEntryVector Values; + VmbErrorType Result = m_Feature()->GetEntries( Values) ; + if( VmbErrorSuccess != Result) + { + throw Exception( __FUNCTION__, "could not get entry values for enum feature", Result); + } + return Values; + } + // + // Method: ValueCount + // + // Purpose: get number of supported feature values. + // + VmbInt64_t ValueCount() const + { + return static_cast< VmbInt64_t>( GetValues().size() ); + } + // + // Method: IsAvailable + // + // Purpose: test if string value is currently available. + // + // Parameters: + // + // [in] Value string value to test + // + VmbBool_t IsAvailable( const std::string &Value) + { + VmbBool_t Available; + VmbErrorType Result = m_Feature()->IsValueAvailable( Value.c_str(), Available ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not read enums available flag",Result); + } + return Available; + } + // + // Method: IsAvailable + // + // Purpose: test if integer feature value is available. + // + // Parameters: + // + // [in] Value integer feature value to test + // + VmbBool_t IsAvailable( VmbInt64_t Value) + { + VmbBool_t Available; + VmbErrorType Result = m_Feature()->IsValueAvailable( Value, Available ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not read enums available flag",Result); + } + return Available; + } + // + // Method: GetStringValue + // + // Purpose:get current feature value as string. + // + std::string GetStringValue() const + { + std::string Value; + VmbErrorType Result = m_Feature()->GetValue( Value ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not get string value", Result); + } + return Value; + } + // + // Method: SetStringValue + // + // Purpose: set new feature value from string. + // + // Parameters: + // + // [in] Value string value to set + // + void SetStringValue( const std::string &Value) + { + VmbErrorType Result = m_Feature()->SetValue( Value.c_str() ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not set string value",Result); + } + } + // + // Method: GetEntry + // + // Purpose: get current enum value as EnumEntry + // + EnumEntry GetEntry() const + { + EnumEntry Value; + VmbErrorType Result = m_Feature()->GetEntry( Value, GetStringValue().c_str() ); + if( VmbErrorSuccess != Result ) + { + throw Exception( __FUNCTION__,"could not get enum feature entry", Result); + } + return Value; + } + // + // Method: operator() const + // + // Purpose: get current integer value. + // + VmbInt64_t operator()() const + { + VmbInt64_t Value; + VmbErrorType Result = m_Feature()->GetValue( Value ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not get value for feature", Result); + } + return Value; + } + // + // Method: operator() + // + // Purpose: set new integer value. + // + // Parameters: + // + // [in] Value new value to set + // + void operator()( VmbInt64_t Value) + { + VmbErrorType Result = m_Feature()->SetValue( Value ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not set feature value", Result); + } + } + }; + + // + // Vimba string feature + class VimbaFeatureString + { + VimbaFeature m_Feature; + public: + VimbaFeatureString( const FeaturePtr & feature) + : m_Feature( feature ) + { + if( VmbFeatureDataString != m_Feature.GetType() ) + { + throw Exception( __FUNCTION__,"wrong feature data type", VmbErrorWrongType ); + } + } + VimbaFeatureString( const CameraPtr & cam, const std::string &name) + :m_Feature( cam, name ) + { + if( VmbFeatureDataString != m_Feature.GetType() ) + { + throw Exception( __FUNCTION__,"wrong feature data type", VmbErrorWrongType ); + } + } + std::string operator()() const + { + std::string Value; + VmbErrorType Result = m_Feature()->GetValue( Value ); + if( VmbErrorSuccess != Result ) + { + throw Exception( __FUNCTION__,"could not get value for string feature", Result); + } + return Value; + } + void operator()( const std::string & value) + { + VmbErrorType Result = m_Feature()->SetValue( value.c_str() ); + if( VmbErrorSuccess != Result) + { + throw Exception( __FUNCTION__,"could not set string feature value" , Result ); + } + } + }; + // + // feature command + // + class VimbaFeatureCommand + { + VimbaFeature m_Feature; + public: + // + // Method: VimbaFeatureCommand + // + // Purpose: constructor from feature pointer. + // + // Parameters: + // + // [in] feature feature pointer to use + // + VimbaFeatureCommand( const FeaturePtr &feature) + :m_Feature( feature ) + { + if( VmbFeatureDataCommand != m_Feature.GetType() ) + { + throw Exception(__FUNCTION__,"wrong feature data type", VmbErrorWrongType); + } + } + // + // Method: VimbaFeatureCommand + // + // Purpose: constructor from camera and feature name. + // + // Parameters: + // + // [in] cam camera to get feature from + // [in] name name of the feature + // + VimbaFeatureCommand( const CameraPtr &cam, const std::string &name) + :m_Feature( cam, name) + { + if( VmbFeatureDataCommand != m_Feature.GetType() ) + { + throw Exception(__FUNCTION__,"wrong feature data type", VmbErrorWrongType); + } + } + // + // Method: Run + // + // Purpose: run command. + // + void Run() + { + VmbErrorType Result = m_Feature()->RunCommand(); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not run feature command",Result); + } + } + // + // Method: IsDone + // + // Purpose:test if command has finished. + // + VmbBool_t IsDone() const + { + VmbBool_t Value; + VmbErrorType Result = m_Feature()->IsCommandDone( Value); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not get is done state of feature command",Result); + } + return Value; + } + }; + // + // raw buffer feature. + // + class VimbaFeatureRaw + { + VimbaFeature m_Feature; + public: + // + // Method: VimbaFeatureRaw + // + // Purpose: constructor from feature pointer. + // + // Parameters: + // + // [in] feature feature pointer to use + // + VimbaFeatureRaw( const FeaturePtr &feature) + :m_Feature( feature ) + { + if( VmbFeatureDataRaw != m_Feature.GetType() ) + { + throw Exception(__FUNCTION__,"wrong feature data type", VmbErrorWrongType); + } + } + // + // Method: VimbaFeatureRaw + // + // Purpose: constructor from camera and feature name. + // + // Parameters: + // + // [in] cam camera to get feature from + // [in] name feature name + // + VimbaFeatureRaw( const CameraPtr &cam, const std::string &name) + :m_Feature( cam, name) + { + if( VmbFeatureDataRaw != m_Feature.GetType() ) + { + throw Exception(__FUNCTION__,"wrong feature data type", VmbErrorWrongType); + } + } + // + // Method: GetBuffer + // + // Purpose: get raw buffer, reuses supplied data vector . + // + // Parameters: + // + // [out] data returns read data + // + void GetBuffer( UcharVector &data) const + { + VmbErrorType Result = m_Feature()->GetValue( data ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not read raw data feature",Result); + } + } + // + // Method: operator() const + // + // Purpose: get raw data buffer. + // + UcharVector operator()() const + { + UcharVector Data; + VmbErrorType Result = m_Feature()->GetValue( Data ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not read raw data feature",Result); + } + return Data; + } + // + // Method: operator( UcharVector ) + // + // Purpose: set raw data buffer. + // + // Parameters: + // + // [in] data data to set + // + void operator()( const UcharVector & Data) + { + VmbErrorType Result =m_Feature()->SetValue( Data ); + if( VmbErrorSuccess != Result) + { + throw Exception(__FUNCTION__,"could not set raw feature data",Result); + } + } + }; + // + // Method: CreateOneOf + // + // Purpose: create a feature from two possible names. + // Parameters: + // + // [in] cam camera to get feature from + // [in] name_one first name to try + // [in] name_two second name to try + // + template + FEATURE_TYPE CreateOneOf(const CameraPtr &cam, const std::string& name_one, const std::string &name_two) + { + FeaturePtr feature; + VmbErrorType Result = cam->GetFeatureByName( name_one.c_str(), feature); + if( VmbErrorSuccess != Result) + { + if( VmbErrorNotFound == Result) + { + return FEATURE_TYPE( cam, name_two); + } + throw Exception(__FUNCTION__,"could not generate feature",Result); + } + return FEATURE_TYPE(feature); + } +}}} +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/program.cpp b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/program.cpp new file mode 100644 index 0000000..1acd14a --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/LookUpTable/Source/program.cpp @@ -0,0 +1,639 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: Main entry point of LookUpTable example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#include "LookUpTable.h" +#include "Exception.h" + +#include "Common/StreamSystemInfo.h" + +using namespace std; + +enum Mode +{ + ModeUnknown = 0, + ModeSave = 1, + ModeLoad = 2, + ModeSaveCSV = 3, + ModeLoadCSV = 4, + ModeEnable = 7, + ModeIsEnabled = 8, + ModeSetValue = 9, + ModeGetValue = 10, + ModeBitIn = 11, + ModeBitOut = 12, + ModeCount = 13 +}; + +bool StartsWith( const char *pString, const char *pStart ) +{ + if( NULL == pString ) + { + return false; + } + if( NULL == pStart ) + { + return false; + } + + if( std::strlen( pString ) < std::strlen( pStart ) ) + { + return false; + } + + if( std::memcmp( pString, pStart, std::strlen( pStart ) ) != 0 ) + { + return false; + } + + return true; +} + +int main( int argc, char* argv[] ) +{ + cout << "///////////////////////////////////////\n"; + cout << "/// Vimba API Look Up Table Example ///\n"; + cout << "///////////////////////////////////////\n\n"; + + VmbErrorType err = VmbErrorSuccess; + + string cameraID; + string fileName; + string controlIndex; + bool bValue = false; + VmbInt64_t nValue = 0; + string parameter; + Mode eMode = ModeUnknown; + bool printHelp = false; + + ////////////////////// + //Parse command line// + ////////////////////// + + for( int i = 1; i < argc; i++ ) + { + char *pParameter = argv[i]; + if( std::strlen( pParameter ) < 0 ) + { + err = VmbErrorBadParameter; + break; + } + + if( pParameter[0] == '/' ) + { + if( std::strcmp( pParameter, "/s" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeSave; + } + else if( std::strcmp( pParameter, "/l" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeLoad; + } + else if( std::strcmp( pParameter, "/sc" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeSaveCSV; + } + else if( StartsWith( pParameter, "/lc:" ) ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + if( parameter.empty() == false ) + { + err = VmbErrorBadParameter; + break; + } + + parameter = pParameter + 4; + if( parameter.size() <= 0 ) + { + err = VmbErrorBadParameter; + break; + } + + nValue = atoi( parameter.c_str() ); + + eMode = ModeLoadCSV; + } + else if( StartsWith( pParameter, "/lc" ) ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + if( parameter.empty() == false ) + { + err = VmbErrorBadParameter; + break; + } + + nValue = 0; + eMode = ModeLoadCSV; + } + else if( std::strcmp( pParameter, "/bi" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeBitIn; + } + else if( std::strcmp( pParameter, "/bo" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeBitOut; + } + else if( std::strcmp( pParameter, "/n" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeCount; + } + else if( StartsWith( pParameter, "/e:" ) ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + if( parameter.empty() == false ) + { + err = VmbErrorBadParameter; + break; + } + + parameter = pParameter + 3; + if( parameter.size() <= 0 ) + { + err = VmbErrorBadParameter; + break; + } + + if( std::strcmp( parameter.c_str(), "on" ) == 0 ) + { + bValue = true; + } + else if( std::strcmp( parameter.c_str(), "off" ) == 0 ) + { + bValue = false; + } + else + { + cout << "Could not set look up table enable. Wrong parameter!\n"; + err = VmbErrorBadParameter; + break; + } + eMode = ModeEnable; + } + else if( std::strcmp( pParameter, "/e" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeIsEnabled; + } + else if( StartsWith( pParameter, "/v:" ) ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + if( parameter.empty() == false ) + { + err = VmbErrorBadParameter; + break; + } + + parameter = pParameter + 3; + if( parameter.size() <= 0 ) + { + err = VmbErrorBadParameter; + break; + } + + nValue = atoi( parameter.c_str() ); + + eMode = ModeSetValue; + } + else if( std::strcmp( pParameter, "/v" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeGetValue; + } + else if( StartsWith( pParameter, "/f:" ) ) + { + if( (ModeUnknown != eMode) && + (ModeSaveCSV != eMode) && + (ModeLoadCSV != eMode) ) + { + err = VmbErrorBadParameter; + break; + } + + if( fileName.empty() == false ) + { + err = VmbErrorBadParameter; + break; + } + + fileName = pParameter + 3; + if( fileName.size() <= 0 ) + { + err = VmbErrorBadParameter; + break; + } + } + else if( StartsWith( pParameter, "/i:" ) ) + { + if( controlIndex.empty() == false ) + { + err = VmbErrorBadParameter; + break; + } + + controlIndex = pParameter + 3; + if( controlIndex.size() <= 0 ) + { + err = VmbErrorBadParameter; + break; + } + } + else if( std::strcmp( pParameter, "/h" ) == 0 ) + { + if( (cameraID.empty() == false) + || (ModeUnknown != eMode) + || (true == printHelp)) + { + err = VmbErrorBadParameter; + break; + } + + printHelp = true; + } + else + { + err = VmbErrorBadParameter; + break; + } + } + else + { + if( cameraID.empty() == false ) + { + err = VmbErrorBadParameter; + break; + } + + cameraID = pParameter; + } + } + + //Write out an error if we could not parse the command line + if( VmbErrorBadParameter == err ) + { + cout << "Invalid parameters!\n\n"; + printHelp = true; + } + + //Print out help and end program + if( true == printHelp ) + { + cout << "Usage: LookUpTable [CameraID] [/i:Index] [/h] [/{s|l|sc|lc:Column|u|d|v(:Value)|e(:Enable)|bi|bo|n}] [/f:FileName]\n"; + cout << "Parameters: CameraID ID of the camera to use\n"; + cout << " (using first camera if not specified)\n"; + cout << " /i:Index Set look up table index\n"; + cout << " /h Print out help\n"; + cout << " /s Save look up table to flash\n"; + cout << " /l Load look up table from flash\n"; + cout << " /sc Save look up table to Csv\n"; + cout << " (Look up table previously downloaded)\n"; + cout << " /lc:Column Load look up table from Csv using specified column\n"; + cout << " (default if not specified)\n"; + cout << " /e:Enable Set look up table enable [on/off]\n"; + cout << " /e Get look up table enable\n"; + cout << " (default if not specified)\n"; + cout << " /v:Value Set look up table value\n"; + cout << " /v Get look up table value\n"; + cout << " /bi Get look up table bit depth in\n"; + cout << " /bo Get look up table bit depth out\n"; + cout << " /n Get look up table count\n"; + cout << " /f:FileName File name for operation\n\n"; + cout << "For example to load a look up table from the csv file C:\\lut.csv and\n" + << "write it to the camera's flash as LUT1 call\n\n"; + cout << "LookUpTable /i:0 /lc:0 /f:\"C:\\lut.csv\"\n\n"; + cout << "To load the look up table LUT2 from the camera and write it\n" + << "to the csv file C:\\lut.csv call\n\n"; + cout << "LookUpTable /i:1 /sc /f:\"C:\\lut.csv\"\n\n"; + + return err; + } + + bool bVimbaStarted = false; + AVT::VmbAPI::CameraPtr pCamera; + AVT::VmbAPI::VimbaSystem& vimbaSystem = AVT::VmbAPI::VimbaSystem::GetInstance(); + + try + { + // Print out version of Vimba + std::cout<<"Vimba C++ API Version "< 0 ) + { + for( AVT::VmbAPI::CameraPtrVector::const_iterator iter = cameras.begin(); + cameras.end() != iter; + ++iter ) + { + //Check if we can open the camera in full mode + VmbAccessModeType eAccessMode = VmbAccessModeNone; + err = (*iter)->GetPermittedAccess( eAccessMode ); + if( VmbErrorSuccess == err ) + { + if( (VmbAccessModeFull == (VmbAccessModeFull & eAccessMode)) || + ((cameras.end() - 1) == iter) ) + { + //Now get the camera ID + err = ( *iter )->GetID( cameraID ); + if( VmbErrorSuccess == err ) + { + //Try to open the camera + err = ( *iter )->Open( VmbAccessModeFull ); + if( VmbErrorSuccess == err ) + { + pCamera = *iter; + break; + } + } + } + } + } + + if( VmbErrorSuccess != err ) + { + err = VmbErrorNotFound; + throw AVT::VmbAPI::Examples::Exception( "Could not open any camera.", err ); + } + } + else + { + err = VmbErrorNotFound; + throw AVT::VmbAPI::Examples::Exception( "Could not open any camera.", err ); + } + } + else + { + throw AVT::VmbAPI::Examples::Exception( "Could not list cameras.", err ); + } + } + else + { + //Open specific camera + err = vimbaSystem.OpenCameraByID( cameraID.c_str(), VmbAccessModeFull, pCamera ); + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not open camera.", err ); + } + } + } + + if( VmbErrorSuccess == err ) + { + cout << "Camera ID: " << cameraID << "\n\n"; + if( VmbBoolTrue == AVT::VmbAPI::Examples::LookUpTableCollection::HasLookUpTable( pCamera) ) + { + + AVT::VmbAPI::Examples::LookUpTableCollection collection( pCamera ); + + + VmbInt64_t nIndex; + + if( controlIndex.empty() == false ) + { + nIndex = atoi( controlIndex.c_str() ); + } + else + { + nIndex = collection.GetActiveIndex( ); + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not get active index of look up table collection.", err ); + } + } + + AVT::VmbAPI::Examples::LookUpTableControl control( pCamera, nIndex ); + control = collection.GetControl( nIndex ); + + if( VmbErrorSuccess == err ) + { + switch( eMode ) + { + default: + case ModeIsEnabled: + { + //Is look up table enabled + cout << "Get look up table enable was successful. Enable = " << control.IsEnabled( ) <<"\n"; + } + break; + + case ModeLoad: + { + //Load look up table from flash + control.LoadFromFlash(); + cout << "Look up table successfully loaded from flash.\n"; + } + break; + + case ModeSave: + { + //Save look up table to flash + control.SaveToFlash(); + cout << "Look up table successfully saved to flash.\n"; + } + break; + + case ModeSaveCSV: + { + //Download LUT + control.Download(); + //Save look up table to file + control.SaveToCsv( fileName.c_str() ); + cout << "Look up table successfully saved to CSV.\n"; + } + break; + + case ModeLoadCSV: + { + //Load look up table from file + control.LoadFromCsv( fileName, (int)nValue ); + control.Upload(); + cout << "Look up table successfully loaded from CSV.\n"; + } + break; + + case ModeEnable: + { + //Set look up table enable + control.Enable( bValue ); + cout << "Look up table was enabled successfully.\n"; + } + break; + + case ModeBitIn: + { + //Get bit depth in of look up table + cout << "Get look up table 'bit depth in' was successful. BitDepthIn = " << control.GetBitDepthIn( ) <<"\n"; + } + break; + + case ModeBitOut: + { + //Get bit depth out of look up table + cout << "Get look up table 'bit depth out' was successful. BitDepthOut = " << control.GetBitDepthOut( ) <<"\n"; + } + break; + + case ModeSetValue: + { + //Set look up table value + control.SetValue( nValue ); + cout << "Look up table value was set successfully." <<"\n"; + } + break; + + case ModeGetValue: + { + //Get look up table value + cout << "Get look up table value was successful. Value = " << control.GetValue() <<"\n"; + } + break; + + case ModeCount: + { + //Get look up table count + cout << "Get look up table count was successful. Count = " << collection.GetCount( ) <<"\n"; + } + break; + + } + } + } + else + { + cout<<"Camera does not support LookUp Table Feature\n"; + } + } + } + + catch( AVT::VmbAPI::Examples::Exception& ex ) + { + cout << ex.GetMessageStr() << " VimbaException: " << ex.GetError() << " = " << ex.ErrorCodeToMessage( ex.GetError() ) <<"\n"; + } + + //Close camera + if( NULL != pCamera ) + { + pCamera->Close(); + } + + //Shutdown API + if( true == bVimbaStarted ) + { + vimbaSystem.Shutdown(); + } + + return err; +} \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Build/Make/Makefile new file mode 100644 index 0000000..6b695a3 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Build/Make/Makefile @@ -0,0 +1,51 @@ +PROJECT_NAME = SynchronousGrabConsole + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/../.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBACPP_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ApiController.o \ + $(OBJ_DIR)/Bitmap.o \ + $(OBJ_DIR)/program.o + +DEPENDENCIES = VimbaCPP + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Source/ApiController.cpp b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Source/ApiController.cpp new file mode 100644 index 0000000..743603f --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Source/ApiController.cpp @@ -0,0 +1,181 @@ +/*============================================================================= + Copyright (C) 2013 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ApiController.cpp + + Description: Implementation file for the ApiController helper class that + demonstrates how to implement a synchronous single image + acquisition with VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include + +#include "ApiController.h" +#include "Common/StreamSystemInfo.h" +#include "Common/ErrorCodeToMessage.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +enum { NUM_FRAMES = 3, }; + +ApiController::ApiController() + // Get a reference to the Vimba singleton + : m_system ( VimbaSystem::GetInstance() ) +{ +} + +ApiController::~ApiController() +{ +} + +// +// Starts the Vimba API and loads all transport layers +// +// Returns: +// An API status code +// +VmbErrorType ApiController::StartUp() +{ + return m_system.Startup(); +} + +// +// Shuts down the API +// +void ApiController::ShutDown() +{ + // Release Vimba + m_system.Shutdown(); +} + +// +// Opens the given camera +// Sets the maximum possible Ethernet packet size +// Adjusts the image format +// Calls the API convenience function to start single image acquisition +// Closes the camera in case of failure +// +// Parameters: +// [in] rStrCameraID The ID of the camera to work on +// [out] rpFrame The frame that will be filled. Does not need to be initialized. +// +// Returns: +// An API status code +// +VmbErrorType ApiController::AcquireSingleImage( const std::string &rStrCameraID, FramePtr &rpFrame ) +{ + // Open the desired camera by its ID + VmbErrorType res = m_system.OpenCameraByID( rStrCameraID.c_str(), VmbAccessModeFull, m_pCamera ); + if ( VmbErrorSuccess == res ) + { + // Set the GeV packet size to the highest possible value + // (In this example we do not test whether this cam actually is a GigE cam) + FeaturePtr pCommandFeature; + if ( VmbErrorSuccess == m_pCamera->GetFeatureByName( "GVSPAdjustPacketSize", pCommandFeature )) + { + if ( VmbErrorSuccess == pCommandFeature->RunCommand() ) + { + bool bIsCommandDone = false; + do + { + if ( VmbErrorSuccess != pCommandFeature->IsCommandDone( bIsCommandDone )) + { + break; + } + } while ( false == bIsCommandDone ); + } + } + FeaturePtr pFormatFeature; + // Set pixel format. For the sake of simplicity we only support Mono and BGR in this example. + res = m_pCamera->GetFeatureByName( "PixelFormat", pFormatFeature ); + if ( VmbErrorSuccess == res ) + { + // Try to set BGR + res = pFormatFeature->SetValue( VmbPixelFormatRgb8 ); + if ( VmbErrorSuccess != res ) + { + // Fall back to Mono + res = pFormatFeature->SetValue( VmbPixelFormatMono8 ); + } + + if ( VmbErrorSuccess == res ) + { + // Acquire + res = m_pCamera->AcquireSingleImage( rpFrame, 5000 ); + } + } + + m_pCamera->Close(); + } + + return res; +} + +// +// Gets all cameras known to Vimba +// +// Returns: +// A vector of camera shared pointers +// +CameraPtrVector ApiController::GetCameraList() +{ + CameraPtrVector cameras; + // Get all known cameras + if ( VmbErrorSuccess == m_system.GetCameras( cameras )) + { + // And return them + return cameras; + } + return CameraPtrVector(); +} + +// +// Translates Vimba error codes to readable error messages +// +// Parameters: +// [in] eErr The error code to be converted to string +// +// Returns: +// A descriptive string representation of the error code +// +std::string ApiController::ErrorCodeToMessage( VmbErrorType eErr ) const +{ + return AVT::VmbAPI::Examples::ErrorCodeToMessage( eErr ); +} + +// +// Gets the version of the Vimba API +// +// Returns: +// The version as string +// +std::string ApiController::GetVersion() const +{ + std::ostringstream os; + os< + +#include "VimbaCPP/Include/VimbaCPP.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class ApiController +{ + public: + ApiController(); + ~ApiController(); + + // + // Starts the Vimba API and loads all transport layers + // + // Returns: + // An API status code + // + VmbErrorType StartUp(); + + // + // Shuts down the API + // + void ShutDown(); + + // + // Opens the given camera + // Sets the maximum possible Ethernet packet size + // Adjusts the image format + // Calls the API convenience function to start single image acquisition + // Closes the camera in case of failure + // + // Parameters: + // [in] rStrCameraID The ID of the camera to work on + // [out] rpFrame The frame that will be filled. Does not need to be initialized. + // + // Returns: + // An API status code + // + VmbErrorType AcquireSingleImage( const std::string &rStrCameraID, FramePtr &rpFrame ); + + // + // Gets all cameras known to Vimba + // + // Returns: + // A vector of camera shared pointers + // + CameraPtrVector GetCameraList(); + + // + // Translates Vimba error codes to readable error messages + // + // Parameters: + // [in] eErr The error code to be converted to string + // + // Returns: + // A descriptive string representation of the error code + // + std::string ErrorCodeToMessage( VmbErrorType eErr ) const; + + // + // Gets the version of the Vimba API + // + // Returns: + // The version as string + // + std::string GetVersion() const; + + private: + // A reference to our Vimba singleton + VimbaSystem &m_system; + // The currently streaming camera + CameraPtr m_pCamera; +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Source/Bitmap.cpp b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Source/Bitmap.cpp new file mode 100644 index 0000000..5ae3d53 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Source/Bitmap.cpp @@ -0,0 +1,267 @@ +/*============================================================================= + Copyright (C) 2013 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: Bitmap.cpp + + Description: The bitmap class represents a MS(R) Windows(TM) bitmap version 3 + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#include "Bitmap.h" + +enum { THREE_CHANNEL = 0xC,}; +enum { BMP_HEADER_SIZE = 54, }; +enum { ALIGNMENT_SIZE = 4, }; + +// +// Creates a MS Windows bitmap with header and color palette. +// Fills it with the content of the given byte buffer +// +// Parameters: +// [out] pBitmap A pointer to an AVTBitmap that will get filled +// [in] pBuffer The buffer that will be used to fill the created bitmap +// +// Returns: +// 0 in case of error +// 1 in case of success +// +unsigned char AVTCreateBitmap( AVTBitmap * const pBitmap, const void* pBuffer ) +{ + unsigned char nNumColors; // Number of colors of our image + unsigned char nPadLength; // The padding we need to align the bitmap ALIGNMENT_SIZE + unsigned long nPaletteSize = 0; // The size of the bitmap's palette + unsigned long nHeaderSize; // The size of the bitmap's header + unsigned long nFileSize; // The size of the bitmap file + unsigned char* pBitmapBuffer; // A buffer we use for creating the bitmap + unsigned char* pCurBitmapBuf; // A cursor to move over "pBitmapBuffer" + unsigned char* pCurSrc; // A cursor to move over the given buffer "pBuffer" + unsigned long px; // A single pixel for storing transformed color information + unsigned long x; // The horizontal position within our image + unsigned long y; // The vertical position within our image + unsigned long i; // Counter for some iteration + + // The bitmap header + char fileHeader[14] = { 'B','M', // Default + 0,0,0,0, // File size + 0,0,0,0, // Reserved + 0,0,0,0 }; // Offset to image content + char infoHeader[40] = { 40,0,0,0, // Size of info header + 0,0,0,0, // Width + 0,0,0,0, // Height + 1,0, // Default + 0, 0 }; // bpp + + if ( NULL == pBitmap + || 0 == pBitmap->bufferSize + || 0 == pBitmap->width + || 0 == pBitmap->height ) + { + return 0; + } + + if ( pBitmap->colorCode == (pBitmap->colorCode & THREE_CHANNEL) ) + { + nNumColors = 3; + } + else + { + nNumColors = 1; + } + + // Bitmap padding always is a multiple of four Bytes. If data is not we need to pad with zeros. + nPadLength = (pBitmap->width * nNumColors) % ALIGNMENT_SIZE; + if ( 0 != nPadLength ) + { + nPadLength = ALIGNMENT_SIZE - nPadLength; + } + + if ( ColorCodeRGB24 != pBitmap->colorCode ) + { + nPaletteSize = 256; + } + + nHeaderSize = BMP_HEADER_SIZE + nPaletteSize * 4; + pBitmapBuffer = (unsigned char*)malloc( nHeaderSize + pBitmap->bufferSize + (nPadLength * pBitmap->height) ); + nFileSize = nHeaderSize + pBitmap->bufferSize + (nPadLength * pBitmap->height); + + // File size + fileHeader[ 2] = (char)(nFileSize); + fileHeader[ 3] = (char)(nFileSize >> 8); + fileHeader[ 4] = (char)(nFileSize >> 16); + fileHeader[ 5] = (char)(nFileSize >> 24); + // Offset to image content + fileHeader[10] = (char)(nHeaderSize); + fileHeader[11] = (char)(nHeaderSize >> 8); + fileHeader[12] = (char)(nHeaderSize >> 16); + fileHeader[13] = (char)(nHeaderSize >> 24); + + // Width + infoHeader[ 4] = (char)(pBitmap->width); + infoHeader[ 5] = (char)(pBitmap->width >> 8); + infoHeader[ 6] = (char)(pBitmap->width >> 16); + infoHeader[ 7] = (char)(pBitmap->width >> 24); + // Height (has to be negative for a top down image) + infoHeader[ 8] = (char)(-(long)pBitmap->height); + infoHeader[ 9] = (char)(-(long)pBitmap->height >> 8); + infoHeader[10] = (char)(-(long)pBitmap->height >> 16); + infoHeader[11] = (char)(-(long)pBitmap->height >> 24); + // bpp + infoHeader[14] = 8 * nNumColors; + // Image size + infoHeader[20] = (char)(pBitmap->bufferSize); + infoHeader[21] = (char)(pBitmap->bufferSize >> 8); + infoHeader[22] = (char)(pBitmap->bufferSize >> 16); + infoHeader[23] = (char)(pBitmap->bufferSize >> 24); + // Palette size + infoHeader[32] = (char)(nPaletteSize); + infoHeader[33] = (char)(nPaletteSize >> 8); + infoHeader[34] = (char)(nPaletteSize >> 16); + infoHeader[35] = (char)(nPaletteSize >> 24); + // Used colors + infoHeader[36] = (char)(nPaletteSize); + infoHeader[37] = (char)(nPaletteSize >> 8); + infoHeader[38] = (char)(nPaletteSize >> 16); + infoHeader[39] = (char)(nPaletteSize >> 24); + + // Write header + pCurBitmapBuf = pBitmapBuffer; + memcpy( pCurBitmapBuf, fileHeader, 14 ); + pCurBitmapBuf += 14; + memcpy( pCurBitmapBuf, infoHeader, 40 ); + pCurBitmapBuf += 40; + for(i = 0; i < nPaletteSize; ++i) + { + pCurBitmapBuf[0] = (char)(i); + pCurBitmapBuf[1] = (char)(i); + pCurBitmapBuf[2] = (char)(i); + pCurBitmapBuf[3] = 0; + pCurBitmapBuf += 4; + } + + // RGB -> BGR (a Windows bitmap is BGR) + if ( ColorCodeRGB24 == pBitmap->colorCode ) + { + pCurSrc = (unsigned char*)pBuffer; + for ( y=0; yheight; ++y, pCurBitmapBuf+=nPadLength ) + { + for ( x = 0; + x < pBitmap->width; + ++x, + pCurSrc += 3, + pCurBitmapBuf += 3 ) + { + px = 0; + // Create a 4 Byte structure to store ARGB (we don't use A) + px = px | (pCurSrc[0] << 16) | (pCurSrc[1] << 8) | pCurSrc[2]; + // Due to endianess ARGB is stored as BGRA + // and we only have to write the first three Bytes + memcpy( pCurBitmapBuf, &px, 3 ); + } + // Add padding at the end of each row + memset( pCurBitmapBuf, 0, nPadLength ); + } + pBitmap->colorCode = ColorCodeBGR24; + } + // Mono8 + else + { + if ( 0 == nPadLength ) + { + memcpy( pCurBitmapBuf, pBuffer, pBitmap->bufferSize ); + } + else + { + pCurSrc = (unsigned char*)pBuffer; + for ( y=0; + yheight; + ++y, + pCurSrc += pBitmap->width * nNumColors ) + { + // Write a single row of colored pixels + memcpy( pCurBitmapBuf, pCurSrc, pBitmap->width * nNumColors ); + pCurBitmapBuf += pBitmap->width * nNumColors; + // Write padding pixels + memset( pCurBitmapBuf, 0, nPadLength ); + pCurBitmapBuf += nPadLength; + } + } + } + + pBitmap->buffer = pBitmapBuffer; + pBitmap->bufferSize = nFileSize; + return 1; +} + +// +// Releases (frees) a given bitmap +// +// Parameters: +// [in, out] pBitmap The bitmap whose memory will be freed +// +// Returns: +// 0 in case of error +// 1 in case of success +// +unsigned char AVTReleaseBitmap( AVTBitmap * const pBitmap ) +{ + if ( NULL != pBitmap + && NULL != pBitmap->buffer + && 0 < pBitmap->bufferSize ) + { + free( pBitmap->buffer ); + pBitmap->buffer = NULL; + return 1; + } + + return 0; +} + +// +// Writes a given bitmap to file +// +// Parameters: +// [in] pBitmap The AVTBitmap to write to file +// [in] pFileName The destination (complete path) where to write the bitmap to +// +// Returns: +// 0 in case of error +// 1 in case of success +// +unsigned char AVTWriteBitmapToFile( AVTBitmap const * const pBitmap, char const * const pFileName ) +{ + FILE *file; + if ( NULL != pBitmap + && NULL != pBitmap->buffer + && NULL != pFileName ) + { + file = fopen(pFileName, "wb"); + fwrite(pBitmap->buffer, 1, pBitmap->bufferSize, file ); + fclose(file); + + return 1; + } + + return 0; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Source/Bitmap.h b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Source/Bitmap.h new file mode 100644 index 0000000..66019bd --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Source/Bitmap.h @@ -0,0 +1,87 @@ +/*============================================================================= + Copyright (C) 2013 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: Bitmap.h + + Description: The bitmap class represents a MS(R) Windows(TM) bitmap version 3 + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_BITMAP_H +#define AVT_BITMAP_H + +typedef enum +{ + ColorCodeMono8 = 1, + ColorCodeMono16 = 2, + ColorCodeBGR24 = 4, + ColorCodeRGB24 = 8 +} ColorCode; + +typedef struct +{ + void* buffer; + unsigned long bufferSize; + unsigned long width; + unsigned long height; + ColorCode colorCode; +} AVTBitmap; + +// +// Creates a MS Windows bitmap with header and color palette. +// Fills it with the content of the given byte buffer +// +// Parameters: +// [out] pBitmap A pointer to an AVTBitmap that will get filled +// [in] pBuffer The buffer that will be used to fill the created bitmap +// +// Returns: +// 0 in case of error +// 1 in case of success +// +unsigned char AVTCreateBitmap( AVTBitmap * const pBitmap, const void* pBuffer ); + +// +// Releases (frees) a given bitmap +// +// Parameters: +// [in, out] pBitmap The bitmap whose memory will be freed +// +// Returns: +// 0 in case of error +// 1 in case of success +// +unsigned char AVTReleaseBitmap( AVTBitmap * const pBitmap ); + +// +// Writes a given bitmap to file +// +// Parameters: +// [in] pBitmap The AVTBitmap to write to file +// [in] pFileName The destination (complete path) where to write the bitmap to +// +// Returns: +// 0 in case of error +// 1 in case of success +// +unsigned char AVTWriteBitmapToFile( AVTBitmap const * const pBitmap, char const * const pFileName ); + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Source/program.cpp b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Source/program.cpp new file mode 100644 index 0000000..829946a --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Console/Source/program.cpp @@ -0,0 +1,287 @@ +/*============================================================================= + Copyright (C) 2013 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: Implementation of main entry point of SynchronousGrabConsole + example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#include "ApiController.h" +#include "Bitmap.h" + +unsigned char StartsWith(const char *pString, const char *pStart) +{ + if(NULL == pString) + { + return 0; + } + if(NULL == pStart) + { + return 0; + } + + if(std::strlen(pString) < std::strlen(pStart)) + { + return 0; + } + + if(std::memcmp(pString, pStart, std::strlen(pStart)) != 0) + { + return 0; + } + + return 1; +} + +int main( int argc, char* argv[] ) +{ + VmbErrorType err = VmbErrorSuccess; + + char * pCameraID = NULL; // The ID of the camera to use + const char * pFileName = NULL; // The filename for the bitmap to save + bool bPrintHelp = false; // Output help? + int i; // Counter for some iteration + char * pParameter; // The command line parameter + + std::cout << "//////////////////////////////////////////\n"; + std::cout << "/// Vimba API Synchronous Grab Example ///\n"; + std::cout << "//////////////////////////////////////////\n\n"; + + ////////////////////// + //Parse command line// + ////////////////////// + + for( i = 1; i < argc; ++i ) + { + pParameter = argv[i]; + if( 0 > std::strlen( pParameter )) + { + err = VmbErrorBadParameter; + break; + } + + if( '/' == pParameter[0] ) + { + if( StartsWith( pParameter, "/f:" )) + { + if( NULL != pFileName ) + { + err = VmbErrorBadParameter; + break; + } + + pFileName = pParameter + 3; + if( 0 >= std::strlen( pFileName )) + { + err = VmbErrorBadParameter; + break; + } + } + else if( 0 == std::strcmp( pParameter, "/h" )) + { + if( ( NULL != pCameraID ) + || ( NULL != pFileName ) + || ( bPrintHelp )) + { + err = VmbErrorBadParameter; + break; + } + + bPrintHelp = true; + } + else + { + err = VmbErrorBadParameter; + break; + } + } + else + { + if( NULL != pCameraID ) + { + err = VmbErrorBadParameter; + break; + } + + pCameraID = pParameter; + } + } + + //Write out an error if we could not parse the command line + if ( VmbErrorBadParameter == err ) + { + std::cout << "Invalid parameters!\n\n"; + bPrintHelp = true; + } + + //Print out help and end program + if ( bPrintHelp ) + { + std::cout << "Usage: SynchronousGrab [CameraID] [/h] [/f:FileName]\n"; + std::cout << "Parameters: CameraID ID of the camera to use (using first camera if not specified)\n"; + std::cout << " /h Print out help\n"; + std::cout << " /f:FileName File name for operation\n"; + std::cout << " (default \"SynchronousGrab.bmp\" if not specified)\n"; + } + else + { + if ( NULL == pFileName ) + { + pFileName = "SynchronousGrab.bmp"; + } + + AVT::VmbAPI::Examples::ApiController apiController; + + std::cout << "Vimba C++ API Version " << apiController.GetVersion() << "\n"; + + VmbFrameStatusType status = VmbFrameStatusIncomplete; + err = apiController.StartUp(); + if ( VmbErrorSuccess == err ) + { + std::string strCameraID; + if ( NULL == pCameraID ) + { + AVT::VmbAPI::CameraPtrVector cameras = apiController.GetCameraList(); + if ( cameras.size() <= 0 ) + { + err = VmbErrorNotFound; + } + else + { + err = cameras[0]->GetID( strCameraID ); + } + } + else + { + strCameraID = pCameraID; + } + + if ( VmbErrorSuccess == err ) + { + std::cout << "Camera ID:" << strCameraID.c_str() << "\n\n"; + + AVT::VmbAPI::FramePtr pFrame; + err = apiController.AcquireSingleImage( strCameraID, pFrame ); + if ( VmbErrorSuccess == err ) + { + err = pFrame->GetReceiveStatus( status ); + if ( VmbErrorSuccess == err + && VmbFrameStatusComplete == status ) + { + VmbPixelFormatType ePixelFormat = VmbPixelFormatMono8; + err = pFrame->GetPixelFormat( ePixelFormat ); + if ( VmbErrorSuccess == err ) + { + if ( ( VmbPixelFormatMono8 != ePixelFormat ) + && ( VmbPixelFormatRgb8 != ePixelFormat )) + { + err = VmbErrorInvalidValue; + } + else + { + VmbUint32_t nImageSize = 0; + err = pFrame->GetImageSize( nImageSize ); + if ( VmbErrorSuccess == err ) + { + VmbUint32_t nWidth = 0; + err = pFrame->GetWidth( nWidth ); + if ( VmbErrorSuccess == err ) + { + VmbUint32_t nHeight = 0; + err = pFrame->GetHeight( nHeight ); + if ( VmbErrorSuccess == err ) + { + VmbUchar_t *pImage = NULL; + err = pFrame->GetImage( pImage ); + if ( VmbErrorSuccess == err ) + { + AVTBitmap bitmap; + + if ( VmbPixelFormatRgb8 == ePixelFormat ) + { + bitmap.colorCode = ColorCodeRGB24; + } + else + { + bitmap.colorCode = ColorCodeMono8; + } + + bitmap.bufferSize = nImageSize; + bitmap.width = nWidth; + bitmap.height = nHeight; + + // Create the bitmap + if ( 0 == AVTCreateBitmap( &bitmap, pImage )) + { + std::cout << "Could not create bitmap.\n"; + err = VmbErrorResources; + } + else + { + // Save the bitmap + if ( 0 == AVTWriteBitmapToFile( &bitmap, pFileName )) + { + std::cout << "Could not write bitmap to file.\n"; + err = VmbErrorOther; + } + else + { + std::cout << "Bitmap successfully written to file \"" << pFileName << "\"\n" ; + // Release the bitmap's buffer + if ( 0 == AVTReleaseBitmap( &bitmap )) + { + std::cout << "Could not release the bitmap.\n"; + err = VmbErrorInternalFault; + } + } + } + } + } + } + } + } + } + } + } + } + + apiController.ShutDown(); + } + + if ( VmbErrorSuccess != err ) + { + std::string strError = apiController.ErrorCodeToMessage( err ); + std::cout << "\nAn error occurred: " << strError.c_str() << "\n"; + } + if( VmbFrameStatusIncomplete == status) + { + std::cout<<"received frame was not complete\n"; + } + } + + return err; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Build/Make/Makefile new file mode 100644 index 0000000..c1f39a6 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Build/Make/Makefile @@ -0,0 +1,77 @@ +PROJECT_NAME = SynchronousGrabQt + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/../.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk +include $(MAKE_INCLUDE_DIR)/Qt.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + -I$(OBJ_DIR) + +LIBS = $(VIMBACPP_LIBS) \ + $(QTCORE_LIBS) \ + $(QTGUI_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) \ + $(QTCORE_CFLAGS) \ + $(QTGUI_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ApiController.o \ + $(OBJ_DIR)/SynchronousGrab.o \ + $(OBJ_DIR)/CameraObserver.o \ + $(OBJ_DIR)/main.o \ + $(OBJ_DIR)/moc_SynchronousGrab.o \ + $(OBJ_DIR)/moc_CameraObserver.o \ + $(OBJ_DIR)/qrc_SynchronousGrab.o + +GEN_HEADERS = $(OBJ_DIR)/ui_SynchronousGrab.h + +DEPENDENCIES = VimbaCPP \ + QtCore \ + QtGui + +$(OBJ_DIR)/moc_%.cpp: $(SOURCE_DIR)/%.h $(OBJ_DIR) + $(MOC) -o $@ $< + +$(OBJ_DIR)/ui_%.h: $(SOURCE_DIR)/res/%.ui $(OBJ_DIR) + $(UIC) -o $@ $< + +$(OBJ_DIR)/qrc_%.cpp: $(SOURCE_DIR)/res/%.qrc $(OBJ_DIR) + $(RCC) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) $(GEN_HEADERS) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(OBJ_DIR)/%.cpp $(OBJ_DIR) $(GEN_HEADERS) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/ApiController.cpp b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/ApiController.cpp new file mode 100644 index 0000000..7ca11b9 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/ApiController.cpp @@ -0,0 +1,256 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ApiController.cpp + + Description: Implementation file for the ApiController helper class that + demonstrates how to implement a synchronous single image + acquisition with VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include + +#include "ApiController.h" + +#include "Common/StreamSystemInfo.h" +#include "Common/ErrorCodeToMessage.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +enum { NUM_FRAMES = 3, }; + +ApiController::ApiController() + // Get a reference to the Vimba singleton + : m_system ( VimbaSystem::GetInstance() ) +{ +} + +ApiController::~ApiController() +{ +} + +// +// Translates Vimba error codes to readable error messages +// +// Parameters: +// [in] eErr The error code to be converted to string +// +// Returns: +// A descriptive string representation of the error code +// +std::string ApiController::ErrorCodeToMessage( VmbErrorType eErr ) const +{ + return AVT::VmbAPI::Examples::ErrorCodeToMessage( eErr ); +} + +// +// Starts the Vimba API and loads all transport layers +// +// Returns: +// An API status code +// +VmbErrorType ApiController::StartUp() +{ + VmbErrorType res; + + // Start Vimba + res = m_system.Startup(); + if ( VmbErrorSuccess == res ) + { + // This will be wrapped in a shared_ptr so we don't delete it + m_pCameraObserver = new CameraObserver(); + // Register an observer whose callback routine gets triggered whenever a camera is plugged in or out + res = m_system.RegisterCameraListObserver( ICameraListObserverPtr( m_pCameraObserver )); + } + + return res; +} + +// +// Shuts down the API +// +void ApiController::ShutDown() +{ + // Release Vimba + m_system.Shutdown(); +} + +// +// Opens the given camera +// Sets the maximum possible Ethernet packet size +// Adjusts the image format +// Calls the API convenience function to start single image acquisition +// Closes the camera in case of failure +// +// Parameters: +// [in] rStrCameraID The ID of the camera to work on +// [out] rpFrame The frame that will be filled. Does not need to be initialized. +// +// Returns: +// An API status code +// +VmbErrorType ApiController::AcquireSingleImage( const std::string &rStrCameraID, FramePtr &rpFrame ) +{ + // Open the desired camera by its ID + VmbErrorType res = m_system.OpenCameraByID( rStrCameraID.c_str(), VmbAccessModeFull, m_pCamera ); + if ( VmbErrorSuccess == res ) + { + // Set the GeV packet size to the highest possible value + // (In this example we do not test whether this cam actually is a GigE cam) + FeaturePtr pCommandFeature; + if ( VmbErrorSuccess == m_pCamera->GetFeatureByName( "GVSPAdjustPacketSize", pCommandFeature )) + { + if ( VmbErrorSuccess == pCommandFeature->RunCommand() ) + { + bool bIsCommandDone = false; + do + { + if ( VmbErrorSuccess != pCommandFeature->IsCommandDone( bIsCommandDone )) + { + break; + } + } while ( false == bIsCommandDone ); + } + } + FeaturePtr pFormatFeature; + // Save the current width + res = m_pCamera->GetFeatureByName( "Width", pFormatFeature ); + if ( VmbErrorSuccess == res ) + { + res = pFormatFeature->GetValue( m_nWidth ); + if ( VmbErrorSuccess == res ) + { + // Save the current height + res = m_pCamera->GetFeatureByName( "Height", pFormatFeature ); + if ( VmbErrorSuccess == res ) + { + pFormatFeature->GetValue( this->m_nHeight ); + if ( VmbErrorSuccess == res ) + { + // Set pixel format. For the sake of simplicity we only support Mono and RGB in this example. + res = m_pCamera->GetFeatureByName( "PixelFormat", pFormatFeature ); + if ( VmbErrorSuccess == res ) + { + // Try to set RGB + res = pFormatFeature->SetValue( VmbPixelFormatRgb8 ); + if ( VmbErrorSuccess != res ) + { + // Fall back to Mono + res = pFormatFeature->SetValue( VmbPixelFormatMono8 ); + } + + // Read back the currently selected pixel format + pFormatFeature->GetValue( m_nPixelFormat ); + + if ( VmbErrorSuccess == res ) + { + // Acquire + res = m_pCamera->AcquireSingleImage( rpFrame, 2000 ); + } + } + } + } + } + } + m_pCamera->Close(); + } + + return res; +} + +// +// Calls the API convenience function to stop image acquisition +// Closes the camera +// +// Returns: +// An API status code +// +CameraPtrVector ApiController::GetCameraList() const +{ + CameraPtrVector cameras; + // Get all known cameras + if ( VmbErrorSuccess == m_system.GetCameras( cameras )) + { + // And return them + return cameras; + } + return CameraPtrVector(); +} + +// +// Gets the width of a frame +// +// Returns: +// The width as integer +// +int ApiController::GetWidth() const +{ + return static_cast( m_nWidth ); +} + +// +// Gets the height of a frame +// +// Returns: +// The height as integer +// +int ApiController::GetHeight() const +{ + return static_cast( m_nHeight ); +} + +// +// Gets the pixel format of a frame +// +// Returns: +// The pixel format as enum +// +VmbPixelFormatType ApiController::GetPixelFormat() const +{ + return static_cast( m_nPixelFormat ); +} + +// +// Returns the frame observer as QObject pointer to connect their signals to the view's slots +// +QObject* ApiController::GetCameraObserver() +{ + return m_pCameraObserver; +} + +// +// Gets the version of the Vimba API +// +// Returns: +// The version as string +// +std::string ApiController::GetVersion() const +{ + std::ostringstream os; + os< + +#include "VimbaCPP/Include/VimbaCPP.h" + +#include "CameraObserver.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class ApiController +{ + public: + ApiController(); + ~ApiController(); + + // + // Starts the Vimba API and loads all transport layers + // + // Returns: + // An API status code + // + VmbErrorType StartUp(); + + // + // Shuts down the API + // + void ShutDown(); + + // + // Opens the given camera + // Sets the maximum possible Ethernet packet size + // Adjusts the image format + // Calls the API convenience function to start single image acquisition + // Closes the camera in case of failure + // + // Parameters: + // [in] rStrCameraID The ID of the camera to work on + // [out] rpFrame The frame that will be filled. Does not need to be initialized. + // + // Returns: + // An API status code + // + VmbErrorType AcquireSingleImage( const std::string &rStrCameraID, FramePtr &rpFrame ); + + // + // Gets the width of a frame + // + // Returns: + // The width as integer + // + int GetWidth() const; + + // + // Gets the height of a frame + // + // Returns: + // The height as integer + // + int GetHeight() const; + + // + // Gets the pixel format of a frame + // + // Returns: + // The pixel format as enum + // + VmbPixelFormatType GetPixelFormat() const; + + // + // Calls the API convenience function to stop image acquisition + // Closes the camera + // + // Returns: + // An API status code + // + CameraPtrVector GetCameraList() const; + + // + // Returns the frame observer as QObject pointer to connect their signals to the view's slots + // + QObject* GetCameraObserver(); + + // + // Translates Vimba error codes to readable error messages + // + // Parameters: + // [in] eErr The error code to be converted to string + // + // Returns: + // A descriptive string representation of the error code + // + std::string ErrorCodeToMessage( VmbErrorType eErr ) const; + + // + // Gets the version of the Vimba API + // + // Returns: + // The version as string + // + std::string GetVersion() const; + + private: + // A reference to our Vimba singleton + VimbaSystem & m_system; + // The currently streaming camera + CameraPtr m_pCamera; + // Our camera observer + CameraObserver* m_pCameraObserver; + // The current pixel format + VmbInt64_t m_nPixelFormat; + // The current width + VmbInt64_t m_nWidth; + // The current height + VmbInt64_t m_nHeight; +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/CameraObserver.cpp b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/CameraObserver.cpp new file mode 100644 index 0000000..7574974 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/CameraObserver.cpp @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: CameraObserver.cpp + + Description: The camera observer that is used for notifications from VimbaCPP + regarding a change in the camera list. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 "CameraObserver.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +// +// This is our callback routine that will be executed every time a camera was plugged in or out +// +// Parameters: +// [in] pCam The camera that triggered the callback +// [in] reason The reason why the callback was triggered +// +void CameraObserver::CameraListChanged( CameraPtr pCam, UpdateTriggerType reason ) +{ + if ( UpdateTriggerPluggedIn == reason + || UpdateTriggerPluggedOut == reason ) + { + // Emit the new camera signal + emit CameraListChangedSignal( reason ); + } +} + +}}} // namespace AVT::VmbAPI::Examples diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/CameraObserver.h b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/CameraObserver.h new file mode 100644 index 0000000..b76e545 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/CameraObserver.h @@ -0,0 +1,66 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: CameraObserver.h + + Description: The camera observer that is used for notifications from VimbaCPP + regarding a change in the camera list. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_CAMERAOBSERVER +#define AVT_VMBAPI_EXAMPLES_CAMERAOBSERVER + +#include + +#include "VimbaCPP/Include/VimbaCPP.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class CameraObserver : public QObject, public ICameraListObserver +{ + Q_OBJECT + + public: + // + // This is our callback routine that will be executed every time a camera was plugged in or out + // + // Parameters: + // [in] pCam The camera that triggered the callback + // [in] reason The reason why the callback was triggered + // + virtual void CameraListChanged( CameraPtr pCamera, UpdateTriggerType reason ); + + signals: + // + // The camera list changed event (Qt signal) that notifies about a camera change and its reason + // + // Parameters: + // [out] reason The reason why this event was fired + // + void CameraListChangedSignal( int reason ); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/SynchronousGrab.cpp b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/SynchronousGrab.cpp new file mode 100644 index 0000000..99bf968 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/SynchronousGrab.cpp @@ -0,0 +1,268 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: SynchronousGrab.cpp + + Description: Qt dialog class for the GUI of the SynchronousGrab example of + VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 + +#include "SynchronousGrab.h" +using AVT::VmbAPI::FramePtr; +using AVT::VmbAPI::CameraPtrVector; + +enum { NUM_COLORS = 3, }; +enum { BIT_DEPTH = 8, }; + +SynchronousGrab::SynchronousGrab(QWidget *parent, Qt::WindowFlags flags) + : QMainWindow(parent, flags) + , m_pApiController( new ApiController() ) +{ + ui.setupUi(this); + ui.m_LabelStream->setAlignment( Qt::AlignCenter ); + // Connect GUI events with event handlers + QObject::connect( ui.m_ButtonStartStop, SIGNAL( clicked() ), this, SLOT( OnBnClickedButtonStartstop() )); + + // Start Vimba + VmbErrorType err = m_pApiController->StartUp(); + Log( "Starting Vimba", err ); + if ( VmbErrorSuccess == err ) + { + std::string WindowText("SynchronousGrab (Qt version) Vimba C++ API Version "); + WindowText += m_pApiController->GetVersion(); + this->setWindowTitle( QString::fromStdString(WindowText) ); + // Connect new camera found event with event handler + QObject::connect( m_pApiController->GetCameraObserver(), SIGNAL( CameraListChangedSignal( int )), this, SLOT( OnCameraListChanged( int ))); + + // Initially get all connected cameras + UpdateCameraListBox(); + std::stringstream strMsg; + strMsg << "Cameras found..." << m_cameras.size(); + Log( strMsg.str() ); + } +} + +SynchronousGrab::~SynchronousGrab() +{ + // Before we close the application we stop Vimba + m_pApiController->ShutDown(); + + delete m_pApiController; + m_pApiController = NULL; +} + +void SynchronousGrab::OnBnClickedButtonStartstop() +{ + VmbErrorType err; + int nRow = ui.m_ListBoxCameras->currentRow(); + + if ( -1 < nRow ) + { + // Get the frame + FramePtr pFrame; + err = m_pApiController->AcquireSingleImage( m_cameras[nRow], pFrame ); + if ( VmbErrorSuccess == err ) + { + // See if it is not corrupt + VmbFrameStatusType eReceiveStatus; + err = pFrame->GetReceiveStatus( eReceiveStatus ); + if ( VmbErrorSuccess == err + && VmbFrameStatusComplete == eReceiveStatus ) + { + // Set up Qt image + QImage tmpImage( m_pApiController->GetWidth(), + m_pApiController->GetHeight(), + VmbPixelFormatRgb8 == m_pApiController->GetPixelFormat() ? QImage::Format_RGB888 : QImage::Format_Indexed8 ); + + if(VmbPixelFormatRgb8 != m_pApiController->GetPixelFormat()) + { + tmpImage.setNumColors(256); + for(int i = 0; i < 256; i++) + { + tmpImage.setColor(i, qRgb(i, i, i)); + } + } + + VmbUchar_t *pBuffer; + err = pFrame->GetImage( pBuffer ); + if ( VmbErrorSuccess == err ) + { + VmbUint32_t nSize; + err = pFrame->GetImageSize( nSize ); + if ( VmbErrorSuccess == err ) + { + VmbPixelFormatType ePixelFormat = m_pApiController->GetPixelFormat(); + if ( VmbPixelFormatMono8 == ePixelFormat + || VmbPixelFormatRgb8 == ePixelFormat ) + { + // Copy it + // We need that because Qt might repaint the view after we have released the frame already + CopyToImage( pBuffer, tmpImage ); + + // Display it + QSize s= ui.m_LabelStream->size(); + ui.m_LabelStream->setPixmap( QPixmap::fromImage( tmpImage ).scaled( s, Qt::KeepAspectRatio) ); + } + } + } + + Log( "Starting Acquisition", err ); + m_bIsStreaming = VmbErrorSuccess == err; + } + else + { + // If we receive an incomplete image we do nothing + err = VmbErrorOther; + } + } + Log( "Acquire single image", err ); + } + else + { + Log( "Please select a camera." ); + } + +} + +// +// This event handler (Qt slot) is triggered through a Qt signal posted by the camera observer +// +// Parameters: +// [in] reason The reason why the callback of the observer was triggered (plug-in, plug-out, ...) +// +void SynchronousGrab::OnCameraListChanged( int reason ) +{ + bool bUpdateList = false; + + // We only react on new cameras being found and known cameras being unplugged + if ( AVT::VmbAPI::UpdateTriggerPluggedIn == reason ) + { + Log( "Camera list changed. A new camera was discovered by Vimba." ); + bUpdateList = true; + } + else if ( AVT::VmbAPI::UpdateTriggerPluggedOut == reason ) + { + Log( "Camera list changed. A camera was disconnected from Vimba." ); + bUpdateList = true; + } + + if ( true == bUpdateList ) + { + UpdateCameraListBox(); + } + + ui.m_ButtonStartStop->setEnabled( 0 < m_cameras.size() || m_bIsStreaming ); +} + +// +// Copies the content of a byte buffer to a Qt image with respect to the image's alignment +// +// Parameters: +// [in] pInbuffer The byte buffer as received from the cam +// [out] OutImage The filled Qt image +// +void SynchronousGrab::CopyToImage( VmbUchar_t *pInBuffer, QImage &OutImage ) +{ + VmbUchar_t * pCursor = OutImage.bits(); + int nHeight = m_pApiController->GetHeight(); + int nWidth = QImage::Format_Indexed8 == OutImage.format() + ? m_pApiController->GetWidth() + : m_pApiController->GetWidth() * NUM_COLORS; + + if ( OutImage.bytesPerLine() != nWidth ) + { + for ( int y=0; yGetCameraList(); + + // Simply forget about all cameras known so far + ui.m_ListBoxCameras->clear(); + m_cameras.clear(); + + // And query the camera details again + for ( CameraPtrVector::const_iterator iter = cameras.begin(); + cameras.end() != iter; + ++iter ) + { + std::string strCameraName; + std::string strCameraID; + if ( VmbErrorSuccess != (*iter)->GetName( strCameraName )) + { + strCameraName = "[NoName]"; + } + // If for any reason we cannot get the ID of a camera we skip it + if ( VmbErrorSuccess == (*iter)->GetID( strCameraID )) + { + ui.m_ListBoxCameras->addItem( QString::fromStdString( strCameraName + " " +strCameraID ) ); + m_cameras.push_back( strCameraID ); + } + } + + ui.m_ButtonStartStop->setEnabled( 0 < m_cameras.size() || m_bIsStreaming ); +} + +// +// Prints out a given logging string, error code and the descriptive representation of that error code +// +// Parameters: +// [in] strMsg A given message to be printed out +// [in] eErr The API status code +// +void SynchronousGrab::Log( std::string strMsg, VmbErrorType eErr ) +{ + strMsg += "..." + m_pApiController->ErrorCodeToMessage( eErr ); + ui.m_ListLog->insertItem( 0, QString::fromStdString( strMsg ) ); +} + +// +// Prints out a given logging string +// +// Parameters: +// [in] strMsg A given message to be printed out +// +void SynchronousGrab::Log( std::string strMsg ) +{ + ui.m_ListLog->insertItem( 0, QString::fromStdString( strMsg ) ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/SynchronousGrab.h b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/SynchronousGrab.h new file mode 100644 index 0000000..b081fd4 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/SynchronousGrab.h @@ -0,0 +1,100 @@ +/*============================================================================= + Copyright (C) 2012 - 2016 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: SynchronousGrab.cpp + + Description: Qt dialog class for the GUI of the SynchronousGrab example of + VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef SYNCHRONOUSGRABQT_H +#define SYNCHRONOUSGRABQT_H + +#include + +#include "ui_SynchronousGrab.h" + +#include "ApiController.h" + +using AVT::VmbAPI::Examples::ApiController; + +class SynchronousGrab : public QMainWindow +{ + Q_OBJECT + +public: + SynchronousGrab(QWidget *parent = 0, Qt::WindowFlags flags = 0); + ~SynchronousGrab(); + +private: + Ui::SynchronousGrabClass ui; + // Our controller that wraps API access + ApiController * m_pApiController; + // A list of known camera IDs + std::vector m_cameras; + // Are we streaming? + bool m_bIsStreaming; + + // + // Queries and lists all known camera + // + void UpdateCameraListBox(); + + // + // Prints out a given logging string, error code and the descriptive representation of that error code + // + // Parameters: + // [in] strMsg A given message to be printed out + // [in] eErr The API status code + // + void Log( std::string strMsg, VmbErrorType eErr ); + + // + // Prints out a given logging string + // + // Parameters: + // [in] strMsg A given message to be printed out + // + void Log( std::string strMsg ); + + // + // Copies the content of a byte buffer to a Qt image with respect to the image's alignment + // + // Parameters: + // [in] pInbuffer The byte buffer as received from the cam + // [out] OutImage The filled Qt image + // + void CopyToImage( VmbUchar_t *pInBuffer, QImage &OutImage ); + +private slots: + void OnBnClickedButtonStartstop(); + + // + // This event handler (Qt slot) is triggered through a Qt signal posted by the camera observer + // + // Parameters: + // [in] reason The reason why the callback of the observer was triggered (plug-in, plug-out, ...) + // + void OnCameraListChanged( int reason ); +}; + +#endif // SYNCHRONOUSGRABQT_H diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/main.cpp b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/main.cpp new file mode 100644 index 0000000..e6200b6 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/main.cpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: main.cpp + + Description: The main entry point of the SynchronousGrab example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 "SynchronousGrab.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + SynchronousGrab w; + w.show(); + return a.exec(); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/res/SynchronousGrab.png b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/res/SynchronousGrab.png new file mode 100644 index 0000000..61642b4 Binary files /dev/null and b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/res/SynchronousGrab.png differ diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/res/SynchronousGrab.qrc b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/res/SynchronousGrab.qrc new file mode 100644 index 0000000..ba3a2dd --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/res/SynchronousGrab.qrc @@ -0,0 +1,5 @@ + + + SynchronousGrab.png + + diff --git a/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/res/SynchronousGrab.ui b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/res/SynchronousGrab.ui new file mode 100644 index 0000000..ac7d5e1 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/SynchronousGrab/Qt/Source/res/SynchronousGrab.ui @@ -0,0 +1,98 @@ + + + SynchronousGrabClass + + + + 0 + 0 + 1040 + 780 + + + + + 0 + 0 + + + + + 1040 + 780 + + + + + 1040 + 780 + + + + SynchronousGrab (Qt version) + + + + :/SynchronousGrabQt/SynchronousGrab.png:/SynchronousGrabQt/SynchronousGrab.png + + + + + + 0 + 10 + 261 + 521 + + + + + + + 0 + 580 + 1041 + 191 + + + + + + + 0 + 540 + 261 + 31 + + + + Acquire Single Image + + + + + + 270 + 10 + 771 + 561 + + + + + 0 + 0 + + + + + + + + + + + + + + diff --git a/Vimba_6_0/VimbaCPP/Examples/UserSet/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/UserSet/Build/Make/Makefile new file mode 100644 index 0000000..3b6e05d --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/UserSet/Build/Make/Makefile @@ -0,0 +1,50 @@ +PROJECT_NAME = UserSet + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(EXAMPLES_DIR) \ + +LIBS = $(VIMBACPP_LIBS) + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBACPP_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/UserSet.o \ + $(OBJ_DIR)/program.o + +DEPENDENCIES = VimbaCPP + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/UserSet/Source/Exception.h b/Vimba_6_0/VimbaCPP/Examples/UserSet/Source/Exception.h new file mode 100644 index 0000000..ccf2ba9 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/UserSet/Source/Exception.h @@ -0,0 +1,78 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: Exception.h + + Description: Helper for exceptions. + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_EXCEPTION +#define AVT_VMBAPI_EXAMPLES_EXCEPTION + +#include "VimbaCPP/Include/VimbaCPP.h" +#include "Common/ErrorCodeToMessage.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class Exception: public std::exception +{ +private: + std::string m_sMsg; + // Vimba error code + VmbErrorType m_eError; +public: + Exception( const std::string &rsMessage, const VmbErrorType eError ) + : m_eError(eError) + { + try + { + m_sMsg = rsMessage ; + }catch(...) {} + } + + virtual ~Exception() throw() + { + } + + VmbErrorType GetError() const + { + return m_eError; + } + + std::string GetMessageStr() const + { + return m_sMsg; + } + + // Translates Vimba error codes to readable error messages + static std::string ErrorCodeToMessage( VmbErrorType eErr ) + { + return AVT::VmbAPI::Examples::ErrorCodeToMessage( eErr ); + } +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/UserSet/Source/UserSet.cpp b/Vimba_6_0/VimbaCPP/Examples/UserSet/Source/UserSet.cpp new file mode 100644 index 0000000..7ccd6ca --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/UserSet/Source/UserSet.cpp @@ -0,0 +1,299 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: UserSet.cpp + + Description: The UserSet example will demonstrate how deal with the user sets + stored inside the cameras using VimbaCPP. + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#include "UserSet.h" +#include "Exception.h" + +#include "VimbaCPP/Include/VimbaCPP.h" + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +CameraPtr UserSetCollection::m_pCamera; +std::vector UserSetCollection::m_usersets; + +UserSetCollection::UserSetCollection( CameraPtr pCamera ) +{ + //Check parameters + if ( NULL == pCamera ) + { + throw Exception( "UserSetCollection failed.", VmbErrorBadParameter ); + } + + m_pCamera = pCamera; + + VmbErrorType err = VmbErrorSuccess; + + VmbInt64_t nCount; + err = GetCount ( nCount ); + if ( VmbErrorSuccess == err ) + { + m_usersets.reserve( (size_t)nCount ); + } + + if ( VmbErrorSuccess == err ) + { + for ( int i = 0; i < nCount; i++ ) + { + AVT::VmbAPI::Examples::UserSetControl control( m_pCamera, i ) ; + m_usersets.push_back( control ); + } + } + + if ( VmbErrorSuccess != err ) + { + throw Exception( "UserSetCollection failed.", err ); + } +} + +//Get user set count +VmbErrorType UserSetCollection::GetCount ( VmbInt64_t& rCount ) +{ + VmbErrorType err = VmbErrorSuccess; + + FeaturePtr pFeature; + AVT::VmbAPI::StringVector selector; + + err = m_pCamera->GetFeatureByName ( "UserSetSelector", pFeature ); + + if ( VmbErrorSuccess == err ) + { + err = pFeature->GetValues ( selector ); + rCount = selector.size(); + } + + return err; +} + +//Get user set control +VmbErrorType UserSetCollection::GetControl ( VmbInt64_t nIndex, UserSetControl& rUserSet ) +{ + VmbErrorType err = VmbErrorSuccess; + + VmbInt64_t nCount; + err = GetCount ( nCount ); + if ( VmbErrorSuccess == err ) + { + if ( nIndex >= nCount ) + { + err = VmbErrorBadParameter; + } + + FeaturePtr pFeature; + + //Access to user set changes the selector + if ( VmbErrorSuccess == err ) + { + err = m_pCamera->GetFeatureByName( "UserSetSelector", pFeature ); + } + + if(VmbErrorSuccess == err) + { + err = pFeature->SetValue( nIndex ); + } + + if(VmbErrorSuccess == err) + { + rUserSet = m_usersets[ (size_t)nIndex ]; + } + } + + return err; +} + +//Get selected user set index +VmbErrorType UserSetCollection::GetSelectedIndex ( VmbInt64_t& rIndex ) +{ + VmbErrorType err = VmbErrorSuccess; + + FeaturePtr pFeature; + + err = m_pCamera->GetFeatureByName ( "UserSetSelector", pFeature ); + + if ( VmbErrorSuccess == err ) + { + err = pFeature->GetValue ( rIndex ); + } + + return err; +} + +//Get default user set index +VmbErrorType UserSetCollection::GetDefaultIndex ( VmbInt64_t& rDefaultIndex ) +{ + VmbErrorType err = VmbErrorSuccess; + + FeaturePtr pFeature; + + err = m_pCamera->GetFeatureByName ( "UserSetDefaultSelector", pFeature ); + + if ( VmbErrorSuccess == err ) + { + err = pFeature->GetValue ( rDefaultIndex ); + } + + return err; +} + +UserSetControl::UserSetControl( CameraPtr pCamera, VmbInt64_t nIndex ) +{ + //Check parameters + if ( NULL == pCamera ) + { + throw Exception( "UserSetControl failed.", VmbErrorBadParameter ); + } + + m_pCamera = pCamera; + m_nIndex = nIndex; +} + +//Is user set default +VmbErrorType UserSetControl::IsDefault ( bool& bIsDefault ) +{ + bIsDefault = false; + + VmbErrorType err = VmbErrorSuccess; + + FeaturePtr pFeature; + + err = m_pCamera->GetFeatureByName( "UserSetDefaultSelector", pFeature ); + + VmbInt64_t nDefaultIndex; + if(VmbErrorSuccess == err) + { + err = pFeature->GetValue( nDefaultIndex ); + } + + if(VmbErrorSuccess == err) + { + if ( nDefaultIndex == m_nIndex ) + { + bIsDefault = true; + } + } + + return err; +} + +//Make user set default +VmbErrorType UserSetControl::MakeDefault () +{ + VmbErrorType err = VmbErrorSuccess; + + FeaturePtr pFeature; + + err = m_pCamera->GetFeatureByName( "UserSetDefaultSelector", pFeature ); + if ( VmbErrorNotFound == err ) + { + err = m_pCamera->GetFeatureByName ( "UserSetMakeDefault", pFeature ); + if(VmbErrorSuccess == err) + { + err = pFeature->RunCommand(); + } + } + else if(VmbErrorSuccess == err) + { + err = pFeature->SetValue( m_nIndex ); + } + + return err; +} + +//Save user set to flash +VmbErrorType UserSetControl::SaveToFlash () +{ + VmbErrorType err = VmbErrorSuccess; + + FeaturePtr pFeature; + + err = m_pCamera->GetFeatureByName( "UserSetSave", pFeature ); + if(VmbErrorSuccess == err) + { + err = pFeature->RunCommand(); + } + + return err; +} + +//Load user set from flash +VmbErrorType UserSetControl::LoadFromFlash () +{ + VmbErrorType err = VmbErrorSuccess; + + FeaturePtr pFeature; + + err = m_pCamera->GetFeatureByName( "UserSetLoad", pFeature ); + if(VmbErrorSuccess == err) + { + err = pFeature->RunCommand(); + } + + return err; +} + +//Get user set operation result +VmbErrorType UserSetControl::GetOperationResult( VmbInt64_t& nResult ) +{ + VmbErrorType err = VmbErrorSuccess; + + FeaturePtr pFeature; + + err = m_pCamera->GetFeatureByName( "UserSetOperationResult", pFeature ); + if(VmbErrorSuccess == err) + { + err = pFeature->GetValue( nResult ); + } + + return err; +} + +//Get user set operation status +VmbErrorType UserSetControl::GetOperationStatus( VmbInt64_t& nStatus ) +{ + VmbErrorType err = VmbErrorSuccess; + + FeaturePtr pFeature; + + err = m_pCamera->GetFeatureByName( "UserSetOperationStatus", pFeature ); + if(VmbErrorSuccess == err) + { + err = pFeature->GetValue( nStatus ); + } + + return err; +} + + +}}} // namespace AVT::VmbAPI::Examples + diff --git a/Vimba_6_0/VimbaCPP/Examples/UserSet/Source/UserSet.h b/Vimba_6_0/VimbaCPP/Examples/UserSet/Source/UserSet.h new file mode 100644 index 0000000..87320d7 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/UserSet/Source/UserSet.h @@ -0,0 +1,95 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: UserSet.h + + Description: The UserSet example will demonstrate how deal with the user sets + stored inside the cameras. + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef AVT_VMBAPI_EXAMPLES_USERSET +#define AVT_VMBAPI_EXAMPLES_USERSET + +#include "VimbaCPP/Include/VimbaCPP.h" + + +namespace AVT { +namespace VmbAPI { +namespace Examples { + +class UserSetControl +{ +private: + CameraPtr m_pCamera; + VmbInt64_t m_nIndex; + +public: + + //ctor + UserSetControl( CameraPtr pCamera, VmbInt64_t nIndex ); + + //Is user set default + VmbErrorType IsDefault ( bool& bIsDefault ); + + //Make user set default + VmbErrorType MakeDefault (); + + //Save current camera settings to user set + VmbErrorType SaveToFlash (); + + //Load settings from user set into the camera + VmbErrorType LoadFromFlash (); + + //Get operation result + VmbErrorType GetOperationResult( VmbInt64_t& nResult ); + + //Get operation status + VmbErrorType GetOperationStatus( VmbInt64_t& nStatus ); +}; + +class UserSetCollection +{ +private: + static CameraPtr m_pCamera; + static std::vector m_usersets; + +public: + //ctor + UserSetCollection( CameraPtr pCamera ); + + //Get count + static VmbErrorType GetCount ( VmbInt64_t& nCount ); + + //Get control + static VmbErrorType GetControl ( VmbInt64_t nIndex, UserSetControl& control ); + + //Get selected index + static VmbErrorType GetSelectedIndex ( VmbInt64_t& nIndex ); + + //Get default index + static VmbErrorType GetDefaultIndex ( VmbInt64_t& nDefaultIndex ); +}; + +}}} // namespace AVT::VmbAPI::Examples + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/UserSet/Source/program.cpp b/Vimba_6_0/VimbaCPP/Examples/UserSet/Source/program.cpp new file mode 100644 index 0000000..31c516a --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/UserSet/Source/program.cpp @@ -0,0 +1,518 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: program.cpp + + Description: Main entry point of UserSet example of VimbaCPP. + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#include "UserSet.h" +#include "Exception.h" + +#include "Common/StreamSystemInfo.h" + +enum Mode +{ + ModeUnknown = 0, + ModeSave = 1, + ModeLoad = 2, + ModeCount = 3, + ModeIndex = 4, + ModeMakeDefault = 5, + ModeIsDefault = 6, + ModeOperationResult = 7, + ModeOperationStatus = 8, +}; + +bool StartsWith( const char *pString, const char *pStart ) +{ + if( NULL == pString ) + { + return false; + } + if( NULL == pStart ) + { + return false; + } + + if( std::strlen(pString) < std::strlen(pStart) ) + { + return false; + } + + if( std::memcmp(pString, pStart, std::strlen(pStart)) != 0 ) + { + return false; + } + + return true; +} + +int main( int argc, char* argv[] ) +{ + std::cout << "//////////////////////////////////" << std::endl; + std::cout << "/// Vimba API User Set Example ///" << std::endl; + std::cout << "//////////////////////////////////" << std::endl << std::endl; + + VmbErrorType err = VmbErrorSuccess; + + std::string cameraID; + std::string controlIndex; + Mode eMode = ModeUnknown; + bool printHelp = false; + + ////////////////////// + //Parse command line// + ////////////////////// + + for(int i = 1; i < argc; i++) + { + char *pParameter = argv[i]; + if( std::strlen( pParameter ) < 0 ) + { + err = VmbErrorBadParameter; + break; + } + + if( pParameter[0] == '/' ) + { + if( std::strcmp( pParameter, "/s" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeSave; + } + else if( std::strcmp( pParameter, "/l" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeLoad; + } + else if( std::strcmp( pParameter, "/n" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeCount; + } + else if( std::strcmp( pParameter, "/i" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeIndex; + } + else if( StartsWith( pParameter, "/i:" )) + { + if( controlIndex.empty() == false ) + { + err = VmbErrorBadParameter; + break; + } + + controlIndex = pParameter + 3; + if( controlIndex.size() <= 0 ) + { + err = VmbErrorBadParameter; + break; + } + } + else if( std::strcmp( pParameter, "/m" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeMakeDefault; + } + else if( std::strcmp( pParameter, "/d" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeIsDefault; + } + else if( std::strcmp( pParameter, "/or" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeOperationResult; + } + else if( std::strcmp( pParameter, "/os" ) == 0 ) + { + if( ModeUnknown != eMode ) + { + err = VmbErrorBadParameter; + break; + } + + eMode = ModeOperationStatus; + } + else if( std::strcmp( pParameter, "/h" ) == 0 ) + { + if( (cameraID.empty() == false) + || (ModeUnknown != eMode) + || (true == printHelp)) + { + err = VmbErrorBadParameter; + break; + } + + printHelp = true; + } + else + { + err = VmbErrorBadParameter; + break; + } + } + else + { + if( cameraID.empty() == false ) + { + err = VmbErrorBadParameter; + break; + } + + cameraID = pParameter; + } + } + + //Write out an error if we could not parse the command line + if( VmbErrorBadParameter == err ) + { + std::cout << "Invalid parameters!\n\n"; + printHelp = true; + } + + //Print out help and end program + if( true == printHelp ) + { + std::cout << "Usage: UserSet [CameraID] [/i:Index] [/h] [/{s|l|i|m|d|or|os|n}]\n"; + std::cout << "Parameters: CameraID ID of the camera to use\n"; + std::cout << " (using first camera if not specified)\n"; + std::cout << " /i:Index Set user set index\n"; + std::cout << " /h Print out help\n"; + std::cout << " /s Save user set to flash\n"; + std::cout << " /l Load user set from flash\n"; + std::cout << " (default if not specified)\n"; + std::cout << " /i Get selected user set index\n"; + std::cout << " /m Make user set default\n"; + std::cout << " /d Is user set default\n"; + std::cout << " /or Get user set operation result\n"; + std::cout << " /os Get user set operation status\n"; + std::cout << " /n Get user set count\n\n"; + std::cout << "For example to load user set 0 (factory set) from flash in order to\nactivate it call\n"; + std::cout << "UserSet /i:0 /l\n\n" ; + std::cout << "To save the current settings to user set 1 call\n"; + std::cout << "UserSet /i:1 /s\n\n"; + + return err; + } + + bool bVimbaStarted = false; + AVT::VmbAPI::CameraPtr pCamera; + AVT::VmbAPI::VimbaSystem * pVimbaSystem = NULL; + + try + { + // Get a pointer to the VimbaSystem singleton + pVimbaSystem = &AVT::VmbAPI::VimbaSystem::GetInstance(); + + // Print out version of Vimba + std::cout<<"Vimba C++ API Version "<<*pVimbaSystem<<"\n"; + + //Startup API + if( VmbErrorSuccess == err ) + { + err = pVimbaSystem->Startup(); + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not start system.", err ); + } + bVimbaStarted = true; + } + + //Open camera + if( VmbErrorSuccess == err ) + { + if( cameraID.empty() ) + { + //Open first available camera + + //Fetch all cameras known to Vimba + AVT::VmbAPI::CameraPtrVector cameras; + err = pVimbaSystem->GetCameras(cameras); + if( VmbErrorSuccess == err ) + { + if( cameras.size() > 0 ) + { + for ( AVT::VmbAPI::CameraPtrVector::const_iterator iter = cameras.begin(); + cameras.end() != iter; + ++iter ) + { + //Check if we can open the camera in full mode + VmbAccessModeType eAccessMode = VmbAccessModeNone; + err = (*iter)->GetPermittedAccess( eAccessMode ); + if( VmbErrorSuccess == err ) + { + if( (VmbAccessModeFull == (VmbAccessModeFull & eAccessMode)) || + ((cameras.end() - 1) == iter) ) + { + //Now get the camera ID + err = (*iter)->GetID(cameraID); + if(VmbErrorSuccess == err) + { + //Try to open the camera + err = (*iter)->Open(VmbAccessModeFull); + if(VmbErrorSuccess == err) + { + pCamera = *iter; + break; + } + } + } + } + } + + if( VmbErrorSuccess != err ) + { + err = VmbErrorNotFound; + throw AVT::VmbAPI::Examples::Exception("Could not open any camera.", err); + } + } + else + { + err = VmbErrorNotFound; + throw AVT::VmbAPI::Examples::Exception("Could not open any camera.", err); + } + } + else + { + throw AVT::VmbAPI::Examples::Exception("Could not list cameras.", err); + } + } + else + { + //Open specific camera + err = pVimbaSystem->OpenCameraByID(cameraID.c_str(), VmbAccessModeFull, pCamera); + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception("Could not open camera.", err); + } + } + } + + if( VmbErrorSuccess == err ) + { + std::cout << "Camera ID: " << cameraID << std::endl << std::endl; + + AVT::VmbAPI::Examples::UserSetCollection collection( pCamera ); + + VmbInt64_t nIndex; + + if ( controlIndex.empty() == false ) + { + nIndex = atoi( controlIndex.c_str() ); + } + else + { + err = collection.GetSelectedIndex( nIndex ); + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not get selected user set index.", err ); + } + } + + AVT::VmbAPI::Examples::UserSetControl control( pCamera, nIndex ); + if ( (ModeCount != eMode) && (ModeIndex != eMode) ) + { + err = collection.GetControl( nIndex, control ); + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not get user set control.", err ); + } + } + + switch( eMode ) + { + default: + case ModeLoad: + { + //Load user set + err = control.LoadFromFlash(); + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not load user set from flash.", err ); + } + + std::cout << "User set successfully loaded from flash." << std::endl; + } + break; + + case ModeSave: + { + //Save user set + err = control.SaveToFlash(); + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not save user set to flash.", err ); + } + + std::cout << "User set successfully saved to flash." << std::endl; + } + break; + + case ModeCount: + { + //Get user set count + VmbInt64_t nCount; + err = collection.GetCount( nCount ); + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not get user set count.", err ); + } + + std::cout << "Get user set count was successful. Count = " << nCount << std::endl; + } + break; + + case ModeIndex: + { + //Get selected user set index + VmbInt64_t nSelectedIndex; + err = collection.GetSelectedIndex( nSelectedIndex ); + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not get user set index.", err ); + } + + std::cout << "Get selected user set was successful. Index = " << nSelectedIndex << std::endl; + } + break; + + case ModeMakeDefault: + { + err = control.MakeDefault(); + + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not set user set default.", err ); + } + + std::cout << "Make user set default was successful. " << std::endl; + } + break; + + case ModeIsDefault: + { + bool bIsDefault = false; + if( VmbErrorSuccess == err ) + { + err = control.IsDefault( bIsDefault ); + } + + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not get user set default.", err ); + } + + std::cout << "Is user set default was successful. Result = " << bIsDefault << std::endl; + } + break; + + + case ModeOperationResult: + { + VmbInt64_t nResult; + err = control.GetOperationResult( nResult ); + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not get user set opration result.", err ); + } + + std::cout << "Get user set operation result was successful. Operation Result = " << nResult << std::endl; + } + break; + case ModeOperationStatus: + { + VmbInt64_t nStatus; + err = control.GetOperationStatus( nStatus ); + if( VmbErrorSuccess != err ) + { + throw AVT::VmbAPI::Examples::Exception( "Could not get user set operation status.", err ); + } + + std::cout << "Get user set operation status was successful. Operation Status = " << nStatus << std::endl; + } + break; + + } + } + } + + catch( AVT::VmbAPI::Examples::Exception& ex ) + { + std::cout << ex.GetMessageStr() << " VimbaException: " << ex.GetError() << " = " << ex.ErrorCodeToMessage( ex.GetError() ) << std::endl; + } + + //Close camera + if( NULL != pCamera ) + { + pCamera->Close(); + } + + //Shutdown API + if(true == bVimbaStarted) + { + pVimbaSystem->Shutdown(); + } + + return err; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Build/Make/Info.plist b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Build/Make/Info.plist new file mode 100644 index 0000000..2d9fbda --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Build/Make/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleGetInfoString + Allied Vision Vimba Viewer + CFBundleExecutable + VimbaViewer + CFBundleIdentifier + com.Allied-Vision-Technologies.VimbaViewer + CFBundleName + VimbaViewer + CFBundleIconFile + VimbaViewer.icns + CFBundleShortVersionString + 0.1.3a + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + IFMajorVersion + 0 + IFMinorVersion + 1 + + diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Build/Make/Make_VimbaViewerApp.sh b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Build/Make/Make_VimbaViewerApp.sh new file mode 100755 index 0000000..0bb350f --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Build/Make/Make_VimbaViewerApp.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +# delete the old app folder +rm -dfR VimbaViewer.app + +# create the folder +mkdir VimbaViewer.app +mkdir VimbaViewer.app/Contents +mkdir VimbaViewer.app/Contents/libs +mkdir VimbaViewer.app/Contents/MacOS +mkdir VimbaViewer.app/Contents/Resources +mkdir VimbaViewer.app/Contents/Frameworks + +# copy the data allied vision files +cp binary/Darwin_x86_64bit/Release/libVimbaC.dylib VimbaViewer.app/Contents/libs/ +cp binary/Darwin_x86_64bit/Release/libVimbaCPP.dylib VimbaViewer.app/Contents/libs/ +cp binary/Darwin_x86_64bit/Release/libVimbaImageTransform.dylib VimbaViewer.app/Contents/libs/ +cp VimbaGigETL.cti VimbaViewer.app/Contents/libs/ +# cp VimbaPCIeTL.cti VimbaViewer.app/Contents/libs/ +cp binary/Darwin_x86_64bit/Release/VimbaViewer VimbaViewer.app/Contents/MacOS/ +cp ../../Source/Images/VimbaViewer.icns VimbaViewer.app/Contents/Resources/ +cp Info.plist VimbaViewer.app/Contents/Info.plist + +# copy the qt files +cp -R /opt/local/Library/Frameworks/QtCore.framework VimbaViewer.app/Contents/Frameworks +cp -R /opt/local/Library/Frameworks/QtGui.framework VimbaViewer.app/Contents/Frameworks +cp -R /opt/local/Library/Frameworks/QtSvg.framework VimbaViewer.app/Contents/Frameworks + +#copy libpng +cp -R /opt/local/lib/libpng16.16.dylib VimbaViewer.app/Contents/libs/ + +# change the dynamic lib pathes +install_name_tool -change libVimbaC.dylib @executable_path/../libs/libVimbaC.dylib VimbaViewer.app/Contents/libs/libVimbaCPP.dylib +install_name_tool -change libVimbaCPP.dylib @executable_path/../libs/libVimbaCPP.dylib VimbaViewer.app/Contents/MacOS/VimbaViewer +install_name_tool -change libVimbaImageTransform.dylib @executable_path/../libs/libVimbaImageTransform.dylib VimbaViewer.app/Contents/MacOS/VimbaViewer + +# change the Qt frameworks pathes +install_name_tool -change /opt/local/Library/Frameworks/QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore VimbaViewer.app/Contents/Frameworks/QtCore.framework/Versions/4/QtCore +install_name_tool -change /opt/local/Library/Frameworks/QtGui.framework/Versions/4/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui VimbaViewer.app/Contents/Frameworks/QtGui.framework/Versions/4/QtGui +install_name_tool -change /opt/local/Library/Frameworks/QtSvg.framework/Versions/4/QtSvg @executable_path/../Frameworks/QtSvg.framework/Versions/4/QtSvg VimbaViewer.app/Contents/Frameworks/QtSvg.framework/Versions/4/QtSvg + +install_name_tool -change /opt/local/Library/Frameworks/QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore VimbaViewer.app/Contents/MacOS/VimbaViewer +install_name_tool -change /opt/local/Library/Frameworks/QtGui.framework/Versions/4/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui VimbaViewer.app/Contents/MacOS/VimbaViewer +install_name_tool -change /opt/local/Library/Frameworks/QtSvg.framework/Versions/4/QtSvg @executable_path/../Frameworks/QtSvg.framework/Versions/4/QtSvg VimbaViewer.app/Contents/MacOS/VimbaViewer + +install_name_tool -change /opt/local/Library/Frameworks/QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore VimbaViewer.app/Contents/Frameworks/QtGui.framework/Versions/4/QtGui +install_name_tool -change /opt/local/Library/Frameworks/QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore VimbaViewer.app/Contents/Frameworks/QtSvg.framework/Versions/4/QtSvg +install_name_tool -change /opt/local/Library/Frameworks/QtGui.framework/Versions/4/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui VimbaViewer.app/Contents/Frameworks/QtSvg.framework/Versions/4/QtSvg + +install_name_tool -change /opt/local/lib/libpng16.16.dylib @executable_path/../libs/libpng16.16.dylib VimbaViewer.app/Contents/Frameworks/QtGui.framework/Versions/4/QtGui diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Build/Make/Makefile b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Build/Make/Makefile new file mode 100644 index 0000000..e9ab11b --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Build/Make/Makefile @@ -0,0 +1,301 @@ +PROJECT_NAME = VimbaViewer + +PROJECT_DIR = ../.. +EXAMPLES_DIR = $(PROJECT_DIR)/.. +VIMBASDK_DIR = $(EXAMPLES_DIR)/../.. +MAKE_INCLUDE_DIR = $(CURDIR)/$(EXAMPLES_DIR)/Build/Make + +include $(MAKE_INCLUDE_DIR)/Common.mk + +CONFIG_DIR = $(ARCH)_$(WORDSIZE)bit +BIN_FILE = $(PROJECT_NAME) +BIN_DIR = binary/$(CONFIG_DIR) +OBJ_DIR = object/$(CONFIG_DIR) +BIN_PATH = $(BIN_DIR)/$(BIN_FILE) + +all: $(BIN_PATH) + +include $(MAKE_INCLUDE_DIR)/VimbaCPP.mk +include $(MAKE_INCLUDE_DIR)/VimbaImageTransform.mk +include $(MAKE_INCLUDE_DIR)/Qt.mk + +SOURCE_DIR = $(PROJECT_DIR)/Source +INCLUDE_DIRS = -I$(SOURCE_DIR) \ + -I$(SOURCE_DIR)/UI \ + -I$(SOURCE_DIR)/UI/Histogram \ + -I$(SOURCE_DIR)/UI/HexEditor \ + -I$(SOURCE_DIR)/ExternLib/qwt \ + -I$(SOURCE_DIR)/ExternLib/qwt \ + -I$(OBJ_DIR) + +LIBS = $(VIMBACPP_LIBS) \ + $(VIMBAIMAGETRANSFORM_LIBS) \ + $(QTCORE_LIBS) \ + $(QTGUI_LIBS) \ + $(QTSVG_LIBS) \ + -lrt + +DEFINES = + +CFLAGS = $(COMMON_CFLAGS) \ + $(VIMBAIMAGETRANSFORM_CFLAGS) \ + $(VIMBACPP_CFLAGS) \ + $(QTCORE_CFLAGS) \ + $(QTGUI_CFLAGS) \ + $(QTSVG_CFLAGS) + +OBJ_FILES = $(OBJ_DIR)/ActionCommand.o \ + $(OBJ_DIR)/CameraObserver.o \ + $(OBJ_DIR)/FeatureObserver.o \ + $(OBJ_DIR)/FrameObserver.o \ + $(OBJ_DIR)/Helper.o \ + $(OBJ_DIR)/Main.o \ + $(OBJ_DIR)/MainWindow.o \ + $(OBJ_DIR)/SplashScreen.o \ + $(OBJ_DIR)/ViewerWindow.o \ + $(OBJ_DIR)/ImageSaver.o \ + $(OBJ_DIR)/ImageWriter.o \ + $(OBJ_DIR)/ForceIP.o \ + $(OBJ_DIR)/qwt_abstract_legend.o \ + $(OBJ_DIR)/qwt_abstract_scale.o \ + $(OBJ_DIR)/qwt_abstract_scale_draw.o \ + $(OBJ_DIR)/qwt_abstract_slider.o \ + $(OBJ_DIR)/qwt_analog_clock.o \ + $(OBJ_DIR)/qwt_arrow_button.o \ + $(OBJ_DIR)/qwt_clipper.o \ + $(OBJ_DIR)/qwt_color_map.o \ + $(OBJ_DIR)/qwt_column_symbol.o \ + $(OBJ_DIR)/qwt_compass.o \ + $(OBJ_DIR)/qwt_compass_rose.o \ + $(OBJ_DIR)/qwt_counter.o \ + $(OBJ_DIR)/qwt_curve_fitter.o \ + $(OBJ_DIR)/qwt_date.o \ + $(OBJ_DIR)/qwt_date_scale_draw.o \ + $(OBJ_DIR)/qwt_date_scale_engine.o \ + $(OBJ_DIR)/qwt_dial.o \ + $(OBJ_DIR)/qwt_dial_needle.o \ + $(OBJ_DIR)/qwt_dyngrid_layout.o \ + $(OBJ_DIR)/qwt_event_pattern.o \ + $(OBJ_DIR)/qwt_graphic.o \ + $(OBJ_DIR)/qwt_interval.o \ + $(OBJ_DIR)/qwt_interval_symbol.o \ + $(OBJ_DIR)/qwt_knob.o \ + $(OBJ_DIR)/qwt_legend.o \ + $(OBJ_DIR)/qwt_legend_data.o \ + $(OBJ_DIR)/qwt_legend_label.o \ + $(OBJ_DIR)/qwt_magnifier.o \ + $(OBJ_DIR)/qwt_math.o \ + $(OBJ_DIR)/qwt_matrix_raster_data.o \ + $(OBJ_DIR)/qwt_null_paintdevice.o \ + $(OBJ_DIR)/qwt_painter.o \ + $(OBJ_DIR)/qwt_painter_command.o \ + $(OBJ_DIR)/qwt_panner.o \ + $(OBJ_DIR)/qwt_picker.o \ + $(OBJ_DIR)/qwt_picker_machine.o \ + $(OBJ_DIR)/qwt_pixel_matrix.o \ + $(OBJ_DIR)/qwt_plot_axis.o \ + $(OBJ_DIR)/qwt_plot_canvas.o \ + $(OBJ_DIR)/qwt_plot.o \ + $(OBJ_DIR)/qwt_plot_abstract_barchart.o \ + $(OBJ_DIR)/qwt_plot_barchart.o \ + $(OBJ_DIR)/qwt_plot_curve.o \ + $(OBJ_DIR)/qwt_plot_dict.o \ + $(OBJ_DIR)/qwt_plot_directpainter.o \ + $(OBJ_DIR)/qwt_plot_grid.o \ + $(OBJ_DIR)/qwt_plot_histogram.o \ + $(OBJ_DIR)/qwt_plot_intervalcurve.o \ + $(OBJ_DIR)/qwt_plot_item.o \ + $(OBJ_DIR)/qwt_plot_layout.o \ + $(OBJ_DIR)/qwt_plot_legenditem.o \ + $(OBJ_DIR)/qwt_plot_magnifier.o \ + $(OBJ_DIR)/qwt_plot_marker.o \ + $(OBJ_DIR)/qwt_plot_multi_barchart.o \ + $(OBJ_DIR)/qwt_plot_panner.o \ + $(OBJ_DIR)/qwt_plot_picker.o \ + $(OBJ_DIR)/qwt_plot_rasteritem.o \ + $(OBJ_DIR)/qwt_plot_renderer.o \ + $(OBJ_DIR)/qwt_plot_rescaler.o \ + $(OBJ_DIR)/qwt_plot_scaleitem.o \ + $(OBJ_DIR)/qwt_plot_seriesitem.o \ + $(OBJ_DIR)/qwt_plot_shapeitem.o \ + $(OBJ_DIR)/qwt_plot_spectrocurve.o \ + $(OBJ_DIR)/qwt_plot_spectrogram.o \ + $(OBJ_DIR)/qwt_plot_svgitem.o \ + $(OBJ_DIR)/qwt_plot_textlabel.o \ + $(OBJ_DIR)/qwt_plot_tradingcurve.o \ + $(OBJ_DIR)/qwt_plot_xml.o \ + $(OBJ_DIR)/qwt_plot_zoneitem.o \ + $(OBJ_DIR)/qwt_plot_zoomer.o \ + $(OBJ_DIR)/qwt_point_3d.o \ + $(OBJ_DIR)/qwt_point_data.o \ + $(OBJ_DIR)/qwt_point_mapper.o \ + $(OBJ_DIR)/qwt_point_polar.o \ + $(OBJ_DIR)/qwt_raster_data.o \ + $(OBJ_DIR)/qwt_round_scale_draw.o \ + $(OBJ_DIR)/qwt_sampling_thread.o \ + $(OBJ_DIR)/qwt_scale_div.o \ + $(OBJ_DIR)/qwt_scale_draw.o \ + $(OBJ_DIR)/qwt_scale_engine.o \ + $(OBJ_DIR)/qwt_scale_map.o \ + $(OBJ_DIR)/qwt_scale_widget.o \ + $(OBJ_DIR)/qwt_series_data.o \ + $(OBJ_DIR)/qwt_slider.o \ + $(OBJ_DIR)/qwt_spline.o \ + $(OBJ_DIR)/qwt_symbol.o \ + $(OBJ_DIR)/qwt_system_clock.o \ + $(OBJ_DIR)/qwt_text.o \ + $(OBJ_DIR)/qwt_text_engine.o \ + $(OBJ_DIR)/qwt_text_label.o \ + $(OBJ_DIR)/qwt_thermo.o \ + $(OBJ_DIR)/qwt_transform.o \ + $(OBJ_DIR)/qwt_wheel.o \ + $(OBJ_DIR)/qwt_widget_overlay.o \ + $(OBJ_DIR)/CameraTreeWindow.o \ + $(OBJ_DIR)/ControllerTreeWindow.o \ + $(OBJ_DIR)/LineEditCompleter.o \ + $(OBJ_DIR)/MultiCompleter.o \ + $(OBJ_DIR)/DockWidgetWindow.o \ + $(OBJ_DIR)/ExComboBox.o \ + $(OBJ_DIR)/FloatSpinBox.o \ + $(OBJ_DIR)/IntSpinBox.o \ + $(OBJ_DIR)/LoggerWindow.o \ + $(OBJ_DIR)/MainInformationWindow.o \ + $(OBJ_DIR)/MdiChild.o \ + $(OBJ_DIR)/SortFilterProxyModel.o \ + $(OBJ_DIR)/Viewer.o \ + $(OBJ_DIR)/Commands.o \ + $(OBJ_DIR)/HexMainWindow.o \ + $(OBJ_DIR)/HexOptionDialog.o \ + $(OBJ_DIR)/QHexEdit.o \ + $(OBJ_DIR)/QHexEdit_p.o \ + $(OBJ_DIR)/XByteArray.o \ + $(OBJ_DIR)/Histogram.o \ + $(OBJ_DIR)/HistogramThread.o \ + $(OBJ_DIR)/HistogramWindow.o \ + $(OBJ_DIR)/moc_ActionCommand.o \ + $(OBJ_DIR)/moc_CameraObserver.o \ + $(OBJ_DIR)/moc_FeatureObserver.o \ + $(OBJ_DIR)/moc_FrameObserver.o \ + $(OBJ_DIR)/moc_MainWindow.o \ + $(OBJ_DIR)/qrc_VimbaViewer.o \ + $(OBJ_DIR)/moc_ViewerWindow.o \ + $(OBJ_DIR)/moc_ImageSaver.o \ + $(OBJ_DIR)/moc_CameraTreeWindow.o \ + $(OBJ_DIR)/moc_ControllerTreeWindow.o \ + $(OBJ_DIR)/moc_LineEditCompleter.o \ + $(OBJ_DIR)/moc_MultiCompleter.o \ + $(OBJ_DIR)/moc_DockWidgetWindow.o \ + $(OBJ_DIR)/moc_ExComboBox.o \ + $(OBJ_DIR)/moc_FloatSpinBox.o \ + $(OBJ_DIR)/moc_IntSpinBox.o \ + $(OBJ_DIR)/moc_LoggerWindow.o \ + $(OBJ_DIR)/moc_MainInformationWindow.o \ + $(OBJ_DIR)/moc_MdiChild.o \ + $(OBJ_DIR)/moc_Viewer.o \ + $(OBJ_DIR)/moc_HexMainWindow.o \ + $(OBJ_DIR)/moc_HexOptionDialog.o \ + $(OBJ_DIR)/moc_QHexEdit.o \ + $(OBJ_DIR)/moc_QHexEdit_p.o \ + $(OBJ_DIR)/moc_HistogramThread.o \ + $(OBJ_DIR)/moc_HistogramWindow.o \ + $(OBJ_DIR)/moc_qwt_abstract_legend.o \ + $(OBJ_DIR)/moc_qwt_abstract_scale.o \ + $(OBJ_DIR)/moc_qwt_abstract_slider.o \ + $(OBJ_DIR)/moc_qwt_analog_clock.o \ + $(OBJ_DIR)/moc_qwt_compass.o \ + $(OBJ_DIR)/moc_qwt_counter.o \ + $(OBJ_DIR)/moc_qwt_dial.o \ + $(OBJ_DIR)/moc_qwt_dyngrid_layout.o \ + $(OBJ_DIR)/moc_qwt_knob.o \ + $(OBJ_DIR)/moc_qwt_legend.o \ + $(OBJ_DIR)/moc_qwt_legend_label.o \ + $(OBJ_DIR)/moc_qwt_magnifier.o \ + $(OBJ_DIR)/moc_qwt_panner.o \ + $(OBJ_DIR)/moc_qwt_picker.o \ + $(OBJ_DIR)/moc_qwt_plot_canvas.o \ + $(OBJ_DIR)/moc_qwt_plot.o \ + $(OBJ_DIR)/moc_qwt_plot_magnifier.o \ + $(OBJ_DIR)/moc_qwt_plot_panner.o \ + $(OBJ_DIR)/moc_qwt_plot_picker.o \ + $(OBJ_DIR)/moc_qwt_plot_renderer.o \ + $(OBJ_DIR)/moc_qwt_plot_zoomer.o \ + $(OBJ_DIR)/moc_qwt_sampling_thread.o \ + $(OBJ_DIR)/moc_qwt_scale_widget.o \ + $(OBJ_DIR)/moc_qwt_slider.o \ + $(OBJ_DIR)/moc_qwt_text_label.o \ + $(OBJ_DIR)/moc_qwt_thermo.o \ + $(OBJ_DIR)/moc_qwt_wheel.o \ + $(OBJ_DIR)/moc_ForceIP.o + +GEN_HEADERS = $(OBJ_DIR)/ui_ActionCommand.h \ + $(OBJ_DIR)/ui_DirectAccess.h \ + $(OBJ_DIR)/ui_OpenByID.h \ + $(OBJ_DIR)/ui_MainWindow.h \ + $(OBJ_DIR)/ui_SaveImageOption.h \ + $(OBJ_DIR)/ui_ViewerOption.h \ + $(OBJ_DIR)/ui_ViewerWindow.h \ + $(OBJ_DIR)/ui_OptionDialog.h \ + $(OBJ_DIR)/ui_SavingProgress.h \ + $(OBJ_DIR)/ui_StartOption.h \ + $(OBJ_DIR)/ui_ForceIP.h \ + +DEPENDENCIES = VimbaCPP \ + VimbaImageTransform \ + QtCore \ + QtGui \ + QtSvg + +$(OBJ_DIR)/moc_%.cpp: $(SOURCE_DIR)/%.h $(OBJ_DIR) + $(MOC) -o $@ $< + +$(OBJ_DIR)/moc_%.cpp: $(SOURCE_DIR)/ExternLib/qwt/%.h $(OBJ_DIR) + $(MOC) -o $@ $< + +$(OBJ_DIR)/moc_%.cpp: $(SOURCE_DIR)/UI/%.h $(OBJ_DIR) + $(MOC) -o $@ $< + +$(OBJ_DIR)/moc_%.cpp: $(SOURCE_DIR)/UI/HexEditor/%.h $(OBJ_DIR) + $(MOC) -o $@ $< + +$(OBJ_DIR)/moc_%.cpp: $(SOURCE_DIR)/UI/Histogram/%.h $(OBJ_DIR) + $(MOC) -o $@ $< + +$(OBJ_DIR)/ui_%.h: $(SOURCE_DIR)/%.ui $(OBJ_DIR) + $(UIC) -o $@ $< + +$(OBJ_DIR)/ui_%.h: $(SOURCE_DIR)/UI/HexEditor/%.ui $(OBJ_DIR) + $(UIC) -o $@ $< + +$(OBJ_DIR)/qrc_%.cpp: $(SOURCE_DIR)/%.qrc $(OBJ_DIR) + $(RCC) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(OBJ_DIR) $(GEN_HEADERS) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/ExternLib/qwt/%.cpp $(OBJ_DIR) $(GEN_HEADERS) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/UI/%.cpp $(OBJ_DIR) $(GEN_HEADERS) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/UI/HexEditor/%.cpp $(OBJ_DIR) $(GEN_HEADERS) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(SOURCE_DIR)/UI/Histogram/%.cpp $(OBJ_DIR) $(GEN_HEADERS) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(OBJ_DIR)/%.o: $(OBJ_DIR)/%.cpp $(OBJ_DIR) $(GEN_HEADERS) + $(CXX) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) -o $@ $< + +$(BIN_PATH): $(DEPENDENCIES) $(OBJ_FILES) $(BIN_DIR) + $(CXX) $(ARCH_CFLAGS) -o $(BIN_PATH) $(OBJ_FILES) $(LIBS) -Wl,-rpath,'$$ORIGIN' + +clean: + $(RM) binary -r -f + $(RM) object -r -f + +$(OBJ_DIR): + $(MKDIR) -p $(OBJ_DIR) + +$(BIN_DIR): + $(MKDIR) -p $(BIN_DIR) diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ActionCommand.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ActionCommand.cpp new file mode 100644 index 0000000..b345d71 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ActionCommand.cpp @@ -0,0 +1,648 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ActionCommand.cpp + + Description: Dialog for creating and sending Action Commands + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 "ActionCommand.h" + +typedef enum eInterfaceIndex +{ + eInterfaceIndexUnknown = -2, + eInterfaceIndexAll = -1 + +} eInterfaceIndex; + +ActionCommandDialog::ActionCommandDialog( AVT::VmbAPI::VimbaSystem &system ) + : m_Dialog( NULL ) + , m_Sys( system ) + , m_Interfaces( NULL ) + , m_SelectedInterface( eInterfaceIndexUnknown ) + , m_Unicast( false ) + , m_MsgBox( NULL ) + , m_FeatureList( NULL ) + , m_FeatureValues( NULL ) +{ + bool check = false; + + // create and setup Qt dialog + this->m_Dialog = new QDialog( this, windowFlags() & ~Qt::WindowContextHelpButtonHint & ~Qt::WindowMinimizeButtonHint & ~Qt::WindowMaximizeButtonHint ); + this->m_Ui.setupUi( m_Dialog ); + this->m_Dialog->setFixedSize( 790, 340 ); + + // create interface vector + this->m_Interfaces = new QVector(); + + // connect slots + check = connect( this->m_Ui.pushButton_Send, SIGNAL(clicked(bool)), this, SLOT(OnSendButtonActionCommand(void)) ); + check = connect( this->m_Ui.checkBox_singleDevice, SIGNAL(clicked(bool)), this, SLOT(OnCheckBoxSingleDevice(void)) ); + check = connect( this->m_Ui.checkBox_networkInterface, SIGNAL(clicked(bool)), this, SLOT(OnCheckBoxNetworkInterface(void)) ); + check = connect( this->m_Ui.comboBox_networkInterface, SIGNAL(currentIndexChanged(int)), this, SLOT(OnComboBoxNetworkInterface(int)) ); + + // setup message box + this->m_MsgBox = new QMessageBox( this ); + + // setup feature list + this->m_FeatureList = new QVector(); + this->m_FeatureList->append( "ActionDeviceKey" ); + this->m_FeatureList->append( "ActionGroupKey" ); + this->m_FeatureList->append( "ActionGroupMask" ); + this->m_FeatureList->append( "ActionCommand" ); + + // setup feature value list + this->m_FeatureValues = new QVector(); + + // disable ip input for unicast + // and set network selection as unchecked + this->m_Ui.lineEdit_singleDevice->setEnabled( false ); + this->m_Ui.checkBox_networkInterface->setChecked( false ); +} + +ActionCommandDialog::~ActionCommandDialog() +{ + // delete Qt dialog + if( NULL != m_Dialog ) + { + delete m_Dialog; + } + + // delete interface vector + if( NULL != m_Interfaces ) + { + delete m_Interfaces; + } + + // delete message box + if( NULL != m_MsgBox ) + { + delete m_MsgBox; + } + + // delete feature list + if( NULL != m_FeatureList ) + { + delete m_FeatureList; + } + + // delete feature value list + if( NULL != m_FeatureValues ) + { + delete m_FeatureValues; + } +} + +void ActionCommandDialog::RunDialog() +{ + VmbErrorType err = VmbErrorSuccess; + bool check = false; + bool failureFlag = true; + int rval = 0; + QString msg = ""; + + if( NULL != this->m_Dialog ) + { + // reset dialog + ResetDialog(); + + try + { + // get avaialable interfaces from Vimba + // and fill combo box (GigE only) + err = this->CreateInterfaceList(); + if( VmbErrorSuccess != err ) + { + throw std::exception(); + } + + // run dialog + this->m_Dialog->show(); + } + catch( std::exception& /*e*/ ) + { + this->ShowMsgBox(); + } + catch(...) + { + this->ShowMsgBox(); + } + + if( (VmbErrorSuccess == err) && (QDialog::Accepted == rval) ) + { + this->PrepareMsgBox( QMessageBox::Information, "Action Command has been sent successfully", VmbErrorSuccess ); + this->ShowMsgBox(); + } + + } +} + +void ActionCommandDialog::OnSendButtonActionCommand() +{ + bool check = false; + VmbErrorType err = VmbErrorSuccess; + VmbInt64_t ipAddress = 0; + QString msg = ""; + AVT::VmbAPI::InterfacePtr selectedInterface; + + try + { + // clear feature values + this->m_FeatureValues->clear(); + + // get deviceKey from user input + check = this->GetDeviceKey(); + if( false == check ) + { + this->PrepareMsgBox( QMessageBox::Critical, "Invalid Device Key entered", VmbErrorBadParameter ); + throw std::exception(); + } + + // get groupKey from user input + check = this->GetGroupKey(); + if( false == check ) + { + this->PrepareMsgBox( QMessageBox::Critical, "Invalid Group Key entered", VmbErrorBadParameter ); + throw std::exception(); + } + + // get groupMask from user input + check = this->GetGroupMask(); + if( false == check ) + { + this->PrepareMsgBox( QMessageBox::Critical, "Invalid Group Mask entered", VmbErrorBadParameter ); + throw std::exception(); + } + + // if unicast is enabled, get IP address + if( true == this->m_Unicast ) + { + ipAddress = this->GetIpAddress(); + if( -1 == ipAddress ) + { + this->PrepareMsgBox( QMessageBox::Critical, "Invalid IP address entered", VmbErrorBadParameter ); + throw std::exception(); + } + } + + // check if specific interface was selcted + if( eInterfaceIndexAll != this->m_SelectedInterface ) + { + // get interface pointer + selectedInterface = this->m_Interfaces->at( this->m_SelectedInterface ); + if( false == SP_ISNULL(selectedInterface) ) + { + // open interface + err = selectedInterface->Open(); + if( VmbErrorSuccess != err ) + { + this->PrepareMsgBox( QMessageBox::Critical, "Failed to open interface", err ); + throw std::exception(); + } + } + } + + // proceed if no error occured + if( VmbErrorSuccess == err ) + { + // iterate through feature names and values + for( int i=0; i<3; ++i ) + { + // get current feature name and corresponding value to set + QString featureName = m_FeatureList->at(i); + VmbInt64_t featureValue = m_FeatureValues->at(i); + + // set feature value + err = this->SetFeatureValue( featureName, featureValue, this->m_SelectedInterface ); + if( VmbErrorSuccess != err ) + { + throw std::exception(); + } + } + } + + // if unicast is enabled, set corresponding ip feature + if( true == this->m_Unicast ) + { + // get feature pointer + AVT::VmbAPI::FeaturePtr feature; + const char *featureName = "GevActionDestinationIPAddress"; + if( eInterfaceIndexAll == this->m_SelectedInterface ) + { + err = this->m_Sys.GetFeatureByName( featureName, feature ); + } + else + { + err = selectedInterface->GetFeatureByName( featureName, feature ); + } + + if( VmbErrorSuccess == err ) + { + // set feature value + err = feature->SetValue( ipAddress ); + if( VmbErrorSuccess != err ) + { + msg = "Failed to set feature value '" + QString::number(ipAddress) + "' for '" + QString(featureName) + "'"; + this->PrepareMsgBox( QMessageBox::Critical, msg, err ); + throw std::exception(); + } + } + else + { + msg = "Failed to retrieve feature pointer for '" + QString(featureName) + "'"; + this->PrepareMsgBox( QMessageBox::Critical, msg, err ); + throw std::exception(); + } + } + + // send Action Command + err = this->SendCommand( this->m_SelectedInterface ); + if( VmbErrorSuccess != err ) + { + throw std::exception(); + } + + this->LogActionCommand(); + + // close interface, if one selected and opened + if( eInterfaceIndexAll != this->m_SelectedInterface ) + { + if( false == SP_ISNULL( selectedInterface ) ) + { + err = selectedInterface->Close(); + if( VmbErrorSuccess != err ) + { + this->PrepareMsgBox( QMessageBox::Critical, "Failed to close interface", err ); + throw std::exception(); + } + } + } + + } + catch( std::exception& e ) + { + this->ShowMsgBox(); + } + catch(...) + { + this->ShowMsgBox(); + } +} + +void ActionCommandDialog::OnComboBoxNetworkInterface( int index ) +{ + // get selected interface index + this->m_SelectedInterface = index; +} + +void ActionCommandDialog::OnCheckBoxNetworkInterface() +{ + // if checkbox was checked, + // set internal variable accordingly + if( true == this->m_Ui.checkBox_networkInterface->isChecked() ) + { + this->m_Ui.comboBox_networkInterface->setEnabled( false ); + this->m_SelectedInterface = eInterfaceIndexAll; + } + else + { + this->m_Ui.comboBox_networkInterface->setEnabled( true ); + this->m_SelectedInterface = this->m_Ui.comboBox_networkInterface->currentIndex(); + } +} + +void ActionCommandDialog::OnCheckBoxSingleDevice() +{ + // if checkbox was checked, + // set internal variable accordingly + if( true == this->m_Ui.checkBox_singleDevice->isChecked() ) + { + this->m_Ui.lineEdit_singleDevice->setEnabled( true ); + this->m_Unicast = true; + } + else + { + this->m_Ui.lineEdit_singleDevice->setEnabled( false ); + this->m_Unicast = false; + } +} + +VmbErrorType ActionCommandDialog::CreateInterfaceList() +{ + VmbErrorType err = VmbErrorOther; + QString msg = "Failed to retrieve interfaces"; + + // get interfaces from vimba + AVT::VmbAPI::InterfacePtrVector interfaceList; + err = m_Sys.GetInterfaces( interfaceList ); + if( VmbErrorSuccess == err ) + { + // iterate through Vimba interface list + // and retrieve IDs (ethernet only) + AVT::VmbAPI::InterfacePtrVector::iterator iter; + for( iter = interfaceList.begin(); + iter != interfaceList.end(); + ++iter ) + { + // determine interface type + VmbInterfaceType interfaceType; + err = (*iter)->GetType( interfaceType ); + if( VmbErrorSuccess == err ) + { + if( VmbInterfaceEthernet == interfaceType ) + { + // store current interface to internal vector + this->m_Interfaces->append( *iter ); + + // get interface ID + std::string interfaceId = ""; + err = (*iter)->GetID( interfaceId ); + if( VmbErrorSuccess == err ) + { + this->m_Ui.comboBox_networkInterface->addItem( QString(interfaceId.c_str()) ); + } + else + { + msg += QString( ". GetID() failed" ); + this->PrepareMsgBox( QMessageBox::Critical, msg, err ); + break; + } + } + } + else + { + msg += QString( ". Unable to determine interface type" ); + this->PrepareMsgBox( QMessageBox::Critical, msg, err ); + break; + } + } + } + else + { + this->PrepareMsgBox( QMessageBox::Critical, msg, err ); + } + + // in case of any failure, + // show message box + if( VmbErrorSuccess == err ) + { + this->m_Ui.comboBox_networkInterface->setCurrentIndex( 0 ); + this->m_SelectedInterface = 0; + } + + return err; +} + +VmbErrorType ActionCommandDialog::SetFeatureValue( QString featureName, VmbInt64_t featureValue, int selectedInterface ) +{ + VmbErrorType err = VmbErrorSuccess; + QString msg = ""; + AVT::VmbAPI::InterfacePtr interfacePtr; + AVT::VmbAPI::FeaturePtr feature; + + // check parameter + if( false == featureName.isEmpty() ) + { + // check if 'all interfaces' is selected + if( eInterfaceIndexAll == selectedInterface ) + { + // get feature pointer + err = this->m_Sys.GetFeatureByName( featureName.toStdString().c_str(), feature ); + if( VmbErrorSuccess != err ) + { + msg = "Failed to retrieve feature '" + featureName + "'"; + this->PrepareMsgBox( QMessageBox::Critical, msg, err ); + } + } + else + { + // get feature pointer + interfacePtr = this->m_Interfaces->at( selectedInterface ); + if( false == SP_ISNULL( interfacePtr ) ) + { + err = interfacePtr->GetFeatureByName( featureName.toStdString().c_str(), feature ); + if( VmbErrorSuccess != err ) + { + msg = "Failed to retrieve feature '" + featureName + "' from selected interface"; + this->PrepareMsgBox( QMessageBox::Critical, msg, err ); + } + } + } + + if( VmbErrorSuccess == err ) + { + // set given feature value + err = feature->SetValue( featureValue ); + if( VmbErrorSuccess != err ) + { + msg = "Failed to set feature value '" + QString::number(featureValue) + "' for '" + featureName + "'"; + this->PrepareMsgBox( QMessageBox::Critical, msg, err ); + } + } + } + + return err; +} + +bool ActionCommandDialog::GetDeviceKey() +{ + bool rval = true; + + // get user input from device key field + QString stringValue = this->m_Ui.lineEdit_DeviceKey->text(); + if( false == stringValue.isEmpty() ) + { + // convert string value to integer + VmbInt64_t intValue = stringValue.toUInt( &rval ); + if( true == rval ) + { + this->m_FeatureValues->append( intValue ); + } + } + else + { + rval = false; + } + + return rval; +} + +bool ActionCommandDialog::GetGroupKey() +{ + bool rval = true; + + // get user input from group key field + QString stringValue = this->m_Ui.lineEdit_GroupKey->text(); + if( false == stringValue.isEmpty() ) + { + // convert string value to integer + VmbInt64_t intValue = stringValue.toUInt( &rval ); + if( true == rval ) + { + this->m_FeatureValues->append( intValue ); + } + } + else + { + rval = false; + } + + return rval; +} + +bool ActionCommandDialog::GetGroupMask() +{ + bool rval = true; + + // get user input from group mask field + QString stringValue = this->m_Ui.lineEdit_GroupMask->text(); + if( false == stringValue.isEmpty() ) + { + // convert string value to integer + VmbInt64_t intValue = stringValue.toUInt( &rval ); + if( true == rval ) + { + this->m_FeatureValues->append( intValue ); + } + } + else + { + rval = false; + } + + return rval; +} + +VmbInt64_t ActionCommandDialog::GetIpAddress() +{ + VmbInt64_t rval = 0; + + // get user input from ip address field + QString stringValue = this->m_Ui.lineEdit_singleDevice->text(); + if( false == stringValue.isEmpty() ) + { + // convert ip address string to integer value + VmbInt64_t intValue = Helper::StringToIPv4( stringValue); + if( -1 != intValue ) + { + rval = intValue; + } + } + else + { + rval = -1; + } + + return rval; +} + +VmbErrorType ActionCommandDialog::SendCommand( int selectedInterface ) +{ + VmbErrorType err = VmbErrorSuccess; + QString msg = ""; + AVT::VmbAPI::FeaturePtr feature; + + // get feature name for sending Action Command + QString featureName = this->m_FeatureList->at(3); + + // get feature pointer + // on interface or system level (all interfaces) + if( eInterfaceIndexAll == selectedInterface ) + { + err = m_Sys.GetFeatureByName( featureName.toStdString().c_str(), feature ); + } + else + { + AVT::VmbAPI::InterfacePtr interfacePtr = this->m_Interfaces->at( selectedInterface ); + if( false == SP_ISNULL(interfacePtr) ) + { + err = interfacePtr->GetFeatureByName( featureName.toStdString().c_str(), feature ); + } + } + + if( VmbErrorSuccess == err ) + { + // send action command + err = feature->RunCommand(); + if( VmbErrorSuccess != err ) + { + this->PrepareMsgBox( QMessageBox::Critical, "Failed to send Action Command", err ); + } + } + else + { + msg = "Failed to retrieve feature '" + featureName + "'"; + this->PrepareMsgBox( QMessageBox::Critical, msg, err ); + } + + return err; +} + +void ActionCommandDialog::PrepareMsgBox( QMessageBox::Icon icon, QString text, VmbErrorType err ) +{ + if( NULL != this->m_MsgBox ) + { + this->m_MsgBox->setIcon( icon ); + QString msg = text; + if( 0 != err ) + { + msg + ".\n[error code: " + QString::number(err) + "]"; + } + this->m_MsgBox->setText( msg ); + } +} + +void ActionCommandDialog::ShowMsgBox() +{ + if( NULL != this->m_MsgBox ) + { + this->m_MsgBox->exec(); + } +} + +void ActionCommandDialog::ResetDialog() +{ + // network interface group + this->m_Ui.comboBox_networkInterface->clear(); + this->m_Ui.comboBox_networkInterface->setEnabled( true ); + this->m_Ui.checkBox_networkInterface->setChecked( false ); + this->m_SelectedInterface = eInterfaceIndexUnknown; + + // action command group + this->m_FeatureValues->clear(); + + // single device group + this->m_Ui.lineEdit_singleDevice->setEnabled( false ); + this->m_Ui.checkBox_singleDevice->setChecked( false ); + + // command log + this->m_Ui.listWidget_commandLog->clear(); +} + +void ActionCommandDialog::LogActionCommand() +{ + QTime timeStamp; + QString temp; + temp = timeStamp.currentTime().toString() + QString( "..." ) + QString( "Action Command has been sent" ); + this->m_Ui.listWidget_commandLog->insertItem( 0, temp ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ActionCommand.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ActionCommand.h new file mode 100644 index 0000000..8e549ad --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ActionCommand.h @@ -0,0 +1,85 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: ActionCommand.h + + Description: Dialog for creating and sending Action Commands + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + +#ifndef ACTION_COMMAND_H +#define ACTION_COMMAND_H + +#include "Helper.h" +#include "ui_ActionCommand.h" +#include +#include +#include + +class ActionCommandDialog : public QDialog +{ + Q_OBJECT + + private: + Ui::ActionCommandDialog m_Ui; + QDialog *m_Dialog; + AVT::VmbAPI::VimbaSystem &m_Sys; + QVector *m_Interfaces; + int m_SelectedInterface; + bool m_Unicast; + QMessageBox *m_MsgBox; + QVector *m_FeatureList; + QVector *m_FeatureValues; + + public: + ActionCommandDialog( AVT::VmbAPI::VimbaSystem &system ); + ~ActionCommandDialog(); + + void RunDialog(); + + private slots: + void OnSendButtonActionCommand(); + void OnComboBoxNetworkInterface( int index ); + void OnCheckBoxNetworkInterface( void ); + void OnCheckBoxSingleDevice( void ); + + private: + VmbErrorType CreateInterfaceList(); + VmbErrorType SetFeatureValue( QString featureName, VmbInt64_t featureValue, int selectedInterface ); + + bool GetDeviceKey(); + bool GetGroupKey(); + bool GetGroupMask(); + VmbInt64_t GetIpAddress(); + + VmbErrorType SendCommand( int selectedInterface ); + + void PrepareMsgBox( QMessageBox::Icon icon, QString text, VmbErrorType err ); + void ShowMsgBox(); + + void ResetDialog(); + void LogActionCommand(); + + +}; + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ActionCommand.ui b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ActionCommand.ui new file mode 100644 index 0000000..e99910f --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ActionCommand.ui @@ -0,0 +1,561 @@ + + + ActionCommandDialog + + + + 0 + 0 + 790 + 333 + + + + + 0 + 0 + + + + Trigger over Ethernet - Action Commands + + + + Images/stripes_256.pngImages/stripes_256.png + + + + + 10 + 10 + 381 + 151 + + + + Network Interface + + + + + 20 + 30 + 360 + 102 + + + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + + 16777215 + 20 + + + + Select Interface + + + + + + + + 0 + 0 + + + + + 250 + 20 + + + + + 16777215 + 20 + + + + + + + + + 0 + 20 + + + + + 16777215 + 20 + + + + All Interfaces + + + + + + + Qt::Horizontal + + + + 188 + 20 + + + + + + + + + + + 0 + 0 + + + + + 100 + 100 + + + + + 100 + 100 + + + + + + + :/VimbaViewer/Images/network.png + + + true + + + + + + + + + + 410 + 10 + 361 + 151 + + + + Action Command + + + + + 20 + 30 + 318 + 105 + + + + + + + + + + 0 + 0 + + + + + 100 + 20 + + + + + 100 + 20 + + + + Device Key + + + + + + + + 0 + 0 + + + + + 100 + 20 + + + + + 100 + 20 + + + + Group Key + + + + + + + + 0 + 0 + + + + + 100 + 20 + + + + + 100 + 20 + + + + Group Mask + + + + + + + + + + + + 0 + 0 + + + + + 125 + 20 + + + + + 125 + 20 + + + + + + + + + 0 + 0 + + + + + 125 + 20 + + + + + 125 + 20 + + + + + + + + + 0 + 0 + + + + + 125 + 20 + + + + + 125 + 20 + + + + + + + + + + + 0 + 0 + + + + + 75 + 75 + + + + + 75 + 75 + + + + + + + :/VimbaViewer/Images/actionCommand.png + + + true + + + + + + + + + Qt::Horizontal + + + + 100 + 20 + + + + + + + + + 0 + 0 + + + + + 75 + 20 + + + + + 75 + 20 + + + + Send + + + + + + + + 0 + 0 + + + + + 75 + 20 + + + + + 75 + 20 + + + + Cancel + + + + + + + + + + + + 10 + 170 + 381 + 151 + + + + Single Device + + + + + 20 + 30 + 331 + 45 + + + + + + + + 120 + 20 + + + + + 120 + 20 + + + + + 120 + 16777215 + + + + Destination IP Address + + + + + + + + 20 + 200 + + + + + 200 + 20 + + + + + 200 + 20 + + + + + + + + Enable Unicast + + + + + + + + + + 410 + 170 + 361 + 151 + + + + Command Log + + + + + 20 + 30 + 311 + 101 + + + + + + + + + + + pushButton_Cancel + clicked() + ActionCommandDialog + reject() + + + 621 + 142 + + + 292 + 133 + + + + + diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/CameraObserver.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/CameraObserver.cpp new file mode 100644 index 0000000..fcec04e --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/CameraObserver.cpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: CameraObserver.cpp + + Description: A notification whenever device list has been changed + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 "CameraObserver.h" + +CameraObserver::CameraObserver ( void ) +{ + +} + +CameraObserver::~CameraObserver ( void ) +{ + +} + +void CameraObserver::CameraListChanged ( AVT::VmbAPI::CameraPtr pCam, AVT::VmbAPI::UpdateTriggerType reason ) +{ + emit updateDeviceList ( ); +} \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/CameraObserver.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/CameraObserver.h new file mode 100644 index 0000000..fe596ae --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/CameraObserver.h @@ -0,0 +1,62 @@ +/*============================================================================= + Copyright (C) 2012 Allied Vision Technologies. All Rights Reserved. + + Redistribution of this file, in original or modified form, without + prior written consent of Allied Vision Technologies is prohibited. + +------------------------------------------------------------------------------- + + File: CameraObserver.h + + Description: A notification whenever device list has been changed + + +------------------------------------------------------------------------------- + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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. + +=============================================================================*/ + + +#ifndef CAMERAOBSERVER_H +#define CAMERAOBSERVER_H + +#include +#include +#include +#include + + +class CameraObserver : public QObject, public AVT::VmbAPI::ICameraListObserver +{ + Q_OBJECT + + public: + + CameraObserver(void); + ~CameraObserver(void); + + virtual void CameraListChanged( AVT::VmbAPI::CameraPtr pCam, AVT::VmbAPI::UpdateTriggerType reason ); + + protected: + private: + + + signals: + void updateDeviceList ( void ); + + + +}; + +typedef AVT::VmbAPI::shared_ptr QtCameraObserverPtr; +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ControllerViewer.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ControllerViewer.h new file mode 100644 index 0000000..dd05f5b --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ControllerViewer.h @@ -0,0 +1,49 @@ +#pragma once + + +#ifndef CONTROLLERVIEWER_H +#define CONTROLLERVIEWER_H + +//TODO sort the header you dont need +#include + + + +class ControllerViewer : public QTreeView +{ + Q_OBJECT + public: + ControllerViewer ( QWidget *parent = 0 ); + ~ControllerViewer(); + void SetupTree( void ); + + QStandardItemModel *m_Model; + + protected: + private: + + public: + + + + protected: + + private: + +private slots: + +signals: + + +}; + + + + + + + + + + +#endif \ No newline at end of file diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/DirectAccess.ui b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/DirectAccess.ui new file mode 100644 index 0000000..ce9b6e3 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/DirectAccess.ui @@ -0,0 +1,173 @@ + + + DirectAccessDialog + + + + 0 + 0 + 439 + 160 + + + + + 400 + 160 + + + + + 500 + 160 + + + + Direct Access + + + + + 9 + 10 + 421 + 144 + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + + + + + + + + + + Register Address: + + + + + + + 0x + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Data: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 0x + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + The register content shown in endianess of the device + + + + + + + Data: + + + + + + + Dec + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + The decimal representation of the register content + + + + + + + Convert the decimal value to little endian + + + Little endian device + + + + + + + The register address + + + + + + + + + + + READ + + + + + + + WRITE + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt.h new file mode 100644 index 0000000..4936d9a --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt.h @@ -0,0 +1,22 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_H +#define QWT_H + +#include "qwt_global.h" + +/*! + Some constants for use within Qwt. +*/ +namespace Qwt +{ +} + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_legend.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_legend.cpp new file mode 100644 index 0000000..7f49648 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_legend.cpp @@ -0,0 +1,38 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_abstract_legend.h" + +/*! + Constructor + + \param parent Parent widget +*/ +QwtAbstractLegend::QwtAbstractLegend( QWidget *parent ): + QFrame( parent ) +{ +} + +//! Destructor +QwtAbstractLegend::~QwtAbstractLegend() +{ +} + +/*! + Return the extent, that is needed for elements to scroll + the legend ( usually scrollbars ), + + \param orientation Orientation + \return Extent of the corresponding scroll element +*/ +int QwtAbstractLegend::scrollExtent( Qt::Orientation orientation ) const +{ + Q_UNUSED( orientation ); + return 0; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_legend.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_legend.h new file mode 100644 index 0000000..a17f360 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_legend.h @@ -0,0 +1,71 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_ABSTRACT_LEGEND_H +#define QWT_ABSTRACT_LEGEND_H + +#include "qwt_global.h" +#include "qwt_legend_data.h" +#include +#include + +class QVariant; + +/*! + \brief Abstract base class for legend widgets + + Legends, that need to be under control of the QwtPlot layout system + need to be derived from QwtAbstractLegend. + + \note Other type of legends can be implemented by connecting to + the QwtPlot::legendDataChanged() signal. But as these legends + are unknown to the plot layout system the layout code + ( on screen and for QwtPlotRenderer ) need to be organized + in application code. + + \sa QwtLegend + */ +class QWT_EXPORT QwtAbstractLegend : public QFrame +{ + Q_OBJECT + +public: + explicit QwtAbstractLegend( QWidget *parent = NULL ); + virtual ~QwtAbstractLegend(); + + /*! + Render the legend into a given rectangle. + + \param painter Painter + \param rect Bounding rectangle + \param fillBackground When true, fill rect with the widget background + + \sa renderLegend() is used by QwtPlotRenderer + */ + virtual void renderLegend( QPainter *painter, + const QRectF &rect, bool fillBackground ) const = 0; + + //! \return True, when no plot item is inserted + virtual bool isEmpty() const = 0; + + virtual int scrollExtent( Qt::Orientation ) const; + +public Q_SLOTS: + + /*! + \brief Update the entries for a plot item + + \param itemInfo Info about an item + \param data List of legend entry attributes for the item + */ + virtual void updateLegend( const QVariant &itemInfo, + const QList &data ) = 0; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_scale.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_scale.cpp new file mode 100644 index 0000000..4eaf62a --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_scale.cpp @@ -0,0 +1,449 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_abstract_scale.h" +#include "qwt_scale_engine.h" +#include "qwt_scale_draw.h" +#include "qwt_scale_div.h" +#include "qwt_scale_map.h" +#include "qwt_interval.h" + +class QwtAbstractScale::PrivateData +{ +public: + PrivateData(): + maxMajor( 5 ), + maxMinor( 3 ), + stepSize( 0.0 ) + { + scaleEngine = new QwtLinearScaleEngine(); + scaleDraw = new QwtScaleDraw(); + } + + ~PrivateData() + { + delete scaleEngine; + delete scaleDraw; + } + + QwtScaleEngine *scaleEngine; + QwtAbstractScaleDraw *scaleDraw; + + int maxMajor; + int maxMinor; + double stepSize; +}; + +/*! + Constructor + + \param parent Parent widget + + Creates a default QwtScaleDraw and a QwtLinearScaleEngine. + The initial scale boundaries are set to [ 0.0, 100.0 ] + + The scaleStepSize() is initialized to 0.0, scaleMaxMajor() to 5 + and scaleMaxMajor to 3. +*/ + +QwtAbstractScale::QwtAbstractScale( QWidget *parent ): + QWidget( parent ) +{ + d_data = new PrivateData; + rescale( 0.0, 100.0, d_data->stepSize ); +} + +//! Destructor +QwtAbstractScale::~QwtAbstractScale() +{ + delete d_data; +} + +/*! + Set the lower bound of the scale + + \param value Lower bound + + \sa lowerBound(), setScale(), setUpperBound() + \note For inverted scales the lower bound + is greater than the upper bound +*/ +void QwtAbstractScale::setLowerBound( double value ) +{ + setScale( value, upperBound() ); +} + +/*! + \return Lower bound of the scale + \sa setLowerBound(), setScale(), upperBound() +*/ +double QwtAbstractScale::lowerBound() const +{ + return d_data->scaleDraw->scaleDiv().lowerBound(); +} + +/*! + Set the upper bound of the scale + + \param value Upper bound + + \sa upperBound(), setScale(), setLowerBound() + \note For inverted scales the lower bound + is greater than the upper bound +*/ +void QwtAbstractScale::setUpperBound( double value ) +{ + setScale( lowerBound(), value ); +} + +/*! + \return Upper bound of the scale + \sa setUpperBound(), setScale(), lowerBound() +*/ +double QwtAbstractScale::upperBound() const +{ + return d_data->scaleDraw->scaleDiv().upperBound(); +} + +/*! + \brief Specify a scale. + + Define a scale by an interval + + The ticks are calculated using scaleMaxMinor(), + scaleMaxMajor() and scaleStepSize(). + + \param lowerBound lower limit of the scale interval + \param upperBound upper limit of the scale interval + + \note For inverted scales the lower bound + is greater than the upper bound +*/ +void QwtAbstractScale::setScale( double lowerBound, double upperBound ) +{ + rescale( lowerBound, upperBound, d_data->stepSize ); +} + +/*! + \brief Specify a scale. + + Define a scale by an interval + + The ticks are calculated using scaleMaxMinor(), + scaleMaxMajor() and scaleStepSize(). + + \param interval Interval +*/ +void QwtAbstractScale::setScale( const QwtInterval &interval ) +{ + setScale( interval.minValue(), interval.maxValue() ); +} + +/*! + \brief Specify a scale. + + scaleMaxMinor(), scaleMaxMajor() and scaleStepSize() and have no effect. + + \param scaleDiv Scale division + \sa setAutoScale() +*/ +void QwtAbstractScale::setScale( const QwtScaleDiv &scaleDiv ) +{ + if ( scaleDiv != d_data->scaleDraw->scaleDiv() ) + { +#if 1 + if ( d_data->scaleEngine ) + { + d_data->scaleDraw->setTransformation( + d_data->scaleEngine->transformation() ); + } +#endif + + d_data->scaleDraw->setScaleDiv( scaleDiv ); + + scaleChange(); + } +} + +/*! + \brief Set the maximum number of major tick intervals. + + The scale's major ticks are calculated automatically such that + the number of major intervals does not exceed ticks. + + The default value is 5. + + \param ticks Maximal number of major ticks. + + \sa scaleMaxMajor(), setScaleMaxMinor(), + setScaleStepSize(), QwtScaleEngine::divideInterval() +*/ +void QwtAbstractScale::setScaleMaxMajor( int ticks ) +{ + if ( ticks != d_data->maxMajor ) + { + d_data->maxMajor = ticks; + updateScaleDraw(); + } +} + +/*! + \return Maximal number of major tick intervals + \sa setScaleMaxMajor(), scaleMaxMinor() +*/ +int QwtAbstractScale::scaleMaxMajor() const +{ + return d_data->maxMajor; +} + +/*! + \brief Set the maximum number of minor tick intervals + + The scale's minor ticks are calculated automatically such that + the number of minor intervals does not exceed ticks. + The default value is 3. + + \param ticks Maximal number of minor ticks. + + \sa scaleMaxMajor(), setScaleMaxMinor(), + setScaleStepSize(), QwtScaleEngine::divideInterval() +*/ +void QwtAbstractScale::setScaleMaxMinor( int ticks ) +{ + if ( ticks != d_data->maxMinor ) + { + d_data->maxMinor = ticks; + updateScaleDraw(); + } +} + +/*! + \return Maximal number of minor tick intervals + \sa setScaleMaxMinor(), scaleMaxMajor() +*/ +int QwtAbstractScale::scaleMaxMinor() const +{ + return d_data->maxMinor; +} + +/*! + \brief Set the step size used for calculating a scale division + + The step size is hint for calculating the intervals for + the major ticks of the scale. A value of 0.0 is interpreted + as no hint. + + \param stepSize Hint for the step size of the scale + + \sa scaleStepSize(), QwtScaleEngine::divideScale() + + \note Position and distance between the major ticks also + depends on scaleMaxMajor(). +*/ +void QwtAbstractScale::setScaleStepSize( double stepSize ) +{ + if ( stepSize != d_data->stepSize ) + { + d_data->stepSize = stepSize; + updateScaleDraw(); + } +} + +/*! + \return Hint for the step size of the scale + \sa setScaleStepSize(), QwtScaleEngine::divideScale() +*/ +double QwtAbstractScale::scaleStepSize() const +{ + return d_data->stepSize; +} + +/*! + \brief Set a scale draw + + scaleDraw has to be created with new and will be deleted in + the destructor or the next call of setAbstractScaleDraw(). + + \sa abstractScaleDraw() +*/ +void QwtAbstractScale::setAbstractScaleDraw( QwtAbstractScaleDraw *scaleDraw ) +{ + if ( scaleDraw == NULL || scaleDraw == d_data->scaleDraw ) + return; + + if ( d_data->scaleDraw != NULL ) + scaleDraw->setScaleDiv( d_data->scaleDraw->scaleDiv() ); + + delete d_data->scaleDraw; + d_data->scaleDraw = scaleDraw; +} + +/*! + \return Scale draw + \sa setAbstractScaleDraw() +*/ +QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw() +{ + return d_data->scaleDraw; +} + +/*! + \return Scale draw + \sa setAbstractScaleDraw() +*/ +const QwtAbstractScaleDraw *QwtAbstractScale::abstractScaleDraw() const +{ + return d_data->scaleDraw; +} + +/*! + \brief Set a scale engine + + The scale engine is responsible for calculating the scale division + and provides a transformation between scale and widget coordinates. + + scaleEngine has to be created with new and will be deleted in + the destructor or the next call of setScaleEngine. +*/ +void QwtAbstractScale::setScaleEngine( QwtScaleEngine *scaleEngine ) +{ + if ( scaleEngine != NULL && scaleEngine != d_data->scaleEngine ) + { + delete d_data->scaleEngine; + d_data->scaleEngine = scaleEngine; + } +} + +/*! + \return Scale engine + \sa setScaleEngine() +*/ +const QwtScaleEngine *QwtAbstractScale::scaleEngine() const +{ + return d_data->scaleEngine; +} + +/*! + \return Scale engine + \sa setScaleEngine() +*/ +QwtScaleEngine *QwtAbstractScale::scaleEngine() +{ + return d_data->scaleEngine; +} + +/*! + \return Scale boundaries and positions of the ticks + + The scale division might have been assigned explicitly + or calculated implicitly by rescale(). + */ +const QwtScaleDiv &QwtAbstractScale::scaleDiv() const +{ + return d_data->scaleDraw->scaleDiv(); +} + +/*! + \return Map to translate between scale and widget coordinates + */ +const QwtScaleMap &QwtAbstractScale::scaleMap() const +{ + return d_data->scaleDraw->scaleMap(); +} + +/*! + Translate a scale value into a widget coordinate + + \param value Scale value + \return Corresponding widget coordinate for value + \sa scaleMap(), invTransform() + */ +int QwtAbstractScale::transform( double value ) const +{ + return qRound( d_data->scaleDraw->scaleMap().transform( value ) ); +} + +/*! + Translate a widget coordinate into a scale value + + \param value Widget coordinate + \return Corresponding scale coordinate for value + \sa scaleMap(), transform() + */ +double QwtAbstractScale::invTransform( int value ) const +{ + return d_data->scaleDraw->scaleMap().invTransform( value ); +} + +/*! + \return True, when the scale is increasing in opposite direction + to the widget coordinates + */ +bool QwtAbstractScale::isInverted() const +{ + return d_data->scaleDraw->scaleMap().isInverting(); +} + +/*! + \return The boundary with the smaller value + \sa maximum(), lowerBound(), upperBound() + */ +double QwtAbstractScale::minimum() const +{ + return qMin( d_data->scaleDraw->scaleDiv().lowerBound(), + d_data->scaleDraw->scaleDiv().upperBound() ); +} + +/*! + \return The boundary with the larger value + \sa minimum(), lowerBound(), upperBound() + */ +double QwtAbstractScale::maximum() const +{ + return qMax( d_data->scaleDraw->scaleDiv().lowerBound(), + d_data->scaleDraw->scaleDiv().upperBound() ); +} + +//! Notify changed scale +void QwtAbstractScale::scaleChange() +{ +} + +/*! + Recalculate the scale division and update the scale. + + \param lowerBound Lower limit of the scale interval + \param upperBound Upper limit of the scale interval + \param stepSize Major step size + + \sa scaleChange() +*/ +void QwtAbstractScale::rescale( + double lowerBound, double upperBound, double stepSize ) +{ + const QwtScaleDiv scaleDiv = d_data->scaleEngine->divideScale( + lowerBound, upperBound, d_data->maxMajor, d_data->maxMinor, stepSize ); + + if ( scaleDiv != d_data->scaleDraw->scaleDiv() ) + { +#if 1 + d_data->scaleDraw->setTransformation( + d_data->scaleEngine->transformation() ); +#endif + + d_data->scaleDraw->setScaleDiv( scaleDiv ); + scaleChange(); + } +} + +void QwtAbstractScale::updateScaleDraw() +{ + rescale( d_data->scaleDraw->scaleDiv().lowerBound(), + d_data->scaleDraw->scaleDiv().upperBound(), d_data->stepSize ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_scale.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_scale.h new file mode 100644 index 0000000..15dd742 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_scale.h @@ -0,0 +1,105 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_ABSTRACT_SCALE_H +#define QWT_ABSTRACT_SCALE_H + +#include "qwt_global.h" +#include + +class QwtScaleEngine; +class QwtAbstractScaleDraw; +class QwtScaleDiv; +class QwtScaleMap; +class QwtInterval; + +/*! + \brief An abstract base class for widgets having a scale + + The scale of an QwtAbstractScale is determined by a QwtScaleDiv + definition, that contains the boundaries and the ticks of the scale. + The scale is painted using a QwtScaleDraw object. + + The scale division might be assigned explicitly - but usually + it is calculated from the boundaries using a QwtScaleEngine. + + The scale engine also decides the type of transformation of the scale + ( linear, logarithmic ... ). +*/ + +class QWT_EXPORT QwtAbstractScale: public QWidget +{ + Q_OBJECT + + Q_PROPERTY( double lowerBound READ lowerBound WRITE setLowerBound ) + Q_PROPERTY( double upperBound READ upperBound WRITE setUpperBound ) + + Q_PROPERTY( int scaleMaxMajor READ scaleMaxMajor WRITE setScaleMaxMajor ) + Q_PROPERTY( int scaleMaxMinor READ scaleMaxMinor WRITE setScaleMaxMinor ) + + Q_PROPERTY( double scaleStepSize READ scaleStepSize WRITE setScaleStepSize ) + +public: + QwtAbstractScale( QWidget *parent = NULL ); + virtual ~QwtAbstractScale(); + + void setScale( double lowerBound, double upperBound ); + void setScale( const QwtInterval & ); + void setScale( const QwtScaleDiv & ); + + const QwtScaleDiv& scaleDiv() const; + + void setLowerBound( double value ); + double lowerBound() const; + + void setUpperBound( double value ); + double upperBound() const; + + void setScaleStepSize( double stepSize ); + double scaleStepSize() const; + + void setScaleMaxMajor( int ticks ); + int scaleMaxMinor() const; + + void setScaleMaxMinor( int ticks ); + int scaleMaxMajor() const; + + void setScaleEngine( QwtScaleEngine * ); + const QwtScaleEngine *scaleEngine() const; + QwtScaleEngine *scaleEngine(); + + int transform( double ) const; + double invTransform( int ) const; + + bool isInverted() const; + + double minimum() const; + double maximum() const; + + const QwtScaleMap &scaleMap() const; + +protected: + void rescale( double lowerBound, + double upperBound, double stepSize ); + + void setAbstractScaleDraw( QwtAbstractScaleDraw * ); + + const QwtAbstractScaleDraw *abstractScaleDraw() const; + QwtAbstractScaleDraw *abstractScaleDraw(); + + virtual void scaleChange(); + +private: + void updateScaleDraw(); + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_scale_draw.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_scale_draw.cpp new file mode 100644 index 0000000..ee39cfd --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_scale_draw.cpp @@ -0,0 +1,420 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_abstract_scale_draw.h" +#include "qwt_math.h" +#include "qwt_text.h" +#include "qwt_painter.h" +#include "qwt_scale_map.h" +#include +#include +#include +#include + +class QwtAbstractScaleDraw::PrivateData +{ +public: + PrivateData(): + spacing( 4.0 ), + penWidth( 0 ), + minExtent( 0.0 ) + { + components = QwtAbstractScaleDraw::Backbone + | QwtAbstractScaleDraw::Ticks + | QwtAbstractScaleDraw::Labels; + + tickLength[QwtScaleDiv::MinorTick] = 4.0; + tickLength[QwtScaleDiv::MediumTick] = 6.0; + tickLength[QwtScaleDiv::MajorTick] = 8.0; + } + + ScaleComponents components; + + QwtScaleMap map; + QwtScaleDiv scaleDiv; + + double spacing; + double tickLength[QwtScaleDiv::NTickTypes]; + int penWidth; + + double minExtent; + + QMap labelCache; +}; + +/*! + \brief Constructor + + The range of the scale is initialized to [0, 100], + The spacing (distance between ticks and labels) is + set to 4, the tick lengths are set to 4,6 and 8 pixels +*/ +QwtAbstractScaleDraw::QwtAbstractScaleDraw() +{ + d_data = new QwtAbstractScaleDraw::PrivateData; +} + +//! Destructor +QwtAbstractScaleDraw::~QwtAbstractScaleDraw() +{ + delete d_data; +} + +/*! + En/Disable a component of the scale + + \param component Scale component + \param enable On/Off + + \sa hasComponent() +*/ +void QwtAbstractScaleDraw::enableComponent( + ScaleComponent component, bool enable ) +{ + if ( enable ) + d_data->components |= component; + else + d_data->components &= ~component; +} + +/*! + Check if a component is enabled + + \param component Component type + \return true, when component is enabled + \sa enableComponent() +*/ +bool QwtAbstractScaleDraw::hasComponent( ScaleComponent component ) const +{ + return ( d_data->components & component ); +} + +/*! + Change the scale division + \param scaleDiv New scale division +*/ +void QwtAbstractScaleDraw::setScaleDiv( const QwtScaleDiv &scaleDiv ) +{ + d_data->scaleDiv = scaleDiv; + d_data->map.setScaleInterval( scaleDiv.lowerBound(), scaleDiv.upperBound() ); + d_data->labelCache.clear(); +} + +/*! + Change the transformation of the scale + \param transformation New scale transformation +*/ +void QwtAbstractScaleDraw::setTransformation( + QwtTransform *transformation ) +{ + d_data->map.setTransformation( transformation ); +} + +//! \return Map how to translate between scale and pixel values +const QwtScaleMap &QwtAbstractScaleDraw::scaleMap() const +{ + return d_data->map; +} + +//! \return Map how to translate between scale and pixel values +QwtScaleMap &QwtAbstractScaleDraw::scaleMap() +{ + return d_data->map; +} + +//! \return scale division +const QwtScaleDiv& QwtAbstractScaleDraw::scaleDiv() const +{ + return d_data->scaleDiv; +} + +/*! + \brief Specify the width of the scale pen + \param width Pen width + \sa penWidth() +*/ +void QwtAbstractScaleDraw::setPenWidth( int width ) +{ + if ( width < 0 ) + width = 0; + + if ( width != d_data->penWidth ) + d_data->penWidth = width; +} + +/*! + \return Scale pen width + \sa setPenWidth() +*/ +int QwtAbstractScaleDraw::penWidth() const +{ + return d_data->penWidth; +} + +/*! + \brief Draw the scale + + \param painter The painter + + \param palette Palette, text color is used for the labels, + foreground color for ticks and backbone +*/ +void QwtAbstractScaleDraw::draw( QPainter *painter, + const QPalette& palette ) const +{ + painter->save(); + + QPen pen = painter->pen(); + pen.setWidth( d_data->penWidth ); + pen.setCosmetic( false ); + painter->setPen( pen ); + + if ( hasComponent( QwtAbstractScaleDraw::Labels ) ) + { + painter->save(); + painter->setPen( palette.color( QPalette::Text ) ); // ignore pen style + + const QList &majorTicks = + d_data->scaleDiv.ticks( QwtScaleDiv::MajorTick ); + + for ( int i = 0; i < majorTicks.count(); i++ ) + { + const double v = majorTicks[i]; + if ( d_data->scaleDiv.contains( v ) ) + drawLabel( painter, v ); + } + + painter->restore(); + } + + if ( hasComponent( QwtAbstractScaleDraw::Ticks ) ) + { + painter->save(); + + QPen pen = painter->pen(); + pen.setColor( palette.color( QPalette::WindowText ) ); + pen.setCapStyle( Qt::FlatCap ); + + painter->setPen( pen ); + + for ( int tickType = QwtScaleDiv::MinorTick; + tickType < QwtScaleDiv::NTickTypes; tickType++ ) + { + const double tickLen = d_data->tickLength[tickType]; + if ( tickLen <= 0.0 ) + continue; + + const QList &ticks = d_data->scaleDiv.ticks( tickType ); + for ( int i = 0; i < ticks.count(); i++ ) + { + const double v = ticks[i]; + if ( d_data->scaleDiv.contains( v ) ) + drawTick( painter, v, tickLen ); + } + } + + painter->restore(); + } + + if ( hasComponent( QwtAbstractScaleDraw::Backbone ) ) + { + painter->save(); + + QPen pen = painter->pen(); + pen.setColor( palette.color( QPalette::WindowText ) ); + pen.setCapStyle( Qt::FlatCap ); + + painter->setPen( pen ); + + drawBackbone( painter ); + + painter->restore(); + } + + painter->restore(); +} + +/*! + \brief Set the spacing between tick and labels + + The spacing is the distance between ticks and labels. + The default spacing is 4 pixels. + + \param spacing Spacing + + \sa spacing() +*/ +void QwtAbstractScaleDraw::setSpacing( double spacing ) +{ + if ( spacing < 0 ) + spacing = 0; + + d_data->spacing = spacing; +} + +/*! + \brief Get the spacing + + The spacing is the distance between ticks and labels. + The default spacing is 4 pixels. + + \return Spacing + \sa setSpacing() +*/ +double QwtAbstractScaleDraw::spacing() const +{ + return d_data->spacing; +} + +/*! + \brief Set a minimum for the extent + + The extent is calculated from the components of the + scale draw. In situations, where the labels are + changing and the layout depends on the extent (f.e scrolling + a scale), setting an upper limit as minimum extent will + avoid jumps of the layout. + + \param minExtent Minimum extent + + \sa extent(), minimumExtent() +*/ +void QwtAbstractScaleDraw::setMinimumExtent( double minExtent ) +{ + if ( minExtent < 0.0 ) + minExtent = 0.0; + + d_data->minExtent = minExtent; +} + +/*! + Get the minimum extent + \return Minimum extent + \sa extent(), setMinimumExtent() +*/ +double QwtAbstractScaleDraw::minimumExtent() const +{ + return d_data->minExtent; +} + +/*! + Set the length of the ticks + + \param tickType Tick type + \param length New length + + \warning the length is limited to [0..1000] +*/ +void QwtAbstractScaleDraw::setTickLength( + QwtScaleDiv::TickType tickType, double length ) +{ + if ( tickType < QwtScaleDiv::MinorTick || + tickType > QwtScaleDiv::MajorTick ) + { + return; + } + + if ( length < 0.0 ) + length = 0.0; + + const double maxTickLen = 1000.0; + if ( length > maxTickLen ) + length = maxTickLen; + + d_data->tickLength[tickType] = length; +} + +/*! + \return Length of the ticks + \sa setTickLength(), maxTickLength() +*/ +double QwtAbstractScaleDraw::tickLength( QwtScaleDiv::TickType tickType ) const +{ + if ( tickType < QwtScaleDiv::MinorTick || + tickType > QwtScaleDiv::MajorTick ) + { + return 0; + } + + return d_data->tickLength[tickType]; +} + +/*! + \return Length of the longest tick + + Useful for layout calculations + \sa tickLength(), setTickLength() +*/ +double QwtAbstractScaleDraw::maxTickLength() const +{ + double length = 0.0; + for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ ) + length = qMax( length, d_data->tickLength[i] ); + + return length; +} + +/*! + \brief Convert a value into its representing label + + The value is converted to a plain text using + QLocale().toString(value). + This method is often overloaded by applications to have individual + labels. + + \param value Value + \return Label string. +*/ +QwtText QwtAbstractScaleDraw::label( double value ) const +{ + return QLocale().toString( value ); +} + +/*! + \brief Convert a value into its representing label and cache it. + + The conversion between value and label is called very often + in the layout and painting code. Unfortunately the + calculation of the label sizes might be slow (really slow + for rich text in Qt4), so it's necessary to cache the labels. + + \param font Font + \param value Value + + \return Tick label +*/ +const QwtText &QwtAbstractScaleDraw::tickLabel( + const QFont &font, double value ) const +{ + QMap::const_iterator it = d_data->labelCache.find( value ); + if ( it == d_data->labelCache.end() ) + { + QwtText lbl = label( value ); + lbl.setRenderFlags( 0 ); + lbl.setLayoutAttribute( QwtText::MinimumLayout ); + + ( void )lbl.textSize( font ); // initialize the internal cache + + it = d_data->labelCache.insert( value, lbl ); + } + + return ( *it ); +} + +/*! + Invalidate the cache used by tickLabel() + + The cache is invalidated, when a new QwtScaleDiv is set. If + the labels need to be changed. while the same QwtScaleDiv is set, + invalidateCache() needs to be called manually. +*/ +void QwtAbstractScaleDraw::invalidateCache() +{ + d_data->labelCache.clear(); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_scale_draw.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_scale_draw.h new file mode 100644 index 0000000..1c09ec7 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_scale_draw.h @@ -0,0 +1,141 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_ABSTRACT_SCALE_DRAW_H +#define QWT_ABSTRACT_SCALE_DRAW_H + +#include "qwt_global.h" +#include "qwt_scale_div.h" +#include "qwt_text.h" + +class QPalette; +class QPainter; +class QFont; +class QwtTransform; +class QwtScaleMap; + +/*! + \brief A abstract base class for drawing scales + + QwtAbstractScaleDraw can be used to draw linear or logarithmic scales. + + After a scale division has been specified as a QwtScaleDiv object + using setScaleDiv(), the scale can be drawn with the draw() member. +*/ +class QWT_EXPORT QwtAbstractScaleDraw +{ +public: + + /*! + Components of a scale + \sa enableComponent(), hasComponent + */ + enum ScaleComponent + { + //! Backbone = the line where the ticks are located + Backbone = 0x01, + + //! Ticks + Ticks = 0x02, + + //! Labels + Labels = 0x04 + }; + + //! Scale components + typedef QFlags ScaleComponents; + + QwtAbstractScaleDraw(); + virtual ~QwtAbstractScaleDraw(); + + void setScaleDiv( const QwtScaleDiv &s ); + const QwtScaleDiv& scaleDiv() const; + + void setTransformation( QwtTransform * ); + const QwtScaleMap &scaleMap() const; + QwtScaleMap &scaleMap(); + + void enableComponent( ScaleComponent, bool enable = true ); + bool hasComponent( ScaleComponent ) const; + + void setTickLength( QwtScaleDiv::TickType, double length ); + double tickLength( QwtScaleDiv::TickType ) const; + double maxTickLength() const; + + void setSpacing( double margin ); + double spacing() const; + + void setPenWidth( int width ); + int penWidth() const; + + virtual void draw( QPainter *, const QPalette & ) const; + + virtual QwtText label( double ) const; + + /*! + Calculate the extent + + The extent is the distance from the baseline to the outermost + pixel of the scale draw in opposite to its orientation. + It is at least minimumExtent() pixels. + + \param font Font used for drawing the tick labels + \return Number of pixels + + \sa setMinimumExtent(), minimumExtent() + */ + virtual double extent( const QFont &font ) const = 0; + + void setMinimumExtent( double ); + double minimumExtent() const; + +protected: + /*! + Draw a tick + + \param painter Painter + \param value Value of the tick + \param len Length of the tick + + \sa drawBackbone(), drawLabel() + */ + virtual void drawTick( QPainter *painter, double value, double len ) const = 0; + + /*! + Draws the baseline of the scale + \param painter Painter + + \sa drawTick(), drawLabel() + */ + virtual void drawBackbone( QPainter *painter ) const = 0; + + /*! + Draws the label for a major scale tick + + \param painter Painter + \param value Value + + \sa drawTick(), drawBackbone() + */ + virtual void drawLabel( QPainter *painter, double value ) const = 0; + + void invalidateCache(); + const QwtText &tickLabel( const QFont &, double value ) const; + +private: + QwtAbstractScaleDraw( const QwtAbstractScaleDraw & ); + QwtAbstractScaleDraw &operator=( const QwtAbstractScaleDraw & ); + + class PrivateData; + PrivateData *d_data; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtAbstractScaleDraw::ScaleComponents ) + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_slider.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_slider.cpp new file mode 100644 index 0000000..449764b --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_slider.cpp @@ -0,0 +1,822 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_abstract_slider.h" +#include "qwt_abstract_scale_draw.h" +#include "qwt_math.h" +#include "qwt_scale_map.h" +#include + +#if QT_VERSION < 0x040601 +#define qFabs(x) ::fabs(x) +#endif + +static double qwtAlignToScaleDiv( + const QwtAbstractSlider *slider, double value ) +{ + const QwtScaleDiv &sd = slider->scaleDiv(); + + const int tValue = slider->transform( value ); + + if ( tValue == slider->transform( sd.lowerBound() ) ) + return sd.lowerBound(); + + if ( tValue == slider->transform( sd.lowerBound() ) ) + return sd.upperBound(); + + for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ ) + { + const QList ticks = sd.ticks( i ); + for ( int j = 0; j < ticks.size(); j++ ) + { + if ( slider->transform( ticks[ j ] ) == tValue ) + return ticks[ j ]; + } + } + + return value; +} + +class QwtAbstractSlider::PrivateData +{ +public: + PrivateData(): + isScrolling( false ), + isTracking( true ), + pendingValueChanged( false ), + readOnly( false ), + totalSteps( 100 ), + singleSteps( 1 ), + pageSteps( 10 ), + stepAlignment( true ), + isValid( false ), + value( 0.0 ), + wrapping( false ), + invertedControls( false ) + { + } + + bool isScrolling; + bool isTracking; + bool pendingValueChanged; + + bool readOnly; + + uint totalSteps; + uint singleSteps; + uint pageSteps; + bool stepAlignment; + + bool isValid; + double value; + + bool wrapping; + bool invertedControls; +}; + +/*! + \brief Constructor + + The scale is initialized to [0.0, 100.0], the + number of steps is set to 100 with 1 and 10 and single + an page step sizes. Step alignment is enabled. + + The initial value is invalid. + + \param parent Parent widget +*/ +QwtAbstractSlider::QwtAbstractSlider( QWidget *parent ): + QwtAbstractScale( parent ) +{ + d_data = new QwtAbstractSlider::PrivateData; + + setScale( 0.0, 100.0 ); + setFocusPolicy( Qt::StrongFocus ); +} + +//! Destructor +QwtAbstractSlider::~QwtAbstractSlider() +{ + delete d_data; +} + +/*! + Set the value to be valid/invalid + + \param on When true, the value is invalidated + + \sa setValue() +*/ +void QwtAbstractSlider::setValid( bool on ) +{ + if ( on != d_data->isValid ) + { + d_data->isValid = on; + sliderChange(); + + Q_EMIT valueChanged( d_data->value ); + } +} + +//! \return True, when the value is invalid +bool QwtAbstractSlider::isValid() const +{ + return d_data->isValid; +} + +/*! + En/Disable read only mode + + In read only mode the slider can't be controlled by mouse + or keyboard. + + \param on Enables in case of true + \sa isReadOnly() + + \warning The focus policy is set to Qt::StrongFocus or Qt::NoFocus +*/ +void QwtAbstractSlider::setReadOnly( bool on ) +{ + if ( d_data->readOnly != on ) + { + d_data->readOnly = on; + setFocusPolicy( on ? Qt::StrongFocus : Qt::NoFocus ); + + update(); + } +} + +/*! + In read only mode the slider can't be controlled by mouse + or keyboard. + + \return true if read only + \sa setReadOnly() +*/ +bool QwtAbstractSlider::isReadOnly() const +{ + return d_data->readOnly; +} + +/*! + \brief Enables or disables tracking. + + If tracking is enabled, the slider emits the valueChanged() + signal while the movable part of the slider is being dragged. + If tracking is disabled, the slider emits the valueChanged() signal + only when the user releases the slider. + + Tracking is enabled by default. + \param on \c true (enable) or \c false (disable) tracking. + + \sa isTracking(), sliderMoved() +*/ +void QwtAbstractSlider::setTracking( bool on ) +{ + d_data->isTracking = on; +} + +/*! + \return True, when tracking has been enabled + \sa setTracking() +*/ +bool QwtAbstractSlider::isTracking() const +{ + return d_data->isTracking; +} + +/*! + Mouse press event handler + \param event Mouse event +*/ +void QwtAbstractSlider::mousePressEvent( QMouseEvent *event ) +{ + if ( isReadOnly() ) + { + event->ignore(); + return; + } + + if ( !d_data->isValid || lowerBound() == upperBound() ) + return; + + d_data->isScrolling = isScrollPosition( event->pos() ); + + if ( d_data->isScrolling ) + { + d_data->pendingValueChanged = false; + + Q_EMIT sliderPressed(); + } +} + +/*! + Mouse Move Event handler + \param event Mouse event +*/ +void QwtAbstractSlider::mouseMoveEvent( QMouseEvent *event ) +{ + if ( isReadOnly() ) + { + event->ignore(); + return; + } + + if ( d_data->isValid && d_data->isScrolling ) + { + double value = scrolledTo( event->pos() ); + if ( value != d_data->value ) + { + value = boundedValue( value ); + + if ( d_data->stepAlignment ) + { + value = alignedValue( value ); + } + else + { + value = qwtAlignToScaleDiv( this, value ); + } + + if ( value != d_data->value ) + { + d_data->value = value; + + sliderChange(); + + Q_EMIT sliderMoved( d_data->value ); + + if ( d_data->isTracking ) + Q_EMIT valueChanged( d_data->value ); + else + d_data->pendingValueChanged = true; + } + } + } +} + +/*! + Mouse Release Event handler + \param event Mouse event +*/ +void QwtAbstractSlider::mouseReleaseEvent( QMouseEvent *event ) +{ + if ( isReadOnly() ) + { + event->ignore(); + return; + } + + if ( d_data->isScrolling && d_data->isValid ) + { + d_data->isScrolling = false; + + if ( d_data->pendingValueChanged ) + Q_EMIT valueChanged( d_data->value ); + + Q_EMIT sliderReleased(); + } +} + +/*! + Wheel Event handler + + In/decreases the value by s number of steps. The direction + depends on the invertedControls() property. + + When the control or shift modifier is pressed the wheel delta + ( divided by 120 ) is mapped to an increment according to + pageSteps(). Otherwise it is mapped to singleSteps(). + + \param event Wheel event +*/ +void QwtAbstractSlider::wheelEvent( QWheelEvent *event ) +{ + if ( isReadOnly() ) + { + event->ignore(); + return; + } + + if ( !d_data->isValid || d_data->isScrolling ) + return; + + int numSteps = 0; + + if ( ( event->modifiers() & Qt::ControlModifier) || + ( event->modifiers() & Qt::ShiftModifier ) ) + { + // one page regardless of delta + numSteps = d_data->pageSteps; + if ( event->delta() < 0 ) + numSteps = -numSteps; + } + else + { + const int numTurns = ( event->delta() / 120 ); + numSteps = numTurns * d_data->singleSteps; + } + + if ( d_data->invertedControls ) + numSteps = -numSteps; + + const double value = incrementedValue( d_data->value, numSteps ); + if ( value != d_data->value ) + { + d_data->value = value; + sliderChange(); + + Q_EMIT sliderMoved( d_data->value ); + Q_EMIT valueChanged( d_data->value ); + } +} + +/*! + Handles key events + + QwtAbstractSlider handles the following keys: + + - Qt::Key_Left\n + Add/Subtract singleSteps() in direction to lowerBound(); + - Qt::Key_Right\n + Add/Subtract singleSteps() in direction to upperBound(); + - Qt::Key_Down\n + Subtract singleSteps(), when invertedControls() is false + - Qt::Key_Up\n + Add singleSteps(), when invertedControls() is false + - Qt::Key_PageDown\n + Subtract pageSteps(), when invertedControls() is false + - Qt::Key_PageUp\n + Add pageSteps(), when invertedControls() is false + - Qt::Key_Home\n + Set the value to the minimum() + - Qt::Key_End\n + Set the value to the maximum() + + \param event Key event + \sa isReadOnly() +*/ +void QwtAbstractSlider::keyPressEvent( QKeyEvent *event ) +{ + if ( isReadOnly() ) + { + event->ignore(); + return; + } + + if ( !d_data->isValid || d_data->isScrolling ) + return; + + int numSteps = 0; + double value = d_data->value; + + switch ( event->key() ) + { + case Qt::Key_Left: + { + numSteps = -static_cast( d_data->singleSteps ); + if ( isInverted() ) + numSteps = -numSteps; + + break; + } + case Qt::Key_Right: + { + numSteps = d_data->singleSteps; + if ( isInverted() ) + numSteps = -numSteps; + + break; + } + case Qt::Key_Down: + { + numSteps = -static_cast( d_data->singleSteps ); + if ( d_data->invertedControls ) + numSteps = -numSteps; + break; + } + case Qt::Key_Up: + { + numSteps = d_data->singleSteps; + if ( d_data->invertedControls ) + numSteps = -numSteps; + + break; + } + case Qt::Key_PageUp: + { + numSteps = d_data->pageSteps; + if ( d_data->invertedControls ) + numSteps = -numSteps; + break; + } + case Qt::Key_PageDown: + { + numSteps = -static_cast( d_data->pageSteps ); + if ( d_data->invertedControls ) + numSteps = -numSteps; + break; + } + case Qt::Key_Home: + { + value = minimum(); + break; + } + case Qt::Key_End: + { + value = maximum(); + break; + } + default:; + { + event->ignore(); + } + } + + if ( numSteps != 0 ) + { + value = incrementedValue( d_data->value, numSteps ); + } + + if ( value != d_data->value ) + { + d_data->value = value; + sliderChange(); + + Q_EMIT sliderMoved( d_data->value ); + Q_EMIT valueChanged( d_data->value ); + } +} + +/*! + \brief Set the number of steps + + The range of the slider is divided into a number of steps from + which the value increments according to user inputs depend. + + The default setting is 100. + + \param stepCount Number of steps + + \sa totalSteps(), setSingleSteps(), setPageSteps() + */ +void QwtAbstractSlider::setTotalSteps( uint stepCount ) +{ + d_data->totalSteps = stepCount; +} + +/*! + \return Number of steps + \sa setTotalSteps(), singleSteps(), pageSteps() + */ +uint QwtAbstractSlider::totalSteps() const +{ + return d_data->totalSteps; +} + +/*! + \brief Set the number of steps for a single increment + + The range of the slider is divided into a number of steps from + which the value increments according to user inputs depend. + + \param stepCount Number of steps + + \sa singleSteps(), setTotalSteps(), setPageSteps() + */ + +void QwtAbstractSlider::setSingleSteps( uint stepCount ) +{ + d_data->singleSteps = stepCount; +} + +/*! + \return Number of steps + \sa setSingleSteps(), totalSteps(), pageSteps() + */ +uint QwtAbstractSlider::singleSteps() const +{ + return d_data->singleSteps; +} + +/*! + \brief Set the number of steps for a page increment + + The range of the slider is divided into a number of steps from + which the value increments according to user inputs depend. + + \param stepCount Number of steps + + \sa pageSteps(), setTotalSteps(), setSingleSteps() + */ + +void QwtAbstractSlider::setPageSteps( uint stepCount ) +{ + d_data->pageSteps = stepCount; +} + +/*! + \return Number of steps + \sa setPageSteps(), totalSteps(), singleSteps() + */ +uint QwtAbstractSlider::pageSteps() const +{ + return d_data->pageSteps; +} + +/*! + \brief Enable step alignment + + When step alignment is enabled values resulting from slider + movements are aligned to the step size. + + \param on Enable step alignment when true + \sa stepAlignment() +*/ +void QwtAbstractSlider::setStepAlignment( bool on ) +{ + if ( on != d_data->stepAlignment ) + { + d_data->stepAlignment = on; + } +} + +/*! + \return True, when step alignment is enabled + \sa setStepAlignment() + */ +bool QwtAbstractSlider::stepAlignment() const +{ + return d_data->stepAlignment; +} + +/*! + Set the slider to the specified value + + \param value New value + \sa setValid(), sliderChange(), valueChanged() +*/ +void QwtAbstractSlider::setValue( double value ) +{ + value = qBound( minimum(), value, maximum() ); + + const bool changed = ( d_data->value != value ) || !d_data->isValid; + + d_data->value = value; + d_data->isValid = true; + + if ( changed ) + { + sliderChange(); + Q_EMIT valueChanged( d_data->value ); + } +} + +//! Returns the current value. +double QwtAbstractSlider::value() const +{ + return d_data->value; +} + +/*! + If wrapping is true stepping up from upperBound() value will + take you to the minimum() value and vice versa. + + \param on En/Disable wrapping + \sa wrapping() +*/ +void QwtAbstractSlider::setWrapping( bool on ) +{ + d_data->wrapping = on; +} + +/*! + \return True, when wrapping is set + \sa setWrapping() + */ +bool QwtAbstractSlider::wrapping() const +{ + return d_data->wrapping; +} + +/*! + Invert wheel and key events + + Usually scrolling the mouse wheel "up" and using keys like page + up will increase the slider's value towards its maximum. + When invertedControls() is enabled the value is scrolled + towards its minimum. + + Inverting the controls might be f.e. useful for a vertical slider + with an inverted scale ( decreasing from top to bottom ). + + \param on Invert controls, when true + + \sa invertedControls(), keyEvent(), wheelEvent() + */ +void QwtAbstractSlider::setInvertedControls( bool on ) +{ + d_data->invertedControls = on; +} + +/*! + \return True, when the controls are inverted + \sa setInvertedControls() + */ +bool QwtAbstractSlider::invertedControls() const +{ + return d_data->invertedControls; +} + +/*! + Increment the slider + + The step size depends on the number of totalSteps() + + \param stepCount Number of steps + \sa setTotalSteps(), incrementedValue() + */ +void QwtAbstractSlider::incrementValue( int stepCount ) +{ + const double value = incrementedValue( + d_data->value, stepCount ); + + if ( value != d_data->value ) + { + d_data->value = value; + sliderChange(); + } +} + +/*! + Increment a value + + \param value Value + \param stepCount Number of steps + + \return Incremented value + */ +double QwtAbstractSlider::incrementedValue( + double value, int stepCount ) const +{ + if ( d_data->totalSteps == 0 ) + return value; + + const QwtTransform *transformation = + scaleMap().transformation(); + + if ( transformation == NULL ) + { + const double range = maximum() - minimum(); + value += stepCount * range / d_data->totalSteps; + } + else + { + QwtScaleMap map = scaleMap(); + map.setPaintInterval( 0, d_data->totalSteps ); + + // we need equidant steps according to + // paint device coordinates + const double range = transformation->transform( maximum() ) + - transformation->transform( minimum() ); + + const double stepSize = range / d_data->totalSteps; + + double v = transformation->transform( value ); + + v = qRound( v / stepSize ) * stepSize; + v += stepCount * range / d_data->totalSteps; + + value = transformation->invTransform( v ); + } + + value = boundedValue( value ); + + if ( d_data->stepAlignment ) + value = alignedValue( value ); + + return value; +} + +double QwtAbstractSlider::boundedValue( double value ) const +{ + const double vmin = minimum(); + const double vmax = maximum(); + + if ( d_data->wrapping && vmin != vmax ) + { + const int fullCircle = 360 * 16; + + const double pd = scaleMap().pDist(); + if ( int( pd / fullCircle ) * fullCircle == pd ) + { + // full circle scales: min and max are the same + const double range = vmax - vmin; + + if ( value < vmin ) + { + value += ::ceil( ( vmin - value ) / range ) * range; + } + else if ( value > vmax ) + { + value -= ::ceil( ( value - vmax ) / range ) * range; + } + } + else + { + if ( value < vmin ) + value = vmax; + else if ( value > vmax ) + value = vmin; + } + } + else + { + value = qBound( vmin, value, vmax ); + } + + return value; +} + +double QwtAbstractSlider::alignedValue( double value ) const +{ + if ( d_data->totalSteps == 0 ) + return value; + + double stepSize; + + if ( scaleMap().transformation() == NULL ) + { + stepSize = ( maximum() - minimum() ) / d_data->totalSteps; + if ( stepSize > 0.0 ) + { + value = lowerBound() + + qRound( ( value - lowerBound() ) / stepSize ) * stepSize; + } + } + else + { + stepSize = ( scaleMap().p2() - scaleMap().p1() ) / d_data->totalSteps; + + if ( stepSize > 0.0 ) + { + double v = scaleMap().transform( value ); + + v = scaleMap().p1() + + qRound( ( v - scaleMap().p1() ) / stepSize ) * stepSize; + + value = scaleMap().invTransform( v ); + } + } + + if ( qAbs( stepSize ) > 1e-12 ) + { + if ( qFuzzyCompare( value + 1.0, 1.0 ) ) + { + // correct rounding error if value = 0 + value = 0.0; + } + else + { + // correct rounding error at the border + if ( qFuzzyCompare( value, upperBound() ) ) + value = upperBound(); + else if ( qFuzzyCompare( value, lowerBound() ) ) + value = lowerBound(); + } + } + + return value; +} + +/*! + Update the slider according to modifications of the scale + */ +void QwtAbstractSlider::scaleChange() +{ + const double value = qBound( minimum(), d_data->value, maximum() ); + + const bool changed = ( value != d_data->value ); + if ( changed ) + { + d_data->value = value; + } + + if ( d_data->isValid || changed ) + Q_EMIT valueChanged( d_data->value ); + + updateGeometry(); + update(); +} + +//! Calling update() +void QwtAbstractSlider::sliderChange() +{ + update(); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_slider.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_slider.h new file mode 100644 index 0000000..ff1dbea --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_abstract_slider.h @@ -0,0 +1,167 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_ABSTRACT_SLIDER_H +#define QWT_ABSTRACT_SLIDER_H + +#include "qwt_global.h" +#include "qwt_abstract_scale.h" + +/*! + \brief An abstract base class for slider widgets with a scale + + A slider widget displays a value according to a scale. + The class is designed as a common super class for widgets like + QwtKnob, QwtDial and QwtSlider. + + When the slider is nor readOnly() its value can be modified + by keyboard, mouse and wheel inputs. + + The range of the slider is divided into a number of steps from + which the value increments according to user inputs depend. + Only for linear scales the number of steps correspond with + a fixed step size. +*/ + +class QWT_EXPORT QwtAbstractSlider: public QwtAbstractScale +{ + Q_OBJECT + + Q_PROPERTY( double value READ value WRITE setValue ) + + Q_PROPERTY( uint totalSteps READ totalSteps WRITE setTotalSteps ) + Q_PROPERTY( uint singleSteps READ singleSteps WRITE setSingleSteps ) + Q_PROPERTY( uint pageSteps READ pageSteps WRITE setPageSteps ) + Q_PROPERTY( bool stepAlignment READ stepAlignment WRITE setStepAlignment ) + + Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly ) + Q_PROPERTY( bool tracking READ isTracking WRITE setTracking ) + Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping ) + + Q_PROPERTY( bool invertedControls READ invertedControls WRITE setInvertedControls ) + +public: + explicit QwtAbstractSlider( QWidget *parent = NULL ); + virtual ~QwtAbstractSlider(); + + void setValid( bool ); + bool isValid() const; + + double value() const; + + void setWrapping( bool ); + bool wrapping() const; + + void setTotalSteps( uint ); + uint totalSteps() const; + + void setSingleSteps( uint ); + uint singleSteps() const; + + void setPageSteps( uint ); + uint pageSteps() const; + + void setStepAlignment( bool ); + bool stepAlignment() const; + + void setTracking( bool ); + bool isTracking() const; + + void setReadOnly( bool ); + bool isReadOnly() const; + + void setInvertedControls( bool ); + bool invertedControls() const; + +public Q_SLOTS: + void setValue( double val ); + +Q_SIGNALS: + + /*! + \brief Notify a change of value. + + When tracking is enabled (default setting), + this signal will be emitted every time the value changes. + + \param value New value + + \sa setTracking(), sliderMoved() + */ + void valueChanged( double value ); + + /*! + This signal is emitted when the user presses the + movable part of the slider. + */ + void sliderPressed(); + + /*! + This signal is emitted when the user releases the + movable part of the slider. + */ + void sliderReleased(); + + /*! + This signal is emitted when the user moves the + slider with the mouse. + + \param value New value + + \sa valueChanged() + */ + void sliderMoved( double value ); + +protected: + virtual void mousePressEvent( QMouseEvent * ); + virtual void mouseReleaseEvent( QMouseEvent * ); + virtual void mouseMoveEvent( QMouseEvent * ); + virtual void keyPressEvent( QKeyEvent * ); + virtual void wheelEvent( QWheelEvent * ); + + /*! + \brief Determine what to do when the user presses a mouse button. + + \param pos Mouse position + + \retval True, when pos is a valid scroll position + \sa scrolledTo() + */ + virtual bool isScrollPosition( const QPoint &pos ) const = 0; + + /*! + \brief Determine the value for a new position of the + movable part of the slider + + \param pos Mouse position + + \return Value for the mouse position + \sa isScrollPosition() + */ + virtual double scrolledTo( const QPoint &pos ) const = 0; + + void incrementValue( int numSteps ); + + virtual void scaleChange(); + +protected: + virtual void sliderChange(); + + double incrementedValue( + double value, int stepCount ) const; + +private: + double alignedValue( double ) const; + double boundedValue( double ) const; + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_analog_clock.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_analog_clock.cpp new file mode 100644 index 0000000..5521dd1 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_analog_clock.cpp @@ -0,0 +1,244 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_analog_clock.h" +#include "qwt_round_scale_draw.h" +#include +#include + +class QwtAnalogClockScaleDraw: public QwtRoundScaleDraw +{ +public: + QwtAnalogClockScaleDraw() + { + setSpacing( 8 ); + + enableComponent( QwtAbstractScaleDraw::Backbone, false ); + + setTickLength( QwtScaleDiv::MinorTick, 2 ); + setTickLength( QwtScaleDiv::MediumTick, 4 ); + setTickLength( QwtScaleDiv::MajorTick, 8 ); + + setPenWidth( 1 ); + } + + virtual QwtText label( double value ) const + { + if ( qFuzzyCompare( value + 1.0, 1.0 ) ) + value = 60.0 * 60.0 * 12.0; + + return QLocale().toString( qRound( value / ( 60.0 * 60.0 ) ) ); + } +}; + +/*! + Constructor + \param parent Parent widget +*/ +QwtAnalogClock::QwtAnalogClock( QWidget *parent ): + QwtDial( parent ) +{ + setWrapping( true ); + setReadOnly( true ); + + setOrigin( 270.0 ); + setScaleDraw( new QwtAnalogClockScaleDraw() ); + + setTotalSteps( 60 ); + + const int secondsPerHour = 60.0 * 60.0; + + QList majorTicks; + QList minorTicks; + + for ( int i = 0; i < 12; i++ ) + { + majorTicks += i * secondsPerHour; + + for ( int j = 1; j < 5; j++ ) + minorTicks += i * secondsPerHour + j * secondsPerHour / 5.0; + } + + QwtScaleDiv scaleDiv; + scaleDiv.setInterval( 0.0, 12.0 * secondsPerHour ); + scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks ); + scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks ); + setScale( scaleDiv ); + + QColor knobColor = palette().color( QPalette::Active, QPalette::Text ); + knobColor = knobColor.dark( 120 ); + + QColor handColor; + int width; + + for ( int i = 0; i < NHands; i++ ) + { + if ( i == SecondHand ) + { + width = 2; + handColor = knobColor.dark( 120 ); + } + else + { + width = 8; + handColor = knobColor; + } + + QwtDialSimpleNeedle *hand = new QwtDialSimpleNeedle( + QwtDialSimpleNeedle::Arrow, true, handColor, knobColor ); + hand->setWidth( width ); + + d_hand[i] = NULL; + setHand( static_cast( i ), hand ); + } +} + +//! Destructor +QwtAnalogClock::~QwtAnalogClock() +{ + for ( int i = 0; i < NHands; i++ ) + delete d_hand[i]; +} + +/*! + Nop method, use setHand() instead + \sa setHand() +*/ +void QwtAnalogClock::setNeedle( QwtDialNeedle * ) +{ + // no op + return; +} + +/*! + Set a clock hand + \param hand Specifies the type of hand + \param needle Hand + \sa hand() +*/ +void QwtAnalogClock::setHand( Hand hand, QwtDialNeedle *needle ) +{ + if ( hand >= 0 && hand < NHands ) + { + delete d_hand[hand]; + d_hand[hand] = needle; + } +} + +/*! + \return Clock hand + \param hd Specifies the type of hand + \sa setHand() +*/ +QwtDialNeedle *QwtAnalogClock::hand( Hand hd ) +{ + if ( hd < 0 || hd >= NHands ) + return NULL; + + return d_hand[hd]; +} + +/*! + \return Clock hand + \param hd Specifies the type of hand + \sa setHand() +*/ +const QwtDialNeedle *QwtAnalogClock::hand( Hand hd ) const +{ + return const_cast( this )->hand( hd ); +} + +/*! + \brief Set the current time +*/ +void QwtAnalogClock::setCurrentTime() +{ + setTime( QTime::currentTime() ); +} + +/*! + Set a time + \param time Time to display +*/ +void QwtAnalogClock::setTime( const QTime &time ) +{ + if ( time.isValid() ) + { + setValue( ( time.hour() % 12 ) * 60.0 * 60.0 + + time.minute() * 60.0 + time.second() ); + } + else + setValid( false ); +} + +/*! + \brief Draw the needle + + A clock has no single needle but three hands instead. drawNeedle() + translates value() into directions for the hands and calls + drawHand(). + + \param painter Painter + \param center Center of the clock + \param radius Maximum length for the hands + \param dir Dummy, not used. + \param colorGroup ColorGroup + + \sa drawHand() +*/ +void QwtAnalogClock::drawNeedle( QPainter *painter, const QPointF ¢er, + double radius, double dir, QPalette::ColorGroup colorGroup ) const +{ + Q_UNUSED( dir ); + + if ( isValid() ) + { + const double hours = value() / ( 60.0 * 60.0 ); + const double minutes = + ( value() - qFloor(hours) * 60.0 * 60.0 ) / 60.0; + const double seconds = value() - qFloor(hours) * 60.0 * 60.0 + - qFloor(minutes) * 60.0; + + double angle[NHands]; + angle[HourHand] = 360.0 * hours / 12.0; + angle[MinuteHand] = 360.0 * minutes / 60.0; + angle[SecondHand] = 360.0 * seconds / 60.0; + + for ( int hand = 0; hand < NHands; hand++ ) + { + const double d = 360.0 - angle[hand] - origin(); + drawHand( painter, static_cast( hand ), + center, radius, d, colorGroup ); + } + } +} + +/*! + Draw a clock hand + + \param painter Painter + \param hd Specify the type of hand + \param center Center of the clock + \param radius Maximum length for the hands + \param direction Direction of the hand in degrees, counter clockwise + \param cg ColorGroup +*/ +void QwtAnalogClock::drawHand( QPainter *painter, Hand hd, + const QPointF ¢er, double radius, double direction, + QPalette::ColorGroup cg ) const +{ + const QwtDialNeedle *needle = hand( hd ); + if ( needle ) + { + if ( hd == HourHand ) + radius = qRound( 0.8 * radius ); + + needle->draw( painter, center, radius, direction, cg ); + } +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_analog_clock.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_analog_clock.h new file mode 100644 index 0000000..781a334 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_analog_clock.h @@ -0,0 +1,93 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_ANALOG_CLOCK_H +#define QWT_ANALOG_CLOCK_H + +#include "qwt_global.h" +#include "qwt_dial.h" +#include "qwt_dial_needle.h" +#include + +/*! + \brief An analog clock + + \image html analogclock.png + + \par Example + \code + #include + + QwtAnalogClock *clock = new QwtAnalogClock(...); + clock->scaleDraw()->setPenWidth(3); + clock->setLineWidth(6); + clock->setFrameShadow(QwtDial::Sunken); + clock->setTime(); + + // update the clock every second + QTimer *timer = new QTimer(clock); + timer->connect(timer, SIGNAL(timeout()), clock, SLOT(setCurrentTime())); + timer->start(1000); + + \endcode + + \note The examples/dials example shows how to use QwtAnalogClock. +*/ + +class QWT_EXPORT QwtAnalogClock: public QwtDial +{ + Q_OBJECT + +public: + /*! + Hand type + \sa setHand(), hand() + */ + enum Hand + { + //! Needle displaying the seconds + SecondHand, + + //! Needle displaying the minutes + MinuteHand, + + //! Needle displaying the hours + HourHand, + + //! Number of needles + NHands + }; + + explicit QwtAnalogClock( QWidget* parent = NULL ); + virtual ~QwtAnalogClock(); + + void setHand( Hand, QwtDialNeedle * ); + + const QwtDialNeedle *hand( Hand ) const; + QwtDialNeedle *hand( Hand ); + +public Q_SLOTS: + void setCurrentTime(); + void setTime( const QTime & ); + +protected: + virtual void drawNeedle( QPainter *, const QPointF &, + double radius, double direction, QPalette::ColorGroup ) const; + + virtual void drawHand( QPainter *, Hand, const QPointF &, + double radius, double direction, QPalette::ColorGroup ) const; + +private: + // use setHand instead + void setNeedle( QwtDialNeedle * ); + + QwtDialNeedle *d_hand[NHands]; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_arrow_button.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_arrow_button.cpp new file mode 100644 index 0000000..28fe2a6 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_arrow_button.cpp @@ -0,0 +1,333 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_arrow_button.h" +#include "qwt_math.h" +#include +#include +#include +#include +#include + +static const int MaxNum = 3; +static const int Margin = 2; +static const int Spacing = 1; + +class QwtArrowButton::PrivateData +{ +public: + int num; + Qt::ArrowType arrowType; +}; + +static QStyleOptionButton styleOpt( const QwtArrowButton* btn ) +{ + QStyleOptionButton option; + option.init( btn ); + option.features = QStyleOptionButton::None; + if ( btn->isFlat() ) + option.features |= QStyleOptionButton::Flat; + if ( btn->menu() ) + option.features |= QStyleOptionButton::HasMenu; + if ( btn->autoDefault() || btn->isDefault() ) + option.features |= QStyleOptionButton::AutoDefaultButton; + if ( btn->isDefault() ) + option.features |= QStyleOptionButton::DefaultButton; + if ( btn->isDown() ) + option.state |= QStyle::State_Sunken; + if ( !btn->isFlat() && !btn->isDown() ) + option.state |= QStyle::State_Raised; + + return option; +} + +/*! + \param num Number of arrows + \param arrowType see Qt::ArrowType in the Qt docs. + \param parent Parent widget +*/ +QwtArrowButton::QwtArrowButton( int num, + Qt::ArrowType arrowType, QWidget *parent ): + QPushButton( parent ) +{ + d_data = new PrivateData; + d_data->num = qBound( 1, num, MaxNum ); + d_data->arrowType = arrowType; + + setAutoRepeat( true ); + setAutoDefault( false ); + + switch ( d_data->arrowType ) + { + case Qt::LeftArrow: + case Qt::RightArrow: + setSizePolicy( QSizePolicy::Expanding, + QSizePolicy::Fixed ); + break; + default: + setSizePolicy( QSizePolicy::Fixed, + QSizePolicy::Expanding ); + } +} + +//! Destructor +QwtArrowButton::~QwtArrowButton() +{ + delete d_data; + d_data = NULL; +} + +/*! + \brief The direction of the arrows +*/ +Qt::ArrowType QwtArrowButton::arrowType() const +{ + return d_data->arrowType; +} + +/*! + \brief The number of arrows +*/ +int QwtArrowButton::num() const +{ + return d_data->num; +} + +/*! + \return the bounding rectangle for the label +*/ +QRect QwtArrowButton::labelRect() const +{ + const int m = Margin; + + QRect r = rect(); + r.setRect( r.x() + m, r.y() + m, + r.width() - 2 * m, r.height() - 2 * m ); + + if ( isDown() ) + { + QStyleOptionButton option = styleOpt( this ); + const int ph = style()->pixelMetric( + QStyle::PM_ButtonShiftHorizontal, &option, this ); + const int pv = style()->pixelMetric( + QStyle::PM_ButtonShiftVertical, &option, this ); + + r.translate( ph, pv ); + } + + return r; +} + +/*! + Paint event handler + \param event Paint event +*/ +void QwtArrowButton::paintEvent( QPaintEvent *event ) +{ + QPushButton::paintEvent( event ); + QPainter painter( this ); + drawButtonLabel( &painter ); +} + +/*! + \brief Draw the button label + + \param painter Painter + \sa The Qt Manual for QPushButton +*/ +void QwtArrowButton::drawButtonLabel( QPainter *painter ) +{ + const bool isVertical = d_data->arrowType == Qt::UpArrow || + d_data->arrowType == Qt::DownArrow; + + const QRect r = labelRect(); + QSize boundingSize = labelRect().size(); + if ( isVertical ) + boundingSize.transpose(); + + const int w = + ( boundingSize.width() - ( MaxNum - 1 ) * Spacing ) / MaxNum; + + QSize arrow = arrowSize( Qt::RightArrow, + QSize( w, boundingSize.height() ) ); + + if ( isVertical ) + arrow.transpose(); + + QRect contentsSize; // aligned rect where to paint all arrows + if ( d_data->arrowType == Qt::LeftArrow || d_data->arrowType == Qt::RightArrow ) + { + contentsSize.setWidth( d_data->num * arrow.width() + + ( d_data->num - 1 ) * Spacing ); + contentsSize.setHeight( arrow.height() ); + } + else + { + contentsSize.setWidth( arrow.width() ); + contentsSize.setHeight( d_data->num * arrow.height() + + ( d_data->num - 1 ) * Spacing ); + } + + QRect arrowRect( contentsSize ); + arrowRect.moveCenter( r.center() ); + arrowRect.setSize( arrow ); + + painter->save(); + for ( int i = 0; i < d_data->num; i++ ) + { + drawArrow( painter, arrowRect, d_data->arrowType ); + + int dx = 0; + int dy = 0; + + if ( isVertical ) + dy = arrow.height() + Spacing; + else + dx = arrow.width() + Spacing; + + arrowRect.translate( dx, dy ); + } + painter->restore(); + + if ( hasFocus() ) + { + QStyleOptionFocusRect option; + option.init( this ); + option.backgroundColor = palette().color( QPalette::Window ); + + style()->drawPrimitive( QStyle::PE_FrameFocusRect, + &option, painter, this ); + } +} + +/*! + Draw an arrow int a bounding rectangle + + \param painter Painter + \param r Rectangle where to paint the arrow + \param arrowType Arrow type +*/ +void QwtArrowButton::drawArrow( QPainter *painter, + const QRect &r, Qt::ArrowType arrowType ) const +{ + QPolygon pa( 3 ); + + switch ( arrowType ) + { + case Qt::UpArrow: + pa.setPoint( 0, r.bottomLeft() ); + pa.setPoint( 1, r.bottomRight() ); + pa.setPoint( 2, r.center().x(), r.top() ); + break; + case Qt::DownArrow: + pa.setPoint( 0, r.topLeft() ); + pa.setPoint( 1, r.topRight() ); + pa.setPoint( 2, r.center().x(), r.bottom() ); + break; + case Qt::RightArrow: + pa.setPoint( 0, r.topLeft() ); + pa.setPoint( 1, r.bottomLeft() ); + pa.setPoint( 2, r.right(), r.center().y() ); + break; + case Qt::LeftArrow: + pa.setPoint( 0, r.topRight() ); + pa.setPoint( 1, r.bottomRight() ); + pa.setPoint( 2, r.left(), r.center().y() ); + break; + default: + break; + } + + painter->save(); + + painter->setRenderHint( QPainter::Antialiasing, true ); + painter->setPen( Qt::NoPen ); + painter->setBrush( palette().brush( QPalette::ButtonText ) ); + painter->drawPolygon( pa ); + + painter->restore(); +} + +/*! + \return a size hint +*/ +QSize QwtArrowButton::sizeHint() const +{ + const QSize hint = minimumSizeHint(); + return hint.expandedTo( QApplication::globalStrut() ); +} + +/*! + \brief Return a minimum size hint +*/ +QSize QwtArrowButton::minimumSizeHint() const +{ + const QSize asz = arrowSize( Qt::RightArrow, QSize() ); + + QSize sz( + 2 * Margin + ( MaxNum - 1 ) * Spacing + MaxNum * asz.width(), + 2 * Margin + asz.height() + ); + + if ( d_data->arrowType == Qt::UpArrow || d_data->arrowType == Qt::DownArrow ) + sz.transpose(); + + QStyleOption styleOption; + styleOption.init( this ); + + sz = style()->sizeFromContents( QStyle::CT_PushButton, + &styleOption, sz, this ); + + return sz; +} + +/*! + Calculate the size for a arrow that fits into a rectangle of a given size + + \param arrowType Arrow type + \param boundingSize Bounding size + \return Size of the arrow +*/ +QSize QwtArrowButton::arrowSize( Qt::ArrowType arrowType, + const QSize &boundingSize ) const +{ + QSize bs = boundingSize; + if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow ) + bs.transpose(); + + const int MinLen = 2; + const QSize sz = bs.expandedTo( + QSize( MinLen, 2 * MinLen - 1 ) ); // minimum + + int w = sz.width(); + int h = 2 * w - 1; + + if ( h > sz.height() ) + { + h = sz.height(); + w = ( h + 1 ) / 2; + } + + QSize arrSize( w, h ); + if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow ) + arrSize.transpose(); + + return arrSize; +} + +/*! + \brief autoRepeat for the space keys +*/ +void QwtArrowButton::keyPressEvent( QKeyEvent *event ) +{ + if ( event->isAutoRepeat() && event->key() == Qt::Key_Space ) + Q_EMIT clicked(); + + QPushButton::keyPressEvent( event ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_arrow_button.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_arrow_button.h new file mode 100644 index 0000000..b3285da --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_arrow_button.h @@ -0,0 +1,52 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_ARROW_BUTTON_H +#define QWT_ARROW_BUTTON_H + +#include "qwt_global.h" +#include + +/*! + \brief Arrow Button + + A push button with one or more filled triangles on its front. + An Arrow button can have 1 to 3 arrows in a row, pointing + up, down, left or right. +*/ +class QWT_EXPORT QwtArrowButton : public QPushButton +{ +public: + explicit QwtArrowButton ( int num, Qt::ArrowType, QWidget *parent = NULL ); + virtual ~QwtArrowButton(); + + Qt::ArrowType arrowType() const; + int num() const; + + virtual QSize sizeHint() const; + virtual QSize minimumSizeHint() const; + +protected: + virtual void paintEvent( QPaintEvent *event ); + + virtual void drawButtonLabel( QPainter *p ); + virtual void drawArrow( QPainter *, + const QRect &, Qt::ArrowType ) const; + virtual QRect labelRect() const; + virtual QSize arrowSize( Qt::ArrowType, + const QSize &boundingSize ) const; + + virtual void keyPressEvent( QKeyEvent * ); + +private: + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_clipper.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_clipper.cpp new file mode 100644 index 0000000..0602c8d --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_clipper.cpp @@ -0,0 +1,510 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_clipper.h" +#include "qwt_point_polar.h" +#include +#include +#include + +#if QT_VERSION < 0x040601 +#define qAtan(x) ::atan(x) +#endif + +namespace QwtClip +{ + // some templates used for inlining + template class LeftEdge; + template class RightEdge; + template class TopEdge; + template class BottomEdge; + + template class PointBuffer; +} + +template +class QwtClip::LeftEdge +{ +public: + inline LeftEdge( Value x1, Value, Value, Value ): + d_x1( x1 ) + { + } + + inline bool isInside( const Point &p ) const + { + return p.x() >= d_x1; + } + + inline Point intersection( const Point &p1, const Point &p2 ) const + { + double dy = ( p1.y() - p2.y() ) / double( p1.x() - p2.x() ); + return Point( d_x1, static_cast< Value >( p2.y() + ( d_x1 - p2.x() ) * dy ) ); + } +private: + const Value d_x1; +}; + +template +class QwtClip::RightEdge +{ +public: + inline RightEdge( Value, Value x2, Value, Value ): + d_x2( x2 ) + { + } + + inline bool isInside( const Point &p ) const + { + return p.x() <= d_x2; + } + + inline Point intersection( const Point &p1, const Point &p2 ) const + { + double dy = ( p1.y() - p2.y() ) / double( p1.x() - p2.x() ); + return Point( d_x2, static_cast( p2.y() + ( d_x2 - p2.x() ) * dy ) ); + } + +private: + const Value d_x2; +}; + +template +class QwtClip::TopEdge +{ +public: + inline TopEdge( Value, Value, Value y1, Value ): + d_y1( y1 ) + { + } + + inline bool isInside( const Point &p ) const + { + return p.y() >= d_y1; + } + + inline Point intersection( const Point &p1, const Point &p2 ) const + { + double dx = ( p1.x() - p2.x() ) / double( p1.y() - p2.y() ); + return Point( static_cast( p2.x() + ( d_y1 - p2.y() ) * dx ), d_y1 ); + } + +private: + const Value d_y1; +}; + +template +class QwtClip::BottomEdge +{ +public: + inline BottomEdge( Value, Value, Value, Value y2 ): + d_y2( y2 ) + { + } + + inline bool isInside( const Point &p ) const + { + return p.y() <= d_y2; + } + + inline Point intersection( const Point &p1, const Point &p2 ) const + { + double dx = ( p1.x() - p2.x() ) / double( p1.y() - p2.y() ); + return Point( static_cast( p2.x() + ( d_y2 - p2.y() ) * dx ), d_y2 ); + } + +private: + const Value d_y2; +}; + +template +class QwtClip::PointBuffer +{ +public: + PointBuffer( int capacity = 0 ): + m_capacity( 0 ), + m_size( 0 ), + m_buffer( NULL ) + { + if ( capacity > 0 ) + reserve( capacity ); + } + + ~PointBuffer() + { + if ( m_buffer ) + ::free( m_buffer ); + } + + inline void setPoints( int numPoints, const Point *points ) + { + reserve( numPoints ); + + m_size = numPoints; + ::memcpy( m_buffer, points, m_size * sizeof( Point ) ); + } + + inline void reset() + { + m_size = 0; + } + + inline int size() const + { + return m_size; + } + + inline Point *data() const + { + return m_buffer; + } + + inline Point &operator[]( int i ) + { + return m_buffer[i]; + } + + inline const Point &operator[]( int i ) const + { + return m_buffer[i]; + } + + inline void add( const Point &point ) + { + if ( m_capacity <= m_size ) + reserve( m_size + 1 ); + + m_buffer[m_size++] = point; + } + +private: + inline void reserve( int size ) + { + if ( m_capacity == 0 ) + m_capacity = 1; + + while ( m_capacity < size ) + m_capacity *= 2; + + m_buffer = static_cast( + ::realloc( m_buffer, m_capacity * sizeof( Point ) ) ); + } + + int m_capacity; + int m_size; + Point *m_buffer; +}; + +using namespace QwtClip; + +template +class QwtPolygonClipper +{ +public: + QwtPolygonClipper( const Rect &clipRect ): + d_clipRect( clipRect ) + { + } + + Polygon clipPolygon( const Polygon &polygon, bool closePolygon ) const + { +#if 0 + if ( d_clipRect.contains( polygon.boundingRect() ) ) + return polygon; +#endif + + PointBuffer points1; + PointBuffer points2( qMin( 256, polygon.size() ) ); + + points1.setPoints( polygon.size(), polygon.data() ); + + clipEdge< LeftEdge >( closePolygon, points1, points2 ); + clipEdge< RightEdge >( closePolygon, points2, points1 ); + clipEdge< TopEdge >( closePolygon, points1, points2 ); + clipEdge< BottomEdge >( closePolygon, points2, points1 ); + + Polygon p; + p.resize( points1.size() ); + ::memcpy( p.data(), points1.data(), points1.size() * sizeof( Point ) ); + + return p; + } + +private: + template + inline void clipEdge( bool closePolygon, + PointBuffer &points, PointBuffer &clippedPoints ) const + { + clippedPoints.reset(); + + if ( points.size() < 2 ) + { + if ( points.size() == 1 ) + clippedPoints.add( points[0] ); + return; + } + + const Edge edge( d_clipRect.x(), d_clipRect.x() + d_clipRect.width(), + d_clipRect.y(), d_clipRect.y() + d_clipRect.height() ); + + int lastPos, start; + if ( closePolygon ) + { + start = 0; + lastPos = points.size() - 1; + } + else + { + start = 1; + lastPos = 0; + + if ( edge.isInside( points[0] ) ) + clippedPoints.add( points[0] ); + } + + const uint nPoints = points.size(); + for ( uint i = start; i < nPoints; i++ ) + { + const Point &p1 = points[i]; + const Point &p2 = points[lastPos]; + + if ( edge.isInside( p1 ) ) + { + if ( edge.isInside( p2 ) ) + { + clippedPoints.add( p1 ); + } + else + { + clippedPoints.add( edge.intersection( p1, p2 ) ); + clippedPoints.add( p1 ); + } + } + else + { + if ( edge.isInside( p2 ) ) + { + clippedPoints.add( edge.intersection( p1, p2 ) ); + } + } + lastPos = i; + } + } + + const Rect d_clipRect; +}; + +class QwtCircleClipper +{ +public: + QwtCircleClipper( const QRectF &r ); + QVector clipCircle( const QPointF &, double radius ) const; + +private: + enum Edge + { + Left, + Top, + Right, + Bottom, + + NEdges + }; + + QList cuttingPoints( + Edge, const QPointF &pos, double radius ) const; + + double toAngle( const QPointF &, const QPointF & ) const; + + const QRectF d_rect; +}; + + +QwtCircleClipper::QwtCircleClipper( const QRectF &r ): + d_rect( r ) +{ +} + +QVector QwtCircleClipper::clipCircle( + const QPointF &pos, double radius ) const +{ + QList points; + for ( int edge = 0; edge < NEdges; edge++ ) + points += cuttingPoints( static_cast(edge), pos, radius ); + + QVector intv; + if ( points.size() <= 0 ) + { + QRectF cRect( 0, 0, 2 * radius, 2 * radius ); + cRect.moveCenter( pos ); + if ( d_rect.contains( cRect ) ) + intv += QwtInterval( 0.0, 2 * M_PI ); + } + else + { + QList angles; + for ( int i = 0; i < points.size(); i++ ) + angles += toAngle( pos, points[i] ); + qSort( angles ); + + const int in = d_rect.contains( qwtPolar2Pos( pos, radius, + angles[0] + ( angles[1] - angles[0] ) / 2 ) ); + + if ( in ) + { + for ( int i = 0; i < angles.size() - 1; i += 2 ) + intv += QwtInterval( angles[i], angles[i+1] ); + } + else + { + for ( int i = 1; i < angles.size() - 1; i += 2 ) + intv += QwtInterval( angles[i], angles[i+1] ); + intv += QwtInterval( angles.last(), angles.first() ); + } + } + + return intv; +} + +double QwtCircleClipper::toAngle( + const QPointF &from, const QPointF &to ) const +{ + if ( from.x() == to.x() ) + return from.y() <= to.y() ? M_PI / 2.0 : 3 * M_PI / 2.0; + + const double m = qAbs( ( to.y() - from.y() ) / ( to.x() - from.x() ) ); + + double angle = qAtan( m ); + if ( to.x() > from.x() ) + { + if ( to.y() > from.y() ) + angle = 2 * M_PI - angle; + } + else + { + if ( to.y() > from.y() ) + angle = M_PI + angle; + else + angle = M_PI - angle; + } + + return angle; +} + +QList QwtCircleClipper::cuttingPoints( + Edge edge, const QPointF &pos, double radius ) const +{ + QList points; + + if ( edge == Left || edge == Right ) + { + const double x = ( edge == Left ) ? d_rect.left() : d_rect.right(); + if ( qAbs( pos.x() - x ) < radius ) + { + const double off = qSqrt( qwtSqr( radius ) - qwtSqr( pos.x() - x ) ); + const double m_y1 = pos.y() + off; + if ( m_y1 >= d_rect.top() && m_y1 <= d_rect.bottom() ) + points += QPointF( x, m_y1 ); + + const double m_y2 = pos.y() - off; + if ( m_y2 >= d_rect.top() && m_y2 <= d_rect.bottom() ) + points += QPointF( x, m_y2 ); + } + } + else + { + const double y = ( edge == Top ) ? d_rect.top() : d_rect.bottom(); + if ( qAbs( pos.y() - y ) < radius ) + { + const double off = qSqrt( qwtSqr( radius ) - qwtSqr( pos.y() - y ) ); + const double x1 = pos.x() + off; + if ( x1 >= d_rect.left() && x1 <= d_rect.right() ) + points += QPointF( x1, y ); + + const double m_x2 = pos.x() - off; + if ( m_x2 >= d_rect.left() && m_x2 <= d_rect.right() ) + points += QPointF( m_x2, y ); + } + } + return points; +} + +/*! + Sutherland-Hodgman polygon clipping + + \param clipRect Clip rectangle + \param polygon Polygon + \param closePolygon True, when the polygon is closed + + \return Clipped polygon +*/ +QPolygon QwtClipper::clipPolygon( + const QRectF &clipRect, const QPolygon &polygon, bool closePolygon ) +{ + const int minX = qCeil( clipRect.left() ); + const int maxX = qFloor( clipRect.right() ); + const int minY = qCeil( clipRect.top() ); + const int maxY = qFloor( clipRect.bottom() ); + + const QRect r( minX, minY, maxX - minX, maxY - minY ); + + QwtPolygonClipper clipper( r ); + return clipper.clipPolygon( polygon, closePolygon ); +} +/*! + Sutherland-Hodgman polygon clipping + + \param clipRect Clip rectangle + \param polygon Polygon + \param closePolygon True, when the polygon is closed + + \return Clipped polygon +*/ +QPolygon QwtClipper::clipPolygon( + const QRect &clipRect, const QPolygon &polygon, bool closePolygon ) +{ + QwtPolygonClipper clipper( clipRect ); + return clipper.clipPolygon( polygon, closePolygon ); +} + +/*! + Sutherland-Hodgman polygon clipping + + \param clipRect Clip rectangle + \param polygon Polygon + \param closePolygon True, when the polygon is closed + + \return Clipped polygon +*/ +QPolygonF QwtClipper::clipPolygonF( + const QRectF &clipRect, const QPolygonF &polygon, bool closePolygon ) +{ + QwtPolygonClipper clipper( clipRect ); + return clipper.clipPolygon( polygon, closePolygon ); +} + +/*! + Circle clipping + + clipCircle() divides a circle into intervals of angles representing arcs + of the circle. When the circle is completely inside the clip rectangle + an interval [0.0, 2 * M_PI] is returned. + + \param clipRect Clip rectangle + \param center Center of the circle + \param radius Radius of the circle + + \return Arcs of the circle +*/ +QVector QwtClipper::clipCircle( const QRectF &clipRect, + const QPointF ¢er, double radius ) +{ + QwtCircleClipper clipper( clipRect ); + return clipper.clipCircle( center, radius ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_clipper.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_clipper.h new file mode 100644 index 0000000..ad69489 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_clipper.h @@ -0,0 +1,40 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_CLIPPER_H +#define QWT_CLIPPER_H + +#include "qwt_global.h" +#include "qwt_interval.h" +#include +#include + +class QRect; +class QRectF; + +/*! + \brief Some clipping algorithms +*/ + +class QWT_EXPORT QwtClipper +{ +public: + static QPolygon clipPolygon( const QRect &, + const QPolygon &, bool closePolygon = false ); + static QPolygon clipPolygon( const QRectF &, + const QPolygon &, bool closePolygon = false ); + + static QPolygonF clipPolygonF( const QRectF &, + const QPolygonF &, bool closePolygon = false ); + + static QVector clipCircle( + const QRectF &, const QPointF &, double radius ); +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_color_map.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_color_map.cpp new file mode 100644 index 0000000..5490627 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_color_map.cpp @@ -0,0 +1,499 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_color_map.h" +#include "qwt_math.h" +#include "qwt_interval.h" +#include + +class QwtLinearColorMap::ColorStops +{ +public: + ColorStops(): + d_doAlpha( false ) + { + d_stops.reserve( 256 ); + } + + void insert( double pos, const QColor &color ); + QRgb rgb( QwtLinearColorMap::Mode, double pos ) const; + + QVector stops() const; + +private: + + class ColorStop + { + public: + ColorStop(): + pos( 0.0 ), + rgb( 0 ) + { + }; + + ColorStop( double p, const QColor &c ): + pos( p ), + rgb( c.rgba() ) + { + r = qRed( rgb ); + g = qGreen( rgb ); + b = qBlue( rgb ); + a = qAlpha( rgb ); + + /* + when mapping a value to rgb we will have to calcualate: + - const int v = int( ( s1.v0 + ratio * s1.vStep ) + 0.5 ); + + Thus adding 0.5 ( for rounding ) can be done in advance + */ + r0 = r + 0.5; + g0 = g + 0.5; + b0 = b + 0.5; + a0 = a + 0.5; + + rStep = gStep = bStep = aStep = 0.0; + posStep = 0.0; + } + + void updateSteps( const ColorStop &nextStop ) + { + rStep = nextStop.r - r; + gStep = nextStop.g - g; + bStep = nextStop.b - b; + aStep = nextStop.a - a; + posStep = nextStop.pos - pos; + } + + double pos; + QRgb rgb; + int r, g, b, a; + + // precalculated values + double rStep, gStep, bStep, aStep; + double r0, g0, b0, a0; + double posStep; + }; + + inline int findUpper( double pos ) const; + QVector d_stops; + bool d_doAlpha; +}; + +void QwtLinearColorMap::ColorStops::insert( double pos, const QColor &color ) +{ + // Lookups need to be very fast, insertions are not so important. + // Anyway, a balanced tree is what we need here. TODO ... + + if ( pos < 0.0 || pos > 1.0 ) + return; + + int index; + if ( d_stops.size() == 0 ) + { + index = 0; + d_stops.resize( 1 ); + } + else + { + index = findUpper( pos ); + if ( index == d_stops.size() || + qAbs( d_stops[index].pos - pos ) >= 0.001 ) + { + d_stops.resize( d_stops.size() + 1 ); + for ( int i = d_stops.size() - 1; i > index; i-- ) + d_stops[i] = d_stops[i-1]; + } + } + + d_stops[index] = ColorStop( pos, color ); + if ( color.alpha() != 255 ) + d_doAlpha = true; + + if ( index > 0 ) + d_stops[index-1].updateSteps( d_stops[index] ); + + if ( index < d_stops.size() - 1 ) + d_stops[index].updateSteps( d_stops[index+1] ); +} + +inline QVector QwtLinearColorMap::ColorStops::stops() const +{ + QVector positions( d_stops.size() ); + for ( int i = 0; i < d_stops.size(); i++ ) + positions[i] = d_stops[i].pos; + return positions; +} + +inline int QwtLinearColorMap::ColorStops::findUpper( double pos ) const +{ + int index = 0; + int n = d_stops.size(); + + const ColorStop *stops = d_stops.data(); + + while ( n > 0 ) + { + const int half = n >> 1; + const int middle = index + half; + + if ( stops[middle].pos <= pos ) + { + index = middle + 1; + n -= half + 1; + } + else + n = half; + } + + return index; +} + +inline QRgb QwtLinearColorMap::ColorStops::rgb( + QwtLinearColorMap::Mode mode, double pos ) const +{ + if ( pos <= 0.0 ) + return d_stops[0].rgb; + if ( pos >= 1.0 ) + return d_stops[ d_stops.size() - 1 ].rgb; + + const int index = findUpper( pos ); + if ( mode == FixedColors ) + { + return d_stops[index-1].rgb; + } + else + { + const ColorStop &s1 = d_stops[index-1]; + + const double ratio = ( pos - s1.pos ) / ( s1.posStep ); + + const int r = int( s1.r0 + ratio * s1.rStep ); + const int g = int( s1.g0 + ratio * s1.gStep ); + const int b = int( s1.b0 + ratio * s1.bStep ); + + if ( d_doAlpha ) + { + if ( s1.aStep ) + { + const int a = int( s1.a0 + ratio * s1.aStep ); + return qRgba( r, g, b, a ); + } + else + { + return qRgba( r, g, b, s1.a ); + } + } + else + { + return qRgb( r, g, b ); + } + } +} + +//! Constructor +QwtColorMap::QwtColorMap( Format format ): + d_format( format ) +{ +} + +//! Destructor +QwtColorMap::~QwtColorMap() +{ +} + +/*! + Build and return a color map of 256 colors + + The color table is needed for rendering indexed images in combination + with using colorIndex(). + + \param interval Range for the values + \return A color table, that can be used for a QImage +*/ +QVector QwtColorMap::colorTable( const QwtInterval &interval ) const +{ + QVector table( 256 ); + + if ( interval.isValid() ) + { + const double step = interval.width() / ( table.size() - 1 ); + for ( int i = 0; i < table.size(); i++ ) + table[i] = rgb( interval, interval.minValue() + step * i ); + } + + return table; +} + +class QwtLinearColorMap::PrivateData +{ +public: + ColorStops colorStops; + QwtLinearColorMap::Mode mode; +}; + +/*! + Build a color map with two stops at 0.0 and 1.0. The color + at 0.0 is Qt::blue, at 1.0 it is Qt::yellow. + + \param format Preferred format of the color map +*/ +QwtLinearColorMap::QwtLinearColorMap( QwtColorMap::Format format ): + QwtColorMap( format ) +{ + d_data = new PrivateData; + d_data->mode = ScaledColors; + + setColorInterval( Qt::blue, Qt::yellow ); +} + +/*! + Build a color map with two stops at 0.0 and 1.0. + + \param color1 Color used for the minimum value of the value interval + \param color2 Color used for the maximum value of the value interval + \param format Preferred format for the color map +*/ +QwtLinearColorMap::QwtLinearColorMap( const QColor &color1, + const QColor &color2, QwtColorMap::Format format ): + QwtColorMap( format ) +{ + d_data = new PrivateData; + d_data->mode = ScaledColors; + setColorInterval( color1, color2 ); +} + +//! Destructor +QwtLinearColorMap::~QwtLinearColorMap() +{ + delete d_data; +} + +/*! + \brief Set the mode of the color map + + FixedColors means the color is calculated from the next lower + color stop. ScaledColors means the color is calculated + by interpolating the colors of the adjacent stops. + + \sa mode() +*/ +void QwtLinearColorMap::setMode( Mode mode ) +{ + d_data->mode = mode; +} + +/*! + \return Mode of the color map + \sa setMode() +*/ +QwtLinearColorMap::Mode QwtLinearColorMap::mode() const +{ + return d_data->mode; +} + +/*! + Set the color range + + Add stops at 0.0 and 1.0. + + \param color1 Color used for the minimum value of the value interval + \param color2 Color used for the maximum value of the value interval + + \sa color1(), color2() +*/ +void QwtLinearColorMap::setColorInterval( + const QColor &color1, const QColor &color2 ) +{ + d_data->colorStops = ColorStops(); + d_data->colorStops.insert( 0.0, color1 ); + d_data->colorStops.insert( 1.0, color2 ); +} + +/*! + Add a color stop + + The value has to be in the range [0.0, 1.0]. + F.e. a stop at position 17.0 for a range [10.0,20.0] must be + passed as: (17.0 - 10.0) / (20.0 - 10.0) + + \param value Value between [0.0, 1.0] + \param color Color stop +*/ +void QwtLinearColorMap::addColorStop( double value, const QColor& color ) +{ + if ( value >= 0.0 && value <= 1.0 ) + d_data->colorStops.insert( value, color ); +} + +/*! + \return Positions of color stops in increasing order +*/ +QVector QwtLinearColorMap::colorStops() const +{ + return d_data->colorStops.stops(); +} + +/*! + \return the first color of the color range + \sa setColorInterval() +*/ +QColor QwtLinearColorMap::color1() const +{ + return QColor( d_data->colorStops.rgb( d_data->mode, 0.0 ) ); +} + +/*! + \return the second color of the color range + \sa setColorInterval() +*/ +QColor QwtLinearColorMap::color2() const +{ + return QColor( d_data->colorStops.rgb( d_data->mode, 1.0 ) ); +} + +/*! + Map a value of a given interval into a RGB value + + \param interval Range for all values + \param value Value to map into a RGB value + + \return RGB value for value +*/ +QRgb QwtLinearColorMap::rgb( + const QwtInterval &interval, double value ) const +{ + if ( qIsNaN(value) ) + return 0u; + + const double width = interval.width(); + if ( width <= 0.0 ) + return 0u; + + const double ratio = ( value - interval.minValue() ) / width; + return d_data->colorStops.rgb( d_data->mode, ratio ); +} + +/*! + \brief Map a value of a given interval into a color index + + \param interval Range for all values + \param value Value to map into a color index + + \return Index, between 0 and 255 +*/ +unsigned char QwtLinearColorMap::colorIndex( + const QwtInterval &interval, double value ) const +{ + const double width = interval.width(); + + if ( qIsNaN(value) || width <= 0.0 || value <= interval.minValue() ) + return 0; + + if ( value >= interval.maxValue() ) + return 255; + + const double ratio = ( value - interval.minValue() ) / width; + + unsigned char index; + if ( d_data->mode == FixedColors ) + index = static_cast( ratio * 255 ); // always floor + else + index = static_cast( ratio * 255 + 0.5 ); + + return index; +} + +class QwtAlphaColorMap::PrivateData +{ +public: + QColor color; + QRgb rgb; + QRgb rgbMax; +}; + + +/*! + Constructor + \param color Color of the map +*/ +QwtAlphaColorMap::QwtAlphaColorMap( const QColor &color ): + QwtColorMap( QwtColorMap::RGB ) +{ + d_data = new PrivateData; + setColor( color ); +} + +//! Destructor +QwtAlphaColorMap::~QwtAlphaColorMap() +{ + delete d_data; +} + +/*! + Set the color + + \param color Color + \sa color() +*/ +void QwtAlphaColorMap::setColor( const QColor &color ) +{ + d_data->color = color; + d_data->rgb = color.rgb() & qRgba( 255, 255, 255, 0 ); + d_data->rgbMax = d_data->rgb | ( 255 << 24 ); +} + +/*! + \return the color + \sa setColor() +*/ +QColor QwtAlphaColorMap::color() const +{ + return d_data->color; +} + +/*! + \brief Map a value of a given interval into a alpha value + + alpha := (value - interval.minValue()) / interval.width(); + + \param interval Range for all values + \param value Value to map into a RGB value + \return RGB value, with an alpha value +*/ +QRgb QwtAlphaColorMap::rgb( const QwtInterval &interval, double value ) const +{ + if ( qIsNaN(value) ) + return 0u; + + const double width = interval.width(); + if ( width <= 0.0 ) + return 0u; + + if ( value <= interval.minValue() ) + return d_data->rgb; + + if ( value >= interval.maxValue() ) + return d_data->rgbMax; + + const double ratio = ( value - interval.minValue() ) / width; + return d_data->rgb | ( qRound( 255 * ratio ) << 24 ); +} + +/*! + Dummy function, needed to be implemented as it is pure virtual + in QwtColorMap. Color indices make no sense in combination with + an alpha channel. + + \return Always 0 +*/ +unsigned char QwtAlphaColorMap::colorIndex( + const QwtInterval &, double ) const +{ + return 0; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_color_map.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_color_map.h new file mode 100644 index 0000000..f36e564 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_color_map.h @@ -0,0 +1,200 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_COLOR_MAP_H +#define QWT_COLOR_MAP_H + +#include "qwt_global.h" +#include "qwt_interval.h" +#include +#include + +/*! + \brief QwtColorMap is used to map values into colors. + + For displaying 3D data on a 2D plane the 3rd dimension is often + displayed using colors, like f.e in a spectrogram. + + Each color map is optimized to return colors for only one of the + following image formats: + + - QImage::Format_Indexed8\n + - QImage::Format_ARGB32\n + + \sa QwtPlotSpectrogram, QwtScaleWidget +*/ + +class QWT_EXPORT QwtColorMap +{ +public: + /*! + Format for color mapping + \sa rgb(), colorIndex(), colorTable() + */ + + enum Format + { + //! The map is intended to map into RGB values. + RGB, + + /*! + The map is intended to map into 8 bit values, that + are indices into the color table. + */ + Indexed + }; + + QwtColorMap( Format = QwtColorMap::RGB ); + virtual ~QwtColorMap(); + + Format format() const; + + /*! + Map a value of a given interval into a RGB value. + + \param interval Range for the values + \param value Value + \return RGB value, corresponding to value + */ + virtual QRgb rgb( const QwtInterval &interval, + double value ) const = 0; + + /*! + Map a value of a given interval into a color index + + \param interval Range for the values + \param value Value + \return color index, corresponding to value + */ + virtual unsigned char colorIndex( + const QwtInterval &interval, double value ) const = 0; + + QColor color( const QwtInterval &, double value ) const; + virtual QVector colorTable( const QwtInterval & ) const; + +private: + Format d_format; +}; + +/*! + \brief QwtLinearColorMap builds a color map from color stops. + + A color stop is a color at a specific position. The valid + range for the positions is [0.0, 1.0]. When mapping a value + into a color it is translated into this interval according to mode(). +*/ +class QWT_EXPORT QwtLinearColorMap: public QwtColorMap +{ +public: + /*! + Mode of color map + \sa setMode(), mode() + */ + enum Mode + { + //! Return the color from the next lower color stop + FixedColors, + + //! Interpolating the colors of the adjacent stops. + ScaledColors + }; + + QwtLinearColorMap( QwtColorMap::Format = QwtColorMap::RGB ); + QwtLinearColorMap( const QColor &from, const QColor &to, + QwtColorMap::Format = QwtColorMap::RGB ); + + virtual ~QwtLinearColorMap(); + + void setMode( Mode ); + Mode mode() const; + + void setColorInterval( const QColor &color1, const QColor &color2 ); + void addColorStop( double value, const QColor& ); + QVector colorStops() const; + + QColor color1() const; + QColor color2() const; + + virtual QRgb rgb( const QwtInterval &, double value ) const; + virtual unsigned char colorIndex( + const QwtInterval &, double value ) const; + + class ColorStops; + +private: + // Disabled copy constructor and operator= + QwtLinearColorMap( const QwtLinearColorMap & ); + QwtLinearColorMap &operator=( const QwtLinearColorMap & ); + + class PrivateData; + PrivateData *d_data; +}; + +/*! + \brief QwtAlphaColorMap varies the alpha value of a color +*/ +class QWT_EXPORT QwtAlphaColorMap: public QwtColorMap +{ +public: + QwtAlphaColorMap( const QColor & = QColor( Qt::gray ) ); + virtual ~QwtAlphaColorMap(); + + void setColor( const QColor & ); + QColor color() const; + + virtual QRgb rgb( const QwtInterval &, double value ) const; + +private: + QwtAlphaColorMap( const QwtAlphaColorMap & ); + QwtAlphaColorMap &operator=( const QwtAlphaColorMap & ); + + virtual unsigned char colorIndex( + const QwtInterval &, double value ) const; + + class PrivateData; + PrivateData *d_data; +}; + + +/*! + Map a value into a color + + \param interval Valid interval for values + \param value Value + + \return Color corresponding to value + + \warning This method is slow for Indexed color maps. If it is + necessary to map many values, its better to get the + color table once and find the color using colorIndex(). +*/ +inline QColor QwtColorMap::color( + const QwtInterval &interval, double value ) const +{ + if ( d_format == RGB ) + { + return QColor::fromRgba( rgb( interval, value ) ); + } + else + { + const unsigned int index = colorIndex( interval, value ); + return colorTable( interval )[index]; // slow + } +} + +/*! + \return Intended format of the color map + \sa Format +*/ +inline QwtColorMap::Format QwtColorMap::format() const +{ + return d_format; +} + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_column_symbol.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_column_symbol.cpp new file mode 100644 index 0000000..ab428d9 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_column_symbol.cpp @@ -0,0 +1,293 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_column_symbol.h" +#include "qwt_math.h" +#include "qwt_painter.h" +#include +#include + +static void qwtDrawBox( QPainter *p, const QRectF &rect, + const QPalette &pal, double lw ) +{ + if ( lw > 0.0 ) + { + if ( rect.width() == 0.0 ) + { + p->setPen( pal.dark().color() ); + p->drawLine( rect.topLeft(), rect.bottomLeft() ); + return; + } + + if ( rect.height() == 0.0 ) + { + p->setPen( pal.dark().color() ); + p->drawLine( rect.topLeft(), rect.topRight() ); + return; + } + + lw = qMin( lw, rect.height() / 2.0 - 1.0 ); + lw = qMin( lw, rect.width() / 2.0 - 1.0 ); + + const QRectF outerRect = rect.adjusted( 0, 0, 1, 1 ); + QPolygonF polygon( outerRect ); + + if ( outerRect.width() > 2 * lw && + outerRect.height() > 2 * lw ) + { + const QRectF innerRect = outerRect.adjusted( lw, lw, -lw, -lw ); + polygon = polygon.subtracted( innerRect ); + } + + p->setPen( Qt::NoPen ); + + p->setBrush( pal.dark() ); + p->drawPolygon( polygon ); + } + + const QRectF windowRect = rect.adjusted( lw, lw, -lw + 1, -lw + 1 ); + if ( windowRect.isValid() ) + p->fillRect( windowRect, pal.window() ); +} + +static void qwtDrawPanel( QPainter *painter, const QRectF &rect, + const QPalette &pal, double lw ) +{ + if ( lw > 0.0 ) + { + if ( rect.width() == 0.0 ) + { + painter->setPen( pal.window().color() ); + painter->drawLine( rect.topLeft(), rect.bottomLeft() ); + return; + } + + if ( rect.height() == 0.0 ) + { + painter->setPen( pal.window().color() ); + painter->drawLine( rect.topLeft(), rect.topRight() ); + return; + } + + lw = qMin( lw, rect.height() / 2.0 - 1.0 ); + lw = qMin( lw, rect.width() / 2.0 - 1.0 ); + + const QRectF outerRect = rect.adjusted( 0, 0, 1, 1 ); + const QRectF innerRect = outerRect.adjusted( lw, lw, -lw, -lw ); + + QPolygonF lines[2]; + + lines[0] += outerRect.bottomLeft(); + lines[0] += outerRect.topLeft(); + lines[0] += outerRect.topRight(); + lines[0] += innerRect.topRight(); + lines[0] += innerRect.topLeft(); + lines[0] += innerRect.bottomLeft(); + + lines[1] += outerRect.topRight(); + lines[1] += outerRect.bottomRight(); + lines[1] += outerRect.bottomLeft(); + lines[1] += innerRect.bottomLeft(); + lines[1] += innerRect.bottomRight(); + lines[1] += innerRect.topRight(); + + painter->setPen( Qt::NoPen ); + + painter->setBrush( pal.light() ); + painter->drawPolygon( lines[0] ); + painter->setBrush( pal.dark() ); + painter->drawPolygon( lines[1] ); + } + + painter->fillRect( rect.adjusted( lw, lw, -lw + 1, -lw + 1 ), pal.window() ); +} + +class QwtColumnSymbol::PrivateData +{ +public: + PrivateData(): + style( QwtColumnSymbol::Box ), + frameStyle( QwtColumnSymbol::Raised ), + lineWidth( 2 ) + { + palette = QPalette( Qt::gray ); + } + + QwtColumnSymbol::Style style; + QwtColumnSymbol::FrameStyle frameStyle; + + QPalette palette; + int lineWidth; +}; + +/*! + Constructor + + \param style Style of the symbol + \sa setStyle(), style(), Style +*/ +QwtColumnSymbol::QwtColumnSymbol( Style style ) +{ + d_data = new PrivateData(); + d_data->style = style; +} + +//! Destructor +QwtColumnSymbol::~QwtColumnSymbol() +{ + delete d_data; +} + +/*! + Specify the symbol style + + \param style Style + \sa style(), setPalette() +*/ +void QwtColumnSymbol::setStyle( Style style ) +{ + d_data->style = style; +} + +/*! + \return Current symbol style + \sa setStyle() +*/ +QwtColumnSymbol::Style QwtColumnSymbol::style() const +{ + return d_data->style; +} + +/*! + Assign a palette for the symbol + + \param palette Palette + \sa palette(), setStyle() +*/ +void QwtColumnSymbol::setPalette( const QPalette &palette ) +{ + d_data->palette = palette; +} + +/*! + \return Current palette + \sa setPalette() +*/ +const QPalette& QwtColumnSymbol::palette() const +{ + return d_data->palette; +} + +/*! + Set the frame, that is used for the Box style. + + \param frameStyle Frame style + \sa frameStyle(), setLineWidth(), setStyle() +*/ +void QwtColumnSymbol::setFrameStyle( FrameStyle frameStyle ) +{ + d_data->frameStyle = frameStyle; +} + +/*! + \return Current frame style, that is used for the Box style. + \sa setFrameStyle(), lineWidth(), setStyle() +*/ +QwtColumnSymbol::FrameStyle QwtColumnSymbol::frameStyle() const +{ + return d_data->frameStyle; +} + +/*! + Set the line width of the frame, that is used for the Box style. + + \param width Width + \sa lineWidth(), setFrameStyle() +*/ +void QwtColumnSymbol::setLineWidth( int width ) +{ + if ( width < 0 ) + width = 0; + + d_data->lineWidth = width; +} + +/*! + \return Line width of the frame, that is used for the Box style. + \sa setLineWidth(), frameStyle(), setStyle() +*/ +int QwtColumnSymbol::lineWidth() const +{ + return d_data->lineWidth; +} + +/*! + Draw the symbol depending on its style. + + \param painter Painter + \param rect Directed rectangle + + \sa drawBox() +*/ +void QwtColumnSymbol::draw( QPainter *painter, + const QwtColumnRect &rect ) const +{ + painter->save(); + + switch ( d_data->style ) + { + case QwtColumnSymbol::Box: + { + drawBox( painter, rect ); + break; + } + default:; + } + + painter->restore(); +} + +/*! + Draw the symbol when it is in Box style. + + \param painter Painter + \param rect Directed rectangle + + \sa draw() +*/ +void QwtColumnSymbol::drawBox( QPainter *painter, + const QwtColumnRect &rect ) const +{ + QRectF r = rect.toRect(); + if ( QwtPainter::roundingAlignment( painter ) ) + { + r.setLeft( qRound( r.left() ) ); + r.setRight( qRound( r.right() ) ); + r.setTop( qRound( r.top() ) ); + r.setBottom( qRound( r.bottom() ) ); + } + + switch ( d_data->frameStyle ) + { + case QwtColumnSymbol::Raised: + { + qwtDrawPanel( painter, r, d_data->palette, d_data->lineWidth ); + break; + } + case QwtColumnSymbol::Plain: + { + qwtDrawBox( painter, r, d_data->palette, d_data->lineWidth ); + break; + } + default: + { + painter->fillRect( r, d_data->palette.window() ); + } + } +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_column_symbol.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_column_symbol.h new file mode 100644 index 0000000..83d9a2e --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_column_symbol.h @@ -0,0 +1,161 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_COLUMN_SYMBOL_H +#define QWT_COLUMN_SYMBOL_H + +#include "qwt_global.h" +#include "qwt_interval.h" +#include +#include +#include + +class QPainter; +class QPalette; +class QRect; +class QwtText; + +/*! + \brief Directed rectangle representing bounding rectangle and orientation + of a column. +*/ +class QWT_EXPORT QwtColumnRect +{ +public: + //! Direction of the column + enum Direction + { + //! From left to right + LeftToRight, + + //! From right to left + RightToLeft, + + //! From bottom to top + BottomToTop, + + //! From top to bottom + TopToBottom + }; + + //! Build an rectangle with invalid intervals directed BottomToTop. + QwtColumnRect(): + direction( BottomToTop ) + { + } + + //! \return A normalized QRect built from the intervals + QRectF toRect() const + { + QRectF r( hInterval.minValue(), vInterval.minValue(), + hInterval.maxValue() - hInterval.minValue(), + vInterval.maxValue() - vInterval.minValue() ); + r = r.normalized(); + + if ( hInterval.borderFlags() & QwtInterval::ExcludeMinimum ) + r.adjust( 1, 0, 0, 0 ); + if ( hInterval.borderFlags() & QwtInterval::ExcludeMaximum ) + r.adjust( 0, 0, -1, 0 ); + if ( vInterval.borderFlags() & QwtInterval::ExcludeMinimum ) + r.adjust( 0, 1, 0, 0 ); + if ( vInterval.borderFlags() & QwtInterval::ExcludeMaximum ) + r.adjust( 0, 0, 0, -1 ); + + return r; + } + + //! \return Orientation + Qt::Orientation orientation() const + { + if ( direction == LeftToRight || direction == RightToLeft ) + return Qt::Horizontal; + + return Qt::Vertical; + } + + //! Interval for the horizontal coordinates + QwtInterval hInterval; + + //! Interval for the vertical coordinates + QwtInterval vInterval; + + //! Direction + Direction direction; +}; + +//! A drawing primitive for columns +class QWT_EXPORT QwtColumnSymbol +{ +public: + /*! + Style + \sa setStyle(), style() + */ + enum Style + { + //! No Style, the symbol draws nothing + NoStyle = -1, + + /*! + The column is painted with a frame depending on the frameStyle() + and lineWidth() using the palette(). + */ + Box, + + /*! + Styles >= QwtColumnSymbol::UserStyle are reserved for derived + classes of QwtColumnSymbol that overload draw() with + additional application specific symbol types. + */ + UserStyle = 1000 + }; + + /*! + Frame Style used in Box style(). + \sa Style, setFrameStyle(), frameStyle(), setStyle(), setPalette() + */ + enum FrameStyle + { + //! No frame + NoFrame, + + //! A plain frame style + Plain, + + //! A raised frame style + Raised + }; + +public: + QwtColumnSymbol( Style = NoStyle ); + virtual ~QwtColumnSymbol(); + + void setFrameStyle( FrameStyle style ); + FrameStyle frameStyle() const; + + void setLineWidth( int width ); + int lineWidth() const; + + void setPalette( const QPalette & ); + const QPalette &palette() const; + + void setStyle( Style ); + Style style() const; + + virtual void draw( QPainter *, const QwtColumnRect & ) const; + +protected: + void drawBox( QPainter *, const QwtColumnRect & ) const; + +private: + class PrivateData; + PrivateData* d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compass.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compass.cpp new file mode 100644 index 0000000..f503f8e --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compass.cpp @@ -0,0 +1,308 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_compass.h" +#include "qwt_compass_rose.h" +#include "qwt_math.h" +#include "qwt_scale_draw.h" +#include "qwt_painter.h" +#include "qwt_dial_needle.h" +#include +#include +#include + +/*! + \brief Constructor + + Initializes a label map for multiples of 45 degrees + */ +QwtCompassScaleDraw::QwtCompassScaleDraw() +{ + enableComponent( QwtAbstractScaleDraw::Backbone, false ); + enableComponent( QwtAbstractScaleDraw::Ticks, false ); + + d_labelMap.insert( 0.0, QString::fromLatin1( "N" ) ); + d_labelMap.insert( 45.0, QString::fromLatin1( "NE" ) ); + d_labelMap.insert( 90.0, QString::fromLatin1( "E" ) ); + d_labelMap.insert( 135.0, QString::fromLatin1( "SE" ) ); + d_labelMap.insert( 180.0, QString::fromLatin1( "S" ) ); + d_labelMap.insert( 225.0, QString::fromLatin1( "SW" ) ); + d_labelMap.insert( 270.0, QString::fromLatin1( "W" ) ); + d_labelMap.insert( 315.0, QString::fromLatin1( "NW" ) ); + +#if 0 + d_labelMap.insert( 22.5, QString::fromLatin1( "NNE" ) ); + d_labelMap.insert( 67.5, QString::fromLatin1( "NEE" ) ); + d_labelMap.insert( 112.5, QString::fromLatin1( "SEE" ) ); + d_labelMap.insert( 157.5, QString::fromLatin1( "SSE" ) ); + d_labelMap.insert( 202.5, QString::fromLatin1( "SSW" ) ); + d_labelMap.insert( 247.5, QString::fromLatin1( "SWW" ) ); + d_labelMap.insert( 292.5, QString::fromLatin1( "NWW" ) ); + d_labelMap.insert( 337.5, QString::fromLatin1( "NNW" ) ); +#endif +} + +/*! + \brief Constructor + + \param map Value to label map + */ +QwtCompassScaleDraw::QwtCompassScaleDraw( const QMap &map ): + d_labelMap( map ) +{ + enableComponent( QwtAbstractScaleDraw::Backbone, false ); + enableComponent( QwtAbstractScaleDraw::Ticks, false ); +} + +/*! + \brief Set a map, mapping values to labels + \param map Value to label map + + The values of the major ticks are found by looking into this + map. The default map consists of the labels N, NE, E, SE, S, SW, W, NW. + + \warning The map will have no effect for values that are no major + tick values. Major ticks can be changed by QwtScaleDraw::setScale + + \sa labelMap(), scaleDraw(), setScale() +*/ +void QwtCompassScaleDraw::setLabelMap( const QMap &map ) +{ + d_labelMap = map; +} + + +/*! + \return map, mapping values to labels + \sa setLabelMap() +*/ +QMap QwtCompassScaleDraw::labelMap() const +{ + return d_labelMap; +} + +/*! + Map a value to a corresponding label + + \param value Value that will be mapped + + label() looks in the labelMap() for a corresponding label for value + or returns an null text. + + \return Label, or QString::null + \sa labelMap(), setLabelMap() +*/ + +QwtText QwtCompassScaleDraw::label( double value ) const +{ + if ( qFuzzyCompare( value + 1.0, 1.0 ) ) + value = 0.0; + + if ( value < 0.0 ) + value += 360.0; + + if ( d_labelMap.contains( value ) ) + return d_labelMap[value]; + + return QwtText(); +} + +class QwtCompass::PrivateData +{ +public: + PrivateData(): + rose( NULL ) + { + } + + ~PrivateData() + { + delete rose; + } + + QwtCompassRose *rose; +}; + +/*! + \brief Constructor + \param parent Parent widget + + Create a compass widget with a scale, no needle and no rose. + The default origin is 270.0 with no valid value. It accepts + mouse and keyboard inputs and has no step size. The default mode + is QwtDial::RotateNeedle. +*/ +QwtCompass::QwtCompass( QWidget* parent ): + QwtDial( parent ) +{ + d_data = new PrivateData; + + setScaleDraw( new QwtCompassScaleDraw() ); + + setOrigin( 270.0 ); + setWrapping( true ); + + setScaleMaxMajor( 36 ); + setScaleMaxMinor( 10 ); + + setScale( 0.0, 360.0 ); // degrees as default + setTotalSteps( 360 ); +} + +//! Destructor +QwtCompass::~QwtCompass() +{ + delete d_data; +} + + +/*! + Draw the contents of the scale + + \param painter Painter + \param center Center of the content circle + \param radius Radius of the content circle +*/ +void QwtCompass::drawScaleContents( QPainter *painter, + const QPointF ¢er, double radius ) const +{ + QPalette::ColorGroup cg; + if ( isEnabled() ) + cg = hasFocus() ? QPalette::Active : QPalette::Inactive; + else + cg = QPalette::Disabled; + + double north = origin(); + if ( isValid() ) + { + if ( mode() == RotateScale ) + north -= value(); + } + + const int margin = 4; + drawRose( painter, center, radius - margin, 360.0 - north, cg ); +} + +/*! + Draw the compass rose + + \param painter Painter + \param center Center of the compass + \param radius of the circle, where to paint the rose + \param north Direction pointing north, in degrees counter clockwise + \param cg Color group +*/ +void QwtCompass::drawRose( QPainter *painter, const QPointF ¢er, + double radius, double north, QPalette::ColorGroup cg ) const +{ + if ( d_data->rose ) + d_data->rose->draw( painter, center, radius, north, cg ); +} + +/*! + Set a rose for the compass + \param rose Compass rose + \warning The rose will be deleted, when a different rose is + set or in ~QwtCompass + \sa rose() +*/ +void QwtCompass::setRose( QwtCompassRose *rose ) +{ + if ( rose != d_data->rose ) + { + if ( d_data->rose ) + delete d_data->rose; + + d_data->rose = rose; + update(); + } +} + +/*! + \return rose + \sa setRose() +*/ +const QwtCompassRose *QwtCompass::rose() const +{ + return d_data->rose; +} + +/*! + \return rose + \sa setRose() +*/ +QwtCompassRose *QwtCompass::rose() +{ + return d_data->rose; +} + +/*! + Handles key events + + Beside the keys described in QwtDial::keyPressEvent numbers + from 1-9 (without 5) set the direction according to their + position on the num pad. + + \sa isReadOnly() +*/ +void QwtCompass::keyPressEvent( QKeyEvent *kev ) +{ + if ( isReadOnly() ) + return; + +#if 0 + if ( kev->key() == Key_5 ) + { + invalidate(); // signal ??? + return; + } +#endif + + double newValue = value(); + + if ( kev->key() >= Qt::Key_1 && kev->key() <= Qt::Key_9 ) + { + if ( mode() != RotateNeedle || kev->key() == Qt::Key_5 ) + return; + + switch ( kev->key() ) + { + case Qt::Key_6: + newValue = 180.0 * 0.0; + break; + case Qt::Key_3: + newValue = 180.0 * 0.25; + break; + case Qt::Key_2: + newValue = 180.0 * 0.5; + break; + case Qt::Key_1: + newValue = 180.0 * 0.75; + break; + case Qt::Key_4: + newValue = 180.0 * 1.0; + break; + case Qt::Key_7: + newValue = 180.0 * 1.25; + break; + case Qt::Key_8: + newValue = 180.0 * 1.5; + break; + case Qt::Key_9: + newValue = 180.0 * 1.75; + break; + } + newValue -= origin(); + setValue( newValue ); + } + else + { + QwtDial::keyPressEvent( kev ); + } +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compass.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compass.h new file mode 100644 index 0000000..9ef3480 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compass.h @@ -0,0 +1,83 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_COMPASS_H +#define QWT_COMPASS_H 1 + +#include "qwt_global.h" +#include "qwt_dial.h" +#include "qwt_round_scale_draw.h" +#include +#include + +class QwtCompassRose; + +/*! + \brief A special scale draw made for QwtCompass + + QwtCompassScaleDraw maps values to strings using + a special map, that can be modified by the application + + The default map consists of the labels N, NE, E, SE, S, SW, W, NW. + + \sa QwtCompass +*/ +class QWT_EXPORT QwtCompassScaleDraw: public QwtRoundScaleDraw +{ +public: + explicit QwtCompassScaleDraw(); + explicit QwtCompassScaleDraw( const QMap &map ); + + void setLabelMap( const QMap &map ); + QMap labelMap() const; + + virtual QwtText label( double value ) const; + +private: + QMap d_labelMap; +}; + +/*! + \brief A Compass Widget + + QwtCompass is a widget to display and enter directions. It consists + of a scale, an optional needle and rose. + + \image html dials1.png + + \note The examples/dials example shows how to use QwtCompass. +*/ + +class QWT_EXPORT QwtCompass: public QwtDial +{ + Q_OBJECT + +public: + explicit QwtCompass( QWidget* parent = NULL ); + virtual ~QwtCompass(); + + void setRose( QwtCompassRose *rose ); + const QwtCompassRose *rose() const; + QwtCompassRose *rose(); + +protected: + virtual void drawRose( QPainter *, const QPointF ¢er, + double radius, double north, QPalette::ColorGroup ) const; + + virtual void drawScaleContents( QPainter *, + const QPointF ¢er, double radius ) const; + + virtual void keyPressEvent( QKeyEvent * ); + +private: + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compass_rose.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compass_rose.cpp new file mode 100644 index 0000000..a470302 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compass_rose.cpp @@ -0,0 +1,269 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_compass_rose.h" +#include "qwt_point_polar.h" +#include "qwt_painter.h" +#include + +static QPointF qwtIntersection( + QPointF p11, QPointF p12, QPointF p21, QPointF p22 ) +{ + const QLineF line1( p11, p12 ); + const QLineF line2( p21, p22 ); + + QPointF pos; + if ( line1.intersect( line2, &pos ) == QLineF::NoIntersection ) + return QPointF(); + + return pos; +} + +class QwtSimpleCompassRose::PrivateData +{ +public: + PrivateData(): + width( 0.2 ), + numThorns( 8 ), + numThornLevels( -1 ), + shrinkFactor( 0.9 ) + { + } + + double width; + int numThorns; + int numThornLevels; + double shrinkFactor; +}; + +/*! + Constructor + + \param numThorns Number of thorns + \param numThornLevels Number of thorn levels +*/ +QwtSimpleCompassRose::QwtSimpleCompassRose( + int numThorns, int numThornLevels ) +{ + d_data = new PrivateData(); + d_data->numThorns = numThorns; + d_data->numThornLevels = numThornLevels; + + const QColor dark( 128, 128, 255 ); + const QColor light( 192, 255, 255 ); + + QPalette palette; + palette.setColor( QPalette::Dark, dark ); + palette.setColor( QPalette::Light, light ); + + setPalette( palette ); +} + +//! Destructor +QwtSimpleCompassRose::~QwtSimpleCompassRose() +{ + delete d_data; +} + +/*! + Set the Factor how to shrink the thorns with each level + The default value is 0.9. + + \param factor Shrink factor + \sa shrinkFactor() +*/ +void QwtSimpleCompassRose::setShrinkFactor( double factor ) +{ + d_data->shrinkFactor = factor; +} + +/*! + \return Factor how to shrink the thorns with each level + \sa setShrinkFactor() +*/ +double QwtSimpleCompassRose::shrinkFactor() const +{ + return d_data->shrinkFactor; +} + +/*! + Draw the rose + + \param painter Painter + \param center Center point + \param radius Radius of the rose + \param north Position + \param cg Color group +*/ +void QwtSimpleCompassRose::draw( QPainter *painter, const QPointF ¢er, + double radius, double north, QPalette::ColorGroup cg ) const +{ + QPalette pal = palette(); + pal.setCurrentColorGroup( cg ); + + drawRose( painter, pal, center, radius, north, d_data->width, + d_data->numThorns, d_data->numThornLevels, d_data->shrinkFactor ); +} + +/*! + Draw the rose + + \param painter Painter + \param palette Palette + \param center Center of the rose + \param radius Radius of the rose + \param north Position pointing to north + \param width Width of the rose + \param numThorns Number of thorns + \param numThornLevels Number of thorn levels + \param shrinkFactor Factor to shrink the thorns with each level +*/ +void QwtSimpleCompassRose::drawRose( + QPainter *painter, + const QPalette &palette, + const QPointF ¢er, double radius, double north, double width, + int numThorns, int numThornLevels, double shrinkFactor ) +{ + if ( numThorns < 4 ) + numThorns = 4; + + if ( numThorns % 4 ) + numThorns += 4 - numThorns % 4; + + if ( numThornLevels <= 0 ) + numThornLevels = numThorns / 4; + + if ( shrinkFactor >= 1.0 ) + shrinkFactor = 1.0; + + if ( shrinkFactor <= 0.5 ) + shrinkFactor = 0.5; + + painter->save(); + + painter->setPen( Qt::NoPen ); + + for ( int j = 1; j <= numThornLevels; j++ ) + { + double step = qPow( 2.0, j ) * M_PI / numThorns; + if ( step > M_PI_2 ) + break; + + double r = radius; + for ( int k = 0; k < 3; k++ ) + { + if ( j + k < numThornLevels ) + r *= shrinkFactor; + } + + double leafWidth = r * width; + if ( 2.0 * M_PI / step > 32 ) + leafWidth = 16; + + const double origin = qwtRadians( north ); + for ( double angle = origin; + angle < 2.0 * M_PI + origin; angle += step ) + { + const QPointF p = qwtPolar2Pos( center, r, angle ); + const QPointF p1 = qwtPolar2Pos( center, leafWidth, angle + M_PI_2 ); + const QPointF p2 = qwtPolar2Pos( center, leafWidth, angle - M_PI_2 ); + const QPointF p3 = qwtPolar2Pos( center, r, angle + step / 2.0 ); + const QPointF p4 = qwtPolar2Pos( center, r, angle - step / 2.0 ); + + QPainterPath darkPath; + darkPath.moveTo( center ); + darkPath.lineTo( p ); + darkPath.lineTo( qwtIntersection( center, p3, p1, p ) ); + + painter->setBrush( palette.brush( QPalette::Dark ) ); + painter->drawPath( darkPath ); + + QPainterPath lightPath; + lightPath.moveTo( center ); + lightPath.lineTo( p ); + lightPath.lineTo( qwtIntersection( center, p4, p2, p ) ); + + painter->setBrush( palette.brush( QPalette::Light ) ); + painter->drawPath( lightPath ); + } + } + painter->restore(); +} + +/*! + Set the width of the rose heads. Lower value make thinner heads. + The range is limited from 0.03 to 0.4. + + \param width Width +*/ +void QwtSimpleCompassRose::setWidth( double width ) +{ + d_data->width = width; + if ( d_data->width < 0.03 ) + d_data->width = 0.03; + + if ( d_data->width > 0.4 ) + d_data->width = 0.4; +} + +/*! + \return Width of the rose + \sa setWidth() + */ +double QwtSimpleCompassRose::width() const +{ + return d_data->width; +} + +/*! + Set the number of thorns on one level + The number is aligned to a multiple of 4, with a minimum of 4 + + \param numThorns Number of thorns + \sa numThorns(), setNumThornLevels() +*/ +void QwtSimpleCompassRose::setNumThorns( int numThorns ) +{ + if ( numThorns < 4 ) + numThorns = 4; + + if ( numThorns % 4 ) + numThorns += 4 - numThorns % 4; + + d_data->numThorns = numThorns; +} + +/*! + \return Number of thorns + \sa setNumThorns(), setNumThornLevels() +*/ +int QwtSimpleCompassRose::numThorns() const +{ + return d_data->numThorns; +} + +/*! + Set the of thorns levels + + \param numThornLevels Number of thorns levels + \sa setNumThorns(), numThornLevels() +*/ +void QwtSimpleCompassRose::setNumThornLevels( int numThornLevels ) +{ + d_data->numThornLevels = numThornLevels; +} + +/*! + \return Number of thorn levels + \sa setNumThorns(), setNumThornLevels() +*/ +int QwtSimpleCompassRose::numThornLevels() const +{ + return d_data->numThornLevels; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compass_rose.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compass_rose.h new file mode 100644 index 0000000..8a8f1ce --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compass_rose.h @@ -0,0 +1,89 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_COMPASS_ROSE_H +#define QWT_COMPASS_ROSE_H 1 + +#include "qwt_global.h" +#include + +class QPainter; + +/*! + \brief Abstract base class for a compass rose +*/ +class QWT_EXPORT QwtCompassRose +{ +public: + //! Destructor + virtual ~QwtCompassRose() {}; + + //! Assign a palette + virtual void setPalette( const QPalette &p ) + { + d_palette = p; + } + + //! \return Current palette + const QPalette &palette() const + { + return d_palette; + } + + /*! + Draw the rose + + \param painter Painter + \param center Center point + \param radius Radius of the rose + \param north Position + \param colorGroup Color group + */ + virtual void draw( QPainter *painter, + const QPointF ¢er, double radius, double north, + QPalette::ColorGroup colorGroup = QPalette::Active ) const = 0; + +private: + QPalette d_palette; +}; + +/*! + \brief A simple rose for QwtCompass +*/ +class QWT_EXPORT QwtSimpleCompassRose: public QwtCompassRose +{ +public: + QwtSimpleCompassRose( int numThorns = 8, int numThornLevels = -1 ); + virtual ~QwtSimpleCompassRose(); + + void setWidth( double w ); + double width() const; + + void setNumThorns( int count ); + int numThorns() const; + + void setNumThornLevels( int count ); + int numThornLevels() const; + + void setShrinkFactor( double factor ); + double shrinkFactor() const; + + virtual void draw( QPainter *, const QPointF ¢er, double radius, + double north, QPalette::ColorGroup = QPalette::Active ) const; + + static void drawRose( QPainter *, const QPalette &, + const QPointF ¢er, double radius, double origin, double width, + int numThorns, int numThornLevels, double shrinkFactor ); + +private: + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compat.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compat.h new file mode 100644 index 0000000..f22a6a9 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_compat.h @@ -0,0 +1,42 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef _QWT_COMPAT_H_ +#define _QWT_COMPAT_H_ + +#include "qwt_global.h" +#include "qwt_interval.h" +#include "qwt_point_3d.h" +#include +#include +#include +#include +#include +#include + +// A couple of definition for Qwt5 compatibility + +#define qwtMax qMax +#define qwtMin qMin +#define qwtAbs qAbs +#define qwtRound qRound + +#define QwtArray QVector + +typedef QList QwtValueList; +typedef QPointF QwtDoublePoint; +typedef QSizeF QwtDoubleSize; +typedef QRectF QwtDoubleRect; + +typedef QPolygon QwtPolygon; +typedef QPolygonF QwtPolygonF; +typedef QwtInterval QwtDoubleInterval; +typedef QwtPoint3D QwtDoublePoint3D; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_counter.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_counter.cpp new file mode 100644 index 0000000..662a8e8 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_counter.cpp @@ -0,0 +1,785 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_arrow_button.h" +#include "qwt_math.h" +#include "qwt_counter.h" +#include +#include +#include +#include +#include + +class QwtCounter::PrivateData +{ +public: + PrivateData(): + minimum( 0.0 ), + maximum( 0.0 ), + singleStep( 1.0 ), + isValid( false ), + value( 0.0 ), + wrapping( false ) + { + increment[Button1] = 1; + increment[Button2] = 10; + increment[Button3] = 100; + } + + QwtArrowButton *buttonDown[ButtonCnt]; + QwtArrowButton *buttonUp[ButtonCnt]; + QLineEdit *valueEdit; + + int increment[ButtonCnt]; + int numButtons; + + double minimum; + double maximum; + double singleStep; + + bool isValid; + double value; + + bool wrapping; +}; + +/*! + The counter is initialized with a range is set to [0.0, 1.0] with + 0.01 as single step size. The value is invalid. + + The default number of buttons is set to 2. The default increments are: + \li Button 1: 1 step + \li Button 2: 10 steps + \li Button 3: 100 steps + + \param parent + */ +QwtCounter::QwtCounter( QWidget *parent ): + QWidget( parent ) +{ + initCounter(); +} + +void QwtCounter::initCounter() +{ + d_data = new PrivateData; + + QHBoxLayout *layout = new QHBoxLayout( this ); + layout->setSpacing( 0 ); + layout->setMargin( 0 ); + + for ( int i = ButtonCnt - 1; i >= 0; i-- ) + { + QwtArrowButton *btn = + new QwtArrowButton( i + 1, Qt::DownArrow, this ); + btn->setFocusPolicy( Qt::NoFocus ); + btn->installEventFilter( this ); + layout->addWidget( btn ); + + connect( btn, SIGNAL( released() ), SLOT( btnReleased() ) ); + connect( btn, SIGNAL( clicked() ), SLOT( btnClicked() ) ); + + d_data->buttonDown[i] = btn; + } + + d_data->valueEdit = new QLineEdit( this ); + d_data->valueEdit->setReadOnly( false ); + d_data->valueEdit->setValidator( new QDoubleValidator( d_data->valueEdit ) ); + layout->addWidget( d_data->valueEdit ); + + connect( d_data->valueEdit, SIGNAL( editingFinished() ), + SLOT( textChanged() ) ); + + layout->setStretchFactor( d_data->valueEdit, 10 ); + + for ( int i = 0; i < ButtonCnt; i++ ) + { + QwtArrowButton *btn = + new QwtArrowButton( i + 1, Qt::UpArrow, this ); + btn->setFocusPolicy( Qt::NoFocus ); + btn->installEventFilter( this ); + layout->addWidget( btn ); + + connect( btn, SIGNAL( released() ), SLOT( btnReleased() ) ); + connect( btn, SIGNAL( clicked() ), SLOT( btnClicked() ) ); + + d_data->buttonUp[i] = btn; + } + + setNumButtons( 2 ); + setRange( 0.0, 1.0 ); + setSingleStep( 0.001 ); + setValue( 0.0 ); + + setSizePolicy( + QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) ); + + setFocusProxy( d_data->valueEdit ); + setFocusPolicy( Qt::StrongFocus ); +} + +//! Destructor +QwtCounter::~QwtCounter() +{ + delete d_data; +} + +/*! + Set the counter to be in valid/invalid state + + When the counter is set to invalid, no numbers are displayed and + the buttons are disabled. + + \param on If true the counter will be set as valid + + \sa setValue(), isValid() +*/ +void QwtCounter::setValid( bool on ) +{ + if ( on != d_data->isValid ) + { + d_data->isValid = on; + + updateButtons(); + + if ( d_data->isValid ) + { + showNumber( value() ); + Q_EMIT valueChanged( value() ); + } + else + { + d_data->valueEdit->setText( QString::null ); + } + } +} + +/*! + \return True, if the value is valid + \sa setValid(), setValue() + */ +bool QwtCounter::isValid() const +{ + return d_data->isValid; +} + +/*! + \brief Allow/disallow the user to manually edit the value + + \param on True disable editing + \sa isReadOnly() +*/ +void QwtCounter::setReadOnly( bool on ) +{ + d_data->valueEdit->setReadOnly( on ); +} + +/*! + \return True, when the line line edit is read only. (default is no) + \sa setReadOnly() + */ +bool QwtCounter::isReadOnly() const +{ + return d_data->valueEdit->isReadOnly(); +} + +/*! + \brief Set a new value without adjusting to the step raster + + The state of the counter is set to be valid. + + \param value New value + + \sa isValid(), value(), valueChanged() + \warning The value is clipped when it lies outside the range. +*/ + +void QwtCounter::setValue( double value ) +{ + const double vmin = qMin( d_data->minimum, d_data->maximum ); + const double vmax = qMax( d_data->minimum, d_data->maximum ); + + value = qBound( vmin, value, vmax ); + + if ( !d_data->isValid || value != d_data->value ) + { + d_data->isValid = true; + d_data->value = value; + + showNumber( value ); + updateButtons(); + + Q_EMIT valueChanged( value ); + } +} + +/*! + \return Current value of the counter + \sa setValue(), valueChanged() + */ +double QwtCounter::value() const +{ + return d_data->value; +} + +/*! + \brief Set the minimum and maximum values + + The maximum is adjusted if necessary to ensure that the range remains valid. + The value might be modified to be inside of the range. + + \param min Minimum value + \param max Maximum value + + \sa minimum(), maximum() + */ +void QwtCounter::setRange( double min, double max ) +{ + max = qMax( min, max ); + + if ( d_data->maximum == max && d_data->minimum == min ) + return; + + d_data->minimum = min; + d_data->maximum = max; + + setSingleStep( singleStep() ); + + const double value = qBound( min, d_data->value, max ); + + if ( value != d_data->value ) + { + d_data->value = value; + + if ( d_data->isValid ) + { + showNumber( value ); + Q_EMIT valueChanged( value ); + } + } + + updateButtons(); +} + +/*! + Set the minimum value of the range + + \param value Minimum value + \sa setRange(), setMaximum(), minimum() + + \note The maximum is adjusted if necessary to ensure that the range remains valid. +*/ +void QwtCounter::setMinimum( double value ) +{ + setRange( value, maximum() ); +} + +/*! + \return The minimum of the range + \sa setRange(), setMinimum(), maximum() +*/ +double QwtCounter::minimum() const +{ + return d_data->minimum; +} + +/*! + Set the maximum value of the range + + \param value Maximum value + \sa setRange(), setMinimum(), maximum() +*/ +void QwtCounter::setMaximum( double value ) +{ + setRange( minimum(), value ); +} + +/*! + \return The maximum of the range + \sa setRange(), setMaximum(), minimum() +*/ +double QwtCounter::maximum() const +{ + return d_data->maximum; +} + +/*! + \brief Set the step size of the counter + + A value <= 0.0 disables stepping + + \param stepSize Single step size + \sa singleStep() +*/ +void QwtCounter::setSingleStep( double stepSize ) +{ + d_data->singleStep = qMax( stepSize, 0.0 ); +} + +/*! + \return Single step size + \sa setSingleStep() + */ +double QwtCounter::singleStep() const +{ + return d_data->singleStep; +} + +/*! + \brief En/Disable wrapping + + If wrapping is true stepping up from maximum() value will take + you to the minimum() value and vice versa. + + \param on En/Disable wrapping + \sa wrapping() + */ +void QwtCounter::setWrapping( bool on ) +{ + d_data->wrapping = on; +} + +/*! + \return True, when wrapping is set + \sa setWrapping() + */ +bool QwtCounter::wrapping() const +{ + return d_data->wrapping; +} + +/*! + Specify the number of buttons on each side of the label + + \param numButtons Number of buttons + \sa numButtons() +*/ +void QwtCounter::setNumButtons( int numButtons ) +{ + if ( numButtons < 0 || numButtons > QwtCounter::ButtonCnt ) + return; + + for ( int i = 0; i < QwtCounter::ButtonCnt; i++ ) + { + if ( i < numButtons ) + { + d_data->buttonDown[i]->show(); + d_data->buttonUp[i]->show(); + } + else + { + d_data->buttonDown[i]->hide(); + d_data->buttonUp[i]->hide(); + } + } + + d_data->numButtons = numButtons; +} + +/*! + \return The number of buttons on each side of the widget. + \sa setNumButtons() +*/ +int QwtCounter::numButtons() const +{ + return d_data->numButtons; +} + +/*! + Specify the number of steps by which the value + is incremented or decremented when a specified button + is pushed. + + \param button Button index + \param numSteps Number of steps + + \sa incSteps() +*/ +void QwtCounter::setIncSteps( QwtCounter::Button button, int numSteps ) +{ + if ( button >= 0 && button < QwtCounter::ButtonCnt ) + d_data->increment[ button ] = numSteps; +} + +/*! + \return The number of steps by which a specified button increments the value + or 0 if the button is invalid. + \param button Button index + + \sa setIncSteps() +*/ +int QwtCounter::incSteps( QwtCounter::Button button ) const +{ + if ( button >= 0 && button < QwtCounter::ButtonCnt ) + return d_data->increment[ button ]; + + return 0; +} + + +/*! + Set the number of increment steps for button 1 + \param nSteps Number of steps +*/ +void QwtCounter::setStepButton1( int nSteps ) +{ + setIncSteps( QwtCounter::Button1, nSteps ); +} + +//! returns the number of increment steps for button 1 +int QwtCounter::stepButton1() const +{ + return incSteps( QwtCounter::Button1 ); +} + +/*! + Set the number of increment steps for button 2 + \param nSteps Number of steps +*/ +void QwtCounter::setStepButton2( int nSteps ) +{ + setIncSteps( QwtCounter::Button2, nSteps ); +} + +//! returns the number of increment steps for button 2 +int QwtCounter::stepButton2() const +{ + return incSteps( QwtCounter::Button2 ); +} + +/*! + Set the number of increment steps for button 3 + \param nSteps Number of steps +*/ +void QwtCounter::setStepButton3( int nSteps ) +{ + setIncSteps( QwtCounter::Button3, nSteps ); +} + +//! returns the number of increment steps for button 3 +int QwtCounter::stepButton3() const +{ + return incSteps( QwtCounter::Button3 ); +} + +//! Set from lineedit +void QwtCounter::textChanged() +{ + bool converted = false; + + const double value = d_data->valueEdit->text().toDouble( &converted ); + if ( converted ) + setValue( value ); +} + +/*! + Handle QEvent::PolishRequest events + \param event Event + \return see QWidget::event() +*/ +bool QwtCounter::event( QEvent *event ) +{ + if ( event->type() == QEvent::PolishRequest ) + { + const int w = d_data->valueEdit->fontMetrics().width( "W" ) + 8; + for ( int i = 0; i < ButtonCnt; i++ ) + { + d_data->buttonDown[i]->setMinimumWidth( w ); + d_data->buttonUp[i]->setMinimumWidth( w ); + } + } + + return QWidget::event( event ); +} + +/*! + Handle key events + + - Ctrl + Qt::Key_Home\n + Step to minimum() + - Ctrl + Qt::Key_End\n + Step to maximum() + - Qt::Key_Up\n + Increment by incSteps(QwtCounter::Button1) + - Qt::Key_Down\n + Decrement by incSteps(QwtCounter::Button1) + - Qt::Key_PageUp\n + Increment by incSteps(QwtCounter::Button2) + - Qt::Key_PageDown\n + Decrement by incSteps(QwtCounter::Button2) + - Shift + Qt::Key_PageUp\n + Increment by incSteps(QwtCounter::Button3) + - Shift + Qt::Key_PageDown\n + Decrement by incSteps(QwtCounter::Button3) + + \param event Key event +*/ +void QwtCounter::keyPressEvent ( QKeyEvent *event ) +{ + bool accepted = true; + + switch ( event->key() ) + { + case Qt::Key_Home: + { + if ( event->modifiers() & Qt::ControlModifier ) + setValue( minimum() ); + else + accepted = false; + break; + } + case Qt::Key_End: + { + if ( event->modifiers() & Qt::ControlModifier ) + setValue( maximum() ); + else + accepted = false; + break; + } + case Qt::Key_Up: + { + incrementValue( d_data->increment[0] ); + break; + } + case Qt::Key_Down: + { + incrementValue( -d_data->increment[0] ); + break; + } + case Qt::Key_PageUp: + case Qt::Key_PageDown: + { + int increment = d_data->increment[0]; + if ( d_data->numButtons >= 2 ) + increment = d_data->increment[1]; + if ( d_data->numButtons >= 3 ) + { + if ( event->modifiers() & Qt::ShiftModifier ) + increment = d_data->increment[2]; + } + if ( event->key() == Qt::Key_PageDown ) + increment = -increment; + incrementValue( increment ); + break; + } + default: + { + accepted = false; + } + } + + if ( accepted ) + { + event->accept(); + return; + } + + QWidget::keyPressEvent ( event ); +} + +/*! + Handle wheel events + \param event Wheel event +*/ +void QwtCounter::wheelEvent( QWheelEvent *event ) +{ + event->accept(); + + if ( d_data->numButtons <= 0 ) + return; + + int increment = d_data->increment[0]; + if ( d_data->numButtons >= 2 ) + { + if ( event->modifiers() & Qt::ControlModifier ) + increment = d_data->increment[1]; + } + if ( d_data->numButtons >= 3 ) + { + if ( event->modifiers() & Qt::ShiftModifier ) + increment = d_data->increment[2]; + } + + for ( int i = 0; i < d_data->numButtons; i++ ) + { + if ( d_data->buttonDown[i]->geometry().contains( event->pos() ) || + d_data->buttonUp[i]->geometry().contains( event->pos() ) ) + { + increment = d_data->increment[i]; + } + } + + const int wheel_delta = 120; + +#if 1 + int delta = event->delta(); + if ( delta >= 2 * wheel_delta ) + delta /= 2; // Never saw an abs(delta) < 240 +#endif + + incrementValue( delta / wheel_delta * increment ); +} + +void QwtCounter::incrementValue( int numSteps ) +{ + const double min = d_data->minimum; + const double max = d_data->maximum; + double stepSize = d_data->singleStep; + + if ( !d_data->isValid || min >= max || stepSize <= 0.0 ) + return; + + +#if 1 + stepSize = qMax( stepSize, 1.0e-10 * ( max - min ) ); +#endif + + double value = d_data->value + numSteps * stepSize; + + if ( d_data->wrapping ) + { + const double range = max - min; + + if ( value < min ) + { + value += ::ceil( ( min - value ) / range ) * range; + } + else if ( value > max ) + { + value -= ::ceil( ( value - max ) / range ) * range; + } + } + else + { + value = qBound( min, value, max ); + } + + value = min + qRound( ( value - min ) / stepSize ) * stepSize; + + if ( stepSize > 1e-12 ) + { + if ( qFuzzyCompare( value + 1.0, 1.0 ) ) + { + // correct rounding error if value = 0 + value = 0.0; + } + else if ( qFuzzyCompare( value, max ) ) + { + // correct rounding error at the border + value = max; + } + } + + if ( value != d_data->value ) + { + d_data->value = value; + showNumber( d_data->value ); + updateButtons(); + + Q_EMIT valueChanged( d_data->value ); + } +} + + +/*! + \brief Update buttons according to the current value + + When the QwtCounter under- or over-flows, the focus is set to the smallest + up- or down-button and counting is disabled. + + Counting is re-enabled on a button release event (mouse or space bar). +*/ +void QwtCounter::updateButtons() +{ + if ( d_data->isValid ) + { + // 1. save enabled state of the smallest down- and up-button + // 2. change enabled state on under- or over-flow + + for ( int i = 0; i < QwtCounter::ButtonCnt; i++ ) + { + d_data->buttonDown[i]->setEnabled( value() > minimum() ); + d_data->buttonUp[i]->setEnabled( value() < maximum() ); + } + } + else + { + for ( int i = 0; i < QwtCounter::ButtonCnt; i++ ) + { + d_data->buttonDown[i]->setEnabled( false ); + d_data->buttonUp[i]->setEnabled( false ); + } + } +} +/*! + Display number string + + \param number Number +*/ +void QwtCounter::showNumber( double number ) +{ + QString text; + text.setNum( number ); + + const int cursorPos = d_data->valueEdit->cursorPosition(); + d_data->valueEdit->setText( text ); + d_data->valueEdit->setCursorPosition( cursorPos ); +} + +//! Button clicked +void QwtCounter::btnClicked() +{ + for ( int i = 0; i < ButtonCnt; i++ ) + { + if ( d_data->buttonUp[i] == sender() ) + incrementValue( d_data->increment[i] ); + + if ( d_data->buttonDown[i] == sender() ) + incrementValue( -d_data->increment[i] ); + } +} + +//! Button released +void QwtCounter::btnReleased() +{ + Q_EMIT buttonReleased( value() ); +} + +//! A size hint +QSize QwtCounter::sizeHint() const +{ + QString tmp; + + int w = tmp.setNum( minimum() ).length(); + int w1 = tmp.setNum( maximum() ).length(); + if ( w1 > w ) + w = w1; + w1 = tmp.setNum( minimum() + singleStep() ).length(); + if ( w1 > w ) + w = w1; + w1 = tmp.setNum( maximum() - singleStep() ).length(); + if ( w1 > w ) + w = w1; + + tmp.fill( '9', w ); + + QFontMetrics fm( d_data->valueEdit->font() ); + w = fm.width( tmp ) + 2; + if ( d_data->valueEdit->hasFrame() ) + w += 2 * style()->pixelMetric( QStyle::PM_DefaultFrameWidth ); + + // Now we replace default sizeHint contribution of d_data->valueEdit by + // what we really need. + + w += QWidget::sizeHint().width() - d_data->valueEdit->sizeHint().width(); + + const int h = qMin( QWidget::sizeHint().height(), + d_data->valueEdit->minimumSizeHint().height() ); + return QSize( w, h ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_counter.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_counter.h new file mode 100644 index 0000000..52a9e92 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_counter.h @@ -0,0 +1,161 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_COUNTER_H +#define QWT_COUNTER_H + +#include "qwt_global.h" +#include + +/*! + \brief The Counter Widget + + A Counter consists of a label displaying a number and + one ore more (up to three) push buttons on each side + of the label which can be used to increment or decrement + the counter's value. + + A counter has a range from a minimum value to a maximum value + and a step size. When the wrapping property is set + the counter is circular. + + The number of steps by which a button increments or decrements the value + can be specified using setIncSteps(). The number of buttons can be + changed with setNumButtons(). + + Example: +\code +#include + +QwtCounter *counter = new QwtCounter(parent); + +counter->setRange(0.0, 100.0); // From 0.0 to 100 +counter->setSingleStep( 1.0 ); // Step size 1.0 +counter->setNumButtons(2); // Two buttons each side +counter->setIncSteps(QwtCounter::Button1, 1); // Button 1 increments 1 step +counter->setIncSteps(QwtCounter::Button2, 20); // Button 2 increments 20 steps + +connect(counter, SIGNAL(valueChanged(double)), myClass, SLOT(newValue(double))); +\endcode + */ + +class QWT_EXPORT QwtCounter : public QWidget +{ + Q_OBJECT + + Q_PROPERTY( double value READ value WRITE setValue ) + Q_PROPERTY( double minimum READ minimum WRITE setMinimum ) + Q_PROPERTY( double maximum READ maximum WRITE setMaximum ) + Q_PROPERTY( double singleStep READ singleStep WRITE setSingleStep ) + + Q_PROPERTY( int numButtons READ numButtons WRITE setNumButtons ) + Q_PROPERTY( int stepButton1 READ stepButton1 WRITE setStepButton1 ) + Q_PROPERTY( int stepButton2 READ stepButton2 WRITE setStepButton2 ) + Q_PROPERTY( int stepButton3 READ stepButton3 WRITE setStepButton3 ) + + Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly ) + Q_PROPERTY( bool wrapping READ wrapping WRITE setWrapping ) + +public: + //! Button index + enum Button + { + //! Button intended for minor steps + Button1, + + //! Button intended for medium steps + Button2, + + //! Button intended for large steps + Button3, + + //! Number of buttons + ButtonCnt + }; + + explicit QwtCounter( QWidget *parent = NULL ); + virtual ~QwtCounter(); + + void setValid( bool ); + bool isValid() const; + + void setWrapping( bool ); + bool wrapping() const; + + bool isReadOnly() const; + void setReadOnly( bool ); + + void setNumButtons( int n ); + int numButtons() const; + + void setIncSteps( QwtCounter::Button btn, int nSteps ); + int incSteps( QwtCounter::Button btn ) const; + + virtual QSize sizeHint() const; + + double singleStep() const; + void setSingleStep( double s ); + + void setRange( double min, double max ); + + double minimum() const; + void setMinimum( double min ); + + double maximum() const; + void setMaximum( double max ); + + void setStepButton1( int nSteps ); + int stepButton1() const; + + void setStepButton2( int nSteps ); + int stepButton2() const; + + void setStepButton3( int nSteps ); + int stepButton3() const; + + double value() const; + +public Q_SLOTS: + void setValue( double ); + + +Q_SIGNALS: + /*! + This signal is emitted when a button has been released + \param value The new value + */ + void buttonReleased ( double value ); + + /*! + This signal is emitted when the counter's value has changed + \param value The new value + */ + void valueChanged ( double value ); + +protected: + virtual bool event( QEvent * ); + virtual void wheelEvent( QWheelEvent * ); + virtual void keyPressEvent( QKeyEvent * ); + +private Q_SLOTS: + void btnReleased(); + void btnClicked(); + void textChanged(); + +private: + void incrementValue( int numSteps ); + void initCounter(); + void updateButtons(); + void showNumber( double ); + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_curve_fitter.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_curve_fitter.cpp new file mode 100644 index 0000000..c037c85 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_curve_fitter.cpp @@ -0,0 +1,453 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_curve_fitter.h" +#include "qwt_math.h" +#include "qwt_spline.h" +#include +#include + +#if QT_VERSION < 0x040601 +#define qFabs(x) ::fabs(x) +#endif + +//! Constructor +QwtCurveFitter::QwtCurveFitter() +{ +} + +//! Destructor +QwtCurveFitter::~QwtCurveFitter() +{ +} + +class QwtSplineCurveFitter::PrivateData +{ +public: + PrivateData(): + fitMode( QwtSplineCurveFitter::Auto ), + splineSize( 250 ) + { + } + + QwtSpline spline; + QwtSplineCurveFitter::FitMode fitMode; + int splineSize; +}; + +//! Constructor +QwtSplineCurveFitter::QwtSplineCurveFitter() +{ + d_data = new PrivateData; +} + +//! Destructor +QwtSplineCurveFitter::~QwtSplineCurveFitter() +{ + delete d_data; +} + +/*! + Select the algorithm used for building the spline + + \param mode Mode representing a spline algorithm + \sa fitMode() +*/ +void QwtSplineCurveFitter::setFitMode( FitMode mode ) +{ + d_data->fitMode = mode; +} + +/*! + \return Mode representing a spline algorithm + \sa setFitMode() +*/ +QwtSplineCurveFitter::FitMode QwtSplineCurveFitter::fitMode() const +{ + return d_data->fitMode; +} + +/*! + Assign a spline + + \param spline Spline + \sa spline() +*/ +void QwtSplineCurveFitter::setSpline( const QwtSpline &spline ) +{ + d_data->spline = spline; + d_data->spline.reset(); +} + +/*! + \return Spline + \sa setSpline() +*/ +const QwtSpline &QwtSplineCurveFitter::spline() const +{ + return d_data->spline; +} + +/*! + \return Spline + \sa setSpline() +*/ +QwtSpline &QwtSplineCurveFitter::spline() +{ + return d_data->spline; +} + +/*! + Assign a spline size ( has to be at least 10 points ) + + \param splineSize Spline size + \sa splineSize() +*/ +void QwtSplineCurveFitter::setSplineSize( int splineSize ) +{ + d_data->splineSize = qMax( splineSize, 10 ); +} + +/*! + \return Spline size + \sa setSplineSize() +*/ +int QwtSplineCurveFitter::splineSize() const +{ + return d_data->splineSize; +} + +/*! + Find a curve which has the best fit to a series of data points + + \param points Series of data points + \return Curve points +*/ +QPolygonF QwtSplineCurveFitter::fitCurve( const QPolygonF &points ) const +{ + const int size = points.size(); + if ( size <= 2 ) + return points; + + FitMode fitMode = d_data->fitMode; + if ( fitMode == Auto ) + { + fitMode = Spline; + + const QPointF *p = points.data(); + for ( int i = 1; i < size; i++ ) + { + if ( p[i].x() <= p[i-1].x() ) + { + fitMode = ParametricSpline; + break; + } + }; + } + + if ( fitMode == ParametricSpline ) + return fitParametric( points ); + else + return fitSpline( points ); +} + +QPolygonF QwtSplineCurveFitter::fitSpline( const QPolygonF &points ) const +{ + d_data->spline.setPoints( points ); + if ( !d_data->spline.isValid() ) + return points; + + QPolygonF fittedPoints( d_data->splineSize ); + + const double x1 = points[0].x(); + const double x2 = points[int( points.size() - 1 )].x(); + const double dx = x2 - x1; + const double delta = dx / ( d_data->splineSize - 1 ); + + for ( int i = 0; i < d_data->splineSize; i++ ) + { + QPointF &p = fittedPoints[i]; + + const double v = x1 + i * delta; + const double sv = d_data->spline.value( v ); + + p.setX( v ); + p.setY( sv ); + } + d_data->spline.reset(); + + return fittedPoints; +} + +QPolygonF QwtSplineCurveFitter::fitParametric( const QPolygonF &points ) const +{ + int i; + const int size = points.size(); + + QPolygonF fittedPoints( d_data->splineSize ); + QPolygonF splinePointsX( size ); + QPolygonF splinePointsY( size ); + + const QPointF *p = points.data(); + QPointF *spX = splinePointsX.data(); + QPointF *spY = splinePointsY.data(); + + double param = 0.0; + for ( i = 0; i < size; i++ ) + { + const double x = p[i].x(); + const double y = p[i].y(); + if ( i > 0 ) + { + const double delta = qSqrt( qwtSqr( x - spX[i-1].y() ) + + qwtSqr( y - spY[i-1].y() ) ); + param += qMax( delta, 1.0 ); + } + spX[i].setX( param ); + spX[i].setY( x ); + spY[i].setX( param ); + spY[i].setY( y ); + } + + d_data->spline.setPoints( splinePointsX ); + if ( !d_data->spline.isValid() ) + return points; + + const double deltaX = + splinePointsX[size - 1].x() / ( d_data->splineSize - 1 ); + for ( i = 0; i < d_data->splineSize; i++ ) + { + const double dtmp = i * deltaX; + fittedPoints[i].setX( d_data->spline.value( dtmp ) ); + } + + d_data->spline.setPoints( splinePointsY ); + if ( !d_data->spline.isValid() ) + return points; + + const double deltaY = + splinePointsY[size - 1].x() / ( d_data->splineSize - 1 ); + for ( i = 0; i < d_data->splineSize; i++ ) + { + const double dtmp = i * deltaY; + fittedPoints[i].setY( d_data->spline.value( dtmp ) ); + } + + return fittedPoints; +} + +class QwtWeedingCurveFitter::PrivateData +{ +public: + PrivateData(): + tolerance( 1.0 ), + chunkSize( 0 ) + { + } + + double tolerance; + uint chunkSize; +}; + +class QwtWeedingCurveFitter::Line +{ +public: + Line( int i1 = 0, int i2 = 0 ): + from( i1 ), + to( i2 ) + { + } + + int from; + int to; +}; + +/*! + Constructor + + \param tolerance Tolerance + \sa setTolerance(), tolerance() +*/ +QwtWeedingCurveFitter::QwtWeedingCurveFitter( double tolerance ) +{ + d_data = new PrivateData; + setTolerance( tolerance ); +} + +//! Destructor +QwtWeedingCurveFitter::~QwtWeedingCurveFitter() +{ + delete d_data; +} + +/*! + Assign the tolerance + + The tolerance is the maximum distance, that is acceptable + between the original curve and the smoothed curve. + + Increasing the tolerance will reduce the number of the + resulting points. + + \param tolerance Tolerance + + \sa tolerance() +*/ +void QwtWeedingCurveFitter::setTolerance( double tolerance ) +{ + d_data->tolerance = qMax( tolerance, 0.0 ); +} + +/*! + \return Tolerance + \sa setTolerance() +*/ +double QwtWeedingCurveFitter::tolerance() const +{ + return d_data->tolerance; +} + +/*! + Limit the number of points passed to a run of the algorithm + + The runtime of the Douglas Peucker algorithm increases non linear + with the number of points. For a chunk size > 0 the polygon + is split into pieces passed to the algorithm one by one. + + \param numPoints Maximum for the number of points passed to the algorithm + + \sa chunkSize() +*/ +void QwtWeedingCurveFitter::setChunkSize( uint numPoints ) +{ + if ( numPoints > 0 ) + numPoints = qMax( numPoints, 3U ); + + d_data->chunkSize = numPoints; +} + +/*! + + \return Maximum for the number of points passed to a run + of the algorithm - or 0, when unlimited + \sa setChunkSize() +*/ +uint QwtWeedingCurveFitter::chunkSize() const +{ + return d_data->chunkSize; +} + +/*! + \param points Series of data points + \return Curve points +*/ +QPolygonF QwtWeedingCurveFitter::fitCurve( const QPolygonF &points ) const +{ + QPolygonF fittedPoints; + + if ( d_data->chunkSize == 0 ) + { + fittedPoints = simplify( points ); + } + else + { + for ( int i = 0; i < points.size(); i += d_data->chunkSize ) + { + const QPolygonF p = points.mid( i, d_data->chunkSize ); + fittedPoints += simplify( p ); + } + } + + return fittedPoints; +} + +QPolygonF QwtWeedingCurveFitter::simplify( const QPolygonF &points ) const +{ + const double toleranceSqr = d_data->tolerance * d_data->tolerance; + + QStack stack; + stack.reserve( 500 ); + + const QPointF *p = points.data(); + const int nPoints = points.size(); + + QVector usePoint( nPoints, false ); + + stack.push( Line( 0, nPoints - 1 ) ); + + while ( !stack.isEmpty() ) + { + const Line r = stack.pop(); + + // initialize line segment + const double vecX = p[r.to].x() - p[r.from].x(); + const double vecY = p[r.to].y() - p[r.from].y(); + + const double vecLength = qSqrt( vecX * vecX + vecY * vecY ); + + const double unitVecX = ( vecLength != 0.0 ) ? vecX / vecLength : 0.0; + const double unitVecY = ( vecLength != 0.0 ) ? vecY / vecLength : 0.0; + + double maxDistSqr = 0.0; + int nVertexIndexMaxDistance = r.from + 1; + for ( int i = r.from + 1; i < r.to; i++ ) + { + //compare to anchor + const double fromVecX = p[i].x() - p[r.from].x(); + const double fromVecY = p[i].y() - p[r.from].y(); + + double distToSegmentSqr; + if ( fromVecX * unitVecX + fromVecY * unitVecY < 0.0 ) + { + distToSegmentSqr = fromVecX * fromVecX + fromVecY * fromVecY; + } + else + { + const double toVecX = p[i].x() - p[r.to].x(); + const double toVecY = p[i].y() - p[r.to].y(); + const double toVecLength = toVecX * toVecX + toVecY * toVecY; + + const double s = toVecX * ( -unitVecX ) + toVecY * ( -unitVecY ); + if ( s < 0.0 ) + { + distToSegmentSqr = toVecLength; + } + else + { + distToSegmentSqr = qFabs( toVecLength - s * s ); + } + } + + if ( maxDistSqr < distToSegmentSqr ) + { + maxDistSqr = distToSegmentSqr; + nVertexIndexMaxDistance = i; + } + } + if ( maxDistSqr <= toleranceSqr ) + { + usePoint[r.from] = true; + usePoint[r.to] = true; + } + else + { + stack.push( Line( r.from, nVertexIndexMaxDistance ) ); + stack.push( Line( nVertexIndexMaxDistance, r.to ) ); + } + } + + QPolygonF stripped; + for ( int i = 0; i < nPoints; i++ ) + { + if ( usePoint[i] ) + stripped += p[i]; + } + + return stripped; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_curve_fitter.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_curve_fitter.h new file mode 100644 index 0000000..480ea3e --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_curve_fitter.h @@ -0,0 +1,139 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_CURVE_FITTER_H +#define QWT_CURVE_FITTER_H + +#include "qwt_global.h" +#include +#include + +class QwtSpline; + +/*! + \brief Abstract base class for a curve fitter +*/ +class QWT_EXPORT QwtCurveFitter +{ +public: + virtual ~QwtCurveFitter(); + + /*! + Find a curve which has the best fit to a series of data points + + \param polygon Series of data points + \return Curve points + */ + virtual QPolygonF fitCurve( const QPolygonF &polygon ) const = 0; + +protected: + QwtCurveFitter(); + +private: + QwtCurveFitter( const QwtCurveFitter & ); + QwtCurveFitter &operator=( const QwtCurveFitter & ); +}; + +/*! + \brief A curve fitter using cubic splines +*/ +class QWT_EXPORT QwtSplineCurveFitter: public QwtCurveFitter +{ +public: + /*! + Spline type + The default setting is Auto + \sa setFitMode(), FitMode() + */ + enum FitMode + { + /*! + Use the default spline algorithm for polygons with + increasing x values ( p[i-1] < p[i] ), otherwise use + a parametric spline algorithm. + */ + Auto, + + //! Use a default spline algorithm + Spline, + + //! Use a parametric spline algorithm + ParametricSpline + }; + + QwtSplineCurveFitter(); + virtual ~QwtSplineCurveFitter(); + + void setFitMode( FitMode ); + FitMode fitMode() const; + + void setSpline( const QwtSpline& ); + const QwtSpline &spline() const; + QwtSpline &spline(); + + void setSplineSize( int size ); + int splineSize() const; + + virtual QPolygonF fitCurve( const QPolygonF & ) const; + +private: + QPolygonF fitSpline( const QPolygonF & ) const; + QPolygonF fitParametric( const QPolygonF & ) const; + + class PrivateData; + PrivateData *d_data; +}; + +/*! + \brief A curve fitter implementing Douglas and Peucker algorithm + + The purpose of the Douglas and Peucker algorithm is that given a 'curve' + composed of line segments to find a curve not too dissimilar but that + has fewer points. The algorithm defines 'too dissimilar' based on the + maximum distance (tolerance) between the original curve and the + smoothed curve. + + The runtime of the algorithm increases non linear ( worst case O( n*n ) ) + and might be very slow for huge polygons. To avoid performance issues + it might be useful to split the polygon ( setChunkSize() ) and to run the algorithm + for these smaller parts. The disadvantage of having no interpolation + at the borders is for most use cases irrelevant. + + The smoothed curve consists of a subset of the points that defined the + original curve. + + In opposite to QwtSplineCurveFitter the Douglas and Peucker algorithm reduces + the number of points. By adjusting the tolerance parameter according to the + axis scales QwtSplineCurveFitter can be used to implement different + level of details to speed up painting of curves of many points. +*/ +class QWT_EXPORT QwtWeedingCurveFitter: public QwtCurveFitter +{ +public: + QwtWeedingCurveFitter( double tolerance = 1.0 ); + virtual ~QwtWeedingCurveFitter(); + + void setTolerance( double ); + double tolerance() const; + + void setChunkSize( uint ); + uint chunkSize() const; + + virtual QPolygonF fitCurve( const QPolygonF & ) const; + +private: + virtual QPolygonF simplify( const QPolygonF & ) const; + + class Line; + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date.cpp new file mode 100644 index 0000000..b78b423 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date.cpp @@ -0,0 +1,760 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_date.h" +#include +#include +#include +#include +#include + +#if QT_VERSION >= 0x050000 + +typedef qint64 QwtJulianDay; +static const QwtJulianDay minJulianDayD = Q_INT64_C( -784350574879 ); +static const QwtJulianDay maxJulianDayD = Q_INT64_C( 784354017364 ); + +#else + +// QDate stores the Julian day as unsigned int, but +// but it is QDate::fromJulianDay( int ). That's why +// we have the range [ 1, INT_MAX ] +typedef int QwtJulianDay; +static const QwtJulianDay minJulianDayD = 1; +static const QwtJulianDay maxJulianDayD = std::numeric_limits::max(); + +#endif + +static QString qwtExpandedFormat( const QString & format, + const QDateTime &dateTime, QwtDate::Week0Type week0Type ) +{ + const int week = QwtDate::weekNumber( dateTime.date(), week0Type ); + + QString weekNo; + weekNo.setNum( week ); + + QString weekNoWW; + if ( weekNo.length() == 1 ) + weekNoWW += "0"; + + weekNoWW += weekNo; + + QString fmt = format; + fmt.replace( "ww", weekNoWW ); + fmt.replace( "w", weekNo ); + + if ( week == 1 && dateTime.date().month() != 1 ) + { + // in case of week 1, we might need to increment the year + + static QString s_yyyy = "yyyy"; + static QString s_yy = "yy"; + + // week 1 might start in the previous year + + bool doReplaceYear = fmt.contains( s_yy ); + + if ( doReplaceYear ) + { + if ( fmt.contains( 'M' ) ) + { + // in case of also having 'M' we have a conflict about + // which year to show + + doReplaceYear = false; + } + else + { + // in case of also having 'd' or 'dd' we have a conflict about + // which year to show + + int numD = 0; + + for ( int i = 0; i < fmt.size(); i++ ) + { + if ( fmt[i] == 'd' ) + { + numD++; + } + else + { + if ( numD > 0 && numD <= 2 ) + break; + + numD = 0; + } + } + + if ( numD > 0 && numD <= 2 ) + doReplaceYear = false; + } + } + + if ( doReplaceYear ) + { + const QDate dt( dateTime.date().year() + 1, 1, 1 ); + + if ( fmt.contains( s_yyyy ) ) + { + fmt.replace( s_yyyy, dt.toString( s_yyyy ) ); + } + else + { + fmt.replace( s_yy, dt.toString( s_yyyy ) ); + } + } + } + + return fmt; +} + +static inline Qt::DayOfWeek qwtFirstDayOfWeek() +{ +#if QT_VERSION >= 0x040800 + return QLocale().firstDayOfWeek(); +#else + + switch( QLocale().country() ) + { + case QLocale::Maldives: + return Qt::Friday; + + case QLocale::Afghanistan: + case QLocale::Algeria: + case QLocale::Bahrain: + case QLocale::Djibouti: + case QLocale::Egypt: + case QLocale::Eritrea: + case QLocale::Ethiopia: + case QLocale::Iran: + case QLocale::Iraq: + case QLocale::Jordan: + case QLocale::Kenya: + case QLocale::Kuwait: + case QLocale::LibyanArabJamahiriya: + case QLocale::Morocco: + case QLocale::Oman: + case QLocale::Qatar: + case QLocale::SaudiArabia: + case QLocale::Somalia: + case QLocale::Sudan: + case QLocale::Tunisia: + case QLocale::Yemen: + return Qt::Saturday; + + case QLocale::AmericanSamoa: + case QLocale::Argentina: + case QLocale::Azerbaijan: + case QLocale::Botswana: + case QLocale::Canada: + case QLocale::China: + case QLocale::FaroeIslands: + case QLocale::Georgia: + case QLocale::Greenland: + case QLocale::Guam: + case QLocale::HongKong: + case QLocale::Iceland: + case QLocale::India: + case QLocale::Ireland: + case QLocale::Israel: + case QLocale::Jamaica: + case QLocale::Japan: + case QLocale::Kyrgyzstan: + case QLocale::Lao: + case QLocale::Malta: + case QLocale::MarshallIslands: + case QLocale::Macau: + case QLocale::Mongolia: + case QLocale::NewZealand: + case QLocale::NorthernMarianaIslands: + case QLocale::Pakistan: + case QLocale::Philippines: + case QLocale::RepublicOfKorea: + case QLocale::Singapore: + case QLocale::SyrianArabRepublic: + case QLocale::Taiwan: + case QLocale::Thailand: + case QLocale::TrinidadAndTobago: + case QLocale::UnitedStates: + case QLocale::UnitedStatesMinorOutlyingIslands: + case QLocale::USVirginIslands: + case QLocale::Uzbekistan: + case QLocale::Zimbabwe: + return Qt::Sunday; + + default: + return Qt::Monday; + } +#endif +} + +static inline void qwtFloorTime( + QwtDate::IntervalType intervalType, QDateTime &dt ) +{ + // when dt is inside the special hour where DST is ending + // an hour is no unique. Therefore we have to + // use UTC time. + + const Qt::TimeSpec timeSpec = dt.timeSpec(); + + if ( timeSpec == Qt::LocalTime ) + dt = dt.toTimeSpec( Qt::UTC ); + + const QTime t = dt.time(); + switch( intervalType ) + { + case QwtDate::Second: + { + dt.setTime( QTime( t.hour(), t.minute(), t.second() ) ); + break; + } + case QwtDate::Minute: + { + dt.setTime( QTime( t.hour(), t.minute(), 0 ) ); + break; + } + case QwtDate::Hour: + { + dt.setTime( QTime( t.hour(), 0, 0 ) ); + break; + } + default: + break; + } + + if ( timeSpec == Qt::LocalTime ) + dt = dt.toTimeSpec( Qt::LocalTime ); +} + +static inline QDateTime qwtToTimeSpec( + const QDateTime &dt, Qt::TimeSpec spec ) +{ + if ( dt.timeSpec() == spec ) + return dt; + + const qint64 jd = dt.date().toJulianDay(); + if ( jd < 0 || jd >= INT_MAX ) + { + // the conversion between local time and UTC + // is internally limited. To avoid + // overflows we simply ignore the difference + // for those dates + + QDateTime dt2 = dt; + dt2.setTimeSpec( spec ); + return dt2; + } + + return dt.toTimeSpec( spec ); +} + +static inline double qwtToJulianDay( int year, int month, int day ) +{ + // code from QDate but using doubles to avoid overflows + // for large values + + const int m1 = ( month - 14 ) / 12; + const int m2 = ( 367 * ( month - 2 - 12 * m1 ) ) / 12; + const double y1 = ::floor( ( 4900.0 + year + m1 ) / 100 ); + + return ::floor( ( 1461.0 * ( year + 4800 + m1 ) ) / 4 ) + m2 + - ::floor( ( 3 * y1 ) / 4 ) + day - 32075; +} + +static inline qint64 qwtFloorDiv64( qint64 a, int b ) +{ + if ( a < 0 ) + a -= b - 1; + + return a / b; +} + +static inline qint64 qwtFloorDiv( int a, int b ) +{ + if ( a < 0 ) + a -= b - 1; + + return a / b; +} + +static inline QDate qwtToDate( int year, int month = 1, int day = 1 ) +{ +#if QT_VERSION >= 0x050000 + return QDate( year, month, day ); +#else + if ( year > 100000 ) + { + // code from QDate but using doubles to avoid overflows + // for large values + + const int m1 = ( month - 14 ) / 12; + const int m2 = ( 367 * ( month - 2 - 12 * m1 ) ) / 12; + const double y1 = ::floor( ( 4900.0 + year + m1 ) / 100 ); + + const double jd = ::floor( ( 1461.0 * ( year + 4800 + m1 ) ) / 4 ) + m2 + - ::floor( ( 3 * y1 ) / 4 ) + day - 32075; + + if ( jd > maxJulianDayD ) + { + qWarning() << "qwtToDate: overflow"; + return QDate(); + } + + return QDate::fromJulianDay( static_cast( jd ) ); + } + else + { + return QDate( year, month, day ); + } +#endif +} + +/*! + Translate from double to QDateTime + + \param value Number of milliseconds since the epoch, + 1970-01-01T00:00:00 UTC + \param timeSpec Time specification + \return Datetime value + + \sa toDouble(), QDateTime::setMSecsSinceEpoch() + \note The return datetime for Qt::OffsetFromUTC will be Qt::UTC + */ +QDateTime QwtDate::toDateTime( double value, Qt::TimeSpec timeSpec ) +{ + const int msecsPerDay = 86400000; + + const double days = static_cast( ::floor( value / msecsPerDay ) ); + + const double jd = QwtDate::JulianDayForEpoch + days; + if ( ( jd > maxJulianDayD ) || ( jd < minJulianDayD ) ) + { + qWarning() << "QwtDate::toDateTime: overflow"; + return QDateTime(); + } + + const QDate d = QDate::fromJulianDay( static_cast( jd ) ); + + const int msecs = static_cast( value - days * msecsPerDay ); + + static const QTime timeNull( 0, 0, 0, 0 ); + + QDateTime dt( d, timeNull.addMSecs( msecs ), Qt::UTC ); + + if ( timeSpec == Qt::LocalTime ) + dt = qwtToTimeSpec( dt, timeSpec ); + + return dt; +} + +/*! + Translate from QDateTime to double + + \param dateTime Datetime value + \return Number of milliseconds since 1970-01-01T00:00:00 UTC has passed. + + \sa toDateTime(), QDateTime::toMSecsSinceEpoch() + \warning For values very far below or above 1970-01-01 UTC rounding errors + will happen due to the limited significance of a double. + */ +double QwtDate::toDouble( const QDateTime &dateTime ) +{ + const int msecsPerDay = 86400000; + + const QDateTime dt = qwtToTimeSpec( dateTime, Qt::UTC ); + + const double days = dt.date().toJulianDay() - QwtDate::JulianDayForEpoch; + + const QTime time = dt.time(); + const double secs = 3600.0 * time.hour() + + 60.0 * time.minute() + time.second(); + + return days * msecsPerDay + time.msec() + 1000.0 * secs; +} + +/*! + Ceil a datetime according the interval type + + \param dateTime Datetime value + \param intervalType Interval type, how to ceil. + F.e. when intervalType = QwtDate::Months, the result + will be ceiled to the next beginning of a month + \return Ceiled datetime + \sa floor() + */ +QDateTime QwtDate::ceil( const QDateTime &dateTime, IntervalType intervalType ) +{ + if ( dateTime.date() >= QwtDate::maxDate() ) + return dateTime; + + QDateTime dt = dateTime; + + switch ( intervalType ) + { + case QwtDate::Millisecond: + { + break; + } + case QwtDate::Second: + { + qwtFloorTime( QwtDate::Second, dt ); + if ( dt < dateTime ) + dt = dt.addSecs( 1 ); + + break; + } + case QwtDate::Minute: + { + qwtFloorTime( QwtDate::Minute, dt ); + if ( dt < dateTime ) + dt = dt.addSecs( 60 ); + + break; + } + case QwtDate::Hour: + { + qwtFloorTime( QwtDate::Hour, dt ); + if ( dt < dateTime ) + dt = dt.addSecs( 3600 ); + + break; + } + case QwtDate::Day: + { + dt.setTime( QTime( 0, 0 ) ); + if ( dt < dateTime ) + dt = dt.addDays( 1 ); + + break; + } + case QwtDate::Week: + { + dt.setTime( QTime( 0, 0 ) ); + if ( dt < dateTime ) + dt = dt.addDays( 1 ); + + int days = qwtFirstDayOfWeek() - dt.date().dayOfWeek(); + if ( days < 0 ) + days += 7; + + dt = dt.addDays( days ); + + break; + } + case QwtDate::Month: + { + dt.setTime( QTime( 0, 0 ) ); + dt.setDate( qwtToDate( dateTime.date().year(), + dateTime.date().month() ) ); + + if ( dt < dateTime ) + dt = dt.addMonths( 1 ); + + break; + } + case QwtDate::Year: + { + dt.setTime( QTime( 0, 0 ) ); + + const QDate d = dateTime.date(); + + int year = d.year(); + if ( d.month() > 1 || d.day() > 1 || !dateTime.time().isNull() ) + year++; + + if ( year == 0 ) + year++; // there is no year 0 + + dt.setDate( qwtToDate( year ) ); + break; + } + } + + return dt; +} + +/*! + Floor a datetime according the interval type + + \param dateTime Datetime value + \param intervalType Interval type, how to ceil. + F.e. when intervalType = QwtDate::Months, + the result will be ceiled to the next + beginning of a month + \return Floored datetime + \sa floor() + */ +QDateTime QwtDate::floor( const QDateTime &dateTime, + IntervalType intervalType ) +{ + if ( dateTime.date() <= QwtDate::minDate() ) + return dateTime; + + QDateTime dt = dateTime; + + switch ( intervalType ) + { + case QwtDate::Millisecond: + { + break; + } + case QwtDate::Second: + case QwtDate::Minute: + case QwtDate::Hour: + { + qwtFloorTime( intervalType, dt ); + break; + } + case QwtDate::Day: + { + dt.setTime( QTime( 0, 0 ) ); + break; + } + case QwtDate::Week: + { + dt.setTime( QTime( 0, 0 ) ); + + int days = dt.date().dayOfWeek() - qwtFirstDayOfWeek(); + if ( days < 0 ) + days += 7; + + dt = dt.addDays( -days ); + + break; + } + case QwtDate::Month: + { + dt.setTime( QTime( 0, 0 ) ); + + const QDate date = qwtToDate( dt.date().year(), + dt.date().month() ); + dt.setDate( date ); + + break; + } + case QwtDate::Year: + { + dt.setTime( QTime( 0, 0 ) ); + + const QDate date = qwtToDate( dt.date().year() ); + dt.setDate( date ); + + break; + } + } + + return dt; +} + +/*! + Minimum for the supported date range + + The range of valid dates depends on how QDate stores the + Julian day internally. + + - For Qt4 it is "Tue Jan 2 -4713" + - For Qt5 it is "Thu Jan 1 -2147483648" + + \return minimum of the date range + \sa maxDate() + */ +QDate QwtDate::minDate() +{ + static QDate date; + if ( !date.isValid() ) + date = QDate::fromJulianDay( minJulianDayD ); + + return date; +} + +/*! + Maximum for the supported date range + + The range of valid dates depends on how QDate stores the + Julian day internally. + + - For Qt4 it is "Tue Jun 3 5874898" + - For Qt5 it is "Tue Dec 31 2147483647" + + \return maximum of the date range + \sa minDate() + \note The maximum differs between Qt4 and Qt5 + */ +QDate QwtDate::maxDate() +{ + static QDate date; + if ( !date.isValid() ) + date = QDate::fromJulianDay( maxJulianDayD ); + + return date; +} + +/*! + \brief Date of the first day of the first week for a year + + The first day of a week depends on the current locale + ( QLocale::firstDayOfWeek() ). + + \param year Year + \param type Option how to identify the first week + \return First day of week 0 + + \sa QLocale::firstDayOfWeek(), weekNumber() + */ +QDate QwtDate::dateOfWeek0( int year, Week0Type type ) +{ + const Qt::DayOfWeek firstDayOfWeek = qwtFirstDayOfWeek(); + + QDate dt0( year, 1, 1 ); + + // floor to the first day of the week + int days = dt0.dayOfWeek() - firstDayOfWeek; + if ( days < 0 ) + days += 7; + + dt0 = dt0.addDays( -days ); + + if ( type == QwtDate::FirstThursday ) + { + // according to ISO 8601 the first week is defined + // by the first thursday. + + int d = Qt::Thursday - firstDayOfWeek; + if ( d < 0 ) + d += 7; + + if ( dt0.addDays( d ).year() < year ) + dt0 = dt0.addDays( 7 ); + } + + return dt0; +} + +/*! + Find the week number of a date + + - QwtDate::FirstThursday\n + Corresponding to ISO 8601 ( see QDate::weekNumber() ). + + - QwtDate::FirstDay\n + Number of weeks that have begun since dateOfWeek0(). + + \param date Date + \param type Option how to identify the first week + + \return Week number, starting with 1 + */ +int QwtDate::weekNumber( const QDate &date, Week0Type type ) +{ + int weekNo; + + if ( type == QwtDate::FirstDay ) + { + QDate day0; + + if ( date.month() == 12 && date.day() >= 24 ) + { + // week 1 usually starts in the previous years. + // and we have to check if we are already there + + day0 = dateOfWeek0( date.year() + 1, type ); + if ( day0.daysTo( date ) < 0 ) + day0 = dateOfWeek0( date.year(), type ); + } + else + { + day0 = dateOfWeek0( date.year(), type ); + } + + weekNo = day0.daysTo( date ) / 7 + 1; + } + else + { + weekNo = date.weekNumber(); + } + + return weekNo; +} + +/*! + Offset in seconds from Coordinated Universal Time + + The offset depends on the time specification of dateTime: + + - Qt::UTC + 0, dateTime has no offset + - Qt::OffsetFromUTC + returns dateTime.utcOffset() + - Qt::LocalTime: + number of seconds from the UTC + + For Qt::LocalTime the offset depends on the timezone and + daylight savings. + + \param dateTime Datetime value + \return Offset in seconds + */ +int QwtDate::utcOffset( const QDateTime &dateTime ) +{ + int seconds = 0; + + switch( dateTime.timeSpec() ) + { + case Qt::UTC: + { + break; + } + case Qt::OffsetFromUTC: + { + seconds = dateTime.utcOffset(); + break; + } + default: + { + const QDateTime dt1( dateTime.date(), dateTime.time(), Qt::UTC ); + seconds = dateTime.secsTo( dt1 ); + } + } + + return seconds; +} + +/*! + Translate a datetime into a string + + Beside the format expressions documented in QDateTime::toString() + the following expressions are supported: + + - w\n + week number: ( 1 - 53 ) + - ww\n + week number with a leading zero ( 01 - 53 ) + + As week 1 usually starts in the previous year a special rule + is applied for formats, where the year is expected to match the + week number - even if the date belongs to the previous year. + + \param dateTime Datetime value + \param format Format string + \param week0Type Specification of week 0 + + \return Datetime string + \sa QDateTime::toString(), weekNumber(), QwtDateScaleDraw + */ +QString QwtDate::toString( const QDateTime &dateTime, + const QString & format, Week0Type week0Type ) +{ + QString fmt = format; + if ( fmt.contains( 'w' ) ) + { + fmt = qwtExpandedFormat( fmt, dateTime, week0Type ); + } + + return dateTime.toString( fmt ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date.h new file mode 100644 index 0000000..ad6ac09 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date.h @@ -0,0 +1,128 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef _QWT_DATE_H_ +#define _QWT_DATE_H_ + +#include "qwt_global.h" +#include + +/*! + \brief A collection of methods around date/time values + + Qt offers convenient classes for dealing with date/time values, + but Qwt uses coordinate systems that are based on doubles. + QwtDate offers methods to translate from QDateTime to double and v.v. + + A double is interpreted as the number of milliseconds since + 1970-01-01T00:00:00 Universal Coordinated Time - also known + as "The Epoch". + + While the range of the Julian day in Qt4 is limited to [0, MAX_INT], + Qt5 stores it as qint64 offering a huge range of valid dates. + As the significance of a double is below this ( assuming a + fraction of 52 bits ) the translation is not + bijective with rounding errors for dates very far from Epoch. + For a resolution of 1 ms those start to happen for dates above the + year 144683. + + An axis for a date/time interval is expected to be aligned + and divided in time/date units like seconds, minutes, ... + QwtDate offers several algorithms that are needed to + calculate these axes. + + \sa QwtDateScaleEngine, QwtDateScaleDraw, QDate, QTime +*/ +class QWT_EXPORT QwtDate +{ +public: + /*! + How to identify the first week of year differs between + countries. + */ + enum Week0Type + { + /*! + According to ISO 8601 the first week of a year is defined + as "the week with the year's first Thursday in it". + + FirstThursday corresponds to the numbering that is + implemented in QDate::weekNumber(). + */ + FirstThursday, + + /*! + "The week with January 1.1 in it." + + In the U.S. this definition is more common than + FirstThursday. + */ + FirstDay + }; + + /*! + Classification of an time interval + + Time intervals needs to be classified to decide how to + align and divide it. + */ + enum IntervalType + { + //! The interval is related to milliseconds + Millisecond, + + //! The interval is related to seconds + Second, + + //! The interval is related to minutes + Minute, + + //! The interval is related to hours + Hour, + + //! The interval is related to days + Day, + + //! The interval is related to weeks + Week, + + //! The interval is related to months + Month, + + //! The interval is related to years + Year + }; + + enum + { + //! The Julian day of "The Epoch" + JulianDayForEpoch = 2440588 + }; + + static QDate minDate(); + static QDate maxDate(); + + static QDateTime toDateTime( double value, + Qt::TimeSpec = Qt::UTC ); + + static double toDouble( const QDateTime & ); + + static QDateTime ceil( const QDateTime &, IntervalType ); + static QDateTime floor( const QDateTime &, IntervalType ); + + static QDate dateOfWeek0( int year, Week0Type ); + static int weekNumber( const QDate &, Week0Type ); + + static int utcOffset( const QDateTime & ); + + static QString toString( const QDateTime &, + const QString & format, Week0Type ); +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date_scale_draw.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date_scale_draw.cpp new file mode 100644 index 0000000..991dd38 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date_scale_draw.cpp @@ -0,0 +1,278 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_date_scale_draw.h" + +class QwtDateScaleDraw::PrivateData +{ +public: + PrivateData( Qt::TimeSpec spec ): + timeSpec( spec ), + utcOffset( 0 ), + week0Type( QwtDate::FirstThursday ) + { + dateFormats[ QwtDate::Millisecond ] = "hh:mm:ss:zzz\nddd dd MMM yyyy"; + dateFormats[ QwtDate::Second ] = "hh:mm:ss\nddd dd MMM yyyy"; + dateFormats[ QwtDate::Minute ] = "hh:mm\nddd dd MMM yyyy"; + dateFormats[ QwtDate::Hour ] = "hh:mm\nddd dd MMM yyyy"; + dateFormats[ QwtDate::Day ] = "ddd dd MMM yyyy"; + dateFormats[ QwtDate::Week ] = "Www yyyy"; + dateFormats[ QwtDate::Month ] = "MMM yyyy"; + dateFormats[ QwtDate::Year ] = "yyyy"; + } + + Qt::TimeSpec timeSpec; + int utcOffset; + QwtDate::Week0Type week0Type; + QString dateFormats[ QwtDate::Year + 1 ]; +}; + +/*! + \brief Constructor + + The default setting is to display tick labels for the + given time specification. The first week of a year is defined like + for QwtDate::FirstThursday. + + \param timeSpec Time specification + + \sa setTimeSpec(), setWeek0Type() + */ +QwtDateScaleDraw::QwtDateScaleDraw( Qt::TimeSpec timeSpec ) +{ + d_data = new PrivateData( timeSpec ); +} + +//! Destructor +QwtDateScaleDraw::~QwtDateScaleDraw() +{ + delete d_data; +} + +/*! + Set the time specification used for the tick labels + + \param timeSpec Time specification + \sa timeSpec(), setUtcOffset(), toDateTime() + */ +void QwtDateScaleDraw::setTimeSpec( Qt::TimeSpec timeSpec ) +{ + d_data->timeSpec = timeSpec; +} + +/*! + \return Time specification used for the tick labels + \sa setTimeSpec(), utcOffset(), toDateTime() + */ +Qt::TimeSpec QwtDateScaleDraw::timeSpec() const +{ + return d_data->timeSpec; +} + +/*! + Set the offset in seconds from Coordinated Universal Time + + \param seconds Offset in seconds + + \note The offset has no effect beside for the time specification + Qt::OffsetFromUTC. + + \sa QDate::utcOffset(), setTimeSpec(), toDateTime() + */ +void QwtDateScaleDraw::setUtcOffset( int seconds ) +{ + d_data->utcOffset = seconds; +} + +/*! + \return Offset in seconds from Coordinated Universal Time + \note The offset has no effect beside for the time specification + Qt::OffsetFromUTC. + + \sa QDate::setUtcOffset(), setTimeSpec(), toDateTime() + */ +int QwtDateScaleDraw::utcOffset() const +{ + return d_data->utcOffset; +} + +/*! + Sets how to identify the first week of a year. + + \param week0Type Mode how to identify the first week of a year + + \sa week0Type(). + \note week0Type has no effect beside for intervals classified as + QwtDate::Week. + */ +void QwtDateScaleDraw::setWeek0Type( QwtDate::Week0Type week0Type ) +{ + d_data->week0Type = week0Type; +} + +/*! + \return Setting how to identify the first week of a year. + \sa setWeek0Type() + */ +QwtDate::Week0Type QwtDateScaleDraw::week0Type() const +{ + return d_data->week0Type; +} + +/*! + Set the default format string for an datetime interval type + + \param intervalType Interval type + \param format Default format string + + \sa dateFormat(), dateFormatOfDate(), QwtDate::toString() + */ +void QwtDateScaleDraw::setDateFormat( + QwtDate::IntervalType intervalType, const QString &format ) +{ + if ( intervalType >= QwtDate::Millisecond && + intervalType <= QwtDate::Year ) + { + d_data->dateFormats[ intervalType ] = format; + } +} + +/*! + \param intervalType Interval type + \return Default format string for an datetime interval type + \sa setDateFormat(), dateFormatOfDate() + */ +QString QwtDateScaleDraw::dateFormat( + QwtDate::IntervalType intervalType ) const +{ + if ( intervalType >= QwtDate::Millisecond && + intervalType <= QwtDate::Year ) + { + return d_data->dateFormats[ intervalType ]; + } + + return QString::null; +} + +/*! + Format string for the representation of a datetime + + dateFormatOfDate() is intended to be overloaded for + situations, where formats are individual for specific + datetime values. + + The default setting ignores dateTime and return + the default format for the interval type. + + \param dateTime Datetime value + \param intervalType Interval type + \return Format string + + \sa setDateFormat(), QwtDate::toString() + */ +QString QwtDateScaleDraw::dateFormatOfDate( const QDateTime &dateTime, + QwtDate::IntervalType intervalType ) const +{ + Q_UNUSED( dateTime ) + + if ( intervalType >= QwtDate::Millisecond && + intervalType <= QwtDate::Year ) + { + return d_data->dateFormats[ intervalType ]; + } + + return d_data->dateFormats[ QwtDate::Second ]; +} + +/*! + \brief Convert a value into its representing label + + The value is converted to a datetime value using toDateTime() + and converted to a plain text using QwtDate::toString(). + + \param value Value + \return Label string. + + \sa dateFormatOfDate() +*/ +QwtText QwtDateScaleDraw::label( double value ) const +{ + const QDateTime dt = toDateTime( value ); + const QString fmt = dateFormatOfDate( + dt, intervalType( scaleDiv() ) ); + + return QwtDate::toString( dt, fmt, d_data->week0Type ); +} + +/*! + Find the less detailed datetime unit, where no rounding + errors happen. + + \param scaleDiv Scale division + \return Interval type + + \sa dateFormatOfDate() + */ +QwtDate::IntervalType QwtDateScaleDraw::intervalType( + const QwtScaleDiv &scaleDiv ) const +{ + int intvType = QwtDate::Year; + + bool alignedToWeeks = true; + + const QList ticks = scaleDiv.ticks( QwtScaleDiv::MajorTick ); + for ( int i = 0; i < ticks.size(); i++ ) + { + const QDateTime dt = toDateTime( ticks[i] ); + for ( int j = QwtDate::Second; j <= intvType; j++ ) + { + const QDateTime dt0 = QwtDate::floor( dt, + static_cast( j ) ); + + if ( dt0 != dt ) + { + if ( j == QwtDate::Week ) + { + alignedToWeeks = false; + } + else + { + intvType = j - 1; + break; + } + } + } + + if ( intvType == QwtDate::Millisecond ) + break; + } + + if ( intvType == QwtDate::Week && !alignedToWeeks ) + intvType = QwtDate::Day; + + return static_cast( intvType ); +} + +/*! + Translate a double value into a QDateTime object. + + \return QDateTime object initialized with timeSpec() and utcOffset(). + \sa timeSpec(), utcOffset(), QwtDate::toDateTime() + */ +QDateTime QwtDateScaleDraw::toDateTime( double value ) const +{ + QDateTime dt = QwtDate::toDateTime( value, d_data->timeSpec ); + if ( d_data->timeSpec == Qt::OffsetFromUTC ) + { + dt = dt.addSecs( d_data->utcOffset ); + dt.setUtcOffset( d_data->utcOffset ); + } + + return dt; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date_scale_draw.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date_scale_draw.h new file mode 100644 index 0000000..f0b0956 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date_scale_draw.h @@ -0,0 +1,86 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef _QWT_DATE_SCALE_DRAW_H_ +#define _QWT_DATE_SCALE_DRAW_H_ 1 + +#include "qwt_global.h" +#include "qwt_scale_draw.h" +#include "qwt_date.h" + +/*! + \brief A class for drawing datetime scales + + QwtDateScaleDraw displays values as datetime labels. + The format of the labels depends on the alignment of + the major tick labels. + + The default format strings are: + + - Millisecond\n + "hh:mm:ss:zzz\nddd dd MMM yyyy" + - Second\n + "hh:mm:ss\nddd dd MMM yyyy" + - Minute\n + "hh:mm\nddd dd MMM yyyy" + - Hour\n + "hh:mm\nddd dd MMM yyyy" + - Day\n + "ddd dd MMM yyyy" + - Week\n + "Www yyyy" + - Month\n + "MMM yyyy" + - Year\n + "yyyy" + + The format strings can be modified using setDateFormat() + or individually for each tick label by overloading dateFormatOfDate(), + + Usually QwtDateScaleDraw is used in combination with + QwtDateScaleEngine, that calculates scales for datetime + intervals. + + \sa QwtDateScaleEngine, QwtPlot::setAxisScaleDraw() +*/ +class QWT_EXPORT QwtDateScaleDraw: public QwtScaleDraw +{ +public: + QwtDateScaleDraw( Qt::TimeSpec = Qt::LocalTime ); + virtual ~QwtDateScaleDraw(); + + void setDateFormat( QwtDate::IntervalType, const QString & ); + QString dateFormat( QwtDate::IntervalType ) const; + + void setTimeSpec( Qt::TimeSpec ); + Qt::TimeSpec timeSpec() const; + + void setUtcOffset( int seconds ); + int utcOffset() const; + + void setWeek0Type( QwtDate::Week0Type ); + QwtDate::Week0Type week0Type() const; + + virtual QwtText label( double ) const; + + QDateTime toDateTime( double ) const; + +protected: + virtual QwtDate::IntervalType + intervalType( const QwtScaleDiv & ) const; + + virtual QString dateFormatOfDate( const QDateTime &, + QwtDate::IntervalType ) const; + +private: + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date_scale_engine.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date_scale_engine.cpp new file mode 100644 index 0000000..d338bbd --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date_scale_engine.cpp @@ -0,0 +1,1309 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_date_scale_engine.h" +#include "qwt_math.h" +#include "qwt_transform.h" +#include +#include + +static inline double qwtMsecsForType( QwtDate::IntervalType type ) +{ + static const double msecs[] = + { + 1.0, + 1000.0, + 60.0 * 1000.0, + 3600.0 * 1000.0, + 24.0 * 3600.0 * 1000.0, + 7.0 * 24.0 * 3600.0 * 1000.0, + 30.0 * 24.0 * 3600.0 * 1000.0, + 365.0 * 24.0 * 3600.0 * 1000.0, + }; + + if ( type < 0 || type >= static_cast( sizeof( msecs ) / sizeof( msecs[0] ) ) ) + return 1.0; + + return msecs[ type ]; +} + +static inline int qwtAlignValue( + double value, double stepSize, bool up ) +{ + double d = value / stepSize; + d = up ? ::ceil( d ) : ::floor( d ); + + return static_cast( d * stepSize ); +} + +static double qwtIntervalWidth( const QDateTime &minDate, + const QDateTime &maxDate, QwtDate::IntervalType intervalType ) +{ + switch( intervalType ) + { + case QwtDate::Millisecond: + { + const double secsTo = minDate.secsTo( maxDate ); + const double msecs = maxDate.time().msec() - + minDate.time().msec(); + + return secsTo * 1000 + msecs; + } + case QwtDate::Second: + { + return minDate.secsTo( maxDate ); + } + case QwtDate::Minute: + { + const double secsTo = minDate.secsTo( maxDate ); + return ::floor( secsTo / 60 ); + } + case QwtDate::Hour: + { + const double secsTo = minDate.secsTo( maxDate ); + return ::floor( secsTo / 3600 ); + } + case QwtDate::Day: + { + return minDate.daysTo( maxDate ); + } + case QwtDate::Week: + { + return ::floor( minDate.daysTo( maxDate ) / 7.0 ); + } + case QwtDate::Month: + { + const double years = + double( maxDate.date().year() ) - minDate.date().year(); + + int months = maxDate.date().month() - minDate.date().month(); + if ( maxDate.date().day() < minDate.date().day() ) + months--; + + return years * 12 + months; + } + case QwtDate::Year: + { + double years = + double( maxDate.date().year() ) - minDate.date().year(); + + if ( maxDate.date().month() < minDate.date().month() ) + years -= 1.0; + + return years; + } + } + + return 0.0; +} + +static double qwtRoundedIntervalWidth( + const QDateTime &minDate, const QDateTime &maxDate, + QwtDate::IntervalType intervalType ) +{ + const QDateTime minD = QwtDate::floor( minDate, intervalType ); + const QDateTime maxD = QwtDate::ceil( maxDate, intervalType ); + + return qwtIntervalWidth( minD, maxD, intervalType ); +} + +static inline int qwtStepCount( int intervalSize, int maxSteps, + const int limits[], size_t numLimits ) +{ + for ( uint i = 0; i < numLimits; i++ ) + { + const int numSteps = intervalSize / limits[ i ]; + + if ( numSteps > 1 && numSteps <= maxSteps && + numSteps * limits[ i ] == intervalSize ) + { + return numSteps; + } + } + + return 0; +} + +static int qwtStepSize( int intervalSize, int maxSteps, uint base ) +{ + if ( maxSteps <= 0 ) + return 0; + + if ( maxSteps > 2 ) + { + for ( int numSteps = maxSteps; numSteps > 1; numSteps-- ) + { + const double stepSize = double( intervalSize ) / numSteps; + + const double p = ::floor( ::log( stepSize ) / ::log( double( base ) ) ); + const double fraction = qPow( base, p ); + + for ( uint n = base; n >= 1; n /= 2 ) + { + if ( qFuzzyCompare( stepSize, n * fraction ) ) + return qRound( stepSize ); + + if ( n == 3 && ( base % 2 ) == 0 ) + { + if ( qFuzzyCompare( stepSize, 2 * fraction ) ) + return qRound( stepSize ); + } + } + } + } + + return 0; +} + +static int qwtDivideInterval( double intervalSize, int numSteps, + const int limits[], size_t numLimits ) +{ + const int v = qCeil( intervalSize / double( numSteps ) ); + + for ( uint i = 0; i < numLimits - 1; i++ ) + { + if ( v <= limits[i] ) + return limits[i]; + } + + return limits[ numLimits - 1 ]; +} + +static double qwtDivideScale( double intervalSize, int numSteps, + QwtDate::IntervalType intervalType ) +{ + if ( intervalType != QwtDate::Day ) + { + if ( ( intervalSize > numSteps ) && + ( intervalSize <= 2 * numSteps ) ) + { + return 2.0; + } + } + + double stepSize; + + switch( intervalType ) + { + case QwtDate::Second: + case QwtDate::Minute: + { + static int limits[] = { 1, 2, 5, 10, 15, 20, 30, 60 }; + + stepSize = qwtDivideInterval( intervalSize, numSteps, + limits, sizeof( limits ) / sizeof( int ) ); + + break; + } + case QwtDate::Hour: + { + static int limits[] = { 1, 2, 3, 4, 6, 12, 24 }; + + stepSize = qwtDivideInterval( intervalSize, numSteps, + limits, sizeof( limits ) / sizeof( int ) ); + + break; + } + case QwtDate::Day: + { + const double v = intervalSize / double( numSteps ); + if ( v <= 5.0 ) + stepSize = qCeil( v ); + else + stepSize = qCeil( v / 7 ) * 7; + + break; + } + case QwtDate::Week: + { + static int limits[] = { 1, 2, 4, 8, 12, 26, 52 }; + + stepSize = qwtDivideInterval( intervalSize, numSteps, + limits, sizeof( limits ) / sizeof( int ) ); + + break; + } + case QwtDate::Month: + { + static int limits[] = { 1, 2, 3, 4, 6, 12 }; + + stepSize = qwtDivideInterval( intervalSize, numSteps, + limits, sizeof( limits ) / sizeof( int ) ); + + break; + } + case QwtDate::Year: + case QwtDate::Millisecond: + default: + { + stepSize = QwtScaleArithmetic::divideInterval( + intervalSize, numSteps, 10 ); + } + } + + return stepSize; +} + +static double qwtDivideMajorStep( double stepSize, int maxMinSteps, + QwtDate::IntervalType intervalType ) +{ + double minStepSize = 0.0; + + switch( intervalType ) + { + case QwtDate::Second: + { + minStepSize = qwtStepSize( stepSize, maxMinSteps, 10 ); + if ( minStepSize == 0.0 ) + minStepSize = 0.5 * stepSize; + + break; + } + case QwtDate::Minute: + { + static int limits[] = { 1, 2, 5, 10, 15, 20, 30, 60 }; + + int numSteps; + + if ( stepSize > maxMinSteps ) + { + numSteps = qwtStepCount( stepSize, maxMinSteps, + limits, sizeof( limits ) / sizeof( int ) ); + + } + else + { + numSteps = qwtStepCount( stepSize * 60, maxMinSteps, + limits, sizeof( limits ) / sizeof( int ) ); + } + + if ( numSteps > 0 ) + minStepSize = double( stepSize ) / numSteps; + + break; + } + case QwtDate::Hour: + { + int numSteps = 0; + + if ( stepSize > maxMinSteps ) + { + static int limits[] = { 1, 2, 3, 4, 6, 12, 24, 48, 72 }; + + numSteps = qwtStepCount( stepSize, maxMinSteps, + limits, sizeof( limits ) / sizeof( int ) ); + } + else + { + static int limits[] = { 1, 2, 5, 10, 15, 20, 30, 60 }; + + numSteps = qwtStepCount( stepSize * 60, maxMinSteps, + limits, sizeof( limits ) / sizeof( int ) ); + } + + if ( numSteps > 0 ) + minStepSize = double( stepSize ) / numSteps; + + break; + } + case QwtDate::Day: + { + int numSteps = 0; + + if ( stepSize > maxMinSteps ) + { + static int limits[] = { 1, 2, 3, 7, 14, 28 }; + + numSteps = qwtStepCount( stepSize, maxMinSteps, + limits, sizeof( limits ) / sizeof( int ) ); + } + else + { + static int limits[] = { 1, 2, 3, 4, 6, 12, 24, 48, 72 }; + + numSteps = qwtStepCount( stepSize * 24, maxMinSteps, + limits, sizeof( limits ) / sizeof( int ) ); + } + + if ( numSteps > 0 ) + minStepSize = double( stepSize ) / numSteps; + + break; + } + case QwtDate::Week: + { + const int daysInStep = stepSize * 7; + + if ( maxMinSteps >= daysInStep ) + { + // we want to have one tick per day + minStepSize = 1.0 / 7.0; + } + else + { + // when the stepSize is more than a week we want to + // have a tick for each week + + const int stepSizeInWeeks = stepSize; + + if ( stepSizeInWeeks <= maxMinSteps ) + { + minStepSize = 1; + } + else + { + minStepSize = QwtScaleArithmetic::divideInterval( + stepSizeInWeeks, maxMinSteps, 10 ); + } + } + break; + } + case QwtDate::Month: + { + // fractions of months doesn't make any sense + + if ( stepSize < maxMinSteps ) + maxMinSteps = static_cast( stepSize ); + + static int limits[] = { 1, 2, 3, 4, 6, 12 }; + + int numSteps = qwtStepCount( stepSize, maxMinSteps, + limits, sizeof( limits ) / sizeof( int ) ); + + if ( numSteps > 0 ) + minStepSize = double( stepSize ) / numSteps; + + break; + } + case QwtDate::Year: + { + if ( stepSize >= maxMinSteps ) + { + minStepSize = QwtScaleArithmetic::divideInterval( + stepSize, maxMinSteps, 10 ); + } + else + { + // something in months + + static int limits[] = { 1, 2, 3, 4, 6, 12 }; + + int numSteps = qwtStepCount( 12 * stepSize, maxMinSteps, + limits, sizeof( limits ) / sizeof( int ) ); + + if ( numSteps > 0 ) + minStepSize = double( stepSize ) / numSteps; + } + + break; + } + default: + break; + } + + if ( intervalType != QwtDate::Month + && minStepSize == 0.0 ) + { + minStepSize = 0.5 * stepSize; + } + + return minStepSize; +} + +static QList qwtDstTicks( const QDateTime &dateTime, + int secondsMajor, int secondsMinor ) +{ + if ( secondsMinor <= 0 ) + QList(); + + QDateTime minDate = dateTime.addSecs( -secondsMajor ); + minDate = QwtDate::floor( minDate, QwtDate::Hour ); + + const double utcOffset = QwtDate::utcOffset( dateTime ); + + // find the hours where daylight saving time happens + + double dstMin = QwtDate::toDouble( minDate ); + while ( minDate < dateTime && + QwtDate::utcOffset( minDate ) != utcOffset ) + { + minDate = minDate.addSecs( 3600 ); + dstMin += 3600 * 1000.0; + } + + QList ticks; + for ( int i = 0; i < 3600; i += secondsMinor ) + ticks += dstMin + i * 1000.0; + + return ticks; +} + +static QwtScaleDiv qwtDivideToSeconds( + const QDateTime &minDate, const QDateTime &maxDate, + double stepSize, int maxMinSteps, + QwtDate::IntervalType intervalType ) +{ + // calculate the min step size + double minStepSize = 0; + + if ( maxMinSteps > 1 ) + { + minStepSize = qwtDivideMajorStep( stepSize, + maxMinSteps, intervalType ); + } + + bool daylightSaving = false; + if ( minDate.timeSpec() == Qt::LocalTime ) + { + daylightSaving = intervalType > QwtDate::Hour; + if ( intervalType == QwtDate::Hour ) + { + daylightSaving = stepSize > 1; + } + } + + const double s = qwtMsecsForType( intervalType ) / 1000; + const int secondsMajor = static_cast( stepSize * s ); + const double secondsMinor = minStepSize * s; + + // UTC excludes daylight savings. So from the difference + // of a date and its UTC counterpart we can find out + // the daylight saving hours + + const double utcOffset = QwtDate::utcOffset( minDate ); + double dstOff = 0; + + QList majorTicks; + QList mediumTicks; + QList minorTicks; + + for ( QDateTime dt = minDate; dt <= maxDate; + dt = dt.addSecs( secondsMajor ) ) + { + if ( !dt.isValid() ) + break; + + double majorValue = QwtDate::toDouble( dt ); + + if ( daylightSaving ) + { + const double offset = utcOffset - QwtDate::utcOffset( dt ); + majorValue += offset * 1000.0; + + if ( offset > dstOff ) + { + // we add some minor ticks for the DST hour, + // otherwise the ticks will be unaligned: 0, 2, 3, 5 ... + minorTicks += qwtDstTicks( + dt, secondsMajor, qRound( secondsMinor ) ); + } + + dstOff = offset; + } + + if ( majorTicks.isEmpty() || majorTicks.last() != majorValue ) + majorTicks += majorValue; + + if ( secondsMinor > 0.0 ) + { + const int numMinorSteps = qFloor( secondsMajor / secondsMinor ); + + for ( int i = 1; i < numMinorSteps; i++ ) + { + const QDateTime mt = dt.addMSecs( + qRound64( i * secondsMinor * 1000 ) ); + + double minorValue = QwtDate::toDouble( mt ); + if ( daylightSaving ) + { + const double offset = utcOffset - QwtDate::utcOffset( mt ); + minorValue += offset * 1000.0; + } + + if ( minorTicks.isEmpty() || minorTicks.last() != minorValue ) + { + const bool isMedium = ( numMinorSteps % 2 == 0 ) + && ( i != 1 ) && ( i == numMinorSteps / 2 ); + + if ( isMedium ) + mediumTicks += minorValue; + else + minorTicks += minorValue; + } + } + } + } + + QwtScaleDiv scaleDiv; + + scaleDiv.setInterval( QwtDate::toDouble( minDate ), + QwtDate::toDouble( maxDate ) ); + + scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks ); + scaleDiv.setTicks( QwtScaleDiv::MediumTick, mediumTicks ); + scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks ); + + return scaleDiv; +} + +static QwtScaleDiv qwtDivideToMonths( + QDateTime &minDate, const QDateTime &maxDate, + double stepSize, int maxMinSteps ) +{ + // months are intervals with non + // equidistant ( in ms ) steps: we have to build the + // scale division manually + + int minStepDays = 0; + int minStepSize = 0.0; + + if ( maxMinSteps > 1 ) + { + if ( stepSize == 1 ) + { + if ( maxMinSteps >= 30 ) + minStepDays = 1; + else if ( maxMinSteps >= 6 ) + minStepDays = 5; + else if ( maxMinSteps >= 3 ) + minStepDays = 10; + else + minStepDays = 15; + } + else + { + minStepSize = qwtDivideMajorStep( + stepSize, maxMinSteps, QwtDate::Month ); + } + } + + QList majorTicks; + QList mediumTicks; + QList minorTicks; + + for ( QDateTime dt = minDate; + dt <= maxDate; dt = dt.addMonths( stepSize ) ) + { + if ( !dt.isValid() ) + break; + + majorTicks += QwtDate::toDouble( dt ); + + if ( minStepDays > 0 ) + { + for ( int days = minStepDays; + days < 30; days += minStepDays ) + { + const double tick = QwtDate::toDouble( dt.addDays( days ) ); + + if ( days == 15 && minStepDays != 15 ) + mediumTicks += tick; + else + minorTicks += tick; + } + } + else if ( minStepSize > 0.0 ) + { + const int numMinorSteps = qRound( stepSize / (double) minStepSize ); + + for ( int i = 1; i < numMinorSteps; i++ ) + { + const double minorValue = + QwtDate::toDouble( dt.addMonths( i * minStepSize ) ); + + if ( ( numMinorSteps % 2 == 0 ) && ( i == numMinorSteps / 2 ) ) + mediumTicks += minorValue; + else + minorTicks += minorValue; + } + } + } + + QwtScaleDiv scaleDiv; + scaleDiv.setInterval( QwtDate::toDouble( minDate ), + QwtDate::toDouble( maxDate ) ); + + scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks ); + scaleDiv.setTicks( QwtScaleDiv::MediumTick, mediumTicks ); + scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks ); + + return scaleDiv; +} + +static QwtScaleDiv qwtDivideToYears( + const QDateTime &minDate, const QDateTime &maxDate, + double stepSize, int maxMinSteps ) +{ + QList majorTicks; + QList mediumTicks; + QList minorTicks; + + double minStepSize = 0.0; + + if ( maxMinSteps > 1 ) + { + minStepSize = qwtDivideMajorStep( + stepSize, maxMinSteps, QwtDate::Year ); + } + + int numMinorSteps = 0; + if ( minStepSize > 0.0 ) + numMinorSteps = qFloor( stepSize / minStepSize ); + + bool dateBC = minDate.date().year() < -1; + + for ( QDateTime dt = minDate; dt <= maxDate; + dt = dt.addYears( stepSize ) ) + { + if ( dateBC && dt.date().year() > 1 ) + { + // there is no year 0 in the Julian calendar + dt = dt.addYears( -1 ); + dateBC = false; + } + + if ( !dt.isValid() ) + break; + + majorTicks += QwtDate::toDouble( dt ); + + for ( int i = 1; i < numMinorSteps; i++ ) + { + QDateTime tickDate; + + const double years = qRound( i * minStepSize ); + if ( years >= INT_MAX / 12 ) + { + tickDate = dt.addYears( years ); + } + else + { + tickDate = dt.addMonths( qRound( years * 12 ) ); + } + + const bool isMedium = ( numMinorSteps > 2 ) && + ( numMinorSteps % 2 == 0 ) && ( i == numMinorSteps / 2 ); + + const double minorValue = QwtDate::toDouble( tickDate ); + if ( isMedium ) + mediumTicks += minorValue; + else + minorTicks += minorValue; + } + + if ( QwtDate::maxDate().addYears( -stepSize ) < dt.date() ) + { + break; + } + } + + QwtScaleDiv scaleDiv; + scaleDiv.setInterval( QwtDate::toDouble( minDate ), + QwtDate::toDouble( maxDate ) ); + + scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks ); + scaleDiv.setTicks( QwtScaleDiv::MediumTick, mediumTicks ); + scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks ); + + return scaleDiv; +} + +class QwtDateScaleEngine::PrivateData +{ +public: + PrivateData( Qt::TimeSpec spec ): + timeSpec( spec ), + utcOffset( 0 ), + week0Type( QwtDate::FirstThursday ), + maxWeeks( 4 ) + { + } + + Qt::TimeSpec timeSpec; + int utcOffset; + QwtDate::Week0Type week0Type; + int maxWeeks; +}; + + +/*! + \brief Constructor + + The engine is initialized to build scales for the + given time specification. It classifies intervals > 4 weeks + as >= Qt::Month. The first week of a year is defined like + for QwtDate::FirstThursday. + + \param timeSpec Time specification + + \sa setTimeSpec(), setMaxWeeks(), setWeek0Type() + */ +QwtDateScaleEngine::QwtDateScaleEngine( Qt::TimeSpec timeSpec ): + QwtLinearScaleEngine( 10 ) +{ + d_data = new PrivateData( timeSpec ); +} + +//! Destructor +QwtDateScaleEngine::~QwtDateScaleEngine() +{ + delete d_data; +} + +/*! + Set the time specification used by the engine + + \param timeSpec Time specification + \sa timeSpec(), setUtcOffset(), toDateTime() + */ +void QwtDateScaleEngine::setTimeSpec( Qt::TimeSpec timeSpec ) +{ + d_data->timeSpec = timeSpec; +} + +/*! + \return Time specification used by the engine + \sa setTimeSpec(), utcOffset(), toDateTime() + */ +Qt::TimeSpec QwtDateScaleEngine::timeSpec() const +{ + return d_data->timeSpec; +} + +/*! + Set the offset in seconds from Coordinated Universal Time + + \param seconds Offset in seconds + + \note The offset has no effect beside for the time specification + Qt::OffsetFromUTC. + + \sa QDate::utcOffset(), setTimeSpec(), toDateTime() + */ +void QwtDateScaleEngine::setUtcOffset( int seconds ) +{ + d_data->utcOffset = seconds; +} + +/*! + \return Offset in seconds from Coordinated Universal Time + \note The offset has no effect beside for the time specification + Qt::OffsetFromUTC. + + \sa QDate::setUtcOffset(), setTimeSpec(), toDateTime() + */ +int QwtDateScaleEngine::utcOffset() const +{ + return d_data->utcOffset; +} + +/*! + Sets how to identify the first week of a year. + + \param week0Type Mode how to identify the first week of a year + + \sa week0Type(), setMaxWeeks() + \note week0Type has no effect beside for intervals classified as + QwtDate::Week. + */ +void QwtDateScaleEngine::setWeek0Type( QwtDate::Week0Type week0Type ) +{ + d_data->week0Type = week0Type; +} + +/*! + \return Setting how to identify the first week of a year. + \sa setWeek0Type(), maxWeeks() + */ +QwtDate::Week0Type QwtDateScaleEngine::week0Type() const +{ + return d_data->week0Type; +} + +/*! + Set a upper limit for the number of weeks, when an interval + can be classified as Qt::Week. + + The default setting is 4 weeks. + + \param weeks Upper limit for the number of weeks + + \note In business charts a year is often devided + into weeks [1-52] + \sa maxWeeks(), setWeek0Type() + */ +void QwtDateScaleEngine::setMaxWeeks( int weeks ) +{ + d_data->maxWeeks = qMax( weeks, 0 ); +} + +/*! + \return Upper limit for the number of weeks, when an interval + can be classified as Qt::Week. + \sa setMaxWeeks(), week0Type() + */ +int QwtDateScaleEngine::maxWeeks() const +{ + return d_data->maxWeeks; +} + +/*! + Classification of a date/time interval division + + \param minDate Minimum ( = earlier ) of the interval + \param maxDate Maximum ( = later ) of the interval + \param maxSteps Maximum for the number of steps + + \return Interval classification + */ +QwtDate::IntervalType QwtDateScaleEngine::intervalType( + const QDateTime &minDate, const QDateTime &maxDate, + int maxSteps ) const +{ + const double jdMin = minDate.date().toJulianDay(); + const double jdMax = maxDate.date().toJulianDay(); + + if ( ( jdMax - jdMin ) / 365 > maxSteps ) + return QwtDate::Year; + + const int months = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Month ); + if ( months > maxSteps * 6 ) + return QwtDate::Year; + + const int days = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Day ); + const int weeks = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Week ); + + if ( weeks > d_data->maxWeeks ) + { + if ( days > 4 * maxSteps * 7 ) + return QwtDate::Month; + } + + if ( days > maxSteps * 7 ) + return QwtDate::Week; + + const int hours = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Hour ); + if ( hours > maxSteps * 24 ) + return QwtDate::Day; + + const int seconds = qwtRoundedIntervalWidth( minDate, maxDate, QwtDate::Second ); + + if ( seconds >= maxSteps * 3600 ) + return QwtDate::Hour; + + if ( seconds >= maxSteps * 60 ) + return QwtDate::Minute; + + if ( seconds >= maxSteps ) + return QwtDate::Second; + + return QwtDate::Millisecond; +} + +/*! + Align and divide an interval + + The algorithm aligns and divides the interval into steps. + + Datetime interval divisions are usually not equidistant and the + calculated stepSize can only be used as an approximation + for the steps calculated by divideScale(). + + \param maxNumSteps Max. number of steps + \param x1 First limit of the interval (In/Out) + \param x2 Second limit of the interval (In/Out) + \param stepSize Step size (Out) + + \sa QwtScaleEngine::setAttribute() +*/ +void QwtDateScaleEngine::autoScale( int maxNumSteps, + double &x1, double &x2, double &stepSize ) const +{ + stepSize = 0.0; + + QwtInterval interval( x1, x2 ); + interval = interval.normalized(); + + interval.setMinValue( interval.minValue() - lowerMargin() ); + interval.setMaxValue( interval.maxValue() + upperMargin() ); + + if ( testAttribute( QwtScaleEngine::Symmetric ) ) + interval = interval.symmetrize( reference() ); + + if ( testAttribute( QwtScaleEngine::IncludeReference ) ) + interval = interval.extend( reference() ); + + if ( interval.width() == 0.0 ) + interval = buildInterval( interval.minValue() ); + + const QDateTime from = toDateTime( interval.minValue() ); + const QDateTime to = toDateTime( interval.maxValue() ); + + if ( from.isValid() && to.isValid() ) + { + if ( maxNumSteps < 1 ) + maxNumSteps = 1; + + const QwtDate::IntervalType intvType = + intervalType( from, to, maxNumSteps ); + + const double width = qwtIntervalWidth( from, to, intvType ); + + const double stepWidth = qwtDivideScale( width, maxNumSteps, intvType ); + if ( stepWidth != 0.0 && !testAttribute( QwtScaleEngine::Floating ) ) + { + const QDateTime d1 = alignDate( from, stepWidth, intvType, false ); + const QDateTime d2 = alignDate( to, stepWidth, intvType, true ); + + interval.setMinValue( QwtDate::toDouble( d1 ) ); + interval.setMaxValue( QwtDate::toDouble( d2 ) ); + } + + stepSize = stepWidth * qwtMsecsForType( intvType ); + } + + x1 = interval.minValue(); + x2 = interval.maxValue(); + + if ( testAttribute( QwtScaleEngine::Inverted ) ) + { + qSwap( x1, x2 ); + stepSize = -stepSize; + } +} + +/*! + \brief Calculate a scale division for a date/time interval + + \param x1 First interval limit + \param x2 Second interval limit + \param maxMajorSteps Maximum for the number of major steps + \param maxMinorSteps Maximum number of minor steps + \param stepSize Step size. If stepSize == 0, the scaleEngine + calculates one. + \return Calculated scale division +*/ +QwtScaleDiv QwtDateScaleEngine::divideScale( double x1, double x2, + int maxMajorSteps, int maxMinorSteps, double stepSize ) const +{ + if ( maxMajorSteps < 1 ) + maxMajorSteps = 1; + + const double min = qMin( x1, x2 ); + const double max = qMax( x1, x2 ); + + const QDateTime from = toDateTime( min ); + const QDateTime to = toDateTime( max ); + + if ( from == to ) + return QwtScaleDiv(); + + stepSize = qAbs( stepSize ); + if ( stepSize > 0.0 ) + { + // as interval types above hours are not equidistant + // ( even days might have 23/25 hours because of daylight saving ) + // the stepSize is used as a hint only + + maxMajorSteps = qCeil( ( max - min ) / stepSize ); + } + + const QwtDate::IntervalType intvType = + intervalType( from, to, maxMajorSteps ); + + QwtScaleDiv scaleDiv; + + if ( intvType == QwtDate::Millisecond ) + { + // for milliseconds and below we can use the decimal system + scaleDiv = QwtLinearScaleEngine::divideScale( min, max, + maxMajorSteps, maxMinorSteps, stepSize ); + } + else + { + const QDateTime minDate = QwtDate::floor( from, intvType ); + const QDateTime maxDate = QwtDate::ceil( to, intvType ); + + scaleDiv = buildScaleDiv( minDate, maxDate, + maxMajorSteps, maxMinorSteps, intvType ); + + // scaleDiv has been calculated from an extended interval + // adjusted to the step size. We have to shrink it again. + + scaleDiv = scaleDiv.bounded( min, max ); + } + + if ( x1 > x2 ) + scaleDiv.invert(); + + return scaleDiv; +} + +QwtScaleDiv QwtDateScaleEngine::buildScaleDiv( + const QDateTime &minDate, const QDateTime &maxDate, + int maxMajorSteps, int maxMinorSteps, + QwtDate::IntervalType intervalType ) const +{ + // calculate the step size + const double stepSize = qwtDivideScale( + qwtIntervalWidth( minDate, maxDate, intervalType ), + maxMajorSteps, intervalType ); + + // align minDate to the step size + QDateTime dt0 = alignDate( minDate, stepSize, intervalType, false ); + if ( !dt0.isValid() ) + { + // the floored date is out of the range of a + // QDateTime - we ceil instead. + dt0 = alignDate( minDate, stepSize, intervalType, true ); + } + + QwtScaleDiv scaleDiv; + + if ( intervalType <= QwtDate::Week ) + { + scaleDiv = qwtDivideToSeconds( dt0, maxDate, + stepSize, maxMinorSteps, intervalType ); + } + else + { + if( intervalType == QwtDate::Month ) + { + scaleDiv = qwtDivideToMonths( dt0, maxDate, + stepSize, maxMinorSteps ); + } + else if ( intervalType == QwtDate::Year ) + { + scaleDiv = qwtDivideToYears( dt0, maxDate, + stepSize, maxMinorSteps ); + } + } + + + return scaleDiv; +} + +/*! + Align a date/time value for a step size + + For Qt::Day alignments there is no "natural day 0" - + instead the first day of the year is used to avoid jumping + major ticks positions when panning a scale. For other alignments + ( f.e according to the first day of the month ) alignDate() + has to be overloaded. + + \param dateTime Date/time value + \param stepSize Step size + \param intervalType Interval type + \param up When true dateTime is ceiled - otherwise it is floored + + \return Aligned date/time value + */ +QDateTime QwtDateScaleEngine::alignDate( + const QDateTime &dateTime, double stepSize, + QwtDate::IntervalType intervalType, bool up ) const +{ + // what about: (year == 1582 && month == 10 && day > 4 && day < 15) ?? + + QDateTime dt = dateTime; + + if ( dateTime.timeSpec() == Qt::OffsetFromUTC ) + { + dt.setUtcOffset( 0 ); + } + + switch( intervalType ) + { + case QwtDate::Millisecond: + { + const int ms = qwtAlignValue( + dt.time().msec(), stepSize, up ) ; + + dt = QwtDate::floor( dateTime, QwtDate::Second ); + dt = dt.addMSecs( ms ); + + break; + } + case QwtDate::Second: + { + int second = dt.time().second(); + if ( up ) + { + if ( dt.time().msec() > 0 ) + second++; + } + + const int s = qwtAlignValue( second, stepSize, up ); + + dt = QwtDate::floor( dt, QwtDate::Minute ); + dt = dt.addSecs( s ); + + break; + } + case QwtDate::Minute: + { + int minute = dt.time().minute(); + if ( up ) + { + if ( dt.time().msec() > 0 || dt.time().second() > 0 ) + minute++; + } + + const int m = qwtAlignValue( minute, stepSize, up ); + + dt = QwtDate::floor( dt, QwtDate::Hour ); + dt = dt.addSecs( m * 60 ); + + break; + } + case QwtDate::Hour: + { + int hour = dt.time().hour(); + if ( up ) + { + if ( dt.time().msec() > 0 || dt.time().second() > 0 + || dt.time().minute() > 0 ) + { + hour++; + } + } + const int h = qwtAlignValue( hour, stepSize, up ); + + dt = QwtDate::floor( dt, QwtDate::Day ); + dt = dt.addSecs( h * 3600 ); + + break; + } + case QwtDate::Day: + { + // What date do we expect f.e. from an alignment of 5 days ?? + // Aligning them to the beginning of the year avoids at least + // jumping major ticks when panning + + int day = dt.date().dayOfYear(); + if ( up ) + { + if ( dt.time() > QTime( 0, 0 ) ) + day++; + } + + const int d = qwtAlignValue( day, stepSize, up ); + + dt = QwtDate::floor( dt, QwtDate::Year ); + dt = dt.addDays( d - 1 ); + + break; + } + case QwtDate::Week: + { + const QDate date = QwtDate::dateOfWeek0( + dt.date().year(), d_data->week0Type ); + + int numWeeks = date.daysTo( dt.date() ) / 7; + if ( up ) + { + if ( dt.time() > QTime( 0, 0 ) || + date.daysTo( dt.date() ) % 7 ) + { + numWeeks++; + } + } + + const int d = qwtAlignValue( numWeeks, stepSize, up ) * 7; + + dt = QwtDate::floor( dt, QwtDate::Day ); + dt.setDate( date ); + dt = dt.addDays( d ); + + break; + } + case QwtDate::Month: + { + int month = dt.date().month(); + if ( up ) + { + if ( dt.date().day() > 1 || + dt.time() > QTime( 0, 0 ) ) + { + month++; + } + } + + const int m = qwtAlignValue( month - 1, stepSize, up ); + + dt = QwtDate::floor( dt, QwtDate::Year ); + dt = dt.addMonths( m ); + + break; + } + case QwtDate::Year: + { + int year = dateTime.date().year(); + if ( up ) + { + if ( dateTime.date().dayOfYear() > 1 || + dt.time() > QTime( 0, 0 ) ) + { + year++; + } + } + + const int y = qwtAlignValue( year, stepSize, up ); + + dt = QwtDate::floor( dt, QwtDate::Day ); + if ( y == 0 ) + { + // there is no year 0 in the Julian calendar + dt.setDate( QDate( stepSize, 1, 1 ).addYears( -stepSize ) ); + } + else + { + dt.setDate( QDate( y, 1, 1 ) ); + } + + break; + } + } + + if ( dateTime.timeSpec() == Qt::OffsetFromUTC ) + { + dt.setUtcOffset( dateTime.utcOffset() ); + } + + return dt; +} + +/*! + Translate a double value into a QDateTime object. + + For QDateTime result is bounded by QwtDate::minDate() and QwtDate::maxDate() + + \return QDateTime object initialized with timeSpec() and utcOffset(). + \sa timeSpec(), utcOffset(), QwtDate::toDateTime() + */ +QDateTime QwtDateScaleEngine::toDateTime( double value ) const +{ + QDateTime dt = QwtDate::toDateTime( value, d_data->timeSpec ); + if ( !dt.isValid() ) + { + const QDate date = ( value <= 0.0 ) + ? QwtDate::minDate() : QwtDate::maxDate(); + + dt = QDateTime( date, QTime( 0, 0 ), d_data->timeSpec ); + } + + if ( d_data->timeSpec == Qt::OffsetFromUTC ) + { + dt = dt.addSecs( d_data->utcOffset ); + dt.setUtcOffset( d_data->utcOffset ); + } + + return dt; +} + diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date_scale_engine.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date_scale_engine.h new file mode 100644 index 0000000..2458d86 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_date_scale_engine.h @@ -0,0 +1,86 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef _QWT_DATE_SCALE_ENGINE_H_ +#define _QWT_DATE_SCALE_ENGINE_H_ 1 + +#include "qwt_date.h" +#include "qwt_scale_engine.h" + +/*! + \brief A scale engine for date/time values + + QwtDateScaleEngine builds scales from a time intervals. + Together with QwtDateScaleDraw it can be used for + axes according to date/time values. + + Years, months, weeks, days, hours and minutes are organized + in steps with non constant intervals. QwtDateScaleEngine + classifies intervals and aligns the boundaries and tick positions + according to this classification. + + QwtDateScaleEngine supports representations depending + on Qt::TimeSpec specifications. The valid range for scales + is limited by the range of QDateTime, that differs + between Qt4 and Qt5. + + Datetime values are expected as the number of milliseconds since + 1970-01-01T00:00:00 Universal Coordinated Time - also known + as "The Epoch", that can be converted to QDateTime using + QwtDate::toDateTime(). + + \sa QwtDate, QwtPlot::setAxisScaleEngine(), + QwtAbstractScale::setScaleEngine() +*/ +class QWT_EXPORT QwtDateScaleEngine: public QwtLinearScaleEngine +{ +public: + QwtDateScaleEngine( Qt::TimeSpec = Qt::LocalTime ); + virtual ~QwtDateScaleEngine(); + + void setTimeSpec( Qt::TimeSpec ); + Qt::TimeSpec timeSpec() const; + + void setUtcOffset( int seconds ); + int utcOffset() const; + + void setWeek0Type( QwtDate::Week0Type ); + QwtDate::Week0Type week0Type() const; + + void setMaxWeeks( int ); + int maxWeeks() const; + + virtual void autoScale( int maxNumSteps, + double &x1, double &x2, double &stepSize ) const; + + virtual QwtScaleDiv divideScale( + double x1, double x2, + int maxMajorSteps, int maxMinorSteps, + double stepSize = 0.0 ) const; + + virtual QwtDate::IntervalType intervalType( + const QDateTime &, const QDateTime &, int maxSteps ) const; + + QDateTime toDateTime( double ) const; + +protected: + virtual QDateTime alignDate( const QDateTime &, double stepSize, + QwtDate::IntervalType, bool up ) const; + +private: + QwtScaleDiv buildScaleDiv( const QDateTime &, const QDateTime &, + int maxMajorSteps, int maxMinorSteps, + QwtDate::IntervalType ) const; + +private: + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dial.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dial.cpp new file mode 100644 index 0000000..60db511 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dial.cpp @@ -0,0 +1,871 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_dial.h" +#include "qwt_dial_needle.h" +#include "qwt_math.h" +#include "qwt_scale_engine.h" +#include "qwt_scale_map.h" +#include "qwt_round_scale_draw.h" +#include "qwt_painter.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline double qwtAngleDist( double a1, double a2 ) +{ + double dist = qAbs( a2 - a1 ); + if ( dist > 360.0 ) + dist -= 360.0; + + return dist; +} + +static inline bool qwtIsOnArc( double angle, double min, double max ) +{ + if ( min < max ) + { + return ( angle >= min ) && ( angle <= max ); + } + else + { + return ( angle >= min ) || ( angle <= max ); + } +} + +static inline double qwtBoundedAngle( double min, double angle, double max ) +{ + double from = qwtNormalizeDegrees( min ); + double to = qwtNormalizeDegrees( max ); + + double a; + + if ( qwtIsOnArc( angle, from, to ) ) + { + a = angle; + if ( a < min ) + a += 360.0; + } + else + { + if ( qwtAngleDist( angle, from ) < + qwtAngleDist( angle, to ) ) + { + a = min; + } + else + { + a = max; + } + } + + return a; +} + +class QwtDial::PrivateData +{ +public: + PrivateData(): + frameShadow( Sunken ), + lineWidth( 0 ), + mode( RotateNeedle ), + origin( 90.0 ), + minScaleArc( 0.0 ), + maxScaleArc( 0.0 ), + needle( NULL ), + arcOffset( 0.0 ), + mouseOffset( 0.0 ) + { + } + + ~PrivateData() + { + delete needle; + } + Shadow frameShadow; + int lineWidth; + + QwtDial::Mode mode; + + double origin; + double minScaleArc; + double maxScaleArc; + + QwtDialNeedle *needle; + + double arcOffset; + double mouseOffset; + + QPixmap pixmapCache; +}; + +/*! + \brief Constructor + \param parent Parent widget + + Create a dial widget with no needle. The scale is initialized + to [ 0.0, 360.0 ] and 360 steps ( QwtAbstractSlider::setTotalSteps() ). + The origin of the scale is at 90°, + + The value is set to 0.0. + + The default mode is QwtDial::RotateNeedle. +*/ +QwtDial::QwtDial( QWidget* parent ): + QwtAbstractSlider( parent ) +{ + d_data = new PrivateData; + + setFocusPolicy( Qt::TabFocus ); + + QPalette p = palette(); + for ( int i = 0; i < QPalette::NColorGroups; i++ ) + { + const QPalette::ColorGroup colorGroup = + static_cast( i ); + + // Base: background color of the circle inside the frame. + // WindowText: background color of the circle inside the scale + + p.setColor( colorGroup, QPalette::WindowText, + p.color( colorGroup, QPalette::Base ) ); + } + setPalette( p ); + + QwtRoundScaleDraw* scaleDraw = new QwtRoundScaleDraw(); + scaleDraw->setRadius( 0 ); + + setScaleDraw( scaleDraw ); + + setScaleArc( 0.0, 360.0 ); // scale as a full circle + + setScaleMaxMajor( 10 ); + setScaleMaxMinor( 5 ); + + setValue( 0.0 ); +} + +//! Destructor +QwtDial::~QwtDial() +{ + delete d_data; +} + +/*! + Sets the frame shadow value from the frame style. + + \param shadow Frame shadow + \sa setLineWidth(), QFrame::setFrameShadow() +*/ +void QwtDial::setFrameShadow( Shadow shadow ) +{ + if ( shadow != d_data->frameShadow ) + { + invalidateCache(); + + d_data->frameShadow = shadow; + if ( lineWidth() > 0 ) + update(); + } +} + +/*! + \return Frame shadow + /sa setFrameShadow(), lineWidth(), QFrame::frameShadow() +*/ +QwtDial::Shadow QwtDial::frameShadow() const +{ + return d_data->frameShadow; +} + +/*! + Sets the line width of the frame + + \param lineWidth Line width + \sa setFrameShadow() +*/ +void QwtDial::setLineWidth( int lineWidth ) +{ + if ( lineWidth < 0 ) + lineWidth = 0; + + if ( d_data->lineWidth != lineWidth ) + { + invalidateCache(); + + d_data->lineWidth = lineWidth; + update(); + } +} + +/*! + \return Line width of the frame + \sa setLineWidth(), frameShadow(), lineWidth() +*/ +int QwtDial::lineWidth() const +{ + return d_data->lineWidth; +} + +/*! + \return bounding rectangle of the circle inside the frame + \sa setLineWidth(), scaleInnerRect(), boundingRect() +*/ +QRect QwtDial::innerRect() const +{ + const int lw = lineWidth(); + return boundingRect().adjusted( lw, lw, -lw, -lw ); +} + +/*! + \return bounding rectangle of the dial including the frame + \sa setLineWidth(), scaleInnerRect(), innerRect() +*/ +QRect QwtDial::boundingRect() const +{ + const QRect cr = contentsRect(); + + const double dim = qMin( cr.width(), cr.height() ); + + QRect inner( 0, 0, dim, dim ); + inner.moveCenter( cr.center() ); + + return inner; +} + +/*! + \return rectangle inside the scale + \sa setLineWidth(), boundingRect(), innerRect() +*/ +QRect QwtDial::scaleInnerRect() const +{ + QRect rect = innerRect(); + + const QwtAbstractScaleDraw *sd = scaleDraw(); + if ( sd ) + { + int scaleDist = qCeil( sd->extent( font() ) ); + scaleDist++; // margin + + rect.adjust( scaleDist, scaleDist, -scaleDist, -scaleDist ); + } + + return rect; +} + +/*! + \brief Change the mode of the dial. + \param mode New mode + + In case of QwtDial::RotateNeedle the needle is rotating, in case of + QwtDial::RotateScale, the needle points to origin() + and the scale is rotating. + + The default mode is QwtDial::RotateNeedle. + + \sa mode(), setValue(), setOrigin() +*/ +void QwtDial::setMode( Mode mode ) +{ + if ( mode != d_data->mode ) + { + invalidateCache(); + + d_data->mode = mode; + sliderChange(); + } +} + +/*! + \return Mode of the dial. + \sa setMode(), origin(), setScaleArc(), value() +*/ +QwtDial::Mode QwtDial::mode() const +{ + return d_data->mode; +} + +/*! + Invalidate the internal caches used to speed up repainting + */ +void QwtDial::invalidateCache() +{ + d_data->pixmapCache = QPixmap(); +} + +/*! + Paint the dial + \param event Paint event +*/ +void QwtDial::paintEvent( QPaintEvent *event ) +{ + QPainter painter( this ); + painter.setClipRegion( event->region() ); + + QStyleOption opt; + opt.init(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); + + if ( d_data->mode == QwtDial::RotateScale ) + { + painter.save(); + painter.setRenderHint( QPainter::Antialiasing, true ); + + drawContents( &painter ); + + painter.restore(); + } + + const QRect r = contentsRect(); + if ( r.size() != d_data->pixmapCache.size() ) + { + d_data->pixmapCache = QwtPainter::backingStore( this, r.size() ); + d_data->pixmapCache.fill( Qt::transparent ); + + QPainter p( &d_data->pixmapCache ); + p.setRenderHint( QPainter::Antialiasing, true ); + p.translate( -r.topLeft() ); + + if ( d_data->mode != QwtDial::RotateScale ) + drawContents( &p ); + + if ( lineWidth() > 0 ) + drawFrame( &p ); + + if ( d_data->mode != QwtDial::RotateNeedle ) + drawNeedle( &p ); + } + + painter.drawPixmap( r.topLeft(), d_data->pixmapCache ); + + if ( d_data->mode == QwtDial::RotateNeedle ) + drawNeedle( &painter ); + + if ( hasFocus() ) + drawFocusIndicator( &painter ); +} + +/*! + Draw the focus indicator + \param painter Painter +*/ +void QwtDial::drawFocusIndicator( QPainter *painter ) const +{ + QwtPainter::drawFocusRect( painter, this, boundingRect() ); +} + +/*! + Draw the frame around the dial + + \param painter Painter + \sa lineWidth(), frameShadow() +*/ +void QwtDial::drawFrame( QPainter *painter ) +{ + QwtPainter::drawRoundFrame( painter, boundingRect(), + palette(), lineWidth(), d_data->frameShadow ); +} + +/*! + \brief Draw the contents inside the frame + + QPalette::Window is the background color outside of the frame. + QPalette::Base is the background color inside the frame. + QPalette::WindowText is the background color inside the scale. + + \param painter Painter + + \sa boundingRect(), innerRect(), + scaleInnerRect(), QWidget::setPalette() +*/ +void QwtDial::drawContents( QPainter *painter ) const +{ + if ( testAttribute( Qt::WA_NoSystemBackground ) || + palette().brush( QPalette::Base ) != + palette().brush( QPalette::Window ) ) + { + const QRectF br = boundingRect(); + + painter->save(); + painter->setPen( Qt::NoPen ); + painter->setBrush( palette().brush( QPalette::Base ) ); + painter->drawEllipse( br ); + painter->restore(); + } + + const QRectF insideScaleRect = scaleInnerRect(); + if ( palette().brush( QPalette::WindowText ) != + palette().brush( QPalette::Base ) ) + { + painter->save(); + painter->setPen( Qt::NoPen ); + painter->setBrush( palette().brush( QPalette::WindowText ) ); + painter->drawEllipse( insideScaleRect ); + painter->restore(); + } + + const QPointF center = insideScaleRect.center(); + const double radius = 0.5 * insideScaleRect.width(); + + painter->save(); + drawScale( painter, center, radius ); + painter->restore(); + + painter->save(); + drawScaleContents( painter, center, radius ); + painter->restore(); +} + +/*! + Draw the needle + + \param painter Painter + \param center Center of the dial + \param radius Length for the needle + \param direction Direction of the needle in degrees, counter clockwise + \param colorGroup ColorGroup +*/ +void QwtDial::drawNeedle( QPainter *painter, const QPointF ¢er, + double radius, double direction, QPalette::ColorGroup colorGroup ) const +{ + if ( d_data->needle ) + { + direction = 360.0 - direction; // counter clockwise + d_data->needle->draw( painter, center, radius, direction, colorGroup ); + } +} + +void QwtDial::drawNeedle( QPainter *painter ) const +{ + if ( !isValid() ) + return; + + QPalette::ColorGroup colorGroup; + if ( isEnabled() ) + colorGroup = hasFocus() ? QPalette::Active : QPalette::Inactive; + else + colorGroup = QPalette::Disabled; + + const QRectF sr = scaleInnerRect(); + + painter->save(); + painter->setRenderHint( QPainter::Antialiasing, true ); + drawNeedle( painter, sr.center(), 0.5 * sr.width(), + scaleMap().transform( value() ) + 270.0, colorGroup ); + painter->restore(); +} + +/*! + Draw the scale + + \param painter Painter + \param center Center of the dial + \param radius Radius of the scale +*/ +void QwtDial::drawScale( QPainter *painter, + const QPointF ¢er, double radius ) const +{ + QwtRoundScaleDraw *sd = const_cast( scaleDraw() ); + if ( sd == NULL ) + return; + + sd->setRadius( radius ); + sd->moveCenter( center ); + + QPalette pal = palette(); + + const QColor textColor = pal.color( QPalette::Text ); + pal.setColor( QPalette::WindowText, textColor ); // ticks, backbone + + painter->setFont( font() ); + painter->setPen( QPen( textColor, sd->penWidth() ) ); + + painter->setBrush( Qt::red ); + sd->draw( painter, pal ); +} + +/*! + Draw the contents inside the scale + + Paints nothing. + + \param painter Painter + \param center Center of the contents circle + \param radius Radius of the contents circle +*/ +void QwtDial::drawScaleContents( QPainter *painter, + const QPointF ¢er, double radius ) const +{ + Q_UNUSED(painter); + Q_UNUSED(center); + Q_UNUSED(radius); +} + +/*! + Set a needle for the dial + + \param needle Needle + + \warning The needle will be deleted, when a different needle is + set or in ~QwtDial() +*/ +void QwtDial::setNeedle( QwtDialNeedle *needle ) +{ + if ( needle != d_data->needle ) + { + if ( d_data->needle ) + delete d_data->needle; + + d_data->needle = needle; + update(); + } +} + +/*! + \return needle + \sa setNeedle() +*/ +const QwtDialNeedle *QwtDial::needle() const +{ + return d_data->needle; +} + +/*! + \return needle + \sa setNeedle() +*/ +QwtDialNeedle *QwtDial::needle() +{ + return d_data->needle; +} + +//! \return the scale draw +QwtRoundScaleDraw *QwtDial::scaleDraw() +{ + return static_cast( abstractScaleDraw() ); +} + +//! \return the scale draw +const QwtRoundScaleDraw *QwtDial::scaleDraw() const +{ + return static_cast( abstractScaleDraw() ); +} + +/*! + Set an individual scale draw + + The motivation for setting a scale draw is often + to overload QwtRoundScaleDraw::label() to return + individual tick labels. + + \param scaleDraw Scale draw + \warning The previous scale draw is deleted +*/ +void QwtDial::setScaleDraw( QwtRoundScaleDraw *scaleDraw ) +{ + setAbstractScaleDraw( scaleDraw ); + sliderChange(); +} + +/*! + Change the arc of the scale + + \param minArc Lower limit + \param maxArc Upper limit + + \sa minScaleArc(), maxScaleArc() +*/ +void QwtDial::setScaleArc( double minArc, double maxArc ) +{ + if ( minArc != 360.0 && minArc != -360.0 ) + minArc = ::fmod( minArc, 360.0 ); + if ( maxArc != 360.0 && maxArc != -360.0 ) + maxArc = ::fmod( maxArc, 360.0 ); + + double minScaleArc = qMin( minArc, maxArc ); + double maxScaleArc = qMax( minArc, maxArc ); + + if ( maxScaleArc - minScaleArc > 360.0 ) + maxScaleArc = minScaleArc + 360.0; + + if ( ( minScaleArc != d_data->minScaleArc ) || + ( maxScaleArc != d_data->maxScaleArc ) ) + { + d_data->minScaleArc = minScaleArc; + d_data->maxScaleArc = maxScaleArc; + + invalidateCache(); + sliderChange(); + } +} + +/*! + Set the lower limit for the scale arc + + \param min Lower limit of the scale arc + \sa setScaleArc(), setMaxScaleArc() + */ +void QwtDial::setMinScaleArc( double min ) +{ + setScaleArc( min, d_data->maxScaleArc ); +} + +/*! + \return Lower limit of the scale arc + \sa setScaleArc() +*/ +double QwtDial::minScaleArc() const +{ + return d_data->minScaleArc; +} + +/*! + Set the upper limit for the scale arc + + \param max Upper limit of the scale arc + \sa setScaleArc(), setMinScaleArc() + */ +void QwtDial::setMaxScaleArc( double max ) +{ + setScaleArc( d_data->minScaleArc, max ); +} + +/*! + \return Upper limit of the scale arc + \sa setScaleArc() +*/ +double QwtDial::maxScaleArc() const +{ + return d_data->maxScaleArc; +} + +/*! + \brief Change the origin + + The origin is the angle where scale and needle is relative to. + + \param origin New origin + \sa origin() +*/ +void QwtDial::setOrigin( double origin ) +{ + invalidateCache(); + + d_data->origin = origin; + sliderChange(); +} + +/*! + The origin is the angle where scale and needle is relative to. + + \return Origin of the dial + \sa setOrigin() +*/ +double QwtDial::origin() const +{ + return d_data->origin; +} + +/*! + \return Size hint + \sa minimumSizeHint() +*/ +QSize QwtDial::sizeHint() const +{ + int sh = 0; + if ( scaleDraw() ) + sh = qCeil( scaleDraw()->extent( font() ) ); + + const int d = 6 * sh + 2 * lineWidth(); + + QSize hint( d, d ); + if ( !isReadOnly() ) + hint = hint.expandedTo( QApplication::globalStrut() ); + + return hint; +} + +/*! + \return Minimum size hint + \sa sizeHint() +*/ +QSize QwtDial::minimumSizeHint() const +{ + int sh = 0; + if ( scaleDraw() ) + sh = qCeil( scaleDraw()->extent( font() ) ); + + const int d = 3 * sh + 2 * lineWidth(); + + return QSize( d, d ); +} + +/*! + \brief Determine what to do when the user presses a mouse button. + + \param pos Mouse position + + \retval True, when the inner circle contains pos + \sa scrolledTo() +*/ +bool QwtDial::isScrollPosition( const QPoint &pos ) const +{ + const QRegion region( innerRect(), QRegion::Ellipse ); + if ( region.contains( pos ) && ( pos != innerRect().center() ) ) + { + double angle = QLineF( rect().center(), pos ).angle(); + if ( d_data->mode == QwtDial::RotateScale ) + angle = 360.0 - angle; + + double valueAngle = + qwtNormalizeDegrees( 90.0 - scaleMap().transform( value() ) ); + + d_data->mouseOffset = qwtNormalizeDegrees( angle - valueAngle ); + d_data->arcOffset = scaleMap().p1(); + + return true; + } + + return false; +} + +/*! + \brief Determine the value for a new position of the + slider handle. + + \param pos Mouse position + + \return Value for the mouse position + \sa isScrollPosition() +*/ +double QwtDial::scrolledTo( const QPoint &pos ) const +{ + double angle = QLineF( rect().center(), pos ).angle(); + if ( d_data->mode == QwtDial::RotateScale ) + { + angle += scaleMap().p1() - d_data->arcOffset; + angle = 360.0 - angle; + } + + angle = qwtNormalizeDegrees( angle - d_data->mouseOffset ); + angle = qwtNormalizeDegrees( 90.0 - angle ); + + if ( scaleMap().pDist() >= 360.0 ) + { + if ( angle < scaleMap().p1() ) + angle += 360.0; + + if ( !wrapping() ) + { + double boundedAngle = angle; + + const double arc = angle - scaleMap().transform( value() ); + if ( qAbs( arc ) > 180.0 ) + { + boundedAngle = ( arc > 0 ) + ? scaleMap().p1() : scaleMap().p2(); + } + + d_data->mouseOffset += ( boundedAngle - angle ); + + angle = boundedAngle; + } + } + else + { + const double boundedAngle = + qwtBoundedAngle( scaleMap().p1(), angle, scaleMap().p2() ); + + if ( !wrapping() ) + d_data->mouseOffset += ( boundedAngle - angle ); + + angle = boundedAngle; + } + + return scaleMap().invTransform( angle ); +} + +/*! + Change Event handler + \param event Change event + + Invalidates internal paint caches if necessary +*/ +void QwtDial::changeEvent( QEvent *event ) +{ + switch( event->type() ) + { + case QEvent::EnabledChange: + case QEvent::FontChange: + case QEvent::StyleChange: + case QEvent::PaletteChange: + case QEvent::LanguageChange: + case QEvent::LocaleChange: + { + invalidateCache(); + break; + } + default: + break; + } + + QwtAbstractSlider::changeEvent( event ); +} + +/*! + Wheel Event handler + \param event Wheel event +*/ +void QwtDial::wheelEvent( QWheelEvent *event ) +{ + const QRegion region( innerRect(), QRegion::Ellipse ); + if ( region.contains( event->pos() ) ) + QwtAbstractSlider::wheelEvent( event ); +} + +void QwtDial::setAngleRange( double angle, double span ) +{ + QwtRoundScaleDraw *sd = const_cast( scaleDraw() ); + if ( sd ) + { + angle = qwtNormalizeDegrees( angle - 270.0 ); + sd->setAngleRange( angle, angle + span ); + } +} + +/*! + Invalidate the internal caches and call + QwtAbstractSlider::scaleChange() + */ +void QwtDial::scaleChange() +{ + invalidateCache(); + QwtAbstractSlider::scaleChange(); +} + +void QwtDial::sliderChange() +{ + setAngleRange( d_data->origin + d_data->minScaleArc, + d_data->maxScaleArc - d_data->minScaleArc ); + + if ( mode() == RotateScale ) + { + const double arc = scaleMap().transform( value() ) - scaleMap().p1(); + setAngleRange( d_data->origin - arc, + d_data->maxScaleArc - d_data->minScaleArc ); + } + + QwtAbstractSlider::sliderChange(); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dial.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dial.h new file mode 100644 index 0000000..800152c --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dial.h @@ -0,0 +1,168 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_DIAL_H +#define QWT_DIAL_H 1 + +#include "qwt_global.h" +#include "qwt_abstract_slider.h" +#include "qwt_abstract_scale_draw.h" +#include +#include + +class QwtDialNeedle; +class QwtRoundScaleDraw; + +/*! + \brief QwtDial class provides a rounded range control. + + QwtDial is intended as base class for dial widgets like + speedometers, compass widgets, clocks ... + + \image html dials2.png + + A dial contains a scale and a needle indicating the current value + of the dial. Depending on Mode one of them is fixed and the + other is rotating. If not isReadOnly() the + dial can be rotated by dragging the mouse or using keyboard inputs + (see QwtAbstractSlider::keyPressEvent()). A dial might be wrapping, what means + a rotation below/above one limit continues on the other limit (f.e compass). + The scale might cover any arc of the dial, its values are related to + the origin() of the dial. + + Often dials have to be updated very often according to values from external + devices. For these high refresh rates QwtDial caches as much as possible. + For derived classes it might be necessary to clear these caches manually + according to attribute changes using invalidateCache(). + + \sa QwtCompass, QwtAnalogClock, QwtDialNeedle + \note The controls and dials examples shows different types of dials. + \note QDial is more similar to QwtKnob than to QwtDial +*/ + +class QWT_EXPORT QwtDial: public QwtAbstractSlider +{ + Q_OBJECT + + Q_ENUMS( Shadow Mode Direction ) + + Q_PROPERTY( int lineWidth READ lineWidth WRITE setLineWidth ) + Q_PROPERTY( Shadow frameShadow READ frameShadow WRITE setFrameShadow ) + Q_PROPERTY( Mode mode READ mode WRITE setMode ) + Q_PROPERTY( double origin READ origin WRITE setOrigin ) + Q_PROPERTY( double minScaleArc READ minScaleArc WRITE setMinScaleArc ) + Q_PROPERTY( double maxScaleArc READ maxScaleArc WRITE setMaxScaleArc ) + +public: + + /*! + \brief Frame shadow + + Unfortunately it is not possible to use QFrame::Shadow + as a property of a widget that is not derived from QFrame. + The following enum is made for the designer only. It is safe + to use QFrame::Shadow instead. + */ + enum Shadow + { + //! QFrame::Plain + Plain = QFrame::Plain, + + //! QFrame::Raised + Raised = QFrame::Raised, + + //! QFrame::Sunken + Sunken = QFrame::Sunken + }; + + //! Mode controlling whether the needle or the scale is rotating + enum Mode + { + //! The needle is rotating + RotateNeedle, + + //! The needle is fixed, the scales are rotating + RotateScale + }; + + explicit QwtDial( QWidget *parent = NULL ); + virtual ~QwtDial(); + + void setFrameShadow( Shadow ); + Shadow frameShadow() const; + + void setLineWidth( int ); + int lineWidth() const; + + void setMode( Mode ); + Mode mode() const; + + void setScaleArc( double min, double max ); + + void setMinScaleArc( double min ); + double minScaleArc() const; + + void setMaxScaleArc( double min ); + double maxScaleArc() const; + + virtual void setOrigin( double ); + double origin() const; + + void setNeedle( QwtDialNeedle * ); + const QwtDialNeedle *needle() const; + QwtDialNeedle *needle(); + + QRect boundingRect() const; + QRect innerRect() const; + + virtual QRect scaleInnerRect() const; + + virtual QSize sizeHint() const; + virtual QSize minimumSizeHint() const; + + void setScaleDraw( QwtRoundScaleDraw * ); + + QwtRoundScaleDraw *scaleDraw(); + const QwtRoundScaleDraw *scaleDraw() const; + +protected: + virtual void wheelEvent( QWheelEvent * ); + virtual void paintEvent( QPaintEvent * ); + virtual void changeEvent( QEvent * ); + + virtual void drawFrame( QPainter *p ); + virtual void drawContents( QPainter * ) const; + virtual void drawFocusIndicator( QPainter * ) const; + + void invalidateCache(); + + virtual void drawScale( QPainter *, + const QPointF ¢er, double radius ) const; + + virtual void drawScaleContents( QPainter *painter, + const QPointF ¢er, double radius ) const; + + virtual void drawNeedle( QPainter *, const QPointF &, + double radius, double direction, QPalette::ColorGroup ) const; + + virtual double scrolledTo( const QPoint & ) const; + virtual bool isScrollPosition( const QPoint & ) const; + + virtual void sliderChange(); + virtual void scaleChange(); + +private: + void setAngleRange( double angle, double span ); + void drawNeedle( QPainter * ) const; + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dial_needle.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dial_needle.cpp new file mode 100644 index 0000000..6b15d2a --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dial_needle.cpp @@ -0,0 +1,440 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_dial_needle.h" +#include "qwt_global.h" +#include "qwt_math.h" +#include "qwt_painter.h" +#include +#include + +#if QT_VERSION < 0x040601 +#define qFastSin(x) qSin(x) +#define qFastCos(x) qCos(x) +#endif + +static void qwtDrawStyle1Needle( QPainter *painter, + const QPalette &palette, QPalette::ColorGroup colorGroup, + double length ) +{ + const double r[] = { 0.4, 0.3, 1, 0.8, 1, 0.3, 0.4 }; + const double a[] = { -45, -20, -15, 0, 15, 20, 45 }; + + QPainterPath path; + for ( int i = 0; i < 7; i++ ) + { + const double angle = a[i] / 180.0 * M_PI; + const double radius = r[i] * length; + + const double x = radius * qFastCos( angle ); + const double y = radius * qFastSin( angle ); + + path.lineTo( x, -y ); + } + + painter->setPen( Qt::NoPen ); + painter->setBrush( palette.brush( colorGroup, QPalette::Light ) ); + painter->drawPath( path ); +} + +static void qwtDrawStyle2Needle( QPainter *painter, + const QPalette &palette, QPalette::ColorGroup colorGroup, double length ) +{ + const double ratioX = 0.7; + const double ratioY = 0.3; + + QPainterPath path1; + path1.lineTo( ratioX * length, 0.0 ); + path1.lineTo( length, ratioY * length ); + + QPainterPath path2; + path2.lineTo( ratioX * length, 0.0 ); + path2.lineTo( length, -ratioY * length ); + + painter->setPen( Qt::NoPen ); + + painter->setBrush( palette.brush( colorGroup, QPalette::Light ) ); + painter->drawPath( path1 ); + + painter->setBrush( palette.brush( colorGroup, QPalette::Dark ) ); + painter->drawPath( path2 ); +} + +static void qwtDrawShadedPointer( QPainter *painter, + const QColor &lightColor, const QColor &darkColor, + double length, double width ) +{ + const double peak = qMax( length / 10.0, 5.0 ); + + const double knobWidth = width + 8; + QRectF knobRect( 0, 0, knobWidth, knobWidth ); + knobRect.moveCenter( QPointF(0, 0) ); + + QPainterPath path1; + path1.lineTo( 0.0, 0.5 * width ); + path1.lineTo( length - peak, 0.5 * width ); + path1.lineTo( length, 0.0 ); + path1.lineTo( 0.0, 0.0 ); + + QPainterPath arcPath1; + arcPath1.arcTo( knobRect, 0.0, -90.0 ); + + path1 = path1.united( arcPath1 ); + + QPainterPath path2; + path2.lineTo( 0.0, -0.5 * width ); + path2.lineTo( length - peak, -0.5 * width ); + path2.lineTo( length, 0.0 ); + path2.lineTo( 0.0, 0.0 ); + + QPainterPath arcPath2; + arcPath2.arcTo( knobRect, 0.0, 90.0 ); + + path2 = path2.united( arcPath2 ); + + painter->setPen( Qt::NoPen ); + + painter->setBrush( lightColor ); + painter->drawPath( path1 ); + + painter->setBrush( darkColor ); + painter->drawPath( path2 ); +} + +static void qwtDrawArrowNeedle( QPainter *painter, + const QPalette &palette, QPalette::ColorGroup colorGroup, + double length, double width ) +{ + if ( width <= 0 ) + width = qMax( length * 0.06, 9.0 ); + + const double peak = qMax( 2.0, 0.4 * width ); + + QPainterPath path; + path.moveTo( 0.0, 0.5 * width ); + path.lineTo( length - peak, 0.3 * width ); + path.lineTo( length, 0.0 ); + path.lineTo( length - peak, -0.3 * width ); + path.lineTo( 0.0, -0.5 * width ); + + QRectF br = path.boundingRect(); + + QPalette pal( palette.color( QPalette::Mid ) ); + QColor c1 = pal.color( QPalette::Light ); + QColor c2 = pal.color( QPalette::Dark ); + + QLinearGradient gradient( br.topLeft(), br.bottomLeft() ); + gradient.setColorAt( 0.0, c1 ); + gradient.setColorAt( 0.5, c1 ); + gradient.setColorAt( 0.5001, c2 ); + gradient.setColorAt( 1.0, c2 ); + + QPen pen( gradient, 1 ); + pen.setJoinStyle( Qt::MiterJoin ); + + painter->setPen( pen ); + painter->setBrush( palette.brush( colorGroup, QPalette::Mid ) ); + + painter->drawPath( path ); +} + +static void qwtDrawTriangleNeedle( QPainter *painter, + const QPalette &palette, QPalette::ColorGroup colorGroup, + double length ) +{ + const double width = qRound( length / 3.0 ); + + QPainterPath path[4]; + + path[0].lineTo( length, 0.0 ); + path[0].lineTo( 0.0, width / 2 ); + + path[1].lineTo( length, 0.0 ); + path[1].lineTo( 0.0, -width / 2 ); + + path[2].lineTo( -length, 0.0 ); + path[2].lineTo( 0.0, width / 2 ); + + path[3].lineTo( -length, 0.0 ); + path[3].lineTo( 0.0, -width / 2 ); + + + const int colorOffset = 10; + const QColor darkColor = palette.color( colorGroup, QPalette::Dark ); + const QColor lightColor = palette.color( colorGroup, QPalette::Light ); + + QColor color[4]; + color[0] = darkColor.light( 100 + colorOffset ); + color[1] = darkColor.dark( 100 + colorOffset ); + color[2] = lightColor.light( 100 + colorOffset ); + color[3] = lightColor.dark( 100 + colorOffset ); + + painter->setPen( Qt::NoPen ); + + for ( int i = 0; i < 4; i++ ) + { + painter->setBrush( color[i] ); + painter->drawPath( path[i] ); + } +} + +//! Constructor +QwtDialNeedle::QwtDialNeedle(): + d_palette( QApplication::palette() ) +{ +} + +//! Destructor +QwtDialNeedle::~QwtDialNeedle() +{ +} + +/*! + Sets the palette for the needle. + + \param palette New Palette +*/ +void QwtDialNeedle::setPalette( const QPalette &palette ) +{ + d_palette = palette; +} + +/*! + \return the palette of the needle. +*/ +const QPalette &QwtDialNeedle::palette() const +{ + return d_palette; +} + +/*! + Draw the needle + + \param painter Painter + \param center Center of the dial, start position for the needle + \param length Length of the needle + \param direction Direction of the needle, in degrees counter clockwise + \param colorGroup Color group, used for painting +*/ +void QwtDialNeedle::draw( QPainter *painter, + const QPointF ¢er, double length, double direction, + QPalette::ColorGroup colorGroup ) const +{ + painter->save(); + + painter->translate( center ); + painter->rotate( -direction ); + + drawNeedle( painter, length, colorGroup ); + + painter->restore(); +} + +//! Draw the knob +void QwtDialNeedle::drawKnob( QPainter *painter, + double width, const QBrush &brush, bool sunken ) const +{ + QPalette palette( brush.color() ); + + QColor c1 = palette.color( QPalette::Light ); + QColor c2 = palette.color( QPalette::Dark ); + + if ( sunken ) + qSwap( c1, c2 ); + + QRectF rect( 0.0, 0.0, width, width ); + rect.moveCenter( painter->combinedTransform().map( QPointF() ) ); + + QLinearGradient gradient( rect.topLeft(), rect.bottomRight() ); + gradient.setColorAt( 0.0, c1 ); + gradient.setColorAt( 0.3, c1 ); + gradient.setColorAt( 0.7, c2 ); + gradient.setColorAt( 1.0, c2 ); + + painter->save(); + + painter->resetTransform(); + + painter->setPen( QPen( gradient, 1 ) ); + painter->setBrush( brush ); + painter->drawEllipse( rect ); + + painter->restore(); +} + +/*! + Constructor + + \param style Style + \param hasKnob With/Without knob + \param mid Middle color + \param base Base color +*/ +QwtDialSimpleNeedle::QwtDialSimpleNeedle( Style style, bool hasKnob, + const QColor &mid, const QColor &base ): + d_style( style ), + d_hasKnob( hasKnob ), + d_width( -1 ) +{ + QPalette palette; + palette.setColor( QPalette::Mid, mid ); + palette.setColor( QPalette::Base, base ); + + setPalette( palette ); +} + +/*! + Set the width of the needle + \param width Width + \sa width() +*/ +void QwtDialSimpleNeedle::setWidth( double width ) +{ + d_width = width; +} + +/*! + \return the width of the needle + \sa setWidth() +*/ +double QwtDialSimpleNeedle::width() const +{ + return d_width; +} + +/*! + Draw the needle + + \param painter Painter + \param length Length of the needle + \param colorGroup Color group, used for painting +*/ +void QwtDialSimpleNeedle::drawNeedle( QPainter *painter, + double length, QPalette::ColorGroup colorGroup ) const +{ + double knobWidth = 0.0; + double width = d_width; + + if ( d_style == Arrow ) + { + if ( width <= 0.0 ) + width = qMax(length * 0.06, 6.0); + + qwtDrawArrowNeedle( painter, + palette(), colorGroup, length, width ); + + knobWidth = qMin( width * 2.0, 0.2 * length ); + } + else + { + if ( width <= 0.0 ) + width = 5.0; + + QPen pen ( palette().brush( colorGroup, QPalette::Mid ), width ); + pen.setCapStyle( Qt::FlatCap ); + + painter->setPen( pen ); + painter->drawLine( QPointF( 0.0, 0.0 ), QPointF( length, 0.0 ) ); + + knobWidth = qMax( width * 3.0, 5.0 ); + } + + if ( d_hasKnob && knobWidth > 0.0 ) + { + drawKnob( painter, knobWidth, + palette().brush( colorGroup, QPalette::Base ), false ); + } +} + +//! Constructor +QwtCompassMagnetNeedle::QwtCompassMagnetNeedle( Style style, + const QColor &light, const QColor &dark ): + d_style( style ) +{ + QPalette palette; + palette.setColor( QPalette::Light, light ); + palette.setColor( QPalette::Dark, dark ); + palette.setColor( QPalette::Base, Qt::gray ); + + setPalette( palette ); +} + +/*! + Draw the needle + + \param painter Painter + \param length Length of the needle + \param colorGroup Color group, used for painting +*/ +void QwtCompassMagnetNeedle::drawNeedle( QPainter *painter, + double length, QPalette::ColorGroup colorGroup ) const +{ + if ( d_style == ThinStyle ) + { + const double width = qMax( length / 6.0, 3.0 ); + + const int colorOffset = 10; + + const QColor light = palette().color( colorGroup, QPalette::Light ); + const QColor dark = palette().color( colorGroup, QPalette::Dark ); + + qwtDrawShadedPointer( painter, + dark.light( 100 + colorOffset ), + dark.dark( 100 + colorOffset ), + length, width ); + + painter->rotate( 180.0 ); + + qwtDrawShadedPointer( painter, + light.light( 100 + colorOffset ), + light.dark( 100 + colorOffset ), + length, width ); + + const QBrush baseBrush = palette().brush( colorGroup, QPalette::Base ); + drawKnob( painter, width, baseBrush, true ); + } + else + { + qwtDrawTriangleNeedle( painter, palette(), colorGroup, length ); + } +} + +/*! + Constructor + + \param style Arrow style + \param light Light color + \param dark Dark color +*/ +QwtCompassWindArrow::QwtCompassWindArrow( Style style, + const QColor &light, const QColor &dark ): + d_style( style ) +{ + QPalette palette; + palette.setColor( QPalette::Light, light ); + palette.setColor( QPalette::Dark, dark ); + + setPalette( palette ); +} + +/*! + Draw the needle + + \param painter Painter + \param length Length of the needle + \param colorGroup Color group, used for painting +*/ +void QwtCompassWindArrow::drawNeedle( QPainter *painter, + double length, QPalette::ColorGroup colorGroup ) const +{ + if ( d_style == Style1 ) + qwtDrawStyle1Needle( painter, palette(), colorGroup, length ); + else + qwtDrawStyle2Needle( painter, palette(), colorGroup, length ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dial_needle.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dial_needle.h new file mode 100644 index 0000000..21a2342 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dial_needle.h @@ -0,0 +1,187 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_DIAL_NEEDLE_H +#define QWT_DIAL_NEEDLE_H 1 + +#include "qwt_global.h" +#include + +class QPainter; +class QPoint; + +/*! + \brief Base class for needles that can be used in a QwtDial. + + QwtDialNeedle is a pointer that indicates a value by pointing + to a specific direction. + + \sa QwtDial, QwtCompass +*/ + +class QWT_EXPORT QwtDialNeedle +{ +public: + QwtDialNeedle(); + virtual ~QwtDialNeedle(); + + virtual void setPalette( const QPalette & ); + const QPalette &palette() const; + + virtual void draw( QPainter *painter, const QPointF ¢er, + double length, double direction, + QPalette::ColorGroup = QPalette::Active ) const; + +protected: + /*! + \brief Draw the needle + + The origin of the needle is at position (0.0, 0.0 ) + pointing in direction 0.0 ( = east ). + + The painter is already initialized with translation and + rotation. + + \param painter Painter + \param length Length of the needle + \param colorGroup Color group, used for painting + + \sa setPalette(), palette() + */ + virtual void drawNeedle( QPainter *painter, + double length, QPalette::ColorGroup colorGroup ) const = 0; + + virtual void drawKnob( QPainter *, double width, + const QBrush &, bool sunken ) const; + +private: + QPalette d_palette; +}; + +/*! + \brief A needle for dial widgets + + The following colors are used: + + - QPalette::Mid\n + Pointer + - QPalette::Base\n + Knob + + \sa QwtDial, QwtCompass +*/ + +class QWT_EXPORT QwtDialSimpleNeedle: public QwtDialNeedle +{ +public: + //! Style of the needle + enum Style + { + //! Arrow + Arrow, + + //! A straight line from the center + Ray + }; + + QwtDialSimpleNeedle( Style, bool hasKnob = true, + const QColor &mid = Qt::gray, const QColor &base = Qt::darkGray ); + + void setWidth( double width ); + double width() const; + +protected: + virtual void drawNeedle( QPainter *, double length, + QPalette::ColorGroup ) const; + +private: + Style d_style; + bool d_hasKnob; + double d_width; +}; + +/*! + \brief A magnet needle for compass widgets + + A magnet needle points to two opposite directions indicating + north and south. + + The following colors are used: + - QPalette::Light\n + Used for pointing south + - QPalette::Dark\n + Used for pointing north + - QPalette::Base\n + Knob (ThinStyle only) + + \sa QwtDial, QwtCompass +*/ + +class QWT_EXPORT QwtCompassMagnetNeedle: public QwtDialNeedle +{ +public: + //! Style of the needle + enum Style + { + //! A needle with a triangular shape + TriangleStyle, + + //! A thin needle + ThinStyle + }; + + QwtCompassMagnetNeedle( Style = TriangleStyle, + const QColor &light = Qt::white, const QColor &dark = Qt::red ); + +protected: + virtual void drawNeedle( QPainter *, + double length, QPalette::ColorGroup ) const; + +private: + Style d_style; +}; + +/*! + \brief An indicator for the wind direction + + QwtCompassWindArrow shows the direction where the wind comes from. + + - QPalette::Light\n + Used for Style1, or the light half of Style2 + - QPalette::Dark\n + Used for the dark half of Style2 + + \sa QwtDial, QwtCompass +*/ + +class QWT_EXPORT QwtCompassWindArrow: public QwtDialNeedle +{ +public: + //! Style of the arrow + enum Style + { + //! A needle pointing to the center + Style1, + + //! A needle pointing to the center + Style2 + }; + + QwtCompassWindArrow( Style, const QColor &light = Qt::white, + const QColor &dark = Qt::gray ); + +protected: + virtual void drawNeedle( QPainter *, + double length, QPalette::ColorGroup ) const; + +private: + Style d_style; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dyngrid_layout.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dyngrid_layout.cpp new file mode 100644 index 0000000..e213116 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dyngrid_layout.cpp @@ -0,0 +1,591 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_dyngrid_layout.h" +#include "qwt_math.h" +#include +#include + +class QwtDynGridLayout::PrivateData +{ +public: + PrivateData(): + isDirty( true ) + { + } + + void updateLayoutCache(); + + mutable QList itemList; + + uint maxColumns; + uint numRows; + uint numColumns; + + Qt::Orientations expanding; + + bool isDirty; + QVector itemSizeHints; +}; + +void QwtDynGridLayout::PrivateData::updateLayoutCache() +{ + itemSizeHints.resize( itemList.count() ); + + int index = 0; + + for ( QList::iterator it = itemList.begin(); + it != itemList.end(); ++it, index++ ) + { + itemSizeHints[ index ] = ( *it )->sizeHint(); + } + + isDirty = false; +} + +/*! + \param parent Parent widget + \param margin Margin + \param spacing Spacing +*/ + +QwtDynGridLayout::QwtDynGridLayout( QWidget *parent, + int margin, int spacing ): + QLayout( parent ) +{ + init(); + + setSpacing( spacing ); + setMargin( margin ); +} + +/*! + \param spacing Spacing +*/ + +QwtDynGridLayout::QwtDynGridLayout( int spacing ) +{ + init(); + setSpacing( spacing ); +} + +/*! + Initialize the layout with default values. +*/ +void QwtDynGridLayout::init() +{ + d_data = new QwtDynGridLayout::PrivateData; + d_data->maxColumns = d_data->numRows = d_data->numColumns = 0; + d_data->expanding = 0; +} + +//! Destructor + +QwtDynGridLayout::~QwtDynGridLayout() +{ + for ( int i = 0; i < d_data->itemList.size(); i++ ) + delete d_data->itemList[i]; + + delete d_data; +} + +//! Invalidate all internal caches +void QwtDynGridLayout::invalidate() +{ + d_data->isDirty = true; + QLayout::invalidate(); +} + +/*! + Limit the number of columns. + \param maxColumns upper limit, 0 means unlimited + \sa maxColumns() +*/ +void QwtDynGridLayout::setMaxColumns( uint maxColumns ) +{ + d_data->maxColumns = maxColumns; +} + +/*! + \brief Return the upper limit for the number of columns. + + 0 means unlimited, what is the default. + + \return Upper limit for the number of columns + \sa setMaxColumns() +*/ +uint QwtDynGridLayout::maxColumns() const +{ + return d_data->maxColumns; +} + +/*! + \brief Add an item to the next free position. + \param item Layout item + */ +void QwtDynGridLayout::addItem( QLayoutItem *item ) +{ + d_data->itemList.append( item ); + invalidate(); +} + +/*! + \return true if this layout is empty. +*/ +bool QwtDynGridLayout::isEmpty() const +{ + return d_data->itemList.isEmpty(); +} + +/*! + \return number of layout items +*/ +uint QwtDynGridLayout::itemCount() const +{ + return d_data->itemList.count(); +} + +/*! + Find the item at a specific index + + \param index Index + \return Item at a specific index + \sa takeAt() +*/ +QLayoutItem *QwtDynGridLayout::itemAt( int index ) const +{ + if ( index < 0 || index >= d_data->itemList.count() ) + return NULL; + + return d_data->itemList.at( index ); +} + +/*! + Find the item at a specific index and remove it from the layout + + \param index Index + \return Layout item, removed from the layout + \sa itemAt() +*/ +QLayoutItem *QwtDynGridLayout::takeAt( int index ) +{ + if ( index < 0 || index >= d_data->itemList.count() ) + return NULL; + + d_data->isDirty = true; + return d_data->itemList.takeAt( index ); +} + +//! \return Number of items in the layout +int QwtDynGridLayout::count() const +{ + return d_data->itemList.count(); +} + +/*! + Set whether this layout can make use of more space than sizeHint(). + A value of Qt::Vertical or Qt::Horizontal means that it wants to grow in only + one dimension, while Qt::Vertical | Qt::Horizontal means that it wants + to grow in both dimensions. The default value is 0. + + \param expanding Or'd orientations + \sa expandingDirections() +*/ +void QwtDynGridLayout::setExpandingDirections( Qt::Orientations expanding ) +{ + d_data->expanding = expanding; +} + +/*! + \brief Returns whether this layout can make use of more space than sizeHint(). + + A value of Qt::Vertical or Qt::Horizontal means that it wants to grow in only + one dimension, while Qt::Vertical | Qt::Horizontal means that it wants + to grow in both dimensions. + + \return Orientations, where the layout expands + \sa setExpandingDirections() +*/ +Qt::Orientations QwtDynGridLayout::expandingDirections() const +{ + return d_data->expanding; +} + +/*! + Reorganizes columns and rows and resizes managed items within + a rectangle. + + \param rect Layout geometry +*/ +void QwtDynGridLayout::setGeometry( const QRect &rect ) +{ + QLayout::setGeometry( rect ); + + if ( isEmpty() ) + return; + + d_data->numColumns = columnsForWidth( rect.width() ); + d_data->numRows = itemCount() / d_data->numColumns; + if ( itemCount() % d_data->numColumns ) + d_data->numRows++; + + QList itemGeometries = layoutItems( rect, d_data->numColumns ); + + int index = 0; + for ( QList::iterator it = d_data->itemList.begin(); + it != d_data->itemList.end(); ++it ) + { + ( *it )->setGeometry( itemGeometries[index] ); + index++; + } +} + +/*! + \brief Calculate the number of columns for a given width. + + The calculation tries to use as many columns as possible + ( limited by maxColumns() ) + + \param width Available width for all columns + \return Number of columns for a given width + + \sa maxColumns(), setMaxColumns() +*/ +uint QwtDynGridLayout::columnsForWidth( int width ) const +{ + if ( isEmpty() ) + return 0; + + uint maxColumns = itemCount(); + if ( d_data->maxColumns > 0 ) + maxColumns = qMin( d_data->maxColumns, maxColumns ); + + if ( maxRowWidth( maxColumns ) <= width ) + return maxColumns; + + for ( uint numColumns = 2; numColumns <= maxColumns; numColumns++ ) + { + const int rowWidth = maxRowWidth( numColumns ); + if ( rowWidth > width ) + return numColumns - 1; + } + + return 1; // At least 1 column +} + +/*! + Calculate the width of a layout for a given number of + columns. + + \param numColumns Given number of columns + \param itemWidth Array of the width hints for all items +*/ +int QwtDynGridLayout::maxRowWidth( int numColumns ) const +{ + int col; + + QVector colWidth( numColumns ); + for ( col = 0; col < numColumns; col++ ) + colWidth[col] = 0; + + if ( d_data->isDirty ) + d_data->updateLayoutCache(); + + for ( int index = 0; + index < d_data->itemSizeHints.count(); index++ ) + { + col = index % numColumns; + colWidth[col] = qMax( colWidth[col], + d_data->itemSizeHints[int( index )].width() ); + } + + int rowWidth = 2 * margin() + ( numColumns - 1 ) * spacing(); + for ( col = 0; col < numColumns; col++ ) + rowWidth += colWidth[col]; + + return rowWidth; +} + +/*! + \return the maximum width of all layout items +*/ +int QwtDynGridLayout::maxItemWidth() const +{ + if ( isEmpty() ) + return 0; + + if ( d_data->isDirty ) + d_data->updateLayoutCache(); + + int w = 0; + for ( int i = 0; i < d_data->itemSizeHints.count(); i++ ) + { + const int itemW = d_data->itemSizeHints[i].width(); + if ( itemW > w ) + w = itemW; + } + + return w; +} + +/*! + Calculate the geometries of the layout items for a layout + with numColumns columns and a given rectangle. + + \param rect Rect where to place the items + \param numColumns Number of columns + \return item geometries +*/ + +QList QwtDynGridLayout::layoutItems( const QRect &rect, + uint numColumns ) const +{ + QList itemGeometries; + if ( numColumns == 0 || isEmpty() ) + return itemGeometries; + + uint numRows = itemCount() / numColumns; + if ( numColumns % itemCount() ) + numRows++; + + if ( numRows == 0 ) + return itemGeometries; + + QVector rowHeight( numRows ); + QVector colWidth( numColumns ); + + layoutGrid( numColumns, rowHeight, colWidth ); + + bool expandH, expandV; + expandH = expandingDirections() & Qt::Horizontal; + expandV = expandingDirections() & Qt::Vertical; + + if ( expandH || expandV ) + stretchGrid( rect, numColumns, rowHeight, colWidth ); + + const int maxColumns = d_data->maxColumns; + d_data->maxColumns = numColumns; + const QRect alignedRect = alignmentRect( rect ); + d_data->maxColumns = maxColumns; + + const int xOffset = expandH ? 0 : alignedRect.x(); + const int yOffset = expandV ? 0 : alignedRect.y(); + + QVector colX( numColumns ); + QVector rowY( numRows ); + + const int xySpace = spacing(); + + rowY[0] = yOffset + margin(); + for ( uint r = 1; r < numRows; r++ ) + rowY[r] = rowY[r-1] + rowHeight[r-1] + xySpace; + + colX[0] = xOffset + margin(); + for ( uint c = 1; c < numColumns; c++ ) + colX[c] = colX[c-1] + colWidth[c-1] + xySpace; + + const int itemCount = d_data->itemList.size(); + for ( int i = 0; i < itemCount; i++ ) + { + const int row = i / numColumns; + const int col = i % numColumns; + + QRect itemGeometry( colX[col], rowY[row], + colWidth[col], rowHeight[row] ); + itemGeometries.append( itemGeometry ); + } + + return itemGeometries; +} + + +/*! + Calculate the dimensions for the columns and rows for a grid + of numColumns columns. + + \param numColumns Number of columns. + \param rowHeight Array where to fill in the calculated row heights. + \param colWidth Array where to fill in the calculated column widths. +*/ + +void QwtDynGridLayout::layoutGrid( uint numColumns, + QVector& rowHeight, QVector& colWidth ) const +{ + if ( numColumns <= 0 ) + return; + + if ( d_data->isDirty ) + d_data->updateLayoutCache(); + + for ( int index = 0; index < d_data->itemSizeHints.count(); index++ ) + { + const int row = index / numColumns; + const int col = index % numColumns; + + const QSize &size = d_data->itemSizeHints[int( index )]; + + rowHeight[row] = ( col == 0 ) + ? size.height() : qMax( rowHeight[row], size.height() ); + colWidth[col] = ( row == 0 ) + ? size.width() : qMax( colWidth[col], size.width() ); + } +} + +/*! + \return true: QwtDynGridLayout implements heightForWidth(). + \sa heightForWidth() +*/ +bool QwtDynGridLayout::hasHeightForWidth() const +{ + return true; +} + +/*! + \return The preferred height for this layout, given a width. + \sa hasHeightForWidth() +*/ +int QwtDynGridLayout::heightForWidth( int width ) const +{ + if ( isEmpty() ) + return 0; + + const uint numColumns = columnsForWidth( width ); + uint numRows = itemCount() / numColumns; + if ( itemCount() % numColumns ) + numRows++; + + QVector rowHeight( numRows ); + QVector colWidth( numColumns ); + + layoutGrid( numColumns, rowHeight, colWidth ); + + int h = 2 * margin() + ( numRows - 1 ) * spacing(); + for ( uint row = 0; row < numRows; row++ ) + h += rowHeight[row]; + + return h; +} + +/*! + Stretch columns in case of expanding() & QSizePolicy::Horizontal and + rows in case of expanding() & QSizePolicy::Vertical to fill the entire + rect. Rows and columns are stretched with the same factor. + + \param rect Bounding rectangle + \param numColumns Number of columns + \param rowHeight Array to be filled with the calculated row heights + \param colWidth Array to be filled with the calculated column widths + + \sa setExpanding(), expanding() +*/ +void QwtDynGridLayout::stretchGrid( const QRect &rect, + uint numColumns, QVector& rowHeight, QVector& colWidth ) const +{ + if ( numColumns == 0 || isEmpty() ) + return; + + bool expandH, expandV; + expandH = expandingDirections() & Qt::Horizontal; + expandV = expandingDirections() & Qt::Vertical; + + if ( expandH ) + { + int xDelta = rect.width() - 2 * margin() - ( numColumns - 1 ) * spacing(); + for ( uint col = 0; col < numColumns; col++ ) + xDelta -= colWidth[col]; + + if ( xDelta > 0 ) + { + for ( uint col = 0; col < numColumns; col++ ) + { + const int space = xDelta / ( numColumns - col ); + colWidth[col] += space; + xDelta -= space; + } + } + } + + if ( expandV ) + { + uint numRows = itemCount() / numColumns; + if ( itemCount() % numColumns ) + numRows++; + + int yDelta = rect.height() - 2 * margin() - ( numRows - 1 ) * spacing(); + for ( uint row = 0; row < numRows; row++ ) + yDelta -= rowHeight[row]; + + if ( yDelta > 0 ) + { + for ( uint row = 0; row < numRows; row++ ) + { + const int space = yDelta / ( numRows - row ); + rowHeight[row] += space; + yDelta -= space; + } + } + } +} + +/*! + Return the size hint. If maxColumns() > 0 it is the size for + a grid with maxColumns() columns, otherwise it is the size for + a grid with only one row. + + \return Size hint + \sa maxColumns(), setMaxColumns() +*/ +QSize QwtDynGridLayout::sizeHint() const +{ + if ( isEmpty() ) + return QSize(); + + uint numColumns = itemCount(); + if ( d_data->maxColumns > 0 ) + numColumns = qMin( d_data->maxColumns, numColumns ); + + uint numRows = itemCount() / numColumns; + if ( itemCount() % numColumns ) + numRows++; + + QVector rowHeight( numRows ); + QVector colWidth( numColumns ); + + layoutGrid( numColumns, rowHeight, colWidth ); + + int h = 2 * margin() + ( numRows - 1 ) * spacing(); + for ( uint row = 0; row < numRows; row++ ) + h += rowHeight[row]; + + int w = 2 * margin() + ( numColumns - 1 ) * spacing(); + for ( uint col = 0; col < numColumns; col++ ) + w += colWidth[col]; + + return QSize( w, h ); +} + +/*! + \return Number of rows of the current layout. + \sa numColumns() + \warning The number of rows might change whenever the geometry changes +*/ +uint QwtDynGridLayout::numRows() const +{ + return d_data->numRows; +} + +/*! + \return Number of columns of the current layout. + \sa numRows() + \warning The number of columns might change whenever the geometry changes +*/ +uint QwtDynGridLayout::numColumns() const +{ + return d_data->numColumns; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dyngrid_layout.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dyngrid_layout.h new file mode 100644 index 0000000..9ea0bc2 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_dyngrid_layout.h @@ -0,0 +1,83 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_DYNGRID_LAYOUT_H +#define QWT_DYNGRID_LAYOUT_H + +#include "qwt_global.h" +#include +#include +#include + +/*! + \brief The QwtDynGridLayout class lays out widgets in a grid, + adjusting the number of columns and rows to the current size. + + QwtDynGridLayout takes the space it gets, divides it up into rows and + columns, and puts each of the widgets it manages into the correct cell(s). + It lays out as many number of columns as possible (limited by maxColumns()). +*/ + +class QWT_EXPORT QwtDynGridLayout : public QLayout +{ + Q_OBJECT +public: + explicit QwtDynGridLayout( QWidget *, int margin = 0, int space = -1 ); + explicit QwtDynGridLayout( int space = -1 ); + + virtual ~QwtDynGridLayout(); + + virtual void invalidate(); + + void setMaxColumns( uint maxCols ); + uint maxColumns() const; + + uint numRows () const; + uint numColumns () const; + + virtual void addItem( QLayoutItem * ); + + virtual QLayoutItem *itemAt( int index ) const; + virtual QLayoutItem *takeAt( int index ); + virtual int count() const; + + void setExpandingDirections( Qt::Orientations ); + virtual Qt::Orientations expandingDirections() const; + QList layoutItems( const QRect &, uint numCols ) const; + + virtual int maxItemWidth() const; + + virtual void setGeometry( const QRect &rect ); + + virtual bool hasHeightForWidth() const; + virtual int heightForWidth( int ) const; + + virtual QSize sizeHint() const; + + virtual bool isEmpty() const; + uint itemCount() const; + + virtual uint columnsForWidth( int width ) const; + +protected: + + void layoutGrid( uint numCols, + QVector& rowHeight, QVector& colWidth ) const; + void stretchGrid( const QRect &rect, uint numCols, + QVector& rowHeight, QVector& colWidth ) const; + +private: + void init(); + int maxRowWidth( int numCols ) const; + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_event_pattern.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_event_pattern.cpp new file mode 100644 index 0000000..e4248a6 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_event_pattern.cpp @@ -0,0 +1,265 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_event_pattern.h" +#include + +/*! + Constructor + + \sa MousePatternCode, KeyPatternCode +*/ + +QwtEventPattern::QwtEventPattern(): + d_mousePattern( MousePatternCount ), + d_keyPattern( KeyPatternCount ) +{ + initKeyPattern(); + initMousePattern( 3 ); +} + +//! Destructor +QwtEventPattern::~QwtEventPattern() +{ +} + +/*! + Set default mouse patterns, depending on the number of mouse buttons + + \param numButtons Number of mouse buttons ( <= 3 ) + \sa MousePatternCode +*/ +void QwtEventPattern::initMousePattern( int numButtons ) +{ + d_mousePattern.resize( MousePatternCount ); + + switch ( numButtons ) + { + case 1: + { + setMousePattern( MouseSelect1, Qt::LeftButton ); + setMousePattern( MouseSelect2, Qt::LeftButton, Qt::ControlModifier ); + setMousePattern( MouseSelect3, Qt::LeftButton, Qt::AltModifier ); + break; + } + case 2: + { + setMousePattern( MouseSelect1, Qt::LeftButton ); + setMousePattern( MouseSelect2, Qt::RightButton ); + setMousePattern( MouseSelect3, Qt::LeftButton, Qt::AltModifier ); + break; + } + default: + { + setMousePattern( MouseSelect1, Qt::LeftButton ); + setMousePattern( MouseSelect2, Qt::RightButton ); + setMousePattern( MouseSelect3, Qt::MidButton ); + } + } + + setMousePattern( MouseSelect4, d_mousePattern[MouseSelect1].button, + d_mousePattern[MouseSelect1].modifiers | Qt::ShiftModifier ); + + setMousePattern( MouseSelect5, d_mousePattern[MouseSelect2].button, + d_mousePattern[MouseSelect2].modifiers | Qt::ShiftModifier ); + + setMousePattern( MouseSelect6, d_mousePattern[MouseSelect3].button, + d_mousePattern[MouseSelect3].modifiers | Qt::ShiftModifier ); +} + +/*! + Set default mouse patterns. + + \sa KeyPatternCode +*/ +void QwtEventPattern::initKeyPattern() +{ + d_keyPattern.resize( KeyPatternCount ); + + setKeyPattern( KeySelect1, Qt::Key_Return ); + setKeyPattern( KeySelect2, Qt::Key_Space ); + setKeyPattern( KeyAbort, Qt::Key_Escape ); + + setKeyPattern( KeyLeft, Qt::Key_Left ); + setKeyPattern( KeyRight, Qt::Key_Right ); + setKeyPattern( KeyUp, Qt::Key_Up ); + setKeyPattern( KeyDown, Qt::Key_Down ); + + setKeyPattern( KeyRedo, Qt::Key_Plus ); + setKeyPattern( KeyUndo, Qt::Key_Minus ); + setKeyPattern( KeyHome, Qt::Key_Escape ); +} + +/*! + Change one mouse pattern + + \param pattern Index of the pattern + \param button Button + \param modifiers Keyboard modifiers + + \sa QMouseEvent +*/ +void QwtEventPattern::setMousePattern( MousePatternCode pattern, + Qt::MouseButton button, Qt::KeyboardModifiers modifiers ) +{ + if ( pattern >= 0 && pattern < MousePatternCount ) + { + d_mousePattern[ pattern ].button = button; + d_mousePattern[ pattern ].modifiers = modifiers; + } +} + +/*! + Change one key pattern + + \param pattern Index of the pattern + \param key Key + \param modifiers Keyboard modifiers + + \sa QKeyEvent +*/ +void QwtEventPattern::setKeyPattern( KeyPatternCode pattern, + int key, Qt::KeyboardModifiers modifiers ) +{ + if ( pattern >= 0 && pattern < KeyPatternCount ) + { + d_keyPattern[ pattern ].key = key; + d_keyPattern[ pattern ].modifiers = modifiers; + } +} + +//! Change the mouse event patterns +void QwtEventPattern::setMousePattern( const QVector &pattern ) +{ + d_mousePattern = pattern; +} + +//! Change the key event patterns +void QwtEventPattern::setKeyPattern( const QVector &pattern ) +{ + d_keyPattern = pattern; +} + +//! \return Mouse pattern +const QVector & +QwtEventPattern::mousePattern() const +{ + return d_mousePattern; +} + +//! \return Key pattern +const QVector & +QwtEventPattern::keyPattern() const +{ + return d_keyPattern; +} + +//! \return Mouse pattern +QVector &QwtEventPattern::mousePattern() +{ + return d_mousePattern; +} + +//! \return Key pattern +QVector &QwtEventPattern::keyPattern() +{ + return d_keyPattern; +} + +/*! + \brief Compare a mouse event with an event pattern. + + A mouse event matches the pattern when both have the same button + value and in the state value the same key flags(Qt::KeyButtonMask) + are set. + + \param code Index of the event pattern + \param event Mouse event + \return true if matches + + \sa keyMatch() +*/ +bool QwtEventPattern::mouseMatch( MousePatternCode code, + const QMouseEvent *event ) const +{ + if ( code >= 0 && code < MousePatternCount ) + return mouseMatch( d_mousePattern[ code ], event ); + + return false; +} + +/*! + \brief Compare a mouse event with an event pattern. + + A mouse event matches the pattern when both have the same button + value and in the state value the same key flags(Qt::KeyButtonMask) + are set. + + \param pattern Mouse event pattern + \param event Mouse event + \return true if matches + + \sa keyMatch() +*/ + +bool QwtEventPattern::mouseMatch( const MousePattern &pattern, + const QMouseEvent *event ) const +{ + if ( event == NULL ) + return false; + + const MousePattern mousePattern( event->button(), event->modifiers() ); + return mousePattern == pattern; +} + +/*! + \brief Compare a key event with an event pattern. + + A key event matches the pattern when both have the same key + value and in the state value the same key flags (Qt::KeyButtonMask) + are set. + + \param code Index of the event pattern + \param event Key event + \return true if matches + + \sa mouseMatch() +*/ +bool QwtEventPattern::keyMatch( KeyPatternCode code, + const QKeyEvent *event ) const +{ + if ( code >= 0 && code < KeyPatternCount ) + return keyMatch( d_keyPattern[ code ], event ); + + return false; +} + +/*! + \brief Compare a key event with an event pattern. + + A key event matches the pattern when both have the same key + value and in the state value the same key flags (Qt::KeyButtonMask) + are set. + + \param pattern Key event pattern + \param event Key event + \return true if matches + + \sa mouseMatch() +*/ + +bool QwtEventPattern::keyMatch( + const KeyPattern &pattern, const QKeyEvent *event ) const +{ + if ( event == NULL ) + return false; + + const KeyPattern keyPattern( event->key(), event->modifiers() ); + return keyPattern == pattern; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_event_pattern.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_event_pattern.h new file mode 100644 index 0000000..8955045 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_event_pattern.h @@ -0,0 +1,240 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_EVENT_PATTERN +#define QWT_EVENT_PATTERN 1 + +#include "qwt_global.h" +#include +#include + +class QMouseEvent; +class QKeyEvent; + +/*! + \brief A collection of event patterns + + QwtEventPattern introduces an level of indirection for mouse and + keyboard inputs. Those are represented by symbolic names, so + the application code can be configured by individual mappings. + + \sa QwtPicker, QwtPickerMachine, QwtPlotZoomer +*/ +class QWT_EXPORT QwtEventPattern +{ +public: + /*! + \brief Symbolic mouse input codes + + QwtEventPattern implements 3 different settings for + mice with 1, 2, or 3 buttons that can be activated + using initMousePattern(). The default setting is for + 3 button mice. + + Individual settings can be configured using setMousePattern(). + + \sa initMousePattern(), setMousePattern(), setKeyPattern() + */ + enum MousePatternCode + { + /*! + The default setting for 1, 2 and 3 button mice is: + + - Qt::LeftButton + - Qt::LeftButton + - Qt::LeftButton + */ + MouseSelect1, + + /*! + The default setting for 1, 2 and 3 button mice is: + + - Qt::LeftButton + Qt::ControlModifier + - Qt::RightButton + - Qt::RightButton + */ + MouseSelect2, + + /*! + The default setting for 1, 2 and 3 button mice is: + + - Qt::LeftButton + Qt::AltModifier + - Qt::LeftButton + Qt::AltModifier + - Qt::MidButton + */ + MouseSelect3, + + /*! + The default setting for 1, 2 and 3 button mice is: + + - Qt::LeftButton + Qt::ShiftModifier + - Qt::LeftButton + Qt::ShiftModifier + - Qt::LeftButton + Qt::ShiftModifier + */ + MouseSelect4, + + /*! + The default setting for 1, 2 and 3 button mice is: + + - Qt::LeftButton + Qt::ControlButton | Qt::ShiftModifier + - Qt::RightButton + Qt::ShiftModifier + - Qt::RightButton + Qt::ShiftModifier + */ + MouseSelect5, + + /*! + The default setting for 1, 2 and 3 button mice is: + + - Qt::LeftButton + Qt::AltModifier + Qt::ShiftModifier + - Qt::LeftButton + Qt::AltModifier | Qt::ShiftModifier + - Qt::MidButton + Qt::ShiftModifier + */ + MouseSelect6, + + //! Number of mouse patterns + MousePatternCount + }; + + /*! + \brief Symbolic keyboard input codes + + Individual settings can be configured using setKeyPattern() + + \sa setKeyPattern(), setMousePattern() + */ + enum KeyPatternCode + { + //! Qt::Key_Return + KeySelect1, + + //! Qt::Key_Space + KeySelect2, + + //! Qt::Key_Escape + KeyAbort, + + //! Qt::Key_Left + KeyLeft, + + //! Qt::Key_Right + KeyRight, + + //! Qt::Key_Up + KeyUp, + + //! Qt::Key_Down + KeyDown, + + //! Qt::Key_Plus + KeyRedo, + + //! Qt::Key_Minus + KeyUndo, + + //! Qt::Key_Escape + KeyHome, + + //! Number of key patterns + KeyPatternCount + }; + + //! A pattern for mouse events + class MousePattern + { + public: + //! Constructor + MousePattern( Qt::MouseButton btn = Qt::NoButton, + Qt::KeyboardModifiers modifierCodes = Qt::NoModifier ): + button( btn ), + modifiers( modifierCodes ) + { + } + + //! Button + Qt::MouseButton button; + + //! Keyboard modifier + Qt::KeyboardModifiers modifiers; + }; + + //! A pattern for key events + class KeyPattern + { + public: + //! Constructor + KeyPattern( int keyCode = Qt::Key_unknown, + Qt::KeyboardModifiers modifierCodes = Qt::NoModifier ): + key( keyCode ), + modifiers( modifierCodes ) + { + } + + //! Key code + int key; + + //! Modifiers + Qt::KeyboardModifiers modifiers; + }; + + QwtEventPattern(); + virtual ~QwtEventPattern(); + + void initMousePattern( int numButtons ); + void initKeyPattern(); + + void setMousePattern( MousePatternCode, Qt::MouseButton button, + Qt::KeyboardModifiers = Qt::NoModifier ); + + void setKeyPattern( KeyPatternCode, int keyCode, + Qt::KeyboardModifiers modifierCodes = Qt::NoModifier ); + + void setMousePattern( const QVector & ); + void setKeyPattern( const QVector & ); + + const QVector &mousePattern() const; + const QVector &keyPattern() const; + + QVector &mousePattern(); + QVector &keyPattern(); + + bool mouseMatch( MousePatternCode, const QMouseEvent * ) const; + bool keyMatch( KeyPatternCode, const QKeyEvent * ) const; + +protected: + virtual bool mouseMatch( const MousePattern &, const QMouseEvent * ) const; + virtual bool keyMatch( const KeyPattern &, const QKeyEvent * ) const; + +private: + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + QVector d_mousePattern; + QVector d_keyPattern; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +}; + +//! Compare operator +inline bool operator==( QwtEventPattern::MousePattern b1, + QwtEventPattern::MousePattern b2 ) +{ + return b1.button == b2.button && b1.modifiers == b2.modifiers; +} + +//! Compare operator +inline bool operator==( QwtEventPattern::KeyPattern b1, + QwtEventPattern::KeyPattern b2 ) +{ + return b1.key == b2.key && b1.modifiers == b2.modifiers; +} + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_global.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_global.h new file mode 100644 index 0000000..3ad83e4 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_global.h @@ -0,0 +1,41 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_GLOBAL_H +#define QWT_GLOBAL_H + +#include + +// QWT_VERSION is (major << 16) + (minor << 8) + patch. + +#define QWT_VERSION 0x060103 +#define QWT_VERSION_STR "6.1.3" + +#if defined(_MSC_VER) /* MSVC Compiler */ +/* template-class specialization 'identifier' is already instantiated */ +#pragma warning(disable: 4660) +/* inherits via dominance */ +#pragma warning(disable: 4250) +#endif // _MSC_VER + +#ifdef QWT_DLL + +#if defined(QWT_MAKEDLL) // create a Qwt DLL library +#define QWT_EXPORT Q_DECL_EXPORT +#else // use a Qwt DLL library +#define QWT_EXPORT Q_DECL_IMPORT +#endif + +#endif // QWT_DLL + +#ifndef QWT_EXPORT +#define QWT_EXPORT +#endif + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_graphic.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_graphic.cpp new file mode 100644 index 0000000..70aa86e --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_graphic.cpp @@ -0,0 +1,1009 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_graphic.h" +#include "qwt_painter_command.h" +#include +#include +#include +#include +#include +#include +#include + +static bool qwtHasScalablePen( const QPainter *painter ) +{ + const QPen pen = painter->pen(); + + bool scalablePen = false; + + if ( pen.style() != Qt::NoPen && pen.brush().style() != Qt::NoBrush ) + { + scalablePen = !pen.isCosmetic(); + if ( !scalablePen && pen.widthF() == 0.0 ) + { + const QPainter::RenderHints hints = painter->renderHints(); + if ( hints.testFlag( QPainter::NonCosmeticDefaultPen ) ) + scalablePen = true; + } + } + + return scalablePen; +} + +static QRectF qwtStrokedPathRect( + const QPainter *painter, const QPainterPath &path ) +{ + QPainterPathStroker stroker; + stroker.setWidth( painter->pen().widthF() ); + stroker.setCapStyle( painter->pen().capStyle() ); + stroker.setJoinStyle( painter->pen().joinStyle() ); + stroker.setMiterLimit( painter->pen().miterLimit() ); + + QRectF rect; + if ( qwtHasScalablePen( painter ) ) + { + QPainterPath stroke = stroker.createStroke(path); + rect = painter->transform().map(stroke).boundingRect(); + } + else + { + QPainterPath mappedPath = painter->transform().map(path); + mappedPath = stroker.createStroke( mappedPath ); + + rect = mappedPath.boundingRect(); + } + + return rect; +} + +static inline void qwtExecCommand( + QPainter *painter, const QwtPainterCommand &cmd, + QwtGraphic::RenderHints renderHints, + const QTransform &transform, + const QTransform *initialTransform ) +{ + switch( cmd.type() ) + { + case QwtPainterCommand::Path: + { + bool doMap = false; + + if ( renderHints.testFlag( QwtGraphic::RenderPensUnscaled ) + && painter->transform().isScaling() ) + { + bool isCosmetic = painter->pen().isCosmetic(); + if ( isCosmetic && painter->pen().widthF() == 0.0 ) + { + QPainter::RenderHints hints = painter->renderHints(); + if ( hints.testFlag( QPainter::NonCosmeticDefaultPen ) ) + isCosmetic = false; + } + + doMap = !isCosmetic; + } + + if ( doMap ) + { + const QTransform tr = painter->transform(); + + painter->resetTransform(); + + QPainterPath path = tr.map( *cmd.path() ); + if ( initialTransform ) + { + painter->setTransform( *initialTransform ); + path = initialTransform->inverted().map( path ); + } + + painter->drawPath( path ); + + painter->setTransform( tr ); + } + else + { + painter->drawPath( *cmd.path() ); + } + break; + } + case QwtPainterCommand::Pixmap: + { + const QwtPainterCommand::PixmapData *data = cmd.pixmapData(); + painter->drawPixmap( data->rect, data->pixmap, data->subRect ); + break; + } + case QwtPainterCommand::Image: + { + const QwtPainterCommand::ImageData *data = cmd.imageData(); + painter->drawImage( data->rect, data->image, + data->subRect, data->flags ); + break; + } + case QwtPainterCommand::State: + { + const QwtPainterCommand::StateData *data = cmd.stateData(); + + if ( data->flags & QPaintEngine::DirtyPen ) + painter->setPen( data->pen ); + + if ( data->flags & QPaintEngine::DirtyBrush ) + painter->setBrush( data->brush ); + + if ( data->flags & QPaintEngine::DirtyBrushOrigin ) + painter->setBrushOrigin( data->brushOrigin ); + + if ( data->flags & QPaintEngine::DirtyFont ) + painter->setFont( data->font ); + + if ( data->flags & QPaintEngine::DirtyBackground ) + { + painter->setBackgroundMode( data->backgroundMode ); + painter->setBackground( data->backgroundBrush ); + } + + if ( data->flags & QPaintEngine::DirtyTransform ) + { + painter->setTransform( data->transform * transform ); + } + + if ( data->flags & QPaintEngine::DirtyClipEnabled ) + painter->setClipping( data->isClipEnabled ); + + if ( data->flags & QPaintEngine::DirtyClipRegion) + { + painter->setClipRegion( data->clipRegion, + data->clipOperation ); + } + + if ( data->flags & QPaintEngine::DirtyClipPath ) + { + painter->setClipPath( data->clipPath, data->clipOperation ); + } + + if ( data->flags & QPaintEngine::DirtyHints) + { + const QPainter::RenderHints hints = data->renderHints; + + painter->setRenderHint( QPainter::Antialiasing, + hints.testFlag( QPainter::Antialiasing ) ); + + painter->setRenderHint( QPainter::TextAntialiasing, + hints.testFlag( QPainter::TextAntialiasing ) ); + + painter->setRenderHint( QPainter::SmoothPixmapTransform, + hints.testFlag( QPainter::SmoothPixmapTransform ) ); + + painter->setRenderHint( QPainter::HighQualityAntialiasing, + hints.testFlag( QPainter::HighQualityAntialiasing ) ); + + painter->setRenderHint( QPainter::NonCosmeticDefaultPen, + hints.testFlag( QPainter::NonCosmeticDefaultPen ) ); + } + + if ( data->flags & QPaintEngine::DirtyCompositionMode) + painter->setCompositionMode( data->compositionMode ); + + if ( data->flags & QPaintEngine::DirtyOpacity) + painter->setOpacity( data->opacity ); + + break; + } + default: + break; + } + +} + +class QwtGraphic::PathInfo +{ +public: + PathInfo(): + d_scalablePen( false ) + { + // QVector needs a default constructor + } + + PathInfo( const QRectF &pointRect, + const QRectF &boundingRect, bool scalablePen ): + d_pointRect( pointRect ), + d_boundingRect( boundingRect ), + d_scalablePen( scalablePen ) + { + } + + inline QRectF scaledBoundingRect( double sx, double sy, + bool scalePens ) const + { + if ( sx == 1.0 && sy == 1.0 ) + return d_boundingRect; + + QTransform transform; + transform.scale( sx, sy ); + + QRectF rect; + if ( scalePens && d_scalablePen ) + { + rect = transform.mapRect( d_boundingRect ); + } + else + { + rect = transform.mapRect( d_pointRect ); + + const double l = qAbs( d_pointRect.left() - d_boundingRect.left() ); + const double r = qAbs( d_pointRect.right() - d_boundingRect.right() ); + const double t = qAbs( d_pointRect.top() - d_boundingRect.top() ); + const double b = qAbs( d_pointRect.bottom() - d_boundingRect.bottom() ); + + rect.adjust( -l, -t, r, b ); + } + + return rect; + } + + inline double scaleFactorX( const QRectF& pathRect, + const QRectF &targetRect, bool scalePens ) const + { + if ( pathRect.width() <= 0.0 ) + return 0.0; + + const QPointF p0 = d_pointRect.center(); + + const double l = qAbs( pathRect.left() - p0.x() ); + const double r = qAbs( pathRect.right() - p0.x() ); + + const double w = 2.0 * qMin( l, r ) + * targetRect.width() / pathRect.width(); + + double sx; + if ( scalePens && d_scalablePen ) + { + sx = w / d_boundingRect.width(); + } + else + { + const double pw = qMax( + qAbs( d_boundingRect.left() - d_pointRect.left() ), + qAbs( d_boundingRect.right() - d_pointRect.right() ) ); + + sx = ( w - 2 * pw ) / d_pointRect.width(); + } + + return sx; + } + + inline double scaleFactorY( const QRectF& pathRect, + const QRectF &targetRect, bool scalePens ) const + { + if ( pathRect.height() <= 0.0 ) + return 0.0; + + const QPointF p0 = d_pointRect.center(); + + const double t = qAbs( pathRect.top() - p0.y() ); + const double b = qAbs( pathRect.bottom() - p0.y() ); + + const double h = 2.0 * qMin( t, b ) + * targetRect.height() / pathRect.height(); + + double sy; + if ( scalePens && d_scalablePen ) + { + sy = h / d_boundingRect.height(); + } + else + { + const double pw = + qMax( qAbs( d_boundingRect.top() - d_pointRect.top() ), + qAbs( d_boundingRect.bottom() - d_pointRect.bottom() ) ); + + sy = ( h - 2 * pw ) / d_pointRect.height(); + } + + return sy; + } + +private: + QRectF d_pointRect; + QRectF d_boundingRect; + bool d_scalablePen; +}; + +class QwtGraphic::PrivateData +{ +public: + PrivateData(): + boundingRect( 0.0, 0.0, -1.0, -1.0 ), + pointRect( 0.0, 0.0, -1.0, -1.0 ), + initialTransform( NULL ) + { + } + + QSizeF defaultSize; + QVector commands; + QVector pathInfos; + + QRectF boundingRect; + QRectF pointRect; + + QwtGraphic::RenderHints renderHints; + QTransform *initialTransform; +}; + +/*! + \brief Constructor + + Initializes a null graphic + \sa isNull() + */ +QwtGraphic::QwtGraphic(): + QwtNullPaintDevice() +{ + setMode( QwtNullPaintDevice::PathMode ); + d_data = new PrivateData; +} + +/*! + \brief Copy constructor + + \param other Source + \sa operator=() + */ +QwtGraphic::QwtGraphic( const QwtGraphic &other ): + QwtNullPaintDevice() +{ + setMode( other.mode() ); + d_data = new PrivateData( *other.d_data ); +} + +//! Destructor +QwtGraphic::~QwtGraphic() +{ + delete d_data; +} + +/*! + \brief Assignment operator + + \param other Source + \return A reference of this object + */ +QwtGraphic& QwtGraphic::operator=(const QwtGraphic &other) +{ + setMode( other.mode() ); + *d_data = *other.d_data; + + return *this; +} + +/*! + \brief Clear all stored commands + \sa isNull() + */ +void QwtGraphic::reset() +{ + d_data->commands.clear(); + d_data->pathInfos.clear(); + + d_data->boundingRect = QRectF( 0.0, 0.0, -1.0, -1.0 ); + d_data->pointRect = QRectF( 0.0, 0.0, -1.0, -1.0 ); + d_data->defaultSize = QSizeF(); + +} + +/*! + \return True, when no painter commands have been stored + \sa isEmpty(), commands() +*/ +bool QwtGraphic::isNull() const +{ + return d_data->commands.isEmpty(); +} + +/*! + \return True, when the bounding rectangle is empty + \sa boundingRect(), isNull() +*/ +bool QwtGraphic::isEmpty() const +{ + return d_data->boundingRect.isEmpty(); +} + +/*! + Toggle an render hint + + \param hint Render hint + \param on true/false + + \sa testRenderHint(), RenderHint +*/ +void QwtGraphic::setRenderHint( RenderHint hint, bool on ) +{ + if ( on ) + d_data->renderHints |= hint; + else + d_data->renderHints &= ~hint; +} + +/*! + Test a render hint + + \param hint Render hint + \return true/false + \sa setRenderHint(), RenderHint +*/ +bool QwtGraphic::testRenderHint( RenderHint hint ) const +{ + return d_data->renderHints.testFlag( hint ); +} + +/*! + The bounding rectangle is the controlPointRect() + extended by the areas needed for rendering the outlines + with unscaled pens. + + \return Bounding rectangle of the graphic + \sa controlPointRect(), scaledBoundingRect() + */ +QRectF QwtGraphic::boundingRect() const +{ + if ( d_data->boundingRect.width() < 0 ) + return QRectF(); + + return d_data->boundingRect; +} + +/*! + The control point rectangle is the bounding rectangle + of all control points of the paths and the target + rectangles of the images/pixmaps. + + \return Control point rectangle + \sa boundingRect(), scaledBoundingRect() + */ +QRectF QwtGraphic::controlPointRect() const +{ + if ( d_data->pointRect.width() < 0 ) + return QRectF(); + + return d_data->pointRect; +} + +/*! + \brief Calculate the target rectangle for scaling the graphic + + \param sx Horizontal scaling factor + \param sy Vertical scaling factor + + \note In case of paths that are painted with a cosmetic pen + ( see QPen::isCosmetic() ) the target rectangle is different to + multiplying the bounding rectangle. + + \return Scaled bounding rectangle + \sa boundingRect(), controlPointRect() + */ +QRectF QwtGraphic::scaledBoundingRect( double sx, double sy ) const +{ + if ( sx == 1.0 && sy == 1.0 ) + return d_data->boundingRect; + + QTransform transform; + transform.scale( sx, sy ); + + QRectF rect = transform.mapRect( d_data->pointRect ); + + for ( int i = 0; i < d_data->pathInfos.size(); i++ ) + { + rect |= d_data->pathInfos[i].scaledBoundingRect( sx, sy, + !d_data->renderHints.testFlag( RenderPensUnscaled ) ); + } + + return rect; +} + +//! \return Ceiled defaultSize() +QSize QwtGraphic::sizeMetrics() const +{ + const QSizeF sz = defaultSize(); + return QSize( qCeil( sz.width() ), qCeil( sz.height() ) ); +} + +/*! + \brief Set a default size + + The default size is used in all methods rendering the graphic, + where no size is explicitly specified. Assigning an empty size + means, that the default size will be calculated from the bounding + rectangle. + + The default setting is an empty size. + + \param size Default size + + \sa defaultSize(), boundingRect() + */ +void QwtGraphic::setDefaultSize( const QSizeF &size ) +{ + const double w = qMax( qreal( 0.0 ), size.width() ); + const double h = qMax( qreal( 0.0 ), size.height() ); + + d_data->defaultSize = QSizeF( w, h ); +} + +/*! + \brief Default size + + When a non empty size has been assigned by setDefaultSize() this + size will be returned. Otherwise the default size is the size + of the bounding rectangle. + + The default size is used in all methods rendering the graphic, + where no size is explicitly specified. + + \return Default size + \sa setDefaultSize(), boundingRect() + */ +QSizeF QwtGraphic::defaultSize() const +{ + if ( !d_data->defaultSize.isEmpty() ) + return d_data->defaultSize; + + return boundingRect().size(); +} + +/*! + \brief Replay all recorded painter commands + \param painter Qt painter + */ +void QwtGraphic::render( QPainter *painter ) const +{ + if ( isNull() ) + return; + + const int numCommands = d_data->commands.size(); + const QwtPainterCommand *commands = d_data->commands.constData(); + + const QTransform transform = painter->transform(); + + painter->save(); + + for ( int i = 0; i < numCommands; i++ ) + { + qwtExecCommand( painter, commands[i], + d_data->renderHints, transform, d_data->initialTransform ); + } + + painter->restore(); +} + +/*! + \brief Replay all recorded painter commands + + The graphic is scaled to fit into the rectangle + of the given size starting at ( 0, 0 ). + + \param painter Qt painter + \param size Size for the scaled graphic + \param aspectRatioMode Mode how to scale - See Qt::AspectRatioMode + */ +void QwtGraphic::render( QPainter *painter, const QSizeF &size, + Qt::AspectRatioMode aspectRatioMode ) const +{ + const QRectF r( 0.0, 0.0, size.width(), size.height() ); + render( painter, r, aspectRatioMode ); +} + +/*! + \brief Replay all recorded painter commands + + The graphic is scaled to fit into the given rectangle + + \param painter Qt painter + \param rect Rectangle for the scaled graphic + \param aspectRatioMode Mode how to scale - See Qt::AspectRatioMode + */ +void QwtGraphic::render( QPainter *painter, const QRectF &rect, + Qt::AspectRatioMode aspectRatioMode ) const +{ + if ( isEmpty() || rect.isEmpty() ) + return; + + double sx = 1.0; + double sy = 1.0; + + if ( d_data->pointRect.width() > 0.0 ) + sx = rect.width() / d_data->pointRect.width(); + + if ( d_data->pointRect.height() > 0.0 ) + sy = rect.height() / d_data->pointRect.height(); + + const bool scalePens = + !d_data->renderHints.testFlag( RenderPensUnscaled ); + + for ( int i = 0; i < d_data->pathInfos.size(); i++ ) + { + const PathInfo info = d_data->pathInfos[i]; + + const double ssx = info.scaleFactorX( + d_data->pointRect, rect, scalePens ); + + if ( ssx > 0.0 ) + sx = qMin( sx, ssx ); + + const double ssy = info.scaleFactorY( + d_data->pointRect, rect, scalePens ); + + if ( ssy > 0.0 ) + sy = qMin( sy, ssy ); + } + + if ( aspectRatioMode == Qt::KeepAspectRatio ) + { + const double s = qMin( sx, sy ); + sx = s; + sy = s; + } + else if ( aspectRatioMode == Qt::KeepAspectRatioByExpanding ) + { + const double s = qMax( sx, sy ); + sx = s; + sy = s; + } + + QTransform tr; + tr.translate( rect.center().x() - 0.5 * sx * d_data->pointRect.width(), + rect.center().y() - 0.5 * sy * d_data->pointRect.height() ); + tr.scale( sx, sy ); + tr.translate( -d_data->pointRect.x(), -d_data->pointRect.y() ); + + const QTransform transform = painter->transform(); + if ( !scalePens && transform.isScaling() ) + { + // we don't want to scale pens according to sx/sy, + // but we want to apply the scaling from the + // painter transformation later + + d_data->initialTransform = new QTransform(); + d_data->initialTransform->scale( transform.m11(), transform.m22() ); + } + + painter->setTransform( tr, true ); + render( painter ); + + painter->setTransform( transform ); + + delete d_data->initialTransform; + d_data->initialTransform = NULL; +} + +/*! + \brief Replay all recorded painter commands + + The graphic is scaled to the defaultSize() and aligned + to a position. + + \param painter Qt painter + \param pos Reference point, where to render + \param alignment Flags how to align the target rectangle + to pos. + */ +void QwtGraphic::render( QPainter *painter, + const QPointF &pos, Qt::Alignment alignment ) const +{ + QRectF r( pos, defaultSize() ); + + if ( alignment & Qt::AlignLeft ) + { + r.moveLeft( pos.x() ); + } + else if ( alignment & Qt::AlignHCenter ) + { + r.moveCenter( QPointF( pos.x(), r.center().y() ) ); + } + else if ( alignment & Qt::AlignRight ) + { + r.moveRight( pos.x() ); + } + + if ( alignment & Qt::AlignTop ) + { + r.moveTop( pos.y() ); + } + else if ( alignment & Qt::AlignVCenter ) + { + r.moveCenter( QPointF( r.center().x(), pos.y() ) ); + } + else if ( alignment & Qt::AlignBottom ) + { + r.moveBottom( pos.y() ); + } + + render( painter, r ); +} + +/*! + \brief Convert the graphic to a QPixmap + + All pixels of the pixmap get initialized by Qt::transparent + before the graphic is scaled and rendered on it. + + The size of the pixmap is the default size ( ceiled to integers ) + of the graphic. + + \return The graphic as pixmap in default size + \sa defaultSize(), toImage(), render() + */ +QPixmap QwtGraphic::toPixmap() const +{ + if ( isNull() ) + return QPixmap(); + + const QSizeF sz = defaultSize(); + + const int w = qCeil( sz.width() ); + const int h = qCeil( sz.height() ); + + QPixmap pixmap( w, h ); + pixmap.fill( Qt::transparent ); + + const QRectF r( 0.0, 0.0, sz.width(), sz.height() ); + + QPainter painter( &pixmap ); + render( &painter, r, Qt::KeepAspectRatio ); + painter.end(); + + return pixmap; +} + +/*! + \brief Convert the graphic to a QPixmap + + All pixels of the pixmap get initialized by Qt::transparent + before the graphic is scaled and rendered on it. + + \param size Size of the image + \param aspectRatioMode Aspect ratio how to scale the graphic + + \return The graphic as pixmap + \sa toImage(), render() + */ +QPixmap QwtGraphic::toPixmap( const QSize &size, + Qt::AspectRatioMode aspectRatioMode ) const +{ + QPixmap pixmap( size ); + pixmap.fill( Qt::transparent ); + + const QRect r( 0, 0, size.width(), size.height() ); + + QPainter painter( &pixmap ); + render( &painter, r, aspectRatioMode ); + painter.end(); + + return pixmap; +} + +/*! + \brief Convert the graphic to a QImage + + All pixels of the image get initialized by 0 ( transparent ) + before the graphic is scaled and rendered on it. + + The format of the image is QImage::Format_ARGB32_Premultiplied. + + \param size Size of the image + \param aspectRatioMode Aspect ratio how to scale the graphic + + \return The graphic as image + \sa toPixmap(), render() + */ +QImage QwtGraphic::toImage( const QSize &size, + Qt::AspectRatioMode aspectRatioMode ) const +{ + QImage image( size, QImage::Format_ARGB32_Premultiplied ); + image.fill( 0 ); + + const QRect r( 0, 0, size.width(), size.height() ); + + QPainter painter( &image ); + render( &painter, r, aspectRatioMode ); + painter.end(); + + return image; +} + +/*! + \brief Convert the graphic to a QImage + + All pixels of the image get initialized by 0 ( transparent ) + before the graphic is scaled and rendered on it. + + The format of the image is QImage::Format_ARGB32_Premultiplied. + + The size of the image is the default size ( ceiled to integers ) + of the graphic. + + \return The graphic as image in default size + \sa defaultSize(), toPixmap(), render() + */ +QImage QwtGraphic::toImage() const +{ + if ( isNull() ) + return QImage(); + + const QSizeF sz = defaultSize(); + + const int w = qCeil( sz.width() ); + const int h = qCeil( sz.height() ); + + QImage image( w, h, QImage::Format_ARGB32 ); + image.fill( 0 ); + + const QRect r( 0, 0, sz.width(), sz.height() ); + + QPainter painter( &image ); + render( &painter, r, Qt::KeepAspectRatio ); + painter.end(); + + return image; +} + +/*! + Store a path command in the command list + + \param path Painter path + \sa QPaintEngine::drawPath() +*/ +void QwtGraphic::drawPath( const QPainterPath &path ) +{ + const QPainter *painter = paintEngine()->painter(); + if ( painter == NULL ) + return; + + d_data->commands += QwtPainterCommand( path ); + + if ( !path.isEmpty() ) + { + const QPainterPath scaledPath = painter->transform().map( path ); + + QRectF pointRect = scaledPath.boundingRect(); + QRectF boundingRect = pointRect; + + if ( painter->pen().style() != Qt::NoPen + && painter->pen().brush().style() != Qt::NoBrush ) + { + boundingRect = qwtStrokedPathRect( painter, path ); + } + + updateControlPointRect( pointRect ); + updateBoundingRect( boundingRect ); + + d_data->pathInfos += PathInfo( pointRect, + boundingRect, qwtHasScalablePen( painter ) ); + } +} + +/*! + \brief Store a pixmap command in the command list + + \param rect target rectangle + \param pixmap Pixmap to be painted + \param subRect Reactangle of the pixmap to be painted + + \sa QPaintEngine::drawPixmap() +*/ +void QwtGraphic::drawPixmap( const QRectF &rect, + const QPixmap &pixmap, const QRectF &subRect ) +{ + const QPainter *painter = paintEngine()->painter(); + if ( painter == NULL ) + return; + + d_data->commands += QwtPainterCommand( rect, pixmap, subRect ); + + const QRectF r = painter->transform().mapRect( rect ); + updateControlPointRect( r ); + updateBoundingRect( r ); +} + +/*! + \brief Store a image command in the command list + + \param rect traget rectangle + \param image Image to be painted + \param subRect Reactangle of the pixmap to be painted + \param flags Image conversion flags + + \sa QPaintEngine::drawImage() + */ +void QwtGraphic::drawImage( const QRectF &rect, const QImage &image, + const QRectF &subRect, Qt::ImageConversionFlags flags) +{ + const QPainter *painter = paintEngine()->painter(); + if ( painter == NULL ) + return; + + d_data->commands += QwtPainterCommand( rect, image, subRect, flags ); + + const QRectF r = painter->transform().mapRect( rect ); + + updateControlPointRect( r ); + updateBoundingRect( r ); +} + +/*! + \brief Store a state command in the command list + + \param state State to be stored + \sa QPaintEngine::updateState() + */ +void QwtGraphic::updateState( const QPaintEngineState &state) +{ + d_data->commands += QwtPainterCommand( state ); +} + +void QwtGraphic::updateBoundingRect( const QRectF &rect ) +{ + QRectF br = rect; + + const QPainter *painter = paintEngine()->painter(); + if ( painter && painter->hasClipping() ) + { + QRectF cr = painter->clipRegion().boundingRect(); + cr = painter->transform().mapRect( cr ); + + br &= cr; + } + + if ( d_data->boundingRect.width() < 0 ) + d_data->boundingRect = br; + else + d_data->boundingRect |= br; +} + +void QwtGraphic::updateControlPointRect( const QRectF &rect ) +{ + if ( d_data->pointRect.width() < 0.0 ) + d_data->pointRect = rect; + else + d_data->pointRect |= rect; +} + +/*! + \return List of recorded paint commands + \sa setCommands() + */ +const QVector< QwtPainterCommand > &QwtGraphic::commands() const +{ + return d_data->commands; +} + +/*! + \brief Append paint commands + + \param commands Paint commands + \sa commands() + */ +void QwtGraphic::setCommands( QVector< QwtPainterCommand > &commands ) +{ + reset(); + + const int numCommands = commands.size(); + if ( numCommands <= 0 ) + return; + + // to calculate a proper bounding rectangle we don't simply copy + // the commands. + + const QwtPainterCommand *cmds = commands.constData(); + + QPainter painter( this ); + for ( int i = 0; i < numCommands; i++ ) + qwtExecCommand( &painter, cmds[i], RenderHints(), QTransform(), NULL ); + + painter.end(); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_graphic.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_graphic.h new file mode 100644 index 0000000..592b8c1 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_graphic.h @@ -0,0 +1,176 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_GRAPHIC_H +#define QWT_GRAPHIC_H + +#include "qwt_global.h" +#include "qwt_null_paintdevice.h" +#include +#include +#include + +class QwtPainterCommand; + +/*! + \brief A paint device for scalable graphics + + QwtGraphic is the representation of a graphic that is tailored for + scalability. Like QPicture it will be initialized by QPainter + operations and can be replayed later to any target paint device. + + While the usual image representations QImage and QPixmap are not + scalable Qt offers two paint devices, that might be candidates + for representing a vector graphic: + + - QPicture\n + Unfortunately QPicture had been forgotten, when Qt4 + introduced floating point based render engines. Its API + is still on integers, what make it unusable for proper scaling. + + - QSvgRenderer/QSvgGenerator\n + Unfortunately QSvgRenderer hides to much information about + its nodes in internal APIs, that are necessary for proper + layout calculations. Also it is derived from QObject and + can't be copied like QImage/QPixmap. + + QwtGraphic maps all scalable drawing primitives to a QPainterPath + and stores them together with the painter state changes + ( pen, brush, transformation ... ) in a list of QwtPaintCommands. + For being a complete QPaintDevice it also stores pixmaps or images, + what is somehow against the idea of the class, because these objects + can't be scaled without a loss in quality. + + The main issue about scaling a QwtGraphic object are the pens used for + drawing the outlines of the painter paths. While non cosmetic pens + ( QPen::isCosmetic() ) are scaled with the same ratio as the path, + cosmetic pens have a fixed width. A graphic might have paths with + different pens - cosmetic and non-cosmetic. + + QwtGraphic caches 2 different rectangles: + + - control point rectangle\n + The control point rectangle is the bounding rectangle of all + control point rectangles of the painter paths, or the target + rectangle of the pixmaps/images. + + - bounding rectangle\n + The bounding rectangle extends the control point rectangle by + what is needed for rendering the outline with an unscaled pen. + + Because the offset for drawing the outline depends on the shape + of the painter path ( the peak of a triangle is different than the flat side ) + scaling with a fixed aspect ratio always needs to be calculated from the + control point rectangle. + + \sa QwtPainterCommand + */ +class QWT_EXPORT QwtGraphic: public QwtNullPaintDevice +{ +public: + /*! + Hint how to render a graphic + \sa setRenderHint(), testRenderHint() + */ + enum RenderHint + { + /*! + When rendering a QwtGraphic a specific scaling between + the controlPointRect() and the coordinates of the target rectangle + is set up internally in render(). + + When RenderPensUnscaled is set this specific scaling is applied + for the control points only, but not for the pens. + All other painter transformations ( set up by application code ) + are supposed to work like usual. + + \sa render(); + */ + RenderPensUnscaled = 0x1 + }; + + /*! + \brief Render hints + + The default setting is to disable all hints + */ + typedef QFlags RenderHints; + + QwtGraphic(); + QwtGraphic( const QwtGraphic & ); + + virtual ~QwtGraphic(); + + QwtGraphic& operator=( const QwtGraphic & ); + + void reset(); + + bool isNull() const; + bool isEmpty() const; + + void render( QPainter * ) const; + + void render( QPainter *, const QSizeF &, + Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const; + + void render( QPainter *, const QRectF &, + Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const; + + void render( QPainter *, const QPointF &, + Qt::Alignment = Qt::AlignTop | Qt::AlignLeft ) const; + + QPixmap toPixmap() const; + QPixmap toPixmap( const QSize &, + Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const; + + QImage toImage() const; + QImage toImage( const QSize &, + Qt::AspectRatioMode = Qt::IgnoreAspectRatio ) const; + + QRectF scaledBoundingRect( double sx, double sy ) const; + + QRectF boundingRect() const; + QRectF controlPointRect() const; + + const QVector< QwtPainterCommand > &commands() const; + void setCommands( QVector< QwtPainterCommand > & ); + + void setDefaultSize( const QSizeF & ); + QSizeF defaultSize() const; + + void setRenderHint( RenderHint, bool on = true ); + bool testRenderHint( RenderHint ) const; + +protected: + virtual QSize sizeMetrics() const; + + virtual void drawPath( const QPainterPath & ); + + virtual void drawPixmap( const QRectF &, + const QPixmap &, const QRectF & ); + + virtual void drawImage( const QRectF &, + const QImage &, const QRectF &, Qt::ImageConversionFlags ); + + virtual void updateState( const QPaintEngineState &state ); + +private: + void updateBoundingRect( const QRectF & ); + void updateControlPointRect( const QRectF & ); + + class PathInfo; + + class PrivateData; + PrivateData *d_data; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtGraphic::RenderHints ) +Q_DECLARE_METATYPE( QwtGraphic ) + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_interval.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_interval.cpp new file mode 100644 index 0000000..90f10d9 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_interval.cpp @@ -0,0 +1,354 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_interval.h" +#include "qwt_math.h" +#include + +/*! + \brief Normalize the limits of the interval + + If maxValue() < minValue() the limits will be inverted. + \return Normalized interval + + \sa isValid(), inverted() +*/ +QwtInterval QwtInterval::normalized() const +{ + if ( d_minValue > d_maxValue ) + { + return inverted(); + } + if ( d_minValue == d_maxValue && d_borderFlags == ExcludeMinimum ) + { + return inverted(); + } + + return *this; +} + +/*! + Invert the limits of the interval + \return Inverted interval + \sa normalized() +*/ +QwtInterval QwtInterval::inverted() const +{ + BorderFlags borderFlags = IncludeBorders; + if ( d_borderFlags & ExcludeMinimum ) + borderFlags |= ExcludeMaximum; + if ( d_borderFlags & ExcludeMaximum ) + borderFlags |= ExcludeMinimum; + + return QwtInterval( d_maxValue, d_minValue, borderFlags ); +} + +/*! + Test if a value is inside an interval + + \param value Value + \return true, if value >= minValue() && value <= maxValue() +*/ +bool QwtInterval::contains( double value ) const +{ + if ( !isValid() ) + return false; + + if ( value < d_minValue || value > d_maxValue ) + return false; + + if ( value == d_minValue && d_borderFlags & ExcludeMinimum ) + return false; + + if ( value == d_maxValue && d_borderFlags & ExcludeMaximum ) + return false; + + return true; +} + +//! Unite 2 intervals +QwtInterval QwtInterval::unite( const QwtInterval &other ) const +{ + /* + If one of the intervals is invalid return the other one. + If both are invalid return an invalid default interval + */ + if ( !isValid() ) + { + if ( !other.isValid() ) + return QwtInterval(); + else + return other; + } + if ( !other.isValid() ) + return *this; + + QwtInterval united; + BorderFlags flags = IncludeBorders; + + // minimum + if ( d_minValue < other.minValue() ) + { + united.setMinValue( d_minValue ); + flags &= d_borderFlags & ExcludeMinimum; + } + else if ( other.minValue() < d_minValue ) + { + united.setMinValue( other.minValue() ); + flags &= other.borderFlags() & ExcludeMinimum; + } + else // d_minValue == other.minValue() + { + united.setMinValue( d_minValue ); + flags &= ( d_borderFlags & other.borderFlags() ) & ExcludeMinimum; + } + + // maximum + if ( d_maxValue > other.maxValue() ) + { + united.setMaxValue( d_maxValue ); + flags &= d_borderFlags & ExcludeMaximum; + } + else if ( other.maxValue() > d_maxValue ) + { + united.setMaxValue( other.maxValue() ); + flags &= other.borderFlags() & ExcludeMaximum; + } + else // d_maxValue == other.maxValue() ) + { + united.setMaxValue( d_maxValue ); + flags &= d_borderFlags & other.borderFlags() & ExcludeMaximum; + } + + united.setBorderFlags( flags ); + return united; +} + +/*! + \brief Intersect 2 intervals + + \param other Interval to be intersect with + \return Intersection + */ +QwtInterval QwtInterval::intersect( const QwtInterval &other ) const +{ + if ( !other.isValid() || !isValid() ) + return QwtInterval(); + + QwtInterval i1 = *this; + QwtInterval i2 = other; + + // swap i1/i2, so that the minimum of i1 + // is smaller then the minimum of i2 + + if ( i1.minValue() > i2.minValue() ) + { + qSwap( i1, i2 ); + } + else if ( i1.minValue() == i2.minValue() ) + { + if ( i1.borderFlags() & ExcludeMinimum ) + qSwap( i1, i2 ); + } + + if ( i1.maxValue() < i2.minValue() ) + { + return QwtInterval(); + } + + if ( i1.maxValue() == i2.minValue() ) + { + if ( i1.borderFlags() & ExcludeMaximum || + i2.borderFlags() & ExcludeMinimum ) + { + return QwtInterval(); + } + } + + QwtInterval intersected; + BorderFlags flags = IncludeBorders; + + intersected.setMinValue( i2.minValue() ); + flags |= i2.borderFlags() & ExcludeMinimum; + + if ( i1.maxValue() < i2.maxValue() ) + { + intersected.setMaxValue( i1.maxValue() ); + flags |= i1.borderFlags() & ExcludeMaximum; + } + else if ( i2.maxValue() < i1.maxValue() ) + { + intersected.setMaxValue( i2.maxValue() ); + flags |= i2.borderFlags() & ExcludeMaximum; + } + else // i1.maxValue() == i2.maxValue() + { + intersected.setMaxValue( i1.maxValue() ); + flags |= i1.borderFlags() & i2.borderFlags() & ExcludeMaximum; + } + + intersected.setBorderFlags( flags ); + return intersected; +} + +/*! + \brief Unite this interval with the given interval. + + \param other Interval to be united with + \return This interval + */ +QwtInterval& QwtInterval::operator|=( const QwtInterval &other ) +{ + *this = *this | other; + return *this; +} + +/*! + \brief Intersect this interval with the given interval. + + \param other Interval to be intersected with + \return This interval + */ +QwtInterval& QwtInterval::operator&=( const QwtInterval &other ) +{ + *this = *this & other; + return *this; +} + +/*! + \brief Test if two intervals overlap + + \param other Interval + \return True, when the intervals are intersecting +*/ +bool QwtInterval::intersects( const QwtInterval &other ) const +{ + if ( !isValid() || !other.isValid() ) + return false; + + QwtInterval i1 = *this; + QwtInterval i2 = other; + + // swap i1/i2, so that the minimum of i1 + // is smaller then the minimum of i2 + + if ( i1.minValue() > i2.minValue() ) + { + qSwap( i1, i2 ); + } + else if ( i1.minValue() == i2.minValue() && + i1.borderFlags() & ExcludeMinimum ) + { + qSwap( i1, i2 ); + } + + if ( i1.maxValue() > i2.minValue() ) + { + return true; + } + if ( i1.maxValue() == i2.minValue() ) + { + return !( ( i1.borderFlags() & ExcludeMaximum ) || + ( i2.borderFlags() & ExcludeMinimum ) ); + } + return false; +} + +/*! + Adjust the limit that is closer to value, so that value becomes + the center of the interval. + + \param value Center + \return Interval with value as center +*/ +QwtInterval QwtInterval::symmetrize( double value ) const +{ + if ( !isValid() ) + return *this; + + const double delta = + qMax( qAbs( value - d_maxValue ), qAbs( value - d_minValue ) ); + + return QwtInterval( value - delta, value + delta ); +} + +/*! + Limit the interval, keeping the border modes + + \param lowerBound Lower limit + \param upperBound Upper limit + + \return Limited interval +*/ +QwtInterval QwtInterval::limited( double lowerBound, double upperBound ) const +{ + if ( !isValid() || lowerBound > upperBound ) + return QwtInterval(); + + double minValue = qMax( d_minValue, lowerBound ); + minValue = qMin( minValue, upperBound ); + + double maxValue = qMax( d_maxValue, lowerBound ); + maxValue = qMin( maxValue, upperBound ); + + return QwtInterval( minValue, maxValue, d_borderFlags ); +} + +/*! + \brief Extend the interval + + If value is below minValue(), value becomes the lower limit. + If value is above maxValue(), value becomes the upper limit. + + extend() has no effect for invalid intervals + + \param value Value + \return extended interval + + \sa isValid() +*/ +QwtInterval QwtInterval::extend( double value ) const +{ + if ( !isValid() ) + return *this; + + return QwtInterval( qMin( value, d_minValue ), + qMax( value, d_maxValue ), d_borderFlags ); +} + +/*! + Extend an interval + + \param value Value + \return Reference of the extended interval + + \sa extend() +*/ +QwtInterval& QwtInterval::operator|=( double value ) +{ + *this = *this | value; + return *this; +} + +#ifndef QT_NO_DEBUG_STREAM + +QDebug operator<<( QDebug debug, const QwtInterval &interval ) +{ + const int flags = interval.borderFlags(); + + debug.nospace() << "QwtInterval(" + << ( ( flags & QwtInterval::ExcludeMinimum ) ? "]" : "[" ) + << interval.minValue() << "," << interval.maxValue() + << ( ( flags & QwtInterval::ExcludeMaximum ) ? "[" : "]" ) + << ")"; + + return debug.space(); +} + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_interval.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_interval.h new file mode 100644 index 0000000..b55e434 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_interval.h @@ -0,0 +1,320 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_INTERVAL_H +#define QWT_INTERVAL_H + +#include "qwt_global.h" +#include + +#ifndef QT_NO_DEBUG_STREAM +#include +#endif + +/*! + \brief A class representing an interval + + The interval is represented by 2 doubles, the lower and the upper limit. +*/ + +class QWT_EXPORT QwtInterval +{ +public: + /*! + Flag indicating if a border is included or excluded + \sa setBorderFlags(), borderFlags() + */ + enum BorderFlag + { + //! Min/Max values are inside the interval + IncludeBorders = 0x00, + + //! Min value is not included in the interval + ExcludeMinimum = 0x01, + + //! Max value is not included in the interval + ExcludeMaximum = 0x02, + + //! Min/Max values are not included in the interval + ExcludeBorders = ExcludeMinimum | ExcludeMaximum + }; + + //! Border flags + typedef QFlags BorderFlags; + + QwtInterval(); + QwtInterval( double minValue, double maxValue, + BorderFlags = IncludeBorders ); + + void setInterval( double minValue, double maxValue, + BorderFlags = IncludeBorders ); + + QwtInterval normalized() const; + QwtInterval inverted() const; + QwtInterval limited( double minValue, double maxValue ) const; + + bool operator==( const QwtInterval & ) const; + bool operator!=( const QwtInterval & ) const; + + void setBorderFlags( BorderFlags ); + BorderFlags borderFlags() const; + + double minValue() const; + double maxValue() const; + + double width() const; + + void setMinValue( double ); + void setMaxValue( double ); + + bool contains( double value ) const; + + bool intersects( const QwtInterval & ) const; + QwtInterval intersect( const QwtInterval & ) const; + QwtInterval unite( const QwtInterval & ) const; + + QwtInterval operator|( const QwtInterval & ) const; + QwtInterval operator&( const QwtInterval & ) const; + + QwtInterval &operator|=( const QwtInterval & ); + QwtInterval &operator&=( const QwtInterval & ); + + QwtInterval extend( double value ) const; + QwtInterval operator|( double ) const; + QwtInterval &operator|=( double ); + + bool isValid() const; + bool isNull() const; + void invalidate(); + + QwtInterval symmetrize( double value ) const; + +private: + double d_minValue; + double d_maxValue; + BorderFlags d_borderFlags; +}; + +Q_DECLARE_TYPEINFO(QwtInterval, Q_MOVABLE_TYPE); + +/*! + \brief Default Constructor + + Creates an invalid interval [0.0, -1.0] + \sa setInterval(), isValid() +*/ +inline QwtInterval::QwtInterval(): + d_minValue( 0.0 ), + d_maxValue( -1.0 ), + d_borderFlags( IncludeBorders ) +{ +} + +/*! + Constructor + + Build an interval with from min/max values + + \param minValue Minimum value + \param maxValue Maximum value + \param borderFlags Include/Exclude borders +*/ +inline QwtInterval::QwtInterval( + double minValue, double maxValue, BorderFlags borderFlags ): + d_minValue( minValue ), + d_maxValue( maxValue ), + d_borderFlags( borderFlags ) +{ +} + +/*! + Assign the limits of the interval + + \param minValue Minimum value + \param maxValue Maximum value + \param borderFlags Include/Exclude borders +*/ +inline void QwtInterval::setInterval( + double minValue, double maxValue, BorderFlags borderFlags ) +{ + d_minValue = minValue; + d_maxValue = maxValue; + d_borderFlags = borderFlags; +} + +/*! + Change the border flags + + \param borderFlags Or'd BorderMode flags + \sa borderFlags() +*/ +inline void QwtInterval::setBorderFlags( BorderFlags borderFlags ) +{ + d_borderFlags = borderFlags; +} + +/*! + \return Border flags + \sa setBorderFlags() +*/ +inline QwtInterval::BorderFlags QwtInterval::borderFlags() const +{ + return d_borderFlags; +} + +/*! + Assign the lower limit of the interval + + \param minValue Minimum value +*/ +inline void QwtInterval::setMinValue( double minValue ) +{ + d_minValue = minValue; +} + +/*! + Assign the upper limit of the interval + + \param maxValue Maximum value +*/ +inline void QwtInterval::setMaxValue( double maxValue ) +{ + d_maxValue = maxValue; +} + +//! \return Lower limit of the interval +inline double QwtInterval::minValue() const +{ + return d_minValue; +} + +//! \return Upper limit of the interval +inline double QwtInterval::maxValue() const +{ + return d_maxValue; +} + +/*! + A interval is valid when minValue() <= maxValue(). + In case of QwtInterval::ExcludeBorders it is true + when minValue() < maxValue() + + \return True, when the interval is valid +*/ +inline bool QwtInterval::isValid() const +{ + if ( ( d_borderFlags & ExcludeBorders ) == 0 ) + return d_minValue <= d_maxValue; + else + return d_minValue < d_maxValue; +} + +/*! + \brief Return the width of an interval + + The width of invalid intervals is 0.0, otherwise the result is + maxValue() - minValue(). + + \return Interval width + \sa isValid() +*/ +inline double QwtInterval::width() const +{ + return isValid() ? ( d_maxValue - d_minValue ) : 0.0; +} + +/*! + \brief Intersection of two intervals + + \param other Interval to intersect with + \return Intersection of this and other + + \sa intersect() +*/ +inline QwtInterval QwtInterval::operator&( + const QwtInterval &other ) const +{ + return intersect( other ); +} + +/*! + Union of two intervals + + \param other Interval to unite with + \return Union of this and other + + \sa unite() +*/ +inline QwtInterval QwtInterval::operator|( + const QwtInterval &other ) const +{ + return unite( other ); +} + +/*! + \brief Compare two intervals + + \param other Interval to compare with + \return True, when this and other are equal +*/ +inline bool QwtInterval::operator==( const QwtInterval &other ) const +{ + return ( d_minValue == other.d_minValue ) && + ( d_maxValue == other.d_maxValue ) && + ( d_borderFlags == other.d_borderFlags ); +} +/*! + \brief Compare two intervals + + \param other Interval to compare with + \return True, when this and other are not equal +*/ +inline bool QwtInterval::operator!=( const QwtInterval &other ) const +{ + return ( !( *this == other ) ); +} + +/*! + Extend an interval + + \param value Value + \return Extended interval + \sa extend() +*/ +inline QwtInterval QwtInterval::operator|( double value ) const +{ + return extend( value ); +} + +//! \return true, if isValid() && (minValue() >= maxValue()) +inline bool QwtInterval::isNull() const +{ + return isValid() && d_minValue >= d_maxValue; +} + +/*! + Invalidate the interval + + The limits are set to interval [0.0, -1.0] + \sa isValid() +*/ +inline void QwtInterval::invalidate() +{ + d_minValue = 0.0; + d_maxValue = -1.0; +} + +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtInterval::BorderFlags ) +Q_DECLARE_METATYPE( QwtInterval ) + +#ifndef QT_NO_DEBUG_STREAM +QWT_EXPORT QDebug operator<<( QDebug, const QwtInterval & ); +#endif + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_interval_symbol.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_interval_symbol.cpp new file mode 100644 index 0000000..9b782cf --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_interval_symbol.cpp @@ -0,0 +1,319 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_interval_symbol.h" +#include "qwt_painter.h" +#include "qwt_math.h" +#include + +#if QT_VERSION < 0x040601 +#define qAtan2(y, x) ::atan2(y, x) +#define qFastSin(x) qSin(x) +#define qFastCos(x) qCos(x) +#endif + +class QwtIntervalSymbol::PrivateData +{ +public: + PrivateData(): + style( QwtIntervalSymbol::NoSymbol ), + width( 6 ) + { + } + + bool operator==( const PrivateData &other ) const + { + return ( style == other.style ) + && ( width == other.width ) + && ( brush == other.brush ) + && ( pen == other.pen ); + } + + QwtIntervalSymbol::Style style; + int width; + + QPen pen; + QBrush brush; +}; + +/*! + Constructor + + \param style Style of the symbol + \sa setStyle(), style(), Style +*/ +QwtIntervalSymbol::QwtIntervalSymbol( Style style ) +{ + d_data = new PrivateData(); + d_data->style = style; +} + +//! Copy constructor +QwtIntervalSymbol::QwtIntervalSymbol( const QwtIntervalSymbol &other ) +{ + d_data = new PrivateData(); + *d_data = *other.d_data; +} + +//! Destructor +QwtIntervalSymbol::~QwtIntervalSymbol() +{ + delete d_data; +} + +//! \brief Assignment operator +QwtIntervalSymbol &QwtIntervalSymbol::operator=( + const QwtIntervalSymbol &other ) +{ + *d_data = *other.d_data; + return *this; +} + +//! \brief Compare two symbols +bool QwtIntervalSymbol::operator==( + const QwtIntervalSymbol &other ) const +{ + return *d_data == *other.d_data; +} + +//! \brief Compare two symbols +bool QwtIntervalSymbol::operator!=( + const QwtIntervalSymbol &other ) const +{ + return !( *d_data == *other.d_data ); +} + +/*! + Specify the symbol style + + \param style Style + \sa style(), Style +*/ +void QwtIntervalSymbol::setStyle( Style style ) +{ + d_data->style = style; +} + +/*! + \return Current symbol style + \sa setStyle() +*/ +QwtIntervalSymbol::Style QwtIntervalSymbol::style() const +{ + return d_data->style; +} + +/*! + Specify the width of the symbol + It is used depending on the style. + + \param width Width + \sa width(), setStyle() +*/ +void QwtIntervalSymbol::setWidth( int width ) +{ + d_data->width = width; +} + +/*! + \return Width of the symbol. + \sa setWidth(), setStyle() +*/ +int QwtIntervalSymbol::width() const +{ + return d_data->width; +} + +/*! + \brief Assign a brush + + The brush is used for the Box style. + + \param brush Brush + \sa brush() +*/ +void QwtIntervalSymbol::setBrush( const QBrush &brush ) +{ + d_data->brush = brush; +} + +/*! + \return Brush + \sa setBrush() +*/ +const QBrush& QwtIntervalSymbol::brush() const +{ + return d_data->brush; +} + +/*! + Build and assign a pen + + In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it + non cosmetic ( see QPen::isCosmetic() ). This method has been introduced + to hide this incompatibility. + + \param color Pen color + \param width Pen width + \param style Pen style + + \sa pen(), brush() + */ +void QwtIntervalSymbol::setPen( const QColor &color, + qreal width, Qt::PenStyle style ) +{ + setPen( QPen( color, width, style ) ); +} + +/*! + Assign a pen + + \param pen Pen + \sa pen(), setBrush() +*/ +void QwtIntervalSymbol::setPen( const QPen &pen ) +{ + d_data->pen = pen; +} + +/*! + \return Pen + \sa setPen(), brush() +*/ +const QPen& QwtIntervalSymbol::pen() const +{ + return d_data->pen; +} + +/*! + Draw a symbol depending on its style + + \param painter Painter + \param orientation Orientation + \param from Start point of the interval in target device coordinates + \param to End point of the interval in target device coordinates + + \sa setStyle() +*/ +void QwtIntervalSymbol::draw( QPainter *painter, Qt::Orientation orientation, + const QPointF &from, const QPointF &to ) const +{ + const qreal pw = qMax( painter->pen().widthF(), qreal( 1.0 ) ); + + QPointF p1 = from; + QPointF p2 = to; + if ( QwtPainter::roundingAlignment( painter ) ) + { + p1 = p1.toPoint(); + p2 = p2.toPoint(); + } + + switch ( d_data->style ) + { + case QwtIntervalSymbol::Bar: + { + QwtPainter::drawLine( painter, p1, p2 ); + if ( d_data->width > pw ) + { + if ( ( orientation == Qt::Horizontal ) + && ( p1.y() == p2.y() ) ) + { + const double sw = d_data->width; + + const double y = p1.y() - sw / 2; + QwtPainter::drawLine( painter, + p1.x(), y, p1.x(), y + sw ); + QwtPainter::drawLine( painter, + p2.x(), y, p2.x(), y + sw ); + } + else if ( ( orientation == Qt::Vertical ) + && ( p1.x() == p2.x() ) ) + { + const double sw = d_data->width; + + const double x = p1.x() - sw / 2; + QwtPainter::drawLine( painter, + x, p1.y(), x + sw, p1.y() ); + QwtPainter::drawLine( painter, + x, p2.y(), x + sw, p2.y() ); + } + else + { + const double sw = d_data->width; + + const double dx = p2.x() - p1.x(); + const double dy = p2.y() - p1.y(); + const double angle = qAtan2( dy, dx ) + M_PI_2; + double dw2 = sw / 2.0; + + const double cx = qFastCos( angle ) * dw2; + const double sy = qFastSin( angle ) * dw2; + + QwtPainter::drawLine( painter, + p1.x() - cx, p1.y() - sy, + p1.x() + cx, p1.y() + sy ); + QwtPainter::drawLine( painter, + p2.x() - cx, p2.y() - sy, + p2.x() + cx, p2.y() + sy ); + } + } + break; + } + case QwtIntervalSymbol::Box: + { + if ( d_data->width <= pw ) + { + QwtPainter::drawLine( painter, p1, p2 ); + } + else + { + if ( ( orientation == Qt::Horizontal ) + && ( p1.y() == p2.y() ) ) + { + const double sw = d_data->width; + + const double y = p1.y() - d_data->width / 2; + QwtPainter::drawRect( painter, + p1.x(), y, p2.x() - p1.x(), sw ); + } + else if ( ( orientation == Qt::Vertical ) + && ( p1.x() == p2.x() ) ) + { + const double sw = d_data->width; + + const double x = p1.x() - d_data->width / 2; + QwtPainter::drawRect( painter, + x, p1.y(), sw, p2.y() - p1.y() ); + } + else + { + const double sw = d_data->width; + + const double dx = p2.x() - p1.x(); + const double dy = p2.y() - p1.y(); + const double angle = qAtan2( dy, dx ) + M_PI_2; + double dw2 = sw / 2.0; + + const double cx = qFastCos( angle ) * dw2; + const double sy = qFastSin( angle ) * dw2; + + QPolygonF polygon; + polygon += QPointF( p1.x() - cx, p1.y() - sy ); + polygon += QPointF( p1.x() + cx, p1.y() + sy ); + polygon += QPointF( p2.x() + cx, p2.y() + sy ); + polygon += QPointF( p2.x() - cx, p2.y() - sy ); + + QwtPainter::drawPolygon( painter, polygon ); + } + } + break; + } + default:; + } +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_interval_symbol.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_interval_symbol.h new file mode 100644 index 0000000..c233213 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_interval_symbol.h @@ -0,0 +1,87 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_INTERVAL_SYMBOL_H +#define QWT_INTERVAL_SYMBOL_H + +#include "qwt_global.h" +#include +#include + +class QPainter; +class QRect; +class QPointF; + +/*! + \brief A drawing primitive for displaying an interval like an error bar + + \sa QwtPlotIntervalCurve +*/ +class QWT_EXPORT QwtIntervalSymbol +{ +public: + //! Symbol style + enum Style + { + //! No Style. The symbol cannot be drawn. + NoSymbol = -1, + + /*! + The symbol displays a line with caps at the beginning/end. + The size of the caps depends on the symbol width(). + */ + Bar, + + /*! + The symbol displays a plain rectangle using pen() and brush(). + The size of the rectangle depends on the translated interval and + the width(), + */ + Box, + + /*! + Styles >= UserSymbol are reserved for derived + classes of QwtIntervalSymbol that overload draw() with + additional application specific symbol types. + */ + UserSymbol = 1000 + }; + +public: + QwtIntervalSymbol( Style = NoSymbol ); + QwtIntervalSymbol( const QwtIntervalSymbol & ); + virtual ~QwtIntervalSymbol(); + + QwtIntervalSymbol &operator=( const QwtIntervalSymbol & ); + bool operator==( const QwtIntervalSymbol & ) const; + bool operator!=( const QwtIntervalSymbol & ) const; + + void setWidth( int ); + int width() const; + + void setBrush( const QBrush& b ); + const QBrush& brush() const; + + void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); + void setPen( const QPen & ); + const QPen& pen() const; + + void setStyle( Style ); + Style style() const; + + virtual void draw( QPainter *, Qt::Orientation, + const QPointF& from, const QPointF& to ) const; + +private: + + class PrivateData; + PrivateData* d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_knob.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_knob.cpp new file mode 100644 index 0000000..f9bde9a --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_knob.cpp @@ -0,0 +1,855 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_knob.h" +#include "qwt_round_scale_draw.h" +#include "qwt_math.h" +#include "qwt_painter.h" +#include "qwt_scale_map.h" +#include +#include +#include +#include +#include +#include +#include + +#if QT_VERSION < 0x040601 +#define qAtan2(y, x) ::atan2(y, x) +#define qFabs(x) ::fabs(x) +#define qFastCos(x) qCos(x) +#define qFastSin(x) qSin(x) +#endif + +static QSize qwtKnobSizeHint( const QwtKnob *knob, int min ) +{ + int knobWidth = knob->knobWidth(); + if ( knobWidth <= 0 ) + knobWidth = qMax( 3 * knob->markerSize(), min ); + + // Add the scale radial thickness to the knobWidth + const int extent = qCeil( knob->scaleDraw()->extent( knob->font() ) ); + const int d = 2 * ( extent + 4 ) + knobWidth; + + int left, right, top, bottom; + knob->getContentsMargins( &left, &top, &right, &bottom ); + + return QSize( d + left + right, d + top + bottom ); +} + +static inline double qwtToScaleAngle( double angle ) +{ + // the map is counter clockwise with the origin + // at 90° using angles from -180° -> 180° + + double a = 90.0 - angle; + if ( a <= -180.0 ) + a += 360.0; + else if ( a >= 180.0 ) + a -= 360.0; + + return a; +} + +static double qwtToDegrees( double value ) +{ + return qwtNormalizeDegrees( 90.0 - value ); +} + +class QwtKnob::PrivateData +{ +public: + PrivateData(): + knobStyle( QwtKnob::Raised ), + markerStyle( QwtKnob::Notch ), + borderWidth( 2 ), + borderDist( 4 ), + scaleDist( 4 ), + maxScaleTicks( 11 ), + knobWidth( 0 ), + alignment( Qt::AlignCenter ), + markerSize( 8 ), + totalAngle( 270.0 ), + mouseOffset( 0.0 ) + { + } + + QwtKnob::KnobStyle knobStyle; + QwtKnob::MarkerStyle markerStyle; + + int borderWidth; + int borderDist; + int scaleDist; + int maxScaleTicks; + int knobWidth; + Qt::Alignment alignment; + int markerSize; + + double totalAngle; + + double mouseOffset; +}; + +/*! + \brief Constructor + + Construct a knob with an angle of 270°. The style is + QwtKnob::Raised and the marker style is QwtKnob::Notch. + The width of the knob is set to 50 pixels. + + \param parent Parent widget + + \sa setTotalAngle() +*/ +QwtKnob::QwtKnob( QWidget* parent ): + QwtAbstractSlider( parent ) +{ + d_data = new PrivateData; + + setScaleDraw( new QwtRoundScaleDraw() ); + + setTotalAngle( 270.0 ); + + setScale( 0.0, 10.0 ); + setValue( 0.0 ); + + setSizePolicy( QSizePolicy::MinimumExpanding, + QSizePolicy::MinimumExpanding ); +} + +//! Destructor +QwtKnob::~QwtKnob() +{ + delete d_data; +} + +/*! + \brief Set the knob type + + \param knobStyle Knob type + \sa knobStyle(), setBorderWidth() +*/ +void QwtKnob::setKnobStyle( KnobStyle knobStyle ) +{ + if ( d_data->knobStyle != knobStyle ) + { + d_data->knobStyle = knobStyle; + update(); + } +} + +/*! + \return Marker type of the knob + \sa setKnobStyle(), setBorderWidth() +*/ +QwtKnob::KnobStyle QwtKnob::knobStyle() const +{ + return d_data->knobStyle; +} + +/*! + \brief Set the marker type of the knob + + \param markerStyle Marker type + \sa markerStyle(), setMarkerSize() +*/ +void QwtKnob::setMarkerStyle( MarkerStyle markerStyle ) +{ + if ( d_data->markerStyle != markerStyle ) + { + d_data->markerStyle = markerStyle; + update(); + } +} + +/*! + \return Marker type of the knob + \sa setMarkerStyle(), setMarkerSize() +*/ +QwtKnob::MarkerStyle QwtKnob::markerStyle() const +{ + return d_data->markerStyle; +} + +/*! + \brief Set the total angle by which the knob can be turned + \param angle Angle in degrees. + + The angle has to be between [10, 360] degrees. Angles above + 360 ( so that the knob can be turned several times around its axis ) + have to be set using setNumTurns(). + + The default angle is 270 degrees. + + \sa totalAngle(), setNumTurns() +*/ +void QwtKnob::setTotalAngle ( double angle ) +{ + angle = qBound( 10.0, angle, 360.0 ); + + if ( angle != d_data->totalAngle ) + { + d_data->totalAngle = angle; + + scaleDraw()->setAngleRange( -0.5 * d_data->totalAngle, + 0.5 * d_data->totalAngle ); + + updateGeometry(); + update(); + } +} + +/*! + \return the total angle + \sa setTotalAngle(), setNumTurns(), numTurns() + */ +double QwtKnob::totalAngle() const +{ + return d_data->totalAngle; +} + +/*! + \brief Set the number of turns + + When numTurns > 1 the knob can be turned several times around its axis + - otherwise the total angle is floored to 360°. + + \sa numTurns(), totalAngle(), setTotalAngle() +*/ + +void QwtKnob::setNumTurns( int numTurns ) +{ + numTurns = qMax( numTurns, 1 ); + + if ( numTurns == 1 && d_data->totalAngle <= 360.0 ) + return; + + const double angle = numTurns * 360.0; + if ( angle != d_data->totalAngle ) + { + d_data->totalAngle = angle; + + scaleDraw()->setAngleRange( -0.5 * d_data->totalAngle, + 0.5 * d_data->totalAngle ); + + updateGeometry(); + update(); + } +} + +/*! + \return Number of turns. + + When the total angle is below 360° numTurns() is ceiled to 1. + \sa setNumTurns(), setTotalAngle(), totalAngle() + */ +int QwtKnob::numTurns() const +{ + return qCeil( d_data->totalAngle / 360.0 ); +} + +/*! + Change the scale draw of the knob + + For changing the labels of the scales, it + is necessary to derive from QwtRoundScaleDraw and + overload QwtRoundScaleDraw::label(). + + \sa scaleDraw() +*/ +void QwtKnob::setScaleDraw( QwtRoundScaleDraw *scaleDraw ) +{ + setAbstractScaleDraw( scaleDraw ); + setTotalAngle( d_data->totalAngle ); + + updateGeometry(); + update(); +} + +/*! + \return the scale draw of the knob + \sa setScaleDraw() +*/ +const QwtRoundScaleDraw *QwtKnob::scaleDraw() const +{ + return static_cast( abstractScaleDraw() ); +} + +/*! + \return the scale draw of the knob + \sa setScaleDraw() +*/ +QwtRoundScaleDraw *QwtKnob::scaleDraw() +{ + return static_cast( abstractScaleDraw() ); +} + +/*! + Calculate the bounding rectangle of the knob without the scale + + \return Bounding rectangle of the knob + \sa knobWidth(), alignment(), QWidget::contentsRect() + */ +QRect QwtKnob::knobRect() const +{ + const QRect cr = contentsRect(); + + const int extent = qCeil( scaleDraw()->extent( font() ) ); + const int d = extent + d_data->scaleDist; + + int w = d_data->knobWidth; + if ( w <= 0 ) + { + const int dim = qMin( cr.width(), cr.height() ); + + w = dim - 2 * ( d ); + w = qMax( 0, w ); + } + + QRect r( 0, 0, w, w ); + + if ( d_data->alignment & Qt::AlignLeft ) + { + r.moveLeft( cr.left() + d ); + } + else if ( d_data->alignment & Qt::AlignRight ) + { + r.moveRight( cr.right() - d ); + } + else + { + r.moveCenter( QPoint( cr.center().x(), r.center().y() ) ); + } + + if ( d_data->alignment & Qt::AlignTop ) + { + r.moveTop( cr.top() + d ); + } + else if ( d_data->alignment & Qt::AlignBottom ) + { + r.moveBottom( cr.bottom() - d ); + } + else + { + r.moveCenter( QPoint( r.center().x(), cr.center().y() ) ); + } + + return r; +} + +/*! + \brief Determine what to do when the user presses a mouse button. + + \param pos Mouse position + + \retval True, when pos is inside the circle of the knob. + \sa scrolledTo() +*/ +bool QwtKnob::isScrollPosition( const QPoint &pos ) const +{ + const QRect kr = knobRect(); + + const QRegion region( kr, QRegion::Ellipse ); + if ( region.contains( pos ) && ( pos != kr.center() ) ) + { + const double angle = QLineF( kr.center(), pos ).angle(); + const double valueAngle = qwtToDegrees( scaleMap().transform( value() ) ); + + d_data->mouseOffset = qwtNormalizeDegrees( angle - valueAngle ); + + return true; + } + + return false; +} + +/*! + \brief Determine the value for a new position of the mouse + + \param pos Mouse position + + \return Value for the mouse position + \sa isScrollPosition() +*/ +double QwtKnob::scrolledTo( const QPoint &pos ) const +{ + double angle = QLineF( rect().center(), pos ).angle(); + angle = qwtNormalizeDegrees( angle - d_data->mouseOffset ); + + if ( scaleMap().pDist() > 360.0 ) + { + angle = qwtToDegrees( angle ); + + const double v = scaleMap().transform( value() ); + + int numTurns = qFloor( ( v - scaleMap().p1() ) / 360.0 ); + + double valueAngle = qwtNormalizeDegrees( v ); + if ( qAbs( valueAngle - angle ) > 180.0 ) + { + numTurns += ( angle > valueAngle ) ? -1 : 1; + } + + angle += scaleMap().p1() + numTurns * 360.0; + + if ( !wrapping() ) + { + const double boundedAngle = + qBound( scaleMap().p1(), angle, scaleMap().p2() ); + + d_data->mouseOffset += ( boundedAngle - angle ); + angle = boundedAngle; + } + } + else + { + angle = qwtToScaleAngle( angle ); + + double boundedAngle = qBound( scaleMap().p1(), angle, scaleMap().p2() ); + + if ( !wrapping() ) + { + const double currentAngle = scaleMap().transform( value() ); + + if ( ( currentAngle > 90.0 ) && ( boundedAngle < -90.0 ) ) + boundedAngle = scaleMap().p2(); + else if ( ( currentAngle < -90.0 ) && ( boundedAngle > 90.0 ) ) + boundedAngle = scaleMap().p1(); + + d_data->mouseOffset += ( boundedAngle - angle ); + } + + angle = boundedAngle; + } + + return scaleMap().invTransform( angle ); +} + +/*! + Handle QEvent::StyleChange and QEvent::FontChange; + \param event Change event +*/ +void QwtKnob::changeEvent( QEvent *event ) +{ + switch( event->type() ) + { + case QEvent::StyleChange: + case QEvent::FontChange: + { + updateGeometry(); + update(); + break; + } + default: + break; + } +} + +/*! + Repaint the knob + \param event Paint event +*/ +void QwtKnob::paintEvent( QPaintEvent *event ) +{ + const QRectF knobRect = this->knobRect(); + + QPainter painter( this ); + painter.setClipRegion( event->region() ); + + QStyleOption opt; + opt.init(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); + + painter.setRenderHint( QPainter::Antialiasing, true ); + + if ( !knobRect.contains( event->region().boundingRect() ) ) + { + scaleDraw()->setRadius( 0.5 * knobRect.width() + d_data->scaleDist ); + scaleDraw()->moveCenter( knobRect.center() ); + + scaleDraw()->draw( &painter, palette() ); + } + + drawKnob( &painter, knobRect ); + + drawMarker( &painter, knobRect, + qwtNormalizeDegrees( scaleMap().transform( value() ) ) ); + + painter.setRenderHint( QPainter::Antialiasing, false ); + + if ( hasFocus() ) + drawFocusIndicator( &painter ); +} + +/*! + \brief Draw the knob + + \param painter painter + \param knobRect Bounding rectangle of the knob (without scale) +*/ +void QwtKnob::drawKnob( QPainter *painter, const QRectF &knobRect ) const +{ + double dim = qMin( knobRect.width(), knobRect.height() ); + dim -= d_data->borderWidth * 0.5; + + QRectF aRect( 0, 0, dim, dim ); + aRect.moveCenter( knobRect.center() ); + + QPen pen( Qt::NoPen ); + if ( d_data->borderWidth > 0 ) + { + QColor c1 = palette().color( QPalette::Light ); + QColor c2 = palette().color( QPalette::Dark ); + + QLinearGradient gradient( aRect.topLeft(), aRect.bottomRight() ); + gradient.setColorAt( 0.0, c1 ); + gradient.setColorAt( 0.3, c1 ); + gradient.setColorAt( 0.7, c2 ); + gradient.setColorAt( 1.0, c2 ); + + pen = QPen( gradient, d_data->borderWidth ); + } + + QBrush brush; + switch( d_data->knobStyle ) + { + case QwtKnob::Raised: + { + double off = 0.3 * knobRect.width(); + QRadialGradient gradient( knobRect.center(), + knobRect.width(), knobRect.topLeft() + QPointF( off, off ) ); + + gradient.setColorAt( 0.0, palette().color( QPalette::Midlight ) ); + gradient.setColorAt( 1.0, palette().color( QPalette::Button ) ); + + brush = QBrush( gradient ); + + break; + } + case QwtKnob::Styled: + { + QRadialGradient gradient(knobRect.center().x() - knobRect.width() / 3, + knobRect.center().y() - knobRect.height() / 2, + knobRect.width() * 1.3, + knobRect.center().x(), + knobRect.center().y() - knobRect.height() / 2); + + const QColor c = palette().color( QPalette::Button ); + gradient.setColorAt(0, c.lighter(110)); + gradient.setColorAt(qreal(0.5), c); + gradient.setColorAt(qreal(0.501), c.darker(102)); + gradient.setColorAt(1, c.darker(115)); + + brush = QBrush( gradient ); + + break; + } + case QwtKnob::Sunken: + { + QLinearGradient gradient( + knobRect.topLeft(), knobRect.bottomRight() ); + gradient.setColorAt( 0.0, palette().color( QPalette::Mid ) ); + gradient.setColorAt( 0.5, palette().color( QPalette::Button ) ); + gradient.setColorAt( 1.0, palette().color( QPalette::Midlight ) ); + brush = QBrush( gradient ); + + break; + } + case QwtKnob::Flat: + default: + brush = palette().brush( QPalette::Button ); + } + + painter->setPen( pen ); + painter->setBrush( brush ); + painter->drawEllipse( aRect ); +} + + +/*! + \brief Draw the marker at the knob's front + + \param painter Painter + \param rect Bounding rectangle of the knob without scale + \param angle Angle of the marker in degrees + ( clockwise, 0 at the 12 o'clock position ) +*/ +void QwtKnob::drawMarker( QPainter *painter, + const QRectF &rect, double angle ) const +{ + if ( d_data->markerStyle == NoMarker || !isValid() ) + return; + + const double radians = qwtRadians( angle ); + const double sinA = -qFastSin( radians ); + const double cosA = qFastCos( radians ); + + const double xm = rect.center().x(); + const double ym = rect.center().y(); + const double margin = 4.0; + + double radius = 0.5 * ( rect.width() - d_data->borderWidth ) - margin; + if ( radius < 1.0 ) + radius = 1.0; + + int markerSize = d_data->markerSize; + if ( markerSize <= 0 ) + markerSize = qRound( 0.4 * radius ); + + switch ( d_data->markerStyle ) + { + case Notch: + case Nub: + { + const double dotWidth = + qMin( double( markerSize ), radius); + + const double dotCenterDist = radius - 0.5 * dotWidth; + if ( dotCenterDist > 0.0 ) + { + const QPointF center( xm - sinA * dotCenterDist, + ym - cosA * dotCenterDist ); + + QRectF ellipse( 0.0, 0.0, dotWidth, dotWidth ); + ellipse.moveCenter( center ); + + QColor c1 = palette().color( QPalette::Light ); + QColor c2 = palette().color( QPalette::Mid ); + + if ( d_data->markerStyle == Notch ) + qSwap( c1, c2 ); + + QLinearGradient gradient( + ellipse.topLeft(), ellipse.bottomRight() ); + gradient.setColorAt( 0.0, c1 ); + gradient.setColorAt( 1.0, c2 ); + + painter->setPen( Qt::NoPen ); + painter->setBrush( gradient ); + + painter->drawEllipse( ellipse ); + } + break; + } + case Dot: + { + const double dotWidth = + qMin( double( markerSize ), radius); + + const double dotCenterDist = radius - 0.5 * dotWidth; + if ( dotCenterDist > 0.0 ) + { + const QPointF center( xm - sinA * dotCenterDist, + ym - cosA * dotCenterDist ); + + QRectF ellipse( 0.0, 0.0, dotWidth, dotWidth ); + ellipse.moveCenter( center ); + + painter->setPen( Qt::NoPen ); + painter->setBrush( palette().color( QPalette::ButtonText ) ); + painter->drawEllipse( ellipse ); + } + + break; + } + case Tick: + { + const double rb = qMax( radius - markerSize, 1.0 ); + const double re = radius; + + const QLineF line( xm - sinA * rb, ym - cosA * rb, + xm - sinA * re, ym - cosA * re ); + + QPen pen( palette().color( QPalette::ButtonText ), 0 ); + pen.setCapStyle( Qt::FlatCap ); + painter->setPen( pen ); + painter->drawLine ( line ); + + break; + } + case Triangle: + { + const double rb = qMax( radius - markerSize, 1.0 ); + const double re = radius; + + painter->translate( rect.center() ); + painter->rotate( angle - 90.0 ); + + QPolygonF polygon; + polygon += QPointF( re, 0.0 ); + polygon += QPointF( rb, 0.5 * ( re - rb ) ); + polygon += QPointF( rb, -0.5 * ( re - rb ) ); + + painter->setPen( Qt::NoPen ); + painter->setBrush( palette().color( QPalette::ButtonText ) ); + painter->drawPolygon( polygon ); + + painter->resetTransform(); + + break; + } + default: + break; + } +} + +/*! + Draw the focus indicator + \param painter Painter +*/ +void QwtKnob::drawFocusIndicator( QPainter *painter ) const +{ + const QRect cr = contentsRect(); + + int w = d_data->knobWidth; + if ( w <= 0 ) + { + w = qMin( cr.width(), cr.height() ); + } + else + { + const int extent = qCeil( scaleDraw()->extent( font() ) ); + w += 2 * ( extent + d_data->scaleDist ); + } + + QRect focusRect( 0, 0, w, w ); + focusRect.moveCenter( cr.center() ); + + QwtPainter::drawFocusRect( painter, this, focusRect ); +} + +/*! + \brief Set the alignment of the knob + + Similar to a QLabel::alignment() the flags decide how + to align the knob inside of contentsRect(). + + The default setting is Qt::AlignCenter + + \param alignment Or'd alignment flags + + \sa alignment(), setKnobWidth(), knobRect() + */ +void QwtKnob::setAlignment( Qt::Alignment alignment ) +{ + if ( d_data->alignment != alignment ) + { + d_data->alignment = alignment; + update(); + } +} + +/*! + \return Alignment of the knob inside of contentsRect() + \sa setAlignment(), knobWidth(), knobRect() + */ +Qt::Alignment QwtKnob::alignment() const +{ + return d_data->alignment; +} + +/*! + \brief Change the knob's width. + + Setting a fixed value for the diameter of the knob + is helpful for aligning several knobs in a row. + + \param width New width + + \sa knobWidth(), setAlignment() + \note Modifies the sizePolicy() +*/ +void QwtKnob::setKnobWidth( int width ) +{ + width = qMax( width, 0 ); + + if ( width != d_data->knobWidth ) + { + QSizePolicy::Policy policy; + if ( width > 0 ) + policy = QSizePolicy::Minimum; + else + policy = QSizePolicy::MinimumExpanding; + + setSizePolicy( policy, policy ); + + d_data->knobWidth = width; + + updateGeometry(); + update(); + } +} + +//! Return the width of the knob +int QwtKnob::knobWidth() const +{ + return d_data->knobWidth; +} + +/*! + \brief Set the knob's border width + \param borderWidth new border width +*/ +void QwtKnob::setBorderWidth( int borderWidth ) +{ + d_data->borderWidth = qMax( borderWidth, 0 ); + + updateGeometry(); + update(); +} + +//! Return the border width +int QwtKnob::borderWidth() const +{ + return d_data->borderWidth; +} + +/*! + \brief Set the size of the marker + + When setting a size <= 0 the marker will + automatically scaled to 40% of the radius of the knob. + + \sa markerSize(), markerStyle() +*/ +void QwtKnob::setMarkerSize( int size ) +{ + if ( d_data->markerSize != size ) + { + d_data->markerSize = size; + update(); + } +} + +/*! + \return Marker size + \sa setMarkerSize() + */ +int QwtKnob::markerSize() const +{ + return d_data->markerSize; +} + +/*! + \return sizeHint() +*/ +QSize QwtKnob::sizeHint() const +{ + const QSize hint = qwtKnobSizeHint( this, 50 ); + return hint.expandedTo( QApplication::globalStrut() ); +} + +/*! + \return Minimum size hint + \sa sizeHint() +*/ +QSize QwtKnob::minimumSizeHint() const +{ + return qwtKnobSizeHint( this, 20 ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_knob.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_knob.h new file mode 100644 index 0000000..8a6f5c4 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_knob.h @@ -0,0 +1,178 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_KNOB_H +#define QWT_KNOB_H + +#include "qwt_global.h" +#include "qwt_abstract_slider.h" + +class QwtRoundScaleDraw; + +/*! + \brief The Knob Widget + + The QwtKnob widget imitates look and behavior of a volume knob on a radio. + It looks similar to QDial - not to QwtDial. + + The value range of a knob might be divided into several turns. + + The layout of the knob depends on the knobWidth(). + + - width > 0 + The diameter of the knob is fixed and the knob is aligned + according to the alignment() flags inside of the contentsRect(). + + - width <= 0 + The knob is extended to the minimum of width/height of the contentsRect() + and aligned in the other direction according to alignment(). + + Setting a fixed knobWidth() is helpful to align several knobs with different + scale labels. + + \image html knob.png +*/ + +class QWT_EXPORT QwtKnob: public QwtAbstractSlider +{ + Q_OBJECT + + Q_ENUMS ( KnobStyle MarkerStyle ) + + Q_PROPERTY( KnobStyle knobStyle READ knobStyle WRITE setKnobStyle ) + Q_PROPERTY( int knobWidth READ knobWidth WRITE setKnobWidth ) + Q_PROPERTY( Qt::Alignment alignment READ alignment WRITE setAlignment ) + Q_PROPERTY( double totalAngle READ totalAngle WRITE setTotalAngle ) + Q_PROPERTY( int numTurns READ numTurns WRITE setNumTurns ) + Q_PROPERTY( MarkerStyle markerStyle READ markerStyle WRITE setMarkerStyle ) + Q_PROPERTY( int markerSize READ markerSize WRITE setMarkerSize ) + Q_PROPERTY( int borderWidth READ borderWidth WRITE setBorderWidth ) + +public: + /*! + \brief Style of the knob surface + + Depending on the KnobStyle the surface of the knob is + filled from the brushes of the widget palette(). + + \sa setKnobStyle(), knobStyle() + */ + enum KnobStyle + { + //! Fill the knob with a brush from QPalette::Button. + Flat, + + //! Build a gradient from QPalette::Midlight and QPalette::Button + Raised, + + /*! + Build a gradient from QPalette::Midlight, QPalette::Button + and QPalette::Midlight + */ + Sunken, + + /*! + Build a radial gradient from QPalette::Button + like it is used for QDial in various Qt styles. + */ + Styled + }; + + /*! + \brief Marker type + + The marker indicates the current value on the knob + The default setting is a Notch marker. + + \sa setMarkerStyle(), setMarkerSize() + */ + enum MarkerStyle + { + //! Don't paint any marker + NoMarker = -1, + + //! Paint a single tick in QPalette::ButtonText color + Tick, + + //! Paint a triangle in QPalette::ButtonText color + Triangle, + + //! Paint a circle in QPalette::ButtonText color + Dot, + + /*! + Draw a raised ellipse with a gradient build from + QPalette::Light and QPalette::Mid + */ + Nub, + + /*! + Draw a sunken ellipse with a gradient build from + QPalette::Light and QPalette::Mid + */ + Notch + }; + + explicit QwtKnob( QWidget* parent = NULL ); + virtual ~QwtKnob(); + + void setAlignment( Qt::Alignment ); + Qt::Alignment alignment() const; + + void setKnobWidth( int ); + int knobWidth() const; + + void setNumTurns( int ); + int numTurns() const; + + void setTotalAngle ( double angle ); + double totalAngle() const; + + void setKnobStyle( KnobStyle ); + KnobStyle knobStyle() const; + + void setBorderWidth( int bw ); + int borderWidth() const; + + void setMarkerStyle( MarkerStyle ); + MarkerStyle markerStyle() const; + + void setMarkerSize( int ); + int markerSize() const; + + virtual QSize sizeHint() const; + virtual QSize minimumSizeHint() const; + + void setScaleDraw( QwtRoundScaleDraw * ); + + const QwtRoundScaleDraw *scaleDraw() const; + QwtRoundScaleDraw *scaleDraw(); + + QRect knobRect() const; + +protected: + virtual void paintEvent( QPaintEvent * ); + virtual void changeEvent( QEvent * ); + + virtual void drawKnob( QPainter *, const QRectF & ) const; + + virtual void drawFocusIndicator( QPainter * ) const; + + virtual void drawMarker( QPainter *, + const QRectF &, double arc ) const; + + virtual double scrolledTo( const QPoint & ) const; + virtual bool isScrollPosition( const QPoint & ) const; + +private: + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend.cpp new file mode 100644 index 0000000..afb3597 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend.cpp @@ -0,0 +1,811 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_legend.h" +#include "qwt_legend_label.h" +#include "qwt_dyngrid_layout.h" +#include "qwt_math.h" +#include "qwt_plot_item.h" +#include "qwt_painter.h" +#include +#include +#include +#include +#include +#include + +class QwtLegendMap +{ +public: + inline bool isEmpty() const { return d_entries.isEmpty(); } + + void insert( const QVariant &, const QList & ); + void remove( const QVariant & ); + + void removeWidget( const QWidget * ); + + QList legendWidgets( const QVariant & ) const; + QVariant itemInfo( const QWidget * ) const; + +private: + // we don't know anything about itemInfo and therefore don't have + // any key that can be used for a map or hashtab. + // But a simple linear list is o.k. here, as we will never have + // more than a few entries. + + class Entry + { + public: + QVariant itemInfo; + QList widgets; + }; + + QList< Entry > d_entries; +}; + +void QwtLegendMap::insert( const QVariant &itemInfo, + const QList &widgets ) +{ + for ( int i = 0; i < d_entries.size(); i++ ) + { + Entry &entry = d_entries[i]; + if ( entry.itemInfo == itemInfo ) + { + entry.widgets = widgets; + return; + } + } + + Entry newEntry; + newEntry.itemInfo = itemInfo; + newEntry.widgets = widgets; + + d_entries += newEntry; +} + +void QwtLegendMap::remove( const QVariant &itemInfo ) +{ + for ( int i = 0; i < d_entries.size(); i++ ) + { + Entry &entry = d_entries[i]; + if ( entry.itemInfo == itemInfo ) + { + d_entries.removeAt( i ); + return; + } + } +} + +void QwtLegendMap::removeWidget( const QWidget *widget ) +{ + QWidget *w = const_cast( widget ); + + for ( int i = 0; i < d_entries.size(); i++ ) + d_entries[ i ].widgets.removeAll( w ); +} + +QVariant QwtLegendMap::itemInfo( const QWidget *widget ) const +{ + if ( widget != NULL ) + { + QWidget *w = const_cast( widget ); + + for ( int i = 0; i < d_entries.size(); i++ ) + { + const Entry &entry = d_entries[i]; + if ( entry.widgets.indexOf( w ) >= 0 ) + return entry.itemInfo; + } + } + + return QVariant(); +} + +QList QwtLegendMap::legendWidgets( const QVariant &itemInfo ) const +{ + if ( itemInfo.isValid() ) + { + for ( int i = 0; i < d_entries.size(); i++ ) + { + const Entry &entry = d_entries[i]; + if ( entry.itemInfo == itemInfo ) + return entry.widgets; + } + } + + return QList(); +} + +class QwtLegend::PrivateData +{ +public: + PrivateData(): + itemMode( QwtLegendData::ReadOnly ), + view( NULL ) + { + } + + QwtLegendData::Mode itemMode; + QwtLegendMap itemMap; + + class LegendView; + LegendView *view; +}; + +class QwtLegend::PrivateData::LegendView: public QScrollArea +{ +public: + LegendView( QWidget *parent ): + QScrollArea( parent ) + { + contentsWidget = new QWidget( this ); + contentsWidget->setObjectName( "QwtLegendViewContents" ); + + setWidget( contentsWidget ); + setWidgetResizable( false ); + + viewport()->setObjectName( "QwtLegendViewport" ); + + // QScrollArea::setWidget internally sets autoFillBackground to true + // But we don't want a background. + contentsWidget->setAutoFillBackground( false ); + viewport()->setAutoFillBackground( false ); + } + + virtual bool event( QEvent *event ) + { + if ( event->type() == QEvent::PolishRequest ) + { + setFocusPolicy( Qt::NoFocus ); + } + + if ( event->type() == QEvent::Resize ) + { + // adjust the size to en/disable the scrollbars + // before QScrollArea adjusts the viewport size + + const QRect cr = contentsRect(); + + int w = cr.width(); + int h = contentsWidget->heightForWidth( cr.width() ); + if ( h > w ) + { + w -= verticalScrollBar()->sizeHint().width(); + h = contentsWidget->heightForWidth( w ); + } + + contentsWidget->resize( w, h ); + } + + return QScrollArea::event( event ); + } + + virtual bool viewportEvent( QEvent *event ) + { + bool ok = QScrollArea::viewportEvent( event ); + + if ( event->type() == QEvent::Resize ) + { + layoutContents(); + } + return ok; + } + + QSize viewportSize( int w, int h ) const + { + const int sbHeight = horizontalScrollBar()->sizeHint().height(); + const int sbWidth = verticalScrollBar()->sizeHint().width(); + + const int cw = contentsRect().width(); + const int ch = contentsRect().height(); + + int vw = cw; + int vh = ch; + + if ( w > vw ) + vh -= sbHeight; + + if ( h > vh ) + { + vw -= sbWidth; + if ( w > vw && vh == ch ) + vh -= sbHeight; + } + return QSize( vw, vh ); + } + + void layoutContents() + { + const QwtDynGridLayout *tl = qobject_cast( + contentsWidget->layout() ); + if ( tl == NULL ) + return; + + const QSize visibleSize = viewport()->contentsRect().size(); + + const int minW = int( tl->maxItemWidth() ) + 2 * tl->margin(); + + int w = qMax( visibleSize.width(), minW ); + int h = qMax( tl->heightForWidth( w ), visibleSize.height() ); + + const int vpWidth = viewportSize( w, h ).width(); + if ( w > vpWidth ) + { + w = qMax( vpWidth, minW ); + h = qMax( tl->heightForWidth( w ), visibleSize.height() ); + } + + contentsWidget->resize( w, h ); + } + + QWidget *contentsWidget; +}; + +/*! + Constructor + \param parent Parent widget +*/ +QwtLegend::QwtLegend( QWidget *parent ): + QwtAbstractLegend( parent ) +{ + setFrameStyle( NoFrame ); + + d_data = new QwtLegend::PrivateData; + + d_data->view = new QwtLegend::PrivateData::LegendView( this ); + d_data->view->setObjectName( "QwtLegendView" ); + d_data->view->setFrameStyle( NoFrame ); + + QwtDynGridLayout *gridLayout = new QwtDynGridLayout( + d_data->view->contentsWidget ); + gridLayout->setAlignment( Qt::AlignHCenter | Qt::AlignTop ); + + d_data->view->contentsWidget->installEventFilter( this ); + + QVBoxLayout *layout = new QVBoxLayout( this ); + layout->setContentsMargins( 0, 0, 0, 0 ); + layout->addWidget( d_data->view ); +} + +//! Destructor +QwtLegend::~QwtLegend() +{ + delete d_data; +} + +/*! + \brief Set the maximum number of entries in a row + + F.e when the maximum is set to 1 all items are aligned + vertically. 0 means unlimited + + \param numColums Maximum number of entries in a row + + \sa maxColumns(), QwtDynGridLayout::setMaxColumns() + */ +void QwtLegend::setMaxColumns( uint numColums ) +{ + QwtDynGridLayout *tl = qobject_cast( + d_data->view->contentsWidget->layout() ); + if ( tl ) + tl->setMaxColumns( numColums ); +} + +/*! + \return Maximum number of entries in a row + \sa setMaxColumns(), QwtDynGridLayout::maxColumns() + */ +uint QwtLegend::maxColumns() const +{ + uint maxCols = 0; + + const QwtDynGridLayout *tl = qobject_cast( + d_data->view->contentsWidget->layout() ); + if ( tl ) + maxCols = tl->maxColumns(); + + return maxCols; +} + +/*! + \brief Set the default mode for legend labels + + Legend labels will be constructed according to the + attributes in a QwtLegendData object. When it doesn't + contain a value for the QwtLegendData::ModeRole the + label will be initialized with the default mode of the legend. + + \param mode Default item mode + + \sa itemMode(), QwtLegendData::value(), QwtPlotItem::legendData() + \note Changing the mode doesn't have any effect on existing labels. + */ +void QwtLegend::setDefaultItemMode( QwtLegendData::Mode mode ) +{ + d_data->itemMode = mode; +} + +/*! + \return Default item mode + \sa setDefaultItemMode() +*/ +QwtLegendData::Mode QwtLegend::defaultItemMode() const +{ + return d_data->itemMode; +} + +/*! + The contents widget is the only child of the viewport of + the internal QScrollArea and the parent widget of all legend items. + + \return Container widget of the legend items +*/ +QWidget *QwtLegend::contentsWidget() +{ + return d_data->view->contentsWidget; +} + +/*! + \return Horizontal scrollbar + \sa verticalScrollBar() +*/ +QScrollBar *QwtLegend::horizontalScrollBar() const +{ + return d_data->view->horizontalScrollBar(); +} + +/*! + \return Vertical scrollbar + \sa horizontalScrollBar() +*/ +QScrollBar *QwtLegend::verticalScrollBar() const +{ + return d_data->view->verticalScrollBar(); +} + +/*! + The contents widget is the only child of the viewport of + the internal QScrollArea and the parent widget of all legend items. + + \return Container widget of the legend items + +*/ +const QWidget *QwtLegend::contentsWidget() const +{ + return d_data->view->contentsWidget; +} + +/*! + \brief Update the entries for an item + + \param itemInfo Info for an item + \param data List of legend entry attributes for the item + */ +void QwtLegend::updateLegend( const QVariant &itemInfo, + const QList &data ) +{ + QList widgetList = legendWidgets( itemInfo ); + + if ( widgetList.size() != data.size() ) + { + QLayout *contentsLayout = d_data->view->contentsWidget->layout(); + + while ( widgetList.size() > data.size() ) + { + QWidget *w = widgetList.takeLast(); + + contentsLayout->removeWidget( w ); + + // updates might be triggered by signals from the legend widget + // itself. So we better don't delete it here. + + w->hide(); + w->deleteLater(); + } + + for ( int i = widgetList.size(); i < data.size(); i++ ) + { + QWidget *widget = createWidget( data[i] ); + + if ( contentsLayout ) + contentsLayout->addWidget( widget ); + + if ( isVisible() ) + { + // QLayout does a delayed show, with the effect, that + // the size hint will be wrong, when applications + // call replot() right after changing the list + // of plot items. So we better do the show now. + + widget->setVisible( true ); + } + + widgetList += widget; + } + + if ( widgetList.isEmpty() ) + { + d_data->itemMap.remove( itemInfo ); + } + else + { + d_data->itemMap.insert( itemInfo, widgetList ); + } + + updateTabOrder(); + } + + for ( int i = 0; i < data.size(); i++ ) + updateWidget( widgetList[i], data[i] ); +} + +/*! + \brief Create a widget to be inserted into the legend + + The default implementation returns a QwtLegendLabel. + + \param data Attributes of the legend entry + \return Widget representing data on the legend + + \note updateWidget() will called soon after createWidget() + with the same attributes. + */ +QWidget *QwtLegend::createWidget( const QwtLegendData &data ) const +{ + Q_UNUSED( data ); + + QwtLegendLabel *label = new QwtLegendLabel(); + label->setItemMode( defaultItemMode() ); + + connect( label, SIGNAL( clicked() ), SLOT( itemClicked() ) ); + connect( label, SIGNAL( checked( bool ) ), SLOT( itemChecked( bool ) ) ); + + return label; +} + +/*! + \brief Update the widget + + \param widget Usually a QwtLegendLabel + \param data Attributes to be displayed + + \sa createWidget() + \note When widget is no QwtLegendLabel updateWidget() does nothing. + */ +void QwtLegend::updateWidget( QWidget *widget, const QwtLegendData &data ) +{ + QwtLegendLabel *label = qobject_cast( widget ); + if ( label ) + { + label->setData( data ); + if ( !data.value( QwtLegendData::ModeRole ).isValid() ) + { + // use the default mode, when there is no specific + // hint from the legend data + + label->setItemMode( defaultItemMode() ); + } + } +} + +void QwtLegend::updateTabOrder() +{ + QLayout *contentsLayout = d_data->view->contentsWidget->layout(); + if ( contentsLayout ) + { + // set tab focus chain + + QWidget *w = NULL; + + for ( int i = 0; i < contentsLayout->count(); i++ ) + { + QLayoutItem *item = contentsLayout->itemAt( i ); + if ( w && item->widget() ) + QWidget::setTabOrder( w, item->widget() ); + + w = item->widget(); + } + } +} + +//! Return a size hint. +QSize QwtLegend::sizeHint() const +{ + QSize hint = d_data->view->contentsWidget->sizeHint(); + hint += QSize( 2 * frameWidth(), 2 * frameWidth() ); + + return hint; +} + +/*! + \return The preferred height, for a width. + \param width Width +*/ +int QwtLegend::heightForWidth( int width ) const +{ + width -= 2 * frameWidth(); + + int h = d_data->view->contentsWidget->heightForWidth( width ); + if ( h >= 0 ) + h += 2 * frameWidth(); + + return h; +} + + +/*! + Handle QEvent::ChildRemoved andQEvent::LayoutRequest events + for the contentsWidget(). + + \param object Object to be filtered + \param event Event + + \return Forwarded to QwtAbstractLegend::eventFilter() +*/ +bool QwtLegend::eventFilter( QObject *object, QEvent *event ) +{ + if ( object == d_data->view->contentsWidget ) + { + switch ( event->type() ) + { + case QEvent::ChildRemoved: + { + const QChildEvent *ce = + static_cast(event); + if ( ce->child()->isWidgetType() ) + { + QWidget *w = static_cast< QWidget * >( ce->child() ); + d_data->itemMap.removeWidget( w ); + } + break; + } + case QEvent::LayoutRequest: + { + d_data->view->layoutContents(); + + if ( parentWidget() && parentWidget()->layout() == NULL ) + { + /* + We want the parent widget ( usually QwtPlot ) to recalculate + its layout, when the contentsWidget has changed. But + because of the scroll view we have to forward the LayoutRequest + event manually. + + We don't use updateGeometry() because it doesn't post LayoutRequest + events when the legend is hidden. But we want the + parent widget notified, so it can show/hide the legend + depending on its items. + */ + QApplication::postEvent( parentWidget(), + new QEvent( QEvent::LayoutRequest ) ); + } + break; + } + default: + break; + } + } + + return QwtAbstractLegend::eventFilter( object, event ); +} + +/*! + Called internally when the legend has been clicked on. + Emits a clicked() signal. +*/ +void QwtLegend::itemClicked() +{ + QWidget *w = qobject_cast( sender() ); + if ( w ) + { + const QVariant itemInfo = d_data->itemMap.itemInfo( w ); + if ( itemInfo.isValid() ) + { + const QList widgetList = + d_data->itemMap.legendWidgets( itemInfo ); + + const int index = widgetList.indexOf( w ); + if ( index >= 0 ) + Q_EMIT clicked( itemInfo, index ); + } + } +} + +/*! + Called internally when the legend has been checked + Emits a checked() signal. +*/ +void QwtLegend::itemChecked( bool on ) +{ + QWidget *w = qobject_cast( sender() ); + if ( w ) + { + const QVariant itemInfo = d_data->itemMap.itemInfo( w ); + if ( itemInfo.isValid() ) + { + const QList widgetList = + d_data->itemMap.legendWidgets( itemInfo ); + + const int index = widgetList.indexOf( w ); + if ( index >= 0 ) + Q_EMIT checked( itemInfo, on, index ); + } + } +} + +/*! + Render the legend into a given rectangle. + + \param painter Painter + \param rect Bounding rectangle + \param fillBackground When true, fill rect with the widget background + + \sa renderLegend() is used by QwtPlotRenderer - not by QwtLegend itself +*/ +void QwtLegend::renderLegend( QPainter *painter, + const QRectF &rect, bool fillBackground ) const +{ + if ( d_data->itemMap.isEmpty() ) + return; + + if ( fillBackground ) + { + if ( autoFillBackground() || + testAttribute( Qt::WA_StyledBackground ) ) + { + QwtPainter::drawBackgound( painter, rect, this ); + } + } + + const QwtDynGridLayout *legendLayout = + qobject_cast( contentsWidget()->layout() ); + if ( legendLayout == NULL ) + return; + + int left, right, top, bottom; + getContentsMargins( &left, &top, &right, &bottom ); + + QRect layoutRect; + layoutRect.setLeft( qCeil( rect.left() ) + left ); + layoutRect.setTop( qCeil( rect.top() ) + top ); + layoutRect.setRight( qFloor( rect.right() ) - right ); + layoutRect.setBottom( qFloor( rect.bottom() ) - bottom ); + + uint numCols = legendLayout->columnsForWidth( layoutRect.width() ); + QList itemRects = + legendLayout->layoutItems( layoutRect, numCols ); + + int index = 0; + + for ( int i = 0; i < legendLayout->count(); i++ ) + { + QLayoutItem *item = legendLayout->itemAt( i ); + QWidget *w = item->widget(); + if ( w ) + { + painter->save(); + + painter->setClipRect( itemRects[index], Qt::IntersectClip ); + renderItem( painter, w, itemRects[index], fillBackground ); + + index++; + painter->restore(); + } + } +} + +/*! + Render a legend entry into a given rectangle. + + \param painter Painter + \param widget Widget representing a legend entry + \param rect Bounding rectangle + \param fillBackground When true, fill rect with the widget background + + \note When widget is not derived from QwtLegendLabel renderItem + does nothing beside the background +*/ +void QwtLegend::renderItem( QPainter *painter, + const QWidget *widget, const QRectF &rect, bool fillBackground ) const +{ + if ( fillBackground ) + { + if ( widget->autoFillBackground() || + widget->testAttribute( Qt::WA_StyledBackground ) ) + { + QwtPainter::drawBackgound( painter, rect, widget ); + } + } + + const QwtLegendLabel *label = qobject_cast( widget ); + if ( label ) + { + // icon + + const QwtGraphic &icon = label->data().icon(); + const QSizeF sz = icon.defaultSize(); + + const QRectF iconRect( rect.x() + label->margin(), + rect.center().y() - 0.5 * sz.height(), + sz.width(), sz.height() ); + + icon.render( painter, iconRect, Qt::KeepAspectRatio ); + + // title + + QRectF titleRect = rect; + titleRect.setX( iconRect.right() + 2 * label->spacing() ); + + painter->setFont( label->font() ); + painter->setPen( label->palette().color( QPalette::Text ) ); + const_cast< QwtLegendLabel *>( label )->drawText( painter, titleRect ); + } +} + +/*! + \return List of widgets associated to a item + \param itemInfo Info about an item + \sa legendWidget(), itemInfo(), QwtPlot::itemToInfo() + */ +QList QwtLegend::legendWidgets( const QVariant &itemInfo ) const +{ + return d_data->itemMap.legendWidgets( itemInfo ); +} + +/*! + \return First widget in the list of widgets associated to an item + \param itemInfo Info about an item + \sa itemInfo(), QwtPlot::itemToInfo() + \note Almost all types of items have only one widget +*/ +QWidget *QwtLegend::legendWidget( const QVariant &itemInfo ) const +{ + const QList list = d_data->itemMap.legendWidgets( itemInfo ); + if ( list.isEmpty() ) + return NULL; + + return list[0]; +} + +/*! + Find the item that is associated to a widget + + \param widget Widget on the legend + \return Associated item info + \sa legendWidget() + */ +QVariant QwtLegend::itemInfo( const QWidget *widget ) const +{ + return d_data->itemMap.itemInfo( widget ); +} + +//! \return True, when no item is inserted +bool QwtLegend::isEmpty() const +{ + return d_data->itemMap.isEmpty(); +} + +/*! + Return the extent, that is needed for the scrollbars + + \param orientation Orientation ( + \return The width of the vertical scrollbar for Qt::Horizontal and v.v. + */ +int QwtLegend::scrollExtent( Qt::Orientation orientation ) const +{ + int extent = 0; + + if ( orientation == Qt::Horizontal ) + extent = verticalScrollBar()->sizeHint().width(); + else + extent = horizontalScrollBar()->sizeHint().height(); + + return extent; +} + diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend.h new file mode 100644 index 0000000..6aefb0f --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend.h @@ -0,0 +1,117 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_LEGEND_H +#define QWT_LEGEND_H + +#include "qwt_global.h" +#include "qwt_abstract_legend.h" +#include + +class QScrollBar; + +/*! + \brief The legend widget + + The QwtLegend widget is a tabular arrangement of legend items. Legend + items might be any type of widget, but in general they will be + a QwtLegendLabel. + + \sa QwtLegendLabel, QwtPlotItem, QwtPlot +*/ + +class QWT_EXPORT QwtLegend : public QwtAbstractLegend +{ + Q_OBJECT + +public: + explicit QwtLegend( QWidget *parent = NULL ); + virtual ~QwtLegend(); + + void setMaxColumns( uint numColums ); + uint maxColumns() const; + + void setDefaultItemMode( QwtLegendData::Mode ); + QwtLegendData::Mode defaultItemMode() const; + + QWidget *contentsWidget(); + const QWidget *contentsWidget() const; + + QWidget *legendWidget( const QVariant & ) const; + QList legendWidgets( const QVariant & ) const; + + QVariant itemInfo( const QWidget * ) const; + + virtual bool eventFilter( QObject *, QEvent * ); + + virtual QSize sizeHint() const; + virtual int heightForWidth( int w ) const; + + QScrollBar *horizontalScrollBar() const; + QScrollBar *verticalScrollBar() const; + + virtual void renderLegend( QPainter *, + const QRectF &, bool fillBackground ) const; + + virtual void renderItem( QPainter *, + const QWidget *, const QRectF &, bool fillBackground ) const; + + virtual bool isEmpty() const; + virtual int scrollExtent( Qt::Orientation ) const; + +Q_SIGNALS: + /*! + A signal which is emitted when the user has clicked on + a legend label, which is in QwtLegendData::Clickable mode. + + \param itemInfo Info for the item item of the + selected legend item + \param index Index of the legend label in the list of widgets + that are associated with the plot item + + \note clicks are disabled as default + \sa setDefaultItemMode(), defaultItemMode(), QwtPlot::itemToInfo() + */ + void clicked( const QVariant &itemInfo, int index ); + + /*! + A signal which is emitted when the user has clicked on + a legend label, which is in QwtLegendData::Checkable mode + + \param itemInfo Info for the item of the + selected legend label + \param index Index of the legend label in the list of widgets + that are associated with the plot item + \param on True when the legend label is checked + + \note clicks are disabled as default + \sa setDefaultItemMode(), defaultItemMode(), QwtPlot::itemToInfo() + */ + void checked( const QVariant &itemInfo, bool on, int index ); + +public Q_SLOTS: + virtual void updateLegend( const QVariant &, + const QList & ); + +protected Q_SLOTS: + void itemClicked(); + void itemChecked( bool ); + +protected: + virtual QWidget *createWidget( const QwtLegendData & ) const; + virtual void updateWidget( QWidget *widget, const QwtLegendData &data ); + +private: + void updateTabOrder(); + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend_data.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend_data.cpp new file mode 100644 index 0000000..9d346e9 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend_data.cpp @@ -0,0 +1,129 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_legend_data.h" + +//! Constructor +QwtLegendData::QwtLegendData() +{ +} + +//! Destructor +QwtLegendData::~QwtLegendData() +{ +} + +/*! + Set the legend attributes + + QwtLegendData actually is a QMap with some + convenience interfaces + + \param map Values + \sa values() + */ +void QwtLegendData::setValues( const QMap &map ) +{ + d_map = map; +} + +/*! + \return Legend attributes + \sa setValues() + */ +const QMap &QwtLegendData::values() const +{ + return d_map; +} + +/*! + \param role Attribute role + \return True, when the internal map has an entry for role + */ +bool QwtLegendData::hasRole( int role ) const +{ + return d_map.contains( role ); +} + +/*! + Set an attribute value + + \param role Attribute role + \param data Attribute value + + \sa value() + */ +void QwtLegendData::setValue( int role, const QVariant &data ) +{ + d_map[role] = data; +} + +/*! + \param role Attribute role + \return Attribute value for a specific role + */ +QVariant QwtLegendData::value( int role ) const +{ + if ( !d_map.contains( role ) ) + return QVariant(); + + return d_map[role]; +} + +//! \return True, when the internal map is empty +bool QwtLegendData::isValid() const +{ + return !d_map.isEmpty(); +} + +//! \return Value of the TitleRole attribute +QwtText QwtLegendData::title() const +{ + QwtText text; + + const QVariant titleValue = value( QwtLegendData::TitleRole ); + if ( titleValue.canConvert() ) + { + text = qvariant_cast( titleValue ); + } + else if ( titleValue.canConvert() ) + { + text.setText( qvariant_cast( titleValue ) ); + } + + return text; +} + +//! \return Value of the IconRole attribute +QwtGraphic QwtLegendData::icon() const +{ + const QVariant iconValue = value( QwtLegendData::IconRole ); + + QwtGraphic graphic; + if ( iconValue.canConvert() ) + { + graphic = qvariant_cast( iconValue ); + } + + return graphic; +} + +//! \return Value of the ModeRole attribute +QwtLegendData::Mode QwtLegendData::mode() const +{ + const QVariant modeValue = value( QwtLegendData::ModeRole ); + if ( modeValue.canConvert() ) + { + const int mode = qvariant_cast( modeValue ); + return static_cast( mode ); + } + + return QwtLegendData::ReadOnly; +} + diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend_data.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend_data.h new file mode 100644 index 0000000..c42debc --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend_data.h @@ -0,0 +1,87 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_LEGEND_DATA_H +#define QWT_LEGEND_DATA_H + +#include "qwt_global.h" +#include "qwt_text.h" +#include "qwt_graphic.h" +#include +#include +#include + +/*! + \brief Attributes of an entry on a legend + + QwtLegendData is an abstract container ( like QAbstractModel ) + to exchange attributes, that are only known between to + the plot item and the legend. + + By overloading QwtPlotItem::legendData() any other set of attributes + could be used, that can be handled by a modified ( or completely + different ) implementation of a legend. + + \sa QwtLegend, QwtPlotLegendItem + \note The stockchart example implements a legend as a tree + with checkable items + */ +class QWT_EXPORT QwtLegendData +{ +public: + //! Mode defining how a legend entry interacts + enum Mode + { + //! The legend item is not interactive, like a label + ReadOnly, + + //! The legend item is clickable, like a push button + Clickable, + + //! The legend item is checkable, like a checkable button + Checkable + }; + + //! Identifier how to interprete a QVariant + enum Role + { + // The value is a Mode + ModeRole, + + // The value is a title + TitleRole, + + // The value is an icon + IconRole, + + // Values < UserRole are reserved for internal use + UserRole = 32 + }; + + QwtLegendData(); + ~QwtLegendData(); + + void setValues( const QMap & ); + const QMap &values() const; + + void setValue( int role, const QVariant & ); + QVariant value( int role ) const; + + bool hasRole( int role ) const; + bool isValid() const; + + QwtGraphic icon() const; + QwtText title() const; + Mode mode() const; + +private: + QMap d_map; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend_label.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend_label.cpp new file mode 100644 index 0000000..674c0bd --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend_label.cpp @@ -0,0 +1,421 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_legend_label.h" +#include "qwt_legend_data.h" +#include "qwt_math.h" +#include "qwt_painter.h" +#include "qwt_symbol.h" +#include "qwt_graphic.h" +#include +#include +#include +#include +#include +#include +#include + +static const int ButtonFrame = 2; +static const int Margin = 2; + +static QSize buttonShift( const QwtLegendLabel *w ) +{ + QStyleOption option; + option.init( w ); + + const int ph = w->style()->pixelMetric( + QStyle::PM_ButtonShiftHorizontal, &option, w ); + const int pv = w->style()->pixelMetric( + QStyle::PM_ButtonShiftVertical, &option, w ); + return QSize( ph, pv ); +} + +class QwtLegendLabel::PrivateData +{ +public: + PrivateData(): + itemMode( QwtLegendData::ReadOnly ), + isDown( false ), + spacing( Margin ) + { + } + + QwtLegendData::Mode itemMode; + QwtLegendData legendData; + bool isDown; + + QPixmap icon; + + int spacing; +}; + +/*! + Set the attributes of the legend label + + \param legendData Attributes of the label + \sa data() + */ +void QwtLegendLabel::setData( const QwtLegendData &legendData ) +{ + d_data->legendData = legendData; + + const bool doUpdate = updatesEnabled(); + setUpdatesEnabled( false ); + + setText( legendData.title() ); + setIcon( legendData.icon().toPixmap() ); + + if ( legendData.hasRole( QwtLegendData::ModeRole ) ) + setItemMode( legendData.mode() ); + + if ( doUpdate ) + { + setUpdatesEnabled( true ); + update(); + } +} + +/*! + \return Attributes of the label + \sa setData(), QwtPlotItem::legendData() + */ +const QwtLegendData &QwtLegendLabel::data() const +{ + return d_data->legendData; +} + +/*! + \param parent Parent widget +*/ +QwtLegendLabel::QwtLegendLabel( QWidget *parent ): + QwtTextLabel( parent ) +{ + d_data = new PrivateData; + setMargin( Margin ); + setIndent( Margin ); +} + +//! Destructor +QwtLegendLabel::~QwtLegendLabel() +{ + delete d_data; + d_data = NULL; +} + +/*! + Set the text to the legend item + + \param text Text label + \sa QwtTextLabel::text() +*/ +void QwtLegendLabel::setText( const QwtText &text ) +{ + const int flags = Qt::AlignLeft | Qt::AlignVCenter + | Qt::TextExpandTabs | Qt::TextWordWrap; + + QwtText txt = text; + txt.setRenderFlags( flags ); + + QwtTextLabel::setText( txt ); +} + +/*! + Set the item mode + The default is QwtLegendData::ReadOnly + + \param mode Item mode + \sa itemMode() +*/ +void QwtLegendLabel::setItemMode( QwtLegendData::Mode mode ) +{ + if ( mode != d_data->itemMode ) + { + d_data->itemMode = mode; + d_data->isDown = false; + + setFocusPolicy( ( mode != QwtLegendData::ReadOnly ) + ? Qt::TabFocus : Qt::NoFocus ); + setMargin( ButtonFrame + Margin ); + + updateGeometry(); + } +} + +/*! + \return Item mode + \sa setItemMode() +*/ +QwtLegendData::Mode QwtLegendLabel::itemMode() const +{ + return d_data->itemMode; +} + +/*! + Assign the icon + + \param icon Pixmap representing a plot item + + \sa icon(), QwtPlotItem::legendIcon() +*/ +void QwtLegendLabel::setIcon( const QPixmap &icon ) +{ + d_data->icon = icon; + + int indent = margin() + d_data->spacing; + if ( icon.width() > 0 ) + indent += icon.width() + d_data->spacing; + + setIndent( indent ); +} + +/*! + \return Pixmap representing a plot item + \sa setIcon() +*/ +QPixmap QwtLegendLabel::icon() const +{ + return d_data->icon; +} + +/*! + \brief Change the spacing between icon and text + + \param spacing Spacing + \sa spacing(), QwtTextLabel::margin() +*/ +void QwtLegendLabel::setSpacing( int spacing ) +{ + spacing = qMax( spacing, 0 ); + if ( spacing != d_data->spacing ) + { + d_data->spacing = spacing; + + int indent = margin() + d_data->spacing; + if ( d_data->icon.width() > 0 ) + indent += d_data->icon.width() + d_data->spacing; + + setIndent( indent ); + } +} + +/*! + \return Spacing between icon and text + \sa setSpacing(), QwtTextLabel::margin() +*/ +int QwtLegendLabel::spacing() const +{ + return d_data->spacing; +} + +/*! + Check/Uncheck a the item + + \param on check/uncheck + \sa setItemMode() +*/ +void QwtLegendLabel::setChecked( bool on ) +{ + if ( d_data->itemMode == QwtLegendData::Checkable ) + { + const bool isBlocked = signalsBlocked(); + blockSignals( true ); + + setDown( on ); + + blockSignals( isBlocked ); + } +} + +//! Return true, if the item is checked +bool QwtLegendLabel::isChecked() const +{ + return d_data->itemMode == QwtLegendData::Checkable && isDown(); +} + +//! Set the item being down +void QwtLegendLabel::setDown( bool down ) +{ + if ( down == d_data->isDown ) + return; + + d_data->isDown = down; + update(); + + if ( d_data->itemMode == QwtLegendData::Clickable ) + { + if ( d_data->isDown ) + Q_EMIT pressed(); + else + { + Q_EMIT released(); + Q_EMIT clicked(); + } + } + + if ( d_data->itemMode == QwtLegendData::Checkable ) + Q_EMIT checked( d_data->isDown ); +} + +//! Return true, if the item is down +bool QwtLegendLabel::isDown() const +{ + return d_data->isDown; +} + +//! Return a size hint +QSize QwtLegendLabel::sizeHint() const +{ + QSize sz = QwtTextLabel::sizeHint(); + sz.setHeight( qMax( sz.height(), d_data->icon.height() + 4 ) ); + + if ( d_data->itemMode != QwtLegendData::ReadOnly ) + { + sz += buttonShift( this ); + sz = sz.expandedTo( QApplication::globalStrut() ); + } + + return sz; +} + +//! Paint event +void QwtLegendLabel::paintEvent( QPaintEvent *e ) +{ + const QRect cr = contentsRect(); + + QPainter painter( this ); + painter.setClipRegion( e->region() ); + + if ( d_data->isDown ) + { + qDrawWinButton( &painter, 0, 0, width(), height(), + palette(), true ); + } + + painter.save(); + + if ( d_data->isDown ) + { + const QSize shiftSize = buttonShift( this ); + painter.translate( shiftSize.width(), shiftSize.height() ); + } + + painter.setClipRect( cr ); + + drawContents( &painter ); + + if ( !d_data->icon.isNull() ) + { + QRect iconRect = cr; + iconRect.setX( iconRect.x() + margin() ); + if ( d_data->itemMode != QwtLegendData::ReadOnly ) + iconRect.setX( iconRect.x() + ButtonFrame ); + + iconRect.setSize( d_data->icon.size() ); + iconRect.moveCenter( QPoint( iconRect.center().x(), cr.center().y() ) ); + + painter.drawPixmap( iconRect, d_data->icon ); + } + + painter.restore(); +} + +//! Handle mouse press events +void QwtLegendLabel::mousePressEvent( QMouseEvent *e ) +{ + if ( e->button() == Qt::LeftButton ) + { + switch ( d_data->itemMode ) + { + case QwtLegendData::Clickable: + { + setDown( true ); + return; + } + case QwtLegendData::Checkable: + { + setDown( !isDown() ); + return; + } + default:; + } + } + QwtTextLabel::mousePressEvent( e ); +} + +//! Handle mouse release events +void QwtLegendLabel::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( e->button() == Qt::LeftButton ) + { + switch ( d_data->itemMode ) + { + case QwtLegendData::Clickable: + { + setDown( false ); + return; + } + case QwtLegendData::Checkable: + { + return; // do nothing, but accept + } + default:; + } + } + QwtTextLabel::mouseReleaseEvent( e ); +} + +//! Handle key press events +void QwtLegendLabel::keyPressEvent( QKeyEvent *e ) +{ + if ( e->key() == Qt::Key_Space ) + { + switch ( d_data->itemMode ) + { + case QwtLegendData::Clickable: + { + if ( !e->isAutoRepeat() ) + setDown( true ); + return; + } + case QwtLegendData::Checkable: + { + if ( !e->isAutoRepeat() ) + setDown( !isDown() ); + return; + } + default:; + } + } + + QwtTextLabel::keyPressEvent( e ); +} + +//! Handle key release events +void QwtLegendLabel::keyReleaseEvent( QKeyEvent *e ) +{ + if ( e->key() == Qt::Key_Space ) + { + switch ( d_data->itemMode ) + { + case QwtLegendData::Clickable: + { + if ( !e->isAutoRepeat() ) + setDown( false ); + return; + } + case QwtLegendData::Checkable: + { + return; // do nothing, but accept + } + default:; + } + } + + QwtTextLabel::keyReleaseEvent( e ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend_label.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend_label.h new file mode 100644 index 0000000..9906b03 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_legend_label.h @@ -0,0 +1,80 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_LEGEND_LABEL_H +#define QWT_LEGEND_LABEL_H + +#include "qwt_global.h" +#include "qwt_legend_data.h" +#include "qwt_text.h" +#include "qwt_text_label.h" +#include + +class QwtLegendData; + +/*! + \brief A widget representing something on a QwtLegend. +*/ +class QWT_EXPORT QwtLegendLabel: public QwtTextLabel +{ + Q_OBJECT +public: + explicit QwtLegendLabel( QWidget *parent = 0 ); + virtual ~QwtLegendLabel(); + + void setData( const QwtLegendData & ); + const QwtLegendData &data() const; + + void setItemMode( QwtLegendData::Mode ); + QwtLegendData::Mode itemMode() const; + + void setSpacing( int spacing ); + int spacing() const; + + virtual void setText( const QwtText & ); + + void setIcon( const QPixmap & ); + QPixmap icon() const; + + virtual QSize sizeHint() const; + + bool isChecked() const; + +public Q_SLOTS: + void setChecked( bool on ); + +Q_SIGNALS: + //! Signal, when the legend item has been clicked + void clicked(); + + //! Signal, when the legend item has been pressed + void pressed(); + + //! Signal, when the legend item has been released + void released(); + + //! Signal, when the legend item has been toggled + void checked( bool ); + +protected: + void setDown( bool ); + bool isDown() const; + + virtual void paintEvent( QPaintEvent * ); + virtual void mousePressEvent( QMouseEvent * ); + virtual void mouseReleaseEvent( QMouseEvent * ); + virtual void keyPressEvent( QKeyEvent * ); + virtual void keyReleaseEvent( QKeyEvent * ); + +private: + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_magnifier.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_magnifier.cpp new file mode 100644 index 0000000..c131f5f --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_magnifier.cpp @@ -0,0 +1,492 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_magnifier.h" +#include "qwt_math.h" +#include +#include + +class QwtMagnifier::PrivateData +{ +public: + PrivateData(): + isEnabled( false ), + wheelFactor( 0.9 ), + wheelModifiers( Qt::NoModifier ), + mouseFactor( 0.95 ), + mouseButton( Qt::RightButton ), + mouseButtonModifiers( Qt::NoModifier ), + keyFactor( 0.9 ), + zoomInKey( Qt::Key_Plus ), + zoomInKeyModifiers( Qt::NoModifier ), + zoomOutKey( Qt::Key_Minus ), + zoomOutKeyModifiers( Qt::NoModifier ), + mousePressed( false ) + { + } + + bool isEnabled; + + double wheelFactor; + Qt::KeyboardModifiers wheelModifiers; + + double mouseFactor; + + Qt::MouseButton mouseButton; + Qt::KeyboardModifiers mouseButtonModifiers; + + double keyFactor; + + int zoomInKey; + Qt::KeyboardModifiers zoomInKeyModifiers; + + int zoomOutKey; + Qt::KeyboardModifiers zoomOutKeyModifiers; + + bool mousePressed; + bool hasMouseTracking; + QPoint mousePos; +}; + +/*! + Constructor + \param parent Widget to be magnified +*/ +QwtMagnifier::QwtMagnifier( QWidget *parent ): + QObject( parent ) +{ + d_data = new PrivateData(); + setEnabled( true ); +} + +//! Destructor +QwtMagnifier::~QwtMagnifier() +{ + delete d_data; +} + +/*! + \brief En/disable the magnifier + + When enabled is true an event filter is installed for + the observed widget, otherwise the event filter is removed. + + \param on true or false + \sa isEnabled(), eventFilter() +*/ +void QwtMagnifier::setEnabled( bool on ) +{ + if ( d_data->isEnabled != on ) + { + d_data->isEnabled = on; + + QObject *o = parent(); + if ( o ) + { + if ( d_data->isEnabled ) + o->installEventFilter( this ); + else + o->removeEventFilter( this ); + } + } +} + +/*! + \return true when enabled, false otherwise + \sa setEnabled(), eventFilter() +*/ +bool QwtMagnifier::isEnabled() const +{ + return d_data->isEnabled; +} + +/*! + \brief Change the wheel factor + + The wheel factor defines the ratio between the current range + on the parent widget and the zoomed range for each step of the wheel. + + Use values > 1 for magnification (i.e. 2.0) and values < 1 for + scaling down (i.e. 1/2.0 = 0.5). You can use this feature for + inverting the direction of the wheel. + + The default value is 0.9. + + \param factor Wheel factor + \sa wheelFactor(), setWheelButtonState(), + setMouseFactor(), setKeyFactor() +*/ +void QwtMagnifier::setWheelFactor( double factor ) +{ + d_data->wheelFactor = factor; +} + +/*! + \return Wheel factor + \sa setWheelFactor() +*/ +double QwtMagnifier::wheelFactor() const +{ + return d_data->wheelFactor; +} + +/*! + Assign keyboard modifiers for zooming in/out using the wheel. + The default modifiers are Qt::NoModifiers. + + \param modifiers Keyboard modifiers + \sa wheelModifiers() +*/ +void QwtMagnifier::setWheelModifiers( Qt::KeyboardModifiers modifiers ) +{ + d_data->wheelModifiers = modifiers; +} + +/*! + \return Wheel modifiers + \sa setWheelModifiers() +*/ +Qt::KeyboardModifiers QwtMagnifier::wheelModifiers() const +{ + return d_data->wheelModifiers; +} + +/*! + \brief Change the mouse factor + + The mouse factor defines the ratio between the current range + on the parent widget and the zoomed range for each vertical mouse movement. + The default value is 0.95. + + \param factor Wheel factor + \sa mouseFactor(), setMouseButton(), setWheelFactor(), setKeyFactor() +*/ +void QwtMagnifier::setMouseFactor( double factor ) +{ + d_data->mouseFactor = factor; +} + +/*! + \return Mouse factor + \sa setMouseFactor() +*/ +double QwtMagnifier::mouseFactor() const +{ + return d_data->mouseFactor; +} + +/*! + Assign the mouse button, that is used for zooming in/out. + The default value is Qt::RightButton. + + \param button Button + \param modifiers Keyboard modifiers + + \sa getMouseButton() +*/ +void QwtMagnifier::setMouseButton( + Qt::MouseButton button, Qt::KeyboardModifiers modifiers ) +{ + d_data->mouseButton = button; + d_data->mouseButtonModifiers = modifiers; +} + +//! \sa setMouseButton() +void QwtMagnifier::getMouseButton( + Qt::MouseButton &button, Qt::KeyboardModifiers &modifiers ) const +{ + button = d_data->mouseButton; + modifiers = d_data->mouseButtonModifiers; +} + +/*! + \brief Change the key factor + + The key factor defines the ratio between the current range + on the parent widget and the zoomed range for each key press of + the zoom in/out keys. The default value is 0.9. + + \param factor Key factor + \sa keyFactor(), setZoomInKey(), setZoomOutKey(), + setWheelFactor, setMouseFactor() +*/ +void QwtMagnifier::setKeyFactor( double factor ) +{ + d_data->keyFactor = factor; +} + +/*! + \return Key factor + \sa setKeyFactor() +*/ +double QwtMagnifier::keyFactor() const +{ + return d_data->keyFactor; +} + +/*! + Assign the key, that is used for zooming in. + The default combination is Qt::Key_Plus + Qt::NoModifier. + + \param key + \param modifiers + \sa getZoomInKey(), setZoomOutKey() +*/ +void QwtMagnifier::setZoomInKey( int key, + Qt::KeyboardModifiers modifiers ) +{ + d_data->zoomInKey = key; + d_data->zoomInKeyModifiers = modifiers; +} + +/*! + \brief Retrieve the settings of the zoom in key + + \param key Key code, see Qt::Key + \param modifiers Keyboard modifiers + + \sa setZoomInKey() +*/ +void QwtMagnifier::getZoomInKey( int &key, + Qt::KeyboardModifiers &modifiers ) const +{ + key = d_data->zoomInKey; + modifiers = d_data->zoomInKeyModifiers; +} + +/*! + Assign the key, that is used for zooming out. + The default combination is Qt::Key_Minus + Qt::NoModifier. + + \param key + \param modifiers + \sa getZoomOutKey(), setZoomOutKey() +*/ +void QwtMagnifier::setZoomOutKey( int key, + Qt::KeyboardModifiers modifiers ) +{ + d_data->zoomOutKey = key; + d_data->zoomOutKeyModifiers = modifiers; +} + +/*! + \brief Retrieve the settings of the zoom out key + + \param key Key code, see Qt::Key + \param modifiers Keyboard modifiers + + \sa setZoomOutKey() +*/ +void QwtMagnifier::getZoomOutKey( int &key, + Qt::KeyboardModifiers &modifiers ) const +{ + key = d_data->zoomOutKey; + modifiers = d_data->zoomOutKeyModifiers; +} + +/*! + \brief Event filter + + When isEnabled() is true, the mouse events of the + observed widget are filtered. + + \param object Object to be filtered + \param event Event + + \return Forwarded to QObject::eventFilter() + + \sa widgetMousePressEvent(), widgetMouseReleaseEvent(), + widgetMouseMoveEvent(), widgetWheelEvent(), widgetKeyPressEvent() + widgetKeyReleaseEvent() +*/ +bool QwtMagnifier::eventFilter( QObject *object, QEvent *event ) +{ + if ( object && object == parent() ) + { + switch ( event->type() ) + { + case QEvent::MouseButtonPress: + { + widgetMousePressEvent( static_cast( event ) ); + break; + } + case QEvent::MouseMove: + { + widgetMouseMoveEvent( static_cast( event ) ); + break; + } + case QEvent::MouseButtonRelease: + { + widgetMouseReleaseEvent( static_cast( event ) ); + break; + } + case QEvent::Wheel: + { + widgetWheelEvent( static_cast( event ) ); + break; + } + case QEvent::KeyPress: + { + widgetKeyPressEvent( static_cast( event ) ); + break; + } + case QEvent::KeyRelease: + { + widgetKeyReleaseEvent( static_cast( event ) ); + break; + } + default:; + } + } + return QObject::eventFilter( object, event ); +} + +/*! + Handle a mouse press event for the observed widget. + + \param mouseEvent Mouse event + \sa eventFilter(), widgetMouseReleaseEvent(), widgetMouseMoveEvent() +*/ +void QwtMagnifier::widgetMousePressEvent( QMouseEvent *mouseEvent ) +{ + if ( parentWidget() == NULL ) + return; + + if ( ( mouseEvent->button() != d_data->mouseButton ) || + ( mouseEvent->modifiers() != d_data->mouseButtonModifiers ) ) + { + return; + } + + d_data->hasMouseTracking = parentWidget()->hasMouseTracking(); + + parentWidget()->setMouseTracking( true ); + d_data->mousePos = mouseEvent->pos(); + d_data->mousePressed = true; +} + +/*! + Handle a mouse release event for the observed widget. + + \param mouseEvent Mouse event + + \sa eventFilter(), widgetMousePressEvent(), widgetMouseMoveEvent(), +*/ +void QwtMagnifier::widgetMouseReleaseEvent( QMouseEvent *mouseEvent ) +{ + Q_UNUSED( mouseEvent ); + + if ( d_data->mousePressed && parentWidget() ) + { + d_data->mousePressed = false; + parentWidget()->setMouseTracking( d_data->hasMouseTracking ); + } +} + +/*! + Handle a mouse move event for the observed widget. + + \param mouseEvent Mouse event + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), +*/ +void QwtMagnifier::widgetMouseMoveEvent( QMouseEvent *mouseEvent ) +{ + if ( !d_data->mousePressed ) + return; + + const int dy = mouseEvent->pos().y() - d_data->mousePos.y(); + if ( dy != 0 ) + { + double f = d_data->mouseFactor; + if ( dy < 0 ) + f = 1 / f; + + rescale( f ); + } + + d_data->mousePos = mouseEvent->pos(); +} + +/*! + Handle a wheel event for the observed widget. + + \param wheelEvent Wheel event + \sa eventFilter() +*/ +void QwtMagnifier::widgetWheelEvent( QWheelEvent *wheelEvent ) +{ + if ( wheelEvent->modifiers() != d_data->wheelModifiers ) + { + return; + } + + if ( d_data->wheelFactor != 0.0 ) + { + /* + A positive delta indicates that the wheel was + rotated forwards away from the user; a negative + value indicates that the wheel was rotated + backwards toward the user. + Most mouse types work in steps of 15 degrees, + in which case the delta value is a multiple + of 120 (== 15 * 8). + */ + double f = qPow( d_data->wheelFactor, + qAbs( wheelEvent->delta() / 120.0 ) ); + + if ( wheelEvent->delta() > 0 ) + f = 1 / f; + + rescale( f ); + } +} + +/*! + Handle a key press event for the observed widget. + + \param keyEvent Key event + \sa eventFilter(), widgetKeyReleaseEvent() +*/ +void QwtMagnifier::widgetKeyPressEvent( QKeyEvent *keyEvent ) +{ + if ( keyEvent->key() == d_data->zoomInKey && + keyEvent->modifiers() == d_data->zoomInKeyModifiers ) + { + rescale( d_data->keyFactor ); + } + else if ( keyEvent->key() == d_data->zoomOutKey && + keyEvent->modifiers() == d_data->zoomOutKeyModifiers ) + { + rescale( 1.0 / d_data->keyFactor ); + } +} + +/*! + Handle a key release event for the observed widget. + + \param keyEvent Key event + \sa eventFilter(), widgetKeyReleaseEvent() +*/ +void QwtMagnifier::widgetKeyReleaseEvent( QKeyEvent *keyEvent ) +{ + Q_UNUSED( keyEvent ); +} + +//! \return Parent widget, where the rescaling happens +QWidget *QwtMagnifier::parentWidget() +{ + return qobject_cast( parent() ); +} + +//! \return Parent widget, where the rescaling happens +const QWidget *QwtMagnifier::parentWidget() const +{ + return qobject_cast( parent() ); +} + diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_magnifier.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_magnifier.h new file mode 100644 index 0000000..42ff41f --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_magnifier.h @@ -0,0 +1,86 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_MAGNIFIER_H +#define QWT_MAGNIFIER_H 1 + +#include "qwt_global.h" +#include + +class QWidget; +class QMouseEvent; +class QWheelEvent; +class QKeyEvent; + +/*! + \brief QwtMagnifier provides zooming, by magnifying in steps. + + Using QwtMagnifier a plot can be zoomed in/out in steps using + keys, the mouse wheel or moving a mouse button in vertical direction. +*/ +class QWT_EXPORT QwtMagnifier: public QObject +{ + Q_OBJECT + +public: + explicit QwtMagnifier( QWidget * ); + virtual ~QwtMagnifier(); + + QWidget *parentWidget(); + const QWidget *parentWidget() const; + + void setEnabled( bool ); + bool isEnabled() const; + + // mouse + void setMouseFactor( double ); + double mouseFactor() const; + + void setMouseButton( Qt::MouseButton, Qt::KeyboardModifiers = Qt::NoModifier ); + void getMouseButton( Qt::MouseButton &, Qt::KeyboardModifiers & ) const; + + // mouse wheel + void setWheelFactor( double ); + double wheelFactor() const; + + void setWheelModifiers( Qt::KeyboardModifiers ); + Qt::KeyboardModifiers wheelModifiers() const; + + // keyboard + void setKeyFactor( double ); + double keyFactor() const; + + void setZoomInKey( int key, Qt::KeyboardModifiers = Qt::NoModifier ); + void getZoomInKey( int &key, Qt::KeyboardModifiers & ) const; + + void setZoomOutKey( int key, Qt::KeyboardModifiers = Qt::NoModifier ); + void getZoomOutKey( int &key, Qt::KeyboardModifiers & ) const; + + virtual bool eventFilter( QObject *, QEvent * ); + +protected: + /*! + Rescale the parent widget + \param factor Scale factor + */ + virtual void rescale( double factor ) = 0; + + virtual void widgetMousePressEvent( QMouseEvent * ); + virtual void widgetMouseReleaseEvent( QMouseEvent * ); + virtual void widgetMouseMoveEvent( QMouseEvent * ); + virtual void widgetWheelEvent( QWheelEvent * ); + virtual void widgetKeyPressEvent( QKeyEvent * ); + virtual void widgetKeyReleaseEvent( QKeyEvent * ); + +private: + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_math.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_math.cpp new file mode 100644 index 0000000..2186e02 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_math.cpp @@ -0,0 +1,74 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_math.h" + +/*! + \brief Find the smallest value in an array + \param array Pointer to an array + \param size Array size +*/ +double qwtGetMin( const double *array, int size ) +{ + if ( size <= 0 ) + return 0.0; + + double rv = array[0]; + for ( int i = 1; i < size; i++ ) + rv = qMin( rv, array[i] ); + + return rv; +} + + +/*! + \brief Find the largest value in an array + \param array Pointer to an array + \param size Array size +*/ +double qwtGetMax( const double *array, int size ) +{ + if ( size <= 0 ) + return 0.0; + + double rv = array[0]; + for ( int i = 1; i < size; i++ ) + rv = qMax( rv, array[i] ); + + return rv; +} + +/*! + \brief Normalize an angle to be int the range [0.0, 2 * PI[ + \param radians Angle in radians + \return Normalized angle in radians +*/ +double qwtNormalizeRadians( double radians ) +{ + double a = ::fmod( radians, 2.0 * M_PI ); + if ( a < 0.0 ) + a += 2.0 * M_PI; + + return a; + +} + +/*! + \brief Normalize an angle to be int the range [0.0, 360.0[ + \param radians Angle in degrees + \return Normalized angle in degrees +*/ +double qwtNormalizeDegrees( double degrees ) +{ + double a = ::fmod( degrees, 360.0 ); + if ( a < 0.0 ) + a += 360.0; + + return a; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_math.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_math.h new file mode 100644 index 0000000..d6d0495 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_math.h @@ -0,0 +1,149 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_MATH_H +#define QWT_MATH_H + +#include "qwt_global.h" + +#if defined(_MSC_VER) +/* + Microsoft says: + + Define _USE_MATH_DEFINES before including math.h to expose these macro + definitions for common math constants. These are placed under an #ifdef + since these commonly-defined names are not part of the C/C++ standards. +*/ +#define _USE_MATH_DEFINES 1 +#endif + +#include +#include "qwt_global.h" + +#ifndef M_PI_2 +// For Qt <= 4.8.4 M_PI_2 is not known by MinGW-w64 +// when compiling with -std=c++11 +#define M_PI_2 (1.57079632679489661923) +#endif + +#ifndef LOG_MIN +//! Minimum value for logarithmic scales +#define LOG_MIN 1.0e-100 +#endif + +#ifndef LOG_MAX +//! Maximum value for logarithmic scales +#define LOG_MAX 1.0e100 +#endif + +QWT_EXPORT double qwtGetMin( const double *array, int size ); +QWT_EXPORT double qwtGetMax( const double *array, int size ); + +QWT_EXPORT double qwtNormalizeRadians( double radians ); +QWT_EXPORT double qwtNormalizeDegrees( double degrees ); + +/*! + \brief Compare 2 values, relative to an interval + + Values are "equal", when : + \f$\cdot value2 - value1 <= abs(intervalSize * 10e^{-6})\f$ + + \param value1 First value to compare + \param value2 Second value to compare + \param intervalSize interval size + + \return 0: if equal, -1: if value2 > value1, 1: if value1 > value2 +*/ +inline int qwtFuzzyCompare( double value1, double value2, double intervalSize ) +{ + const double eps = qAbs( 1.0e-6 * intervalSize ); + + if ( value2 - value1 > eps ) + return -1; + + if ( value1 - value2 > eps ) + return 1; + + return 0; +} + + +inline bool qwtFuzzyGreaterOrEqual( double d1, double d2 ) +{ + return ( d1 >= d2 ) || qFuzzyCompare( d1, d2 ); +} + +inline bool qwtFuzzyLessOrEqual( double d1, double d2 ) +{ + return ( d1 <= d2 ) || qFuzzyCompare( d1, d2 ); +} + +//! Return the sign +inline int qwtSign( double x ) +{ + if ( x > 0.0 ) + return 1; + else if ( x < 0.0 ) + return ( -1 ); + else + return 0; +} + +//! Return the square of a number +inline double qwtSqr( double x ) +{ + return x * x; +} + +//! Approximation of arc tangent ( error below 0,005 radians ) +inline double qwtFastAtan( double x ) +{ + if ( x < -1.0 ) + return -M_PI_2 - x / ( x * x + 0.28 ); + + if ( x > 1.0 ) + return M_PI_2 - x / ( x * x + 0.28 ); + + return x / ( 1.0 + x * x * 0.28 ); +} + +//! Approximation of arc tangent ( error below 0,005 radians ) +inline double qwtFastAtan2( double y, double x ) +{ + if ( x > 0 ) + return qwtFastAtan( y / x ); + + if ( x < 0 ) + { + const double d = qwtFastAtan( y / x ); + return ( y >= 0 ) ? d + M_PI : d - M_PI; + } + + if ( y < 0.0 ) + return -M_PI_2; + + if ( y > 0.0 ) + return M_PI_2; + + return 0.0; +} + +//! Translate degrees into radians +inline double qwtRadians( double degrees ) +{ + return degrees * M_PI / 180.0; +} + +//! Translate radians into degrees +inline double qwtDegrees( double degrees ) +{ + return degrees * 180.0 / M_PI; +} + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_matrix_raster_data.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_matrix_raster_data.cpp new file mode 100644 index 0000000..d0d2703 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_matrix_raster_data.cpp @@ -0,0 +1,298 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_matrix_raster_data.h" +#include +#include + +class QwtMatrixRasterData::PrivateData +{ +public: + PrivateData(): + resampleMode(QwtMatrixRasterData::NearestNeighbour), + numColumns(0) + { + } + + inline double value(int row, int col) const + { + return values.data()[ row * numColumns + col ]; + } + + QwtMatrixRasterData::ResampleMode resampleMode; + + QVector values; + int numColumns; + int numRows; + + double dx; + double dy; +}; + +//! Constructor +QwtMatrixRasterData::QwtMatrixRasterData() +{ + d_data = new PrivateData(); + update(); +} + +//! Destructor +QwtMatrixRasterData::~QwtMatrixRasterData() +{ + delete d_data; +} + +/*! + \brief Set the resampling algorithm + + \param mode Resampling mode + \sa resampleMode(), value() +*/ +void QwtMatrixRasterData::setResampleMode( ResampleMode mode ) +{ + d_data->resampleMode = mode; +} + +/*! + \return resampling algorithm + \sa setResampleMode(), value() +*/ +QwtMatrixRasterData::ResampleMode QwtMatrixRasterData::resampleMode() const +{ + return d_data->resampleMode; +} + +/*! + \brief Assign the bounding interval for an axis + + Setting the bounding intervals for the X/Y axis is mandatory + to define the positions for the values of the value matrix. + The interval in Z direction defines the possible range for + the values in the matrix, what is f.e used by QwtPlotSpectrogram + to map values to colors. The Z-interval might be the bounding + interval of the values in the matrix, but usually it isn't. + ( f.e a interval of 0.0-100.0 for values in percentage ) + + \param axis X, Y or Z axis + \param interval Interval + + \sa QwtRasterData::interval(), setValueMatrix() +*/ +void QwtMatrixRasterData::setInterval( + Qt::Axis axis, const QwtInterval &interval ) +{ + QwtRasterData::setInterval( axis, interval ); + update(); +} + +/*! + \brief Assign a value matrix + + The positions of the values are calculated by dividing + the bounding rectangle of the X/Y intervals into equidistant + rectangles ( pixels ). Each value corresponds to the center of + a pixel. + + \param values Vector of values + \param numColumns Number of columns + + \sa valueMatrix(), numColumns(), numRows(), setInterval()() +*/ +void QwtMatrixRasterData::setValueMatrix( + const QVector &values, int numColumns ) +{ + d_data->values = values; + d_data->numColumns = qMax( numColumns, 0 ); + update(); +} + +/*! + \return Value matrix + \sa setValueMatrix(), numColumns(), numRows(), setInterval() +*/ +const QVector QwtMatrixRasterData::valueMatrix() const +{ + return d_data->values; +} + +/*! + \brief Change a single value in the matrix + + \param row Row index + \param col Column index + \param value New value + + \sa value(), setValueMatrix() +*/ +void QwtMatrixRasterData::setValue( int row, int col, double value ) +{ + if ( row >= 0 && row < d_data->numRows && + col >= 0 && col < d_data->numColumns ) + { + const int index = row * d_data->numColumns + col; + d_data->values.data()[ index ] = value; + } +} + +/*! + \return Number of columns of the value matrix + \sa valueMatrix(), numRows(), setValueMatrix() +*/ +int QwtMatrixRasterData::numColumns() const +{ + return d_data->numColumns; +} + +/*! + \return Number of rows of the value matrix + \sa valueMatrix(), numColumns(), setValueMatrix() +*/ +int QwtMatrixRasterData::numRows() const +{ + return d_data->numRows; +} + +/*! + \brief Calculate the pixel hint + + pixelHint() returns the geometry of a pixel, that can be used + to calculate the resolution and alignment of the plot item, that is + representing the data. + + - NearestNeighbour\n + pixelHint() returns the surrounding pixel of the top left value + in the matrix. + + - BilinearInterpolation\n + Returns an empty rectangle recommending + to render in target device ( f.e. screen ) resolution. + + \param area Requested area, ignored + \return Calculated hint + + \sa ResampleMode, setMatrix(), setInterval() +*/ +QRectF QwtMatrixRasterData::pixelHint( const QRectF &area ) const +{ + Q_UNUSED( area ) + + QRectF rect; + if ( d_data->resampleMode == NearestNeighbour ) + { + const QwtInterval intervalX = interval( Qt::XAxis ); + const QwtInterval intervalY = interval( Qt::YAxis ); + if ( intervalX.isValid() && intervalY.isValid() ) + { + rect = QRectF( intervalX.minValue(), intervalY.minValue(), + d_data->dx, d_data->dy ); + } + } + + return rect; +} + +/*! + \return the value at a raster position + + \param x X value in plot coordinates + \param y Y value in plot coordinates + + \sa ResampleMode +*/ +double QwtMatrixRasterData::value( double x, double y ) const +{ + const QwtInterval xInterval = interval( Qt::XAxis ); + const QwtInterval yInterval = interval( Qt::YAxis ); + + if ( !( xInterval.contains(x) && yInterval.contains(y) ) ) + return qQNaN(); + + double value; + + switch( d_data->resampleMode ) + { + case BilinearInterpolation: + { + int col1 = qRound( (x - xInterval.minValue() ) / d_data->dx ) - 1; + int row1 = qRound( (y - yInterval.minValue() ) / d_data->dy ) - 1; + int col2 = col1 + 1; + int row2 = row1 + 1; + + if ( col1 < 0 ) + col1 = col2; + else if ( col2 >= static_cast( d_data->numColumns ) ) + col2 = col1; + + if ( row1 < 0 ) + row1 = row2; + else if ( row2 >= static_cast( d_data->numRows ) ) + row2 = row1; + + const double v11 = d_data->value( row1, col1 ); + const double v21 = d_data->value( row1, col2 ); + const double v12 = d_data->value( row2, col1 ); + const double v22 = d_data->value( row2, col2 ); + + const double x2 = xInterval.minValue() + + ( col2 + 0.5 ) * d_data->dx; + const double y2 = yInterval.minValue() + + ( row2 + 0.5 ) * d_data->dy; + + const double rx = ( x2 - x ) / d_data->dx; + const double ry = ( y2 - y ) / d_data->dy; + + const double vr1 = rx * v11 + ( 1.0 - rx ) * v21; + const double vr2 = rx * v12 + ( 1.0 - rx ) * v22; + + value = ry * vr1 + ( 1.0 - ry ) * vr2; + + break; + } + case NearestNeighbour: + default: + { + int row = int( (y - yInterval.minValue() ) / d_data->dy ); + int col = int( (x - xInterval.minValue() ) / d_data->dx ); + + // In case of intervals, where the maximum is included + // we get out of bound for row/col, when the value for the + // maximum is requested. Instead we return the value + // from the last row/col + + if ( row >= d_data->numRows ) + row = d_data->numRows - 1; + + if ( col >= d_data->numColumns ) + col = d_data->numColumns - 1; + + value = d_data->value( row, col ); + } + } + + return value; +} + +void QwtMatrixRasterData::update() +{ + d_data->numRows = 0; + d_data->dx = 0.0; + d_data->dy = 0.0; + + if ( d_data->numColumns > 0 ) + { + d_data->numRows = d_data->values.size() / d_data->numColumns; + + const QwtInterval xInterval = interval( Qt::XAxis ); + const QwtInterval yInterval = interval( Qt::YAxis ); + if ( xInterval.isValid() ) + d_data->dx = xInterval.width() / d_data->numColumns; + if ( yInterval.isValid() ) + d_data->dy = yInterval.width() / d_data->numRows; + } +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_matrix_raster_data.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_matrix_raster_data.h new file mode 100644 index 0000000..34c4cf4 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_matrix_raster_data.h @@ -0,0 +1,74 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_MATRIX_RASTER_DATA_H +#define QWT_MATRIX_RASTER_DATA_H 1 + +#include "qwt_global.h" +#include "qwt_raster_data.h" +#include + +/*! + \brief A class representing a matrix of values as raster data + + QwtMatrixRasterData implements an interface for a matrix of + equidistant values, that can be used by a QwtPlotRasterItem. + It implements a couple of resampling algorithms, to provide + values for positions, that or not on the value matrix. +*/ +class QWT_EXPORT QwtMatrixRasterData: public QwtRasterData +{ +public: + /*! + \brief Resampling algorithm + The default setting is NearestNeighbour; + */ + enum ResampleMode + { + /*! + Return the value from the matrix, that is nearest to the + the requested position. + */ + NearestNeighbour, + + /*! + Interpolate the value from the distances and values of the + 4 surrounding values in the matrix, + */ + BilinearInterpolation + }; + + QwtMatrixRasterData(); + virtual ~QwtMatrixRasterData(); + + void setResampleMode(ResampleMode mode); + ResampleMode resampleMode() const; + + virtual void setInterval( Qt::Axis, const QwtInterval & ); + + void setValueMatrix( const QVector &values, int numColumns ); + const QVector valueMatrix() const; + + void setValue( int row, int col, double value ); + + int numColumns() const; + int numRows() const; + + virtual QRectF pixelHint( const QRectF & ) const; + + virtual double value( double x, double y ) const; + +private: + void update(); + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_null_paintdevice.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_null_paintdevice.cpp new file mode 100644 index 0000000..1d1169f --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_null_paintdevice.cpp @@ -0,0 +1,593 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_null_paintdevice.h" +#include +#include + +class QwtNullPaintDevice::PrivateData +{ +public: + PrivateData(): + mode( QwtNullPaintDevice::NormalMode ) + { + } + + QwtNullPaintDevice::Mode mode; +}; + +class QwtNullPaintDevice::PaintEngine: public QPaintEngine +{ +public: + PaintEngine(); + + virtual bool begin( QPaintDevice * ); + virtual bool end(); + + virtual Type type () const; + virtual void updateState(const QPaintEngineState &); + + virtual void drawRects(const QRect *, int ); + virtual void drawRects(const QRectF *, int ); + + virtual void drawLines(const QLine *, int ); + virtual void drawLines(const QLineF *, int ); + + virtual void drawEllipse(const QRectF &); + virtual void drawEllipse(const QRect &); + + virtual void drawPath(const QPainterPath &); + + virtual void drawPoints(const QPointF *, int ); + virtual void drawPoints(const QPoint *, int ); + + virtual void drawPolygon(const QPointF *, int , PolygonDrawMode ); + virtual void drawPolygon(const QPoint *, int , PolygonDrawMode ); + + virtual void drawPixmap(const QRectF &, + const QPixmap &, const QRectF &); + + virtual void drawTextItem(const QPointF &, const QTextItem &); + + virtual void drawTiledPixmap(const QRectF &, + const QPixmap &, const QPointF &s); + + virtual void drawImage(const QRectF &, + const QImage &, const QRectF &, Qt::ImageConversionFlags ); + +private: + QwtNullPaintDevice *nullDevice(); +}; + +QwtNullPaintDevice::PaintEngine::PaintEngine(): + QPaintEngine( QPaintEngine::AllFeatures ) +{ +} + +bool QwtNullPaintDevice::PaintEngine::begin( QPaintDevice * ) +{ + setActive( true ); + return true; +} + +bool QwtNullPaintDevice::PaintEngine::end() +{ + setActive( false ); + return true; +} + +QPaintEngine::Type QwtNullPaintDevice::PaintEngine::type() const +{ + return QPaintEngine::User; +} + +void QwtNullPaintDevice::PaintEngine::drawRects( + const QRect *rects, int rectCount) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + if ( device->mode() != QwtNullPaintDevice::NormalMode ) + { + QPaintEngine::drawRects( rects, rectCount ); + return; + } + + device->drawRects( rects, rectCount ); +} + +void QwtNullPaintDevice::PaintEngine::drawRects( + const QRectF *rects, int rectCount) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + if ( device->mode() != QwtNullPaintDevice::NormalMode ) + { + QPaintEngine::drawRects( rects, rectCount ); + return; + } + + device->drawRects( rects, rectCount ); +} + +void QwtNullPaintDevice::PaintEngine::drawLines( + const QLine *lines, int lineCount) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + if ( device->mode() != QwtNullPaintDevice::NormalMode ) + { + QPaintEngine::drawLines( lines, lineCount ); + return; + } + + device->drawLines( lines, lineCount ); +} + +void QwtNullPaintDevice::PaintEngine::drawLines( + const QLineF *lines, int lineCount) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + if ( device->mode() != QwtNullPaintDevice::NormalMode ) + { + QPaintEngine::drawLines( lines, lineCount ); + return; + } + + device->drawLines( lines, lineCount ); +} + +void QwtNullPaintDevice::PaintEngine::drawEllipse( + const QRectF &rect) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + if ( device->mode() != QwtNullPaintDevice::NormalMode ) + { + QPaintEngine::drawEllipse( rect ); + return; + } + + device->drawEllipse( rect ); +} + +void QwtNullPaintDevice::PaintEngine::drawEllipse( + const QRect &rect) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + if ( device->mode() != QwtNullPaintDevice::NormalMode ) + { + QPaintEngine::drawEllipse( rect ); + return; + } + + device->drawEllipse( rect ); +} + + +void QwtNullPaintDevice::PaintEngine::drawPath( + const QPainterPath &path) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + device->drawPath( path ); +} + +void QwtNullPaintDevice::PaintEngine::drawPoints( + const QPointF *points, int pointCount) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + if ( device->mode() != QwtNullPaintDevice::NormalMode ) + { + QPaintEngine::drawPoints( points, pointCount ); + return; + } + + device->drawPoints( points, pointCount ); +} + +void QwtNullPaintDevice::PaintEngine::drawPoints( + const QPoint *points, int pointCount) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + if ( device->mode() != QwtNullPaintDevice::NormalMode ) + { + QPaintEngine::drawPoints( points, pointCount ); + return; + } + + device->drawPoints( points, pointCount ); +} + +void QwtNullPaintDevice::PaintEngine::drawPolygon( + const QPointF *points, int pointCount, PolygonDrawMode mode) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + if ( device->mode() == QwtNullPaintDevice::PathMode ) + { + QPainterPath path; + + if ( pointCount > 0 ) + { + path.moveTo( points[0] ); + for ( int i = 1; i < pointCount; i++ ) + path.lineTo( points[i] ); + + if ( mode != PolylineMode ) + path.closeSubpath(); + } + + device->drawPath( path ); + return; + } + + device->drawPolygon( points, pointCount, mode ); +} + +void QwtNullPaintDevice::PaintEngine::drawPolygon( + const QPoint *points, int pointCount, PolygonDrawMode mode) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + if ( device->mode() == QwtNullPaintDevice::PathMode ) + { + QPainterPath path; + + if ( pointCount > 0 ) + { + path.moveTo( points[0] ); + for ( int i = 1; i < pointCount; i++ ) + path.lineTo( points[i] ); + + if ( mode != PolylineMode ) + path.closeSubpath(); + } + + device->drawPath( path ); + return; + } + + device->drawPolygon( points, pointCount, mode ); +} + +void QwtNullPaintDevice::PaintEngine::drawPixmap( + const QRectF &rect, const QPixmap &pm, const QRectF &subRect ) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + device->drawPixmap( rect, pm, subRect ); +} + +void QwtNullPaintDevice::PaintEngine::drawTextItem( + const QPointF &pos, const QTextItem &textItem) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + if ( device->mode() != QwtNullPaintDevice::NormalMode ) + { + QPaintEngine::drawTextItem( pos, textItem ); + return; + } + + device->drawTextItem( pos, textItem ); +} + +void QwtNullPaintDevice::PaintEngine::drawTiledPixmap( + const QRectF &rect, const QPixmap &pixmap, + const QPointF &subRect) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + if ( device->mode() != QwtNullPaintDevice::NormalMode ) + { + QPaintEngine::drawTiledPixmap( rect, pixmap, subRect ); + return; + } + + device->drawTiledPixmap( rect, pixmap, subRect ); +} + +void QwtNullPaintDevice::PaintEngine::drawImage( + const QRectF &rect, const QImage &image, + const QRectF &subRect, Qt::ImageConversionFlags flags) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + device->drawImage( rect, image, subRect, flags ); +} + +void QwtNullPaintDevice::PaintEngine::updateState( + const QPaintEngineState &state) +{ + QwtNullPaintDevice *device = nullDevice(); + if ( device == NULL ) + return; + + device->updateState( state ); +} + +inline QwtNullPaintDevice *QwtNullPaintDevice::PaintEngine::nullDevice() +{ + if ( !isActive() ) + return NULL; + + return static_cast( paintDevice() ); +} + +//! Constructor +QwtNullPaintDevice::QwtNullPaintDevice(): + d_engine( NULL ) +{ + d_data = new PrivateData; +} + +//! Destructor +QwtNullPaintDevice::~QwtNullPaintDevice() +{ + delete d_engine; + delete d_data; +} + +/*! + Set the render mode + + \param mode New mode + \sa mode() + */ +void QwtNullPaintDevice::setMode( Mode mode ) +{ + d_data->mode = mode; +} + +/*! + \return Render mode + \sa setMode() +*/ +QwtNullPaintDevice::Mode QwtNullPaintDevice::mode() const +{ + return d_data->mode; +} + +//! See QPaintDevice::paintEngine() +QPaintEngine *QwtNullPaintDevice::paintEngine() const +{ + if ( d_engine == NULL ) + { + QwtNullPaintDevice *that = + const_cast< QwtNullPaintDevice * >( this ); + + that->d_engine = new PaintEngine(); + } + + return d_engine; +} + +/*! + See QPaintDevice::metric() + + \param deviceMetric Type of metric + \return Metric information for the given paint device metric. + + \sa sizeMetrics() +*/ +int QwtNullPaintDevice::metric( PaintDeviceMetric deviceMetric ) const +{ + int value; + + switch ( deviceMetric ) + { + case PdmWidth: + { + value = sizeMetrics().width(); + break; + } + case PdmHeight: + { + value = sizeMetrics().height(); + break; + } + case PdmNumColors: + { + value = 0xffffffff; + break; + } + case PdmDepth: + { + value = 32; + break; + } + case PdmPhysicalDpiX: + case PdmPhysicalDpiY: + case PdmDpiY: + case PdmDpiX: + { + value = 72; + break; + } + case PdmWidthMM: + { + value = qRound( metric( PdmWidth ) * 25.4 / metric( PdmDpiX ) ); + break; + } + case PdmHeightMM: + { + value = qRound( metric( PdmHeight ) * 25.4 / metric( PdmDpiY ) ); + break; + } + default: + value = 0; + } + return value; + +} + +//! See QPaintEngine::drawRects() +void QwtNullPaintDevice::drawRects( + const QRect *rects, int rectCount) +{ + Q_UNUSED(rects); + Q_UNUSED(rectCount); +} + +//! See QPaintEngine::drawRects() +void QwtNullPaintDevice::drawRects( + const QRectF *rects, int rectCount) +{ + Q_UNUSED(rects); + Q_UNUSED(rectCount); +} + +//! See QPaintEngine::drawLines() +void QwtNullPaintDevice::drawLines( + const QLine *lines, int lineCount) +{ + Q_UNUSED(lines); + Q_UNUSED(lineCount); +} + +//! See QPaintEngine::drawLines() +void QwtNullPaintDevice::drawLines( + const QLineF *lines, int lineCount) +{ + Q_UNUSED(lines); + Q_UNUSED(lineCount); +} + +//! See QPaintEngine::drawEllipse() +void QwtNullPaintDevice::drawEllipse( const QRectF &rect ) +{ + Q_UNUSED(rect); +} + +//! See QPaintEngine::drawEllipse() +void QwtNullPaintDevice::drawEllipse( const QRect &rect ) +{ + Q_UNUSED(rect); +} + +//! See QPaintEngine::drawPath() +void QwtNullPaintDevice::drawPath( const QPainterPath &path ) +{ + Q_UNUSED(path); +} + +//! See QPaintEngine::drawPoints() +void QwtNullPaintDevice::drawPoints( + const QPointF *points, int pointCount) +{ + Q_UNUSED(points); + Q_UNUSED(pointCount); +} + +//! See QPaintEngine::drawPoints() +void QwtNullPaintDevice::drawPoints( + const QPoint *points, int pointCount) +{ + Q_UNUSED(points); + Q_UNUSED(pointCount); +} + +//! See QPaintEngine::drawPolygon() +void QwtNullPaintDevice::drawPolygon( + const QPointF *points, int pointCount, + QPaintEngine::PolygonDrawMode mode) +{ + Q_UNUSED(points); + Q_UNUSED(pointCount); + Q_UNUSED(mode); +} + +//! See QPaintEngine::drawPolygon() +void QwtNullPaintDevice::drawPolygon( + const QPoint *points, int pointCount, + QPaintEngine::PolygonDrawMode mode) +{ + Q_UNUSED(points); + Q_UNUSED(pointCount); + Q_UNUSED(mode); +} + +//! See QPaintEngine::drawPixmap() +void QwtNullPaintDevice::drawPixmap( const QRectF &rect, + const QPixmap &pm, const QRectF &subRect ) +{ + Q_UNUSED(rect); + Q_UNUSED(pm); + Q_UNUSED(subRect); +} + +//! See QPaintEngine::drawTextItem() +void QwtNullPaintDevice::drawTextItem( + const QPointF &pos, const QTextItem &textItem) +{ + Q_UNUSED(pos); + Q_UNUSED(textItem); +} + +//! See QPaintEngine::drawTiledPixmap() +void QwtNullPaintDevice::drawTiledPixmap( + const QRectF &rect, const QPixmap &pixmap, + const QPointF &subRect) +{ + Q_UNUSED(rect); + Q_UNUSED(pixmap); + Q_UNUSED(subRect); +} + +//! See QPaintEngine::drawImage() +void QwtNullPaintDevice::drawImage( + const QRectF &rect, const QImage &image, + const QRectF &subRect, Qt::ImageConversionFlags flags) +{ + Q_UNUSED(rect); + Q_UNUSED(image); + Q_UNUSED(subRect); + Q_UNUSED(flags); +} + +//! See QPaintEngine::updateState() +void QwtNullPaintDevice::updateState( + const QPaintEngineState &state ) +{ + Q_UNUSED(state); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_null_paintdevice.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_null_paintdevice.h new file mode 100644 index 0000000..679ec5d --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_null_paintdevice.h @@ -0,0 +1,126 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_NULL_PAINT_DEVICE_H +#define QWT_NULL_PAINT_DEVICE_H 1 + +#include "qwt_global.h" +#include +#include + +/*! + \brief A null paint device doing nothing + + Sometimes important layout/rendering geometries are not + available or changeable from the public Qt class interface. + ( f.e hidden in the style implementation ). + + QwtNullPaintDevice can be used to manipulate or filter out + this information by analyzing the stream of paint primitives. + + F.e. QwtNullPaintDevice is used by QwtPlotCanvas to identify + styled backgrounds with rounded corners. +*/ + +class QWT_EXPORT QwtNullPaintDevice: public QPaintDevice +{ +public: + /*! + \brief Render mode + + \sa setMode(), mode() + */ + enum Mode + { + /*! + All vector graphic primitives are painted by + the corresponding draw methods + */ + NormalMode, + + /*! + Vector graphic primitives ( beside polygons ) are mapped to a QPainterPath + and are painted by drawPath. In PathMode mode + only a few draw methods are called: + + - drawPath() + - drawPixmap() + - drawImage() + - drawPolygon() + */ + PolygonPathMode, + + /*! + Vector graphic primitives are mapped to a QPainterPath + and are painted by drawPath. In PathMode mode + only a few draw methods are called: + + - drawPath() + - drawPixmap() + - drawImage() + */ + PathMode + }; + + QwtNullPaintDevice(); + virtual ~QwtNullPaintDevice(); + + void setMode( Mode ); + Mode mode() const; + + virtual QPaintEngine *paintEngine() const; + + virtual int metric( PaintDeviceMetric metric ) const; + + virtual void drawRects(const QRect *, int ); + virtual void drawRects(const QRectF *, int ); + + virtual void drawLines(const QLine *, int ); + virtual void drawLines(const QLineF *, int ); + + virtual void drawEllipse(const QRectF &); + virtual void drawEllipse(const QRect &); + + virtual void drawPath(const QPainterPath &); + + virtual void drawPoints(const QPointF *, int ); + virtual void drawPoints(const QPoint *, int ); + + virtual void drawPolygon( + const QPointF *, int , QPaintEngine::PolygonDrawMode ); + + virtual void drawPolygon( + const QPoint *, int , QPaintEngine::PolygonDrawMode ); + + virtual void drawPixmap(const QRectF &, + const QPixmap &, const QRectF &); + + virtual void drawTextItem(const QPointF &, const QTextItem &); + + virtual void drawTiledPixmap(const QRectF &, + const QPixmap &, const QPointF &s); + + virtual void drawImage(const QRectF &, + const QImage &, const QRectF &, Qt::ImageConversionFlags ); + + virtual void updateState( const QPaintEngineState &state ); + +protected: + //! \return Size needed to implement metric() + virtual QSize sizeMetrics() const = 0; + +private: + class PaintEngine; + PaintEngine *d_engine; + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_painter.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_painter.cpp new file mode 100644 index 0000000..b952ea2 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_painter.cpp @@ -0,0 +1,1298 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_painter.h" +#include "qwt_math.h" +#include "qwt_clipper.h" +#include "qwt_color_map.h" +#include "qwt_scale_map.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if QT_VERSION >= 0x050000 +#include +#endif + +#if QT_VERSION < 0x050000 + +#ifdef Q_WS_X11 +#include +#endif + +#endif + +bool QwtPainter::d_polylineSplitting = true; +bool QwtPainter::d_roundingAlignment = true; + +static inline bool qwtIsClippingNeeded( + const QPainter *painter, QRectF &clipRect ) +{ + bool doClipping = false; + const QPaintEngine *pe = painter->paintEngine(); + if ( pe && pe->type() == QPaintEngine::SVG ) + { + // The SVG paint engine ignores any clipping, + + if ( painter->hasClipping() ) + { + doClipping = true; + clipRect = painter->clipRegion().boundingRect(); + } + } + + return doClipping; +} + +template +static inline void qwtDrawPolyline( QPainter *painter, + const T *points, int pointCount, bool polylineSplitting ) +{ + bool doSplit = false; + if ( polylineSplitting ) + { + const QPaintEngine *pe = painter->paintEngine(); + if ( pe && pe->type() == QPaintEngine::Raster ) + { + /* + The raster paint engine seems to use some algo with O(n*n). + ( Qt 4.3 is better than Qt 4.2, but remains unacceptable) + To work around this problem, we have to split the polygon into + smaller pieces. + */ + doSplit = true; + } + } + + if ( doSplit ) + { + const int splitSize = 6; + + for ( int i = 0; i < pointCount; i += splitSize ) + { + const int n = qMin( splitSize + 1, pointCount - i ); + painter->drawPolyline( points + i, n ); + } + } + else + { + painter->drawPolyline( points, pointCount ); + } +} + +static inline QSize qwtScreenResolution() +{ + static QSize screenResolution; + if ( !screenResolution.isValid() ) + { + QDesktopWidget *desktop = QApplication::desktop(); + if ( desktop ) + { + screenResolution.setWidth( desktop->logicalDpiX() ); + screenResolution.setHeight( desktop->logicalDpiY() ); + } + } + + return screenResolution; +} + +static inline void qwtUnscaleFont( QPainter *painter ) +{ + if ( painter->font().pixelSize() >= 0 ) + return; + + const QSize screenResolution = qwtScreenResolution(); + + const QPaintDevice *pd = painter->device(); + if ( pd->logicalDpiX() != screenResolution.width() || + pd->logicalDpiY() != screenResolution.height() ) + { + QFont pixelFont( painter->font(), QApplication::desktop() ); + pixelFont.setPixelSize( QFontInfo( pixelFont ).pixelSize() ); + + painter->setFont( pixelFont ); + } +} + +/*! + Check is the application is running with the X11 graphics system + that has some special capabilities that can be used for incremental + painting to a widget. + + \return True, when the graphics system is X11 +*/ +bool QwtPainter::isX11GraphicsSystem() +{ + static int onX11 = -1; + if ( onX11 < 0 ) + { + QPixmap pm( 1, 1 ); + QPainter painter( &pm ); + + onX11 = ( painter.paintEngine()->type() == QPaintEngine::X11 ) ? 1 : 0; + } + + return onX11 == 1; +} + +/*! + Check if the painter is using a paint engine, that aligns + coordinates to integers. Today these are all paint engines + beside QPaintEngine::Pdf and QPaintEngine::SVG. + + If we have an integer based paint engine it is also + checked if the painter has a transformation matrix, + that rotates or scales. + + \param painter Painter + \return true, when the painter is aligning + + \sa setRoundingAlignment() +*/ +bool QwtPainter::isAligning( QPainter *painter ) +{ + if ( painter && painter->isActive() ) + { + switch ( painter->paintEngine()->type() ) + { + case QPaintEngine::Pdf: + case QPaintEngine::SVG: + return false; + + default:; + } + + const QTransform tr = painter->transform(); + if ( tr.isRotating() || tr.isScaling() ) + { + // we might have to check translations too + return false; + } + } + + return true; +} + +/*! + Enable whether coordinates should be rounded, before they are painted + to a paint engine that floors to integer values. For other paint engines + ( PDF, SVG ) this flag has no effect. + QwtPainter stores this flag only, the rounding itself is done in + the painting code ( f.e the plot items ). + + The default setting is true. + + \sa roundingAlignment(), isAligning() +*/ +void QwtPainter::setRoundingAlignment( bool enable ) +{ + d_roundingAlignment = enable; +} + +/*! + \brief En/Disable line splitting for the raster paint engine + + In some Qt versions the raster paint engine paints polylines of many points + much faster when they are split in smaller chunks: f.e all supported Qt versions + >= Qt 5.0 when drawing an antialiased polyline with a pen width >=2. + + The default setting is true. + + \sa polylineSplitting() +*/ +void QwtPainter::setPolylineSplitting( bool enable ) +{ + d_polylineSplitting = enable; +} + +//! Wrapper for QPainter::drawPath() +void QwtPainter::drawPath( QPainter *painter, const QPainterPath &path ) +{ + painter->drawPath( path ); +} + +//! Wrapper for QPainter::drawRect() +void QwtPainter::drawRect( QPainter *painter, double x, double y, double w, double h ) +{ + drawRect( painter, QRectF( x, y, w, h ) ); +} + +//! Wrapper for QPainter::drawRect() +void QwtPainter::drawRect( QPainter *painter, const QRectF &rect ) +{ + const QRectF r = rect; + + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + if ( deviceClipping ) + { + if ( !clipRect.intersects( r ) ) + return; + + if ( !clipRect.contains( r ) ) + { + fillRect( painter, r & clipRect, painter->brush() ); + + painter->save(); + painter->setBrush( Qt::NoBrush ); + drawPolyline( painter, QPolygonF( r ) ); + painter->restore(); + + return; + } + } + + painter->drawRect( r ); +} + +//! Wrapper for QPainter::fillRect() +void QwtPainter::fillRect( QPainter *painter, + const QRectF &rect, const QBrush &brush ) +{ + if ( !rect.isValid() ) + return; + + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + /* + Performance of Qt4 is horrible for a non trivial brush. Without + clipping expect minutes or hours for repainting large rectangles + (might result from zooming) + */ + + if ( deviceClipping ) + clipRect &= painter->window(); + else + clipRect = painter->window(); + + if ( painter->hasClipping() ) + clipRect &= painter->clipRegion().boundingRect(); + + QRectF r = rect; + if ( deviceClipping ) + r = r.intersected( clipRect ); + + if ( r.isValid() ) + painter->fillRect( r, brush ); +} + +//! Wrapper for QPainter::drawPie() +void QwtPainter::drawPie( QPainter *painter, const QRectF &rect, + int a, int alen ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + if ( deviceClipping && !clipRect.contains( rect ) ) + return; + + painter->drawPie( rect, a, alen ); +} + +//! Wrapper for QPainter::drawEllipse() +void QwtPainter::drawEllipse( QPainter *painter, const QRectF &rect ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + if ( deviceClipping && !clipRect.contains( rect ) ) + return; + + painter->drawEllipse( rect ); +} + +//! Wrapper for QPainter::drawText() +void QwtPainter::drawText( QPainter *painter, double x, double y, + const QString &text ) +{ + drawText( painter, QPointF( x, y ), text ); +} + +//! Wrapper for QPainter::drawText() +void QwtPainter::drawText( QPainter *painter, const QPointF &pos, + const QString &text ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + if ( deviceClipping && !clipRect.contains( pos ) ) + return; + + + painter->save(); + qwtUnscaleFont( painter ); + painter->drawText( pos, text ); + painter->restore(); +} + +//! Wrapper for QPainter::drawText() +void QwtPainter::drawText( QPainter *painter, + double x, double y, double w, double h, + int flags, const QString &text ) +{ + drawText( painter, QRectF( x, y, w, h ), flags, text ); +} + +//! Wrapper for QPainter::drawText() +void QwtPainter::drawText( QPainter *painter, const QRectF &rect, + int flags, const QString &text ) +{ + painter->save(); + qwtUnscaleFont( painter ); + painter->drawText( rect, flags, text ); + painter->restore(); +} + +#ifndef QT_NO_RICHTEXT + +/*! + Draw a text document into a rectangle + + \param painter Painter + \param rect Traget rectangle + \param flags Alignments/Text flags, see QPainter::drawText() + \param text Text document +*/ +void QwtPainter::drawSimpleRichText( QPainter *painter, const QRectF &rect, + int flags, const QTextDocument &text ) +{ + QTextDocument *txt = text.clone(); + + painter->save(); + + QRectF unscaledRect = rect; + + if ( painter->font().pixelSize() < 0 ) + { + const QSize res = qwtScreenResolution(); + + const QPaintDevice *pd = painter->device(); + if ( pd->logicalDpiX() != res.width() || + pd->logicalDpiY() != res.height() ) + { + QTransform transform; + transform.scale( res.width() / double( pd->logicalDpiX() ), + res.height() / double( pd->logicalDpiY() )); + + painter->setWorldTransform( transform, true ); + unscaledRect = transform.inverted().mapRect(rect); + } + } + + txt->setDefaultFont( painter->font() ); + txt->setPageSize( QSizeF( unscaledRect.width(), QWIDGETSIZE_MAX ) ); + + QAbstractTextDocumentLayout* layout = txt->documentLayout(); + + const double height = layout->documentSize().height(); + double y = unscaledRect.y(); + if ( flags & Qt::AlignBottom ) + y += ( unscaledRect.height() - height ); + else if ( flags & Qt::AlignVCenter ) + y += ( unscaledRect.height() - height ) / 2; + + QAbstractTextDocumentLayout::PaintContext context; + context.palette.setColor( QPalette::Text, painter->pen().color() ); + + painter->translate( unscaledRect.x(), y ); + layout->draw( painter, context ); + + painter->restore(); + delete txt; +} + +#endif // !QT_NO_RICHTEXT + + +//! Wrapper for QPainter::drawLine() +void QwtPainter::drawLine( QPainter *painter, + const QPointF &p1, const QPointF &p2 ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + if ( deviceClipping && + !( clipRect.contains( p1 ) && clipRect.contains( p2 ) ) ) + { + QPolygonF polygon; + polygon += p1; + polygon += p2; + drawPolyline( painter, polygon ); + return; + } + + painter->drawLine( p1, p2 ); +} + +//! Wrapper for QPainter::drawPolygon() +void QwtPainter::drawPolygon( QPainter *painter, const QPolygonF &polygon ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + QPolygonF cpa = polygon; + if ( deviceClipping ) + cpa = QwtClipper::clipPolygonF( clipRect, polygon ); + + painter->drawPolygon( cpa ); +} + +//! Wrapper for QPainter::drawPolyline() +void QwtPainter::drawPolyline( QPainter *painter, const QPolygonF &polygon ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + QPolygonF cpa = polygon; + if ( deviceClipping ) + cpa = QwtClipper::clipPolygonF( clipRect, cpa ); + + qwtDrawPolyline( painter, + cpa.constData(), cpa.size(), d_polylineSplitting ); +} + +//! Wrapper for QPainter::drawPolyline() +void QwtPainter::drawPolyline( QPainter *painter, + const QPointF *points, int pointCount ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + if ( deviceClipping ) + { + QPolygonF polygon( pointCount ); + ::memcpy( polygon.data(), points, pointCount * sizeof( QPointF ) ); + + polygon = QwtClipper::clipPolygonF( clipRect, polygon ); + qwtDrawPolyline( painter, + polygon.constData(), polygon.size(), d_polylineSplitting ); + } + else + { + qwtDrawPolyline( painter, points, pointCount, d_polylineSplitting ); + } +} + +//! Wrapper for QPainter::drawPolygon() +void QwtPainter::drawPolygon( QPainter *painter, const QPolygon &polygon ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + QPolygon cpa = polygon; + if ( deviceClipping ) + cpa = QwtClipper::clipPolygon( clipRect, polygon ); + + painter->drawPolygon( cpa ); +} + +//! Wrapper for QPainter::drawPolyline() +void QwtPainter::drawPolyline( QPainter *painter, const QPolygon &polygon ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + QPolygon cpa = polygon; + if ( deviceClipping ) + cpa = QwtClipper::clipPolygon( clipRect, cpa ); + + qwtDrawPolyline( painter, + cpa.constData(), cpa.size(), d_polylineSplitting ); +} + +//! Wrapper for QPainter::drawPolyline() +void QwtPainter::drawPolyline( QPainter *painter, + const QPoint *points, int pointCount ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + if ( deviceClipping ) + { + QPolygon polygon( pointCount ); + ::memcpy( polygon.data(), points, pointCount * sizeof( QPoint ) ); + + polygon = QwtClipper::clipPolygon( clipRect, polygon ); + qwtDrawPolyline( painter, + polygon.constData(), polygon.size(), d_polylineSplitting ); + } + else + qwtDrawPolyline( painter, points, pointCount, d_polylineSplitting ); +} + +//! Wrapper for QPainter::drawPoint() +void QwtPainter::drawPoint( QPainter *painter, const QPointF &pos ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + if ( deviceClipping && !clipRect.contains( pos ) ) + return; + + painter->drawPoint( pos ); +} + +//! Wrapper for QPainter::drawPoint() +void QwtPainter::drawPoint( QPainter *painter, const QPoint &pos ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + if ( deviceClipping ) + { + const int minX = qCeil( clipRect.left() ); + const int maxX = qFloor( clipRect.right() ); + const int minY = qCeil( clipRect.top() ); + const int maxY = qFloor( clipRect.bottom() ); + + if ( pos.x() < minX || pos.x() > maxX + || pos.y() < minY || pos.y() > maxY ) + { + return; + } + } + + painter->drawPoint( pos ); +} + +//! Wrapper for QPainter::drawPoints() +void QwtPainter::drawPoints( QPainter *painter, + const QPoint *points, int pointCount ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + if ( deviceClipping ) + { + const int minX = qCeil( clipRect.left() ); + const int maxX = qFloor( clipRect.right() ); + const int minY = qCeil( clipRect.top() ); + const int maxY = qFloor( clipRect.bottom() ); + + const QRect r( minX, minY, maxX - minX, maxY - minY ); + + QPolygon clippedPolygon( pointCount ); + QPoint *clippedData = clippedPolygon.data(); + + int numClippedPoints = 0; + for ( int i = 0; i < pointCount; i++ ) + { + if ( r.contains( points[i] ) ) + clippedData[ numClippedPoints++ ] = points[i]; + } + painter->drawPoints( clippedData, numClippedPoints ); + } + else + { + painter->drawPoints( points, pointCount ); + } +} + +//! Wrapper for QPainter::drawPoints() +void QwtPainter::drawPoints( QPainter *painter, + const QPointF *points, int pointCount ) +{ + QRectF clipRect; + const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect ); + + if ( deviceClipping ) + { + QPolygonF clippedPolygon( pointCount ); + QPointF *clippedData = clippedPolygon.data(); + + int numClippedPoints = 0; + for ( int i = 0; i < pointCount; i++ ) + { + if ( clipRect.contains( points[i] ) ) + clippedData[ numClippedPoints++ ] = points[i]; + } + painter->drawPoints( clippedData, numClippedPoints ); + } + else + { + painter->drawPoints( points, pointCount ); + } +} + +//! Wrapper for QPainter::drawImage() +void QwtPainter::drawImage( QPainter *painter, + const QRectF &rect, const QImage &image ) +{ + const QRect alignedRect = rect.toAlignedRect(); + + if ( alignedRect != rect ) + { + const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 ); + + painter->save(); + painter->setClipRect( clipRect, Qt::IntersectClip ); + painter->drawImage( alignedRect, image ); + painter->restore(); + } + else + { + painter->drawImage( alignedRect, image ); + } +} + +//! Wrapper for QPainter::drawPixmap() +void QwtPainter::drawPixmap( QPainter *painter, + const QRectF &rect, const QPixmap &pixmap ) +{ + const QRect alignedRect = rect.toAlignedRect(); + + if ( alignedRect != rect ) + { + const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 ); + + painter->save(); + painter->setClipRect( clipRect, Qt::IntersectClip ); + painter->drawPixmap( alignedRect, pixmap ); + painter->restore(); + } + else + { + painter->drawPixmap( alignedRect, pixmap ); + } +} + +//! Draw a focus rectangle on a widget using its style. +void QwtPainter::drawFocusRect( QPainter *painter, const QWidget *widget ) +{ + drawFocusRect( painter, widget, widget->rect() ); +} + +//! Draw a focus rectangle on a widget using its style. +void QwtPainter::drawFocusRect( QPainter *painter, const QWidget *widget, + const QRect &rect ) +{ + QStyleOptionFocusRect opt; + opt.init( widget ); + opt.rect = rect; + opt.state |= QStyle::State_HasFocus; + + widget->style()->drawPrimitive( QStyle::PE_FrameFocusRect, + &opt, painter, widget ); +} + +/*! + Draw a round frame + + \param painter Painter + \param rect Frame rectangle + \param palette QPalette::WindowText is used for plain borders + QPalette::Dark and QPalette::Light for raised + or sunken borders + \param lineWidth Line width + \param frameStyle bitwise OR´ed value of QFrame::Shape and QFrame::Shadow +*/ +void QwtPainter::drawRoundFrame( QPainter *painter, + const QRectF &rect, const QPalette &palette, + int lineWidth, int frameStyle ) +{ + enum Style + { + Plain, + Sunken, + Raised + }; + + Style style = Plain; + if ( (frameStyle & QFrame::Sunken) == QFrame::Sunken ) + style = Sunken; + else if ( (frameStyle & QFrame::Raised) == QFrame::Raised ) + style = Raised; + + const double lw2 = 0.5 * lineWidth; + QRectF r = rect.adjusted( lw2, lw2, -lw2, -lw2 ); + + QBrush brush; + + if ( style != Plain ) + { + QColor c1 = palette.color( QPalette::Light ); + QColor c2 = palette.color( QPalette::Dark ); + + if ( style == Sunken ) + qSwap( c1, c2 ); + + QLinearGradient gradient( r.topLeft(), r.bottomRight() ); + gradient.setColorAt( 0.0, c1 ); +#if 0 + gradient.setColorAt( 0.3, c1 ); + gradient.setColorAt( 0.7, c2 ); +#endif + gradient.setColorAt( 1.0, c2 ); + + brush = QBrush( gradient ); + } + else // Plain + { + brush = palette.brush( QPalette::WindowText ); + } + + painter->save(); + + painter->setPen( QPen( brush, lineWidth ) ); + painter->setBrush( Qt::NoBrush ); + + painter->drawEllipse( r ); + + painter->restore(); +} + +/*! + Draw a rectangular frame + + \param painter Painter + \param rect Frame rectangle + \param palette Palette + \param foregroundRole Foreground role used for QFrame::Plain + \param frameWidth Frame width + \param midLineWidth Used for QFrame::Box + \param frameStyle bitwise OR´ed value of QFrame::Shape and QFrame::Shadow +*/ +void QwtPainter::drawFrame( QPainter *painter, const QRectF &rect, + const QPalette &palette, QPalette::ColorRole foregroundRole, + int frameWidth, int midLineWidth, int frameStyle ) +{ + if ( frameWidth <= 0 || rect.isEmpty() ) + return; + + const int shadow = frameStyle & QFrame::Shadow_Mask; + + painter->save(); + + if ( shadow == QFrame::Plain ) + { + const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 ); + const QRectF innerRect = outerRect.adjusted( + frameWidth, frameWidth, -frameWidth, -frameWidth ); + + QPainterPath path; + path.addRect( outerRect ); + path.addRect( innerRect ); + + painter->setPen( Qt::NoPen ); + painter->setBrush( palette.color( foregroundRole ) ); + + painter->drawPath( path ); + } + else + { + const int shape = frameStyle & QFrame::Shape_Mask; + + if ( shape == QFrame::Box ) + { + const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 ); + const QRectF midRect1 = outerRect.adjusted( + frameWidth, frameWidth, -frameWidth, -frameWidth ); + const QRectF midRect2 = midRect1.adjusted( + midLineWidth, midLineWidth, -midLineWidth, -midLineWidth ); + + const QRectF innerRect = midRect2.adjusted( + frameWidth, frameWidth, -frameWidth, -frameWidth ); + + QPainterPath path1; + path1.moveTo( outerRect.bottomLeft() ); + path1.lineTo( outerRect.topLeft() ); + path1.lineTo( outerRect.topRight() ); + path1.lineTo( midRect1.topRight() ); + path1.lineTo( midRect1.topLeft() ); + path1.lineTo( midRect1.bottomLeft() ); + + QPainterPath path2; + path2.moveTo( outerRect.bottomLeft() ); + path2.lineTo( outerRect.bottomRight() ); + path2.lineTo( outerRect.topRight() ); + path2.lineTo( midRect1.topRight() ); + path2.lineTo( midRect1.bottomRight() ); + path2.lineTo( midRect1.bottomLeft() ); + + QPainterPath path3; + path3.moveTo( midRect2.bottomLeft() ); + path3.lineTo( midRect2.topLeft() ); + path3.lineTo( midRect2.topRight() ); + path3.lineTo( innerRect.topRight() ); + path3.lineTo( innerRect.topLeft() ); + path3.lineTo( innerRect.bottomLeft() ); + + QPainterPath path4; + path4.moveTo( midRect2.bottomLeft() ); + path4.lineTo( midRect2.bottomRight() ); + path4.lineTo( midRect2.topRight() ); + path4.lineTo( innerRect.topRight() ); + path4.lineTo( innerRect.bottomRight() ); + path4.lineTo( innerRect.bottomLeft() ); + + QPainterPath path5; + path5.addRect( midRect1 ); + path5.addRect( midRect2 ); + + painter->setPen( Qt::NoPen ); + + QBrush brush1 = palette.dark().color(); + QBrush brush2 = palette.light().color(); + + if ( shadow == QFrame::Raised ) + qSwap( brush1, brush2 ); + + painter->setBrush( brush1 ); + painter->drawPath( path1 ); + painter->drawPath( path4 ); + + painter->setBrush( brush2 ); + painter->drawPath( path2 ); + painter->drawPath( path3 ); + + painter->setBrush( palette.mid() ); + painter->drawPath( path5 ); + } +#if 0 + // qDrawWinPanel doesn't result in something nice + // on a scalable document like PDF. Better draw a + // Panel. + + else if ( shape == QFrame::WinPanel ) + { + painter->setRenderHint( QPainter::NonCosmeticDefaultPen, true ); + qDrawWinPanel ( painter, rect.toRect(), palette, + frameStyle & QFrame::Sunken ); + } + else if ( shape == QFrame::StyledPanel ) + { + } +#endif + else + { + const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 ); + const QRectF innerRect = outerRect.adjusted( + frameWidth - 1.0, frameWidth - 1.0, + -( frameWidth - 1.0 ), -( frameWidth - 1.0 ) ); + + QPainterPath path1; + path1.moveTo( outerRect.bottomLeft() ); + path1.lineTo( outerRect.topLeft() ); + path1.lineTo( outerRect.topRight() ); + path1.lineTo( innerRect.topRight() ); + path1.lineTo( innerRect.topLeft() ); + path1.lineTo( innerRect.bottomLeft() ); + + + QPainterPath path2; + path2.moveTo( outerRect.bottomLeft() ); + path2.lineTo( outerRect.bottomRight() ); + path2.lineTo( outerRect.topRight() ); + path2.lineTo( innerRect.topRight() ); + path2.lineTo( innerRect.bottomRight() ); + path2.lineTo( innerRect.bottomLeft() ); + + painter->setPen( Qt::NoPen ); + + QBrush brush1 = palette.dark().color(); + QBrush brush2 = palette.light().color(); + + if ( shadow == QFrame::Raised ) + qSwap( brush1, brush2 ); + + painter->setBrush( brush1 ); + painter->drawPath( path1 ); + + painter->setBrush( brush2 ); + painter->drawPath( path2 ); + } + + } + + painter->restore(); +} + +/*! + Draw a rectangular frame with rounded borders + + \param painter Painter + \param rect Frame rectangle + \param xRadius x-radius of the ellipses defining the corners + \param yRadius y-radius of the ellipses defining the corners + \param palette QPalette::WindowText is used for plain borders + QPalette::Dark and QPalette::Light for raised + or sunken borders + \param lineWidth Line width + \param frameStyle bitwise OR´ed value of QFrame::Shape and QFrame::Shadow +*/ + +void QwtPainter::drawRoundedFrame( QPainter *painter, + const QRectF &rect, double xRadius, double yRadius, + const QPalette &palette, int lineWidth, int frameStyle ) +{ + painter->save(); + painter->setRenderHint( QPainter::Antialiasing, true ); + painter->setBrush( Qt::NoBrush ); + + double lw2 = lineWidth * 0.5; + QRectF r = rect.adjusted( lw2, lw2, -lw2, -lw2 ); + + QPainterPath path; + path.addRoundedRect( r, xRadius, yRadius ); + + enum Style + { + Plain, + Sunken, + Raised + }; + + Style style = Plain; + if ( (frameStyle & QFrame::Sunken) == QFrame::Sunken ) + style = Sunken; + else if ( (frameStyle & QFrame::Raised) == QFrame::Raised ) + style = Raised; + + if ( style != Plain && path.elementCount() == 17 ) + { + // move + 4 * ( cubicTo + lineTo ) + QPainterPath pathList[8]; + + for ( int i = 0; i < 4; i++ ) + { + const int j = i * 4 + 1; + + pathList[ 2 * i ].moveTo( + path.elementAt(j - 1).x, path.elementAt( j - 1 ).y + ); + + pathList[ 2 * i ].cubicTo( + path.elementAt(j + 0).x, path.elementAt(j + 0).y, + path.elementAt(j + 1).x, path.elementAt(j + 1).y, + path.elementAt(j + 2).x, path.elementAt(j + 2).y ); + + pathList[ 2 * i + 1 ].moveTo( + path.elementAt(j + 2).x, path.elementAt(j + 2).y + ); + pathList[ 2 * i + 1 ].lineTo( + path.elementAt(j + 3).x, path.elementAt(j + 3).y + ); + } + + QColor c1( palette.color( QPalette::Dark ) ); + QColor c2( palette.color( QPalette::Light ) ); + + if ( style == Raised ) + qSwap( c1, c2 ); + + for ( int i = 0; i < 4; i++ ) + { + QRectF r = pathList[2 * i].controlPointRect(); + + QPen arcPen; + arcPen.setCapStyle( Qt::FlatCap ); + arcPen.setWidth( lineWidth ); + + QPen linePen; + linePen.setCapStyle( Qt::FlatCap ); + linePen.setWidth( lineWidth ); + + switch( i ) + { + case 0: + { + arcPen.setColor( c1 ); + linePen.setColor( c1 ); + break; + } + case 1: + { + QLinearGradient gradient; + gradient.setStart( r.topLeft() ); + gradient.setFinalStop( r.bottomRight() ); + gradient.setColorAt( 0.0, c1 ); + gradient.setColorAt( 1.0, c2 ); + + arcPen.setBrush( gradient ); + linePen.setColor( c2 ); + break; + } + case 2: + { + arcPen.setColor( c2 ); + linePen.setColor( c2 ); + break; + } + case 3: + { + QLinearGradient gradient; + + gradient.setStart( r.bottomRight() ); + gradient.setFinalStop( r.topLeft() ); + gradient.setColorAt( 0.0, c2 ); + gradient.setColorAt( 1.0, c1 ); + + arcPen.setBrush( gradient ); + linePen.setColor( c1 ); + break; + } + } + + + painter->setPen( arcPen ); + painter->drawPath( pathList[ 2 * i] ); + + painter->setPen( linePen ); + painter->drawPath( pathList[ 2 * i + 1] ); + } + } + else + { + QPen pen( palette.color( QPalette::WindowText ), lineWidth ); + painter->setPen( pen ); + painter->drawPath( path ); + } + + painter->restore(); +} + +/*! + Draw a color bar into a rectangle + + \param painter Painter + \param colorMap Color map + \param interval Value range + \param scaleMap Scale map + \param orientation Orientation + \param rect Traget rectangle +*/ +void QwtPainter::drawColorBar( QPainter *painter, + const QwtColorMap &colorMap, const QwtInterval &interval, + const QwtScaleMap &scaleMap, Qt::Orientation orientation, + const QRectF &rect ) +{ + QVector colorTable; + if ( colorMap.format() == QwtColorMap::Indexed ) + colorTable = colorMap.colorTable( interval ); + + QColor c; + + const QRect devRect = rect.toAlignedRect(); + + /* + We paint to a pixmap first to have something scalable for printing + ( f.e. in a Pdf document ) + */ + + QPixmap pixmap( devRect.size() ); + pixmap.fill( Qt::transparent ); + + QPainter pmPainter( &pixmap ); + pmPainter.translate( -devRect.x(), -devRect.y() ); + + if ( orientation == Qt::Horizontal ) + { + QwtScaleMap sMap = scaleMap; + sMap.setPaintInterval( rect.left(), rect.right() ); + + for ( int x = devRect.left(); x <= devRect.right(); x++ ) + { + const double value = sMap.invTransform( x ); + + if ( colorMap.format() == QwtColorMap::RGB ) + c.setRgba( colorMap.rgb( interval, value ) ); + else + c = colorTable[colorMap.colorIndex( interval, value )]; + + pmPainter.setPen( c ); + pmPainter.drawLine( x, devRect.top(), x, devRect.bottom() ); + } + } + else // Vertical + { + QwtScaleMap sMap = scaleMap; + sMap.setPaintInterval( rect.bottom(), rect.top() ); + + for ( int y = devRect.top(); y <= devRect.bottom(); y++ ) + { + const double value = sMap.invTransform( y ); + + if ( colorMap.format() == QwtColorMap::RGB ) + c.setRgba( colorMap.rgb( interval, value ) ); + else + c = colorTable[colorMap.colorIndex( interval, value )]; + + pmPainter.setPen( c ); + pmPainter.drawLine( devRect.left(), y, devRect.right(), y ); + } + } + pmPainter.end(); + + drawPixmap( painter, rect, pixmap ); +} + +static inline void qwtFillRect( const QWidget *widget, QPainter *painter, + const QRect &rect, const QBrush &brush) +{ + if ( brush.style() == Qt::TexturePattern ) + { + painter->save(); + + painter->setClipRect( rect ); + painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); + + painter->restore(); + } + else if ( brush.gradient() ) + { + painter->save(); + + painter->setClipRect( rect ); + painter->fillRect(0, 0, widget->width(), + widget->height(), brush); + + painter->restore(); + } + else + { + painter->fillRect(rect, brush); + } +} + +/*! + Fill a pixmap with the content of a widget + + In Qt >= 5.0 QPixmap::fill() is a nop, in Qt 4.x it is buggy + for backgrounds with gradients. Thus fillPixmap() offers + an alternative implementation. + + \param widget Widget + \param pixmap Pixmap to be filled + \param offset Offset + + \sa QPixmap::fill() + */ +void QwtPainter::fillPixmap( const QWidget *widget, + QPixmap &pixmap, const QPoint &offset ) +{ + const QRect rect( offset, pixmap.size() ); + + QPainter painter( &pixmap ); + painter.translate( -offset ); + + const QBrush autoFillBrush = + widget->palette().brush( widget->backgroundRole() ); + + if ( !( widget->autoFillBackground() && autoFillBrush.isOpaque() ) ) + { + const QBrush bg = widget->palette().brush( QPalette::Window ); + qwtFillRect( widget, &painter, rect, bg); + } + + if ( widget->autoFillBackground() ) + qwtFillRect( widget, &painter, rect, autoFillBrush); + + if ( widget->testAttribute(Qt::WA_StyledBackground) ) + { + painter.setClipRegion( rect ); + + QStyleOption opt; + opt.initFrom( widget ); + widget->style()->drawPrimitive( QStyle::PE_Widget, + &opt, &painter, widget ); + } +} + +/*! + Fill rect with the background of a widget + + \param painter Painter + \param rect Rectangle to be filled + \param widget Widget + + \sa QStyle::PE_Widget, QWidget::backgroundRole() + */ +void QwtPainter::drawBackgound( QPainter *painter, + const QRectF &rect, const QWidget *widget ) +{ + if ( widget->testAttribute( Qt::WA_StyledBackground ) ) + { + QStyleOption opt; + opt.initFrom( widget ); + opt.rect = rect.toAlignedRect(); + + widget->style()->drawPrimitive( + QStyle::PE_Widget, &opt, painter, widget); + } + else + { + const QBrush brush = + widget->palette().brush( widget->backgroundRole() ); + + painter->fillRect( rect, brush ); + } +} + +/*! + \return A pixmap that can be used as backing store + + \param widget Widget, for which the backinstore is intended + \param size Size of the pixmap + */ +QPixmap QwtPainter::backingStore( QWidget *widget, const QSize &size ) +{ + QPixmap pm; + +#define QWT_HIGH_DPI 1 + +#if QT_VERSION >= 0x050000 && QWT_HIGH_DPI + qreal pixelRatio = 1.0; + + if ( widget && widget->windowHandle() ) + { +#if QT_VERSION < 0x050100 + pixelRatio = widget->windowHandle()->devicePixelRatio(); +#else + pixelRatio = widget->devicePixelRatio(); +#endif + } + else + { + if ( qApp ) + pixelRatio = qApp->devicePixelRatio(); + } + + pm = QPixmap( size * pixelRatio ); + pm.setDevicePixelRatio( pixelRatio ); +#else + Q_UNUSED( widget ) + pm = QPixmap( size ); +#endif + +#if QT_VERSION < 0x050000 +#ifdef Q_WS_X11 + if ( widget && isX11GraphicsSystem() ) + { + if ( pm.x11Info().screen() != widget->x11Info().screen() ) + pm.x11SetScreen( widget->x11Info().screen() ); + } +#endif +#endif + + return pm; +} + diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_painter.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_painter.h new file mode 100644 index 0000000..871f95b --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_painter.h @@ -0,0 +1,188 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PAINTER_H +#define QWT_PAINTER_H + +#include "qwt_global.h" + +#include +#include +#include +#include +#include + +class QPainter; +class QBrush; +class QColor; +class QWidget; +class QPolygonF; +class QRectF; +class QImage; +class QPixmap; +class QwtScaleMap; +class QwtColorMap; +class QwtInterval; + +class QTextDocument; +class QPainterPath; + +/*! + \brief A collection of QPainter workarounds +*/ +class QWT_EXPORT QwtPainter +{ +public: + static void setPolylineSplitting( bool ); + static bool polylineSplitting(); + + static void setRoundingAlignment( bool ); + static bool roundingAlignment(); + static bool roundingAlignment(QPainter *); + + static void drawText( QPainter *, double x, double y, const QString & ); + static void drawText( QPainter *, const QPointF &, const QString & ); + static void drawText( QPainter *, double x, double y, double w, double h, + int flags, const QString & ); + static void drawText( QPainter *, const QRectF &, + int flags, const QString & ); + +#ifndef QT_NO_RICHTEXT + static void drawSimpleRichText( QPainter *, const QRectF &, + int flags, const QTextDocument & ); +#endif + + static void drawRect( QPainter *, double x, double y, double w, double h ); + static void drawRect( QPainter *, const QRectF &rect ); + static void fillRect( QPainter *, const QRectF &, const QBrush & ); + + static void drawEllipse( QPainter *, const QRectF & ); + static void drawPie( QPainter *, const QRectF & r, int a, int alen ); + + static void drawLine( QPainter *, double x1, double y1, double x2, double y2 ); + static void drawLine( QPainter *, const QPointF &p1, const QPointF &p2 ); + static void drawLine( QPainter *, const QLineF & ); + + static void drawPolygon( QPainter *, const QPolygonF & ); + static void drawPolyline( QPainter *, const QPolygonF & ); + static void drawPolyline( QPainter *, const QPointF *, int pointCount ); + + static void drawPolygon( QPainter *, const QPolygon & ); + static void drawPolyline( QPainter *, const QPolygon & ); + static void drawPolyline( QPainter *, const QPoint *, int pointCount ); + + static void drawPoint( QPainter *, const QPoint & ); + static void drawPoints( QPainter *, const QPolygon & ); + static void drawPoints( QPainter *, const QPoint *, int pointCount ); + + static void drawPoint( QPainter *, double x, double y ); + static void drawPoint( QPainter *, const QPointF & ); + static void drawPoints( QPainter *, const QPolygonF & ); + static void drawPoints( QPainter *, const QPointF *, int pointCount ); + + static void drawPath( QPainter *, const QPainterPath & ); + static void drawImage( QPainter *, const QRectF &, const QImage & ); + static void drawPixmap( QPainter *, const QRectF &, const QPixmap & ); + + static void drawRoundFrame( QPainter *, + const QRectF &, const QPalette &, int lineWidth, int frameStyle ); + + static void drawRoundedFrame( QPainter *, + const QRectF &, double xRadius, double yRadius, + const QPalette &, int lineWidth, int frameStyle ); + + static void drawFrame( QPainter *, const QRectF &rect, + const QPalette &palette, QPalette::ColorRole foregroundRole, + int lineWidth, int midLineWidth, int frameStyle ); + + static void drawFocusRect( QPainter *, const QWidget * ); + static void drawFocusRect( QPainter *, const QWidget *, const QRect & ); + + static void drawColorBar( QPainter *painter, + const QwtColorMap &, const QwtInterval &, + const QwtScaleMap &, Qt::Orientation, const QRectF & ); + + static bool isAligning( QPainter *painter ); + static bool isX11GraphicsSystem(); + + static void fillPixmap( const QWidget *, + QPixmap &, const QPoint &offset = QPoint() ); + + static void drawBackgound( QPainter *painter, + const QRectF &rect, const QWidget *widget ); + + static QPixmap backingStore( QWidget *, const QSize & ); + +private: + static bool d_polylineSplitting; + static bool d_roundingAlignment; +}; + +//! Wrapper for QPainter::drawPoint() +inline void QwtPainter::drawPoint( QPainter *painter, double x, double y ) +{ + QwtPainter::drawPoint( painter, QPointF( x, y ) ); +} + +//! Wrapper for QPainter::drawPoints() +inline void QwtPainter::drawPoints( QPainter *painter, const QPolygon &polygon ) +{ + drawPoints( painter, polygon.data(), polygon.size() ); +} + +//! Wrapper for QPainter::drawPoints() +inline void QwtPainter::drawPoints( QPainter *painter, const QPolygonF &polygon ) +{ + drawPoints( painter, polygon.data(), polygon.size() ); +} + +//! Wrapper for QPainter::drawLine() +inline void QwtPainter::drawLine( QPainter *painter, + double x1, double y1, double x2, double y2 ) +{ + QwtPainter::drawLine( painter, QPointF( x1, y1 ), QPointF( x2, y2 ) ); +} + +//! Wrapper for QPainter::drawLine() +inline void QwtPainter::drawLine( QPainter *painter, const QLineF &line ) +{ + QwtPainter::drawLine( painter, line.p1(), line.p2() ); +} + +/*! + \return True, when line splitting for the raster paint engine is enabled. + \sa setPolylineSplitting() +*/ +inline bool QwtPainter::polylineSplitting() +{ + return d_polylineSplitting; +} + +/*! + Check whether coordinates should be rounded, before they are painted + to a paint engine that rounds to integer values. For other paint engines + ( PDF, SVG ), this flag has no effect. + + \return True, when rounding is enabled + \sa setRoundingAlignment(), isAligning() +*/ +inline bool QwtPainter::roundingAlignment() +{ + return d_roundingAlignment; +} + +/*! + \return roundingAlignment() && isAligning(painter); + \param painter Painter +*/ +inline bool QwtPainter::roundingAlignment(QPainter *painter) +{ + return d_roundingAlignment && isAligning(painter); +} +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_painter_command.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_painter_command.cpp new file mode 100644 index 0000000..222f8b4 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_painter_command.cpp @@ -0,0 +1,237 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_painter_command.h" + +//! Construct an invalid command +QwtPainterCommand::QwtPainterCommand(): + d_type( Invalid ) +{ +} + +//! Copy constructor +QwtPainterCommand::QwtPainterCommand( const QPainterPath &path ): + d_type( Path ) +{ + d_path = new QPainterPath( path ); +} + +/*! + Constructor for Pixmap paint operation + + \param rect Target rectangle + \param pixmap Pixmap + \param subRect Rectangle inside the pixmap + + \sa QPainter::drawPixmap() + */ +QwtPainterCommand::QwtPainterCommand( const QRectF &rect, + const QPixmap &pixmap, const QRectF& subRect ): + d_type( Pixmap ) +{ + d_pixmapData = new PixmapData(); + d_pixmapData->rect = rect; + d_pixmapData->pixmap = pixmap; + d_pixmapData->subRect = subRect; +} + +/*! + Constructor for Image paint operation + + \param rect Target rectangle + \param image Image + \param subRect Rectangle inside the image + \param flags Conversion flags + + \sa QPainter::drawImage() + */ +QwtPainterCommand::QwtPainterCommand( const QRectF &rect, + const QImage &image, const QRectF& subRect, + Qt::ImageConversionFlags flags ): + d_type( Image ) +{ + d_imageData = new ImageData(); + d_imageData->rect = rect; + d_imageData->image = image; + d_imageData->subRect = subRect; + d_imageData->flags = flags; +} + +/*! + Constructor for State paint operation + \param state Paint engine state + */ +QwtPainterCommand::QwtPainterCommand( const QPaintEngineState &state ): + d_type( State ) +{ + d_stateData = new StateData(); + + d_stateData->flags = state.state(); + + if ( d_stateData->flags & QPaintEngine::DirtyPen ) + d_stateData->pen = state.pen(); + + if ( d_stateData->flags & QPaintEngine::DirtyBrush ) + d_stateData->brush = state.brush(); + + if ( d_stateData->flags & QPaintEngine::DirtyBrushOrigin ) + d_stateData->brushOrigin = state.brushOrigin(); + + if ( d_stateData->flags & QPaintEngine::DirtyFont ) + d_stateData->font = state.font(); + + if ( d_stateData->flags & QPaintEngine::DirtyBackground ) + { + d_stateData->backgroundMode = state.backgroundMode(); + d_stateData->backgroundBrush = state.backgroundBrush(); + } + + if ( d_stateData->flags & QPaintEngine::DirtyTransform ) + d_stateData->transform = state.transform(); + + if ( d_stateData->flags & QPaintEngine::DirtyClipEnabled ) + d_stateData->isClipEnabled = state.isClipEnabled(); + + if ( d_stateData->flags & QPaintEngine::DirtyClipRegion ) + { + d_stateData->clipRegion = state.clipRegion(); + d_stateData->clipOperation = state.clipOperation(); + } + + if ( d_stateData->flags & QPaintEngine::DirtyClipPath ) + { + d_stateData->clipPath = state.clipPath(); + d_stateData->clipOperation = state.clipOperation(); + } + + if ( d_stateData->flags & QPaintEngine::DirtyHints ) + d_stateData->renderHints = state.renderHints(); + + if ( d_stateData->flags & QPaintEngine::DirtyCompositionMode ) + d_stateData->compositionMode = state.compositionMode(); + + if ( d_stateData->flags & QPaintEngine::DirtyOpacity ) + d_stateData->opacity = state.opacity(); +} + +/*! + Copy constructor + \param other Command to be copied + + */ +QwtPainterCommand::QwtPainterCommand(const QwtPainterCommand &other) +{ + copy( other ); +} + +//! Destructor +QwtPainterCommand::~QwtPainterCommand() +{ + reset(); +} + +/*! + Assignment operator + + \param other Command to be copied + \return Modified command + */ +QwtPainterCommand &QwtPainterCommand::operator=(const QwtPainterCommand &other) +{ + reset(); + copy( other ); + + return *this; +} + +void QwtPainterCommand::copy( const QwtPainterCommand &other ) +{ + d_type = other.d_type; + + switch( other.d_type ) + { + case Path: + { + d_path = new QPainterPath( *other.d_path ); + break; + } + case Pixmap: + { + d_pixmapData = new PixmapData( *other.d_pixmapData ); + break; + } + case Image: + { + d_imageData = new ImageData( *other.d_imageData ); + break; + } + case State: + { + d_stateData = new StateData( *other.d_stateData ); + break; + } + default: + break; + } +} + +void QwtPainterCommand::reset() +{ + switch( d_type ) + { + case Path: + { + delete d_path; + break; + } + case Pixmap: + { + delete d_pixmapData; + break; + } + case Image: + { + delete d_imageData; + break; + } + case State: + { + delete d_stateData; + break; + } + default: + break; + } + + d_type = Invalid; +} + +//! \return Painter path to be painted +QPainterPath *QwtPainterCommand::path() +{ + return d_path; +} + +//! \return Attributes how to paint a QPixmap +QwtPainterCommand::PixmapData* QwtPainterCommand::pixmapData() +{ + return d_pixmapData; +} + +//! \return Attributes how to paint a QImage +QwtPainterCommand::ImageData* QwtPainterCommand::imageData() +{ + return d_imageData; +} + +//! \return Attributes of a state change +QwtPainterCommand::StateData* QwtPainterCommand::stateData() +{ + return d_stateData; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_painter_command.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_painter_command.h new file mode 100644 index 0000000..e3cdcb2 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_painter_command.h @@ -0,0 +1,173 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PAINTER_COMMAND_H +#define QWT_PAINTER_COMMAND_H + +#include "qwt_global.h" +#include +#include +#include +#include + +class QPainterPath; + +/*! + QwtPainterCommand represents the attributes of a paint operation + how it is used between QPainter and QPaintDevice + + It is used by QwtGraphic to record and replay paint operations + + \sa QwtGraphic::commands() + */ + +class QWT_EXPORT QwtPainterCommand +{ +public: + //! Type of the paint command + enum Type + { + //! Invalid command + Invalid = -1, + + //! Draw a QPainterPath + Path, + + //! Draw a QPixmap + Pixmap, + + //! Draw a QImage + Image, + + //! QPainter state change + State + }; + + //! Attributes how to paint a QPixmap + struct PixmapData + { + QRectF rect; + QPixmap pixmap; + QRectF subRect; + }; + + //! Attributes how to paint a QImage + struct ImageData + { + QRectF rect; + QImage image; + QRectF subRect; + Qt::ImageConversionFlags flags; + }; + + //! Attributes of a state change + struct StateData + { + QPaintEngine::DirtyFlags flags; + + QPen pen; + QBrush brush; + QPointF brushOrigin; + QBrush backgroundBrush; + Qt::BGMode backgroundMode; + QFont font; + QMatrix matrix; + QTransform transform; + + Qt::ClipOperation clipOperation; + QRegion clipRegion; + QPainterPath clipPath; + bool isClipEnabled; + + QPainter::RenderHints renderHints; + QPainter::CompositionMode compositionMode; + qreal opacity; + }; + + QwtPainterCommand(); + QwtPainterCommand(const QwtPainterCommand &); + + QwtPainterCommand( const QPainterPath & ); + + QwtPainterCommand( const QRectF &rect, + const QPixmap &, const QRectF& subRect ); + + QwtPainterCommand( const QRectF &rect, + const QImage &, const QRectF& subRect, + Qt::ImageConversionFlags ); + + QwtPainterCommand( const QPaintEngineState & ); + + ~QwtPainterCommand(); + + QwtPainterCommand &operator=(const QwtPainterCommand & ); + + Type type() const; + + QPainterPath *path(); + const QPainterPath *path() const; + + PixmapData* pixmapData(); + const PixmapData* pixmapData() const; + + ImageData* imageData(); + const ImageData* imageData() const; + + StateData* stateData(); + const StateData* stateData() const; + +private: + void copy( const QwtPainterCommand & ); + void reset(); + + Type d_type; + + union + { + QPainterPath *d_path; + PixmapData *d_pixmapData; + ImageData *d_imageData; + StateData *d_stateData; + }; +}; + +//! \return Type of the command +inline QwtPainterCommand::Type QwtPainterCommand::type() const +{ + return d_type; +} + +//! \return Painter path to be painted +inline const QPainterPath *QwtPainterCommand::path() const +{ + return d_path; +} + +//! \return Attributes how to paint a QPixmap +inline const QwtPainterCommand::PixmapData* +QwtPainterCommand::pixmapData() const +{ + return d_pixmapData; +} + +//! \return Attributes how to paint a QImage +inline const QwtPainterCommand::ImageData * +QwtPainterCommand::imageData() const +{ + return d_imageData; +} + +//! \return Attributes of a state change +inline const QwtPainterCommand::StateData * +QwtPainterCommand::stateData() const +{ + return d_stateData; +} + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_panner.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_panner.cpp new file mode 100644 index 0000000..187bfb6 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_panner.cpp @@ -0,0 +1,538 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_panner.h" +#include "qwt_picker.h" +#include "qwt_painter.h" +#include +#include +#include +#include +#include + +static QVector qwtActivePickers( QWidget *w ) +{ + QVector pickers; + + QObjectList children = w->children(); + for ( int i = 0; i < children.size(); i++ ) + { + QwtPicker *picker = qobject_cast( children[i] ); + if ( picker && picker->isEnabled() ) + pickers += picker; + } + + return pickers; +} + +class QwtPanner::PrivateData +{ +public: + PrivateData(): + button( Qt::LeftButton ), + buttonModifiers( Qt::NoModifier ), + abortKey( Qt::Key_Escape ), + abortKeyModifiers( Qt::NoModifier ), +#ifndef QT_NO_CURSOR + cursor( NULL ), + restoreCursor( NULL ), + hasCursor( false ), +#endif + isEnabled( false ) + { + orientations = Qt::Vertical | Qt::Horizontal; + } + + ~PrivateData() + { +#ifndef QT_NO_CURSOR + delete cursor; + delete restoreCursor; +#endif + } + + Qt::MouseButton button; + Qt::KeyboardModifiers buttonModifiers; + + int abortKey; + Qt::KeyboardModifiers abortKeyModifiers; + + QPoint initialPos; + QPoint pos; + + QPixmap pixmap; + QBitmap contentsMask; + +#ifndef QT_NO_CURSOR + QCursor *cursor; + QCursor *restoreCursor; + bool hasCursor; +#endif + bool isEnabled; + Qt::Orientations orientations; +}; + +/*! + Creates an panner that is enabled for the left mouse button. + + \param parent Parent widget to be panned +*/ +QwtPanner::QwtPanner( QWidget *parent ): + QWidget( parent ) +{ + d_data = new PrivateData(); + + setAttribute( Qt::WA_TransparentForMouseEvents ); + setAttribute( Qt::WA_NoSystemBackground ); + setFocusPolicy( Qt::NoFocus ); + hide(); + + setEnabled( true ); +} + +//! Destructor +QwtPanner::~QwtPanner() +{ + delete d_data; +} + +/*! + Change the mouse button and modifiers used for panning + The defaults are Qt::LeftButton and Qt::NoModifier +*/ +void QwtPanner::setMouseButton( Qt::MouseButton button, + Qt::KeyboardModifiers modifiers ) +{ + d_data->button = button; + d_data->buttonModifiers = modifiers; +} + +//! Get mouse button and modifiers used for panning +void QwtPanner::getMouseButton( Qt::MouseButton &button, + Qt::KeyboardModifiers &modifiers ) const +{ + button = d_data->button; + modifiers = d_data->buttonModifiers; +} + +/*! + Change the abort key + The defaults are Qt::Key_Escape and Qt::NoModifiers + + \param key Key ( See Qt::Keycode ) + \param modifiers Keyboard modifiers +*/ +void QwtPanner::setAbortKey( int key, + Qt::KeyboardModifiers modifiers ) +{ + d_data->abortKey = key; + d_data->abortKeyModifiers = modifiers; +} + +//! Get the abort key and modifiers +void QwtPanner::getAbortKey( int &key, + Qt::KeyboardModifiers &modifiers ) const +{ + key = d_data->abortKey; + modifiers = d_data->abortKeyModifiers; +} + +/*! + Change the cursor, that is active while panning + The default is the cursor of the parent widget. + + \param cursor New cursor + + \sa setCursor() +*/ +#ifndef QT_NO_CURSOR +void QwtPanner::setCursor( const QCursor &cursor ) +{ + d_data->cursor = new QCursor( cursor ); +} +#endif + +/*! + \return Cursor that is active while panning + \sa setCursor() +*/ +#ifndef QT_NO_CURSOR +const QCursor QwtPanner::cursor() const +{ + if ( d_data->cursor ) + return *d_data->cursor; + + if ( parentWidget() ) + return parentWidget()->cursor(); + + return QCursor(); +} +#endif + +/*! + \brief En/disable the panner + + When enabled is true an event filter is installed for + the observed widget, otherwise the event filter is removed. + + \param on true or false + \sa isEnabled(), eventFilter() +*/ +void QwtPanner::setEnabled( bool on ) +{ + if ( d_data->isEnabled != on ) + { + d_data->isEnabled = on; + + QWidget *w = parentWidget(); + if ( w ) + { + if ( d_data->isEnabled ) + { + w->installEventFilter( this ); + } + else + { + w->removeEventFilter( this ); + hide(); + } + } + } +} + +/*! + Set the orientations, where panning is enabled + The default value is in both directions: Qt::Horizontal | Qt::Vertical + + /param o Orientation +*/ +void QwtPanner::setOrientations( Qt::Orientations o ) +{ + d_data->orientations = o; +} + +//! Return the orientation, where paning is enabled +Qt::Orientations QwtPanner::orientations() const +{ + return d_data->orientations; +} + +/*! + \return True if an orientation is enabled + \sa orientations(), setOrientations() +*/ +bool QwtPanner::isOrientationEnabled( Qt::Orientation o ) const +{ + return d_data->orientations & o; +} + +/*! + \return true when enabled, false otherwise + \sa setEnabled, eventFilter() +*/ +bool QwtPanner::isEnabled() const +{ + return d_data->isEnabled; +} + +/*! + \brief Paint event + + Repaint the grabbed pixmap on its current position and + fill the empty spaces by the background of the parent widget. + + \param pe Paint event +*/ +void QwtPanner::paintEvent( QPaintEvent *pe ) +{ + int dx = d_data->pos.x() - d_data->initialPos.x(); + int dy = d_data->pos.y() - d_data->initialPos.y(); + + QRect r( 0, 0, d_data->pixmap.width(), d_data->pixmap.height() ); + r.moveCenter( QPoint( r.center().x() + dx, r.center().y() + dy ) ); + + QPixmap pm( size() ); + QwtPainter::fillPixmap( parentWidget(), pm ); + + QPainter painter( &pm ); + + if ( !d_data->contentsMask.isNull() ) + { + QPixmap masked = d_data->pixmap; + masked.setMask( d_data->contentsMask ); + painter.drawPixmap( r, masked ); + } + else + { + painter.drawPixmap( r, d_data->pixmap ); + } + + painter.end(); + + if ( !d_data->contentsMask.isNull() ) + pm.setMask( d_data->contentsMask ); + + painter.begin( this ); + painter.setClipRegion( pe->region() ); + painter.drawPixmap( 0, 0, pm ); +} + +/*! + \brief Calculate a mask for the contents of the panned widget + + Sometimes only parts of the contents of a widget should be + panned. F.e. for a widget with a styled background with rounded borders + only the area inside of the border should be panned. + + \return An empty bitmap, indicating no mask +*/ +QBitmap QwtPanner::contentsMask() const +{ + return QBitmap(); +} + +/*! + Grab the widget into a pixmap. + \return Grabbed pixmap +*/ +QPixmap QwtPanner::grab() const +{ +#if QT_VERSION >= 0x050000 + return parentWidget()->grab( parentWidget()->rect() ); +#else + return QPixmap::grabWidget( parentWidget() ); +#endif +} + +/*! + \brief Event filter + + When isEnabled() is true mouse events of the + observed widget are filtered. + + \param object Object to be filtered + \param event Event + + \return Always false, beside for paint events for the + parent widget. + + \sa widgetMousePressEvent(), widgetMouseReleaseEvent(), + widgetMouseMoveEvent() +*/ +bool QwtPanner::eventFilter( QObject *object, QEvent *event ) +{ + if ( object == NULL || object != parentWidget() ) + return false; + + switch ( event->type() ) + { + case QEvent::MouseButtonPress: + { + widgetMousePressEvent( static_cast( event ) ); + break; + } + case QEvent::MouseMove: + { + widgetMouseMoveEvent( static_cast( event ) ); + break; + } + case QEvent::MouseButtonRelease: + { + widgetMouseReleaseEvent( static_cast( event ) ); + break; + } + case QEvent::KeyPress: + { + widgetKeyPressEvent( static_cast( event ) ); + break; + } + case QEvent::KeyRelease: + { + widgetKeyReleaseEvent( static_cast( event ) ); + break; + } + case QEvent::Paint: + { + if ( isVisible() ) + return true; + break; + } + default:; + } + + return false; +} + +/*! + Handle a mouse press event for the observed widget. + + \param mouseEvent Mouse event + \sa eventFilter(), widgetMouseReleaseEvent(), + widgetMouseMoveEvent(), +*/ +void QwtPanner::widgetMousePressEvent( QMouseEvent *mouseEvent ) +{ + if ( ( mouseEvent->button() != d_data->button ) + || ( mouseEvent->modifiers() != d_data->buttonModifiers ) ) + { + return; + } + + QWidget *w = parentWidget(); + if ( w == NULL ) + return; + +#ifndef QT_NO_CURSOR + showCursor( true ); +#endif + + d_data->initialPos = d_data->pos = mouseEvent->pos(); + + setGeometry( parentWidget()->rect() ); + + // We don't want to grab the picker ! + QVector pickers = qwtActivePickers( parentWidget() ); + for ( int i = 0; i < pickers.size(); i++ ) + pickers[i]->setEnabled( false ); + + d_data->pixmap = grab(); + d_data->contentsMask = contentsMask(); + + for ( int i = 0; i < pickers.size(); i++ ) + pickers[i]->setEnabled( true ); + + show(); +} + +/*! + Handle a mouse move event for the observed widget. + + \param mouseEvent Mouse event + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent() +*/ +void QwtPanner::widgetMouseMoveEvent( QMouseEvent *mouseEvent ) +{ + if ( !isVisible() ) + return; + + QPoint pos = mouseEvent->pos(); + if ( !isOrientationEnabled( Qt::Horizontal ) ) + pos.setX( d_data->initialPos.x() ); + if ( !isOrientationEnabled( Qt::Vertical ) ) + pos.setY( d_data->initialPos.y() ); + + if ( pos != d_data->pos && rect().contains( pos ) ) + { + d_data->pos = pos; + update(); + + Q_EMIT moved( d_data->pos.x() - d_data->initialPos.x(), + d_data->pos.y() - d_data->initialPos.y() ); + } +} + +/*! + Handle a mouse release event for the observed widget. + + \param mouseEvent Mouse event + \sa eventFilter(), widgetMousePressEvent(), + widgetMouseMoveEvent(), +*/ +void QwtPanner::widgetMouseReleaseEvent( QMouseEvent *mouseEvent ) +{ + if ( isVisible() ) + { + hide(); +#ifndef QT_NO_CURSOR + showCursor( false ); +#endif + + QPoint pos = mouseEvent->pos(); + if ( !isOrientationEnabled( Qt::Horizontal ) ) + pos.setX( d_data->initialPos.x() ); + if ( !isOrientationEnabled( Qt::Vertical ) ) + pos.setY( d_data->initialPos.y() ); + + d_data->pixmap = QPixmap(); + d_data->contentsMask = QBitmap(); + d_data->pos = pos; + + if ( d_data->pos != d_data->initialPos ) + { + Q_EMIT panned( d_data->pos.x() - d_data->initialPos.x(), + d_data->pos.y() - d_data->initialPos.y() ); + } + } +} + +/*! + Handle a key press event for the observed widget. + + \param keyEvent Key event + \sa eventFilter(), widgetKeyReleaseEvent() +*/ +void QwtPanner::widgetKeyPressEvent( QKeyEvent *keyEvent ) +{ + if ( ( keyEvent->key() == d_data->abortKey ) + && ( keyEvent->modifiers() == d_data->abortKeyModifiers ) ) + { + hide(); + +#ifndef QT_NO_CURSOR + showCursor( false ); +#endif + d_data->pixmap = QPixmap(); + } +} + +/*! + Handle a key release event for the observed widget. + + \param keyEvent Key event + \sa eventFilter(), widgetKeyReleaseEvent() +*/ +void QwtPanner::widgetKeyReleaseEvent( QKeyEvent *keyEvent ) +{ + Q_UNUSED( keyEvent ); +} + +#ifndef QT_NO_CURSOR +void QwtPanner::showCursor( bool on ) +{ + if ( on == d_data->hasCursor ) + return; + + QWidget *w = parentWidget(); + if ( w == NULL || d_data->cursor == NULL ) + return; + + d_data->hasCursor = on; + + if ( on ) + { + if ( w->testAttribute( Qt::WA_SetCursor ) ) + { + delete d_data->restoreCursor; + d_data->restoreCursor = new QCursor( w->cursor() ); + } + w->setCursor( *d_data->cursor ); + } + else + { + if ( d_data->restoreCursor ) + { + w->setCursor( *d_data->restoreCursor ); + delete d_data->restoreCursor; + d_data->restoreCursor = NULL; + } + else + w->unsetCursor(); + } +} +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_panner.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_panner.h new file mode 100644 index 0000000..e31b4ab --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_panner.h @@ -0,0 +1,103 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PANNER_H +#define QWT_PANNER_H 1 + +#include "qwt_global.h" +#include +#include + +class QCursor; + +/*! + \brief QwtPanner provides panning of a widget + + QwtPanner grabs the contents of a widget, that can be dragged + in all directions. The offset between the start and the end position + is emitted by the panned signal. + + QwtPanner grabs the content of the widget into a pixmap and moves + the pixmap around, without initiating any repaint events for the widget. + Areas, that are not part of content are not painted while panning. + This makes panning fast enough for widgets, where + repaints are too slow for mouse movements. + + For widgets, where repaints are very fast it might be better to + implement panning manually by mapping mouse events into paint events. +*/ +class QWT_EXPORT QwtPanner: public QWidget +{ + Q_OBJECT + +public: + QwtPanner( QWidget* parent ); + virtual ~QwtPanner(); + + void setEnabled( bool ); + bool isEnabled() const; + + void setMouseButton( Qt::MouseButton, + Qt::KeyboardModifiers = Qt::NoModifier ); + void getMouseButton( Qt::MouseButton &button, + Qt::KeyboardModifiers & ) const; + + void setAbortKey( int key, Qt::KeyboardModifiers = Qt::NoModifier ); + void getAbortKey( int &key, Qt::KeyboardModifiers & ) const; + + void setCursor( const QCursor & ); + const QCursor cursor() const; + + void setOrientations( Qt::Orientations ); + Qt::Orientations orientations() const; + + bool isOrientationEnabled( Qt::Orientation ) const; + + virtual bool eventFilter( QObject *, QEvent * ); + +Q_SIGNALS: + /*! + Signal emitted, when panning is done + + \param dx Offset in horizontal direction + \param dy Offset in vertical direction + */ + void panned( int dx, int dy ); + + /*! + Signal emitted, while the widget moved, but panning + is not finished. + + \param dx Offset in horizontal direction + \param dy Offset in vertical direction + */ + void moved( int dx, int dy ); + +protected: + virtual void widgetMousePressEvent( QMouseEvent * ); + virtual void widgetMouseReleaseEvent( QMouseEvent * ); + virtual void widgetMouseMoveEvent( QMouseEvent * ); + virtual void widgetKeyPressEvent( QKeyEvent * ); + virtual void widgetKeyReleaseEvent( QKeyEvent * ); + + virtual void paintEvent( QPaintEvent * ); + + virtual QBitmap contentsMask() const; + virtual QPixmap grab() const; + +private: +#ifndef QT_NO_CURSOR + void showCursor( bool ); +#endif + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_picker.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_picker.cpp new file mode 100644 index 0000000..c6f06a5 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_picker.cpp @@ -0,0 +1,1593 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_picker.h" +#include "qwt_picker_machine.h" +#include "qwt_painter.h" +#include "qwt_math.h" +#include "qwt_widget_overlay.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline QRegion qwtMaskRegion( const QRect &r, int penWidth ) +{ + const int pw = qMax( penWidth, 1 ); + const int pw2 = penWidth / 2; + + int x1 = r.left() - pw2; + int x2 = r.right() + 1 + pw2 + ( pw % 2 ); + + int y1 = r.top() - pw2; + int y2 = r.bottom() + 1 + pw2 + ( pw % 2 ); + + QRegion region; + + region += QRect( x1, y1, x2 - x1, pw ); + region += QRect( x1, y1, pw, y2 - y1 ); + region += QRect( x1, y2 - pw, x2 - x1, pw ); + region += QRect( x2 - pw, y1, pw, y2 - y1 ); + + return region; +} + +static inline QRegion qwtMaskRegion( const QLine &l, int penWidth ) +{ + const int pw = qMax( penWidth, 1 ); + const int pw2 = penWidth / 2; + + QRegion region; + + if ( l.x1() == l.x2() ) + { + region += QRect( l.x1() - pw2, l.y1(), + pw, l.y2() ).normalized(); + } + else if ( l.y1() == l.y2() ) + { + region += QRect( l.x1(), l.y1() - pw2, + l.x2(), pw ).normalized(); + } + + return region; +} + +class QwtPickerRubberband: public QwtWidgetOverlay +{ +public: + QwtPickerRubberband( QwtPicker *, QWidget * ); + +protected: + virtual void drawOverlay( QPainter * ) const; + virtual QRegion maskHint() const; + + QwtPicker *d_picker; +}; + +class QwtPickerTracker: public QwtWidgetOverlay +{ +public: + QwtPickerTracker( QwtPicker *, QWidget * ); + +protected: + virtual void drawOverlay( QPainter * ) const; + virtual QRegion maskHint() const; + + QwtPicker *d_picker; +}; + + +class QwtPicker::PrivateData +{ +public: + PrivateData(): + enabled( false ), + stateMachine( NULL ), + resizeMode( QwtPicker::Stretch ), + rubberBand( QwtPicker::NoRubberBand ), + trackerMode( QwtPicker::AlwaysOff ), + isActive( false ), + trackerPosition( -1, -1 ), + mouseTracking( false ), + openGL( false ) + { + } + + bool enabled; + + QwtPickerMachine *stateMachine; + + QwtPicker::ResizeMode resizeMode; + + QwtPicker::RubberBand rubberBand; + QPen rubberBandPen; + + QwtPicker::DisplayMode trackerMode; + QPen trackerPen; + QFont trackerFont; + + QPolygon pickedPoints; + bool isActive; + QPoint trackerPosition; + + bool mouseTracking; // used to save previous value + + QPointer< QwtPickerRubberband > rubberBandOverlay; + QPointer< QwtPickerTracker> trackerOverlay; + + bool openGL; +}; + +QwtPickerRubberband::QwtPickerRubberband( + QwtPicker *picker, QWidget *parent ): + QwtWidgetOverlay( parent ), + d_picker( picker ) +{ + setMaskMode( QwtWidgetOverlay::MaskHint ); +} + +QRegion QwtPickerRubberband::maskHint() const +{ + return d_picker->rubberBandMask(); +} + +void QwtPickerRubberband::drawOverlay( QPainter *painter ) const +{ + painter->setPen( d_picker->rubberBandPen() ); + d_picker->drawRubberBand( painter ); +} + +QwtPickerTracker::QwtPickerTracker( + QwtPicker *picker, QWidget *parent ): + QwtWidgetOverlay( parent ), + d_picker( picker ) +{ + setMaskMode( QwtWidgetOverlay::MaskHint ); +} + +QRegion QwtPickerTracker::maskHint() const +{ + return d_picker->trackerRect( font() ); +} + +void QwtPickerTracker::drawOverlay( QPainter *painter ) const +{ + painter->setPen( d_picker->trackerPen() ); + d_picker->drawTracker( painter ); +} + +/*! + Constructor + + Creates an picker that is enabled, but without a state machine. + rubber band and tracker are disabled. + + \param parent Parent widget, that will be observed + */ + +QwtPicker::QwtPicker( QWidget *parent ): + QObject( parent ) +{ + init( parent, NoRubberBand, AlwaysOff ); +} + +/*! + Constructor + + \param rubberBand Rubber band style + \param trackerMode Tracker mode + \param parent Parent widget, that will be observed + */ +QwtPicker::QwtPicker( RubberBand rubberBand, + DisplayMode trackerMode, QWidget *parent ): + QObject( parent ) +{ + init( parent, rubberBand, trackerMode ); +} + +//! Destructor +QwtPicker::~QwtPicker() +{ + setMouseTracking( false ); + + delete d_data->stateMachine; + delete d_data->rubberBandOverlay; + delete d_data->trackerOverlay; + + delete d_data; +} + +//! Initialize the picker - used by the constructors +void QwtPicker::init( QWidget *parent, + RubberBand rubberBand, DisplayMode trackerMode ) +{ + d_data = new PrivateData; + + d_data->rubberBand = rubberBand; + + if ( parent ) + { + if ( parent->focusPolicy() == Qt::NoFocus ) + parent->setFocusPolicy( Qt::WheelFocus ); + + d_data->openGL = parent->inherits( "QGLWidget" ); + d_data->trackerFont = parent->font(); + d_data->mouseTracking = parent->hasMouseTracking(); + + setEnabled( true ); + } + + setTrackerMode( trackerMode ); +} + +/*! + Set a state machine and delete the previous one + + \param stateMachine State machine + \sa stateMachine() +*/ +void QwtPicker::setStateMachine( QwtPickerMachine *stateMachine ) +{ + if ( d_data->stateMachine != stateMachine ) + { + reset(); + + delete d_data->stateMachine; + d_data->stateMachine = stateMachine; + + if ( d_data->stateMachine ) + d_data->stateMachine->reset(); + } +} + +/*! + \return Assigned state machine + \sa setStateMachine() +*/ +QwtPickerMachine *QwtPicker::stateMachine() +{ + return d_data->stateMachine; +} + +/*! + \return Assigned state machine + \sa setStateMachine() +*/ +const QwtPickerMachine *QwtPicker::stateMachine() const +{ + return d_data->stateMachine; +} + +//! Return the parent widget, where the selection happens +QWidget *QwtPicker::parentWidget() +{ + QObject *obj = parent(); + if ( obj && obj->isWidgetType() ) + return static_cast( obj ); + + return NULL; +} + +//! Return the parent widget, where the selection happens +const QWidget *QwtPicker::parentWidget() const +{ + QObject *obj = parent(); + if ( obj && obj->isWidgetType() ) + return static_cast< const QWidget *>( obj ); + + return NULL; +} + +/*! + Set the rubber band style + + \param rubberBand Rubber band style + The default value is NoRubberBand. + + \sa rubberBand(), RubberBand, setRubberBandPen() +*/ +void QwtPicker::setRubberBand( RubberBand rubberBand ) +{ + d_data->rubberBand = rubberBand; +} + +/*! + \return Rubber band style + \sa setRubberBand(), RubberBand, rubberBandPen() +*/ +QwtPicker::RubberBand QwtPicker::rubberBand() const +{ + return d_data->rubberBand; +} + +/*! + \brief Set the display mode of the tracker. + + A tracker displays information about current position of + the cursor as a string. The display mode controls + if the tracker has to be displayed whenever the observed + widget has focus and cursor (AlwaysOn), never (AlwaysOff), or + only when the selection is active (ActiveOnly). + + \param mode Tracker display mode + + \warning In case of AlwaysOn, mouseTracking will be enabled + for the observed widget. + \sa trackerMode(), DisplayMode +*/ + +void QwtPicker::setTrackerMode( DisplayMode mode ) +{ + if ( d_data->trackerMode != mode ) + { + d_data->trackerMode = mode; + setMouseTracking( d_data->trackerMode == AlwaysOn ); + } +} + +/*! + \return Tracker display mode + \sa setTrackerMode(), DisplayMode +*/ +QwtPicker::DisplayMode QwtPicker::trackerMode() const +{ + return d_data->trackerMode; +} + +/*! + \brief Set the resize mode. + + The resize mode controls what to do with the selected points of an active + selection when the observed widget is resized. + + Stretch means the points are scaled according to the new + size, KeepSize means the points remain unchanged. + + The default mode is Stretch. + + \param mode Resize mode + \sa resizeMode(), ResizeMode +*/ +void QwtPicker::setResizeMode( ResizeMode mode ) +{ + d_data->resizeMode = mode; +} + +/*! + \return Resize mode + \sa setResizeMode(), ResizeMode +*/ + +QwtPicker::ResizeMode QwtPicker::resizeMode() const +{ + return d_data->resizeMode; +} + +/*! + \brief En/disable the picker + + When enabled is true an event filter is installed for + the observed widget, otherwise the event filter is removed. + + \param enabled true or false + \sa isEnabled(), eventFilter() +*/ +void QwtPicker::setEnabled( bool enabled ) +{ + if ( d_data->enabled != enabled ) + { + d_data->enabled = enabled; + + QWidget *w = parentWidget(); + if ( w ) + { + if ( enabled ) + w->installEventFilter( this ); + else + w->removeEventFilter( this ); + } + + updateDisplay(); + } +} + +/*! + \return true when enabled, false otherwise + \sa setEnabled(), eventFilter() +*/ + +bool QwtPicker::isEnabled() const +{ + return d_data->enabled; +} + +/*! + Set the font for the tracker + + \param font Tracker font + \sa trackerFont(), setTrackerMode(), setTrackerPen() +*/ +void QwtPicker::setTrackerFont( const QFont &font ) +{ + if ( font != d_data->trackerFont ) + { + d_data->trackerFont = font; + updateDisplay(); + } +} + +/*! + \return Tracker font + \sa setTrackerFont(), trackerMode(), trackerPen() +*/ + +QFont QwtPicker::trackerFont() const +{ + return d_data->trackerFont; +} + +/*! + Set the pen for the tracker + + \param pen Tracker pen + \sa trackerPen(), setTrackerMode(), setTrackerFont() +*/ +void QwtPicker::setTrackerPen( const QPen &pen ) +{ + if ( pen != d_data->trackerPen ) + { + d_data->trackerPen = pen; + updateDisplay(); + } +} + +/*! + \return Tracker pen + \sa setTrackerPen(), trackerMode(), trackerFont() +*/ +QPen QwtPicker::trackerPen() const +{ + return d_data->trackerPen; +} + +/*! + Set the pen for the rubberband + + \param pen Rubber band pen + \sa rubberBandPen(), setRubberBand() +*/ +void QwtPicker::setRubberBandPen( const QPen &pen ) +{ + if ( pen != d_data->rubberBandPen ) + { + d_data->rubberBandPen = pen; + updateDisplay(); + } +} + +/*! + \return Rubber band pen + \sa setRubberBandPen(), rubberBand() +*/ +QPen QwtPicker::rubberBandPen() const +{ + return d_data->rubberBandPen; +} + +/*! + \brief Return the label for a position + + In case of HLineRubberBand the label is the value of the + y position, in case of VLineRubberBand the value of the x position. + Otherwise the label contains x and y position separated by a ',' . + + The format for the string conversion is "%d". + + \param pos Position + \return Converted position as string +*/ + +QwtText QwtPicker::trackerText( const QPoint &pos ) const +{ + QString label; + + switch ( rubberBand() ) + { + case HLineRubberBand: + label.sprintf( "%d", pos.y() ); + break; + case VLineRubberBand: + label.sprintf( "%d", pos.x() ); + break; + default: + label.sprintf( "%d, %d", pos.x(), pos.y() ); + } + return label; +} + +/*! + Calculate the mask for the rubber band overlay + + \return Region for the mask + \sa QWidget::setMask() + */ +QRegion QwtPicker::rubberBandMask() const +{ + QRegion mask; + + if ( !isActive() || rubberBand() == NoRubberBand || + rubberBandPen().style() == Qt::NoPen ) + { + return mask; + } + + const QPolygon pa = adjustedPoints( d_data->pickedPoints ); + + QwtPickerMachine::SelectionType selectionType = + QwtPickerMachine::NoSelection; + + if ( d_data->stateMachine ) + selectionType = d_data->stateMachine->selectionType(); + + switch ( selectionType ) + { + case QwtPickerMachine::NoSelection: + case QwtPickerMachine::PointSelection: + { + if ( pa.count() < 1 ) + return mask; + + const QPoint pos = pa[0]; + const int pw = rubberBandPen().width(); + + const QRect pRect = pickArea().boundingRect().toRect(); + switch ( rubberBand() ) + { + case VLineRubberBand: + { + mask += qwtMaskRegion( QLine( pos.x(), pRect.top(), + pos.x(), pRect.bottom() ), pw ); + break; + } + case HLineRubberBand: + { + mask += qwtMaskRegion( QLine( pRect.left(), pos.y(), + pRect.right(), pos.y() ), pw ); + break; + } + case CrossRubberBand: + { + mask += qwtMaskRegion( QLine( pos.x(), pRect.top(), + pos.x(), pRect.bottom() ), pw ); + mask += qwtMaskRegion( QLine( pRect.left(), pos.y(), + pRect.right(), pos.y() ), pw ); + break; + } + default: + break; + } + break; + } + case QwtPickerMachine::RectSelection: + { + if ( pa.count() < 2 ) + return mask; + + const int pw = rubberBandPen().width(); + + switch ( rubberBand() ) + { + case RectRubberBand: + { + const QRect r = QRect( pa.first(), pa.last() ); + mask = qwtMaskRegion( r.normalized(), pw ); + break; + } + case EllipseRubberBand: + { + const QRect r = QRect( pa.first(), pa.last() ); + mask += r.adjusted( -pw, -pw, pw, pw ); + break; + } + default: + break; + } + break; + } + case QwtPickerMachine::PolygonSelection: + { + const int pw = rubberBandPen().width(); + if ( pw <= 1 ) + { + // because of the join style we better + // return a mask for a pen width <= 1 only + + const int off = 2 * pw; + const QRect r = pa.boundingRect(); + mask += r.adjusted( -off, -off, off, off ); + } + break; + } + default: + break; + } + + return mask; +} + +/*! + Draw a rubber band, depending on rubberBand() + + \param painter Painter, initialized with a clip region + + \sa rubberBand(), RubberBand +*/ + +void QwtPicker::drawRubberBand( QPainter *painter ) const +{ + if ( !isActive() || rubberBand() == NoRubberBand || + rubberBandPen().style() == Qt::NoPen ) + { + return; + } + + const QPolygon pa = adjustedPoints( d_data->pickedPoints ); + + QwtPickerMachine::SelectionType selectionType = + QwtPickerMachine::NoSelection; + + if ( d_data->stateMachine ) + selectionType = d_data->stateMachine->selectionType(); + + switch ( selectionType ) + { + case QwtPickerMachine::NoSelection: + case QwtPickerMachine::PointSelection: + { + if ( pa.count() < 1 ) + return; + + const QPoint pos = pa[0]; + + const QRect pRect = pickArea().boundingRect().toRect(); + switch ( rubberBand() ) + { + case VLineRubberBand: + { + QwtPainter::drawLine( painter, pos.x(), + pRect.top(), pos.x(), pRect.bottom() ); + break; + } + case HLineRubberBand: + { + QwtPainter::drawLine( painter, pRect.left(), + pos.y(), pRect.right(), pos.y() ); + break; + } + case CrossRubberBand: + { + QwtPainter::drawLine( painter, pos.x(), + pRect.top(), pos.x(), pRect.bottom() ); + QwtPainter::drawLine( painter, pRect.left(), + pos.y(), pRect.right(), pos.y() ); + break; + } + default: + break; + } + break; + } + case QwtPickerMachine::RectSelection: + { + if ( pa.count() < 2 ) + return; + + const QRect rect = QRect( pa.first(), pa.last() ).normalized(); + switch ( rubberBand() ) + { + case EllipseRubberBand: + { + QwtPainter::drawEllipse( painter, rect ); + break; + } + case RectRubberBand: + { + QwtPainter::drawRect( painter, rect ); + break; + } + default: + break; + } + break; + } + case QwtPickerMachine::PolygonSelection: + { + if ( rubberBand() == PolygonRubberBand ) + painter->drawPolyline( pa ); + break; + } + default: + break; + } +} + +/*! + Draw the tracker + + \param painter Painter + \sa trackerRect(), trackerText() +*/ + +void QwtPicker::drawTracker( QPainter *painter ) const +{ + const QRect textRect = trackerRect( painter->font() ); + if ( !textRect.isEmpty() ) + { + const QwtText label = trackerText( d_data->trackerPosition ); + if ( !label.isEmpty() ) + label.draw( painter, textRect ); + } +} + +/*! + \brief Map the pickedPoints() into a selection() + + adjustedPoints() maps the points, that have been collected on + the parentWidget() into a selection(). The default implementation + simply returns the points unmodified. + + The reason, why a selection() differs from the picked points + depends on the application requirements. F.e. : + + - A rectangular selection might need to have a specific aspect ratio only.\n + - A selection could accept non intersecting polygons only.\n + - ...\n + + The example below is for a rectangular selection, where the first + point is the center of the selected rectangle. + \par Example + \verbatim QPolygon MyPicker::adjustedPoints(const QPolygon &points) const +{ + QPolygon adjusted; + if ( points.size() == 2 ) + { + const int width = qAbs(points[1].x() - points[0].x()); + const int height = qAbs(points[1].y() - points[0].y()); + + QRect rect(0, 0, 2 * width, 2 * height); + rect.moveCenter(points[0]); + + adjusted += rect.topLeft(); + adjusted += rect.bottomRight(); + } + return adjusted; +}\endverbatim\n + + \param points Selected points + \return Selected points unmodified +*/ +QPolygon QwtPicker::adjustedPoints( const QPolygon &points ) const +{ + return points; +} + +/*! + \return Selected points + \sa pickedPoints(), adjustedPoints() +*/ +QPolygon QwtPicker::selection() const +{ + return adjustedPoints( d_data->pickedPoints ); +} + +//! \return Current position of the tracker +QPoint QwtPicker::trackerPosition() const +{ + return d_data->trackerPosition; +} + +/*! + Calculate the bounding rectangle for the tracker text + from the current position of the tracker + + \param font Font of the tracker text + \return Bounding rectangle of the tracker text + + \sa trackerPosition() +*/ +QRect QwtPicker::trackerRect( const QFont &font ) const +{ + if ( trackerMode() == AlwaysOff || + ( trackerMode() == ActiveOnly && !isActive() ) ) + { + return QRect(); + } + + if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 ) + return QRect(); + + QwtText text = trackerText( d_data->trackerPosition ); + if ( text.isEmpty() ) + return QRect(); + + const QSizeF textSize = text.textSize( font ); + QRect textRect( 0, 0, qCeil( textSize.width() ), qCeil( textSize.height() ) ); + + const QPoint &pos = d_data->trackerPosition; + + int alignment = 0; + if ( isActive() && d_data->pickedPoints.count() > 1 + && rubberBand() != NoRubberBand ) + { + const QPoint last = + d_data->pickedPoints[int( d_data->pickedPoints.count() ) - 2]; + + alignment |= ( pos.x() >= last.x() ) ? Qt::AlignRight : Qt::AlignLeft; + alignment |= ( pos.y() > last.y() ) ? Qt::AlignBottom : Qt::AlignTop; + } + else + alignment = Qt::AlignTop | Qt::AlignRight; + + const int margin = 5; + + int x = pos.x(); + if ( alignment & Qt::AlignLeft ) + x -= textRect.width() + margin; + else if ( alignment & Qt::AlignRight ) + x += margin; + + int y = pos.y(); + if ( alignment & Qt::AlignBottom ) + y += margin; + else if ( alignment & Qt::AlignTop ) + y -= textRect.height() + margin; + + textRect.moveTopLeft( QPoint( x, y ) ); + + const QRect pickRect = pickArea().boundingRect().toRect(); + + int right = qMin( textRect.right(), pickRect.right() - margin ); + int bottom = qMin( textRect.bottom(), pickRect.bottom() - margin ); + textRect.moveBottomRight( QPoint( right, bottom ) ); + + int left = qMax( textRect.left(), pickRect.left() + margin ); + int top = qMax( textRect.top(), pickRect.top() + margin ); + textRect.moveTopLeft( QPoint( left, top ) ); + + return textRect; +} + +/*! + \brief Event filter + + When isEnabled() is true all events of the observed widget are filtered. + Mouse and keyboard events are translated into widgetMouse- and widgetKey- + and widgetWheel-events. Paint and Resize events are handled to keep + rubber band and tracker up to date. + + \param object Object to be filtered + \param event Event + + \return Always false. + + \sa widgetEnterEvent(), widgetLeaveEvent(), + widgetMousePressEvent(), widgetMouseReleaseEvent(), + widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), + widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent(), + QObject::installEventFilter(), QObject::event() +*/ +bool QwtPicker::eventFilter( QObject *object, QEvent *event ) +{ + if ( object && object == parentWidget() ) + { + switch ( event->type() ) + { + case QEvent::Resize: + { + const QResizeEvent *re = static_cast( event ); + + /* + Adding/deleting additional event filters inside of an event filter + is not safe dues to the implementation in Qt ( changing alist while iterating ). + So we create the overlays in a way, that they don't install en event filter + ( parent set to NULL ) and do the resizing here. + */ + if ( d_data->trackerOverlay ) + d_data->trackerOverlay->resize( re->size() ); + + if ( d_data->rubberBandOverlay ) + d_data->rubberBandOverlay->resize( re->size() ); + + if ( d_data->resizeMode == Stretch ) + stretchSelection( re->oldSize(), re->size() ); + + updateDisplay(); + break; + } + case QEvent::Enter: + { + widgetEnterEvent( event ); + break; + } + case QEvent::Leave: + { + widgetLeaveEvent( event ); + break; + } + case QEvent::MouseButtonPress: + { + widgetMousePressEvent( static_cast( event ) ); + break; + } + case QEvent::MouseButtonRelease: + { + widgetMouseReleaseEvent( static_cast( event ) ); + break; + } + case QEvent::MouseButtonDblClick: + { + widgetMouseDoubleClickEvent( static_cast( event ) ); + break; + } + case QEvent::MouseMove: + { + widgetMouseMoveEvent( static_cast( event ) ); + break; + } + case QEvent::KeyPress: + { + widgetKeyPressEvent( static_cast( event ) ); + break; + } + case QEvent::KeyRelease: + { + widgetKeyReleaseEvent( static_cast( event ) ); + break; + } + case QEvent::Wheel: + { + widgetWheelEvent( static_cast( event ) ); + break; + } + default: + break; + } + } + return false; +} + +/*! + Handle a mouse press event for the observed widget. + + \param mouseEvent Mouse event + + \sa eventFilter(), widgetMouseReleaseEvent(), + widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), + widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() +*/ +void QwtPicker::widgetMousePressEvent( QMouseEvent *mouseEvent ) +{ + transition( mouseEvent ); +} + +/*! + Handle a mouse move event for the observed widget. + + \param mouseEvent Mouse event + + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), + widgetMouseDoubleClickEvent(), + widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() +*/ +void QwtPicker::widgetMouseMoveEvent( QMouseEvent *mouseEvent ) +{ + if ( pickArea().contains( mouseEvent->pos() ) ) + d_data->trackerPosition = mouseEvent->pos(); + else + d_data->trackerPosition = QPoint( -1, -1 ); + + if ( !isActive() ) + updateDisplay(); + + transition( mouseEvent ); +} + +/*! + Handle a enter event for the observed widget. + + \param event Qt event + + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), + widgetMouseDoubleClickEvent(), + widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() +*/ +void QwtPicker::widgetEnterEvent( QEvent *event ) +{ + transition( event ); +} + +/*! + Handle a leave event for the observed widget. + + \param event Qt event + + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), + widgetMouseDoubleClickEvent(), + widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() +*/ +void QwtPicker::widgetLeaveEvent( QEvent *event ) +{ + transition( event ); + + d_data->trackerPosition = QPoint( -1, -1 ); + if ( !isActive() ) + updateDisplay(); +} + +/*! + Handle a mouse release event for the observed widget. + + \param mouseEvent Mouse event + + \sa eventFilter(), widgetMousePressEvent(), + widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), + widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() +*/ +void QwtPicker::widgetMouseReleaseEvent( QMouseEvent *mouseEvent ) +{ + transition( mouseEvent ); +} + +/*! + Handle mouse double click event for the observed widget. + + \param mouseEvent Mouse event + + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), + widgetMouseMoveEvent(), + widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent() +*/ +void QwtPicker::widgetMouseDoubleClickEvent( QMouseEvent *mouseEvent ) +{ + transition( mouseEvent ); +} + + +/*! + Handle a wheel event for the observed widget. + + Move the last point of the selection in case of isActive() == true + + \param wheelEvent Wheel event + + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), + widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), + widgetKeyPressEvent(), widgetKeyReleaseEvent() +*/ +void QwtPicker::widgetWheelEvent( QWheelEvent *wheelEvent ) +{ + if ( pickArea().contains( wheelEvent->pos() ) ) + d_data->trackerPosition = wheelEvent->pos(); + else + d_data->trackerPosition = QPoint( -1, -1 ); + + updateDisplay(); + + transition( wheelEvent ); +} + +/*! + Handle a key press event for the observed widget. + + Selections can be completely done by the keyboard. The arrow keys + move the cursor, the abort key aborts a selection. All other keys + are handled by the current state machine. + + \param keyEvent Key event + + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), + widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), + widgetWheelEvent(), widgetKeyReleaseEvent(), stateMachine(), + QwtEventPattern::KeyPatternCode +*/ +void QwtPicker::widgetKeyPressEvent( QKeyEvent *keyEvent ) +{ + int dx = 0; + int dy = 0; + + int offset = 1; + if ( keyEvent->isAutoRepeat() ) + offset = 5; + + if ( keyMatch( KeyLeft, keyEvent ) ) + dx = -offset; + else if ( keyMatch( KeyRight, keyEvent ) ) + dx = offset; + else if ( keyMatch( KeyUp, keyEvent ) ) + dy = -offset; + else if ( keyMatch( KeyDown, keyEvent ) ) + dy = offset; + else if ( keyMatch( KeyAbort, keyEvent ) ) + { + reset(); + } + else + transition( keyEvent ); + + if ( dx != 0 || dy != 0 ) + { + const QRect rect = pickArea().boundingRect().toRect(); + const QPoint pos = parentWidget()->mapFromGlobal( QCursor::pos() ); + + int x = pos.x() + dx; + x = qMax( rect.left(), x ); + x = qMin( rect.right(), x ); + + int y = pos.y() + dy; + y = qMax( rect.top(), y ); + y = qMin( rect.bottom(), y ); + + QCursor::setPos( parentWidget()->mapToGlobal( QPoint( x, y ) ) ); + } +} + +/*! + Handle a key release event for the observed widget. + + Passes the event to the state machine. + + \param keyEvent Key event + + \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(), + widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(), + widgetWheelEvent(), widgetKeyPressEvent(), stateMachine() +*/ +void QwtPicker::widgetKeyReleaseEvent( QKeyEvent *keyEvent ) +{ + transition( keyEvent ); +} + +/*! + Passes an event to the state machine and executes the resulting + commands. Append and Move commands use the current position + of the cursor ( QCursor::pos() ). + + \param event Event +*/ +void QwtPicker::transition( const QEvent *event ) +{ + if ( !d_data->stateMachine ) + return; + + const QList commandList = + d_data->stateMachine->transition( *this, event ); + + QPoint pos; + switch ( event->type() ) + { + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + { + const QMouseEvent *me = + static_cast< const QMouseEvent * >( event ); + pos = me->pos(); + break; + } + default: + pos = parentWidget()->mapFromGlobal( QCursor::pos() ); + } + + for ( int i = 0; i < commandList.count(); i++ ) + { + switch ( commandList[i] ) + { + case QwtPickerMachine::Begin: + { + begin(); + break; + } + case QwtPickerMachine::Append: + { + append( pos ); + break; + } + case QwtPickerMachine::Move: + { + move( pos ); + break; + } + case QwtPickerMachine::Remove: + { + remove(); + break; + } + case QwtPickerMachine::End: + { + end(); + break; + } + } + } +} + +/*! + Open a selection setting the state to active + + \sa isActive(), end(), append(), move() +*/ +void QwtPicker::begin() +{ + if ( d_data->isActive ) + return; + + d_data->pickedPoints.resize( 0 ); + d_data->isActive = true; + Q_EMIT activated( true ); + + if ( trackerMode() != AlwaysOff ) + { + if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 ) + { + QWidget *w = parentWidget(); + if ( w ) + d_data->trackerPosition = w->mapFromGlobal( QCursor::pos() ); + } + } + + updateDisplay(); + setMouseTracking( true ); +} + +/*! + \brief Close a selection setting the state to inactive. + + The selection is validated and maybe fixed by accept(). + + \param ok If true, complete the selection and emit a selected signal + otherwise discard the selection. + \return true if the selection is accepted, false otherwise + \sa isActive(), begin(), append(), move(), selected(), accept() +*/ +bool QwtPicker::end( bool ok ) +{ + if ( d_data->isActive ) + { + setMouseTracking( false ); + + d_data->isActive = false; + Q_EMIT activated( false ); + + if ( trackerMode() == ActiveOnly ) + d_data->trackerPosition = QPoint( -1, -1 ); + + if ( ok ) + ok = accept( d_data->pickedPoints ); + + if ( ok ) + Q_EMIT selected( d_data->pickedPoints ); + else + d_data->pickedPoints.resize( 0 ); + + updateDisplay(); + } + else + ok = false; + + return ok; +} + +/*! + Reset the state machine and terminate ( end(false) ) the selection +*/ +void QwtPicker::reset() +{ + if ( d_data->stateMachine ) + d_data->stateMachine->reset(); + + if ( isActive() ) + end( false ); +} + +/*! + Append a point to the selection and update rubber band and tracker. + The appended() signal is emitted. + + \param pos Additional point + + \sa isActive(), begin(), end(), move(), appended() +*/ +void QwtPicker::append( const QPoint &pos ) +{ + if ( d_data->isActive ) + { + const int idx = d_data->pickedPoints.count(); + d_data->pickedPoints.resize( idx + 1 ); + d_data->pickedPoints[idx] = pos; + + updateDisplay(); + Q_EMIT appended( pos ); + } +} + +/*! + Move the last point of the selection + The moved() signal is emitted. + + \param pos New position + \sa isActive(), begin(), end(), append() +*/ +void QwtPicker::move( const QPoint &pos ) +{ + if ( d_data->isActive ) + { + const int idx = d_data->pickedPoints.count() - 1; + if ( idx >= 0 ) + { + if ( d_data->pickedPoints[idx] != pos ) + { + d_data->pickedPoints[idx] = pos; + + updateDisplay(); + Q_EMIT moved( pos ); + } + } + } +} + +/*! + Remove the last point of the selection + The removed() signal is emitted. + + \sa isActive(), begin(), end(), append(), move() +*/ +void QwtPicker::remove() +{ + if ( d_data->isActive ) + { + const int idx = d_data->pickedPoints.count() - 1; + if ( idx > 0 ) + { + const int idx = d_data->pickedPoints.count(); + + const QPoint pos = d_data->pickedPoints[idx - 1]; + d_data->pickedPoints.resize( idx - 1 ); + + updateDisplay(); + Q_EMIT removed( pos ); + } + } +} + +/*! + \brief Validate and fix up the selection + + Accepts all selections unmodified + + \param selection Selection to validate and fix up + \return true, when accepted, false otherwise +*/ +bool QwtPicker::accept( QPolygon &selection ) const +{ + Q_UNUSED( selection ); + return true; +} + +/*! + A picker is active between begin() and end(). + \return true if the selection is active. +*/ +bool QwtPicker::isActive() const +{ + return d_data->isActive; +} + +/*! + Return the points, that have been collected so far. The selection() + is calculated from the pickedPoints() in adjustedPoints(). + \return Picked points +*/ +const QPolygon &QwtPicker::pickedPoints() const +{ + return d_data->pickedPoints; +} + +/*! + Scale the selection by the ratios of oldSize and newSize + The changed() signal is emitted. + + \param oldSize Previous size + \param newSize Current size + + \sa ResizeMode, setResizeMode(), resizeMode() +*/ +void QwtPicker::stretchSelection( const QSize &oldSize, const QSize &newSize ) +{ + if ( oldSize.isEmpty() ) + { + // avoid division by zero. But scaling for small sizes also + // doesn't make much sense, because of rounding losses. TODO ... + return; + } + + const double xRatio = + double( newSize.width() ) / double( oldSize.width() ); + const double yRatio = + double( newSize.height() ) / double( oldSize.height() ); + + for ( int i = 0; i < int( d_data->pickedPoints.count() ); i++ ) + { + QPoint &p = d_data->pickedPoints[i]; + p.setX( qRound( p.x() * xRatio ) ); + p.setY( qRound( p.y() * yRatio ) ); + + Q_EMIT changed( d_data->pickedPoints ); + } +} + +/*! + Set mouse tracking for the observed widget. + + In case of enable is true, the previous value + is saved, that is restored when enable is false. + + \warning Even when enable is false, mouse tracking might be restored + to true. When mouseTracking for the observed widget + has been changed directly by QWidget::setMouseTracking + while mouse tracking has been set to true, this value can't + be restored. +*/ + +void QwtPicker::setMouseTracking( bool enable ) +{ + QWidget *widget = parentWidget(); + if ( !widget ) + return; + + if ( enable ) + { + d_data->mouseTracking = widget->hasMouseTracking(); + widget->setMouseTracking( true ); + } + else + { + widget->setMouseTracking( d_data->mouseTracking ); + } +} + +/*! + Find the area of the observed widget, where selection might happen. + + \return parentWidget()->contentsRect() +*/ +QPainterPath QwtPicker::pickArea() const +{ + QPainterPath path; + + const QWidget *widget = parentWidget(); + if ( widget ) + path.addRect( widget->contentsRect() ); + + return path; +} + +//! Update the state of rubber band and tracker label +void QwtPicker::updateDisplay() +{ + QWidget *w = parentWidget(); + + bool showRubberband = false; + bool showTracker = false; + + if ( w && w->isVisible() && d_data->enabled ) + { + if ( rubberBand() != NoRubberBand && isActive() && + rubberBandPen().style() != Qt::NoPen ) + { + showRubberband = true; + } + + if ( trackerMode() == AlwaysOn || + ( trackerMode() == ActiveOnly && isActive() ) ) + { + if ( trackerPen() != Qt::NoPen + && !trackerRect( QFont() ).isEmpty() ) + { + showTracker = true; + } + } + } + + QPointer< QwtPickerRubberband > &rw = d_data->rubberBandOverlay; + if ( showRubberband ) + { + if ( rw.isNull() ) + { + rw = new QwtPickerRubberband( this, NULL ); // NULL -> no extra event filter + rw->setObjectName( "PickerRubberBand" ); + rw->setParent( w ); + rw->resize( w->size() ); + } + + if ( d_data->rubberBand <= RectRubberBand ) + rw->setMaskMode( QwtWidgetOverlay::MaskHint ); + else + rw->setMaskMode( QwtWidgetOverlay::AlphaMask ); + + rw->updateOverlay(); + } + else + { + if ( d_data->openGL ) + { + // Qt 4.8 crashes for a delete + if ( !rw.isNull() ) + { + rw->hide(); + rw->deleteLater(); + rw = NULL; + } + } + else + { + delete rw; + } + } + + QPointer< QwtPickerTracker > &tw = d_data->trackerOverlay; + if ( showTracker ) + { + if ( tw.isNull() ) + { + tw = new QwtPickerTracker( this, NULL ); // NULL -> no extra event filter + tw->setObjectName( "PickerTracker" ); + tw->setParent( w ); + tw->resize( w->size() ); + } + tw->setFont( d_data->trackerFont ); + tw->updateOverlay(); + } + else + { + if ( d_data->openGL ) + { + // Qt 4.8 crashes for a delete + if ( !tw.isNull() ) + { + tw->hide(); + tw->deleteLater(); + tw = NULL; + } + } + else + { + delete tw; + } + } +} + +//! \return Overlay displaying the rubber band +const QwtWidgetOverlay *QwtPicker::rubberBandOverlay() const +{ + return d_data->rubberBandOverlay; +} + +//! \return Overlay displaying the tracker text +const QwtWidgetOverlay *QwtPicker::trackerOverlay() const +{ + return d_data->trackerOverlay; +} + diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_picker.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_picker.h new file mode 100644 index 0000000..c847cd5 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_picker.h @@ -0,0 +1,329 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PICKER +#define QWT_PICKER 1 + +#include "qwt_global.h" +#include "qwt_text.h" +#include "qwt_event_pattern.h" +#include +#include +#include +#include +#include + +class QWidget; +class QMouseEvent; +class QWheelEvent; +class QKeyEvent; +class QwtPickerMachine; +class QwtWidgetOverlay; + +/*! + \brief QwtPicker provides selections on a widget + + QwtPicker filters all enter, leave, mouse and keyboard events of a widget + and translates them into an array of selected points. + + The way how the points are collected depends on type of state machine + that is connected to the picker. Qwt offers a couple of predefined + state machines for selecting: + + - Nothing\n + QwtPickerTrackerMachine + - Single points\n + QwtPickerClickPointMachine, QwtPickerDragPointMachine + - Rectangles\n + QwtPickerClickRectMachine, QwtPickerDragRectMachine + - Polygons\n + QwtPickerPolygonMachine + + While these state machines cover the most common ways to collect points + it is also possible to implement individual machines as well. + + QwtPicker translates the picked points into a selection using the + adjustedPoints() method. adjustedPoints() is intended to be reimplemented + to fix up the selection according to application specific requirements. + (F.e. when an application accepts rectangles of a fixed aspect ratio only.) + + Optionally QwtPicker support the process of collecting points by a + rubber band and tracker displaying a text for the current mouse + position. + + \par Example + \verbatim #include +#include + +QwtPicker *picker = new QwtPicker(widget); +picker->setStateMachine(new QwtPickerDragRectMachine); +picker->setTrackerMode(QwtPicker::ActiveOnly); +picker->setRubberBand(QwtPicker::RectRubberBand); \endverbatim\n + + The state machine triggers the following commands: + + - begin()\n + Activate/Initialize the selection. + - append()\n + Add a new point + - move() \n + Change the position of the last point. + - remove()\n + Remove the last point. + - end()\n + Terminate the selection and call accept to validate the picked points. + + The picker is active (isActive()), between begin() and end(). + In active state the rubber band is displayed, and the tracker is visible + in case of trackerMode is ActiveOnly or AlwaysOn. + + The cursor can be moved using the arrow keys. All selections can be aborted + using the abort key. (QwtEventPattern::KeyPatternCode) + + \warning In case of QWidget::NoFocus the focus policy of the observed + widget is set to QWidget::WheelFocus and mouse tracking + will be manipulated while the picker is active, + or if trackerMode() is AlwayOn. +*/ + +class QWT_EXPORT QwtPicker: public QObject, public QwtEventPattern +{ + Q_OBJECT + + Q_ENUMS( RubberBand DisplayMode ResizeMode ) + + Q_PROPERTY( bool isEnabled READ isEnabled WRITE setEnabled ) + Q_PROPERTY( ResizeMode resizeMode READ resizeMode WRITE setResizeMode ) + + Q_PROPERTY( DisplayMode trackerMode READ trackerMode WRITE setTrackerMode ) + Q_PROPERTY( QPen trackerPen READ trackerPen WRITE setTrackerPen ) + Q_PROPERTY( QFont trackerFont READ trackerFont WRITE setTrackerFont ) + + Q_PROPERTY( RubberBand rubberBand READ rubberBand WRITE setRubberBand ) + Q_PROPERTY( QPen rubberBandPen READ rubberBandPen WRITE setRubberBandPen ) + +public: + /*! + Rubber band style + + The default value is QwtPicker::NoRubberBand. + \sa setRubberBand(), rubberBand() + */ + + enum RubberBand + { + //! No rubberband. + NoRubberBand = 0, + + //! A horizontal line ( only for QwtPickerMachine::PointSelection ) + HLineRubberBand, + + //! A vertical line ( only for QwtPickerMachine::PointSelection ) + VLineRubberBand, + + //! A crosshair ( only for QwtPickerMachine::PointSelection ) + CrossRubberBand, + + //! A rectangle ( only for QwtPickerMachine::RectSelection ) + RectRubberBand, + + //! An ellipse ( only for QwtPickerMachine::RectSelection ) + EllipseRubberBand, + + //! A polygon ( only for QwtPickerMachine::PolygonSelection ) + PolygonRubberBand, + + /*! + Values >= UserRubberBand can be used to define additional + rubber bands. + */ + UserRubberBand = 100 + }; + + /*! + \brief Display mode + \sa setTrackerMode(), trackerMode(), isActive() + */ + enum DisplayMode + { + //! Display never + AlwaysOff, + + //! Display always + AlwaysOn, + + //! Display only when the selection is active + ActiveOnly + }; + + /*! + Controls what to do with the selected points of an active + selection when the observed widget is resized. + + The default value is QwtPicker::Stretch. + \sa setResizeMode() + */ + + enum ResizeMode + { + //! All points are scaled according to the new size, + Stretch, + + //! All points remain unchanged. + KeepSize + }; + + explicit QwtPicker( QWidget *parent ); + explicit QwtPicker( RubberBand rubberBand, + DisplayMode trackerMode, QWidget * ); + + virtual ~QwtPicker(); + + void setStateMachine( QwtPickerMachine * ); + const QwtPickerMachine *stateMachine() const; + QwtPickerMachine *stateMachine(); + + void setRubberBand( RubberBand ); + RubberBand rubberBand() const; + + void setTrackerMode( DisplayMode ); + DisplayMode trackerMode() const; + + void setResizeMode( ResizeMode ); + ResizeMode resizeMode() const; + + void setRubberBandPen( const QPen & ); + QPen rubberBandPen() const; + + void setTrackerPen( const QPen & ); + QPen trackerPen() const; + + void setTrackerFont( const QFont & ); + QFont trackerFont() const; + + bool isEnabled() const; + bool isActive() const; + + virtual bool eventFilter( QObject *, QEvent * ); + + QWidget *parentWidget(); + const QWidget *parentWidget() const; + + virtual QPainterPath pickArea() const; + + virtual void drawRubberBand( QPainter * ) const; + virtual void drawTracker( QPainter * ) const; + + virtual QRegion rubberBandMask() const; + + virtual QwtText trackerText( const QPoint &pos ) const; + QPoint trackerPosition() const; + virtual QRect trackerRect( const QFont & ) const; + + QPolygon selection() const; + +public Q_SLOTS: + void setEnabled( bool ); + +Q_SIGNALS: + /*! + A signal indicating, when the picker has been activated. + Together with setEnabled() it can be used to implement + selections with more than one picker. + + \param on True, when the picker has been activated + */ + void activated( bool on ); + + /*! + A signal emitting the selected points, + at the end of a selection. + + \param polygon Selected points + */ + void selected( const QPolygon &polygon ); + + /*! + A signal emitted when a point has been appended to the selection + + \param pos Position of the appended point. + \sa append(). moved() + */ + void appended( const QPoint &pos ); + + /*! + A signal emitted whenever the last appended point of the + selection has been moved. + + \param pos Position of the moved last point of the selection. + \sa move(), appended() + */ + void moved( const QPoint &pos ); + + /*! + A signal emitted whenever the last appended point of the + selection has been removed. + + \param pos Position of the point, that has been removed + \sa remove(), appended() + */ + void removed( const QPoint &pos ); + /*! + A signal emitted when the active selection has been changed. + This might happen when the observed widget is resized. + + \param selection Changed selection + \sa stretchSelection() + */ + void changed( const QPolygon &selection ); + +protected: + virtual QPolygon adjustedPoints( const QPolygon & ) const; + + virtual void transition( const QEvent * ); + + virtual void begin(); + virtual void append( const QPoint & ); + virtual void move( const QPoint & ); + virtual void remove(); + virtual bool end( bool ok = true ); + + virtual bool accept( QPolygon & ) const; + virtual void reset(); + + virtual void widgetMousePressEvent( QMouseEvent * ); + virtual void widgetMouseReleaseEvent( QMouseEvent * ); + virtual void widgetMouseDoubleClickEvent( QMouseEvent * ); + virtual void widgetMouseMoveEvent( QMouseEvent * ); + virtual void widgetWheelEvent( QWheelEvent * ); + virtual void widgetKeyPressEvent( QKeyEvent * ); + virtual void widgetKeyReleaseEvent( QKeyEvent * ); + virtual void widgetEnterEvent( QEvent * ); + virtual void widgetLeaveEvent( QEvent * ); + + virtual void stretchSelection( const QSize &oldSize, + const QSize &newSize ); + + virtual void updateDisplay(); + + const QwtWidgetOverlay *rubberBandOverlay() const; + const QwtWidgetOverlay *trackerOverlay() const; + + const QPolygon &pickedPoints() const; + +private: + void init( QWidget *, RubberBand rubberBand, DisplayMode trackerMode ); + + void setMouseTracking( bool ); + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_picker_machine.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_picker_machine.cpp new file mode 100644 index 0000000..9f2f6f8 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_picker_machine.cpp @@ -0,0 +1,541 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_picker_machine.h" +#include "qwt_event_pattern.h" +#include + +//! Constructor +QwtPickerMachine::QwtPickerMachine( SelectionType type ): + d_selectionType( type ), + d_state( 0 ) +{ +} + +//! Destructor +QwtPickerMachine::~QwtPickerMachine() +{ +} + +//! Return the selection type +QwtPickerMachine::SelectionType QwtPickerMachine::selectionType() const +{ + return d_selectionType; +} + +//! Return the current state +int QwtPickerMachine::state() const +{ + return d_state; +} + +//! Change the current state +void QwtPickerMachine::setState( int state ) +{ + d_state = state; +} + +//! Set the current state to 0. +void QwtPickerMachine::reset() +{ + setState( 0 ); +} + +//! Constructor +QwtPickerTrackerMachine::QwtPickerTrackerMachine(): + QwtPickerMachine( NoSelection ) +{ +} + +//! Transition +QList QwtPickerTrackerMachine::transition( + const QwtEventPattern &, const QEvent *e ) +{ + QList cmdList; + + switch ( e->type() ) + { + case QEvent::Enter: + case QEvent::MouseMove: + { + if ( state() == 0 ) + { + cmdList += Begin; + cmdList += Append; + setState( 1 ); + } + else + { + cmdList += Move; + } + break; + } + case QEvent::Leave: + { + cmdList += Remove; + cmdList += End; + setState( 0 ); + } + default: + break; + } + + return cmdList; +} + +//! Constructor +QwtPickerClickPointMachine::QwtPickerClickPointMachine(): + QwtPickerMachine( PointSelection ) +{ +} + +//! Transition +QList QwtPickerClickPointMachine::transition( + const QwtEventPattern &eventPattern, const QEvent *event ) +{ + QList cmdList; + + switch ( event->type() ) + { + case QEvent::MouseButtonPress: + { + if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, + static_cast( event ) ) ) + { + cmdList += Begin; + cmdList += Append; + cmdList += End; + } + break; + } + case QEvent::KeyPress: + { + const QKeyEvent *keyEvent = static_cast ( event ); + if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, keyEvent ) ) + { + if ( !keyEvent->isAutoRepeat() ) + { + cmdList += Begin; + cmdList += Append; + cmdList += End; + } + } + break; + } + default: + break; + } + + return cmdList; +} + +//! Constructor +QwtPickerDragPointMachine::QwtPickerDragPointMachine(): + QwtPickerMachine( PointSelection ) +{ +} + +//! Transition +QList QwtPickerDragPointMachine::transition( + const QwtEventPattern &eventPattern, const QEvent *event ) +{ + QList cmdList; + + switch ( event->type() ) + { + case QEvent::MouseButtonPress: + { + if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, + static_cast( event ) ) ) + { + if ( state() == 0 ) + { + cmdList += Begin; + cmdList += Append; + setState( 1 ); + } + } + break; + } + case QEvent::MouseMove: + case QEvent::Wheel: + { + if ( state() != 0 ) + cmdList += Move; + break; + } + case QEvent::MouseButtonRelease: + { + if ( state() != 0 ) + { + cmdList += End; + setState( 0 ); + } + break; + } + case QEvent::KeyPress: + { + const QKeyEvent *keyEvent = static_cast ( event ); + if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, keyEvent ) ) + { + if ( !keyEvent->isAutoRepeat() ) + { + if ( state() == 0 ) + { + cmdList += Begin; + cmdList += Append; + setState( 1 ); + } + else + { + cmdList += End; + setState( 0 ); + } + } + } + break; + } + default: + break; + } + + return cmdList; +} + +//! Constructor +QwtPickerClickRectMachine::QwtPickerClickRectMachine(): + QwtPickerMachine( RectSelection ) +{ +} + +//! Transition +QList QwtPickerClickRectMachine::transition( + const QwtEventPattern &eventPattern, const QEvent *event ) +{ + QList cmdList; + + switch ( event->type() ) + { + case QEvent::MouseButtonPress: + { + if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, + static_cast( event ) ) ) + { + switch ( state() ) + { + case 0: + { + cmdList += Begin; + cmdList += Append; + setState( 1 ); + break; + } + case 1: + { + // Uh, strange we missed the MouseButtonRelease + break; + } + default: + { + cmdList += End; + setState( 0 ); + } + } + } + break; + } + case QEvent::MouseMove: + case QEvent::Wheel: + { + if ( state() != 0 ) + cmdList += Move; + break; + } + case QEvent::MouseButtonRelease: + { + if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, + static_cast( event ) ) ) + { + if ( state() == 1 ) + { + cmdList += Append; + setState( 2 ); + } + } + break; + } + case QEvent::KeyPress: + { + const QKeyEvent *keyEvent = static_cast ( event ); + if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, keyEvent ) ) + { + if ( !keyEvent->isAutoRepeat() ) + { + if ( state() == 0 ) + { + cmdList += Begin; + cmdList += Append; + setState( 1 ); + } + else + { + if ( state() == 1 ) + { + cmdList += Append; + setState( 2 ); + } + else if ( state() == 2 ) + { + cmdList += End; + setState( 0 ); + } + } + } + } + break; + } + default: + break; + } + + return cmdList; +} + +//! Constructor +QwtPickerDragRectMachine::QwtPickerDragRectMachine(): + QwtPickerMachine( RectSelection ) +{ +} + +//! Transition +QList QwtPickerDragRectMachine::transition( + const QwtEventPattern &eventPattern, const QEvent *event ) +{ + QList cmdList; + + switch ( event->type() ) + { + case QEvent::MouseButtonPress: + { + if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, + static_cast( event ) ) ) + { + if ( state() == 0 ) + { + cmdList += Begin; + cmdList += Append; + cmdList += Append; + setState( 2 ); + } + } + break; + } + case QEvent::MouseMove: + case QEvent::Wheel: + { + if ( state() != 0 ) + cmdList += Move; + break; + } + case QEvent::MouseButtonRelease: + { + if ( state() == 2 ) + { + cmdList += End; + setState( 0 ); + } + break; + } + case QEvent::KeyPress: + { + if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, + static_cast ( event ) ) ) + { + if ( state() == 0 ) + { + cmdList += Begin; + cmdList += Append; + cmdList += Append; + setState( 2 ); + } + else + { + cmdList += End; + setState( 0 ); + } + } + break; + } + default: + break; + } + + return cmdList; +} + +//! Constructor +QwtPickerPolygonMachine::QwtPickerPolygonMachine(): + QwtPickerMachine( PolygonSelection ) +{ +} + +//! Transition +QList QwtPickerPolygonMachine::transition( + const QwtEventPattern &eventPattern, const QEvent *event ) +{ + QList cmdList; + + switch ( event->type() ) + { + case QEvent::MouseButtonPress: + { + if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, + static_cast( event ) ) ) + { + if ( state() == 0 ) + { + cmdList += Begin; + cmdList += Append; + cmdList += Append; + setState( 1 ); + } + else + { + cmdList += Append; + } + } + if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect2, + static_cast( event ) ) ) + { + if ( state() == 1 ) + { + cmdList += End; + setState( 0 ); + } + } + break; + } + case QEvent::MouseMove: + case QEvent::Wheel: + { + if ( state() != 0 ) + cmdList += Move; + break; + } + case QEvent::KeyPress: + { + const QKeyEvent *keyEvent = static_cast ( event ); + if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, keyEvent ) ) + { + if ( !keyEvent->isAutoRepeat() ) + { + if ( state() == 0 ) + { + cmdList += Begin; + cmdList += Append; + cmdList += Append; + setState( 1 ); + } + else + { + cmdList += Append; + } + } + } + else if ( eventPattern.keyMatch( QwtEventPattern::KeySelect2, keyEvent ) ) + { + if ( !keyEvent->isAutoRepeat() ) + { + if ( state() == 1 ) + { + cmdList += End; + setState( 0 ); + } + } + } + break; + } + default: + break; + } + + return cmdList; +} + +//! Constructor +QwtPickerDragLineMachine::QwtPickerDragLineMachine(): + QwtPickerMachine( PolygonSelection ) +{ +} + +//! Transition +QList QwtPickerDragLineMachine::transition( + const QwtEventPattern &eventPattern, const QEvent *event ) +{ + QList cmdList; + + switch( event->type() ) + { + case QEvent::MouseButtonPress: + { + if ( eventPattern.mouseMatch( QwtEventPattern::MouseSelect1, + static_cast( event ) ) ) + { + if ( state() == 0 ) + { + cmdList += Begin; + cmdList += Append; + cmdList += Append; + setState( 1 ); + } + } + break; + } + case QEvent::KeyPress: + { + if ( eventPattern.keyMatch( QwtEventPattern::KeySelect1, + static_cast ( event ) ) ) + { + if ( state() == 0 ) + { + cmdList += Begin; + cmdList += Append; + cmdList += Append; + setState( 1 ); + } + else + { + cmdList += End; + setState( 0 ); + } + } + break; + } + case QEvent::MouseMove: + case QEvent::Wheel: + { + if ( state() != 0 ) + cmdList += Move; + + break; + } + case QEvent::MouseButtonRelease: + { + if ( state() != 0 ) + { + cmdList += End; + setState( 0 ); + } + } + default: + break; + } + + return cmdList; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_picker_machine.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_picker_machine.h new file mode 100644 index 0000000..a1d2499 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_picker_machine.h @@ -0,0 +1,214 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PICKER_MACHINE +#define QWT_PICKER_MACHINE 1 + +#include "qwt_global.h" +#include + +class QEvent; +class QwtEventPattern; + +/*! + \brief A state machine for QwtPicker selections + + QwtPickerMachine accepts key and mouse events and translates them + into selection commands. + + \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode +*/ + +class QWT_EXPORT QwtPickerMachine +{ +public: + /*! + Type of a selection. + \sa selectionType() + */ + enum SelectionType + { + //! The state machine not usable for any type of selection. + NoSelection = -1, + + //! The state machine is for selecting a single point. + PointSelection, + + //! The state machine is for selecting a rectangle (2 points). + RectSelection, + + //! The state machine is for selecting a polygon (many points). + PolygonSelection + }; + + //! Commands - the output of a state machine + enum Command + { + Begin, + Append, + Move, + Remove, + End + }; + + QwtPickerMachine( SelectionType ); + virtual ~QwtPickerMachine(); + + //! Transition + virtual QList transition( + const QwtEventPattern &, const QEvent * ) = 0; + void reset(); + + int state() const; + void setState( int ); + + SelectionType selectionType() const; + +private: + const SelectionType d_selectionType; + int d_state; +}; + +/*! + \brief A state machine for indicating mouse movements + + QwtPickerTrackerMachine supports displaying information + corresponding to mouse movements, but is not intended for + selecting anything. Begin/End are related to Enter/Leave events. +*/ +class QWT_EXPORT QwtPickerTrackerMachine: public QwtPickerMachine +{ +public: + QwtPickerTrackerMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); +}; + +/*! + \brief A state machine for point selections + + Pressing QwtEventPattern::MouseSelect1 or + QwtEventPattern::KeySelect1 selects a point. + + \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode +*/ +class QWT_EXPORT QwtPickerClickPointMachine: public QwtPickerMachine +{ +public: + QwtPickerClickPointMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); +}; + +/*! + \brief A state machine for point selections + + Pressing QwtEventPattern::MouseSelect1 or QwtEventPattern::KeySelect1 + starts the selection, releasing QwtEventPattern::MouseSelect1 or + a second press of QwtEventPattern::KeySelect1 terminates it. +*/ +class QWT_EXPORT QwtPickerDragPointMachine: public QwtPickerMachine +{ +public: + QwtPickerDragPointMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); +}; + +/*! + \brief A state machine for rectangle selections + + Pressing QwtEventPattern::MouseSelect1 starts + the selection, releasing it selects the first point. Pressing it + again selects the second point and terminates the selection. + Pressing QwtEventPattern::KeySelect1 also starts the + selection, a second press selects the first point. A third one selects + the second point and terminates the selection. + + \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode +*/ + +class QWT_EXPORT QwtPickerClickRectMachine: public QwtPickerMachine +{ +public: + QwtPickerClickRectMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); +}; + +/*! + \brief A state machine for rectangle selections + + Pressing QwtEventPattern::MouseSelect1 selects + the first point, releasing it the second point. + Pressing QwtEventPattern::KeySelect1 also selects the + first point, a second press selects the second point and terminates + the selection. + + \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode +*/ + +class QWT_EXPORT QwtPickerDragRectMachine: public QwtPickerMachine +{ +public: + QwtPickerDragRectMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); +}; + +/*! + \brief A state machine for line selections + + Pressing QwtEventPattern::MouseSelect1 selects + the first point, releasing it the second point. + Pressing QwtEventPattern::KeySelect1 also selects the + first point, a second press selects the second point and terminates + the selection. + + A common use case of QwtPickerDragLineMachine are pickers for + distance measurements. + + \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode +*/ + +class QWT_EXPORT QwtPickerDragLineMachine: public QwtPickerMachine +{ +public: + QwtPickerDragLineMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); +}; + +/*! + \brief A state machine for polygon selections + + Pressing QwtEventPattern::MouseSelect1 or QwtEventPattern::KeySelect1 + starts the selection and selects the first point, or appends a point. + Pressing QwtEventPattern::MouseSelect2 or QwtEventPattern::KeySelect2 + appends the last point and terminates the selection. + + \sa QwtEventPattern::MousePatternCode, QwtEventPattern::KeyPatternCode +*/ + +class QWT_EXPORT QwtPickerPolygonMachine: public QwtPickerMachine +{ +public: + QwtPickerPolygonMachine(); + + virtual QList transition( + const QwtEventPattern &, const QEvent * ); +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_pixel_matrix.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_pixel_matrix.cpp new file mode 100644 index 0000000..6b28653 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_pixel_matrix.cpp @@ -0,0 +1,51 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_pixel_matrix.h" + +/*! + \brief Constructor + + \param rect Bounding rectangle for the matrix +*/ +QwtPixelMatrix::QwtPixelMatrix( const QRect& rect ): + QBitArray( qMax( rect.width() * rect.height(), 0 ) ), + d_rect( rect ) +{ +} + +//! Destructor +QwtPixelMatrix::~QwtPixelMatrix() +{ +} + +/*! + Set the bounding rectangle of the matrix + + \param rect Bounding rectangle + + \note All bits are cleared + */ +void QwtPixelMatrix::setRect( const QRect& rect ) +{ + if ( rect != d_rect ) + { + d_rect = rect; + const int sz = qMax( rect.width() * rect.height(), 0 ); + resize( sz ); + } + + fill( false ); +} + +//! \return Bounding rectangle +QRect QwtPixelMatrix::rect() const +{ + return d_rect; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_pixel_matrix.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_pixel_matrix.h new file mode 100644 index 0000000..1428d1b --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_pixel_matrix.h @@ -0,0 +1,98 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PIXEL_MATRIX_H +#define QWT_PIXEL_MATRIX_H + +#include "qwt_global.h" +#include +#include + +/*! + \brief A bit field corresponding to the pixels of a rectangle + + QwtPixelMatrix is intended to filter out duplicates in an + unsorted array of points. +*/ +class QWT_EXPORT QwtPixelMatrix: public QBitArray +{ +public: + QwtPixelMatrix( const QRect& rect ); + ~QwtPixelMatrix(); + + void setRect( const QRect& rect ); + QRect rect() const; + + bool testPixel( int x, int y ) const; + bool testAndSetPixel( int x, int y, bool on ); + + int index( int x, int y ) const; + +private: + QRect d_rect; +}; + +/*! + \brief Test if a pixel has been set + + \param x X-coordinate + \param y Y-coordinate + + \return true, when pos is outside of rect(), or when the pixel + has already been set. + */ +inline bool QwtPixelMatrix::testPixel( int x, int y ) const +{ + const int idx = index( x, y ); + return ( idx >= 0 ) ? testBit( idx ) : true; +} + +/*! + \brief Set a pixel and test if a pixel has been set before + + \param x X-coordinate + \param y Y-coordinate + \param on Set/Clear the pixel + + \return true, when pos is outside of rect(), or when the pixel + was set before. + */ +inline bool QwtPixelMatrix::testAndSetPixel( int x, int y, bool on ) +{ + const int idx = index( x, y ); + if ( idx < 0 ) + return true; + + const bool onBefore = testBit( idx ); + setBit( idx, on ); + + return onBefore; +} + +/*! + \brief Calculate the index in the bit field corresponding to a position + + \param x X-coordinate + \param y Y-coordinate + \return Index, when rect() contains pos - otherwise -1. + */ +inline int QwtPixelMatrix::index( int x, int y ) const +{ + const int dx = x - d_rect.x(); + if ( dx < 0 || dx >= d_rect.width() ) + return -1; + + const int dy = y - d_rect.y(); + if ( dy < 0 || dy >= d_rect.height() ) + return -1; + + return dy * d_rect.width() + dx; +} + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot.cpp new file mode 100644 index 0000000..7cba355 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot.cpp @@ -0,0 +1,1176 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot.h" +#include "qwt_plot_dict.h" +#include "qwt_plot_layout.h" +#include "qwt_scale_widget.h" +#include "qwt_scale_engine.h" +#include "qwt_text_label.h" +#include "qwt_legend.h" +#include "qwt_legend_data.h" +#include "qwt_plot_canvas.h" +#include +#include +#include +#include +#include +#include + +static inline void qwtEnableLegendItems( QwtPlot *plot, bool on ) +{ + if ( on ) + { + QObject::connect( + plot, SIGNAL( legendDataChanged( + const QVariant &, const QList & ) ), + plot, SLOT( updateLegendItems( + const QVariant &, const QList & ) ) ); + } + else + { + QObject::disconnect( + plot, SIGNAL( legendDataChanged( + const QVariant &, const QList & ) ), + plot, SLOT( updateLegendItems( + const QVariant &, const QList & ) ) ); + } +} + +static void qwtSetTabOrder( + QWidget *first, QWidget *second, bool withChildren ) +{ + QList tabChain; + tabChain += first; + tabChain += second; + + if ( withChildren ) + { + QList children = second->findChildren(); + + QWidget *w = second->nextInFocusChain(); + while ( children.contains( w ) ) + { + children.removeAll( w ); + + tabChain += w; + w = w->nextInFocusChain(); + } + } + + for ( int i = 0; i < tabChain.size() - 1; i++ ) + { + QWidget *from = tabChain[i]; + QWidget *to = tabChain[i+1]; + + const Qt::FocusPolicy policy1 = from->focusPolicy(); + const Qt::FocusPolicy policy2 = to->focusPolicy(); + + QWidget *proxy1 = from->focusProxy(); + QWidget *proxy2 = to->focusProxy(); + + from->setFocusPolicy( Qt::TabFocus ); + from->setFocusProxy( NULL); + + to->setFocusPolicy( Qt::TabFocus ); + to->setFocusProxy( NULL); + + QWidget::setTabOrder( from, to ); + + from->setFocusPolicy( policy1 ); + from->setFocusProxy( proxy1); + + to->setFocusPolicy( policy2 ); + to->setFocusProxy( proxy2 ); + } +} + +class QwtPlot::PrivateData +{ +public: + QPointer titleLabel; + QPointer footerLabel; + QPointer canvas; + QPointer legend; + QwtPlotLayout *layout; + + bool autoReplot; +}; + +/*! + \brief Constructor + \param parent Parent widget + */ +QwtPlot::QwtPlot( QWidget *parent ): + QFrame( parent ) +{ + initPlot( QwtText() ); +} + +/*! + \brief Constructor + \param title Title text + \param parent Parent widget + */ +QwtPlot::QwtPlot( const QwtText &title, QWidget *parent ): + QFrame( parent ) +{ + initPlot( title ); +} + +//! Destructor +QwtPlot::~QwtPlot() +{ + setAutoReplot( false ); + detachItems( QwtPlotItem::Rtti_PlotItem, autoDelete() ); + + delete d_data->layout; + deleteAxesData(); + delete d_data; +} + +/*! + \brief Initializes a QwtPlot instance + \param title Title text + */ +void QwtPlot::initPlot( const QwtText &title ) +{ + d_data = new PrivateData; + + d_data->layout = new QwtPlotLayout; + d_data->autoReplot = false; + + // title + d_data->titleLabel = new QwtTextLabel( this ); + d_data->titleLabel->setObjectName( "QwtPlotTitle" ); + d_data->titleLabel->setFont( QFont( fontInfo().family(), 14, QFont::Bold ) ); + + QwtText text( title ); + text.setRenderFlags( Qt::AlignCenter | Qt::TextWordWrap ); + d_data->titleLabel->setText( text ); + + // footer + d_data->footerLabel = new QwtTextLabel( this ); + d_data->footerLabel->setObjectName( "QwtPlotFooter" ); + + QwtText footer; + footer.setRenderFlags( Qt::AlignCenter | Qt::TextWordWrap ); + d_data->footerLabel->setText( footer ); + + // legend + d_data->legend = NULL; + + // axis + initAxesData(); + + // canvas + d_data->canvas = new QwtPlotCanvas( this ); + d_data->canvas->setObjectName( "QwtPlotCanvas" ); + d_data->canvas->installEventFilter( this ); + + setSizePolicy( QSizePolicy::MinimumExpanding, + QSizePolicy::MinimumExpanding ); + + resize( 200, 200 ); + + QList focusChain; + focusChain << this << d_data->titleLabel << axisWidget( xTop ) + << axisWidget( yLeft ) << d_data->canvas << axisWidget( yRight ) + << axisWidget( xBottom ) << d_data->footerLabel; + + for ( int i = 0; i < focusChain.size() - 1; i++ ) + qwtSetTabOrder( focusChain[i], focusChain[i+1], false ); + + qwtEnableLegendItems( this, true ); +} + +/*! + \brief Set the drawing canvas of the plot widget + + QwtPlot invokes methods of the canvas as meta methods ( see QMetaObject ). + In opposite to using conventional C++ techniques like virtual methods + they allow to use canvas implementations that are derived from + QWidget or QGLWidget. + + The following meta methods could be implemented: + + - replot() + When the canvas doesn't offer a replot method, QwtPlot calls + update() instead. + + - borderPath() + The border path is necessary to clip the content of the canvas + When the canvas doesn't have any special border ( f.e rounded corners ) + it is o.k. not to implement this method. + + The default canvas is a QwtPlotCanvas + + \param canvas Canvas Widget + \sa canvas() + */ +void QwtPlot::setCanvas( QWidget *canvas ) +{ + if ( canvas == d_data->canvas ) + return; + + delete d_data->canvas; + d_data->canvas = canvas; + + if ( canvas ) + { + canvas->setParent( this ); + canvas->installEventFilter( this ); + + if ( isVisible() ) + canvas->show(); + } +} + +/*! + \brief Adds handling of layout requests + \param event Event + + \return See QFrame::event() +*/ +bool QwtPlot::event( QEvent *event ) +{ + bool ok = QFrame::event( event ); + switch ( event->type() ) + { + case QEvent::LayoutRequest: + updateLayout(); + break; + case QEvent::PolishRequest: + replot(); + break; + default:; + } + return ok; +} + +/*! + \brief Event filter + + The plot handles the following events for the canvas: + + - QEvent::Resize + The canvas margins might depend on its size + + - QEvent::ContentsRectChange + The layout needs to be recalculated + + \param object Object to be filtered + \param event Event + + \return See QFrame::eventFilter() + + \sa updateCanvasMargins(), updateLayout() +*/ +bool QwtPlot::eventFilter( QObject *object, QEvent *event ) +{ + if ( object == d_data->canvas ) + { + if ( event->type() == QEvent::Resize ) + { + updateCanvasMargins(); + } + else if ( event->type() == QEvent::ContentsRectChange ) + { + updateLayout(); + } + } + + return QFrame::eventFilter( object, event ); +} + +//! Replots the plot if autoReplot() is \c true. +void QwtPlot::autoRefresh() +{ + if ( d_data->autoReplot ) + replot(); +} + +/*! + \brief Set or reset the autoReplot option + + If the autoReplot option is set, the plot will be + updated implicitly by manipulating member functions. + Since this may be time-consuming, it is recommended + to leave this option switched off and call replot() + explicitly if necessary. + + The autoReplot option is set to false by default, which + means that the user has to call replot() in order to make + changes visible. + \param tf \c true or \c false. Defaults to \c true. + \sa replot() +*/ +void QwtPlot::setAutoReplot( bool tf ) +{ + d_data->autoReplot = tf; +} + +/*! + \return true if the autoReplot option is set. + \sa setAutoReplot() +*/ +bool QwtPlot::autoReplot() const +{ + return d_data->autoReplot; +} + +/*! + Change the plot's title + \param title New title +*/ +void QwtPlot::setTitle( const QString &title ) +{ + if ( title != d_data->titleLabel->text().text() ) + { + d_data->titleLabel->setText( title ); + updateLayout(); + } +} + +/*! + Change the plot's title + \param title New title +*/ +void QwtPlot::setTitle( const QwtText &title ) +{ + if ( title != d_data->titleLabel->text() ) + { + d_data->titleLabel->setText( title ); + updateLayout(); + } +} + +//! \return Title of the plot +QwtText QwtPlot::title() const +{ + return d_data->titleLabel->text(); +} + +//! \return Title label widget. +QwtTextLabel *QwtPlot::titleLabel() +{ + return d_data->titleLabel; +} + +//! \return Title label widget. +const QwtTextLabel *QwtPlot::titleLabel() const +{ + return d_data->titleLabel; +} + +/*! + Change the text the footer + \param text New text of the footer +*/ +void QwtPlot::setFooter( const QString &text ) +{ + if ( text != d_data->footerLabel->text().text() ) + { + d_data->footerLabel->setText( text ); + updateLayout(); + } +} + +/*! + Change the text the footer + \param text New text of the footer +*/ +void QwtPlot::setFooter( const QwtText &text ) +{ + if ( text != d_data->footerLabel->text() ) + { + d_data->footerLabel->setText( text ); + updateLayout(); + } +} + +//! \return Text of the footer +QwtText QwtPlot::footer() const +{ + return d_data->footerLabel->text(); +} + +//! \return Footer label widget. +QwtTextLabel *QwtPlot::footerLabel() +{ + return d_data->footerLabel; +} + +//! \return Footer label widget. +const QwtTextLabel *QwtPlot::footerLabel() const +{ + return d_data->footerLabel; +} + +/*! + \brief Assign a new plot layout + + \param layout Layout() + \sa plotLayout() + */ +void QwtPlot::setPlotLayout( QwtPlotLayout *layout ) +{ + if ( layout != d_data->layout ) + { + delete d_data->layout; + d_data->layout = layout; + + updateLayout(); + } +} + +//! \return the plot's layout +QwtPlotLayout *QwtPlot::plotLayout() +{ + return d_data->layout; +} + +//! \return the plot's layout +const QwtPlotLayout *QwtPlot::plotLayout() const +{ + return d_data->layout; +} + +/*! + \return the plot's legend + \sa insertLegend() +*/ +QwtAbstractLegend *QwtPlot::legend() +{ + return d_data->legend; +} + +/*! + \return the plot's legend + \sa insertLegend() +*/ +const QwtAbstractLegend *QwtPlot::legend() const +{ + return d_data->legend; +} + + +/*! + \return the plot's canvas +*/ +QWidget *QwtPlot::canvas() +{ + return d_data->canvas; +} + +/*! + \return the plot's canvas +*/ +const QWidget *QwtPlot::canvas() const +{ + return d_data->canvas; +} + +/*! + \return Size hint for the plot widget + \sa minimumSizeHint() +*/ +QSize QwtPlot::sizeHint() const +{ + int dw = 0; + int dh = 0; + for ( int axisId = 0; axisId < axisCnt; axisId++ ) + { + if ( axisEnabled( axisId ) ) + { + const int niceDist = 40; + const QwtScaleWidget *scaleWidget = axisWidget( axisId ); + const QwtScaleDiv &scaleDiv = scaleWidget->scaleDraw()->scaleDiv(); + const int majCnt = scaleDiv.ticks( QwtScaleDiv::MajorTick ).count(); + + if ( axisId == yLeft || axisId == yRight ) + { + int hDiff = ( majCnt - 1 ) * niceDist + - scaleWidget->minimumSizeHint().height(); + if ( hDiff > dh ) + dh = hDiff; + } + else + { + int wDiff = ( majCnt - 1 ) * niceDist + - scaleWidget->minimumSizeHint().width(); + if ( wDiff > dw ) + dw = wDiff; + } + } + } + return minimumSizeHint() + QSize( dw, dh ); +} + +/*! + \brief Return a minimum size hint +*/ +QSize QwtPlot::minimumSizeHint() const +{ + QSize hint = d_data->layout->minimumSizeHint( this ); + hint += QSize( 2 * frameWidth(), 2 * frameWidth() ); + + return hint; +} + +/*! + Resize and update internal layout + \param e Resize event +*/ +void QwtPlot::resizeEvent( QResizeEvent *e ) +{ + QFrame::resizeEvent( e ); + updateLayout(); +} + +/*! + \brief Redraw the plot + + If the autoReplot option is not set (which is the default) + or if any curves are attached to raw data, the plot has to + be refreshed explicitly in order to make changes visible. + + \sa updateAxes(), setAutoReplot() +*/ +void QwtPlot::replot() +{ + bool doAutoReplot = autoReplot(); + setAutoReplot( false ); + + updateAxes(); + + /* + Maybe the layout needs to be updated, because of changed + axes labels. We need to process them here before painting + to avoid that scales and canvas get out of sync. + */ + QApplication::sendPostedEvents( this, QEvent::LayoutRequest ); + + if ( d_data->canvas ) + { + const bool ok = QMetaObject::invokeMethod( + d_data->canvas, "replot", Qt::DirectConnection ); + if ( !ok ) + { + // fallback, when canvas has no a replot method + d_data->canvas->update( d_data->canvas->contentsRect() ); + } + } + + setAutoReplot( doAutoReplot ); +} + +/*! + \brief Adjust plot content to its current size. + \sa resizeEvent() +*/ +void QwtPlot::updateLayout() +{ + d_data->layout->activate( this, contentsRect() ); + + QRect titleRect = d_data->layout->titleRect().toRect(); + QRect footerRect = d_data->layout->footerRect().toRect(); + QRect scaleRect[QwtPlot::axisCnt]; + for ( int axisId = 0; axisId < axisCnt; axisId++ ) + scaleRect[axisId] = d_data->layout->scaleRect( axisId ).toRect(); + QRect legendRect = d_data->layout->legendRect().toRect(); + QRect canvasRect = d_data->layout->canvasRect().toRect(); + + // resize and show the visible widgets + + if ( !d_data->titleLabel->text().isEmpty() ) + { + d_data->titleLabel->setGeometry( titleRect ); + if ( !d_data->titleLabel->isVisibleTo( this ) ) + d_data->titleLabel->show(); + } + else + d_data->titleLabel->hide(); + + if ( !d_data->footerLabel->text().isEmpty() ) + { + d_data->footerLabel->setGeometry( footerRect ); + if ( !d_data->footerLabel->isVisibleTo( this ) ) + d_data->footerLabel->show(); + } + else + d_data->footerLabel->hide(); + + for ( int axisId = 0; axisId < axisCnt; axisId++ ) + { + if ( axisEnabled( axisId ) ) + { + axisWidget( axisId )->setGeometry( scaleRect[axisId] ); + +#if 1 + if ( axisId == xBottom || axisId == xTop ) + { + // do we need this code any longer ??? + + QRegion r( scaleRect[axisId] ); + if ( axisEnabled( yLeft ) ) + r = r.subtracted( QRegion( scaleRect[yLeft] ) ); + if ( axisEnabled( yRight ) ) + r = r.subtracted( QRegion( scaleRect[yRight] ) ); + r.translate( -scaleRect[ axisId ].x(), + -scaleRect[axisId].y() ); + + axisWidget( axisId )->setMask( r ); + } +#endif + if ( !axisWidget( axisId )->isVisibleTo( this ) ) + axisWidget( axisId )->show(); + } + else + axisWidget( axisId )->hide(); + } + + if ( d_data->legend ) + { + if ( d_data->legend->isEmpty() ) + { + d_data->legend->hide(); + } + else + { + d_data->legend->setGeometry( legendRect ); + d_data->legend->show(); + } + } + + d_data->canvas->setGeometry( canvasRect ); +} + +/*! + \brief Calculate the canvas margins + + \param maps QwtPlot::axisCnt maps, mapping between plot and paint device coordinates + \param canvasRect Bounding rectangle where to paint + \param left Return parameter for the left margin + \param top Return parameter for the top margin + \param right Return parameter for the right margin + \param bottom Return parameter for the bottom margin + + Plot items might indicate, that they need some extra space + at the borders of the canvas by the QwtPlotItem::Margins flag. + + updateCanvasMargins(), QwtPlotItem::getCanvasMarginHint() + */ +void QwtPlot::getCanvasMarginsHint( + const QwtScaleMap maps[], const QRectF &canvasRect, + double &left, double &top, double &right, double &bottom) const +{ + left = top = right = bottom = -1.0; + + const QwtPlotItemList& itmList = itemList(); + for ( QwtPlotItemIterator it = itmList.begin(); + it != itmList.end(); ++it ) + { + const QwtPlotItem *item = *it; + if ( item->testItemAttribute( QwtPlotItem::Margins ) ) + { + double m[ QwtPlot::axisCnt ]; + item->getCanvasMarginHint( + maps[ item->xAxis() ], maps[ item->yAxis() ], + canvasRect, m[yLeft], m[xTop], m[yRight], m[xBottom] ); + + left = qMax( left, m[yLeft] ); + top = qMax( top, m[xTop] ); + right = qMax( right, m[yRight] ); + bottom = qMax( bottom, m[xBottom] ); + } + } +} + +/*! + \brief Update the canvas margins + + Plot items might indicate, that they need some extra space + at the borders of the canvas by the QwtPlotItem::Margins flag. + + getCanvasMarginsHint(), QwtPlotItem::getCanvasMarginHint() + */ +void QwtPlot::updateCanvasMargins() +{ + QwtScaleMap maps[axisCnt]; + for ( int axisId = 0; axisId < axisCnt; axisId++ ) + maps[axisId] = canvasMap( axisId ); + + double margins[axisCnt]; + getCanvasMarginsHint( maps, canvas()->contentsRect(), + margins[yLeft], margins[xTop], margins[yRight], margins[xBottom] ); + + bool doUpdate = false; + for ( int axisId = 0; axisId < axisCnt; axisId++ ) + { + if ( margins[axisId] >= 0.0 ) + { + const int m = qCeil( margins[axisId] ); + plotLayout()->setCanvasMargin( m, axisId); + doUpdate = true; + } + } + + if ( doUpdate ) + updateLayout(); +} + +/*! + Redraw the canvas. + \param painter Painter used for drawing + + \warning drawCanvas calls drawItems what is also used + for printing. Applications that like to add individual + plot items better overload drawItems() + \sa drawItems() +*/ +void QwtPlot::drawCanvas( QPainter *painter ) +{ + QwtScaleMap maps[axisCnt]; + for ( int axisId = 0; axisId < axisCnt; axisId++ ) + maps[axisId] = canvasMap( axisId ); + + drawItems( painter, d_data->canvas->contentsRect(), maps ); +} + +/*! + Redraw the canvas items. + + \param painter Painter used for drawing + \param canvasRect Bounding rectangle where to paint + \param maps QwtPlot::axisCnt maps, mapping between plot and paint device coordinates + + \note Usually canvasRect is contentsRect() of the plot canvas. + Due to a bug in Qt this rectangle might be wrong for certain + frame styles ( f.e QFrame::Box ) and it might be necessary to + fix the margins manually using QWidget::setContentsMargins() +*/ + +void QwtPlot::drawItems( QPainter *painter, const QRectF &canvasRect, + const QwtScaleMap maps[axisCnt] ) const +{ + const QwtPlotItemList& itmList = itemList(); + for ( QwtPlotItemIterator it = itmList.begin(); + it != itmList.end(); ++it ) + { + QwtPlotItem *item = *it; + if ( item && item->isVisible() ) + { + painter->save(); + + painter->setRenderHint( QPainter::Antialiasing, + item->testRenderHint( QwtPlotItem::RenderAntialiased ) ); + painter->setRenderHint( QPainter::HighQualityAntialiasing, + item->testRenderHint( QwtPlotItem::RenderAntialiased ) ); + + item->draw( painter, + maps[item->xAxis()], maps[item->yAxis()], + canvasRect ); + + painter->restore(); + } + } +} + +/*! + \param axisId Axis + \return Map for the axis on the canvas. With this map pixel coordinates can + translated to plot coordinates and vice versa. + \sa QwtScaleMap, transform(), invTransform() + +*/ +QwtScaleMap QwtPlot::canvasMap( int axisId ) const +{ + QwtScaleMap map; + if ( !d_data->canvas ) + return map; + + map.setTransformation( axisScaleEngine( axisId )->transformation() ); + + const QwtScaleDiv &sd = axisScaleDiv( axisId ); + map.setScaleInterval( sd.lowerBound(), sd.upperBound() ); + + if ( axisEnabled( axisId ) ) + { + const QwtScaleWidget *s = axisWidget( axisId ); + if ( axisId == yLeft || axisId == yRight ) + { + double y = s->y() + s->startBorderDist() - d_data->canvas->y(); + double h = s->height() - s->startBorderDist() - s->endBorderDist(); + map.setPaintInterval( y + h, y ); + } + else + { + double x = s->x() + s->startBorderDist() - d_data->canvas->x(); + double w = s->width() - s->startBorderDist() - s->endBorderDist(); + map.setPaintInterval( x, x + w ); + } + } + else + { + const QRect &canvasRect = d_data->canvas->contentsRect(); + if ( axisId == yLeft || axisId == yRight ) + { + int top = 0; + if ( !plotLayout()->alignCanvasToScale( xTop ) ) + top = plotLayout()->canvasMargin( xTop ); + + int bottom = 0; + if ( !plotLayout()->alignCanvasToScale( xBottom ) ) + bottom = plotLayout()->canvasMargin( xBottom ); + + map.setPaintInterval( canvasRect.bottom() - bottom, + canvasRect.top() + top ); + } + else + { + int left = 0; + if ( !plotLayout()->alignCanvasToScale( yLeft ) ) + left = plotLayout()->canvasMargin( yLeft ); + + int right = 0; + if ( !plotLayout()->alignCanvasToScale( yRight ) ) + right = plotLayout()->canvasMargin( yRight ); + + map.setPaintInterval( canvasRect.left() + left, + canvasRect.right() - right ); + } + } + + return map; +} + +/*! + \brief Change the background of the plotting area + + Sets brush to QPalette::Window of all color groups of + the palette of the canvas. Using canvas()->setPalette() + is a more powerful way to set these colors. + + \param brush New background brush + \sa canvasBackground() +*/ +void QwtPlot::setCanvasBackground( const QBrush &brush ) +{ + QPalette pal = d_data->canvas->palette(); + pal.setBrush( QPalette::Window, brush ); + + canvas()->setPalette( pal ); +} + +/*! + Nothing else than: canvas()->palette().brush( + QPalette::Normal, QPalette::Window); + + \return Background brush of the plotting area. + \sa setCanvasBackground() +*/ +QBrush QwtPlot::canvasBackground() const +{ + return canvas()->palette().brush( + QPalette::Normal, QPalette::Window ); +} + +/*! + \return \c true if the specified axis exists, otherwise \c false + \param axisId axis index + */ +bool QwtPlot::axisValid( int axisId ) +{ + return ( ( axisId >= QwtPlot::yLeft ) && ( axisId < QwtPlot::axisCnt ) ); +} + +/*! + \brief Insert a legend + + If the position legend is \c QwtPlot::LeftLegend or \c QwtPlot::RightLegend + the legend will be organized in one column from top to down. + Otherwise the legend items will be placed in a table + with a best fit number of columns from left to right. + + insertLegend() will set the plot widget as parent for the legend. + The legend will be deleted in the destructor of the plot or when + another legend is inserted. + + Legends, that are not inserted into the layout of the plot widget + need to connect to the legendDataChanged() signal. Calling updateLegend() + initiates this signal for an initial update. When the application code + wants to implement its own layout this also needs to be done for + rendering plots to a document ( see QwtPlotRenderer ). + + \param legend Legend + \param pos The legend's position. For top/left position the number + of columns will be limited to 1, otherwise it will be set to + unlimited. + + \param ratio Ratio between legend and the bounding rectangle + of title, canvas and axes. The legend will be shrunk + if it would need more space than the given ratio. + The ratio is limited to ]0.0 .. 1.0]. In case of <= 0.0 + it will be reset to the default ratio. + The default vertical/horizontal ratio is 0.33/0.5. + + \sa legend(), QwtPlotLayout::legendPosition(), + QwtPlotLayout::setLegendPosition() +*/ +void QwtPlot::insertLegend( QwtAbstractLegend *legend, + QwtPlot::LegendPosition pos, double ratio ) +{ + d_data->layout->setLegendPosition( pos, ratio ); + + if ( legend != d_data->legend ) + { + if ( d_data->legend && d_data->legend->parent() == this ) + delete d_data->legend; + + d_data->legend = legend; + + if ( d_data->legend ) + { + connect( this, + SIGNAL( legendDataChanged( + const QVariant &, const QList & ) ), + d_data->legend, + SLOT( updateLegend( + const QVariant &, const QList & ) ) + ); + + if ( d_data->legend->parent() != this ) + d_data->legend->setParent( this ); + + qwtEnableLegendItems( this, false ); + updateLegend(); + qwtEnableLegendItems( this, true ); + + QwtLegend *lgd = qobject_cast( legend ); + if ( lgd ) + { + switch ( d_data->layout->legendPosition() ) + { + case LeftLegend: + case RightLegend: + { + if ( lgd->maxColumns() == 0 ) + lgd->setMaxColumns( 1 ); // 1 column: align vertical + break; + } + case TopLegend: + case BottomLegend: + { + lgd->setMaxColumns( 0 ); // unlimited + break; + } + default: + break; + } + } + + QWidget *previousInChain = NULL; + switch ( d_data->layout->legendPosition() ) + { + case LeftLegend: + { + previousInChain = axisWidget( QwtPlot::xTop ); + break; + } + case TopLegend: + { + previousInChain = this; + break; + } + case RightLegend: + { + previousInChain = axisWidget( QwtPlot::yRight ); + break; + } + case BottomLegend: + { + previousInChain = footerLabel(); + break; + } + } + + if ( previousInChain ) + qwtSetTabOrder( previousInChain, legend, true ); + } + } + + updateLayout(); +} + +/*! + Emit legendDataChanged() for all plot item + + \sa QwtPlotItem::legendData(), legendDataChanged() + */ +void QwtPlot::updateLegend() +{ + const QwtPlotItemList& itmList = itemList(); + for ( QwtPlotItemIterator it = itmList.begin(); + it != itmList.end(); ++it ) + { + updateLegend( *it ); + } +} + +/*! + Emit legendDataChanged() for a plot item + + \param plotItem Plot item + \sa QwtPlotItem::legendData(), legendDataChanged() + */ +void QwtPlot::updateLegend( const QwtPlotItem *plotItem ) +{ + if ( plotItem == NULL ) + return; + + QList legendData; + + if ( plotItem->testItemAttribute( QwtPlotItem::Legend ) ) + legendData = plotItem->legendData(); + + const QVariant itemInfo = itemToInfo( const_cast< QwtPlotItem *>( plotItem) ); + Q_EMIT legendDataChanged( itemInfo, legendData ); +} + +/*! + \brief Update all plot items interested in legend attributes + + Call QwtPlotItem::updateLegend(), when the QwtPlotItem::LegendInterest + flag is set. + + \param itemInfo Info about the plot item + \param legendData Entries to be displayed for the plot item ( usually 1 ) + + \sa QwtPlotItem::LegendInterest, + QwtPlotLegendItem, QwtPlotItem::updateLegend() + */ +void QwtPlot::updateLegendItems( const QVariant &itemInfo, + const QList &legendData ) +{ + QwtPlotItem *plotItem = infoToItem( itemInfo ); + if ( plotItem ) + { + const QwtPlotItemList& itmList = itemList(); + for ( QwtPlotItemIterator it = itmList.begin(); + it != itmList.end(); ++it ) + { + QwtPlotItem *item = *it; + if ( item->testItemInterest( QwtPlotItem::LegendInterest ) ) + item->updateLegend( plotItem, legendData ); + } + } +} + +/*! + \brief Attach/Detach a plot item + + \param plotItem Plot item + \param on When true attach the item, otherwise detach it + */ +void QwtPlot::attachItem( QwtPlotItem *plotItem, bool on ) +{ + if ( plotItem->testItemInterest( QwtPlotItem::LegendInterest ) ) + { + // plotItem is some sort of legend + + const QwtPlotItemList& itmList = itemList(); + for ( QwtPlotItemIterator it = itmList.begin(); + it != itmList.end(); ++it ) + { + QwtPlotItem *item = *it; + + QList legendData; + if ( on && item->testItemAttribute( QwtPlotItem::Legend ) ) + { + legendData = item->legendData(); + plotItem->updateLegend( item, legendData ); + } + } + } + + if ( on ) + insertItem( plotItem ); + else + removeItem( plotItem ); + + Q_EMIT itemAttached( plotItem, on ); + + if ( plotItem->testItemAttribute( QwtPlotItem::Legend ) ) + { + // the item wants to be represented on the legend + + if ( on ) + { + updateLegend( plotItem ); + } + else + { + const QVariant itemInfo = itemToInfo( plotItem ); + Q_EMIT legendDataChanged( itemInfo, QList() ); + } + } + + autoRefresh(); +} + +/*! + \brief Build an information, that can be used to identify + a plot item on the legend. + + The default implementation simply wraps the plot item + into a QVariant object. When overloading itemToInfo() + usually infoToItem() needs to reimplemeted too. + +\code + QVariant itemInfo; + qVariantSetValue( itemInfo, plotItem ); +\endcode + + \param plotItem Plot item + \return Plot item embedded in a QVariant + \sa infoToItem() + */ +QVariant QwtPlot::itemToInfo( QwtPlotItem *plotItem ) const +{ + QVariant itemInfo; + qVariantSetValue( itemInfo, plotItem ); + + return itemInfo; +} + +/*! + \brief Identify the plot item according to an item info object, + that has bee generated from itemToInfo(). + + The default implementation simply tries to unwrap a QwtPlotItem + pointer: + +\code + if ( itemInfo.canConvert() ) + return qvariant_cast( itemInfo ); +\endcode + \param itemInfo Plot item + \return A plot item, when successful, otherwise a NULL pointer. + \sa itemToInfo() +*/ +QwtPlotItem *QwtPlot::infoToItem( const QVariant &itemInfo ) const +{ + if ( itemInfo.canConvert() ) + return qvariant_cast( itemInfo ); + + return NULL; +} + + diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot.h new file mode 100644 index 0000000..a5d24ef --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot.h @@ -0,0 +1,312 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PLOT_H +#define QWT_PLOT_H + +#include "qwt_global.h" +#include "qwt_text.h" +#include "qwt_plot_dict.h" +#include "qwt_scale_map.h" +#include "qwt_interval.h" +#include +#include +#include + +class QwtPlotLayout; +class QwtAbstractLegend; +class QwtScaleWidget; +class QwtScaleEngine; +class QwtScaleDiv; +class QwtScaleDraw; +class QwtTextLabel; + +/*! + \brief A 2-D plotting widget + + QwtPlot is a widget for plotting two-dimensional graphs. + An unlimited number of plot items can be displayed on + its canvas. Plot items might be curves (QwtPlotCurve), markers + (QwtPlotMarker), the grid (QwtPlotGrid), or anything else derived + from QwtPlotItem. + A plot can have up to four axes, with each plot item attached to an x- and + a y axis. The scales at the axes can be explicitly set (QwtScaleDiv), or + are calculated from the plot items, using algorithms (QwtScaleEngine) which + can be configured separately for each axis. + + The simpleplot example is a good starting point to see how to set up a + plot widget. + + \image html plot.png + + \par Example + The following example shows (schematically) the most simple + way to use QwtPlot. By default, only the left and bottom axes are + visible and their scales are computed automatically. + \verbatim +#include +#include + +QwtPlot *myPlot = new QwtPlot("Two Curves", parent); + +// add curves +QwtPlotCurve *curve1 = new QwtPlotCurve("Curve 1"); +QwtPlotCurve *curve2 = new QwtPlotCurve("Curve 2"); + +// connect or copy the data to the curves +curve1->setData(...); +curve2->setData(...); + +curve1->attach(myPlot); +curve2->attach(myPlot); + +// finally, refresh the plot +myPlot->replot(); +\endverbatim +*/ + +class QWT_EXPORT QwtPlot: public QFrame, public QwtPlotDict +{ + Q_OBJECT + + Q_PROPERTY( QBrush canvasBackground + READ canvasBackground WRITE setCanvasBackground ) + Q_PROPERTY( bool autoReplot READ autoReplot WRITE setAutoReplot ) + +#if 0 + // This property is intended to configure the plot + // widget from a special dialog in the deigner plugin. + // Disabled until such a dialog has been implemented. + + Q_PROPERTY( QString propertiesDocument + READ grabProperties WRITE applyProperties ) +#endif + +public: + //! \brief Axis index + enum Axis + { + //! Y axis left of the canvas + yLeft, + + //! Y axis right of the canvas + yRight, + + //! X axis below the canvas + xBottom, + + //! X axis above the canvas + xTop, + + //! Number of axes + axisCnt + }; + + /*! + Position of the legend, relative to the canvas. + + \sa insertLegend() + */ + enum LegendPosition + { + //! The legend will be left from the QwtPlot::yLeft axis. + LeftLegend, + + //! The legend will be right from the QwtPlot::yRight axis. + RightLegend, + + //! The legend will be below the footer + BottomLegend, + + //! The legend will be above the title + TopLegend + }; + + explicit QwtPlot( QWidget * = NULL ); + explicit QwtPlot( const QwtText &title, QWidget * = NULL ); + + virtual ~QwtPlot(); + + void applyProperties( const QString & ); + QString grabProperties() const; + + void setAutoReplot( bool = true ); + bool autoReplot() const; + + // Layout + + void setPlotLayout( QwtPlotLayout * ); + + QwtPlotLayout *plotLayout(); + const QwtPlotLayout *plotLayout() const; + + // Title + + void setTitle( const QString & ); + void setTitle( const QwtText &t ); + QwtText title() const; + + QwtTextLabel *titleLabel(); + const QwtTextLabel *titleLabel() const; + + // Footer + + void setFooter( const QString & ); + void setFooter( const QwtText &t ); + QwtText footer() const; + + QwtTextLabel *footerLabel(); + const QwtTextLabel *footerLabel() const; + + // Canvas + + void setCanvas( QWidget * ); + + QWidget *canvas(); + const QWidget *canvas() const; + + void setCanvasBackground( const QBrush & ); + QBrush canvasBackground() const; + + virtual QwtScaleMap canvasMap( int axisId ) const; + + double invTransform( int axisId, int pos ) const; + double transform( int axisId, double value ) const; + + // Axes + + QwtScaleEngine *axisScaleEngine( int axisId ); + const QwtScaleEngine *axisScaleEngine( int axisId ) const; + void setAxisScaleEngine( int axisId, QwtScaleEngine * ); + + void setAxisAutoScale( int axisId, bool on = true ); + bool axisAutoScale( int axisId ) const; + + void enableAxis( int axisId, bool tf = true ); + bool axisEnabled( int axisId ) const; + + void setAxisFont( int axisId, const QFont &f ); + QFont axisFont( int axisId ) const; + + void setAxisScale( int axisId, double min, double max, double step = 0 ); + void setAxisScaleDiv( int axisId, const QwtScaleDiv & ); + void setAxisScaleDraw( int axisId, QwtScaleDraw * ); + + double axisStepSize( int axisId ) const; + QwtInterval axisInterval( int axisId ) const; + + const QwtScaleDiv &axisScaleDiv( int axisId ) const; + + const QwtScaleDraw *axisScaleDraw( int axisId ) const; + QwtScaleDraw *axisScaleDraw( int axisId ); + + const QwtScaleWidget *axisWidget( int axisId ) const; + QwtScaleWidget *axisWidget( int axisId ); + + void setAxisLabelAlignment( int axisId, Qt::Alignment ); + void setAxisLabelRotation( int axisId, double rotation ); + + void setAxisTitle( int axisId, const QString & ); + void setAxisTitle( int axisId, const QwtText & ); + QwtText axisTitle( int axisId ) const; + + void setAxisMaxMinor( int axisId, int maxMinor ); + int axisMaxMinor( int axisId ) const; + + void setAxisMaxMajor( int axisId, int maxMajor ); + int axisMaxMajor( int axisId ) const; + + // Legend + + void insertLegend( QwtAbstractLegend *, + LegendPosition = QwtPlot::RightLegend, double ratio = -1.0 ); + + QwtAbstractLegend *legend(); + const QwtAbstractLegend *legend() const; + + void updateLegend(); + void updateLegend( const QwtPlotItem * ); + + // Misc + + virtual QSize sizeHint() const; + virtual QSize minimumSizeHint() const; + + virtual void updateLayout(); + virtual void drawCanvas( QPainter * ); + + void updateAxes(); + void updateCanvasMargins(); + + virtual void getCanvasMarginsHint( + const QwtScaleMap maps[], const QRectF &canvasRect, + double &left, double &top, double &right, double &bottom) const; + + virtual bool event( QEvent * ); + virtual bool eventFilter( QObject *, QEvent * ); + + virtual void drawItems( QPainter *, const QRectF &, + const QwtScaleMap maps[axisCnt] ) const; + + virtual QVariant itemToInfo( QwtPlotItem * ) const; + virtual QwtPlotItem *infoToItem( const QVariant & ) const; + +Q_SIGNALS: + /*! + A signal indicating, that an item has been attached/detached + + \param plotItem Plot item + \param on Attached/Detached + */ + void itemAttached( QwtPlotItem *plotItem, bool on ); + + /*! + A signal with the attributes how to update + the legend entries for a plot item. + + \param itemInfo Info about a plot item, build from itemToInfo() + \param data Attributes of the entries ( usually <= 1 ) for + the plot item. + + \sa itemToInfo(), infoToItem(), QwtAbstractLegend::updateLegend() + */ + void legendDataChanged( const QVariant &itemInfo, + const QList &data ); + +public Q_SLOTS: + virtual void replot(); + void autoRefresh(); + +protected: + static bool axisValid( int axisId ); + + virtual void resizeEvent( QResizeEvent *e ); + +private Q_SLOTS: + void updateLegendItems( const QVariant &itemInfo, + const QList &data ); + +private: + friend class QwtPlotItem; + void attachItem( QwtPlotItem *, bool ); + + void initAxesData(); + void deleteAxesData(); + void updateScaleDiv(); + + void initPlot( const QwtText &title ); + + class AxisData; + AxisData *d_axisData[axisCnt]; + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_abstract_barchart.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_abstract_barchart.cpp new file mode 100644 index 0000000..3296fba --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_abstract_barchart.cpp @@ -0,0 +1,368 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot_abstract_barchart.h" +#include "qwt_scale_map.h" + +static inline double qwtTransformWidth( + const QwtScaleMap &map, double value, double width ) +{ + const double w2 = 0.5 * width; + + const double v1 = map.transform( value - w2 ); + const double v2 = map.transform( value + w2 ); + + return qAbs( v2 - v1 ); +} + +class QwtPlotAbstractBarChart::PrivateData +{ +public: + PrivateData(): + layoutPolicy( QwtPlotAbstractBarChart::AutoAdjustSamples ), + layoutHint( 0.5 ), + spacing( 10 ), + margin( 5 ), + baseline( 0.0 ) + { + } + + QwtPlotAbstractBarChart::LayoutPolicy layoutPolicy; + double layoutHint; + int spacing; + int margin; + double baseline; +}; + +/*! + Constructor + \param title Title of the chart +*/ +QwtPlotAbstractBarChart::QwtPlotAbstractBarChart( const QwtText &title ): + QwtPlotSeriesItem( title ) +{ + d_data = new PrivateData; + + setItemAttribute( QwtPlotItem::Legend, true ); + setItemAttribute( QwtPlotItem::AutoScale, true ); + setItemAttribute( QwtPlotItem::Margins, true ); + setZ( 19.0 ); +} + +//! Destructor +QwtPlotAbstractBarChart::~QwtPlotAbstractBarChart() +{ + delete d_data; +} + +/*! + The combination of layoutPolicy() and layoutHint() define how the width + of the bars is calculated + + \param policy Layout policy + + \sa layoutPolicy(), layoutHint() + */ +void QwtPlotAbstractBarChart::setLayoutPolicy( LayoutPolicy policy ) +{ + if ( policy != d_data->layoutPolicy ) + { + d_data->layoutPolicy = policy; + itemChanged(); + } +} + +/*! + The combination of layoutPolicy() and layoutHint() define how the width + of the bars is calculated + + \return Layout policy of the chart item + \sa setLayoutPolicy(), layoutHint() + */ +QwtPlotAbstractBarChart::LayoutPolicy QwtPlotAbstractBarChart::layoutPolicy() const +{ + return d_data->layoutPolicy; +} + +/*! + The combination of layoutPolicy() and layoutHint() define how the width + of the bars is calculated + + \param hint Layout hint + + \sa LayoutPolicy, layoutPolicy(), layoutHint() + */ +void QwtPlotAbstractBarChart::setLayoutHint( double hint ) +{ + hint = qMax( 0.0, hint ); + if ( hint != d_data->layoutHint ) + { + d_data->layoutHint = hint; + itemChanged(); + } +} + +/*! + The combination of layoutPolicy() and layoutHint() define how the width + of the bars is calculated + + \return Layout policy of the chart item + \sa LayoutPolicy, setLayoutHint(), layoutPolicy() +*/ +double QwtPlotAbstractBarChart::layoutHint() const +{ + return d_data->layoutHint; +} + +/*! + \brief Set the spacing + + The spacing is the distance between 2 samples ( bars for QwtPlotBarChart or + a group of bars for QwtPlotMultiBarChart ) in paint device coordinates. + + \sa spacing() + */ +void QwtPlotAbstractBarChart::setSpacing( int spacing ) +{ + spacing = qMax( spacing, 0 ); + if ( spacing != d_data->spacing ) + { + d_data->spacing = spacing; + itemChanged(); + } +} + +/*! + \return Spacing between 2 samples ( bars or groups of bars ) + \sa setSpacing(), margin() + */ +int QwtPlotAbstractBarChart::spacing() const +{ + return d_data->spacing; +} +/*! + \brief Set the margin + + The margin is the distance between the outmost bars and the contentsRect() + of the canvas. The default setting is 5 pixels. + + \param margin Margin + + \sa spacing(), margin() + */ +void QwtPlotAbstractBarChart::setMargin( int margin ) +{ + margin = qMax( margin, 0 ); + if ( margin != d_data->margin ) + { + d_data->margin = margin; + itemChanged(); + } +} + +/*! + \return Margin between the outmost bars and the contentsRect() + of the canvas. + + \sa setMargin(), spacing() + */ +int QwtPlotAbstractBarChart::margin() const +{ + return d_data->margin; +} + +/*! + \brief Set the baseline + + The baseline is the origin for the chart. Each bar is + painted from the baseline in the direction of the sample + value. In case of a horizontal orientation() the baseline + is interpreted as x - otherwise as y - value. + + The default value for the baseline is 0. + + \param value Value for the baseline + + \sa baseline(), QwtPlotSeriesItem::orientation() +*/ +void QwtPlotAbstractBarChart::setBaseline( double value ) +{ + if ( value != d_data->baseline ) + { + d_data->baseline = value; + itemChanged(); + } +} + +/*! + \return Value for the origin of the bar chart + \sa setBaseline(), QwtPlotSeriesItem::orientation() + */ +double QwtPlotAbstractBarChart::baseline() const +{ + return d_data->baseline; +} + +/*! + Calculate the width for a sample in paint device coordinates + + \param map Scale map for the corresponding scale + \param canvasSize Size of the canvas in paint device coordinates + \param boundingSize Bounding size of the chart in plot coordinates + ( used in AutoAdjustSamples mode ) + \param value Value of the sample + + \return Sample width + \sa layoutPolicy(), layoutHint() +*/ +double QwtPlotAbstractBarChart::sampleWidth( const QwtScaleMap &map, + double canvasSize, double boundingSize, double value ) const +{ + double width; + + switch( d_data->layoutPolicy ) + { + case ScaleSamplesToAxes: + { + width = qwtTransformWidth( map, value, d_data->layoutHint ); + break; + } + case ScaleSampleToCanvas: + { + width = canvasSize * d_data->layoutHint; + break; + } + case FixedSampleSize: + { + width = d_data->layoutHint; + break; + } + case AutoAdjustSamples: + default: + { + const size_t numSamples = dataSize(); + + double w = 1.0; + if ( numSamples > 1 ) + { + w = qAbs( boundingSize / ( numSamples - 1 ) ); + } + + width = qwtTransformWidth( map, value, w ); + width -= d_data->spacing; + width = qMax( width, d_data->layoutHint ); + } + } + + return width; +} + +/*! + \brief Calculate a hint for the canvas margin + + Bar charts need to reserve some space for displaying the bars + for the first and the last sample. The hint is calculated + from the layoutHint() depending on the layoutPolicy(). + + The margins are in target device coordinates ( pixels on screen ) + + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param canvasRect Contents rectangle of the canvas in painter coordinates + \param left Returns the left margin + \param top Returns the top margin + \param right Returns the right margin + \param bottom Returns the bottom margin + + \return Margin + + \sa layoutPolicy(), layoutHint(), QwtPlotItem::Margins + QwtPlot::getCanvasMarginsHint(), QwtPlot::updateCanvasMargins() + */ +void QwtPlotAbstractBarChart::getCanvasMarginHint( const QwtScaleMap &xMap, + const QwtScaleMap &yMap, const QRectF &canvasRect, + double &left, double &top, double &right, double &bottom ) const +{ + double hint = -1.0; + + switch( layoutPolicy() ) + { + case ScaleSampleToCanvas: + { + if ( orientation() == Qt::Vertical ) + hint = 0.5 * canvasRect.width() * d_data->layoutHint; + else + hint = 0.5 * canvasRect.height() * d_data->layoutHint; + + break; + } + case FixedSampleSize: + { + hint = 0.5 * d_data->layoutHint; + break; + } + case AutoAdjustSamples: + case ScaleSamplesToAxes: + default: + { + const size_t numSamples = dataSize(); + if ( numSamples <= 0 ) + break; + + // doesn't work for nonlinear scales + + const QRectF br = dataRect(); + double spacing = 0.0; + double sampleWidthS = 1.0; + + if ( layoutPolicy() == ScaleSamplesToAxes ) + { + sampleWidthS = qMax( d_data->layoutHint, 0.0 ); + } + else + { + spacing = d_data->spacing; + + if ( numSamples > 1 ) + { + sampleWidthS = qAbs( br.width() / ( numSamples - 1 ) ); + } + } + + double ds, w; + if ( orientation() == Qt::Vertical ) + { + ds = qAbs( xMap.sDist() ); + w = canvasRect.width(); + } + else + { + ds = qAbs( yMap.sDist() ); + w = canvasRect.height(); + } + + const double sampleWidthP = ( w - spacing * ( numSamples - 1 ) ) + * sampleWidthS / ( ds + sampleWidthS ); + + hint = 0.5 * sampleWidthP; + hint += qMax( d_data->margin, 0 ); + } + } + + if ( orientation() == Qt::Vertical ) + { + left = right = hint; + top = bottom = -1.0; // no hint + } + else + { + left = right = -1.0; // no hint + top = bottom = hint; + } +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_abstract_barchart.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_abstract_barchart.h new file mode 100644 index 0000000..b948bcd --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_abstract_barchart.h @@ -0,0 +1,97 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PLOT_ABSTRACT_BAR_CHART_H +#define QWT_PLOT_ABSTRACT_BAR_CHART_H + +#include "qwt_global.h" +#include "qwt_plot_seriesitem.h" +#include "qwt_series_data.h" + +/*! + \brief Abstract base class for bar chart items + + In opposite to almost all other plot items bar charts can't be + displayed inside of their bounding rectangle and need a special + API how to calculate the width of the bars and how they affect + the layout of the attached plot. + */ +class QWT_EXPORT QwtPlotAbstractBarChart: public QwtPlotSeriesItem +{ +public: + /*! + \brief Mode how to calculate the bar width + + setLayoutPolicy(), setLayoutHint(), barWidthHint() + */ + enum LayoutPolicy + { + /*! + The sample width is calculated by dividing the bounding rectangle + by the number of samples. The layoutHint() is used as a minimum width + in paint device coordinates. + + \sa boundingRectangle() + */ + AutoAdjustSamples, + + /*! + layoutHint() defines an interval in axis coordinates + */ + ScaleSamplesToAxes, + + /*! + The bar width is calculated by multiplying layoutHint() + with the height or width of the canvas. + + \sa boundingRectangle() + */ + ScaleSampleToCanvas, + + /*! + layoutHint() defines a fixed width in paint device coordinates. + */ + FixedSampleSize + }; + + explicit QwtPlotAbstractBarChart( const QwtText &title ); + virtual ~QwtPlotAbstractBarChart(); + + void setLayoutPolicy( LayoutPolicy ); + LayoutPolicy layoutPolicy() const; + + void setLayoutHint( double ); + double layoutHint() const; + + void setSpacing( int ); + int spacing() const; + + void setMargin( int ); + int margin() const; + + void setBaseline( double ); + double baseline() const; + + virtual void getCanvasMarginHint( + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, + double &left, double &top, double &right, double &bottom) const; + + +protected: + double sampleWidth( const QwtScaleMap &map, + double canvasSize, double dataSize, + double value ) const; + +private: + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_axis.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_axis.cpp new file mode 100644 index 0000000..5cc6c17 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_axis.cpp @@ -0,0 +1,719 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot.h" +#include "qwt_math.h" +#include "qwt_scale_widget.h" +#include "qwt_scale_div.h" +#include "qwt_scale_engine.h" + +class QwtPlot::AxisData +{ +public: + bool isEnabled; + bool doAutoScale; + + double minValue; + double maxValue; + double stepSize; + + int maxMajor; + int maxMinor; + + bool isValid; + + QwtScaleDiv scaleDiv; + QwtScaleEngine *scaleEngine; + QwtScaleWidget *scaleWidget; +}; + +//! Initialize axes +void QwtPlot::initAxesData() +{ + int axisId; + + for ( axisId = 0; axisId < axisCnt; axisId++ ) + d_axisData[axisId] = new AxisData; + + d_axisData[yLeft]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::LeftScale, this ); + d_axisData[yRight]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::RightScale, this ); + d_axisData[xTop]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::TopScale, this ); + d_axisData[xBottom]->scaleWidget = + new QwtScaleWidget( QwtScaleDraw::BottomScale, this ); + + d_axisData[yLeft]->scaleWidget->setObjectName( "QwtPlotAxisYLeft" ); + d_axisData[yRight]->scaleWidget->setObjectName( "QwtPlotAxisYRight" ); + d_axisData[xTop]->scaleWidget->setObjectName( "QwtPlotAxisXTop" ); + d_axisData[xBottom]->scaleWidget->setObjectName( "QwtPlotAxisXBottom" ); + +#if 1 + // better find the font sizes from the application font + QFont fscl( fontInfo().family(), 10 ); + QFont fttl( fontInfo().family(), 12, QFont::Bold ); +#endif + + for ( axisId = 0; axisId < axisCnt; axisId++ ) + { + AxisData &d = *d_axisData[axisId]; + + d.scaleEngine = new QwtLinearScaleEngine; + + d.scaleWidget->setTransformation( + d.scaleEngine->transformation() ); + + d.scaleWidget->setFont( fscl ); + d.scaleWidget->setMargin( 2 ); + + QwtText text = d.scaleWidget->title(); + text.setFont( fttl ); + d.scaleWidget->setTitle( text ); + + d.doAutoScale = true; + + d.minValue = 0.0; + d.maxValue = 1000.0; + d.stepSize = 0.0; + + d.maxMinor = 5; + d.maxMajor = 8; + + + d.isValid = false; + } + + d_axisData[yLeft]->isEnabled = true; + d_axisData[yRight]->isEnabled = false; + d_axisData[xBottom]->isEnabled = true; + d_axisData[xTop]->isEnabled = false; +} + +void QwtPlot::deleteAxesData() +{ + for ( int axisId = 0; axisId < axisCnt; axisId++ ) + { + delete d_axisData[axisId]->scaleEngine; + delete d_axisData[axisId]; + d_axisData[axisId] = NULL; + } +} + +/*! + \return Scale widget of the specified axis, or NULL if axisId is invalid. + \param axisId Axis index +*/ +const QwtScaleWidget *QwtPlot::axisWidget( int axisId ) const +{ + if ( axisValid( axisId ) ) + return d_axisData[axisId]->scaleWidget; + + return NULL; +} + +/*! + \return Scale widget of the specified axis, or NULL if axisId is invalid. + \param axisId Axis index +*/ +QwtScaleWidget *QwtPlot::axisWidget( int axisId ) +{ + if ( axisValid( axisId ) ) + return d_axisData[axisId]->scaleWidget; + + return NULL; +} + +/*! + Change the scale engine for an axis + + \param axisId Axis index + \param scaleEngine Scale engine + + \sa axisScaleEngine() +*/ +void QwtPlot::setAxisScaleEngine( int axisId, QwtScaleEngine *scaleEngine ) +{ + if ( axisValid( axisId ) && scaleEngine != NULL ) + { + AxisData &d = *d_axisData[axisId]; + + delete d.scaleEngine; + d.scaleEngine = scaleEngine; + + d_axisData[axisId]->scaleWidget->setTransformation( + scaleEngine->transformation() ); + + d.isValid = false; + + autoRefresh(); + } +} + +/*! + \param axisId Axis index + \return Scale engine for a specific axis +*/ +QwtScaleEngine *QwtPlot::axisScaleEngine( int axisId ) +{ + if ( axisValid( axisId ) ) + return d_axisData[axisId]->scaleEngine; + else + return NULL; +} + +/*! + \param axisId Axis index + \return Scale engine for a specific axis +*/ +const QwtScaleEngine *QwtPlot::axisScaleEngine( int axisId ) const +{ + if ( axisValid( axisId ) ) + return d_axisData[axisId]->scaleEngine; + else + return NULL; +} +/*! + \return \c True, if autoscaling is enabled + \param axisId Axis index +*/ +bool QwtPlot::axisAutoScale( int axisId ) const +{ + if ( axisValid( axisId ) ) + return d_axisData[axisId]->doAutoScale; + else + return false; + +} + +/*! + \return \c True, if a specified axis is enabled + \param axisId Axis index +*/ +bool QwtPlot::axisEnabled( int axisId ) const +{ + if ( axisValid( axisId ) ) + return d_axisData[axisId]->isEnabled; + else + return false; +} + +/*! + \return The font of the scale labels for a specified axis + \param axisId Axis index +*/ +QFont QwtPlot::axisFont( int axisId ) const +{ + if ( axisValid( axisId ) ) + return axisWidget( axisId )->font(); + else + return QFont(); + +} + +/*! + \return The maximum number of major ticks for a specified axis + \param axisId Axis index + \sa setAxisMaxMajor(), QwtScaleEngine::divideScale() +*/ +int QwtPlot::axisMaxMajor( int axisId ) const +{ + if ( axisValid( axisId ) ) + return d_axisData[axisId]->maxMajor; + else + return 0; +} + +/*! + \return the maximum number of minor ticks for a specified axis + \param axisId Axis index + \sa setAxisMaxMinor(), QwtScaleEngine::divideScale() +*/ +int QwtPlot::axisMaxMinor( int axisId ) const +{ + if ( axisValid( axisId ) ) + return d_axisData[axisId]->maxMinor; + else + return 0; +} + +/*! + \brief Return the scale division of a specified axis + + axisScaleDiv(axisId).lowerBound(), axisScaleDiv(axisId).upperBound() + are the current limits of the axis scale. + + \param axisId Axis index + \return Scale division + + \sa QwtScaleDiv, setAxisScaleDiv(), QwtScaleEngine::divideScale() +*/ +const QwtScaleDiv &QwtPlot::axisScaleDiv( int axisId ) const +{ + return d_axisData[axisId]->scaleDiv; +} + +/*! + \brief Return the scale draw of a specified axis + + \param axisId Axis index + \return Specified scaleDraw for axis, or NULL if axis is invalid. +*/ +const QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId ) const +{ + if ( !axisValid( axisId ) ) + return NULL; + + return axisWidget( axisId )->scaleDraw(); +} + +/*! + \brief Return the scale draw of a specified axis + + \param axisId Axis index + \return Specified scaleDraw for axis, or NULL if axis is invalid. +*/ +QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId ) +{ + if ( !axisValid( axisId ) ) + return NULL; + + return axisWidget( axisId )->scaleDraw(); +} + +/*! + \brief Return the step size parameter that has been set in setAxisScale. + + This doesn't need to be the step size of the current scale. + + \param axisId Axis index + \return step size parameter value + + \sa setAxisScale(), QwtScaleEngine::divideScale() +*/ +double QwtPlot::axisStepSize( int axisId ) const +{ + if ( !axisValid( axisId ) ) + return 0; + + return d_axisData[axisId]->stepSize; +} + +/*! + \brief Return the current interval of the specified axis + + This is only a convenience function for axisScaleDiv( axisId )->interval(); + + \param axisId Axis index + \return Scale interval + + \sa QwtScaleDiv, axisScaleDiv() +*/ +QwtInterval QwtPlot::axisInterval( int axisId ) const +{ + if ( !axisValid( axisId ) ) + return QwtInterval(); + + return d_axisData[axisId]->scaleDiv.interval(); +} + +/*! + \return Title of a specified axis + \param axisId Axis index +*/ +QwtText QwtPlot::axisTitle( int axisId ) const +{ + if ( axisValid( axisId ) ) + return axisWidget( axisId )->title(); + else + return QwtText(); +} + +/*! + \brief Enable or disable a specified axis + + When an axis is disabled, this only means that it is not + visible on the screen. Curves, markers and can be attached + to disabled axes, and transformation of screen coordinates + into values works as normal. + + Only xBottom and yLeft are enabled by default. + + \param axisId Axis index + \param tf \c true (enabled) or \c false (disabled) +*/ +void QwtPlot::enableAxis( int axisId, bool tf ) +{ + if ( axisValid( axisId ) && tf != d_axisData[axisId]->isEnabled ) + { + d_axisData[axisId]->isEnabled = tf; + updateLayout(); + } +} + +/*! + Transform the x or y coordinate of a position in the + drawing region into a value. + + \param axisId Axis index + \param pos position + + \return Position as axis coordinate + + \warning The position can be an x or a y coordinate, + depending on the specified axis. +*/ +double QwtPlot::invTransform( int axisId, int pos ) const +{ + if ( axisValid( axisId ) ) + return( canvasMap( axisId ).invTransform( pos ) ); + else + return 0.0; +} + + +/*! + \brief Transform a value into a coordinate in the plotting region + + \param axisId Axis index + \param value value + \return X or Y coordinate in the plotting region corresponding + to the value. +*/ +double QwtPlot::transform( int axisId, double value ) const +{ + if ( axisValid( axisId ) ) + return( canvasMap( axisId ).transform( value ) ); + else + return 0.0; +} + +/*! + \brief Change the font of an axis + + \param axisId Axis index + \param font Font + \warning This function changes the font of the tick labels, + not of the axis title. +*/ +void QwtPlot::setAxisFont( int axisId, const QFont &font ) +{ + if ( axisValid( axisId ) ) + axisWidget( axisId )->setFont( font ); +} + +/*! + \brief Enable autoscaling for a specified axis + + This member function is used to switch back to autoscaling mode + after a fixed scale has been set. Autoscaling is enabled by default. + + \param axisId Axis index + \param on On/Off + \sa setAxisScale(), setAxisScaleDiv(), updateAxes() + + \note The autoscaling flag has no effect until updateAxes() is executed + ( called by replot() ). +*/ +void QwtPlot::setAxisAutoScale( int axisId, bool on ) +{ + if ( axisValid( axisId ) && ( d_axisData[axisId]->doAutoScale != on ) ) + { + d_axisData[axisId]->doAutoScale = on; + autoRefresh(); + } +} + +/*! + \brief Disable autoscaling and specify a fixed scale for a selected axis. + + In updateAxes() the scale engine calculates a scale division from the + specified parameters, that will be assigned to the scale widget. So + updates of the scale widget usually happen delayed with the next replot. + + \param axisId Axis index + \param min Minimum of the scale + \param max Maximum of the scale + \param stepSize Major step size. If step == 0, the step size is + calculated automatically using the maxMajor setting. + + \sa setAxisMaxMajor(), setAxisAutoScale(), axisStepSize(), QwtScaleEngine::divideScale() +*/ +void QwtPlot::setAxisScale( int axisId, double min, double max, double stepSize ) +{ + if ( axisValid( axisId ) ) + { + AxisData &d = *d_axisData[axisId]; + + d.doAutoScale = false; + d.isValid = false; + + d.minValue = min; + d.maxValue = max; + d.stepSize = stepSize; + + autoRefresh(); + } +} + +/*! + \brief Disable autoscaling and specify a fixed scale for a selected axis. + + The scale division will be stored locally only until the next call + of updateAxes(). So updates of the scale widget usually happen delayed with + the next replot. + + \param axisId Axis index + \param scaleDiv Scale division + + \sa setAxisScale(), setAxisAutoScale() +*/ +void QwtPlot::setAxisScaleDiv( int axisId, const QwtScaleDiv &scaleDiv ) +{ + if ( axisValid( axisId ) ) + { + AxisData &d = *d_axisData[axisId]; + + d.doAutoScale = false; + d.scaleDiv = scaleDiv; + d.isValid = true; + + autoRefresh(); + } +} + +/*! + \brief Set a scale draw + + \param axisId Axis index + \param scaleDraw Object responsible for drawing scales. + + By passing scaleDraw it is possible to extend QwtScaleDraw + functionality and let it take place in QwtPlot. Please note + that scaleDraw has to be created with new and will be deleted + by the corresponding QwtScale member ( like a child object ). + + \sa QwtScaleDraw, QwtScaleWidget + \warning The attributes of scaleDraw will be overwritten by those of the + previous QwtScaleDraw. +*/ + +void QwtPlot::setAxisScaleDraw( int axisId, QwtScaleDraw *scaleDraw ) +{ + if ( axisValid( axisId ) ) + { + axisWidget( axisId )->setScaleDraw( scaleDraw ); + autoRefresh(); + } +} + +/*! + Change the alignment of the tick labels + + \param axisId Axis index + \param alignment Or'd Qt::AlignmentFlags see + + \sa QwtScaleDraw::setLabelAlignment() +*/ +void QwtPlot::setAxisLabelAlignment( int axisId, Qt::Alignment alignment ) +{ + if ( axisValid( axisId ) ) + axisWidget( axisId )->setLabelAlignment( alignment ); +} + +/*! + Rotate all tick labels + + \param axisId Axis index + \param rotation Angle in degrees. When changing the label rotation, + the label alignment might be adjusted too. + + \sa QwtScaleDraw::setLabelRotation(), setAxisLabelAlignment() +*/ +void QwtPlot::setAxisLabelRotation( int axisId, double rotation ) +{ + if ( axisValid( axisId ) ) + axisWidget( axisId )->setLabelRotation( rotation ); +} + +/*! + Set the maximum number of minor scale intervals for a specified axis + + \param axisId Axis index + \param maxMinor Maximum number of minor steps + + \sa axisMaxMinor() +*/ +void QwtPlot::setAxisMaxMinor( int axisId, int maxMinor ) +{ + if ( axisValid( axisId ) ) + { + maxMinor = qBound( 0, maxMinor, 100 ); + + AxisData &d = *d_axisData[axisId]; + if ( maxMinor != d.maxMinor ) + { + d.maxMinor = maxMinor; + d.isValid = false; + autoRefresh(); + } + } +} + +/*! + Set the maximum number of major scale intervals for a specified axis + + \param axisId Axis index + \param maxMajor Maximum number of major steps + + \sa axisMaxMajor() +*/ +void QwtPlot::setAxisMaxMajor( int axisId, int maxMajor ) +{ + if ( axisValid( axisId ) ) + { + maxMajor = qBound( 1, maxMajor, 10000 ); + + AxisData &d = *d_axisData[axisId]; + if ( maxMajor != d.maxMajor ) + { + d.maxMajor = maxMajor; + d.isValid = false; + autoRefresh(); + } + } +} + +/*! + \brief Change the title of a specified axis + + \param axisId Axis index + \param title axis title +*/ +void QwtPlot::setAxisTitle( int axisId, const QString &title ) +{ + if ( axisValid( axisId ) ) + axisWidget( axisId )->setTitle( title ); +} + +/*! + \brief Change the title of a specified axis + + \param axisId Axis index + \param title Axis title +*/ +void QwtPlot::setAxisTitle( int axisId, const QwtText &title ) +{ + if ( axisValid( axisId ) ) + axisWidget( axisId )->setTitle( title ); +} + +/*! + \brief Rebuild the axes scales + + In case of autoscaling the boundaries of a scale are calculated + from the bounding rectangles of all plot items, having the + QwtPlotItem::AutoScale flag enabled ( QwtScaleEngine::autoScale() ). + Then a scale division is calculated ( QwtScaleEngine::didvideScale() ) + and assigned to scale widget. + + When the scale boundaries have been assigned with setAxisScale() a + scale division is calculated ( QwtScaleEngine::didvideScale() ) + for this interval and assigned to the scale widget. + + When the scale has been set explicitly by setAxisScaleDiv() the + locally stored scale division gets assigned to the scale widget. + + The scale widget indicates modifications by emitting a + QwtScaleWidget::scaleDivChanged() signal. + + updateAxes() is usually called by replot(). + + \sa setAxisAutoScale(), setAxisScale(), setAxisScaleDiv(), replot() + QwtPlotItem::boundingRect() + */ +void QwtPlot::updateAxes() +{ + // Find bounding interval of the item data + // for all axes, where autoscaling is enabled + + QwtInterval intv[axisCnt]; + + const QwtPlotItemList& itmList = itemList(); + + QwtPlotItemIterator it; + for ( it = itmList.begin(); it != itmList.end(); ++it ) + { + const QwtPlotItem *item = *it; + + if ( !item->testItemAttribute( QwtPlotItem::AutoScale ) ) + continue; + + if ( !item->isVisible() ) + continue; + + if ( axisAutoScale( item->xAxis() ) || axisAutoScale( item->yAxis() ) ) + { + const QRectF rect = item->boundingRect(); + + if ( rect.width() >= 0.0 ) + intv[item->xAxis()] |= QwtInterval( rect.left(), rect.right() ); + + if ( rect.height() >= 0.0 ) + intv[item->yAxis()] |= QwtInterval( rect.top(), rect.bottom() ); + } + } + + // Adjust scales + + for ( int axisId = 0; axisId < axisCnt; axisId++ ) + { + AxisData &d = *d_axisData[axisId]; + + double minValue = d.minValue; + double maxValue = d.maxValue; + double stepSize = d.stepSize; + + if ( d.doAutoScale && intv[axisId].isValid() ) + { + d.isValid = false; + + minValue = intv[axisId].minValue(); + maxValue = intv[axisId].maxValue(); + + d.scaleEngine->autoScale( d.maxMajor, + minValue, maxValue, stepSize ); + } + if ( !d.isValid ) + { + d.scaleDiv = d.scaleEngine->divideScale( + minValue, maxValue, + d.maxMajor, d.maxMinor, stepSize ); + d.isValid = true; + } + + QwtScaleWidget *scaleWidget = axisWidget( axisId ); + scaleWidget->setScaleDiv( d.scaleDiv ); + + int startDist, endDist; + scaleWidget->getBorderDistHint( startDist, endDist ); + scaleWidget->setBorderDist( startDist, endDist ); + } + + for ( it = itmList.begin(); it != itmList.end(); ++it ) + { + QwtPlotItem *item = *it; + if ( item->testItemInterest( QwtPlotItem::ScaleInterest ) ) + { + item->updateScaleDiv( axisScaleDiv( item->xAxis() ), + axisScaleDiv( item->yAxis() ) ); + } + } +} + diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_barchart.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_barchart.cpp new file mode 100644 index 0000000..97abc50 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_barchart.cpp @@ -0,0 +1,459 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot_barchart.h" +#include "qwt_scale_map.h" +#include "qwt_column_symbol.h" +#include "qwt_painter.h" +#include + +class QwtPlotBarChart::PrivateData +{ +public: + PrivateData(): + symbol( NULL ), + legendMode( QwtPlotBarChart::LegendChartTitle ) + { + } + + ~PrivateData() + { + delete symbol; + } + + QwtColumnSymbol *symbol; + QwtPlotBarChart::LegendMode legendMode; +}; + +/*! + Constructor + \param title Title of the curve +*/ +QwtPlotBarChart::QwtPlotBarChart( const QwtText &title ): + QwtPlotAbstractBarChart( title ) +{ + init(); +} + +/*! + Constructor + \param title Title of the curve +*/ +QwtPlotBarChart::QwtPlotBarChart( const QString &title ): + QwtPlotAbstractBarChart( QwtText( title ) ) +{ + init(); +} + +//! Destructor +QwtPlotBarChart::~QwtPlotBarChart() +{ + delete d_data; +} + +void QwtPlotBarChart::init() +{ + d_data = new PrivateData; + setData( new QwtPointSeriesData() ); +} + +//! \return QwtPlotItem::Rtti_PlotBarChart +int QwtPlotBarChart::rtti() const +{ + return QwtPlotItem::Rtti_PlotBarChart; +} + +/*! + Initialize data with an array of points + + \param samples Vector of points + \note QVector is implicitly shared + \note QPolygonF is derived from QVector +*/ +void QwtPlotBarChart::setSamples( + const QVector &samples ) +{ + setData( new QwtPointSeriesData( samples ) ); +} + +/*! + Initialize data with an array of doubles + + The indices in the array are taken as x coordinate, + while the doubles are interpreted as y values. + + \param samples Vector of y coordinates + \note QVector is implicitly shared +*/ +void QwtPlotBarChart::setSamples( + const QVector &samples ) +{ + QVector points; + for ( int i = 0; i < samples.size(); i++ ) + points += QPointF( i, samples[ i ] ); + + setData( new QwtPointSeriesData( points ) ); +} + +/*! + Assign a series of samples + + setSamples() is just a wrapper for setData() without any additional + value - beside that it is easier to find for the developer. + + \param data Data + \warning The item takes ownership of the data object, deleting + it when its not used anymore. +*/ +void QwtPlotBarChart::setSamples( QwtSeriesData *data ) +{ + setData( data ); +} + +/*! + \brief Assign a symbol + + The bar chart will take the ownership of the symbol, hence the previously + set symbol will be delete by setting a new one. If \p symbol is + \c NULL no symbol will be drawn. + + \param symbol Symbol + \sa symbol() +*/ +void QwtPlotBarChart::setSymbol( QwtColumnSymbol *symbol ) +{ + if ( symbol != d_data->symbol ) + { + delete d_data->symbol; + d_data->symbol = symbol; + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Current symbol or NULL, when no symbol has been assigned + \sa setSymbol() +*/ +const QwtColumnSymbol *QwtPlotBarChart::symbol() const +{ + return d_data->symbol; +} + +/*! + Set the mode that decides what to display on the legend + + In case of LegendBarTitles barTitle() needs to be overloaded + to return individual titles for each bar. + + \param mode New mode + \sa legendMode(), legendData(), barTitle(), QwtPlotItem::ItemAttribute + */ +void QwtPlotBarChart::setLegendMode( LegendMode mode ) +{ + if ( mode != d_data->legendMode ) + { + d_data->legendMode = mode; + legendChanged(); + } +} + +/*! + \return Legend mode + \sa setLegendMode() + */ +QwtPlotBarChart::LegendMode QwtPlotBarChart::legendMode() const +{ + return d_data->legendMode; +} + +/*! + \return Bounding rectangle of all samples. + For an empty series the rectangle is invalid. +*/ +QRectF QwtPlotBarChart::boundingRect() const +{ + const size_t numSamples = dataSize(); + if ( numSamples == 0 ) + return QwtPlotSeriesItem::boundingRect(); + + QRectF rect = QwtPlotSeriesItem::boundingRect(); + if ( rect.height() >= 0 ) + { + const double baseLine = baseline(); + + if ( rect.bottom() < baseLine ) + rect.setBottom( baseLine ); + + if ( rect.top() > baseLine ) + rect.setTop( baseLine ); + } + + if ( orientation() == Qt::Horizontal ) + rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() ); + + return rect; +} + +/*! + Draw an interval of the bar chart + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param canvasRect Contents rect of the canvas + \param from Index of the first point to be painted + \param to Index of the last point to be painted. If to < 0 the + curve will be painted to its last point. + + \sa drawSymbols() +*/ +void QwtPlotBarChart::drawSeries( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + if ( to < 0 ) + to = dataSize() - 1; + + if ( from < 0 ) + from = 0; + + if ( from > to ) + return; + + + const QRectF br = data()->boundingRect(); + const QwtInterval interval( br.left(), br.right() ); + + painter->save(); + + for ( int i = from; i <= to; i++ ) + { + drawSample( painter, xMap, yMap, + canvasRect, interval, i, sample( i ) ); + } + + painter->restore(); +} + +/*! + Draw a sample + + \param painter Painter + \param xMap x map + \param yMap y map + \param canvasRect Contents rect of the canvas + \param boundingInterval Bounding interval of sample values + \param index Index of the sample + \param sample Value of the sample + + \sa drawSeries() +*/ +void QwtPlotBarChart::drawSample( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, const QwtInterval &boundingInterval, + int index, const QPointF &sample ) const +{ + QwtColumnRect barRect; + + if ( orientation() == Qt::Horizontal ) + { + const double barHeight = sampleWidth( yMap, canvasRect.height(), + boundingInterval.width(), sample.y() ); + + const double x1 = xMap.transform( baseline() ); + const double x2 = xMap.transform( sample.y() ); + + const double y = yMap.transform( sample.x() ); + const double y1 = y - 0.5 * barHeight; + const double y2 = y + 0.5 * barHeight; + + barRect.direction = ( x1 < x2 ) ? + QwtColumnRect::LeftToRight : QwtColumnRect::RightToLeft; + + barRect.hInterval = QwtInterval( x1, x2 ).normalized(); + barRect.vInterval = QwtInterval( y1, y2 ); + } + else + { + const double barWidth = sampleWidth( xMap, canvasRect.width(), + boundingInterval.width(), sample.y() ); + + const double x = xMap.transform( sample.x() ); + const double x1 = x - 0.5 * barWidth; + const double x2 = x + 0.5 * barWidth; + + const double y1 = yMap.transform( baseline() ); + const double y2 = yMap.transform( sample.y() ); + + barRect.direction = ( y1 < y2 ) ? + QwtColumnRect::TopToBottom : QwtColumnRect::BottomToTop; + + barRect.hInterval = QwtInterval( x1, x2 ); + barRect.vInterval = QwtInterval( y1, y2 ).normalized(); + } + + drawBar( painter, index, sample, barRect ); +} + +/*! + Draw a bar + + \param painter Painter + \param sampleIndex Index of the sample represented by the bar + \param sample Value of the sample + \param rect Bounding rectangle of the bar + */ +void QwtPlotBarChart::drawBar( QPainter *painter, + int sampleIndex, const QPointF &sample, + const QwtColumnRect &rect ) const +{ + const QwtColumnSymbol *specialSym = + specialSymbol( sampleIndex, sample ); + + const QwtColumnSymbol *sym = specialSym; + if ( sym == NULL ) + sym = d_data->symbol; + + if ( sym ) + { + sym->draw( painter, rect ); + } + else + { + // we build a temporary default symbol + QwtColumnSymbol sym( QwtColumnSymbol::Box ); + sym.setLineWidth( 1 ); + sym.setFrameStyle( QwtColumnSymbol::Plain ); + sym.draw( painter, rect ); + } + + delete specialSym; +} + +/*! + Needs to be overloaded to return a + non default symbol for a specific sample + + \param sampleIndex Index of the sample represented by the bar + \param sample Value of the sample + + \return NULL, indicating to use the default symbol + */ +QwtColumnSymbol *QwtPlotBarChart::specialSymbol( + int sampleIndex, const QPointF &sample ) const +{ + Q_UNUSED( sampleIndex ); + Q_UNUSED( sample ); + + return NULL; +} + +/*! + \brief Return the title of a bar + + In LegendBarTitles mode the title is displayed on + the legend entry corresponding to a bar. + + The default implementation is a dummy, that is intended + to be overloaded. + + \param sampleIndex Index of the bar + \return An empty text + \sa LegendBarTitles + */ +QwtText QwtPlotBarChart::barTitle( int sampleIndex ) const +{ + Q_UNUSED( sampleIndex ); + return QwtText(); +} + +/*! + \brief Return all information, that is needed to represent + the item on the legend + + In case of LegendBarTitles an entry for each bar is returned, + otherwise the chart is represented like any other plot item + from its title() and the legendIcon(). + + \return Information, that is needed to represent the item on the legend + \sa title(), setLegendMode(), barTitle(), QwtLegend, QwtPlotLegendItem + */ +QList QwtPlotBarChart::legendData() const +{ + QList list; + + if ( d_data->legendMode == LegendBarTitles ) + { + const size_t numSamples = dataSize(); + for ( size_t i = 0; i < numSamples; i++ ) + { + QwtLegendData data; + + QVariant titleValue; + qVariantSetValue( titleValue, barTitle( i ) ); + data.setValue( QwtLegendData::TitleRole, titleValue ); + + if ( !legendIconSize().isEmpty() ) + { + QVariant iconValue; + qVariantSetValue( iconValue, + legendIcon( i, legendIconSize() ) ); + + data.setValue( QwtLegendData::IconRole, iconValue ); + } + + list += data; + } + } + else + { + return QwtPlotAbstractBarChart::legendData(); + } + + return list; +} + +/*! + \return Icon representing a bar or the chart on the legend + + When the legendMode() is LegendBarTitles the icon shows + the bar corresponding to index - otherwise the bar + displays the default symbol. + + \param index Index of the legend entry + \param size Icon size + + \sa setLegendMode(), drawBar(), + QwtPlotItem::setLegendIconSize(), QwtPlotItem::legendData() + */ +QwtGraphic QwtPlotBarChart::legendIcon( + int index, const QSizeF &size ) const +{ + QwtColumnRect column; + column.hInterval = QwtInterval( 0.0, size.width() - 1.0 ); + column.vInterval = QwtInterval( 0.0, size.height() - 1.0 ); + + QwtGraphic icon; + icon.setDefaultSize( size ); + icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true ); + + QPainter painter( &icon ); + painter.setRenderHint( QPainter::Antialiasing, + testRenderHint( QwtPlotItem::RenderAntialiased ) ); + + int barIndex = -1; + if ( d_data->legendMode == QwtPlotBarChart::LegendBarTitles ) + barIndex = index; + + drawBar( &painter, barIndex, QPointF(), column ); + + return icon; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_barchart.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_barchart.h new file mode 100644 index 0000000..f5cd9b2 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_barchart.h @@ -0,0 +1,118 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PLOT_BAR_CHART_H +#define QWT_PLOT_BAR_CHART_H + +#include "qwt_global.h" +#include "qwt_plot_abstract_barchart.h" +#include "qwt_series_data.h" + +class QwtColumnRect; +class QwtColumnSymbol; + +/*! + \brief QwtPlotBarChart displays a series of a values as bars. + + Each bar might be customized individually by implementing + a specialSymbol(). Otherwise it is rendered using a default symbol. + + Depending on its orientation() the bars are displayed horizontally + or vertically. The bars cover the interval between the baseline() + and the value. + + By activating the LegendBarTitles mode each sample will have + its own entry on the legend. + + The most common use case of a bar chart is to display a + list of y coordinates, where the x coordinate is simply the index + in the list. But for other situations ( f.e. when values are related + to dates ) it is also possible to set x coordinates explicitly. + + \sa QwtPlotMultiBarChart, QwtPlotHistogram, QwtPlotCurve::Sticks, + QwtPlotSeriesItem::orientation(), QwtPlotAbstractBarChart::baseline() + */ +class QWT_EXPORT QwtPlotBarChart: + public QwtPlotAbstractBarChart, public QwtSeriesStore +{ +public: + /*! + \brief Legend modes. + + The default setting is QwtPlotBarChart::LegendChartTitle. + \sa setLegendMode(), legendMode() + */ + enum LegendMode + { + /*! + One entry on the legend showing the default symbol + and the title() of the chart + + \sa QwtPlotItem::title() + */ + LegendChartTitle, + + /*! + One entry for each value showing the individual symbol + of the corresponding bar and the bar title. + + \sa specialSymbol(), barTitle() + */ + LegendBarTitles + }; + + explicit QwtPlotBarChart( const QString &title = QString::null ); + explicit QwtPlotBarChart( const QwtText &title ); + + virtual ~QwtPlotBarChart(); + + virtual int rtti() const; + + void setSamples( const QVector & ); + void setSamples( const QVector & ); + void setSamples( QwtSeriesData *series ); + + void setSymbol( QwtColumnSymbol * ); + const QwtColumnSymbol *symbol() const; + + void setLegendMode( LegendMode ); + LegendMode legendMode() const; + + virtual void drawSeries( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual QRectF boundingRect() const; + + virtual QwtColumnSymbol *specialSymbol( + int sampleIndex, const QPointF& ) const; + + virtual QwtText barTitle( int sampleIndex ) const; + +protected: + virtual void drawSample( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, const QwtInterval &boundingInterval, + int index, const QPointF& sample ) const; + + virtual void drawBar( QPainter *, + int sampleIndex, const QPointF& point, + const QwtColumnRect & ) const; + + QList legendData() const; + QwtGraphic legendIcon( int index, const QSizeF & ) const; + +private: + void init(); + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_canvas.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_canvas.cpp new file mode 100644 index 0000000..660ef14 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_canvas.cpp @@ -0,0 +1,1101 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot_canvas.h" +#include "qwt_painter.h" +#include "qwt_null_paintdevice.h" +#include "qwt_math.h" +#include "qwt_plot.h" +#include +#include +#include +#include +#include + +class QwtStyleSheetRecorder: public QwtNullPaintDevice +{ +public: + QwtStyleSheetRecorder( const QSize &size ): + d_size( size ) + { + } + + virtual void updateState( const QPaintEngineState &state ) + { + if ( state.state() & QPaintEngine::DirtyPen ) + { + d_pen = state.pen(); + } + if ( state.state() & QPaintEngine::DirtyBrush ) + { + d_brush = state.brush(); + } + if ( state.state() & QPaintEngine::DirtyBrushOrigin ) + { + d_origin = state.brushOrigin(); + } + } + + virtual void drawRects(const QRectF *rects, int count ) + { + for ( int i = 0; i < count; i++ ) + border.rectList += rects[i]; + } + + virtual void drawPath( const QPainterPath &path ) + { + const QRectF rect( QPointF( 0.0, 0.0 ), d_size ); + if ( path.controlPointRect().contains( rect.center() ) ) + { + setCornerRects( path ); + alignCornerRects( rect ); + + background.path = path; + background.brush = d_brush; + background.origin = d_origin; + } + else + { + border.pathList += path; + } + } + + void setCornerRects( const QPainterPath &path ) + { + QPointF pos( 0.0, 0.0 ); + + for ( int i = 0; i < path.elementCount(); i++ ) + { + QPainterPath::Element el = path.elementAt(i); + switch( el.type ) + { + case QPainterPath::MoveToElement: + case QPainterPath::LineToElement: + { + pos.setX( el.x ); + pos.setY( el.y ); + break; + } + case QPainterPath::CurveToElement: + { + QRectF r( pos, QPointF( el.x, el.y ) ); + clipRects += r.normalized(); + + pos.setX( el.x ); + pos.setY( el.y ); + + break; + } + case QPainterPath::CurveToDataElement: + { + if ( clipRects.size() > 0 ) + { + QRectF r = clipRects.last(); + r.setCoords( + qMin( r.left(), el.x ), + qMin( r.top(), el.y ), + qMax( r.right(), el.x ), + qMax( r.bottom(), el.y ) + ); + clipRects.last() = r.normalized(); + } + break; + } + } + } + } + +protected: + virtual QSize sizeMetrics() const + { + return d_size; + } + +private: + void alignCornerRects( const QRectF &rect ) + { + for ( int i = 0; i < clipRects.size(); i++ ) + { + QRectF &r = clipRects[i]; + if ( r.center().x() < rect.center().x() ) + r.setLeft( rect.left() ); + else + r.setRight( rect.right() ); + + if ( r.center().y() < rect.center().y() ) + r.setTop( rect.top() ); + else + r.setBottom( rect.bottom() ); + } + } + + +public: + QVector clipRects; + + struct Border + { + QList pathList; + QList rectList; + QRegion clipRegion; + } border; + + struct Background + { + QPainterPath path; + QBrush brush; + QPointF origin; + } background; + +private: + const QSize d_size; + + QPen d_pen; + QBrush d_brush; + QPointF d_origin; +}; + +static void qwtDrawBackground( QPainter *painter, QwtPlotCanvas *canvas ) +{ + painter->save(); + + const QPainterPath borderClip = canvas->borderPath( canvas->rect() ); + if ( !borderClip.isEmpty() ) + painter->setClipPath( borderClip, Qt::IntersectClip ); + + const QBrush &brush = + canvas->palette().brush( canvas->backgroundRole() ); + + if ( brush.style() == Qt::TexturePattern ) + { + QPixmap pm( canvas->size() ); + QwtPainter::fillPixmap( canvas, pm ); + painter->drawPixmap( 0, 0, pm ); + } + else if ( brush.gradient() ) + { + QVector rects; + + if ( brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode ) + { + rects += canvas->rect(); + } + else + { + rects = painter->clipRegion().rects(); + } + +#if 1 + bool useRaster = false; + + if ( painter->paintEngine()->type() == QPaintEngine::X11 ) + { + // Qt 4.7.1: gradients on X11 are broken ( subrects + + // QGradient::StretchToDeviceMode ) and horrible slow. + // As workaround we have to use the raster paintengine. + // Even if the QImage -> QPixmap translation is slow + // it is three times faster, than using X11 directly + + useRaster = true; + } +#endif + if ( useRaster ) + { + QImage::Format format = QImage::Format_RGB32; + + const QGradientStops stops = brush.gradient()->stops(); + for ( int i = 0; i < stops.size(); i++ ) + { + if ( stops[i].second.alpha() != 255 ) + { + // don't use Format_ARGB32_Premultiplied. It's + // recommended by the Qt docs, but QPainter::drawImage() + // is horrible slow on X11. + + format = QImage::Format_ARGB32; + break; + } + } + + QImage image( canvas->size(), format ); + + QPainter p( &image ); + p.setPen( Qt::NoPen ); + p.setBrush( brush ); + + p.drawRects( rects ); + + p.end(); + + painter->drawImage( 0, 0, image ); + } + else + { + painter->setPen( Qt::NoPen ); + painter->setBrush( brush ); + + painter->drawRects( rects ); + } + } + else + { + painter->setPen( Qt::NoPen ); + painter->setBrush( brush ); + + painter->drawRects( painter->clipRegion().rects() ); + + } + + painter->restore(); +} + +static inline void qwtRevertPath( QPainterPath &path ) +{ + if ( path.elementCount() == 4 ) + { + QPainterPath::Element el0 = path.elementAt(0); + QPainterPath::Element el3 = path.elementAt(3); + + path.setElementPositionAt( 0, el3.x, el3.y ); + path.setElementPositionAt( 3, el0.x, el0.y ); + } +} + +static QPainterPath qwtCombinePathList( const QRectF &rect, + const QList &pathList ) +{ + if ( pathList.isEmpty() ) + return QPainterPath(); + + QPainterPath ordered[8]; // starting top left + + for ( int i = 0; i < pathList.size(); i++ ) + { + int index = -1; + QPainterPath subPath = pathList[i]; + + const QRectF br = pathList[i].controlPointRect(); + if ( br.center().x() < rect.center().x() ) + { + if ( br.center().y() < rect.center().y() ) + { + if ( qAbs( br.top() - rect.top() ) < + qAbs( br.left() - rect.left() ) ) + { + index = 1; + } + else + { + index = 0; + } + } + else + { + if ( qAbs( br.bottom() - rect.bottom() ) < + qAbs( br.left() - rect.left() ) ) + { + index = 6; + } + else + { + index = 7; + } + } + + if ( subPath.currentPosition().y() > br.center().y() ) + qwtRevertPath( subPath ); + } + else + { + if ( br.center().y() < rect.center().y() ) + { + if ( qAbs( br.top() - rect.top() ) < + qAbs( br.right() - rect.right() ) ) + { + index = 2; + } + else + { + index = 3; + } + } + else + { + if ( qAbs( br.bottom() - rect.bottom() ) < + qAbs( br.right() - rect.right() ) ) + { + index = 5; + } + else + { + index = 4; + } + } + if ( subPath.currentPosition().y() < br.center().y() ) + qwtRevertPath( subPath ); + } + ordered[index] = subPath; + } + + for ( int i = 0; i < 4; i++ ) + { + if ( ordered[ 2 * i].isEmpty() != ordered[2 * i + 1].isEmpty() ) + { + // we don't accept incomplete rounded borders + return QPainterPath(); + } + } + + + const QPolygonF corners( rect ); + + QPainterPath path; + //path.moveTo( rect.topLeft() ); + + for ( int i = 0; i < 4; i++ ) + { + if ( ordered[2 * i].isEmpty() ) + { + path.lineTo( corners[i] ); + } + else + { + path.connectPath( ordered[2 * i] ); + path.connectPath( ordered[2 * i + 1] ); + } + } + + path.closeSubpath(); + +#if 0 + return path.simplified(); +#else + return path; +#endif +} + +static inline void qwtDrawStyledBackground( + QWidget *w, QPainter *painter ) +{ + QStyleOption opt; + opt.initFrom(w); + w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w); +} + +static QWidget *qwtBackgroundWidget( QWidget *w ) +{ + if ( w->parentWidget() == NULL ) + return w; + + if ( w->autoFillBackground() ) + { + const QBrush brush = w->palette().brush( w->backgroundRole() ); + if ( brush.color().alpha() > 0 ) + return w; + } + + if ( w->testAttribute( Qt::WA_StyledBackground ) ) + { + QImage image( 1, 1, QImage::Format_ARGB32 ); + image.fill( Qt::transparent ); + + QPainter painter( &image ); + painter.translate( -w->rect().center() ); + qwtDrawStyledBackground( w, &painter ); + painter.end(); + + if ( qAlpha( image.pixel( 0, 0 ) ) != 0 ) + return w; + } + + return qwtBackgroundWidget( w->parentWidget() ); +} + +static void qwtFillBackground( QPainter *painter, + QWidget *widget, const QVector &fillRects ) +{ + if ( fillRects.isEmpty() ) + return; + + QRegion clipRegion; + if ( painter->hasClipping() ) + clipRegion = painter->transform().map( painter->clipRegion() ); + else + clipRegion = widget->contentsRect(); + + // Try to find out which widget fills + // the unfilled areas of the styled background + + QWidget *bgWidget = qwtBackgroundWidget( widget->parentWidget() ); + + for ( int i = 0; i < fillRects.size(); i++ ) + { + const QRect rect = fillRects[i].toAlignedRect(); + if ( clipRegion.intersects( rect ) ) + { + QPixmap pm( rect.size() ); + QwtPainter::fillPixmap( bgWidget, pm, widget->mapTo( bgWidget, rect.topLeft() ) ); + painter->drawPixmap( rect, pm ); + } + } +} + +static void qwtFillBackground( QPainter *painter, QwtPlotCanvas *canvas ) +{ + QVector rects; + + if ( canvas->testAttribute( Qt::WA_StyledBackground ) ) + { + QwtStyleSheetRecorder recorder( canvas->size() ); + + QPainter p( &recorder ); + qwtDrawStyledBackground( canvas, &p ); + p.end(); + + if ( recorder.background.brush.isOpaque() ) + rects = recorder.clipRects; + else + rects += canvas->rect(); + } + else + { + const QRectF r = canvas->rect(); + const double radius = canvas->borderRadius(); + if ( radius > 0.0 ) + { + QSizeF sz( radius, radius ); + + rects += QRectF( r.topLeft(), sz ); + rects += QRectF( r.topRight() - QPointF( radius, 0 ), sz ); + rects += QRectF( r.bottomRight() - QPointF( radius, radius ), sz ); + rects += QRectF( r.bottomLeft() - QPointF( 0, radius ), sz ); + } + } + + qwtFillBackground( painter, canvas, rects); +} + + +class QwtPlotCanvas::PrivateData +{ +public: + PrivateData(): + focusIndicator( NoFocusIndicator ), + borderRadius( 0 ), + paintAttributes( 0 ), + backingStore( NULL ) + { + styleSheet.hasBorder = false; + } + + ~PrivateData() + { + delete backingStore; + } + + FocusIndicator focusIndicator; + double borderRadius; + QwtPlotCanvas::PaintAttributes paintAttributes; + QPixmap *backingStore; + + struct StyleSheet + { + bool hasBorder; + QPainterPath borderPath; + QVector cornerRects; + + struct StyleSheetBackground + { + QBrush brush; + QPointF origin; + } background; + + } styleSheet; + +}; + +/*! + \brief Constructor + + \param plot Parent plot widget + \sa QwtPlot::setCanvas() +*/ +QwtPlotCanvas::QwtPlotCanvas( QwtPlot *plot ): + QFrame( plot ) +{ + setFrameStyle( QFrame::Panel | QFrame::Sunken ); + setLineWidth( 2 ); + + d_data = new PrivateData; + +#ifndef QT_NO_CURSOR + setCursor( Qt::CrossCursor ); +#endif + + setAutoFillBackground( true ); + setPaintAttribute( QwtPlotCanvas::BackingStore, true ); + setPaintAttribute( QwtPlotCanvas::Opaque, true ); + setPaintAttribute( QwtPlotCanvas::HackStyledBackground, true ); +} + +//! Destructor +QwtPlotCanvas::~QwtPlotCanvas() +{ + delete d_data; +} + +//! Return parent plot widget +QwtPlot *QwtPlotCanvas::plot() +{ + return qobject_cast( parent() ); +} + +//! Return parent plot widget +const QwtPlot *QwtPlotCanvas::plot() const +{ + return qobject_cast( parent() ); +} + +/*! + \brief Changing the paint attributes + + \param attribute Paint attribute + \param on On/Off + + \sa testPaintAttribute(), backingStore() +*/ +void QwtPlotCanvas::setPaintAttribute( PaintAttribute attribute, bool on ) +{ + if ( bool( d_data->paintAttributes & attribute ) == on ) + return; + + if ( on ) + d_data->paintAttributes |= attribute; + else + d_data->paintAttributes &= ~attribute; + + switch ( attribute ) + { + case BackingStore: + { + if ( on ) + { + if ( d_data->backingStore == NULL ) + d_data->backingStore = new QPixmap(); + + if ( isVisible() ) + { +#if QT_VERSION >= 0x050000 + *d_data->backingStore = grab( rect() ); +#else + *d_data->backingStore = + QPixmap::grabWidget( this, rect() ); +#endif + } + } + else + { + delete d_data->backingStore; + d_data->backingStore = NULL; + } + break; + } + case Opaque: + { + if ( on ) + setAttribute( Qt::WA_OpaquePaintEvent, true ); + + break; + } + case HackStyledBackground: + case ImmediatePaint: + { + break; + } + } +} + +/*! + Test whether a paint attribute is enabled + + \param attribute Paint attribute + \return true, when attribute is enabled + \sa setPaintAttribute() +*/ +bool QwtPlotCanvas::testPaintAttribute( PaintAttribute attribute ) const +{ + return d_data->paintAttributes & attribute; +} + +//! \return Backing store, might be null +const QPixmap *QwtPlotCanvas::backingStore() const +{ + return d_data->backingStore; +} + +//! Invalidate the internal backing store +void QwtPlotCanvas::invalidateBackingStore() +{ + if ( d_data->backingStore ) + *d_data->backingStore = QPixmap(); +} + +/*! + Set the focus indicator + + \sa FocusIndicator, focusIndicator() +*/ +void QwtPlotCanvas::setFocusIndicator( FocusIndicator focusIndicator ) +{ + d_data->focusIndicator = focusIndicator; +} + +/*! + \return Focus indicator + + \sa FocusIndicator, setFocusIndicator() +*/ +QwtPlotCanvas::FocusIndicator QwtPlotCanvas::focusIndicator() const +{ + return d_data->focusIndicator; +} + +/*! + Set the radius for the corners of the border frame + + \param radius Radius of a rounded corner + \sa borderRadius() +*/ +void QwtPlotCanvas::setBorderRadius( double radius ) +{ + d_data->borderRadius = qMax( 0.0, radius ); +} + +/*! + \return Radius for the corners of the border frame + \sa setBorderRadius() +*/ +double QwtPlotCanvas::borderRadius() const +{ + return d_data->borderRadius; +} + +/*! + Qt event handler for QEvent::PolishRequest and QEvent::StyleChange + + \param event Qt Event + \return See QFrame::event() +*/ +bool QwtPlotCanvas::event( QEvent *event ) +{ + if ( event->type() == QEvent::PolishRequest ) + { + if ( testPaintAttribute( QwtPlotCanvas::Opaque ) ) + { + // Setting a style sheet changes the + // Qt::WA_OpaquePaintEvent attribute, but we insist + // on painting the background. + + setAttribute( Qt::WA_OpaquePaintEvent, true ); + } + } + + if ( event->type() == QEvent::PolishRequest || + event->type() == QEvent::StyleChange ) + { + updateStyleSheetInfo(); + } + + return QFrame::event( event ); +} + +/*! + Paint event + \param event Paint event +*/ +void QwtPlotCanvas::paintEvent( QPaintEvent *event ) +{ + QPainter painter( this ); + painter.setClipRegion( event->region() ); + + if ( testPaintAttribute( QwtPlotCanvas::BackingStore ) && + d_data->backingStore != NULL ) + { + QPixmap &bs = *d_data->backingStore; + if ( bs.size() != size() ) + { + bs = QwtPainter::backingStore( this, size() ); + + if ( testAttribute(Qt::WA_StyledBackground) ) + { + QPainter p( &bs ); + qwtFillBackground( &p, this ); + drawCanvas( &p, true ); + } + else + { + QPainter p; + if ( d_data->borderRadius <= 0.0 ) + { + QwtPainter::fillPixmap( this, bs ); + p.begin( &bs ); + drawCanvas( &p, false ); + } + else + { + p.begin( &bs ); + qwtFillBackground( &p, this ); + drawCanvas( &p, true ); + } + + if ( frameWidth() > 0 ) + drawBorder( &p ); + } + } + + painter.drawPixmap( 0, 0, *d_data->backingStore ); + } + else + { + if ( testAttribute(Qt::WA_StyledBackground ) ) + { + if ( testAttribute( Qt::WA_OpaquePaintEvent ) ) + { + qwtFillBackground( &painter, this ); + drawCanvas( &painter, true ); + } + else + { + drawCanvas( &painter, false ); + } + } + else + { + if ( testAttribute( Qt::WA_OpaquePaintEvent ) ) + { + if ( autoFillBackground() ) + { + qwtFillBackground( &painter, this ); + qwtDrawBackground( &painter, this ); + } + } + else + { + if ( borderRadius() > 0.0 ) + { + QPainterPath clipPath; + clipPath.addRect( rect() ); + clipPath = clipPath.subtracted( borderPath( rect() ) ); + + painter.save(); + + painter.setClipPath( clipPath, Qt::IntersectClip ); + qwtFillBackground( &painter, this ); + qwtDrawBackground( &painter, this ); + + painter.restore(); + } + } + + drawCanvas( &painter, false ); + + if ( frameWidth() > 0 ) + drawBorder( &painter ); + } + } + + if ( hasFocus() && focusIndicator() == CanvasFocusIndicator ) + drawFocusIndicator( &painter ); +} + +void QwtPlotCanvas::drawCanvas( QPainter *painter, bool withBackground ) +{ + bool hackStyledBackground = false; + + if ( withBackground && testAttribute( Qt::WA_StyledBackground ) + && testPaintAttribute( HackStyledBackground ) ) + { + // Antialiasing rounded borders is done by + // inserting pixels with colors between the + // border color and the color on the canvas, + // When the border is painted before the plot items + // these colors are interpolated for the canvas + // and the plot items need to be clipped excluding + // the anialiased pixels. In situations, where + // the plot items fill the area at the rounded + // borders this is noticeable. + // The only way to avoid these annoying "artefacts" + // is to paint the border on top of the plot items. + + if ( d_data->styleSheet.hasBorder && + !d_data->styleSheet.borderPath.isEmpty() ) + { + // We have a border with at least one rounded corner + hackStyledBackground = true; + } + } + + if ( withBackground ) + { + painter->save(); + + if ( testAttribute( Qt::WA_StyledBackground ) ) + { + if ( hackStyledBackground ) + { + // paint background without border + + painter->setPen( Qt::NoPen ); + painter->setBrush( d_data->styleSheet.background.brush ); + painter->setBrushOrigin( d_data->styleSheet.background.origin ); + painter->setClipPath( d_data->styleSheet.borderPath ); + painter->drawRect( contentsRect() ); + } + else + { + qwtDrawStyledBackground( this, painter ); + } + } + else if ( autoFillBackground() ) + { + painter->setPen( Qt::NoPen ); + painter->setBrush( palette().brush( backgroundRole() ) ); + + if ( d_data->borderRadius > 0.0 && ( rect() == frameRect() ) ) + { + if ( frameWidth() > 0 ) + { + painter->setClipPath( borderPath( rect() ) ); + painter->drawRect( rect() ); + } + else + { + painter->setRenderHint( QPainter::Antialiasing, true ); + painter->drawPath( borderPath( rect() ) ); + } + } + else + { + painter->drawRect( rect() ); + } + } + + painter->restore(); + } + + painter->save(); + + if ( !d_data->styleSheet.borderPath.isEmpty() ) + { + painter->setClipPath( + d_data->styleSheet.borderPath, Qt::IntersectClip ); + } + else + { + if ( d_data->borderRadius > 0.0 ) + painter->setClipPath( borderPath( frameRect() ), Qt::IntersectClip ); + else + painter->setClipRect( contentsRect(), Qt::IntersectClip ); + } + + plot()->drawCanvas( painter ); + + painter->restore(); + + if ( withBackground && hackStyledBackground ) + { + // Now paint the border on top + QStyleOptionFrame opt; + opt.initFrom(this); + style()->drawPrimitive( QStyle::PE_Frame, &opt, painter, this); + } +} + +/*! + Draw the border of the plot canvas + + \param painter Painter + \sa setBorderRadius() +*/ +void QwtPlotCanvas::drawBorder( QPainter *painter ) +{ + if ( d_data->borderRadius > 0 ) + { + if ( frameWidth() > 0 ) + { + QwtPainter::drawRoundedFrame( painter, QRectF( frameRect() ), + d_data->borderRadius, d_data->borderRadius, + palette(), frameWidth(), frameStyle() ); + } + } + else + { +#if QT_VERSION >= 0x040500 +#if QT_VERSION < 0x050000 + QStyleOptionFrameV3 opt; +#else + QStyleOptionFrame opt; +#endif + opt.init(this); + + int frameShape = frameStyle() & QFrame::Shape_Mask; + int frameShadow = frameStyle() & QFrame::Shadow_Mask; + + opt.frameShape = QFrame::Shape( int( opt.frameShape ) | frameShape ); +#if 0 + opt.rect = frameRect(); +#endif + + switch (frameShape) + { + case QFrame::Box: + case QFrame::HLine: + case QFrame::VLine: + case QFrame::StyledPanel: + case QFrame::Panel: + { + opt.lineWidth = lineWidth(); + opt.midLineWidth = midLineWidth(); + break; + } + default: + { + opt.lineWidth = frameWidth(); + break; + } + } + + if ( frameShadow == Sunken ) + opt.state |= QStyle::State_Sunken; + else if ( frameShadow == Raised ) + opt.state |= QStyle::State_Raised; + + style()->drawControl(QStyle::CE_ShapedFrame, &opt, painter, this); +#else + drawFrame( painter ); +#endif + } +} + +/*! + Resize event + \param event Resize event +*/ +void QwtPlotCanvas::resizeEvent( QResizeEvent *event ) +{ + QFrame::resizeEvent( event ); + updateStyleSheetInfo(); +} + +/*! + Draw the focus indication + \param painter Painter +*/ +void QwtPlotCanvas::drawFocusIndicator( QPainter *painter ) +{ + const int margin = 1; + + QRect focusRect = contentsRect(); + focusRect.setRect( focusRect.x() + margin, focusRect.y() + margin, + focusRect.width() - 2 * margin, focusRect.height() - 2 * margin ); + + QwtPainter::drawFocusRect( painter, this, focusRect ); +} + +/*! + Invalidate the paint cache and repaint the canvas + \sa invalidatePaintCache() +*/ +void QwtPlotCanvas::replot() +{ + invalidateBackingStore(); + + if ( testPaintAttribute( QwtPlotCanvas::ImmediatePaint ) ) + repaint( contentsRect() ); + else + update( contentsRect() ); +} + +//! Update the cached information about the current style sheet +void QwtPlotCanvas::updateStyleSheetInfo() +{ + if ( !testAttribute(Qt::WA_StyledBackground ) ) + return; + + QwtStyleSheetRecorder recorder( size() ); + + QPainter painter( &recorder ); + + QStyleOption opt; + opt.initFrom(this); + style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, this); + + painter.end(); + + d_data->styleSheet.hasBorder = !recorder.border.rectList.isEmpty(); + d_data->styleSheet.cornerRects = recorder.clipRects; + + if ( recorder.background.path.isEmpty() ) + { + if ( !recorder.border.rectList.isEmpty() ) + { + d_data->styleSheet.borderPath = + qwtCombinePathList( rect(), recorder.border.pathList ); + } + } + else + { + d_data->styleSheet.borderPath = recorder.background.path; + d_data->styleSheet.background.brush = recorder.background.brush; + d_data->styleSheet.background.origin = recorder.background.origin; + } +} + +/*! + Calculate the painter path for a styled or rounded border + + When the canvas has no styled background or rounded borders + the painter path is empty. + + \param rect Bounding rectangle of the canvas + \return Painter path, that can be used for clipping +*/ +QPainterPath QwtPlotCanvas::borderPath( const QRect &rect ) const +{ + if ( testAttribute(Qt::WA_StyledBackground ) ) + { + QwtStyleSheetRecorder recorder( rect.size() ); + + QPainter painter( &recorder ); + + QStyleOption opt; + opt.initFrom(this); + opt.rect = rect; + style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, this); + + painter.end(); + + if ( !recorder.background.path.isEmpty() ) + return recorder.background.path; + + if ( !recorder.border.rectList.isEmpty() ) + return qwtCombinePathList( rect, recorder.border.pathList ); + } + else if ( d_data->borderRadius > 0.0 ) + { + double fw2 = frameWidth() * 0.5; + QRectF r = QRectF(rect).adjusted( fw2, fw2, -fw2, -fw2 ); + + QPainterPath path; + path.addRoundedRect( r, d_data->borderRadius, d_data->borderRadius ); + return path; + } + + return QPainterPath(); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_canvas.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_canvas.h new file mode 100644 index 0000000..ccf7a6a --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_canvas.h @@ -0,0 +1,171 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PLOT_CANVAS_H +#define QWT_PLOT_CANVAS_H + +#include "qwt_global.h" +#include +#include + +class QwtPlot; +class QPixmap; + +/*! + \brief Canvas of a QwtPlot. + + Canvas is the widget where all plot items are displayed + + \sa QwtPlot::setCanvas(), QwtPlotGLCanvas +*/ +class QWT_EXPORT QwtPlotCanvas : public QFrame +{ + Q_OBJECT + + Q_PROPERTY( double borderRadius READ borderRadius WRITE setBorderRadius ) + +public: + + /*! + \brief Paint attributes + + The default setting enables BackingStore and Opaque. + + \sa setPaintAttribute(), testPaintAttribute() + */ + enum PaintAttribute + { + /*! + \brief Paint double buffered reusing the content + of the pixmap buffer when possible. + + Using a backing store might improve the performance + significantly, when working with widget overlays ( like rubber bands ). + Disabling the cache might improve the performance for + incremental paints (using QwtPlotDirectPainter ). + + \sa backingStore(), invalidateBackingStore() + */ + BackingStore = 1, + + /*! + \brief Try to fill the complete contents rectangle + of the plot canvas + + When using styled backgrounds Qt assumes, that the + canvas doesn't fill its area completely + ( f.e because of rounded borders ) and fills the area + below the canvas. When this is done with gradients it might + result in a serious performance bottleneck - depending on the size. + + When the Opaque attribute is enabled the canvas tries to + identify the gaps with some heuristics and to fill those only. + + \warning Will not work for semitransparent backgrounds + */ + Opaque = 2, + + /*! + \brief Try to improve painting of styled backgrounds + + QwtPlotCanvas supports the box model attributes for + customizing the layout with style sheets. Unfortunately + the design of Qt style sheets has no concept how to + handle backgrounds with rounded corners - beside of padding. + + When HackStyledBackground is enabled the plot canvas tries + to separate the background from the background border + by reverse engineering to paint the background before and + the border after the plot items. In this order the border + gets perfectly antialiased and you can avoid some pixel + artifacts in the corners. + */ + HackStyledBackground = 4, + + /*! + When ImmediatePaint is set replot() calls repaint() + instead of update(). + + \sa replot(), QWidget::repaint(), QWidget::update() + */ + ImmediatePaint = 8 + }; + + //! Paint attributes + typedef QFlags PaintAttributes; + + /*! + \brief Focus indicator + The default setting is NoFocusIndicator + \sa setFocusIndicator(), focusIndicator(), drawFocusIndicator() + */ + + enum FocusIndicator + { + //! Don't paint a focus indicator + NoFocusIndicator, + + /*! + The focus is related to the complete canvas. + Paint the focus indicator using drawFocusIndicator() + */ + CanvasFocusIndicator, + + /*! + The focus is related to an item (curve, point, ...) on + the canvas. It is up to the application to display a + focus indication using f.e. highlighting. + */ + ItemFocusIndicator + }; + + explicit QwtPlotCanvas( QwtPlot * = NULL ); + virtual ~QwtPlotCanvas(); + + QwtPlot *plot(); + const QwtPlot *plot() const; + + void setFocusIndicator( FocusIndicator ); + FocusIndicator focusIndicator() const; + + void setBorderRadius( double ); + double borderRadius() const; + + void setPaintAttribute( PaintAttribute, bool on = true ); + bool testPaintAttribute( PaintAttribute ) const; + + const QPixmap *backingStore() const; + void invalidateBackingStore(); + + virtual bool event( QEvent * ); + + Q_INVOKABLE QPainterPath borderPath( const QRect & ) const; + +public Q_SLOTS: + void replot(); + +protected: + virtual void paintEvent( QPaintEvent * ); + virtual void resizeEvent( QResizeEvent * ); + + virtual void drawFocusIndicator( QPainter * ); + virtual void drawBorder( QPainter * ); + + void updateStyleSheetInfo(); + +private: + void drawCanvas( QPainter *, bool withBackground ); + + class PrivateData; + PrivateData *d_data; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotCanvas::PaintAttributes ) + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_curve.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_curve.cpp new file mode 100644 index 0000000..a29e42e --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_curve.cpp @@ -0,0 +1,1204 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot_curve.h" +#include "qwt_point_data.h" +#include "qwt_math.h" +#include "qwt_clipper.h" +#include "qwt_painter.h" +#include "qwt_scale_map.h" +#include "qwt_plot.h" +#include "qwt_curve_fitter.h" +#include "qwt_symbol.h" +#include "qwt_point_mapper.h" +#include +#include +#include +#include + +static void qwtUpdateLegendIconSize( QwtPlotCurve *curve ) +{ + if ( curve->symbol() && + curve->testLegendAttribute( QwtPlotCurve::LegendShowSymbol ) ) + { + QSize sz = curve->symbol()->boundingRect().size(); + sz += QSize( 2, 2 ); // margin + + if ( curve->testLegendAttribute( QwtPlotCurve::LegendShowLine ) ) + { + // Avoid, that the line is completely covered by the symbol + + int w = qCeil( 1.5 * sz.width() ); + if ( w % 2 ) + w++; + + sz.setWidth( qMax( 8, w ) ); + } + + curve->setLegendIconSize( sz ); + } +} + +static int qwtVerifyRange( int size, int &i1, int &i2 ) +{ + if ( size < 1 ) + return 0; + + i1 = qBound( 0, i1, size - 1 ); + i2 = qBound( 0, i2, size - 1 ); + + if ( i1 > i2 ) + qSwap( i1, i2 ); + + return ( i2 - i1 + 1 ); +} + +class QwtPlotCurve::PrivateData +{ +public: + PrivateData(): + style( QwtPlotCurve::Lines ), + baseline( 0.0 ), + symbol( NULL ), + attributes( 0 ), + paintAttributes( + QwtPlotCurve::ClipPolygons | QwtPlotCurve::FilterPoints ), + legendAttributes( 0 ) + { + pen = QPen( Qt::black ); + curveFitter = new QwtSplineCurveFitter; + } + + ~PrivateData() + { + delete symbol; + delete curveFitter; + } + + QwtPlotCurve::CurveStyle style; + double baseline; + + const QwtSymbol *symbol; + QwtCurveFitter *curveFitter; + + QPen pen; + QBrush brush; + + QwtPlotCurve::CurveAttributes attributes; + QwtPlotCurve::PaintAttributes paintAttributes; + + QwtPlotCurve::LegendAttributes legendAttributes; +}; + +/*! + Constructor + \param title Title of the curve +*/ +QwtPlotCurve::QwtPlotCurve( const QwtText &title ): + QwtPlotSeriesItem( title ) +{ + init(); +} + +/*! + Constructor + \param title Title of the curve +*/ +QwtPlotCurve::QwtPlotCurve( const QString &title ): + QwtPlotSeriesItem( QwtText( title ) ) +{ + init(); +} + +//! Destructor +QwtPlotCurve::~QwtPlotCurve() +{ + delete d_data; +} + +//! Initialize internal members +void QwtPlotCurve::init() +{ + setItemAttribute( QwtPlotItem::Legend ); + setItemAttribute( QwtPlotItem::AutoScale ); + + d_data = new PrivateData; + setData( new QwtPointSeriesData() ); + + setZ( 20.0 ); +} + +//! \return QwtPlotItem::Rtti_PlotCurve +int QwtPlotCurve::rtti() const +{ + return QwtPlotItem::Rtti_PlotCurve; +} + +/*! + Specify an attribute how to draw the curve + + \param attribute Paint attribute + \param on On/Off + \sa testPaintAttribute() +*/ +void QwtPlotCurve::setPaintAttribute( PaintAttribute attribute, bool on ) +{ + if ( on ) + d_data->paintAttributes |= attribute; + else + d_data->paintAttributes &= ~attribute; +} + +/*! + \return True, when attribute is enabled + \sa setPaintAttribute() +*/ +bool QwtPlotCurve::testPaintAttribute( PaintAttribute attribute ) const +{ + return ( d_data->paintAttributes & attribute ); +} + +/*! + Specify an attribute how to draw the legend icon + + \param attribute Attribute + \param on On/Off + /sa testLegendAttribute(). legendIcon() +*/ +void QwtPlotCurve::setLegendAttribute( LegendAttribute attribute, bool on ) +{ + if ( on != testLegendAttribute( attribute ) ) + { + if ( on ) + d_data->legendAttributes |= attribute; + else + d_data->legendAttributes &= ~attribute; + + qwtUpdateLegendIconSize( this ); + legendChanged(); + } +} + +/*! + \return True, when attribute is enabled + \sa setLegendAttribute() +*/ +bool QwtPlotCurve::testLegendAttribute( LegendAttribute attribute ) const +{ + return ( d_data->legendAttributes & attribute ); +} + +/*! + Set the curve's drawing style + + \param style Curve style + \sa style() +*/ +void QwtPlotCurve::setStyle( CurveStyle style ) +{ + if ( style != d_data->style ) + { + d_data->style = style; + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Style of the curve + \sa setStyle() +*/ +QwtPlotCurve::CurveStyle QwtPlotCurve::style() const +{ + return d_data->style; +} + +/*! + \brief Assign a symbol + + The curve will take the ownership of the symbol, hence the previously + set symbol will be delete by setting a new one. If \p symbol is + \c NULL no symbol will be drawn. + + \param symbol Symbol + \sa symbol() +*/ +void QwtPlotCurve::setSymbol( QwtSymbol *symbol ) +{ + if ( symbol != d_data->symbol ) + { + delete d_data->symbol; + d_data->symbol = symbol; + + qwtUpdateLegendIconSize( this ); + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Current symbol or NULL, when no symbol has been assigned + \sa setSymbol() +*/ +const QwtSymbol *QwtPlotCurve::symbol() const +{ + return d_data->symbol; +} + +/*! + Build and assign a pen + + In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it + non cosmetic ( see QPen::isCosmetic() ). This method has been introduced + to hide this incompatibility. + + \param color Pen color + \param width Pen width + \param style Pen style + + \sa pen(), brush() + */ +void QwtPlotCurve::setPen( const QColor &color, qreal width, Qt::PenStyle style ) +{ + setPen( QPen( color, width, style ) ); +} + +/*! + Assign a pen + + \param pen New pen + \sa pen(), brush() +*/ +void QwtPlotCurve::setPen( const QPen &pen ) +{ + if ( pen != d_data->pen ) + { + d_data->pen = pen; + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Pen used to draw the lines + \sa setPen(), brush() +*/ +const QPen& QwtPlotCurve::pen() const +{ + return d_data->pen; +} + +/*! + \brief Assign a brush. + + In case of brush.style() != QBrush::NoBrush + and style() != QwtPlotCurve::Sticks + the area between the curve and the baseline will be filled. + + In case !brush.color().isValid() the area will be filled by + pen.color(). The fill algorithm simply connects the first and the + last curve point to the baseline. So the curve data has to be sorted + (ascending or descending). + + \param brush New brush + \sa brush(), setBaseline(), baseline() +*/ +void QwtPlotCurve::setBrush( const QBrush &brush ) +{ + if ( brush != d_data->brush ) + { + d_data->brush = brush; + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Brush used to fill the area between lines and the baseline + \sa setBrush(), setBaseline(), baseline() +*/ +const QBrush& QwtPlotCurve::brush() const +{ + return d_data->brush; +} + +/*! + Draw an interval of the curve + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param canvasRect Contents rectangle of the canvas + \param from Index of the first point to be painted + \param to Index of the last point to be painted. If to < 0 the + curve will be painted to its last point. + + \sa drawCurve(), drawSymbols(), +*/ +void QwtPlotCurve::drawSeries( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + const size_t numSamples = dataSize(); + + if ( !painter || numSamples <= 0 ) + return; + + if ( to < 0 ) + to = numSamples - 1; + + if ( qwtVerifyRange( numSamples, from, to ) > 0 ) + { + painter->save(); + painter->setPen( d_data->pen ); + + /* + Qt 4.0.0 is slow when drawing lines, but it's even + slower when the painter has a brush. So we don't + set the brush before we really need it. + */ + + drawCurve( painter, d_data->style, xMap, yMap, canvasRect, from, to ); + painter->restore(); + + if ( d_data->symbol && + ( d_data->symbol->style() != QwtSymbol::NoSymbol ) ) + { + painter->save(); + drawSymbols( painter, *d_data->symbol, + xMap, yMap, canvasRect, from, to ); + painter->restore(); + } + } +} + +/*! + \brief Draw the line part (without symbols) of a curve interval. + \param painter Painter + \param style curve style, see QwtPlotCurve::CurveStyle + \param xMap x map + \param yMap y map + \param canvasRect Contents rectangle of the canvas + \param from index of the first point to be painted + \param to index of the last point to be painted + \sa draw(), drawDots(), drawLines(), drawSteps(), drawSticks() +*/ +void QwtPlotCurve::drawCurve( QPainter *painter, int style, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + switch ( style ) + { + case Lines: + if ( testCurveAttribute( Fitted ) ) + { + // we always need the complete + // curve for fitting + from = 0; + to = dataSize() - 1; + } + drawLines( painter, xMap, yMap, canvasRect, from, to ); + break; + case Sticks: + drawSticks( painter, xMap, yMap, canvasRect, from, to ); + break; + case Steps: + drawSteps( painter, xMap, yMap, canvasRect, from, to ); + break; + case Dots: + drawDots( painter, xMap, yMap, canvasRect, from, to ); + break; + case NoCurve: + default: + break; + } +} + +/*! + \brief Draw lines + + If the CurveAttribute Fitted is enabled a QwtCurveFitter tries + to interpolate/smooth the curve, before it is painted. + + \param painter Painter + \param xMap x map + \param yMap y map + \param canvasRect Contents rectangle of the canvas + \param from index of the first point to be painted + \param to index of the last point to be painted + + \sa setCurveAttribute(), setCurveFitter(), draw(), + drawLines(), drawDots(), drawSteps(), drawSticks() +*/ +void QwtPlotCurve::drawLines( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + if ( from > to ) + return; + + const bool doAlign = QwtPainter::roundingAlignment( painter ); + const bool doFit = ( d_data->attributes & Fitted ) && d_data->curveFitter; + const bool doFill = ( d_data->brush.style() != Qt::NoBrush ) + && ( d_data->brush.color().alpha() > 0 ); + + QRectF clipRect; + if ( d_data->paintAttributes & ClipPolygons ) + { + qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF()); + clipRect = canvasRect.adjusted(-pw, -pw, pw, pw); + } + + bool doIntegers = false; + +#if QT_VERSION < 0x040800 + + // For Qt <= 4.7 the raster paint engine is significantly faster + // for rendering QPolygon than for QPolygonF. So let's + // see if we can use it. + + if ( painter->paintEngine()->type() == QPaintEngine::Raster ) + { + // In case of filling or fitting performance doesn't count + // because both operations are much more expensive + // then drawing the polyline itself + + if ( !doFit && !doFill ) + doIntegers = true; + } +#endif + + const bool noDuplicates = d_data->paintAttributes & FilterPoints; + + QwtPointMapper mapper; + mapper.setFlag( QwtPointMapper::RoundPoints, doAlign ); + mapper.setFlag( QwtPointMapper::WeedOutPoints, noDuplicates ); + mapper.setBoundingRect( canvasRect ); + + if ( doIntegers ) + { + QPolygon polyline = mapper.toPolygon( + xMap, yMap, data(), from, to ); + + if ( d_data->paintAttributes & ClipPolygons ) + { + polyline = QwtClipper::clipPolygon( + clipRect.toAlignedRect(), polyline, false ); + } + + QwtPainter::drawPolyline( painter, polyline ); + } + else + { + QPolygonF polyline = mapper.toPolygonF( xMap, yMap, data(), from, to ); + + if ( doFit ) + polyline = d_data->curveFitter->fitCurve( polyline ); + + if ( doFill ) + { + if ( painter->pen().style() != Qt::NoPen ) + { + // here we are wasting memory for the filled copy, + // do polygon clipping twice etc .. TODO + + QPolygonF filled = polyline; + fillCurve( painter, xMap, yMap, canvasRect, filled ); + filled.clear(); + + if ( d_data->paintAttributes & ClipPolygons ) + { + polyline = QwtClipper::clipPolygonF( + clipRect, polyline, false ); + } + + QwtPainter::drawPolyline( painter, polyline ); + } + else + { + fillCurve( painter, xMap, yMap, canvasRect, polyline ); + } + } + else + { + if ( d_data->paintAttributes & ClipPolygons ) + { + polyline = QwtClipper::clipPolygonF( + clipRect, polyline, false ); + } + + QwtPainter::drawPolyline( painter, polyline ); + } + } +} + +/*! + Draw sticks + + \param painter Painter + \param xMap x map + \param yMap y map + \param canvasRect Contents rectangle of the canvas + \param from index of the first point to be painted + \param to index of the last point to be painted + + \sa draw(), drawCurve(), drawDots(), drawLines(), drawSteps() +*/ +void QwtPlotCurve::drawSticks( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &, int from, int to ) const +{ + painter->save(); + painter->setRenderHint( QPainter::Antialiasing, false ); + + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + double x0 = xMap.transform( d_data->baseline ); + double y0 = yMap.transform( d_data->baseline ); + if ( doAlign ) + { + x0 = qRound( x0 ); + y0 = qRound( y0 ); + } + + const Qt::Orientation o = orientation(); + + const QwtSeriesData *series = data(); + + for ( int i = from; i <= to; i++ ) + { + const QPointF sample = series->sample( i ); + double xi = xMap.transform( sample.x() ); + double yi = yMap.transform( sample.y() ); + if ( doAlign ) + { + xi = qRound( xi ); + yi = qRound( yi ); + } + + if ( o == Qt::Horizontal ) + QwtPainter::drawLine( painter, x0, yi, xi, yi ); + else + QwtPainter::drawLine( painter, xi, y0, xi, yi ); + } + + painter->restore(); +} + +/*! + Draw dots + + \param painter Painter + \param xMap x map + \param yMap y map + \param canvasRect Contents rectangle of the canvas + \param from index of the first point to be painted + \param to index of the last point to be painted + + \sa draw(), drawCurve(), drawSticks(), drawLines(), drawSteps() +*/ +void QwtPlotCurve::drawDots( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + const QColor color = painter->pen().color(); + + if ( painter->pen().style() == Qt::NoPen || color.alpha() == 0 ) + { + return; + } + + const bool doFill = ( d_data->brush.style() != Qt::NoBrush ) + && ( d_data->brush.color().alpha() > 0 ); + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + QwtPointMapper mapper; + mapper.setBoundingRect( canvasRect ); + mapper.setFlag( QwtPointMapper::RoundPoints, doAlign ); + + if ( d_data->paintAttributes & FilterPoints ) + { + if ( ( color.alpha() == 255 ) + && !( painter->renderHints() & QPainter::Antialiasing ) ) + { + mapper.setFlag( QwtPointMapper::WeedOutPoints, true ); + } + } + + if ( doFill ) + { + mapper.setFlag( QwtPointMapper::WeedOutPoints, false ); + + QPolygonF points = mapper.toPointsF( + xMap, yMap, data(), from, to ); + + QwtPainter::drawPoints( painter, points ); + fillCurve( painter, xMap, yMap, canvasRect, points ); + } + else if ( d_data->paintAttributes & ImageBuffer ) + { + const QImage image = mapper.toImage( xMap, yMap, + data(), from, to, d_data->pen, + painter->testRenderHint( QPainter::Antialiasing ), + renderThreadCount() ); + + painter->drawImage( canvasRect.toAlignedRect(), image ); + } + else if ( d_data->paintAttributes & MinimizeMemory ) + { + const QwtSeriesData *series = data(); + + for ( int i = from; i <= to; i++ ) + { + const QPointF sample = series->sample( i ); + + double xi = xMap.transform( sample.x() ); + double yi = yMap.transform( sample.y() ); + + if ( doAlign ) + { + xi = qRound( xi ); + yi = qRound( yi ); + } + + QwtPainter::drawPoint( painter, QPointF( xi, yi ) ); + } + } + else + { + if ( doAlign ) + { + const QPolygon points = mapper.toPoints( + xMap, yMap, data(), from, to ); + + QwtPainter::drawPoints( painter, points ); + } + else + { + const QPolygonF points = mapper.toPointsF( + xMap, yMap, data(), from, to ); + + QwtPainter::drawPoints( painter, points ); + } + } +} + +/*! + Draw step function + + The direction of the steps depends on Inverted attribute. + + \param painter Painter + \param xMap x map + \param yMap y map + \param canvasRect Contents rectangle of the canvas + \param from index of the first point to be painted + \param to index of the last point to be painted + + \sa CurveAttribute, setCurveAttribute(), + draw(), drawCurve(), drawDots(), drawLines(), drawSticks() +*/ +void QwtPlotCurve::drawSteps( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + QPolygonF polygon( 2 * ( to - from ) + 1 ); + QPointF *points = polygon.data(); + + bool inverted = orientation() == Qt::Vertical; + if ( d_data->attributes & Inverted ) + inverted = !inverted; + + const QwtSeriesData *series = data(); + + int i, ip; + for ( i = from, ip = 0; i <= to; i++, ip += 2 ) + { + const QPointF sample = series->sample( i ); + double xi = xMap.transform( sample.x() ); + double yi = yMap.transform( sample.y() ); + if ( doAlign ) + { + xi = qRound( xi ); + yi = qRound( yi ); + } + + if ( ip > 0 ) + { + const QPointF &p0 = points[ip - 2]; + QPointF &p = points[ip - 1]; + + if ( inverted ) + { + p.rx() = p0.x(); + p.ry() = yi; + } + else + { + p.rx() = xi; + p.ry() = p0.y(); + } + } + + points[ip].rx() = xi; + points[ip].ry() = yi; + } + + if ( d_data->paintAttributes & ClipPolygons ) + { + const QPolygonF clipped = QwtClipper::clipPolygonF( + canvasRect, polygon, false ); + + QwtPainter::drawPolyline( painter, clipped ); + } + else + { + QwtPainter::drawPolyline( painter, polygon ); + } + + if ( d_data->brush.style() != Qt::NoBrush ) + fillCurve( painter, xMap, yMap, canvasRect, polygon ); +} + + +/*! + Specify an attribute for drawing the curve + + \param attribute Curve attribute + \param on On/Off + + /sa testCurveAttribute(), setCurveFitter() +*/ +void QwtPlotCurve::setCurveAttribute( CurveAttribute attribute, bool on ) +{ + if ( bool( d_data->attributes & attribute ) == on ) + return; + + if ( on ) + d_data->attributes |= attribute; + else + d_data->attributes &= ~attribute; + + itemChanged(); +} + +/*! + \return true, if attribute is enabled + \sa setCurveAttribute() +*/ +bool QwtPlotCurve::testCurveAttribute( CurveAttribute attribute ) const +{ + return d_data->attributes & attribute; +} + +/*! + Assign a curve fitter + + The curve fitter "smooths" the curve points, when the Fitted + CurveAttribute is set. setCurveFitter(NULL) also disables curve fitting. + + The curve fitter operates on the translated points ( = widget coordinates) + to be functional for logarithmic scales. Obviously this is less performant + for fitting algorithms, that reduce the number of points. + + For situations, where curve fitting is used to improve the performance + of painting huge series of points it might be better to execute the fitter + on the curve points once and to cache the result in the QwtSeriesData object. + + \param curveFitter() Curve fitter + \sa Fitted +*/ +void QwtPlotCurve::setCurveFitter( QwtCurveFitter *curveFitter ) +{ + delete d_data->curveFitter; + d_data->curveFitter = curveFitter; + + itemChanged(); +} + +/*! + Get the curve fitter. If curve fitting is disabled NULL is returned. + + \return Curve fitter + \sa setCurveFitter(), Fitted +*/ +QwtCurveFitter *QwtPlotCurve::curveFitter() const +{ + return d_data->curveFitter; +} + +/*! + Fill the area between the curve and the baseline with + the curve brush + + \param painter Painter + \param xMap x map + \param yMap y map + \param canvasRect Contents rectangle of the canvas + \param polygon Polygon - will be modified ! + + \sa setBrush(), setBaseline(), setStyle() +*/ +void QwtPlotCurve::fillCurve( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, QPolygonF &polygon ) const +{ + if ( d_data->brush.style() == Qt::NoBrush ) + return; + + closePolyline( painter, xMap, yMap, polygon ); + if ( polygon.count() <= 2 ) // a line can't be filled + return; + + QBrush brush = d_data->brush; + if ( !brush.color().isValid() ) + brush.setColor( d_data->pen.color() ); + + if ( d_data->paintAttributes & ClipPolygons ) + polygon = QwtClipper::clipPolygonF( canvasRect, polygon, true ); + + painter->save(); + + painter->setPen( Qt::NoPen ); + painter->setBrush( brush ); + + QwtPainter::drawPolygon( painter, polygon ); + + painter->restore(); +} + +/*! + \brief Complete a polygon to be a closed polygon including the + area between the original polygon and the baseline. + + \param painter Painter + \param xMap X map + \param yMap Y map + \param polygon Polygon to be completed +*/ +void QwtPlotCurve::closePolyline( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + QPolygonF &polygon ) const +{ + if ( polygon.size() < 2 ) + return; + + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + double baseline = d_data->baseline; + + if ( orientation() == Qt::Vertical ) + { + if ( yMap.transformation() ) + baseline = yMap.transformation()->bounded( baseline ); + + double refY = yMap.transform( baseline ); + if ( doAlign ) + refY = qRound( refY ); + + polygon += QPointF( polygon.last().x(), refY ); + polygon += QPointF( polygon.first().x(), refY ); + } + else + { + if ( xMap.transformation() ) + baseline = xMap.transformation()->bounded( baseline ); + + double refX = xMap.transform( baseline ); + if ( doAlign ) + refX = qRound( refX ); + + polygon += QPointF( refX, polygon.last().y() ); + polygon += QPointF( refX, polygon.first().y() ); + } +} + +/*! + Draw symbols + + \param painter Painter + \param symbol Curve symbol + \param xMap x map + \param yMap y map + \param canvasRect Contents rectangle of the canvas + \param from Index of the first point to be painted + \param to Index of the last point to be painted + + \sa setSymbol(), drawSeries(), drawCurve() +*/ +void QwtPlotCurve::drawSymbols( QPainter *painter, const QwtSymbol &symbol, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + QwtPointMapper mapper; + mapper.setFlag( QwtPointMapper::RoundPoints, + QwtPainter::roundingAlignment( painter ) ); + mapper.setFlag( QwtPointMapper::WeedOutPoints, + testPaintAttribute( QwtPlotCurve::FilterPoints ) ); + mapper.setBoundingRect( canvasRect ); + + const int chunkSize = 500; + + for ( int i = from; i <= to; i += chunkSize ) + { + const int n = qMin( chunkSize, to - i + 1 ); + + const QPolygonF points = mapper.toPointsF( xMap, yMap, + data(), i, i + n - 1 ); + + if ( points.size() > 0 ) + symbol.drawSymbols( painter, points ); + } +} + +/*! + \brief Set the value of the baseline + + The baseline is needed for filling the curve with a brush or + the Sticks drawing style. + + The interpretation of the baseline depends on the orientation(). + With Qt::Horizontal, the baseline is interpreted as a horizontal line + at y = baseline(), with Qt::Vertical, it is interpreted as a vertical + line at x = baseline(). + + The default value is 0.0. + + \param value Value of the baseline + \sa baseline(), setBrush(), setStyle(), QwtPlotAbstractSeriesItem::orientation() +*/ +void QwtPlotCurve::setBaseline( double value ) +{ + if ( d_data->baseline != value ) + { + d_data->baseline = value; + itemChanged(); + } +} + +/*! + \return Value of the baseline + \sa setBaseline() +*/ +double QwtPlotCurve::baseline() const +{ + return d_data->baseline; +} + +/*! + Find the closest curve point for a specific position + + \param pos Position, where to look for the closest curve point + \param dist If dist != NULL, closestPoint() returns the distance between + the position and the closest curve point + \return Index of the closest curve point, or -1 if none can be found + ( f.e when the curve has no points ) + \note closestPoint() implements a dumb algorithm, that iterates + over all points +*/ +int QwtPlotCurve::closestPoint( const QPoint &pos, double *dist ) const +{ + const size_t numSamples = dataSize(); + + if ( plot() == NULL || numSamples <= 0 ) + return -1; + + const QwtSeriesData *series = data(); + + const QwtScaleMap xMap = plot()->canvasMap( xAxis() ); + const QwtScaleMap yMap = plot()->canvasMap( yAxis() ); + + int index = -1; + double dmin = 1.0e10; + + for ( uint i = 0; i < numSamples; i++ ) + { + const QPointF sample = series->sample( i ); + + const double cx = xMap.transform( sample.x() ) - pos.x(); + const double cy = yMap.transform( sample.y() ) - pos.y(); + + const double f = qwtSqr( cx ) + qwtSqr( cy ); + if ( f < dmin ) + { + index = i; + dmin = f; + } + } + if ( dist ) + *dist = qSqrt( dmin ); + + return index; +} + +/*! + \return Icon representing the curve on the legend + + \param index Index of the legend entry + ( ignored as there is only one ) + \param size Icon size + + \sa QwtPlotItem::setLegendIconSize(), QwtPlotItem::legendData() + */ +QwtGraphic QwtPlotCurve::legendIcon( int index, + const QSizeF &size ) const +{ + Q_UNUSED( index ); + + if ( size.isEmpty() ) + return QwtGraphic(); + + QwtGraphic graphic; + graphic.setDefaultSize( size ); + graphic.setRenderHint( QwtGraphic::RenderPensUnscaled, true ); + + QPainter painter( &graphic ); + painter.setRenderHint( QPainter::Antialiasing, + testRenderHint( QwtPlotItem::RenderAntialiased ) ); + + if ( d_data->legendAttributes == 0 || + d_data->legendAttributes & QwtPlotCurve::LegendShowBrush ) + { + QBrush brush = d_data->brush; + + if ( brush.style() == Qt::NoBrush && + d_data->legendAttributes == 0 ) + { + if ( style() != QwtPlotCurve::NoCurve ) + { + brush = QBrush( pen().color() ); + } + else if ( d_data->symbol && + ( d_data->symbol->style() != QwtSymbol::NoSymbol ) ) + { + brush = QBrush( d_data->symbol->pen().color() ); + } + } + + if ( brush.style() != Qt::NoBrush ) + { + QRectF r( 0, 0, size.width(), size.height() ); + painter.fillRect( r, brush ); + } + } + + if ( d_data->legendAttributes & QwtPlotCurve::LegendShowLine ) + { + if ( pen() != Qt::NoPen ) + { + QPen pn = pen(); + pn.setCapStyle( Qt::FlatCap ); + + painter.setPen( pn ); + + const double y = 0.5 * size.height(); + QwtPainter::drawLine( &painter, 0.0, y, size.width(), y ); + } + } + + if ( d_data->legendAttributes & QwtPlotCurve::LegendShowSymbol ) + { + if ( d_data->symbol ) + { + QRectF r( 0, 0, size.width(), size.height() ); + d_data->symbol->drawSymbol( &painter, r ); + } + } + + return graphic; +} + +/*! + Initialize data with an array of points. + + \param samples Vector of points + \note QVector is implicitly shared + \note QPolygonF is derived from QVector +*/ +void QwtPlotCurve::setSamples( const QVector &samples ) +{ + setData( new QwtPointSeriesData( samples ) ); +} + +/*! + Assign a series of points + + setSamples() is just a wrapper for setData() without any additional + value - beside that it is easier to find for the developer. + + \param data Data + \warning The item takes ownership of the data object, deleting + it when its not used anymore. +*/ +void QwtPlotCurve::setSamples( QwtSeriesData *data ) +{ + setData( data ); +} + +#ifndef QWT_NO_COMPAT + +/*! + \brief Initialize the data by pointing to memory blocks which + are not managed by QwtPlotCurve. + + setRawSamples is provided for efficiency. + It is important to keep the pointers + during the lifetime of the underlying QwtCPointerData class. + + \param xData pointer to x data + \param yData pointer to y data + \param size size of x and y + + \sa QwtCPointerData +*/ +void QwtPlotCurve::setRawSamples( + const double *xData, const double *yData, int size ) +{ + setData( new QwtCPointerData( xData, yData, size ) ); +} + +/*! + Set data by copying x- and y-values from specified memory blocks. + Contrary to setRawSamples(), this function makes a 'deep copy' of + the data. + + \param xData pointer to x values + \param yData pointer to y values + \param size size of xData and yData + + \sa QwtPointArrayData +*/ +void QwtPlotCurve::setSamples( + const double *xData, const double *yData, int size ) +{ + setData( new QwtPointArrayData( xData, yData, size ) ); +} + +/*! + \brief Initialize data with x- and y-arrays (explicitly shared) + + \param xData x data + \param yData y data + + \sa QwtPointArrayData +*/ +void QwtPlotCurve::setSamples( const QVector &xData, + const QVector &yData ) +{ + setData( new QwtPointArrayData( xData, yData ) ); +} + +#endif // !QWT_NO_COMPAT + diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_curve.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_curve.h new file mode 100644 index 0000000..cfba1fb --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_curve.h @@ -0,0 +1,337 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PLOT_CURVE_H +#define QWT_PLOT_CURVE_H + +#include "qwt_global.h" +#include "qwt_plot_seriesitem.h" +#include "qwt_series_data.h" +#include "qwt_text.h" +#include +#include + +class QPainter; +class QPolygonF; +class QwtScaleMap; +class QwtSymbol; +class QwtCurveFitter; + +/*! + \brief A plot item, that represents a series of points + + A curve is the representation of a series of points in the x-y plane. + It supports different display styles, interpolation ( f.e. spline ) + and symbols. + + \par Usage +
a) Assign curve properties
+
When a curve is created, it is configured to draw black solid lines + with in QwtPlotCurve::Lines style and no symbols. + You can change this by calling + setPen(), setStyle() and setSymbol().
+
b) Connect/Assign data.
+
QwtPlotCurve gets its points using a QwtSeriesData object offering + a bridge to the real storage of the points ( like QAbstractItemModel ). + There are several convenience classes derived from QwtSeriesData, that also store + the points inside ( like QStandardItemModel ). QwtPlotCurve also offers + a couple of variations of setSamples(), that build QwtSeriesData objects from + arrays internally.
+
c) Attach the curve to a plot
+
See QwtPlotItem::attach() +
+ + \par Example: + see examples/bode + + \sa QwtPointSeriesData, QwtSymbol, QwtScaleMap +*/ +class QWT_EXPORT QwtPlotCurve: + public QwtPlotSeriesItem, public QwtSeriesStore +{ +public: + /*! + Curve styles. + \sa setStyle(), style() + */ + enum CurveStyle + { + /*! + Don't draw a curve. Note: This doesn't affect the symbols. + */ + NoCurve = -1, + + /*! + Connect the points with straight lines. The lines might + be interpolated depending on the 'Fitted' attribute. Curve + fitting can be configured using setCurveFitter(). + */ + Lines, + + /*! + Draw vertical or horizontal sticks ( depending on the + orientation() ) from a baseline which is defined by setBaseline(). + */ + Sticks, + + /*! + Connect the points with a step function. The step function + is drawn from the left to the right or vice versa, + depending on the QwtPlotCurve::Inverted attribute. + */ + Steps, + + /*! + Draw dots at the locations of the data points. Note: + This is different from a dotted line (see setPen()), and faster + as a curve in QwtPlotCurve::NoStyle style and a symbol + painting a point. + */ + Dots, + + /*! + Styles >= QwtPlotCurve::UserCurve are reserved for derived + classes of QwtPlotCurve that overload drawCurve() with + additional application specific curve types. + */ + UserCurve = 100 + }; + + /*! + Attribute for drawing the curve + \sa setCurveAttribute(), testCurveAttribute(), curveFitter() + */ + enum CurveAttribute + { + /*! + For QwtPlotCurve::Steps only. + Draws a step function from the right to the left. + */ + Inverted = 0x01, + + /*! + Only in combination with QwtPlotCurve::Lines + A QwtCurveFitter tries to + interpolate/smooth the curve, before it is painted. + + \note Curve fitting requires temporary memory + for calculating coefficients and additional points. + If painting in QwtPlotCurve::Fitted mode is slow it might be better + to fit the points, before they are passed to QwtPlotCurve. + */ + Fitted = 0x02 + }; + + //! Curve attributes + typedef QFlags CurveAttributes; + + /*! + Attributes how to represent the curve on the legend + + \sa setLegendAttribute(), testLegendAttribute(), + QwtPlotItem::legendData(), legendIcon() + */ + + enum LegendAttribute + { + /*! + QwtPlotCurve tries to find a color representing the curve + and paints a rectangle with it. + */ + LegendNoAttribute = 0x00, + + /*! + If the style() is not QwtPlotCurve::NoCurve a line + is painted with the curve pen(). + */ + LegendShowLine = 0x01, + + /*! + If the curve has a valid symbol it is painted. + */ + LegendShowSymbol = 0x02, + + /*! + If the curve has a brush a rectangle filled with the + curve brush() is painted. + */ + LegendShowBrush = 0x04 + }; + + //! Legend attributes + typedef QFlags LegendAttributes; + + /*! + Attributes to modify the drawing algorithm. + The default setting enables ClipPolygons | FilterPoints + + \sa setPaintAttribute(), testPaintAttribute() + */ + enum PaintAttribute + { + /*! + Clip polygons before painting them. In situations, where points + are far outside the visible area (f.e when zooming deep) this + might be a substantial improvement for the painting performance + */ + ClipPolygons = 0x01, + + /*! + Tries to reduce the data that has to be painted, by sorting out + duplicates, or paintings outside the visible area. Might have a + notable impact on curves with many close points. + Only a couple of very basic filtering algorithms are implemented. + */ + FilterPoints = 0x02, + + /*! + Minimize memory usage that is temporarily needed for the + translated points, before they get painted. + This might slow down the performance of painting + */ + MinimizeMemory = 0x04, + + /*! + Render the points to a temporary image and paint the image. + This is a very special optimization for Dots style, when + having a huge amount of points. + With a reasonable number of points QPainter::drawPoints() + will be faster. + */ + ImageBuffer = 0x08 + }; + + //! Paint attributes + typedef QFlags PaintAttributes; + + explicit QwtPlotCurve( const QString &title = QString::null ); + explicit QwtPlotCurve( const QwtText &title ); + + virtual ~QwtPlotCurve(); + + virtual int rtti() const; + + void setPaintAttribute( PaintAttribute, bool on = true ); + bool testPaintAttribute( PaintAttribute ) const; + + void setLegendAttribute( LegendAttribute, bool on = true ); + bool testLegendAttribute( LegendAttribute ) const; + +#ifndef QWT_NO_COMPAT + void setRawSamples( const double *xData, const double *yData, int size ); + void setSamples( const double *xData, const double *yData, int size ); + void setSamples( const QVector &xData, const QVector &yData ); +#endif + void setSamples( const QVector & ); + void setSamples( QwtSeriesData * ); + + int closestPoint( const QPoint &pos, double *dist = NULL ) const; + + double minXValue() const; + double maxXValue() const; + double minYValue() const; + double maxYValue() const; + + void setCurveAttribute( CurveAttribute, bool on = true ); + bool testCurveAttribute( CurveAttribute ) const; + + void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); + void setPen( const QPen & ); + const QPen &pen() const; + + void setBrush( const QBrush & ); + const QBrush &brush() const; + + void setBaseline( double ); + double baseline() const; + + void setStyle( CurveStyle style ); + CurveStyle style() const; + + void setSymbol( QwtSymbol * ); + const QwtSymbol *symbol() const; + + void setCurveFitter( QwtCurveFitter * ); + QwtCurveFitter *curveFitter() const; + + virtual void drawSeries( QPainter *, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; + +protected: + + void init(); + + virtual void drawCurve( QPainter *p, int style, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual void drawSymbols( QPainter *p, const QwtSymbol &, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual void drawLines( QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual void drawSticks( QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual void drawDots( QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual void drawSteps( QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual void fillCurve( QPainter *, + const QwtScaleMap &, const QwtScaleMap &, + const QRectF &canvasRect, QPolygonF & ) const; + + void closePolyline( QPainter *, + const QwtScaleMap &, const QwtScaleMap &, QPolygonF & ) const; + +private: + class PrivateData; + PrivateData *d_data; +}; + +//! boundingRect().left() +inline double QwtPlotCurve::minXValue() const +{ + return boundingRect().left(); +} + +//! boundingRect().right() +inline double QwtPlotCurve::maxXValue() const +{ + return boundingRect().right(); +} + +//! boundingRect().top() +inline double QwtPlotCurve::minYValue() const +{ + return boundingRect().top(); +} + +//! boundingRect().bottom() +inline double QwtPlotCurve::maxYValue() const +{ + return boundingRect().bottom(); +} + +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotCurve::PaintAttributes ) +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotCurve::LegendAttributes ) +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotCurve::CurveAttributes ) + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_dict.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_dict.cpp new file mode 100644 index 0000000..935d6df --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_dict.cpp @@ -0,0 +1,191 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot_dict.h" + +class QwtPlotDict::PrivateData +{ +public: + + class ItemList: public QList + { + public: + void insertItem( QwtPlotItem *item ) + { + if ( item == NULL ) + return; + + QList::iterator it = + qUpperBound( begin(), end(), item, LessZThan() ); + insert( it, item ); + } + + void removeItem( QwtPlotItem *item ) + { + if ( item == NULL ) + return; + + QList::iterator it = + qLowerBound( begin(), end(), item, LessZThan() ); + + for ( ; it != end(); ++it ) + { + if ( item == *it ) + { + erase( it ); + break; + } + } + } + private: + class LessZThan + { + public: + inline bool operator()( const QwtPlotItem *item1, + const QwtPlotItem *item2 ) const + { + return item1->z() < item2->z(); + } + }; + }; + + ItemList itemList; + bool autoDelete; +}; + +/*! + Constructor + + Auto deletion is enabled. + \sa setAutoDelete(), QwtPlotItem::attach() +*/ +QwtPlotDict::QwtPlotDict() +{ + d_data = new QwtPlotDict::PrivateData; + d_data->autoDelete = true; +} + +/*! + Destructor + + If autoDelete() is on, all attached items will be deleted + \sa setAutoDelete(), autoDelete(), QwtPlotItem::attach() +*/ +QwtPlotDict::~QwtPlotDict() +{ + detachItems( QwtPlotItem::Rtti_PlotItem, d_data->autoDelete ); + delete d_data; +} + +/*! + En/Disable Auto deletion + + If Auto deletion is on all attached plot items will be deleted + in the destructor of QwtPlotDict. The default value is on. + + \sa autoDelete(), insertItem() +*/ +void QwtPlotDict::setAutoDelete( bool autoDelete ) +{ + d_data->autoDelete = autoDelete; +} + +/*! + \return true if auto deletion is enabled + \sa setAutoDelete(), insertItem() +*/ +bool QwtPlotDict::autoDelete() const +{ + return d_data->autoDelete; +} + +/*! + Insert a plot item + + \param item PlotItem + \sa removeItem() + */ +void QwtPlotDict::insertItem( QwtPlotItem *item ) +{ + d_data->itemList.insertItem( item ); +} + +/*! + Remove a plot item + + \param item PlotItem + \sa insertItem() + */ +void QwtPlotDict::removeItem( QwtPlotItem *item ) +{ + d_data->itemList.removeItem( item ); +} + +/*! + Detach items from the dictionary + + \param rtti In case of QwtPlotItem::Rtti_PlotItem detach all items + otherwise only those items of the type rtti. + \param autoDelete If true, delete all detached items +*/ +void QwtPlotDict::detachItems( int rtti, bool autoDelete ) +{ + PrivateData::ItemList list = d_data->itemList; + QwtPlotItemIterator it = list.begin(); + while ( it != list.end() ) + { + QwtPlotItem *item = *it; + + ++it; // increment before removing item from the list + + if ( rtti == QwtPlotItem::Rtti_PlotItem || item->rtti() == rtti ) + { + item->attach( NULL ); + if ( autoDelete ) + delete item; + } + } +} + +/*! + \brief A QwtPlotItemList of all attached plot items. + + Use caution when iterating these lists, as removing/detaching an item will + invalidate the iterator. Instead you can place pointers to objects to be + removed in a removal list, and traverse that list later. + + \return List of all attached plot items. +*/ +const QwtPlotItemList &QwtPlotDict::itemList() const +{ + return d_data->itemList; +} + +/*! + \return List of all attached plot items of a specific type. + \param rtti See QwtPlotItem::RttiValues + \sa QwtPlotItem::rtti() +*/ +QwtPlotItemList QwtPlotDict::itemList( int rtti ) const +{ + if ( rtti == QwtPlotItem::Rtti_PlotItem ) + return d_data->itemList; + + QwtPlotItemList items; + + PrivateData::ItemList list = d_data->itemList; + for ( QwtPlotItemIterator it = list.begin(); it != list.end(); ++it ) + { + QwtPlotItem *item = *it; + if ( item->rtti() == rtti ) + items += item; + } + + return items; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_dict.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_dict.h new file mode 100644 index 0000000..4da2ea2 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_dict.h @@ -0,0 +1,58 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +/*! \file !*/ +#ifndef QWT_PLOT_DICT +#define QWT_PLOT_DICT + +#include "qwt_global.h" +#include "qwt_plot_item.h" +#include + +/// \var typedef QList< QwtPlotItem *> QwtPlotItemList +/// \brief See QT 4.x assistant documentation for QList +typedef QList QwtPlotItemList; +typedef QList::ConstIterator QwtPlotItemIterator; + +/*! + \brief A dictionary for plot items + + QwtPlotDict organizes plot items in increasing z-order. + If autoDelete() is enabled, all attached items will be deleted + in the destructor of the dictionary. + QwtPlotDict can be used to get access to all QwtPlotItem items - or all + items of a specific type - that are currently on the plot. + + \sa QwtPlotItem::attach(), QwtPlotItem::detach(), QwtPlotItem::z() +*/ +class QWT_EXPORT QwtPlotDict +{ +public: + explicit QwtPlotDict(); + virtual ~QwtPlotDict(); + + void setAutoDelete( bool ); + bool autoDelete() const; + + const QwtPlotItemList& itemList() const; + QwtPlotItemList itemList( int rtti ) const; + + void detachItems( int rtti = QwtPlotItem::Rtti_PlotItem, + bool autoDelete = true ); + +protected: + void insertItem( QwtPlotItem * ); + void removeItem( QwtPlotItem * ); + +private: + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_directpainter.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_directpainter.cpp new file mode 100644 index 0000000..53f8e32 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_directpainter.cpp @@ -0,0 +1,321 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot_directpainter.h" +#include "qwt_scale_map.h" +#include "qwt_plot.h" +#include "qwt_plot_canvas.h" +#include "qwt_plot_seriesitem.h" +#include +#include +#include +#include + +static inline void qwtRenderItem( + QPainter *painter, const QRect &canvasRect, + QwtPlotSeriesItem *seriesItem, int from, int to ) +{ + // A minor performance improvement is possible + // with caching the maps. TODO ... + + QwtPlot *plot = seriesItem->plot(); + const QwtScaleMap xMap = plot->canvasMap( seriesItem->xAxis() ); + const QwtScaleMap yMap = plot->canvasMap( seriesItem->yAxis() ); + + painter->setRenderHint( QPainter::Antialiasing, + seriesItem->testRenderHint( QwtPlotItem::RenderAntialiased ) ); + seriesItem->drawSeries( painter, xMap, yMap, canvasRect, from, to ); +} + +static inline bool qwtHasBackingStore( const QwtPlotCanvas *canvas ) +{ + return canvas->testPaintAttribute( QwtPlotCanvas::BackingStore ) + && canvas->backingStore() && !canvas->backingStore()->isNull(); +} + +class QwtPlotDirectPainter::PrivateData +{ +public: + PrivateData(): + attributes( 0 ), + hasClipping(false), + seriesItem( NULL ), + from( 0 ), + to( 0 ) + { + } + + QwtPlotDirectPainter::Attributes attributes; + + bool hasClipping; + QRegion clipRegion; + + QPainter painter; + + QwtPlotSeriesItem *seriesItem; + int from; + int to; +}; + +//! Constructor +QwtPlotDirectPainter::QwtPlotDirectPainter( QObject *parent ): + QObject( parent ) +{ + d_data = new PrivateData; +} + +//! Destructor +QwtPlotDirectPainter::~QwtPlotDirectPainter() +{ + delete d_data; +} + +/*! + Change an attribute + + \param attribute Attribute to change + \param on On/Off + + \sa Attribute, testAttribute() +*/ +void QwtPlotDirectPainter::setAttribute( Attribute attribute, bool on ) +{ + if ( bool( d_data->attributes & attribute ) != on ) + { + if ( on ) + d_data->attributes |= attribute; + else + d_data->attributes &= ~attribute; + + if ( ( attribute == AtomicPainter ) && on ) + reset(); + } +} + +/*! + \return True, when attribute is enabled + \param attribute Attribute to be tested + \sa Attribute, setAttribute() +*/ +bool QwtPlotDirectPainter::testAttribute( Attribute attribute ) const +{ + return d_data->attributes & attribute; +} + +/*! + En/Disables clipping + + \param enable Enables clipping is true, disable it otherwise + \sa hasClipping(), clipRegion(), setClipRegion() +*/ +void QwtPlotDirectPainter::setClipping( bool enable ) +{ + d_data->hasClipping = enable; +} + +/*! + \return true, when clipping is enabled + \sa setClipping(), clipRegion(), setClipRegion() +*/ +bool QwtPlotDirectPainter::hasClipping() const +{ + return d_data->hasClipping; +} + +/*! + \brief Assign a clip region and enable clipping + + Depending on the environment setting a proper clip region might improve + the performance heavily. F.e. on Qt embedded only the clipped part of + the backing store will be copied to a ( maybe unaccelerated ) frame buffer + device. + + \param region Clip region + \sa clipRegion(), hasClipping(), setClipping() +*/ +void QwtPlotDirectPainter::setClipRegion( const QRegion ®ion ) +{ + d_data->clipRegion = region; + d_data->hasClipping = true; +} + +/*! + \return Currently set clip region. + \sa setClipRegion(), setClipping(), hasClipping() +*/ +QRegion QwtPlotDirectPainter::clipRegion() const +{ + return d_data->clipRegion; +} + +/*! + \brief Draw a set of points of a seriesItem. + + When observing an measurement while it is running, new points have to be + added to an existing seriesItem. drawSeries() can be used to display them avoiding + a complete redraw of the canvas. + + Setting plot()->canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true); + will result in faster painting, if the paint engine of the canvas widget + supports this feature. + + \param seriesItem Item to be painted + \param from Index of the first point to be painted + \param to Index of the last point to be painted. If to < 0 the + series will be painted to its last point. +*/ +void QwtPlotDirectPainter::drawSeries( + QwtPlotSeriesItem *seriesItem, int from, int to ) +{ + if ( seriesItem == NULL || seriesItem->plot() == NULL ) + return; + + QWidget *canvas = seriesItem->plot()->canvas(); + const QRect canvasRect = canvas->contentsRect(); + + QwtPlotCanvas *plotCanvas = qobject_cast( canvas ); + + if ( plotCanvas && qwtHasBackingStore( plotCanvas ) ) + { + QPainter painter( const_cast( plotCanvas->backingStore() ) ); + + if ( d_data->hasClipping ) + painter.setClipRegion( d_data->clipRegion ); + + qwtRenderItem( &painter, canvasRect, seriesItem, from, to ); + + painter.end(); + + if ( testAttribute( QwtPlotDirectPainter::FullRepaint ) ) + { + plotCanvas->repaint(); + return; + } + } + + bool immediatePaint = true; + if ( !canvas->testAttribute( Qt::WA_WState_InPaintEvent ) ) + { +#if QT_VERSION < 0x050000 + if ( !canvas->testAttribute( Qt::WA_PaintOutsidePaintEvent ) ) +#endif + immediatePaint = false; + } + + if ( immediatePaint ) + { + if ( !d_data->painter.isActive() ) + { + reset(); + + d_data->painter.begin( canvas ); + canvas->installEventFilter( this ); + } + + if ( d_data->hasClipping ) + { + d_data->painter.setClipRegion( + QRegion( canvasRect ) & d_data->clipRegion ); + } + else + { + if ( !d_data->painter.hasClipping() ) + d_data->painter.setClipRect( canvasRect ); + } + + qwtRenderItem( &d_data->painter, canvasRect, seriesItem, from, to ); + + if ( d_data->attributes & QwtPlotDirectPainter::AtomicPainter ) + { + reset(); + } + else + { + if ( d_data->hasClipping ) + d_data->painter.setClipping( false ); + } + } + else + { + reset(); + + d_data->seriesItem = seriesItem; + d_data->from = from; + d_data->to = to; + + QRegion clipRegion = canvasRect; + if ( d_data->hasClipping ) + clipRegion &= d_data->clipRegion; + + canvas->installEventFilter( this ); + canvas->repaint(clipRegion); + canvas->removeEventFilter( this ); + + d_data->seriesItem = NULL; + } +} + +//! Close the internal QPainter +void QwtPlotDirectPainter::reset() +{ + if ( d_data->painter.isActive() ) + { + QWidget *w = static_cast( d_data->painter.device() ); + if ( w ) + w->removeEventFilter( this ); + + d_data->painter.end(); + } +} + +//! Event filter +bool QwtPlotDirectPainter::eventFilter( QObject *, QEvent *event ) +{ + if ( event->type() == QEvent::Paint ) + { + reset(); + + if ( d_data->seriesItem ) + { + const QPaintEvent *pe = static_cast< QPaintEvent *>( event ); + + QWidget *canvas = d_data->seriesItem->plot()->canvas(); + + QPainter painter( canvas ); + painter.setClipRegion( pe->region() ); + + bool doCopyCache = testAttribute( CopyBackingStore ); + + if ( doCopyCache ) + { + QwtPlotCanvas *plotCanvas = + qobject_cast( canvas ); + if ( plotCanvas ) + { + doCopyCache = qwtHasBackingStore( plotCanvas ); + if ( doCopyCache ) + { + painter.drawPixmap( plotCanvas->contentsRect().topLeft(), + *plotCanvas->backingStore() ); + } + } + } + + if ( !doCopyCache ) + { + qwtRenderItem( &painter, canvas->contentsRect(), + d_data->seriesItem, d_data->from, d_data->to ); + } + + return true; // don't call QwtPlotCanvas::paintEvent() + } + } + + return false; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_directpainter.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_directpainter.h new file mode 100644 index 0000000..d39c711 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_directpainter.h @@ -0,0 +1,100 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PLOT_DIRECT_PAINTER_H +#define QWT_PLOT_DIRECT_PAINTER_H + +#include "qwt_global.h" +#include + +class QRegion; +class QwtPlotSeriesItem; + +/*! + \brief Painter object trying to paint incrementally + + Often applications want to display samples while they are + collected. When there are too many samples complete replots + will be expensive to be processed in a collection cycle. + + QwtPlotDirectPainter offers an API to paint + subsets ( f.e all additions points ) without erasing/repainting + the plot canvas. + + On certain environments it might be important to calculate a proper + clip region before painting. F.e. for Qt Embedded only the clipped part + of the backing store will be copied to a ( maybe unaccelerated ) + frame buffer. + + \warning Incremental painting will only help when no replot is triggered + by another operation ( like changing scales ) and nothing needs + to be erased. +*/ +class QWT_EXPORT QwtPlotDirectPainter: public QObject +{ +public: + /*! + \brief Paint attributes + \sa setAttribute(), testAttribute(), drawSeries() + */ + enum Attribute + { + /*! + Initializing a QPainter is an expensive operation. + When AtomicPainter is set each call of drawSeries() opens/closes + a temporary QPainter. Otherwise QwtPlotDirectPainter tries to + use the same QPainter as long as possible. + */ + AtomicPainter = 0x01, + + /*! + When FullRepaint is set the plot canvas is explicitly repainted + after the samples have been rendered. + */ + FullRepaint = 0x02, + + /*! + When QwtPlotCanvas::BackingStore is enabled the painter + has to paint to the backing store and the widget. In certain + situations/environments it might be faster to paint to + the backing store only and then copy the backing store to the canvas. + This flag can also be useful for settings, where Qt fills the + the clip region with the widget background. + */ + CopyBackingStore = 0x04 + }; + + //! Paint attributes + typedef QFlags Attributes; + + QwtPlotDirectPainter( QObject *parent = NULL ); + virtual ~QwtPlotDirectPainter(); + + void setAttribute( Attribute, bool on ); + bool testAttribute( Attribute ) const; + + void setClipping( bool ); + bool hasClipping() const; + + void setClipRegion( const QRegion & ); + QRegion clipRegion() const; + + void drawSeries( QwtPlotSeriesItem *, int from, int to ); + void reset(); + + virtual bool eventFilter( QObject *, QEvent * ); + +private: + class PrivateData; + PrivateData *d_data; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotDirectPainter::Attributes ) + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_glcanvas.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_glcanvas.cpp new file mode 100644 index 0000000..2900194 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_glcanvas.cpp @@ -0,0 +1,377 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot_glcanvas.h" +#include "qwt_plot.h" +#include "qwt_painter.h" +#include +#include +#include +#include +#include + +#define FIX_GL_TRANSLATION 0 + +static QWidget *qwtBGWidget( QWidget *widget ) +{ + QWidget *w = widget; + + for ( ; w->parentWidget() != NULL; w = w->parentWidget() ) + { + if ( w->autoFillBackground() || + w->testAttribute( Qt::WA_StyledBackground ) ) + { + return w; + } + } + + return w; +} + +static void qwtUpdateContentsRect( QwtPlotGLCanvas *canvas ) +{ + const int fw = canvas->frameWidth(); + canvas->setContentsMargins( fw, fw, fw, fw ); +} + +class QwtPlotGLCanvas::PrivateData +{ +public: + PrivateData(): + frameStyle( QFrame::Panel | QFrame::Sunken), + lineWidth( 2 ), + midLineWidth( 0 ) + { + } + + int frameStyle; + int lineWidth; + int midLineWidth; +}; + +class QwtPlotGLCanvasFormat: public QGLFormat +{ +public: + QwtPlotGLCanvasFormat(): + QGLFormat( QGLFormat::defaultFormat() ) + { + setSampleBuffers( true ); + } +}; + +/*! + \brief Constructor + + \param plot Parent plot widget + \sa QwtPlot::setCanvas() +*/ +QwtPlotGLCanvas::QwtPlotGLCanvas( QwtPlot *plot ): + QGLWidget( QwtPlotGLCanvasFormat(), plot ) +{ + d_data = new PrivateData; + +#ifndef QT_NO_CURSOR + setCursor( Qt::CrossCursor ); +#endif + + setAutoFillBackground( true ); + qwtUpdateContentsRect( this ); +} + +//! Destructor +QwtPlotGLCanvas::~QwtPlotGLCanvas() +{ + delete d_data; +} + +/*! + Set the frame style + + \param style The bitwise OR between a shape and a shadow. + + \sa frameStyle(), QFrame::setFrameStyle(), + setFrameShadow(), setFrameShape() + */ +void QwtPlotGLCanvas::setFrameStyle( int style ) +{ + if ( style != d_data->frameStyle ) + { + d_data->frameStyle = style; + qwtUpdateContentsRect( this ); + + update(); + } +} + +/*! + \return The bitwise OR between a frameShape() and a frameShadow() + \sa setFrameStyle(), QFrame::frameStyle() + */ +int QwtPlotGLCanvas::frameStyle() const +{ + return d_data->frameStyle; +} + +/*! + Set the frame shadow + + \param shadow Frame shadow + \sa frameShadow(), setFrameShape(), QFrame::setFrameShadow() + */ +void QwtPlotGLCanvas::setFrameShadow( Shadow shadow ) +{ + setFrameStyle(( d_data->frameStyle & QFrame::Shape_Mask ) | shadow ); +} + +/*! + \return Frame shadow + \sa setFrameShadow(), QFrame::setFrameShadow() + */ +QwtPlotGLCanvas::Shadow QwtPlotGLCanvas::frameShadow() const +{ + return (Shadow) ( d_data->frameStyle & QFrame::Shadow_Mask ); +} + +/*! + Set the frame shape + + \param shape Frame shape + \sa frameShape(), setFrameShadow(), QFrame::frameShape() + */ +void QwtPlotGLCanvas::setFrameShape( Shape shape ) +{ + setFrameStyle( ( d_data->frameStyle & QFrame::Shadow_Mask ) | shape ); +} + +/*! + \return Frame shape + \sa setFrameShape(), QFrame::frameShape() + */ +QwtPlotGLCanvas::Shape QwtPlotGLCanvas::frameShape() const +{ + return (Shape) ( d_data->frameStyle & QFrame::Shape_Mask ); +} + +/*! + Set the frame line width + + The default line width is 2 pixels. + + \param width Line width of the frame + \sa lineWidth(), setMidLineWidth() +*/ +void QwtPlotGLCanvas::setLineWidth( int width ) +{ + width = qMax( width, 0 ); + if ( width != d_data->lineWidth ) + { + d_data->lineWidth = qMax( width, 0 ); + qwtUpdateContentsRect( this ); + update(); + } +} + +/*! + \return Line width of the frame + \sa setLineWidth(), midLineWidth() + */ +int QwtPlotGLCanvas::lineWidth() const +{ + return d_data->lineWidth; +} + +/*! + Set the frame mid line width + + The default midline width is 0 pixels. + + \param width Midline width of the frame + \sa midLineWidth(), setLineWidth() +*/ +void QwtPlotGLCanvas::setMidLineWidth( int width ) +{ + width = qMax( width, 0 ); + if ( width != d_data->midLineWidth ) + { + d_data->midLineWidth = width; + qwtUpdateContentsRect( this ); + update(); + } +} + +/*! + \return Midline width of the frame + \sa setMidLineWidth(), lineWidth() + */ +int QwtPlotGLCanvas::midLineWidth() const +{ + return d_data->midLineWidth; +} + +/*! + \return Frame width depending on the style, line width and midline width. + */ +int QwtPlotGLCanvas::frameWidth() const +{ + return ( frameStyle() != NoFrame ) ? d_data->lineWidth : 0; +} + +/*! + Paint event + + \param event Paint event + \sa QwtPlot::drawCanvas() +*/ +void QwtPlotGLCanvas::paintEvent( QPaintEvent *event ) +{ + Q_UNUSED( event ); + + QPainter painter( this ); + +#if FIX_GL_TRANSLATION + if ( painter.paintEngine()->type() == QPaintEngine::OpenGL2 ) + { + // work around a translation bug of QPaintEngine::OpenGL2 + painter.translate( 1, 1 ); + } +#endif + + drawBackground( &painter ); + drawItems( &painter ); + + if ( !testAttribute( Qt::WA_StyledBackground ) ) + { + if ( frameWidth() > 0 ) + drawBorder( &painter ); + } +} +/*! + Qt event handler for QEvent::PolishRequest and QEvent::StyleChange + \param event Qt Event + \return See QGLWidget::event() +*/ +bool QwtPlotGLCanvas::event( QEvent *event ) +{ + const bool ok = QGLWidget::event( event ); + + if ( event->type() == QEvent::PolishRequest || + event->type() == QEvent::StyleChange ) + { + // assuming, that we always have a styled background + // when we have a style sheet + + setAttribute( Qt::WA_StyledBackground, + testAttribute( Qt::WA_StyleSheet ) ); + } + + return ok; +} + +/*! + Draw the plot items + \param painter Painter + + \sa QwtPlot::drawCanvas() +*/ +void QwtPlotGLCanvas::drawItems( QPainter *painter ) +{ + painter->save(); + + painter->setClipRect( contentsRect(), Qt::IntersectClip ); + + QwtPlot *plot = qobject_cast< QwtPlot *>( parent() ); + if ( plot ) + plot->drawCanvas( painter ); + + painter->restore(); +} + +/*! + Draw the background of the canvas + \param painter Painter +*/ +void QwtPlotGLCanvas::drawBackground( QPainter *painter ) +{ + painter->save(); + + QWidget *w = qwtBGWidget( this ); + + const QPoint off = mapTo( w, QPoint() ); + painter->translate( -off ); + + const QRect fillRect = rect().translated( off ); + + if ( w->testAttribute( Qt::WA_StyledBackground ) ) + { + painter->setClipRect( fillRect ); + + QStyleOption opt; + opt.initFrom( w ); + w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w); + } + else + { + painter->fillRect( fillRect, + w->palette().brush( w->backgroundRole() ) ); + } + + painter->restore(); +} + +/*! + Draw the border of the canvas + \param painter Painter +*/ +void QwtPlotGLCanvas::drawBorder( QPainter *painter ) +{ + const int fw = frameWidth(); + if ( fw <= 0 ) + return; + + if ( frameShadow() == QwtPlotGLCanvas::Plain ) + { + qDrawPlainRect( painter, frameRect(), + palette().shadow().color(), lineWidth() ); + } + else + { + if ( frameShape() == QwtPlotGLCanvas::Box ) + { + qDrawShadeRect( painter, frameRect(), palette(), + frameShadow() == Sunken, lineWidth(), midLineWidth() ); + } + else + { + qDrawShadePanel( painter, frameRect(), palette(), + frameShadow() == Sunken, lineWidth() ); + } + } +} + +//! Calls repaint() +void QwtPlotGLCanvas::replot() +{ + repaint(); +} + +/*! + \return Empty path +*/ +QPainterPath QwtPlotGLCanvas::borderPath( const QRect &rect ) const +{ + Q_UNUSED( rect ); + return QPainterPath(); +} + +//! \return The rectangle where the frame is drawn in. +QRect QwtPlotGLCanvas::frameRect() const +{ + const int fw = frameWidth(); + return contentsRect().adjusted( -fw, -fw, fw, fw ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_glcanvas.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_glcanvas.h new file mode 100644 index 0000000..da0fb0e --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_glcanvas.h @@ -0,0 +1,130 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PLOT_GLCANVAS_H +#define QWT_PLOT_GLCANVAS_H + +#include "qwt_global.h" +#include +#include + +class QwtPlot; + +/*! + \brief An alternative canvas for a QwtPlot derived from QGLWidget + + QwtPlotGLCanvas implements the very basics to act as canvas + inside of a QwtPlot widget. It might be extended to a full + featured alternative to QwtPlotCanvas in a future version of Qwt. + + Even if QwtPlotGLCanvas is not derived from QFrame it imitates + its API. When using style sheets it supports the box model - beside + backgrounds with rounded borders. + + \sa QwtPlot::setCanvas(), QwtPlotCanvas + + \note With Qt4 you might want to use the QPaintEngine::OpenGL paint engine + ( see QGL::setPreferredPaintEngine() ). On a Linux test system + QPaintEngine::OpenGL2 shows very basic problems like translated + geometries. +*/ +class QWT_EXPORT QwtPlotGLCanvas: public QGLWidget +{ + Q_OBJECT + + Q_ENUMS( Shape Shadow ) + + Q_PROPERTY( Shadow frameShadow READ frameShadow WRITE setFrameShadow ) + Q_PROPERTY( Shape frameShape READ frameShape WRITE setFrameShape ) + Q_PROPERTY( int lineWidth READ lineWidth WRITE setLineWidth ) + Q_PROPERTY( int midLineWidth READ midLineWidth WRITE setMidLineWidth ) + Q_PROPERTY( int frameWidth READ frameWidth ) + Q_PROPERTY( QRect frameRect READ frameRect DESIGNABLE false ) + +public: + /*! + \brief Frame shadow + + Unfortunately it is not possible to use QFrame::Shadow + as a property of a widget that is not derived from QFrame. + The following enum is made for the designer only. It is safe + to use QFrame::Shadow instead. + */ + enum Shadow + { + //! QFrame::Plain + Plain = QFrame::Plain, + + //! QFrame::Raised + Raised = QFrame::Raised, + + //! QFrame::Sunken + Sunken = QFrame::Sunken + }; + + /*! + \brief Frame shape + + Unfortunately it is not possible to use QFrame::Shape + as a property of a widget that is not derived from QFrame. + The following enum is made for the designer only. It is safe + to use QFrame::Shadow instead. + + \note QFrame::StyledPanel and QFrame::WinPanel are unsuported + and will be displayed as QFrame::Panel. + */ + enum Shape + { + NoFrame = QFrame::NoFrame, + + Box = QFrame::Box, + Panel = QFrame::Panel + }; + + explicit QwtPlotGLCanvas( QwtPlot * = NULL ); + virtual ~QwtPlotGLCanvas(); + + void setFrameStyle( int style ); + int frameStyle() const; + + void setFrameShadow( Shadow ); + Shadow frameShadow() const; + + void setFrameShape( Shape ); + Shape frameShape() const; + + void setLineWidth( int ); + int lineWidth() const; + + void setMidLineWidth( int ); + int midLineWidth() const; + + int frameWidth() const; + QRect frameRect() const; + + Q_INVOKABLE QPainterPath borderPath( const QRect & ) const; + + virtual bool event( QEvent * ); + +public Q_SLOTS: + void replot(); + +protected: + virtual void paintEvent( QPaintEvent * ); + + virtual void drawBackground( QPainter * ); + virtual void drawBorder( QPainter * ); + virtual void drawItems( QPainter * ); + +private: + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_grid.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_grid.cpp new file mode 100644 index 0000000..31fb821 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_grid.cpp @@ -0,0 +1,438 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot_grid.h" +#include "qwt_painter.h" +#include "qwt_text.h" +#include "qwt_scale_map.h" +#include "qwt_scale_div.h" +#include "qwt_math.h" +#include +#include + +class QwtPlotGrid::PrivateData +{ +public: + PrivateData(): + xEnabled( true ), + yEnabled( true ), + xMinEnabled( false ), + yMinEnabled( false ) + { + } + + bool xEnabled; + bool yEnabled; + bool xMinEnabled; + bool yMinEnabled; + + QwtScaleDiv xScaleDiv; + QwtScaleDiv yScaleDiv; + + QPen majorPen; + QPen minorPen; +}; + +//! Enables major grid, disables minor grid +QwtPlotGrid::QwtPlotGrid(): + QwtPlotItem( QwtText( "Grid" ) ) +{ + d_data = new PrivateData; + + setItemInterest( QwtPlotItem::ScaleInterest, true ); + setZ( 10.0 ); +} + +//! Destructor +QwtPlotGrid::~QwtPlotGrid() +{ + delete d_data; +} + +//! \return QwtPlotItem::Rtti_PlotGrid +int QwtPlotGrid::rtti() const +{ + return QwtPlotItem::Rtti_PlotGrid; +} + +/*! + \brief Enable or disable vertical grid lines + \param on Enable (true) or disable + + \sa Minor grid lines can be enabled or disabled with + enableXMin() +*/ +void QwtPlotGrid::enableX( bool on ) +{ + if ( d_data->xEnabled != on ) + { + d_data->xEnabled = on; + + legendChanged(); + itemChanged(); + } +} + +/*! + \brief Enable or disable horizontal grid lines + \param on Enable (true) or disable + \sa Minor grid lines can be enabled or disabled with enableYMin() +*/ +void QwtPlotGrid::enableY( bool on ) +{ + if ( d_data->yEnabled != on ) + { + d_data->yEnabled = on; + + legendChanged(); + itemChanged(); + } +} + +/*! + \brief Enable or disable minor vertical grid lines. + \param on Enable (true) or disable + \sa enableX() +*/ +void QwtPlotGrid::enableXMin( bool on ) +{ + if ( d_data->xMinEnabled != on ) + { + d_data->xMinEnabled = on; + + legendChanged(); + itemChanged(); + } +} + +/*! + \brief Enable or disable minor horizontal grid lines + \param on Enable (true) or disable + \sa enableY() +*/ +void QwtPlotGrid::enableYMin( bool on ) +{ + if ( d_data->yMinEnabled != on ) + { + d_data->yMinEnabled = on; + + legendChanged(); + itemChanged(); + } +} + +/*! + Assign an x axis scale division + + \param scaleDiv Scale division +*/ +void QwtPlotGrid::setXDiv( const QwtScaleDiv &scaleDiv ) +{ + if ( d_data->xScaleDiv != scaleDiv ) + { + d_data->xScaleDiv = scaleDiv; + itemChanged(); + } +} + +/*! + Assign a y axis division + + \param scaleDiv Scale division +*/ +void QwtPlotGrid::setYDiv( const QwtScaleDiv &scaleDiv ) +{ + if ( d_data->yScaleDiv != scaleDiv ) + { + d_data->yScaleDiv = scaleDiv; + itemChanged(); + } +} + +/*! + Build and assign a pen for both major and minor grid lines + + In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it + non cosmetic ( see QPen::isCosmetic() ). This method has been introduced + to hide this incompatibility. + + \param color Pen color + \param width Pen width + \param style Pen style + + \sa pen(), brush() + */ +void QwtPlotGrid::setPen( const QColor &color, qreal width, Qt::PenStyle style ) +{ + setPen( QPen( color, width, style ) ); +} + +/*! + Assign a pen for both major and minor grid lines + + \param pen Pen + \sa setMajorPen(), setMinorPen() +*/ +void QwtPlotGrid::setPen( const QPen &pen ) +{ + if ( d_data->majorPen != pen || d_data->minorPen != pen ) + { + d_data->majorPen = pen; + d_data->minorPen = pen; + + legendChanged(); + itemChanged(); + } +} + +/*! + Build and assign a pen for both major grid lines + + In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it + non cosmetic ( see QPen::isCosmetic() ). This method has been introduced + to hide this incompatibility. + + \param color Pen color + \param width Pen width + \param style Pen style + + \sa pen(), brush() + */ +void QwtPlotGrid::setMajorPen( const QColor &color, qreal width, Qt::PenStyle style ) +{ + setMajorPen( QPen( color, width, style ) ); +} + +/*! + Assign a pen for the major grid lines + + \param pen Pen + \sa majorPen(), setMinorPen(), setPen() +*/ +void QwtPlotGrid::setMajorPen( const QPen &pen ) +{ + if ( d_data->majorPen != pen ) + { + d_data->majorPen = pen; + + legendChanged(); + itemChanged(); + } +} + +/*! + Build and assign a pen for the minor grid lines + + In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it + non cosmetic ( see QPen::isCosmetic() ). This method has been introduced + to hide this incompatibility. + + \param color Pen color + \param width Pen width + \param style Pen style + + \sa pen(), brush() + */ +void QwtPlotGrid::setMinorPen( const QColor &color, qreal width, Qt::PenStyle style ) +{ + setMinorPen( QPen( color, width, style ) ); +} + +/*! + Assign a pen for the minor grid lines + + \param pen Pen + \sa minorPen(), setMajorPen(), setPen() +*/ +void QwtPlotGrid::setMinorPen( const QPen &pen ) +{ + if ( d_data->minorPen != pen ) + { + d_data->minorPen = pen; + + legendChanged(); + itemChanged(); + } +} + +/*! + \brief Draw the grid + + The grid is drawn into the bounding rectangle such that + grid lines begin and end at the rectangle's borders. The X and Y + maps are used to map the scale divisions into the drawing region + screen. + + \param painter Painter + \param xMap X axis map + \param yMap Y axis + \param canvasRect Contents rectangle of the plot canvas +*/ +void QwtPlotGrid::draw( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect ) const +{ + // draw minor grid lines + QPen minorPen = d_data->minorPen; + minorPen.setCapStyle( Qt::FlatCap ); + + painter->setPen( minorPen ); + + if ( d_data->xEnabled && d_data->xMinEnabled ) + { + drawLines( painter, canvasRect, Qt::Vertical, xMap, + d_data->xScaleDiv.ticks( QwtScaleDiv::MinorTick ) ); + drawLines( painter, canvasRect, Qt::Vertical, xMap, + d_data->xScaleDiv.ticks( QwtScaleDiv::MediumTick ) ); + } + + if ( d_data->yEnabled && d_data->yMinEnabled ) + { + drawLines( painter, canvasRect, Qt::Horizontal, yMap, + d_data->yScaleDiv.ticks( QwtScaleDiv::MinorTick ) ); + drawLines( painter, canvasRect, Qt::Horizontal, yMap, + d_data->yScaleDiv.ticks( QwtScaleDiv::MediumTick ) ); + } + + // draw major grid lines + QPen majorPen = d_data->majorPen; + majorPen.setCapStyle( Qt::FlatCap ); + + painter->setPen( majorPen ); + + if ( d_data->xEnabled ) + { + drawLines( painter, canvasRect, Qt::Vertical, xMap, + d_data->xScaleDiv.ticks( QwtScaleDiv::MajorTick ) ); + } + + if ( d_data->yEnabled ) + { + drawLines( painter, canvasRect, Qt::Horizontal, yMap, + d_data->yScaleDiv.ticks( QwtScaleDiv::MajorTick ) ); + } +} + +void QwtPlotGrid::drawLines( QPainter *painter, const QRectF &canvasRect, + Qt::Orientation orientation, const QwtScaleMap &scaleMap, + const QList &values ) const +{ + const double x1 = canvasRect.left(); + const double x2 = canvasRect.right() - 1.0; + const double y1 = canvasRect.top(); + const double y2 = canvasRect.bottom() - 1.0; + + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + for ( int i = 0; i < values.count(); i++ ) + { + double value = scaleMap.transform( values[i] ); + if ( doAlign ) + value = qRound( value ); + + if ( orientation == Qt::Horizontal ) + { + if ( qwtFuzzyGreaterOrEqual( value, y1 ) && + qwtFuzzyLessOrEqual( value, y2 ) ) + { + QwtPainter::drawLine( painter, x1, value, x2, value ); + } + } + else + { + if ( qwtFuzzyGreaterOrEqual( value, x1 ) && + qwtFuzzyLessOrEqual( value, x2 ) ) + { + QwtPainter::drawLine( painter, value, y1, value, y2 ); + } + } + } +} + +/*! + \return the pen for the major grid lines + \sa setMajorPen(), setMinorPen(), setPen() +*/ +const QPen &QwtPlotGrid::majorPen() const +{ + return d_data->majorPen; +} + +/*! + \return the pen for the minor grid lines + \sa setMinorPen(), setMajorPen(), setPen() +*/ +const QPen &QwtPlotGrid::minorPen() const +{ + return d_data->minorPen; +} + +/*! + \return true if vertical grid lines are enabled + \sa enableX() +*/ +bool QwtPlotGrid::xEnabled() const +{ + return d_data->xEnabled; +} + +/*! + \return true if minor vertical grid lines are enabled + \sa enableXMin() +*/ +bool QwtPlotGrid::xMinEnabled() const +{ + return d_data->xMinEnabled; +} + +/*! + \return true if horizontal grid lines are enabled + \sa enableY() +*/ +bool QwtPlotGrid::yEnabled() const +{ + return d_data->yEnabled; +} + +/*! + \return true if minor horizontal grid lines are enabled + \sa enableYMin() +*/ +bool QwtPlotGrid::yMinEnabled() const +{ + return d_data->yMinEnabled; +} + + +/*! \return the scale division of the x axis */ +const QwtScaleDiv &QwtPlotGrid::xScaleDiv() const +{ + return d_data->xScaleDiv; +} + +/*! \return the scale division of the y axis */ +const QwtScaleDiv &QwtPlotGrid::yScaleDiv() const +{ + return d_data->yScaleDiv; +} + +/*! + Update the grid to changes of the axes scale division + + \param xScaleDiv Scale division of the x-axis + \param yScaleDiv Scale division of the y-axis + + \sa QwtPlot::updateAxes() +*/ +void QwtPlotGrid::updateScaleDiv( const QwtScaleDiv& xScaleDiv, + const QwtScaleDiv& yScaleDiv ) +{ + setXDiv( xScaleDiv ); + setYDiv( yScaleDiv ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_grid.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_grid.h new file mode 100644 index 0000000..50c343a --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_grid.h @@ -0,0 +1,87 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PLOT_GRID_H +#define QWT_PLOT_GRID_H + +#include "qwt_global.h" +#include "qwt_plot_item.h" +#include "qwt_scale_div.h" + +class QPainter; +class QPen; +class QwtScaleMap; +class QwtScaleDiv; + +/*! + \brief A class which draws a coordinate grid + + The QwtPlotGrid class can be used to draw a coordinate grid. + A coordinate grid consists of major and minor vertical + and horizontal grid lines. The locations of the grid lines + are determined by the X and Y scale divisions which can + be assigned with setXDiv() and setYDiv(). + The draw() member draws the grid within a bounding + rectangle. +*/ + +class QWT_EXPORT QwtPlotGrid: public QwtPlotItem +{ +public: + explicit QwtPlotGrid(); + virtual ~QwtPlotGrid(); + + virtual int rtti() const; + + void enableX( bool tf ); + bool xEnabled() const; + + void enableY( bool tf ); + bool yEnabled() const; + + void enableXMin( bool tf ); + bool xMinEnabled() const; + + void enableYMin( bool tf ); + bool yMinEnabled() const; + + void setXDiv( const QwtScaleDiv &sx ); + const QwtScaleDiv &xScaleDiv() const; + + void setYDiv( const QwtScaleDiv &sy ); + const QwtScaleDiv &yScaleDiv() const; + + void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); + void setPen( const QPen & ); + + void setMajorPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); + void setMajorPen( const QPen & ); + const QPen& majorPen() const; + + void setMinorPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); + void setMinorPen( const QPen &p ); + const QPen& minorPen() const; + + virtual void draw( QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &rect ) const; + + virtual void updateScaleDiv( + const QwtScaleDiv &xMap, const QwtScaleDiv &yMap ); + +private: + void drawLines( QPainter *painter, const QRectF &, + Qt::Orientation orientation, const QwtScaleMap &, + const QList & ) const; + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_histogram.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_histogram.cpp new file mode 100644 index 0000000..fd4a9d8 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_histogram.cpp @@ -0,0 +1,690 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot_histogram.h" +#include "qwt_plot.h" +#include "qwt_painter.h" +#include "qwt_column_symbol.h" +#include "qwt_scale_map.h" +#include +#include + +static inline bool qwtIsCombinable( const QwtInterval &d1, + const QwtInterval &d2 ) +{ + if ( d1.isValid() && d2.isValid() ) + { + if ( d1.maxValue() == d2.minValue() ) + { + if ( !( d1.borderFlags() & QwtInterval::ExcludeMaximum + && d2.borderFlags() & QwtInterval::ExcludeMinimum ) ) + { + return true; + } + } + } + + return false; +} + +class QwtPlotHistogram::PrivateData +{ +public: + PrivateData(): + baseline( 0.0 ), + style( Columns ), + symbol( NULL ) + { + } + + ~PrivateData() + { + delete symbol; + } + + double baseline; + + QPen pen; + QBrush brush; + QwtPlotHistogram::HistogramStyle style; + const QwtColumnSymbol *symbol; +}; + +/*! + Constructor + \param title Title of the histogram. +*/ +QwtPlotHistogram::QwtPlotHistogram( const QwtText &title ): + QwtPlotSeriesItem( title ) +{ + init(); +} + +/*! + Constructor + \param title Title of the histogram. +*/ +QwtPlotHistogram::QwtPlotHistogram( const QString &title ): + QwtPlotSeriesItem( title ) +{ + init(); +} + +//! Destructor +QwtPlotHistogram::~QwtPlotHistogram() +{ + delete d_data; +} + +//! Initialize data members +void QwtPlotHistogram::init() +{ + d_data = new PrivateData(); + setData( new QwtIntervalSeriesData() ); + + setItemAttribute( QwtPlotItem::AutoScale, true ); + setItemAttribute( QwtPlotItem::Legend, true ); + + setZ( 20.0 ); +} + +/*! + Set the histogram's drawing style + + \param style Histogram style + \sa HistogramStyle, style() +*/ +void QwtPlotHistogram::setStyle( HistogramStyle style ) +{ + if ( style != d_data->style ) + { + d_data->style = style; + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Style of the histogram + \sa HistogramStyle, setStyle() +*/ +QwtPlotHistogram::HistogramStyle QwtPlotHistogram::style() const +{ + return d_data->style; +} + +/*! + Build and assign a pen + + In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it + non cosmetic ( see QPen::isCosmetic() ). This method has been introduced + to hide this incompatibility. + + \param color Pen color + \param width Pen width + \param style Pen style + + \sa pen(), brush() + */ +void QwtPlotHistogram::setPen( const QColor &color, qreal width, Qt::PenStyle style ) +{ + setPen( QPen( color, width, style ) ); +} + +/*! + Assign a pen, that is used in a style() depending way. + + \param pen New pen + \sa pen(), brush() +*/ +void QwtPlotHistogram::setPen( const QPen &pen ) +{ + if ( pen != d_data->pen ) + { + d_data->pen = pen; + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Pen used in a style() depending way. + \sa setPen(), brush() +*/ +const QPen &QwtPlotHistogram::pen() const +{ + return d_data->pen; +} + +/*! + Assign a brush, that is used in a style() depending way. + + \param brush New brush + \sa pen(), brush() +*/ +void QwtPlotHistogram::setBrush( const QBrush &brush ) +{ + if ( brush != d_data->brush ) + { + d_data->brush = brush; + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Brush used in a style() depending way. + \sa setPen(), brush() +*/ +const QBrush &QwtPlotHistogram::brush() const +{ + return d_data->brush; +} + +/*! + \brief Assign a symbol + + In Column style an optional symbol can be assigned, that is responsible + for displaying the rectangle that is defined by the interval and + the distance between baseline() and value. When no symbol has been + defined the area is displayed as plain rectangle using pen() and brush(). + + \sa style(), symbol(), drawColumn(), pen(), brush() + + \note In applications, where different intervals need to be displayed + in a different way ( f.e different colors or even using different symbols) + it is recommended to overload drawColumn(). +*/ +void QwtPlotHistogram::setSymbol( const QwtColumnSymbol *symbol ) +{ + if ( symbol != d_data->symbol ) + { + delete d_data->symbol; + d_data->symbol = symbol; + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Current symbol or NULL, when no symbol has been assigned + \sa setSymbol() +*/ +const QwtColumnSymbol *QwtPlotHistogram::symbol() const +{ + return d_data->symbol; +} + +/*! + \brief Set the value of the baseline + + Each column representing an QwtIntervalSample is defined by its + interval and the interval between baseline and the value of the sample. + + The default value of the baseline is 0.0. + + \param value Value of the baseline + \sa baseline() +*/ +void QwtPlotHistogram::setBaseline( double value ) +{ + if ( d_data->baseline != value ) + { + d_data->baseline = value; + itemChanged(); + } +} + +/*! + \return Value of the baseline + \sa setBaseline() +*/ +double QwtPlotHistogram::baseline() const +{ + return d_data->baseline; +} + +/*! + \return Bounding rectangle of all samples. + For an empty series the rectangle is invalid. +*/ +QRectF QwtPlotHistogram::boundingRect() const +{ + QRectF rect = data()->boundingRect(); + if ( !rect.isValid() ) + return rect; + + if ( orientation() == Qt::Horizontal ) + { + rect = QRectF( rect.y(), rect.x(), + rect.height(), rect.width() ); + + if ( rect.left() > d_data->baseline ) + rect.setLeft( d_data->baseline ); + else if ( rect.right() < d_data->baseline ) + rect.setRight( d_data->baseline ); + } + else + { + if ( rect.bottom() < d_data->baseline ) + rect.setBottom( d_data->baseline ); + else if ( rect.top() > d_data->baseline ) + rect.setTop( d_data->baseline ); + } + + return rect; +} + +//! \return QwtPlotItem::Rtti_PlotHistogram +int QwtPlotHistogram::rtti() const +{ + return QwtPlotItem::Rtti_PlotHistogram; +} + +/*! + Initialize data with an array of samples. + \param samples Vector of points +*/ +void QwtPlotHistogram::setSamples( + const QVector &samples ) +{ + setData( new QwtIntervalSeriesData( samples ) ); +} + +/*! + Assign a series of samples + + setSamples() is just a wrapper for setData() without any additional + value - beside that it is easier to find for the developer. + + \param data Data + \warning The item takes ownership of the data object, deleting + it when its not used anymore. +*/ +void QwtPlotHistogram::setSamples( + QwtSeriesData *data ) +{ + setData( data ); +} + +/*! + Draw a subset of the histogram samples + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param canvasRect Contents rectangle of the canvas + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted. If to < 0 the + series will be painted to its last sample. + + \sa drawOutline(), drawLines(), drawColumns +*/ +void QwtPlotHistogram::drawSeries( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &, int from, int to ) const +{ + if ( !painter || dataSize() <= 0 ) + return; + + if ( to < 0 ) + to = dataSize() - 1; + + switch ( d_data->style ) + { + case Outline: + drawOutline( painter, xMap, yMap, from, to ); + break; + case Lines: + drawLines( painter, xMap, yMap, from, to ); + break; + case Columns: + drawColumns( painter, xMap, yMap, from, to ); + break; + default: + break; + } +} + +/*! + Draw a histogram in Outline style() + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted. If to < 0 the + histogram will be painted to its last point. + + \sa setStyle(), style() + \warning The outline style requires, that the intervals are in increasing + order and not overlapping. +*/ +void QwtPlotHistogram::drawOutline( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + int from, int to ) const +{ + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + double v0 = ( orientation() == Qt::Horizontal ) ? + xMap.transform( baseline() ) : yMap.transform( baseline() ); + if ( doAlign ) + v0 = qRound( v0 ); + + QwtIntervalSample previous; + + QPolygonF polygon; + for ( int i = from; i <= to; i++ ) + { + const QwtIntervalSample sample = this->sample( i ); + + if ( !sample.interval.isValid() ) + { + flushPolygon( painter, v0, polygon ); + previous = sample; + continue; + } + + if ( previous.interval.isValid() ) + { + if ( !qwtIsCombinable( previous.interval, sample.interval ) ) + flushPolygon( painter, v0, polygon ); + } + + if ( orientation() == Qt::Vertical ) + { + double x1 = xMap.transform( sample.interval.minValue() ); + double x2 = xMap.transform( sample.interval.maxValue() ); + double y = yMap.transform( sample.value ); + if ( doAlign ) + { + x1 = qRound( x1 ); + x2 = qRound( x2 ); + y = qRound( y ); + } + + if ( polygon.size() == 0 ) + polygon += QPointF( x1, v0 ); + + polygon += QPointF( x1, y ); + polygon += QPointF( x2, y ); + } + else + { + double y1 = yMap.transform( sample.interval.minValue() ); + double y2 = yMap.transform( sample.interval.maxValue() ); + double x = xMap.transform( sample.value ); + if ( doAlign ) + { + y1 = qRound( y1 ); + y2 = qRound( y2 ); + x = qRound( x ); + } + + if ( polygon.size() == 0 ) + polygon += QPointF( v0, y1 ); + + polygon += QPointF( x, y1 ); + polygon += QPointF( x, y2 ); + } + previous = sample; + } + + flushPolygon( painter, v0, polygon ); +} + +/*! + Draw a histogram in Columns style() + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted. If to < 0 the + histogram will be painted to its last point. + + \sa setStyle(), style(), setSymbol(), drawColumn() +*/ +void QwtPlotHistogram::drawColumns( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + int from, int to ) const +{ + painter->setPen( d_data->pen ); + painter->setBrush( d_data->brush ); + + const QwtSeriesData *series = data(); + + for ( int i = from; i <= to; i++ ) + { + const QwtIntervalSample sample = series->sample( i ); + if ( !sample.interval.isNull() ) + { + const QwtColumnRect rect = columnRect( sample, xMap, yMap ); + drawColumn( painter, rect, sample ); + } + } +} + +/*! + Draw a histogram in Lines style() + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted. If to < 0 the + histogram will be painted to its last point. + + \sa setStyle(), style(), setPen() +*/ +void QwtPlotHistogram::drawLines( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + int from, int to ) const +{ + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + painter->setPen( d_data->pen ); + painter->setBrush( Qt::NoBrush ); + + const QwtSeriesData *series = data(); + + for ( int i = from; i <= to; i++ ) + { + const QwtIntervalSample sample = series->sample( i ); + if ( !sample.interval.isNull() ) + { + const QwtColumnRect rect = columnRect( sample, xMap, yMap ); + + QRectF r = rect.toRect(); + if ( doAlign ) + { + r.setLeft( qRound( r.left() ) ); + r.setRight( qRound( r.right() ) ); + r.setTop( qRound( r.top() ) ); + r.setBottom( qRound( r.bottom() ) ); + } + + switch ( rect.direction ) + { + case QwtColumnRect::LeftToRight: + { + QwtPainter::drawLine( painter, + r.topRight(), r.bottomRight() ); + break; + } + case QwtColumnRect::RightToLeft: + { + QwtPainter::drawLine( painter, + r.topLeft(), r.bottomLeft() ); + break; + } + case QwtColumnRect::TopToBottom: + { + QwtPainter::drawLine( painter, + r.bottomRight(), r.bottomLeft() ); + break; + } + case QwtColumnRect::BottomToTop: + { + QwtPainter::drawLine( painter, + r.topRight(), r.topLeft() ); + break; + } + } + } + } +} + +//! Internal, used by the Outline style. +void QwtPlotHistogram::flushPolygon( QPainter *painter, + double baseLine, QPolygonF &polygon ) const +{ + if ( polygon.size() == 0 ) + return; + + if ( orientation() == Qt::Horizontal ) + polygon += QPointF( baseLine, polygon.last().y() ); + else + polygon += QPointF( polygon.last().x(), baseLine ); + + if ( d_data->brush.style() != Qt::NoBrush ) + { + painter->setPen( Qt::NoPen ); + painter->setBrush( d_data->brush ); + + if ( orientation() == Qt::Horizontal ) + { + polygon += QPointF( polygon.last().x(), baseLine ); + polygon += QPointF( polygon.first().x(), baseLine ); + } + else + { + polygon += QPointF( baseLine, polygon.last().y() ); + polygon += QPointF( baseLine, polygon.first().y() ); + } + + QwtPainter::drawPolygon( painter, polygon ); + + polygon.pop_back(); + polygon.pop_back(); + } + if ( d_data->pen.style() != Qt::NoPen ) + { + painter->setBrush( Qt::NoBrush ); + painter->setPen( d_data->pen ); + QwtPainter::drawPolyline( painter, polygon ); + } + polygon.clear(); +} + +/*! + Calculate the area that is covered by a sample + + \param sample Sample + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + + \return Rectangle, that is covered by a sample +*/ +QwtColumnRect QwtPlotHistogram::columnRect( const QwtIntervalSample &sample, + const QwtScaleMap &xMap, const QwtScaleMap &yMap ) const +{ + QwtColumnRect rect; + + const QwtInterval &iv = sample.interval; + if ( !iv.isValid() ) + return rect; + + if ( orientation() == Qt::Horizontal ) + { + const double x0 = xMap.transform( baseline() ); + const double x = xMap.transform( sample.value ); + const double y1 = yMap.transform( iv.minValue() ); + const double y2 = yMap.transform( iv.maxValue() ); + + rect.hInterval.setInterval( x0, x ); + rect.vInterval.setInterval( y1, y2, iv.borderFlags() ); + rect.direction = ( x < x0 ) ? QwtColumnRect::RightToLeft : + QwtColumnRect::LeftToRight; + } + else + { + const double x1 = xMap.transform( iv.minValue() ); + const double x2 = xMap.transform( iv.maxValue() ); + const double y0 = yMap.transform( baseline() ); + const double y = yMap.transform( sample.value ); + + rect.hInterval.setInterval( x1, x2, iv.borderFlags() ); + rect.vInterval.setInterval( y0, y ); + rect.direction = ( y < y0 ) ? QwtColumnRect::BottomToTop : + QwtColumnRect::TopToBottom; + } + + return rect; +} + +/*! + Draw a column for a sample in Columns style(). + + When a symbol() has been set the symbol is used otherwise the + column is displayed as plain rectangle using pen() and brush(). + + \param painter Painter + \param rect Rectangle where to paint the column in paint device coordinates + \param sample Sample to be displayed + + \note In applications, where different intervals need to be displayed + in a different way ( f.e different colors or even using different symbols) + it is recommended to overload drawColumn(). +*/ +void QwtPlotHistogram::drawColumn( QPainter *painter, + const QwtColumnRect &rect, const QwtIntervalSample &sample ) const +{ + Q_UNUSED( sample ); + + if ( d_data->symbol && + ( d_data->symbol->style() != QwtColumnSymbol::NoStyle ) ) + { + d_data->symbol->draw( painter, rect ); + } + else + { + QRectF r = rect.toRect(); + if ( QwtPainter::roundingAlignment( painter ) ) + { + r.setLeft( qRound( r.left() ) ); + r.setRight( qRound( r.right() ) ); + r.setTop( qRound( r.top() ) ); + r.setBottom( qRound( r.bottom() ) ); + } + + QwtPainter::drawRect( painter, r ); + } +} + +/*! + A plain rectangle without pen using the brush() + + \param index Index of the legend entry + ( ignored as there is only one ) + \param size Icon size + \return A graphic displaying the icon + + \sa QwtPlotItem::setLegendIconSize(), QwtPlotItem::legendData() +*/ +QwtGraphic QwtPlotHistogram::legendIcon( int index, + const QSizeF &size ) const +{ + Q_UNUSED( index ); + return defaultIcon( d_data->brush, size ); +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_histogram.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_histogram.h new file mode 100644 index 0000000..a000d58 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_histogram.h @@ -0,0 +1,139 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PLOT_HISTOGRAM_H +#define QWT_PLOT_HISTOGRAM_H + +#include "qwt_global.h" +#include "qwt_plot_seriesitem.h" +#include "qwt_column_symbol.h" +#include +#include + +class QwtIntervalData; +class QString; +class QPolygonF; + +/*! + \brief QwtPlotHistogram represents a series of samples, where an interval + is associated with a value ( \f$y = f([x1,x2])\f$ ). + + The representation depends on the style() and an optional symbol() + that is displayed for each interval. + + \note The term "histogram" is used in a different way in the areas of + digital image processing and statistics. Wikipedia introduces the + terms "image histogram" and "color histogram" to avoid confusions. + While "image histograms" can be displayed by a QwtPlotCurve there + is no applicable plot item for a "color histogram" yet. + + \sa QwtPlotBarChart, QwtPlotMultiBarChart +*/ + +class QWT_EXPORT QwtPlotHistogram: + public QwtPlotSeriesItem, public QwtSeriesStore +{ +public: + /*! + Histogram styles. + The default style is QwtPlotHistogram::Columns. + + \sa setStyle(), style(), setSymbol(), symbol(), setBaseline() + */ + enum HistogramStyle + { + /*! + Draw an outline around the area, that is build by all intervals + using the pen() and fill it with the brush(). The outline style + requires, that the intervals are in increasing order and + not overlapping. + */ + Outline, + + /*! + Draw a column for each interval. When a symbol() has been set + the symbol is used otherwise the column is displayed as + plain rectangle using pen() and brush(). + */ + Columns, + + /*! + Draw a simple line using the pen() for each interval. + */ + Lines, + + /*! + Styles >= UserStyle are reserved for derived + classes that overload drawSeries() with + additional application specific ways to display a histogram. + */ + UserStyle = 100 + }; + + explicit QwtPlotHistogram( const QString &title = QString::null ); + explicit QwtPlotHistogram( const QwtText &title ); + virtual ~QwtPlotHistogram(); + + virtual int rtti() const; + + void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); + void setPen( const QPen & ); + const QPen &pen() const; + + void setBrush( const QBrush & ); + const QBrush &brush() const; + + void setSamples( const QVector & ); + void setSamples( QwtSeriesData * ); + + void setBaseline( double reference ); + double baseline() const; + + void setStyle( HistogramStyle style ); + HistogramStyle style() const; + + void setSymbol( const QwtColumnSymbol * ); + const QwtColumnSymbol *symbol() const; + + virtual void drawSeries( QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual QRectF boundingRect() const; + + virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; + +protected: + virtual QwtColumnRect columnRect( const QwtIntervalSample &, + const QwtScaleMap &, const QwtScaleMap & ) const; + + virtual void drawColumn( QPainter *, const QwtColumnRect &, + const QwtIntervalSample & ) const; + + void drawColumns( QPainter *, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + int from, int to ) const; + + void drawOutline( QPainter *, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + int from, int to ) const; + + void drawLines( QPainter *, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + int from, int to ) const; + +private: + void init(); + void flushPolygon( QPainter *, double baseLine, QPolygonF & ) const; + + class PrivateData; + PrivateData *d_data; +}; + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_intervalcurve.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_intervalcurve.cpp new file mode 100644 index 0000000..3b06a66 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_intervalcurve.cpp @@ -0,0 +1,603 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot_intervalcurve.h" +#include "qwt_interval_symbol.h" +#include "qwt_scale_map.h" +#include "qwt_clipper.h" +#include "qwt_painter.h" +#include + +#include + +static inline bool qwtIsHSampleInside( const QwtIntervalSample &sample, + double xMin, double xMax, double yMin, double yMax ) +{ + const double y = sample.value; + const double x1 = sample.interval.minValue(); + const double x2 = sample.interval.maxValue(); + + const bool isOffScreen = ( y < yMin ) || ( y > yMax ) + || ( x1 < xMin && x2 < xMin ) || ( x1 > xMax && x2 > xMax ); + + return !isOffScreen; +} + +static inline bool qwtIsVSampleInside( const QwtIntervalSample &sample, + double xMin, double xMax, double yMin, double yMax ) +{ + const double x = sample.value; + const double y1 = sample.interval.minValue(); + const double y2 = sample.interval.maxValue(); + + const bool isOffScreen = ( x < xMin ) || ( x > xMax ) + || ( y1 < yMin && y2 < yMin ) || ( y1 > yMax && y2 > yMax ); + + return !isOffScreen; +} + +class QwtPlotIntervalCurve::PrivateData +{ +public: + PrivateData(): + style( QwtPlotIntervalCurve::Tube ), + symbol( NULL ), + pen( Qt::black ), + brush( Qt::white ) + { + paintAttributes = QwtPlotIntervalCurve::ClipPolygons; + paintAttributes |= QwtPlotIntervalCurve::ClipSymbol; + + pen.setCapStyle( Qt::FlatCap ); + } + + ~PrivateData() + { + delete symbol; + } + + QwtPlotIntervalCurve::CurveStyle style; + const QwtIntervalSymbol *symbol; + + QPen pen; + QBrush brush; + + QwtPlotIntervalCurve::PaintAttributes paintAttributes; +}; + +/*! + Constructor + \param title Title of the curve +*/ +QwtPlotIntervalCurve::QwtPlotIntervalCurve( const QwtText &title ): + QwtPlotSeriesItem( title ) +{ + init(); +} + +/*! + Constructor + \param title Title of the curve +*/ +QwtPlotIntervalCurve::QwtPlotIntervalCurve( const QString &title ): + QwtPlotSeriesItem( QwtText( title ) ) +{ + init(); +} + +//! Destructor +QwtPlotIntervalCurve::~QwtPlotIntervalCurve() +{ + delete d_data; +} + +//! Initialize internal members +void QwtPlotIntervalCurve::init() +{ + setItemAttribute( QwtPlotItem::Legend, true ); + setItemAttribute( QwtPlotItem::AutoScale, true ); + + d_data = new PrivateData; + setData( new QwtIntervalSeriesData() ); + + setZ( 19.0 ); +} + +//! \return QwtPlotItem::Rtti_PlotIntervalCurve +int QwtPlotIntervalCurve::rtti() const +{ + return QwtPlotIntervalCurve::Rtti_PlotIntervalCurve; +} + +/*! + Specify an attribute how to draw the curve + + \param attribute Paint attribute + \param on On/Off + \sa testPaintAttribute() +*/ +void QwtPlotIntervalCurve::setPaintAttribute( + PaintAttribute attribute, bool on ) +{ + if ( on ) + d_data->paintAttributes |= attribute; + else + d_data->paintAttributes &= ~attribute; +} + +/*! + \return True, when attribute is enabled + \sa PaintAttribute, setPaintAttribute() +*/ +bool QwtPlotIntervalCurve::testPaintAttribute( + PaintAttribute attribute ) const +{ + return ( d_data->paintAttributes & attribute ); +} + +/*! + Initialize data with an array of samples. + \param samples Vector of samples +*/ +void QwtPlotIntervalCurve::setSamples( + const QVector &samples ) +{ + setData( new QwtIntervalSeriesData( samples ) ); +} + +/*! + Assign a series of samples + + setSamples() is just a wrapper for setData() without any additional + value - beside that it is easier to find for the developer. + + \param data Data + \warning The item takes ownership of the data object, deleting + it when its not used anymore. +*/ +void QwtPlotIntervalCurve::setSamples( + QwtSeriesData *data ) +{ + setData( data ); +} + +/*! + Set the curve's drawing style + + \param style Curve style + \sa CurveStyle, style() +*/ +void QwtPlotIntervalCurve::setStyle( CurveStyle style ) +{ + if ( style != d_data->style ) + { + d_data->style = style; + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Style of the curve + \sa setStyle() +*/ +QwtPlotIntervalCurve::CurveStyle QwtPlotIntervalCurve::style() const +{ + return d_data->style; +} + +/*! + Assign a symbol. + + \param symbol Symbol + \sa symbol() +*/ +void QwtPlotIntervalCurve::setSymbol( const QwtIntervalSymbol *symbol ) +{ + if ( symbol != d_data->symbol ) + { + delete d_data->symbol; + d_data->symbol = symbol; + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Current symbol or NULL, when no symbol has been assigned + \sa setSymbol() +*/ +const QwtIntervalSymbol *QwtPlotIntervalCurve::symbol() const +{ + return d_data->symbol; +} + +/*! + Build and assign a pen + + In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it + non cosmetic ( see QPen::isCosmetic() ). This method has been introduced + to hide this incompatibility. + + \param color Pen color + \param width Pen width + \param style Pen style + + \sa pen(), brush() + */ +void QwtPlotIntervalCurve::setPen( const QColor &color, qreal width, Qt::PenStyle style ) +{ + setPen( QPen( color, width, style ) ); +} + +/*! + \brief Assign a pen + \param pen New pen + \sa pen(), brush() +*/ +void QwtPlotIntervalCurve::setPen( const QPen &pen ) +{ + if ( pen != d_data->pen ) + { + d_data->pen = pen; + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Pen used to draw the lines + \sa setPen(), brush() +*/ +const QPen& QwtPlotIntervalCurve::pen() const +{ + return d_data->pen; +} + +/*! + Assign a brush. + + The brush is used to fill the area in Tube style(). + + \param brush Brush + \sa brush(), pen(), setStyle(), CurveStyle +*/ +void QwtPlotIntervalCurve::setBrush( const QBrush &brush ) +{ + if ( brush != d_data->brush ) + { + d_data->brush = brush; + + legendChanged(); + itemChanged(); + } +} + +/*! + \return Brush used to fill the area in Tube style() + \sa setBrush(), setStyle(), CurveStyle +*/ +const QBrush& QwtPlotIntervalCurve::brush() const +{ + return d_data->brush; +} + +/*! + \return Bounding rectangle of all samples. + For an empty series the rectangle is invalid. +*/ +QRectF QwtPlotIntervalCurve::boundingRect() const +{ + QRectF rect = QwtPlotSeriesItem::boundingRect(); + if ( rect.isValid() && orientation() == Qt::Vertical ) + rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() ); + + return rect; +} + +/*! + Draw a subset of the samples + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param canvasRect Contents rectangle of the canvas + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted. If to < 0 the + series will be painted to its last sample. + + \sa drawTube(), drawSymbols() +*/ +void QwtPlotIntervalCurve::drawSeries( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + if ( to < 0 ) + to = dataSize() - 1; + + if ( from < 0 ) + from = 0; + + if ( from > to ) + return; + + switch ( d_data->style ) + { + case Tube: + drawTube( painter, xMap, yMap, canvasRect, from, to ); + break; + + case NoCurve: + default: + break; + } + + if ( d_data->symbol && + ( d_data->symbol->style() != QwtIntervalSymbol::NoSymbol ) ) + { + drawSymbols( painter, *d_data->symbol, + xMap, yMap, canvasRect, from, to ); + } +} + +/*! + Draw a tube + + Builds 2 curves from the upper and lower limits of the intervals + and draws them with the pen(). The area between the curves is + filled with the brush(). + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param canvasRect Contents rectangle of the canvas + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted. If to < 0 the + series will be painted to its last sample. + + \sa drawSeries(), drawSymbols() +*/ +void QwtPlotIntervalCurve::drawTube( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + const bool doAlign = QwtPainter::roundingAlignment( painter ); + + painter->save(); + + const size_t size = to - from + 1; + QPolygonF polygon( 2 * size ); + QPointF *points = polygon.data(); + + for ( uint i = 0; i < size; i++ ) + { + QPointF &minValue = points[i]; + QPointF &maxValue = points[2 * size - 1 - i]; + + const QwtIntervalSample intervalSample = sample( from + i ); + if ( orientation() == Qt::Vertical ) + { + double x = xMap.transform( intervalSample.value ); + double y1 = yMap.transform( intervalSample.interval.minValue() ); + double y2 = yMap.transform( intervalSample.interval.maxValue() ); + if ( doAlign ) + { + x = qRound( x ); + y1 = qRound( y1 ); + y2 = qRound( y2 ); + } + + minValue.rx() = x; + minValue.ry() = y1; + maxValue.rx() = x; + maxValue.ry() = y2; + } + else + { + double y = yMap.transform( intervalSample.value ); + double x1 = xMap.transform( intervalSample.interval.minValue() ); + double x2 = xMap.transform( intervalSample.interval.maxValue() ); + if ( doAlign ) + { + y = qRound( y ); + x1 = qRound( x1 ); + x2 = qRound( x2 ); + } + + minValue.rx() = x1; + minValue.ry() = y; + maxValue.rx() = x2; + maxValue.ry() = y; + } + } + + if ( d_data->brush.style() != Qt::NoBrush ) + { + painter->setPen( QPen( Qt::NoPen ) ); + painter->setBrush( d_data->brush ); + + if ( d_data->paintAttributes & ClipPolygons ) + { + const qreal m = 1.0; + const QPolygonF p = QwtClipper::clipPolygonF( + canvasRect.adjusted( -m, -m, m, m ), polygon, true ); + + QwtPainter::drawPolygon( painter, p ); + } + else + { + QwtPainter::drawPolygon( painter, polygon ); + } + } + + if ( d_data->pen.style() != Qt::NoPen ) + { + painter->setPen( d_data->pen ); + painter->setBrush( Qt::NoBrush ); + + if ( d_data->paintAttributes & ClipPolygons ) + { + qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF() ); + const QRectF clipRect = canvasRect.adjusted( -pw, -pw, pw, pw ); + + QPolygonF p; + + p.resize( size ); + ::memcpy( p.data(), points, size * sizeof( QPointF ) ); + p = QwtClipper::clipPolygonF( clipRect, p ); + QwtPainter::drawPolyline( painter, p ); + + p.resize( size ); + ::memcpy( p.data(), points + size, size * sizeof( QPointF ) ); + p = QwtClipper::clipPolygonF( clipRect, p ); + QwtPainter::drawPolyline( painter, p ); + } + else + { + QwtPainter::drawPolyline( painter, points, size ); + QwtPainter::drawPolyline( painter, points + size, size ); + } + } + + painter->restore(); +} + +/*! + Draw symbols for a subset of the samples + + \param painter Painter + \param symbol Interval symbol + \param xMap x map + \param yMap y map + \param canvasRect Contents rectangle of the canvas + \param from Index of the first sample to be painted + \param to Index of the last sample to be painted + + \sa setSymbol(), drawSeries(), drawTube() +*/ +void QwtPlotIntervalCurve::drawSymbols( + QPainter *painter, const QwtIntervalSymbol &symbol, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const +{ + painter->save(); + + QPen pen = symbol.pen(); + pen.setCapStyle( Qt::FlatCap ); + + painter->setPen( pen ); + painter->setBrush( symbol.brush() ); + + const QRectF tr = QwtScaleMap::invTransform( xMap, yMap, canvasRect ); + + const double xMin = tr.left(); + const double xMax = tr.right(); + const double yMin = tr.top(); + const double yMax = tr.bottom(); + + const bool doClip = d_data->paintAttributes & ClipSymbol; + + for ( int i = from; i <= to; i++ ) + { + const QwtIntervalSample s = sample( i ); + + if ( orientation() == Qt::Vertical ) + { + if ( !doClip || qwtIsVSampleInside( s, xMin, xMax, yMin, yMax ) ) + { + const double x = xMap.transform( s.value ); + const double y1 = yMap.transform( s.interval.minValue() ); + const double y2 = yMap.transform( s.interval.maxValue() ); + + symbol.draw( painter, orientation(), + QPointF( x, y1 ), QPointF( x, y2 ) ); + } + } + else + { + if ( !doClip || qwtIsHSampleInside( s, xMin, xMax, yMin, yMax ) ) + { + const double y = yMap.transform( s.value ); + const double x1 = xMap.transform( s.interval.minValue() ); + const double x2 = xMap.transform( s.interval.maxValue() ); + + symbol.draw( painter, orientation(), + QPointF( x1, y ), QPointF( x2, y ) ); + } + } + } + + painter->restore(); +} + +/*! + \return Icon for the legend + + In case of Tube style() the icon is a plain rectangle filled with the brush(). + If a symbol is assigned it is scaled to size. + + \param index Index of the legend entry + ( ignored as there is only one ) + \param size Icon size + + \sa QwtPlotItem::setLegendIconSize(), QwtPlotItem::legendData() +*/ +QwtGraphic QwtPlotIntervalCurve::legendIcon( + int index, const QSizeF &size ) const +{ + Q_UNUSED( index ); + + if ( size.isEmpty() ) + return QwtGraphic(); + + QwtGraphic icon; + icon.setDefaultSize( size ); + icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true ); + + QPainter painter( &icon ); + painter.setRenderHint( QPainter::Antialiasing, + testRenderHint( QwtPlotItem::RenderAntialiased ) ); + + if ( d_data->style == Tube ) + { + QRectF r( 0, 0, size.width(), size.height() ); + painter.fillRect( r, d_data->brush ); + } + + if ( d_data->symbol && + ( d_data->symbol->style() != QwtIntervalSymbol::NoSymbol ) ) + { + QPen pen = d_data->symbol->pen(); + pen.setWidthF( pen.widthF() ); + pen.setCapStyle( Qt::FlatCap ); + + painter.setPen( pen ); + painter.setBrush( d_data->symbol->brush() ); + + if ( orientation() == Qt::Vertical ) + { + const double x = 0.5 * size.width(); + + d_data->symbol->draw( &painter, orientation(), + QPointF( x, 0 ), QPointF( x, size.height() - 1.0 ) ); + } + else + { + const double y = 0.5 * size.height(); + + d_data->symbol->draw( &painter, orientation(), + QPointF( 0.0, y ), QPointF( size.width() - 1.0, y ) ); + } + } + + return icon; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_intervalcurve.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_intervalcurve.h new file mode 100644 index 0000000..74a4226 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_intervalcurve.h @@ -0,0 +1,132 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PLOT_INTERVAL_CURVE_H +#define QWT_PLOT_INTERVAL_CURVE_H + +#include "qwt_global.h" +#include "qwt_plot_seriesitem.h" +#include "qwt_series_data.h" + +class QwtIntervalSymbol; + +/*! + \brief QwtPlotIntervalCurve represents a series of samples, where each value + is associated with an interval ( \f$[y1,y2] = f(x)\f$ ). + + The representation depends on the style() and an optional symbol() + that is displayed for each interval. QwtPlotIntervalCurve might be used + to display error bars or the area between 2 curves. +*/ +class QWT_EXPORT QwtPlotIntervalCurve: + public QwtPlotSeriesItem, public QwtSeriesStore +{ +public: + /*! + \brief Curve styles. + The default setting is QwtPlotIntervalCurve::Tube. + + \sa setStyle(), style() + */ + enum CurveStyle + { + /*! + Don't draw a curve. Note: This doesn't affect the symbols. + */ + NoCurve, + + /*! + Build 2 curves from the upper and lower limits of the intervals + and draw them with the pen(). The area between the curves is + filled with the brush(). + */ + Tube, + + /*! + Styles >= QwtPlotIntervalCurve::UserCurve are reserved for derived + classes that overload drawSeries() with + additional application specific curve types. + */ + UserCurve = 100 + }; + + /*! + Attributes to modify the drawing algorithm. + \sa setPaintAttribute(), testPaintAttribute() + */ + enum PaintAttribute + { + /*! + Clip polygons before painting them. In situations, where points + are far outside the visible area (f.e when zooming deep) this + might be a substantial improvement for the painting performance. + */ + ClipPolygons = 0x01, + + //! Check if a symbol is on the plot canvas before painting it. + ClipSymbol = 0x02 + }; + + //! Paint attributes + typedef QFlags PaintAttributes; + + explicit QwtPlotIntervalCurve( const QString &title = QString::null ); + explicit QwtPlotIntervalCurve( const QwtText &title ); + + virtual ~QwtPlotIntervalCurve(); + + virtual int rtti() const; + + void setPaintAttribute( PaintAttribute, bool on = true ); + bool testPaintAttribute( PaintAttribute ) const; + + void setSamples( const QVector & ); + void setSamples( QwtSeriesData * ); + + void setPen( const QColor &, qreal width = 0.0, Qt::PenStyle = Qt::SolidLine ); + void setPen( const QPen & ); + const QPen &pen() const; + + void setBrush( const QBrush & ); + const QBrush &brush() const; + + void setStyle( CurveStyle style ); + CurveStyle style() const; + + void setSymbol( const QwtIntervalSymbol * ); + const QwtIntervalSymbol *symbol() const; + + virtual void drawSeries( QPainter *p, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual QRectF boundingRect() const; + + virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; + +protected: + + void init(); + + virtual void drawTube( QPainter *, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + + virtual void drawSymbols( QPainter *, const QwtIntervalSymbol &, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect, int from, int to ) const; + +private: + class PrivateData; + PrivateData *d_data; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotIntervalCurve::PaintAttributes ) + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_item.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_item.cpp new file mode 100644 index 0000000..15ae724 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_item.cpp @@ -0,0 +1,698 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot_item.h" +#include "qwt_text.h" +#include "qwt_plot.h" +#include "qwt_legend_data.h" +#include "qwt_scale_div.h" +#include "qwt_graphic.h" +#include + +class QwtPlotItem::PrivateData +{ +public: + PrivateData(): + plot( NULL ), + isVisible( true ), + attributes( 0 ), + interests( 0 ), + renderHints( 0 ), + renderThreadCount( 1 ), + z( 0.0 ), + xAxis( QwtPlot::xBottom ), + yAxis( QwtPlot::yLeft ), + legendIconSize( 8, 8 ) + { + } + + mutable QwtPlot *plot; + + bool isVisible; + + QwtPlotItem::ItemAttributes attributes; + QwtPlotItem::ItemInterests interests; + + QwtPlotItem::RenderHints renderHints; + uint renderThreadCount; + + double z; + + int xAxis; + int yAxis; + + QwtText title; + QSize legendIconSize; +}; + +/*! + Constructor + \param title Title of the item +*/ +QwtPlotItem::QwtPlotItem( const QwtText &title ) +{ + d_data = new PrivateData; + d_data->title = title; +} + +//! Destroy the QwtPlotItem +QwtPlotItem::~QwtPlotItem() +{ + attach( NULL ); + delete d_data; +} + +/*! + \brief Attach the item to a plot. + + This method will attach a QwtPlotItem to the QwtPlot argument. It will first + detach the QwtPlotItem from any plot from a previous call to attach (if + necessary). If a NULL argument is passed, it will detach from any QwtPlot it + was attached to. + + \param plot Plot widget + \sa detach() +*/ +void QwtPlotItem::attach( QwtPlot *plot ) +{ + if ( plot == d_data->plot ) + return; + + if ( d_data->plot ) + d_data->plot->attachItem( this, false ); + + d_data->plot = plot; + + if ( d_data->plot ) + d_data->plot->attachItem( this, true ); +} + +/*! + \brief This method detaches a QwtPlotItem from any + QwtPlot it has been associated with. + + detach() is equivalent to calling attach( NULL ) + \sa attach() +*/ +void QwtPlotItem::detach() +{ + attach( NULL ); +} + +/*! + Return rtti for the specific class represented. QwtPlotItem is simply + a virtual interface class, and base classes will implement this method + with specific rtti values so a user can differentiate them. + + The rtti value is useful for environments, where the + runtime type information is disabled and it is not possible + to do a dynamic_cast<...>. + + \return rtti value + \sa RttiValues +*/ +int QwtPlotItem::rtti() const +{ + return Rtti_PlotItem; +} + +//! Return attached plot +QwtPlot *QwtPlotItem::plot() const +{ + return d_data->plot; +} + +/*! + Plot items are painted in increasing z-order. + + \return setZ(), QwtPlotDict::itemList() +*/ +double QwtPlotItem::z() const +{ + return d_data->z; +} + +/*! + \brief Set the z value + + Plot items are painted in increasing z-order. + + \param z Z-value + \sa z(), QwtPlotDict::itemList() +*/ +void QwtPlotItem::setZ( double z ) +{ + if ( d_data->z != z ) + { + if ( d_data->plot ) // update the z order + d_data->plot->attachItem( this, false ); + + d_data->z = z; + + if ( d_data->plot ) + d_data->plot->attachItem( this, true ); + + itemChanged(); + } +} + +/*! + Set a new title + + \param title Title + \sa title() +*/ +void QwtPlotItem::setTitle( const QString &title ) +{ + setTitle( QwtText( title ) ); +} + +/*! + Set a new title + + \param title Title + \sa title() +*/ +void QwtPlotItem::setTitle( const QwtText &title ) +{ + if ( d_data->title != title ) + { + d_data->title = title; + + legendChanged(); +#if 0 + itemChanged(); +#endif + } +} + +/*! + \return Title of the item + \sa setTitle() +*/ +const QwtText &QwtPlotItem::title() const +{ + return d_data->title; +} + +/*! + Toggle an item attribute + + \param attribute Attribute type + \param on true/false + + \sa testItemAttribute(), ItemInterest +*/ +void QwtPlotItem::setItemAttribute( ItemAttribute attribute, bool on ) +{ + if ( d_data->attributes.testFlag( attribute ) != on ) + { + if ( on ) + d_data->attributes |= attribute; + else + d_data->attributes &= ~attribute; + + if ( attribute == QwtPlotItem::Legend ) + legendChanged(); + + itemChanged(); + } +} + +/*! + Test an item attribute + + \param attribute Attribute type + \return true/false + \sa setItemAttribute(), ItemInterest +*/ +bool QwtPlotItem::testItemAttribute( ItemAttribute attribute ) const +{ + return d_data->attributes.testFlag( attribute ); +} + +/*! + Toggle an item interest + + \param interest Interest type + \param on true/false + + \sa testItemInterest(), ItemAttribute +*/ +void QwtPlotItem::setItemInterest( ItemInterest interest, bool on ) +{ + if ( d_data->interests.testFlag( interest ) != on ) + { + if ( on ) + d_data->interests |= interest; + else + d_data->interests &= ~interest; + + itemChanged(); + } +} + +/*! + Test an item interest + + \param interest Interest type + \return true/false + \sa setItemInterest(), ItemAttribute +*/ +bool QwtPlotItem::testItemInterest( ItemInterest interest ) const +{ + return d_data->interests.testFlag( interest ); +} + +/*! + Toggle an render hint + + \param hint Render hint + \param on true/false + + \sa testRenderHint(), RenderHint +*/ +void QwtPlotItem::setRenderHint( RenderHint hint, bool on ) +{ + if ( d_data->renderHints.testFlag( hint ) != on ) + { + if ( on ) + d_data->renderHints |= hint; + else + d_data->renderHints &= ~hint; + + itemChanged(); + } +} + +/*! + Test a render hint + + \param hint Render hint + \return true/false + \sa setRenderHint(), RenderHint +*/ +bool QwtPlotItem::testRenderHint( RenderHint hint ) const +{ + return d_data->renderHints.testFlag( hint ); +} + +/*! + On multi core systems rendering of certain plot item + ( f.e QwtPlotRasterItem ) can be done in parallel in + several threads. + + The default setting is set to 1. + + \param numThreads Number of threads to be used for rendering. + If numThreads is set to 0, the system specific + ideal thread count is used. + + The default thread count is 1 ( = no additional threads ) +*/ +void QwtPlotItem::setRenderThreadCount( uint numThreads ) +{ + d_data->renderThreadCount = numThreads; +} + +/*! + \return Number of threads to be used for rendering. + If numThreads() is set to 0, the system specific + ideal thread count is used. +*/ +uint QwtPlotItem::renderThreadCount() const +{ + return d_data->renderThreadCount; +} + +/*! + Set the size of the legend icon + + The default setting is 8x8 pixels + + \param size Size + \sa legendIconSize(), legendIcon() +*/ +void QwtPlotItem::setLegendIconSize( const QSize &size ) +{ + if ( d_data->legendIconSize != size ) + { + d_data->legendIconSize = size; + legendChanged(); + } +} + +/*! + \return Legend icon size + \sa setLegendIconSize(), legendIcon() +*/ +QSize QwtPlotItem::legendIconSize() const +{ + return d_data->legendIconSize; +} + +/*! + \return Icon representing the item on the legend + + The default implementation returns an invalid icon + + \param index Index of the legend entry + ( usually there is only one ) + \param size Icon size + + \sa setLegendIconSize(), legendData() + */ +QwtGraphic QwtPlotItem::legendIcon( + int index, const QSizeF &size ) const +{ + Q_UNUSED( index ) + Q_UNUSED( size ) + + return QwtGraphic(); +} + +/*! + \brief Return a default icon from a brush + + The default icon is a filled rectangle used + in several derived classes as legendIcon(). + + \param brush Fill brush + \param size Icon size + + \return A filled rectangle + */ +QwtGraphic QwtPlotItem::defaultIcon( + const QBrush &brush, const QSizeF &size ) const +{ + QwtGraphic icon; + if ( !size.isEmpty() ) + { + icon.setDefaultSize( size ); + + QRectF r( 0, 0, size.width(), size.height() ); + + QPainter painter( &icon ); + painter.fillRect( r, brush ); + } + + return icon; +} + +//! Show the item +void QwtPlotItem::show() +{ + setVisible( true ); +} + +//! Hide the item +void QwtPlotItem::hide() +{ + setVisible( false ); +} + +/*! + Show/Hide the item + + \param on Show if true, otherwise hide + \sa isVisible(), show(), hide() +*/ +void QwtPlotItem::setVisible( bool on ) +{ + if ( on != d_data->isVisible ) + { + d_data->isVisible = on; + itemChanged(); + } +} + +/*! + \return true if visible + \sa setVisible(), show(), hide() +*/ +bool QwtPlotItem::isVisible() const +{ + return d_data->isVisible; +} + +/*! + Update the legend and call QwtPlot::autoRefresh() for the + parent plot. + + \sa QwtPlot::legendChanged(), QwtPlot::autoRefresh() +*/ +void QwtPlotItem::itemChanged() +{ + if ( d_data->plot ) + d_data->plot->autoRefresh(); +} + +/*! + Update the legend of the parent plot. + \sa QwtPlot::updateLegend(), itemChanged() +*/ +void QwtPlotItem::legendChanged() +{ + if ( testItemAttribute( QwtPlotItem::Legend ) && d_data->plot ) + d_data->plot->updateLegend( this ); +} + +/*! + Set X and Y axis + + The item will painted according to the coordinates of its Axes. + + \param xAxis X Axis ( QwtPlot::xBottom or QwtPlot::xTop ) + \param yAxis Y Axis ( QwtPlot::yLeft or QwtPlot::yRight ) + + \sa setXAxis(), setYAxis(), xAxis(), yAxis(), QwtPlot::Axis +*/ +void QwtPlotItem::setAxes( int xAxis, int yAxis ) +{ + if ( xAxis == QwtPlot::xBottom || xAxis == QwtPlot::xTop ) + d_data->xAxis = xAxis; + + if ( yAxis == QwtPlot::yLeft || yAxis == QwtPlot::yRight ) + d_data->yAxis = yAxis; + + itemChanged(); +} + +/*! + Set the X axis + + The item will painted according to the coordinates its Axes. + + \param axis X Axis ( QwtPlot::xBottom or QwtPlot::xTop ) + \sa setAxes(), setYAxis(), xAxis(), QwtPlot::Axis +*/ +void QwtPlotItem::setXAxis( int axis ) +{ + if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) + { + d_data->xAxis = axis; + itemChanged(); + } +} + +/*! + Set the Y axis + + The item will painted according to the coordinates its Axes. + + \param axis Y Axis ( QwtPlot::yLeft or QwtPlot::yRight ) + \sa setAxes(), setXAxis(), yAxis(), QwtPlot::Axis +*/ +void QwtPlotItem::setYAxis( int axis ) +{ + if ( axis == QwtPlot::yLeft || axis == QwtPlot::yRight ) + { + d_data->yAxis = axis; + itemChanged(); + } +} + +//! Return xAxis +int QwtPlotItem::xAxis() const +{ + return d_data->xAxis; +} + +//! Return yAxis +int QwtPlotItem::yAxis() const +{ + return d_data->yAxis; +} + +/*! + \return An invalid bounding rect: QRectF(1.0, 1.0, -2.0, -2.0) + \note A width or height < 0.0 is ignored by the autoscaler +*/ +QRectF QwtPlotItem::boundingRect() const +{ + return QRectF( 1.0, 1.0, -2.0, -2.0 ); // invalid +} + +/*! + \brief Calculate a hint for the canvas margin + + When the QwtPlotItem::Margins flag is enabled the plot item + indicates, that it needs some margins at the borders of the canvas. + This is f.e. used by bar charts to reserve space for displaying + the bars. + + The margins are in target device coordinates ( pixels on screen ) + + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param canvasRect Contents rectangle of the canvas in painter coordinates + \param left Returns the left margin + \param top Returns the top margin + \param right Returns the right margin + \param bottom Returns the bottom margin + + \return The default implementation returns 0 for all margins + + \sa QwtPlot::getCanvasMarginsHint(), QwtPlot::updateCanvasMargins() + */ +void QwtPlotItem::getCanvasMarginHint( const QwtScaleMap &xMap, + const QwtScaleMap &yMap, const QRectF &canvasRect, + double &left, double &top, double &right, double &bottom ) const +{ + Q_UNUSED( xMap ); + Q_UNUSED( yMap ); + Q_UNUSED( canvasRect ); + + // use QMargins, when we don't need to support Qt < 4.6 anymore + left = top = right = bottom = 0.0; +} + +/*! + \brief Return all information, that is needed to represent + the item on the legend + + Most items are represented by one entry on the legend + showing an icon and a text, but f.e. QwtPlotMultiBarChart + displays one entry for each bar. + + QwtLegendData is basically a list of QVariants that makes it + possible to overload and reimplement legendData() to + return almost any type of information, that is understood + by the receiver that acts as the legend. + + The default implementation returns one entry with + the title() of the item and the legendIcon(). + + \return Data, that is needed to represent the item on the legend + \sa title(), legendIcon(), QwtLegend, QwtPlotLegendItem + */ +QList QwtPlotItem::legendData() const +{ + QwtLegendData data; + + QwtText label = title(); + label.setRenderFlags( label.renderFlags() & Qt::AlignLeft ); + + QVariant titleValue; + qVariantSetValue( titleValue, label ); + data.setValue( QwtLegendData::TitleRole, titleValue ); + + const QwtGraphic graphic = legendIcon( 0, legendIconSize() ); + if ( !graphic.isNull() ) + { + QVariant iconValue; + qVariantSetValue( iconValue, graphic ); + data.setValue( QwtLegendData::IconRole, iconValue ); + } + + QList list; + list += data; + + return list; +} + +/*! + \brief Update the item to changes of the axes scale division + + Update the item, when the axes of plot have changed. + The default implementation does nothing, but items that depend + on the scale division (like QwtPlotGrid()) have to reimplement + updateScaleDiv() + + updateScaleDiv() is only called when the ScaleInterest interest + is enabled. The default implementation does nothing. + + \param xScaleDiv Scale division of the x-axis + \param yScaleDiv Scale division of the y-axis + + \sa QwtPlot::updateAxes(), ScaleInterest +*/ +void QwtPlotItem::updateScaleDiv( const QwtScaleDiv &xScaleDiv, + const QwtScaleDiv &yScaleDiv ) +{ + Q_UNUSED( xScaleDiv ); + Q_UNUSED( yScaleDiv ); +} + +/*! + \brief Update the item to changes of the legend info + + Plot items that want to display a legend ( not those, that want to + be displayed on a legend ! ) will have to implement updateLegend(). + + updateLegend() is only called when the LegendInterest interest + is enabled. The default implementation does nothing. + + \param item Plot item to be displayed on a legend + \param data Attributes how to display item on the legend + + \sa QwtPlotLegendItem + + \note Plot items, that want to be displayed on a legend + need to enable the QwtPlotItem::Legend flag and to implement + legendData() and legendIcon() + */ +void QwtPlotItem::updateLegend( const QwtPlotItem *item, + const QList &data ) +{ + Q_UNUSED( item ); + Q_UNUSED( data ); +} + +/*! + \brief Calculate the bounding scale rectangle of 2 maps + + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + + \return Bounding scale rect of the scale maps, not normalized +*/ +QRectF QwtPlotItem::scaleRect( const QwtScaleMap &xMap, + const QwtScaleMap &yMap ) const +{ + return QRectF( xMap.s1(), yMap.s1(), + xMap.sDist(), yMap.sDist() ); +} + +/*! + \brief Calculate the bounding paint rectangle of 2 maps + + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + + \return Bounding paint rectangle of the scale maps, not normalized +*/ +QRectF QwtPlotItem::paintRect( const QwtScaleMap &xMap, + const QwtScaleMap &yMap ) const +{ + const QRectF rect( xMap.p1(), yMap.p1(), + xMap.pDist(), yMap.pDist() ); + + return rect; +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_item.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_item.h new file mode 100644 index 0000000..1683d29 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_item.h @@ -0,0 +1,307 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PLOT_ITEM_H +#define QWT_PLOT_ITEM_H + +#include "qwt_global.h" +#include "qwt_text.h" +#include "qwt_legend_data.h" +#include "qwt_graphic.h" +#include +#include +#include + +class QPainter; +class QwtScaleMap; +class QwtScaleDiv; +class QwtPlot; + +/*! + \brief Base class for items on the plot canvas + + A plot item is "something", that can be painted on the plot canvas, + or only affects the scales of the plot widget. They can be categorized as: + + - Representator\n + A "Representator" is an item that represents some sort of data + on the plot canvas. The different representator classes are organized + according to the characteristics of the data: + - QwtPlotMarker + Represents a point or a horizontal/vertical coordinate + - QwtPlotCurve + Represents a series of points + - QwtPlotSpectrogram ( QwtPlotRasterItem ) + Represents raster data + - ... + + - Decorators\n + A "Decorator" is an item, that displays additional information, that + is not related to any data: + - QwtPlotGrid + - QwtPlotScaleItem + - QwtPlotSvgItem + - ... + + Depending on the QwtPlotItem::ItemAttribute flags, an item is included + into autoscaling or has an entry on the legend. + + Before misusing the existing item classes it might be better to + implement a new type of plot item + ( don't implement a watermark as spectrogram ). + Deriving a new type of QwtPlotItem primarily means to implement + the YourPlotItem::draw() method. + + \sa The cpuplot example shows the implementation of additional plot items. +*/ + +class QWT_EXPORT QwtPlotItem +{ +public: + /*! + \brief Runtime type information + + RttiValues is used to cast plot items, without + having to enable runtime type information of the compiler. + */ + enum RttiValues + { + //! Unspecific value, that can be used, when it doesn't matter + Rtti_PlotItem = 0, + + //! For QwtPlotGrid + Rtti_PlotGrid, + + //! For QwtPlotScaleItem + Rtti_PlotScale, + + //! For QwtPlotLegendItem + Rtti_PlotLegend, + + //! For QwtPlotMarker + Rtti_PlotMarker, + + //! For QwtPlotCurve + Rtti_PlotCurve, + + //! For QwtPlotSpectroCurve + Rtti_PlotSpectroCurve, + + //! For QwtPlotIntervalCurve + Rtti_PlotIntervalCurve, + + //! For QwtPlotHistogram + Rtti_PlotHistogram, + + //! For QwtPlotSpectrogram + Rtti_PlotSpectrogram, + + //! For QwtPlotSvgItem + Rtti_PlotSVG, + + //! For QwtPlotTradingCurve + Rtti_PlotTradingCurve, + + //! For QwtPlotBarChart + Rtti_PlotBarChart, + + //! For QwtPlotMultiBarChart + Rtti_PlotMultiBarChart, + + //! For QwtPlotShapeItem + Rtti_PlotShape, + + //! For QwtPlotTextLabel + Rtti_PlotTextLabel, + + //! For QwtPlotZoneItem + Rtti_PlotZone, + + /*! + Values >= Rtti_PlotUserItem are reserved for plot items + not implemented in the Qwt library. + */ + Rtti_PlotUserItem = 1000 + }; + + /*! + \brief Plot Item Attributes + + Various aspects of a plot widget depend on the attributes of + the attached plot items. If and how a single plot item + participates in these updates depends on its attributes. + + \sa setItemAttribute(), testItemAttribute(), ItemInterest + */ + enum ItemAttribute + { + //! The item is represented on the legend. + Legend = 0x01, + + /*! + The boundingRect() of the item is included in the + autoscaling calculation as long as its width or height + is >= 0.0. + */ + AutoScale = 0x02, + + /*! + The item needs extra space to display something outside + its bounding rectangle. + \sa getCanvasMarginHint() + */ + Margins = 0x04 + }; + + //! Plot Item Attributes + typedef QFlags ItemAttributes; + + /*! + \brief Plot Item Interests + + Plot items might depend on the situation of the corresponding + plot widget. By enabling an interest the plot item will be + notified, when the corresponding attribute of the plot widgets + has changed. + + \sa setItemAttribute(), testItemAttribute(), ItemInterest + */ + enum ItemInterest + { + /*! + The item is interested in updates of the scales + \sa updateScaleDiv() + */ + ScaleInterest = 0x01, + + /*! + The item is interested in updates of the legend ( of other items ) + This flag is intended for items, that want to implement a legend + for displaying entries of other plot item. + + \note If the plot item wants to be represented on a legend + enable QwtPlotItem::Legend instead. + + \sa updateLegend() + */ + LegendInterest = 0x02 + }; + + //! Plot Item Interests + typedef QFlags ItemInterests; + + //! Render hints + enum RenderHint + { + //! Enable antialiasing + RenderAntialiased = 0x1 + }; + + //! Render hints + typedef QFlags RenderHints; + + explicit QwtPlotItem( const QwtText &title = QwtText() ); + virtual ~QwtPlotItem(); + + void attach( QwtPlot *plot ); + void detach(); + + QwtPlot *plot() const; + + void setTitle( const QString &title ); + void setTitle( const QwtText &title ); + const QwtText &title() const; + + virtual int rtti() const; + + void setItemAttribute( ItemAttribute, bool on = true ); + bool testItemAttribute( ItemAttribute ) const; + + void setItemInterest( ItemInterest, bool on = true ); + bool testItemInterest( ItemInterest ) const; + + void setRenderHint( RenderHint, bool on = true ); + bool testRenderHint( RenderHint ) const; + + void setRenderThreadCount( uint numThreads ); + uint renderThreadCount() const; + + void setLegendIconSize( const QSize & ); + QSize legendIconSize() const; + + double z() const; + void setZ( double z ); + + void show(); + void hide(); + virtual void setVisible( bool ); + bool isVisible () const; + + void setAxes( int xAxis, int yAxis ); + + void setXAxis( int axis ); + int xAxis() const; + + void setYAxis( int axis ); + int yAxis() const; + + virtual void itemChanged(); + virtual void legendChanged(); + + /*! + \brief Draw the item + + \param painter Painter + \param xMap Maps x-values into pixel coordinates. + \param yMap Maps y-values into pixel coordinates. + \param canvasRect Contents rect of the canvas in painter coordinates + */ + virtual void draw( QPainter *painter, + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasRect ) const = 0; + + virtual QRectF boundingRect() const; + + virtual void getCanvasMarginHint( + const QwtScaleMap &xMap, const QwtScaleMap &yMap, + const QRectF &canvasSize, + double &left, double &top, double &right, double &bottom) const; + + virtual void updateScaleDiv( + const QwtScaleDiv&, const QwtScaleDiv& ); + + virtual void updateLegend( const QwtPlotItem *, + const QList & ); + + QRectF scaleRect( const QwtScaleMap &, const QwtScaleMap & ) const; + QRectF paintRect( const QwtScaleMap &, const QwtScaleMap & ) const; + + virtual QList legendData() const; + + virtual QwtGraphic legendIcon( int index, const QSizeF & ) const; + +protected: + QwtGraphic defaultIcon( const QBrush &, const QSizeF & ) const; + +private: + // Disabled copy constructor and operator= + QwtPlotItem( const QwtPlotItem & ); + QwtPlotItem &operator=( const QwtPlotItem & ); + + class PrivateData; + PrivateData *d_data; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotItem::ItemAttributes ) +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotItem::ItemInterests ) +Q_DECLARE_OPERATORS_FOR_FLAGS( QwtPlotItem::RenderHints ) + +Q_DECLARE_METATYPE( QwtPlotItem * ) + +#endif diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_layout.cpp b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_layout.cpp new file mode 100644 index 0000000..56ee441 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_layout.cpp @@ -0,0 +1,1442 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#include "qwt_plot_layout.h" +#include "qwt_text.h" +#include "qwt_text_label.h" +#include "qwt_scale_widget.h" +#include "qwt_abstract_legend.h" +#include +#include + +class QwtPlotLayout::LayoutData +{ +public: + void init( const QwtPlot *, const QRectF &rect ); + + struct t_legendData + { + int frameWidth; + int hScrollExtent; + int vScrollExtent; + QSize hint; + } legend; + + struct t_titleData + { + QwtText text; + int frameWidth; + } title; + + struct t_footerData + { + QwtText text; + int frameWidth; + } footer; + + struct t_scaleData + { + bool isEnabled; + const QwtScaleWidget *scaleWidget; + QFont scaleFont; + int start; + int end; + int baseLineOffset; + double tickOffset; + int dimWithoutTitle; + } scale[QwtPlot::axisCnt]; + + struct t_canvasData + { + int contentsMargins[ QwtPlot::axisCnt ]; + + } canvas; +}; + +/* + Extract all layout relevant data from the plot components +*/ +void QwtPlotLayout::LayoutData::init( const QwtPlot *plot, const QRectF &rect ) +{ + // legend + + if ( plot->legend() ) + { + legend.frameWidth = plot->legend()->frameWidth(); + legend.hScrollExtent = + plot->legend()->scrollExtent( Qt::Horizontal ); + legend.vScrollExtent = + plot->legend()->scrollExtent( Qt::Vertical ); + + const QSize hint = plot->legend()->sizeHint(); + + const int w = qMin( hint.width(), qFloor( rect.width() ) ); + + int h = plot->legend()->heightForWidth( w ); + if ( h <= 0 ) + h = hint.height(); + + legend.hint = QSize( w, h ); + } + + // title + + title.frameWidth = 0; + title.text = QwtText(); + + if ( plot->titleLabel() ) + { + const QwtTextLabel *label = plot->titleLabel(); + title.text = label->text(); + if ( !( title.text.testPaintAttribute( QwtText::PaintUsingTextFont ) ) ) + title.text.setFont( label->font() ); + + title.frameWidth = plot->titleLabel()->frameWidth(); + } + + // footer + + footer.frameWidth = 0; + footer.text = QwtText(); + + if ( plot->footerLabel() ) + { + const QwtTextLabel *label = plot->footerLabel(); + footer.text = label->text(); + if ( !( footer.text.testPaintAttribute( QwtText::PaintUsingTextFont ) ) ) + footer.text.setFont( label->font() ); + + footer.frameWidth = plot->footerLabel()->frameWidth(); + } + + // scales + + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + { + if ( plot->axisEnabled( axis ) ) + { + const QwtScaleWidget *scaleWidget = plot->axisWidget( axis ); + + scale[axis].isEnabled = true; + + scale[axis].scaleWidget = scaleWidget; + + scale[axis].scaleFont = scaleWidget->font(); + + scale[axis].start = scaleWidget->startBorderDist(); + scale[axis].end = scaleWidget->endBorderDist(); + + scale[axis].baseLineOffset = scaleWidget->margin(); + scale[axis].tickOffset = scaleWidget->margin(); + if ( scaleWidget->scaleDraw()->hasComponent( + QwtAbstractScaleDraw::Ticks ) ) + { + scale[axis].tickOffset += + scaleWidget->scaleDraw()->maxTickLength(); + } + + scale[axis].dimWithoutTitle = scaleWidget->dimForLength( + QWIDGETSIZE_MAX, scale[axis].scaleFont ); + + if ( !scaleWidget->title().isEmpty() ) + { + scale[axis].dimWithoutTitle -= + scaleWidget->titleHeightForWidth( QWIDGETSIZE_MAX ); + } + } + else + { + scale[axis].isEnabled = false; + scale[axis].start = 0; + scale[axis].end = 0; + scale[axis].baseLineOffset = 0; + scale[axis].tickOffset = 0.0; + scale[axis].dimWithoutTitle = 0; + } + } + + // canvas + + plot->canvas()->getContentsMargins( + &canvas.contentsMargins[ QwtPlot::yLeft ], + &canvas.contentsMargins[ QwtPlot::xTop ], + &canvas.contentsMargins[ QwtPlot::yRight ], + &canvas.contentsMargins[ QwtPlot::xBottom ] ); +} + +class QwtPlotLayout::PrivateData +{ +public: + PrivateData(): + spacing( 5 ) + { + } + + QRectF titleRect; + QRectF footerRect; + QRectF legendRect; + QRectF scaleRect[QwtPlot::axisCnt]; + QRectF canvasRect; + + QwtPlotLayout::LayoutData layoutData; + + QwtPlot::LegendPosition legendPos; + double legendRatio; + unsigned int spacing; + unsigned int canvasMargin[QwtPlot::axisCnt]; + bool alignCanvasToScales[QwtPlot::axisCnt]; +}; + +/*! + \brief Constructor + */ + +QwtPlotLayout::QwtPlotLayout() +{ + d_data = new PrivateData; + + setLegendPosition( QwtPlot::BottomLegend ); + setCanvasMargin( 4 ); + setAlignCanvasToScales( false ); + + invalidate(); +} + +//! Destructor +QwtPlotLayout::~QwtPlotLayout() +{ + delete d_data; +} + +/*! + Change a margin of the canvas. The margin is the space + above/below the scale ticks. A negative margin will + be set to -1, excluding the borders of the scales. + + \param margin New margin + \param axis One of QwtPlot::Axis. Specifies where the position of the margin. + -1 means margin at all borders. + \sa canvasMargin() + + \warning The margin will have no effect when alignCanvasToScale() is true +*/ + +void QwtPlotLayout::setCanvasMargin( int margin, int axis ) +{ + if ( margin < -1 ) + margin = -1; + + if ( axis == -1 ) + { + for ( axis = 0; axis < QwtPlot::axisCnt; axis++ ) + d_data->canvasMargin[axis] = margin; + } + else if ( axis >= 0 && axis < QwtPlot::axisCnt ) + d_data->canvasMargin[axis] = margin; +} + +/*! + \param axisId Axis index + \return Margin around the scale tick borders + \sa setCanvasMargin() +*/ +int QwtPlotLayout::canvasMargin( int axisId ) const +{ + if ( axisId < 0 || axisId >= QwtPlot::axisCnt ) + return 0; + + return d_data->canvasMargin[axisId]; +} + +/*! + \brief Set the align-canvas-to-axis-scales flag for all axes + + \param on True/False + \sa setAlignCanvasToScale(), alignCanvasToScale() +*/ +void QwtPlotLayout::setAlignCanvasToScales( bool on ) +{ + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + d_data->alignCanvasToScales[axis] = on; +} + +/*! + Change the align-canvas-to-axis-scales setting. The canvas may: + + - extend beyond the axis scale ends to maximize its size, + - align with the axis scale ends to control its size. + + The axisId parameter is somehow confusing as it identifies a border + of the plot and not the axes, that are aligned. F.e when QwtPlot::yLeft + is set, the left end of the the x-axes ( QwtPlot::xTop, QwtPlot::xBottom ) + is aligned. + + \param axisId Axis index + \param on New align-canvas-to-axis-scales setting + + \sa setCanvasMargin(), alignCanvasToScale(), setAlignCanvasToScales() + \warning In case of on == true canvasMargin() will have no effect +*/ +void QwtPlotLayout::setAlignCanvasToScale( int axisId, bool on ) +{ + if ( axisId >= 0 && axisId < QwtPlot::axisCnt ) + d_data->alignCanvasToScales[axisId] = on; +} + +/*! + Return the align-canvas-to-axis-scales setting. The canvas may: + - extend beyond the axis scale ends to maximize its size + - align with the axis scale ends to control its size. + + \param axisId Axis index + \return align-canvas-to-axis-scales setting + \sa setAlignCanvasToScale(), setAlignCanvasToScale(), setCanvasMargin() +*/ +bool QwtPlotLayout::alignCanvasToScale( int axisId ) const +{ + if ( axisId < 0 || axisId >= QwtPlot::axisCnt ) + return false; + + return d_data->alignCanvasToScales[ axisId ]; +} + +/*! + Change the spacing of the plot. The spacing is the distance + between the plot components. + + \param spacing New spacing + \sa setCanvasMargin(), spacing() +*/ +void QwtPlotLayout::setSpacing( int spacing ) +{ + d_data->spacing = qMax( 0, spacing ); +} + +/*! + \return Spacing + \sa margin(), setSpacing() +*/ +int QwtPlotLayout::spacing() const +{ + return d_data->spacing; +} + +/*! + \brief Specify the position of the legend + \param pos The legend's position. + \param ratio Ratio between legend and the bounding rectangle + of title, footer, canvas and axes. The legend will be shrunk + if it would need more space than the given ratio. + The ratio is limited to ]0.0 .. 1.0]. In case of <= 0.0 + it will be reset to the default ratio. + The default vertical/horizontal ratio is 0.33/0.5. + + \sa QwtPlot::setLegendPosition() +*/ + +void QwtPlotLayout::setLegendPosition( QwtPlot::LegendPosition pos, double ratio ) +{ + if ( ratio > 1.0 ) + ratio = 1.0; + + switch ( pos ) + { + case QwtPlot::TopLegend: + case QwtPlot::BottomLegend: + if ( ratio <= 0.0 ) + ratio = 0.33; + d_data->legendRatio = ratio; + d_data->legendPos = pos; + break; + case QwtPlot::LeftLegend: + case QwtPlot::RightLegend: + if ( ratio <= 0.0 ) + ratio = 0.5; + d_data->legendRatio = ratio; + d_data->legendPos = pos; + break; + default: + break; + } +} + +/*! + \brief Specify the position of the legend + \param pos The legend's position. Valid values are + \c QwtPlot::LeftLegend, \c QwtPlot::RightLegend, + \c QwtPlot::TopLegend, \c QwtPlot::BottomLegend. + + \sa QwtPlot::setLegendPosition() +*/ +void QwtPlotLayout::setLegendPosition( QwtPlot::LegendPosition pos ) +{ + setLegendPosition( pos, 0.0 ); +} + +/*! + \return Position of the legend + \sa setLegendPosition(), QwtPlot::setLegendPosition(), + QwtPlot::legendPosition() +*/ +QwtPlot::LegendPosition QwtPlotLayout::legendPosition() const +{ + return d_data->legendPos; +} + +/*! + Specify the relative size of the legend in the plot + \param ratio Ratio between legend and the bounding rectangle + of title, footer, canvas and axes. The legend will be shrunk + if it would need more space than the given ratio. + The ratio is limited to ]0.0 .. 1.0]. In case of <= 0.0 + it will be reset to the default ratio. + The default vertical/horizontal ratio is 0.33/0.5. +*/ +void QwtPlotLayout::setLegendRatio( double ratio ) +{ + setLegendPosition( legendPosition(), ratio ); +} + +/*! + \return The relative size of the legend in the plot. + \sa setLegendPosition() +*/ +double QwtPlotLayout::legendRatio() const +{ + return d_data->legendRatio; +} + +/*! + \brief Set the geometry for the title + + This method is intended to be used from derived layouts + overloading activate() + + \sa titleRect(), activate() + */ +void QwtPlotLayout::setTitleRect( const QRectF &rect ) +{ + d_data->titleRect = rect; +} + +/*! + \return Geometry for the title + \sa activate(), invalidate() +*/ +QRectF QwtPlotLayout::titleRect() const +{ + return d_data->titleRect; +} + +/*! + \brief Set the geometry for the footer + + This method is intended to be used from derived layouts + overloading activate() + + \sa footerRect(), activate() + */ +void QwtPlotLayout::setFooterRect( const QRectF &rect ) +{ + d_data->footerRect = rect; +} + +/*! + \return Geometry for the footer + \sa activate(), invalidate() +*/ +QRectF QwtPlotLayout::footerRect() const +{ + return d_data->footerRect; +} + +/*! + \brief Set the geometry for the legend + + This method is intended to be used from derived layouts + overloading activate() + + \param rect Rectangle for the legend + + \sa legendRect(), activate() + */ +void QwtPlotLayout::setLegendRect( const QRectF &rect ) +{ + d_data->legendRect = rect; +} + +/*! + \return Geometry for the legend + \sa activate(), invalidate() +*/ +QRectF QwtPlotLayout::legendRect() const +{ + return d_data->legendRect; +} + +/*! + \brief Set the geometry for an axis + + This method is intended to be used from derived layouts + overloading activate() + + \param axis Axis index + \param rect Rectangle for the scale + + \sa scaleRect(), activate() + */ +void QwtPlotLayout::setScaleRect( int axis, const QRectF &rect ) +{ + if ( axis >= 0 && axis < QwtPlot::axisCnt ) + d_data->scaleRect[axis] = rect; +} + +/*! + \param axis Axis index + \return Geometry for the scale + \sa activate(), invalidate() +*/ +QRectF QwtPlotLayout::scaleRect( int axis ) const +{ + if ( axis < 0 || axis >= QwtPlot::axisCnt ) + { + static QRectF dummyRect; + return dummyRect; + } + return d_data->scaleRect[axis]; +} + +/*! + \brief Set the geometry for the canvas + + This method is intended to be used from derived layouts + overloading activate() + + \sa canvasRect(), activate() + */ +void QwtPlotLayout::setCanvasRect( const QRectF &rect ) +{ + d_data->canvasRect = rect; +} + +/*! + \return Geometry for the canvas + \sa activate(), invalidate() +*/ +QRectF QwtPlotLayout::canvasRect() const +{ + return d_data->canvasRect; +} + +/*! + Invalidate the geometry of all components. + \sa activate() +*/ +void QwtPlotLayout::invalidate() +{ + d_data->titleRect = d_data->footerRect + = d_data->legendRect = d_data->canvasRect = QRect(); + + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + d_data->scaleRect[axis] = QRect(); +} + +/*! + \return Minimum size hint + \param plot Plot widget + + \sa QwtPlot::minimumSizeHint() +*/ + +QSize QwtPlotLayout::minimumSizeHint( const QwtPlot *plot ) const +{ + class ScaleData + { + public: + ScaleData() + { + w = h = minLeft = minRight = tickOffset = 0; + } + + int w; + int h; + int minLeft; + int minRight; + int tickOffset; + } scaleData[QwtPlot::axisCnt]; + + int canvasBorder[QwtPlot::axisCnt]; + + int fw; + plot->canvas()->getContentsMargins( &fw, NULL, NULL, NULL ); + + int axis; + for ( axis = 0; axis < QwtPlot::axisCnt; axis++ ) + { + if ( plot->axisEnabled( axis ) ) + { + const QwtScaleWidget *scl = plot->axisWidget( axis ); + ScaleData &sd = scaleData[axis]; + + const QSize hint = scl->minimumSizeHint(); + sd.w = hint.width(); + sd.h = hint.height(); + scl->getBorderDistHint( sd.minLeft, sd.minRight ); + sd.tickOffset = scl->margin(); + if ( scl->scaleDraw()->hasComponent( QwtAbstractScaleDraw::Ticks ) ) + sd.tickOffset += qCeil( scl->scaleDraw()->maxTickLength() ); + } + + canvasBorder[axis] = fw + d_data->canvasMargin[axis] + 1; + } + + + for ( axis = 0; axis < QwtPlot::axisCnt; axis++ ) + { + ScaleData &sd = scaleData[axis]; + if ( sd.w && ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) ) + { + if ( ( sd.minLeft > canvasBorder[QwtPlot::yLeft] ) + && scaleData[QwtPlot::yLeft].w ) + { + int shiftLeft = sd.minLeft - canvasBorder[QwtPlot::yLeft]; + if ( shiftLeft > scaleData[QwtPlot::yLeft].w ) + shiftLeft = scaleData[QwtPlot::yLeft].w; + + sd.w -= shiftLeft; + } + if ( ( sd.minRight > canvasBorder[QwtPlot::yRight] ) + && scaleData[QwtPlot::yRight].w ) + { + int shiftRight = sd.minRight - canvasBorder[QwtPlot::yRight]; + if ( shiftRight > scaleData[QwtPlot::yRight].w ) + shiftRight = scaleData[QwtPlot::yRight].w; + + sd.w -= shiftRight; + } + } + + if ( sd.h && ( axis == QwtPlot::yLeft || axis == QwtPlot::yRight ) ) + { + if ( ( sd.minLeft > canvasBorder[QwtPlot::xBottom] ) && + scaleData[QwtPlot::xBottom].h ) + { + int shiftBottom = sd.minLeft - canvasBorder[QwtPlot::xBottom]; + if ( shiftBottom > scaleData[QwtPlot::xBottom].tickOffset ) + shiftBottom = scaleData[QwtPlot::xBottom].tickOffset; + + sd.h -= shiftBottom; + } + if ( ( sd.minLeft > canvasBorder[QwtPlot::xTop] ) && + scaleData[QwtPlot::xTop].h ) + { + int shiftTop = sd.minRight - canvasBorder[QwtPlot::xTop]; + if ( shiftTop > scaleData[QwtPlot::xTop].tickOffset ) + shiftTop = scaleData[QwtPlot::xTop].tickOffset; + + sd.h -= shiftTop; + } + } + } + + const QWidget *canvas = plot->canvas(); + + int left, top, right, bottom; + canvas->getContentsMargins( &left, &top, &right, &bottom ); + + const QSize minCanvasSize = canvas->minimumSize(); + + int w = scaleData[QwtPlot::yLeft].w + scaleData[QwtPlot::yRight].w; + int cw = qMax( scaleData[QwtPlot::xBottom].w, scaleData[QwtPlot::xTop].w ) + + left + 1 + right + 1; + w += qMax( cw, minCanvasSize.width() ); + + int h = scaleData[QwtPlot::xBottom].h + scaleData[QwtPlot::xTop].h; + int ch = qMax( scaleData[QwtPlot::yLeft].h, scaleData[QwtPlot::yRight].h ) + + top + 1 + bottom + 1; + h += qMax( ch, minCanvasSize.height() ); + + const QwtTextLabel *labels[2]; + labels[0] = plot->titleLabel(); + labels[1] = plot->footerLabel(); + + for ( int i = 0; i < 2; i++ ) + { + const QwtTextLabel *label = labels[i]; + if ( label && !label->text().isEmpty() ) + { + // If only QwtPlot::yLeft or QwtPlot::yRight is showing, + // we center on the plot canvas. + const bool centerOnCanvas = !( plot->axisEnabled( QwtPlot::yLeft ) + && plot->axisEnabled( QwtPlot::yRight ) ); + + int labelW = w; + if ( centerOnCanvas ) + { + labelW -= scaleData[QwtPlot::yLeft].w + + scaleData[QwtPlot::yRight].w; + } + + int labelH = label->heightForWidth( labelW ); + if ( labelH > labelW ) // Compensate for a long title + { + w = labelW = labelH; + if ( centerOnCanvas ) + { + w += scaleData[QwtPlot::yLeft].w + + scaleData[QwtPlot::yRight].w; + } + + labelH = label->heightForWidth( labelW ); + } + h += labelH + d_data->spacing; + } + } + + // Compute the legend contribution + + const QwtAbstractLegend *legend = plot->legend(); + if ( legend && !legend->isEmpty() ) + { + if ( d_data->legendPos == QwtPlot::LeftLegend + || d_data->legendPos == QwtPlot::RightLegend ) + { + int legendW = legend->sizeHint().width(); + int legendH = legend->heightForWidth( legendW ); + + if ( legend->frameWidth() > 0 ) + w += d_data->spacing; + + if ( legendH > h ) + legendW += legend->scrollExtent( Qt::Horizontal ); + + if ( d_data->legendRatio < 1.0 ) + legendW = qMin( legendW, int( w / ( 1.0 - d_data->legendRatio ) ) ); + + w += legendW + d_data->spacing; + } + else // QwtPlot::Top, QwtPlot::Bottom + { + int legendW = qMin( legend->sizeHint().width(), w ); + int legendH = legend->heightForWidth( legendW ); + + if ( legend->frameWidth() > 0 ) + h += d_data->spacing; + + if ( d_data->legendRatio < 1.0 ) + legendH = qMin( legendH, int( h / ( 1.0 - d_data->legendRatio ) ) ); + + h += legendH + d_data->spacing; + } + } + + return QSize( w, h ); +} + +/*! + Find the geometry for the legend + + \param options Options how to layout the legend + \param rect Rectangle where to place the legend + + \return Geometry for the legend + \sa Options +*/ + +QRectF QwtPlotLayout::layoutLegend( Options options, + const QRectF &rect ) const +{ + const QSize hint( d_data->layoutData.legend.hint ); + + int dim; + if ( d_data->legendPos == QwtPlot::LeftLegend + || d_data->legendPos == QwtPlot::RightLegend ) + { + // We don't allow vertical legends to take more than + // half of the available space. + + dim = qMin( hint.width(), int( rect.width() * d_data->legendRatio ) ); + + if ( !( options & IgnoreScrollbars ) ) + { + if ( hint.height() > rect.height() ) + { + // The legend will need additional + // space for the vertical scrollbar. + + dim += d_data->layoutData.legend.hScrollExtent; + } + } + } + else + { + dim = qMin( hint.height(), int( rect.height() * d_data->legendRatio ) ); + dim = qMax( dim, d_data->layoutData.legend.vScrollExtent ); + } + + QRectF legendRect = rect; + switch ( d_data->legendPos ) + { + case QwtPlot::LeftLegend: + legendRect.setWidth( dim ); + break; + case QwtPlot::RightLegend: + legendRect.setX( rect.right() - dim ); + legendRect.setWidth( dim ); + break; + case QwtPlot::TopLegend: + legendRect.setHeight( dim ); + break; + case QwtPlot::BottomLegend: + legendRect.setY( rect.bottom() - dim ); + legendRect.setHeight( dim ); + break; + } + + return legendRect; +} + +/*! + Align the legend to the canvas + + \param canvasRect Geometry of the canvas + \param legendRect Maximum geometry for the legend + + \return Geometry for the aligned legend +*/ +QRectF QwtPlotLayout::alignLegend( const QRectF &canvasRect, + const QRectF &legendRect ) const +{ + QRectF alignedRect = legendRect; + + if ( d_data->legendPos == QwtPlot::BottomLegend + || d_data->legendPos == QwtPlot::TopLegend ) + { + if ( d_data->layoutData.legend.hint.width() < canvasRect.width() ) + { + alignedRect.setX( canvasRect.x() ); + alignedRect.setWidth( canvasRect.width() ); + } + } + else + { + if ( d_data->layoutData.legend.hint.height() < canvasRect.height() ) + { + alignedRect.setY( canvasRect.y() ); + alignedRect.setHeight( canvasRect.height() ); + } + } + + return alignedRect; +} + +/*! + Expand all line breaks in text labels, and calculate the height + of their widgets in orientation of the text. + + \param options Options how to layout the legend + \param rect Bounding rectangle for title, footer, axes and canvas. + \param dimTitle Expanded height of the title widget + \param dimFooter Expanded height of the footer widget + \param dimAxis Expanded heights of the axis in axis orientation. + + \sa Options +*/ +void QwtPlotLayout::expandLineBreaks( Options options, const QRectF &rect, + int &dimTitle, int &dimFooter, int dimAxis[QwtPlot::axisCnt] ) const +{ + dimTitle = dimFooter = 0; + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + dimAxis[axis] = 0; + + int backboneOffset[QwtPlot::axisCnt]; + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + { + backboneOffset[axis] = 0; + if ( !( options & IgnoreFrames ) ) + backboneOffset[axis] += d_data->layoutData.canvas.contentsMargins[ axis ]; + + if ( !d_data->alignCanvasToScales[axis] ) + backboneOffset[axis] += d_data->canvasMargin[axis]; + } + + bool done = false; + while ( !done ) + { + done = true; + + // the size for the 4 axis depend on each other. Expanding + // the height of a horizontal axis will shrink the height + // for the vertical axis, shrinking the height of a vertical + // axis will result in a line break what will expand the + // width and results in shrinking the width of a horizontal + // axis what might result in a line break of a horizontal + // axis ... . So we loop as long until no size changes. + + if ( !( ( options & IgnoreTitle ) || + d_data->layoutData.title.text.isEmpty() ) ) + { + double w = rect.width(); + + if ( d_data->layoutData.scale[QwtPlot::yLeft].isEnabled + != d_data->layoutData.scale[QwtPlot::yRight].isEnabled ) + { + // center to the canvas + w -= dimAxis[QwtPlot::yLeft] + dimAxis[QwtPlot::yRight]; + } + + int d = qCeil( d_data->layoutData.title.text.heightForWidth( w ) ); + if ( !( options & IgnoreFrames ) ) + d += 2 * d_data->layoutData.title.frameWidth; + + if ( d > dimTitle ) + { + dimTitle = d; + done = false; + } + } + + if ( !( ( options & IgnoreFooter ) || + d_data->layoutData.footer.text.isEmpty() ) ) + { + double w = rect.width(); + + if ( d_data->layoutData.scale[QwtPlot::yLeft].isEnabled + != d_data->layoutData.scale[QwtPlot::yRight].isEnabled ) + { + // center to the canvas + w -= dimAxis[QwtPlot::yLeft] + dimAxis[QwtPlot::yRight]; + } + + int d = qCeil( d_data->layoutData.footer.text.heightForWidth( w ) ); + if ( !( options & IgnoreFrames ) ) + d += 2 * d_data->layoutData.footer.frameWidth; + + if ( d > dimFooter ) + { + dimFooter = d; + done = false; + } + } + + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + { + const struct LayoutData::t_scaleData &scaleData = + d_data->layoutData.scale[axis]; + + if ( scaleData.isEnabled ) + { + double length; + if ( axis == QwtPlot::xTop || axis == QwtPlot::xBottom ) + { + length = rect.width() - dimAxis[QwtPlot::yLeft] + - dimAxis[QwtPlot::yRight]; + length -= scaleData.start + scaleData.end; + + if ( dimAxis[QwtPlot::yRight] > 0 ) + length -= 1; + + length += qMin( dimAxis[QwtPlot::yLeft], + scaleData.start - backboneOffset[QwtPlot::yLeft] ); + length += qMin( dimAxis[QwtPlot::yRight], + scaleData.end - backboneOffset[QwtPlot::yRight] ); + } + else // QwtPlot::yLeft, QwtPlot::yRight + { + length = rect.height() - dimAxis[QwtPlot::xTop] + - dimAxis[QwtPlot::xBottom]; + length -= scaleData.start + scaleData.end; + length -= 1; + + if ( dimAxis[QwtPlot::xBottom] <= 0 ) + length -= 1; + if ( dimAxis[QwtPlot::xTop] <= 0 ) + length -= 1; + + if ( dimAxis[QwtPlot::xBottom] > 0 ) + { + length += qMin( + d_data->layoutData.scale[QwtPlot::xBottom].tickOffset, + double( scaleData.start - backboneOffset[QwtPlot::xBottom] ) ); + } + if ( dimAxis[QwtPlot::xTop] > 0 ) + { + length += qMin( + d_data->layoutData.scale[QwtPlot::xTop].tickOffset, + double( scaleData.end - backboneOffset[QwtPlot::xTop] ) ); + } + + if ( dimTitle > 0 ) + length -= dimTitle + d_data->spacing; + } + + int d = scaleData.dimWithoutTitle; + if ( !scaleData.scaleWidget->title().isEmpty() ) + { + d += scaleData.scaleWidget->titleHeightForWidth( qFloor( length ) ); + } + + + if ( d > dimAxis[axis] ) + { + dimAxis[axis] = d; + done = false; + } + } + } + } +} + +/*! + Align the ticks of the axis to the canvas borders using + the empty corners. + + \param options Layout options + \param canvasRect Geometry of the canvas ( IN/OUT ) + \param scaleRect Geometries of the scales ( IN/OUT ) + + \sa Options +*/ + +void QwtPlotLayout::alignScales( Options options, + QRectF &canvasRect, QRectF scaleRect[QwtPlot::axisCnt] ) const +{ + int backboneOffset[QwtPlot::axisCnt]; + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + { + backboneOffset[axis] = 0; + + if ( !d_data->alignCanvasToScales[axis] ) + { + backboneOffset[axis] += d_data->canvasMargin[axis]; + } + + if ( !( options & IgnoreFrames ) ) + { + backboneOffset[axis] += + d_data->layoutData.canvas.contentsMargins[axis]; + } + } + + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + { + if ( !scaleRect[axis].isValid() ) + continue; + + const int startDist = d_data->layoutData.scale[axis].start; + const int endDist = d_data->layoutData.scale[axis].end; + + QRectF &axisRect = scaleRect[axis]; + + if ( axis == QwtPlot::xTop || axis == QwtPlot::xBottom ) + { + const QRectF &leftScaleRect = scaleRect[QwtPlot::yLeft]; + const int leftOffset = + backboneOffset[QwtPlot::yLeft] - startDist; + + if ( leftScaleRect.isValid() ) + { + const double dx = leftOffset + leftScaleRect.width(); + if ( d_data->alignCanvasToScales[QwtPlot::yLeft] && dx < 0.0 ) + { + /* + The axis needs more space than the width + of the left scale. + */ + const double cLeft = canvasRect.left(); // qreal -> double + canvasRect.setLeft( qMax( cLeft, axisRect.left() - dx ) ); + } + else + { + const double minLeft = leftScaleRect.left(); + const double left = axisRect.left() + leftOffset; + axisRect.setLeft( qMax( left, minLeft ) ); + } + } + else + { + if ( d_data->alignCanvasToScales[QwtPlot::yLeft] && leftOffset < 0 ) + { + canvasRect.setLeft( qMax( canvasRect.left(), + axisRect.left() - leftOffset ) ); + } + else + { + if ( leftOffset > 0 ) + axisRect.setLeft( axisRect.left() + leftOffset ); + } + } + + const QRectF &rightScaleRect = scaleRect[QwtPlot::yRight]; + const int rightOffset = + backboneOffset[QwtPlot::yRight] - endDist + 1; + + if ( rightScaleRect.isValid() ) + { + const double dx = rightOffset + rightScaleRect.width(); + if ( d_data->alignCanvasToScales[QwtPlot::yRight] && dx < 0 ) + { + /* + The axis needs more space than the width + of the right scale. + */ + const double cRight = canvasRect.right(); // qreal -> double + canvasRect.setRight( qMin( cRight, axisRect.right() + dx ) ); + } + + const double maxRight = rightScaleRect.right(); + const double right = axisRect.right() - rightOffset; + axisRect.setRight( qMin( right, maxRight ) ); + } + else + { + if ( d_data->alignCanvasToScales[QwtPlot::yRight] && rightOffset < 0 ) + { + canvasRect.setRight( qMin( canvasRect.right(), + axisRect.right() + rightOffset ) ); + } + else + { + if ( rightOffset > 0 ) + axisRect.setRight( axisRect.right() - rightOffset ); + } + } + } + else // QwtPlot::yLeft, QwtPlot::yRight + { + const QRectF &bottomScaleRect = scaleRect[QwtPlot::xBottom]; + const int bottomOffset = + backboneOffset[QwtPlot::xBottom] - endDist + 1; + + if ( bottomScaleRect.isValid() ) + { + const double dy = bottomOffset + bottomScaleRect.height(); + if ( d_data->alignCanvasToScales[QwtPlot::xBottom] && dy < 0 ) + { + /* + The axis needs more space than the height + of the bottom scale. + */ + const double cBottom = canvasRect.bottom(); // qreal -> double + canvasRect.setBottom( qMin( cBottom, axisRect.bottom() + dy ) ); + } + else + { + const double maxBottom = bottomScaleRect.top() + + d_data->layoutData.scale[QwtPlot::xBottom].tickOffset; + const double bottom = axisRect.bottom() - bottomOffset; + axisRect.setBottom( qMin( bottom, maxBottom ) ); + } + } + else + { + if ( d_data->alignCanvasToScales[QwtPlot::xBottom] && bottomOffset < 0 ) + { + canvasRect.setBottom( qMin( canvasRect.bottom(), + axisRect.bottom() + bottomOffset ) ); + } + else + { + if ( bottomOffset > 0 ) + axisRect.setBottom( axisRect.bottom() - bottomOffset ); + } + } + + const QRectF &topScaleRect = scaleRect[QwtPlot::xTop]; + const int topOffset = backboneOffset[QwtPlot::xTop] - startDist; + + if ( topScaleRect.isValid() ) + { + const double dy = topOffset + topScaleRect.height(); + if ( d_data->alignCanvasToScales[QwtPlot::xTop] && dy < 0 ) + { + /* + The axis needs more space than the height + of the top scale. + */ + const double cTop = canvasRect.top(); // qreal -> double + canvasRect.setTop( qMax( cTop, axisRect.top() - dy ) ); + } + else + { + const double minTop = topScaleRect.bottom() - + d_data->layoutData.scale[QwtPlot::xTop].tickOffset; + const double top = axisRect.top() + topOffset; + axisRect.setTop( qMax( top, minTop ) ); + } + } + else + { + if ( d_data->alignCanvasToScales[QwtPlot::xTop] && topOffset < 0 ) + { + canvasRect.setTop( qMax( canvasRect.top(), + axisRect.top() - topOffset ) ); + } + else + { + if ( topOffset > 0 ) + axisRect.setTop( axisRect.top() + topOffset ); + } + } + } + } + + /* + The canvas has been aligned to the scale with largest + border distances. Now we have to realign the other scale. + */ + + + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + { + QRectF &sRect = scaleRect[axis]; + + if ( !sRect.isValid() ) + continue; + + if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop ) + { + if ( d_data->alignCanvasToScales[QwtPlot::yLeft] ) + { + double y = canvasRect.left() - d_data->layoutData.scale[axis].start; + if ( !( options & IgnoreFrames ) ) + y += d_data->layoutData.canvas.contentsMargins[ QwtPlot::yLeft ]; + + sRect.setLeft( y ); + } + if ( d_data->alignCanvasToScales[QwtPlot::yRight] ) + { + double y = canvasRect.right() - 1 + d_data->layoutData.scale[axis].end; + if ( !( options & IgnoreFrames ) ) + y -= d_data->layoutData.canvas.contentsMargins[ QwtPlot::yRight ]; + + sRect.setRight( y ); + } + + if ( d_data->alignCanvasToScales[ axis ] ) + { + if ( axis == QwtPlot::xTop ) + sRect.setBottom( canvasRect.top() ); + else + sRect.setTop( canvasRect.bottom() ); + } + } + else + { + if ( d_data->alignCanvasToScales[QwtPlot::xTop] ) + { + double x = canvasRect.top() - d_data->layoutData.scale[axis].start; + if ( !( options & IgnoreFrames ) ) + x += d_data->layoutData.canvas.contentsMargins[ QwtPlot::xTop ]; + + sRect.setTop( x ); + } + if ( d_data->alignCanvasToScales[QwtPlot::xBottom] ) + { + double x = canvasRect.bottom() - 1 + d_data->layoutData.scale[axis].end; + if ( !( options & IgnoreFrames ) ) + x -= d_data->layoutData.canvas.contentsMargins[ QwtPlot::xBottom ]; + + sRect.setBottom( x ); + } + + if ( d_data->alignCanvasToScales[ axis ] ) + { + if ( axis == QwtPlot::yLeft ) + sRect.setRight( canvasRect.left() ); + else + sRect.setLeft( canvasRect.right() ); + } + } + } +} + +/*! + \brief Recalculate the geometry of all components. + + \param plot Plot to be layout + \param plotRect Rectangle where to place the components + \param options Layout options + + \sa invalidate(), titleRect(), footerRect() + legendRect(), scaleRect(), canvasRect() +*/ +void QwtPlotLayout::activate( const QwtPlot *plot, + const QRectF &plotRect, Options options ) +{ + invalidate(); + + QRectF rect( plotRect ); // undistributed rest of the plot rect + + // We extract all layout relevant parameters from the widgets, + // and save them to d_data->layoutData. + + d_data->layoutData.init( plot, rect ); + + if ( !( options & IgnoreLegend ) + && plot->legend() && !plot->legend()->isEmpty() ) + { + d_data->legendRect = layoutLegend( options, rect ); + + // subtract d_data->legendRect from rect + + const QRegion region( rect.toRect() ); + rect = region.subtracted( d_data->legendRect.toRect() ).boundingRect(); + + switch ( d_data->legendPos ) + { + case QwtPlot::LeftLegend: + rect.setLeft( rect.left() + d_data->spacing ); + break; + case QwtPlot::RightLegend: + rect.setRight( rect.right() - d_data->spacing ); + break; + case QwtPlot::TopLegend: + rect.setTop( rect.top() + d_data->spacing ); + break; + case QwtPlot::BottomLegend: + rect.setBottom( rect.bottom() - d_data->spacing ); + break; + } + } + + /* + +---+-----------+---+ + | Title | + +---+-----------+---+ + | | Axis | | + +---+-----------+---+ + | A | | A | + | x | Canvas | x | + | i | | i | + | s | | s | + +---+-----------+---+ + | | Axis | | + +---+-----------+---+ + | Footer | + +---+-----------+---+ + */ + + // title, footer and axes include text labels. The height of each + // label depends on its line breaks, that depend on the width + // for the label. A line break in a horizontal text will reduce + // the available width for vertical texts and vice versa. + // expandLineBreaks finds the height/width for title, footer and axes + // including all line breaks. + + int dimTitle, dimFooter, dimAxes[QwtPlot::axisCnt]; + expandLineBreaks( options, rect, dimTitle, dimFooter, dimAxes ); + + if ( dimTitle > 0 ) + { + d_data->titleRect.setRect( + rect.left(), rect.top(), rect.width(), dimTitle ); + + rect.setTop( d_data->titleRect.bottom() + d_data->spacing ); + + if ( d_data->layoutData.scale[QwtPlot::yLeft].isEnabled != + d_data->layoutData.scale[QwtPlot::yRight].isEnabled ) + { + // if only one of the y axes is missing we align + // the title centered to the canvas + + d_data->titleRect.setX( rect.left() + dimAxes[QwtPlot::yLeft] ); + d_data->titleRect.setWidth( rect.width() + - dimAxes[QwtPlot::yLeft] - dimAxes[QwtPlot::yRight] ); + } + } + + if ( dimFooter > 0 ) + { + d_data->footerRect.setRect( + rect.left(), rect.bottom() - dimFooter, rect.width(), dimFooter ); + + rect.setBottom( d_data->footerRect.top() - d_data->spacing ); + + if ( d_data->layoutData.scale[QwtPlot::yLeft].isEnabled != + d_data->layoutData.scale[QwtPlot::yRight].isEnabled ) + { + // if only one of the y axes is missing we align + // the footer centered to the canvas + + d_data->footerRect.setX( rect.left() + dimAxes[QwtPlot::yLeft] ); + d_data->footerRect.setWidth( rect.width() + - dimAxes[QwtPlot::yLeft] - dimAxes[QwtPlot::yRight] ); + } + } + + d_data->canvasRect.setRect( + rect.x() + dimAxes[QwtPlot::yLeft], + rect.y() + dimAxes[QwtPlot::xTop], + rect.width() - dimAxes[QwtPlot::yRight] - dimAxes[QwtPlot::yLeft], + rect.height() - dimAxes[QwtPlot::xBottom] - dimAxes[QwtPlot::xTop] ); + + for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ ) + { + // set the rects for the axes + + if ( dimAxes[axis] ) + { + int dim = dimAxes[axis]; + QRectF &scaleRect = d_data->scaleRect[axis]; + + scaleRect = d_data->canvasRect; + switch ( axis ) + { + case QwtPlot::yLeft: + scaleRect.setX( d_data->canvasRect.left() - dim ); + scaleRect.setWidth( dim ); + break; + case QwtPlot::yRight: + scaleRect.setX( d_data->canvasRect.right() ); + scaleRect.setWidth( dim ); + break; + case QwtPlot::xBottom: + scaleRect.setY( d_data->canvasRect.bottom() ); + scaleRect.setHeight( dim ); + break; + case QwtPlot::xTop: + scaleRect.setY( d_data->canvasRect.top() - dim ); + scaleRect.setHeight( dim ); + break; + } + scaleRect = scaleRect.normalized(); + } + } + + // +---+-----------+---+ + // | <- Axis -> | + // +-^-+-----------+-^-+ + // | | | | | | + // | | | | + // | A | | A | + // | x | Canvas | x | + // | i | | i | + // | s | | s | + // | | | | + // | | | | | | + // +-V-+-----------+-V-+ + // | <- Axis -> | + // +---+-----------+---+ + + // The ticks of the axes - not the labels above - should + // be aligned to the canvas. So we try to use the empty + // corners to extend the axes, so that the label texts + // left/right of the min/max ticks are moved into them. + + alignScales( options, d_data->canvasRect, d_data->scaleRect ); + + if ( !d_data->legendRect.isEmpty() ) + { + // We prefer to align the legend to the canvas - not to + // the complete plot - if possible. + + d_data->legendRect = alignLegend( d_data->canvasRect, d_data->legendRect ); + } +} diff --git a/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_layout.h b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_layout.h new file mode 100644 index 0000000..27feab5 --- /dev/null +++ b/Vimba_6_0/VimbaCPP/Examples/VimbaViewer/Source/ExternLib/qwt/qwt_plot_layout.h @@ -0,0 +1,122 @@ +/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** + * Qwt Widget Library + * Copyright (C) 1997 Josef Wilgen + * Copyright (C) 2002 Uwe Rathmann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the Qwt License, Version 1.0 + *****************************************************************************/ + +#ifndef QWT_PLOT_LAYOUT_H +#define QWT_PLOT_LAYOUT_H + +#include "qwt_global.h" +#include "qwt_plot.h" + +/*! + \brief Layout engine for QwtPlot. + + It is used by the QwtPlot widget to organize its internal widgets + or by QwtPlot::print() to render its content to a QPaintDevice like + a QPrinter, QPixmap/QImage or QSvgRenderer. + + \sa QwtPlot::setPlotLayout() +*/ + +class QWT_EXPORT QwtPlotLayout +{ +public: + /*! + Options to configure the plot layout engine + \sa activate(), QwtPlotRenderer + */ + enum Option + { + //! Unused + AlignScales = 0x01, + + /*! + Ignore the dimension of the scrollbars. There are no + scrollbars, when the plot is not rendered to widgets. + */ + IgnoreScrollbars = 0x02, + + //! Ignore all frames. + IgnoreFrames = 0x04, + + //! Ignore the legend. + IgnoreLegend = 0x08, + + //! Ignore the title. + IgnoreTitle = 0x10, + + //! Ignore the footer. + IgnoreFooter = 0x20 + }; + + //! Layout options + typedef QFlags