diff --git a/CMakeLists.txt b/CMakeLists.txt index b96e836b..ecaebb0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -244,7 +244,8 @@ add_subdirectory( plasma ) add_subdirectory( kunitconversion ) add_subdirectory( kdewebkit ) add_subdirectory( includes ) - +add_subdirectory( libkdcraw ) +add_subdirectory( libkexiv2 ) add_subdirectory( experimental ) ################# write dependency file which will be installed ################# diff --git a/cmake/modules/FindLibRaw.cmake b/cmake/modules/FindLibRaw.cmake new file mode 100644 index 00000000..d6966dbc --- /dev/null +++ b/cmake/modules/FindLibRaw.cmake @@ -0,0 +1,79 @@ +# - Find LibRaw +# Find the LibRaw library +# This module defines +# LibRaw_VERSION_STRING, the version string of LibRaw +# LibRaw_INCLUDE_DIR, where to find libraw.h +# LibRaw_LIBRARIES, the libraries needed to use LibRaw (non-thread-safe) +# LibRaw_r_LIBRARIES, the libraries needed to use LibRaw (thread-safe) +# LibRaw_DEFINITIONS, the definitions needed to use LibRaw (non-thread-safe) +# LibRaw_r_DEFINITIONS, the definitions needed to use LibRaw (thread-safe) +# +# Copyright (c) 2013, Pino Toscano +# Copyright (c) 2013, Gilles Caulier +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +FIND_PACKAGE(PkgConfig) + +IF(PKG_CONFIG_FOUND) + PKG_CHECK_MODULES(PC_LIBRAW libraw) + SET(LibRaw_DEFINITIONS ${PC_LIBRAW_CFLAGS_OTHER}) + + PKG_CHECK_MODULES(PC_LIBRAW_R libraw_r) + SET(LibRaw_r_DEFINITIONS ${PC_LIBRAW_R_CFLAGS_OTHER}) +ENDIF() + +FIND_PATH(LibRaw_INCLUDE_DIR libraw.h + HINTS + ${PC_LIBRAW_INCLUDEDIR} + ${PC_LibRaw_INCLUDE_DIRS} + PATH_SUFFIXES libraw + ) + +FIND_LIBRARY(LibRaw_LIBRARIES NAMES raw + HINTS + ${PC_LIBRAW_LIBDIR} + ${PC_LIBRAW_LIBRARY_DIRS} + ) + +FIND_LIBRARY(LibRaw_r_LIBRARIES NAMES raw_r + HINTS + ${PC_LIBRAW_R_LIBDIR} + ${PC_LIBRAW_R_LIBRARY_DIRS} + ) + +IF(LibRaw_INCLUDE_DIR) + FILE(READ ${LibRaw_INCLUDE_DIR}/libraw_version.h _libraw_version_content) + + STRING(REGEX MATCH "#define LIBRAW_MAJOR_VERSION[ \t]*([0-9]*)\n" _version_major_match ${_libraw_version_content}) + SET(_libraw_version_major "${CMAKE_MATCH_1}") + + STRING(REGEX MATCH "#define LIBRAW_MINOR_VERSION[ \t]*([0-9]*)\n" _version_minor_match ${_libraw_version_content}) + SET(_libraw_version_minor "${CMAKE_MATCH_1}") + + STRING(REGEX MATCH "#define LIBRAW_PATCH_VERSION[ \t]*([0-9]*)\n" _version_patch_match ${_libraw_version_content}) + SET(_libraw_version_patch "${CMAKE_MATCH_1}") + + IF(_version_major_match AND _version_minor_match AND _version_patch_match) + SET(LibRaw_VERSION_STRING "${_libraw_version_major}.${_libraw_version_minor}.${_libraw_version_patch}") + ELSE() + IF(NOT LibRaw_FIND_QUIETLY) + MESSAGE(STATUS "Failed to get version information from ${LibRaw_INCLUDE_DIR}/libraw_version.h") + ENDIF() + ENDIF() +ENDIF() + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibRaw + REQUIRED_VARS LibRaw_LIBRARIES LibRaw_INCLUDE_DIR + VERSION_VAR LibRaw_VERSION_STRING + ) + +MARK_AS_ADVANCED(LibRaw_VERSION_STRING + LibRaw_INCLUDE_DIR + LibRaw_LIBRARIES + LibRaw_r_LIBRARIES + LibRaw_DEFINITIONS + LibRaw_r_DEFINITIONS + ) diff --git a/kdewebkit/kwebkitpart/kwebkitpart.lsm b/kdewebkit/kwebkitpart/kwebkitpart.lsm deleted file mode 100644 index 4f7ccf52..00000000 --- a/kdewebkit/kwebkitpart/kwebkitpart.lsm +++ /dev/null @@ -1,17 +0,0 @@ -Begin3 -Title: kwebkitpart -Version: 1.2.0 -Entered-date: 06APR2011 -Description: A WebKit browser component for KDE (KPart) -Keywords: webkit, webkitpart -Author: Trolltech ASA - Urs Wolfer - Laurent Montel - Dawit Alemayehu -Maintained-by: Dawit Alemayehu -Primary-site: ftp://ftp.kde.org/pub/kde/stable/kwebkitpart/1.2/ -Home-Page: https://projects.kde.org/projects/extragear/base/kwebkitpart -Original-site: None -Platforms: KDE 4.4 and higher -Copying-policy: LGPL -End diff --git a/libkdcraw/.gitignore b/libkdcraw/.gitignore new file mode 100644 index 00000000..41554037 --- /dev/null +++ b/libkdcraw/.gitignore @@ -0,0 +1,2 @@ +*.kate-swp +tests/databases/*/*.db diff --git a/libkdcraw/.krazy b/libkdcraw/.krazy new file mode 100644 index 00000000..70047a58 --- /dev/null +++ b/libkdcraw/.krazy @@ -0,0 +1,2 @@ +SKIP /libraw/ + diff --git a/libkdcraw/AUTHORS b/libkdcraw/AUTHORS new file mode 100644 index 00000000..4ece2f5b --- /dev/null +++ b/libkdcraw/AUTHORS @@ -0,0 +1,15 @@ +AUTHORS AND MAINTAINERS : + +Caulier Gilles +Marcel Wiesweg + +CONTRIBUTORS: + +Angelo Naselli +Gerhard Kulzer +Achim Bohnet +Guillaume Castagnino + +THANKS: + +Alex Tutubalin from LibRaw project (http://www.libraw.org) \ No newline at end of file diff --git a/libkdcraw/CMakeLists.txt b/libkdcraw/CMakeLists.txt new file mode 100644 index 00000000..66ba767a --- /dev/null +++ b/libkdcraw/CMakeLists.txt @@ -0,0 +1,102 @@ +# =========================================================== +# +# This file is a part of digiKam project +# http://www.digikam.org +# +# @date 2006-12-09 +# @brief a tread-safe libraw C++ program interface for KDE +# +# @author Copyright (C) 2006-2014 by Gilles Caulier +# caulier dot gilles at gmail dot com +# +# This program is free software; you can redistribute it +# and/or modify it under the terms of the GNU General +# Public License as published by the Free Software Foundation; +# either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# ============================================================ + +PROJECT(libkdcraw) + +MESSAGE(STATUS "----------------------------------------------------------------------------------") +MESSAGE(STATUS "Starting CMake configuration for: libkdcraw") + +FIND_PACKAGE(KDE4 REQUIRED 4.14.3) +INCLUDE(KDE4Defaults) +INCLUDE(MacroLibrary) +INCLUDE(MacroOptionalAddSubdirectory) +INCLUDE(FindPackageHandleStandardArgs) +INCLUDE(CMakePackageConfigHelpers) + +# NOTE: Libraw 0.16.x is prefered version to use because it's ported to Cmake with full features supported. +# Until libraw 0.16.0 is release (ends of 2013), we will support previous version (with limited support) +FIND_PACKAGE(LibRaw 0.15) +SET_PACKAGE_PROPERTIES(LibRaw PROPERTIES DESCRIPTION "library that provides image Raw file demosaicing" URL "http://www.libraw.org" TYPE REQUIRED PURPOSE "Required to build libkdcraw") +IF(NOT LIBRAW_FOUND) + FEATURE_SUMMARY( + WHAT ALL + INCLUDE_QUIET_PACKAGES + FATAL_ON_MISSING_REQUIRED_PACKAGES + ) + RETURN() +ENDIF() + +# Check LibRaw config header. +MESSAGE(STATUS "LibRaw version: ${LibRaw_VERSION_STRING}") + +IF(EXISTS "${LibRaw_INCLUDE_DIR}/libraw_config.h") + ADD_DEFINITIONS(-DLIBRAW_HAS_CONFIG) + MESSAGE(STATUS "LibRaw config file exists: yes") +ELSE() + MESSAGE(STATUS "LibRaw config file exists: no") +ENDIF() + +ADD_DEFINITIONS(${QT_DEFINITIONS} + ${QT_QTDBUS_DEFINITIONS} + ${KDE4_DEFINITIONS} + ${LibRaw_r_DEFINITIONS} + ) + +INCLUDE_DIRECTORIES(${QDBUS_INCLUDE_DIRS} + ${CMAKE_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${KDE4_INCLUDES} + ${CMAKE_SOURCE_DIR}/threadweaver + ${LibRaw_INCLUDE_DIR} + ) + +SET(LIBKDCRAW_AREA_CODE_GENERAL 51002) +ADD_DEFINITIONS(-DKDE_DEFAULT_DEBUG_AREA=${LIBKDCRAW_AREA_CODE_GENERAL}) + +# ================================================================================================== +# Set env. variables accordinly. + +SET(DCRAW_LIB_VERSION_STRING "${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}.${KDE_VERSION_RELEASE}") +SET(DCRAW_LIB_VERSION_ID "0x0${KDE_VERSION_MAJOR}0${KDE_VERSION_MINOR}0${KDE_VERSION_RELEASE}") + +SET(DCRAW_LIB_SO_VERSION_STRING "${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}.${KDE_VERSION_RELEASE}") + +# ================================================================================================== + +ADD_SUBDIRECTORY(libkdcraw) +ADD_SUBDIRECTORY(icons) +ADD_SUBDIRECTORY(profiles) + +IF(KDE4_BUILD_TESTS) + MACRO_OPTIONAL_ADD_SUBDIRECTORY(tests) +ENDIF(KDE4_BUILD_TESTS) + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libkdcraw.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libkdcraw.pc) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libkdcraw.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +FEATURE_SUMMARY( + WHAT ALL + INCLUDE_QUIET_PACKAGES + FATAL_ON_MISSING_REQUIRED_PACKAGES +) diff --git a/libkdcraw/COPYING b/libkdcraw/COPYING new file mode 100644 index 00000000..c13faf0d --- /dev/null +++ b/libkdcraw/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libkdcraw/COPYING-CMAKE-SCRIPTS b/libkdcraw/COPYING-CMAKE-SCRIPTS new file mode 100644 index 00000000..4b417765 --- /dev/null +++ b/libkdcraw/COPYING-CMAKE-SCRIPTS @@ -0,0 +1,22 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. diff --git a/libkdcraw/COPYING.LIB b/libkdcraw/COPYING.LIB new file mode 100644 index 00000000..5bc8fb2c --- /dev/null +++ b/libkdcraw/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 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 library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + 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 Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the 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 a program 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. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + 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, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +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 compile 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) 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. + + c) 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. + + d) 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 source code 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 to +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 Library 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. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/libkdcraw/ChangeLog b/libkdcraw/ChangeLog new file mode 100644 index 00000000..d2140ad1 --- /dev/null +++ b/libkdcraw/ChangeLog @@ -0,0 +1,1661 @@ +V 0.1.4 - 2008-03-09 +---------------------------------------------------------------------------- +2008-03-05 10:25 cgilles + + * [r782489] libkdcraw/NEWS: + update + +2008-03-05 10:24 cgilles + + * [r782487] libkdcraw/dcraw/CAMERALIST, libkdcraw/dcraw/dcraw.c, + libkdcraw/libkdcraw/dcrawbinary.cpp: + backport commit #782437 from KDE4 + +2008-03-02 08:31 cgilles + + * [r781202] libkdcraw/libkdcraw/dcrawsettingswidget.cpp: + fix i18n + +2008-02-26 07:01 cgilles + + * [r779443] libkdcraw/libkdcraw/dcrawbinary.cpp, + libkdcraw/libkdcraw/dcrawbinary.h, + libkdcraw/libkdcraw/dcrawinfocontainer.h, + libkdcraw/libkdcraw/kdcraw.cpp, libkdcraw/libkdcraw/rawfiles.h, + libkdcraw/libkdcraw/version.h: + polish + +2008-02-26 06:59 cgilles + + * [r779442] libkdcraw/libkdcraw/kdcraw.cpp: + polish + +2008-02-22 14:24 vfuoglio + + * [r778103] kipi-plugins/rawconverter/batchdialog.cpp, + kipi-plugins/rawconverter/batchdialog.h, + kipi-plugins/rawconverter/singledialog.cpp, + kipi-plugins/rawconverter/singledialog.h, libkdcraw/NEWS, + libkdcraw/libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/libkdcraw/dcrawsettingswidget.h, + libkdcraw/libkdcraw/kdcraw.cpp, libkdcraw/libkdcraw/kdcraw.h, + libkdcraw/libkdcraw/rawdecodingsettings.h: + White balance with RAW files improvements (related to bug + #142055). + + Patches by Guillaume Castagnino. + + CCMAIL : kde-imaging@kde.org + CCMAIL : casta@xwing.info + CCMAIL : caulier.gilles@gmail.com + +2008-02-07 13:23 cgilles + + * [r772001] libkdcraw/libkdcraw/dcrawbinary.cpp: + fix dcraw release + +2008-02-07 12:57 gkulzer + + * [r771991] libkdcraw/NEWS: + update to 8.82 + no new options, just renameing of -k black ro -k darkness + 4 new cameras: + Sony DSLR-A200, Sony DSLR-A700, Sony XCD-SX910CR, STV680 VGA + CCMAIL: caulier.gilles@gmail.com + +2008-02-07 12:56 gkulzer + + * [r771990] libkdcraw/dcraw/CAMERALIST, libkdcraw/dcraw/dcraw.c, + libkdcraw/dcraw/kdcraw.1: + update to 8.82 + no new options, just renameing of -k black ro -k darkness + 4 new cameras: + Sony DSLR-A200, Sony DSLR-A700, Sony XCD-SX910CR, STV680 VGA + CCMAIL: caulier.gilles@gmail.com + +2008-01-01 20:40 cgilles + + * [r755552] libkdcraw/libkdcraw/dcrawbinary.h: + static method + +2008-01-01 20:03 cgilles + + * [r755539] kipi-plugins/imageviewer/texture.cpp, + kipi-plugins/jpeglossless/utils.cpp, + kipi-plugins/printwizard/tphoto.cpp, + kipi-plugins/rawconverter/plugin_rawconverter.cpp, + kipi-plugins/sendimages/sendimages.cpp, + libkdcraw/libkdcraw/dcrawbinary.cpp, + libkdcraw/libkdcraw/dcrawbinary.h: + new method to get raw files extension string depending of the + libkdcraw version installled on computer. + +2008-01-01 09:36 cgilles + + * [r755359] libkdcraw/libkdcraw/dcrawbinary.cpp, + libkdcraw/libkdcraw/dcrawbinary.h: + new method backported from KDE4 to get list of supported RAW + camera + +2007-12-30 22:04 anaselli + + * [r754876] libkdcraw/configure.in.in, libkdcraw/libkdcraw.lsm, + libkdcraw/libkdcraw.pc.in, libkdcraw/libkdcraw/kdcraw.cpp, + libkdcraw/libkdcraw/kdcraw.h: + Breakage of the year, new static method version() has been added + + CCMAIL: kde-imaging@kde.org + +---------------------------------------------------------------------------- +V 0.1.3 - 2007-12-23 +---------------------------------------------------------------------------- +2007-12-14 14:09 cgilles + + * [r748435] libkdcraw/libkdcraw/version.h: + fix new version + +2007-12-14 08:17 gkulzer + + * [r748345] libkdcraw/dcraw/CAMERALIST: + clean-up list + +2007-12-14 07:57 gkulzer + + * [r748333] libkdcraw/NEWS, libkdcraw/dcraw/CAMERALIST, + libkdcraw/dcraw/README, libkdcraw/dcraw/dcraw.c, + libkdcraw/dcraw/kdcraw.1, libkdcraw/libkdcraw/dcrawbinary.cpp: + update dcraw to 8.81. Interface stays compatible, regression + testing done. 4 cameras added. Additional parameter -W to not + adjust brightness + +2007-11-16 14:59 gkulzer + + * [r737564] libkdcraw/NEWS: + dcraw update to 8.80 + CCMAIL:caulier.gilles@gmail.com + +2007-11-16 14:48 gkulzer + + * [r737563] libkdcraw/dcraw/CAMERALIST, libkdcraw/dcraw/dcraw.c, + libkdcraw/libkdcraw/dcrawbinary.cpp: + update dcraw to version 8.80 + +2007-11-14 10:22 cgilles + + * [r736540] libkdcraw/dcraw/dcraw.c: + fix double "%s" + +2007-11-02 14:13 gkulzer + + * [r732003] libkdcraw/dcraw/kdcraw.1: + man page update + +2007-11-02 11:58 cgilles + + * [r731957] libkdcraw/dcraw/Makefile.am: + polish + +2007-11-02 11:44 cgilles + + * [r731953] libkdcraw/libkdcraw.lsm, libkdcraw/libkdcraw.pc.in: + upgrate libkdcraw version + +2007-11-02 11:44 cgilles + + * [r731952] libkdcraw/dcraw/Makefile.am: + install CAMERALIST on kdcraw bin folder + +2007-11-02 11:33 cgilles + + * [r731948] libkdcraw/dcraw/dcraw.c: + separate Make ans Model informations from identify command line + +2007-11-02 10:46 gkulzer + + * [r731936] libkdcraw/dcraw/CAMERALIST, libkdcraw/dcraw/dcraw.c, + libkdcraw/dcraw/kdcraw.1, libkdcraw/libkdcraw/dcrawbinary.cpp: + dcraw update to version 8.78 + CCMAIL:caulier.gilles@gmail.com + +2007-10-21 10:34 hasso + + * [r727627] libkdcraw/configure.in.in, libkdcraw/dcraw/Makefile.am: + Make it to find the lcms from nonstandard places provided by user + via + --with-extra-* flags. Fixes detecting lcms installed from pkgsrc + package + system. + +2007-09-07 22:02 vfuoglio + + * [r709600] libkdcraw/ChangeLog, libkdcraw/configure.in.in, + libkdcraw/libkdcraw.lsm, prepare_libkdcraw.rb: + Preparing libkdcraw 0.1.2 release + + SNV_SILENT: + +---------------------------------------------------------------------------- +V 0.1.2 - 2007-09-07 +---------------------------------------------------------------------------- +2007-09-04 21:03 cgilles + + * [r708412] libkdcraw/AUTHORS: + fix email + +2007-09-04 09:57 cgilles + + * [r708249] libkdcraw/AUTHORS: + Add Guillaume as contributor + +2007-08-24 08:10 cgilles + + * [r704175] libkdcraw/configure.in.in: + fix ABI number for next release + +2007-08-23 11:07 cgilles + + * [r703805] libkdcraw/configure.in.in: + fix release number + +2007-08-22 13:58 cgilles + + * [r703433] libkdcraw/libkdcraw/kdcraw.cpp: + add comment + +2007-08-22 13:23 cgilles + + * [r703414] libkdcraw/libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/libkdcraw/dcrawsettingswidget.h, + libkdcraw/libkdcraw/kdcraw.cpp, + libkdcraw/libkdcraw/rawdecodingsettings.h: + libkdcraw from KDE3 branch : patch from Guillaume Castagnino + about to support new chromatic aberration reduction options + provided by dcraw 8.77 + CCBUGS: 148561 + CCMAIL: casta@xwing.info + +2007-08-22 04:33 cgilles + + * [r703160] libkdcraw/libkdcraw/dcrawinfocontainer.h, + libkdcraw/libkdcraw/kdcraw.cpp: + libkdcraw from KDE3 branch : like BC is broken with future + release, i backport "Picture Owner" extraction code from KDE4 + provided by new dcraw 8.77 + +2007-08-20 09:59 cgilles + + * [r702272] libkdcraw/libkdcraw/dcrawsettingswidget.cpp: + fix option + +2007-08-20 09:39 cgilles + + * [r702258] libkdcraw/libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/libkdcraw/rawdecodingsettings.h: + libkdcraw from KDE3 branch : patch from Guillaume Castagnino + about to handle RAW decoding quality settings properlly since + dcraw 8.73 include a new interpolation method named PPG + CCMAIL: kde-imaging@kde.org + CCMAIL: casta@xwing.info + +2007-07-25 14:37 cgilles + + * [r692427] libkdcraw/libkdcraw/dcrawsettingswidget.cpp: + fix typo + +2007-07-24 12:06 cgilles + + * [r691818] libkdcraw/libkdcraw/dcrawbinary.cpp: + fix internal dcraw version + +2007-07-24 11:57 cgilles + + * [r691813] libkdcraw/dcraw/CAMERALIST, libkdcraw/dcraw/dcraw.c, + libkdcraw/dcraw/kdcraw.1: + libkdcraw from KDE3 branch : + - update internal dcraw.c implementation from 8.76 to 8.77. + - new cameras RAW file supported : Leaf Aptus 54S and Leaf Aptus + 75S + - Binary compatibility respected. + - Changelog from dcraw repository : + * Reject 8-bit grayscale TIFFs. + * Decode raw CINE files, which may exceed 2GB. + * Error-check the "-s" option, and enable "-s all". + * Support camera WB for the Canon EOS-1D and EOS-1DS. + * Use full output range for "-H 2". + + CCMAIL: digikam-devel@kde.org + +2007-07-04 07:59 cgilles + + * [r683108] libkdcraw/libkdcraw/dcrawsettingswidget.cpp: + fix unclip color control with reconstruct setting + +2007-07-04 07:53 cgilles + + * [r683105] libkdcraw/AUTHORS, libkdcraw/NEWS, + libkdcraw/libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/libkdcraw/rawdecodingsettings.h: + libkdcraw from KDE3 branch: update setting widget to new dcraw + 8.76. + +2007-07-04 07:44 cgilles + + * [r683099] libkdcraw/libkdcraw/dcrawbinary.cpp: + update + +2007-07-04 07:41 cgilles + + * [r683096] libkdcraw/libkdcraw/version.h: + update + +2007-07-04 07:41 cgilles + + * [r683095] libkdcraw/libkdcraw.lsm, libkdcraw/libkdcraw.pc.in: + update + +2007-07-04 07:40 cgilles + + * [r683094] libkdcraw/dcraw/kdcraw.1: + update man page + +2007-07-04 07:39 cgilles + + * [r683093] libkdcraw/dcraw/CAMERALIST, libkdcraw/dcraw/README, + libkdcraw/dcraw/dcraw.c: + libkdcraw from KDE3 branch: update internal dcraw version from + 8.60 to 8.76. + + New digital still camera supported are given below : + + Apple QuickTake 100 + Apple QuickTake 150 + Canon PowerShot A630 + Canon PowerShot A640 + Canon PowerShot A710 IS + Canon EOS-1D Mark III + Casio QV-R41 + Fuji FinePix S5Pro + Hasselblad CFV + Kodak C330 + Mamiya ZD + Nikon D2Xs + Nikon D40X + Olympus E-410 + Olympus E-510 + Olympus SP510UZ + Olympus SP550UZ + Panasonic DMC-FZ8 + Pentax Optio 750Z + Samsung GX-10 + Sigma SD14 + + The current implementation of libkdcraw for KDE3 do not break + binary compatibility. RAW decoding settings still the same. Only + private methods have been fixed, especally the settings widget. + + I will break binary compatibility of libkdcraw with KDE4 port + where i will add new settings like chromatic aberration + correction for ex. + + CCBUGS: 142568 + CCMAIL: kde-imaging@kde.org + CCMAIL: digikam-devel@kde.org + CCMAIL: ach@mpe.mpg.de + CCMAIL: boud@valdyas.org + +2007-06-13 16:54 cgilles + + * [r674972] libkdcraw/libkdcraw/Makefile.am: + fix broken compilation about moc file + +2007-06-13 08:38 cgilles + + * [r674833] libkdcraw/libkdcraw/kdcraw.cpp: + no i18n here + +2007-06-13 06:49 cgilles + + * [r674798] libkdcraw/dcraw/CAMERALIST, libkdcraw/dcraw/cameralist: + rename + +2007-06-13 06:48 cgilles + + * [r674797] libkdcraw/libkdcraw/Makefile.am: + use CXXFLAGS instead INCLUDES to dispatch -D option suring + compilation + +---------------------------------------------------------------------------- +V 0.1.1 - 2007-06-13 +---------------------------------------------------------------------------- + +2007-06-12 22:32 ach + + * [r674731] libkdcraw/configure.in.in, libkdcraw/dcraw/Makefile.am, + libkdcraw/libkdcraw/Makefile.am, + libkdcraw/libkdcraw/dcrawbinary.cpp: + o install the '(dirty) implementation detail' kdcraw into a + directory that depends on the ABI_MAJOR. This allows + several libs with different ABI_MAJOR be installed at the + same time. + o don't install manpage. kdcraw is not for the user + +2007-06-12 21:15 anaselli + + * [r674703] libkdcraw/libkdcraw/Makefile.am: + Changed to add libtools version managing into prepare script + (hope this will avoid to forget it) + +2007-06-11 12:04 cgilles + + * [r673923] libkdcraw/libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/libkdcraw/dcrawsettingswidget.h: + new signal emit when sixteen bits options is toggled + +2007-06-07 15:12 cgilles + + * [r672576] libkdcraw/Makefile.am: + compile + +2007-06-07 15:12 cgilles + + * [r672575] libkdcraw/libkdcraw, libkdcraw/src: + compile + +2007-06-07 14:52 cgilles + + * [r672567] libkdcraw/Makefile.am, libkdcraw/dcrawbinary.cpp, + libkdcraw/dcrawbinary.h, libkdcraw/dcrawinfocontainer.h, + libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp, + libkdcraw/kdcraw.h, libkdcraw/libkdcraw_export.h, + libkdcraw/rawdecodingsettings.h, libkdcraw/rawfiles.h, + libkdcraw/src, libkdcraw/src/Makefile.am, + libkdcraw/src/dcrawbinary.cpp, libkdcraw/src/dcrawbinary.h, + libkdcraw/src/dcrawinfocontainer.h, + libkdcraw/src/dcrawsettingswidget.cpp, + libkdcraw/src/dcrawsettingswidget.h, libkdcraw/src/kdcraw.cpp, + libkdcraw/src/kdcraw.h, libkdcraw/src/libkdcraw_export.h, + libkdcraw/src/rawdecodingsettings.h, libkdcraw/src/rawfiles.h, + libkdcraw/src/version.h, libkdcraw/version.h: + libkdcraw from KDE3 branch : move all source code files to "src" + sub dir + +2007-06-07 07:00 cgilles + + * [r672447] libkdcraw/rawdecodingsettings.h: + libkdraw from KDE3 branches : patch from Jakob Stergaard to + perform equality test between 2 rawdecoding settings. + CCBUGS: 146464 + +2007-06-05 09:33 vkrause + + * [r671669] libkdcraw/dcrawbinary.cpp: + compile, this is still Qt3 + +2007-06-05 09:12 cgilles + + * [r671664] libkdcraw/dcraw/Makefile.am: + digiKam => libkdcraw + +2007-06-05 08:20 cgilles + + * [r671639] libkdcraw/dcrawbinary.cpp: + krazy fix + +2007-06-12 08:39 mlaurent + + * [r674372] kipi-plugins/wallpaper/plugin_wallpaper.cpp, + libkdcraw/libkdcraw/CMakeLists.txt: + Fix compile/install + +2007-06-11 12:14 cgilles + + * [r673926] libkdcraw/libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/libkdcraw/dcrawsettingswidget.h: + new signal emit with sixteen bits option is toggled + +2007-06-10 21:01 cgilles + + * [r673688] kipi-plugins/CMakeLists.txt, + kipi-plugins/common/Makefile.am, + kipi-plugins/jpeglossless/utils.cpp, + libkdcraw/libkdcraw/kdcraw.cpp, libkexiv2/libkexiv2/kexiv2.cpp: + completeSuffix -> suffix + +2007-06-10 10:01 coolo + + * [r673456] libkdcraw/Messages.sh: + no files here + +2007-06-08 12:43 cgilles + + * [r672906] kipi-plugins/README, libkdcraw/README, + libkexiv2/README, libkipi/README: + add "export VERBOSE=1" in INSTALL section + +2007-06-08 12:30 cgilles + + * [r672897] libkdcraw/README: + update + +2007-06-07 15:19 cgilles + + * [r672581] libkdcraw/CMakeLists.txt, libkdcraw/libkdcraw, + libkdcraw/src, libkipi/CMakeLists.txt, libkipi/libkipi, + libkipi/src: + rename 'src' sub dir to libraries name + +2007-06-07 07:03 cgilles + + * [r672448] libkdcraw/src/rawdecodingsettings.h: + libkdcraw from trunk (KDE) : backport KDE3 patch from Jakob + CCBUGS: 146464 + +2007-06-06 10:48 mlaurent + + * [r672195] libkdcraw/CMakeLists.txt, + libkdcraw/dcraw/CMakeLists.txt, libkdcraw/src/CMakeLists.txt, + libkdcraw/src/dcrawbinary.cpp, libkdcraw/src/dcrawbinary.h, + libkdcraw/src/kdcraw.cpp, libkdcraw/src/kdcraw.h, + libkdcraw/src/version.h, libkdcraw/src/version.h.cmake: + Simplify it now when we change soname not necessary + to change in 3 files just into libkdcraw/CMakeLists.txt + +2007-06-06 10:09 cgilles + + * [r672188] libkdcraw/dcraw/CMakeLists.txt, + libkdcraw/src/dcrawbinary.cpp: + libkdcraw form trunk (KDE): first approach to introduce the + soname ID of libary like suffixe of kdcraw binary program. By + this way, we can install more than one libkdcraw version on the + same computer. + CCMAIL: ach@mpe.mpg.de + +2007-06-06 08:26 cgilles + + * [r672158] libkdcraw/cmake/modules/FindLCMS.cmake: + backport temporally FindLCMS from KDElibs. + Laurent, i will remove later... + +2007-06-06 08:22 cgilles + + * [r672156] libkdcraw/src/CMakeLists.txt: + no need to link with lcms. Only dcraw.c require it + +2007-06-06 07:26 mlaurent + + * [r672130] libkdcraw/CMakeLists.txt, + libkdcraw/dcraw/CMakeLists.txt, libkdcraw/src/CMakeLists.txt: + Use variable found by find_package + (search before to go into directory) + +2007-06-05 22:28 cgilles + + * [r671971] libkdcraw/src/CMakeLists.txt: + compile + +2007-06-05 22:19 cgilles + + * [r671968] libkdcraw/CMakeLists.txt, libkipi/src/CMakeLists.txt, + libkipi/src/plugin.cpp, libkipi/src/plugin.h: + compile + +2007-06-05 18:05 cgilles + + * [r671890] libkdcraw/CMakeLists.txt, libkdcraw/dcrawbinary.cpp, + libkdcraw/dcrawbinary.h, libkdcraw/dcrawinfocontainer.h, + libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp, + libkdcraw/kdcraw.h, libkdcraw/libkdcraw_export.h, + libkdcraw/rawdecodingsettings.h, libkdcraw/rawfiles.h, + libkdcraw/src/CMakeLists.txt, libkdcraw/src/dcrawbinary.cpp, + libkdcraw/src/dcrawbinary.h, libkdcraw/src/dcrawinfocontainer.h, + libkdcraw/src/dcrawsettingswidget.cpp, + libkdcraw/src/dcrawsettingswidget.h, libkdcraw/src/kdcraw.cpp, + libkdcraw/src/kdcraw.h, libkdcraw/src/libkdcraw_export.h, + libkdcraw/src/rawdecodingsettings.h, libkdcraw/src/rawfiles.h, + libkdcraw/src/version.h, libkdcraw/version.h: + libkdcraw from trunk : polish sub-folders. Use 'src' to hosts all + source code files + +2007-06-05 17:58 cgilles + + * [r671888] libkdcraw/src: + add + +2007-06-05 17:18 cgilles + + * [r671880] libkdcraw/dcraw/CMakeLists.txt: + polish + +2007-06-05 17:16 cgilles + + * [r671877] libkdcraw/libkdcraw.kdevelop: + rm + +2007-06-05 17:13 cgilles + + * [r671876] libkdcraw/Makefile.am: + rm + +2007-06-05 17:11 cgilles + + * [r671872] libkdcraw/libkdcraw_export.h: + fix export symbol + +2007-06-05 16:48 cgilles + + * [r671862] libkdcraw/configure.in.bot, libkdcraw/configure.in.in: + rm old files + +2007-06-05 16:46 cgilles + + * [r671861] libkdcraw/Messages.sh: + i18n rules + +2007-06-05 14:39 mlaurent + + * [r671798] libkdcraw/cmake/modules/FindLCMS.cmake: + Move into kdelibs (now used by koffice/libdcraw and digikam for + the future) + +2007-06-05 13:30 cgilles + + * [r671739] libkdcraw/CMakeLists.txt, + libkdcraw/dcrawsettingswidget.cpp: + libkdcraw from trunk : port to CMake/Qt4/KDE4 complete ! + + CCMAIL: digikam-devel@kde.org + CCMAIL: kde-imaging@kde.org + CCMAIL: boud@valdyas.org + +2007-06-05 13:13 cgilles + + * [r671731] libkdcraw/dcraw/CMakeLists.txt: + do not use enablefinal mode to compile dcraw.c + +2007-06-05 12:06 cgilles + + * [r671702] libkdcraw/dcrawinfocontainer.h: + port to QT4/KDE4 + +2007-06-05 12:04 cgilles + + * [r671701] libkdcraw/kdcraw.cpp, libkdcraw/kdcraw.h: + libkdcraw from trunk : porting to Qt4/KDE4 + +2007-06-05 10:48 cgilles + + * [r671692] libkdcraw/CMakeLists.txt, libkdcraw/dcrawbinary.cpp, + libkdcraw/dcrawbinary.h: + libkdcraw from trunk : port to KDE4/QT4 + +2007-06-05 09:43 cgilles + + * [r671676] libkdcraw/dcraw/CMakeLists.txt: + polish + +2007-06-05 09:42 cgilles + + * [r671675] libkdcraw/dcraw/Makefile.am: + this file is obsolete now + +2007-06-05 09:42 cgilles + + * [r671674] libkdcraw/dcraw/CMakeLists.txt: + install kcraw man page + +2007-06-05 09:37 cgilles + + * [r671671] libkdcraw/dcraw/CMakeLists.txt: + dcraw.c now compile with cmake + +2007-06-05 09:20 cgilles + + * [r671666] libkdcraw/dcraw/CMakeLists.txt: + port to cmake. Uncomplete + +2007-06-05 09:11 cgilles + + * [r671663] libkdcraw/dcraw/Makefile.am: + digiKam => libkdcraw + +2007-06-05 09:08 cgilles + + * [r671662] libkdcraw/CMakeLists.txt, + libkdcraw/icons/CMakeLists.txt, libkdcraw/icons/Makefile.am: + include icons sub-dir + +2007-06-05 09:04 cgilles + + * [r671661] libkdcraw/CMakeLists.txt: + include dcraw sub dir + +2007-06-05 09:00 cgilles + + * [r671660] libkdcraw/README: + update + +2007-06-05 08:58 cgilles + + * [r671658] libkdcraw/NEWS: + update + +2007-06-05 08:57 cgilles + + * [r671657] libkdcraw/libkdcraw.pc.cmake: + new line at EOF + +2007-06-05 08:50 cgilles + + * [r671655] libkdcraw/CMakeLists.txt: + cmake port continue + +2007-06-05 08:43 cgilles + + * [r671649] libkdcraw/libkdcraw.pc.cmake: + cmake port continue + +2007-06-05 08:41 cgilles + + * [r671647] libkdcraw/libkdcraw.pc.cmake, + libkdcraw/libkdcraw.pc.in: + port to cmake + +2007-06-05 08:35 cgilles + + * [r671646] libkdcraw/cmake, libkdcraw/cmake/modules, + libkdcraw/cmake/modules/FindLCMS.cmake, + libkdcraw/dcrawbinary.cpp, libkdcraw/libkdcraw.lsm, + libkdcraw/libkdcraw.pc.in, libkdcraw/version.h: + libkdcraw from trunk : start CMake port + +2007-06-05 06:13 cgilles + + * [r671600] libkdcraw: + CMake/QT4/KDE4 port + +2007-06-02 14:14 helio + + * [r670712] branches/extragear/kde3/libs, .: + - First directory to move. No 4.x apps here yet. + +2007-05-16 19:27 mwiesweg + + * [r665389] libkdcraw/kdcraw.cpp: + I think these lines got lost when splitting the methods... + +2007-05-16 08:51 cgilles + + * [r665231] libkdcraw/NEWS, libkdcraw/kdcraw.cpp, + libkdcraw/kdcraw.h: + libkdcraw from trunk : separate methods to extract RAW JPEG + preview and RAW half decoding + +2007-05-16 07:39 cgilles + + * [r665228] libkdcraw/NEWS: + updated + +2007-05-16 07:38 cgilles + + * [r665227] libkdcraw/dcrawinfocontainer.h: + added destructor. Fix API doc + +2007-05-16 07:31 cgilles + + * [r665226] libkdcraw/dcrawsettingswidget.h: + destructor is now virtual + +2007-05-16 07:30 cgilles + + * [r665225] libkdcraw/rawdecodingsettings.h: + destructor is now virtual + +2007-05-16 07:30 cgilles + + * [r665224] libkdcraw/version.h: + update + +2007-05-16 07:29 cgilles + + * [r665222] libkdcraw/libkdcraw.pc.in: + update + +2007-05-16 07:25 cgilles + + * [r665218] libkdcraw/libkdcraw.lsm: + update + +2007-05-16 07:24 cgilles + + * [r665217] libkdcraw/NEWS: + update + +2007-05-16 07:24 cgilles + + * [r665215] libkdcraw/kdcraw.h: + destructor is now virtual + +2007-05-16 07:22 cgilles + + * [r665213] libkdcraw/AUTHORS: + update + +2007-05-16 05:36 cgilles + + * [r665183] libkdcraw/NEWS: + update + +2007-05-16 05:34 cgilles + + * [r665182] libkdcraw/dcrawbinary.cpp: + libkdcraw from trunk : patch to compile under CYGWIN + BUG: 145482 + +2007-05-14 08:10 cgilles + + * [r664527] libkdcraw/README, libkdcraw/dcrawbinary.cpp, + libkdcraw/dcrawbinary.h, libkdcraw/dcrawinfocontainer.h, + libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp, + libkdcraw/kdcraw.h, libkdcraw/libkdcraw_export.h, + libkdcraw/rawdecodingsettings.h, libkdcraw/rawfiles.h, + libkdcraw/version.h: + fix header + +2007-05-05 14:18 gkulzer + + * [r661421] libkdcraw/libkdcraw.pc.in: + 0.1.0 release, coordinated with digiKam 0.9.2-beta1 release + +2007-05-05 14:10 gkulzer + + * [r661419] libkdcraw/libkdcraw.lsm: + 0.1.3 release, coordinated with digiKam 0.9.2-beta1 release + +2007-05-05 14:07 gkulzer + + * [r661418] libkdcraw/version.h: + 0.1.3 release, coordinated with digiKam 0.9.2-beta1 release + +2007-05-05 14:07 gkulzer + + * [r661417] libkdcraw/dcraw/dcraw.c: + 0.1.3 release, coordinated with digiKam 0.9.2-beta1 release + +2007-05-02 07:09 cgilles + + * [r660284] libkdcraw/dcrawbinary.cpp, libkdcraw/dcrawbinary.h, + libkdcraw/dcrawinfocontainer.h, + libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp, + libkdcraw/kdcraw.h, libkdcraw/libkdcraw_export.h, + libkdcraw/rawdecodingsettings.h, libkdcraw/rawfiles.h, + libkdcraw/version.h: + fix headers + +2007-04-21 20:26 mwiesweg + + * [r656606] libkdcraw/kdcraw.cpp: + Trying to fix crash: Do not wait on process exit here, and leave + setting + d->normalExit to slotProcessExited. + + This fixes the crash I was experiencing here. + + CCMAIL: caulier.gilles@gmail.com + +2007-03-14 12:00 cgilles + + * [r642424] libkdcraw/libkdcraw.lsm: + fix version + +2007-03-14 12:00 cgilles + + * [r642423] libkdcraw/libkdcraw.pc.in: + fix version + +2007-03-14 11:59 cgilles + + * [r642422] libkdcraw/version.h: + fix version + +2007-03-09 06:34 gkulzer + + * [r640778] libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h: + Disabling 'Brightness' slider when in 16bit mode, dcraw does not + support this. + CCMAIL:caulier.gilles@gmail.com + +2007-02-27 04:55 gkulzer + + * [r637623] libkdcraw/dcrawsettingswidget.cpp: + i18n strings polished + +2007-02-23 06:54 cgilles + + * [r636445] libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/libkdcraw.kdevelop, libkdcraw/rawdecodingsettings.h: + API doc + +2007-02-22 19:20 cgilles + + * [r636303] libkdcraw/dcrawsettingswidget.cpp: + fix interval + +2007-02-22 19:14 cgilles + + * [r636301] libkdcraw/dcrawsettingswidget.cpp: + fix + +2007-02-22 14:52 cgilles + + * [r636237] libkdcraw/dcrawsettingswidget.cpp: + added labels + +2007-02-22 12:13 cgilles + + * [r636213] libkdcraw/dcraw/README: + update + +2007-02-22 12:12 cgilles + + * [r636212] libkdcraw/dcraw/README, libkdcraw/dcraw/cameralist: + add camera list supported by current dcraw release. + +2007-02-22 12:01 cgilles + + * [r636211] kipi-plugins/kipiplugins.kdevelop, + kipi-plugins/rawconverter/batchdialog.cpp, + kipi-plugins/rawconverter/singledialog.cpp, + libkdcraw/dcraw/dcraw.c, libkdcraw/dcraw/kdcraw.1, + libkdcraw/dcrawbinary.cpp, libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp, + libkdcraw/libkdcraw.kdevelop, libkdcraw/rawdecodingsettings.h, + libkexiv2/libkexiv2.kdevelop: + libkdcraw from trunk : backport last dcraw implementation "8.60" + : the old noise reduction algorithm used with 8.54 version have + been remplaced by a wavelet algorithm witch is more intuitive, + more easy to use (just one threshold setting) and very powerfull. + + Kipi-plugins RAWConverter from svn trunk is fixed. + The patch to use libkdcraw with current implementation of digiKam + have been updated : + + http://digikam3rdparty.free.fr/misc.tarballs/libkdcrawdigikamport.patch + + CCMAIL: digikam-users@kde.org + CCMAIL: digikam-devel@kde.org + CCMAIL: kde-imaging@kde.org + +2007-02-22 09:19 cgilles + + * [r636182] libkdcraw/libkdcraw.kdevelop: + update project + +2007-02-20 20:25 ach + + * [r635753] libkdcraw/dcrawbinary.cpp, + libkdcraw/dcrawsettingswidget.cpp, libkdcraw/kdcraw.cpp, + libkdcraw/kdcraw.h: + EBN: QString::null -> QString() and some spelling fixes + +2007-02-20 19:59 ach + + * [r635744] libkdcraw/dcrawbinary.cpp, + libkdcraw/dcrawsettingswidget.cpp: + EBN: isn't -> is not etc + +2007-02-20 19:12 ach + + * [r635732] libkdcraw/README: + polish README + +2007-02-20 19:03 ach + + * [r635729] libkdcraw/libkdcraw.pc.in: + libkdcraw: add homepage URL to pkg-config file + +2007-02-20 19:01 ach + + * [r635727] libkdcraw/libkdcraw.lsm, libkdcraw/libkdcraw.pc.in, + libkdcraw/version.h: + fix version 0.1.0 -> 0.1.0-beta1+svn + +2007-02-20 18:58 ach + + * [r635726] libkdcraw/dcrawbinary.cpp, libkdcraw/dcrawbinary.h, + libkdcraw/dcrawinfocontainer.h, + libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp, + libkdcraw/kdcraw.h, libkdcraw/libkdcraw_export.h, + libkdcraw/rawdecodingsettings.h, libkdcraw/rawfiles.h, + libkdcraw/version.h: + libkdcraw: + o add email to copyright lines + o remove unnecessary line wrap in license + +2007-02-20 18:53 ach + + * [r635721] libkdcraw/dcraw/kdcraw.1: + libkdcraw: s/dcraw/kdcraw in manpage and add + e-mail to copyright line + +2007-02-20 14:20 cgilles + + * [r635648] kipi-plugins/rawconverter/batchdialog.cpp, + kipi-plugins/rawconverter/singledialog.cpp, + libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp, + libkdcraw/rawdecodingsettings.h: + libkdcraw from trunk : introduce the color balance multipliers + settings + +2007-02-20 12:28 cgilles + + * [r635609] libkdcraw/dcrawsettingswidget.cpp: + polish + +2007-02-20 10:28 cgilles + + * [r635565] libkdcraw/dcrawsettingswidget.cpp: + fix layout + +2007-02-19 22:30 cgilles + + * [r635409] libkdcraw/dcrawsettingswidget.cpp: + fix layout + +2007-02-19 22:28 cgilles + + * [r635408] libkdcraw/dcrawsettingswidget.cpp: + fix layout + +2007-02-19 22:15 cgilles + + * [r635400] libkdcraw/dcrawsettingswidget.cpp: + fix layout + +2007-02-19 21:52 cgilles + + * [r635352] libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h, libkdcraw/libkdcraw.kdevelop: + use KtabWidget to separate Standard and Advanced settings + +2007-02-19 15:20 cgilles + + * [r635245] libkdcraw/dcrawsettingswidget.cpp: + fix i18n + +2007-02-19 15:05 cgilles + + * [r635242] kipi-plugins/rawconverter/batchdialog.cpp, + kipi-plugins/rawconverter/singledialog.cpp, + libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp, + libkdcraw/rawdecodingsettings.h: + libkdcraw from trunk : introduce the blackpoint compensation + value settings + +2007-02-19 11:56 cgilles + + * [r635195] kipi-plugins/rawconverter/batchdialog.cpp, + kipi-plugins/rawconverter/singledialog.cpp, + libkdcraw/dcraw/README, libkdcraw/dcraw/dcraw.c, + libkdcraw/dcrawbinary.cpp, libkdcraw/dcrawbinary.h, + libkdcraw/dcrawinfocontainer.h, + libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp, + libkdcraw/rawdecodingsettings.h: + After 8 days of intensive work, I'm very proud to announce the + first LibKdcraw shared library 0.1.0 beta release. + + LibKdcraw is a C++ interface around dcraw binary program used to + decode RAW picture files. This library is actually used by + kipi-plugins (trunk), and later by digiKam (with future 0.9.2 + release). + + http://digikam3rdparty.free.fr/Screenshots/newkipirawconverter.png + + The library documentation is available on header files. Check svn + trunk repository for details : + + http://websvn.kde.org/trunk/extragear/libs/libkdcraw + + Libkdcraw include the last dcraw program (version 8.54) from Dave + Coffin. It provide a kdcraw binary witch is used instead dcraw. + This way prevent _all_ compatibility problems with all options + see with dcraw. In fact the dcraw author to not respect a + compatibilty between dcraw release witch break all RAW workflow ! + Also, he won't provide dcraw as a shared library. We have lost a + waste a time with these problems in digiKam project. Using a + specific version of dcraw in the library, we will valid this one + with the library API and preserve the compatibility for the + future. + + The dcraw source code can be updated easily using the + libkdcraw/dcraw/README file where i have written a notice for + that. The library don't touch the content of dcraw source code. + It use it as well... + + With this library, you can extract preview image (used by camera + to display picture on TV screen) as a QImage, and extract all + informations given by dcraw to identify a RAW file. Of course, + you can decode and extract the RAW pictures with a lot of + settings. The image data (8 or 16 bits color depth) is returned + in a QByteArray container. The library include a widget to + control all RAW decoding settings in your application : + + http://digikam3rdparty.free.fr/Screenshots/rawsettings.png + + Using the last dcraw source code, the libary support all last + Camera models, especially all models out at Christmas 2006. The + complete list is given below : + + Adobe Digital Negative (DNG) + AVT F-145C + AVT F-201C + AVT F-510C + AVT F-810C + Canon PowerShot 600 + Canon PowerShot A5 + Canon PowerShot A5 Zoom + Canon PowerShot A50 + Canon PowerShot A610 + Canon PowerShot A620 + Canon PowerShot Pro70 + Canon PowerShot Pro90 IS + Canon PowerShot G1 + Canon PowerShot G2 + Canon PowerShot G3 + Canon PowerShot G5 + Canon PowerShot G6 + Canon PowerShot S2 IS + Canon PowerShot S3 IS + Canon PowerShot S30 + Canon PowerShot S40 + Canon PowerShot S45 + Canon PowerShot S50 + Canon PowerShot S60 + Canon PowerShot S70 + Canon PowerShot Pro1 + Canon EOS D30 + Canon EOS D60 + Canon EOS 5D + Canon EOS 10D + Canon EOS 20D + Canon EOS 30D + Canon EOS 300D / Digital Rebel / Kiss Digital + Canon EOS 350D / Digital Rebel XT / Kiss Digital N + Canon EOS 400D / Digital Rebel XTi / Kiss Digital X + Canon EOS D2000C + Canon EOS-1D + Canon EOS-1DS + Canon EOS-1D Mark II + Canon EOS-1D Mark II N + Canon EOS-1Ds Mark II + Casio QV-2000UX + Casio QV-3000EX + Casio QV-3500EX + Casio QV-4000 + Casio QV-5700 + Casio QV-R51 + Casio QV-R61 + Casio EX-S100 + Casio EX-Z4 + Casio EX-Z50 + Casio EX-Z55 + Casio Exlim Pro 505 + Casio Exlim Pro 600 + Casio Exlim Pro 700 + Contax N Digital + Creative PC-CAM 600 + Epson R-D1 + Foculus 531C + Fuji FinePix E550 + Fuji FinePix E900 + Fuji FinePix F700 + Fuji FinePix F710 + Fuji FinePix F800 + Fuji FinePix F810 + Fuji FinePix S2Pro + Fuji FinePix S3Pro + Fuji FinePix S20Pro + Fuji FinePix S5000 + Fuji FinePix S5100/S5500 + Fuji FinePix S5200/S5600 + Fuji FinePix S6000fd + Fuji FinePix S7000 + Fuji FinePix S9000/S9500 + Imacon Ixpress 16-megapixel + Imacon Ixpress 22-megapixel + Imacon Ixpress 39-megapixel + ISG 2020x1520 + Kodak DC20 (see Oliver Hartman's page) + Kodak DC25 (see Jun-ichiro Itoh's page) + Kodak DC40 + Kodak DC50 + Kodak DC120 (also try kdc2tiff) + Kodak DCS200 + Kodak DCS315C + Kodak DCS330C + Kodak DCS420 + Kodak DCS460 + Kodak DCS460A + Kodak DCS520C + Kodak DCS560C + Kodak DCS620C + Kodak DCS620X + Kodak DCS660C + Kodak DCS660M + Kodak DCS720X + Kodak DCS760C + Kodak DCS760M + Kodak EOSDCS1 + Kodak EOSDCS3B + Kodak NC2000F + Kodak ProBack + Kodak PB645C + Kodak PB645H + Kodak PB645M + Kodak DCS Pro 14n + Kodak DCS Pro 14nx + Kodak DCS Pro SLR/c + Kodak DCS Pro SLR/n + Kodak P850 + Kodak P880 + Kodak KAI-0340 + Konica KD-400Z + Konica KD-510Z + Leaf Aptus 17 + Leaf Aptus 22 + Leaf Aptus 65 + Leaf Aptus 75 + Leaf Cantare + Leaf CatchLight + Leaf CMost + Leaf DCB2 + Leaf Valeo 6 + Leaf Valeo 11 + Leaf Valeo 17 + Leaf Valeo 22 + Leaf Volare + Leica Digilux 2 + Leica Digilux 3 + Leica D-LUX2 + Leica D-LUX3 + Leica V-LUX1 + Logitech Fotoman Pixtura + Micron 2010 + Minolta RD175 + Minolta DiMAGE 5 + Minolta DiMAGE 7 + Minolta DiMAGE 7i + Minolta DiMAGE 7Hi + Minolta DiMAGE A1 + Minolta DiMAGE A2 + Minolta DiMAGE A200 + Minolta DiMAGE G400 + Minolta DiMAGE G500 + Minolta DiMAGE G530 + Minolta DiMAGE G600 + Minolta DiMAGE Z2 + Minolta Alpha/Dynax/Maxxum 5D + Minolta Alpha/Dynax/Maxxum 7D + Nikon D1 + Nikon D1H + Nikon D1X + Nikon D2H + Nikon D2Hs + Nikon D2X + Nikon D40 + Nikon D50 + Nikon D70 + Nikon D70s + Nikon D80 + Nikon D100 + Nikon D200 + Nikon E700 ("DIAG RAW" hack) + Nikon E800 ("DIAG RAW" hack) + Nikon E880 ("DIAG RAW" hack) + Nikon E900 ("DIAG RAW" hack) + Nikon E950 ("DIAG RAW" hack) + Nikon E990 ("DIAG RAW" hack) + Nikon E995 ("DIAG RAW" hack) + Nikon E2100 ("DIAG RAW" hack) + Nikon E2500 ("DIAG RAW" hack) + Nikon E3200 ("DIAG RAW" hack) + Nikon E3700 ("DIAG RAW" hack) + Nikon E4300 ("DIAG RAW" hack) + Nikon E4500 ("DIAG RAW" hack) + Nikon E5000 + Nikon E5400 + Nikon E5700 + Nikon E8400 + Nikon E8700 + Nikon E8800 + Olympus C3030Z + Olympus C5050Z + Olympus C5060WZ + Olympus C7070WZ + Olympus C70Z,C7000Z + Olympus C740UZ + Olympus C770UZ + Olympus C8080WZ + Olympus E-1 + Olympus E-10 + Olympus E-20 + Olympus E-300 + Olympus E-330 + Olympus E-400 + Olympus E-500 + Olympus SP310 + Olympus SP320 + Olympus SP350 + Olympus SP500UZ + Panasonic DMC-FZ30 + Panasonic DMC-FZ50 + Panasonic DMC-L1 + Panasonic DMC-LC1 + Panasonic DMC-LX1 + Panasonic DMC-LX2 + Pentax *ist D + Pentax *ist DL + Pentax *ist DL2 + Pentax *ist DS + Pentax *ist DS2 + Pentax K10D + Pentax K100D + Pentax Optio S + Pentax Optio S4 + Pentax Optio 33WR + Phase One LightPhase + Phase One H 10 + Phase One H 20 + Phase One H 25 + Phase One P 20 + Phase One P 25 + Phase One P 30 + Phase One P 45 + Pixelink A782 + Polaroid x530 + Rollei d530flex + RoverShot 3320af + Samsung GX-1S + Sarnoff 4096x5440 + Sigma SD9 + Sigma SD10 + Sinar 3072x2048 + Sinar 4080x4080 + Sinar 4080x5440 + Sinar STI format + SMaL Ultra-Pocket 3 + SMaL Ultra-Pocket 4 + SMaL Ultra-Pocket 5 + Sony DSC-F828 + Sony DSC-R1 + Sony DSC-V3 + Sony DSLR-A100 + Sony XCD-SX910CR + STV680 VGA + + About digiKam and this library, I have a big patch on my computer + to use this library with all RAW files. I will commit this code + in svn repository later digiKam 0.9.1 release. It will be + available for 0.9.2 release. If you is impatient to test it, the + patch against current svn implementation of digiKam can be + downloaded at this url : + + http://digikam3rdparty.free.fr/misc.tarballs/libkdcrawdigikamport.patch + + Of course, you need to checkout, compile and install LibKdcraw + first. It is stored on extragear/libs folder of svn trunk. + + All feedbacks are welcome, especially all RAW pictures sample + taken with a recent camera to perform advanced test. Thanks in + advance for your help... + + Gilles Caulier + digiKam team + + BUG: 140865 + CCBUG : 138744 + CCMAIL: digikam-users@kde.org, digikam-devel@kde.org, + kde-imaging@kde.org + +2007-02-19 09:05 cgilles + + * [r635146] libkdcraw/dcrawbinary.cpp: + fix test if version is right + +2007-02-19 09:03 cgilles + + * [r635144] libkdcraw/dcrawbinary.cpp: + fix test if version is right + +2007-02-19 08:56 cgilles + + * [r635141] libkdcraw/kdcraw.cpp: + be verboze during RAW decoding + +2007-02-19 08:32 cgilles + + * [r635135] libkdcraw/dcraw/Makefile.am, libkdcraw/dcraw/kdcraw.1: + added official dcraw manual page + +2007-02-19 07:34 cgilles + + * [r635123] libkdcraw/kdcraw.cpp, libkdcraw/kdcraw.h: + API doc + polishing + +2007-02-19 06:53 cgilles + + * [r635114] libkdcraw/README: + update depencies + +2007-02-19 06:48 cgilles + + * [r635113] libkdcraw/Makefile.am, libkdcraw/icons, + libkdcraw/icons/Makefile.am, + libkdcraw/icons/hi128-app-kdcraw.png, + libkdcraw/icons/hi32-app-kdcraw.png, + libkdcraw/icons/hi48-app-kdcraw.png, + libkdcraw/icons/hi64-app-kdcraw.png: + kdcraw icons + +2007-02-18 20:05 cgilles + + * [r634923] libkdcraw/kdcraw.cpp, libkdcraw/kdcraw.h: + API doc + +2007-02-18 18:16 cgilles + + * [r634885] libkdcraw/kdcraw.cpp: + libkdcraw : loading progress value will be continue now. We will + folowing the last progress value used by pseudo progress during + internal dcraw decoding loop and when you recieve data from + dcraw, we continue progress at this point. + + LibKDcraw shared library is now finalized. digiKam patch to used + it is ready for next 0.9.2 release. + + CCMAIL: marcel.wiesweg@gmx.de + +2007-02-18 16:27 cgilles + + * [r634858] libkdcraw/kdcraw.cpp, libkdcraw/kdcraw.h: + give raw decoding settings protected + +2007-02-18 14:55 cgilles + + * [r634842] libkdcraw/kdcraw.cpp, libkdcraw/kdcraw.h: + polish implementation + +2007-02-18 12:15 cgilles + + * [r634814] libkdcraw/kdcraw.cpp, libkdcraw/kdcraw.h: + add new method to handle progress info in digiKam during RAW file + decoding + +2007-02-18 11:46 cgilles + + * [r634799] libkdcraw/kdcraw.cpp, libkdcraw/kdcraw.h: + update to compile with digiKam + +2007-02-18 11:40 cgilles + + * [r634795] libkdcraw/kdcraw.cpp, libkdcraw/kdcraw.h: + added new virtual method to cancel RAW decoding with digiKam + +2007-02-17 20:53 cgilles + + * [r634615] libkdcraw/kdcraw.cpp, libkdcraw/kdcraw.h: + update to compile with digiKam + +2007-02-17 17:21 cgilles + + * [r634581] libkdcraw/dcrawbinary.cpp, libkdcraw/dcrawbinary.h: + update to compile with digiKam + +2007-02-17 16:40 cgilles + + * [r634572] libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h: + update to compile with digiKam + +2007-02-17 14:53 cgilles + + * [r634545] libkdcraw/Makefile.am: + compile + +2007-02-17 14:47 cgilles + + * [r634544] libkdcraw/dcrawinfocontainer.h: + compile + +2007-02-16 22:01 cgilles + + * [r634334] kipi-plugins/rawconverter/actionthread.cpp, + kipi-plugins/rawconverter/rawdecodingiface.cpp, + libkdcraw/kdcraw.cpp, libkexiv2/kexiv2.cpp: + fix comments + +2007-02-16 19:23 cgilles + + * [r634278] libkdcraw/rawdecodingsettings.h: + API doc + optimized time loading settings backported from digiKam + core + +2007-02-16 15:44 cgilles + + * [r634185] libkdcraw/libkdcraw.lsm: + fix email + +2007-02-16 15:41 cgilles + + * [r634183] libkdcraw/AUTHORS, libkdcraw/dcrawbinary.cpp, + libkdcraw/dcrawbinary.h, libkdcraw/dcrawinfocontainer.h, + libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp, + libkdcraw/kdcraw.h, libkdcraw/rawdecodingsettings.h, + libkdcraw/rawfiles.h: + fix email + +2007-02-16 13:38 cgilles + + * [r634150] libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h: + add link to dcraw web page + +2007-02-16 12:54 cgilles + + * [r634137] libkdcraw/Makefile.am: + forget i18n rules + +2007-02-16 12:52 cgilles + + * [r634136] libkdcraw/dcrawinfocontainer.h, + libkdcraw/dcrawsettingswidget.h: + use LIBKDCRAW_EXPORT + +2007-02-16 12:48 cgilles + + * [r634134] libkdcraw/kdcraw.h: + polish + +2007-02-16 10:30 cgilles + + * [r634091] libkdcraw/Makefile.am, + libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h: + libkdcraw from trunk : continue implementation. Still under + developement. Not yet suitable. + +2007-02-16 09:56 cgilles + + * [r634082] libkdcraw/kdcraw.cpp, libkdcraw/kdcraw.h: + update API + +2007-02-16 09:39 cgilles + + * [r634076] libkdcraw/kdcraw.cpp, libkdcraw/kdcraw.h: + update API + +2007-02-16 09:07 cgilles + + * [r634066] libkdcraw/Makefile.am, libkdcraw/dcrawiface.cpp, + libkdcraw/dcrawiface.h, libkdcraw/kdcraw.cpp, libkdcraw/kdcraw.h: + polish + +2007-02-16 08:50 cgilles + + * [r634064] libkdcraw/dcrawbinary.cpp, libkdcraw/dcrawbinary.h, + libkdcraw/libkdcraw.kdevelop: + API doc + +2007-02-16 08:37 cgilles + + * [r634063] libkdcraw/dcrawbinary.h: + polish + +2007-02-16 08:05 cgilles + + * [r634059] libkdcraw/dcrawiface.cpp: + polish + +2007-02-16 07:57 cgilles + + * [r634058] libkdcraw/dcrawiface.cpp, + libkdcraw/rawdecodingsettings.h: + fix API + +2007-02-16 07:55 cgilles + + * [r634057] libkdcraw/dcrawiface.cpp, libkdcraw/dcrawiface.h: + fix API + +2007-02-15 17:56 cgilles + + * [r633901] libkdcraw/libkdcraw.kdevelop: + kdevelop project + +2007-02-15 15:14 cgilles + + * [r633865] libkdcraw/dcrawiface.h: + polish + +2007-02-15 15:08 cgilles + + * [r633863] libkdcraw/dcrawiface.cpp, libkdcraw/dcrawiface.h: + libkdcraw from trunk : continue implementation. Still under + developement. Not yet suitable. + +2007-02-15 14:43 cgilles + + * [r633856] libkdcraw/Makefile.am, libkdcraw/dcrawiface.cpp, + libkdcraw/dcrawiface.h, libkdcraw/dcrawinfocontainer.h, + libkdcraw/rawdecodingsettings.h: + libkdcraw from trunk : continue implementation. Still under + developement. Not yet suitable. + +2007-02-15 13:17 cgilles + + * [r633837] libkdcraw/rawfiles.h: + typo + +2007-02-15 13:16 cgilles + + * [r633836] libkdcraw/Makefile.am, libkdcraw/dcrawbinary.cpp, + libkdcraw/dcrawbinary.h, libkdcraw/dcrawiface.cpp, + libkdcraw/dcrawiface.h, libkdcraw/rawdecodingsettings.h: + libkdcraw from trunk : continue implementation. Still under + developement. Not yet suitable. + +2007-02-12 15:24 cgilles + + * [r632867] libkdcraw, libkdcraw/AUTHORS, libkdcraw/COPYING, + libkdcraw/ChangeLog, libkdcraw/INSTALL, libkdcraw/Makefile.am, + libkdcraw/NEWS, libkdcraw/README, libkdcraw/configure.in.bot, + libkdcraw/configure.in.in, libkdcraw/dcraw, + libkdcraw/dcraw/Makefile.am, libkdcraw/dcraw/README, + libkdcraw/dcraw/dcraw.c, libkdcraw/dcrawbinary.cpp, + libkdcraw/dcrawbinary.h, libkdcraw/libkdcraw.lsm, + libkdcraw/libkdcraw.pc.in, libkdcraw/libkdcraw_export.h, + libkdcraw/rawfiles.h, libkdcraw/version.h: + kipi-plugins from trunk : starting new shared library "libkdcraw" + based on digiKam core and RAW converter implementations. + + This library will provide a C++ interface to dcraw command line + program to decode RAW pictures. It will be used by digiKam and + kipi-plugins. A common implementation is require to prevent + duplicate source code. + + The library is not yet complete. I'm working on actually. + Compilation is disable by default. Future digiKam 0.9.2 release + will use it. + + CCMAIL: marcel.wiesweg@gmx.de, kde-imaging@kde.org, + digikam-devel@kde.org + diff --git a/libkdcraw/Messages.sh b/libkdcraw/Messages.sh new file mode 100644 index 00000000..67c0af4b --- /dev/null +++ b/libkdcraw/Messages.sh @@ -0,0 +1,2 @@ +#! /bin/sh +$XGETTEXT libkdcraw/*.cpp -o $podir/libkdcraw.pot diff --git a/libkdcraw/NEWS b/libkdcraw/NEWS new file mode 100644 index 00000000..653dcc87 --- /dev/null +++ b/libkdcraw/NEWS @@ -0,0 +1,190 @@ +1.1.0 - Released with KDE 4.5.0 +------------------------------------------------------------------------ + +*dcraw 9.03 (1.437) imported: + + + New cameras: Canon SX20, Nikon D3s, Olympus E-P2, Panasoni DMC-GF1, Samsung EX1, Sony A450. + + Color data changed for some cameras. + +* dcraw 9.01 (1.434) imported: + + Separate black levels for each color channel. + + New cameras: Canon 550D, Casio EX-Z1050, Fuji HS10/HS11, + Kodak Z981, Panasonic G2 and G10, Phase One P65, + Samsung NX-10 and WB550, Sony NEX-3 and NEX-5. + + Fixed file descriptor leak in dark frame subtraction processing + +* Fixed dcraw 9.01's bug in DNG black level processing + +* Preliminary support for Sony A450 camera. + +* New command-line switch -h in mem_image sample (half_size support) + +* Some patches by Johannes Hanika (darktable author): + + OpenMP speedup for PPG-interpolation + + green_matching - suppress of 'color maze' on cameras with + different green channel sensitivity. This option is turns on + by filed with same name in imgdata.params + +* LibRaw::free() is now public instead of private. + +1.0.0 - Released with KDE 4.4.0 +------------------------------------------------------------------------ + +- Updated to LibRaw 0.8.4: +# Fixed a bug in Phase One uncompressed files processing + +- Updated to LibRaw 0.8.3: +# New cameras : Canon 7D, Panasonic GF1, Sony A850 and A380, Casio Z850, Nikon D300s + +- Updated to LibRaw 0.8.2: +# Fixed bug in Hasselblad .3FR unpacking code +# Imported dcraw 8.97/1.428: Nikon D3000 image width fix +# Enum LibRaw_thumbnail_formats (LIBRAW_IMAGE_*) values changed to match values in enum LibRaw_image_formats (LIBRAW_THUMBNAIL_*). + +- Updated to LibRaw 0.8.1: +# Imported dcraw 8.97/1.427: new cameras: Canon A470, Canon G11 (without color data), Nikon D3000, Olympus E-P1, Panasonic DMC-FZ35/FZ38 +# Fixes for Microsoft Visual C++ 6.0 compatibility +# C-API libraw_dcraw_make_mem_thumb() call finally exported in API + +- Updated to LibRaw 0.8.0: +# Support of RAW files larger than 2Gb +# dcraw 8.86/1.426 imported: + * many new cameras supported: + Casio EX-S20, EX-Z60, EX-Z75 + Kodak Z980, Z1015 + Nikon D5000 + Olympus X200, D560Z, C350Z, E30, E620 + Canon SX1, 500D/Rebel T1i, A570, A590, SX110 + Motorola PIXL, Panasonic DMC-GH1, Pentax K7, Sony A330 + AGFAPHOTO DC-833m,Phase One P65, Samsung S850. + * New color data for many cameras. + * Generalized unpacking code for many formats. + * Removed hardcoded white-balance data for many P&S cameras. It is recommended to set params.use_camera_wb to 1 for safe WB. + * Canon cameras: black level is not subtracted if params.document_mode =2 +# API changes: params.gamma_16bit field removed. Gamma curve is set via params.gamm[0]/gamm[1] values (see documentation and samples for details) +# Many cosmetic changes to support more platforms/compilers. +# Samples: dcraw_emu and mem_image samples supports new dcraw 16bit/gamma semantics: + * -6: set 16 bit output + * -4: set 16 bit output and linear gamma curve and no auto brightness +# C-API: added missed (but documented) calls libraw_dcraw_make_mem_image() and libraw_dcraw_ make_mem_thumb() + +- API changed : remove RawDecodingSetting::gamma16bit settings. Obsolete with LibRaw 0.8.0. + remove KDcraw depreciated methods. +- New widget to host settings : RExpanderBox. + +0.5.0 - Released with KDE 4.3.0 +------------------------------------------------------------------------ +- Updated to LibRaw 0.7.2 : More accurate types conversion in libraw_datastream.h to make compilers happy. + New postprocessing parameter auto_bright_thr: set portion of clipped pixels for + auto brightening code (instead of dcraw-derived hardcoded 1%). + -U option for dcraw_emu sample sets auto_bright_thr parameter. +- Updated to LibRaw 0.7.1 : Fixed broken OpenMP support. +- Updated to LibRaw 0.7.0 : Black (masked) pixels data extracted from RAW and avaliable in application. + Application can turn off RAW data filtering (black level subtraction, + zero pixels removal and raw tone curve). + New 'input framework' released. Reading raw data from file and memory buffer supported from scratch. + LibRaw-using application can implement own data reading functions (e.g. reading from network stream). + Fuji SuperCCD: raw data extracted without 45-degree rotation. + New sample applications: 4channels and unprocessed_raw + Imported (subsequentally) new dcraw versions from 8.89 to 8.93 (up to date) +- New option to switch on/off auto brightness adjsutements. +- Add support of Leica Raw files (RWL). +- New method to see if Libraw use OpenMP shared library to perform parallel demosaicing. +- OpenMP support auto detection based on FindOpenMP Cmake script. + +0.4.0 - Released with KDE 4.2.0 +------------------------------------------------------------------------ +- Updated to LibRaw 0.6.5 : Fixed file descriptor and buffer memory leak when thumbnail extractor is called, + but library object is not properly initialized. + Fixes in Imacon files unpacking. + Fixes in Hasselblad .fff files unpacking. +- Updated to LibRaw 0.6.3 : NEF processing code changed (some overflow control added). +- Updated to LibRaw 0.6.2. +- New cameras: Canon G10 & 5D Mk2, Leaf AFi 7, Leica D-LUX4, + Panasonic FX150 & G 1, Fujifilm IS Pro. +- Updated to LibRaw 0.6.1. +- New cameras: Canon 50D, Sony A900, Nikon D90 & P6000, Panasonic LX3 FZ28. +- Ported to LibRaw Api 0.6.0. Removed dcraw.c and DcrawBinary class. +- Use kDebug(51002) instead qDebug(). + +0.3.0 - Released with KDE 4.1.2 +------------------------------------------------------------------------ +- Sync with KDE3 branch 0.1.5 API changes. + +0.2.0 - Released with KDE 4.1.0 +------------------------------------------------------------------------ +- Port to CMake/KDE4/QT4 +- Moved from extragear/libs to kdegraphics/libs + +0.1.5 +------------------------------------------------------------------------ + +- API changed: add white point settings support (dcraw -S option) + +- Updated dcraw to 8.86 + New camera : Sony A300. + Fixed camera WB on the A200. + Set model-specific saturation levels in adobe_coeff(). + No new options introduced. +- Updated dcraw to 8.85 + New camera : Olympus E-420. + No new options introduced. +- Updated dcraw to 8.84 + New cameras: Canon EOS 450D, Nikon D60, and Fuji S100FS. + Copied new matrices from Adobe DNG Converter 4.4. + sRAW support in 1.393 broke Fuji DNG files, now fixed. + No new options introduced. + +0.1.4 +------------------------------------------------------------------------ +- updated dcraw to 8.83 + new cameras: Apple QuickTake 200, Fuji IS-1, Sony DSLR-A350, Pentax K20D, + Nokia N95, Canon PowerShots A460, Canon PowerShots A530, + Canon PowerShots A650. + no new options introduced. +- updated dcraw to 8.82 + new cameras: Sony DSLR-A200, Sony DSLR-A700, Sony XCD-SX910CR, STV680 VGA + no new options introduced. + +Bugs fixed from B.K.O (http://bugs.kde.org): +001 ==> 142055 : Which whitebalance is used. + +0.1.3 +------------------------------------------------------------------------ +- updated dcraw to 8.81 +- New cameras: Canon G7, Fuji FinePix S9100/S9600, Olympus SP560UZ, Panasonic DMC-L10 + +- updated dcraw to 8.80 +- new cameras: Hasselblad H3D, Olympus E-3, Canon EOS 40D, Canon PowerShot G9, + Canon EOS-1Ds Mark III, AVT F-080C, Nikon D3, Nikon D300, + Nikon Coolpix S6, Panasonic DMC-FZ18, Sony DSLR-A700 + + -m number_of_passes + After interpolation, clean up color artifacts by repeatedly + applying a 3x3 median filter to the R-G and B-G channels. +- dcraw.c licence : is GPL compatible again == less wories) + +0.1.2 +------------------------------------------------------------------------ + +New features +- updated internal dcraw from 8.60 to 8.77. API changed. +- add new chromatic aberration reduction options (patch from Guillaume Castagnino). + +0.1.1 +------------------------------------------------------------------------ + +New features +- API changed: * KDcraw destructor is now virtual. + * Added DcrawSettingsContainer destructor. + * Separate embedded JPEG preview extraction and half decoding methods + to get a preview of RAW pictures. + +Bugs fixed from B.K.O (http://bugs.kde.org): +001 ==> 145482 : libkdraw compile fails on Cygwin. + +0.1.0 +------------------------------------------------------------------------ +First implementation + +For details and info about previous versions, see ChangeLog. diff --git a/libkdcraw/README b/libkdcraw/README new file mode 100644 index 00000000..729a5ae1 --- /dev/null +++ b/libkdcraw/README @@ -0,0 +1,76 @@ +LibRaw C++ interface for KDE + +This library is a part of digiKam project (http://www.digikam.org) + +-- AUTHORS ----------------------------------------------------------- + +See AUTHORS file for details. + +-- ABOUT ------------------------------------------------------------- + +Libkdcraw is a C++ interface around LibRaw library used to decode RAW +picture files. More information about LibRaw can be found at http://www.libraw.org. + +This library is used by kipi-plugins, digiKam and others kipi host programs. + +The library documentation is available on header files. + +-- DEPENDENCIES ------------------------------------------------------- + +CMake >= 2.4.3 http://www.cmake.org +libqt >= 4.2.x http://www.qtsoftware.com +libkde >= 4.0.x http://www.kde.org +libraw >= 0.16.x http://www.libraw.org + +Note: all library dependencies require development and binary packages installed on your +computer to compile digiKam. + +-- INSTALL ------------------------------------------------------------ + +In order to compile, especially when QT3/Qt4 are installed at the same time, +just use something like that: + +# export VERBOSE=1 +# export QTDIR=/usr/lib/qt4/ +# export PATH=$QTDIR/bin:$PATH +# cmake . +# make + +Usual CMake options : + +-DCMAKE_INSTALL_PREFIX : decide where the program will be install on your computer. +-DCMAKE_BUILD_TYPE : decide which type of build you want. You can chose between "debugfull", "debug", "profile", "relwithdebinfo" and "release". The default is "relwithdebinfo" (-O2 -g). + +Compared to old KDE3 autoconf options: + +"cmake . -DCMAKE_BUILD_TYPE=debugfull" is equivalent to "./configure --enable-debug=full" +"cmake . -DCMAKE_INSTALL_PREFIX=/usr" is equivalent to "./configure --prefix=/usr" + +More details can be found ata this url: http://techbase.kde.org/Development/Tutorials/CMake#Environment_Variables + +Note: To know KDE install path on your computer, use 'kde-config --prefix' command line like this (with full debug object enabled): + +"cmake . -DCMAKE_BUILD_TYPE=debugfull -DCMAKE_INSTALL_PREFIX=`kde4-config --prefix`" + +-- CONTACT ------------------------------------------------------------ + +If you have questions, comments, suggestions to make do email at : + +kde-imaging@kde.org + +IRC channel from freenode.net server: + +#kde-imaging + +-- BUGS --------------------------------------------------------------- + +IMPORTANT : the bugreports and wishlist are hosted by the KDE bugs report +system who can be contacted by the standard Kde help menu of plugins dialog. +A mail will be automatically sent to the Kipi mailing list. +There is no need to contact directly the Kipi mailing list for a bug report +or a devel wish. + +The current Kipi bugs and devel wish reported to the Kde bugs report can be see +at this url : + +http://bugs.kde.org/buglist.cgi?product=digikam&component=libkdcraw&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED diff --git a/libkdcraw/TODO b/libkdcraw/TODO new file mode 100644 index 00000000..9d92a09c --- /dev/null +++ b/libkdcraw/TODO @@ -0,0 +1,14 @@ +- Add DNG writting mode support using Adobe DNG sdk + +- Libraw 0.13.0 features to support : + +1) Green channel local averaging. All interpolation methods, but may conflict with green_matching option, so it is safer to use only one green averaging. + + int cfa_green; Boolean, default is 0 (off) + float green_threshold; - Sensitivity of method (green is averaged if difference less than this value in percent). Usable range between 0.01 and 0.1, commonly 0.03 + +This filtering is applied *before* demosaic. + +The problem is simple: on some cameras (for example, Olympus E-xxx) two green channels are different (in sensitivity and, may be, in spectral response). +As a result, it produces 'maze artifacts' on flat surfaces (like sky). +The solution is simple: if two channels are *slightly* different in some local area, it is better to equalize it. diff --git a/libkdcraw/icons/CMakeLists.txt b/libkdcraw/icons/CMakeLists.txt new file mode 100644 index 00000000..75795cce --- /dev/null +++ b/libkdcraw/icons/CMakeLists.txt @@ -0,0 +1,25 @@ +# =========================================================== +# +# This file is a part of digiKam project +# http://www.digikam.org +# +# @date 2006-12-09 +# @brief a tread-safe libraw C++ program interface for KDE +# +# @author Copyright (C) 2006-2012 by Gilles Caulier +# caulier dot gilles at gmail dot com +# +# This program is free software; you can redistribute it +# and/or modify it under the terms of the GNU General +# Public License as published by the Free Software Foundation; +# either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# ============================================================ + +kde4_install_icons ( ${ICON_INSTALL_DIR} ) diff --git a/libkdcraw/icons/hi128-app-kdcraw.png b/libkdcraw/icons/hi128-app-kdcraw.png new file mode 100644 index 00000000..bfe05031 Binary files /dev/null and b/libkdcraw/icons/hi128-app-kdcraw.png differ diff --git a/libkdcraw/icons/hi32-app-kdcraw.png b/libkdcraw/icons/hi32-app-kdcraw.png new file mode 100644 index 00000000..d089133b Binary files /dev/null and b/libkdcraw/icons/hi32-app-kdcraw.png differ diff --git a/libkdcraw/icons/hi48-app-kdcraw.png b/libkdcraw/icons/hi48-app-kdcraw.png new file mode 100644 index 00000000..862a8886 Binary files /dev/null and b/libkdcraw/icons/hi48-app-kdcraw.png differ diff --git a/libkdcraw/icons/hi64-app-kdcraw.png b/libkdcraw/icons/hi64-app-kdcraw.png new file mode 100644 index 00000000..495f62e5 Binary files /dev/null and b/libkdcraw/icons/hi64-app-kdcraw.png differ diff --git a/libkdcraw/libkdcraw.pc.cmake b/libkdcraw/libkdcraw.pc.cmake new file mode 100644 index 00000000..a7a876c4 --- /dev/null +++ b/libkdcraw/libkdcraw.pc.cmake @@ -0,0 +1,12 @@ +prefix=${CMAKE_INSTALL_PREFIX} +exec_prefix=${BIN_INSTALL_DIR} +libdir=${LIB_INSTALL_DIR} +includedir=${INCLUDE_INSTALL_DIR} + +Name: libkdcraw +Description: A C++ wrapper around LibRaw library to decode RAW pictures. This library is used by digiKam and kipi-plugins. +URL: http://www.digikam.org/sharedlibs +Requires: +Version: ${DCRAW_LIB_VERSION_STRING} +Libs: -L${LIB_INSTALL_DIR} -lkdcraw +Cflags: -I${INCLUDE_INSTALL_DIR} diff --git a/libkdcraw/libkdcraw/CMakeLists.txt b/libkdcraw/libkdcraw/CMakeLists.txt new file mode 100644 index 00000000..841158dc --- /dev/null +++ b/libkdcraw/libkdcraw/CMakeLists.txt @@ -0,0 +1,68 @@ +# =========================================================== +# +# This file is a part of digiKam project +# http://www.digikam.org +# +# @date 2006-12-09 +# @brief a tread-safe libraw C++ program interface for KDE +# +# @author Copyright (C) 2006-2013 by Gilles Caulier +# caulier dot gilles at gmail dot com +# +# This program is free software; you can redistribute it +# and/or modify it under the terms of the GNU General +# Public License as published by the Free Software Foundation; +# either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# ============================================================ + +add_definitions(${KDE4_ENABLE_EXCEPTIONS}) + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/version.h) + +SET(kdcraw_LIB_SRCS kdcraw.cpp + kdcraw_p.cpp + dcrawsettingswidget.cpp + dcrawinfocontainer.cpp + rawdecodingsettings.cpp + rcombobox.cpp + rnuminput.cpp + rexpanderbox.cpp + ractionthreadbase.cpp + ractionthreadbase_p.cpp + squeezedcombobox.cpp + ) + +KDE4_ADD_LIBRARY(kdcraw SHARED ${kdcraw_LIB_SRCS}) + +TARGET_LINK_LIBRARIES(kdcraw + ${KDE4_KDEUI_LIBS} + ${KDE4_KIO_LIBS} + ${KDE4_SOLID_LIBS} + ${KDE4_THREADWEAVER_LIBS} + ${LibRaw_r_LIBRARIES} + ) + +SET_TARGET_PROPERTIES(kdcraw PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION}) + +INSTALL(TARGETS kdcraw ${INSTALL_TARGETS_DEFAULT_ARGS}) + +INSTALL(FILES rawdecodingsettings.h + kdcraw.h + dcrawsettingswidget.h + rnuminput.h + rcombobox.h + rexpanderbox.h + ractionthreadbase.h + squeezedcombobox.h + dcrawinfocontainer.h + rawfiles.h + libkdcraw_export.h + ${CMAKE_CURRENT_BINARY_DIR}/version.h + DESTINATION ${INCLUDE_INSTALL_DIR}/libkdcraw COMPONENT Devel) diff --git a/libkdcraw/libkdcraw/Doxyfile b/libkdcraw/libkdcraw/Doxyfile new file mode 100644 index 00000000..312bfac2 --- /dev/null +++ b/libkdcraw/libkdcraw/Doxyfile @@ -0,0 +1,1067 @@ +# Doxyfile 1.3.5 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = libKDcraw + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en +# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese, +# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is used +# as the annotated text. Otherwise, the brief description is used as-is. If left +# blank, the following values are used ("$name" is automatically replaced with the +# name of the entity): "The $name class" "The $name widget" "The $name file" +# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ./ +INPUT += ./Mainpage.dox + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc + +FILE_PATTERNS = *.cpp \ + *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the +# parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superseded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = YES + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes that +# lay further from the root node will be omitted. Note that setting this option to +# 1 or 2 may greatly reduce the computation time needed for large code bases. Also +# note that a graph may be further truncated if the graph's image dimensions are +# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). +# If 0 is used for the depth value (the default), the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/libkdcraw/libkdcraw/Mainpage.dox b/libkdcraw/libkdcraw/Mainpage.dox new file mode 100644 index 00000000..7b96e9e5 --- /dev/null +++ b/libkdcraw/libkdcraw/Mainpage.dox @@ -0,0 +1,7 @@ +/** @mainpage libKDcraw + +libKDcraw is a thread-safe wrapper around libraw. Have a look at KDcrawIface::KDcraw to get started. + +@see KDcrawIface::KDcraw + + */ diff --git a/libkdcraw/libkdcraw/dcrawinfocontainer.cpp b/libkdcraw/libkdcraw/dcrawinfocontainer.cpp new file mode 100644 index 00000000..c2e2d8a7 --- /dev/null +++ b/libkdcraw/libkdcraw/dcrawinfocontainer.cpp @@ -0,0 +1,173 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2007-05-02 + * @brief RAW file identification information container + * + * @author Copyright (C) 2007-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// Local includes + +#include "dcrawinfocontainer.h" + +namespace KDcrawIface +{ + +DcrawInfoContainer::DcrawInfoContainer() +{ + sensitivity = -1.0; + exposureTime = -1.0; + aperture = -1.0; + focalLength = -1.0; + pixelAspectRatio = 1.0; // Default value. This can be unavailable (depending of camera model). + rawColors = -1; + rawImages = -1; + hasIccProfile = false; + isDecodable = false; + daylightMult[0] = 0.0; + daylightMult[1] = 0.0; + daylightMult[2] = 0.0; + cameraMult[0] = 0.0; + cameraMult[1] = 0.0; + cameraMult[2] = 0.0; + cameraMult[3] = 0.0; + blackPoint = 0; + + for (int ch=0; ch<4; ch++) + { + blackPointCh[ch] = 0; + } + + whitePoint = 0; + topMargin = 0; + leftMargin = 0; + orientation = ORIENTATION_NONE; + + for (int x=0 ; x<3 ; x++) + { + for (int y=0 ; y<4 ; y++) + { + cameraColorMatrix1[x][y] = 0.0; + cameraColorMatrix2[x][y] = 0.0; + cameraXYZMatrix[y][x] = 0.0; // NOTE: see B.K.O # 253911 : [y][x] not [x][y] + } + } +} + +DcrawInfoContainer::~DcrawInfoContainer() +{ +} + +bool DcrawInfoContainer::isEmpty() +{ + if (make.isEmpty() && + model.isEmpty() && + filterPattern.isEmpty() && + colorKeys.isEmpty() && + DNGVersion.isEmpty() && + exposureTime == -1.0 && + aperture == -1.0 && + focalLength == -1.0 && + pixelAspectRatio == 1.0 && + sensitivity == -1.0 && + rawColors == -1 && + rawImages == -1 && + blackPoint == 0 && + blackPointCh[0] == 0 && + blackPointCh[1] == 0 && + blackPointCh[2] == 0 && + blackPointCh[3] == 0 && + whitePoint == 0 && + topMargin == 0 && + leftMargin == 0 && + !dateTime.isValid() && + !imageSize.isValid() && + !fullSize.isValid() && + !outputSize.isValid() && + !thumbSize.isValid() && + cameraColorMatrix1[0][0] == 0.0 && + cameraColorMatrix1[0][1] == 0.0 && + cameraColorMatrix1[0][2] == 0.0 && + cameraColorMatrix1[0][3] == 0.0 && + cameraColorMatrix1[1][0] == 0.0 && + cameraColorMatrix1[1][1] == 0.0 && + cameraColorMatrix1[1][2] == 0.0 && + cameraColorMatrix1[1][3] == 0.0 && + cameraColorMatrix1[2][0] == 0.0 && + cameraColorMatrix1[2][1] == 0.0 && + cameraColorMatrix1[2][2] == 0.0 && + cameraColorMatrix1[2][3] == 0.0 && + cameraColorMatrix2[0][0] == 0.0 && + cameraColorMatrix2[0][1] == 0.0 && + cameraColorMatrix2[0][2] == 0.0 && + cameraColorMatrix2[0][3] == 0.0 && + cameraColorMatrix2[1][0] == 0.0 && + cameraColorMatrix2[1][1] == 0.0 && + cameraColorMatrix2[1][2] == 0.0 && + cameraColorMatrix2[1][3] == 0.0 && + cameraColorMatrix2[2][0] == 0.0 && + cameraColorMatrix2[2][1] == 0.0 && + cameraColorMatrix2[2][2] == 0.0 && + cameraColorMatrix2[2][3] == 0.0 && + cameraXYZMatrix[0][0] == 0.0 && + cameraXYZMatrix[0][1] == 0.0 && + cameraXYZMatrix[0][2] == 0.0 && + cameraXYZMatrix[1][0] == 0.0 && + cameraXYZMatrix[1][1] == 0.0 && + cameraXYZMatrix[1][2] == 0.0 && + cameraXYZMatrix[2][0] == 0.0 && + cameraXYZMatrix[2][1] == 0.0 && + cameraXYZMatrix[2][2] == 0.0 && + cameraXYZMatrix[3][0] == 0.0 && + cameraXYZMatrix[3][1] == 0.0 && + cameraXYZMatrix[3][2] == 0.0 && + orientation == ORIENTATION_NONE + ) + { + return true; + } + else + { + return false; + } +} + +QDebug operator<<(QDebug dbg, const DcrawInfoContainer& c) +{ + dbg.nospace() << "DcrawInfoContainer::sensitivity: " << c.sensitivity << ", "; + dbg.nospace() << "DcrawInfoContainer::exposureTime: " << c.exposureTime << ", "; + dbg.nospace() << "DcrawInfoContainer::aperture: " << c.aperture << ", "; + dbg.nospace() << "DcrawInfoContainer::focalLength: " << c.focalLength << ", "; + dbg.nospace() << "DcrawInfoContainer::pixelAspectRatio: " << c.pixelAspectRatio << ", "; + dbg.nospace() << "DcrawInfoContainer::rawColors: " << c.rawColors << ", "; + dbg.nospace() << "DcrawInfoContainer::rawImages: " << c.rawImages << ", "; + dbg.nospace() << "DcrawInfoContainer::hasIccProfile: " << c.hasIccProfile << ", "; + dbg.nospace() << "DcrawInfoContainer::isDecodable: " << c.isDecodable << ", "; + dbg.nospace() << "DcrawInfoContainer::daylightMult: " << c.daylightMult << ", "; + dbg.nospace() << "DcrawInfoContainer::cameraMult: " << c.cameraMult << ", "; + dbg.nospace() << "DcrawInfoContainer::blackPoint: " << c.blackPoint << ", "; + dbg.nospace() << "DcrawInfoContainer::whitePoint: " << c.whitePoint << ", "; + dbg.nospace() << "DcrawInfoContainer::topMargin: " << c.topMargin << ", "; + dbg.nospace() << "DcrawInfoContainer::leftMargin: " << c.leftMargin << ", "; + dbg.nospace() << "DcrawInfoContainer::orientation: " << c.orientation; + return dbg.space(); +} + +} // namespace KDcrawIface diff --git a/libkdcraw/libkdcraw/dcrawinfocontainer.h b/libkdcraw/libkdcraw/dcrawinfocontainer.h new file mode 100644 index 00000000..5ab6f36f --- /dev/null +++ b/libkdcraw/libkdcraw/dcrawinfocontainer.h @@ -0,0 +1,158 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2007-05-02 + * @brief RAW file identification information container + * + * @author Copyright (C) 2007-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef DCRAW_INFO_CONTAINER_H +#define DCRAW_INFO_CONTAINER_H + +// Qt includes + +#include +#include +#include +#include + +// Local includes + +#include "libkdcraw_export.h" + +namespace KDcrawIface +{ + +class LIBKDCRAW_EXPORT DcrawInfoContainer +{ + +public: + + /** The RAW image orientation values + */ + enum ImageOrientation + { + ORIENTATION_NONE = 0, + ORIENTATION_180 = 3, + ORIENTATION_Mirror90CCW = 4, + ORIENTATION_90CCW = 5, + ORIENTATION_90CW = 6 + }; + +public: + + /** Standard constructor */ + DcrawInfoContainer(); + + /** Standard destructor */ + virtual ~DcrawInfoContainer(); + + /** Return 'true' if container is empty, else 'false' */ + bool isEmpty(); + +public: + + /** True if RAW file include an ICC color profile. */ + bool hasIccProfile; + /** True is RAW file is decodable by dcraw. */ + bool isDecodable; + + /** The number of RAW colors. */ + int rawColors; + + /** The number of RAW images. */ + int rawImages; + + /** Black level from Raw histogram. */ + unsigned int blackPoint; + + /** Channel black levels from Raw histogram. */ + unsigned int blackPointCh[4]; + + /** White level from Raw histogram. */ + unsigned int whitePoint; + + /** Top margin of raw image. */ + unsigned int topMargin; + + /** Left margin of raw image. */ + unsigned int leftMargin; + + /** The raw image orientation */ + ImageOrientation orientation; + + /** The sensitivity in ISO used by camera to take the picture. */ + float sensitivity; + + /** ==> 1/exposureTime = exposure time in seconds. */ + float exposureTime; + /** ==> Aperture value in APEX. */ + float aperture; + /** ==> Focal Length value in mm. */ + float focalLength; + /** The pixel Aspect Ratio if != 1.0. NOTE: if == 1.0, dcraw do not show this value. */ + float pixelAspectRatio; + + /** White color balance settings. */ + double daylightMult[3]; + /** Camera multipliers used for White Balance adjustments */ + double cameraMult[4]; + + /** Camera Color Matrix */ + float cameraColorMatrix1[3][4]; + float cameraColorMatrix2[3][4]; + float cameraXYZMatrix[4][3]; + + /** The used Color Keys */ + QString colorKeys; + + /** The camera maker. */ + QString make; + /** The camera model. */ + QString model; + /** The artist name who have picture owner. */ + QString owner; + /** The demosaising filter pattern. */ + QString filterPattern; + /** The DNG version. NOTE: it is only shown with DNG RAW files. */ + QString DNGVersion; + + /** Date & time when the picture has been taken. */ + QDateTime dateTime; + + /** The image dimensions in pixels. */ + QSize imageSize; + + /** The thumb dimensions in pixels. */ + QSize thumbSize; + + /** The full RAW image dimensions in pixels. */ + QSize fullSize; + + /** The output dimensions in pixels. */ + QSize outputSize; +}; + +//! kDebug() stream operator. Writes container @a c to the debug output in a nicely formatted way. +LIBKDCRAW_EXPORT QDebug operator<<(QDebug dbg, const DcrawInfoContainer& c); + +} // namespace KDcrawIface + +#endif /* DCRAW_INFO_CONTAINER_H */ diff --git a/libkdcraw/libkdcraw/dcrawsettingswidget.cpp b/libkdcraw/libkdcraw/dcrawsettingswidget.cpp new file mode 100644 index 00000000..790f6865 --- /dev/null +++ b/libkdcraw/libkdcraw/dcrawsettingswidget.cpp @@ -0,0 +1,1332 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-09-13 + * @brief LibRaw settings widgets + * + * @author Copyright (C) 2006-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2011 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * @author Copyright (C) 2007-2008 by Guillaume Castagnino + * casta at xwing dot info + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "moc_dcrawsettingswidget.cpp" + +// C++ includes + +#include + +// Qt includes + +#include +#include +#include +#include +#include + +// KDE includes + +#include +#include +#include +#include +#include +#include + +// Local includes + +#include "kdcraw.h" +#include "rnuminput.h" +#include "rcombobox.h" +#include "rexpanderbox.h" + +namespace KDcrawIface +{ + +class DcrawSettingsWidget::Private +{ +public: + + Private() + { + autoBrightnessBox = 0; + sixteenBitsImage = 0; + fourColorCheckBox = 0; + brightnessLabel = 0; + brightnessSpinBox = 0; + blackPointCheckBox = 0; + blackPointSpinBox = 0; + whitePointCheckBox = 0; + whitePointSpinBox = 0; + whiteBalanceComboBox = 0; + whiteBalanceLabel = 0; + customWhiteBalanceSpinBox = 0; + customWhiteBalanceLabel = 0; + customWhiteBalanceGreenSpinBox = 0; + customWhiteBalanceGreenLabel = 0; + unclipColorLabel = 0; + dontStretchPixelsCheckBox = 0; + RAWQualityComboBox = 0; + RAWQualityLabel = 0; + noiseReductionComboBox = 0; + NRSpinBox1 = 0; + NRSpinBox2 = 0; + NRLabel1 = 0; + NRLabel2 = 0; + enableCACorrectionBox = 0; + autoCACorrectionBox = 0; + caRedMultSpinBox = 0; + caBlueMultSpinBox = 0; + caRedMultLabel = 0; + caBlueMultLabel = 0; + unclipColorComboBox = 0; + reconstructLabel = 0; + reconstructSpinBox = 0; + outputColorSpaceLabel = 0; + outputColorSpaceComboBox = 0; + demosaicingSettings = 0; + whiteBalanceSettings = 0; + correctionsSettings = 0; + colormanSettings = 0; + medianFilterPassesSpinBox = 0; + medianFilterPassesLabel = 0; + inIccUrlEdit = 0; + outIccUrlEdit = 0; + inputColorSpaceLabel = 0; + inputColorSpaceComboBox = 0; + fixColorsHighlightsBox = 0; + refineInterpolationBox = 0; + noiseReductionLabel = 0; + expoCorrectionBox = 0; + expoCorrectionShiftSpinBox = 0; + expoCorrectionHighlightSpinBox = 0; + expoCorrectionShiftLabel = 0; + expoCorrectionHighlightLabel = 0; + } + + /** Convert Exposure correction shift E.V value from GUI to Linear value needs by libraw decoder. + */ + double shiftExpoFromEvToLinear(double ev) const + { + // From GUI : -2.0EV => 0.25 + // +3.0EV => 8.00 + return (1.55*ev + 3.35); + } + + /** Convert Exposure correction shift Linear value from liraw decoder to E.V value needs by GUI. + */ + double shiftExpoFromLinearToEv(double lin) const + { + // From GUI : 0.25 => -2.0EV + // 8.00 => +3.0EV + return ((lin-3.35) / 1.55); + } + +public: + + QWidget* demosaicingSettings; + QWidget* whiteBalanceSettings; + QWidget* correctionsSettings; + QWidget* colormanSettings; + + QLabel* whiteBalanceLabel; + QLabel* customWhiteBalanceLabel; + QLabel* customWhiteBalanceGreenLabel; + QLabel* brightnessLabel; + QLabel* RAWQualityLabel; + QLabel* NRLabel1; + QLabel* NRLabel2; + QLabel* caRedMultLabel; + QLabel* caBlueMultLabel; + QLabel* unclipColorLabel; + QLabel* reconstructLabel; + QLabel* inputColorSpaceLabel; + QLabel* outputColorSpaceLabel; + QLabel* medianFilterPassesLabel; + QLabel* noiseReductionLabel; + QLabel* expoCorrectionShiftLabel; + QLabel* expoCorrectionHighlightLabel; + + QCheckBox* blackPointCheckBox; + QCheckBox* whitePointCheckBox; + QCheckBox* sixteenBitsImage; + QCheckBox* autoBrightnessBox; + QCheckBox* fourColorCheckBox; + QCheckBox* dontStretchPixelsCheckBox; + QCheckBox* enableCACorrectionBox; + QCheckBox* autoCACorrectionBox; + QCheckBox* fixColorsHighlightsBox; + QCheckBox* refineInterpolationBox; + QCheckBox* expoCorrectionBox; + + KUrlRequester* inIccUrlEdit; + KUrlRequester* outIccUrlEdit; + + RComboBox* noiseReductionComboBox; + RComboBox* whiteBalanceComboBox; + RComboBox* RAWQualityComboBox; + RComboBox* unclipColorComboBox; + RComboBox* inputColorSpaceComboBox; + RComboBox* outputColorSpaceComboBox; + + RIntNumInput* customWhiteBalanceSpinBox; + RIntNumInput* reconstructSpinBox; + RIntNumInput* blackPointSpinBox; + RIntNumInput* whitePointSpinBox; + RIntNumInput* NRSpinBox1; + RIntNumInput* NRSpinBox2; + RIntNumInput* medianFilterPassesSpinBox; + + RDoubleNumInput* customWhiteBalanceGreenSpinBox; + RDoubleNumInput* caRedMultSpinBox; + RDoubleNumInput* caBlueMultSpinBox; + RDoubleNumInput* brightnessSpinBox; + RDoubleNumInput* expoCorrectionShiftSpinBox; + RDoubleNumInput* expoCorrectionHighlightSpinBox; +}; + +DcrawSettingsWidget::DcrawSettingsWidget(QWidget* const parent, int advSettings) + : RExpanderBox(parent), d(new Private) +{ + setup(advSettings); +} + +void DcrawSettingsWidget::setup(int advSettings) +{ + setObjectName( QLatin1String("DCRawSettings Expander" )); + + // --------------------------------------------------------------- + // DEMOSAICING Settings panel + + d->demosaicingSettings = new QWidget(this); + QGridLayout* const demosaicingLayout = new QGridLayout(d->demosaicingSettings); + + int line = 0; + + d->sixteenBitsImage = new QCheckBox(i18nc("@option:check", "16 bits color depth"), d->demosaicingSettings); + d->sixteenBitsImage->setWhatsThis(i18nc("@info:whatsthis", "If enabled, all RAW files will " + "be decoded in 16-bit color depth using a linear gamma curve. To " + "prevent dark picture rendering in the editor, it is recommended to " + "use Color Management in this mode." + "If disabled, all RAW files will be decoded in 8-bit color " + "depth with a BT.709 gamma curve and a 99th-percentile white point. " + "This mode is faster than 16-bit decoding.")); + demosaicingLayout->addWidget(d->sixteenBitsImage, 0, 0, 1, 2); + + if (advSettings & SIXTEENBITS) + { + d->sixteenBitsImage->show(); + line = 1; + } + else + { + d->sixteenBitsImage->hide(); + } + + d->fourColorCheckBox = new QCheckBox(i18nc("@option:check", "Interpolate RGB as four colors"), d->demosaicingSettings); + d->fourColorCheckBox->setWhatsThis(i18nc("@info:whatsthis", "Interpolate RGB as four " + "colors" + "The default is to assume that all green pixels are the same. " + "If even-row green pixels are more sensitive to ultraviolet light " + "than odd-row this difference causes a mesh pattern in the output; " + "using this option solves this problem with minimal loss of detail." + "To resume, this option blurs the image a little, but it " + "eliminates false 2x2 mesh patterns with VNG quality method or " + "mazes with AHD quality method.")); + demosaicingLayout->addWidget(d->fourColorCheckBox, line, 0, 1, line == 0 ? 2 : 3); + line++; + + KUrlLabel* const dcrawVersion = new KUrlLabel("http://www.libraw.org", QString("libraw %1") + .arg(KDcraw::librawVersion()), d->demosaicingSettings); + dcrawVersion->setAlignment(Qt::AlignRight); + dcrawVersion->setToolTip(i18nc("@info:tooltip", "Visit LibRaw project website")); + demosaicingLayout->addWidget(dcrawVersion, 0, 2, 1, 1); + + d->dontStretchPixelsCheckBox = new QCheckBox(i18nc("@option:check", "Do not stretch or rotate pixels"), d->demosaicingSettings); + d->dontStretchPixelsCheckBox->setWhatsThis(i18nc("@info:whatsthis", + "Do not stretch or rotate pixels" + "For Fuji Super CCD cameras, show the image tilted 45 degrees. " + "For cameras with non-square pixels, do not stretch the image to " + "its correct aspect ratio. In any case, this option guarantees that " + "each output pixel corresponds to one RAW pixel.")); + demosaicingLayout->addWidget(d->dontStretchPixelsCheckBox, line, 0, 1, 3); + line++; + + d->RAWQualityLabel = new QLabel(i18nc("@label:listbox", "Quality:"), d->demosaicingSettings); + d->RAWQualityComboBox = new RComboBox(d->demosaicingSettings); + + // Original dcraw demosaicing methods + d->RAWQualityComboBox->insertItem(RawDecodingSettings::BILINEAR, i18nc("@item:inlistbox Quality", "Bilinear")); + d->RAWQualityComboBox->insertItem(RawDecodingSettings::VNG, i18nc("@item:inlistbox Quality", "VNG")); + d->RAWQualityComboBox->insertItem(RawDecodingSettings::PPG, i18nc("@item:inlistbox Quality", "PPG")); + d->RAWQualityComboBox->insertItem(RawDecodingSettings::AHD, i18nc("@item:inlistbox Quality", "AHD")); + + // Extended demosaicing method from GPL2 pack + d->RAWQualityComboBox->insertItem(RawDecodingSettings::DCB, i18nc("@item:inlistbox Quality", "DCB")); + d->RAWQualityComboBox->insertItem(RawDecodingSettings::PL_AHD, i18nc("@item:inlistbox Quality", "AHD v2")); + d->RAWQualityComboBox->insertItem(RawDecodingSettings::AFD, i18nc("@item:inlistbox Quality", "AFD")); + d->RAWQualityComboBox->insertItem(RawDecodingSettings::VCD, i18nc("@item:inlistbox Quality", "VCD")); + d->RAWQualityComboBox->insertItem(RawDecodingSettings::VCD_AHD, i18nc("@item:inlistbox Quality", "VCD & AHD")); + d->RAWQualityComboBox->insertItem(RawDecodingSettings::LMMSE, i18nc("@item:inlistbox Quality", "LMMSE")); + // Extended demosaicing method from GPL3 pack + d->RAWQualityComboBox->insertItem(RawDecodingSettings::AMAZE, i18nc("@item:inlistbox Quality", "AMaZE")); + + // If Libraw do not support GPL2 pack, disable entries relevant. + if (!KDcraw::librawUseGPL2DemosaicPack()) + { + for (int i=RawDecodingSettings::DCB ; i <=RawDecodingSettings::LMMSE ; ++i) + d->RAWQualityComboBox->combo()->setItemData(i, false, Qt::UserRole-1); + } + + // If Libraw do not support GPL3 pack, disable entries relevant. + if (!KDcraw::librawUseGPL3DemosaicPack()) + { + d->RAWQualityComboBox->combo()->setItemData(RawDecodingSettings::AMAZE, false, Qt::UserRole-1); + } + + d->RAWQualityComboBox->setDefaultIndex(RawDecodingSettings::BILINEAR); + d->RAWQualityComboBox->setCurrentIndex(RawDecodingSettings::BILINEAR); + d->RAWQualityComboBox->setWhatsThis(i18nc("@info:whatsthis", "Quality (interpolation)" + "Select here the demosaicing method to use when decoding RAW " + "images. A demosaicing algorithm is a digital image process used to " + "interpolate a complete image from the partial raw data received " + "from the color-filtered image sensor, internal to many digital " + "cameras, in form of a matrix of colored pixels. Also known as CFA " + "interpolation or color reconstruction, another common spelling is " + "demosaicing. The following methods are available for demosaicing " + "RAW images:" + + // Original dcraw demosaicing methods + + "Bilinear: use " + "high-speed but low-quality bilinear interpolation (default - for " + "slow computers). In this method, the red value of a non-red pixel " + "is computed as the average of the adjacent red pixels, and similarly " + "for blue and green." + + "VNG: use Variable Number " + "of Gradients interpolation. This method computes gradients near " + "the pixel of interest and uses the lower gradients (representing " + "smoother and more similar parts of the image) to make an estimate." + + "PPG: use Patterned-Pixel-" + "Grouping interpolation. Pixel Grouping uses assumptions about " + "natural scenery in making estimates. It has fewer color artifacts " + "on natural images than the Variable Number of Gradients method." + + "AHD: use Adaptive " + "Homogeneity-Directed interpolation. This method selects the " + "direction of interpolation so as to maximize a homogeneity metric, " + "thus typically minimizing color artifacts." + + // Extended demosaicing method + + "DCB: DCB interpolation from " + "linuxphoto.org project." + + "AHD v2: modified AHD " + "interpolation using Variance of Color Differences method." + + "AFD: Adaptive Filtered " + "Demosaicing interpolation through 5 pass median filter from PerfectRaw " + "project." + + "VCD: Variance of Color " + "Differences interpolation." + + "VCD & AHD: Mixed demosaicing " + "between VCD and AHD." + + "LMMSE: color demosaicing via " + "directional linear minimum mean-square error estimation interpolation " + "from PerfectRaw." + + "AMaZE: Aliasing Minimization " + "interpolation and Zipper Elimination to apply color aberration removal " + "from RawTherapee project." + + "Note: some methods can be unavailable if RAW decoder have been built " + "without extension packs.")); + + demosaicingLayout->addWidget(d->RAWQualityLabel, line, 0, 1, 1); + demosaicingLayout->addWidget(d->RAWQualityComboBox, line, 1, 1, 2); + line++; + + d->medianFilterPassesSpinBox = new RIntNumInput(d->demosaicingSettings); + d->medianFilterPassesSpinBox->setRange(0, 10, 1); + d->medianFilterPassesSpinBox->setDefaultValue(0); + d->medianFilterPassesSpinBox->setSliderEnabled(true); + d->medianFilterPassesLabel = new QLabel(i18nc("@label:slider", "Pass:"), d->whiteBalanceSettings); + d->medianFilterPassesSpinBox->setWhatsThis( i18nc("@info:whatsthis", "Pass" + "Set here the passes used by the median filter applied after " + "interpolation to Red-Green and Blue-Green channels." + "This setting is only available for specific Quality options: " + "Bilinear, " + "VNG, PPG, " + "AHD, " + "DCB, and VCD & AHD.")); + demosaicingLayout->addWidget(d->medianFilterPassesLabel, line, 0, 1, 1); + demosaicingLayout->addWidget(d->medianFilterPassesSpinBox, line, 1, 1, 2); + line++; + + d->refineInterpolationBox = new QCheckBox(i18nc("@option:check", "Refine interpolation"), d->demosaicingSettings); + d->refineInterpolationBox->setWhatsThis(i18nc("@info:whatsthis", "Refine interpolation" + "This setting is available only for few Quality options:" + "DCB: turn on " + "the enhance interpolated colors filter." + "VCD & AHD: turn on the " + "enhanced effective color interpolation (EECI) refine to improve " + "sharpness.")); + demosaicingLayout->addWidget(d->refineInterpolationBox, line, 0, 1, 2); + + // If Libraw do not support GPL2 pack, disable options relevant. + if (!KDcraw::librawUseGPL2DemosaicPack()) + { + d->medianFilterPassesLabel->setEnabled(false); + d->medianFilterPassesSpinBox->setEnabled(false); + d->refineInterpolationBox->setEnabled(false); + } + + addItem(d->demosaicingSettings, SmallIcon("kdcraw"), i18nc("@label", "Demosaicing"), QString("demosaicing"), true); + + // --------------------------------------------------------------- + // WHITE BALANCE Settings Panel + + d->whiteBalanceSettings = new QWidget(this); + QGridLayout* const whiteBalanceLayout = new QGridLayout(d->whiteBalanceSettings); + + d->whiteBalanceLabel = new QLabel(i18nc("@label:listbox", "Method:"), d->whiteBalanceSettings); + d->whiteBalanceComboBox = new RComboBox(d->whiteBalanceSettings); + d->whiteBalanceComboBox->insertItem(RawDecodingSettings::NONE, i18nc("@item:inlistbox", "Default D65")); + d->whiteBalanceComboBox->insertItem(RawDecodingSettings::CAMERA, i18nc("@item:inlistbox", "Camera")); + d->whiteBalanceComboBox->insertItem(RawDecodingSettings::AUTO, i18nc("@item:inlistbox set while balance automatically", "Automatic")); + d->whiteBalanceComboBox->insertItem(RawDecodingSettings::CUSTOM, i18nc("@item:inlistbox set white balance manually", "Manual")); + d->whiteBalanceComboBox->setDefaultIndex(RawDecodingSettings::CAMERA); + d->whiteBalanceComboBox->setWhatsThis(i18nc("@info:whatsthis", "White Balance" + "Configure the raw white balance:" + "Default D65: " + "Use a standard daylight D65 white balance." + "Camera: Use the white " + "balance specified by the camera. If not available, reverts to " + "default neutral white balance." + "Automatic: Calculates an " + "automatic white balance averaging the entire image." + "Manual: Set a custom " + "temperature and green level values.")); + + d->customWhiteBalanceSpinBox = new RIntNumInput(d->whiteBalanceSettings); + d->customWhiteBalanceSpinBox->setRange(2000, 12000, 10); + d->customWhiteBalanceSpinBox->setDefaultValue(6500); + d->customWhiteBalanceSpinBox->setSliderEnabled(true); + d->customWhiteBalanceLabel = new QLabel(i18nc("@label:slider", "T(K):"), d->whiteBalanceSettings); + d->customWhiteBalanceSpinBox->setWhatsThis( i18nc("@info:whatsthis", "Temperature" + "Set here the color temperature in Kelvin.")); + + d->customWhiteBalanceGreenSpinBox = new RDoubleNumInput(d->whiteBalanceSettings); + d->customWhiteBalanceGreenSpinBox->setDecimals(2); + d->customWhiteBalanceGreenSpinBox->setRange(0.2, 2.5, 0.01); + d->customWhiteBalanceGreenSpinBox->setDefaultValue(1.0); + d->customWhiteBalanceGreenLabel = new QLabel(i18nc("@label:slider Green component", "Green:"), d->whiteBalanceSettings); + d->customWhiteBalanceGreenSpinBox->setWhatsThis(i18nc("@info:whatsthis", "Set here the " + "green component to set magenta color cast removal level.")); + + d->unclipColorLabel = new QLabel(i18nc("@label:listbox", "Highlights:"), d->whiteBalanceSettings); + d->unclipColorComboBox = new RComboBox(d->whiteBalanceSettings); + d->unclipColorComboBox->insertItem(0, i18nc("@item:inlistbox", "Solid white")); + d->unclipColorComboBox->insertItem(1, i18nc("@item:inlistbox", "Unclip")); + d->unclipColorComboBox->insertItem(2, i18nc("@item:inlistbox", "Blend")); + d->unclipColorComboBox->insertItem(3, i18nc("@item:inlistbox", "Rebuild")); + d->unclipColorComboBox->setDefaultIndex(0); + d->unclipColorComboBox->setWhatsThis(i18nc("@info:whatsthis", "Highlights" + "Select here the highlight clipping method:" + "Solid white: " + "clip all highlights to solid white" + "Unclip: leave highlights " + "unclipped in various shades of pink" + "Blend:Blend clipped and " + "unclipped values together for a gradual fade to white" + "Rebuild: reconstruct " + "highlights using a level value")); + + d->reconstructLabel = new QLabel(i18nc("@label:slider Highlight reconstruct level", "Level:"), d->whiteBalanceSettings); + d->reconstructSpinBox = new RIntNumInput(d->whiteBalanceSettings); + d->reconstructSpinBox->setRange(0, 6, 1); + d->reconstructSpinBox->setDefaultValue(0); + d->reconstructSpinBox->setSliderEnabled(true); + d->reconstructSpinBox->setWhatsThis(i18nc("@info:whatsthis", "Level" + "Specify the reconstruct highlight level. Low values favor " + "whites and high values favor colors.")); + + d->expoCorrectionBox = new QCheckBox(i18nc("@option:check", "Exposure Correction (E.V)"), d->whiteBalanceSettings); + d->expoCorrectionBox->setWhatsThis(i18nc("@info:whatsthis", "Turn on the exposure " + "correction before interpolation.")); + + d->expoCorrectionShiftLabel = new QLabel(i18nc("@label:slider", "Linear Shift:"), d->whiteBalanceSettings); + d->expoCorrectionShiftSpinBox = new RDoubleNumInput(d->whiteBalanceSettings); + d->expoCorrectionShiftSpinBox->setDecimals(2); + d->expoCorrectionShiftSpinBox->setRange(-2.0, 3.0, 0.01); + d->expoCorrectionShiftSpinBox->setDefaultValue(0.0); + d->expoCorrectionShiftSpinBox->setWhatsThis(i18nc("@info:whatsthis", "Shift" + "Linear Shift of exposure correction before interpolation in E.V")); + + d->expoCorrectionHighlightLabel = new QLabel(i18nc("@label:slider", "Highlight:"), d->whiteBalanceSettings); + d->expoCorrectionHighlightSpinBox = new RDoubleNumInput(d->whiteBalanceSettings); + d->expoCorrectionHighlightSpinBox->setDecimals(2); + d->expoCorrectionHighlightSpinBox->setRange(0.0, 1.0, 0.01); + d->expoCorrectionHighlightSpinBox->setDefaultValue(0.0); + d->expoCorrectionHighlightSpinBox->setWhatsThis(i18nc("@info:whatsthis", "Highlight" + "Amount of highlight preservation for exposure correction " + "before interpolation in E.V. Only take effect if Shift Correction is > 1.0 E.V")); + + d->fixColorsHighlightsBox = new QCheckBox(i18nc("@option:check", "Correct false colors in highlights"), d->whiteBalanceSettings); + d->fixColorsHighlightsBox->setWhatsThis(i18nc("@info:whatsthis", "If enabled, images with " + "overblown channels are processed much more accurately, without " + "'pink clouds' (and blue highlights under tungsten lamps).")); + + d->autoBrightnessBox = new QCheckBox(i18nc("@option:check", "Auto Brightness"), d->whiteBalanceSettings); + d->autoBrightnessBox->setWhatsThis(i18nc("@info:whatsthis", "If disable, use a fixed white level " + "and ignore the image histogram to adjust brightness.")); + + d->brightnessLabel = new QLabel(i18nc("@label:slider", "Brightness:"), d->whiteBalanceSettings); + d->brightnessSpinBox = new RDoubleNumInput(d->whiteBalanceSettings); + d->brightnessSpinBox->setDecimals(2); + d->brightnessSpinBox->setRange(0.0, 10.0, 0.01); + d->brightnessSpinBox->setDefaultValue(1.0); + d->brightnessSpinBox->setWhatsThis(i18nc("@info:whatsthis", "Brightness" + "Specify the brightness level of output image. The default " + "value is 1.0 (works in 8-bit mode only).")); + + if (! (advSettings & POSTPROCESSING)) + { + d->brightnessLabel->hide(); + d->brightnessSpinBox->hide(); + } + + d->blackPointCheckBox = new QCheckBox(i18nc("@option:check Black point", "Black:"), d->whiteBalanceSettings); + d->blackPointCheckBox->setWhatsThis(i18nc("@info:whatsthis", "Black point" + "Use a specific black point value to decode RAW pictures. If " + "you set this option to off, the Black Point value will be " + "automatically computed.")); + d->blackPointSpinBox = new RIntNumInput(d->whiteBalanceSettings); + d->blackPointSpinBox->setRange(0, 1000, 1); + d->blackPointSpinBox->setDefaultValue(0); + d->blackPointSpinBox->setSliderEnabled(true); + d->blackPointSpinBox->setWhatsThis(i18nc("@info:whatsthis", "Black point value" + "Specify specific black point value of the output image.")); + + d->whitePointCheckBox = new QCheckBox(i18nc("@option:check White point", "White:"), d->whiteBalanceSettings); + d->whitePointCheckBox->setWhatsThis(i18nc("@info:whatsthis", "White point" + "Use a specific white point value to decode RAW pictures. If " + "you set this option to off, the White Point value will be " + "automatically computed.")); + d->whitePointSpinBox = new RIntNumInput(d->whiteBalanceSettings); + d->whitePointSpinBox->setRange(0, 20000, 1); + d->whitePointSpinBox->setDefaultValue(0); + d->whitePointSpinBox->setSliderEnabled(true); + d->whitePointSpinBox->setWhatsThis(i18nc("@info:whatsthis", "White point value" + "Specify specific white point value of the output image.")); + + if (! (advSettings & BLACKWHITEPOINTS)) + { + d->blackPointCheckBox->hide(); + d->blackPointSpinBox->hide(); + d->whitePointCheckBox->hide(); + d->whitePointSpinBox->hide(); + } + + whiteBalanceLayout->addWidget(d->whiteBalanceLabel, 0, 0, 1, 1); + whiteBalanceLayout->addWidget(d->whiteBalanceComboBox, 0, 1, 1, 2); + whiteBalanceLayout->addWidget(d->customWhiteBalanceLabel, 1, 0, 1, 1); + whiteBalanceLayout->addWidget(d->customWhiteBalanceSpinBox, 1, 1, 1, 2); + whiteBalanceLayout->addWidget(d->customWhiteBalanceGreenLabel, 2, 0, 1, 1); + whiteBalanceLayout->addWidget(d->customWhiteBalanceGreenSpinBox, 2, 1, 1, 2); + whiteBalanceLayout->addWidget(d->unclipColorLabel, 3, 0, 1, 1); + whiteBalanceLayout->addWidget(d->unclipColorComboBox, 3, 1, 1, 2); + whiteBalanceLayout->addWidget(d->reconstructLabel, 4, 0, 1, 1); + whiteBalanceLayout->addWidget(d->reconstructSpinBox, 4, 1, 1, 2); + whiteBalanceLayout->addWidget(d->expoCorrectionBox, 5, 0, 1, 2); + whiteBalanceLayout->addWidget(d->expoCorrectionShiftLabel, 6, 0, 1, 1); + whiteBalanceLayout->addWidget(d->expoCorrectionShiftSpinBox, 6, 1, 1, 2); + whiteBalanceLayout->addWidget(d->expoCorrectionHighlightLabel, 7, 0, 1, 1); + whiteBalanceLayout->addWidget(d->expoCorrectionHighlightSpinBox, 7, 1, 1, 2); + whiteBalanceLayout->addWidget(d->fixColorsHighlightsBox, 8, 0, 1, 3); + whiteBalanceLayout->addWidget(d->autoBrightnessBox, 9, 0, 1, 3); + whiteBalanceLayout->addWidget(d->brightnessLabel, 10, 0, 1, 1); + whiteBalanceLayout->addWidget(d->brightnessSpinBox, 10, 1, 1, 2); + whiteBalanceLayout->addWidget(d->blackPointCheckBox, 11, 0, 1, 1); + whiteBalanceLayout->addWidget(d->blackPointSpinBox, 11, 1, 1, 2); + whiteBalanceLayout->addWidget(d->whitePointCheckBox, 12, 0, 1, 1); + whiteBalanceLayout->addWidget(d->whitePointSpinBox, 12, 1, 1, 2); + whiteBalanceLayout->setSpacing(KDialog::spacingHint()); + whiteBalanceLayout->setMargin(KDialog::spacingHint()); + + addItem(d->whiteBalanceSettings, SmallIcon("kdcraw"), i18nc("@label", "White Balance"), QString("whitebalance"), true); + + // --------------------------------------------------------------- + // CORRECTIONS Settings panel + + d->correctionsSettings = new QWidget(this); + QGridLayout* const correctionsLayout = new QGridLayout(d->correctionsSettings); + + d->noiseReductionLabel = new QLabel(i18nc("@label:listbox", "Noise reduction:"), d->correctionsSettings); + d->noiseReductionComboBox = new RComboBox(d->colormanSettings); + d->noiseReductionComboBox->insertItem(RawDecodingSettings::NONR, i18nc("@item:inlistbox Noise Reduction", "None")); + d->noiseReductionComboBox->insertItem(RawDecodingSettings::WAVELETSNR, i18nc("@item:inlistbox Noise Reduction", "Wavelets")); + d->noiseReductionComboBox->insertItem(RawDecodingSettings::FBDDNR, i18nc("@item:inlistbox Noise Reduction", "FBDD")); + d->noiseReductionComboBox->insertItem(RawDecodingSettings::LINENR, i18nc("@item:inlistbox Noise Reduction", "CFA Line Denoise")); + d->noiseReductionComboBox->insertItem(RawDecodingSettings::IMPULSENR, i18nc("@item:inlistbox Noise Reduction", "Impulse Denoise")); + d->noiseReductionComboBox->setDefaultIndex(RawDecodingSettings::NONR); + d->noiseReductionComboBox->setWhatsThis(i18nc("@info:whatsthis", "Noise Reduction" + "Select here the noise reduction method to apply during RAW " + "decoding." + "None: no " + "noise reduction." + "Wavelets: wavelets " + "correction to erase noise while preserving real detail. It's " + "applied after interpolation." + "FBDD: Fake Before " + "Demosaicing Denoising noise reduction. It's applied before " + "interpolation." + "CFA Line Denoise: Banding " + "noise suppression. It's applied after interpolation." + "Impulse Denoise: Impulse " + "noise suppression. It's applied after interpolation.")); + + d->NRSpinBox1 = new RIntNumInput(d->correctionsSettings); + d->NRSpinBox1->setRange(100, 1000, 1); + d->NRSpinBox1->setDefaultValue(100); + d->NRSpinBox1->setSliderEnabled(true); + d->NRLabel1 = new QLabel(d->correctionsSettings); + + d->NRSpinBox2 = new RIntNumInput(d->correctionsSettings); + d->NRSpinBox2->setRange(100, 1000, 1); + d->NRSpinBox2->setDefaultValue(100); + d->NRSpinBox2->setSliderEnabled(true); + d->NRLabel2 = new QLabel(d->correctionsSettings); + + d->enableCACorrectionBox = new QCheckBox(i18nc("@option:check", "Enable Chromatic Aberration correction"), d->correctionsSettings); + d->enableCACorrectionBox->setWhatsThis(i18nc("@info:whatsthis", "Enable Chromatic " + "Aberration correction" + "Enlarge the raw red-green and blue-yellow axis by the given " + "factors (automatic by default).")); + + d->autoCACorrectionBox = new QCheckBox(i18nc("@option:check", "Automatic color axis adjustments"), d->correctionsSettings); + d->autoCACorrectionBox->setWhatsThis(i18nc("@info:whatsthis", "Automatic Chromatic " + "Aberration correction" + "If this option is turned on, it will try to shift image " + "channels slightly and evaluate Chromatic Aberration change. Note " + "that if you shot blue-red pattern, the method may fail. In this " + "case, disable this option and tune manually color factors.")); + + d->caRedMultLabel = new QLabel(i18nc("@label:slider", "Red-Green:"), d->correctionsSettings); + d->caRedMultSpinBox = new RDoubleNumInput(d->correctionsSettings); + d->caRedMultSpinBox->setDecimals(1); + d->caRedMultSpinBox->setRange(-4.0, 4.0, 0.1); + d->caRedMultSpinBox->setDefaultValue(0.0); + d->caRedMultSpinBox->setWhatsThis(i18nc("@info:whatsthis", "Red-Green multiplier" + "Set here the amount of correction on red-green axis")); + + d->caBlueMultLabel = new QLabel(i18nc("@label:slider", "Blue-Yellow:"), d->correctionsSettings); + d->caBlueMultSpinBox = new RDoubleNumInput(d->correctionsSettings); + d->caBlueMultSpinBox->setDecimals(1); + d->caBlueMultSpinBox->setRange(-4.0, 4.0, 0.1); + d->caBlueMultSpinBox->setDefaultValue(0.0); + d->caBlueMultSpinBox->setWhatsThis(i18nc("@info:whatsthis", "Blue-Yellow multiplier" + "Set here the amount of correction on blue-yellow axis")); + + correctionsLayout->addWidget(d->noiseReductionLabel, 0, 0, 1, 1); + correctionsLayout->addWidget(d->noiseReductionComboBox, 0, 1, 1, 2); + correctionsLayout->addWidget(d->NRLabel1, 1, 0, 1, 1); + correctionsLayout->addWidget(d->NRSpinBox1, 1, 1, 1, 2); + correctionsLayout->addWidget(d->NRLabel2, 2, 0, 1, 1); + correctionsLayout->addWidget(d->NRSpinBox2, 2, 1, 1, 2); + correctionsLayout->addWidget(d->enableCACorrectionBox, 3, 0, 1, 3); + correctionsLayout->addWidget(d->autoCACorrectionBox, 4, 0, 1, 3); + correctionsLayout->addWidget(d->caRedMultLabel, 5, 0, 1, 1); + correctionsLayout->addWidget(d->caRedMultSpinBox, 5, 1, 1, 2); + correctionsLayout->addWidget(d->caBlueMultLabel, 6, 0, 1, 1); + correctionsLayout->addWidget(d->caBlueMultSpinBox, 6, 1, 1, 2); + correctionsLayout->setRowStretch(7, 10); + correctionsLayout->setSpacing(KDialog::spacingHint()); + correctionsLayout->setMargin(KDialog::spacingHint()); + + addItem(d->correctionsSettings, SmallIcon("kdcraw"), i18nc("@label", "Corrections"), QString("corrections"), false); + + // --------------------------------------------------------------- + // COLOR MANAGEMENT Settings panel + + d->colormanSettings = new QWidget(this); + QGridLayout* const colormanLayout = new QGridLayout(d->colormanSettings); + + d->inputColorSpaceLabel = new QLabel(i18nc("@label:listbox", "Camera Profile:"), d->colormanSettings); + d->inputColorSpaceComboBox = new RComboBox(d->colormanSettings); + d->inputColorSpaceComboBox->insertItem(RawDecodingSettings::NOINPUTCS, i18nc("@item:inlistbox Camera Profile", "None")); + d->inputColorSpaceComboBox->insertItem(RawDecodingSettings::EMBEDDED, i18nc("@item:inlistbox Camera Profile", "Embedded")); + d->inputColorSpaceComboBox->insertItem(RawDecodingSettings::CUSTOMINPUTCS, i18nc("@item:inlistbox Camera Profile", "Custom")); + d->inputColorSpaceComboBox->setDefaultIndex(RawDecodingSettings::NOINPUTCS); + d->inputColorSpaceComboBox->setWhatsThis(i18nc("@info:whatsthis", "Camera Profile" + "Select here the input color space used to decode RAW data." + "None: no " + "input color profile is used during RAW decoding." + "Embedded: use embedded " + "color profile from RAW file, if it exists." + "Custom: use a custom " + "input color space profile.")); + + d->inIccUrlEdit = new KUrlRequester(d->colormanSettings); + d->inIccUrlEdit->setMode(KFile::LocalOnly | KFile::ExistingOnly | KFile::File); + d->inIccUrlEdit->setFilter("*.icc *.icm|"+i18n("ICC Files (*.icc; *.icm)")); + + d->outputColorSpaceLabel = new QLabel(i18nc("@label:listbox", "Workspace:"), d->colormanSettings); + d->outputColorSpaceComboBox = new RComboBox( d->colormanSettings ); + d->outputColorSpaceComboBox->insertItem(RawDecodingSettings::RAWCOLOR, i18nc("@item:inlistbox Workspace", "Raw (no profile)")); + d->outputColorSpaceComboBox->insertItem(RawDecodingSettings::SRGB, i18nc("@item:inlistbox Workspace", "sRGB")); + d->outputColorSpaceComboBox->insertItem(RawDecodingSettings::ADOBERGB, i18nc("@item:inlistbox Workspace", "Adobe RGB")); + d->outputColorSpaceComboBox->insertItem(RawDecodingSettings::WIDEGAMMUT, i18nc("@item:inlistbox Workspace", "Wide Gamut")); + d->outputColorSpaceComboBox->insertItem(RawDecodingSettings::PROPHOTO, i18nc("@item:inlistbox Workspace", "Pro-Photo")); + d->outputColorSpaceComboBox->insertItem(RawDecodingSettings::CUSTOMOUTPUTCS, i18nc("@item:inlistbox Workspace", "Custom")); + d->outputColorSpaceComboBox->setDefaultIndex(RawDecodingSettings::SRGB); + d->outputColorSpaceComboBox->setWhatsThis(i18nc("@info:whatsthis", "Workspace" + "Select here the output color space used to decode RAW data." + "Raw (linear): " + "in this mode, no output color space is used during RAW decoding." + "sRGB: this is an RGB " + "color space, created cooperatively by Hewlett-Packard and " + "Microsoft. It is the best choice for images destined for the Web " + "and portrait photography." + "Adobe RGB: this color " + "space is an extended RGB color space, developed by Adobe. It is " + "used for photography applications such as advertising and fine " + "art." + "Wide Gamut: this color " + "space is an expanded version of the Adobe RGB color space." + "Pro-Photo: this color " + "space is an RGB color space, developed by Kodak, that offers an " + "especially large gamut designed for use with photographic outputs " + "in mind." + "Custom: use a custom " + "output color space profile.")); + + d->outIccUrlEdit = new KUrlRequester(d->colormanSettings); + d->outIccUrlEdit->setMode(KFile::LocalOnly | KFile::File | KFile::ExistingOnly); + d->outIccUrlEdit->setFilter("*.icc *.icm|"+i18n("ICC Files (*.icc; *.icm)")); + + colormanLayout->addWidget(d->inputColorSpaceLabel, 0, 0, 1, 1); + colormanLayout->addWidget(d->inputColorSpaceComboBox, 0, 1, 1, 2); + colormanLayout->addWidget(d->inIccUrlEdit, 1, 0, 1, 3); + colormanLayout->addWidget(d->outputColorSpaceLabel, 2, 0, 1, 1); + colormanLayout->addWidget(d->outputColorSpaceComboBox, 2, 1, 1, 2); + colormanLayout->addWidget(d->outIccUrlEdit, 3, 0, 1, 3); + colormanLayout->setRowStretch(4, 10); + colormanLayout->setSpacing(KDialog::spacingHint()); + colormanLayout->setMargin(KDialog::spacingHint()); + + addItem(d->colormanSettings, SmallIcon("kdcraw"), i18nc("@label", "Color Management"), QString("colormanagement"), false); + + if (! (advSettings & COLORSPACE)) + removeItem(COLORMANAGEMENT); + + addStretch(); + + // --------------------------------------------------------------- + + connect(d->unclipColorComboBox, SIGNAL(activated(int)), + this, SLOT(slotUnclipColorActivated(int))); + + connect(d->whiteBalanceComboBox, SIGNAL(activated(int)), + this, SLOT(slotWhiteBalanceToggled(int))); + + connect(d->noiseReductionComboBox, SIGNAL(activated(int)), + this, SLOT(slotNoiseReductionChanged(int))); + + connect(d->enableCACorrectionBox, SIGNAL(toggled(bool)), + this, SLOT(slotCACorrectionToggled(bool))); + + connect(d->autoCACorrectionBox, SIGNAL(toggled(bool)), + this, SLOT(slotAutoCAToggled(bool))); + + connect(d->blackPointCheckBox, SIGNAL(toggled(bool)), + d->blackPointSpinBox, SLOT(setEnabled(bool))); + + connect(d->whitePointCheckBox, SIGNAL(toggled(bool)), + d->whitePointSpinBox, SLOT(setEnabled(bool))); + + connect(d->sixteenBitsImage, SIGNAL(toggled(bool)), + this, SLOT(slotsixteenBitsImageToggled(bool))); + + connect(dcrawVersion, SIGNAL(leftClickedUrl(QString)), + this, SLOT(processDcrawUrl(QString))); + + connect(d->inputColorSpaceComboBox, SIGNAL(activated(int)), + this, SLOT(slotInputColorSpaceChanged(int))); + + connect(d->outputColorSpaceComboBox, SIGNAL(activated(int)), + this, SLOT(slotOutputColorSpaceChanged(int))); + + connect(d->expoCorrectionBox, SIGNAL(toggled(bool)), + this, SLOT(slotExposureCorrectionToggled(bool))); + + connect(d->expoCorrectionShiftSpinBox, SIGNAL(valueChanged(double)), + this, SLOT(slotExpoCorrectionShiftChanged(double))); + + // Wrapper to emit signal when something is changed in settings. + + connect(d->inIccUrlEdit, SIGNAL(urlSelected(KUrl)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->outIccUrlEdit, SIGNAL(urlSelected(KUrl)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->whiteBalanceComboBox, SIGNAL(activated(int)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->RAWQualityComboBox, SIGNAL(activated(int)), + this, SLOT(slotRAWQualityChanged(int))); + + connect(d->unclipColorComboBox, SIGNAL(activated(int)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->inputColorSpaceComboBox, SIGNAL(activated(int)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->outputColorSpaceComboBox, SIGNAL(activated(int)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->blackPointCheckBox, SIGNAL(toggled(bool)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->whitePointCheckBox, SIGNAL(toggled(bool)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->sixteenBitsImage, SIGNAL(toggled(bool)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->fixColorsHighlightsBox, SIGNAL(toggled(bool)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->autoBrightnessBox, SIGNAL(toggled(bool)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->fourColorCheckBox, SIGNAL(toggled(bool)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->dontStretchPixelsCheckBox, SIGNAL(toggled(bool)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->refineInterpolationBox, SIGNAL(toggled(bool)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->customWhiteBalanceSpinBox, SIGNAL(valueChanged(int)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->reconstructSpinBox, SIGNAL(valueChanged(int)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->blackPointSpinBox, SIGNAL(valueChanged(int)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->whitePointSpinBox, SIGNAL(valueChanged(int)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->NRSpinBox1, SIGNAL(valueChanged(int)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->NRSpinBox2, SIGNAL(valueChanged(int)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->medianFilterPassesSpinBox, SIGNAL(valueChanged(int)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->customWhiteBalanceGreenSpinBox, SIGNAL(valueChanged(double)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->caRedMultSpinBox, SIGNAL(valueChanged(double)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->caBlueMultSpinBox, SIGNAL(valueChanged(double)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->brightnessSpinBox, SIGNAL(valueChanged(double)), + this, SIGNAL(signalSettingsChanged())); + + connect(d->expoCorrectionHighlightSpinBox, SIGNAL(valueChanged(double)), + this, SIGNAL(signalSettingsChanged())); +} + +DcrawSettingsWidget::~DcrawSettingsWidget() +{ + delete d; +} + +void DcrawSettingsWidget::updateMinimumWidth() +{ + int width = 0; + + for (int i = 0; i < count(); i++) + { + if (widget(i)->width() > width) + width = widget(i)->width(); + } + + setMinimumWidth(width); +} + +void DcrawSettingsWidget::processDcrawUrl(const QString& url) +{ + KToolInvocation::self()->invokeBrowser(url); +} + +KUrlRequester* DcrawSettingsWidget::inputProfileUrlEdit() const +{ + return d->inIccUrlEdit; +} + +KUrlRequester* DcrawSettingsWidget::outputProfileUrlEdit() const +{ + return d->outIccUrlEdit; +} + +void DcrawSettingsWidget::resetToDefault() +{ + setSettings(RawDecodingSettings()); +} + +void DcrawSettingsWidget::slotsixteenBitsImageToggled(bool b) +{ + setEnabledBrightnessSettings(!b); + emit signalSixteenBitsImageToggled(d->sixteenBitsImage->isChecked()); +} + +void DcrawSettingsWidget::slotWhiteBalanceToggled(int v) +{ + if (v == 3) + { + d->customWhiteBalanceSpinBox->setEnabled(true); + d->customWhiteBalanceGreenSpinBox->setEnabled(true); + d->customWhiteBalanceLabel->setEnabled(true); + d->customWhiteBalanceGreenLabel->setEnabled(true); + } + else + { + d->customWhiteBalanceSpinBox->setEnabled(false); + d->customWhiteBalanceGreenSpinBox->setEnabled(false); + d->customWhiteBalanceLabel->setEnabled(false); + d->customWhiteBalanceGreenLabel->setEnabled(false); + } +} + +void DcrawSettingsWidget::slotUnclipColorActivated(int v) +{ + if (v == 3) // Reconstruct Highlight method + { + d->reconstructLabel->setEnabled(true); + d->reconstructSpinBox->setEnabled(true); + } + else + { + d->reconstructLabel->setEnabled(false); + d->reconstructSpinBox->setEnabled(false); + } +} + +void DcrawSettingsWidget::slotNoiseReductionChanged(int item) +{ + d->NRSpinBox1->setEnabled(true); + d->NRLabel1->setEnabled(true); + d->NRSpinBox2->setEnabled(true); + d->NRLabel2->setEnabled(true); + d->NRLabel1->setText(i18nc("@label", "Threshold:")); + d->NRSpinBox1->setWhatsThis(i18nc("@info:whatsthis", "Threshold" + "Set here the noise reduction threshold value to use.")); + + switch(item) + { + case RawDecodingSettings::WAVELETSNR: + case RawDecodingSettings::FBDDNR: + case RawDecodingSettings::LINENR: + d->NRSpinBox2->setVisible(false); + d->NRLabel2->setVisible(false); + break; + + case RawDecodingSettings::IMPULSENR: + d->NRLabel1->setText(i18nc("@label", "Luminance:")); + d->NRSpinBox1->setWhatsThis(i18nc("@info:whatsthis", "Luminance" + "Amount of Luminance impulse noise reduction.")); + d->NRLabel2->setText(i18nc("@label", "Chrominance:")); + d->NRSpinBox2->setWhatsThis(i18nc("@info:whatsthis", "Chrominance" + "Amount of Chrominance impulse noise reduction.")); + d->NRSpinBox2->setVisible(true); + d->NRLabel2->setVisible(true); + break; + + default: + d->NRSpinBox1->setEnabled(false); + d->NRLabel1->setEnabled(false); + d->NRSpinBox2->setEnabled(false); + d->NRLabel2->setEnabled(false); + d->NRSpinBox2->setVisible(false); + d->NRLabel2->setVisible(false); + break; + } + + emit signalSettingsChanged(); +} + +void DcrawSettingsWidget::slotCACorrectionToggled(bool b) +{ + d->autoCACorrectionBox->setEnabled(b); + slotAutoCAToggled(d->autoCACorrectionBox->isChecked()); +} + +void DcrawSettingsWidget::slotAutoCAToggled(bool b) +{ + if (b) + { + d->caRedMultSpinBox->setValue(0.0); + d->caBlueMultSpinBox->setValue(0.0); + } + + bool mult = (!b) && (d->autoCACorrectionBox->isEnabled()); + d->caRedMultSpinBox->setEnabled(mult); + d->caBlueMultSpinBox->setEnabled(mult); + d->caRedMultLabel->setEnabled(mult); + d->caBlueMultLabel->setEnabled(mult); + emit signalSettingsChanged(); +} + +void DcrawSettingsWidget::slotExposureCorrectionToggled(bool b) +{ + d->expoCorrectionShiftLabel->setEnabled(b); + d->expoCorrectionShiftSpinBox->setEnabled(b); + d->expoCorrectionHighlightLabel->setEnabled(b); + d->expoCorrectionHighlightSpinBox->setEnabled(b); + + slotExpoCorrectionShiftChanged(d->expoCorrectionShiftSpinBox->value()); +} + +void DcrawSettingsWidget::slotExpoCorrectionShiftChanged(double ev) +{ + // Only enable Highligh exposure correction if Shift correction is >= 1.0, else this settings do not take effect. + bool b = (ev >= 1.0); + + d->expoCorrectionHighlightLabel->setEnabled(b); + d->expoCorrectionHighlightSpinBox->setEnabled(b); + + emit signalSettingsChanged(); +} + +void DcrawSettingsWidget::slotInputColorSpaceChanged(int item) +{ + d->inIccUrlEdit->setEnabled(item == RawDecodingSettings::CUSTOMINPUTCS); +} + +void DcrawSettingsWidget::slotOutputColorSpaceChanged(int item) +{ + d->outIccUrlEdit->setEnabled(item == RawDecodingSettings::CUSTOMOUTPUTCS); +} + +void DcrawSettingsWidget::slotRAWQualityChanged(int quality) +{ + switch(quality) + { + case RawDecodingSettings::DCB: + case RawDecodingSettings::VCD_AHD: + // These options can be only avaialble if Libraw use GPL2 pack. + d->medianFilterPassesLabel->setEnabled(KDcraw::librawUseGPL2DemosaicPack()); + d->medianFilterPassesSpinBox->setEnabled(KDcraw::librawUseGPL2DemosaicPack()); + d->refineInterpolationBox->setEnabled(KDcraw::librawUseGPL2DemosaicPack()); + break; + + case RawDecodingSettings::PL_AHD: + case RawDecodingSettings::AFD: + case RawDecodingSettings::VCD: + case RawDecodingSettings::LMMSE: + case RawDecodingSettings::AMAZE: + d->medianFilterPassesLabel->setEnabled(false); + d->medianFilterPassesSpinBox->setEnabled(false); + d->refineInterpolationBox->setEnabled(false); + break; + + default: // BILINEAR, VNG, PPG, AHD + d->medianFilterPassesLabel->setEnabled(true); + d->medianFilterPassesSpinBox->setEnabled(true); + d->refineInterpolationBox->setEnabled(false); + break; + } + + emit signalSettingsChanged(); +} + +void DcrawSettingsWidget::setEnabledBrightnessSettings(bool b) +{ + d->brightnessLabel->setEnabled(b); + d->brightnessSpinBox->setEnabled(b); +} + +bool DcrawSettingsWidget::brightnessSettingsIsEnabled() const +{ + return d->brightnessSpinBox->isEnabled(); +} + +void DcrawSettingsWidget::setSettings(const RawDecodingSettings& settings) +{ + d->sixteenBitsImage->setChecked(settings.sixteenBitsImage); + + switch(settings.whiteBalance) + { + case RawDecodingSettings::CAMERA: + d->whiteBalanceComboBox->setCurrentIndex(1); + break; + case RawDecodingSettings::AUTO: + d->whiteBalanceComboBox->setCurrentIndex(2); + break; + case RawDecodingSettings::CUSTOM: + d->whiteBalanceComboBox->setCurrentIndex(3); + break; + default: + d->whiteBalanceComboBox->setCurrentIndex(0); + break; + } + slotWhiteBalanceToggled(d->whiteBalanceComboBox->currentIndex()); + + d->customWhiteBalanceSpinBox->setValue(settings.customWhiteBalance); + d->customWhiteBalanceGreenSpinBox->setValue(settings.customWhiteBalanceGreen); + d->fourColorCheckBox->setChecked(settings.RGBInterpolate4Colors); + d->autoBrightnessBox->setChecked(settings.autoBrightness); + d->fixColorsHighlightsBox->setChecked(settings.fixColorsHighlights); + + switch(settings.unclipColors) + { + case 0: + d->unclipColorComboBox->setCurrentIndex(0); + break; + case 1: + d->unclipColorComboBox->setCurrentIndex(1); + break; + case 2: + d->unclipColorComboBox->setCurrentIndex(2); + break; + default: // Reconstruct Highlight method + d->unclipColorComboBox->setCurrentIndex(3); + d->reconstructSpinBox->setValue(settings.unclipColors-3); + break; + } + slotUnclipColorActivated(d->unclipColorComboBox->currentIndex()); + + d->dontStretchPixelsCheckBox->setChecked(settings.DontStretchPixels); + d->brightnessSpinBox->setValue(settings.brightness); + d->blackPointCheckBox->setChecked(settings.enableBlackPoint); + d->blackPointSpinBox->setEnabled(settings.enableBlackPoint); + d->blackPointSpinBox->setValue(settings.blackPoint); + d->whitePointCheckBox->setChecked(settings.enableWhitePoint); + d->whitePointSpinBox->setEnabled(settings.enableWhitePoint); + d->whitePointSpinBox->setValue(settings.whitePoint); + + int q = settings.RAWQuality; + + // If Libraw do not support GPL2 pack, reset to BILINEAR. + if (!KDcraw::librawUseGPL2DemosaicPack()) + { + for (int i=RawDecodingSettings::DCB ; i <=RawDecodingSettings::LMMSE ; ++i) + { + if (q == i) + { + q = RawDecodingSettings::BILINEAR; + kDebug() << "Libraw GPL2 pack not avaialble. Raw quality set to Bilinear"; + break; + } + } + } + + // If Libraw do not support GPL3 pack, reset to BILINEAR. + if (!KDcraw::librawUseGPL3DemosaicPack() && (q == RawDecodingSettings::AMAZE)) + { + q = RawDecodingSettings::BILINEAR; + kDebug() << "Libraw GPL3 pack not avaialble. Raw quality set to Bilinear"; + } + + d->RAWQualityComboBox->setCurrentIndex(q); + + switch(q) + { + case RawDecodingSettings::DCB: + d->medianFilterPassesSpinBox->setValue(settings.dcbIterations); + d->refineInterpolationBox->setChecked(settings.dcbEnhanceFl); + break; + case RawDecodingSettings::VCD_AHD: + d->medianFilterPassesSpinBox->setValue(settings.eeciRefine); + d->refineInterpolationBox->setChecked(settings.eeciRefine); + break; + default: + d->medianFilterPassesSpinBox->setValue(settings.medianFilterPasses); + d->refineInterpolationBox->setChecked(false); // option not used. + break; + } + + slotRAWQualityChanged(q); + + d->inputColorSpaceComboBox->setCurrentIndex((int)settings.inputColorSpace); + slotInputColorSpaceChanged((int)settings.inputColorSpace); + d->outputColorSpaceComboBox->setCurrentIndex((int)settings.outputColorSpace); + slotOutputColorSpaceChanged((int)settings.outputColorSpace); + + d->noiseReductionComboBox->setCurrentIndex(settings.NRType); + slotNoiseReductionChanged(settings.NRType); + d->NRSpinBox1->setValue(settings.NRThreshold); + d->NRSpinBox2->setValue(settings.NRChroThreshold); + + d->enableCACorrectionBox->setChecked(settings.enableCACorrection); + d->caRedMultSpinBox->setValue(settings.caMultiplier[0]); + d->caBlueMultSpinBox->setValue(settings.caMultiplier[1]); + d->autoCACorrectionBox->setChecked((settings.caMultiplier[0] == 0.0) && (settings.caMultiplier[1] == 0.0)); + slotCACorrectionToggled(settings.enableCACorrection); + + d->expoCorrectionBox->setChecked(settings.expoCorrection); + slotExposureCorrectionToggled(settings.expoCorrection); + d->expoCorrectionShiftSpinBox->setValue(d->shiftExpoFromLinearToEv(settings.expoCorrectionShift)); + d->expoCorrectionHighlightSpinBox->setValue(settings.expoCorrectionHighlight); + + d->inIccUrlEdit->setUrl(KUrl(settings.inputProfile)); + d->outIccUrlEdit->setUrl(KUrl(settings.outputProfile)); +} + +RawDecodingSettings DcrawSettingsWidget::settings() const +{ + RawDecodingSettings prm; + prm.sixteenBitsImage = d->sixteenBitsImage->isChecked(); + + switch(d->whiteBalanceComboBox->currentIndex()) + { + case 1: + prm.whiteBalance = RawDecodingSettings::CAMERA; + break; + case 2: + prm.whiteBalance = RawDecodingSettings::AUTO; + break; + case 3: + prm.whiteBalance = RawDecodingSettings::CUSTOM; + break; + default: + prm.whiteBalance = RawDecodingSettings::NONE; + break; + } + + prm.customWhiteBalance = d->customWhiteBalanceSpinBox->value(); + prm.customWhiteBalanceGreen = d->customWhiteBalanceGreenSpinBox->value(); + prm.RGBInterpolate4Colors = d->fourColorCheckBox->isChecked(); + prm.autoBrightness = d->autoBrightnessBox->isChecked(); + prm.fixColorsHighlights = d->fixColorsHighlightsBox->isChecked(); + + switch(d->unclipColorComboBox->currentIndex()) + { + case 0: + prm.unclipColors = 0; + break; + case 1: + prm.unclipColors = 1; + break; + case 2: + prm.unclipColors = 2; + break; + default: // Reconstruct Highlight method + prm.unclipColors = d->reconstructSpinBox->value()+3; + break; + } + + prm.DontStretchPixels = d->dontStretchPixelsCheckBox->isChecked(); + prm.brightness = d->brightnessSpinBox->value(); + prm.enableBlackPoint = d->blackPointCheckBox->isChecked(); + prm.blackPoint = d->blackPointSpinBox->value(); + prm.enableWhitePoint = d->whitePointCheckBox->isChecked(); + prm.whitePoint = d->whitePointSpinBox->value(); + + prm.RAWQuality = (RawDecodingSettings::DecodingQuality)d->RAWQualityComboBox->currentIndex(); + switch(prm.RAWQuality) + { + case RawDecodingSettings::DCB: + prm.dcbIterations = d->medianFilterPassesSpinBox->value(); + prm.dcbEnhanceFl = d->refineInterpolationBox->isChecked(); + break; + case RawDecodingSettings::VCD_AHD: + prm.esMedPasses = d->medianFilterPassesSpinBox->value(); + prm.eeciRefine = d->refineInterpolationBox->isChecked(); + break; + default: + prm.medianFilterPasses = d->medianFilterPassesSpinBox->value(); + break; + } + + prm.NRType = (RawDecodingSettings::NoiseReduction)d->noiseReductionComboBox->currentIndex(); + switch (prm.NRType) + { + case RawDecodingSettings::NONR: + { + prm.NRThreshold = 0; + prm.NRChroThreshold = 0; + break; + } + case RawDecodingSettings::WAVELETSNR: + case RawDecodingSettings::FBDDNR: + case RawDecodingSettings::LINENR: + { + prm.NRThreshold = d->NRSpinBox1->value(); + prm.NRChroThreshold = 0; + break; + } + default: // IMPULSENR + { + prm.NRThreshold = d->NRSpinBox1->value(); + prm.NRChroThreshold = d->NRSpinBox2->value(); + break; + } + } + + prm.enableCACorrection = d->enableCACorrectionBox->isChecked(); + prm.caMultiplier[0] = d->caRedMultSpinBox->value(); + prm.caMultiplier[1] = d->caBlueMultSpinBox->value(); + + prm.expoCorrection = d->expoCorrectionBox->isChecked(); + prm.expoCorrectionShift = d->shiftExpoFromEvToLinear(d->expoCorrectionShiftSpinBox->value()); + prm.expoCorrectionHighlight = d->expoCorrectionHighlightSpinBox->value(); + + prm.inputColorSpace = (RawDecodingSettings::InputColorSpace)(d->inputColorSpaceComboBox->currentIndex()); + prm.outputColorSpace = (RawDecodingSettings::OutputColorSpace)(d->outputColorSpaceComboBox->currentIndex()); + prm.inputProfile = d->inIccUrlEdit->url().toLocalFile(); + prm.outputProfile = d->outIccUrlEdit->url().toLocalFile(); + + return prm; +} + +void DcrawSettingsWidget::writeSettings(KConfigGroup& group) +{ + RawDecodingSettings prm = settings(); + prm.writeSettings(group); + RExpanderBox::writeSettings(group); +} + +void DcrawSettingsWidget::readSettings(KConfigGroup& group) +{ + RawDecodingSettings prm; + prm.readSettings(group); + setSettings(prm); + RExpanderBox::readSettings(group); +} + +} // NameSpace KDcrawIface diff --git a/libkdcraw/libkdcraw/dcrawsettingswidget.h b/libkdcraw/libkdcraw/dcrawsettingswidget.h new file mode 100644 index 00000000..0e0711c6 --- /dev/null +++ b/libkdcraw/libkdcraw/dcrawsettingswidget.h @@ -0,0 +1,127 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-09-13 + * @brief LibRaw settings widgets + * + * @author Copyright (C) 2006-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2011 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * @author Copyright (C) 2007-2008 by Guillaume Castagnino + * casta at xwing dot info + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef DCRAW_SETTINGS_WIDGET_H +#define DCRAW_SETTINGS_WIDGET_H + +// Qt includes + +#include + +// KDE includes + +#include +#include + +// Local includes + +#include "libkdcraw_export.h" +#include "rawdecodingsettings.h" +#include "rexpanderbox.h" + +namespace KDcrawIface +{ + +class LIBKDCRAW_EXPORT DcrawSettingsWidget : public RExpanderBox +{ + Q_OBJECT + +public: + + enum AdvancedSettingsOptions + { + SIXTEENBITS = 0x00000001, + COLORSPACE = 0x00000002, + POSTPROCESSING = 0x00000004, + BLACKWHITEPOINTS = 0x00000008 + }; + + enum SettingsTabs + { + DEMOSAICING = 0, + WHITEBALANCE, + CORRECTIONS, + COLORMANAGEMENT + }; + +public: + + /** + * @param advSettings the default value is COLORSPACE + */ + explicit DcrawSettingsWidget(QWidget* const parent, int advSettings = COLORSPACE); + virtual ~DcrawSettingsWidget(); + + KUrlRequester* inputProfileUrlEdit() const; + KUrlRequester* outputProfileUrlEdit() const; + + void setup(int advSettings); + + void setEnabledBrightnessSettings(bool b); + bool brightnessSettingsIsEnabled() const; + + void updateMinimumWidth(); + + void resetToDefault(); + + void setSettings(const RawDecodingSettings& settings); + RawDecodingSettings settings() const; + + void readSettings(KConfigGroup& group); + void writeSettings(KConfigGroup& group); + +Q_SIGNALS: + + void signalSixteenBitsImageToggled(bool); + void signalSettingsChanged(); + +private Q_SLOTS: + + void slotWhiteBalanceToggled(int); + void slotsixteenBitsImageToggled(bool); + void slotUnclipColorActivated(int); + void slotNoiseReductionChanged(int); + void slotCACorrectionToggled(bool); + void slotExposureCorrectionToggled(bool); + void slotAutoCAToggled(bool); + void processDcrawUrl(const QString&); + void slotInputColorSpaceChanged(int); + void slotOutputColorSpaceChanged(int); + void slotRAWQualityChanged(int); + void slotExpoCorrectionShiftChanged(double); + +private: + + class Private; + Private* const d; +}; + +} // NameSpace KDcrawIface + +#endif /* DCRAW_SETTINGS_WIDGET_H */ diff --git a/libkdcraw/libkdcraw/kdcraw.cpp b/libkdcraw/libkdcraw/kdcraw.cpp new file mode 100644 index 00000000..69a278c2 --- /dev/null +++ b/libkdcraw/libkdcraw/kdcraw.cpp @@ -0,0 +1,582 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-12-09 + * @brief a tread-safe libraw C++ program interface + * + * @author Copyright (C) 2006-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2013 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * @author Copyright (C) 2007-2008 by Guillaume Castagnino + * casta at xwing dot info + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "moc_kdcraw.cpp" +#include "kdcraw_p.h" + +// Qt includes + +#include +#include +#include + +// KDE includes + +#include + +// LibRaw includes + +#include + +#ifdef LIBRAW_HAS_CONFIG +#include +#endif + +// Local includes + +#include "version.h" +#include "rawfiles.h" + +static const KCatalogLoader loader("libkdcraw"); + +namespace KDcrawIface +{ + +KDcraw::KDcraw() + : d(new Private(this)) +{ + m_cancel = false; +} + +KDcraw::~KDcraw() +{ + cancel(); + delete d; +} + +QString KDcraw::version() +{ + return QString(kdcraw_version); +} + +void KDcraw::cancel() +{ + m_cancel = true; +} + +bool KDcraw::loadRawPreview(QImage& image, const QString& path) +{ + // In first, try to extract the embedded JPEG preview. Very fast. + bool ret = loadEmbeddedPreview(image, path); + + if (ret) + return true; + + // In second, decode and half size of RAW picture. More slow. + return (loadHalfPreview(image, path)); +} + +bool KDcraw::loadEmbeddedPreview(QImage& image, const QString& path) +{ + QByteArray imgData; + + if ( loadEmbeddedPreview(imgData, path) ) + { + kDebug() << "Preview data size:" << imgData.size(); + + if (image.loadFromData( imgData )) + { + kDebug() << "Using embedded RAW preview extraction"; + return true; + } + } + + kDebug() << "Failed to load embedded RAW preview"; + return false; +} + +bool KDcraw::loadEmbeddedPreview(QByteArray& imgData, const QString& path) +{ + QFileInfo fileInfo(path); + QString rawFilesExt(rawFiles()); + QString ext = fileInfo.suffix().toUpper(); + + if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext)) + return false; + + LibRaw raw; + + int ret = raw.open_file(QFile::encodeName(path)); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run open_file: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + return (Private::loadEmbeddedPreview(imgData, raw)); +} + +bool KDcraw::loadEmbeddedPreview(QByteArray& imgData, const QBuffer& buffer) +{ + QString rawFilesExt(KDcrawIface::KDcraw::rawFiles()); + LibRaw raw; + + QByteArray inData = buffer.data(); + int ret = raw.open_buffer((void*) inData.data(), (size_t) inData.size()); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run open_buffer: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + return (Private::loadEmbeddedPreview(imgData, raw)); +} + +bool KDcraw::loadHalfPreview(QImage& image, const QString& path) +{ + QFileInfo fileInfo(path); + QString rawFilesExt(rawFiles()); + QString ext = fileInfo.suffix().toUpper(); + + if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext)) + return false; + + kDebug() << "Try to use reduced RAW picture extraction"; + + LibRaw raw; + raw.imgdata.params.use_auto_wb = 1; // Use automatic white balance. + raw.imgdata.params.use_camera_wb = 1; // Use camera white balance, if possible. + raw.imgdata.params.half_size = 1; // Half-size color image (3x faster than -q). + + int ret = raw.open_file(QFile::encodeName(path)); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run open_file: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + + if(!Private::loadHalfPreview(image, raw)) + { + kDebug() << "Failed to get half preview from LibRaw!"; + return false; + } + + kDebug() << "Using reduced RAW picture extraction"; + + return true; +} + +bool KDcraw::loadHalfPreview(QByteArray& imgData, const QString& path) +{ + QFileInfo fileInfo(path); + QString rawFilesExt(rawFiles()); + QString ext = fileInfo.suffix().toUpper(); + + if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext)) + return false; + + kDebug() << "Try to use reduced RAW picture extraction"; + + LibRaw raw; + int ret = raw.open_file(QFile::encodeName(path)); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run dcraw_process: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + QImage image; + + if (!Private::loadHalfPreview(image, raw)) + { + kDebug() << "KDcraw: failed to get half preview: " << libraw_strerror(ret); + return false; + } + + QBuffer buffer(&imgData); + buffer.open(QIODevice::WriteOnly); + image.save(&buffer, "JPEG"); + + return true; +} + +bool KDcraw::loadHalfPreview(QByteArray& imgData, const QBuffer& inBuffer) +{ + QString rawFilesExt(KDcrawIface::KDcraw::rawFiles()); + LibRaw raw; + + QByteArray inData = inBuffer.data(); + int ret = raw.open_buffer((void*) inData.data(), (size_t) inData.size()); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run dcraw_make_mem_image: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + QImage image; + + if (!Private::loadHalfPreview(image, raw)) + { + kDebug() << "KDcraw: failed to get half preview: " << libraw_strerror(ret); + return false; + } + + QBuffer buffer(&imgData); + buffer.open(QIODevice::WriteOnly); + image.save(&buffer, "JPG"); + + return true; +} + +bool KDcraw::loadFullImage(QImage& image, const QString& path, const RawDecodingSettings& settings) +{ + QFileInfo fileInfo(path); + QString rawFilesExt(rawFiles()); + QString ext = fileInfo.suffix().toUpper(); + + if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext)) + return false; + + kDebug() << "Try to load full RAW picture..."; + + RawDecodingSettings prm = settings; + prm.sixteenBitsImage = false; + QByteArray imgData; + int width, height, rgbmax; + + KDcraw decoder; + bool ret = decoder.decodeRAWImage(path, prm, imgData, width, height, rgbmax); + + if (!ret) + { + kDebug() << "Failled to load full RAW picture"; + return false; + } + + uchar* sptr = (uchar*)imgData.data(); + uchar tmp8[2]; + + // Set RGB color components. + for (int i = 0 ; i < width * height ; ++i) + { + // Swap Red and Blue + tmp8[0] = sptr[2]; + tmp8[1] = sptr[0]; + sptr[0] = tmp8[0]; + sptr[2] = tmp8[1]; + + sptr += 3; + } + + image = QImage(width, height, QImage::Format_ARGB32); + uint* dptr = reinterpret_cast(image.bits()); + sptr = (uchar*)imgData.data(); + + for (int i = 0 ; i < width * height ; ++i) + { + *dptr++ = qRgba(sptr[2], sptr[1], sptr[0], 0xFF); + sptr += 3; + } + + kDebug() << "Load full RAW picture done"; + + return true; +} + +bool KDcraw::rawFileIdentify(DcrawInfoContainer& identify, const QString& path) +{ + QFileInfo fileInfo(path); + QString rawFilesExt(rawFiles()); + QString ext = fileInfo.suffix().toUpper(); + identify.isDecodable = false; + + if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext)) + return false; + + LibRaw raw; + + int ret = raw.open_file(QFile::encodeName(path)); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run open_file: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + ret = raw.adjust_sizes_info_only(); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run adjust_sizes_info_only: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + Private::fillIndentifyInfo(&raw, identify); + raw.recycle(); + return true; +} + +// ---------------------------------------------------------------------------------- + +bool KDcraw::extractRAWData(const QString& filePath, QByteArray& rawData, DcrawInfoContainer& identify, unsigned int shotSelect) +{ + QFileInfo fileInfo(filePath); + QString rawFilesExt(rawFiles()); + QString ext = fileInfo.suffix().toUpper(); + identify.isDecodable = false; + + if (!fileInfo.exists() || ext.isEmpty() || !rawFilesExt.toUpper().contains(ext)) + return false; + + if (m_cancel) + return false; + + d->setProgress(0.1); + + LibRaw raw; + // Set progress call back function. + raw.set_progress_handler(callbackForLibRaw, d); + + int ret = raw.open_file(QFile::encodeName(filePath)); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run open_file: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + if (m_cancel) + { + raw.recycle(); + return false; + } + + d->setProgress(0.3); + + raw.imgdata.params.output_bps = 16; + raw.imgdata.params.shot_select = shotSelect; + ret = raw.unpack(); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run unpack: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + if (m_cancel) + { + raw.recycle(); + return false; + } + + d->setProgress(0.4); + + ret = raw.raw2image(); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run raw2image: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + if (m_cancel) + { + raw.recycle(); + return false; + } + + d->setProgress(0.6); + + Private::fillIndentifyInfo(&raw, identify); + + if (m_cancel) + { + raw.recycle(); + return false; + } + + d->setProgress(0.8); + + rawData = QByteArray(); + + if (raw.imgdata.idata.filters == 0) + { + rawData.resize((int)(raw.imgdata.sizes.iwidth * raw.imgdata.sizes.iheight * raw.imgdata.idata.colors * sizeof(unsigned short))); + + unsigned short* output = reinterpret_cast(rawData.data()); + + for (unsigned int row = 0; row < raw.imgdata.sizes.iheight; row++) + { + for (unsigned int col = 0; col < raw.imgdata.sizes.iwidth; col++) + { + for (int color = 0; color < raw.imgdata.idata.colors; color++) + { + *output = raw.imgdata.image[raw.imgdata.sizes.iwidth*row + col][color]; + output++; + } + } + } + } + else + { + rawData.resize((int)(raw.imgdata.sizes.iwidth * raw.imgdata.sizes.iheight * sizeof(unsigned short))); + + unsigned short* output = reinterpret_cast(rawData.data()); + + for (uint row = 0; row < raw.imgdata.sizes.iheight; row++) + { + for (uint col = 0; col < raw.imgdata.sizes.iwidth; col++) + { + *output = raw.imgdata.image[raw.imgdata.sizes.iwidth*row + col][raw.COLOR(row, col)]; + output++; + } + } + } + + raw.recycle(); + d->setProgress(1.0); + + return true; +} + +bool KDcraw::decodeHalfRAWImage(const QString& filePath, const RawDecodingSettings& rawDecodingSettings, + QByteArray& imageData, int& width, int& height, int& rgbmax) +{ + m_rawDecodingSettings = rawDecodingSettings; + m_rawDecodingSettings.halfSizeColorImage = true; + return (d->loadFromLibraw(filePath, imageData, width, height, rgbmax)); +} + +bool KDcraw::decodeRAWImage(const QString& filePath, const RawDecodingSettings& rawDecodingSettings, + QByteArray& imageData, int& width, int& height, int& rgbmax) +{ + m_rawDecodingSettings = rawDecodingSettings; + return (d->loadFromLibraw(filePath, imageData, width, height, rgbmax)); +} + +bool KDcraw::checkToCancelWaitingData() +{ + return m_cancel; +} + +void KDcraw::setWaitingDataProgress(double) +{ +} + +const char* KDcraw::rawFiles() +{ + return raw_file_extentions; +} + +QStringList KDcraw::rawFilesList() +{ + QString string = QString::fromLatin1(rawFiles()); + return string.remove("*.").split(' '); +} + +int KDcraw::rawFilesVersion() +{ + return raw_file_extensions_version; +} + +QStringList KDcraw::supportedCamera() +{ + QStringList camera; + const char** const list = LibRaw::cameraList(); + + for (int i = 0; i < LibRaw::cameraCount(); i++) + camera.append(list[i]); + + return camera; +} + +QString KDcraw::librawVersion() +{ + return QString(LIBRAW_VERSION_STR).remove("-Release"); +} + +int KDcraw::librawUseGomp() +{ +#ifdef LIBRAW_HAS_CONFIG +# ifdef LIBRAW_USE_OPENMP + return true; +# else + return false; +# endif +#else + return -1; +#endif +} + +int KDcraw::librawUseRawSpeed() +{ +#ifdef LIBRAW_HAS_CONFIG +# ifdef LIBRAW_USE_RAWSPEED + return true; +# else + return false; +# endif +#else + return -1; +#endif +} + +int KDcraw::librawUseGPL2DemosaicPack() +{ +#ifdef LIBRAW_HAS_CONFIG +# ifdef LIBRAW_USE_DEMOSAIC_PACK_GPL2 + return true; +# else + return false; +# endif +#else + return -1; +#endif +} + +int KDcraw::librawUseGPL3DemosaicPack() +{ +#ifdef LIBRAW_HAS_CONFIG +# ifdef LIBRAW_USE_DEMOSAIC_PACK_GPL3 + return true; +# else + return false; +# endif +#else + return -1; +#endif +} + +} // namespace KDcrawIface diff --git a/libkdcraw/libkdcraw/kdcraw.h b/libkdcraw/libkdcraw/kdcraw.h new file mode 100644 index 00000000..281dbe72 --- /dev/null +++ b/libkdcraw/libkdcraw/kdcraw.h @@ -0,0 +1,267 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-12-09 + * @brief a tread-safe libraw C++ program interface + * + * @author Copyright (C) 2006-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2013 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * @author Copyright (C) 2007-2008 by Guillaume Castagnino + * casta at xwing dot info + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef KDCRAW_H +#define KDCRAW_H + +// C++ includes + +#include + +// Qt includes + +#include +#include +#include +#include + +// Local includes + +#include "libkdcraw_export.h" +#include "rawdecodingsettings.h" +#include "dcrawinfocontainer.h" + +/** @brief Main namespace of libKDcraw + */ +namespace KDcrawIface +{ + +class LIBKDCRAW_EXPORT KDcraw : public QObject +{ + Q_OBJECT + +public: + + /** Standard constructor. + */ + KDcraw(); + + /** Standard destructor. + */ + virtual ~KDcraw(); + +public: + + /** Return a string version of libkdcraw release + */ + static QString version(); + + /** Get the preview of RAW picture as a QImage. + It tries loadEmbeddedPreview() first and if it fails, calls loadHalfPreview(). + */ + static bool loadRawPreview(QImage& image, const QString& path); + + /** Get the preview of RAW picture as a QByteArray holding JPEG data. + It tries loadEmbeddedPreview() first and if it fails, calls loadHalfPreview(). + */ + static bool loadRawPreview(QByteArray& imgData, const QString& path); + + /** Get the preview of RAW picture passed in QBuffer as a QByteArray holding JPEG data. + It tries loadEmbeddedPreview() first and if it fails, calls loadHalfPreview(). + */ + static bool loadRawPreview(QByteArray& imgData, const QBuffer& inBuffer); + + /** Get the embedded JPEG preview image from RAW picture as a QByteArray which will include Exif Data. + This is fast and non cancelable. This method does not require a class instance to run. + */ + static bool loadEmbeddedPreview(QByteArray& imgData, const QString& path); + + /** Get the embedded JPEG preview image from RAW picture as a QImage. This is fast and non cancelable + This method does not require a class instance to run. + */ + static bool loadEmbeddedPreview(QImage& image, const QString& path); + + /** Get the embedded JPEG preview image from RAW image passed in QBuffer as a QByteArray which will include Exif Data. + This is fast and non cancelable. This method does not require a class instance to run. + */ + static bool loadEmbeddedPreview(QByteArray& imgData, const QBuffer& inBuffer); + + /** Get the half decoded RAW picture. This is slower than loadEmbeddedPreview() method + and non cancelable. This method does not require a class instance to run. + */ + static bool loadHalfPreview(QImage& image, const QString& path); + + /** Get the half decoded RAW picture as JPEG data in QByteArray. This is slower than loadEmbeddedPreview() + method and non cancelable. This method does not require a class instance to run. + */ + static bool loadHalfPreview(QByteArray& imgData, const QString& path); + + /** Get the half decoded RAW picture passed in QBuffer as JPEG data in QByteArray. This is slower than loadEmbeddedPreview() + method and non cancelable. This method does not require a class instance to run. + */ + static bool loadHalfPreview(QByteArray& imgData, const QBuffer& inBuffer); + + /** Get the full decoded RAW picture. This is a more slower than loadHalfPreview() method + and non cancelable. This method does not require a class instance to run. + */ + static bool loadFullImage(QImage& image, const QString& path, const RawDecodingSettings& settings = RawDecodingSettings()); + + /** Get the camera settings witch have taken RAW file. Look into dcrawinfocontainer.h + for more details. This is a fast and non cancelable method witch do not require + a class instance to run. + */ + static bool rawFileIdentify(DcrawInfoContainer& identify, const QString& path); + + /** Return the string of all RAW file type mime supported. + */ + static const char* rawFiles(); + + /** Return the list of all RAW file type mime supported, + as a QStringList, without wildcard and suffix dot. + */ + static QStringList rawFilesList(); + + /** Returns a version number for the list of supported RAW file types. + This version is incremented if the list of supported formats has changed + between library releases. + */ + static int rawFilesVersion(); + + /** Provide a list of supported RAW Camera name. + */ + static QStringList supportedCamera(); + + /** Return LibRaw version string. + */ + static QString librawVersion(); + + /** Return true or false if LibRaw use parallel demosaicing or not (libgomp support). + * Return -1 if undefined. + */ + static int librawUseGomp(); + + /** Return true or false if LibRaw use RawSpeed codec or not. + * Return -1 if undefined. + */ + static int librawUseRawSpeed(); + + /** Return true or false if LibRaw use Demosaic Pack GPL2 or not. + * Return -1 if undefined. + */ + static int librawUseGPL2DemosaicPack(); + + /** Return true or false if LibRaw use Demosaic Pack GPL3 or not. + * Return -1 if undefined. + */ + static int librawUseGPL3DemosaicPack(); + +public: + + /** Extract Raw image data undemosaiced and without post processing from 'filePath' picture file. + This is a cancelable method which require a class instance to run because RAW pictures loading + can take a while. + + This method return: + + - A byte array container 'rawData' with raw data. + - All info about Raw image into 'identify' container. + - 'false' is returned if loadding failed, else 'true'. + */ + bool extractRAWData(const QString& filePath, QByteArray& rawData, DcrawInfoContainer& identify, unsigned int shotSelect=0); + + /** Extract a small size of decode RAW data from 'filePath' picture file using + 'rawDecodingSettings' settings. This is a cancelable method which require + a class instance to run because RAW pictures decoding can take a while. + + This method return: + + - A byte array container 'imageData' with picture data. Pixels order is RGB. + Color depth can be 8 or 16. In 8 bits you can access to color component + using (uchar*), in 16 bits using (ushort*). + + - Size size of image in number of pixels ('width' and 'height'). + - The max average of RGB components from decoded picture. + - 'false' is returned if decoding failed, else 'true'. + */ + bool decodeHalfRAWImage(const QString& filePath, const RawDecodingSettings& rawDecodingSettings, + QByteArray& imageData, int& width, int& height, int& rgbmax); + + /** Extract a full size of RAW data from 'filePath' picture file using + 'rawDecodingSettings' settings. This is a cancelable method which require + a class instance to run because RAW pictures decoding can take a while. + + This method return: + + - A byte array container 'imageData' with picture data. Pixels order is RGB. + Color depth can be 8 or 16. In 8 bits you can access to color component + using (uchar*), in 16 bits using (ushort*). + + - Size size of image in number of pixels ('width' and 'height'). + - The max average of RGB components from decoded picture. + - 'false' is returned if decoding failed, else 'true'. + */ + bool decodeRAWImage(const QString& filePath, const RawDecodingSettings& rawDecodingSettings, + QByteArray& imageData, int& width, int& height, int& rgbmax); + + /** To cancel 'decodeHalfRAWImage' and 'decodeRAWImage' methods running + in a separate thread. + */ + void cancel(); + +protected: + + /** Used internally to cancel RAW decoding operation. Normally, you don't need to use it + directly, excepted if you derivated this class. Usual way is to use cancel() method + */ + bool m_cancel; + + /** The settings container used to perform RAW pictures decoding. See 'rawdecodingsetting.h' + for details. + */ + RawDecodingSettings m_rawDecodingSettings; + +protected: + + /** Re-implement this method to control the cancelisation of loop witch wait data + from RAW decoding process with your propers envirronement. + By default, this method check if m_cancel is true. + */ + virtual bool checkToCancelWaitingData(); + + /** Re-implement this method to control the pseudo progress value during RAW decoding (when dcraw run with an + internal loop without feedback) with your proper environment. By default, this method does nothing. + Progress value average for this stage is 0%-n%, with 'n' == 40% max (see setWaitingDataProgress() method). + */ + virtual void setWaitingDataProgress(double value); + +public: + + // Declared public to be called externally by callbackForLibRaw() static method. + class Private; + +private: + + Private* const d; + + friend class Private; +}; + +} // namespace KDcrawIface + +#endif /* KDCRAW_H */ diff --git a/libkdcraw/libkdcraw/kdcraw_p.cpp b/libkdcraw/libkdcraw/kdcraw_p.cpp new file mode 100644 index 00000000..dc5a1772 --- /dev/null +++ b/libkdcraw/libkdcraw/kdcraw_p.cpp @@ -0,0 +1,686 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2008-10-09 + * @brief internal private container for KDcraw + * + * @author Copyright (C) 2008-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "kdcraw.h" +#include "kdcraw_p.h" + +// Qt includes + +#include +#include + +namespace KDcrawIface +{ + +int callbackForLibRaw(void* data, enum LibRaw_progress p, int iteration, int expected) +{ + if (data) + { + KDcraw::Private* const d = static_cast(data); + + if (d) + { + return d->progressCallback(p, iteration, expected); + } + } + + return 0; +} + +// -------------------------------------------------------------------------------------------------- + +KDcraw::Private::Private(KDcraw* const p) +{ + m_progress = 0.0; + m_parent = p; +} + +KDcraw::Private::~Private() +{ +} + +void KDcraw::Private::createPPMHeader(QByteArray& imgData, libraw_processed_image_t* const img) +{ + QString header = QString("P%1\n%2 %3\n%4\n").arg(img->colors == 3 ? "6" : "5") + .arg(img->width) + .arg(img->height) + .arg((1 << img->bits)-1); + imgData.append(header.toAscii()); + imgData.append(QByteArray((const char*)img->data, (int)img->data_size)); +} + +int KDcraw::Private::progressCallback(enum LibRaw_progress p, int iteration, int expected) +{ + kDebug() << "LibRaw progress: " << libraw_strprogress(p) << " pass " + << iteration << " of " << expected; + + // post a little change in progress indicator to show raw processor activity. + setProgress(progressValue()+0.01); + + // Clean processing termination by user... + if (m_parent->checkToCancelWaitingData()) + { + kDebug() << "LibRaw process terminaison invoked..."; + m_parent->m_cancel = true; + m_progress = 0.0; + return 1; + } + + // Return 0 to continue processing... + return 0; +} + +void KDcraw::Private::setProgress(double value) +{ + m_progress = value; + m_parent->setWaitingDataProgress(m_progress); +} + +double KDcraw::Private::progressValue() const +{ + return m_progress; +} + +void KDcraw::Private::fillIndentifyInfo(LibRaw* const raw, DcrawInfoContainer& identify) +{ + identify.dateTime.setTime_t(raw->imgdata.other.timestamp); + identify.make = QString(raw->imgdata.idata.make); + identify.model = QString(raw->imgdata.idata.model); + identify.owner = QString(raw->imgdata.other.artist); + identify.DNGVersion = QString::number(raw->imgdata.idata.dng_version); + identify.sensitivity = raw->imgdata.other.iso_speed; + identify.exposureTime = raw->imgdata.other.shutter; + identify.aperture = raw->imgdata.other.aperture; + identify.focalLength = raw->imgdata.other.focal_len; + identify.imageSize = QSize(raw->imgdata.sizes.width, raw->imgdata.sizes.height); + identify.fullSize = QSize(raw->imgdata.sizes.raw_width, raw->imgdata.sizes.raw_height); + identify.outputSize = QSize(raw->imgdata.sizes.iwidth, raw->imgdata.sizes.iheight); + identify.thumbSize = QSize(raw->imgdata.thumbnail.twidth, raw->imgdata.thumbnail.theight); + identify.topMargin = raw->imgdata.sizes.top_margin; + identify.leftMargin = raw->imgdata.sizes.left_margin; + identify.hasIccProfile = raw->imgdata.color.profile ? true : false; + identify.isDecodable = true; + identify.pixelAspectRatio = raw->imgdata.sizes.pixel_aspect; + identify.rawColors = raw->imgdata.idata.colors; + identify.rawImages = raw->imgdata.idata.raw_count; + identify.blackPoint = raw->imgdata.color.black; + + for (int ch = 0; ch < 4; ch++) + { + identify.blackPointCh[ch] = raw->imgdata.color.cblack[ch]; + } + + identify.whitePoint = raw->imgdata.color.maximum; + identify.orientation = (DcrawInfoContainer::ImageOrientation)raw->imgdata.sizes.flip; + + memcpy(&identify.cameraColorMatrix1, &raw->imgdata.color.cmatrix, sizeof(raw->imgdata.color.cmatrix)); + memcpy(&identify.cameraColorMatrix2, &raw->imgdata.color.rgb_cam, sizeof(raw->imgdata.color.rgb_cam)); + memcpy(&identify.cameraXYZMatrix, &raw->imgdata.color.cam_xyz, sizeof(raw->imgdata.color.cam_xyz)); + + if (raw->imgdata.idata.filters) + { + if (!raw->imgdata.idata.cdesc[3]) + { + raw->imgdata.idata.cdesc[3] = 'G'; + } + + for (int i=0; i < 16; i++) + { + identify.filterPattern.append(raw->imgdata.idata.cdesc[raw->COLOR(i >> 1,i & 1)]); + } + + identify.colorKeys = raw->imgdata.idata.cdesc; + } + + for(int c = 0 ; c < raw->imgdata.idata.colors ; c++) + { + identify.daylightMult[c] = raw->imgdata.color.pre_mul[c]; + } + + if (raw->imgdata.color.cam_mul[0] > 0) + { + for(int c = 0 ; c < 4 ; c++) + { + identify.cameraMult[c] = raw->imgdata.color.cam_mul[c]; + } + } +} + +bool KDcraw::Private::loadFromLibraw(const QString& filePath, QByteArray& imageData, + int& width, int& height, int& rgbmax) +{ + m_parent->m_cancel = false; + + LibRaw raw; + // Set progress call back function. + raw.set_progress_handler(callbackForLibRaw, this); + + QByteArray deadpixelPath = QFile::encodeName(m_parent->m_rawDecodingSettings.deadPixelMap); + QByteArray cameraProfile = QFile::encodeName(m_parent->m_rawDecodingSettings.inputProfile); + QByteArray outputProfile = QFile::encodeName(m_parent->m_rawDecodingSettings.outputProfile); + + if (!m_parent->m_rawDecodingSettings.autoBrightness) + { + // Use a fixed white level, ignoring the image histogram. + raw.imgdata.params.no_auto_bright = 1; + } + + if (m_parent->m_rawDecodingSettings.sixteenBitsImage) + { + // (-4) 16bit ppm output + raw.imgdata.params.output_bps = 16; + } + + if (m_parent->m_rawDecodingSettings.halfSizeColorImage) + { + // (-h) Half-size color image (3x faster than -q). + raw.imgdata.params.half_size = 1; + } + + if (m_parent->m_rawDecodingSettings.RGBInterpolate4Colors) + { + // (-f) Interpolate RGB as four colors. + raw.imgdata.params.four_color_rgb = 1; + } + + if (m_parent->m_rawDecodingSettings.DontStretchPixels) + { + // (-j) Do not stretch the image to its correct aspect ratio. + raw.imgdata.params.use_fuji_rotate = 1; + } + + // (-H) Unclip highlight color. + raw.imgdata.params.highlight = m_parent->m_rawDecodingSettings.unclipColors; + + if (m_parent->m_rawDecodingSettings.brightness != 1.0) + { + // (-b) Set Brightness value. + raw.imgdata.params.bright = m_parent->m_rawDecodingSettings.brightness; + } + + if (m_parent->m_rawDecodingSettings.enableBlackPoint) + { + // (-k) Set Black Point value. + raw.imgdata.params.user_black = m_parent->m_rawDecodingSettings.blackPoint; + } + + if (m_parent->m_rawDecodingSettings.enableWhitePoint) + { + // (-S) Set White Point value (saturation). + raw.imgdata.params.user_sat = m_parent->m_rawDecodingSettings.whitePoint; + } + + if (m_parent->m_rawDecodingSettings.medianFilterPasses > 0) + { + // (-m) After interpolation, clean up color artifacts by repeatedly applying a 3x3 median filter to the R-G and B-G channels. + raw.imgdata.params.med_passes = m_parent->m_rawDecodingSettings.medianFilterPasses; + } + + if (!m_parent->m_rawDecodingSettings.deadPixelMap.isEmpty()) + { + // (-P) Read the dead pixel list from this file. + raw.imgdata.params.bad_pixels = deadpixelPath.data(); + } + + switch (m_parent->m_rawDecodingSettings.whiteBalance) + { + case RawDecodingSettings::NONE: + { + break; + } + case RawDecodingSettings::CAMERA: + { + // (-w) Use camera white balance, if possible. + raw.imgdata.params.use_camera_wb = 1; + break; + } + case RawDecodingSettings::AUTO: + { + // (-a) Use automatic white balance. + raw.imgdata.params.use_auto_wb = 1; + break; + } + case RawDecodingSettings::CUSTOM: + { + /* Convert between Temperature and RGB. + */ + double T; + double RGB[3]; + double xD, yD, X, Y, Z; + DcrawInfoContainer identify; + T = m_parent->m_rawDecodingSettings.customWhiteBalance; + + /* Here starts the code picked and adapted from ufraw (0.12.1) + to convert Temperature + green multiplier to RGB multipliers + */ + /* Convert between Temperature and RGB. + * Base on information from http://www.brucelindbloom.com/ + * The fit for D-illuminant between 4000K and 12000K are from CIE + * The generalization to 2000K < T < 4000K and the blackbody fits + * are my own and should be taken with a grain of salt. + */ + const double XYZ_to_RGB[3][3] = { + { 3.24071, -0.969258, 0.0556352 }, + {-1.53726, 1.87599, -0.203996 }, + {-0.498571, 0.0415557, 1.05707 } + }; + + // Fit for CIE Daylight illuminant + if (T <= 4000) + { + xD = 0.27475e9/(T*T*T) - 0.98598e6/(T*T) + 1.17444e3/T + 0.145986; + } + else if (T <= 7000) + { + xD = -4.6070e9/(T*T*T) + 2.9678e6/(T*T) + 0.09911e3/T + 0.244063; + } + else + { + xD = -2.0064e9/(T*T*T) + 1.9018e6/(T*T) + 0.24748e3/T + 0.237040; + } + + yD = -3*xD*xD + 2.87*xD - 0.275; + X = xD/yD; + Y = 1; + Z = (1-xD-yD)/yD; + RGB[0] = X*XYZ_to_RGB[0][0] + Y*XYZ_to_RGB[1][0] + Z*XYZ_to_RGB[2][0]; + RGB[1] = X*XYZ_to_RGB[0][1] + Y*XYZ_to_RGB[1][1] + Z*XYZ_to_RGB[2][1]; + RGB[2] = X*XYZ_to_RGB[0][2] + Y*XYZ_to_RGB[1][2] + Z*XYZ_to_RGB[2][2]; + /* End of the code picked to ufraw + */ + + RGB[1] = RGB[1] / m_parent->m_rawDecodingSettings.customWhiteBalanceGreen; + + /* By default, decraw override his default D65 WB + We need to keep it as a basis : if not, colors with some + DSLR will have a high dominant of color that will lead to + a completely wrong WB + */ + if (rawFileIdentify(identify, filePath)) + { + RGB[0] = identify.daylightMult[0] / RGB[0]; + RGB[1] = identify.daylightMult[1] / RGB[1]; + RGB[2] = identify.daylightMult[2] / RGB[2]; + } + else + { + RGB[0] = 1.0 / RGB[0]; + RGB[1] = 1.0 / RGB[1]; + RGB[2] = 1.0 / RGB[2]; + kDebug() << "Warning: cannot get daylight multipliers"; + } + + // (-r) set Raw Color Balance Multipliers. + raw.imgdata.params.user_mul[0] = RGB[0]; + raw.imgdata.params.user_mul[1] = RGB[1]; + raw.imgdata.params.user_mul[2] = RGB[2]; + raw.imgdata.params.user_mul[3] = RGB[1]; + break; + } + case RawDecodingSettings::AERA: + { + // (-A) Calculate the white balance by averaging a rectangular area from image. + raw.imgdata.params.greybox[0] = m_parent->m_rawDecodingSettings.whiteBalanceArea.left(); + raw.imgdata.params.greybox[1] = m_parent->m_rawDecodingSettings.whiteBalanceArea.top(); + raw.imgdata.params.greybox[2] = m_parent->m_rawDecodingSettings.whiteBalanceArea.width(); + raw.imgdata.params.greybox[3] = m_parent->m_rawDecodingSettings.whiteBalanceArea.height(); + break; + } + } + + // (-q) Use an interpolation method. + raw.imgdata.params.user_qual = m_parent->m_rawDecodingSettings.RAWQuality; + + switch (m_parent->m_rawDecodingSettings.NRType) + { + case RawDecodingSettings::WAVELETSNR: + { + // (-n) Use wavelets to erase noise while preserving real detail. + raw.imgdata.params.threshold = m_parent->m_rawDecodingSettings.NRThreshold; + break; + } + case RawDecodingSettings::FBDDNR: + { + // (100 - 1000) => (1 - 10) conversion + raw.imgdata.params.fbdd_noiserd = lround(m_parent->m_rawDecodingSettings.NRThreshold / 100.0); + break; + } + case RawDecodingSettings::LINENR: + { + // (100 - 1000) => (0.001 - 0.02) conversion. + raw.imgdata.params.linenoise = m_parent->m_rawDecodingSettings.NRThreshold * 2.11E-5 + 0.00111111; + raw.imgdata.params.cfaline = true; + break; + } + + case RawDecodingSettings::IMPULSENR: + { + // (100 - 1000) => (0.005 - 0.05) conversion. + raw.imgdata.params.lclean = m_parent->m_rawDecodingSettings.NRThreshold * 5E-5; + raw.imgdata.params.cclean = m_parent->m_rawDecodingSettings.NRChroThreshold * 5E-5; + raw.imgdata.params.cfa_clean = true; + break; + } + default: // No Noise Reduction + { + raw.imgdata.params.threshold = 0; + raw.imgdata.params.fbdd_noiserd = 0; + raw.imgdata.params.linenoise = 0; + raw.imgdata.params.cfaline = false; + raw.imgdata.params.lclean = 0; + raw.imgdata.params.cclean = 0; + raw.imgdata.params.cfa_clean = false; + break; + } + } + + // Chromatic aberration correction. + raw.imgdata.params.ca_correc = m_parent->m_rawDecodingSettings.enableCACorrection; + raw.imgdata.params.cared = m_parent->m_rawDecodingSettings.caMultiplier[0]; + raw.imgdata.params.cablue = m_parent->m_rawDecodingSettings.caMultiplier[1]; + + // Exposure Correction before interpolation. + raw.imgdata.params.exp_correc = m_parent->m_rawDecodingSettings.expoCorrection; + raw.imgdata.params.exp_shift = m_parent->m_rawDecodingSettings.expoCorrectionShift; + raw.imgdata.params.exp_preser = m_parent->m_rawDecodingSettings.expoCorrectionHighlight; + + switch (m_parent->m_rawDecodingSettings.inputColorSpace) + { + case RawDecodingSettings::EMBEDDED: + { + // (-p embed) Use input profile from RAW file to define the camera's raw colorspace. + raw.imgdata.params.camera_profile = (char*)"embed"; + break; + } + case RawDecodingSettings::CUSTOMINPUTCS: + { + if (!m_parent->m_rawDecodingSettings.inputProfile.isEmpty()) + { + // (-p) Use input profile file to define the camera's raw colorspace. + raw.imgdata.params.camera_profile = cameraProfile.data(); + } + break; + } + default: + { + // No input profile + break; + } + } + + switch (m_parent->m_rawDecodingSettings.outputColorSpace) + { + case RawDecodingSettings::CUSTOMOUTPUTCS: + { + if (!m_parent->m_rawDecodingSettings.outputProfile.isEmpty()) + { + // (-o) Use ICC profile file to define the output colorspace. + raw.imgdata.params.output_profile = outputProfile.data(); + } + break; + } + default: + { + // (-o) Define the output colorspace. + raw.imgdata.params.output_color = m_parent->m_rawDecodingSettings.outputColorSpace; + break; + } + } + + //-- Extended demosaicing settings ---------------------------------------------------------- + + raw.imgdata.params.dcb_iterations = m_parent->m_rawDecodingSettings.dcbIterations; + raw.imgdata.params.dcb_enhance_fl = m_parent->m_rawDecodingSettings.dcbEnhanceFl; + raw.imgdata.params.eeci_refine = m_parent->m_rawDecodingSettings.eeciRefine; + raw.imgdata.params.es_med_passes = m_parent->m_rawDecodingSettings.esMedPasses; + + //------------------------------------------------------------------------------------------- + + setProgress(0.1); + + kDebug() << filePath; + kDebug() << m_parent->m_rawDecodingSettings; + + int ret = raw.open_file(QFile::encodeName(filePath)); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run open_file: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + if (m_parent->m_cancel) + { + raw.recycle(); + return false; + } + + setProgress(0.2); + + ret = raw.unpack(); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run unpack: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + if (m_parent->m_cancel) + { + raw.recycle(); + return false; + } + + setProgress(0.25); + + if (m_parent->m_rawDecodingSettings.fixColorsHighlights) + { + kDebug() << "Applying LibRaw highlights adjustments"; + // 1.0 is fallback to default value + raw.imgdata.params.adjust_maximum_thr = 1.0; + } + else + { + kDebug() << "Disabling LibRaw highlights adjustments"; + // 0.0 disables this feature + raw.imgdata.params.adjust_maximum_thr = 0.0; + } + + ret = raw.dcraw_process(); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run dcraw_process: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + if (m_parent->m_cancel) + { + raw.recycle(); + return false; + } + + setProgress(0.3); + + libraw_processed_image_t* img = raw.dcraw_make_mem_image(&ret); + + if(!img) + { + kDebug() << "LibRaw: failed to run dcraw_make_mem_image: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + if (m_parent->m_cancel) + { + // Clear memory allocation. Introduced with LibRaw 0.11.0 + raw.dcraw_clear_mem(img); + raw.recycle(); + return false; + } + + setProgress(0.35); + + width = img->width; + height = img->height; + rgbmax = (1 << img->bits)-1; + + if (img->colors == 3) + { + imageData = QByteArray((const char*)img->data, (int)img->data_size); + } + else + { + // img->colors == 1 (Grayscale) : convert to RGB + imageData = QByteArray(); + + for (int i = 0 ; i < (int)img->data_size ; ++i) + { + for (int j = 0 ; j < 3 ; ++j) + { + imageData.append(img->data[i]); + } + } + } + + // Clear memory allocation. Introduced with LibRaw 0.11.0 + raw.dcraw_clear_mem(img); + raw.recycle(); + + if (m_parent->m_cancel) + { + return false; + } + + setProgress(0.4); + + kDebug() << "LibRaw: data info: width=" << width + << " height=" << height + << " rgbmax=" << rgbmax; + + return true; +} + +bool KDcraw::Private::loadEmbeddedPreview(QByteArray& imgData, LibRaw& raw) +{ + int ret = raw.unpack_thumb(); + + if (ret != LIBRAW_SUCCESS) + { + raw.recycle(); + kDebug() << "LibRaw: failed to run unpack_thumb: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + libraw_processed_image_t* const thumb = raw.dcraw_make_mem_thumb(&ret); + + if(!thumb) + { + kDebug() << "LibRaw: failed to run dcraw_make_mem_thumb: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + if(thumb->type == LIBRAW_IMAGE_BITMAP) + { + createPPMHeader(imgData, thumb); + } + else + { + imgData = QByteArray((const char*)thumb->data, (int)thumb->data_size); + } + + // Clear memory allocation. Introduced with LibRaw 0.11.0 + raw.dcraw_clear_mem(thumb); + raw.recycle(); + + if ( imgData.isEmpty() ) + { + kDebug() << "Failed to load JPEG thumb from LibRaw!"; + return false; + } + + return true; +} + +bool KDcraw::Private::loadHalfPreview(QImage& image, LibRaw& raw) +{ + raw.imgdata.params.use_auto_wb = 1; // Use automatic white balance. + raw.imgdata.params.use_camera_wb = 1; // Use camera white balance, if possible. + raw.imgdata.params.half_size = 1; // Half-size color image (3x faster than -q). + QByteArray imgData; + + int ret = raw.unpack(); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run unpack: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + ret = raw.dcraw_process(); + + if (ret != LIBRAW_SUCCESS) + { + kDebug() << "LibRaw: failed to run dcraw_process: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + libraw_processed_image_t* halfImg = raw.dcraw_make_mem_image(&ret); + + if(!halfImg) + { + kDebug() << "LibRaw: failed to run dcraw_make_mem_image: " << libraw_strerror(ret); + raw.recycle(); + return false; + } + + Private::createPPMHeader(imgData, halfImg); + // Clear memory allocation. Introduced with LibRaw 0.11.0 + raw.dcraw_clear_mem(halfImg); + raw.recycle(); + + if ( imgData.isEmpty() ) + { + kDebug() << "Failed to load half preview from LibRaw!"; + return false; + } + + if (!image.loadFromData(imgData)) + { + kDebug() << "Failed to load PPM data from LibRaw!"; + return false; + } + + return true; +} + +} // namespace KDcrawIface diff --git a/libkdcraw/libkdcraw/kdcraw_p.h b/libkdcraw/libkdcraw/kdcraw_p.h new file mode 100644 index 00000000..c309f90d --- /dev/null +++ b/libkdcraw/libkdcraw/kdcraw_p.h @@ -0,0 +1,94 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2008-10-09 + * @brief internal private container for KDcraw + * + * @author Copyright (C) 2008-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef KDCRAWPRIVATE_H +#define KDCRAWPRIVATE_H + +// Qt includes + +#include + +// KDE includes + +#include + +// LibRaw includes + +#include + +// Local includes + +#include "dcrawinfocontainer.h" + +namespace KDcrawIface +{ + +class KDcraw; + +extern "C" +{ + int callbackForLibRaw(void* data, enum LibRaw_progress p, int iteration, int expected); +} + +class KDcraw::Private +{ + +public: + + Private(KDcraw* const p); + ~Private(); + +public: + + int progressCallback(enum LibRaw_progress p, int iteration, int expected); + + void setProgress(double value); + double progressValue() const; + + bool loadFromLibraw(const QString& filePath, QByteArray& imageData, + int& width, int& height, int& rgbmax); + +public: + + static void createPPMHeader(QByteArray& imgData, libraw_processed_image_t* const img); + + static void fillIndentifyInfo(LibRaw* const raw, DcrawInfoContainer& identify); + + static bool loadEmbeddedPreview(QByteArray&, LibRaw&); + + static bool loadHalfPreview(QImage&, LibRaw&); + +private: + + double m_progress; + + KDcraw* m_parent; + + friend class KDcraw; +}; + +} // namespace KDcrawIface + +#endif /* KDCRAWPRIVATE_H */ diff --git a/libkdcraw/libkdcraw/libkdcraw_export.h b/libkdcraw/libkdcraw/libkdcraw_export.h new file mode 100644 index 00000000..adf45cc4 --- /dev/null +++ b/libkdcraw/libkdcraw/libkdcraw_export.h @@ -0,0 +1,47 @@ +/** =========================================================== + * @file + * + * This file is part of the KDE project + * + * @brief Helper for exporting functions/classes from the shared library + * + * @author Copyright (C) 2007 David Faure + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * ============================================================ */ + +#ifndef LIBKDCRAW_EXPORT_H +#define LIBKDCRAW_EXPORT_H + +/* needed for KDE_EXPORT and KDE_IMPORT macros */ +#include + +#ifndef LIBKDCRAW_EXPORT +# if defined(MAKE_KDCRAW_LIB) + /* We are building this library */ +# define LIBKDCRAW_EXPORT KDE_EXPORT +# else + /* We are using this library */ +# define LIBKDCRAW_EXPORT KDE_IMPORT +# endif +#endif + +# ifndef LIBKDCRAW_EXPORT_DEPRECATED +# define LIBKDCRAW_EXPORT_DEPRECATED KDE_DEPRECATED LIBKDCRAW_EXPORT +# endif + +#endif diff --git a/libkdcraw/libkdcraw/ractionthreadbase.cpp b/libkdcraw/libkdcraw/ractionthreadbase.cpp new file mode 100644 index 00000000..6dd528b2 --- /dev/null +++ b/libkdcraw/libkdcraw/ractionthreadbase.cpp @@ -0,0 +1,158 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2011-12-28 + * @brief re-implementation of action thread using threadweaver + * + * @author Copyright (C) 2011-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2011-2012 by A Janardhan Reddy + * annapareddyjanardhanreddy at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "moc_ractionthreadbase.cpp" + +// Qt includes + +#include + +// KDE includes + +#include +#include +#include +#include +#include +#include +#include + +// Local includes + +#include "ractionthreadbase_p.h" + +using namespace Solid; + +namespace KDcrawIface +{ + +RActionThreadBase::RActionThreadBase(QObject* const parent) + : QThread(parent), d(new Private) +{ + const int maximumNumberOfThreads = qMax(Device::listFromType(DeviceInterface::Processor).count(), 1); + d->log = new RWeaverObserver(this); + d->weaver = new Weaver(this); + d->weaver->registerObserver(d->log); + d->weaver->setMaximumNumberOfThreads(maximumNumberOfThreads); + kDebug() << "Starting Main Thread"; +} + +RActionThreadBase::~RActionThreadBase() +{ + kDebug() << "calling action thread destructor"; + // cancel the thread + cancel(); + // wait for the thread to finish + wait(); + + delete d->log; + delete d->weaver; + delete d; +} + +void RActionThreadBase::setMaximumNumberOfThreads(int n) +{ + d->weaver->setMaximumNumberOfThreads(n); +} + +void RActionThreadBase::slotFinished() +{ + kDebug() << "Finish Main Thread"; + d->weaverRunning = false; + d->condVarJobs.wakeAll(); + emit QThread::finished(); +} + +void RActionThreadBase::cancel() +{ + kDebug() << "Cancel Main Thread"; + QMutexLocker lock(&d->mutex); + d->todo.clear(); + d->running = false; + d->weaverRunning = true; + d->weaver->requestAbort(); + d->weaver->dequeue(); + d->condVarJobs.wakeAll(); +} + +void RActionThreadBase::finish() +{ + d->weaver->finish(); +} + +bool RActionThreadBase::isEmpty() const +{ + return d->todo.isEmpty(); +} + +void RActionThreadBase::appendJob(JobCollection* const job) +{ + QMutexLocker lock(&d->mutex); + d->todo << job; + d->condVarJobs.wakeAll(); +} + +void RActionThreadBase::run() +{ + d->running = true; + d->weaverRunning = false; + kDebug() << "In action thread Run"; + + while (d->running) + { + JobCollection* t = 0; + { + QMutexLocker lock(&d->mutex); + + if (!isEmpty() && !d->weaverRunning) + { + t = d->todo.takeFirst(); + } + else + { + d->condVarJobs.wait(&d->mutex); + } + } + + if (t) + { + connect(t, SIGNAL(done(ThreadWeaver::Job*)), + this, SLOT(slotFinished())); + + connect(t, SIGNAL(done(ThreadWeaver::Job*)), + t, SLOT(deleteLater())); + + d->weaverRunning = true; + d->weaver->enqueue(t); + } + } + + d->weaver->finish(); + kDebug() << "Exiting Action Thread"; +} + +} // namespace KDcrawIface diff --git a/libkdcraw/libkdcraw/ractionthreadbase.h b/libkdcraw/libkdcraw/ractionthreadbase.h new file mode 100644 index 00000000..41b83cee --- /dev/null +++ b/libkdcraw/libkdcraw/ractionthreadbase.h @@ -0,0 +1,91 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2011-12-28 + * @brief re-implementation of action thread using threadweaver + * + * @author Copyright (C) 2011-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2011-2012 by A Janardhan Reddy + * annapareddyjanardhanreddy at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef RACTION_THREAD_BASE_H +#define RACTION_THREAD_BASE_H + +// Qt includes + +#include + +// Local includes + +#include "libkdcraw_export.h" + +namespace ThreadWeaver +{ + class JobCollection; +} + +using namespace ThreadWeaver; + +namespace KDcrawIface +{ + +class LIBKDCRAW_EXPORT RActionThreadBase : public QThread +{ + Q_OBJECT + +public: + + RActionThreadBase(QObject* const parent=0); + ~RActionThreadBase(); + + /** Adjust maximum number of thread used to parallelize collection of job processing. + * By default in constructor, KDE::Solid API is used to determine the number of CPU available and adjust + * this value automatically. + */ + void setMaximumNumberOfThreads(int n); + + void cancel(); + void finish(); + +protected: + + void run(); + + /** Append a collection of jobs to process in pending list. + */ + void appendJob(JobCollection* const job); + + /** Return true if list of pending jobs to process is empty. + */ + bool isEmpty() const; + +protected Q_SLOTS: + + void slotFinished(); + +private: + + class Private; + Private* const d; +}; + +} // namespace KDcrawIface + +#endif // RACTION_THREAD_BASE_H diff --git a/libkdcraw/libkdcraw/ractionthreadbase_p.cpp b/libkdcraw/libkdcraw/ractionthreadbase_p.cpp new file mode 100644 index 00000000..fae8540a --- /dev/null +++ b/libkdcraw/libkdcraw/ractionthreadbase_p.cpp @@ -0,0 +1,85 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2011-12-28 + * @brief internal RActionThreadBase classes + * + * @author Copyright (C) 2011-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2011-2012 by A Janardhan Reddy + * annapareddyjanardhanreddy at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "moc_ractionthreadbase_p.cpp" + +// KDE includes + +#include + +namespace KDcrawIface +{ + +RWeaverObserver::RWeaverObserver(QObject* const parent) + : WeaverObserver(parent) +{ + connect(this, SIGNAL(weaverStateChanged(ThreadWeaver::State*)), + this, SLOT(slotWeaverStateChanged(ThreadWeaver::State*))); + + connect(this, SIGNAL(threadStarted(ThreadWeaver::Thread*)), + this, SLOT(slotThreadStarted(ThreadWeaver::Thread*))); + + connect(this, SIGNAL(threadBusy(ThreadWeaver::Thread*,ThreadWeaver::Job*)), + this, SLOT(slotThreadBusy(ThreadWeaver::Thread*,ThreadWeaver::Job*))); + + connect(this, SIGNAL(threadSuspended(ThreadWeaver::Thread*)), + this, SLOT(slotThreadSuspended(ThreadWeaver::Thread*))); + + connect(this, SIGNAL(threadExited(ThreadWeaver::Thread*)), + this, SLOT(slotThreadExited(ThreadWeaver::Thread*))); +} + +RWeaverObserver::~RWeaverObserver() +{ +} + +void RWeaverObserver::slotWeaverStateChanged(State* state) +{ + kDebug() << "RWeaverObserver: thread state changed to " << state->stateName(); +} + +void RWeaverObserver::slotThreadStarted(Thread* th) +{ + kDebug() << "RWeaverObserver: thread " << th->id() <<" started"; +} + +void RWeaverObserver::slotThreadBusy(Thread* th, Job*) +{ + kDebug() << "RWeaverObserver: thread " << th->id() << " busy"; +} + +void RWeaverObserver::slotThreadSuspended(Thread* th ) +{ + kDebug() << "RWeaverObserver: thread " << th->id() << " suspended"; +} + +void RWeaverObserver::slotThreadExited(Thread* th) +{ + kDebug() << "RWeaverObserver: thread " << th->id() << " exited"; +} + +} // namespace KDcrawIface diff --git a/libkdcraw/libkdcraw/ractionthreadbase_p.h b/libkdcraw/libkdcraw/ractionthreadbase_p.h new file mode 100644 index 00000000..a765f6a7 --- /dev/null +++ b/libkdcraw/libkdcraw/ractionthreadbase_p.h @@ -0,0 +1,106 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2011-12-28 + * @brief internal RActionThreadBase classes + * + * @author Copyright (C) 2011-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2011-2012 by A Janardhan Reddy + * annapareddyjanardhanreddy at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef RACTION_THREAD_BASE_P_H +#define RACTION_THREAD_BASE_P_H + +// Qt includes + +#include +#include +#include + +// KDE includes + +#include +#include +#include +#include + +// Local includes + +#include "ractionthreadbase.h" + +namespace ThreadWeaver +{ + class Weaver; +} + +using namespace ThreadWeaver; + +namespace KDcrawIface +{ + +/** RWeaverObserver is a simple wrapper to plug on the ActionThread class to + prints debug messages when signals are received. +*/ +class RWeaverObserver : public WeaverObserver +{ + Q_OBJECT + +public: + + RWeaverObserver(QObject* const parent=0); + ~RWeaverObserver(); + +protected Q_SLOTS: + + void slotWeaverStateChanged(ThreadWeaver::State*); + void slotThreadStarted(ThreadWeaver::Thread*); + void slotThreadBusy(ThreadWeaver::Thread*, ThreadWeaver::Job*); + void slotThreadSuspended(ThreadWeaver::Thread*); + void slotThreadExited(ThreadWeaver::Thread*); +}; + +// ---------------------------------------------------------------------------------- + +class RActionThreadBase::Private +{ +public: + + Private() + { + running = false; + weaverRunning = false; + weaver = 0; + log = 0; + } + + volatile bool running; + volatile bool weaverRunning; + + QWaitCondition condVarJobs; + QMutex mutex; + QList todo; + + Weaver* weaver; + RWeaverObserver* log; +}; + +} // namespace KDcrawIface + +#endif // RACTION_THREAD_BASE_P_H diff --git a/libkdcraw/libkdcraw/rawdecodingsettings.cpp b/libkdcraw/libkdcraw/rawdecodingsettings.cpp new file mode 100644 index 00000000..cd8aff69 --- /dev/null +++ b/libkdcraw/libkdcraw/rawdecodingsettings.cpp @@ -0,0 +1,396 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-12-09 + * @brief Raw decoding settings + * + * @author Copyright (C) 2006-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2013 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * @author Copyright (C) 2007-2008 by Guillaume Castagnino + * casta at xwing dot info + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#define OPTIONFIXCOLORSHIGHLIGHTSENTRY "FixColorsHighlights" +#define OPTIONDECODESIXTEENBITENTRY "SixteenBitsImage" +#define OPTIONWHITEBALANCEENTRY "White Balance" +#define OPTIONCUSTOMWHITEBALANCEENTRY "Custom White Balance" +#define OPTIONCUSTOMWBGREENENTRY "Custom White Balance Green" +#define OPTIONFOURCOLORRGBENTRY "Four Color RGB" +#define OPTIONUNCLIPCOLORSENTRY "Unclip Color" +// Wrong spelling, but do not fix it since it is a configuration key +// krazy:cond=spelling +#define OPTIONDONTSTRETCHPIXELSENTRY "Dont Stretch Pixels" +// krazy:endcond=spelling +#define OPTIONMEDIANFILTERPASSESENTRY "Median Filter Passes" +#define OPTIONNOISEREDUCTIONTYPEENTRY "Noise Reduction Type" +#define OPTIONNOISEREDUCTIONTHRESHOLDENTRY "Noise Reduction Threshold" +#define OPTIONUSECACORRECTIONENTRY "EnableCACorrection" +#define OPTIONCAREDMULTIPLIERENTRY "caRedMultiplier" +#define OPTIONCABLUEMULTIPLIERENTRY "caBlueMultiplier" +#define OPTIONAUTOBRIGHTNESSENTRY "AutoBrightness" +#define OPTIONDECODINGQUALITYENTRY "Decoding Quality" +#define OPTIONINPUTCOLORSPACEENTRY "Input Color Space" +#define OPTIONOUTPUTCOLORSPACEENTRY "Output Color Space" +#define OPTIONINPUTCOLORPROFILEENTRY "Input Color Profile" +#define OPTIONOUTPUTCOLORPROFILEENTRY "Output Color Profile" +#define OPTIONBRIGHTNESSMULTIPLIERENTRY "Brightness Multiplier" +#define OPTIONUSEBLACKPOINTENTRY "Use Black Point" +#define OPTIONBLACKPOINTENTRY "Black Point" +#define OPTIONUSEWHITEPOINTENTRY "Use White Point" +#define OPTIONWHITEPOINTENTRY "White Point" + +//-- Extended demosaicing settings ---------------------------------------------------------- + +#define OPTIONDCBITERATIONSENTRY "Dcb Iterations" +#define OPTIONDCBENHANCEFLENTRY "Dcb Enhance Filter" +#define OPTIONEECIREFINEENTRY "Eeci Refine" +#define OPTIONESMEDPASSESENTRY "Es Median Filter Passes" +#define OPTIONNRCHROMINANCETHRESHOLDENTRY "Noise Reduction Chrominance Threshold" +#define OPTIONEXPOCORRECTIONENTRY "Expo Correction" +#define OPTIONEXPOCORRECTIONSHIFTENTRY "Expo Correction Shift" +#define OPTIONEXPOCORRECTIONHIGHLIGHTENTRY "Expo Correction Highlight" + +#include "rawdecodingsettings.h" + +namespace KDcrawIface +{ + +RawDecodingSettings::RawDecodingSettings() +{ + fixColorsHighlights = false; + autoBrightness = true; + sixteenBitsImage = false; + brightness = 1.0; + RAWQuality = BILINEAR; + inputColorSpace = NOINPUTCS; + outputColorSpace = SRGB; + RGBInterpolate4Colors = false; + DontStretchPixels = false; + unclipColors = 0; + whiteBalance = CAMERA; + customWhiteBalance = 6500; + customWhiteBalanceGreen = 1.0; + medianFilterPasses = 0; + + halfSizeColorImage = false; + + enableBlackPoint = false; + blackPoint = 0; + + enableWhitePoint = false; + whitePoint = 0; + + NRType = NONR; + NRThreshold = 0; + + enableCACorrection = false; + caMultiplier[0] = 0.0; + caMultiplier[1] = 0.0; + + inputProfile = QString(); + outputProfile = QString(); + + deadPixelMap = QString(); + + whiteBalanceArea = QRect(); + + //-- Extended demosaicing settings ---------------------------------------------------------- + + dcbIterations = -1; + dcbEnhanceFl = false; + eeciRefine = false; + esMedPasses = 0; + NRChroThreshold = 0; + expoCorrection = false; + expoCorrectionShift = 1.0; + expoCorrectionHighlight = 0.0; +} + +RawDecodingSettings::~RawDecodingSettings() +{ +} + +RawDecodingSettings& RawDecodingSettings::operator=(const RawDecodingSettings& o) +{ + fixColorsHighlights = o.fixColorsHighlights; + autoBrightness = o.autoBrightness; + sixteenBitsImage = o.sixteenBitsImage; + brightness = o.brightness; + RAWQuality = o.RAWQuality; + inputColorSpace = o.inputColorSpace; + outputColorSpace = o.outputColorSpace; + RGBInterpolate4Colors = o.RGBInterpolate4Colors; + DontStretchPixels = o.DontStretchPixels; + unclipColors = o.unclipColors; + whiteBalance = o.whiteBalance; + customWhiteBalance = o.customWhiteBalance; + customWhiteBalanceGreen = o.customWhiteBalanceGreen; + halfSizeColorImage = o.halfSizeColorImage; + enableBlackPoint = o.enableBlackPoint; + blackPoint = o.blackPoint; + enableWhitePoint = o.enableWhitePoint; + whitePoint = o.whitePoint; + NRType = o.NRType; + NRThreshold = o.NRThreshold; + enableCACorrection = o.enableCACorrection; + caMultiplier[0] = o.caMultiplier[0]; + caMultiplier[1] = o.caMultiplier[1]; + medianFilterPasses = o.medianFilterPasses; + inputProfile = o.inputProfile; + outputProfile = o.outputProfile; + deadPixelMap = o.deadPixelMap; + whiteBalanceArea = o.whiteBalanceArea; + + //-- Extended demosaicing settings ---------------------------------------------------------- + + dcbIterations = o.dcbIterations; + dcbEnhanceFl = o.dcbEnhanceFl; + eeciRefine = o.eeciRefine; + esMedPasses = o.esMedPasses; + NRChroThreshold = o.NRChroThreshold; + expoCorrection = o.expoCorrection; + expoCorrectionShift = o.expoCorrectionShift; + expoCorrectionHighlight = o.expoCorrectionHighlight; + + return *this; +} + +bool RawDecodingSettings::operator==(const RawDecodingSettings& o) const +{ + return fixColorsHighlights == o.fixColorsHighlights + && autoBrightness == o.autoBrightness + && sixteenBitsImage == o.sixteenBitsImage + && brightness == o.brightness + && RAWQuality == o.RAWQuality + && inputColorSpace == o.inputColorSpace + && outputColorSpace == o.outputColorSpace + && RGBInterpolate4Colors == o.RGBInterpolate4Colors + && DontStretchPixels == o.DontStretchPixels + && unclipColors == o.unclipColors + && whiteBalance == o.whiteBalance + && customWhiteBalance == o.customWhiteBalance + && customWhiteBalanceGreen == o.customWhiteBalanceGreen + && halfSizeColorImage == o.halfSizeColorImage + && enableBlackPoint == o.enableBlackPoint + && blackPoint == o.blackPoint + && enableWhitePoint == o.enableWhitePoint + && whitePoint == o.whitePoint + && NRType == o.NRType + && NRThreshold == o.NRThreshold + && enableCACorrection == o.enableCACorrection + && caMultiplier[0] == o.caMultiplier[0] + && caMultiplier[1] == o.caMultiplier[1] + && medianFilterPasses == o.medianFilterPasses + && inputProfile == o.inputProfile + && outputProfile == o.outputProfile + && deadPixelMap == o.deadPixelMap + && whiteBalanceArea == o.whiteBalanceArea + + //-- Extended demosaicing settings ---------------------------------------------------------- + + && dcbIterations == o.dcbIterations + && dcbEnhanceFl == o.dcbEnhanceFl + && eeciRefine == o.eeciRefine + && esMedPasses == o.esMedPasses + && NRChroThreshold == o.NRChroThreshold + && expoCorrection == o.expoCorrection + && expoCorrectionShift == o.expoCorrectionShift + && expoCorrectionHighlight == o.expoCorrectionHighlight + ; +} + +void RawDecodingSettings::optimizeTimeLoading() +{ + fixColorsHighlights = false; + autoBrightness = true; + sixteenBitsImage = true; + brightness = 1.0; + RAWQuality = BILINEAR; + inputColorSpace = NOINPUTCS; + outputColorSpace = SRGB; + RGBInterpolate4Colors = false; + DontStretchPixels = false; + unclipColors = 0; + whiteBalance = CAMERA; + customWhiteBalance = 6500; + customWhiteBalanceGreen = 1.0; + halfSizeColorImage = true; + medianFilterPasses = 0; + + enableBlackPoint = false; + blackPoint = 0; + + enableWhitePoint = false; + whitePoint = 0; + + NRType = NONR; + NRThreshold = 0; + + enableCACorrection = false; + caMultiplier[0] = 0.0; + caMultiplier[1] = 0.0; + + inputProfile = QString(); + outputProfile = QString(); + + deadPixelMap = QString(); + + whiteBalanceArea = QRect(); + + //-- Extended demosaicing settings ---------------------------------------------------------- + + dcbIterations = -1; + dcbEnhanceFl = false; + eeciRefine = false; + esMedPasses = 0; + NRChroThreshold = 0; + expoCorrection = false; + expoCorrectionShift = 1.0; + expoCorrectionHighlight = 0.0; +} + +void RawDecodingSettings::readSettings(KConfigGroup& group) +{ + RawDecodingSettings defaultPrm; + + fixColorsHighlights = group.readEntry(OPTIONFIXCOLORSHIGHLIGHTSENTRY, defaultPrm.fixColorsHighlights); + sixteenBitsImage = group.readEntry(OPTIONDECODESIXTEENBITENTRY, defaultPrm.sixteenBitsImage); + whiteBalance = (WhiteBalance) + group.readEntry(OPTIONWHITEBALANCEENTRY, (int)defaultPrm.whiteBalance); + customWhiteBalance = group.readEntry(OPTIONCUSTOMWHITEBALANCEENTRY, defaultPrm.customWhiteBalance); + customWhiteBalanceGreen = group.readEntry(OPTIONCUSTOMWBGREENENTRY, defaultPrm.customWhiteBalanceGreen); + RGBInterpolate4Colors = group.readEntry(OPTIONFOURCOLORRGBENTRY, defaultPrm.RGBInterpolate4Colors); + unclipColors = group.readEntry(OPTIONUNCLIPCOLORSENTRY, defaultPrm.unclipColors); + DontStretchPixels = group.readEntry(OPTIONDONTSTRETCHPIXELSENTRY, defaultPrm.DontStretchPixels); + NRType = (NoiseReduction) + group.readEntry(OPTIONNOISEREDUCTIONTYPEENTRY, (int)defaultPrm.NRType); + brightness = group.readEntry(OPTIONBRIGHTNESSMULTIPLIERENTRY, defaultPrm.brightness); + enableBlackPoint = group.readEntry(OPTIONUSEBLACKPOINTENTRY, defaultPrm.enableBlackPoint); + blackPoint = group.readEntry(OPTIONBLACKPOINTENTRY, defaultPrm.blackPoint); + enableWhitePoint = group.readEntry(OPTIONUSEWHITEPOINTENTRY, defaultPrm.enableWhitePoint); + whitePoint = group.readEntry(OPTIONWHITEPOINTENTRY, defaultPrm.whitePoint); + medianFilterPasses = group.readEntry(OPTIONMEDIANFILTERPASSESENTRY, defaultPrm.medianFilterPasses); + NRThreshold = group.readEntry(OPTIONNOISEREDUCTIONTHRESHOLDENTRY, defaultPrm.NRThreshold); + enableCACorrection = group.readEntry(OPTIONUSECACORRECTIONENTRY, defaultPrm.enableCACorrection); + caMultiplier[0] = group.readEntry(OPTIONCAREDMULTIPLIERENTRY, defaultPrm.caMultiplier[0]); + caMultiplier[1] = group.readEntry(OPTIONCABLUEMULTIPLIERENTRY, defaultPrm.caMultiplier[1]); + RAWQuality = (DecodingQuality) + group.readEntry(OPTIONDECODINGQUALITYENTRY, (int)defaultPrm.RAWQuality); + outputColorSpace = (OutputColorSpace) + group.readEntry(OPTIONOUTPUTCOLORSPACEENTRY, (int)defaultPrm.outputColorSpace); + autoBrightness = group.readEntry(OPTIONAUTOBRIGHTNESSENTRY, defaultPrm.autoBrightness); + + //-- Extended demosaicing settings ---------------------------------------------------------- + + dcbIterations = group.readEntry(OPTIONDCBITERATIONSENTRY, defaultPrm.dcbIterations); + dcbEnhanceFl = group.readEntry(OPTIONDCBENHANCEFLENTRY, defaultPrm.dcbEnhanceFl); + eeciRefine = group.readEntry(OPTIONEECIREFINEENTRY, defaultPrm.eeciRefine); + esMedPasses = group.readEntry(OPTIONESMEDPASSESENTRY, defaultPrm.esMedPasses); + NRChroThreshold = group.readEntry(OPTIONNRCHROMINANCETHRESHOLDENTRY, defaultPrm.NRChroThreshold); + expoCorrection = group.readEntry(OPTIONEXPOCORRECTIONENTRY, defaultPrm.expoCorrection); + expoCorrectionShift = group.readEntry(OPTIONEXPOCORRECTIONSHIFTENTRY, defaultPrm.expoCorrectionShift); + expoCorrectionHighlight = group.readEntry(OPTIONEXPOCORRECTIONHIGHLIGHTENTRY, defaultPrm.expoCorrectionHighlight); +} + +void RawDecodingSettings::writeSettings(KConfigGroup& group) +{ + group.writeEntry(OPTIONFIXCOLORSHIGHLIGHTSENTRY, fixColorsHighlights); + group.writeEntry(OPTIONDECODESIXTEENBITENTRY, sixteenBitsImage); + group.writeEntry(OPTIONWHITEBALANCEENTRY, (int)whiteBalance); + group.writeEntry(OPTIONCUSTOMWHITEBALANCEENTRY, customWhiteBalance); + group.writeEntry(OPTIONCUSTOMWBGREENENTRY, customWhiteBalanceGreen); + group.writeEntry(OPTIONFOURCOLORRGBENTRY, RGBInterpolate4Colors); + group.writeEntry(OPTIONUNCLIPCOLORSENTRY, unclipColors); + group.writeEntry(OPTIONDONTSTRETCHPIXELSENTRY, DontStretchPixels); + group.writeEntry(OPTIONNOISEREDUCTIONTYPEENTRY, (int)NRType); + group.writeEntry(OPTIONBRIGHTNESSMULTIPLIERENTRY, brightness); + group.writeEntry(OPTIONUSEBLACKPOINTENTRY, enableBlackPoint); + group.writeEntry(OPTIONBLACKPOINTENTRY, blackPoint); + group.writeEntry(OPTIONUSEWHITEPOINTENTRY, enableWhitePoint); + group.writeEntry(OPTIONWHITEPOINTENTRY, whitePoint); + group.writeEntry(OPTIONMEDIANFILTERPASSESENTRY, medianFilterPasses); + group.writeEntry(OPTIONNOISEREDUCTIONTHRESHOLDENTRY, NRThreshold); + group.writeEntry(OPTIONUSECACORRECTIONENTRY, enableCACorrection); + group.writeEntry(OPTIONCAREDMULTIPLIERENTRY, caMultiplier[0]); + group.writeEntry(OPTIONCABLUEMULTIPLIERENTRY, caMultiplier[1]); + group.writeEntry(OPTIONDECODINGQUALITYENTRY, (int)RAWQuality); + group.writeEntry(OPTIONOUTPUTCOLORSPACEENTRY, (int)outputColorSpace); + group.writeEntry(OPTIONAUTOBRIGHTNESSENTRY, autoBrightness); + + //-- Extended demosaicing settings ---------------------------------------------------------- + + group.writeEntry(OPTIONDCBITERATIONSENTRY, dcbIterations); + group.writeEntry(OPTIONDCBENHANCEFLENTRY, dcbEnhanceFl); + group.writeEntry(OPTIONEECIREFINEENTRY, eeciRefine); + group.writeEntry(OPTIONESMEDPASSESENTRY, esMedPasses); + group.writeEntry(OPTIONNRCHROMINANCETHRESHOLDENTRY, NRChroThreshold); + group.writeEntry(OPTIONEXPOCORRECTIONENTRY, expoCorrection); + group.writeEntry(OPTIONEXPOCORRECTIONSHIFTENTRY, expoCorrectionShift); + group.writeEntry(OPTIONEXPOCORRECTIONHIGHLIGHTENTRY, expoCorrectionHighlight); +} + +QDebug operator<<(QDebug dbg, const RawDecodingSettings& s) +{ + dbg.nospace() << endl; + dbg.nospace() << "-- RAW DECODING SETTINGS --------------------------------" << endl; + dbg.nospace() << "-- autoBrightness: " << s.autoBrightness << endl; + dbg.nospace() << "-- sixteenBitsImage: " << s.sixteenBitsImage << endl; + dbg.nospace() << "-- brightness: " << s.brightness << endl; + dbg.nospace() << "-- RAWQuality: " << s.RAWQuality << endl; + dbg.nospace() << "-- inputColorSpace: " << s.inputColorSpace << endl; + dbg.nospace() << "-- outputColorSpace: " << s.outputColorSpace << endl; + dbg.nospace() << "-- RGBInterpolate4Colors: " << s.RGBInterpolate4Colors << endl; + dbg.nospace() << "-- DontStretchPixels: " << s.DontStretchPixels << endl; + dbg.nospace() << "-- unclipColors: " << s.unclipColors << endl; + dbg.nospace() << "-- whiteBalance: " << s.whiteBalance << endl; + dbg.nospace() << "-- customWhiteBalance: " << s.customWhiteBalance << endl; + dbg.nospace() << "-- customWhiteBalanceGreen: " << s.customWhiteBalanceGreen << endl; + dbg.nospace() << "-- halfSizeColorImage: " << s.halfSizeColorImage << endl; + dbg.nospace() << "-- enableBlackPoint: " << s.enableBlackPoint << endl; + dbg.nospace() << "-- blackPoint: " << s.blackPoint << endl; + dbg.nospace() << "-- enableWhitePoint: " << s.enableWhitePoint << endl; + dbg.nospace() << "-- whitePoint: " << s.whitePoint << endl; + dbg.nospace() << "-- NoiseReductionType: " << s.NRType << endl; + dbg.nospace() << "-- NoiseReductionThreshold: " << s.NRThreshold << endl; + dbg.nospace() << "-- enableCACorrection: " << s.enableCACorrection << endl; + dbg.nospace() << "-- caMultiplier: " << s.caMultiplier[0] + << ", " << s.caMultiplier[1] << endl; + dbg.nospace() << "-- medianFilterPasses: " << s.medianFilterPasses << endl; + dbg.nospace() << "-- inputProfile: " << s.inputProfile << endl; + dbg.nospace() << "-- outputProfile: " << s.outputProfile << endl; + dbg.nospace() << "-- deadPixelMap: " << s.deadPixelMap << endl; + dbg.nospace() << "-- whiteBalanceArea: " << s.whiteBalanceArea << endl; + + //-- Extended demosaicing settings ---------------------------------------------------------- + + dbg.nospace() << "-- dcbIterations: " << s.dcbIterations << endl; + dbg.nospace() << "-- dcbEnhanceFl: " << s.dcbEnhanceFl << endl; + dbg.nospace() << "-- eeciRefine: " << s.eeciRefine << endl; + dbg.nospace() << "-- esMedPasses: " << s.esMedPasses << endl; + dbg.nospace() << "-- NRChrominanceThreshold: " << s.NRChroThreshold << endl; + dbg.nospace() << "-- expoCorrection: " << s.expoCorrection << endl; + dbg.nospace() << "-- expoCorrectionShift: " << s.expoCorrectionShift << endl; + dbg.nospace() << "-- expoCorrectionHighlight: " << s.expoCorrectionHighlight << endl; + dbg.nospace() << "---------------------------------------------------------" << endl; + + return dbg.space(); +} + +} // namespace KDcrawIface diff --git a/libkdcraw/libkdcraw/rawdecodingsettings.h b/libkdcraw/libkdcraw/rawdecodingsettings.h new file mode 100644 index 00000000..db09e463 --- /dev/null +++ b/libkdcraw/libkdcraw/rawdecodingsettings.h @@ -0,0 +1,372 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-12-09 + * @brief Raw decoding settings + * + * @author Copyright (C) 2006-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2013 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * @author Copyright (C) 2007-2008 by Guillaume Castagnino + * casta at xwing dot info + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef RAW_DECODING_SETTINGS_H +#define RAW_DECODING_SETTINGS_H + +// Qt includes + +#include +#include +#include + +// KDE includes + +#include + +// Local includes + +#include "libkdcraw_export.h" + +namespace KDcrawIface +{ + +class LIBKDCRAW_EXPORT RawDecodingSettings +{ + +public: + + /** RAW decoding Interpolation methods + * + * NOTE: from original dcraw demosaic + * + * Bilinear: use high-speed but low-quality bilinear + * interpolation (default - for slow computer). In this method, + * the red value of a non-red pixel is computed as the average of + * the adjacent red pixels, and similar for blue and green. + * VNG: use Variable Number of Gradients interpolation. + * This method computes gradients near the pixel of interest and uses + * the lower gradients (representing smoother and more similar parts + * of the image) to make an estimate. + * PPG: use Patterned Pixel Grouping interpolation. + * Pixel Grouping uses assumptions about natural scenery in making estimates. + * It has fewer color artifacts on natural images than the Variable Number of + * Gradients method. + * AHD: use Adaptive Homogeneity-Directed interpolation. + * This method selects the direction of interpolation so as to + * maximize a homogeneity metric, thus typically minimizing color artifacts. + * + * NOTE: from GPL2 demosaic pack. + * + * DCB: DCB interpolation (see http://www.linuxphoto.org/html/dcb.html for details) + * PL_AHD: modified AHD interpolation (see http://sites.google.com/site/demosaicalgorithms/modified-dcraw + * for details). + * AFD: demosaicing through 5 pass median filter from PerfectRaw project. + * VCD: VCD interpolation. + * VCD_AHD: mixed demosaicing between VCD and AHD. + * LMMSE: LMMSE interpolation from PerfectRaw. + * + * NOTE: from GPL3 demosaic pack. + * + * AMAZE: AMaZE interpolation and color aberration removal from RawTherapee project. + */ + enum DecodingQuality + { + // from original dcraw demosaic + BILINEAR = 0, + VNG = 1, + PPG = 2, + AHD = 3, + // Extended demosaicing method from GPL2 demosaic pack + DCB = 4, + PL_AHD = 5, + AFD = 6, + VCD = 7, + VCD_AHD = 8, + LMMSE = 9, + // Extended demosaicing methods from GPL3 demosaic pack + AMAZE = 10 + }; + + /** White balances alternatives + * NONE: no white balance used : reverts to standard daylight D65 WB. + * CAMERA: Use the camera embedded WB if available. Reverts to NONE if not. + * AUTO: Averages an auto WB on the entire image. + * CUSTOM: Let use set it's own temperature and green factor (later converted to RGBG factors). + * AERA: Let use an aera from image to average white balance (see whiteBalanceArea for details). + */ + enum WhiteBalance + { + NONE = 0, + CAMERA = 1, + AUTO = 2, + CUSTOM = 3, + AERA = 4 + }; + + /** Noise Reduction method to apply before demosaicing + * NONR: No noise reduction. + * WAVELETSNR: wavelets correction to erase noise while preserving real detail. It's applied after interpolation. + * FBDDNR: Fake Before Demosaicing Denoising noise reduction. It's applied before interpolation. + * LINENR: CFA Line Denoise. It's applied after interpolation. + * IMPULSENR: Impulse Denoise. It's applied after interpolation. + */ + enum NoiseReduction + { + NONR = 0, + WAVELETSNR, + FBDDNR, + LINENR, + IMPULSENR + }; + + /** Input color profile used to decoded image + * NOINPUTCS: No input color profile. + * EMBEDDED: Use the camera profile embedded in RAW file if exist. + * CUSTOMINPUTCS: Use a custom input color space profile. + */ + enum InputColorSpace + { + NOINPUTCS = 0, + EMBEDDED, + CUSTOMINPUTCS + }; + + /** Output RGB color space used to decoded image + * RAWCOLOR: No output color profile (Linear RAW). + * SRGB: Use standard sRGB color space. + * ADOBERGB: Use standard Adobe RGB color space. + * WIDEGAMMUT: Use standard RGB Wide Gamut color space. + * PROPHOTO: Use standard RGB Pro Photo color space. + * CUSTOMOUTPUTCS: Use a custom workspace color profile. + */ + enum OutputColorSpace + { + RAWCOLOR = 0, + SRGB, + ADOBERGB, + WIDEGAMMUT, + PROPHOTO, + CUSTOMOUTPUTCS + }; + + /** Standard constructor with default settings + */ + RawDecodingSettings(); + + /** Equivalent to the copy constructor + */ + RawDecodingSettings& operator=(const RawDecodingSettings& prm); + + /** Compare for equality + */ + bool operator==(const RawDecodingSettings& o) const; + + /** Standard destructor + */ + virtual ~RawDecodingSettings(); + + /** Method to use a settings to optimize time loading, for exemple to compute image histogram + */ + void optimizeTimeLoading(); + + /** Methods to read/write settings from/to a config file + */ + void readSettings(KConfigGroup& group); + void writeSettings(KConfigGroup& group); + +public: + + /** If true, images with overblown channels are processed much more accurate, + * without 'pink clouds' (and blue highlights under tungsteen lamps). + */ + bool fixColorsHighlights; + + /** If false, use a fixed white level, ignoring the image histogram. + */ + bool autoBrightness; + + /** Turn on RAW file decoding in 16 bits per color per pixel instead 8 bits. + */ + bool sixteenBitsImage; + + /** Half-size color image decoding (twice as fast as "enableRAWQuality"). + * Turn on this option to reduce time loading to render histogram for example, + * no to render an image to screen. + */ + bool halfSizeColorImage; + + /** White balance type to use. See WhiteBalance values for detail + */ + WhiteBalance whiteBalance; + + /** The temperature and the green multiplier of the custom white balance + */ + int customWhiteBalance; + double customWhiteBalanceGreen; + + /** Turn on RAW file decoding using RGB interpolation as four colors. + */ + bool RGBInterpolate4Colors; + + /** For cameras with non-square pixels, do not stretch the image to its + * correct aspect ratio. In any case, this option guarantees that each + * output pixel corresponds to one RAW pixel. + */ + bool DontStretchPixels; + + /** Unclip Highlight color level: + * 0 = Clip all highlights to solid white. + * 1 = Leave highlights unclipped in various shades of pink. + * 2 = Blend clipped and unclipped values together for a gradual + * fade to white. + * 3-9 = Reconstruct highlights. Low numbers favor whites; high numbers + * favor colors. + */ + int unclipColors; + + /** RAW quality decoding factor value. See DecodingQuality values + * for details. + */ + DecodingQuality RAWQuality; + + /** After interpolation, clean up color artifacts by repeatedly applying + * a 3x3 median filter to the R-G and B-G channels. + */ + int medianFilterPasses; + + /** Noise reduction method to apply before demosaicing. + */ + NoiseReduction NRType; + + /** Noise reduction threshold value. Null value disable NR. Range is between 100 and 1000. + * For IMPULSENR : set the amount of Luminance impulse denoise. + */ + int NRThreshold; + + /** Turn on chromatic aberrations correction + */ + bool enableCACorrection; + + /** Magnification factor for Red and Blue layers + * - caMultiplier[0] = amount of correction on red-green axis. + * - caMultiplier[1] = amount of correction on blue-yellow axis. + * - Both values set to 0.0 = automatic CA correction. + */ + double caMultiplier[2]; + + /** Brightness of output image. + */ + double brightness; + + /** Turn on the black point setting to decode RAW image. + */ + bool enableBlackPoint; + + /** Black Point value of output image. + */ + int blackPoint; + + /** Turn on the white point setting to decode RAW image. + */ + bool enableWhitePoint; + + /** White Point value of output image. + */ + int whitePoint; + + /** The input color profile used to decoded RAW data. See OutputColorProfile + * values for details. + */ + InputColorSpace inputColorSpace; + + /** Path to custom input ICC profile to define the camera's raw colorspace. + */ + QString inputProfile; + + /** The output color profile used to decoded RAW data. See OutputColorProfile + * values for details. + */ + OutputColorSpace outputColorSpace; + + /** Path to custom output ICC profile to define the color workspace. + */ + QString outputProfile; + + /** Path to text file including dead pixel list. + */ + QString deadPixelMap; + + /** Rectangle used to calculate the white balance by averaging the region of image. + */ + QRect whiteBalanceArea; + + //-- Extended demosaicing settings ---------------------------------------------------------- + + /// For DCB interpolation. + + /** Number of DCB median filtering correction passes. + * -1 : disable (default) + * 1-10 : DCB correction passes + */ + int dcbIterations; + + /** Turn on the DCB interpolation with enhance interpolated colors. + */ + bool dcbEnhanceFl; + + /// For VCD_AHD interpolation. + + /** Turn on the EECI refine for VCD Demosaicing. + */ + bool eeciRefine; + + /** Use edge-sensitive median filtering for artifact supression after VCD demosaicing. + * 0 : disable (default) + * 1-10 : median filter passes. + */ + int esMedPasses; + + /** For IMPULSENR Noise reduction. Set the amount of Chrominance impulse denoise. + Null value disable NR. Range is between 100 and 1000. + */ + int NRChroThreshold; + + /** Turn on the Exposure Correction before interpolation. + */ + bool expoCorrection; + + /** Shift of Exposure Correction before interpolation in linear scale. + * Usable range is from 0.25 (darken image 1 stop : -2EV) to 8.0 (lighten ~1.5 photographic stops : +3EV). + */ + double expoCorrectionShift; + + /** Amount of highlight preservation for exposure correction before interpolation in E.V. + * Usable range is from 0.0 (linear exposure shift, highlights may blow) to 1.0 (maximum highlights preservation) + * This settings can only take effect if expoCorrectionShift > 1.0. + */ + double expoCorrectionHighlight; +}; + +//! kDebug() stream operator. Writes settings @a s to the debug output in a nicely formatted way. +LIBKDCRAW_EXPORT QDebug operator<<(QDebug dbg, const RawDecodingSettings& s); + +} // namespace KDcrawIface + +#endif /* RAW_DECODING_SETTINGS_H */ diff --git a/libkdcraw/libkdcraw/rawfiles.h b/libkdcraw/libkdcraw/rawfiles.h new file mode 100644 index 00000000..00682353 --- /dev/null +++ b/libkdcraw/libkdcraw/rawfiles.h @@ -0,0 +1,99 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2005-11-06 + * @brief list of RAW file extensions supported by libraw + * + * @author Copyright (C) 2005-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef RAW_FILES_H +#define RAW_FILES_H + +// NOTE: extension list Version 1 and 2 are taken from http://www.cybercom.net/~dcoffin/dcraw/rawphoto.c + +// Ext Descriptions From +// www.file-extensions.org +// en.wikipedia.org/wiki/RAW_file_format +// filext.com + +static const char raw_file_extentions[] = + +// NOTE: VERSION 1 + "*.bay " // Casio Digital Camera Raw File Format. + "*.bmq " // NuCore Raw Image File. + "*.cr2 " // Canon Digital Camera RAW Image Format version 2.0. These images are based on the TIFF image standard. + "*.crw " // Canon Digital Camera RAW Image Format version 1.0. + "*.cs1 " // Capture Shop Raw Image File. + "*.dc2 " // Kodak DC25 Digital Camera File. + "*.dcr " // Kodak Digital Camera Raw Image Format for these models: Kodak DSC Pro SLR/c, Kodak DSC Pro SLR/n, Kodak DSC Pro 14N, Kodak DSC PRO 14nx. + "*.dng " // Adobe Digital Negative: DNG is publicly available archival format for the raw files generated by digital cameras. By addressing the lack of an open standard for the raw files created by individual camera models, DNG helps ensure that photographers will be able to access their files in the future. + "*.erf " // Epson Digital Camera Raw Image Format. + "*.fff " // Imacon Digital Camera Raw Image Format. + "*.hdr " // Leaf Raw Image File. + "*.k25 " // Kodak DC25 Digital Camera Raw Image Format. + "*.kdc " // Kodak Digital Camera Raw Image Format. + "*.mdc " // Minolta RD175 Digital Camera Raw Image Format. + "*.mos " // Mamiya Digital Camera Raw Image Format. + "*.mrw " // Minolta Dimage Digital Camera Raw Image Format. + "*.nef " // Nikon Digital Camera Raw Image Format. + "*.orf " // Olympus Digital Camera Raw Image Format. + "*.pef " // Pentax Digital Camera Raw Image Format. + "*.pxn " // Logitech Digital Camera Raw Image Format. + "*.raf " // Fuji Digital Camera Raw Image Format. + "*.raw " // Panasonic Digital Camera Image Format. + "*.rdc " // Digital Foto Maker Raw Image File. + "*.sr2 " // Sony Digital Camera Raw Image Format. + "*.srf " // Sony Digital Camera Raw Image Format for DSC-F828 8 megapixel digital camera or Sony DSC-R1 + "*.x3f " // Sigma Digital Camera Raw Image Format for devices based on Foveon X3 direct image sensor. + "*.arw " // Sony Digital Camera Raw Image Format for Alpha devices. + +// NOTE: VERSION 2 + + "*.3fr " // Hasselblad Digital Camera Raw Image Format. + "*.cine " // Phantom Software Raw Image File. + "*.ia " // Sinar Raw Image File. + "*.kc2 " // Kodak DCS200 Digital Camera Raw Image Format. + "*.mef " // Mamiya Digital Camera Raw Image Format. + "*.nrw " // Nikon Digital Camera Raw Image Format. + "*.qtk " // Apple Quicktake 100/150 Digital Camera Raw Image Format. + "*.rw2 " // Panasonic LX3 Digital Camera Raw Image Format. + "*.sti " // Sinar Capture Shop Raw Image File. + +// NOTE: VERSION 3 + + "*.rwl " // Leica Digital Camera Raw Image Format. + +// NOTE: VERSION 4 + + "*.srw "; // Samnsung Raw Image Format. + +/* TODO: check if these format are supported + "*.drf " // Kodak Digital Camera Raw Image Format. + "*.dsc " // Kodak Digital Camera Raw Image Format. + "*.ptx " // Pentax Digital Camera Raw Image Format. + "*.cap " // Phase One Digital Camera Raw Image Format. + "*.iiq " // Phase One Digital Camera Raw Image Format. + "*.rwz " // Rawzor Digital Camera Raw Image Format. +*/ + +// increment this number whenever you change the above string +static const int raw_file_extensions_version = 4; + +#endif // RAW_FILES_H diff --git a/libkdcraw/libkdcraw/rcombobox.cpp b/libkdcraw/libkdcraw/rcombobox.cpp new file mode 100644 index 00000000..e140e5f0 --- /dev/null +++ b/libkdcraw/libkdcraw/rcombobox.cpp @@ -0,0 +1,149 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2008-08-16 + * @brief a combo box widget re-implemented with a + * reset button to switch to a default item + * + * @author Copyright (C) 2008-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "moc_rcombobox.cpp" + +// Qt includes + +#include + +// KDE includes + +#include +#include +#include + +namespace KDcrawIface +{ + +class RComboBox::Private +{ + +public: + + Private() + { + defaultIndex = 0; + resetButton = 0; + combo = 0; + } + + int defaultIndex; + + QToolButton* resetButton; + + KComboBox* combo; +}; + +RComboBox::RComboBox(QWidget* const parent) + : KHBox(parent), d(new Private) +{ + d->combo = new KComboBox(this); + d->resetButton = new QToolButton(this); + d->resetButton->setAutoRaise(true); + d->resetButton->setFocusPolicy(Qt::NoFocus); + d->resetButton->setIcon(SmallIcon("document-revert")); + d->resetButton->setToolTip(i18nc("@info:tooltip", "Reset to default value")); + + setStretchFactor(d->combo, 10); + setMargin(0); + setSpacing(KDialog::spacingHint()); + + // ------------------------------------------------------------- + + connect(d->resetButton, SIGNAL(clicked()), + this, SLOT(slotReset())); + + connect(d->combo, SIGNAL(activated(int)), + this, SLOT(slotItemActivated(int))); + + connect(d->combo, SIGNAL(currentIndexChanged(int)), + this, SLOT(slotCurrentIndexChanged(int))); +} + +RComboBox::~RComboBox() +{ + delete d; +} + +KComboBox* RComboBox::combo() const +{ + return d->combo; +} + +void RComboBox::addItem(const QString& t, int index) +{ + d->combo->addItem(t, index); +} + +void RComboBox::insertItem(int index, const QString& t) +{ + d->combo->insertItem(index, t); +} + +int RComboBox::currentIndex() const +{ + return d->combo->currentIndex(); +} + +void RComboBox::setCurrentIndex(int v) +{ + d->combo->setCurrentIndex(v); +} + +int RComboBox::defaultIndex() const +{ + return d->defaultIndex; +} + +void RComboBox::setDefaultIndex(int v) +{ + d->defaultIndex = v; + d->combo->setCurrentIndex(d->defaultIndex); + slotItemActivated(v); +} + +void RComboBox::slotReset() +{ + d->combo->setCurrentIndex(d->defaultIndex); + d->resetButton->setEnabled(false); + slotItemActivated(d->defaultIndex); + emit reset(); +} + +void RComboBox::slotItemActivated(int v) +{ + d->resetButton->setEnabled(v != d->defaultIndex); + emit activated(v); +} + +void RComboBox::slotCurrentIndexChanged(int v) +{ + d->resetButton->setEnabled(v != d->defaultIndex); + emit currentIndexChanged(v); +} + +} // namespace KDcrawIface diff --git a/libkdcraw/libkdcraw/rcombobox.h b/libkdcraw/libkdcraw/rcombobox.h new file mode 100644 index 00000000..bb475cee --- /dev/null +++ b/libkdcraw/libkdcraw/rcombobox.h @@ -0,0 +1,86 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2008-08-16 + * @brief a combo box widget re-implemented with a + * reset button to switch to a default item + * + * @author Copyright (C) 2008-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef RCOMBOBOX_H +#define RCOMBOBOX_H + +// KDE includes + +#include +#include + +// Local includes + +#include "libkdcraw_export.h" + +namespace KDcrawIface +{ + +class LIBKDCRAW_EXPORT RComboBox : public KHBox +{ + + Q_OBJECT + +public: + + RComboBox(QWidget* const parent=0); + ~RComboBox(); + + void setCurrentIndex(int d); + int currentIndex() const; + + void setDefaultIndex(int d); + int defaultIndex() const; + + KComboBox* combo() const; + + void addItem(const QString& t, int index = -1); + void insertItem(int index, const QString& t); + +Q_SIGNALS: + + void reset(); + void activated(int); + void currentIndexChanged(int); + +public Q_SLOTS: + + void slotReset(); + +private Q_SLOTS: + + void slotItemActivated(int); + void slotCurrentIndexChanged(int); + +private: + + class Private; + Private* const d; +}; + +} // namespace KDcrawIface + +#endif /* RCOMBOBOX_H */ diff --git a/libkdcraw/libkdcraw/rexpanderbox.cpp b/libkdcraw/libkdcraw/rexpanderbox.cpp new file mode 100644 index 00000000..b74ec0d9 --- /dev/null +++ b/libkdcraw/libkdcraw/rexpanderbox.cpp @@ -0,0 +1,827 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2008-03-14 + * @brief A widget to host settings as expander box + * + * @author Copyright (C) 2008-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2008-2013 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * @author Copyright (C) 2010 by Manuel Viet + * contact at 13zenrv dot fr + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "moc_rexpanderbox.cpp" + +// Qt includes + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// KDE includes + +#include +#include +#include +#include +#include + +namespace KDcrawIface +{ + +RClickLabel::RClickLabel(QWidget* const parent) + : QLabel(parent) +{ + setCursor(Qt::PointingHandCursor); +} + +RClickLabel::RClickLabel(const QString& text, QWidget* const parent) + : QLabel(text, parent) +{ + setCursor(Qt::PointingHandCursor); +} + +RClickLabel::~RClickLabel() +{ +} + +void RClickLabel::mousePressEvent(QMouseEvent* event) +{ + QLabel::mousePressEvent(event); + + /* + * In some contexts, like QGraphicsView, there will be no + * release event if the press event was not accepted. + */ + if (event->button() == Qt::LeftButton) + { + event->accept(); + } +} + +void RClickLabel::mouseReleaseEvent(QMouseEvent* event) +{ + QLabel::mouseReleaseEvent(event); + + if (event->button() == Qt::LeftButton) + { + emit leftClicked(); + emit activated(); + event->accept(); + } +} + +void RClickLabel::keyPressEvent(QKeyEvent* e) +{ + switch (e->key()) + { + case Qt::Key_Down: + case Qt::Key_Right: + case Qt::Key_Space: + emit activated(); + return; + default: + break; + } + + QLabel::keyPressEvent(e); +} + +// ------------------------------------------------------------------------ + +RSqueezedClickLabel::RSqueezedClickLabel(QWidget* const parent) + : KSqueezedTextLabel(parent) +{ + setCursor(Qt::PointingHandCursor); +} + +RSqueezedClickLabel::RSqueezedClickLabel(const QString& text, QWidget* const parent) + : KSqueezedTextLabel(text, parent) +{ + setCursor(Qt::PointingHandCursor); +} + +RSqueezedClickLabel::~RSqueezedClickLabel() +{ +} + +void RSqueezedClickLabel::mouseReleaseEvent(QMouseEvent* event) +{ + KSqueezedTextLabel::mouseReleaseEvent(event); + + if (event->button() == Qt::LeftButton) + { + emit leftClicked(); + emit activated(); + event->accept(); + } +} + +void RSqueezedClickLabel::mousePressEvent(QMouseEvent* event) +{ + QLabel::mousePressEvent(event); + + /* + * In some contexts, like QGraphicsView, there will be no + * release event if the press event was not accepted. + */ + if (event->button() == Qt::LeftButton) + { + event->accept(); + } +} + +void RSqueezedClickLabel::keyPressEvent(QKeyEvent* e) +{ + switch (e->key()) + { + case Qt::Key_Down: + case Qt::Key_Right: + case Qt::Key_Space: + emit activated(); + return; + default: + break; + } + + QLabel::keyPressEvent(e); +} + +// ------------------------------------------------------------------------ + +RArrowClickLabel::RArrowClickLabel(QWidget* const parent) + : QWidget(parent), m_arrowType(Qt::DownArrow) +{ + setCursor(Qt::PointingHandCursor); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + m_size = 8; + m_margin = 2; +} + +void RArrowClickLabel::setArrowType(Qt::ArrowType type) +{ + m_arrowType = type; + update(); +} + +RArrowClickLabel::~RArrowClickLabel() +{ +} + +Qt::ArrowType RArrowClickLabel::arrowType() const +{ + return m_arrowType; +} + +void RArrowClickLabel::mousePressEvent(QMouseEvent* event) +{ + /* + * In some contexts, like QGraphicsView, there will be no + * release event if the press event was not accepted. + */ + if (event->button() == Qt::LeftButton) + { + event->accept(); + } +} + +void RArrowClickLabel::mouseReleaseEvent(QMouseEvent* event) +{ + if (event->button() == Qt::LeftButton) + { + emit leftClicked(); + } +} + +void RArrowClickLabel::paintEvent(QPaintEvent*) +{ + // Inspired by karrowbutton.cpp, + // Copyright (C) 2001 Frerich Raabe + + QPainter p(this); + + QStyleOptionFrame opt; + opt.init(this); + opt.lineWidth = 2; + opt.midLineWidth = 0; + + /* + p.fillRect( rect(), palette().brush( QPalette::Background ) ); + style()->drawPrimitive( QStyle::PE_Frame, &opt, &p, this); + */ + + if (m_arrowType == Qt::NoArrow) + return; + + if (width() < m_size + m_margin || height() < m_size + m_margin) + return; // don't draw arrows if we are too small + + unsigned int x = 0, y = 0; + if (m_arrowType == Qt::DownArrow) + { + x = (width() - m_size) / 2; + y = height() - (m_size + m_margin); + } + else if (m_arrowType == Qt::UpArrow) + { + x = (width() - m_size) / 2; + y = m_margin; + } + else if (m_arrowType == Qt::RightArrow) + { + x = width() - (m_size + m_margin); + y = (height() - m_size) / 2; + } + else // arrowType == LeftArrow + { + x = m_margin; + y = (height() - m_size) / 2; + } + +/* + if (isDown()) + { + ++x; + ++y; + } +*/ + + QStyle::PrimitiveElement e = QStyle::PE_IndicatorArrowLeft; + + switch (m_arrowType) + { + case Qt::LeftArrow: + e = QStyle::PE_IndicatorArrowLeft; + break; + case Qt::RightArrow: + e = QStyle::PE_IndicatorArrowRight; + break; + case Qt::UpArrow: + e = QStyle::PE_IndicatorArrowUp; + break; + case Qt::DownArrow: + e = QStyle::PE_IndicatorArrowDown; + break; + case Qt::NoArrow: + break; + } + + opt.state |= QStyle::State_Enabled; + opt.rect = QRect( x, y, m_size, m_size); + + style()->drawPrimitive( e, &opt, &p, this ); +} + +QSize RArrowClickLabel::sizeHint() const +{ + return QSize(m_size + 2*m_margin, m_size + 2*m_margin); +} + +// ------------------------------------------------------------------------ + +class RLabelExpander::Private +{ + +public: + + Private() + { + clickLabel = 0; + containerWidget = 0; + pixmapLabel = 0; + grid = 0; + arrow = 0; + line = 0; + hbox = 0; + checkBox = 0; + expandByDefault = true; + } + + bool expandByDefault; + + QCheckBox* checkBox; + QLabel* pixmapLabel; + QWidget* containerWidget; + QGridLayout* grid; + + KSeparator* line; + QWidget* hbox; + + RArrowClickLabel* arrow; + RClickLabel* clickLabel; +}; + +RLabelExpander::RLabelExpander(QWidget* const parent) + : QWidget(parent), d(new Private) +{ + d->grid = new QGridLayout(this); + d->line = new KSeparator(Qt::Horizontal, this); + d->hbox = new QWidget(this); + d->arrow = new RArrowClickLabel(d->hbox); + d->checkBox = new QCheckBox(d->hbox); + d->pixmapLabel = new QLabel(d->hbox); + d->clickLabel = new RClickLabel(d->hbox); + + QHBoxLayout* const hlay = new QHBoxLayout(d->hbox); + hlay->addWidget(d->arrow); + hlay->addWidget(d->checkBox); + hlay->addWidget(d->pixmapLabel); + hlay->addWidget(d->clickLabel, 10); + hlay->setMargin(0); + hlay->setSpacing(KDialog::spacingHint()); + + d->pixmapLabel->installEventFilter(this); + d->pixmapLabel->setCursor(Qt::PointingHandCursor); + + d->hbox->setCursor(Qt::PointingHandCursor); + setCheckBoxVisible(false); + + d->grid->addWidget(d->line, 0, 0, 1, 3); + d->grid->addWidget(d->hbox, 1, 0, 1, 3); + d->grid->setColumnStretch(2, 10); + d->grid->setMargin(KDialog::spacingHint()); + d->grid->setSpacing(KDialog::spacingHint()); + + connect(d->arrow, SIGNAL(leftClicked()), + this, SLOT(slotToggleContainer())); + + connect(d->clickLabel, SIGNAL(activated()), + this, SLOT(slotToggleContainer())); + + connect(d->checkBox, SIGNAL(toggled(bool)), + this, SIGNAL(signalToggled(bool))); +} + +RLabelExpander::~RLabelExpander() +{ + delete d; +} + +void RLabelExpander::setCheckBoxVisible(bool b) +{ + d->checkBox->setVisible(b); +} + +bool RLabelExpander::checkBoxIsVisible() const +{ + return d->checkBox->isVisible(); +} + +void RLabelExpander::setChecked(bool b) +{ + d->checkBox->setChecked(b); +} + +bool RLabelExpander::isChecked() const +{ + return d->checkBox->isChecked(); +} + +void RLabelExpander::setLineVisible(bool b) +{ + d->line->setVisible(b); +} + +bool RLabelExpander::lineIsVisible() const +{ + return d->line->isVisible(); +} + +void RLabelExpander::setText(const QString& txt) +{ + d->clickLabel->setText(QString("%1").arg(txt)); +} + +QString RLabelExpander::text() const +{ + return d->clickLabel->text(); +} + +void RLabelExpander::setIcon(const QPixmap& pix) +{ + d->pixmapLabel->setPixmap(pix); +} + +const QPixmap* RLabelExpander::icon() const +{ + return d->pixmapLabel->pixmap(); +} + +void RLabelExpander::setWidget(QWidget* const widget) +{ + if (widget) + { + d->containerWidget = widget; + d->containerWidget->setParent(this); + d->grid->addWidget(d->containerWidget, 2, 0, 1, 3); + } +} + +QWidget* RLabelExpander::widget() const +{ + return d->containerWidget; +} + +void RLabelExpander::setExpandByDefault(bool b) +{ + d->expandByDefault = b; +} + +bool RLabelExpander::isExpandByDefault() const +{ + return d->expandByDefault; +} + +void RLabelExpander::setExpanded(bool b) +{ + if (d->containerWidget) + { + d->containerWidget->setVisible(b); + if (b) + d->arrow->setArrowType(Qt::DownArrow); + else + d->arrow->setArrowType(Qt::RightArrow); + } + + emit signalExpanded(b); +} + +bool RLabelExpander::isExpanded() const +{ + return (d->arrow->arrowType() == Qt::DownArrow); +} + +void RLabelExpander::slotToggleContainer() +{ + if (d->containerWidget) + setExpanded(!d->containerWidget->isVisible()); +} + +bool RLabelExpander::eventFilter(QObject* obj, QEvent* ev) +{ + if ( obj == d->pixmapLabel) + { + if ( ev->type() == QEvent::MouseButtonRelease) + { + slotToggleContainer(); + return false; + } + else + { + return false; + } + } + else + { + // pass the event on to the parent class + return QWidget::eventFilter(obj, ev); + } +} + +// ------------------------------------------------------------------------ + +class RExpanderBox::Private +{ +public: + + Private(RExpanderBox* const box) + { + parent = box; + vbox = 0; + } + + void createItem(int index, QWidget* const w, const QPixmap& pix, const QString& txt, + const QString& objName, bool expandBydefault) + { + RLabelExpander* const exp = new RLabelExpander(parent->viewport()); + exp->setText(txt); + exp->setIcon(pix); + exp->setWidget(w); + exp->setLineVisible(!wList.isEmpty()); + exp->setObjectName(objName); + exp->setExpandByDefault(expandBydefault); + + if (index >= 0) + { + vbox->insertWidget(index, exp); + wList.insert(index, exp); + } + else + { + vbox->addWidget(exp); + wList.append(exp); + } + + parent->connect(exp, SIGNAL(signalExpanded(bool)), + parent, SLOT(slotItemExpanded(bool))); + + parent->connect(exp, SIGNAL(signalToggled(bool)), + parent, SLOT(slotItemToggled(bool))); + } + +public: + + QList wList; + + QVBoxLayout* vbox; + + RExpanderBox* parent; +}; + +RExpanderBox::RExpanderBox(QWidget* const parent) + : QScrollArea(parent), d(new Private(this)) +{ + setFrameStyle(QFrame::NoFrame); + setWidgetResizable(true); + QWidget* const main = new QWidget(viewport()); + d->vbox = new QVBoxLayout(main); + d->vbox->setMargin(0); + d->vbox->setSpacing(KDialog::spacingHint()); + setWidget(main); + + setAutoFillBackground(false); + viewport()->setAutoFillBackground(false); + main->setAutoFillBackground(false); +} + +RExpanderBox::~RExpanderBox() +{ + d->wList.clear(); + delete d; +} + +void RExpanderBox::setCheckBoxVisible(int index, bool b) +{ + if (index > d->wList.count() || index < 0) return; + d->wList[index]->setCheckBoxVisible(b); +} + +bool RExpanderBox::checkBoxIsVisible(int index) const +{ + if (index > d->wList.count() || index < 0) return false; + return d->wList[index]->checkBoxIsVisible(); +} + +void RExpanderBox::setChecked(int index, bool b) +{ + if (index > d->wList.count() || index < 0) return; + d->wList[index]->setChecked(b); +} + +bool RExpanderBox::isChecked(int index) const +{ + if (index > d->wList.count() || index < 0) return false; + return d->wList[index]->isChecked(); +} + +void RExpanderBox::addItem(QWidget* const w, const QPixmap& pix, const QString& txt, + const QString& objName, bool expandBydefault) +{ + d->createItem(-1, w, pix, txt, objName, expandBydefault); +} + +void RExpanderBox::addItem(QWidget* const w, const QString& txt, + const QString& objName, bool expandBydefault) +{ + addItem(w, QPixmap(), txt, objName, expandBydefault); +} + +void RExpanderBox::addStretch() +{ + d->vbox->addStretch(10); +} + +void RExpanderBox::insertItem(int index, QWidget* const w, const QPixmap& pix, const QString& txt, + const QString& objName, bool expandBydefault) +{ + d->createItem(index, w, pix, txt, objName, expandBydefault); +} + +void RExpanderBox::slotItemExpanded(bool b) +{ + RLabelExpander* const exp = dynamic_cast(sender()); + if (exp) + { + int index = indexOf(exp); + emit signalItemExpanded(index, b); + } +} + +void RExpanderBox::slotItemToggled(bool b) +{ + RLabelExpander* const exp = dynamic_cast(sender()); + if (exp) + { + int index = indexOf(exp); + emit signalItemToggled(index, b); + } +} + +void RExpanderBox::insertItem(int index, QWidget* const w, const QString& txt, + const QString& objName, bool expandBydefault) +{ + insertItem(index, w, QPixmap(), txt, objName, expandBydefault); +} + +void RExpanderBox::insertStretch(int index) +{ + d->vbox->insertStretch(index, 10); +} + +void RExpanderBox::removeItem(int index) +{ + if (index > d->wList.count() || index < 0) return; + d->wList[index]->hide(); + d->wList.removeAt(index); +} + +void RExpanderBox::setItemText(int index, const QString& txt) +{ + if (index > d->wList.count() || index < 0) return; + d->wList[index]->setText(txt); +} + +QString RExpanderBox::itemText(int index) const +{ + if (index > d->wList.count() || index < 0) return QString(); + return d->wList[index]->text(); +} + +void RExpanderBox::setItemIcon(int index, const QPixmap& pix) +{ + if (index > d->wList.count() || index < 0) return; + d->wList[index]->setIcon(pix); +} + +const QPixmap* RExpanderBox::itemIcon(int index) const +{ + if (index > d->wList.count() || index < 0) return 0; + return d->wList[index]->icon(); +} + +int RExpanderBox::count() const +{ + return d->wList.count(); +} + +void RExpanderBox::setItemToolTip(int index, const QString& tip) +{ + if (index > d->wList.count() || index < 0) return; + d->wList[index]->setToolTip(tip); +} + +QString RExpanderBox::itemToolTip(int index) const +{ + if (index > d->wList.count() || index < 0) return QString(); + return d->wList[index]->toolTip(); +} + +void RExpanderBox::setItemEnabled(int index, bool enabled) +{ + if (index > d->wList.count() || index < 0) return; + d->wList[index]->setEnabled(enabled); +} + +bool RExpanderBox::isItemEnabled(int index) const +{ + if (index > d->wList.count() || index < 0) return false; + return d->wList[index]->isEnabled(); +} + +RLabelExpander* RExpanderBox::widget(int index) const +{ + if (index > d->wList.count() || index < 0) return 0; + + return d->wList[index]; +} + +int RExpanderBox::indexOf(RLabelExpander* const widget) const +{ + for (int i = 0 ; i < count(); ++i) + { + RLabelExpander* const exp = d->wList[i]; + + if (widget == exp) + return i; + } + return -1; +} + +void RExpanderBox::setItemExpanded(int index, bool b) +{ + if (index > d->wList.count() || index < 0) return; + + RLabelExpander* const exp = d->wList[index]; + + if (!exp) return; + + exp->setExpanded(b); +} + +bool RExpanderBox::isItemExpanded(int index) const +{ + if (index > d->wList.count() || index < 0) return false; + + RLabelExpander* const exp = d->wList[index]; + + if (!exp) return false; + + return (exp->isExpanded()); +} + +void RExpanderBox::readSettings(KConfigGroup& group) +{ + for (int i = 0 ; i < count(); ++i) + { + RLabelExpander* const exp = d->wList[i]; + + if (exp) + { + exp->setExpanded(group.readEntry(QString("%1 Expanded").arg(exp->objectName()), + exp->isExpandByDefault())); + } + } +} + +void RExpanderBox::writeSettings(KConfigGroup& group) +{ + for (int i = 0 ; i < count(); ++i) + { + RLabelExpander* const exp = d->wList[i]; + + if (exp) + { + group.writeEntry(QString("%1 Expanded").arg(exp->objectName()), + exp->isExpanded()); + } + } +} + +// ------------------------------------------------------------------------ + +RExpanderBoxExclusive::RExpanderBoxExclusive(QWidget* const parent) + : RExpanderBox(parent) +{ + setIsToolBox(true); +} + +RExpanderBoxExclusive::~RExpanderBoxExclusive() +{ +} + +void RExpanderBoxExclusive::slotItemExpanded(bool b) +{ + RLabelExpander* const exp = dynamic_cast(sender()); + if (!exp) return; + + if (isToolBox() && b) + { + int item = 0; + + while (item < count()) + { + if (isItemExpanded(item) && item != indexOf(exp)) + { + setItemExpanded(item, false); + } + + item++; + } + } + emit signalItemExpanded(indexOf(exp), b); +} + +void RExpanderBoxExclusive::setIsToolBox(bool b) +{ + m_toolbox = b; +} + +bool RExpanderBoxExclusive::isToolBox() const +{ + return (m_toolbox); +} + +} // namespace KDcrawIface diff --git a/libkdcraw/libkdcraw/rexpanderbox.h b/libkdcraw/libkdcraw/rexpanderbox.h new file mode 100644 index 00000000..ccfc19b2 --- /dev/null +++ b/libkdcraw/libkdcraw/rexpanderbox.h @@ -0,0 +1,299 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2008-03-14 + * @brief A widget to host settings as expander box + * + * @author Copyright (C) 2008-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2008-2013 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * @author Copyright (C) 2010 by Manuel Viet + * contact at 13zenrv dot fr + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef REXPANDERBOX_H +#define REXPANDERBOX_H + +// Qt includes + +#include +#include +#include +#include +#include + +// KDE includes + +#include +#include + +// Local includes + +#include "libkdcraw_export.h" + +namespace KDcrawIface +{ + +class LIBKDCRAW_EXPORT RClickLabel : public QLabel +{ + Q_OBJECT + +public: + + RClickLabel(QWidget* const parent = 0); + explicit RClickLabel(const QString& text, QWidget* const parent = 0); + ~RClickLabel(); + +Q_SIGNALS: + + /// Emitted when activated by left mouse click + void leftClicked(); + /// Emitted when activated, by mouse or key press + void activated(); + +protected: + + virtual void mousePressEvent(QMouseEvent* event); + virtual void mouseReleaseEvent(QMouseEvent* event); + virtual void keyPressEvent(QKeyEvent* event); +}; + +// ------------------------------------------------------------------------- + +class LIBKDCRAW_EXPORT RSqueezedClickLabel : public KSqueezedTextLabel +{ + Q_OBJECT + +public: + + RSqueezedClickLabel(QWidget* const parent = 0); + explicit RSqueezedClickLabel(const QString& text, QWidget* const parent = 0); + ~RSqueezedClickLabel(); + +Q_SIGNALS: + + void leftClicked(); + void activated(); + +protected: + + virtual void mousePressEvent(QMouseEvent* event); + virtual void mouseReleaseEvent(QMouseEvent* event); + virtual void keyPressEvent(QKeyEvent* event); +}; + +// ------------------------------------------------------------------------- + +class LIBKDCRAW_EXPORT RArrowClickLabel : public QWidget +{ + Q_OBJECT + +public: + + RArrowClickLabel(QWidget* const parent = 0); + ~RArrowClickLabel(); + + void setArrowType(Qt::ArrowType arrowType); + Qt::ArrowType arrowType() const; + + virtual QSize sizeHint () const; + +Q_SIGNALS: + + void leftClicked(); + +protected: + + virtual void mousePressEvent(QMouseEvent* event); + virtual void mouseReleaseEvent(QMouseEvent* event); + virtual void paintEvent(QPaintEvent* event); + +protected: + + Qt::ArrowType m_arrowType; + int m_size; + int m_margin; +}; + +// ------------------------------------------------------------------------- + +class LIBKDCRAW_EXPORT RLabelExpander : public QWidget +{ + Q_OBJECT + +public: + + RLabelExpander(QWidget* const parent = 0); + ~RLabelExpander(); + + void setCheckBoxVisible(bool b); + bool checkBoxIsVisible() const; + + void setChecked(bool b); + bool isChecked() const; + + void setLineVisible(bool b); + bool lineIsVisible() const; + + void setText(const QString& txt); + QString text() const; + + void setIcon(const QPixmap& pix); + const QPixmap* icon() const; + + void setWidget(QWidget* const widget); + QWidget* widget() const; + + void setExpanded(bool b); + bool isExpanded() const; + + void setExpandByDefault(bool b); + bool isExpandByDefault() const; + +Q_SIGNALS: + + void signalExpanded(bool); + void signalToggled(bool); + +private Q_SLOTS: + + void slotToggleContainer(); + +private: + + bool eventFilter(QObject* obj, QEvent* ev); + +private: + + class Private; + Private* const d; +}; + +// ------------------------------------------------------------------------- + +class LIBKDCRAW_EXPORT RExpanderBox : public QScrollArea +{ + Q_OBJECT + +public: + + RExpanderBox(QWidget* const parent = 0); + ~RExpanderBox(); + + /** Add RLabelExpander item at end of box layout with these settings : + 'w' : the widget hosted by RLabelExpander. + 'pix' : pixmap used as icon to item title. + 'txt' : text used as item title. + 'objName' : item object name used to read/save expanded settings to rc file. + 'expandBydefault' : item state by default (expanded or not). + */ + void addItem(QWidget* const w, const QPixmap& pix, const QString& txt, + const QString& objName, bool expandBydefault); + void addItem(QWidget* const w, const QString& txt, + const QString& objName, bool expandBydefault); + + /** Insert RLabelExpander item at box layout index with these settings : + 'w' : the widget hosted by RLabelExpander. + 'pix' : pixmap used as icon to item title. + 'txt' : text used as item title. + 'objName' : item object name used to read/save expanded settings to rc file. + 'expandBydefault' : item state by default (expanded or not). + */ + void insertItem(int index, QWidget* const w, const QPixmap& pix, const QString& txt, + const QString& objName, bool expandBydefault); + void insertItem(int index, QWidget* const w, const QString& txt, + const QString& objName, bool expandBydefault); + + void removeItem(int index); + + void setCheckBoxVisible(int index, bool b); + bool checkBoxIsVisible(int index) const; + + void setChecked(int index, bool b); + bool isChecked(int index) const; + + void setItemText(int index, const QString& txt); + QString itemText (int index) const; + + void setItemIcon(int index, const QPixmap& pix); + const QPixmap* itemIcon(int index) const; + + void setItemToolTip(int index, const QString& tip); + QString itemToolTip(int index) const; + + void setItemEnabled(int index, bool enabled); + bool isItemEnabled(int index) const; + + void addStretch(); + void insertStretch(int index); + + void setItemExpanded(int index, bool b); + bool isItemExpanded(int index) const; + + int count() const; + + RLabelExpander* widget(int index) const; + int indexOf(RLabelExpander* const widget) const; + + virtual void readSettings(KConfigGroup& group); + virtual void writeSettings(KConfigGroup& group); + +Q_SIGNALS: + + void signalItemExpanded(int index, bool b); + void signalItemToggled(int index, bool b); + +private Q_SLOTS: + + void slotItemExpanded(bool b); + void slotItemToggled(bool b); + +private: + + class Private; + Private* const d; +}; + +// ------------------------------------------------------------------------- + +class LIBKDCRAW_EXPORT RExpanderBoxExclusive : public RExpanderBox +{ + Q_OBJECT + +public: + + RExpanderBoxExclusive(QWidget* const parent = 0); + ~RExpanderBoxExclusive(); + + /** Show one expander open at most */ + void setIsToolBox(bool b); + bool isToolBox() const; + +private Q_SLOTS: + + void slotItemExpanded(bool b); + +private: + + bool m_toolbox; +}; + +} // namespace KDcrawIface + +#endif // REXPANDERBOX_H diff --git a/libkdcraw/libkdcraw/rnuminput.cpp b/libkdcraw/libkdcraw/rnuminput.cpp new file mode 100644 index 00000000..92b68000 --- /dev/null +++ b/libkdcraw/libkdcraw/rnuminput.cpp @@ -0,0 +1,239 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2008-08-16 + * @brief Integer and double num input widget + * re-implemented with a reset button to switch to + * a default value + * + * @author Copyright (C) 2008-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "moc_rnuminput.cpp" + +// Qt includes + +#include + +// KDE includes + +#include +#include +#include + +namespace KDcrawIface +{ + +class RIntNumInput::Private +{ + +public: + + Private() + { + defaultValue = 0; + resetButton = 0; + input = 0; + } + + int defaultValue; + + QToolButton* resetButton; + + KIntNumInput* input; +}; + +RIntNumInput::RIntNumInput(QWidget* const parent) + : KHBox(parent), d(new Private) +{ + d->input = new KIntNumInput(this); + d->resetButton = new QToolButton(this); + d->resetButton->setAutoRaise(true); + d->resetButton->setFocusPolicy(Qt::NoFocus); + d->resetButton->setIcon(SmallIcon("document-revert")); + d->resetButton->setToolTip(i18nc("@info:tooltip", "Reset to default value")); + + setStretchFactor(d->input, 10); + setMargin(0); + setSpacing(KDialog::spacingHint()); + + // ------------------------------------------------------------- + + connect(d->resetButton, SIGNAL(clicked()), + this, SLOT(slotReset())); + + connect(d->input, SIGNAL(valueChanged(int)), + this, SLOT(slotValueChanged(int))); +} + +RIntNumInput::~RIntNumInput() +{ + delete d; +} + +KIntNumInput* RIntNumInput::input() const +{ + return d->input; +} + +void RIntNumInput::setSliderEnabled(bool b) +{ + d->input->setSliderEnabled(b); +} + +void RIntNumInput::setRange(int min, int max, int step) +{ + d->input->setRange(min, max, step); +} + +int RIntNumInput::value() const +{ + return d->input->value(); +} + +void RIntNumInput::setValue(int v) +{ + d->input->setValue(v); +} + +int RIntNumInput::defaultValue() const +{ + return d->defaultValue; +} + +void RIntNumInput::setDefaultValue(int v) +{ + d->defaultValue = v; + d->input->setValue(d->defaultValue); + slotValueChanged(v); +} + +void RIntNumInput::slotReset() +{ + d->input->setValue(d->defaultValue); + d->resetButton->setEnabled(false); + emit reset(); +} + +void RIntNumInput::slotValueChanged(int v) +{ + d->resetButton->setEnabled(v != d->defaultValue); + emit valueChanged(v); +} + +// ---------------------------------------------------- + +class RDoubleNumInput::Private +{ + +public: + + Private() + { + defaultValue = 0.0; + resetButton = 0; + input = 0; + } + + double defaultValue; + + QToolButton* resetButton; + + KDoubleNumInput* input; +}; + +RDoubleNumInput::RDoubleNumInput(QWidget* const parent) + : KHBox(parent), d(new Private) +{ + d->input = new KDoubleNumInput(this); + d->resetButton = new QToolButton(this); + d->resetButton->setAutoRaise(true); + d->resetButton->setFocusPolicy(Qt::NoFocus); + d->resetButton->setIcon(SmallIcon("document-revert")); + d->resetButton->setToolTip(i18nc("@info:tooltip", "Reset to default value")); + + setStretchFactor(d->input, 10); + setMargin(0); + setSpacing(KDialog::spacingHint()); + + // ------------------------------------------------------------- + + connect(d->resetButton, SIGNAL(clicked()), + this, SLOT(slotReset())); + + connect(d->input, SIGNAL(valueChanged(double)), + this, SLOT(slotValueChanged(double))); +} + +RDoubleNumInput::~RDoubleNumInput() +{ + delete d; +} + +KDoubleNumInput* RDoubleNumInput::input() const +{ + return d->input; +} + +void RDoubleNumInput::setDecimals(int p) +{ + d->input->setDecimals(p); +} + +void RDoubleNumInput::setRange(double min, double max, double step, bool slider) +{ + d->input->setRange(min, max, step, slider); +} + +double RDoubleNumInput::value() const +{ + return d->input->value(); +} + +void RDoubleNumInput::setValue(double v) +{ + d->input->setValue(v); +} + +double RDoubleNumInput::defaultValue() const +{ + return d->defaultValue; +} + +void RDoubleNumInput::setDefaultValue(double v) +{ + d->defaultValue = v; + d->input->setValue(d->defaultValue); + slotValueChanged(v); +} + +void RDoubleNumInput::slotReset() +{ + d->input->setValue(d->defaultValue); + d->resetButton->setEnabled(false); + emit reset(); +} + +void RDoubleNumInput::slotValueChanged(double v) +{ + d->resetButton->setEnabled(v != d->defaultValue); + emit valueChanged(v); +} + +} // namespace KDcrawIface diff --git a/libkdcraw/libkdcraw/rnuminput.h b/libkdcraw/libkdcraw/rnuminput.h new file mode 100644 index 00000000..83ad14fe --- /dev/null +++ b/libkdcraw/libkdcraw/rnuminput.h @@ -0,0 +1,125 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2008-08-16 + * @brief Integer and double num input widget + * re-implemented with a reset button to switch to + * a default value + * + * @author Copyright (C) 2008-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef RNUMINPUT_H +#define RNUMINPUT_H + +// KDE includes + +#include +#include + +// Local includes + +#include "libkdcraw_export.h" + +namespace KDcrawIface +{ + +class LIBKDCRAW_EXPORT RIntNumInput : public KHBox +{ + Q_OBJECT + +public: + + RIntNumInput(QWidget* const parent=0); + ~RIntNumInput(); + + int value() const; + + void setSliderEnabled(bool b); + void setRange(int min, int max, int step); + + void setDefaultValue(int d); + int defaultValue() const; + + KIntNumInput* input() const; + +Q_SIGNALS: + + void reset(); + void valueChanged(int); + +public Q_SLOTS: + + void setValue(int d); + void slotReset(); + +private Q_SLOTS: + + void slotValueChanged(int); + +private: + + class Private; + Private* const d; +}; + +// --------------------------------------------------------- + +class LIBKDCRAW_EXPORT RDoubleNumInput : public KHBox +{ + Q_OBJECT + +public: + + RDoubleNumInput(QWidget* const parent=0); + ~RDoubleNumInput(); + + double value() const; + + void setDecimals(int p); + void setRange(double min, double max, double step, bool slider=true); + + void setDefaultValue(double d); + double defaultValue() const; + + KDoubleNumInput* input() const; + +Q_SIGNALS: + + void reset(); + void valueChanged(double); + +public Q_SLOTS: + + void setValue(double d); + void slotReset(); + +private Q_SLOTS: + + void slotValueChanged(double); + +private: + + class Private; + Private* const d; +}; + +} // namespace KDcrawIface + +#endif /* RNUMINPUT_H */ diff --git a/libkdcraw/libkdcraw/squeezedcombobox.cpp b/libkdcraw/libkdcraw/squeezedcombobox.cpp new file mode 100644 index 00000000..94c893a3 --- /dev/null +++ b/libkdcraw/libkdcraw/squeezedcombobox.cpp @@ -0,0 +1,200 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2008-08-21 + * @brief a combo box with a width not depending of text + * content size + * + * @author Copyright (C) 2006-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2008 by Andi Clemens + * andi dot clemens at googlemail dot com + * @author Copyright (C) 2005 by Tom Albers + * tomalbers at kde dot nl + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "moc_squeezedcombobox.cpp" + +// Qt includes + +#include +#include +#include +#include +#include +#include +#include + +namespace KDcrawIface +{ + +class SqueezedComboBox::Private +{ +public: + + Private() + { + timer = 0; + } + + QMap originalItems; + + QTimer* timer; +}; + +SqueezedComboBox::SqueezedComboBox(QWidget* const parent, const char* name) + : QComboBox(parent), d(new Private) +{ + setObjectName(name); + setMinimumWidth(100); + d->timer = new QTimer(this); + d->timer->setSingleShot(true); + + connect(d->timer, SIGNAL(timeout()), + this, SLOT(slotTimeOut())); + + connect(this, SIGNAL(activated(int)), + SLOT(slotUpdateToolTip(int))); +} + +SqueezedComboBox::~SqueezedComboBox() +{ + d->originalItems.clear(); + delete d->timer; + delete d; +} + +bool SqueezedComboBox::contains(const QString& text) const +{ + if (text.isEmpty()) + return false; + + for (QMap::const_iterator it = d->originalItems.constBegin() ; it != d->originalItems.constEnd(); ++it) + { + if (it.value() == text) + return true; + } + + return false; +} + +QSize SqueezedComboBox::sizeHint() const +{ + ensurePolished(); + QFontMetrics fm = fontMetrics(); + int maxW = count() ? 18 : 7 * fm.width(QChar('x')) + 18; + int maxH = qMax( fm.lineSpacing(), 14 ) + 2; + + QStyleOptionComboBox options; + options.initFrom(this); + + return style()->sizeFromContents(QStyle::CT_ComboBox, &options, + QSize(maxW, maxH), this).expandedTo(QApplication::globalStrut()); +} + +void SqueezedComboBox::insertSqueezedItem(const QString& newItem, int index, + const QVariant& userData) +{ + d->originalItems[index] = newItem; + QComboBox::insertItem(index, squeezeText(newItem), userData); + + // if this is the first item, set the tooltip. + if (index == 0) + slotUpdateToolTip(0); +} + +void SqueezedComboBox::insertSqueezedList(const QStringList& newItems, int index) +{ + for(QStringList::const_iterator it = newItems.constBegin() ; it != newItems.constEnd() ; ++it) + { + insertSqueezedItem(*it, index); + index++; + } +} + +void SqueezedComboBox::addSqueezedItem(const QString& newItem, + const QVariant& userData) +{ + insertSqueezedItem(newItem, count(), userData); +} + +void SqueezedComboBox::setCurrent(const QString& itemText) +{ + QString squeezedText = squeezeText(itemText); + qint32 itemIndex = findText(squeezedText); + + if (itemIndex >= 0) + setCurrentIndex(itemIndex); +} + +void SqueezedComboBox::resizeEvent(QResizeEvent *) +{ + d->timer->start(200); +} + +void SqueezedComboBox::slotTimeOut() +{ + for (QMap::iterator it = d->originalItems.begin() ; it != d->originalItems.end(); ++it) + { + setItemText( it.key(), squeezeText( it.value() ) ); + } +} + +QString SqueezedComboBox::squeezeText(const QString& original) const +{ + // not the complete widgetSize is usable. Need to compensate for that. + int widgetSize = width()-30; + QFontMetrics fm( fontMetrics() ); + + // If we can fit the full text, return that. + if (fm.width(original) < widgetSize) + return(original); + + // We need to squeeze. + QString sqItem = original; // prevent empty return value; + widgetSize = widgetSize-fm.width("..."); + + for (int i = 0 ; i != original.length(); ++i) + { + if ((int)fm.width(original.right(i)) > widgetSize) + { + sqItem = QString(original.left(i) + "..."); + break; + } + } + + return sqItem; +} + +void SqueezedComboBox::slotUpdateToolTip(int index) +{ + setToolTip(d->originalItems[index]); +} + +QString SqueezedComboBox::itemHighlighted() const +{ + int curItem = currentIndex(); + return d->originalItems[curItem]; +} + +QString SqueezedComboBox::item(int index) const +{ + return d->originalItems[index]; +} + +} // namespace KDcrawIface diff --git a/libkdcraw/libkdcraw/squeezedcombobox.h b/libkdcraw/libkdcraw/squeezedcombobox.h new file mode 100644 index 00000000..fe20204f --- /dev/null +++ b/libkdcraw/libkdcraw/squeezedcombobox.h @@ -0,0 +1,165 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2008-08-21 + * @brief a combo box with a width not depending of text + * content size + * + * @author Copyright (C) 2006-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2008 by Andi Clemens + * andi dot clemens at googlemail dot com + * @author Copyright (C) 2005 by Tom Albers + * tomalbers at kde dot nl + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef SQUEEZEDCOMBOBOX_H +#define SQUEEZEDCOMBOBOX_H + +// Qt includes + +#include + +// Local includes + +#include "libkdcraw_export.h" + +namespace KDcrawIface +{ + +/** @class SqueezedComboBox + * + * This widget is a QComboBox, but then a little bit + * different. It only shows the right part of the items + * depending on de size of the widget. When it is not + * possible to show the complete item, it will be shortened + * and "..." will be prepended. + */ +class LIBKDCRAW_EXPORT SqueezedComboBox : public QComboBox +{ + Q_OBJECT + +public: + + /** + * Constructor + * @param parent parent widget + * @param name name to give to the widget + */ + explicit SqueezedComboBox(QWidget* const parent = 0, const char* name = 0 ); + /** + * destructor + */ + virtual ~SqueezedComboBox(); + + /** + * + * Returns true if the combobox contains the original (not-squeezed) + * version of text. + * @param text the original (not-squeezed) text to check for + */ + bool contains(const QString& text) const; + + /** + * This inserts a item to the list. See QComboBox::insertItem() + * for details. Please do not use QComboBox::insertItem() to this + * widget, as that will fail. + * @param newItem the original (long version) of the item which needs + * to be added to the combobox + * @param index the position in the widget. + * @param userData custom meta-data assigned to new item. + */ + void insertSqueezedItem(const QString& newItem, int index, + const QVariant& userData=QVariant()); + + /** + * This inserts items to the list. See QComboBox::insertItems() + * for details. Please do not use QComboBox:: insertItems() to this + * widget, as that will fail. + * @param newItems the originals (long version) of the items which needs + * to be added to the combobox + * @param index the position in the widget. + */ + void insertSqueezedList(const QStringList& newItems, int index); + + /** + * Append an item. + * @param newItem the original (long version) of the item which needs + * to be added to the combobox + * @param userData custom meta-data assigned to new item. + */ + void addSqueezedItem(const QString& newItem, + const QVariant& userData=QVariant()); + + /** + * Set the current item to the one matching the given text. + * + * @param itemText the original (long version) of the item text + */ + void setCurrent(const QString& itemText); + + /** + * This method returns the full text (not squeezed) of the currently + * highlighted item. + * @return full text of the highlighted item + */ + QString itemHighlighted() const; + + /** + * This method returns the full text (not squeezed) for the index. + * @param index the position in the widget. + * @return full text of the item + */ + QString item(int index) const; + + /** + * Sets the sizeHint() of this widget. + */ + virtual QSize sizeHint() const; + +private Q_SLOTS: + + void slotTimeOut(); + void slotUpdateToolTip(int index); + +private: + + void resizeEvent(QResizeEvent*); + QString squeezeText(const QString& original) const; + + // Prevent these from being used. + QString currentText() const; + void setCurrentText(const QString& itemText); + void insertItem(const QString& text); + void insertItem(qint32 index, const QString& text); + void insertItem(int index, const QIcon& icon, const QString& text, const QVariant& userData=QVariant()); + void insertItems(int index, const QStringList& list); + void addItem(const QString& text); + void addItem(const QIcon& icon, const QString& text, const QVariant& userData=QVariant()); + void addItems(const QStringList& texts); + QString itemText(int index) const; + +private: + + class Private; + Private* const d; +}; + +} // namespace KDcrawIface + +#endif // SQUEEZEDCOMBOBOX_H diff --git a/libkdcraw/libkdcraw/version.h.cmake b/libkdcraw/libkdcraw/version.h.cmake new file mode 100644 index 00000000..c93015e3 --- /dev/null +++ b/libkdcraw/libkdcraw/version.h.cmake @@ -0,0 +1,33 @@ +/** =========================================================== + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2007-02-12 + * @brief libraw program interface for KDE + * + * @author Copyright (C) 2007-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef KDCRAW_VERSION_H +#define KDCRAW_VERSION_H + +// Before changing the line below, make sure that FindKdcraw.cmake can still parse it +static const char kdcraw_version[] = "${DCRAW_LIB_VERSION_STRING}"; + +#define KDCRAW_VERSION ${DCRAW_LIB_VERSION_ID} + +#endif // KDCRAW_VERSION_H diff --git a/libkdcraw/profiles/CMakeLists.txt b/libkdcraw/profiles/CMakeLists.txt new file mode 100644 index 00000000..d06b2d40 --- /dev/null +++ b/libkdcraw/profiles/CMakeLists.txt @@ -0,0 +1,28 @@ +# =========================================================== +# +# This file is a part of digiKam project +# http://www.digikam.org +# +# @date 2006-12-09 +# @brief a tread-safe libraw C++ program interface for KDE +# +# @author Copyright (C) 2006-2012 by Gilles Caulier +# caulier dot gilles at gmail dot com +# +# This program is free software; you can redistribute it +# and/or modify it under the terms of the GNU General +# Public License as published by the Free Software Foundation; +# either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# ============================================================ + +FILE(GLOB icmfiles *.icm *.icc) + +INSTALL(FILES ${icmfiles} + DESTINATION ${DATA_INSTALL_DIR}/libkdcraw/profiles ) diff --git a/libkdcraw/profiles/compatibleWithAdobeRGB1998.icc b/libkdcraw/profiles/compatibleWithAdobeRGB1998.icc new file mode 100644 index 00000000..1eedf093 Binary files /dev/null and b/libkdcraw/profiles/compatibleWithAdobeRGB1998.icc differ diff --git a/libkdcraw/profiles/prophoto.icm b/libkdcraw/profiles/prophoto.icm new file mode 100644 index 00000000..82403831 Binary files /dev/null and b/libkdcraw/profiles/prophoto.icm differ diff --git a/libkdcraw/profiles/srgb-d65.icm b/libkdcraw/profiles/srgb-d65.icm new file mode 100644 index 00000000..33f9b34f Binary files /dev/null and b/libkdcraw/profiles/srgb-d65.icm differ diff --git a/libkdcraw/profiles/widegamut.icm b/libkdcraw/profiles/widegamut.icm new file mode 100644 index 00000000..120a99a1 Binary files /dev/null and b/libkdcraw/profiles/widegamut.icm differ diff --git a/libkdcraw/tests/CMakeLists.txt b/libkdcraw/tests/CMakeLists.txt new file mode 100644 index 00000000..3b776869 --- /dev/null +++ b/libkdcraw/tests/CMakeLists.txt @@ -0,0 +1,33 @@ +# =========================================================== +# +# This file is a part of digiKam project +# http://www.digikam.org +# +# @date 2006-12-09 +# @brief a tread-safe libraw C++ program interface for KDE +# +# @author Copyright (C) 2006-2013 by Gilles Caulier +# caulier dot gilles at gmail dot com +# +# This program is free software; you can redistribute it +# and/or modify it under the terms of the GNU General +# Public License as published by the Free Software Foundation; +# either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# ============================================================ + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libkdcraw) + +SET(raw2png_SRCS raw2png.cpp) +ADD_EXECUTABLE(raw2png ${raw2png_SRCS}) +TARGET_LINK_LIBRARIES(raw2png kdcraw ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}) + +SET(libinfo_SRCS libinfo.cpp) +ADD_EXECUTABLE(libinfo ${libinfo_SRCS}) +TARGET_LINK_LIBRARIES(libinfo kdcraw ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}) diff --git a/libkdcraw/tests/libinfo.cpp b/libkdcraw/tests/libinfo.cpp new file mode 100644 index 00000000..e3a05e23 --- /dev/null +++ b/libkdcraw/tests/libinfo.cpp @@ -0,0 +1,49 @@ +/** =========================================================== + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2013-09-07 + * @brief a command line tool to show libkdcraw info + * + * @author Copyright (C) 2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// Qt includes + +#include +#include + +// Local includes + +#include "kdcraw.h" + +using namespace KDcrawIface; + +int main(int /*argc*/, char** /*argv*/) +{ + qDebug() << "Libkdcraw version : " << KDcraw::version(), + qDebug() << "Libraw version : " << KDcraw::librawVersion(); + qDebug() << "Use OpenMP : " << KDcraw::librawUseGomp(); + qDebug() << "Use RawSpeed : " << KDcraw::librawUseRawSpeed(); + qDebug() << "Use GPL2 Pack : " << KDcraw::librawUseGPL2DemosaicPack(); + qDebug() << "Use GPL3 Pack : " << KDcraw::librawUseGPL3DemosaicPack(); + qDebug() << "Raw files list : " << KDcraw::rawFilesList(); + qDebug() << "Raw files version : " << KDcraw::rawFilesVersion(); + qDebug() << "Supported camera : " << KDcraw::supportedCamera(); + + return 0; +} diff --git a/libkdcraw/tests/raw2png.cpp b/libkdcraw/tests/raw2png.cpp new file mode 100644 index 00000000..502a95bc --- /dev/null +++ b/libkdcraw/tests/raw2png.cpp @@ -0,0 +1,138 @@ +/** =========================================================== + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2008-15-09 + * @brief a command line tool to convert RAW file to PNG + * + * @author Copyright (C) 2008-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// Qt includes + +#include +#include +#include +#include + +// Local includes + +#include "kdcraw.h" +#include "rawdecodingsettings.h" + +using namespace KDcrawIface; + +int main(int argc, char** argv) +{ + if(argc != 2) + { + qDebug() << "raw2png - RAW Camera Image to PNG Converter"; + qDebug() << "Usage: "; + return -1; + } + + QString filePath(argv[1]); + QFileInfo input(filePath); + QString previewFilePath(input.baseName() + QString(".preview.png")); + QFileInfo previewOutput(previewFilePath); + QString halfFilePath(input.baseName() + QString(".half.png")); + QFileInfo halfOutput(halfFilePath); + QString fullFilePath(input.baseName() + QString(".full.png")); + QFileInfo fullOutput(fullFilePath); + QImage image; + DcrawInfoContainer identify; + + // ----------------------------------------------------------- + + qDebug() << "raw2png: Identify RAW image from " << input.fileName(); + + KDcraw rawProcessor; + if (!rawProcessor.rawFileIdentify(identify, filePath)) + { + qDebug() << "raw2png: Idendify RAW image failed. Aborted..."; + return -1; + } + + int width = identify.imageSize.width(); + int height = identify.imageSize.height(); + + qDebug() << "raw2png: Raw image info:"; + qDebug() << "--- Date: " << identify.dateTime.toString(Qt::ISODate); + qDebug() << "--- Make: " << identify.make; + qDebug() << "--- Model: " << identify.model; + qDebug() << "--- Size: " << width << "x" << height; + qDebug() << "--- Filter: " << identify.filterPattern; + qDebug() << "--- Colors: " << identify.rawColors; + + // ----------------------------------------------------------- + + qDebug() << "raw2png: Loading RAW image preview"; + + if (!rawProcessor.loadRawPreview(image, filePath)) + { + qDebug() << "raw2png: Loading RAW image preview failed. Aborted..."; + return -1; + } + + qDebug() << "raw2png: Saving preview image to " + << previewOutput.fileName() << " size (" + << image.width() << "x" << image.height() + << ")"; + image.save(previewFilePath, "PNG"); + + // ----------------------------------------------------------- + + qDebug() << "raw2png: Loading half RAW image"; + + image = QImage(); + if (!rawProcessor.loadHalfPreview(image, filePath)) + { + qDebug() << "raw2png: Loading half RAW image failed. Aborted..."; + return -1; + } + + qDebug() << "raw2png: Saving half image to " + << halfOutput.fileName() << " size (" + << image.width() << "x" << image.height() + << ")"; + image.save(halfFilePath, "PNG"); + + // ----------------------------------------------------------- + + qDebug() << "raw2png: Loading full RAW image"; + + image = QImage(); + RawDecodingSettings settings; + settings.halfSizeColorImage = false; + settings.sixteenBitsImage = false; + settings.RGBInterpolate4Colors = false; + settings.RAWQuality = RawDecodingSettings::BILINEAR; + + if (!rawProcessor.loadFullImage(image, filePath, settings)) + { + qDebug() << "raw2png: Loading full RAW image failed. Aborted..."; + return -1; + } + + qDebug() << "raw2png: Saving full RAW image to " + << fullOutput.fileName() << " size (" + << image.width() << "x" << image.height() + << ")"; + image.save(fullFilePath, "PNG"); + + return 0; +} diff --git a/libkexiv2/.gitignore b/libkexiv2/.gitignore new file mode 100644 index 00000000..41554037 --- /dev/null +++ b/libkexiv2/.gitignore @@ -0,0 +1,2 @@ +*.kate-swp +tests/databases/*/*.db diff --git a/libkexiv2/AUTHORS b/libkexiv2/AUTHORS new file mode 100644 index 00000000..b5b7b7b2 --- /dev/null +++ b/libkexiv2/AUTHORS @@ -0,0 +1,11 @@ +AUTHORS AND MAINTAINERS: + +Caulier Gilles +Marcel Wiesweg + +CONTRIBUTORS: + +Angelo Naselli +Gerhard Kulzer +Achim Bohnet +Guillaume Castagnino diff --git a/libkexiv2/CMakeLists.txt b/libkexiv2/CMakeLists.txt new file mode 100644 index 00000000..8aa0d54b --- /dev/null +++ b/libkexiv2/CMakeLists.txt @@ -0,0 +1,69 @@ +# =========================================================== +# +# This file is a part of digiKam project +# http://www.digikam.org +# +# @date 2006-09-15 +# @brief Exiv2 library interface for KDE +# +# @author Copyright (C) 2006-2014 by Gilles Caulier +# caulier dot gilles at gmail dot com +# +# This program is free software; you can redistribute it +# and/or modify it under the terms of the GNU General +# Public License as published by the Free Software Foundation; +# either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# ============================================================ + +PROJECT(libkexiv2) + +MESSAGE(STATUS "----------------------------------------------------------------------------------") +MESSAGE(STATUS "Starting CMake configuration for: libkexiv2") + +FIND_PACKAGE(KDE4 REQUIRED 4.14.3) + +INCLUDE(KDE4Defaults) +INCLUDE(MacroLibrary) +INCLUDE(MacroOptionalAddSubdirectory) +INCLUDE(MacroOptionalFindPackage) +INCLUDE(FindPackageHandleStandardArgs) + +ADD_DEFINITIONS (${QT_DEFINITIONS} ${QT_QTDBUS_DEFINITIONS} ${KDE4_DEFINITIONS}) +INCLUDE_DIRECTORIES (${QDBUS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES}) + +SET(LIBKEXIV2_AREA_CODE_GENERAL 51003) +ADD_DEFINITIONS(-DKDE_DEFAULT_DEBUG_AREA=${LIBKEXIV2_AREA_CODE_GENERAL}) + +SET(EXIV2_MIN_VERSION "0.21") +FIND_PACKAGE(Exiv2) +MACRO_LOG_FEATURE(EXIV2_FOUND "Exiv2" "Required to build libkexiv2." "http://www.exiv2.org" + TRUE ${EXIV2_MIN_VERSION} "") + +# ======================================================= +# Set env. variables accordinly. + +SET(KEXIV2_LIB_VERSION_STRING "${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}.${KDE_VERSION_RELEASE}") +SET(KEXIV2_LIB_VERSION_ID "0x0${KDE_VERSION_MAJOR}0${KDE_VERSION_MINOR}0${KDE_VERSION_RELEASE}") +SET(KEXIV2_LIB_SO_VERSION_STRING "${KDE_VERSION_MAJOR}.${KDE_VERSION_MINOR}.${KDE_VERSION_RELEASE}") + +# ======================================================= + +IF (EXIV2_FOUND) + ADD_SUBDIRECTORY(libkexiv2) + + IF(KDE4_BUILD_TESTS) + MACRO_OPTIONAL_ADD_SUBDIRECTORY(tests) + ENDIF(KDE4_BUILD_TESTS) + + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libkexiv2.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libkexiv2.pc) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libkexiv2.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig ) +ENDIF (EXIV2_FOUND) + +MACRO_DISPLAY_FEATURE_LOG() diff --git a/libkexiv2/COPYING b/libkexiv2/COPYING new file mode 100644 index 00000000..c13faf0d --- /dev/null +++ b/libkexiv2/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libkexiv2/COPYING-CMAKE-SCRIPTS b/libkexiv2/COPYING-CMAKE-SCRIPTS new file mode 100644 index 00000000..4b417765 --- /dev/null +++ b/libkexiv2/COPYING-CMAKE-SCRIPTS @@ -0,0 +1,22 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. diff --git a/libkexiv2/COPYING.LIB b/libkexiv2/COPYING.LIB new file mode 100644 index 00000000..2676d08a --- /dev/null +++ b/libkexiv2/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin St, 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 library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + 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 Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the 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 a program 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. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + 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, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +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 compile 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) 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. + + c) 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. + + d) 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 source code 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 to +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 Library 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. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/libkexiv2/ChangeLog b/libkexiv2/ChangeLog new file mode 100644 index 00000000..09115692 --- /dev/null +++ b/libkexiv2/ChangeLog @@ -0,0 +1,602 @@ +V 0.1.5 - 2007-05-08 +---------------------------------------------------------------------------- +Fixing: libtools version info again, we found not to be back compatible + with libkexiv 0.1.1, unfortunately since 0.1.2 version. + +---------------------------------------------------------------------------- +V 0.1.4 - 2007-05-06 +---------------------------------------------------------------------------- +Fixing: libtools version info + +2007-05-06 21:23 anaselli + + * [r661885] libkexiv2/ChangeLog, libkexiv2/Makefile.am, + libkexiv2/libkexiv2.lsm, libkexiv2/libkexiv2.pc.in, + libkexiv2/version.h: + Release 0.1.4 + - fix libtools version-info + + CCMAIL: kde-imaging@kde.org, digikam-devel@kde.org + +2007-05-06 21:14 anaselli + + * [r661883] libkexiv2/Makefile.am: + Changed to add libtools version managing into prepare script + (hope this will avoid to forget it) + +---------------------------------------------------------------------------- +v 0.1.3 - 2007-05-05 +---------------------------------------------------------------------------- +2007-05-05 14:01 gkulzer + + * [r661413] libkexiv2/ChangeLog: + 0.1.3 release, coordinated with digiKam 0.9.2-beta1 release + +2007-05-05 12:09 gkulzer + + * [r661379] libkexiv2/ChangeLog, libkexiv2/NEWS, + libkexiv2/libkexiv2.lsm: + 0.1.3 release, coordinated with digiKam 0.9.2-beta1 release + +2007-05-02 07:11 cgilles + + * [r660285] libkexiv2/kexiv2.cpp, libkexiv2/kexiv2.h, + libkexiv2/libkexiv2_export.h, libkexiv2/version.h: + fix headers + +2007-05-02 06:42 cgilles + + * [r660276] libkexiv2/kexiv2.cpp, libkexiv2/kexiv2.h: + libkexiv2 from trunk : test if file is readable before to load it + in Exiv2. + CCBUGS: 144895 + + * [r658899] BUG:144455 + thanks a lot to Stéphane Pontier, corrected a lot of spelling errors + and missing mails + M /trunk/extragear/libs/libkexiv2/libkexiv2_export.h + M /trunk/extragear/libs/libkexiv2/kexiv2.cpp + M /trunk/extragear/libs/libkexiv2/version.h + M /trunk/extragear/libs/libkexiv2/kexiv2.h + + * [r658847] GPS problem solved. BUG:144604 + M /trunk/extragear/libs/libkexiv2/kexiv2.cpp + +Gilles patch + * [r658711]M /trunk/extragear/libs/libkexiv2/libkexiv2.pc.in + M /trunk/extragear/libs/libkexiv2/kexiv2.cpp + M /trunk/extragear/libs/libkexiv2/libkexiv2.lsm + M /trunk/extragear/libs/libkexiv2/version.h + M /trunk/extragear/libs/libkexiv2/NEWS + M /trunk/extragear/libs/libkexiv2/README + M /trunk/extragear/libs/libkexiv2/kexiv2.h + +V 0.1.2 - 2007-04-07 +---------------------------------------------------------------------------- +2007-03-26 07:54 cgilles + + * [r646581] libkexiv2/kexiv2.cpp, libkexiv2/kexiv2.h: + libkexiv2 from trunk : polish API : all "get...()" method must + use const operator. + +2007-03-15 11:10 anaselli + + * [r642771] libkexiv2/Makefile.am, libkexiv2/NEWS: + API changed, please check if it is correct. + + CCMAIL: caulier.gilles@kdemail.net + +2007-03-15 09:09 cgilles + + * [r642722] libkexiv2/kexiv2.cpp, libkexiv2/kexiv2.h: + libkexiv2 from trunk : Fix broken compilation with current Exiv2 + implementation (next 0.14.0 release), duing a change with C++ + Exception rule. I recommend to cleanup and recompile this library + and clients program witch use it. + + Note : libkexiv2 still compatible with older Exiv2 releases 0.12 + and 0.13 + + CCMAIL: digikam-devel@kde.org + +2007-03-14 12:12 cgilles + + * [r642432] libkexiv2/NEWS: + --Cette ligupdatene, et les suivantes ci-dessous, seront + ignorées-- + + M NEWS + +2007-03-14 12:11 cgilles + + * [r642431] libkexiv2/kexiv2.cpp: + libkexiv2 from trunk : patch from Arnd Baecker about to avoid the + GPS accuracy loss + BUG: 140297 + +2007-03-14 12:05 cgilles + + * [r642427] libkexiv2/kexiv2.cpp: + sanity check again about empty byte array + +2007-03-14 11:58 cgilles + + * [r642421] libkexiv2/libkexiv2.lsm: + fix version + +2007-03-14 11:58 cgilles + + * [r642420] libkexiv2/libkexiv2.pc.in: + fix version + +2007-03-14 11:57 cgilles + + * [r642419] libkexiv2/version.h: + fix version + +2007-03-11 10:58 cgilles + + * [r641445] libkexiv2/kexiv2.cpp: + libkexiv2 from trunk : when Exiv2 0.14.0 will be available, a new + tag Exif.Image.ProcessingSoftware will be use to store program + informations + +2007-03-11 10:31 cgilles + + * [r641437] libkexiv2/NEWS: + update + +2007-03-11 10:30 cgilles + + * [r641436] libkexiv2/kexiv2.cpp: + fix comment + +2007-03-11 10:29 cgilles + + * [r641435] libkexiv2/kexiv2.cpp: + libkexiv2 from trunk : set the Exif.Image.Software tag only if it + doesn't exist. + BUG: 142564 + +2007-02-28 22:19 ach + + * [r638128] libkexiv2: + libkexiv2: ignore Makefile.in + +2007-02-28 22:14 ach + + * [r638127] libkexiv2/kexiv2.cpp, libkexiv2/kexiv2.h, + libkexiv2/libkexiv2_export.h, libkexiv2/version.h: + libkexiv2: remove unnecessary line break in license notice + +2007-02-28 22:13 ach + + * [r638126] libkexiv2/AUTHORS: + libkexiv2: add final newline to AUTHORS + +---------------------------------------------------------------------------- +V 0.1.1 - 2007-02-24 +---------------------------------------------------------------------------- + +2007-02-24 20:53 anaselli + + * [r636958] libkexiv2/ChangeLog, libkexiv2/Makefile.am, + libkexiv2/NEWS, libkexiv2/libkexiv2.lsm, + libkexiv2/libkexiv2.pc.in, libkexiv2/version.h: + libkexiv2 0.1.1 + bug fixing release + + CCMAIL:kde-imaging@kde.org + +2007-02-22 12:01 cgilles + + * [r636211] kipi-plugins/kipiplugins.kdevelop, + kipi-plugins/rawconverter/batchdialog.cpp, + kipi-plugins/rawconverter/singledialog.cpp, + libkdcraw/dcraw/dcraw.c, libkdcraw/dcraw/kdcraw.1, + libkdcraw/dcrawbinary.cpp, libkdcraw/dcrawsettingswidget.cpp, + libkdcraw/dcrawsettingswidget.h, libkdcraw/kdcraw.cpp, + libkdcraw/libkdcraw.kdevelop, libkdcraw/rawdecodingsettings.h, + libkexiv2/libkexiv2.kdevelop: + libkdcraw from trunk : backport last dcraw implementation "8.60" + : the old noise reduction algorithm used with 8.54 version have + been remplaced by a wavelet algorithm witch is more intuitive, + more easy to use (just one threshold setting) and very powerfull. + + Kipi-plugins RAWConverter from svn trunk is fixed. + The patch to use libkdcraw with current implementation of digiKam + have been updated : + + http://digikam3rdparty.free.fr/misc.tarballs/libkdcrawdigikamport.patch + + CCMAIL: digikam-users@kde.org + CCMAIL: digikam-devel@kde.org + CCMAIL: kde-imaging@kde.org + +2007-02-20 17:22 cgilles + + * [r635684] libkexiv2/kexiv2.cpp: + libkexiv2 from trunk : sanity check if QByteArray are null size + everywhere + Feedback welcome... + + CCBUGS:141980 + +2007-02-16 22:01 cgilles + + * [r634334] kipi-plugins/rawconverter/actionthread.cpp, + kipi-plugins/rawconverter/rawdecodingiface.cpp, + libkdcraw/kdcraw.cpp, libkexiv2/kexiv2.cpp: + fix comments + +2007-02-16 15:44 cgilles + + * [r634186] libkexiv2/libkexiv2.kdevelop: + kdevelop project + +2007-02-16 15:44 cgilles + + * [r634184] libkexiv2/AUTHORS, libkexiv2/kexiv2.cpp, + libkexiv2/kexiv2.h, libkexiv2/libkexiv2.lsm: + fix email + +2007-02-15 13:15 cgilles + + * [r633835] libkexiv2/kexiv2.cpp: + indent + +2007-02-13 22:41 ach + + * [r633377] libkexiv2/README: + fix library name in README + +2007-02-12 15:26 cgilles + + * [r632868] libkexiv2/configure.in.in: + this condition is unused everywhere. removed + +2007-02-12 09:24 cgilles + + * [r632763] libkexiv2/configure.in.in: + revert + +2007-02-12 08:32 cgilles + + * [r632755] libkexiv2/configure.in.in: + polish + +---------------------------------------------------------------------------- +V 0.1.0 - 2007-02-11 +---------------------------------------------------------------------------- + +2007-02-11 20:44 anaselli + + * [r632646] libkexiv2/ChangeLog, libkexiv2/libkexiv2.lsm, + libkexiv2/libkexiv2.pc.in: + libkexiv2 0.1.0 + + CCMAIL:kde-imaging@kde.org + + +2007-02-09 06:50 cgilles + + * [r631791] libkexiv2/kexiv2.cpp, libkexiv2/kexiv2.h: + libkexiv2 from trunk : new method to extract Exiv2 library + release numbers + +2007-02-06 22:12 cgilles + + * [r630973] libkexiv2/version.h: + compile + +2007-02-06 22:04 cgilles + + * [r630967] libkexiv2/Makefile.am, libkexiv2/version.h: + libkexiv2 from trunk : add version header file for this library + CCMAIL: Achim Bohnet + +2007-02-06 21:39 cgilles + + * [r630957] libkexiv2/kexiv2.cpp, libkexiv2/kexiv2.h: + 2 new methods to set IPTC or Exif tag using a bytes array + +2007-02-05 20:16 cgilles + + * [r630585] libkexiv2/kexiv2.cpp, libkexiv2/kexiv2.h: + factorize source code + +2007-02-05 14:38 cgilles + + * [r630488] libkexiv2/kexiv2.cpp, libkexiv2/kexiv2.h: + add boolean flag to add or not program name when a tag is + changed/added + +2007-02-05 14:00 cgilles + + * [r630471] libkexiv2/kexiv2.h: + set load() like virtual method. Re-implemented in digiKam core + +2007-01-30 12:18 cgilles + + * [r628573] libkexiv2/README: + update + +2007-01-30 12:16 cgilles + + * [r628572] libkexiv2/README: + update + +2007-01-30 12:12 cgilles + + * [r628569] libkexiv2/README: + update + +2007-01-30 11:57 cgilles + + * [r628566] libkexiv2/kexiv2.cpp, libkexiv2/kexiv2.h: + libkexiv2 from trunk : polish implementation. Fix API doc + +2007-01-30 11:18 cgilles + + * [r628554] libkexiv2/kexiv2.h: + libkexiv2 from trunk : Finamize API doc. + +2007-01-30 10:23 cgilles + + * [r628541] libkexiv2/kexiv2_export.h: + wrong file name + +2007-01-30 10:22 cgilles + + * [r628540] kipi-plugins/galleryexport/gallerytalker.cpp, + kipi-plugins/gpssync/gpslistviewitem.cpp, + kipi-plugins/gpssync/plugin_gpssync.cpp, + kipi-plugins/jpeglossless/jpegtransform.h, + kipi-plugins/metadataedit/exifadjust.cpp, + kipi-plugins/metadataedit/exifcaption.cpp, + kipi-plugins/metadataedit/exifdatetime.cpp, + kipi-plugins/metadataedit/exifdevice.cpp, + kipi-plugins/metadataedit/exifeditdialog.cpp, + kipi-plugins/metadataedit/exiflens.cpp, + kipi-plugins/metadataedit/exiflight.cpp, + kipi-plugins/metadataedit/iptccaption.cpp, + kipi-plugins/metadataedit/iptccategories.cpp, + kipi-plugins/metadataedit/iptccredits.cpp, + kipi-plugins/metadataedit/iptcdatetime.cpp, + kipi-plugins/metadataedit/iptceditdialog.cpp, + kipi-plugins/metadataedit/iptckeywords.cpp, + kipi-plugins/metadataedit/iptcorigin.cpp, + kipi-plugins/metadataedit/iptcstatus.cpp, + kipi-plugins/metadataedit/iptcsubjects.cpp, + kipi-plugins/metadataedit/plugin_metadataedit.cpp, + kipi-plugins/rawconverter/dcrawiface.cpp, + kipi-plugins/sendimages/sendimages.cpp, + kipi-plugins/timeadjust/timeadjustdialog.cpp, + libkexiv2/Makefile.am, libkexiv2/kexiv2.cpp, libkexiv2/kexiv2.h, + libkexiv2/kexiv2_export.h, libkexiv2/libkexiv2.cpp, + libkexiv2/libkexiv2.h: + kipi-plugins from trunk : fix libkexiv2 header file name + +2007-01-30 09:45 cgilles + + * [r628536] kipi-plugins/galleryexport/gallerytalker.cpp, + kipi-plugins/gpssync/gpslistviewitem.cpp, + kipi-plugins/gpssync/plugin_gpssync.cpp, + kipi-plugins/jpeglossless/jpegtransform.cpp, + kipi-plugins/jpeglossless/jpegtransform.h, + kipi-plugins/metadataedit/exifadjust.cpp, + kipi-plugins/metadataedit/exifcaption.cpp, + kipi-plugins/metadataedit/exifdatetime.cpp, + kipi-plugins/metadataedit/exifdevice.cpp, + kipi-plugins/metadataedit/exifeditdialog.cpp, + kipi-plugins/metadataedit/exiflens.cpp, + kipi-plugins/metadataedit/exiflight.cpp, + kipi-plugins/metadataedit/iptccaption.cpp, + kipi-plugins/metadataedit/iptccategories.cpp, + kipi-plugins/metadataedit/iptccredits.cpp, + kipi-plugins/metadataedit/iptcdatetime.cpp, + kipi-plugins/metadataedit/iptceditdialog.cpp, + kipi-plugins/metadataedit/iptckeywords.cpp, + kipi-plugins/metadataedit/iptcorigin.cpp, + kipi-plugins/metadataedit/iptcstatus.cpp, + kipi-plugins/metadataedit/iptcsubjects.cpp, + kipi-plugins/metadataedit/plugin_metadataedit.cpp, + kipi-plugins/rawconverter/dcrawiface.cpp, + kipi-plugins/sendimages/sendimages.cpp, + kipi-plugins/timeadjust/timeadjustdialog.cpp, + libkexiv2/libkexiv2.cpp, libkexiv2/libkexiv2.h: + kipi-plugins from trunk : fix libkexiv2 namespace and interface + class name + +2007-01-30 09:02 cgilles + + * [r628532] libkexiv2/libkexiv2.cpp, libkexiv2/libkexiv2.h: + libkexiv2 from trunk : backport new method to handle color + work-space of image. update API doc. + +2007-01-29 23:36 ach + + * [r628396] libkexiv2/libkexiv2.h: + libkexiv2: s/informations/information/ + +2007-01-29 21:19 lure + + * [r628356] libkexiv2/libkexiv2.h: + Fix broken comment - did not compile on Kubuntu Feisty + +2007-01-29 19:57 cgilles + + * [r628333] libkexiv2/libkexiv2.h: + libkexiv2 from trunk : Doxygen API (uncomplete) + +2007-01-29 16:49 cgilles + + * [r628263] libkexiv2/libkexiv2.pc.in: + update + +2007-01-29 14:18 cgilles + + * [r628206] libkexiv2/libkexiv2.cpp, libkexiv2/libkexiv2.h: + libkexiv2 from trunk : backport all common methods from + Digikam::DMetadata class. Backport all fix about comments + encoding from Marcel. The implementation is clean now and ready + to use with digiKam core. + + CCMAIL : marcel.wiesweg@gmx.de, digikam-devel@kde.org, + kde-imaging@kde.org + +2007-01-29 09:50 cgilles + + * [r628140] libkexiv2/libkexiv2.cpp, libkexiv2/libkexiv2.h: + new protected methods to use with derivated class + +2007-01-28 10:32 ach + + * [r627809] libkexiv2/libkexiv2.lsm, libkexiv2/libkexiv2.pc.in, + prepare_libkexiv2.rb: + libkexiv2: use same version everywhere + +2007-01-28 09:54 ach + + * [r627801] libkexiv2/libkexiv2.pc.in: + libkexiv2: fix libkexiv2.pc pkg-config file + +2007-01-28 09:47 ach + + * [r627799] libkexiv2/configure.in.in: + libkexiv2: Fix configure. PKGCONFIGFOUND was not set. + + CCMAIL: kde-imaging@kde.org + +2007-01-27 12:40 cgilles + + * [r627622] libkexiv2/libkexiv2.cpp, libkexiv2/libkexiv2_export.h: + kipi-plugins from trunk : libkexiv2 : do not use kdDebug() here + because it's not thread-safe. Use qDebug() instead... + + CCBUGS: 133026 + +2007-01-27 10:57 cgilles + + * [r627593] libkexiv2/README: + update + +2007-01-26 20:59 cgilles + + * [r627509] libkexiv2/libkexiv2.lsm: + update + +2007-01-26 20:40 cgilles + + * [r627501] kipi-plugins/NEWS, kipi-plugins/README, + kipi-plugins/common/Makefile.am, kipi-plugins/common/exiv2iface, + kipi-plugins/configure.in.bot, kipi-plugins/configure.in.in, + kipi-plugins/galleryexport/Makefile.am, + kipi-plugins/galleryexport/gallerytalker.cpp, + kipi-plugins/gpssync/Makefile.am, + kipi-plugins/gpssync/gpslistviewitem.cpp, + kipi-plugins/gpssync/gpslistviewitem.h, + kipi-plugins/gpssync/plugin_gpssync.cpp, + kipi-plugins/gpssync/plugin_gpssync.h, + kipi-plugins/jpeglossless/Makefile.am, + kipi-plugins/jpeglossless/jpegtransform.cpp, + kipi-plugins/jpeglossless/jpegtransform.h, + kipi-plugins/metadataedit/Makefile.am, + kipi-plugins/metadataedit/exifadjust.cpp, + kipi-plugins/metadataedit/exifcaption.cpp, + kipi-plugins/metadataedit/exifdatetime.cpp, + kipi-plugins/metadataedit/exifdevice.cpp, + kipi-plugins/metadataedit/exifeditdialog.cpp, + kipi-plugins/metadataedit/exiflens.cpp, + kipi-plugins/metadataedit/exiflight.cpp, + kipi-plugins/metadataedit/iptccaption.cpp, + kipi-plugins/metadataedit/iptccategories.cpp, + kipi-plugins/metadataedit/iptccredits.cpp, + kipi-plugins/metadataedit/iptcdatetime.cpp, + kipi-plugins/metadataedit/iptceditdialog.cpp, + kipi-plugins/metadataedit/iptckeywords.cpp, + kipi-plugins/metadataedit/iptcorigin.cpp, + kipi-plugins/metadataedit/iptcstatus.cpp, + kipi-plugins/metadataedit/iptcsubjects.cpp, + kipi-plugins/metadataedit/plugin_metadataedit.cpp, + kipi-plugins/rawconverter/Makefile.am, + kipi-plugins/rawconverter/dcrawiface.cpp, + kipi-plugins/rawconverter/dcrawiface.h, + kipi-plugins/sendimages/Makefile.am, + kipi-plugins/sendimages/sendimages.cpp, + kipi-plugins/sendimages/sendimages.h, + kipi-plugins/sync/Makefile.am, + kipi-plugins/sync/gallerytalker.cpp, + kipi-plugins/timeadjust/Makefile.am, + kipi-plugins/timeadjust/timeadjustdialog.cpp, + kipi-plugins/timeadjust/timeadjustdialog.h, + libkexiv2/libkexiv2.cpp, libkexiv2/libkexiv2.h: + kipi-plugins from trunk : all plugins use the new shared library + libkexiv2 instead KipiPlugins::EXiv2Iface class. + + Marcel, next stage is to derivate the DigiKam::DMetadata class + from LibKExiv2. Let's me hear when you whant to do it... + + CCMAIL: digikam-devel@kde.org, kde-imaging@kde.org, + marcel.wiesweg@gmx.de + +2007-01-26 15:51 cgilles + + * [r627439] libkexiv2/configure.in.bot, libkexiv2/configure.in.in: + compile + +2007-01-26 15:38 cgilles + + * [r627433] libkexiv2/libkexiv2.h: + using Export rules + +2007-01-26 13:14 cgilles + + * [r627401] libkexiv2/README: + update + +2007-01-26 13:10 cgilles + + * [r627400] libkexiv2/README: + update + +2007-01-26 13:09 cgilles + + * [r627399] libkexiv2/Makefile.am, libkexiv2/exiv2iface.cpp, + libkexiv2/exiv2iface.h, libkexiv2/libkexiv2.cpp, + libkexiv2/libkexiv2.h: + exiv2iface ==> libkexiv2 + new namespace + +2007-01-26 12:58 cgilles + + * [r627393] libkexiv2/exiv2iface.cpp, libkexiv2/exiv2iface.h, + libkexiv2/libkexiv2_export.h: + fix header + +2007-01-26 12:55 cgilles + + * [r627390] libkexiv2, libkexiv2/AUTHORS, libkexiv2/COPYING, + libkexiv2/ChangeLog, libkexiv2/INSTALL, libkexiv2/Makefile.am, + libkexiv2/NEWS, libkexiv2/README, libkexiv2/configure.in.in, + libkexiv2/exiv2iface.cpp, libkexiv2/exiv2iface.h, + libkexiv2/libkexiv2.lsm, libkexiv2/libkexiv2.pc.in, + libkexiv2/libkexiv2_export.h: + New common library witch will be used by digiKam and kipi-plugins + to handle Pictures metadata (Exif/Iptc). + + This shared library is a wrapper around Exiv2 library. It give a + Qt like interface to control + Exiv2 actions on pictures. Using this library will remove all + duplicate code on kipi-plugins::exiv2iface and + digikam::dmetadata. + + The current implementation is the same than + kipi-plugins/exiv2iface. This library is not yet used in + digiKam/kipi-plugins. + We will added a new depency to this library in kipi-plugins in + first and later to digiKam. + + CCMAIL: digikam-devel@kde.org, kde-imaging@kde.org, + marcel.wiesweg@gmx.de + diff --git a/libkexiv2/Messages.sh b/libkexiv2/Messages.sh new file mode 100755 index 00000000..dc0b8a5b --- /dev/null +++ b/libkexiv2/Messages.sh @@ -0,0 +1,2 @@ +#! /bin/sh +$XGETTEXT libkexiv2/*.cpp -o $podir/libkexiv2.pot diff --git a/libkexiv2/NEWS b/libkexiv2/NEWS new file mode 100644 index 00000000..c286c59a --- /dev/null +++ b/libkexiv2/NEWS @@ -0,0 +1,101 @@ +0.6.0 - Released with KDE 4.4.0 +------------------------------------------------------------------------ + +- New widgets shared between digiKam and kipi-plugins to play with IPTC Subjects and Language Alternative. + +0.5.0 - Released with KDE 4.3.0 +------------------------------------------------------------------------ + +- New option to enable/disable file timestamp updating when metadata are saved. + +0.4.0 - Released with KDE 4.2.0 +------------------------------------------------------------------------ + +- Use kDebug(51003) instead qDebug() +- New option to enable/disable Raw metadata writting. + +0.3.0 - Released with KDE 4.1.2 +------------------------------------------------------------------------ + +- API changed: Added 2 new static methods to init and clear non re-entrant Adobe XMP + SDK code from Exiv2 core. This code must be called before and after + all multithreaded operations with KExiv2. + * initializeExiv2(). + * cleanupExiv2(). + Added a new method to load image data from a byte array. + +Bugs fixed from B.K.O (http://bugs.kde.org): +001 ==> 166424: Crash when editing Caption with Digikam4 SVN. + +0.2.0 - Released with KDE 4.1.0 +------------------------------------------------------------------------ +Port to CMake/KDE4/QT4 +Support of XMP metadata (require Exiv2 0.16) +Split methods to separate files to provide a more readable implementation. +New method to fix orientation of a QImage accordingly with Exif orientation tag. +Moved from extragear/libs to kdegraphics/libs + +Bugs fixed from B.K.O (http://bugs.kde.org): +001 ==> 146864: Lesser XMP support in digiKam. + +0.1.7 +------------------------------------------------------------------------ + +- API changed: Added a version method to get runtime library version. +- Fix RemoveIptcTag() to handle all redondant Iptc tags at the same time. + +Bugs fixed from B.K.O (http://bugs.kde.org): +001 ==> 157552: negative altitudes are not shown in metadata GPS sidebar + +0.1.6 +------------------------------------------------------------------------ +- API Changed : Kexiv2 destructor is now virtual. + Krazy Code Checker fix (http://www.englishbreakfastnetwork.org/krazy) + +Bugs fixed from B.K.O (http://bugs.kde.org): +001 ==> 137750: color mode2 nikon d70s not recognized as adobe rgb +002 ==> 149267: digiKam crashes after finding gif,avi,txt and so on. +003 ==> 148182: Iptc.Application2.Keywords appends always the 0-byte. + +0.1.5 +------------------------------------------------------------------------ +Fix release version information. + +0.1.4 +------------------------------------------------------------------------ +Fix release version information. + +0.1.3 +------------------------------------------------------------------------ +New features +- API changed: added 4 new static methods to get Exif/Iptc tags description/title. + moved depreceate protected methods used by digiKam core to private. + +Bugs fixed from B.K.O (http://bugs.kde.org): +001 ==> 144604: Rotation causes Exif data corruption. GPS data fix + +General : Make size of icons used in album icon view more configurable using a slider + in status bar. +General : Removing direct Exiv2 library depency. libkexiv2 interface is used everywhere + instead. + +0.1.2 +------------------------------------------------------------------------ +New features +- added support for exiv2 from svn (next 0.14.0 release) +- API changed: added printExiv2ExceptionError to manage Exiv2 C++ Exception error message + +Bugs fixed from B.K.O (http://bugs.kde.org): +001 ==> 142564: digiKam-signature in iptc and exif tags. +002 ==> 140297: GPS kipi plugin truncates input coordinates, introducing inacuracy. + +0.1.1 +------------------------------------------------------------------------ +Bugs fixed from B.K.O (http://bugs.kde.org): +001 ==> 141980: digiKam crash when rescan certain files exiv2. + +0.1.0 +------------------------------------------------------------------------ +First implementation + +For details and info about previous versions, see ChangeLog. diff --git a/libkexiv2/README b/libkexiv2/README new file mode 100644 index 00000000..51385be2 --- /dev/null +++ b/libkexiv2/README @@ -0,0 +1,75 @@ +EXIV2 Library interface for KDE + +This library is a part of digiKam project (http://www.digikam.org) + +-- AUTHORS ------------------------------------------------------------ + +See AUTHORS file for details. + +-- ABOUT -------------------------------------------------------------- + +Libkexiv2 is a wrapper around Exiv2 library to manipulate pictures +metadata as EXIF/IPTC and XMP. Metadata interface follow this paper: + +http://www.metadataworkinggroup.com/pdf/mwg_guidance.pdf + +This library is used by kipi-plugins, digiKam and others kipi host programs. + +The library documentation is available on header files. + +-- DEPENDENCIES ------------------------------------------------------- + +CMake >= 2.8.x http://www.cmake.org +libqt >= 4.6.x http://www.qtsoftware.com +libkde >= 4.4.x http://www.kde.org +libexiv2 >= 0.21.0 http://www.exiv2.org + +-- INSTALL ------------------------------------------------------------ + +In order to compile, especially when QT3/Qt4 are installed at the same time, +just use something like that: + +# export VERBOSE=1 +# export QTDIR=/usr/lib/qt4/ +# export PATH=$QTDIR/bin:$PATH +# cmake . +# make + +Usual CMake options: + +-DCMAKE_INSTALL_PREFIX : decide where the program will be install on your computer. +-DCMAKE_BUILD_TYPE : decide which type of build you want. You can chose between "debugfull", "debug", "profile", "relwithdebinfo" and "release". The default is "relwithdebinfo" (-O2 -g). + +Compared to old KDE3 autoconf options: + +"cmake . -DCMAKE_BUILD_TYPE=debugfull" is equivalent to "./configure --enable-debug=full" +"cmake . -DCMAKE_INSTALL_PREFIX=/usr" is equivalent to "./configure --prefix=/usr" + +More details can be found ata this url: http://techbase.kde.org/Development/Tutorials/CMake#Environment_Variables + +Note: To know KDE install path on your computer, use 'kde-config --prefix' command line like this (with full debug object enabled): + +"cmake . -DCMAKE_BUILD_TYPE=debugfull -DCMAKE_INSTALL_PREFIX=`kde4-config --prefix`" + +-- CONTACT ------------------------------------------------------------ + +If you have questions, comments, suggestions to make do email at: + +kde-imaging@kde.org + +IRC channel from freenode.net server: + +#kde-imaging + +-- BUGS --------------------------------------------------------------- + +IMPORTANT : the bugreports and wishlist are hosted by the KDE bugs report +system who can be contacted by the standard Kde help menu of plugins dialog. +A mail will be automatically sent to the Kipi mailing list. +There is no need to contact directly the Kipi mailing list for a bug report +or a devel wish. + +The current Kipi bugs and devel wish reported to the Kde bugs report can be see +at this url: + +http://bugs.kde.org/buglist.cgi?product=digikam&component=libkexiv2&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED diff --git a/libkexiv2/TODO b/libkexiv2/TODO new file mode 100644 index 00000000..9d6ae5ee --- /dev/null +++ b/libkexiv2/TODO @@ -0,0 +1,3 @@ +- Extract GPS info from XMP tags. +- Exif/Iptc => Xmp synchronization. +- Xmp side-car file support. diff --git a/libkexiv2/libkexiv2.pc.cmake b/libkexiv2/libkexiv2.pc.cmake new file mode 100644 index 00000000..d1581344 --- /dev/null +++ b/libkexiv2/libkexiv2.pc.cmake @@ -0,0 +1,12 @@ +prefix=${CMAKE_INSTALL_PREFIX} +exec_prefix=${BIN_INSTALL_DIR} +libdir=${LIB_INSTALL_DIR} +includedir=${INCLUDE_INSTALL_DIR} + +Name: libkexiv2 +Description: A C++ library to manipulate EXIF/IPTC/XMP metadata using Exiv2 library. This library is used by digiKam and kipi-plugins. +URL: http://www.digikam.org +Requires: +Version: ${KEXIV2_LIB_VERSION_STRING} +Libs: -L${LIB_INSTALL_DIR} -lkexiv2 +Cflags: -I${INCLUDE_INSTALL_DIR} diff --git a/libkexiv2/libkexiv2/CMakeLists.txt b/libkexiv2/libkexiv2/CMakeLists.txt new file mode 100644 index 00000000..cc351134 --- /dev/null +++ b/libkexiv2/libkexiv2/CMakeLists.txt @@ -0,0 +1,72 @@ +# =========================================================== +# +# This file is a part of digiKam project +# http://www.digikam.org +# +# @date 2006-09-15 +# @brief Exiv2 library interface for KDE +# +# @author Copyright (C) 2006-2014 by Gilles Caulier +# caulier dot gilles at gmail dot com +# +# This program is free software; you can redistribute it +# and/or modify it under the terms of the GNU General +# Public License as published by the Free Software Foundation; +# either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# ============================================================ + +INCLUDE_DIRECTORIES(${EXIV2_INCLUDE_DIR}) + +ADD_DEFINITIONS(${EXIV2_DEFINITIONS}) +ADD_DEFINITIONS(${KDE4_ENABLE_EXCEPTIONS}) + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/version.h) + +# This was used to enable catching of exceptions thrown by libexiv2. +# We use now #pragma GCC visibility push(default) around the headers +#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default") + +SET(kexiv2_LIB_SRCS kexiv2.cpp + kexiv2_p.cpp + kexiv2image.cpp + kexiv2comments.cpp + kexiv2exif.cpp + kexiv2iptc.cpp + kexiv2gps.cpp + kexiv2xmp.cpp + kexiv2previews.cpp + altlangstredit.cpp + msgtextedit.cpp + countryselector.cpp + subjectwidget.cpp + rotationmatrix.cpp + ) + +KDE4_ADD_LIBRARY(kexiv2 SHARED ${kexiv2_LIB_SRCS}) + +TARGET_LINK_LIBRARIES(kexiv2 ${KDE4_KDEUI_LIBS} ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY} + ${QT_QTXML_LIBRARY} ${EXIV2_LIBRARIES}) +SET_TARGET_PROPERTIES(kexiv2 PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION}) + +INSTALL(FILES topicset.iptc-subjectcode.xml DESTINATION ${DATA_INSTALL_DIR}/libkexiv2/data) + +INSTALL(FILES kexiv2.h + kexiv2data.h + kexiv2previews.h + libkexiv2_export.h + msgtextedit.h + subjectwidget.h + altlangstredit.h + countryselector.h + rotationmatrix.h + ${CMAKE_CURRENT_BINARY_DIR}/version.h + DESTINATION ${INCLUDE_INSTALL_DIR}/libkexiv2 + COMPONENT Devel + ) diff --git a/libkexiv2/libkexiv2/Doxyfile b/libkexiv2/libkexiv2/Doxyfile new file mode 100644 index 00000000..48c4aa54 --- /dev/null +++ b/libkexiv2/libkexiv2/Doxyfile @@ -0,0 +1,1067 @@ +# Doxyfile 1.3.5 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = libKExiv2 + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en +# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese, +# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is used +# as the annotated text. Otherwise, the brief description is used as-is. If left +# blank, the following values are used ("$name" is automatically replaced with the +# name of the entity): "The $name class" "The $name widget" "The $name file" +# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ./ +INPUT += ./Mainpage.dox + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc + +FILE_PATTERNS = *.cpp \ + *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = _XMP_SUPPORT_ + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the +# parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superseded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = YES + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes that +# lay further from the root node will be omitted. Note that setting this option to +# 1 or 2 may greatly reduce the computation time needed for large code bases. Also +# note that a graph may be further truncated if the graph's image dimensions are +# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). +# If 0 is used for the depth value (the default), the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/libkexiv2/libkexiv2/Doxyfile-developer b/libkexiv2/libkexiv2/Doxyfile-developer new file mode 100644 index 00000000..bdfb06bd --- /dev/null +++ b/libkexiv2/libkexiv2/Doxyfile-developer @@ -0,0 +1,1067 @@ +# Doxyfile 1.3.5 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = libKExiv2 + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en +# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese, +# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is used +# as the annotated text. Otherwise, the brief description is used as-is. If left +# blank, the following values are used ("$name" is automatically replaced with the +# name of the entity): "The $name class" "The $name widget" "The $name file" +# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ./ +INPUT += ./Mainpage.dox + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc + +FILE_PATTERNS = *.cpp \ + *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = _XMP_SUPPORT_ + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the +# parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superseded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = YES + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes that +# lay further from the root node will be omitted. Note that setting this option to +# 1 or 2 may greatly reduce the computation time needed for large code bases. Also +# note that a graph may be further truncated if the graph's image dimensions are +# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). +# If 0 is used for the depth value (the default), the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/libkexiv2/libkexiv2/Mainpage.dox b/libkexiv2/libkexiv2/Mainpage.dox new file mode 100644 index 00000000..9c01fac7 --- /dev/null +++ b/libkexiv2/libkexiv2/Mainpage.dox @@ -0,0 +1,14 @@ +/** @mainpage libKExiv2 + +libKExiv2 is a wrapper around exiv2, providing read/write access to EXIF, IPTC and XMP metadata. The main differences to exiv2 are: +
    +
  • Functions take standard Qt containers as parameters +
  • Helper functions for GPS data +
  • Transparent XMP sidecar support +
+ +To get started, have a look at the KExiv2Iface::KExiv2 class. + +@see KExiv2Iface::KExiv2 + + */ \ No newline at end of file diff --git a/libkexiv2/libkexiv2/altlangstredit.cpp b/libkexiv2/libkexiv2/altlangstredit.cpp new file mode 100644 index 00000000..b9d908b5 --- /dev/null +++ b/libkexiv2/libkexiv2/altlangstredit.cpp @@ -0,0 +1,537 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-06-15 + * @brief multi-languages string editor + * + * @author Copyright (C) 2009-2013 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "moc_altlangstredit.cpp" + +// Qt includes + +#include +#include +#include +#include +#include +#include + +// KDE includes + +#include +#include +#include +#include +#include +#include +#include + +// Local includes + +#include "msgtextedit.h" + +namespace KExiv2Iface +{ + +class AltLangStrEdit::Private +{ +public: + + Private() + { + valueEdit = 0; + titleLabel = 0; + delValueButton = 0; + languageCB = 0; + linesVisible = 0; + currentLanguage = "x-default"; + + // We cannot use KLocale::allLanguagesList() here because KDE only + // support 2 characters country codes. XMP require 2+2 characters language+country + // following ISO 3066 (http://babelwiki.babelzilla.org/index.php?title=Language_codes) + + // The first one from the list is the Default Language code specified by XMP paper + languageCodeMap.insert( "x-default", i18n("Default Language") ); + + // Standard ISO 3066 country codes. + + languageCodeMap.insert( "af-ZA", i18n("Afrikaans (South Africa)") ); + languageCodeMap.insert( "am-ET", i18n("Amharic (Ethiopia)") ); + languageCodeMap.insert( "ar-AE", i18n("Arabic (UAE)") ); + languageCodeMap.insert( "ar-BH", i18n("Arabic (Bahrain)") ); + languageCodeMap.insert( "ar-DZ", i18n("Arabic (Algeria)") ); + languageCodeMap.insert( "ar-EG", i18n("Arabic (Egypt)") ); + languageCodeMap.insert( "ar-IQ", i18n("Arabic (Iraq)") ); + languageCodeMap.insert( "ar-JO", i18n("Arabic (Jordan)") ); + languageCodeMap.insert( "ar-KW", i18n("Arabic (Kuwait)") ); + languageCodeMap.insert( "ar-LB", i18n("Arabic (Lebanon)") ); + languageCodeMap.insert( "ar-LY", i18n("Arabic (Libya)") ); + languageCodeMap.insert( "ar-MA", i18n("Arabic (Morocco)") ); + languageCodeMap.insert( "ar-OM", i18n("Arabic (Oman)") ); + languageCodeMap.insert( "ar-QA", i18n("Arabic (Qatar)") ); + languageCodeMap.insert( "ar-SA", i18n("Arabic (Saudi Arabia)") ); + languageCodeMap.insert( "ar-SY", i18n("Arabic (Syria)") ); + languageCodeMap.insert( "ar-TN", i18n("Arabic (Tunisia)") ); + languageCodeMap.insert( "ar-YE", i18n("Arabic (Yemen)") ); + languageCodeMap.insert( "as-IN", i18n("Assamese (India)") ); + languageCodeMap.insert( "ba-RU", i18n("Bashkir (Russia)") ); + languageCodeMap.insert( "be-BY", i18n("Belarusian (Belarus)") ); + languageCodeMap.insert( "bg-BG", i18n("Bulgarian (Bulgaria)") ); + languageCodeMap.insert( "bn-IN", i18n("Bengali (India)") ); + languageCodeMap.insert( "bo-BT", i18n("Tibetan (Bhutan)") ); + languageCodeMap.insert( "bo-CN", i18n("Tibetan (PRC)") ); + languageCodeMap.insert( "br-FR", i18n("Breton (France)") ); + languageCodeMap.insert( "ca-AD", i18n("Catalan (Andorra)") ); + languageCodeMap.insert( "ca-ES", i18n("Catalan (Spain)") ); + languageCodeMap.insert( "ca-FR", i18n("Catalan (France)") ); + languageCodeMap.insert( "co-FR", i18n("Corsican (France)") ); + languageCodeMap.insert( "cs-CZ", i18n("Czech (Czech Republic)") ); + languageCodeMap.insert( "cy-GB", i18n("Welsh (United Kingdom)") ); + languageCodeMap.insert( "da-DK", i18n("Danish (Denmark)") ); + languageCodeMap.insert( "de-AT", i18n("German (Austria)") ); + languageCodeMap.insert( "de-CH", i18n("German (Switzerland)") ); + languageCodeMap.insert( "de-DE", i18n("German (Germany)") ); + languageCodeMap.insert( "de-LI", i18n("German (Liechtenstein)") ); + languageCodeMap.insert( "de-LU", i18n("German (Luxembourg)") ); + languageCodeMap.insert( "el-GR", i18n("Greek (Greece)") ); + languageCodeMap.insert( "en-AU", i18n("English (Australia)") ); + languageCodeMap.insert( "en-BZ", i18n("English (Belize)") ); + languageCodeMap.insert( "en-CA", i18n("English (Canada)") ); + languageCodeMap.insert( "en-CB", i18n("English (Caribbean)") ); + languageCodeMap.insert( "en-GB", i18n("English (United Kingdom)") ); + languageCodeMap.insert( "en-IE", i18n("English (Ireland)") ); + languageCodeMap.insert( "en-IN", i18n("English (India)") ); + languageCodeMap.insert( "en-JA", i18n("English (Jamaica)") ); + languageCodeMap.insert( "en-MY", i18n("English (Malaysia)") ); + languageCodeMap.insert( "en-NZ", i18n("English (New Zealand)") ); + languageCodeMap.insert( "en-PH", i18n("English (Philippines)") ); + languageCodeMap.insert( "en-SG", i18n("English (Singapore)") ); + languageCodeMap.insert( "en-TT", i18n("English (Trinidad)") ); + languageCodeMap.insert( "en-US", i18n("English (United States)") ); + languageCodeMap.insert( "en-ZA", i18n("English (South Africa)") ); + languageCodeMap.insert( "en-ZW", i18n("English (Zimbabwe)") ); + languageCodeMap.insert( "es-AR", i18n("Spanish (Argentina)") ); + languageCodeMap.insert( "es-BO", i18n("Spanish (Bolivia)") ); + languageCodeMap.insert( "es-CL", i18n("Spanish (Chile)") ); + languageCodeMap.insert( "es-CO", i18n("Spanish (Colombia)") ); + languageCodeMap.insert( "es-CR", i18n("Spanish (Costa Rica)") ); + languageCodeMap.insert( "es-DO", i18n("Spanish (Dominican Republic)") ); + languageCodeMap.insert( "es-EC", i18n("Spanish (Ecuador)") ); + languageCodeMap.insert( "es-ES", i18n("Spanish (Spain)") ); + languageCodeMap.insert( "es-GT", i18n("Spanish (Guatemala)") ); + languageCodeMap.insert( "es-HN", i18n("Spanish (Honduras)") ); + languageCodeMap.insert( "es-MX", i18n("Spanish (Mexico)") ); + languageCodeMap.insert( "es-NI", i18n("Spanish (Nicaragua)") ); + languageCodeMap.insert( "es-PA", i18n("Spanish (Panama)") ); + languageCodeMap.insert( "es-PE", i18n("Spanish (Peru)") ); + languageCodeMap.insert( "es-PR", i18n("Spanish (Puerto Rico)") ); + languageCodeMap.insert( "es-PY", i18n("Spanish (Paraguay)") ); + languageCodeMap.insert( "es-SV", i18n("Spanish (El Salvador)") ); + languageCodeMap.insert( "es-UR", i18n("Spanish (Uruguay)") ); + languageCodeMap.insert( "es-US", i18n("Spanish (United States)") ); + languageCodeMap.insert( "es-VE", i18n("Spanish (Venezuela)") ); + languageCodeMap.insert( "et-EE", i18n("Estonian (Estonia)") ); + languageCodeMap.insert( "eu-ES", i18n("Basque (Basque Country)") ); + languageCodeMap.insert( "fa-IR", i18n("Persian (Iran)") ); + languageCodeMap.insert( "fi-FI", i18n("Finnish (Finland)") ); + languageCodeMap.insert( "fo-FO", i18n("Faeroese (Faero Islands)") ); + languageCodeMap.insert( "fr-BE", i18n("French (Belgium)") ); + languageCodeMap.insert( "fr-CA", i18n("French (Canada)") ); + languageCodeMap.insert( "fr-CH", i18n("French (Switzerland)") ); + languageCodeMap.insert( "fr-FR", i18n("French (France)") ); + languageCodeMap.insert( "fr-LU", i18n("French (Luxembourg)") ); + languageCodeMap.insert( "fr-MC", i18n("French (Monaco)") ); + languageCodeMap.insert( "fy-NL", i18n("Frisian (Netherlands)") ); + languageCodeMap.insert( "ga-IE", i18n("Irish (Ireland)") ); + languageCodeMap.insert( "gl-ES", i18n("Galician (Galicia)") ); + languageCodeMap.insert( "gu-IN", i18n("Gujarati (India)") ); + languageCodeMap.insert( "he-IL", i18n("Hebrew (Israel)") ); + languageCodeMap.insert( "hi-IN", i18n("Hindi (India)") ); + languageCodeMap.insert( "hr-BA", i18n("Croatian (Bosnia and Herzegovina, Latin)") ); + languageCodeMap.insert( "hr-HR", i18n("Croatian (Croatia)") ); + languageCodeMap.insert( "hu-HU", i18n("Hungarian (Hungary)") ); + languageCodeMap.insert( "hy-AM", i18n("Armenian (Armenia)") ); + languageCodeMap.insert( "id-ID", i18n("(Indonesian)") ); + languageCodeMap.insert( "ii-CN", i18n("Yi (PRC)") ); + languageCodeMap.insert( "is-IS", i18n("Icelandic (Iceland)") ); + languageCodeMap.insert( "it-CH", i18n("Italian (Switzerland)") ); + languageCodeMap.insert( "it-IT", i18n("Italian (Italy)") ); + languageCodeMap.insert( "ja-JP", i18n("Japanese (Japan)") ); + languageCodeMap.insert( "ka-GE", i18n("Georgian (Georgia)") ); + languageCodeMap.insert( "kk-KZ", i18n("Kazakh (Kazakhstan)") ); + languageCodeMap.insert( "kl-GL", i18n("Greenlandic (Greenland)") ); + languageCodeMap.insert( "km-KH", i18n("Khmer (Cambodia)") ); + languageCodeMap.insert( "kn-IN", i18n("Kannada (India)") ); + languageCodeMap.insert( "ko-KR", i18n("Korean (South Korea)") ); + languageCodeMap.insert( "ky-KG", i18n("Kyrgyz (Kyrgyzstan)") ); + languageCodeMap.insert( "lb-LU", i18n("Luxembourgish (Luxembourg)") ); + languageCodeMap.insert( "lo-LA", i18n("Lao (Lao PDR)") ); + languageCodeMap.insert( "lt-LT", i18n("Lithuanian (Lithuania)") ); + languageCodeMap.insert( "lv-LV", i18n("Latvian (Latvia)") ); + languageCodeMap.insert( "mi-NZ", i18n("Maori (New Zealand)") ); + languageCodeMap.insert( "mk-MK", i18n("Macedonian (Macedonia)") ); + languageCodeMap.insert( "ml-IN", i18n("Malayalam (India)") ); + languageCodeMap.insert( "mn-CN", i18n("Mongolian (PRC)") ); + languageCodeMap.insert( "mn-MN", i18n("Mongolian (Mongolia)") ); + languageCodeMap.insert( "mr-IN", i18n("Marathi (India)") ); + languageCodeMap.insert( "ms-BN", i18n("Malay (Brunei Darussalam)") ); + languageCodeMap.insert( "ms-MY", i18n("Malay (Malaysia)") ); + languageCodeMap.insert( "mt-MT", i18n("Maltese (Malta)") ); + languageCodeMap.insert( "nb-NO", i18n("Norwegian Bokmål (Norway)") ); + languageCodeMap.insert( "ne-NP", i18n("Nepali (Nepal)") ); + languageCodeMap.insert( "nl-BE", i18n("Dutch (Belgium)") ); + languageCodeMap.insert( "nl-NL", i18n("Dutch (Netherlands)") ); + languageCodeMap.insert( "nn-NO", i18n("Norwegian Nynorsk (Norway)") ); + languageCodeMap.insert( "ns-ZA", i18n("Sesotho sa Leboa (South Africa)") ); + languageCodeMap.insert( "oc-FR", i18n("Occitan (France)") ); + languageCodeMap.insert( "or-IN", i18n("Oriya (India)") ); + languageCodeMap.insert( "pa-IN", i18n("Punjabi (India)") ); + languageCodeMap.insert( "pl-PL", i18n("Polish (Poland)") ); + languageCodeMap.insert( "ps-AF", i18n("Pashto (Afghanistan)") ); + languageCodeMap.insert( "pt-BR", i18n("Portuguese (Brazil)") ); + languageCodeMap.insert( "pt-PT", i18n("Portuguese (Portugal)") ); + languageCodeMap.insert( "rm-CH", i18n("Romansh (Switzerland)") ); + languageCodeMap.insert( "ro-RO", i18n("Romanian (Romania)") ); + languageCodeMap.insert( "ru-RU", i18n("Russian (Russia)") ); + languageCodeMap.insert( "rw-RW", i18n("Kinyarwanda (Rwanda)") ); + languageCodeMap.insert( "sa-IN", i18n("Sanskrit (India)") ); + languageCodeMap.insert( "se-FI", i18n("Sami (Northern, Finland)") ); + languageCodeMap.insert( "se-NO", i18n("Sami (Northern, Norway)") ); + languageCodeMap.insert( "se-SE", i18n("Sami (Northern, Sweden)") ); + languageCodeMap.insert( "si-LK", i18n("Sinhala (Sri Lanka)") ); + languageCodeMap.insert( "sk-SK", i18n("Slovak (Slovakia)") ); + languageCodeMap.insert( "sl-SI", i18n("Slovenian (Slovenia)") ); + languageCodeMap.insert( "sq-AL", i18n("Albanian (Albania)") ); + languageCodeMap.insert( "sv-FI", i18n("Swedish (Finland)") ); + languageCodeMap.insert( "sv-SE", i18n("Swedish (Sweden)") ); + languageCodeMap.insert( "sw-KE", i18n("Swahili (Kenya)") ); + languageCodeMap.insert( "ta-IN", i18n("Tamil (India)") ); + languageCodeMap.insert( "te-IN", i18n("Telugu (India)") ); + languageCodeMap.insert( "th-TH", i18n("Thai (Thailand)") ); + languageCodeMap.insert( "tk-TM", i18n("Turkmen (Turkmenistan)") ); + languageCodeMap.insert( "tn-ZA", i18n("Setswana Tswana (South Africa)") ); + languageCodeMap.insert( "tr-IN", i18n("Urdu (India)") ); + languageCodeMap.insert( "tr-TR", i18n("Turkish (Turkey)") ); + languageCodeMap.insert( "tt-RU", i18n("Tatar (Russia)") ); + languageCodeMap.insert( "ug-CN", i18n("Uighur (PRC)") ); + languageCodeMap.insert( "uk-UA", i18n("Ukrainian (Ukraine)") ); + languageCodeMap.insert( "ur-PK", i18n("Urdu (Pakistan)") ); + languageCodeMap.insert( "vi-VN", i18n("Vietnamese (Vietnam)") ); + languageCodeMap.insert( "wo-SN", i18n("Wolof (Senegal)") ); + languageCodeMap.insert( "xh-ZA", i18n("isiXhosa Xhosa (South Africa)") ); + languageCodeMap.insert( "yo-NG", i18n("Yoruba (Nigeria)") ); + languageCodeMap.insert( "zh-CN", i18n("Chinese (PRC)") ); + languageCodeMap.insert( "zh-HK", i18n("Chinese (Hong Kong SAR, PRC)") ); + languageCodeMap.insert( "zh-MO", i18n("Chinese (Macao SAR)") ); + languageCodeMap.insert( "zh-SG", i18n("Chinese (Singapore)") ); + languageCodeMap.insert( "zh-TW", i18n("Chinese (Taiwan)") ); + languageCodeMap.insert( "zu-ZA", i18n("isiZulu Zulu (South Africa)") ); + } + + ~Private() + { + languageCodeMap.clear(); + } + +public: + + typedef QMap LanguageCodeMap; + + LanguageCodeMap languageCodeMap; + + QString currentLanguage; + + uint linesVisible; + + QLabel* titleLabel; + + QToolButton* delValueButton; + + MsgTextEdit* valueEdit; + + KComboBox* languageCB; + + KExiv2::AltLangMap values; +}; + +AltLangStrEdit::AltLangStrEdit(QWidget* parent) + : QWidget(parent), d(new Private) +{ + QGridLayout* const grid = new QGridLayout(this); + d->titleLabel = new QLabel(this); + d->delValueButton = new QToolButton(this); + d->delValueButton->setIcon(SmallIcon("edit-clear")); + d->delValueButton->setToolTip(i18n("Remove entry for this language")); + d->delValueButton->setEnabled(false); + + d->languageCB = new KComboBox(this); + d->languageCB->setSizeAdjustPolicy(KComboBox::AdjustToContents); + d->languageCB->setWhatsThis(i18n("Select item language here.")); + + d->valueEdit = new MsgTextEdit(this); + d->valueEdit->setCheckSpellingEnabled(true); + + // -------------------------------------------------------- + + grid->setAlignment( Qt::AlignTop ); + grid->addWidget(d->titleLabel, 0, 0, 1, 1); + grid->addWidget(d->languageCB, 0, 2, 1, 1); + grid->addWidget(d->delValueButton, 0, 3, 1, 1); + grid->addWidget(d->valueEdit, 1, 0, 1,-1); + grid->setColumnStretch(1, 10); + grid->setMargin(0); + grid->setSpacing(KDialog::spacingHint()); + + loadLangAltListEntries(); + + // -------------------------------------------------------- + + connect(d->languageCB, SIGNAL(currentIndexChanged(int)), + this, SLOT(slotSelectionChanged())); + + connect(d->delValueButton, SIGNAL(clicked()), + this, SLOT(slotDeleteValue())); + + connect(d->valueEdit, SIGNAL(textChanged()), + this, SLOT(slotTextChanged())); +} + +AltLangStrEdit::~AltLangStrEdit() +{ + delete d; +} + +QString AltLangStrEdit::currentLanguageCode() const +{ + return d->currentLanguage; +} + +void AltLangStrEdit::setCurrentLanguageCode(const QString& lang) +{ + if(d->currentLanguage.isEmpty()) + { + d->currentLanguage = "x-default"; + } + else + { + d->currentLanguage = lang; + } +} + +QString AltLangStrEdit::languageCode(int index) const +{ + return d->languageCB->itemText(index); +} + +void AltLangStrEdit::setTitle(const QString& title) +{ + d->titleLabel->setText(title); +} + +void AltLangStrEdit::setClickMessage(const QString& msg) +{ + d->valueEdit->setClickMessage(msg); +} + +void AltLangStrEdit::reset() +{ + setValues(KExiv2::AltLangMap()); +} + +void AltLangStrEdit::slotDeleteValue() +{ + d->values.remove(d->currentLanguage); + setValues(d->values); + emit signalValueDeleted(d->currentLanguage); +} + +void AltLangStrEdit::slotSelectionChanged() +{ + d->currentLanguage = d->languageCB->currentText(); + + // There are bogus signals caused by spell checking, see bug #141663. + // so we must block signals here. + + d->valueEdit->blockSignals(true); + + QString langISO3066 = d->currentLanguage; + langISO3066.replace('-', '_'); + d->valueEdit->setSpellCheckingLanguage(langISO3066); + + QString text = d->values.value(d->currentLanguage); + d->valueEdit->setText(text); + d->delValueButton->setEnabled(!text.isNull()); + + d->valueEdit->blockSignals(false); + + d->languageCB->setToolTip(d->languageCodeMap.value(d->currentLanguage)); + + emit signalSelectionChanged(d->currentLanguage); +} + +void AltLangStrEdit::setValues(const KExiv2::AltLangMap& values) +{ + d->values = values; + loadLangAltListEntries(); + + d->valueEdit->blockSignals(true); + + QString text = d->values.value(d->currentLanguage); + d->valueEdit->setText(text); + d->delValueButton->setEnabled(!text.isNull()); + + d->valueEdit->blockSignals(false); +} + +KExiv2::AltLangMap& AltLangStrEdit::values() +{ + return d->values; +} + +void AltLangStrEdit::loadLangAltListEntries() +{ + d->languageCB->blockSignals(true); + + d->languageCB->clear(); + + // In first we fill already assigned languages. + + QStringList list = d->values.keys(); + + if (!list.isEmpty()) + { + foreach(const QString& item, list) + { + d->languageCB->addItem(item); + d->languageCB->setItemIcon(d->languageCB->count()-1, SmallIcon("dialog-ok")); + } + + d->languageCB->insertSeparator(d->languageCB->count()); + } + + // ...and now, all the rest... + + for (Private::LanguageCodeMap::Iterator it = d->languageCodeMap.begin(); + it != d->languageCodeMap.end(); ++it) + { + if (!list.contains(it.key())) + { + d->languageCB->addItem(it.key()); + } + } + + d->languageCB->setCurrentItem(d->currentLanguage); + + d->languageCB->blockSignals(false); +} + +QString AltLangStrEdit::defaultAltLang() const +{ + return d->values.value(QString("x-default")); +} + +bool AltLangStrEdit::asDefaultAltLang() const +{ + return !defaultAltLang().isNull(); +} + +void AltLangStrEdit::slotTextChanged() +{ + QString editedText = d->valueEdit->toPlainText(); + QString previousText = d->values.value(d->currentLanguage); + + // Special case : if edited and previous strings are empty, do nothing. + // See bug #152948. + if (editedText.isEmpty() && previousText.isNull()) + { + return; + } + + if (editedText.isEmpty()) + { + slotDeleteValue(); + } + else if (previousText.isNull()) + { + addCurrent(); + } + else if (editedText != previousText) + { + // we cannot trust that the text actually changed + // (there are bogus signals caused by spell checking, see bug #141663) + // so we have to check before marking the metadata as modified. + d->values.insert(d->currentLanguage, editedText); + emit signalModified(d->currentLanguage, editedText); + } +} + +void AltLangStrEdit::addCurrent() +{ + QString text = d->valueEdit->toPlainText(); + + d->values.insert(d->currentLanguage, text); + loadLangAltListEntries(); + d->delValueButton->setEnabled(true); + emit signalValueAdded(d->currentLanguage, text); +} + +void AltLangStrEdit::setLinesVisible(uint lines) +{ + d->linesVisible = lines; + + if (d->linesVisible == 0) + { + d->valueEdit->setFixedHeight(QWIDGETSIZE_MAX); // reset + } + else + { + d->valueEdit->setFixedHeight(d->valueEdit->fontMetrics().lineSpacing() * d->linesVisible + + d->valueEdit->contentsMargins().top() + + d->valueEdit->contentsMargins().bottom() + + 1 + + 2*(d->valueEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth) + + d->valueEdit->style()->pixelMetric(QStyle::PM_FocusFrameVMargin)) + ); + } + + // It's not possible to display scrollbar properlly if size is too small + if (d->linesVisible < 3) + { + d->valueEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + } +} + +uint AltLangStrEdit::linesVisible() const +{ + return d->linesVisible; +} + +void AltLangStrEdit::changeEvent(QEvent* e) +{ + if (e->type() == QEvent::FontChange) + { + setLinesVisible(linesVisible()); + } + + QWidget::changeEvent(e); +} + +} // namespace KExiv2Iface diff --git a/libkexiv2/libkexiv2/altlangstredit.h b/libkexiv2/libkexiv2/altlangstredit.h new file mode 100644 index 00000000..bf15697a --- /dev/null +++ b/libkexiv2/libkexiv2/altlangstredit.h @@ -0,0 +1,115 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-06-15 + * @brief multi-languages string editor + * + * @author Copyright (C) 2009-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef ALTLANGSTREDIT_H +#define ALTLANGSTREDIT_H + +// Qt includes + +#include +#include + +// Local includes + +#include "libkexiv2_export.h" +#include "kexiv2.h" + +namespace KExiv2Iface +{ + +class KEXIV2_EXPORT AltLangStrEdit : public QWidget +{ + Q_OBJECT + +public: + + AltLangStrEdit(QWidget* parent); + ~AltLangStrEdit(); + + void setTitle(const QString& title); + void setClickMessage(const QString& msg); + + void setCurrentLanguageCode(const QString& lang); + QString currentLanguageCode() const; + + QString languageCode(int index) const; + + void setValues(const KExiv2::AltLangMap& values); + KExiv2::AltLangMap& values(); + + /** Fix lines visibile in text editor to lines. If zero, do not fix layout to number of lines visible. + */ + void setLinesVisible(uint lines); + uint linesVisible() const; + + QString defaultAltLang() const; + bool asDefaultAltLang() const; + + /** + * Reset widget, clear all entries + */ + void reset(); + + /** + * Ensure that the current language is added to the list of entries, + * even if the text is empty. + * signalValueAdded() will be emitted. + */ + void addCurrent(); + +Q_SIGNALS: + + /** + * Emitted when the user changes the text for the current language. + */ + void signalModified(const QString& lang, const QString& text); + /// Emitted when the current language changed + void signalSelectionChanged(const QString& lang); + /// Emitted when an entry for a new language is added + void signalValueAdded(const QString& lang, const QString& text); + /// Emitted when the entry for a language is removed. + void signalValueDeleted(const QString& lang); + +protected Q_SLOTS: + + void slotTextChanged(); + void slotSelectionChanged(); + void slotDeleteValue(); + +protected: + + void loadLangAltListEntries(); + + virtual void changeEvent(QEvent* e); + +private: + + class Private; + Private* const d; +}; + +} // namespace KExiv2Iface + +#endif // ALTLANGSTREDIT_H diff --git a/libkexiv2/libkexiv2/countryselector.cpp b/libkexiv2/libkexiv2/countryselector.cpp new file mode 100644 index 00000000..133e978a --- /dev/null +++ b/libkexiv2/libkexiv2/countryselector.cpp @@ -0,0 +1,370 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-07-07 + * @brief country selector combo-box. + * + * @author Copyright (C) 2009-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "countryselector.h" + +// Qt includes + +#include +#include + +// KDE includes + +#include +#include + +namespace KExiv2Iface +{ + +class CountrySelector::Private +{ +public: + + Private() + { + // We cannot use KLocale::allCountriesList() here because KDE only + // support 2 characters country codes. XMP require 3 characters country + // following ISO 3166 (http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html) + + // Standard ISO 3166 country codes. + + countryCodeMap.insert( "AFG", i18n("Afghanistan") ); + countryCodeMap.insert( "ALB", i18n("Albania") ); + countryCodeMap.insert( "DZA", i18n("Algeria") ); + countryCodeMap.insert( "ASM", i18n("American Samoa") ); + countryCodeMap.insert( "AND", i18n("Andorra") ); + countryCodeMap.insert( "AGO", i18n("Angola") ); + countryCodeMap.insert( "AIA", i18n("Anguilla") ); + countryCodeMap.insert( "AGO", i18n("Angola") ); + countryCodeMap.insert( "ATA", i18n("Antarctica") ); + countryCodeMap.insert( "ATG", i18n("Antigua and Barbuda") ); + countryCodeMap.insert( "ARG", i18n("Argentina") ); + countryCodeMap.insert( "ARM", i18n("Armenia") ); + countryCodeMap.insert( "ABW", i18n("Aruba") ); + countryCodeMap.insert( "AUS", i18n("Australia") ); + countryCodeMap.insert( "AUT", i18n("Austria") ); + countryCodeMap.insert( "AZE", i18n("Azerbaijan") ); + countryCodeMap.insert( "BHS", i18n("Bahamas") ); + countryCodeMap.insert( "BHR", i18n("Bahrain") ); + countryCodeMap.insert( "BGD", i18n("Bangladesh") ); + countryCodeMap.insert( "BRB", i18n("Barbados") ); + countryCodeMap.insert( "BLR", i18n("Belarus") ); + countryCodeMap.insert( "BEL", i18n("Belgium") ); + countryCodeMap.insert( "BLZ", i18n("Belize") ); + countryCodeMap.insert( "BEN", i18n("Benin") ); + countryCodeMap.insert( "BMU", i18n("Bermuda") ); + countryCodeMap.insert( "BTN", i18n("Bhutan") ); + countryCodeMap.insert( "BOL", i18n("Bolivia") ); + countryCodeMap.insert( "BIH", i18n("Bosnia and Herzegovina") ); + countryCodeMap.insert( "BWA", i18n("Botswana") ); + countryCodeMap.insert( "BVT", i18n("Bouvet Island") ); + countryCodeMap.insert( "BRA", i18n("Brazil") ); + countryCodeMap.insert( "IOT", i18n("British Indian Ocean Territory") ); + countryCodeMap.insert( "VGB", i18n("British Virgin Islands") ); + countryCodeMap.insert( "BRN", i18n("Brunei Darussalam") ); + countryCodeMap.insert( "BGR", i18n("Bulgaria") ); + countryCodeMap.insert( "BFA", i18n("Burkina Faso") ); + countryCodeMap.insert( "BDI", i18n("Burundi") ); + countryCodeMap.insert( "KHM", i18n("Cambodia") ); + countryCodeMap.insert( "CMR", i18n("Cameroon") ); + countryCodeMap.insert( "CAN", i18n("Canada") ); + countryCodeMap.insert( "CPV", i18n("Cape Verde") ); + countryCodeMap.insert( "CYM", i18n("Cayman Islands") ); + countryCodeMap.insert( "CAF", i18n("Central African Republic") ); + countryCodeMap.insert( "TCD", i18n("Chad") ); + countryCodeMap.insert( "CHL", i18n("Chile") ); + countryCodeMap.insert( "CHN", i18n("China") ); + countryCodeMap.insert( "CXR", i18n("Christmas Island ") ); + countryCodeMap.insert( "CCK", i18n("Cocos Islands") ); + countryCodeMap.insert( "COL", i18n("Colombia") ); + countryCodeMap.insert( "COM", i18n("Comoros") ); + countryCodeMap.insert( "COD", i18n("Zaire") ); + countryCodeMap.insert( "COG", i18n("Congo") ); + countryCodeMap.insert( "COK", i18n("Cook Islands") ); + countryCodeMap.insert( "CRI", i18n("Costa Rica") ); + countryCodeMap.insert( "CIV", i18n("Ivory Coast") ); + countryCodeMap.insert( "CUB", i18n("Cuba") ); + countryCodeMap.insert( "CYP", i18n("Cyprus") ); + countryCodeMap.insert( "CZE", i18n("Czech Republic") ); + countryCodeMap.insert( "DNK", i18n("Denmark") ); + countryCodeMap.insert( "DJI", i18n("Djibouti") ); + countryCodeMap.insert( "DMA", i18n("Dominica") ); + countryCodeMap.insert( "DOM", i18n("Dominican Republic") ); + countryCodeMap.insert( "ECU", i18n("Ecuador") ); + countryCodeMap.insert( "EGY", i18n("Egypt") ); + countryCodeMap.insert( "SLV", i18n("El Salvador") ); + countryCodeMap.insert( "GNQ", i18n("Equatorial Guinea") ); + countryCodeMap.insert( "ERI", i18n("Eritrea") ); + countryCodeMap.insert( "EST", i18n("Estonia") ); + countryCodeMap.insert( "ETH", i18n("Ethiopia") ); + countryCodeMap.insert( "FRO", i18n("Faeroe Islands") ); + countryCodeMap.insert( "FLK", i18n("Falkland Islands") ); + countryCodeMap.insert( "FJI", i18n("Fiji Islands") ); + countryCodeMap.insert( "FIN", i18n("Finland") ); + countryCodeMap.insert( "FRA", i18n("France") ); + countryCodeMap.insert( "GUF", i18n("French Guiana") ); + countryCodeMap.insert( "PYF", i18n("French Polynesia") ); + countryCodeMap.insert( "ATF", i18n("French Southern Territories") ); + countryCodeMap.insert( "GAB", i18n("Gabon") ); + countryCodeMap.insert( "GMB", i18n("Gambia") ); + countryCodeMap.insert( "GEO", i18n("Georgia") ); + countryCodeMap.insert( "DEU", i18n("Germany") ); + countryCodeMap.insert( "GHA", i18n("Ghana") ); + countryCodeMap.insert( "GIB", i18n("Gibraltar") ); + countryCodeMap.insert( "GRC", i18n("Greece") ); + countryCodeMap.insert( "GRL", i18n("Greenland") ); + countryCodeMap.insert( "GRD", i18n("Grenada") ); + countryCodeMap.insert( "GLP", i18n("Guadaloupe") ); + countryCodeMap.insert( "GUM", i18n("Guam") ); + countryCodeMap.insert( "GTM", i18n("Guatemala") ); + countryCodeMap.insert( "GIN", i18n("Guinea") ); + countryCodeMap.insert( "GNB", i18n("Guinea-Bissau") ); + countryCodeMap.insert( "GUY", i18n("Guyana") ); + countryCodeMap.insert( "HTI", i18n("Haiti") ); + countryCodeMap.insert( "HMD", i18n("Heard and McDonald Islands") ); + countryCodeMap.insert( "VAT", i18n("Vatican") ); + countryCodeMap.insert( "HND", i18n("Honduras") ); + countryCodeMap.insert( "HKG", i18n("Hong Kong") ); + countryCodeMap.insert( "HRV", i18n("Croatia") ); + countryCodeMap.insert( "HUN", i18n("Hungary") ); + countryCodeMap.insert( "ISL", i18n("Iceland") ); + countryCodeMap.insert( "IND", i18n("India") ); + countryCodeMap.insert( "IDN", i18n("Indonesia") ); + countryCodeMap.insert( "IRN", i18n("Iran") ); + countryCodeMap.insert( "IRQ", i18n("Iraq") ); + countryCodeMap.insert( "IRL", i18n("Ireland") ); + countryCodeMap.insert( "ISR", i18n("Israel") ); + countryCodeMap.insert( "ITA", i18n("Italy") ); + countryCodeMap.insert( "JAM", i18n("Jamaica") ); + countryCodeMap.insert( "JPN", i18n("Japan") ); + countryCodeMap.insert( "JOR", i18n("Jordan") ); + countryCodeMap.insert( "KAZ", i18n("Kazakhstan") ); + countryCodeMap.insert( "KEN", i18n("Kenya") ); + countryCodeMap.insert( "KIR", i18n("Kiribati") ); + countryCodeMap.insert( "PRK", i18n("North-Korea") ); + countryCodeMap.insert( "KOR", i18n("South-Korea") ); + countryCodeMap.insert( "KWT", i18n("Kuwait") ); + countryCodeMap.insert( "KGZ", i18n("Kyrgyz Republic") ); + countryCodeMap.insert( "LAO", i18n("Lao") ); + countryCodeMap.insert( "LVA", i18n("Latvia") ); + countryCodeMap.insert( "LBN", i18n("Lebanon") ); + countryCodeMap.insert( "LSO", i18n("Lesotho") ); + countryCodeMap.insert( "LBR", i18n("Liberia") ); + countryCodeMap.insert( "LBY", i18n("Libyan Arab Jamahiriya") ); + countryCodeMap.insert( "LIE", i18n("Liechtenstein") ); + countryCodeMap.insert( "LTU", i18n("Lithuania") ); + countryCodeMap.insert( "LUX", i18n("Luxembourg") ); + countryCodeMap.insert( "MAC", i18n("Macao") ); + countryCodeMap.insert( "MKD", i18n("Macedonia") ); + countryCodeMap.insert( "MDG", i18n("Madagascar") ); + countryCodeMap.insert( "MWI", i18n("Malawi") ); + countryCodeMap.insert( "MYS", i18n("Malaysia") ); + countryCodeMap.insert( "MDV", i18n("Maldives") ); + countryCodeMap.insert( "MLI", i18n("Mali") ); + countryCodeMap.insert( "MLT", i18n("Malta") ); + countryCodeMap.insert( "MHL", i18n("Marshall Islands") ); + countryCodeMap.insert( "MTQ", i18n("Martinique") ); + countryCodeMap.insert( "MRT", i18n("Mauritania") ); + countryCodeMap.insert( "MUS", i18n("Mauritius") ); + countryCodeMap.insert( "MYT", i18n("Mayotte") ); + countryCodeMap.insert( "MEX", i18n("Mexico") ); + countryCodeMap.insert( "FSM", i18n("Micronesia") ); + countryCodeMap.insert( "MDA", i18n("Moldova") ); + countryCodeMap.insert( "MCO", i18n("Monaco") ); + countryCodeMap.insert( "MNG", i18n("Mongolia") ); + countryCodeMap.insert( "MSR", i18n("Montserrat") ); + countryCodeMap.insert( "MAR", i18n("Morocco") ); + countryCodeMap.insert( "MOZ", i18n("Mozambique") ); + countryCodeMap.insert( "MMR", i18n("Myanmar") ); + countryCodeMap.insert( "NAM", i18n("Namibia") ); + countryCodeMap.insert( "NRU", i18n("Nauru") ); + countryCodeMap.insert( "NPL", i18n("Nepal") ); + countryCodeMap.insert( "ANT", i18n("Netherlands Antilles") ); + countryCodeMap.insert( "NLD", i18n("Netherlands") ); + countryCodeMap.insert( "NCL", i18n("New Caledonia") ); + countryCodeMap.insert( "NZL", i18n("New Zealand") ); + countryCodeMap.insert( "NIC", i18n("Nicaragua") ); + countryCodeMap.insert( "NER", i18n("Niger") ); + countryCodeMap.insert( "NGA", i18n("Nigeria") ); + countryCodeMap.insert( "NIU", i18n("Niue") ); + countryCodeMap.insert( "NFK", i18n("Norfolk Island") ); + countryCodeMap.insert( "MNP", i18n("Northern Mariana Islands") ); + countryCodeMap.insert( "NOR", i18n("Norway") ); + countryCodeMap.insert( "OMN", i18n("Oman") ); + countryCodeMap.insert( "PAK", i18n("Pakistan") ); + countryCodeMap.insert( "PLW", i18n("Palau") ); + countryCodeMap.insert( "PSE", i18n("Palestinian Territory") ); + countryCodeMap.insert( "PAN", i18n("Panama") ); + countryCodeMap.insert( "PNG", i18n("Papua New Guinea") ); + countryCodeMap.insert( "PRY", i18n("Paraguay") ); + countryCodeMap.insert( "PER", i18n("Peru") ); + countryCodeMap.insert( "PHL", i18n("Philippines") ); + countryCodeMap.insert( "PCN", i18n("Pitcairn Island") ); + countryCodeMap.insert( "POL", i18n("Poland") ); + countryCodeMap.insert( "PRT", i18n("Portugal") ); + countryCodeMap.insert( "PRI", i18n("Puerto Rico") ); + countryCodeMap.insert( "QAT", i18n("Qatar") ); + countryCodeMap.insert( "REU", i18n("Reunion") ); + countryCodeMap.insert( "ROU", i18n("Romania") ); + countryCodeMap.insert( "RUS", i18n("Russian Federation") ); + countryCodeMap.insert( "RWA", i18n("Rwanda") ); + countryCodeMap.insert( "SHN", i18n("St. Helena") ); + countryCodeMap.insert( "KNA", i18n("St. Kitts and Nevis") ); + countryCodeMap.insert( "LCA", i18n("St. Lucia") ); + countryCodeMap.insert( "SPM", i18n("St. Pierre and Miquelon") ); + countryCodeMap.insert( "VCT", i18n("St. Vincent and the Grenadines") ); + countryCodeMap.insert( "WSM", i18n("Samoa") ); + countryCodeMap.insert( "SMR", i18n("San Marino") ); + countryCodeMap.insert( "STP", i18n("Sao Tome and Principe") ); + countryCodeMap.insert( "SAU", i18n("Saudi Arabia") ); + countryCodeMap.insert( "SEN", i18n("Senegal") ); + countryCodeMap.insert( "SCG", i18n("Serbia and Montenegro") ); + countryCodeMap.insert( "SYC", i18n("Seychelles") ); + countryCodeMap.insert( "SLE", i18n("Sierra Leone") ); + countryCodeMap.insert( "SGP", i18n("Singapore") ); + countryCodeMap.insert( "SVK", i18n("Slovakia") ); + countryCodeMap.insert( "SVN", i18n("Slovenia") ); + countryCodeMap.insert( "SLB", i18n("Solomon Islands") ); + countryCodeMap.insert( "SOM", i18n("Somalia") ); + countryCodeMap.insert( "ZAF", i18n("South Africa") ); + countryCodeMap.insert( "SGS", i18n("South Georgia and the South Sandwich Islands") ); + countryCodeMap.insert( "ESP", i18n("Spain") ); + countryCodeMap.insert( "LKA", i18n("Sri Lanka") ); + countryCodeMap.insert( "SDN", i18n("Sudan") ); + countryCodeMap.insert( "SUR", i18n("Suriname") ); + countryCodeMap.insert( "SJM", i18n("Svalbard & Jan Mayen Islands") ); + countryCodeMap.insert( "SWZ", i18n("Swaziland") ); + countryCodeMap.insert( "SWE", i18n("Sweden") ); + countryCodeMap.insert( "CHE", i18n("Switzerland") ); + countryCodeMap.insert( "SYR", i18n("Syrian Arab Republic") ); + countryCodeMap.insert( "TWN", i18n("Taiwan") ); + countryCodeMap.insert( "TJK", i18n("Tajikistan") ); + countryCodeMap.insert( "TZA", i18n("Tanzania") ); + countryCodeMap.insert( "THA", i18n("Thailand") ); + countryCodeMap.insert( "TLS", i18n("Timor-Leste") ); + countryCodeMap.insert( "TGO", i18n("Togo") ); + countryCodeMap.insert( "TKL", i18n("Tokelau Islands") ); + countryCodeMap.insert( "TON", i18n("Tonga") ); + countryCodeMap.insert( "TTO", i18n("Trinidad and Tobago") ); + countryCodeMap.insert( "TUN", i18n("Tunisia") ); + countryCodeMap.insert( "TUR", i18n("Turkey") ); + countryCodeMap.insert( "TKM", i18n("Turkmenistan") ); + countryCodeMap.insert( "TCA", i18n("Turks and Caicos Islands") ); + countryCodeMap.insert( "TUV", i18n("Tuvalu") ); + countryCodeMap.insert( "VIR", i18n("US Virgin Islands") ); + countryCodeMap.insert( "UGA", i18n("Uganda") ); + countryCodeMap.insert( "UKR", i18n("Ukraine") ); + countryCodeMap.insert( "ARE", i18n("United Arab Emirates") ); + countryCodeMap.insert( "GBR", i18n("United Kingdom") ); + countryCodeMap.insert( "UMI", i18n("United States Minor Outlying Islands") ); + countryCodeMap.insert( "USA", i18n("United States of America") ); + countryCodeMap.insert( "URY", i18n("Uruguay, Eastern Republic of") ); + countryCodeMap.insert( "UZB", i18n("Uzbekistan") ); + countryCodeMap.insert( "VUT", i18n("Vanuatu") ); + countryCodeMap.insert( "VEN", i18n("Venezuela") ); + countryCodeMap.insert( "VNM", i18n("Viet Nam") ); + countryCodeMap.insert( "WLF", i18n("Wallis and Futuna Islands ") ); + countryCodeMap.insert( "ESH", i18n("Western Sahara") ); + countryCodeMap.insert( "YEM", i18n("Yemen") ); + countryCodeMap.insert( "ZMB", i18n("Zambia") ); + countryCodeMap.insert( "ZWE", i18n("Zimbabwe") ); + + // Supplemental IPTC/IIM country codes. + + countryCodeMap.insert( "XUN", i18n("United Nations") ); + countryCodeMap.insert( "XEU", i18n("European Union") ); + countryCodeMap.insert( "XSP", i18n("Space") ); + countryCodeMap.insert( "XSE", i18n("At Sea") ); + countryCodeMap.insert( "XIF", i18n("In Flight") ); + countryCodeMap.insert( "XEN", i18n("England") ); + countryCodeMap.insert( "XSC", i18n("Scotland") ); + countryCodeMap.insert( "XNI", i18n("Northern Ireland") ); + countryCodeMap.insert( "XWA", i18n("Wales") ); + countryCodeMap.insert( "PSE", i18n("Palestine") ); + countryCodeMap.insert( "GZA", i18n("Gaza") ); + countryCodeMap.insert( "JRO", i18n("Jericho") ); + } + + typedef QMap CountryCodeMap; + + CountryCodeMap countryCodeMap; +}; + +CountrySelector::CountrySelector(QWidget* parent) + : KComboBox(parent), d(new Private) +{ + for (Private::CountryCodeMap::Iterator it = d->countryCodeMap.begin(); + it != d->countryCodeMap.end(); ++it) + { + addItem(QString("%1 - %2").arg(it.key()).arg(it.value())); + } + + model()->sort(0); + + insertSeparator(count()); + addItem(i18nc("Unknown country", "Unknown")); +} + +CountrySelector::~CountrySelector() +{ + delete d; +} + +void CountrySelector::setCountry(const QString& countryCode) +{ + // NOTE: if countryCode is empty or do not matches code map, unknow is selected from the list. + + int id = count()-1; + for (int i = 0 ; i < d->countryCodeMap.count() ; i++) + { + if (itemText(i).left(3) == countryCode) + { + id = i; + break; + } + } + setCurrentIndex(id); + + kDebug() << count() << " :: " << id; +} + +bool CountrySelector::country(QString& countryCode, QString& countryName) +{ + // Unknow is selected ? + if (currentIndex() == count()-1) + return false; + + countryName = currentText().mid(6); + countryCode = currentText().left(3); + return true; +} + +QString CountrySelector::countryForCode(const QString& countryCode) +{ + Private priv; + return (priv.countryCodeMap[countryCode]); +} + +} // namespace KExiv2Iface diff --git a/libkexiv2/libkexiv2/countryselector.h b/libkexiv2/libkexiv2/countryselector.h new file mode 100644 index 00000000..313bd20f --- /dev/null +++ b/libkexiv2/libkexiv2/countryselector.h @@ -0,0 +1,66 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-07-07 + * @brief country selector combo-box. + * + * @author Copyright (C) 2009-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef COUNTRY_SELECTOR_H +#define COUNTRY_SELECTOR_H + +// Qt includes + +#include +#include + +// KDE includes + +#include + +// Local includes + +#include "libkexiv2_export.h" + +namespace KExiv2Iface +{ + +class KEXIV2_EXPORT CountrySelector : public KComboBox +{ + +public: + + CountrySelector(QWidget* parent); + ~CountrySelector(); + + void setCountry(const QString& countryCode); + bool country(QString& countryCode, QString& countryName); + + static QString countryForCode(const QString& countryCode); + +private: + + class Private; + Private* const d; +}; + +} // namespace KExiv2Iface + +#endif // COUNTRY_SELECTOR_H diff --git a/libkexiv2/libkexiv2/kexiv2.cpp b/libkexiv2/libkexiv2/kexiv2.cpp new file mode 100644 index 00000000..8c98fe69 --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2.cpp @@ -0,0 +1,544 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-09-15 + * @brief Exiv2 library interface for KDE + * + * @author Copyright (C) 2006-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2013 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "kexiv2.h" +#include "kexiv2_p.h" + +// Local includes + +#include "version.h" + +namespace KExiv2Iface +{ + +KExiv2Data::KExiv2Data() + : d(0) +{ +} + +KExiv2Data::KExiv2Data(const KExiv2Data& other) +{ + d = other.d; +} + +KExiv2Data::~KExiv2Data() +{ +} + +KExiv2Data& KExiv2Data::operator=(const KExiv2Data& other) +{ + d = other.d; + return *this; +} + +// ------------------------------------------------------------------------------------------- + +KExiv2::KExiv2() + : d(new Private) +{ +} + +KExiv2::KExiv2(const KExiv2& metadata) + : d(new Private) +{ + d->copyPrivateData(metadata.d); +} + +KExiv2::KExiv2(const KExiv2Data& data) + : d(new Private) +{ + setData(data); +} + +KExiv2::KExiv2(const QString& filePath) + : d(new Private) +{ + load(filePath); +} + +KExiv2::~KExiv2() +{ + delete d; +} + +KExiv2& KExiv2::operator=(const KExiv2& metadata) +{ + d->copyPrivateData(metadata.d); + + return *this; +} + +//-- Statics methods ---------------------------------------------- + +bool KExiv2::initializeExiv2() +{ +#ifdef _XMP_SUPPORT_ + + if (!Exiv2::XmpParser::initialize()) + return false; + + registerXmpNameSpace(QString("http://ns.adobe.com/lightroom/1.0/"), QString("lr")); + registerXmpNameSpace(QString("http://www.digikam.org/ns/kipi/1.0/"), QString("kipi")); + registerXmpNameSpace(QString("http://ns.microsoft.com/photo/1.2/"), QString("MP")); + +#endif // _XMP_SUPPORT_ + + return true; +} + +bool KExiv2::cleanupExiv2() +{ + // Fix memory leak if Exiv2 support XMP. +#ifdef _XMP_SUPPORT_ + + unregisterXmpNameSpace(QString("http://ns.adobe.com/lightroom/1.0/")); + unregisterXmpNameSpace(QString("http://www.digikam.org/ns/kipi/1.0/")); + unregisterXmpNameSpace(QString("http://ns.microsoft.com/photo/1.2/")); + + Exiv2::XmpParser::terminate(); + +#endif // _XMP_SUPPORT_ + + return true; +} + +bool KExiv2::supportXmp() +{ +#ifdef _XMP_SUPPORT_ + return true; +#else + return false; +#endif // _XMP_SUPPORT_ +} + +bool KExiv2::supportMetadataWritting(const QString& typeMime) +{ + if (typeMime == QString("image/jpeg")) + { + return true; + } + else if (typeMime == QString("image/tiff")) + { + return true; + } + else if (typeMime == QString("image/png")) + { + return true; + } + else if (typeMime == QString("image/jp2")) + { + return true; + } + else if (typeMime == QString("image/x-raw")) + { + return true; + } + else if (typeMime == QString("image/pgf")) + { + return true; + } + + return false; +} + +QString KExiv2::Exiv2Version() +{ + // Since 0.14.0 release, we can extract run-time version of Exiv2. + // else we return make version. + + return QString(Exiv2::version()); +} + +QString KExiv2::version() +{ + return QString(kexiv2_version); +} + +QString KExiv2::sidecarFilePathForFile(const QString& path) +{ + QString ret; + if (!path.isEmpty()) + { + ret = path + QString(".xmp"); + } + return ret; +} + +KUrl KExiv2::sidecarUrl(const KUrl& url) +{ + QString sidecarPath = sidecarFilePathForFile(url.path()); + KUrl sidecarUrl(url); + sidecarUrl.setPath(sidecarPath); + return sidecarUrl; +} + +KUrl KExiv2::sidecarUrl(const QString& path) +{ + return KUrl::fromPath(sidecarFilePathForFile(path)); +} + +QString KExiv2::sidecarPath(const QString& path) +{ + return sidecarFilePathForFile(path); +} + +bool KExiv2::hasSidecar(const QString& path) +{ + return QFileInfo(sidecarFilePathForFile(path)).exists(); +} + +//-- General methods ---------------------------------------------- + +KExiv2Data KExiv2::data() const +{ + KExiv2Data data; + data.d = d->data; + return data; +} + +void KExiv2::setData(const KExiv2Data& data) +{ + if (data.d) + { + d->data = data.d; + } + else + { + // KExiv2Data can have a null pointer, + // but we never want a null pointer in Private. + d->data->clear(); + } +} + +bool KExiv2::loadFromData(const QByteArray& imgData) const +{ + if (imgData.isEmpty()) + return false; + + try + { + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open((Exiv2::byte*)imgData.data(), imgData.size()); + + d->filePath.clear(); + image->readMetadata(); + + // Size and mimetype --------------------------------- + + d->pixelSize = QSize(image->pixelWidth(), image->pixelHeight()); + d->mimeType = image->mimeType().c_str(); + + // Image comments --------------------------------- + + d->imageComments() = image->comment(); + + // Exif metadata ---------------------------------- + + d->exifMetadata() = image->exifData(); + + // Iptc metadata ---------------------------------- + + d->iptcMetadata() = image->iptcData(); + +#ifdef _XMP_SUPPORT_ + + // Xmp metadata ----------------------------------- + + d->xmpMetadata() = image->xmpData(); + +#endif // _XMP_SUPPORT_ + + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot load metadata using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::load(const QString& filePath) const +{ + if (filePath.isEmpty()) + { + return false; + } + + d->filePath = filePath; + bool hasLoaded = false; + + try + { + Exiv2::Image::AutoPtr image; + + image = Exiv2::ImageFactory::open((const char*)(QFile::encodeName(filePath))); + + image->readMetadata(); + + // Size and mimetype --------------------------------- + + d->pixelSize = QSize(image->pixelWidth(), image->pixelHeight()); + d->mimeType = image->mimeType().c_str(); + + // Image comments --------------------------------- + + d->imageComments() = image->comment(); + + // Exif metadata ---------------------------------- + + d->exifMetadata() = image->exifData(); + + // Iptc metadata ---------------------------------- + + d->iptcMetadata() = image->iptcData(); + +#ifdef _XMP_SUPPORT_ + + // Xmp metadata ----------------------------------- + d->xmpMetadata() = image->xmpData(); + +#endif // _XMP_SUPPORT_ + + hasLoaded = true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot load metadata from file ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#ifdef _XMP_SUPPORT_ + try + { + if (d->useXMPSidecar4Reading) + { + QString xmpSidecarPath = sidecarFilePathForFile(filePath); + QFileInfo xmpSidecarFileInfo(xmpSidecarPath); + + Exiv2::Image::AutoPtr xmpsidecar; + if (xmpSidecarFileInfo.exists() && xmpSidecarFileInfo.isReadable()) + { + // Read sidecar data + xmpsidecar = Exiv2::ImageFactory::open((const char*)QFile::encodeName(xmpSidecarPath)); + xmpsidecar->readMetadata(); + + // Merge + d->loadSidecarData(xmpsidecar); + hasLoaded = true; + } + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot load XMP sidecar", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#endif // _XMP_SUPPORT_ + + return hasLoaded; +} + +bool KExiv2::save(const QString& imageFilePath) const +{ + // If our image is really a symlink, we should follow the symlink so that + // when we delete the file and rewrite it, we are honoring the symlink + // (rather than just deleting it and putting a file there). + + // However, this may be surprising to the user when they are writing sidecar + // files. They might expect them to show up where the symlink is. So, we + // shouldn't follow the link when figuring out what the filename for the + // sidecar should be. + + // Note, we are not yet handling the case where the sidecar itself is a + // symlink. + QString regularFilePath = imageFilePath; // imageFilePath might be a + // symlink. Below we will change + // regularFile to the pointed to + // file if so. + QFileInfo givenFileInfo(imageFilePath); + if (givenFileInfo.isSymLink()) + { + kDebug() << "filePath" << imageFilePath << "is a symlink." + << "Using target" << givenFileInfo.canonicalPath(); + + regularFilePath = givenFileInfo.canonicalPath();// Walk all the symlinks + } + + // NOTE: see B.K.O #137770 & #138540 : never touch the file if is read only. + QFileInfo finfo(regularFilePath); + QFileInfo dinfo(finfo.path()); + if (!dinfo.isWritable()) + { + kDebug() << "Dir '" << dinfo.filePath() << "' is read-only. Metadata not saved."; + return false; + } + + bool writeToFile = false; + bool writeToSidecar = false; + bool writeToSidecarIfFileNotPossible = false; + bool writtenToFile = false; + bool writtenToSidecar = false; + + kDebug() << "KExiv2::metadataWritingMode" << d->metadataWritingMode; + + switch(d->metadataWritingMode) + { + case WRITETOSIDECARONLY: + writeToSidecar = true; + break; + case WRITETOIMAGEONLY: + writeToFile = true; + break; + case WRITETOSIDECARANDIMAGE: + writeToFile = true; + writeToSidecar = true; + break; + case WRITETOSIDECARONLY4READONLYFILES: + writeToFile = true; + writeToSidecarIfFileNotPossible = true; + break; + } + + if (writeToFile) + { + kDebug() << "Will write Metadata to file" << finfo.fileName(); + writtenToFile = d->saveToFile(finfo); + if (writeToFile) + { + kDebug() << "Metadata for file" << finfo.fileName() << "written to file."; + } + } + + if (writeToSidecar || (writeToSidecarIfFileNotPossible && !writtenToFile)) + { + kDebug() << "Will write XMP sidecar for file" << givenFileInfo.fileName(); + writtenToSidecar = d->saveToXMPSidecar(imageFilePath); + if (writtenToSidecar) + { + kDebug() << "Metadata for file '" << givenFileInfo.fileName() << "' written to XMP sidecar."; + } + } + + return writtenToFile || writtenToSidecar; +} + +bool KExiv2::applyChanges() const +{ + if (d->filePath.isEmpty()) + { + kDebug() << "Failed to apply changes: file path is empty!"; + return false; + } + + return save(d->filePath); +} + +bool KExiv2::isEmpty() const +{ + if (!hasComments() && !hasExif() && !hasIptc() && !hasXmp()) + return true; + + return false; +} + +void KExiv2::setFilePath(const QString& path) +{ + d->filePath = path; +} + +QString KExiv2::getFilePath() const +{ + return d->filePath; +} + +QSize KExiv2::getPixelSize() const +{ + return d->pixelSize; +} + +QString KExiv2::getMimeType() const +{ + return d->mimeType; +} + +void KExiv2::setWriteRawFiles(const bool on) +{ + d->writeRawFiles = on; +} + +bool KExiv2::writeRawFiles() const +{ + return d->writeRawFiles; +} + +void KExiv2::setUseXMPSidecar4Reading(const bool on) +{ + d->useXMPSidecar4Reading = on; +} + +bool KExiv2::useXMPSidecar4Reading() const +{ + return d->useXMPSidecar4Reading; +} + +void KExiv2::setMetadataWritingMode(const int mode) +{ + d->metadataWritingMode = mode; +} + +int KExiv2::metadataWritingMode() const +{ + return d->metadataWritingMode; +} + +void KExiv2::setUpdateFileTimeStamp(bool on) +{ + d->updateFileTimeStamp = on; +} + +bool KExiv2::updateFileTimeStamp() const +{ + return d->updateFileTimeStamp; +} + +bool KExiv2::setProgramId(bool /*on*/) const +{ + return true; +} + +} // NameSpace KExiv2Iface diff --git a/libkexiv2/libkexiv2/kexiv2.h b/libkexiv2/libkexiv2/kexiv2.h new file mode 100644 index 00000000..669e7920 --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2.h @@ -0,0 +1,1109 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-09-15 + * @brief Exiv2 library interface for KDE + * @brief Exiv2: http://www.exiv2.org + * @brief Exif : http://www.exif.org/Exif2-2.PDF + * @brief Iptc : http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf + * @brief Xmp : http://www.adobe.com/devnet/xmp/pdfs/xmp_specification.pdf + * @brief http://www.iptc.org/std/Iptc4xmpCore/1.0/specification/Iptc4xmpCore_1.0-spec-XMPSchema_8.pdf + * @brief Paper: http://www.metadataworkinggroup.com/pdf/mwg_guidance.pdf + * + * @author Copyright (C) 2006-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2013 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef KEXIV2_H +#define KEXIV2_H + +// QT includes + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// KDE includes. + +#include + +// Local includes + +#include "libkexiv2_export.h" +#include "kexiv2data.h" + +namespace KExiv2Iface +{ + +class KEXIV2_EXPORT KExiv2 +{ + +public: + + /** The image metadata writing mode, between image file metadata and XMP sidecar file, depending on the context. + * @sa MetadataWritingMode(), metadataWritingMode() + */ + enum MetadataWritingMode + { + /// Write metadata to image file only. + WRITETOIMAGEONLY = 0, + + /// Write metadata to sidecar file only. + WRITETOSIDECARONLY = 1, + + /// Write metadata to image and sidecar files. + WRITETOSIDECARANDIMAGE = 2, + + /// Write metadata to sidecar file only for read only images such as RAW files for example. + WRITETOSIDECARONLY4READONLYFILES = 3 + }; + + /** The image color workspace values given by Exif metadata. + */ + enum ImageColorWorkSpace + { + WORKSPACE_UNSPECIFIED = 0, + WORKSPACE_SRGB = 1, + WORKSPACE_ADOBERGB = 2, + WORKSPACE_UNCALIBRATED = 65535 + }; + + /** The image orientation values given by Exif metadata. + */ + enum ImageOrientation + { + ORIENTATION_UNSPECIFIED = 0, + ORIENTATION_NORMAL = 1, + ORIENTATION_HFLIP = 2, + ORIENTATION_ROT_180 = 3, + ORIENTATION_VFLIP = 4, + ORIENTATION_ROT_90_HFLIP = 5, + ORIENTATION_ROT_90 = 6, + ORIENTATION_ROT_90_VFLIP = 7, + ORIENTATION_ROT_270 = 8 + }; + + /** + * Xmp tag types, used by setXmpTag, only first three types are used + */ + enum XmpTagType + { + NormalTag = 0, + ArrayBagTag = 1, + StructureTag = 2, + ArrayLangTag = 3, + ArraySeqTag = 4 + }; + + /** A map used to store Tags Key and Tags Value. + */ + typedef QMap MetaDataMap; + + /** A map used to store a list of Alternative Language values. + The map key is the language code following RFC3066 notation + (like "fr-FR" for French), and the map value the text. + */ + typedef QMap AltLangMap; + + /** A map used to store Tags Key and a list of Tags properties : + - name, + - title, + - description. + */ + typedef QMap TagsMap; + +public: + + /** Standard constructor. + */ + KExiv2(); + + /** Copy constructor. + */ + KExiv2(const KExiv2& metadata); + + /** Constructor to load from parsed data. + */ + KExiv2(const KExiv2Data& data); + + /** Contructor to Load Metadata from image file. + */ + KExiv2(const QString& filePath); + + /** Standard destructor + */ + virtual ~KExiv2(); + + /** Create a copy of container + */ + KExiv2& operator=(const KExiv2& metadata); + +public: + + //----------------------------------------------------------------- + /// @name Static methods + //@{ + + /** Return true if Exiv2 library initialization is done properly. + This method must be called before using libkexiv2 with multithreading. + It initialize several non re-entrancy code from Adobe XMP SDK + See B.K.O #166424 for details. Call cleanupExiv2() to clean things up later. + */ + static bool initializeExiv2(); + + /** Return true if Exiv2 library memory allocations are cleaned properly. + This method must be called after using libkexiv2 with multithreading. + It cleans up memory used by Adobe XMP SDK + See B.K.O #166424 for details. + */ + static bool cleanupExiv2(); + + /** Return true if library can handle Xmp metadata + */ + static bool supportXmp(); + + /** Return true if library can write metadata to typeMime file format. + */ + static bool supportMetadataWritting(const QString& typeMime); + + /** Return a string version of Exiv2 release in format "major.minor.patch" + */ + static QString Exiv2Version(); + + /** Return a string version of libkexiv2 release + */ + static QString version(); + + /** Return the XMP Sidecar file path for a image file path. + * If image file path do not include a file name or is empty, this function return a null string. + */ + static QString sidecarFilePathForFile(const QString& path); + + /** Like sidecarFilePathForFile(), but works for local file path. + */ + static QString sidecarPath(const QString& path); + + /** Like sidecarFilePathForFile(), but works for remote URLs. + */ + static KUrl sidecarUrl(const KUrl& url); + + /** Gives a file url for a local path. + */ + static KUrl sidecarUrl(const QString& path); + + /** Performs a QFileInfo based check if the given local file has a sidecar. + */ + static bool hasSidecar(const QString& path); + + //@} + + //----------------------------------------------------------------- + /// @name General methods + //@{ + + KExiv2Data data() const; + void setData(const KExiv2Data& data); + + /** Load all metadata (Exif, Iptc, Xmp, and JFIF Comments) from a byte array. + Return true if metadata have been loaded successfully from image data. + */ + bool loadFromData(const QByteArray& imgData) const; + + /** Load all metadata (Exif, Iptc, Xmp, and JFIF Comments) from a picture (JPEG, RAW, TIFF, PNG, + DNG, etc...). Return true if metadata have been loaded successfully from file. + */ + virtual bool load(const QString& filePath) const; + + /** Save all metadata to a file. This one can be different than original picture to perform + transfert operation Return true if metadata have been saved into file. + */ + bool save(const QString& filePath) const; + + /** The same than save() method, but it apply on current image. Return true if metadata + have been saved into file. + */ + bool applyChanges() const; + + /** Return 'true' if metadata container in memory as no Comments, Exif, Iptc, and Xmp. + */ + bool isEmpty() const; + + /** Set the file path of current image. + */ + void setFilePath(const QString& path); + + /** Return the file path of current image. + */ + QString getFilePath() const; + + /** Returns the pixel size of the current image. This information is read from the file, + * not from the metadata. The returned QSize is valid if the KExiv2 object was _constructed_ + * by reading a file or image data; the information is not available when the object + * was created from KExiv2Data. + * Note that in the Exif or XMP metadata, there may be fields describing the image size. + * These fields are not accessed by this method. + * When replacing the metadata with setData(), the metadata may change; this information + * always keeps referring to the file it was initially read from. + */ + QSize getPixelSize() const; + + /** Returns the mime type of this image. The information is read from the file; + * see the docs for getPixelSize() to know when it is available. + */ + QString getMimeType() const; + + /** Enable or disable writing metadata operations to RAW tiff based files. + It requires Exiv2 0.18. By default RAW files are untouched. + */ + void setWriteRawFiles(const bool on); + + /** Return true if writing metadata operations on RAW tiff based files is enabled. + It's require Exiv2 0.18. + */ + bool writeRawFiles() const; + + /** Enable or disable using XMP sidecar for reading metadata + */ + void setUseXMPSidecar4Reading(const bool on); + + /** Return true if using XMP sidecar for reading metadata is enabled. + */ + bool useXMPSidecar4Reading() const; + + /** Set metadata writing mode. + * @param mode Metadata writing mode as defined by the #MetadataWritingMode enum. + * @sa MetadataWritingMode, metadataWritingMode() + */ + void setMetadataWritingMode(const int mode); + + /** Return the metadata writing mode. + * @returns Metadata writing mode as defined by the #MetadataWritingMode enum. + * @sa MetadataWritingMode, setMetadataWritingMode() + */ + int metadataWritingMode() const; + + /** Enable or disable file timestamp updating when metadata are saved. + By default files timestamp are untouched. + */ + void setUpdateFileTimeStamp(bool on); + + /** Return true if file timestamp is updated when metadata are saved. + */ + bool updateFileTimeStamp() const; + + //@} + + //------------------------------------------------------------------- + /// @name Metadata image information manipulation methods + //@{ + + /** Set Program name and program version in Exif and Iptc Metadata. Return true if information + have been changed in metadata. + */ + bool setImageProgramId(const QString& program, const QString& version) const; + + /** Return the size of image in pixels using Exif tags. Return a null dimmension if size cannot + be found. + */ + QSize getImageDimensions() const; + + /** Set the size of image in pixels in Exif tags. Return true if size have been changed + in metadata. + */ + bool setImageDimensions(const QSize& size, bool setProgramName=true) const; + + /** Return the image orientation set in Exif metadata. The makernotes of image are also parsed to + get this information. See ImageOrientation values for details. + */ + KExiv2::ImageOrientation getImageOrientation() const; + + /** Set the Exif orientation tag of image. See ImageOrientation values for details + Return true if orientation have been changed in metadata. + */ + bool setImageOrientation(ImageOrientation orientation, bool setProgramName=true) const; + + /** Return the image color-space set in Exif metadata. The makernotes of image are also parsed to + get this information. See ImageColorWorkSpace values for details. + */ + KExiv2::ImageColorWorkSpace getImageColorWorkSpace() const; + + /** Set the Exif color-space tag of image. See ImageColorWorkSpace values for details + Return true if work-space have been changed in metadata. + */ + bool setImageColorWorkSpace(ImageColorWorkSpace workspace, bool setProgramName=true) const; + + /** Return the time stamp of image. Exif information are check in first, IPTC in second + if image don't have Exif information. If no time stamp is found, a null date is returned. + */ + QDateTime getImageDateTime() const; + + /** Set the Exif and Iptc time stamp. If 'setDateTimeDigitized' parameter is true, the 'Digitalized' + time stamp is set, else only 'Created' time stamp is set. + */ + bool setImageDateTime(const QDateTime& dateTime, bool setDateTimeDigitized=false, + bool setProgramName=true) const; + + /** Return the digitization time stamp of the image. First Exif information is checked, then IPTC. + If no digitization time stamp is found, getImageDateTime() is called if fallbackToCreationTime + is true, or a null QDateTime is returned if fallbackToCreationTime is false. + */ + QDateTime getDigitizationDateTime(bool fallbackToCreationTime=false) const; + + /** Return a QImage copy of Iptc preview image. Return a null image if preview cannot + be found. + */ + bool getImagePreview(QImage& preview) const; + + /** Set the Iptc preview image. The thumbnail image must have the right size before (64Kb max + with JPEG file, else 256Kb). Look Iptc specification for details. Return true if preview + have been changed in metadata. + Re-implemente this method if you want to use another image file format than JPEG to + save preview. + */ + virtual bool setImagePreview(const QImage& preview, bool setProgramName=true) const; + + //@} + + //----------------------------------------------------------------- + /// @name Comments manipulation methods + //@{ + + /** Return 'true' if Comments can be written in file. + */ + static bool canWriteComment(const QString& filePath); + + /** Return 'true' if metadata container in memory as Comments. + */ + bool hasComments() const; + + /** Clear the Comments metadata container in memory. + */ + bool clearComments() const; + + /** Return a Qt byte array copy of Comments container get from current image. + Comments are JFIF section of JPEG images. Look Exiv2 API for more information. + Return a null Qt byte array if there is no Comments metadata in memory. + */ + QByteArray getComments() const; + + /** Return a Qt string object of Comments from current image decoded using + the 'detectEncodingAndDecode()' method. Return a null string if there is no + Comments metadata available. + */ + QString getCommentsDecoded() const; + + /** Set the Comments data using a Qt byte array. Return true if Comments metadata + have been changed in memory. + */ + bool setComments(const QByteArray& data) const; + + /** Language Alternative autodetection. Return a QString without language alternative + header. Header is saved into 'lang'. If no language alternative is founf, value is returned + as well and 'lang' is set to a null string. + */ + static QString detectLanguageAlt(const QString& value, QString& lang); + + //@} + + //----------------------------------------------------------------- + /// @name Exif manipulation methods + //@{ + + /** Return a map of all standard Exif tags supported by Exiv2. + */ + TagsMap getStdExifTagsList() const; + + /** Return a map of all non-standard Exif tags (makernotes) supported by Exiv2. + */ + TagsMap getMakernoteTagsList() const; + + /** Return 'true' if Exif can be written in file. + */ + static bool canWriteExif(const QString& filePath); + + /** Return 'true' if metadata container in memory as Exif. + */ + bool hasExif() const; + + /** Clear the Exif metadata container in memory. + */ + bool clearExif() const; + + /** Returns the exif data encoded to a QByteArray in a form suitable + for storage in a JPEG image. + Note that this encoding is a lossy operation. + + Set true 'addExifHeader' parameter to add an Exif header to Exif metadata. + Returns a null Qt byte array if there is no Exif metadata in memory. + */ + QByteArray getExifEncoded(bool addExifHeader=false) const; + + /** Set the Exif data using a Qt byte array. Return true if Exif metadata + have been changed in memory. + */ + bool setExif(const QByteArray& data) const; + + /** Return a QImage copy of Exif thumbnail image. Return a null image if thumbnail cannot + be found. The 'fixOrientation' parameter will rotate automatically the thumbnail if Exif + orientation tags information are attached with thumbnail. + */ + QImage getExifThumbnail(bool fixOrientation) const; + + /** Fix orientation of a QImage image accordingly with Exif orientation tag. + Return true if image is rotated, else false. + */ + bool rotateExifQImage(QImage& image, ImageOrientation orientation) const; + + /** Set the Exif Thumbnail image. The thumbnail image must have the right dimensions before. + Look Exif specification for details. Return true if thumbnail have been changed in metadata. + */ + bool setExifThumbnail(const QImage& thumb, bool setProgramName=true) const; + + /** Remove the Exif Thumbnail from the image */ + bool removeExifThumbnail() const; + + /** Adds a JPEG thumbnail to a TIFF images. Use this instead of setExifThumbnail for TIFF images. */ + bool setTiffThumbnail(const QImage& thumb, bool setProgramName=true) const; + + /** Return a QString copy of Exif user comments. Return a null string if user comments cannot + be found. + */ + QString getExifComment() const; + + /** Set the Exif user comments from image. Look Exif specification for more details about this tag. + Return true if Exif user comments have been changed in metadata. + */ + bool setExifComment(const QString& comment, bool setProgramName=true) const; + + /** Get an Exif tags content like a string. If 'escapeCR' parameter is true, the CR characters + will be removed. If Exif tag cannot be found a null string is returned. + */ + QString getExifTagString(const char* exifTagName, bool escapeCR=true) const; + + /** Set an Exif tag content using a string. Return true if tag is set successfully. + */ + bool setExifTagString(const char* exifTagName, const QString& value, bool setProgramName=true) const; + + /** Get an Exif tag content like a long value. Return true if Exif tag be found. + */ + bool getExifTagLong(const char* exifTagName, long &val) const; + + /** Get an Exif tag content like a long value. Return true if Exif tag be found. + */ + bool getExifTagLong(const char* exifTagName, long &val, int component) const; + + /** Set an Exif tag content using a long value. Return true if tag is set successfully. + */ + bool setExifTagLong(const char* exifTagName, long val, bool setProgramName=true) const; + + /** Get the 'component' index of an Exif tags content like a rational value. + 'num' and 'den' are the numerator and the denominator of the rational value. + Return true if Exif tag be found. + */ + bool getExifTagRational(const char* exifTagName, long int& num, long int& den, int component=0) const; + + /** Set an Exif tag content using a rational value. + 'num' and 'den' are the numerator and the denominator of the rational value. + Return true if tag is set successfully. + */ + bool setExifTagRational(const char* exifTagName, long int num, long int den, bool setProgramName=true) const; + + /** Get an Exif tag content like a bytes array. Return an empty bytes array if Exif + tag cannot be found. + */ + QByteArray getExifTagData(const char* exifTagName) const; + + /** Set an Exif tag content using a bytes array. Return true if tag is set successfully. + */ + bool setExifTagData(const char* exifTagName, const QByteArray& data, bool setProgramName=true) const; + + /** Get an Exif tags content as a QVariant. Returns a null QVariant if the Exif + tag cannot be found. + For string and integer values the matching QVariant types will be used, + for date and time values QVariant::DateTime. + Rationals will be returned as QVariant::List with two integer QVariants (numerator, denominator) + if rationalAsListOfInts is true, as double if rationalAsListOfInts is false. + An exif tag of numerical type may contain more than one value; set component to the desired index. + */ + QVariant getExifTagVariant(const char* exifTagName, bool rationalAsListOfInts=true, bool escapeCR=true, int component=0) const; + + /** Set an Exif tag content using a QVariant. Returns true if tag is set successfully. + All types described for the getExifTagVariant() method are supported. + Calling with a QVariant of type ByteArray is equivalent to calling setExifTagData. + For the meaning of rationalWantSmallDenominator, see the documentation of the convertToRational methods. + Setting a value with multiple components is currently not supported. + */ + bool setExifTagVariant(const char* exifTagName, const QVariant& data, + bool rationalWantSmallDenominator=true, bool setProgramName=true) const; + + /** Remove the Exif tag 'exifTagName' from Exif metadata. Return true if tag is + removed successfully or if no tag was present. + */ + bool removeExifTag(const char* exifTagName, bool setProgramName=true) const; + + /** Return the Exif Tag title or a null string. + */ + QString getExifTagTitle(const char* exifTagName); + + /** Return the Exif Tag description or a null string. + */ + QString getExifTagDescription(const char* exifTagName); + + /** Takes a QVariant value as it could have been retrieved by getExifTagVariant with the given exifTagName, + and returns its value properly converted to a string (including i18n). + This is equivalent to calling getExifTagString directly. + If escapeCR is true CR characters will be removed from the result. + */ + QString createExifUserStringFromValue(const char* exifTagName, const QVariant& val, bool escapeCR=true); + + /** Return a map of Exif tags name/value found in metadata sorted by + Exif keys given by 'exifKeysFilter'. + + 'exifKeysFilter' is a QStringList of Exif keys. + For example, if you use the string list given below: + + "Iop" + "Thumbnail" + "Image" + "Photo" + + List can be empty to not filter output. + + ... this method will return a map of all Exif tags witch : + + - include "Iop", or "Thumbnail", or "Image", or "Photo" in the Exif tag keys + if 'inverSelection' is false. + - not include "Iop", or "Thumbnail", or "Image", or "Photo" in the Exif tag keys + if 'inverSelection' is true. + */ + KExiv2::MetaDataMap getExifTagsDataList(const QStringList& exifKeysFilter=QStringList(), bool invertSelection=false) const; + + //@} + + //------------------------------------------------------------- + /// @name IPTC manipulation methods + //@{ + + /** Return a map of all standard Iptc tags supported by Exiv2. + */ + KExiv2::TagsMap getIptcTagsList() const; + + /** Return 'true' if Iptc can be written in file. + */ + static bool canWriteIptc(const QString& filePath); + + /** Return 'true' if metadata container in memory as Iptc. + */ + bool hasIptc() const; + + /** Clear the Iptc metadata container in memory. + */ + bool clearIptc() const; + + /** Return a Qt byte array copy of Iptc container get from current image. + Set true 'addIrbHeader' parameter to add an Irb header to Iptc metadata. + Return a null Qt byte array if there is no Iptc metadata in memory. + */ + QByteArray getIptc(bool addIrbHeader=false) const; + + /** Set the Iptc data using a Qt byte array. Return true if Iptc metadata + have been changed in memory. + */ + bool setIptc(const QByteArray& data) const; + + /** Get an Iptc tag content like a string. If 'escapeCR' parameter is true, the CR characters + will be removed. If Iptc tag cannot be found a null string is returned. + */ + QString getIptcTagString(const char* iptcTagName, bool escapeCR=true) const; + + /** Set an Iptc tag content using a string. Return true if tag is set successfully. + */ + bool setIptcTagString(const char* iptcTagName, const QString& value, bool setProgramName=true) const; + + /** Returns a strings list with of multiple Iptc tags from the image. Return an empty list if no tag is found. */ + /** Get the values of all IPTC tags with the given tag name in a string list. + (In Iptc, there can be multiple tags with the same name) + If the 'escapeCR' parameter is true, the CR characters + will be removed. + If no tag can be found an empty list is returned. + */ + QStringList getIptcTagsStringList(const char* iptcTagName, bool escapeCR=true) const; + + /** Set multiple Iptc tags contents using a strings list. 'maxSize' is the max characters size + of one entry. Return true if all tags have been set successfully. + */ + bool setIptcTagsStringList(const char* iptcTagName, int maxSize, + const QStringList& oldValues, const QStringList& newValues, + bool setProgramName=true) const; + + /** Get an Iptc tag content as a bytes array. Return an empty bytes array if Iptc + tag cannot be found. + */ + QByteArray getIptcTagData(const char* iptcTagName) const; + + /** Set an Iptc tag content using a bytes array. Return true if tag is set successfully. + */ + bool setIptcTagData(const char* iptcTagName, const QByteArray& data, bool setProgramName=true) const; + + /** Remove the all instance of Iptc tags 'iptcTagName' from Iptc metadata. Return true if all + tags have been removed successfully (or none were present). + */ + bool removeIptcTag(const char* iptcTagName, bool setProgramName=true) const; + + /** Return the Iptc Tag title or a null string. + */ + QString getIptcTagTitle(const char* iptcTagName); + + /** Return the Iptc Tag description or a null string. + */ + QString getIptcTagDescription(const char* iptcTagName); + + /** Return a map of Iptc tags name/value found in metadata sorted by + Iptc keys given by 'iptcKeysFilter'. + + 'iptcKeysFilter' is a QStringList of Iptc keys. + For example, if you use the string list given below: + + "Envelope" + "Application2" + + List can be empty to not filter output. + + ... this method will return a map of all Iptc tags witch : + + - include "Envelope", or "Application2" in the Iptc tag keys + if 'inverSelection' is false. + - not include "Envelope", or "Application2" in the Iptc tag keys + if 'inverSelection' is true. + */ + KExiv2::MetaDataMap getIptcTagsDataList(const QStringList& iptcKeysFilter=QStringList(), bool invertSelection=false) const; + + /** Return a strings list of Iptc keywords from image. Return an empty list if no keyword are set. + */ + QStringList getIptcKeywords() const; + + /** Set Iptc keywords using a list of strings defined by 'newKeywords' parameter. Use 'getImageKeywords()' + method to set 'oldKeywords' parameter with existing keywords from image. The method will compare + all new keywords with all old keywords to prevent duplicate entries in image. Return true if keywords + have been changed in metadata. + */ + bool setIptcKeywords(const QStringList& oldKeywords, const QStringList& newKeywords, + bool setProgramName=true) const; + + /** Return a strings list of Iptc subjects from image. Return an empty list if no subject are set. + */ + QStringList getIptcSubjects() const; + + /** Set Iptc subjects using a list of strings defined by 'newSubjects' parameter. Use 'getImageSubjects()' + method to set 'oldSubjects' parameter with existing subjects from image. The method will compare + all new subjects with all old subjects to prevent duplicate entries in image. Return true if subjects + have been changed in metadata. + */ + bool setIptcSubjects(const QStringList& oldSubjects, const QStringList& newSubjects, + bool setProgramName=true) const; + + /** Return a strings list of Iptc sub-categories from image. Return an empty list if no sub-category + are set. + */ + QStringList getIptcSubCategories() const; + + /** Set Iptc sub-categories using a list of strings defined by 'newSubCategories' parameter. Use + 'getImageSubCategories()' method to set 'oldSubCategories' parameter with existing sub-categories + from image. The method will compare all new sub-categories with all old sub-categories to prevent + duplicate entries in image. Return true if sub-categories have been changed in metadata. + */ + bool setIptcSubCategories(const QStringList& oldSubCategories, const QStringList& newSubCategories, + bool setProgramName=true) const; + + //@} + + //------------------------------------------------------------ + /// @name XMP manipulation methods + //@{ + + /** Return a map of all standard Xmp tags supported by Exiv2. + */ + KExiv2::TagsMap getXmpTagsList() const; + + /** Return 'true' if Xmp can be written in file. + */ + static bool canWriteXmp(const QString& filePath); + + /** Return 'true' if metadata container in memory as Xmp. + */ + bool hasXmp() const; + + /** Clear the Xmp metadata container in memory. + */ + bool clearXmp() const; + + /** Return a Qt byte array copy of XMp container get from current image. + Return a null Qt byte array if there is no Xmp metadata in memory. + */ + QByteArray getXmp() const; + + /** Set the Xmp data using a Qt byte array. Return true if Xmp metadata + have been changed in memory. + */ + bool setXmp(const QByteArray& data) const; + + /** Get a Xmp tag content like a string. If 'escapeCR' parameter is true, the CR characters + will be removed. If Xmp tag cannot be found a null string is returned. + */ + QString getXmpTagString(const char* xmpTagName, bool escapeCR=true) const; + + /** Set a Xmp tag content using a string. Return true if tag is set successfully. + */ + bool setXmpTagString(const char* xmpTagName, const QString& value, + bool setProgramName=true) const; + + /** Set a Xmp tag with a specific type. Return true if tag is set successfully. + * This method only accept NormalTag, ArrayBagTag and StructureTag. + * Other XmpTagTypes do nothing + */ + bool setXmpTagString(const char* xmpTagName, const QString& value, + XmpTagType type,bool setProgramName=true) const; + + /** Return the Xmp Tag title or a null string. + */ + QString getXmpTagTitle(const char* xmpTagName); + + /** Return the Xmp Tag description or a null string. + */ + QString getXmpTagDescription(const char* xmpTagName); + + /** Return a map of Xmp tags name/value found in metadata sorted by + Xmp keys given by 'xmpKeysFilter'. + + 'xmpKeysFilter' is a QStringList of Xmp keys. + For example, if you use the string list given below: + + "dc" // Dubling Core schema. + "xmp" // Standard Xmp schema. + + List can be empty to not filter output. + + ... this method will return a map of all Xmp tags witch : + + - include "dc", or "xmp" in the Xmp tag keys + if 'inverSelection' is false. + - not include "dc", or "xmp" in the Xmp tag keys + if 'inverSelection' is true. + */ + KExiv2::MetaDataMap getXmpTagsDataList(const QStringList& xmpKeysFilter=QStringList(), bool invertSelection=false) const; + + /** Get all redondant Alternative Language Xmp tags content like a map. + See AltLangMap class description for details. + If 'escapeCR' parameter is true, the CR characters will be removed from strings. + If Xmp tag cannot be found a null string list is returned. + */ + KExiv2::AltLangMap getXmpTagStringListLangAlt(const char* xmpTagName, bool escapeCR=true) const; + + /** Set an Alternative Language Xmp tag content using a map. See AltLangMap class + description for details. If tag already exist, it wil be removed before. + Return true if tag is set successfully. + */ + bool setXmpTagStringListLangAlt(const char* xmpTagName, const KExiv2::AltLangMap& values, + bool setProgramName) const; + + /** Get a Xmp tag content like a string set with an alternative language + header 'langAlt' (like "fr-FR" for French - RFC3066 notation) + If 'escapeCR' parameter is true, the CR characters will be removed. + If Xmp tag cannot be found a null string is returned. + */ + QString getXmpTagStringLangAlt(const char* xmpTagName, const QString& langAlt, bool escapeCR) const; + + /** Set a Xmp tag content using a string with an alternative language header. 'langAlt' contain the + language alternative information (like "fr-FR" for French - RFC3066 notation) or is null to + set alternative language to default settings ("x-default"). + Return true if tag is set successfully. + */ + bool setXmpTagStringLangAlt(const char* xmpTagName, const QString& value, + const QString& langAlt, bool setProgramName=true) const; + + /** Get a Xmp tag content like a sequence of strings. If 'escapeCR' parameter is true, the CR characters + will be removed from strings. If Xmp tag cannot be found a null string list is returned. + */ + QStringList getXmpTagStringSeq(const char* xmpTagName, bool escapeCR=true) const; + + /** Set a Xmp tag content using the sequence of strings 'seq'. + Return true if tag is set successfully. + */ + bool setXmpTagStringSeq(const char* xmpTagName, const QStringList& seq, + bool setProgramName=true) const; + + /** Get a Xmp tag content like a bag of strings. If 'escapeCR' parameter is true, the CR characters + will be removed from strings. If Xmp tag cannot be found a null string list is returned. + */ + QStringList getXmpTagStringBag(const char* xmpTagName, bool escapeCR) const; + + /** Set a Xmp tag content using the bag of strings 'bag'. + Return true if tag is set successfully. + */ + bool setXmpTagStringBag(const char* xmpTagName, const QStringList& bag, + bool setProgramName=true) const; + + /** Set an Xmp tag content using a list of strings defined by the 'entriesToAdd' parameter. + The existing entries are preserved. The method will compare + all new with all already existing entries to prevent duplicates in the image. + Return true if the entries have been added to metadata. + */ + bool addToXmpTagStringBag(const char* xmpTagName, const QStringList& entriesToAdd, + bool setProgramName) const; + + /** Remove those Xmp tag entries that are listed in entriesToRemove from the entries in metadata. + Return true if tag entries are no longer contained in metadata. + All other entries are preserved. + */ + bool removeFromXmpTagStringBag(const char* xmpTagName, const QStringList& entriesToRemove, + bool setProgramName) const; + + /** Get an Xmp tag content as a QVariant. Returns a null QVariant if the Xmp + tag cannot be found. + For string and integer values the matching QVariant types will be used, + for date and time values QVariant::DateTime. + Rationals will be returned as QVariant::List with two integer QVariants (numerator, denominator) + if rationalAsListOfInts is true, as double if rationalAsListOfInts is false. + Arrays (ordered, unordered, alternative) are returned as type StringList. + LangAlt values will have type Map (QMap) with the language + code as key and the contents as value, of type String. + */ + QVariant getXmpTagVariant(const char* xmpTagName, bool rationalAsListOfInts=true, bool stringEscapeCR=true) const; + + /** Return a strings list of Xmp keywords from image. Return an empty list if no keyword are set. + */ + QStringList getXmpKeywords() const; + + /** Set Xmp keywords using a list of strings defined by 'newKeywords' parameter. + The existing keywords from image are preserved. The method will compare + all new keywords with all already existing keywords to prevent duplicate entries in image. + Return true if keywords have been changed in metadata. + */ + bool setXmpKeywords(const QStringList& newKeywords, bool setProgramName=true) const; + + /** Remove those Xmp keywords that are listed in keywordsToRemove from the keywords in metadata. + Return true if keywords are no longer contained in metadata. + */ + bool removeXmpKeywords(const QStringList& keywordsToRemove, bool setProgramName=true); + + /** Return a strings list of Xmp subjects from image. Return an empty list if no subject are set. + */ + QStringList getXmpSubjects() const; + + /** Set Xmp subjects using a list of strings defined by 'newSubjects' parameter. + The existing subjects from image are preserved. The method will compare + all new subject with all already existing subject to prevent duplicate entries in image. + Return true if subjects have been changed in metadata. + */ + bool setXmpSubjects(const QStringList& newSubjects, bool setProgramName=true) const; + + /** Remove those Xmp subjects that are listed in subjectsToRemove from the subjects in metadata. + Return true if subjects are no longer contained in metadata. + */ + bool removeXmpSubjects(const QStringList& subjectsToRemove, bool setProgramName=true); + + /** Return a strings list of Xmp sub-categories from image. Return an empty list if no sub-category + are set. + */ + QStringList getXmpSubCategories() const; + + /** Set Xmp sub-categories using a list of strings defined by 'newSubCategories' parameter. + The existing sub-categories from image are preserved. The method will compare + all new sub-categories with all already existing sub-categories to prevent duplicate entries in image. + Return true if sub-categories have been changed in metadata. + */ + bool setXmpSubCategories(const QStringList& newSubCategories, bool setProgramName=true) const; + + /** Remove those Xmp sub-categories that are listed in categoriesToRemove from the sub-categories in metadata. + Return true if subjects are no longer contained in metadata. + */ + bool removeXmpSubCategories(const QStringList& categoriesToRemove, bool setProgramName=true); + + /** Remove the Xmp tag 'xmpTagName' from Xmp metadata. Return true if tag is + removed successfully or if no tag was present. + */ + bool removeXmpTag(const char* xmpTagName, bool setProgramName=true) const; + + + /** Register a namespace which Exiv2 doesn't know yet. This is only needed + when new Xmp properties are added manually. 'uri' is the namespace url and prefix the + string used to construct new Xmp key (ex. "Xmp.digiKam.tagList"). + NOTE: If the Xmp metadata is read from an image, namespaces are decoded and registered + by Exiv2 at the same time. + */ + static bool registerXmpNameSpace(const QString& uri, const QString& prefix); + + /** Unregister a previously registered custom namespace */ + static bool unregisterXmpNameSpace(const QString& uri); + + //@} + + //------------------------------------------------------------ + /// @name GPS manipulation methods + //@{ + + /** Make sure all static required GPS EXIF and XMP tags exist + */ + bool initializeGPSInfo(const bool setProgramName); + + /** Get all GPS location information set in image. Return true if all information can be found. + */ + bool getGPSInfo(double& altitude, double& latitude, double& longitude) const; + + /** Get GPS location information set in the image, in the GPSCoordinate format + as described in the XMP specification. Returns a null string in the information cannot be found. + */ + QString getGPSLatitudeString() const; + QString getGPSLongitudeString() const; + + /** Get GPS location information set in the image, as a double floating point number as in degrees + where the sign determines the direction ref (North + / South - ; East + / West -). + Returns true if the information is available. + */ + bool getGPSLatitudeNumber(double* const latitude) const; + bool getGPSLongitudeNumber(double* const longitude) const; + + /** Get GPS altitude information, in meters, relative to sea level (positive sign above sea level) + */ + bool getGPSAltitude(double* const altitude) const; + + /** Set all GPS location information into image. Return true if all information have been + changed in metadata. + */ + bool setGPSInfo(const double altitude, const double latitude, const double longitude, const bool setProgramName=true); + + /** Set all GPS location information into image. Return true if all information have been + changed in metadata. If you do not want altitude to be set, pass a null pointer. + */ + bool setGPSInfo(const double* const altitude, const double latitude, const double longitude, const bool setProgramName=true); + + /** Set all GPS location information into image. Return true if all information have been + changed in metadata. + */ + bool setGPSInfo(const double altitude, const QString &latitude, const QString &longitude, const bool setProgramName=true); + + /** Remove all Exif tags relevant of GPS location information. Return true if all tags have been + removed successfully in metadata. + */ + bool removeGPSInfo(const bool setProgramName=true); + + /** This method converts 'number' to a rational value, returned in the 'numerator' and + 'denominator' parameters. Set the precision using 'rounding' parameter. + Use this method if you want to retrieve a most exact rational for a number + without further properties, without any requirements to the denominator. + */ + static void convertToRational(const double number, long int* const numerator, + long int* const denominator, const int rounding); + + /** This method convert a 'number' to a rational value, returned in 'numerator' and + 'denominator' parameters. + This method will be able to retrieve a rational number from a double - if you + constructed your double with 1.0 / 4786.0, this method will retrieve 1 / 4786. + If your number is not expected to be rational, use the method above which is just as + exact with rounding = 4 and more exact with rounding > 4. + */ + static void convertToRationalSmallDenominator(const double number, long int* const numerator, + long int* const denominator); + + /** Converts a GPS position stored as rationals in Exif to the form described + as GPSCoordinate in the XMP specification, either in the from "256,45,34N" or "256,45.566667N" + */ + static QString convertToGPSCoordinateString(const long int numeratorDegrees, const long int denominatorDegrees, + const long int numeratorMinutes, const long int denominatorMinutes, + const long int numeratorSeconds, long int denominatorSeconds, + const char directionReference); + + /** Converts a GPS position stored as double floating point number in degrees to the form described + as GPSCoordinate in the XMP specification. + */ + static QString convertToGPSCoordinateString(const bool isLatitude, double coordinate); + + /** Converts a GPSCoordinate string as defined by XMP to three rationals and the direction reference. + Returns true if the conversion was successful. + If minutes is given in the fractional form, a denominator of 1000000 for the minutes will be used. + */ + static bool convertFromGPSCoordinateString(const QString& coordinate, + long int* const numeratorDegrees, long int* const denominatorDegrees, + long int* const numeratorMinutes, long int* const denominatorMinutes, + long int* const numeratorSeconds, long int* const denominatorSeconds, + char* const directionReference); + + /** Convert a GPSCoordinate string as defined by XMP to a double floating point number in degrees + where the sign determines the direction ref (North + / South - ; East + / West -). + Returns true if the conversion was successful. + */ + static bool convertFromGPSCoordinateString(const QString& gpsString, double* const coordinate); + + /** Converts a GPSCoordinate string to user presentable numbers, integer degrees and minutes and + double floating point seconds, and a direction reference ('N' or 'S', 'E' or 'W') + */ + static bool convertToUserPresentableNumbers(const QString& coordinate, + int* const degrees, int* const minutes, + double* const seconds, char* const directionReference); + + /** Converts a double floating point number to user presentable numbers, integer degrees and minutes and + double floating point seconds, and a direction reference ('N' or 'S', 'E' or 'W'). + The method needs to know for the direction reference + if the latitude or the longitude is meant by the double parameter. + */ + static void convertToUserPresentableNumbers(const bool isLatitude, double coordinate, + int* const degrees, int* const minutes, + double* const seconds, char* const directionReference); + + //@} + +protected: + + /** Re-implement this method to set automatically the Program Name and Program Version + information in Exif and Iptc metadata if 'on' argument is true. This method is called by all methods which + change tags in metadata. By default this method does nothing and returns true. + + In digiKam this method is re-implementated like this: + + if (on) + { + QString version(digikam_version); + QString software("digiKam"); + return setImageProgramId(software, version); + } + + return true; + */ + virtual bool setProgramId(bool on=true) const; + +private: + + /** Internal container to store private members. Used to improve binary compatibility + */ + class Private; + Private* const d; + + friend class KExiv2Previews; +}; + +} // NameSpace KExiv2Iface + +#endif /* KEXIV2_H */ diff --git a/libkexiv2/libkexiv2/kexiv2_p.cpp b/libkexiv2/libkexiv2/kexiv2_p.cpp new file mode 100644 index 00000000..f35b36fa --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2_p.cpp @@ -0,0 +1,538 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2007-09-03 + * @brief Exiv2 library interface for KDE + * + * @author Copyright (C) 2006-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "kexiv2_p.h" + +// C ANSI includes + +extern "C" +{ +#include +#include +} + +namespace KExiv2Iface +{ + +KExiv2::Private::Private() + : data(new KExiv2Data::Private) +{ + writeRawFiles = false; + updateFileTimeStamp = false; + useXMPSidecar4Reading = false; + metadataWritingMode = WRITETOIMAGEONLY; + loadedFromSidecar = false; + Exiv2::LogMsg::setHandler(KExiv2::Private::printExiv2MessageHandler); +} + +KExiv2::Private::~Private() +{ +} + +void KExiv2::Private::copyPrivateData(const Private* const other) +{ + data = other->data; + filePath = other->filePath; + writeRawFiles = other->writeRawFiles; + updateFileTimeStamp = other->updateFileTimeStamp; + useXMPSidecar4Reading = other->useXMPSidecar4Reading; + metadataWritingMode = other->metadataWritingMode; +} + +bool KExiv2::Private::saveToXMPSidecar(const QFileInfo& finfo) const +{ + QString filePath = KExiv2::sidecarFilePathForFile(finfo.filePath()); + + if (filePath.isEmpty()) + { + return false; + } + + try + { + Exiv2::Image::AutoPtr image; + image = Exiv2::ImageFactory::create(Exiv2::ImageType::xmp, (const char*)(QFile::encodeName(filePath))); + return saveOperations(finfo, image); + } + catch( Exiv2::Error& e ) + { + printExiv2ExceptionError("Cannot save metadata to XMP sidecar using Exiv2 ", e); + return false; + } + catch(...) + { + kError() << "Default exception from Exiv2"; + return false; + } +} + +bool KExiv2::Private::saveToFile(const QFileInfo& finfo) const +{ + if (!finfo.isWritable()) + { + kDebug() << "File '" << finfo.fileName().toAscii().constData() << "' is read only. Metadata not written."; + return false; + } + + QStringList rawTiffBasedSupported, rawTiffBasedNotSupported; + + // Raw files supported by Exiv2 0.21 + rawTiffBasedSupported << "dng" << "nef" << "pef" << "orf" << "srw"; + + if (Exiv2::testVersion(0,23,0)) + { + rawTiffBasedSupported << "cr2"; + } + + // Raw files not supported by Exiv2 0.21 + rawTiffBasedNotSupported + << "3fr" << "arw" << "dcr" << "erf" << "k25" << "kdc" + << "mos" << "raw" << "sr2" << "srf" << "rw2"; + + if (!Exiv2::testVersion(0,23,0)) + { + rawTiffBasedNotSupported << "cr2"; + } + + QString ext = finfo.suffix().toLower(); + + if (!writeRawFiles && (rawTiffBasedSupported.contains(ext) || rawTiffBasedNotSupported.contains(ext)) ) + { + kDebug() << finfo.fileName() + << "is a TIFF based RAW file, writing to such a file is disabled by current settings."; + return false; + } + +/* + if (rawTiffBasedNotSupported.contains(ext)) + { + kDebug() << finfo.fileName() + << "is TIFF based RAW file not yet supported. Metadata not saved."; + return false; + } + + if (rawTiffBasedSupported.contains(ext) && !writeRawFiles) + { + kDebug() << finfo.fileName() + << "is TIFF based RAW file supported but writing mode is disabled. " + << "Metadata not saved."; + return false; + } + + kDebug() << "File Extension: " << ext << " is supported for writing mode"; + + bool ret = false; +*/ + + try + { + Exiv2::Image::AutoPtr image; + image = Exiv2::ImageFactory::open((const char*)(QFile::encodeName(finfo.filePath()))); + return saveOperations(finfo, image); + } + catch( Exiv2::Error& e ) + { + printExiv2ExceptionError("Cannot save metadata to image using Exiv2 ", e); + return false; + } + catch(...) + { + kError() << "Default exception from Exiv2"; + return false; + } +} + +bool KExiv2::Private::saveOperations(const QFileInfo& finfo, Exiv2::Image::AutoPtr image) const +{ + try + { + Exiv2::AccessMode mode; + bool wroteComment = false, wroteEXIF = false, wroteIPTC = false, wroteXMP = false; + + // We need to load target file metadata to merge with new one. It's mandatory with TIFF format: + // like all tiff file structure is based on Exif. + image->readMetadata(); + + // Image Comments --------------------------------- + + mode = image->checkMode(Exiv2::mdComment); + + if ((mode == Exiv2::amWrite) || (mode == Exiv2::amReadWrite)) + { + image->setComment(imageComments()); + wroteComment = true; + } + + // Exif metadata ---------------------------------- + + mode = image->checkMode(Exiv2::mdExif); + + if ((mode == Exiv2::amWrite) || (mode == Exiv2::amReadWrite)) + { + if (image->mimeType() == "image/tiff") + { + Exiv2::ExifData orgExif = image->exifData(); + Exiv2::ExifData newExif; + QStringList untouchedTags; + + // With tiff image we cannot overwrite whole Exif data as well, because + // image data are stored in Exif container. We need to take a care about + // to not lost image data. + untouchedTags << "Exif.Image.ImageWidth"; + untouchedTags << "Exif.Image.ImageLength"; + untouchedTags << "Exif.Image.BitsPerSample"; + untouchedTags << "Exif.Image.Compression"; + untouchedTags << "Exif.Image.PhotometricInterpretation"; + untouchedTags << "Exif.Image.FillOrder"; + untouchedTags << "Exif.Image.SamplesPerPixel"; + untouchedTags << "Exif.Image.StripOffsets"; + untouchedTags << "Exif.Image.RowsPerStrip"; + untouchedTags << "Exif.Image.StripByteCounts"; + untouchedTags << "Exif.Image.XResolution"; + untouchedTags << "Exif.Image.YResolution"; + untouchedTags << "Exif.Image.PlanarConfiguration"; + untouchedTags << "Exif.Image.ResolutionUnit"; + + for (Exiv2::ExifData::iterator it = orgExif.begin(); it != orgExif.end(); ++it) + { + if (untouchedTags.contains(it->key().c_str())) + { + newExif[it->key().c_str()] = orgExif[it->key().c_str()]; + } + } + + Exiv2::ExifData readedExif = exifMetadata(); + + for (Exiv2::ExifData::iterator it = readedExif.begin(); it != readedExif.end(); ++it) + { + if (!untouchedTags.contains(it->key().c_str())) + { + newExif[it->key().c_str()] = readedExif[it->key().c_str()]; + } + } + + image->setExifData(newExif); + } + else + { + image->setExifData(exifMetadata()); + } + + wroteEXIF = true; + } + + // Iptc metadata ---------------------------------- + + mode = image->checkMode(Exiv2::mdIptc); + + if ((mode == Exiv2::amWrite) || (mode == Exiv2::amReadWrite)) + { + image->setIptcData(iptcMetadata()); + wroteIPTC = true; + } + + // Xmp metadata ----------------------------------- + + mode = image->checkMode(Exiv2::mdXmp); + + if ((mode == Exiv2::amWrite) || (mode == Exiv2::amReadWrite)) + { +#ifdef _XMP_SUPPORT_ + image->setXmpData(xmpMetadata()); + wroteXMP = true; +#endif + } + + if (!wroteComment && !wroteEXIF && !wroteIPTC && !wroteXMP) + { + kDebug() << "Writing metadata is not supported for file" << finfo.fileName(); + return false; + } + else if (!wroteEXIF || !wroteIPTC || !wroteXMP) + { + kDebug() << "Support for writing metadata is limited for file" << finfo.fileName() + << "EXIF" << wroteEXIF << "IPTC" << wroteIPTC << "XMP" << wroteXMP; + } + + if (!updateFileTimeStamp) + { + // Don't touch access and modification timestamp of file. + struct stat st; + struct utimbuf ut; + int ret = ::stat(QFile::encodeName(filePath), &st); + + if (ret == 0) + { + ut.modtime = st.st_mtime; + ut.actime = st.st_atime; + } + + image->writeMetadata(); + + if (ret == 0) + { + ::utime(QFile::encodeName(filePath), &ut); + } + } + else + { + image->writeMetadata(); + } + + return true; + } + catch( Exiv2::Error& e ) + { + printExiv2ExceptionError("Cannot save metadata using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +void KExiv2Data::Private::clear() +{ + imageComments.clear(); + exifMetadata.clear(); + iptcMetadata.clear(); +#ifdef _XMP_SUPPORT_ + xmpMetadata.clear(); +#endif +} + +void KExiv2::Private::printExiv2ExceptionError(const QString& msg, Exiv2::Error& e) +{ + std::string s(e.what()); + kError() << msg.toAscii().constData() << " (Error #" + << e.code() << ": " << s.c_str(); +} + +void KExiv2::Private::printExiv2MessageHandler(int lvl, const char* msg) +{ + kDebug() << "Exiv2 (" << lvl << ") : " << msg; +} + +QString KExiv2::Private::convertCommentValue(const Exiv2::Exifdatum& exifDatum) const +{ + try + { + std::string comment; + std::string charset; + + comment = exifDatum.toString(); + + // libexiv2 will prepend "charset=\"SomeCharset\" " if charset is specified + // Before conversion to QString, we must know the charset, so we stay with std::string for a while + if (comment.length() > 8 && comment.substr(0, 8) == "charset=") + { + // the prepended charset specification is followed by a blank + std::string::size_type pos = comment.find_first_of(' '); + + if (pos != std::string::npos) + { + // extract string between the = and the blank + charset = comment.substr(8, pos-8); + // get the rest of the string after the charset specification + comment = comment.substr(pos+1); + } + } + + if (charset == "\"Unicode\"") + { + return QString::fromUtf8(comment.data()); + } + else if (charset == "\"Jis\"") + { + QTextCodec* codec = QTextCodec::codecForName("JIS7"); + return codec->toUnicode(comment.c_str()); + } + else if (charset == "\"Ascii\"") + { + return QString::fromLatin1(comment.c_str()); + } + else + { + return detectEncodingAndDecode(comment); + } + } + catch( Exiv2::Error& e ) + { + printExiv2ExceptionError("Cannot convert Comment using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QString(); +} + +QString KExiv2::Private::detectEncodingAndDecode(const std::string& value) const +{ + // For charset autodetection, we could use sophisticated code + // (Mozilla chardet, KHTML's autodetection, QTextCodec::codecForContent), + // but that is probably too much. + // We check for UTF8, Local encoding and ASCII. + // TODO: Gilles ==> Marcel : Look like KEncodingDetector class can provide a full implementation for encoding detection. + + if (value.empty()) + { + return QString(); + } + + if (KStringHandler::isUtf8(value.c_str())) + { + return QString::fromUtf8(value.c_str()); + } + + // Utf8 has a pretty unique byte pattern. + // Thats not true for ASCII, it is not possible + // to reliably autodetect different ISO-8859 charsets. + // So we can use either local encoding, or latin1. + + //TODO: KDE4PORT: check for regression of #134999 (very probably no regression!) + return QString::fromLocal8Bit(value.c_str()); + //return QString::fromLatin1(value.c_str()); +} + +int KExiv2::Private::getXMPTagsListFromPrefix(const QString& pf, KExiv2::TagsMap& tagsMap) const +{ + QList tags; + tags << Exiv2::XmpProperties::propertyList(pf.toAscii().data()); + int i = 0; + + for (QList::iterator it = tags.begin(); it != tags.end(); ++it) + { + while ( (*it) && !QString((*it)->name_).isNull() ) + { + QString key = QLatin1String( Exiv2::XmpKey( pf.toAscii().data(), (*it)->name_ ).key().c_str() ); + QStringList values; + values << (*it)->name_ << (*it)->title_ << (*it)->desc_; + tagsMap.insert(key, values); + ++(*it); + i++; + } + } + + return i; +} + +#ifdef _XMP_SUPPORT_ +void KExiv2::Private::loadSidecarData(Exiv2::Image::AutoPtr xmpsidecar) +{ + // Having a sidecar is a special situation. + // The sidecar data often "dominates", see in particular bug 309058 for important aspects: + // If a field is removed from the sidecar, we must ignore (older) data for this field in the file. + + // First: Ignore file XMP, only use sidecar XMP + xmpMetadata() = xmpsidecar->xmpData(); + loadedFromSidecar = true; + + // EXIF + // Four groups of properties are mapped between EXIF and XMP: + // Date/Time, Description, Copyright, Creator + // A few more tags are defined "writeback" tags in the XMP specification, the sidecar value therefore overrides the Exif value. + // The rest is kept side-by-side. + // (to understand, remember that the xmpsidecar's Exif data is actually XMP data mapped back to Exif) + + // Description, Copyright and Creator is dominated by the sidecar: Remove file Exif fields, if field not in XMP. + ExifMergeHelper exifDominatedHelper; + exifDominatedHelper << QLatin1String("Exif.Image.ImageDescription") + << QLatin1String("Exif.Photo.UserComment") + << QLatin1String("Exif.Image.Copyright") + << QLatin1String("Exif.Image.Artist"); + exifDominatedHelper.exclusiveMerge(xmpsidecar->exifData(), exifMetadata()); + // Date/Time and "the few more" from the XMP spec are handled as writeback + // Note that Date/Time mapping is slightly contradictory in latest specs. + ExifMergeHelper exifWritebackHelper; + exifWritebackHelper << QLatin1String("Exif.Image.DateTime") + << QLatin1String("Exif.Image.DateTime") + << QLatin1String("Exif.Photo.DateTimeOriginal") + << QLatin1String("Exif.Photo.DateTimeDigitized") + << QLatin1String("Exif.Image.Orientation") + << QLatin1String("Exif.Image.XResolution") + << QLatin1String("Exif.Image.YResolution") + << QLatin1String("Exif.Image.ResolutionUnit") + << QLatin1String("Exif.Image.Software") + << QLatin1String("Exif.Photo.RelatedSoundFile"); + exifWritebackHelper.mergeFields(xmpsidecar->exifData(), exifMetadata()); + + // IPTC + // These fields cover almost all relevant IPTC data and are defined in the XMP specification for reconciliation. + IptcMergeHelper iptcDominatedHelper; + iptcDominatedHelper << QLatin1String("Iptc.Application2.ObjectName") + << QLatin1String("Iptc.Application2.Urgency") + << QLatin1String("Iptc.Application2.Category") + << QLatin1String("Iptc.Application2.SuppCategory") + << QLatin1String("Iptc.Application2.Keywords") + << QLatin1String("Iptc.Application2.SubLocation") + << QLatin1String("Iptc.Application2.SpecialInstructions") + << QLatin1String("Iptc.Application2.Byline") + << QLatin1String("Iptc.Application2.BylineTitle") + << QLatin1String("Iptc.Application2.City") + << QLatin1String("Iptc.Application2.ProvinceState") + << QLatin1String("Iptc.Application2.CountryCode") + << QLatin1String("Iptc.Application2.CountryName") + << QLatin1String("Iptc.Application2.TransmissionReference") + << QLatin1String("Iptc.Application2.Headline") + << QLatin1String("Iptc.Application2.Credit") + << QLatin1String("Iptc.Application2.Source") + << QLatin1String("Iptc.Application2.Copyright") + << QLatin1String("Iptc.Application2.Caption") + << QLatin1String("Iptc.Application2.Writer"); + iptcDominatedHelper.exclusiveMerge(xmpsidecar->iptcData(), iptcMetadata()); + + IptcMergeHelper iptcWritebackHelper; + iptcWritebackHelper << QLatin1String("Iptc.Application2.DateCreated") + << QLatin1String("Iptc.Application2.TimeCreated") + << QLatin1String("Iptc.Application2.DigitizationDate") + << QLatin1String("Iptc.Application2.DigitizationTime"); + iptcWritebackHelper.mergeFields(xmpsidecar->iptcData(), iptcMetadata()); + + /* + * TODO: Exiv2 (referring to 0.23) does not correctly synchronize all times values as given below. + * Time values and their synchronization: + * Original Date/Time – Creation date of the intellectual content (e.g. the photograph), + rather than the creatio*n date of the content being shown + Exif DateTimeOriginal (36867, 0x9003) and SubSecTimeOriginal (37521, 0x9291) + IPTC DateCreated (IIM 2:55, 0x0237) and TimeCreated (IIM 2:60, 0x023C) + XMP (photoshop:DateCreated) + * Digitized Date/Time – Creation date of the digital representation + Exif DateTimeDigitized (36868, 0x9004) and SubSecTimeDigitized (37522, 0x9292) + IPTC DigitalCreationDate (IIM 2:62, 0x023E) and DigitalCreationTime (IIM 2:63, 0x023F) + XMP (xmp:CreateDate) + * Modification Date/Time – Modification date of the digital image file + Exif DateTime (306, 0x132) and SubSecTime (37520, 0x9290) + XMP (xmp:ModifyDate) + */ +} +#endif // _XMP_SUPPORT_ + +} // NameSpace KExiv2Iface diff --git a/libkexiv2/libkexiv2/kexiv2_p.h b/libkexiv2/libkexiv2/kexiv2_p.h new file mode 100644 index 00000000..63271af4 --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2_p.h @@ -0,0 +1,328 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2007-09-03 + * @brief Exiv2 library interface for KDE + * + * @author Copyright (C) 2006-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef KEXIV2PRIVATE_H +#define KEXIV2PRIVATE_H + +#include "kexiv2.h" + + // C++ includes + +#include +#include +#include +#include +#include +#include +#include +#include + +// Qt includes + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// KDE includes + +#include +#include +#include +#include +#include + +// Exiv2 includes ------------------------------------------------------- + +// NOTE: All Exiv2 header must be stay there to not expose external source code to Exiv2 API +// and reduce Exiv2 dependency to client code. + +// The pragmas are required to be able to catch exceptions thrown by libexiv2: +// See http://gcc.gnu.org/wiki/Visibility, the section about c++ exceptions. +// They are needed for all libexiv2 versions that do not care about visibility. +#ifdef __GNUC__ +#pragma GCC visibility push(default) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Check if Exiv2 support XMP + +#ifdef EXV_HAVE_XMP_TOOLKIT +# define _XMP_SUPPORT_ 1 +#endif + +// Make sure an EXIV2_TEST_VERSION macro exists: + +#ifdef EXIV2_VERSION +# ifndef EXIV2_TEST_VERSION +# define EXIV2_TEST_VERSION(major,minor,patch) \ + ( EXIV2_VERSION >= EXIV2_MAKE_VERSION(major,minor,patch) ) +# endif +#else +# define EXIV2_TEST_VERSION(major,minor,patch) (false) +#endif + +// With exiv2 > 0.20.0, all makernote header files have been removed to increase binary compatibility. +// See Exiv2 bugzilla entry http://dev.exiv2.org/issues/719 +// and wiki topic http://dev.exiv2.org/boards/3/topics/583 + +#ifdef __GNUC__ +#pragma GCC visibility pop +#endif + +// End of Exiv2 headers ------------------------------------------------------ + +namespace KExiv2Iface +{ + +class KExiv2Data::Private : public QSharedData +{ +public: + + void clear(); + +public: + + std::string imageComments; + + Exiv2::ExifData exifMetadata; + + Exiv2::IptcData iptcMetadata; + +#ifdef _XMP_SUPPORT_ + Exiv2::XmpData xmpMetadata; +#endif +}; + +// -------------------------------------------------------------------------- + +class KExiv2::Private +{ +public: + + Private(); + ~Private(); + + void copyPrivateData(const Private* const other); + + bool saveToXMPSidecar(const QFileInfo& finfo) const; + bool saveToFile(const QFileInfo& finfo) const; + bool saveOperations(const QFileInfo& finfo, Exiv2::Image::AutoPtr image) const; + + /** Wrapper method to convert a Comments content to a QString. + */ + QString convertCommentValue(const Exiv2::Exifdatum& exifDatum) const; + + /** Charset autodetection to convert a string to a QString. + */ + QString detectEncodingAndDecode(const std::string& value) const; + + int getXMPTagsListFromPrefix(const QString& pf, KExiv2::TagsMap& tagsMap) const; + + const Exiv2::ExifData& exifMetadata() const { return data.constData()->exifMetadata; } + const Exiv2::IptcData& iptcMetadata() const { return data.constData()->iptcMetadata; } + const std::string& imageComments() const { return data.constData()->imageComments; } + +#ifdef _XMP_SUPPORT_ + const Exiv2::XmpData& xmpMetadata() const { return data.constData()->xmpMetadata; } +#endif + + Exiv2::ExifData& exifMetadata() { return data.data()->exifMetadata; } + Exiv2::IptcData& iptcMetadata() { return data.data()->iptcMetadata; } + std::string& imageComments() { return data.data()->imageComments; } + +#ifdef _XMP_SUPPORT_ + Exiv2::XmpData& xmpMetadata() { return data.data()->xmpMetadata; } + + void loadSidecarData(Exiv2::Image::AutoPtr xmpsidecar); +#endif + +public: + + /** Generic method to print the Exiv2 C++ Exception error message from 'e'. + * 'msg' string is printed using kDebug rules.. + */ + static void printExiv2ExceptionError(const QString& msg, Exiv2::Error& e); + + /** Generic method to print debug message from Exiv2. + * 'msg' string is printed using kDebug rules. 'lvl' is the debug level of Exiv2 message. + */ + static void printExiv2MessageHandler(int lvl, const char* msg); + +public: + + bool writeRawFiles; + bool updateFileTimeStamp; + + bool useXMPSidecar4Reading; + + /// A mode from #MetadataWritingMode enum. + int metadataWritingMode; + + /// XMP, and parts of EXIF/IPTC, were loaded from an XMP sidecar file + bool loadedFromSidecar; + + QString filePath; + QSize pixelSize; + QString mimeType; + + QSharedDataPointer data; +}; + +template > +class MergeHelper +{ +public: + + KeyStringList keys; + + MergeHelper& operator<<(const KeyString& key) + { + keys << key; + return *this; + } + + /** + * Merge two (Exif,IPTC,Xmp)Data packages, where the result is stored in dest + * and fields from src take precedence over existing data from dest. + */ + void mergeAll(const Data& src, Data& dest) + { + for (typename Data::const_iterator it = src.begin(); it != src.end(); ++it) + { + typename Data::iterator destIt = dest.findKey(Key(it->key())); + + if (destIt == dest.end()) + { + dest.add(*it); + } + else + { + *destIt = *it; + } + } + } + + /** + * Merge two (Exif,IPTC,Xmp)Data packages, the result is stored in dest. + * Only keys in keys are considered for merging. + * Fields from src take precedence over existing data from dest. + */ + void mergeFields(const Data& src, Data& dest) + { + foreach (const KeyString& keyString, keys) + { + Key key(keyString.latin1()); + typename Data::const_iterator it = src.findKey(key); + if (it == src.end()) + { + continue; + } + typename Data::iterator destIt = dest.findKey(key); + if (destIt == dest.end()) + { + dest.add(*it); + } + else + { + *destIt = *it; + } + } + } + + /** + * Merge two (Exif,IPTC,Xmp)Data packages, the result is stored in dest. + * The following steps apply only to keys in "keys": + * The result is determined by src. + * Keys must exist in src to kept in dest. + * Fields from src take precedence over existing data from dest. + */ + void exclusiveMerge(const Data& src, Data& dest) + { + foreach (const KeyString& keyString, keys) + { + Key key(keyString.latin1()); + typename Data::const_iterator it = src.findKey(key); + typename Data::iterator destIt = dest.findKey(key); + + if (destIt == dest.end()) + { + if (it != src.end()) + { + dest.add(*it); + } + } + else + { + if (it == src.end()) + { + dest.erase(destIt); + } + else + { + *destIt = *it; + } + } + } + } +}; + +class ExifMergeHelper : public MergeHelper +{ +}; + +class IptcMergeHelper : public MergeHelper +{ +}; + +#ifdef _XMP_SUPPORT_ +class XmpMergeHelper : public MergeHelper +{ +}; +#endif + + +} // NameSpace KExiv2Iface + +#endif // KEXIV2PRIVATE_H diff --git a/libkexiv2/libkexiv2/kexiv2comments.cpp b/libkexiv2/libkexiv2/kexiv2comments.cpp new file mode 100644 index 00000000..91ea0d9e --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2comments.cpp @@ -0,0 +1,104 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-09-15 + * @brief Comments manipulation methods + * + * @author Copyright (C) 2006-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// Local includes + +#include "kexiv2_p.h" +#include "kexiv2.h" + +namespace KExiv2Iface +{ + +bool KExiv2::canWriteComment(const QString& filePath) +{ + try + { + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open((const char*) + (QFile::encodeName(filePath))); + + Exiv2::AccessMode mode = image->checkMode(Exiv2::mdComment); + return (mode == Exiv2::amWrite || mode == Exiv2::amReadWrite); + } + catch( Exiv2::Error& e ) + { + std::string s(e.what()); + kError() << "Cannot check Comment access mode using Exiv2 (Error #" + << e.code() << ": " << s.c_str() << ")"; + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::hasComments() const +{ + return !d->imageComments().empty(); +} + +bool KExiv2::clearComments() const +{ + return setComments(QByteArray()); +} + +QByteArray KExiv2::getComments() const +{ + return QByteArray(d->imageComments().data(), d->imageComments().size()); +} + +QString KExiv2::getCommentsDecoded() const +{ + return d->detectEncodingAndDecode(d->imageComments()); +} + +bool KExiv2::setComments(const QByteArray& data) const +{ + d->imageComments() = std::string(data.data(), data.size()); + return true; +} + +QString KExiv2::detectLanguageAlt(const QString& value, QString& lang) +{ + // Ex. from an Xmp tag Xmp.tiff.copyright: "lang="x-default" (c) Gilles Caulier 2007" + + if (value.size() > 6 && value.startsWith(QString("lang=\""))) + { + int pos = value.indexOf(QString("\""), 6); + if (pos != -1) + { + lang = value.mid(6, pos-6); + return (value.mid(pos+2)); + } + } + + lang.clear(); + return value; +} + +} // NameSpace KExiv2Iface diff --git a/libkexiv2/libkexiv2/kexiv2data.h b/libkexiv2/libkexiv2/kexiv2data.h new file mode 100644 index 00000000..48e80aff --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2data.h @@ -0,0 +1,66 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-11-15 + * @brief Exiv2 library interface for KDE + * + * @author Copyright (C) 2009-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2009-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef KEXIV2DATA_H +#define KEXIV2DATA_H + +// QT includes + +#include + +// Local includes + +#include "libkexiv2_export.h" + +namespace KExiv2Iface +{ + +class KEXIV2_EXPORT KExiv2Data +{ +public: + + KExiv2Data(); + KExiv2Data(const KExiv2Data&); + ~KExiv2Data(); + + KExiv2Data& operator=(const KExiv2Data&); + +public: + + // Declared as public due to use in KExiv2Priv class + class Private; + +private: + + QSharedDataPointer d; + + friend class KExiv2; +}; + +} // NameSpace KExiv2Iface + +#endif /* KEXIV2_H */ diff --git a/libkexiv2/libkexiv2/kexiv2exif.cpp b/libkexiv2/libkexiv2/kexiv2exif.cpp new file mode 100644 index 00000000..38fee9b4 --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2exif.cpp @@ -0,0 +1,1160 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-09-15 + * @brief Exif manipulation methods + * + * @author Copyright (C) 2006-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "kexiv2.h" +#include "kexiv2_p.h" +#include "rotationmatrix.h" + +// C++ includes + +#include + +// KDE includes + +#include + +namespace KExiv2Iface +{ + +bool KExiv2::canWriteExif(const QString& filePath) +{ + try + { + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open((const char*) + (QFile::encodeName(filePath))); + + Exiv2::AccessMode mode = image->checkMode(Exiv2::mdExif); + + return (mode == Exiv2::amWrite || mode == Exiv2::amReadWrite); + } + catch( Exiv2::Error& e ) + { + std::string s(e.what()); + kError() << "Cannot check Exif access mode using Exiv2 (Error #" + << e.code() << ": " << s.c_str() << ")"; + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::hasExif() const +{ + return !d->exifMetadata().empty(); +} + +bool KExiv2::clearExif() const +{ + try + { + d->exifMetadata().clear(); + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot clear Exif data using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QByteArray KExiv2::getExifEncoded(bool addExifHeader) const +{ + try + { + if (!d->exifMetadata().empty()) + { + QByteArray data; + Exiv2::ExifData& exif = d->exifMetadata(); + Exiv2::Blob blob; + Exiv2::ExifParser::encode(blob, Exiv2::bigEndian, exif); + QByteArray ba((const char*)&blob[0], blob.size()); + if (addExifHeader) + { + const uchar ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; + data.resize(ba.size() + sizeof(ExifHeader)); + memcpy(data.data(), ExifHeader, sizeof(ExifHeader)); + memcpy(data.data()+sizeof(ExifHeader), ba.data(), ba.size()); + } + else + { + data = ba; + } + return data; + } + } + catch( Exiv2::Error& e ) + { + if (!d->filePath.isEmpty()) + kDebug() << "From file " << d->filePath.toAscii().constData(); + + d->printExiv2ExceptionError("Cannot get Exif data using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QByteArray(); +} + +bool KExiv2::setExif(const QByteArray& data) const +{ + try + { + if (!data.isEmpty()) + { + Exiv2::ExifParser::decode(d->exifMetadata(), (const Exiv2::byte*)data.data(), data.size()); + return (!d->exifMetadata().empty()); + } + } + catch( Exiv2::Error& e ) + { + if (!d->filePath.isEmpty()) + kError() << "From file " << d->filePath.toAscii().constData(); + + d->printExiv2ExceptionError("Cannot set Exif data using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +KExiv2::MetaDataMap KExiv2::getExifTagsDataList(const QStringList& exifKeysFilter, bool invertSelection) const +{ + if (d->exifMetadata().empty()) + return MetaDataMap(); + + try + { + Exiv2::ExifData exifData = d->exifMetadata(); + exifData.sortByKey(); + + QString ifDItemName; + MetaDataMap metaDataMap; + + for (Exiv2::ExifData::iterator md = exifData.begin(); md != exifData.end(); ++md) + { + QString key = QString::fromAscii(md->key().c_str()); + + // Decode the tag value with a user friendly output. + QString tagValue; + + if (key == "Exif.Photo.UserComment") + { + tagValue = d->convertCommentValue(*md); + } + else if (key == "Exif.Image.0x935c") + { + tagValue = i18n("Data of size %1", md->value().size()); + } + else + { + std::ostringstream os; + os << *md; + + // Exif tag contents can be an i18n strings, no only simple ascii. + tagValue = QString::fromLocal8Bit(os.str().c_str()); + } + + tagValue.replace('\n', ' '); + + // We apply a filter to get only the Exif tags that we need. + + if (!exifKeysFilter.isEmpty()) + { + if (!invertSelection) + { + if (exifKeysFilter.contains(key.section('.', 1, 1))) + metaDataMap.insert(key, tagValue); + } + else + { + if (!exifKeysFilter.contains(key.section('.', 1, 1))) + metaDataMap.insert(key, tagValue); + } + } + else // else no filter at all. + { + metaDataMap.insert(key, tagValue); + } + } + + return metaDataMap; + } + catch (Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot parse EXIF metadata using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return MetaDataMap(); +} + +QString KExiv2::getExifComment() const +{ + try + { + if (!d->exifMetadata().empty()) + { + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifKey key("Exif.Photo.UserComment"); + Exiv2::ExifData::iterator it = exifData.findKey(key); + + if (it != exifData.end()) + { + QString exifComment = d->convertCommentValue(*it); + + // some cameras fill the UserComment with whitespace + if (!exifComment.isEmpty() && !exifComment.trimmed().isEmpty()) + return exifComment; + } + + Exiv2::ExifKey key2("Exif.Image.ImageDescription"); + Exiv2::ExifData::iterator it2 = exifData.findKey(key2); + + if (it2 != exifData.end()) + { + QString exifComment = d->convertCommentValue(*it2); + + // Some cameras fill in nonsense default values + QStringList blackList; + blackList << "SONY DSC"; // + whitespace + blackList << "OLYMPUS DIGITAL CAMERA"; + blackList << "MINOLTA DIGITAL CAMERA"; + + QString trimmedComment = exifComment.trimmed(); + + // some cameras fill the UserComment with whitespace + if (!exifComment.isEmpty() && !trimmedComment.isEmpty() && !blackList.contains(trimmedComment)) + return exifComment; + } + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot find Exif User Comment using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QString(); +} + +static bool is7BitAscii(const QByteArray& s) +{ + const int size = s.size(); + + for (int i=0; icanEncode(comment)) + { + // We know it's in the ISO-8859-1 8bit range. + // Check if it's in the ASCII 7bit range + if (is7BitAscii(comment.toLatin1())) + { + // write as ASCII + std::string exifComment("charset=\"Ascii\" "); + exifComment += comment.toLatin1().constData(); + d->exifMetadata()["Exif.Photo.UserComment"] = exifComment; + return true; + } + } + // write as Unicode (UCS-2) + std::string exifComment("charset=\"Unicode\" "); + exifComment += comment.toUtf8().constData(); + d->exifMetadata()["Exif.Photo.UserComment"] = exifComment; + } + + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Exif Comment using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QString KExiv2::getExifTagTitle(const char* exifTagName) +{ + try + { + std::string exifkey(exifTagName); + Exiv2::ExifKey ek(exifkey); + + return QString::fromLocal8Bit( ek.tagLabel().c_str() ); + } + catch (Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot get metadata tag title using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QString(); +} + +QString KExiv2::getExifTagDescription(const char* exifTagName) +{ + try + { + std::string exifkey(exifTagName); + Exiv2::ExifKey ek(exifkey); + + return QString::fromLocal8Bit( ek.tagDesc().c_str() ); + } + catch (Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot get metadata tag description using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QString(); +} + +bool KExiv2::removeExifTag(const char* exifTagName, bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + Exiv2::ExifKey exifKey(exifTagName); + Exiv2::ExifData::iterator it = d->exifMetadata().findKey(exifKey); + + if (it != d->exifMetadata().end()) + { + d->exifMetadata().erase(it); + return true; + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot remove Exif tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::getExifTagRational(const char* exifTagName, long int& num, long int& den, int component) const +{ + try + { + Exiv2::ExifKey exifKey(exifTagName); + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifData::iterator it = exifData.findKey(exifKey); + + if (it != exifData.end()) + { + num = (*it).toRational(component).first; + den = (*it).toRational(component).second; + + return true; + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError(QString("Cannot find Exif Rational value from key '%1' " + "into image using Exiv2 ").arg(exifTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::setExifTagLong(const char* exifTagName, long val, bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + d->exifMetadata()[exifTagName] = static_cast(val); + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Exif tag long value into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::setExifTagRational(const char* exifTagName, long int num, long int den, bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + d->exifMetadata()[exifTagName] = Exiv2::Rational(num, den); + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Exif tag rational value into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::setExifTagData(const char* exifTagName, const QByteArray& data, bool setProgramName) const +{ + if (data.isEmpty()) + return false; + + if (!setProgramId(setProgramName)) + return false; + + try + { + Exiv2::DataValue val((Exiv2::byte*)data.data(), data.size()); + d->exifMetadata()[exifTagName] = val; + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Exif tag data into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::setExifTagVariant(const char* exifTagName, const QVariant& val, + bool rationalWantSmallDenominator, bool setProgramName) const +{ + switch (val.type()) + { + case QVariant::Int: + case QVariant::UInt: + case QVariant::Bool: + case QVariant::LongLong: + case QVariant::ULongLong: + return setExifTagLong(exifTagName, val.toInt(), setProgramName); + + case QVariant::Double: + { + long num, den; + + if (rationalWantSmallDenominator) + convertToRationalSmallDenominator(val.toDouble(), &num, &den); + else + convertToRational(val.toDouble(), &num, &den, 4); + + return setExifTagRational(exifTagName, num, den, setProgramName); + } + case QVariant::List: + { + long num = 0, den = 1; + QList list = val.toList(); + + if (list.size() >= 1) + num = list[0].toInt(); + + if (list.size() >= 2) + den = list[1].toInt(); + + return setExifTagRational(exifTagName, num, den, setProgramName); + } + + case QVariant::Date: + case QVariant::DateTime: + { + QDateTime dateTime = val.toDateTime(); + + if(!dateTime.isValid()) + return false; + + if (!setProgramId(setProgramName)) + return false; + + try + { + const std::string &exifdatetime(dateTime.toString(QString("yyyy:MM:dd hh:mm:ss")).toAscii().constData()); + d->exifMetadata()[exifTagName] = exifdatetime; + } + catch( Exiv2::Error &e ) + { + d->printExiv2ExceptionError("Cannot set Date & Time in image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; + } + + case QVariant::String: + case QVariant::Char: + return setExifTagString(exifTagName, val.toString(), setProgramName); + + case QVariant::ByteArray: + return setExifTagData(exifTagName, val.toByteArray(), setProgramName); + default: + break; + } + return false; +} + +QString KExiv2::createExifUserStringFromValue(const char* exifTagName, const QVariant& val, bool escapeCR) +{ + try + { + Exiv2::ExifKey key(exifTagName); + Exiv2::Exifdatum datum(key); + + switch (val.type()) + { + case QVariant::Int: + case QVariant::Bool: + case QVariant::LongLong: + case QVariant::ULongLong: + datum = (int32_t)val.toInt(); + break; + case QVariant::UInt: + datum = (uint32_t)val.toUInt(); + break; + + case QVariant::Double: + { + long num, den; + convertToRationalSmallDenominator(val.toDouble(), &num, &den); + Exiv2::Rational rational; + rational.first = num; + rational.second = den; + datum = rational; + break; + } + case QVariant::List: + { + long num = 0, den = 1; + QList list = val.toList(); + if (list.size() >= 1) + num = list[0].toInt(); + if (list.size() >= 2) + den = list[1].toInt(); + Exiv2::Rational rational; + rational.first = num; + rational.second = den; + datum = rational; + break; + } + + case QVariant::Date: + case QVariant::DateTime: + { + QDateTime dateTime = val.toDateTime(); + if(!dateTime.isValid()) + break; + + const std::string &exifdatetime(dateTime.toString(QString("yyyy:MM:dd hh:mm:ss")).toAscii().constData()); + datum = exifdatetime; + break; + } + + case QVariant::String: + case QVariant::Char: + datum = (std::string)val.toString().toAscii().constData(); + break; + default: + break; + } + + std::ostringstream os; + os << datum; + QString tagValue = QString::fromLocal8Bit(os.str().c_str()); + + if (escapeCR) + tagValue.replace('\n', ' '); + + return tagValue; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Iptc tag string into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QString(); +} + +bool KExiv2::getExifTagLong(const char* exifTagName, long& val) const +{ + return getExifTagLong(exifTagName, val, 0); +} + +bool KExiv2::getExifTagLong(const char* exifTagName, long& val, int component) const +{ + try + { + Exiv2::ExifKey exifKey(exifTagName); + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifData::iterator it = exifData.findKey(exifKey); + + if (it != exifData.end() && it->count() > 0) + { + val = it->toLong(component); + return true; + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError(QString("Cannot find Exif key '%1' into image using Exiv2 ") + .arg(exifTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QByteArray KExiv2::getExifTagData(const char* exifTagName) const +{ + try + { + Exiv2::ExifKey exifKey(exifTagName); + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifData::iterator it = exifData.findKey(exifKey); + + if (it != exifData.end()) + { + char* const s = new char[(*it).size()]; + (*it).copy((Exiv2::byte*)s, Exiv2::bigEndian); + QByteArray data(s, (*it).size()); + delete[] s; + + return data; + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError(QString("Cannot find Exif key '%1' into image using Exiv2 ") + .arg(exifTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QByteArray(); +} + +QVariant KExiv2::getExifTagVariant(const char* exifTagName, bool rationalAsListOfInts, bool stringEscapeCR, int component) const +{ + try + { + Exiv2::ExifKey exifKey(exifTagName); + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifData::iterator it = exifData.findKey(exifKey); + + if (it != exifData.end()) + { + switch (it->typeId()) + { + case Exiv2::unsignedByte: + case Exiv2::unsignedShort: + case Exiv2::unsignedLong: + case Exiv2::signedShort: + case Exiv2::signedLong: + if (it->count() > component) + return QVariant((int)it->toLong(component)); + else + return QVariant(QVariant::Int); + case Exiv2::unsignedRational: + case Exiv2::signedRational: + + if (rationalAsListOfInts) + { + if (it->count() <= component) + return QVariant(QVariant::List); + + QList list; + list << (*it).toRational(component).first; + list << (*it).toRational(component).second; + + return QVariant(list); + } + else + { + if (it->count() <= component) + return QVariant(QVariant::Double); + + // prefer double precision + double num = (*it).toRational(component).first; + double den = (*it).toRational(component).second; + + if (den == 0.0) + return QVariant(QVariant::Double); + + return QVariant(num / den); + } + case Exiv2::date: + case Exiv2::time: + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + return QVariant(dateTime); + } + case Exiv2::asciiString: + case Exiv2::comment: + case Exiv2::string: + { + std::ostringstream os; + os << *it; + QString tagValue = QString::fromLocal8Bit(os.str().c_str()); + + if (stringEscapeCR) + tagValue.replace('\n', ' '); + + return QVariant(tagValue); + } + default: + break; + } + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError(QString("Cannot find Exif key '%1' in the image using Exiv2 ") + .arg(exifTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QVariant(); +} + +QString KExiv2::getExifTagString(const char* exifTagName, bool escapeCR) const +{ + try + { + Exiv2::ExifKey exifKey(exifTagName); + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifData::iterator it = exifData.findKey(exifKey); + + if (it != exifData.end()) + { + // See B.K.O #184156 comment #13 + std::string val = it->print(&exifData); + QString tagValue = QString::fromLocal8Bit(val.c_str()); + + if (escapeCR) + tagValue.replace('\n', ' '); + + return tagValue; + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError(QString("Cannot find Exif key '%1' into image using Exiv2 ") + .arg(exifTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QString(); +} + +bool KExiv2::setExifTagString(const char* exifTagName, const QString& value, bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + d->exifMetadata()[exifTagName] = std::string(value.toAscii().constData()); + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Exif tag string into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QImage KExiv2::getExifThumbnail(bool fixOrientation) const +{ + QImage thumbnail; + + if (d->exifMetadata().empty()) + return thumbnail; + + try + { + Exiv2::ExifThumbC thumb(d->exifMetadata()); + Exiv2::DataBuf const c1 = thumb.copy(); + thumbnail.loadFromData(c1.pData_, c1.size_); + + if (!thumbnail.isNull()) + { + if (fixOrientation) + { + Exiv2::ExifKey key1("Exif.Thumbnail.Orientation"); + Exiv2::ExifKey key2("Exif.Image.Orientation"); + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifData::iterator it = exifData.findKey(key1); + + if (it == exifData.end()) + it = exifData.findKey(key2); + + if (it != exifData.end() && it->count()) + { + long orientation = it->toLong(); + kDebug() << "Exif Thumbnail Orientation: " << (int)orientation; + rotateExifQImage(thumbnail, (ImageOrientation)orientation); + } + + return thumbnail; + } + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot get Exif Thumbnail using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return thumbnail; +} + +bool KExiv2::rotateExifQImage(QImage& image, ImageOrientation orientation) const +{ + QMatrix matrix = RotationMatrix::toMatrix(orientation); + + if ((orientation != ORIENTATION_NORMAL) || (orientation != ORIENTATION_UNSPECIFIED)) + { + image = image.transformed(matrix); + return true; + } + + return false; +} + +bool KExiv2::setExifThumbnail(const QImage& thumbImage, bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + if (thumbImage.isNull()) + { + return removeExifThumbnail(); + } + + try + { + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + thumbImage.save(&buffer, "JPEG"); + Exiv2::ExifThumb thumb(d->exifMetadata()); + thumb.setJpegThumbnail((Exiv2::byte *)data.data(), data.size()); + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Exif Thumbnail using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::setTiffThumbnail(const QImage& thumbImage, bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + removeExifThumbnail(); + + try + { + // Make sure IFD0 is explicitly marked as a main image + Exiv2::ExifData::const_iterator pos = d->exifMetadata().findKey(Exiv2::ExifKey("Exif.Image.NewSubfileType")); + + if (pos == d->exifMetadata().end() || pos->count() != 1 || pos->toLong() != 0) + { + throw Exiv2::Error(1, "Exif.Image.NewSubfileType missing or not set as main image"); + } + + // Remove sub-IFD tags + std::string subImage1("SubImage1"); + + for (Exiv2::ExifData::iterator md = d->exifMetadata().begin(); md != d->exifMetadata().end();) + { + if (md->groupName() == subImage1) + md = d->exifMetadata().erase(md); + else + ++md; + } + + if (!thumbImage.isNull()) + { + // Set thumbnail tags + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + thumbImage.save(&buffer, "JPEG"); + + Exiv2::DataBuf buf((Exiv2::byte *)data.data(), data.size()); + Exiv2::ULongValue val; + val.read("0"); + val.setDataArea(buf.pData_, buf.size_); + d->exifMetadata()["Exif.SubImage1.JPEGInterchangeFormat"] = val; + d->exifMetadata()["Exif.SubImage1.JPEGInterchangeFormatLength"] = uint32_t(buf.size_); + d->exifMetadata()["Exif.SubImage1.Compression"] = uint16_t(6); // JPEG (old-style) + d->exifMetadata()["Exif.SubImage1.NewSubfileType"] = uint32_t(1); // Thumbnail image + return true; + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set TIFF Thumbnail using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::removeExifThumbnail() const +{ + try + { + // Remove all IFD0 subimages. + Exiv2::ExifThumb thumb(d->exifMetadata()); + thumb.erase(); + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot remove Exif Thumbnail using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +KExiv2::TagsMap KExiv2::getStdExifTagsList() const +{ + try + { + QList tags; + TagsMap tagsMap; + + const Exiv2::GroupInfo* gi = Exiv2::ExifTags::groupList(); + + while (gi->tagList_ != 0) + { + if (QString(gi->ifdName_) != QString("Makernote")) + { + Exiv2::TagListFct tl = gi->tagList_; + const Exiv2::TagInfo* ti = tl(); + + while (ti->tag_ != 0xFFFF) + { + tags << ti; + ++ti; + } + } + ++gi; + } + + for (QList::iterator it = tags.begin(); it != tags.end(); ++it) + { + do + { + const Exiv2::TagInfo* const ti = *it; + QString key = QLatin1String(Exiv2::ExifKey(*ti).key().c_str()); + QStringList values; + values << ti->name_ << ti->title_ << ti->desc_; + tagsMap.insert(key, values); + ++(*it); + } + while((*it)->tag_ != 0xffff); + } + return tagsMap; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot get Exif Tags list using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return TagsMap(); +} + +KExiv2::TagsMap KExiv2::getMakernoteTagsList() const +{ + try + { + QList tags; + TagsMap tagsMap; + + const Exiv2::GroupInfo* gi = Exiv2::ExifTags::groupList(); + + while (gi->tagList_ != 0) + { + if (QString(gi->ifdName_) == QString("Makernote")) + { + Exiv2::TagListFct tl = gi->tagList_; + const Exiv2::TagInfo* ti = tl(); + + while (ti->tag_ != 0xFFFF) + { + tags << ti; + ++ti; + } + } + ++gi; + } + + for (QList::iterator it = tags.begin(); it != tags.end(); ++it) + { + do + { + const Exiv2::TagInfo* const ti = *it; + QString key = QLatin1String(Exiv2::ExifKey(*ti).key().c_str()); + QStringList values; + values << ti->name_ << ti->title_ << ti->desc_; + tagsMap.insert(key, values); + ++(*it); + } + while((*it)->tag_ != 0xffff); + } + + return tagsMap; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot get Makernote Tags list using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return TagsMap(); +} + +} // NameSpace KExiv2Iface diff --git a/libkexiv2/libkexiv2/kexiv2gps.cpp b/libkexiv2/libkexiv2/kexiv2gps.cpp new file mode 100644 index 00000000..8911e71e --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2gps.cpp @@ -0,0 +1,989 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-09-15 + * @brief GPS manipulation methods + * + * @author Copyright (C) 2006-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * @author Copyright (C) 2010-2012 by Michael G. Hansen + * mike at mghansen dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "kexiv2.h" +#include "kexiv2_p.h" + +// C++ includes + +#include +#include + +#include + +namespace KExiv2Iface +{ + +bool KExiv2::getGPSInfo(double& altitude, double& latitude, double& longitude) const +{ + // Some GPS device do not set Altitude. So a valid GPS position can be with a zero value. + // No need to check return value. + getGPSAltitude(&altitude); + + if (!getGPSLatitudeNumber(&latitude)) + return false; + + if (!getGPSLongitudeNumber(&longitude)) + return false; + + return true; +} + +bool KExiv2::getGPSLatitudeNumber(double* const latitude) const +{ + try + { + *latitude=0.0; + + // Try XMP first. Reason: XMP in sidecar may be more up-to-date than EXIF in original image. + if ( convertFromGPSCoordinateString(getXmpTagString("Xmp.exif.GPSLatitude"), latitude) ) + return true; + + // Now try to get the reference from Exif. + const QByteArray latRef = getExifTagData("Exif.GPSInfo.GPSLatitudeRef"); + + if (!latRef.isEmpty()) + { + Exiv2::ExifKey exifKey("Exif.GPSInfo.GPSLatitude"); + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifData::iterator it = exifData.findKey(exifKey); + + if (it != exifData.end() && (*it).count() == 3) + { + // Latitude decoding from Exif. + double num, den, min, sec; + + num = (double)((*it).toRational(0).first); + den = (double)((*it).toRational(0).second); + + if (den == 0) + return false; + + *latitude = num/den; + + num = (double)((*it).toRational(1).first); + den = (double)((*it).toRational(1).second); + + if (den == 0) + return false; + + min = num/den; + + if (min != -1.0) + *latitude = *latitude + min/60.0; + + num = (double)((*it).toRational(2).first); + den = (double)((*it).toRational(2).second); + + if (den == 0) + { + // be relaxed and accept 0/0 seconds. See #246077. + if (num == 0) + den = 1; + else + return false; + } + + sec = num/den; + + if (sec != -1.0) + *latitude = *latitude + sec/3600.0; + } + else + { + return false; + } + + if (latRef[0] == 'S') + *latitude *= -1.0; + + return true; + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot get GPS tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::getGPSLongitudeNumber(double* const longitude) const +{ + try + { + *longitude=0.0; + + // Try XMP first. Reason: XMP in sidecar may be more up-to-date than EXIF in original image. + if ( convertFromGPSCoordinateString(getXmpTagString("Xmp.exif.GPSLongitude"), longitude) ) + return true; + + // Now try to get the reference from Exif. + const QByteArray lngRef = getExifTagData("Exif.GPSInfo.GPSLongitudeRef"); + + if (!lngRef.isEmpty()) + { + // Longitude decoding from Exif. + + Exiv2::ExifKey exifKey2("Exif.GPSInfo.GPSLongitude"); + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifData::iterator it = exifData.findKey(exifKey2); + + if (it != exifData.end() && (*it).count() == 3) + { + /// @todo Decoding of latitude and longitude works in the same way, + /// code here can be put in a separate function + double num, den; + + num = (double)((*it).toRational(0).first); + den = (double)((*it).toRational(0).second); + + if (den == 0) + { + return false; + } + + *longitude = num/den; + + num = (double)((*it).toRational(1).first); + den = (double)((*it).toRational(1).second); + + if (den == 0) + { + return false; + } + + const double min = num/den; + + if (min != -1.0) + { + *longitude = *longitude + min/60.0; + } + + num = (double)((*it).toRational(2).first); + den = (double)((*it).toRational(2).second); + + if (den == 0) + { + // be relaxed and accept 0/0 seconds. See #246077. + if (num == 0) + den = 1; + else + return false; + } + + const double sec = num/den; + + if (sec != -1.0) + { + *longitude = *longitude + sec/3600.0; + } + } + else + { + return false; + } + + if (lngRef[0] == 'W') + { + *longitude *= -1.0; + } + + return true; + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot get GPS tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::getGPSAltitude(double* const altitude) const +{ + try + { + double num, den; + *altitude=0.0; + + // Try XMP first. Reason: XMP in sidecar may be more up-to-date than EXIF in original image. + const QString altRefXmp = getXmpTagString("Xmp.exif.GPSAltitudeRef"); + + if (!altRefXmp.isEmpty()) + { + const QString altXmp = getXmpTagString("Xmp.exif.GPSAltitude"); + + if (!altXmp.isEmpty()) + { + num = altXmp.section('/', 0, 0).toDouble(); + den = altXmp.section('/', 1, 1).toDouble(); + + if (den == 0) + return false; + + *altitude = num/den; + + if (altRefXmp == QString("1")) + *altitude *= -1.0; + + return true; + } + } + + // Get the reference from Exif (above/below sea level) + const QByteArray altRef = getExifTagData("Exif.GPSInfo.GPSAltitudeRef"); + + if (!altRef.isEmpty()) + { + // Altitude decoding from Exif. + + Exiv2::ExifKey exifKey3("Exif.GPSInfo.GPSAltitude"); + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifData::iterator it = exifData.findKey(exifKey3); + if (it != exifData.end() && (*it).count()) + { + num = (double)((*it).toRational(0).first); + den = (double)((*it).toRational(0).second); + + if (den == 0) + return false; + + *altitude = num/den; + } + else + { + return false; + } + + if (altRef[0] == '1') + *altitude *= -1.0; + + return true; + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot get GPS tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QString KExiv2::getGPSLatitudeString() const +{ + double latitude; + + if (!getGPSLatitudeNumber(&latitude)) + return QString(); + + return convertToGPSCoordinateString(true, latitude); +} + +QString KExiv2::getGPSLongitudeString() const +{ + double longitude; + + if (!getGPSLongitudeNumber(&longitude)) + return QString(); + + return convertToGPSCoordinateString(false, longitude); +} + +bool KExiv2::initializeGPSInfo(const bool setProgramName) +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + // TODO: what happens if these already exist? + + // Do all the easy constant ones first. + // GPSVersionID tag: standard says is should be four bytes: 02 00 00 00 + // (and, must be present). + Exiv2::Value::AutoPtr value = Exiv2::Value::create(Exiv2::unsignedByte); + value->read("2 0 0 0"); + d->exifMetadata().add(Exiv2::ExifKey("Exif.GPSInfo.GPSVersionID"), value.get()); + + // Datum: the datum of the measured data. If not given, we insert WGS-84. + d->exifMetadata()["Exif.GPSInfo.GPSMapDatum"] = "WGS-84"; + +#ifdef _XMP_SUPPORT_ + setXmpTagString("Xmp.exif.GPSVersionID", QString("2.0.0.0"), false); + setXmpTagString("Xmp.exif.GPSMapDatum", QString("WGS-84"), false); +#endif // _XMP_SUPPORT_ + + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot initialize GPS data using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::setGPSInfo(const double altitude, const double latitude, const double longitude, const bool setProgramName) +{ + return setGPSInfo(&altitude, latitude, longitude, setProgramName); +} + +bool KExiv2::setGPSInfo(const double* const altitude, const double latitude, const double longitude, const bool setProgramName) +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + // In first, we need to clean up all existing GPS info. + removeGPSInfo(); + + // now re-initialize the GPS info: + if (!initializeGPSInfo(setProgramName)) + return false; + + char scratchBuf[100]; + long int nom, denom; + long int deg, min; + + // Now start adding data. + + // ALTITUDE. + if (altitude) + { + // Altitude reference: byte "00" meaning "above sea level", "01" mening "behing sea level". + Exiv2::Value::AutoPtr value = Exiv2::Value::create(Exiv2::unsignedByte); + + if ((*altitude) >= 0) value->read("0"); + else value->read("1"); + + d->exifMetadata().add(Exiv2::ExifKey("Exif.GPSInfo.GPSAltitudeRef"), value.get()); + + // And the actual altitude, as absolute value.. + convertToRational(fabs(*altitude), &nom, &denom, 4); + snprintf(scratchBuf, 100, "%ld/%ld", nom, denom); + d->exifMetadata()["Exif.GPSInfo.GPSAltitude"] = scratchBuf; + +#ifdef _XMP_SUPPORT_ + setXmpTagString("Xmp.exif.GPSAltitudeRef", ((*altitude) >= 0) ? QString("0") : QString("1"), false); + setXmpTagString("Xmp.exif.GPSAltitude", QString(scratchBuf), false); +#endif // _XMP_SUPPORT_ + } + + // LATITUDE + // Latitude reference: + // latitude < 0 : "S" + // latitude > 0 : "N" + // + d->exifMetadata()["Exif.GPSInfo.GPSLatitudeRef"] = (latitude < 0 ) ? "S" : "N"; + + // Now the actual latitude itself. + // This is done as three rationals. + // I choose to do it as: + // dd/1 - degrees. + // mmmm/100 - minutes + // 0/1 - seconds + // Exif standard says you can do it with minutes + // as mm/1 and then seconds as ss/1, but its + // (slightly) more accurate to do it as + // mmmm/100 than to split it. + // We also absolute the value (with fabs()) + // as the sign is encoded in LatRef. + // Further note: original code did not translate between + // dd.dddddd to dd mm.mm - that's why we now multiply + // by 6000 - x60 to get minutes, x1000000 to get to mmmm/1000000. + deg = (int)floor(fabs(latitude)); // Slice off after decimal. + min = (int)floor((fabs(latitude) - floor(fabs(latitude))) * 60000000); + snprintf(scratchBuf, 100, "%ld/1 %ld/1000000 0/1", deg, min); + d->exifMetadata()["Exif.GPSInfo.GPSLatitude"] = scratchBuf; + +#ifdef _XMP_SUPPORT_ + /** @todo The XMP spec does not mention Xmp.exif.GPSLatitudeRef, + * because the reference is included in Xmp.exif.GPSLatitude. + * Is there a historic reason for writing it anyway? + */ + setXmpTagString("Xmp.exif.GPSLatitudeRef", (latitude < 0) ? QString("S") : QString("N"), false); + setXmpTagString("Xmp.exif.GPSLatitude", convertToGPSCoordinateString(true, latitude), false); +#endif // _XMP_SUPPORT_ + + // LONGITUDE + // Longitude reference: + // longitude < 0 : "W" + // longitude > 0 : "E" + d->exifMetadata()["Exif.GPSInfo.GPSLongitudeRef"] = (longitude < 0 ) ? "W" : "E"; + + // Now the actual longitude itself. + // This is done as three rationals. + // I choose to do it as: + // dd/1 - degrees. + // mmmm/100 - minutes + // 0/1 - seconds + // Exif standard says you can do it with minutes + // as mm/1 and then seconds as ss/1, but its + // (slightly) more accurate to do it as + // mmmm/100 than to split it. + // We also absolute the value (with fabs()) + // as the sign is encoded in LongRef. + // Further note: original code did not translate between + // dd.dddddd to dd mm.mm - that's why we now multiply + // by 6000 - x60 to get minutes, x1000000 to get to mmmm/1000000. + deg = (int)floor(fabs(longitude)); // Slice off after decimal. + min = (int)floor((fabs(longitude) - floor(fabs(longitude))) * 60000000); + snprintf(scratchBuf, 100, "%ld/1 %ld/1000000 0/1", deg, min); + d->exifMetadata()["Exif.GPSInfo.GPSLongitude"] = scratchBuf; + +#ifdef _XMP_SUPPORT_ + /** @todo The XMP spec does not mention Xmp.exif.GPSLongitudeRef, + * because the reference is included in Xmp.exif.GPSLongitude. + * Is there a historic reason for writing it anyway? + */ + setXmpTagString("Xmp.exif.GPSLongitudeRef", (longitude < 0) ? QString("W") : QString("E"), false); + setXmpTagString("Xmp.exif.GPSLongitude", convertToGPSCoordinateString(false, longitude), false); +#endif // _XMP_SUPPORT_ + + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Exif GPS tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::setGPSInfo(const double altitude, const QString& latitude, const QString& longitude, const bool setProgramName) +{ + double longitudeValue, latitudeValue; + + if (!convertFromGPSCoordinateString(latitude, &latitudeValue)) + return false; + + if (!convertFromGPSCoordinateString(longitude, &longitudeValue)) + return false; + + return setGPSInfo(&altitude, latitudeValue, longitudeValue, setProgramName); +} + +bool KExiv2::removeGPSInfo(const bool setProgramName) +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + QStringList gpsTagsKeys; + + for (Exiv2::ExifData::iterator it = d->exifMetadata().begin(); + it != d->exifMetadata().end(); ++it) + { + QString key = QString::fromLocal8Bit(it->key().c_str()); + + if (key.section('.', 1, 1) == QString("GPSInfo")) + gpsTagsKeys.append(key); + } + + for(QStringList::const_iterator it2 = gpsTagsKeys.constBegin(); it2 != gpsTagsKeys.constEnd(); ++it2) + { + Exiv2::ExifKey gpsKey((*it2).toAscii().constData()); + Exiv2::ExifData::iterator it3 = d->exifMetadata().findKey(gpsKey); + + if (it3 != d->exifMetadata().end()) + d->exifMetadata().erase(it3); + } + +#ifdef _XMP_SUPPORT_ + /** @todo The XMP spec does not mention Xmp.exif.GPSLongitudeRef, + * and Xmp.exif.GPSLatitudeRef. But because we write them in setGPSInfo(), + * we should also remove them here. + */ + removeXmpTag("Xmp.exif.GPSLatitudeRef", false); + removeXmpTag("Xmp.exif.GPSLongitudeRef", false); + removeXmpTag("Xmp.exif.GPSVersionID", false); + removeXmpTag("Xmp.exif.GPSLatitude", false); + removeXmpTag("Xmp.exif.GPSLongitude", false); + removeXmpTag("Xmp.exif.GPSAltitudeRef", false); + removeXmpTag("Xmp.exif.GPSAltitude", false); + removeXmpTag("Xmp.exif.GPSTimeStamp", false); + removeXmpTag("Xmp.exif.GPSSatellites", false); + removeXmpTag("Xmp.exif.GPSStatus", false); + removeXmpTag("Xmp.exif.GPSMeasureMode", false); + removeXmpTag("Xmp.exif.GPSDOP", false); + removeXmpTag("Xmp.exif.GPSSpeedRef", false); + removeXmpTag("Xmp.exif.GPSSpeed", false); + removeXmpTag("Xmp.exif.GPSTrackRef", false); + removeXmpTag("Xmp.exif.GPSTrack", false); + removeXmpTag("Xmp.exif.GPSImgDirectionRef", false); + removeXmpTag("Xmp.exif.GPSImgDirection", false); + removeXmpTag("Xmp.exif.GPSMapDatum", false); + removeXmpTag("Xmp.exif.GPSDestLatitude", false); + removeXmpTag("Xmp.exif.GPSDestLongitude", false); + removeXmpTag("Xmp.exif.GPSDestBearingRef", false); + removeXmpTag("Xmp.exif.GPSDestBearing", false); + removeXmpTag("Xmp.exif.GPSDestDistanceRef", false); + removeXmpTag("Xmp.exif.GPSDestDistance", false); + removeXmpTag("Xmp.exif.GPSProcessingMethod", false); + removeXmpTag("Xmp.exif.GPSAreaInformation", false); + removeXmpTag("Xmp.exif.GPSDifferential", false); +#endif // _XMP_SUPPORT_ + + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot remove Exif GPS tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +void KExiv2::convertToRational(const double number, long int* const numerator, + long int* const denominator, const int rounding) +{ + // This function converts the given decimal number + // to a rational (fractional) number. + // + // Examples in comments use Number as 25.12345, Rounding as 4. + + // Split up the number. + double whole = trunc(number); + double fractional = number - whole; + + // Calculate the "number" used for rounding. + // This is 10^Digits - ie, 4 places gives us 10000. + double rounder = pow(10.0, rounding); + + // Round the fractional part, and leave the number + // as greater than 1. + // To do this we: (for example) + // 0.12345 * 10000 = 1234.5 + // floor(1234.5) = 1234 - now bigger than 1 - ready... + fractional = round(fractional * rounder); + + // Convert the whole thing to a fraction. + // Fraction is: + // (25 * 10000) + 1234 251234 + // ------------------- = ------ = 25.1234 + // 10000 10000 + double numTemp = (whole * rounder) + fractional; + double denTemp = rounder; + + // Now we should reduce until we can reduce no more. + + // Try simple reduction... + // if Num + // ----- = integer out then.... + // Den + if (trunc(numTemp / denTemp) == (numTemp / denTemp)) + { + // Divide both by Denominator. + numTemp /= denTemp; + denTemp /= denTemp; + } + + // And, if that fails, brute force it. + while (1) + { + // Jump out if we can't integer divide one. + if ((numTemp / 2) != trunc(numTemp / 2)) break; + if ((denTemp / 2) != trunc(denTemp / 2)) break; + // Otherwise, divide away. + numTemp /= 2; + denTemp /= 2; + } + + // Copy out the numbers. + *numerator = (int)numTemp; + *denominator = (int)denTemp; +} + +void KExiv2::convertToRationalSmallDenominator(const double number, long int* const numerator, long int* const denominator) +{ + // This function converts the given decimal number + // to a rational (fractional) number. + // + // This method, in contrast to the method above, will retrieve the smallest possible + // denominator. It is tested to retrieve the correct value for 1/x, with 0 < x <= 1000000. + // Note: This requires double precision, storing in float breaks some numbers (49, 59, 86,...) + + // Split up the number. + double whole = trunc(number); + double fractional = number - whole; + + /* + * Find best rational approximation to a double + * by C.B. Falconer, 2006-09-07. Released to public domain. + * + * Newsgroups: comp.lang.c, comp.programming + * From: CBFalconer + * Date: Thu, 07 Sep 2006 17:35:30 -0400 + * Subject: Rational approximations + */ + int lastnum = 500; // this is _not_ the largest possible denominator + long int num, approx, bestnum=0, bestdenom=1; + double value, error, leasterr, criterion; + + value = fractional; + + if (value == 0.0) + { + *numerator = (long int)whole; + *denominator = 1; + return; + } + + criterion = 2 * value * DBL_EPSILON; + + for (leasterr = value, num = 1; num < lastnum; ++num) + { + approx = (int)(num / value + 0.5); + error = fabs((double)num / approx - value); + + if (error < leasterr) + { + bestnum = num; + bestdenom = approx; + leasterr = error; + + if (leasterr <= criterion) break; + } + } + + // add whole number part + if (bestdenom * whole > (double)INT_MAX) + { + // In some cases, we would generate an integer overflow. + // Fall back to Gilles's code which is better suited for such numbers. + convertToRational(number, numerator, denominator, 5); + } + else + { + bestnum += bestdenom * (long int)whole; + *numerator = bestnum; + *denominator = bestdenom; + } +} + +QString KExiv2::convertToGPSCoordinateString(const long int numeratorDegrees, const long int denominatorDegrees, + const long int numeratorMinutes, const long int denominatorMinutes, + const long int numeratorSeconds, long int denominatorSeconds, + const char directionReference) +{ + /** + * Precision: + * A second at sea level measures 30m for our purposes, a minute 1800m. + * (for more details, see http://en.wikipedia.org/wiki/Geographic_coordinate_system) + * This means with a decimal precision of 8 for minutes we get +/-0,018mm. + * (if I calculated correctly) + */ + + QString coordinate; + + // be relaxed with seconds of 0/0 + if (denominatorSeconds == 0 && numeratorSeconds == 0) + denominatorSeconds = 1; + + if (denominatorDegrees == 1 && + denominatorMinutes == 1 && + denominatorSeconds == 1) + { + // use form DDD,MM,SSk + coordinate = "%1,%2,%3%4"; + coordinate = coordinate.arg(numeratorDegrees).arg(numeratorMinutes).arg(numeratorSeconds).arg(directionReference); + } + else if (denominatorDegrees == 1 && + denominatorMinutes == 100 && + denominatorSeconds == 1) + { + // use form DDD,MM.mmk + coordinate = "%1,%2%3"; + double minutes = (double)numeratorMinutes / (double)denominatorMinutes; + minutes += (double)numeratorSeconds / 60.0; + QString minutesString = QString::number(minutes, 'f', 8); + + while (minutesString.endsWith('0') && !minutesString.endsWith(".0")) + { + minutesString.chop(1); + } + + coordinate = coordinate.arg(numeratorDegrees).arg(minutesString).arg(directionReference); + } + else if (denominatorDegrees == 0 || + denominatorMinutes == 0 || + denominatorSeconds == 0) + { + // Invalid. 1/0 is everything but 0. As is 0/0. + return QString(); + } + else + { + // use form DDD,MM.mmk + coordinate = "%1,%2%3"; + double degrees = (double)numeratorDegrees / (double)denominatorDegrees; + double wholeDegrees = trunc(degrees); + double minutes = (double)numeratorMinutes / (double)denominatorMinutes; + minutes += (degrees - wholeDegrees) * 60.0; + minutes += ((double)numeratorSeconds / (double)denominatorSeconds) / 60.0; + QString minutesString = QString::number(minutes, 'f', 8); + + while (minutesString.endsWith('0') && !minutesString.endsWith(".0")) + { + minutesString.chop(1); + } + + coordinate = coordinate.arg((int)wholeDegrees).arg(minutesString).arg(directionReference); + } + + return coordinate; +} + +QString KExiv2::convertToGPSCoordinateString(const bool isLatitude, double coordinate) +{ + if (coordinate < -360.0 || coordinate > 360.0) + return QString(); + + QString coordinateString; + + char directionReference; + + if (isLatitude) + { + if (coordinate < 0) + directionReference = 'S'; + else + directionReference = 'N'; + } + else + { + if (coordinate < 0) + directionReference = 'W'; + else + directionReference = 'E'; + } + + // remove sign + coordinate = fabs(coordinate); + + int degrees = (int)floor(coordinate); + // get fractional part + coordinate = coordinate - (double)(degrees); + // To minutes + double minutes = coordinate * 60.0; + + // use form DDD,MM.mmk + coordinateString = "%1,%2%3"; + coordinateString = coordinateString.arg(degrees); + coordinateString = coordinateString.arg(minutes, 0, 'f', 8).arg(directionReference); + + return coordinateString; +} + +bool KExiv2::convertFromGPSCoordinateString(const QString& gpsString, + long int* const numeratorDegrees, long int* const denominatorDegrees, + long int* const numeratorMinutes, long int* const denominatorMinutes, + long int* const numeratorSeconds, long int* const denominatorSeconds, + char* const directionReference) +{ + if (gpsString.isEmpty()) + return false; + + *directionReference = gpsString.at(gpsString.length() - 1).toUpper().toLatin1(); + QString coordinate = gpsString.left(gpsString.length() - 1); + QStringList parts = coordinate.split(','); + + if (parts.size() == 2) + { + // form DDD,MM.mmk + *denominatorDegrees = 1; + *denominatorMinutes = 1000000; + *denominatorSeconds = 1; + + *numeratorDegrees = parts[0].toLong(); + + double minutes = parts[1].toDouble(); + minutes *= 1000000; + + *numeratorMinutes = (long)round(minutes); + *numeratorSeconds = 0; + + return true; + } + else if (parts.size() == 3) + { + // use form DDD,MM,SSk + *denominatorDegrees = 1; + *denominatorMinutes = 1; + *denominatorSeconds = 1; + + *numeratorDegrees = parts[0].toLong(); + *numeratorMinutes = parts[1].toLong(); + *numeratorSeconds = parts[2].toLong(); + + return true; + } + else + { + return false; + } +} + +bool KExiv2::convertFromGPSCoordinateString(const QString& gpsString, double* const degrees) +{ + if (gpsString.isEmpty()) + return false; + + char directionReference = gpsString.at(gpsString.length() - 1).toUpper().toLatin1(); + QString coordinate = gpsString.left(gpsString.length() - 1); + QStringList parts = coordinate.split(','); + + if (parts.size() == 2) + { + // form DDD,MM.mmk + *degrees = parts[0].toLong(); + *degrees += parts[1].toDouble() / 60.0; + + if (directionReference == 'W' || directionReference == 'S') + *degrees *= -1.0; + + return true; + } + else if (parts.size() == 3) + { + // use form DDD,MM,SSk + + *degrees = parts[0].toLong(); + *degrees += parts[1].toLong() / 60.0; + *degrees += parts[2].toLong() / 3600.0; + + if (directionReference == 'W' || directionReference == 'S') + *degrees *= -1.0; + + return true; + } + else + { + return false; + } +} + +bool KExiv2::convertToUserPresentableNumbers(const QString& gpsString, + int* const degrees, int* const minutes, + double* const seconds, char* const directionReference) +{ + if (gpsString.isEmpty()) + return false; + + *directionReference = gpsString.at(gpsString.length() - 1).toUpper().toLatin1(); + QString coordinate = gpsString.left(gpsString.length() - 1); + QStringList parts = coordinate.split(','); + + if (parts.size() == 2) + { + // form DDD,MM.mmk + *degrees = parts[0].toInt(); + double fractionalMinutes = parts[1].toDouble(); + *minutes = (int)trunc(fractionalMinutes); + *seconds = (fractionalMinutes - (double)(*minutes)) * 60.0; + + return true; + } + else if (parts.size() == 3) + { + // use form DDD,MM,SSk + *degrees = parts[0].toInt(); + *minutes = parts[1].toInt(); + *seconds = (double)parts[2].toInt(); + + return true; + } + else + { + return false; + } +} + +void KExiv2::convertToUserPresentableNumbers(const bool isLatitude, double coordinate, + int* const degrees, int* const minutes, + double* const seconds, char* const directionReference) +{ + if (isLatitude) + { + if (coordinate < 0) + *directionReference = 'S'; + else + *directionReference = 'N'; + } + else + { + if (coordinate < 0) + *directionReference = 'W'; + else + *directionReference = 'E'; + } + + // remove sign + coordinate = fabs(coordinate); + *degrees = (int)floor(coordinate); + // get fractional part + coordinate = coordinate - (double)(*degrees); + // To minutes + coordinate *= 60.0; + *minutes = (int)floor(coordinate); + // get fractional part + coordinate = coordinate - (double)(*minutes); + // To seconds + coordinate *= 60.0; + *seconds = coordinate; +} + +} // NameSpace KExiv2Iface diff --git a/libkexiv2/libkexiv2/kexiv2image.cpp b/libkexiv2/libkexiv2/kexiv2image.cpp new file mode 100644 index 00000000..4f4d204f --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2image.cpp @@ -0,0 +1,967 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-09-15 + * @brief Common metadata image information manipulation methods + * + * @author Copyright (C) 2006-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "kexiv2.h" +#include "kexiv2_p.h" + +// Local includes + +#include "rotationmatrix.h" + +namespace KExiv2Iface +{ + +bool KExiv2::setImageProgramId(const QString& program, const QString& version) const +{ + try + { + QString software(program); + software.append("-"); + software.append(version); + + // Set program info into Exif.Image.ProcessingSoftware tag (only available with Exiv2 >= 0.14.0). + + d->exifMetadata()["Exif.Image.ProcessingSoftware"] = std::string(software.toAscii().constData()); + + // See B.K.O #142564: Check if Exif.Image.Software already exist. If yes, do not touch this tag. + + if (!d->exifMetadata().empty()) + { + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifKey key("Exif.Image.Software"); + Exiv2::ExifData::iterator it = exifData.findKey(key); + if (it == exifData.end()) + d->exifMetadata()["Exif.Image.Software"] = std::string(software.toAscii().constData()); + } + + // set program info into XMP tags. + +#ifdef _XMP_SUPPORT_ + + if (!d->xmpMetadata().empty()) + { + // Only create Xmp.xmp.CreatorTool if it do not exist. + Exiv2::XmpData xmpData(d->xmpMetadata()); + Exiv2::XmpKey key("Xmp.xmp.CreatorTool"); + Exiv2::XmpData::iterator it = xmpData.findKey(key); + if (it == xmpData.end()) + setXmpTagString("Xmp.xmp.CreatorTool", software, false); + } + + setXmpTagString("Xmp.tiff.Software", software, false); + +#endif // _XMP_SUPPORT_ + + // Set program info into IPTC tags. + + d->iptcMetadata()["Iptc.Application2.Program"] = std::string(program.toAscii().constData()); + d->iptcMetadata()["Iptc.Application2.ProgramVersion"] = std::string(version.toAscii().constData()); + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Program identity into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QSize KExiv2::getImageDimensions() const +{ + try + { + long width=-1, height=-1; + + // Try to get Exif.Photo tags + + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifKey key("Exif.Photo.PixelXDimension"); + Exiv2::ExifData::iterator it = exifData.findKey(key); + if (it != exifData.end() && it->count()) + width = it->toLong(); + + Exiv2::ExifKey key2("Exif.Photo.PixelYDimension"); + Exiv2::ExifData::iterator it2 = exifData.findKey(key2); + if (it2 != exifData.end() && it2->count()) + height = it2->toLong(); + + if (width != -1 && height != -1) + return QSize(width, height); + + // Try to get Exif.Image tags + + width = -1; + height = -1; + + Exiv2::ExifKey key3("Exif.Image.ImageWidth"); + Exiv2::ExifData::iterator it3 = exifData.findKey(key3); + if (it3 != exifData.end() && it3->count()) + width = it3->toLong(); + + Exiv2::ExifKey key4("Exif.Image.ImageLength"); + Exiv2::ExifData::iterator it4 = exifData.findKey(key4); + if (it4 != exifData.end() && it4->count()) + height = it4->toLong(); + + if (width != -1 && height != -1) + return QSize(width, height); + +#ifdef _XMP_SUPPORT_ + + // Try to get Xmp.tiff tags + + width = -1; + height = -1; + bool wOk = false; + bool hOk = false; + + QString str = getXmpTagString("Xmp.tiff.ImageWidth"); + if (!str.isEmpty()) + width = str.toInt(&wOk); + + str = getXmpTagString("Xmp.tiff.ImageLength"); + if (!str.isEmpty()) + height = str.toInt(&hOk); + + if (wOk && hOk) + return QSize(width, height); + + // Try to get Xmp.exif tags + + width = -1; + height = -1; + wOk = false; + hOk = false; + + str = getXmpTagString("Xmp.exif.PixelXDimension"); + if (!str.isEmpty()) + width = str.toInt(&wOk); + + str = getXmpTagString("Xmp.exif.PixelYDimension"); + if (!str.isEmpty()) + height = str.toInt(&hOk); + + if (wOk && hOk) + return QSize(width, height); + +#endif // _XMP_SUPPORT_ + + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot parse image dimensions tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QSize(); +} + +bool KExiv2::setImageDimensions(const QSize& size, bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + // Set Exif values. + + // NOTE: see B.K.O #144604: need to cast to record an unsigned integer value. + d->exifMetadata()["Exif.Image.ImageWidth"] = static_cast(size.width()); + d->exifMetadata()["Exif.Image.ImageLength"] = static_cast(size.height()); + d->exifMetadata()["Exif.Photo.PixelXDimension"] = static_cast(size.width()); + d->exifMetadata()["Exif.Photo.PixelYDimension"] = static_cast(size.height()); + + // Set Xmp values. + +#ifdef _XMP_SUPPORT_ + + setXmpTagString("Xmp.tiff.ImageWidth", QString::number(size.width()), false); + setXmpTagString("Xmp.tiff.ImageLength", QString::number(size.height()), false); + setXmpTagString("Xmp.exif.PixelXDimension", QString::number(size.width()), false); + setXmpTagString("Xmp.exif.PixelYDimension", QString::number(size.height()), false); + +#endif // _XMP_SUPPORT_ + + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set image dimensions using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +KExiv2::ImageOrientation KExiv2::getImageOrientation() const +{ + try + { + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifData::iterator it; + long orientation; + ImageOrientation imageOrient = ORIENTATION_NORMAL; + + // -- Standard Xmp tag -------------------------------- + +#ifdef _XMP_SUPPORT_ + + bool ok = false; + QString str = getXmpTagString("Xmp.tiff.Orientation"); + if (!str.isEmpty()) + { + orientation = str.toLong(&ok); + if (ok) + { + kDebug() << "Orientation => Xmp.tiff.Orientation => " << (int)orientation; + return (ImageOrientation)orientation; + } + } + +#endif // _XMP_SUPPORT_ + + // Because some camera set a wrong standard exif orientation tag, + // We need to check makernote tags in first! + + // -- Minolta Cameras ---------------------------------- + + Exiv2::ExifKey minoltaKey1("Exif.MinoltaCs7D.Rotation"); + it = exifData.findKey(minoltaKey1); + + if (it != exifData.end() && it->count()) + { + orientation = it->toLong(); + kDebug() << "Orientation => Exif.MinoltaCs7D.Rotation => " << (int)orientation; + switch(orientation) + { + case 76: + imageOrient = ORIENTATION_ROT_90; + break; + case 82: + imageOrient = ORIENTATION_ROT_270; + break; + } + return imageOrient; + } + + Exiv2::ExifKey minoltaKey2("Exif.MinoltaCs5D.Rotation"); + it = exifData.findKey(minoltaKey2); + + if (it != exifData.end() && it->count()) + { + orientation = it->toLong(); + kDebug() << "Orientation => Exif.MinoltaCs5D.Rotation => " << (int)orientation; + switch(orientation) + { + case 76: + imageOrient = ORIENTATION_ROT_90; + break; + case 82: + imageOrient = ORIENTATION_ROT_270; + break; + } + return imageOrient; + } + + // -- Standard Exif tag -------------------------------- + + Exiv2::ExifKey keyStd("Exif.Image.Orientation"); + it = exifData.findKey(keyStd); + + if (it != exifData.end() && it->count()) + { + orientation = it->toLong(); + kDebug() << "Orientation => Exif.Image.Orientation => " << (int)orientation; + return (ImageOrientation)orientation; + } + + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot parse Exif Orientation tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return ORIENTATION_UNSPECIFIED; +} + +bool KExiv2::setImageOrientation(ImageOrientation orientation, bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + if (orientation < ORIENTATION_UNSPECIFIED || orientation > ORIENTATION_ROT_270) + { + kDebug() << "Image orientation value is not correct!"; + return false; + } + + // Set Exif values. + + d->exifMetadata()["Exif.Image.Orientation"] = static_cast(orientation); + kDebug() << "Exif.Image.Orientation tag set to: " << (int)orientation; + + // Set Xmp values. + +#ifdef _XMP_SUPPORT_ + + setXmpTagString("Xmp.tiff.Orientation", QString::number((int)orientation), false); + +#endif // _XMP_SUPPORT_ + + // -- Minolta/Sony Cameras ---------------------------------- + + // Minolta and Sony camera store image rotation in Makernote. + // We remove these information to prevent duplicate values. + + Exiv2::ExifData::iterator it; + + Exiv2::ExifKey minoltaKey1("Exif.MinoltaCs7D.Rotation"); + it = d->exifMetadata().findKey(minoltaKey1); + if (it != d->exifMetadata().end()) + { + d->exifMetadata().erase(it); + kDebug() << "Removing Exif.MinoltaCs7D.Rotation tag"; + } + + Exiv2::ExifKey minoltaKey2("Exif.MinoltaCs5D.Rotation"); + it = d->exifMetadata().findKey(minoltaKey2); + if (it != d->exifMetadata().end()) + { + d->exifMetadata().erase(it); + kDebug() << "Removing Exif.MinoltaCs5D.Rotation tag"; + } + + // -- Exif embedded thumbnail ---------------------------------- + + Exiv2::ExifKey thumbKey("Exif.Thumbnail.Orientation"); + it = d->exifMetadata().findKey(thumbKey); + if (it != d->exifMetadata().end() && it->count()) + { + RotationMatrix operation((KExiv2Iface::KExiv2::ImageOrientation)it->toLong()); + operation *= orientation; + (*it) = static_cast(operation.exifOrientation()); + } + + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Exif Orientation tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +KExiv2::ImageColorWorkSpace KExiv2::getImageColorWorkSpace() const +{ + // Check Exif values. + + long exifColorSpace = -1; + if (!getExifTagLong("Exif.Photo.ColorSpace", exifColorSpace)) + { +#ifdef _XMP_SUPPORT_ + QVariant var = getXmpTagVariant("Xmp.exif.ColorSpace"); + if (!var.isNull()) + exifColorSpace = var.toInt(); +#endif // _XMP_SUPPORT_ + } + + if (exifColorSpace == 1) + { + return WORKSPACE_SRGB; // as specified by standard + } + else if (exifColorSpace == 2) + { + return WORKSPACE_ADOBERGB; // not in the standard! + } + else + { + if (exifColorSpace == 65535) + { + // A lot of cameras set the Exif.Iop.InteroperabilityIndex, + // as documented for ExifTool + QString interopIndex = getExifTagString("Exif.Iop.InteroperabilityIndex"); + if (!interopIndex.isNull()) + { + if (interopIndex == "R03") + return WORKSPACE_ADOBERGB; + else if (interopIndex == "R98") + return WORKSPACE_SRGB; + } + } + + // Note: Text EXIF ColorSpace tag may just not be present (NEF files) + + // Nikon camera set Exif.Photo.ColorSpace to uncalibrated or just skip this field, + // then add additional information into the makernotes. + // Exif.Nikon3.ColorSpace: 1 => sRGB, 2 => AdobeRGB + long nikonColorSpace; + if (getExifTagLong("Exif.Nikon3.ColorSpace", nikonColorSpace)) + { + if (nikonColorSpace == 1) + return WORKSPACE_SRGB; + else if (nikonColorSpace == 2) + return WORKSPACE_ADOBERGB; + } + // Exif.Nikon3.ColorMode is set to "MODE2" for AdobeRGB, but there are sometimes two ColorMode fields + // in a NEF, with the first one "COLOR" and the second one "MODE2"; but in this case, ColorSpace (above) was set. + if (getExifTagString("Exif.Nikon3.ColorMode").contains("MODE2")) + return WORKSPACE_ADOBERGB; + + //TODO: This makernote tag (0x00b4) must be added to libexiv2 + /* + long canonColorSpace; + if (getExifTagLong("Exif.Canon.ColorSpace", canonColorSpace)) + { + if (canonColorSpace == 1) + return WORKSPACE_SRGB; + else if (canonColorSpace == 2) + return WORKSPACE_ADOBERGB; + } + */ + + // TODO : add more Makernote parsing here ... + + if (exifColorSpace == 65535) + return WORKSPACE_UNCALIBRATED; + } + + return WORKSPACE_UNSPECIFIED; +} + +bool KExiv2::setImageColorWorkSpace(ImageColorWorkSpace workspace, bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + // Set Exif value. + + d->exifMetadata()["Exif.Photo.ColorSpace"] = static_cast(workspace); + + // Set Xmp value. + +#ifdef _XMP_SUPPORT_ + + setXmpTagString("Xmp.exif.ColorSpace", QString::number((int)workspace), false); + +#endif // _XMP_SUPPORT_ + + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Exif color workspace tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QDateTime KExiv2::getImageDateTime() const +{ + try + { + // In first, trying to get Date & time from Exif tags. + + if (!d->exifMetadata().empty()) + { + Exiv2::ExifData exifData(d->exifMetadata()); + { + Exiv2::ExifKey key("Exif.Photo.DateTimeOriginal"); + Exiv2::ExifData::iterator it = exifData.findKey(key); + + if (it != exifData.end()) + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + + if (dateTime.isValid()) + { + kDebug() << "DateTime => Exif.Photo.DateTimeOriginal => " << dateTime; + return dateTime; + } + } + } + { + Exiv2::ExifKey key("Exif.Photo.DateTimeDigitized"); + Exiv2::ExifData::iterator it = exifData.findKey(key); + + if (it != exifData.end()) + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + + if (dateTime.isValid()) + { + kDebug() << "DateTime => Exif.Photo.DateTimeDigitized => " << dateTime; + return dateTime; + } + } + } + { + Exiv2::ExifKey key("Exif.Image.DateTime"); + Exiv2::ExifData::iterator it = exifData.findKey(key); + + if (it != exifData.end()) + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + + if (dateTime.isValid()) + { + kDebug() << "DateTime => Exif.Image.DateTime => " << dateTime; + return dateTime; + } + } + } + } + + // In second, trying to get Date & time from Xmp tags. + +#ifdef _XMP_SUPPORT_ + + if (!d->xmpMetadata().empty()) + { + Exiv2::XmpData xmpData(d->xmpMetadata()); + { + Exiv2::XmpKey key("Xmp.exif.DateTimeOriginal"); + Exiv2::XmpData::iterator it = xmpData.findKey(key); + + if (it != xmpData.end()) + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + + if (dateTime.isValid()) + { + kDebug() << "DateTime => Xmp.exif.DateTimeOriginal => " << dateTime; + return dateTime; + } + } + } + { + Exiv2::XmpKey key("Xmp.exif.DateTimeDigitized"); + Exiv2::XmpData::iterator it = xmpData.findKey(key); + + if (it != xmpData.end()) + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + + if (dateTime.isValid()) + { + kDebug() << "DateTime => Xmp.exif.DateTimeDigitized => " << dateTime; + return dateTime; + } + } + } + { + Exiv2::XmpKey key("Xmp.photoshop.DateCreated"); + Exiv2::XmpData::iterator it = xmpData.findKey(key); + + if (it != xmpData.end()) + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + + if (dateTime.isValid()) + { + kDebug() << "DateTime => Xmp.photoshop.DateCreated => " << dateTime; + return dateTime; + } + } + } + { + Exiv2::XmpKey key("Xmp.xmp.CreateDate"); + Exiv2::XmpData::iterator it = xmpData.findKey(key); + + if (it != xmpData.end()) + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + + if (dateTime.isValid()) + { + kDebug() << "DateTime => Xmp.xmp.CreateDate => " << dateTime; + return dateTime; + } + } + } + { + Exiv2::XmpKey key("Xmp.tiff.DateTime"); + Exiv2::XmpData::iterator it = xmpData.findKey(key); + + if (it != xmpData.end()) + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + + if (dateTime.isValid()) + { + kDebug() << "DateTime => Xmp.tiff.DateTime => " << dateTime; + return dateTime; + } + } + } + { + Exiv2::XmpKey key("Xmp.xmp.ModifyDate"); + Exiv2::XmpData::iterator it = xmpData.findKey(key); + + if (it != xmpData.end()) + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + + if (dateTime.isValid()) + { + kDebug() << "DateTime => Xmp.xmp.ModifyDate => " << dateTime; + return dateTime; + } + } + } + { + Exiv2::XmpKey key("Xmp.xmp.MetadataDate"); + Exiv2::XmpData::iterator it = xmpData.findKey(key); + + if (it != xmpData.end()) + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + + if (dateTime.isValid()) + { + kDebug() << "DateTime => Xmp.xmp.MetadataDate => " << dateTime; + return dateTime; + } + } + } + } + +#endif // _XMP_SUPPORT_ + + // In third, trying to get Date & time from Iptc tags. + + if (!d->iptcMetadata().empty()) + { + Exiv2::IptcData iptcData(d->iptcMetadata()); + + // Try creation Iptc date & time entries. + + Exiv2::IptcKey keyDateCreated("Iptc.Application2.DateCreated"); + Exiv2::IptcData::iterator it = iptcData.findKey(keyDateCreated); + + if (it != iptcData.end()) + { + QString IptcDateCreated(it->toString().c_str()); + Exiv2::IptcKey keyTimeCreated("Iptc.Application2.TimeCreated"); + Exiv2::IptcData::iterator it2 = iptcData.findKey(keyTimeCreated); + + if (it2 != iptcData.end()) + { + QString IptcTimeCreated(it2->toString().c_str()); + QDate date = QDate::fromString(IptcDateCreated, Qt::ISODate); + QTime time = QTime::fromString(IptcTimeCreated, Qt::ISODate); + QDateTime dateTime = QDateTime(date, time); + + if (dateTime.isValid()) + { + kDebug() << "DateTime => Iptc.Application2.DateCreated => " << dateTime; + return dateTime; + } + } + } + + // Try digitization Iptc date & time entries. + + Exiv2::IptcKey keyDigitizationDate("Iptc.Application2.DigitizationDate"); + Exiv2::IptcData::iterator it3 = iptcData.findKey(keyDigitizationDate); + + if (it3 != iptcData.end()) + { + QString IptcDateDigitization(it3->toString().c_str()); + Exiv2::IptcKey keyDigitizationTime("Iptc.Application2.DigitizationTime"); + Exiv2::IptcData::iterator it4 = iptcData.findKey(keyDigitizationTime); + + if (it4 != iptcData.end()) + { + QString IptcTimeDigitization(it4->toString().c_str()); + QDate date = QDate::fromString(IptcDateDigitization, Qt::ISODate); + QTime time = QTime::fromString(IptcTimeDigitization, Qt::ISODate); + QDateTime dateTime = QDateTime(date, time); + + if (dateTime.isValid()) + { + kDebug() << "DateTime => Iptc.Application2.DigitizationDate => " << dateTime; + return dateTime; + } + } + } + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot parse Exif date & time tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QDateTime(); +} + +bool KExiv2::setImageDateTime(const QDateTime& dateTime, bool setDateTimeDigitized, bool setProgramName) const +{ + if(!dateTime.isValid()) + return false; + + if (!setProgramId(setProgramName)) + return false; + + try + { + // In first we write date & time into Exif. + + // DateTimeDigitized is set by slide scanners etc. when a picture is digitized. + // DateTimeOriginal specifies the date/time when the picture was taken. + // For digital cameras, these dates should be both set, and identical. + // Reference: http://www.exif.org/Exif2-2.PDF, chapter 4.6.5, table 4, section F. + + const std::string &exifdatetime(dateTime.toString(QString("yyyy:MM:dd hh:mm:ss")).toAscii().constData()); + d->exifMetadata()["Exif.Image.DateTime"] = exifdatetime; + d->exifMetadata()["Exif.Photo.DateTimeOriginal"] = exifdatetime; + if(setDateTimeDigitized) + d->exifMetadata()["Exif.Photo.DateTimeDigitized"] = exifdatetime; + +#ifdef _XMP_SUPPORT_ + + // In second we write date & time into Xmp. + + const std::string &xmpdatetime(dateTime.toString(Qt::ISODate).toAscii().constData()); + + Exiv2::Value::AutoPtr xmpTxtVal = Exiv2::Value::create(Exiv2::xmpText); + xmpTxtVal->read(xmpdatetime); + d->xmpMetadata().add(Exiv2::XmpKey("Xmp.exif.DateTimeOriginal"), xmpTxtVal.get()); + d->xmpMetadata().add(Exiv2::XmpKey("Xmp.photoshop.DateCreated"), xmpTxtVal.get()); + d->xmpMetadata().add(Exiv2::XmpKey("Xmp.tiff.DateTime"), xmpTxtVal.get()); + d->xmpMetadata().add(Exiv2::XmpKey("Xmp.xmp.CreateDate"), xmpTxtVal.get()); + d->xmpMetadata().add(Exiv2::XmpKey("Xmp.xmp.MetadataDate"), xmpTxtVal.get()); + d->xmpMetadata().add(Exiv2::XmpKey("Xmp.xmp.ModifyDate"), xmpTxtVal.get()); + if(setDateTimeDigitized) + d->xmpMetadata().add(Exiv2::XmpKey("Xmp.exif.DateTimeDigitized"), xmpTxtVal.get()); + + // Tag not updated: + // "Xmp.dc.DateTime" is a sequence of date relevant of dublin core change. + // This is not the picture date as well + +#endif // _XMP_SUPPORT_ + + // In third we write date & time into Iptc. + + const std::string &iptcdate(dateTime.date().toString(Qt::ISODate).toAscii().constData()); + const std::string &iptctime(dateTime.time().toString(Qt::ISODate).toAscii().constData()); + d->iptcMetadata()["Iptc.Application2.DateCreated"] = iptcdate; + d->iptcMetadata()["Iptc.Application2.TimeCreated"] = iptctime; + if(setDateTimeDigitized) + { + d->iptcMetadata()["Iptc.Application2.DigitizationDate"] = iptcdate; + d->iptcMetadata()["Iptc.Application2.DigitizationTime"] = iptctime; + } + + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Date & Time into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QDateTime KExiv2::getDigitizationDateTime(bool fallbackToCreationTime) const +{ + try + { + // In first, trying to get Date & time from Exif tags. + + if (!d->exifMetadata().empty()) + { + // Try Exif date time digitized. + + Exiv2::ExifData exifData(d->exifMetadata()); + Exiv2::ExifKey key("Exif.Photo.DateTimeDigitized"); + Exiv2::ExifData::iterator it = exifData.findKey(key); + + if (it != exifData.end()) + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + + if (dateTime.isValid()) + { + kDebug() << "DateTime (Exif digitalized): " << dateTime.toString().toAscii().constData(); + return dateTime; + } + } + } + + // In second, trying to get Date & time from Iptc tags. + + if (!d->iptcMetadata().empty()) + { + // Try digitization Iptc date time entries. + + Exiv2::IptcData iptcData(d->iptcMetadata()); + Exiv2::IptcKey keyDigitizationDate("Iptc.Application2.DigitizationDate"); + Exiv2::IptcData::iterator it = iptcData.findKey(keyDigitizationDate); + + if (it != iptcData.end()) + { + QString IptcDateDigitization(it->toString().c_str()); + + Exiv2::IptcKey keyDigitizationTime("Iptc.Application2.DigitizationTime"); + Exiv2::IptcData::iterator it2 = iptcData.findKey(keyDigitizationTime); + + if (it2 != iptcData.end()) + { + QString IptcTimeDigitization(it2->toString().c_str()); + + QDate date = QDate::fromString(IptcDateDigitization, Qt::ISODate); + QTime time = QTime::fromString(IptcTimeDigitization, Qt::ISODate); + QDateTime dateTime = QDateTime(date, time); + + if (dateTime.isValid()) + { + kDebug() << "Date (IPTC digitalized): " << dateTime.toString().toAscii().constData(); + return dateTime; + } + } + } + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot parse Exif digitization date & time tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + if (fallbackToCreationTime) + return getImageDateTime(); + else + return QDateTime(); +} + +bool KExiv2::getImagePreview(QImage& preview) const +{ + try + { + // In first we trying to get from Iptc preview tag. + if (preview.loadFromData(getIptcTagData("Iptc.Application2.Preview")) ) + return true; + + // TODO : Added here Makernotes preview extraction when Exiv2 will be fixed for that. + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot get image preview using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::setImagePreview(const QImage& preview, bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + if (preview.isNull()) + { + removeIptcTag("Iptc.Application2.Preview"); + removeIptcTag("Iptc.Application2.PreviewFormat"); + removeIptcTag("Iptc.Application2.PreviewVersion"); + return true; + } + + try + { + QByteArray data; + QBuffer buffer(&data); + buffer.open(QIODevice::WriteOnly); + + // A little bit compressed preview jpeg image to limit IPTC size. + preview.save(&buffer, "JPEG"); + kDebug() << "JPEG image preview size: (" << preview.width() << " x " + << preview.height() << ") pixels - " << data.size() << " bytes"; + + Exiv2::DataValue val; + val.read((Exiv2::byte *)data.data(), data.size()); + d->iptcMetadata()["Iptc.Application2.Preview"] = val; + + // See http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf Appendix A for details. + d->iptcMetadata()["Iptc.Application2.PreviewFormat"] = 11; // JPEG + d->iptcMetadata()["Iptc.Application2.PreviewVersion"] = 1; + + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot get image preview using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +} // NameSpace KExiv2Iface diff --git a/libkexiv2/libkexiv2/kexiv2iptc.cpp b/libkexiv2/libkexiv2/kexiv2iptc.cpp new file mode 100644 index 00000000..8249325d --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2iptc.cpp @@ -0,0 +1,883 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-09-15 + * @brief Iptc manipulation methods + * + * @author Copyright (C) 2006-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "kexiv2.h" +#include "kexiv2_p.h" + +namespace KExiv2Iface +{ + +bool KExiv2::canWriteIptc(const QString& filePath) +{ + try + { + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open((const char*) + (QFile::encodeName(filePath))); + + Exiv2::AccessMode mode = image->checkMode(Exiv2::mdIptc); + return (mode == Exiv2::amWrite || mode == Exiv2::amReadWrite); + } + catch(Exiv2::Error& e) + { + std::string s(e.what()); + kError() << "Cannot check Iptc access mode using Exiv2 (Error #" + << e.code() << ": " << s.c_str() << ")"; + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::hasIptc() const +{ + return !d->iptcMetadata().empty(); +} + +bool KExiv2::clearIptc() const +{ + try + { + d->iptcMetadata().clear(); + return true; + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot clear Iptc data using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QByteArray KExiv2::getIptc(bool addIrbHeader) const +{ + try + { + if (!d->iptcMetadata().empty()) + { + Exiv2::IptcData& iptc = d->iptcMetadata(); + Exiv2::DataBuf c2; + + if (addIrbHeader) + { + c2 = Exiv2::Photoshop::setIptcIrb(0, 0, iptc); + } + else + { + c2 = Exiv2::IptcParser::encode(d->iptcMetadata()); + } + + QByteArray data((const char*)c2.pData_, c2.size_); + return data; + + } + } + catch(Exiv2::Error& e) + { + if (!d->filePath.isEmpty()) + { + kError() << "From file " << d->filePath.toAscii().constData(); + } + + d->printExiv2ExceptionError("Cannot get Iptc data using Exiv2 ",e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QByteArray(); +} + +bool KExiv2::setIptc(const QByteArray& data) const +{ + try + { + if (!data.isEmpty()) + { + Exiv2::IptcParser::decode(d->iptcMetadata(), (const Exiv2::byte*)data.data(), data.size()); + return (!d->iptcMetadata().empty()); + } + } + catch(Exiv2::Error& e) + { + if (!d->filePath.isEmpty()) + { + kError() << "From file " << d->filePath.toAscii().constData(); + } + + d->printExiv2ExceptionError("Cannot set Iptc data using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +KExiv2::MetaDataMap KExiv2::getIptcTagsDataList(const QStringList& iptcKeysFilter, bool invertSelection) const +{ + if (d->iptcMetadata().empty()) + return MetaDataMap(); + + try + { + Exiv2::IptcData iptcData = d->iptcMetadata(); + iptcData.sortByKey(); + + QString ifDItemName; + MetaDataMap metaDataMap; + + for (Exiv2::IptcData::iterator md = iptcData.begin(); md != iptcData.end(); ++md) + { + QString key = QString::fromLocal8Bit(md->key().c_str()); + + // Decode the tag value with a user friendly output. + std::ostringstream os; + os << *md; + + QString value; + + if (key == QString("Iptc.Envelope.CharacterSet")) + { + value = iptcData.detectCharset(); + } + else + { + value = QString::fromUtf8(os.str().c_str()); + } + + // To make a string just on one line. + value.replace('\n', ' '); + + // Some Iptc key are redondancy. check if already one exist... + MetaDataMap::iterator it = metaDataMap.find(key); + + // We apply a filter to get only the Iptc tags that we need. + + if (!iptcKeysFilter.isEmpty()) + { + if (!invertSelection) + { + if (iptcKeysFilter.contains(key.section('.', 1, 1))) + { + if (it == metaDataMap.end()) + { + metaDataMap.insert(key, value); + } + else + { + QString v = *it; + v.append(", "); + v.append(value); + metaDataMap.insert(key, v); + } + } + } + else + { + if (!iptcKeysFilter.contains(key.section('.', 1, 1))) + { + if (it == metaDataMap.end()) + { + metaDataMap.insert(key, value); + } + else + { + QString v = *it; + v.append(", "); + v.append(value); + metaDataMap.insert(key, v); + } + } + } + } + else // else no filter at all. + { + if (it == metaDataMap.end()) + { + metaDataMap.insert(key, value); + } + else + { + QString v = *it; + v.append(", "); + v.append(value); + metaDataMap.insert(key, v); + } + } + + } + + return metaDataMap; + } + catch (Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot parse Iptc metadata using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return MetaDataMap(); +} + +QString KExiv2::getIptcTagTitle(const char* iptcTagName) +{ + try + { + std::string iptckey(iptcTagName); + Exiv2::IptcKey ik(iptckey); + return QString::fromLocal8Bit( Exiv2::IptcDataSets::dataSetTitle(ik.tag(), ik.record()) ); + } + catch (Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot get metadata tag title using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QString(); +} + +QString KExiv2::getIptcTagDescription(const char* iptcTagName) +{ + try + { + std::string iptckey(iptcTagName); + Exiv2::IptcKey ik(iptckey); + return QString::fromLocal8Bit( Exiv2::IptcDataSets::dataSetDesc(ik.tag(), ik.record()) ); + } + catch (Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot get metadata tag description using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QString(); +} + +bool KExiv2::removeIptcTag(const char* iptcTagName, bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + Exiv2::IptcData::iterator it = d->iptcMetadata().begin(); + int i = 0; + + while(it != d->iptcMetadata().end()) + { + QString key = QString::fromLocal8Bit(it->key().c_str()); + + if (key == QString(iptcTagName)) + { + it = d->iptcMetadata().erase(it); + ++i; + } + else + { + ++it; + } + }; + + if (i > 0) + return true; + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot remove Iptc tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +bool KExiv2::setIptcTagData(const char* iptcTagName, const QByteArray& data, bool setProgramName) const +{ + if (data.isEmpty()) + return false; + + if (!setProgramId(setProgramName)) + return false; + + try + { + Exiv2::DataValue val((Exiv2::byte *)data.data(), data.size()); + d->iptcMetadata()[iptcTagName] = val; + return true; + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot set Iptc tag data into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QByteArray KExiv2::getIptcTagData(const char* iptcTagName) const +{ + try + { + Exiv2::IptcKey iptcKey(iptcTagName); + Exiv2::IptcData iptcData(d->iptcMetadata()); + Exiv2::IptcData::iterator it = iptcData.findKey(iptcKey); + + if (it != iptcData.end()) + { + char* const s = new char[(*it).size()]; + (*it).copy((Exiv2::byte*)s, Exiv2::bigEndian); + QByteArray data(s, (*it).size()); + delete [] s; + return data; + } + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError(QString("Cannot find Iptc key '%1' into image using Exiv2 ") + .arg(iptcTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QByteArray(); +} + +QString KExiv2::getIptcTagString(const char* iptcTagName, bool escapeCR) const +{ + try + { + Exiv2::IptcKey iptcKey(iptcTagName); + Exiv2::IptcData iptcData(d->iptcMetadata()); + Exiv2::IptcData::iterator it = iptcData.findKey(iptcKey); + + if (it != iptcData.end()) + { + std::ostringstream os; + os << *it; + QString tagValue(os.str().c_str()); + + if (escapeCR) + tagValue.replace('\n', ' '); + + return tagValue; + } + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError(QString("Cannot find Iptc key '%1' into image using Exiv2 ") + .arg(iptcTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QString(); +} + +bool KExiv2::setIptcTagString(const char* iptcTagName, const QString& value, bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + d->iptcMetadata()[iptcTagName] = std::string(value.toUtf8().constData()); + + // Make sure we have set the charset to UTF-8 + d->iptcMetadata()["Iptc.Envelope.CharacterSet"] = "\33%G"; + return true; + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot set Iptc tag string into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QStringList KExiv2::getIptcTagsStringList(const char* iptcTagName, bool escapeCR) const +{ + try + { + if (!d->iptcMetadata().empty()) + { + QStringList values; + Exiv2::IptcData iptcData(d->iptcMetadata()); + + for (Exiv2::IptcData::iterator it = iptcData.begin(); it != iptcData.end(); ++it) + { + QString key = QString::fromLocal8Bit(it->key().c_str()); + + if (key == QString(iptcTagName)) + { + QString tagValue = QString::fromUtf8(it->toString().c_str()); + + if (escapeCR) + tagValue.replace('\n', ' '); + + values.append(tagValue); + } + } + + return values; + } + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError(QString("Cannot find Iptc key '%1' into image using Exiv2 ") + .arg(iptcTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QStringList(); +} + +bool KExiv2::setIptcTagsStringList(const char* iptcTagName, int maxSize, + const QStringList& oldValues, const QStringList& newValues, + bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + QStringList oldvals = oldValues; + QStringList newvals = newValues; + + kDebug() << d->filePath.toAscii().constData() << " : " << iptcTagName + << " => " << newvals.join(",").toAscii().constData(); + + // Remove all old values. + Exiv2::IptcData iptcData(d->iptcMetadata()); + Exiv2::IptcData::iterator it = iptcData.begin(); + + while(it != iptcData.end()) + { + QString key = QString::fromLocal8Bit(it->key().c_str()); + QString val = QString::fromUtf8(it->toString().c_str()); + + // Also remove new values to avoid duplicates. They will be added again below. + if ( key == QString(iptcTagName) && + (oldvals.contains(val) || newvals.contains(val)) + ) + it = iptcData.erase(it); + else + ++it; + }; + + // Add new values. + + Exiv2::IptcKey iptcTag(iptcTagName); + + for (QStringList::iterator it = newvals.begin(); it != newvals.end(); ++it) + { + QString key = *it; + key.truncate(maxSize); + + Exiv2::Value::AutoPtr val = Exiv2::Value::create(Exiv2::string); + val->read(key.toUtf8().constData()); + iptcData.add(iptcTag, val.get()); + } + + d->iptcMetadata() = iptcData; + + // Make sure character set is UTF-8 + setIptcTagString("Iptc.Envelope.CharacterSet", "\33%G", false); + + return true; + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError(QString("Cannot set Iptc key '%1' into image using Exiv2 ") + .arg(iptcTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QStringList KExiv2::getIptcKeywords() const +{ + try + { + if (!d->iptcMetadata().empty()) + { + QStringList keywords; + Exiv2::IptcData iptcData(d->iptcMetadata()); + + for (Exiv2::IptcData::iterator it = iptcData.begin(); it != iptcData.end(); ++it) + { + QString key = QString::fromLocal8Bit(it->key().c_str()); + + if (key == QString("Iptc.Application2.Keywords")) + { + QString val = QString::fromUtf8(it->toString().c_str()); + keywords.append(val); + } + } + + kDebug() << d->filePath << " ==> Read Iptc Keywords: " << keywords; + + return keywords; + } + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot get Iptc Keywords from image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QStringList(); +} + +bool KExiv2::setIptcKeywords(const QStringList& oldKeywords, const QStringList& newKeywords, + bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + QStringList oldkeys = oldKeywords; + QStringList newkeys = newKeywords; + + kDebug() << d->filePath << " ==> New Iptc Keywords: " << newkeys; + + // Remove all old keywords. + Exiv2::IptcData iptcData(d->iptcMetadata()); + Exiv2::IptcData::iterator it = iptcData.begin(); + + while(it != iptcData.end()) + { + QString key = QString::fromLocal8Bit(it->key().c_str()); + QString val = QString::fromUtf8(it->toString().c_str()); + + // Also remove new keywords to avoid duplicates. They will be added again below. + if ( key == QString("Iptc.Application2.Keywords") && + (oldKeywords.contains(val) || newKeywords.contains(val)) + ) + it = iptcData.erase(it); + else + ++it; + }; + + // Add new keywords. Note that Keywords Iptc tag is limited to 64 char but can be redondant. + + Exiv2::IptcKey iptcTag("Iptc.Application2.Keywords"); + + for (QStringList::iterator it = newkeys.begin(); it != newkeys.end(); ++it) + { + QString key = *it; + key.truncate(64); + + Exiv2::Value::AutoPtr val = Exiv2::Value::create(Exiv2::string); + val->read(key.toUtf8().constData()); + iptcData.add(iptcTag, val.get()); + } + + d->iptcMetadata() = iptcData; + + // Make sure character set is UTF-8 + setIptcTagString("Iptc.Envelope.CharacterSet", "\33%G", false); + + return true; + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot set Iptc Keywords into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QStringList KExiv2::getIptcSubjects() const +{ + try + { + if (!d->iptcMetadata().empty()) + { + QStringList subjects; + Exiv2::IptcData iptcData(d->iptcMetadata()); + + for (Exiv2::IptcData::iterator it = iptcData.begin(); it != iptcData.end(); ++it) + { + QString key = QString::fromLocal8Bit(it->key().c_str()); + + if (key == QString("Iptc.Application2.Subject")) + { + QString val(it->toString().c_str()); + subjects.append(val); + } + } + + return subjects; + } + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot get Iptc Subjects from image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QStringList(); +} + +bool KExiv2::setIptcSubjects(const QStringList& oldSubjects, const QStringList& newSubjects, + bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + QStringList oldDef = oldSubjects; + QStringList newDef = newSubjects; + + // Remove all old subjects. + Exiv2::IptcData iptcData(d->iptcMetadata()); + Exiv2::IptcData::iterator it = iptcData.begin(); + + while(it != iptcData.end()) + { + QString key = QString::fromLocal8Bit(it->key().c_str()); + QString val = QString::fromUtf8(it->toString().c_str()); + + if (key == QString("Iptc.Application2.Subject") && oldDef.contains(val)) + it = iptcData.erase(it); + else + ++it; + }; + + // Add new subjects. Note that Keywords Iptc tag is limited to 236 char but can be redondant. + + Exiv2::IptcKey iptcTag("Iptc.Application2.Subject"); + + for (QStringList::iterator it = newDef.begin(); it != newDef.end(); ++it) + { + QString key = *it; + key.truncate(236); + + Exiv2::Value::AutoPtr val = Exiv2::Value::create(Exiv2::string); + val->read(key.toUtf8().constData()); + iptcData.add(iptcTag, val.get()); + } + + d->iptcMetadata() = iptcData; + + // Make sure character set is UTF-8 + setIptcTagString("Iptc.Envelope.CharacterSet", "\33%G", false); + + return true; + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot set Iptc Subjects into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +QStringList KExiv2::getIptcSubCategories() const +{ + try + { + if (!d->iptcMetadata().empty()) + { + QStringList subCategories; + Exiv2::IptcData iptcData(d->iptcMetadata()); + + for (Exiv2::IptcData::iterator it = iptcData.begin(); it != iptcData.end(); ++it) + { + QString key = QString::fromLocal8Bit(it->key().c_str()); + + if (key == QString("Iptc.Application2.SuppCategory")) + { + QString val(it->toString().c_str()); + subCategories.append(val); + } + } + + return subCategories; + } + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot get Iptc Sub Categories from image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return QStringList(); +} + +bool KExiv2::setIptcSubCategories(const QStringList& oldSubCategories, const QStringList& newSubCategories, + bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + try + { + QStringList oldkeys = oldSubCategories; + QStringList newkeys = newSubCategories; + + // Remove all old Sub Categories. + Exiv2::IptcData iptcData(d->iptcMetadata()); + Exiv2::IptcData::iterator it = iptcData.begin(); + + while(it != iptcData.end()) + { + QString key = QString::fromLocal8Bit(it->key().c_str()); + QString val = QString::fromUtf8(it->toString().c_str()); + + if (key == QString("Iptc.Application2.SuppCategory") && oldSubCategories.contains(val)) + it = iptcData.erase(it); + else + ++it; + }; + + // Add new Sub Categories. Note that SubCategories Iptc tag is limited to 32 + // characters but can be redondant. + + Exiv2::IptcKey iptcTag("Iptc.Application2.SuppCategory"); + + for (QStringList::iterator it = newkeys.begin(); it != newkeys.end(); ++it) + { + QString key = *it; + key.truncate(32); + + Exiv2::Value::AutoPtr val = Exiv2::Value::create(Exiv2::string); + val->read(key.toUtf8().constData()); + iptcData.add(iptcTag, val.get()); + } + + d->iptcMetadata() = iptcData; + + // Make sure character set is UTF-8 + setIptcTagString("Iptc.Envelope.CharacterSet", "\33%G", false); + + return true; + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot set Iptc Sub Categories into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return false; +} + +KExiv2::TagsMap KExiv2::getIptcTagsList() const +{ + try + { + QList tags; + tags << Exiv2::IptcDataSets::envelopeRecordList() + << Exiv2::IptcDataSets::application2RecordList(); + + TagsMap tagsMap; + for (QList::iterator it = tags.begin(); it != tags.end(); ++it) + { + do + { + QString key = QLatin1String( Exiv2::IptcKey( (*it)->number_, (*it)->recordId_ ).key().c_str() ); + QStringList values; + values << (*it)->name_ << (*it)->title_ << (*it)->desc_; + tagsMap.insert(key, values); + ++(*it); + } + while((*it)->number_ != 0xffff); + } + return tagsMap; + } + catch(Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot get Iptc Tags list using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return TagsMap(); +} + +} // NameSpace KExiv2Iface diff --git a/libkexiv2/libkexiv2/kexiv2previews.cpp b/libkexiv2/libkexiv2/kexiv2previews.cpp new file mode 100644 index 00000000..5bb1f08b --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2previews.cpp @@ -0,0 +1,214 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-11-14 + * @brief Embedded preview loading + * + * @author Copyright (C) 2009-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2009-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "kexiv2previews.h" + +// Local includes + +#include "kexiv2_p.h" +#include "kexiv2.h" + +namespace KExiv2Iface +{ + +class KExiv2Previews::Private +{ +public: + + Private() + { + manager = 0; + } + + ~Private() + { + delete manager; + } + + void load(Exiv2::Image::AutoPtr image_) + { + image = image_; + + image->readMetadata(); + + manager = new Exiv2::PreviewManager(*image); + Exiv2::PreviewPropertiesList props = manager->getPreviewProperties(); + + // reverse order of list, which is smallest-first + Exiv2::PreviewPropertiesList::reverse_iterator it; + + for (it = props.rbegin() ; it != props.rend() ; ++it) + { + properties << *it; + } + } + +public: + + Exiv2::Image::AutoPtr image; + Exiv2::PreviewManager* manager; + QList properties; +}; + +KExiv2Previews::KExiv2Previews(const QString& filePath) + : d(new Private) +{ + try + { + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open((const char*)(QFile::encodeName(filePath))); + d->load(image); + } + catch( Exiv2::Error& e ) + { + KExiv2::Private::printExiv2ExceptionError("Cannot load metadata using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } +} + +KExiv2Previews::KExiv2Previews(const QByteArray& imgData) + : d(new Private) +{ + try + { + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open((Exiv2::byte*)imgData.data(), imgData.size()); + d->load(image); + } + catch( Exiv2::Error& e ) + { + KExiv2::Private::printExiv2ExceptionError("Cannot load metadata using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } +} + +KExiv2Previews::~KExiv2Previews() +{ + delete d; +} + +bool KExiv2Previews::isEmpty() +{ + return d->properties.isEmpty(); +} + +QSize KExiv2Previews::originalSize() const +{ + if (d->image.get()) + return QSize(d->image->pixelWidth(), d->image->pixelHeight()); + + return QSize(); +} + +QString KExiv2Previews::originalMimeType() const +{ + if (d->image.get()) + return d->image->mimeType().c_str(); + + return QString(); +} + +int KExiv2Previews::count() +{ + return d->properties.size(); +} + +int KExiv2Previews::dataSize(int index) +{ + if (index < 0 || index >= size()) return 0; + + return d->properties[index].size_; +} + +int KExiv2Previews::width(int index) +{ + if (index < 0 || index >= size()) return 0; + + return d->properties[index].width_; +} + +int KExiv2Previews::height(int index) +{ + if (index < 0 || index >= size()) return 0; + + return d->properties[index].height_; +} + +QString KExiv2Previews::mimeType(int index) +{ + if (index < 0 || index >= size()) return 0; + + return QString::fromLatin1(d->properties[index].mimeType_.c_str()); +} + +QString KExiv2Previews::fileExtension(int index) +{ + if (index < 0 || index >= size()) return 0; + + return QString::fromLatin1(d->properties[index].extension_.c_str()); +} + +QByteArray KExiv2Previews::data(int index) +{ + if (index < 0 || index >= size()) return QByteArray(); + + kDebug() << "index: " << index; + kDebug() << "d->properties: " << count(); + + try + { + Exiv2::PreviewImage image = d->manager->getPreviewImage(d->properties[index]); + return QByteArray((const char*)image.pData(), image.size()); + } + catch( Exiv2::Error& e ) + { + KExiv2::Private::printExiv2ExceptionError("Cannot load metadata using Exiv2 ", e); + return QByteArray(); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + return QByteArray(); + } +} + +QImage KExiv2Previews::image(int index) +{ + QByteArray previewData = data(index); + QImage image; + + if (!image.loadFromData(previewData)) + return QImage(); + + return image; +} + +} // namespace KExiv2Iface diff --git a/libkexiv2/libkexiv2/kexiv2previews.h b/libkexiv2/libkexiv2/kexiv2previews.h new file mode 100644 index 00000000..195c6f3d --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2previews.h @@ -0,0 +1,106 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-11-14 + * @brief Embedded preview loading + * + * @author Copyright (C) 2009-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2009-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef KEXIV2PREVIEWS +#define KEXIV2PREVIEWS + +// Qt includes + +#include +#include +#include + +// Local includes + +#include "libkexiv2_export.h" + +class QImage; + +namespace KExiv2Iface +{ + +class KEXIV2_EXPORT KExiv2Previews +{ +public: + + /** + * Open the given file and scan for embedded preview images + */ + KExiv2Previews(const QString& filePath); + + /** + * Open the given image data and scan the image for embedded preview images. + */ + KExiv2Previews(const QByteArray& imgData); + ~KExiv2Previews(); + + /// Returns the pixel size of the original image, as read from the file (not the metadata). + QSize originalSize() const; + + /// Returns the mimeType of the original image, detected from the file's content. + QString originalMimeType() const; + + /// Returns if there are any preview images available + bool isEmpty(); + + /// Returns how many embedded previews are available + int count(); + int size() { return count(); } + + /** + * For each contained preview image, return the size + * of the image data in bytes, width and height of the preview, + * the mimeType and the file extension. + * Ensure that index < count(). + * Previews are sorted by width*height, largest first. + */ + int dataSize(int index = 0); + int width(int index = 0); + int height(int index = 0); + QString mimeType(int index = 0); + QString fileExtension(int index = 0); + + /** + * Retrieve the image data for the specified embedded preview image + */ + QByteArray data(int index = 0); + + /** + * Loads the data of the specified preview and creates a QImage + * from this data. Returns a null QImage if the loading failed. + */ + QImage image(int index = 0); + +private: + + class Private; + Private* const d; +}; + +} // namespace KExiv2Iface + +#endif // KEXIV2PREVIEWS diff --git a/libkexiv2/libkexiv2/kexiv2xmp.cpp b/libkexiv2/libkexiv2/kexiv2xmp.cpp new file mode 100644 index 00000000..b6323670 --- /dev/null +++ b/libkexiv2/libkexiv2/kexiv2xmp.cpp @@ -0,0 +1,1220 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-09-15 + * @brief Xmp manipulation methods + * + * @author Copyright (C) 2006-2014 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2006-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "kexiv2.h" +#include "kexiv2_p.h" + +namespace KExiv2Iface +{ + +bool KExiv2::canWriteXmp(const QString& filePath) +{ +#ifdef _XMP_SUPPORT_ + try + { + Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open((const char*) + (QFile::encodeName(filePath))); + + Exiv2::AccessMode mode = image->checkMode(Exiv2::mdXmp); + return (mode == Exiv2::amWrite || mode == Exiv2::amReadWrite); + } + catch( Exiv2::Error& e ) + { + std::string s(e.what()); + kError() << "Cannot check Xmp access mode using Exiv2 (Error #" + << e.code() << ": " << s.c_str() << ")"; + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(filePath); + +#endif // _XMP_SUPPORT_ + + return false; +} + +bool KExiv2::hasXmp() const +{ +#ifdef _XMP_SUPPORT_ + + return !d->xmpMetadata().empty(); + +#else + + return false; + +#endif // _XMP_SUPPORT_ +} + +bool KExiv2::clearXmp() const +{ +#ifdef _XMP_SUPPORT_ + + try + { + d->xmpMetadata().clear(); + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot clear Xmp data using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#endif // _XMP_SUPPORT_ + + return false; +} + +QByteArray KExiv2::getXmp() const +{ +#ifdef _XMP_SUPPORT_ + + try + { + if (!d->xmpMetadata().empty()) + { + + std::string xmpPacket; + Exiv2::XmpParser::encode(xmpPacket, d->xmpMetadata()); + QByteArray data(xmpPacket.data(), xmpPacket.size()); + return data; + } + } + catch( Exiv2::Error& e ) + { + if (!d->filePath.isEmpty()) + + + d->printExiv2ExceptionError("Cannot get Xmp data using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#endif // _XMP_SUPPORT_ + + return QByteArray(); +} + +bool KExiv2::setXmp(const QByteArray& data) const +{ +#ifdef _XMP_SUPPORT_ + + try + { + if (!data.isEmpty()) + { + + std::string xmpPacket; + xmpPacket.assign(data.data(), data.size()); + if (Exiv2::XmpParser::decode(d->xmpMetadata(), xmpPacket) != 0) + return false; + else + return true; + } + } + catch( Exiv2::Error& e ) + { + if (!d->filePath.isEmpty()) + kError() << "From file " << d->filePath.toAscii().constData(); + + d->printExiv2ExceptionError("Cannot set Xmp data using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(data); + +#endif // _XMP_SUPPORT_ + + return false; +} + +KExiv2::MetaDataMap KExiv2::getXmpTagsDataList(const QStringList& xmpKeysFilter, bool invertSelection) const +{ +#ifdef _XMP_SUPPORT_ + + if (d->xmpMetadata().empty()) + return MetaDataMap(); + + try + { + Exiv2::XmpData xmpData = d->xmpMetadata(); + xmpData.sortByKey(); + + QString ifDItemName; + MetaDataMap metaDataMap; + + for (Exiv2::XmpData::iterator md = xmpData.begin(); md != xmpData.end(); ++md) + { + QString key = QString::fromAscii(md->key().c_str()); + + // Decode the tag value with a user friendly output. + std::ostringstream os; + os << *md; + QString value = QString::fromUtf8(os.str().c_str()); + + // If the tag is a language alternative type, parse content to detect language. + if (md->typeId() == Exiv2::langAlt) + { + QString lang; + value = detectLanguageAlt(value, lang); + } + else + { + value = QString::fromUtf8(os.str().c_str()); + } + + // To make a string just on one line. + value.replace('\n', ' '); + + // Some XMP key are redondancy. check if already one exist... + MetaDataMap::iterator it = metaDataMap.find(key); + + // We apply a filter to get only the XMP tags that we need. + + if (!xmpKeysFilter.isEmpty()) + { + if (!invertSelection) + { + if (xmpKeysFilter.contains(key.section('.', 1, 1))) + { + if (it == metaDataMap.end()) + { + metaDataMap.insert(key, value); + } + else + { + QString v = *it; + v.append(", "); + v.append(value); + metaDataMap.insert(key, v); + } + } + } + else + { + if (!xmpKeysFilter.contains(key.section('.', 1, 1))) + { + if (it == metaDataMap.end()) + { + metaDataMap.insert(key, value); + } + else + { + QString v = *it; + v.append(", "); + v.append(value); + metaDataMap.insert(key, v); + } + } + } + } + else // else no filter at all. + { + if (it == metaDataMap.end()) + { + metaDataMap.insert(key, value); + } + else + { + QString v = *it; + v.append(", "); + v.append(value); + metaDataMap.insert(key, v); + } + } + } + + return metaDataMap; + } + catch (Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot parse Xmp metadata using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpKeysFilter); + Q_UNUSED(invertSelection); + +#endif // _XMP_SUPPORT_ + + return MetaDataMap(); +} + +QString KExiv2::getXmpTagTitle(const char* xmpTagName) +{ +#ifdef _XMP_SUPPORT_ + + try + { + std::string xmpkey(xmpTagName); + Exiv2::XmpKey xk(xmpkey); + return QString::fromLocal8Bit( Exiv2::XmpProperties::propertyTitle(xk) ); + } + catch (Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot get Xmp metadata tag title using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + +#endif // _XMP_SUPPORT_ + + return QString(); +} + +QString KExiv2::getXmpTagDescription(const char* xmpTagName) +{ +#ifdef _XMP_SUPPORT_ + try + { + std::string xmpkey(xmpTagName); + Exiv2::XmpKey xk(xmpkey); + return QString::fromLocal8Bit( Exiv2::XmpProperties::propertyDesc(xk) ); + } + catch (Exiv2::Error& e) + { + d->printExiv2ExceptionError("Cannot get Xmp metadata tag description using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + +#endif // _XMP_SUPPORT_ + + return QString(); +} + +QString KExiv2::getXmpTagString(const char* xmpTagName, bool escapeCR) const +{ +#ifdef _XMP_SUPPORT_ + + try + { + Exiv2::XmpData xmpData(d->xmpMetadata()); + Exiv2::XmpKey key(xmpTagName); + Exiv2::XmpData::iterator it = xmpData.findKey(key); + if (it != xmpData.end()) + { + std::ostringstream os; + os << *it; + QString tagValue = QString::fromUtf8(os.str().c_str()); + + if (escapeCR) + tagValue.replace('\n', ' '); + + return tagValue; + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError(QString("Cannot find Xmp key '%1' into image using Exiv2 ") + .arg(xmpTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(escapeCR); + +#endif // _XMP_SUPPORT_ + + return QString(); +} + +bool KExiv2::setXmpTagString(const char* xmpTagName, const QString& value, bool setProgramName) const +{ +#ifdef _XMP_SUPPORT_ + + if (!setProgramId(setProgramName)) + return false; + + try + { + const std::string &txt(value.toUtf8().constData()); + Exiv2::Value::AutoPtr xmpTxtVal = Exiv2::Value::create(Exiv2::xmpText); + xmpTxtVal->read(txt); + d->xmpMetadata()[xmpTagName].setValue(xmpTxtVal.get()); + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Xmp tag string into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(value); + Q_UNUSED(setProgramName); + +#endif // _XMP_SUPPORT_ + + return false; +} +bool KExiv2::setXmpTagString(const char* xmpTagName, const QString& value, + KExiv2::XmpTagType type, bool setProgramName) const +{ +#ifdef _XMP_SUPPORT_ + + if (!setProgramId(setProgramName)) + return false; + + try + { + const std::string &txt(value.toUtf8().constData()); + Exiv2::XmpTextValue xmpTxtVal(""); + + if(type == KExiv2::NormalTag) // normal type + { + xmpTxtVal.read(txt); + d->xmpMetadata().add(Exiv2::XmpKey(xmpTagName),&xmpTxtVal); + return true; + } + if(type == KExiv2::ArrayBagTag) // xmp type = bag + { + xmpTxtVal.setXmpArrayType(Exiv2::XmpValue::xaBag); + xmpTxtVal.read(""); + d->xmpMetadata().add(Exiv2::XmpKey(xmpTagName),&xmpTxtVal); + } + if(type == KExiv2::StructureTag) // xmp type = struct + { + xmpTxtVal.setXmpStruct(); + d->xmpMetadata().add(Exiv2::XmpKey(xmpTagName),&xmpTxtVal); + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Xmp tag string into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(value); + Q_UNUSED(setProgramName); + +#endif // _XMP_SUPPORT_ + + return false; +} +KExiv2::AltLangMap KExiv2::getXmpTagStringListLangAlt(const char* xmpTagName, bool escapeCR) const +{ +#ifdef _XMP_SUPPORT_ + + try + { + Exiv2::XmpData xmpData = d->xmpMetadata(); + + for (Exiv2::XmpData::iterator it = xmpData.begin(); it != xmpData.end(); ++it) + { + if (it->key() == xmpTagName && it->typeId() == Exiv2::langAlt) + { + AltLangMap map; + const Exiv2::LangAltValue &value = static_cast(it->value()); + + for (Exiv2::LangAltValue::ValueType::const_iterator it2 = value.value_.begin(); + it2 != value.value_.end(); ++it2) + { + QString lang = QString::fromUtf8(it2->first.c_str()); + QString text = QString::fromUtf8(it2->second.c_str()); + if (escapeCR) + text.replace('\n', ' '); + + map.insert(lang, text); + } + + return map; + } + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError(QString("Cannot find Xmp key '%1' into image using Exiv2 ") + .arg(xmpTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(escapeCR); + +#endif // _XMP_SUPPORT_ + + return AltLangMap(); +} + +bool KExiv2::setXmpTagStringListLangAlt(const char* xmpTagName, const KExiv2::AltLangMap& values, + bool setProgramName) const +{ +#ifdef _XMP_SUPPORT_ + + if (!setProgramId(setProgramName)) + return false; + + try + { + // Remove old XMP alternative Language tag. + removeXmpTag(xmpTagName); + + if (!values.isEmpty()) + { + Exiv2::Value::AutoPtr xmpTxtVal = Exiv2::Value::create(Exiv2::langAlt); + + for (AltLangMap::const_iterator it = values.constBegin(); it != values.constEnd(); ++it) + { + QString lang = it.key(); + QString text = it.value(); + QString txtLangAlt = QString("lang=%1 %2").arg(lang).arg(text); + const std::string &txt(txtLangAlt.toUtf8().constData()); + xmpTxtVal->read(txt); + } + + // ...and add the new one instead. + d->xmpMetadata().add(Exiv2::XmpKey(xmpTagName), xmpTxtVal.get()); + } + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Xmp tag string lang-alt into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(values); + Q_UNUSED(setProgramName); + +#endif // _XMP_SUPPORT_ + + return false; +} + +QString KExiv2::getXmpTagStringLangAlt(const char* xmpTagName, const QString& langAlt, bool escapeCR) const +{ +#ifdef _XMP_SUPPORT_ + + try + { + Exiv2::XmpData xmpData(d->xmpMetadata()); + Exiv2::XmpKey key(xmpTagName); + for (Exiv2::XmpData::iterator it = xmpData.begin(); it != xmpData.end(); ++it) + { + if (it->key() == xmpTagName && it->typeId() == Exiv2::langAlt) + { + for (int i = 0; i < it->count(); i++) + { + std::ostringstream os; + os << it->toString(i); + QString lang; + QString tagValue = QString::fromUtf8(os.str().c_str()); + tagValue = detectLanguageAlt(tagValue, lang); + if (langAlt == lang) + { + if (escapeCR) + tagValue.replace('\n', ' '); + + return tagValue; + } + } + } + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError(QString("Cannot find Xmp key '%1' into image using Exiv2 ") + .arg(xmpTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(langAlt); + Q_UNUSED(escapeCR); + +#endif // _XMP_SUPPORT_ + + return QString(); +} + +bool KExiv2::setXmpTagStringLangAlt(const char* xmpTagName, const QString& value, + const QString& langAlt, bool setProgramName) const +{ +#ifdef _XMP_SUPPORT_ + + if (!setProgramId(setProgramName)) + return false; + + try + { + QString language("x-default"); // default alternative language. + + if (!langAlt.isEmpty()) + language = langAlt; + + QString txtLangAlt = QString("lang=%1 %2").arg(language).arg(value); + + const std::string &txt(txtLangAlt.toUtf8().constData()); + Exiv2::Value::AutoPtr xmpTxtVal = Exiv2::Value::create(Exiv2::langAlt); + + // Search if an Xmp tag already exist. + + AltLangMap map = getXmpTagStringListLangAlt(xmpTagName, false); + if (!map.isEmpty()) + { + for (AltLangMap::iterator it = map.begin(); it != map.end(); ++it) + { + if (it.key() != langAlt) + { + const std::string &val((*it).toUtf8().constData()); + xmpTxtVal->read(val); + kDebug() << *it; + } + } + } + + xmpTxtVal->read(txt); + removeXmpTag(xmpTagName); + d->xmpMetadata().add(Exiv2::XmpKey(xmpTagName), xmpTxtVal.get()); + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Xmp tag string lang-alt into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(value); + Q_UNUSED(langAlt); + Q_UNUSED(setProgramName); + +#endif // _XMP_SUPPORT_ + + return false; +} + +QStringList KExiv2::getXmpTagStringSeq(const char* xmpTagName, bool escapeCR) const +{ +#ifdef _XMP_SUPPORT_ + + try + { + Exiv2::XmpData xmpData(d->xmpMetadata()); + Exiv2::XmpKey key(xmpTagName); + Exiv2::XmpData::iterator it = xmpData.findKey(key); + if (it != xmpData.end()) + { + if (it->typeId() == Exiv2::xmpSeq) + { + QStringList seq; + + for (int i = 0; i < it->count(); i++) + { + std::ostringstream os; + os << it->toString(i); + QString seqValue = QString::fromUtf8(os.str().c_str()); + + if (escapeCR) + seqValue.replace('\n', ' '); + + seq.append(seqValue); + } + kDebug() << "XMP String Seq (" << xmpTagName << "): " << seq; + + return seq; + } + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError(QString("Cannot find Xmp key '%1' into image using Exiv2 ") + .arg(xmpTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(escapeCR); + +#endif // _XMP_SUPPORT_ + + return QStringList(); +} + +bool KExiv2::setXmpTagStringSeq(const char* xmpTagName, const QStringList& seq, + bool setProgramName) const +{ +#ifdef _XMP_SUPPORT_ + + if (!setProgramId(setProgramName)) + return false; + + try + { + if (seq.isEmpty()) + { + removeXmpTag(xmpTagName); + } + else + { + const QStringList list = seq; + Exiv2::Value::AutoPtr xmpTxtSeq = Exiv2::Value::create(Exiv2::xmpSeq); + + for (QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it ) + { + const std::string &txt((*it).toUtf8().constData()); + xmpTxtSeq->read(txt); + } + d->xmpMetadata()[xmpTagName].setValue(xmpTxtSeq.get()); + } + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Xmp tag string Seq into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(seq); + Q_UNUSED(setProgramName); + +#endif // _XMP_SUPPORT_ + + return false; +} + +QStringList KExiv2::getXmpTagStringBag(const char* xmpTagName, bool escapeCR) const +{ +#ifdef _XMP_SUPPORT_ + + try + { + Exiv2::XmpData xmpData(d->xmpMetadata()); + Exiv2::XmpKey key(xmpTagName); + Exiv2::XmpData::iterator it = xmpData.findKey(key); + if (it != xmpData.end()) + { + if (it->typeId() == Exiv2::xmpBag) + { + QStringList bag; + + for (int i = 0; i < it->count(); i++) + { + std::ostringstream os; + os << it->toString(i); + QString bagValue = QString::fromUtf8(os.str().c_str()); + + if (escapeCR) + bagValue.replace('\n', ' '); + + bag.append(bagValue); + } + + return bag; + } + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError(QString("Cannot find Xmp key '%1' into image using Exiv2 ") + .arg(xmpTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(escapeCR); + +#endif // _XMP_SUPPORT_ + + return QStringList(); +} + +bool KExiv2::setXmpTagStringBag(const char* xmpTagName, const QStringList& bag, + bool setProgramName) const +{ +#ifdef _XMP_SUPPORT_ + + if (!setProgramId(setProgramName)) + return false; + + try + { + if (bag.isEmpty()) + { + removeXmpTag(xmpTagName); + } + else + { + QStringList list = bag; + Exiv2::Value::AutoPtr xmpTxtBag = Exiv2::Value::create(Exiv2::xmpBag); + + for (QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it ) + { + const std::string &txt((*it).toUtf8().constData()); + xmpTxtBag->read(txt); + } + d->xmpMetadata()[xmpTagName].setValue(xmpTxtBag.get()); + } + return true; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot set Xmp tag string Bag into image using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(bag); + Q_UNUSED(setProgramName); + +#endif // _XMP_SUPPORT_ + + return false; +} + +bool KExiv2::addToXmpTagStringBag(const char* xmpTagName, const QStringList& entriesToAdd, + bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + QStringList oldEntries = getXmpTagStringBag(xmpTagName, false); + QStringList newEntries = entriesToAdd; + + // Create a list of keywords including old one which already exists. + for (QStringList::const_iterator it = oldEntries.constBegin(); it != oldEntries.constEnd(); ++it ) + { + if (!newEntries.contains(*it)) + newEntries.append(*it); + } + + if (setXmpTagStringBag(xmpTagName, newEntries, false)) + return true; + + return false; +} + +bool KExiv2::removeFromXmpTagStringBag(const char* xmpTagName, const QStringList& entriesToRemove, + bool setProgramName) const +{ + if (!setProgramId(setProgramName)) + return false; + + QStringList currentEntries = getXmpTagStringBag(xmpTagName, false); + QStringList newEntries; + + // Create a list of current keywords except those that shall be removed + for (QStringList::const_iterator it = currentEntries.constBegin(); it != currentEntries.constEnd(); ++it ) + { + if (!entriesToRemove.contains(*it)) + newEntries.append(*it); + } + + if (setXmpTagStringBag(xmpTagName, newEntries, false)) + return true; + + return false; +} + +QVariant KExiv2::getXmpTagVariant(const char* xmpTagName, bool rationalAsListOfInts, bool stringEscapeCR) const +{ +#ifdef _XMP_SUPPORT_ + try + { + Exiv2::XmpData xmpData(d->xmpMetadata()); + Exiv2::XmpKey key(xmpTagName); + Exiv2::XmpData::iterator it = xmpData.findKey(key); + if (it != xmpData.end()) + { + switch (it->typeId()) + { + case Exiv2::unsignedByte: + case Exiv2::unsignedShort: + case Exiv2::unsignedLong: + case Exiv2::signedShort: + case Exiv2::signedLong: + return QVariant((int)it->toLong()); + case Exiv2::unsignedRational: + case Exiv2::signedRational: + if (rationalAsListOfInts) + { + QList list; + list << (*it).toRational().first; + list << (*it).toRational().second; + return QVariant(list); + } + else + { + // prefer double precision + double num = (*it).toRational().first; + double den = (*it).toRational().second; + if (den == 0.0) + return QVariant(QVariant::Double); + return QVariant(num / den); + } + case Exiv2::date: + case Exiv2::time: + { + QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate); + return QVariant(dateTime); + } + case Exiv2::asciiString: + case Exiv2::comment: + case Exiv2::string: + { + std::ostringstream os; + os << *it; + QString tagValue = QString::fromLocal8Bit(os.str().c_str()); + + if (stringEscapeCR) + tagValue.replace('\n', ' '); + + return QVariant(tagValue); + } + case Exiv2::xmpText: + { + std::ostringstream os; + os << *it; + QString tagValue = QString::fromUtf8(os.str().c_str()); + + if (stringEscapeCR) + tagValue.replace('\n', ' '); + + return tagValue; + } + case Exiv2::xmpBag: + case Exiv2::xmpSeq: + case Exiv2::xmpAlt: + { + QStringList list; + for (int i=0; i < it->count(); i++) + { + list << QString::fromUtf8(it->toString(i).c_str()); + } + return list; + } + case Exiv2::langAlt: + { + // access the value directly + const Exiv2::LangAltValue &value = static_cast(it->value()); + QMap map; + // access the ValueType std::map< std::string, std::string> + Exiv2::LangAltValue::ValueType::const_iterator i; + for (i = value.value_.begin(); i != value.value_.end(); ++i) + { + map[QString::fromUtf8(i->first.c_str())] = QString::fromUtf8(i->second.c_str()); + } + return map; + } + default: + break; + } + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError(QString("Cannot find Xmp key '%1' into image using Exiv2 ") + .arg(xmpTagName), e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(rationalAsListOfInts); + Q_UNUSED(stringEscapeCR); + +#endif // _XMP_SUPPORT_ + + return QVariant(); +} + +bool KExiv2::registerXmpNameSpace(const QString& uri, const QString& prefix) +{ +#ifdef _XMP_SUPPORT_ + + try + { + QString ns = uri; + if (!uri.endsWith('/')) ns.append('/'); + Exiv2::XmpProperties::registerNs(ns.toAscii().constData(), prefix.toAscii().constData()); + return true; + } + catch( Exiv2::Error& e ) + { + Private::printExiv2ExceptionError("Cannot register a new Xmp namespace using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(uri); + Q_UNUSED(prefix); + +#endif // _XMP_SUPPORT_ + + return false; +} + +bool KExiv2::unregisterXmpNameSpace(const QString& uri) +{ +#ifdef _XMP_SUPPORT_ + + try + { + QString ns = uri; + if (!uri.endsWith('/')) ns.append('/'); + Exiv2::XmpProperties::unregisterNs(ns.toAscii().constData()); + return true; + } + catch( Exiv2::Error& e ) + { + Private::printExiv2ExceptionError("Cannot unregister a new Xmp namespace using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(uri); + +#endif // _XMP_SUPPORT_ + + return false; +} + +bool KExiv2::removeXmpTag(const char* xmpTagName, bool setProgramName) const +{ +#ifdef _XMP_SUPPORT_ + + if (!setProgramId(setProgramName)) + return false; + + try + { + Exiv2::XmpKey xmpKey(xmpTagName); + Exiv2::XmpData::iterator it = d->xmpMetadata().findKey(xmpKey); + if (it != d->xmpMetadata().end()) + { + d->xmpMetadata().erase(it); + return true; + } + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot remove Xmp tag using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + +#else + + Q_UNUSED(xmpTagName); + Q_UNUSED(setProgramName); + +#endif // _XMP_SUPPORT_ + + return false; +} + +QStringList KExiv2::getXmpKeywords() const +{ + return (getXmpTagStringBag("Xmp.dc.subject", false)); +} + +bool KExiv2::setXmpKeywords(const QStringList& newKeywords, bool setProgramName) const +{ + return addToXmpTagStringBag("Xmp.dc.subject", newKeywords, setProgramName); +} + +bool KExiv2::removeXmpKeywords(const QStringList& keywordsToRemove, bool setProgramName) +{ + return removeFromXmpTagStringBag("Xmp.dc.subject", keywordsToRemove, setProgramName); +} + +QStringList KExiv2::getXmpSubCategories() const +{ + return (getXmpTagStringBag("Xmp.photoshop.SupplementalCategories", false)); +} + +bool KExiv2::setXmpSubCategories(const QStringList& newSubCategories, bool setProgramName) const +{ + return addToXmpTagStringBag("Xmp.photoshop.SupplementalCategories", newSubCategories, setProgramName); +} + +bool KExiv2::removeXmpSubCategories(const QStringList& subCategoriesToRemove, bool setProgramName) +{ + return removeFromXmpTagStringBag("Xmp.photoshop.SupplementalCategories", subCategoriesToRemove, setProgramName); +} + +QStringList KExiv2::getXmpSubjects() const +{ + return (getXmpTagStringBag("Xmp.iptc.SubjectCode", false)); +} + +bool KExiv2::setXmpSubjects(const QStringList& newSubjects, bool setProgramName) const +{ + return addToXmpTagStringBag("Xmp.iptc.SubjectCode", newSubjects, setProgramName); +} + +bool KExiv2::removeXmpSubjects(const QStringList& subjectsToRemove, bool setProgramName) +{ + return removeFromXmpTagStringBag("Xmp.iptc.SubjectCode", subjectsToRemove, setProgramName); +} + +KExiv2::TagsMap KExiv2::getXmpTagsList() const +{ + try + { + TagsMap tagsMap; + d->getXMPTagsListFromPrefix("dc", tagsMap); + d->getXMPTagsListFromPrefix("digiKam", tagsMap); + d->getXMPTagsListFromPrefix("xmp", tagsMap); + d->getXMPTagsListFromPrefix("xmpRights", tagsMap); + d->getXMPTagsListFromPrefix("xmpMM", tagsMap); + d->getXMPTagsListFromPrefix("xmpBJ", tagsMap); + d->getXMPTagsListFromPrefix("xmpTPg", tagsMap); + d->getXMPTagsListFromPrefix("xmpDM", tagsMap); + d->getXMPTagsListFromPrefix("MicrosoftPhoto", tagsMap); + d->getXMPTagsListFromPrefix("pdf", tagsMap); + d->getXMPTagsListFromPrefix("photoshop", tagsMap); + d->getXMPTagsListFromPrefix("crs", tagsMap); + d->getXMPTagsListFromPrefix("tiff", tagsMap); + d->getXMPTagsListFromPrefix("exif", tagsMap); + d->getXMPTagsListFromPrefix("aux", tagsMap); + d->getXMPTagsListFromPrefix("iptc", tagsMap); + d->getXMPTagsListFromPrefix("iptcExt", tagsMap); + d->getXMPTagsListFromPrefix("plus", tagsMap); + d->getXMPTagsListFromPrefix("mwg-rs", tagsMap); + d->getXMPTagsListFromPrefix("dwc", tagsMap); + return tagsMap; + } + catch( Exiv2::Error& e ) + { + d->printExiv2ExceptionError("Cannot get Xmp Tags list using Exiv2 ", e); + } + catch(...) + { + kError() << "Default exception from Exiv2"; + } + + return TagsMap(); +} + +} // NameSpace KExiv2Iface diff --git a/libkexiv2/libkexiv2/libkexiv2_export.h b/libkexiv2/libkexiv2/libkexiv2_export.h new file mode 100644 index 00000000..4b75cfca --- /dev/null +++ b/libkexiv2/libkexiv2/libkexiv2_export.h @@ -0,0 +1,47 @@ +/** =========================================================== + * @file + * + * This file is part of the KDE project + * + * @brief Helper for exporting functions/classes from the shared library + * + * @author Copyright (C) 2007 David Faure + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * ============================================================ */ + +#ifndef LIBKEXIV2_EXPORT_H +#define LIBKEXIV2_EXPORT_H + +/* needed for KDE_EXPORT and KDE_IMPORT macros */ +#include + +#ifndef KEXIV2_EXPORT +# if defined(MAKE_KEXIV2_LIB) + /* We are building this library */ +# define KEXIV2_EXPORT KDE_EXPORT +# else + /* We are using this library */ +# define KEXIV2_EXPORT KDE_IMPORT +# endif +#endif + +# ifndef KEXIV2_EXPORT_DEPRECATED +# define KEXIV2_EXPORT_DEPRECATED KDE_DEPRECATED KEXIV2_EXPORT +# endif + +#endif diff --git a/libkexiv2/libkexiv2/msgtextedit.cpp b/libkexiv2/libkexiv2/msgtextedit.cpp new file mode 100644 index 00000000..b5d4a5ff --- /dev/null +++ b/libkexiv2/libkexiv2/msgtextedit.cpp @@ -0,0 +1,109 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-07-15 + * @brief a text edit widget with click message. + * + * @author Copyright (C) 2009-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// Qt includes + +#include +#include +#include + +// Local includes + +#include "moc_msgtextedit.cpp" + +namespace KExiv2Iface +{ + +class MsgTextEdit::Private +{ +public: + + Private(){} + + QString message; +}; + +MsgTextEdit::MsgTextEdit(QWidget* parent) + : KTextEdit(parent), d(new Private) +{ + setAcceptRichText(false); +} + +MsgTextEdit::~MsgTextEdit() +{ + delete d; +} + +QString MsgTextEdit::clickMessage() const +{ + return d->message; +} + +void MsgTextEdit::setClickMessage(const QString& msg) +{ + d->message = msg; + viewport()->update(); +} + +void MsgTextEdit::setText(const QString& txt) +{ + KTextEdit::setText(txt); + viewport()->update(); +} + +void MsgTextEdit::paintEvent(QPaintEvent* e) +{ + KTextEdit::paintEvent(e); + + if (toPlainText().isEmpty() && !hasFocus()) + { + QPainter p(viewport()); + QPen tmp = p.pen(); + p.setPen(palette().color(QPalette::Disabled, QPalette::Text)); + QRect cr = contentsRect(); + p.drawText(cr, Qt::AlignTop, d->message); + p.setPen(tmp); + } +} + +void MsgTextEdit::dropEvent(QDropEvent* e) +{ + viewport()->update(); + KTextEdit::dropEvent(e); +} + +void MsgTextEdit::focusInEvent(QFocusEvent* e) +{ + viewport()->update(); + KTextEdit::focusInEvent(e); +} + +void MsgTextEdit::focusOutEvent(QFocusEvent* e) +{ + viewport()->update(); + KTextEdit::focusOutEvent(e); +} + +} // namespace KExiv2Iface diff --git a/libkexiv2/libkexiv2/msgtextedit.h b/libkexiv2/libkexiv2/msgtextedit.h new file mode 100644 index 00000000..e96042b8 --- /dev/null +++ b/libkexiv2/libkexiv2/msgtextedit.h @@ -0,0 +1,74 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-07-15 + * @brief a text edit widget with click message. + * + * @author Copyright (C) 2009-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef MSGTEXTEDIT_H +#define MSGTEXTEDIT_H + +// Qt includes + +#include +#include + +// KDE includes + +#include + +// Local includes + +#include "libkexiv2_export.h" + +namespace KExiv2Iface +{ + +class KEXIV2_EXPORT MsgTextEdit : public KTextEdit +{ + Q_OBJECT + +public: + + MsgTextEdit(QWidget* parent); + ~MsgTextEdit(); + + void setClickMessage(const QString& msg); + QString clickMessage() const; + + void setText(const QString& txt); + +protected: + + void paintEvent(QPaintEvent*); + void dropEvent(QDropEvent*); + void focusInEvent(QFocusEvent*); + void focusOutEvent(QFocusEvent*); + +private: + + class Private; + Private* const d; +}; + +} // namespace KExiv2Iface + +#endif /* MSGTEXTEDIT_H */ diff --git a/libkexiv2/libkexiv2/rotationmatrix.cpp b/libkexiv2/libkexiv2/rotationmatrix.cpp new file mode 100644 index 00000000..b96a1748 --- /dev/null +++ b/libkexiv2/libkexiv2/rotationmatrix.cpp @@ -0,0 +1,340 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-08-03 + * @brief Tools for combining rotation operations + * + * @author Copyright (C) 2006-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2004-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "rotationmatrix.h" + +// KDE includes + +#include + +// local includes + +#include "version.h" + +namespace KExiv2Iface +{ + +/** + If the picture is displayed according to the exif orientation tag, + the user will request rotating operations relative to what he sees, + and that is the picture rotated according to the EXIF tag. + So the operation requested and the given EXIF angle must be combined. + E.g. if orientation is "6" (rotate 90 clockwiseto show correctly) + and the user selects 180 clockwise, the operation is 270. + If the user selected 270, the operation would be None (and clearing the exif tag). + + This requires to describe the transformations in a model which + cares for both composing (180+90=270) and eliminating (180+180=no action), + as well as the non-commutative nature of the operations (vflip+90 is not 90+vflip) + + All 2D transformations can be described by a 2x3 matrix, see QWRotationMatrix. + All transformations needed here - rotate 90, 180, 270, flipV, flipH - + can be described in a 2x2 matrix with the values 0,1,-1 + (because flipping is expressed by changing the sign only, + and sine and cosine of 90, 180 and 270 are either 0,1 or -1). + + x' = m11 x + m12 y + y' = m21 x + m22 y + + Moreover, all combinations of these rotate/flip operations result in one of the eight + matrices defined below. + (I did not proof that mathematically, but empirically) + + static const RotationMatrix identity; //( 1, 0, 0, 1) + static const RotationMatrix rotate90; //( 0, -1, 1, 0) + static const RotationMatrix rotate180; //(-1, 0, 0, -1) + static const RotationMatrix rotate270; //( 0, 1, -1, 0) + static const RotationMatrix flipHorizontal; //(-1, 0, 0, 1) + static const RotationMatrix flipVertical; //( 1, 0, 0, -1) + static const RotationMatrix rotate90flipHorizontal; //( 0, 1, 1, 0), first rotate, then flip + static const RotationMatrix rotate90flipVertical; //( 0, -1, -1, 0), first rotate, then flip + +*/ + +namespace Matrix +{ + +static const RotationMatrix identity ( 1, 0, 0, 1); +static const RotationMatrix rotate90 ( 0, -1, 1, 0); +static const RotationMatrix rotate180 (-1, 0, 0, -1); +static const RotationMatrix rotate270 ( 0, 1, -1, 0); +static const RotationMatrix flipHorizontal (-1, 0, 0, 1); +static const RotationMatrix flipVertical ( 1, 0, 0, -1); +static const RotationMatrix rotate90flipHorizontal ( 0, 1, 1, 0); +static const RotationMatrix rotate90flipVertical ( 0, -1, -1, 0); + +RotationMatrix matrix(RotationMatrix::TransformationAction action) +{ + switch (action) + { + case RotationMatrix::NoTransformation: + return identity; + case RotationMatrix::FlipHorizontal: + return flipHorizontal; + case RotationMatrix::FlipVertical: + return flipVertical; + case RotationMatrix::Rotate90: + return rotate90; + case RotationMatrix::Rotate180: + return rotate180; + case RotationMatrix::Rotate270: + return rotate270; + } + return identity; +} + +RotationMatrix matrix(KExiv2::ImageOrientation exifOrientation) +{ + switch (exifOrientation) + { + case KExiv2::ORIENTATION_NORMAL: + return identity; + case KExiv2::ORIENTATION_HFLIP: + return flipHorizontal; + case KExiv2::ORIENTATION_ROT_180: + return rotate180; + case KExiv2::ORIENTATION_VFLIP: + return flipVertical; + case KExiv2::ORIENTATION_ROT_90_HFLIP: + return rotate90flipHorizontal; + case KExiv2::ORIENTATION_ROT_90: + return rotate90; + case KExiv2::ORIENTATION_ROT_90_VFLIP: + return rotate90flipVertical; + case KExiv2::ORIENTATION_ROT_270: + return rotate270; + case KExiv2::ORIENTATION_UNSPECIFIED: + return identity; + } + return identity; +} + + +} // namespace Matrix + +RotationMatrix::RotationMatrix() +{ + set( 1, 0, 0, 1 ); +} + +RotationMatrix::RotationMatrix(TransformationAction action) +{ + *this = Matrix::matrix(action); +} + +RotationMatrix::RotationMatrix(KExiv2::ImageOrientation exifOrientation) +{ + *this = Matrix::matrix(exifOrientation); +} + +RotationMatrix::RotationMatrix(int m11, int m12, int m21, int m22) +{ + set(m11, m12, m21, m22); +} + +void RotationMatrix::set(int m11, int m12, int m21, int m22) +{ + m[0][0]=m11; + m[0][1]=m12; + m[1][0]=m21; + m[1][1]=m22; +} + +bool RotationMatrix::isNoTransform() const +{ + return *this == Matrix::identity; +} + +RotationMatrix& RotationMatrix::operator*=(const RotationMatrix& ma) +{ + set( ma.m[0][0]*m[0][0] + ma.m[0][1]*m[1][0], ma.m[0][0]*m[0][1] + ma.m[0][1]*m[1][1], + ma.m[1][0]*m[0][0] + ma.m[1][1]*m[1][0], ma.m[1][0]*m[0][1] + ma.m[1][1]*m[1][1] ); + return *this; +} + +bool RotationMatrix::operator==(const RotationMatrix& ma) const +{ + return m[0][0]==ma.m[0][0] && + m[0][1]==ma.m[0][1] && + m[1][0]==ma.m[1][0] && + m[1][1]==ma.m[1][1]; +} + +bool RotationMatrix::operator!=(const RotationMatrix& ma) const +{ + return !(*this==ma); +} + +RotationMatrix& RotationMatrix::operator*=(TransformationAction action) +{ + return (*this *= Matrix::matrix(action)); +} + +RotationMatrix& RotationMatrix::operator*=(QList actions) +{ + foreach(const TransformationAction& action, actions) + { + *this *= Matrix::matrix(action); + } + + return *this; +} + +RotationMatrix& RotationMatrix::operator*=(KExiv2::ImageOrientation exifOrientation) +{ + return (*this *= Matrix::matrix(exifOrientation)); +} + +/** Converts the mathematically correct description + into the primitive operations that can be carried out losslessly. +*/ +QList RotationMatrix::transformations() const +{ + QList transforms; + + if (*this == Matrix::rotate90) + { + transforms << Rotate90; + } + else if (*this == Matrix::rotate180) + { + transforms << Rotate180; + } + else if (*this == Matrix::rotate270) + { + transforms << Rotate270; + } + else if (*this == Matrix::flipHorizontal) + { + transforms << FlipHorizontal; + } + else if (*this == Matrix::flipVertical) + { + transforms << FlipVertical; + } + else if (*this == Matrix::rotate90flipHorizontal) + { + //first rotate, then flip! + transforms << Rotate90; + transforms << FlipHorizontal; + } + else if (*this == Matrix::rotate90flipVertical) + { + //first rotate, then flip! + transforms << Rotate90; + transforms << FlipVertical; + } + return transforms; +} + +KExiv2::ImageOrientation RotationMatrix::exifOrientation() const +{ + if (*this == Matrix::identity) + { + return KExiv2::ORIENTATION_NORMAL; + } + if (*this == Matrix::rotate90) + { + return KExiv2::ORIENTATION_ROT_90; + } + else if (*this == Matrix::rotate180) + { + return KExiv2::ORIENTATION_ROT_180; + } + else if (*this == Matrix::rotate270) + { + return KExiv2::ORIENTATION_ROT_270; + } + else if (*this == Matrix::flipHorizontal) + { + return KExiv2::ORIENTATION_HFLIP; + } + else if (*this == Matrix::flipVertical) + { + return KExiv2::ORIENTATION_VFLIP; + } + else if (*this == Matrix::rotate90flipHorizontal) + { + return KExiv2::ORIENTATION_ROT_90_HFLIP; + } + else if (*this == Matrix::rotate90flipVertical) + { + return KExiv2::ORIENTATION_ROT_90_VFLIP; + } + return KExiv2::ORIENTATION_UNSPECIFIED; +} + +QMatrix RotationMatrix::toMatrix() const +{ + return toMatrix(exifOrientation()); +} + +QMatrix RotationMatrix::toMatrix(KExiv2::ImageOrientation orientation) +{ + QMatrix matrix; + + switch (orientation) + { + case KExiv2::ORIENTATION_NORMAL: + case KExiv2::ORIENTATION_UNSPECIFIED: + break; + + case KExiv2::ORIENTATION_HFLIP: + matrix.scale(-1, 1); + break; + + case KExiv2::ORIENTATION_ROT_180: + matrix.rotate(180); + break; + + case KExiv2::ORIENTATION_VFLIP: + matrix.scale(1, -1); + break; + + case KExiv2::ORIENTATION_ROT_90_HFLIP: + matrix.scale(-1, 1); + matrix.rotate(90); + break; + + case KExiv2::ORIENTATION_ROT_90: + matrix.rotate(90); + break; + + case KExiv2::ORIENTATION_ROT_90_VFLIP: + matrix.scale(1, -1); + matrix.rotate(90); + break; + + case KExiv2::ORIENTATION_ROT_270: + matrix.rotate(270); + break; + } + + return matrix; +} + +} // namespace KExiv2Iface diff --git a/libkexiv2/libkexiv2/rotationmatrix.h b/libkexiv2/libkexiv2/rotationmatrix.h new file mode 100644 index 00000000..ca9d9439 --- /dev/null +++ b/libkexiv2/libkexiv2/rotationmatrix.h @@ -0,0 +1,118 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-08-03 + * @brief Tools for combining rotation operations + * + * @author Copyright (C) 2006-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2004-2012 by Marcel Wiesweg + * marcel dot wiesweg at gmx dot de + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef LIBKEXIV2_ROTATIONMATRIX_H +#define LIBKEXIV2_ROTATIONMATRIX_H + +// Qt includes + +#include + +// Local includes + +#include "kexiv2.h" +#include "libkexiv2_export.h" + +namespace KExiv2Iface +{ + +class KEXIV2_EXPORT RotationMatrix +{ + +public: + + /** This describes single transform primitives. + * Note some of the defined Exif rotation flags combine + * two of these actions. + * The enum values correspond to those defined + * as JXFORM_CODE in the often used the JPEG tool transupp.h. + */ + enum TransformationAction + { + NoTransformation = 0, /// no transformation + FlipHorizontal = 1, /// horizontal flip + FlipVertical = 2, /// vertical flip + Rotate90 = 5, /// 90-degree clockwise rotation + Rotate180 = 6, /// 180-degree rotation + Rotate270 = 7 /// 270-degree clockwise (or 90 ccw) + }; + + /// Constructs the identity matrix (the matrix describing no transformation) + RotationMatrix(); + /// Returns the matrix corresponding to the given TransformationAction + RotationMatrix(TransformationAction action); + /// Returns the matrix corresponding to the given TransformationAction + RotationMatrix(KExiv2::ImageOrientation exifOrientation); + + bool operator==(const RotationMatrix& ma) const; + bool operator!=(const RotationMatrix& ma) const; + + /// Returns true of this matrix describes no transformation (is the identity matrix) + bool isNoTransform() const; + + RotationMatrix& operator*=(const RotationMatrix& ma); + + /// Applies the given transform to this matrix + RotationMatrix& operator*=(TransformationAction action); + + /// Applies the given transform actions to this matrix + RotationMatrix& operator*=(QList actions); + + /// Applies the given Exif orientation flag to this matrix + RotationMatrix& operator*=(KExiv2::ImageOrientation exifOrientation); + + /** Returns the actions described by this matrix. The order matters. + * Not all possible matrices are supported, but all those that can be combined + * by Exif rotation flags and the transform actions above. + * If isNoTransform() or the matrix is not supported returns an empty list. */ + QList transformations() const; + + /** Returns the Exif orienation flag describing this matrix. + * Returns ORIENTATION_UNSPECIFIED if no flag matches this matrix. + */ + KExiv2::ImageOrientation exifOrientation() const; + + /// Returns a QMatrix representing this matrix + QMatrix toMatrix() const; + + /// Returns a QMatrix for the given Exif orientation + static QMatrix toMatrix(KExiv2::ImageOrientation orientation); + + RotationMatrix(int m11, int m12, int m21, int m22); + +protected: + + void set(int m11, int m12, int m21, int m22); + +protected: + + int m[2][2]; +}; + +} // namespace KExiv2Iface + +#endif // LIBKEXIV2_ROTATIONMATRIX_H diff --git a/libkexiv2/libkexiv2/subjectwidget.cpp b/libkexiv2/libkexiv2/subjectwidget.cpp new file mode 100644 index 00000000..70ad5618 --- /dev/null +++ b/libkexiv2/libkexiv2/subjectwidget.cpp @@ -0,0 +1,601 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-10-15 + * @brief IPTC subjects editor. + * + * @author Copyright (C) 2006-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2009-2012 by Andi Clemens + * andi dot clemens at googlemail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#include "moc_subjectwidget.cpp" + +// Qt includes + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// KDE includes + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace KExiv2Iface +{ + +class SubjectWidget::Private +{ +public: + + enum EditionMode + { + STANDARD = 0, + CUSTOM + }; + + Private() + { + addSubjectButton = 0; + delSubjectButton = 0; + repSubjectButton = 0; + subjectsBox = 0; + iprLabel = 0; + refLabel = 0; + nameLabel = 0; + matterLabel = 0; + detailLabel = 0; + btnGroup = 0; + stdBtn = 0; + customBtn = 0; + refCB = 0; + optionsBox = 0; + } + + typedef QMap SubjectCodesMap; + + SubjectCodesMap subMap; + + QStringList subjectsList; + + QWidget* optionsBox; + + QPushButton* addSubjectButton; + QPushButton* delSubjectButton; + QPushButton* repSubjectButton; + + QLabel* iprLabel; + QLabel* refLabel; + QLabel* nameLabel; + QLabel* matterLabel; + QLabel* detailLabel; + + QButtonGroup* btnGroup; + + QRadioButton* stdBtn; + QRadioButton* customBtn; + + KComboBox* refCB; + + KListWidget* subjectsBox; +}; + +// -------------------------------------------------------------------------------- + +SubjectWidget::SubjectWidget(QWidget* parent) + : QWidget(parent), d(new Private) +{ + // Load subject codes provided by IPTC/NAA as xml file. + // See http://iptc.cms.apa.at/std/topicset/topicset.iptc-subjectcode.xml for details. + + KGlobal::dirs()->addResourceDir("iptcschema", KStandardDirs::installPath("data") + + QString("libkexiv2/data")); + QString path = KGlobal::dirs()->findResource("iptcschema", "topicset.iptc-subjectcode.xml"); + + if (!loadSubjectCodesFromXML(KUrl(path))) + kDebug() << "Cannot load IPTC/NAA subject codes XML database"; + + // -------------------------------------------------------- + + // Subject Reference Number only accept digit. + QRegExp refDigitRx("^[0-9]{8}$"); + QValidator *refValidator = new QRegExpValidator(refDigitRx, this); + + // -------------------------------------------------------- + + m_subjectsCheck = new QCheckBox(i18n("Use structured definition of the subject matter:"), this); + d->optionsBox = new QWidget; + d->btnGroup = new QButtonGroup(this); + d->stdBtn = new QRadioButton; + d->customBtn = new QRadioButton; + d->refCB = new KComboBox; + QLabel* codeLink = new QLabel(i18n("Use standard " + "" + "reference code")); + codeLink->setOpenExternalLinks(true); + codeLink->setWordWrap(false); + + // By default, check box is not visible. (digiKam do not use it, kipi-plugins yes). + m_subjectsCheck->setVisible(false); + + QLabel* customLabel = new QLabel(i18n("Use custom definition")); + + d->btnGroup->addButton(d->stdBtn, Private::STANDARD); + d->btnGroup->addButton(d->customBtn, Private::CUSTOM); + d->btnGroup->setExclusive(true); + d->stdBtn->setChecked(true); + + for (Private::SubjectCodesMap::Iterator it = d->subMap.begin(); + it != d->subMap.end(); ++it) + d->refCB->addItem(it.key()); + + // -------------------------------------------------------- + + m_iprEdit = new KLineEdit; + m_iprEdit->setClearButtonShown(true); + m_iprEdit->setMaxLength(32); + + // -------------------------------------------------------- + + m_refEdit = new KLineEdit; + m_refEdit->setClearButtonShown(true); + m_refEdit->setValidator(refValidator); + m_refEdit->setMaxLength(8); + + // -------------------------------------------------------- + + m_nameEdit = new KLineEdit; + m_nameEdit->setClearButtonShown(true); + m_nameEdit->setMaxLength(64); + + // -------------------------------------------------------- + + m_matterEdit = new KLineEdit; + m_matterEdit->setClearButtonShown(true); + m_matterEdit->setMaxLength(64); + + // -------------------------------------------------------- + + m_detailEdit = new KLineEdit; + m_detailEdit->setClearButtonShown(true); + m_detailEdit->setMaxLength(64); + + // -------------------------------------------------------- + + d->iprLabel = new QLabel(i18nc("Information Provider Reference: " + "A name, registered with the IPTC/NAA, " + "identifying the provider that guarantees " + "the uniqueness of the UNO", "I.P.R:")); + d->refLabel = new QLabel(i18n("Reference:")); + d->nameLabel = new QLabel(i18n("Name:")); + d->matterLabel = new QLabel(i18n("Matter:")); + d->detailLabel = new QLabel(i18n("Detail:")); + + // -------------------------------------------------------- + + d->subjectsBox = new KListWidget; + d->subjectsBox->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + + d->addSubjectButton = new QPushButton(i18n("&Add")); + d->delSubjectButton = new QPushButton(i18n("&Delete")); + d->repSubjectButton = new QPushButton(i18n("&Replace")); + d->addSubjectButton->setIcon(SmallIcon("list-add")); + d->delSubjectButton->setIcon(SmallIcon("edit-delete")); + d->repSubjectButton->setIcon(SmallIcon("view-refresh")); + d->delSubjectButton->setEnabled(false); + d->repSubjectButton->setEnabled(false); + + // -------------------------------------------------------- + + m_note = new QLabel; + m_note->setMaximumWidth(150); + m_note->setOpenExternalLinks(true); + m_note->setWordWrap(true); + m_note->setFrameStyle(QFrame::StyledPanel | QFrame::Raised); + + // -------------------------------------------------------- + + QGridLayout* optionsBoxLayout = new QGridLayout; + optionsBoxLayout->addWidget(d->stdBtn, 0, 0, 1, 1); + optionsBoxLayout->addWidget(codeLink, 0, 1, 1, 2); + optionsBoxLayout->addWidget(d->refCB, 0, 3, 1, 1); + optionsBoxLayout->addWidget(d->customBtn, 1, 0, 1, 4); + optionsBoxLayout->addWidget(customLabel, 1, 1, 1, 4); + optionsBoxLayout->addWidget(d->iprLabel, 2, 0, 1, 1); + optionsBoxLayout->addWidget(m_iprEdit, 2, 1, 1, 4); + optionsBoxLayout->addWidget(d->refLabel, 3, 0, 1, 1); + optionsBoxLayout->addWidget(m_refEdit, 3, 1, 1, 1); + optionsBoxLayout->addWidget(d->nameLabel, 4, 0, 1, 1); + optionsBoxLayout->addWidget(m_nameEdit, 4, 1, 1, 4); + optionsBoxLayout->addWidget(d->matterLabel, 5, 0, 1, 1); + optionsBoxLayout->addWidget(m_matterEdit, 5, 1, 1, 4); + optionsBoxLayout->addWidget(d->detailLabel, 6, 0, 1, 1); + optionsBoxLayout->addWidget(m_detailEdit, 6, 1, 1, 4); + optionsBoxLayout->setColumnStretch(4, 10); + optionsBoxLayout->setMargin(0); + optionsBoxLayout->setSpacing(KDialog::spacingHint()); + d->optionsBox->setLayout(optionsBoxLayout); + + // -------------------------------------------------------- + + QGridLayout* mainLayout = new QGridLayout; + mainLayout->setAlignment( Qt::AlignTop ); + mainLayout->addWidget(m_subjectsCheck, 0, 0, 1, 4); + mainLayout->addWidget(d->optionsBox, 1, 0, 1, 4); + mainLayout->addWidget(d->subjectsBox, 2, 0, 5, 3); + mainLayout->addWidget(d->addSubjectButton, 2, 3, 1, 1); + mainLayout->addWidget(d->delSubjectButton, 3, 3, 1, 1); + mainLayout->addWidget(d->repSubjectButton, 4, 3, 1, 1); + mainLayout->addWidget(m_note, 5, 3, 1, 1); + mainLayout->setRowStretch(6, 10); + mainLayout->setColumnStretch(2, 1); + mainLayout->setMargin(0); + mainLayout->setSpacing(KDialog::spacingHint()); + setLayout(mainLayout); + + // -------------------------------------------------------- + + connect(d->subjectsBox, SIGNAL(itemSelectionChanged()), + this, SLOT(slotSubjectSelectionChanged())); + + connect(d->addSubjectButton, SIGNAL(clicked()), + this, SLOT(slotAddSubject())); + + connect(d->delSubjectButton, SIGNAL(clicked()), + this, SLOT(slotDelSubject())); + + connect(d->repSubjectButton, SIGNAL(clicked()), + this, SLOT(slotRepSubject())); + + connect(d->btnGroup, SIGNAL(buttonReleased(int)), + this, SLOT(slotEditOptionChanged(int))); + + connect(d->refCB, SIGNAL(activated(int)), + this, SLOT(slotRefChanged())); + + // -------------------------------------------------------- + + connect(m_subjectsCheck, SIGNAL(toggled(bool)), + this, SLOT(slotSubjectsToggled(bool))); + + // -------------------------------------------------------- + + connect(m_subjectsCheck, SIGNAL(toggled(bool)), + this, SIGNAL(signalModified())); + + connect(d->addSubjectButton, SIGNAL(clicked()), + this, SIGNAL(signalModified())); + + connect(d->delSubjectButton, SIGNAL(clicked()), + this, SIGNAL(signalModified())); + + connect(d->repSubjectButton, SIGNAL(clicked()), + this, SIGNAL(signalModified())); + + // -------------------------------------------------------- + + slotEditOptionChanged(d->btnGroup->id(d->btnGroup->checkedButton())); +} + +SubjectWidget::~SubjectWidget() +{ + delete d; +} + +void SubjectWidget::slotSubjectsToggled(bool b) +{ + d->optionsBox->setEnabled(b); + d->subjectsBox->setEnabled(b); + d->addSubjectButton->setEnabled(b); + d->delSubjectButton->setEnabled(b); + d->repSubjectButton->setEnabled(b); + slotEditOptionChanged(d->btnGroup->id(d->btnGroup->checkedButton())); +} + +void SubjectWidget::slotEditOptionChanged(int b) +{ + if (b == Private::CUSTOM) + { + d->refCB->setEnabled(false); + m_iprEdit->setEnabled(true); + m_refEdit->setEnabled(true); + m_nameEdit->setEnabled(true); + m_matterEdit->setEnabled(true); + m_detailEdit->setEnabled(true); + } + else + { + d->refCB->setEnabled(true); + m_iprEdit->setEnabled(false); + m_refEdit->setEnabled(false); + m_nameEdit->setEnabled(false); + m_matterEdit->setEnabled(false); + m_detailEdit->setEnabled(false); + slotRefChanged(); + } +} + +void SubjectWidget::slotRefChanged() +{ + QString key = d->refCB->currentText(); + QString name, matter, detail; + + for (Private::SubjectCodesMap::Iterator it = d->subMap.begin(); + it != d->subMap.end(); ++it) + { + if (key == it.key()) + { + name = it.value().name; + matter = it.value().matter; + detail = it.value().detail; + } + } + + m_refEdit->setText(key); + m_nameEdit->setText(name); + m_matterEdit->setText(matter); + m_detailEdit->setText(detail); +} + +QString SubjectWidget::buildSubject() const +{ + QString subject = m_iprEdit->text(); + subject.append(":"); + subject.append(m_refEdit->text()); + subject.append(":"); + subject.append(m_nameEdit->text()); + subject.append(":"); + subject.append(m_matterEdit->text()); + subject.append(":"); + subject.append(m_detailEdit->text()); + return subject; +} + +void SubjectWidget::slotDelSubject() +{ + QListWidgetItem* item = d->subjectsBox->currentItem(); + if (!item) return; + d->subjectsBox->takeItem(d->subjectsBox->row(item)); + delete item; +} + +void SubjectWidget::slotRepSubject() +{ + QString newSubject = buildSubject(); + if (newSubject.isEmpty()) return; + + if (!d->subjectsBox->selectedItems().isEmpty()) + { + d->subjectsBox->selectedItems()[0]->setText(newSubject); + m_iprEdit->clear(); + m_refEdit->clear(); + m_nameEdit->clear(); + m_matterEdit->clear(); + m_detailEdit->clear(); + } +} + +void SubjectWidget::slotSubjectSelectionChanged() +{ + if (!d->subjectsBox->selectedItems().isEmpty()) + { + QString subject = d->subjectsBox->selectedItems()[0]->text(); + m_iprEdit->setText(subject.section(':', 0, 0)); + m_refEdit->setText(subject.section(':', 1, 1)); + m_nameEdit->setText(subject.section(':', 2, 2)); + m_matterEdit->setText(subject.section(':', 3, 3)); + m_detailEdit->setText(subject.section(':', 4, 4)); + d->delSubjectButton->setEnabled(true); + d->repSubjectButton->setEnabled(true); + } + else + { + d->delSubjectButton->setEnabled(false); + d->repSubjectButton->setEnabled(false); + } +} + +void SubjectWidget::slotAddSubject() +{ + QString newSubject = buildSubject(); + if (newSubject.isEmpty()) return; + + bool found = false; + for (int i = 0 ; i < d->subjectsBox->count(); i++) + { + QListWidgetItem* item = d->subjectsBox->item(i); + if (newSubject == item->text()) + { + found = true; + break; + } + } + + if (!found) + { + d->subjectsBox->insertItem(d->subjectsBox->count(), newSubject); + m_iprEdit->clear(); + m_refEdit->clear(); + m_nameEdit->clear(); + m_matterEdit->clear(); + m_detailEdit->clear(); + } +} + +bool SubjectWidget::loadSubjectCodesFromXML(const KUrl& url) +{ + QFile xmlfile(url.toLocalFile()); + + if (!xmlfile.open(QIODevice::ReadOnly)) + return false; + + QDomDocument xmlDoc("NewsML"); + if (!xmlDoc.setContent(&xmlfile)) + return false; + + QDomElement xmlDocElem = xmlDoc.documentElement(); + if (xmlDocElem.tagName()!="NewsML") + return false; + + for (QDomNode nbE1 = xmlDocElem.firstChild(); + !nbE1.isNull(); nbE1 = nbE1.nextSibling()) + { + QDomElement newsItemElement = nbE1.toElement(); + if (newsItemElement.isNull()) continue; + if (newsItemElement.tagName() != "NewsItem") continue; + + for (QDomNode nbE2 = newsItemElement.firstChild(); + !nbE2.isNull(); nbE2 = nbE2.nextSibling()) + { + QDomElement topicSetElement = nbE2.toElement(); + if (topicSetElement.isNull()) continue; + if (topicSetElement.tagName() != "TopicSet") continue; + + for (QDomNode nbE3 = topicSetElement.firstChild(); + !nbE3.isNull(); nbE3 = nbE3.nextSibling()) + { + QDomElement topicElement = nbE3.toElement(); + if (topicElement.isNull()) continue; + if (topicElement.tagName() != "Topic") continue; + + QString type, name, matter, detail, ref; + for (QDomNode nbE4 = topicElement.firstChild(); + !nbE4.isNull(); nbE4 = nbE4.nextSibling()) + { + QDomElement topicSubElement = nbE4.toElement(); + if (topicSubElement.isNull()) continue; + + if (topicSubElement.tagName() == "TopicType") + type = topicSubElement.attribute("FormalName"); + + if (topicSubElement.tagName() == "FormalName") + ref = topicSubElement.text(); + + if (topicSubElement.tagName() == "Description" && + topicSubElement.attribute("Variant") == "Name") + { + if (type == "Subject") + name = topicSubElement.text(); + else if (type == "SubjectMatter") + matter = topicSubElement.text(); + else if (type == "SubjectDetail") + detail = topicSubElement.text(); + } + } + + d->subMap.insert(ref, SubjectData(name, matter, detail)); + } + } + } + + // Set the Subject Name everywhere on the map. + + for (Private::SubjectCodesMap::Iterator it = d->subMap.begin(); + it != d->subMap.end(); ++it) + { + QString name, keyPrefix; + if (it.key().endsWith(QLatin1String("00000"))) + { + keyPrefix = it.key().left(3); + name = it.value().name; + + for (Private::SubjectCodesMap::Iterator it2 = d->subMap.begin(); + it2 != d->subMap.end(); ++it2) + { + if (it2.key().startsWith(keyPrefix) && + !it2.key().endsWith(QLatin1String("00000"))) + { + it2.value().name = name; + } + } + } + } + + // Set the Subject Matter Name everywhere on the map. + + for (Private::SubjectCodesMap::Iterator it = d->subMap.begin(); + it != d->subMap.end(); ++it) + { + QString matter, keyPrefix; + if (it.key().endsWith(QLatin1String("000"))) + { + keyPrefix = it.key().left(5); + matter = it.value().matter; + + for (Private::SubjectCodesMap::Iterator it2 = d->subMap.begin(); + it2 != d->subMap.end(); ++it2) + { + if (it2.key().startsWith(keyPrefix) && + !it2.key().endsWith(QLatin1String("000"))) + { + it2.value().matter = matter; + } + } + } + } + + return true; +} + +void SubjectWidget::setSubjectsList(const QStringList& list) +{ + d->subjectsList = list; + + blockSignals(true); + d->subjectsBox->clear(); + m_subjectsCheck->setChecked(false); + if (!d->subjectsList.isEmpty()) + { + d->subjectsBox->insertItems(0, d->subjectsList); + m_subjectsCheck->setChecked(true); + } + + blockSignals(false); + slotSubjectsToggled(m_subjectsCheck->isChecked()); +} + +QStringList SubjectWidget::subjectsList() const +{ + QStringList newSubjects; + + for (int i = 0 ; i < d->subjectsBox->count(); i++) + { + QListWidgetItem* item = d->subjectsBox->item(i); + newSubjects.append(item->text()); + } + + return newSubjects; +} + +} // namespace KExiv2Iface diff --git a/libkexiv2/libkexiv2/subjectwidget.h b/libkexiv2/libkexiv2/subjectwidget.h new file mode 100644 index 00000000..1174577b --- /dev/null +++ b/libkexiv2/libkexiv2/subjectwidget.h @@ -0,0 +1,122 @@ +/** =========================================================== + * @file + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2006-10-15 + * @brief IPTC subjects editor. + * + * @author Copyright (C) 2006-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * @author Copyright (C) 2009-2012 by Andi Clemens + * andi dot clemens at googlemail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef SUBJECTWIDGET_H +#define SUBJECTWIDGET_H + +// Qt includes + +#include +#include +#include +#include +#include +#include +#include + +// KDE includes + +#include +#include + +// Local includes + +#include "libkexiv2_export.h" + +namespace KExiv2Iface +{ + +class KEXIV2_EXPORT SubjectData +{ +public: + + SubjectData(const QString& n, const QString& m, const QString& d) + { + name = n; + matter = m; + detail = d; + } + + QString name; // English and Ascii Name of subject. + QString matter; // English and Ascii Matter Name of subject. + QString detail; // English and Ascii Detail Name of subject. +}; + +// -------------------------------------------------------------------------------- + +class KEXIV2_EXPORT SubjectWidget : public QWidget +{ + Q_OBJECT + +public: + + SubjectWidget(QWidget* parent); + ~SubjectWidget(); + + void setSubjectsList(const QStringList& list); + QStringList subjectsList() const; + +Q_SIGNALS: + + void signalModified(); + +protected Q_SLOTS: + + virtual void slotSubjectsToggled(bool); + virtual void slotRefChanged(); + virtual void slotEditOptionChanged(int); + virtual void slotSubjectSelectionChanged(); + virtual void slotAddSubject(); + virtual void slotDelSubject(); + virtual void slotRepSubject(); + +protected: + + virtual bool loadSubjectCodesFromXML(const KUrl& url); + virtual QString buildSubject() const; + +protected: + + QLabel* m_note; + + QCheckBox* m_subjectsCheck; + + KLineEdit* m_iprEdit; + KLineEdit* m_refEdit; + KLineEdit* m_nameEdit; + KLineEdit* m_matterEdit; + KLineEdit* m_detailEdit; + +private: + + class Private; + Private* const d; +}; + +} // namespace KExiv2Iface + +#endif // SUBJECTWIDGET_H diff --git a/libkexiv2/libkexiv2/topicset.iptc-subjectcode.xml b/libkexiv2/libkexiv2/topicset.iptc-subjectcode.xml new file mode 100644 index 00000000..03f9f3e5 --- /dev/null +++ b/libkexiv2/libkexiv2/topicset.iptc-subjectcode.xml @@ -0,0 +1,14066 @@ + + + + + 20080915T120000+0000 + + + + + iptc.org + 20001006 + topicset.iptc-subjectcode + 19 + urn:newsml:iptc.org:20001006:topicset.iptc-subjectcode:18 + + + + + 20001030T120000+0000 + 20080915T120000+0000 + + + + + + 01000000 + arts, culture and entertainment + Matters pertaining to the advancement and refinement of the human mind, of interests, skills, tastes and emotions + none + 1 + 1 + 0 + + + + 01001000 + archaeology + Probing the past through ruins and artefacts + none + 1 + 1 + 0 + + + + 01002000 + architecture + Designing of buildings, monuments and the spaces around them + none + 1 + 1 + 0 + + + + 01003000 + bullfighting + Classical contest pitting man against the bull + none + 1 + 1 + 0 + + + + 01004000 + festive event (including carnival) + Parades, parties, celebrations and the like not necessarily tied to a fixed occasion or date + none + 1 + 1 + 0 + + + + 01005000 + cinema + Stories related to cinema as art and entertainment + none + 1 + 1 + 0 + + + + 01005001 + film festival + Stories about national and international motion pictures festivals, selections, festival juries, nominations, awards etc. + none + 12 + 12 + 0 + + + + 01006000 + dance + The expression of emotion or message through movement + none + 1 + 1 + 0 + + + + 01007000 + fashion + The design of clothing and accessories + none + 1 + 1 + 0 + + + + 01007001 + jewelry + Accessories to clothing + none + 15 + 15 + 0 + + + + 01008000 + language + The means by which people communicate with each other + none + 1 + 1 + 0 + + + + 01009000 + library and museum + Edifices used to house collections of books, music, art, or objects from the past and present for public use and display + none + 1 + 1 + 0 + + + + 01010000 + literature + The use of pamphlets, books or other printed matter to convey ideas, stories or other messages for the public + none + 1 + 1 + 0 + + + + 01010001 + fiction + Structured stories that are usually not based on fact but are the creation of the authors imagination + none + 9 + 9 + 0 + + + + 01010002 + poetry + The art, structure, forms of poetic expression + none + 15 + 15 + 0 + + + + 01011000 + music + Expressing emotion or message through instruments or voice using different sounds, tones, harmonies and the like + none + 1 + 1 + 0 + + + + 01011001 + classical music + Music that follows classic structures of rhythm and harmony + none + 9 + 9 + 0 + + + + 01011002 + folk music + Music that developed from folk cultures, often based on story-telling + none + 9 + 9 + 0 + + + + 01011003 + jazz music + A music of diverse harmonics, often improvised + none + 9 + 9 + 0 + + + + 01011004 + popular music + The latest fad in music, generally aimed at the younger generation + none + 9 + 9 + 0 + + + + 01011005 + country music + Similar to folk but is unique to the United States and is less about story telling than about loves sought and lost + none + 9 + 9 + 0 + + + + 01011006 + rock and roll music + Popular dance music developed in the 1950s + none + 9 + 9 + 0 + + + + 01011007 + hip-hop + A contemporary urban music originating in the 1970s. + none + 19 + 19 + 0 + + + + 01012000 + painting + Using the mediums of oils, watercolour, pastel, pencils, chalk, crayon etc on various grounds to express emotion or message + none + 1 + 1 + 0 + + + + 01013000 + photography + Mechanical means of creating images of objects by use of light and light sensitive materials with chemicals or by digitals means + none + 1 + 1 + 0 + + + + 01014000 + radio + Stories related to radio as art and entertainment + none + 1 + 1 + 0 + + + + 01015000 + sculpture + Representation of forms in clays, stone, woods, metals or other materials + none + 1 + 1 + 0 + + + + 01015001 + plastic art + Forms of hand created art including installations + none + 15 + 15 + 0 + + + + 01016000 + television + Stories related to television as art and entertainment + none + 1 + 1 + 0 + + + + 01016001 + soap opera + Episodic TV drama or saga, normally aired during daytime + none + 17 + 17 + 0 + + + + 01017000 + theatre + Telling of a story or idea through dialogue, music and physical expression in a space or building designed for it + none + 1 + 1 + 0 + + + + 01017001 + music theatre + Opera, operetta, music revues etc + none + 15 + 15 + 0 + + + + 01018000 + monument and heritage site + Areas containing commemorative objects for historical people or events + none + 1 + 1 + 0 + + + + 01018001 + institution-DEPRECATED + Either an established law, practice or system or an organization having a social, religious, educational or similar purpose such as hospital, school, prison + DEPRECATED in V 14 - term moved to 04018001 + 14 + 14 + 14 + + + + 01019000 + customs and tradition + A particular way of behaving, or observances that have developed over time by a group of people + none + 1 + 1 + 0 + + + + 01020000 + arts (general) + The collective expression of message or emotion through music, literature, painting, theatre or other means + none + 1 + 1 + 0 + + + + 01021000 + entertainment (general) + The collective use of television, radio, theatre, music and the like for the amusement of people + none + 1 + 1 + 0 + + + + 01021001 + entertainment award + Awards for achievement in the entertainment industry, such as the Oscars for film, the Booker Prize for Literature, the Grammys for music, or induction into halls of fame. + none + 17 + 17 + 0 + + + + 01022000 + culture (general) + The ideas, customs, arts, skills of a particular group + none + 1 + 1 + 0 + + + + 01022001 + cultural development + The history of the development of art and culture such as the rise of cave paintings, pre-Colombian art, Chinese paper-making, anything non-political + none + 12 + 12 + 0 + + + + 01023000 + nightclub + A commercial establishment providing music, or other entertainment along with food and drink to selected clientele + none + 1 + 1 + 0 + + + + 01024000 + cartoon + Still images such as editorial cartoons and comic strips + none + 1 + 1 + 0 + + + + 01025000 + animation + Animation, including full-length and short cinema, artists and merchandising of goods featuring animation characters. + none + 1 + 1 + 0 + + + + 01026000 + mass media + Television, radio, magazines, newspapers etc + none + 9 + 9 + 0 + + + + 01026001 + periodicals + Written material that is usually published weekly, bi-weekly, monthly or annually for a long time + none + 9 + 9 + 0 + + + + 01026002 + news media + Television, wire services, radio that collect facts about incidents, developing and presenting them to audiences as a whole story + none + 9 + 9 + 0 + + + + 01026003 + newspapers + Daily or weekly publications that present the day to day history of the world, as well as features, comics etc + none + 9 + 9 + 0 + + + + 01026004 + reviews + A critical look at someone else's work, whether film, theatre or writing + none + 9 + 9 + 0 + + + + 01027000 + internet + Stories related to Internet as art and entertainment + none + 11 + 11 + 0 + + + + 01028000 + history + Issues connected with the past; discoveries, repair, conservation or display of artifacts; anniversaries of historic events + none + 17 + 17 + 0 + + + + 02000000 + crime, law and justice + Establishment and/or statement of the rules of behaviour in society, the enforcement of these rules, breaches of the rules and the punishment of offenders. Organizations and bodies involved in these activities. + none + 1 + 1 + 0 + + + + 02001000 + crime + Violation of established laws by individuals, companies or organizations + none + 1 + 1 + 0 + + + + 02001001 + homicide + Killing of one person by another + none + 9 + 9 + 0 + + + + 02001002 + computer crime + Theft or destructive behaviour using a computer + none + 9 + 9 + 0 + + + + 02001003 + theft + Unlawful taking + none + 9 + 9 + 0 + + + + 02001004 + drug trafficking + Dealing in illicit often harmful substances + none + 9 + 9 + 0 + + + + 02001005 + sexual assault + Sexual battery of one sex against another + none + 12 + 12 + 0 + + + + 02001006 + assault (general) + Battery, slugfests, brawls and threatening behaviour + none + 15 + 15 + 0 + + + + 02001007 + kidnapping + To seize and detain or carry away a person against that person's will by unlawful threat, force or fraud + none + 15 + 15 + 0 + + + + 02001008 + arson + Intentional setting of fires with criminal intent + none + 15 + 15 + 0 + + + + 02001009 + gang activity + Criminal activities by groups of individuals, usually in urban areas, who are allied by common territories, languages, ethnic backgrounds but generally are loosely organized. + none + 15 + 15 + 0 + + + + 02001010 + terrorism + Violence against people to create fear in order to achieve political or ideological objectives + none + 19 + 19 + 0 + + + + 02002000 + judiciary (system of justice) + The system set up to deal with crime and those who do them + none + 1 + 1 + 0 + + + + 02002001 + lawyer + Anyone legally able to represent another person or entity in a legal matter, such as a lawyer, solicitor, barrister, procurator, notary. + none + 15 + 15 + 0 + + + + 02002002 + judge + Members of the bench that sit in judgement + none + 15 + 15 + 0 + + + + 02002003 + court administration + Court clerks, bailiffs, stenographers etc. + none + 15 + 15 + 0 + + + + 02003000 + police + Agents of the legal system set up enforce the laws + none + 1 + 1 + 0 + + + + 02003001 + law enforcement + Agencies involved in attempts to prevent disobedience to established laws, or to bring to justice those that disobey those laws + none + 9 + 9 + 0 + + + + 02003002 + investigation + Process of inquiry of a possible crime up to the point of arrest + none + 12 + 12 + 0 + + + + 02003003 + arrest + Detention of a suspect of a crime + none + 12 + 12 + 0 + + + + 02004000 + punishment + The retribution handed out to those who break the laws + none + 1 + 1 + 0 + + + + 02004001 + fine + Monetary punishment + none + 15 + 15 + 0 + + + + 02004002 + execution + The carrying out of executions by a government or state, not by extralegal groups/organisations + none + 18 + 18 + 0 + + + + 02005000 + prison + Also know as jails, lockups, calaboose, etc. for keeping law breakers from society + none + 1 + 1 + 0 + + + + 02006000 + laws + The codification of rules of behaviour + none + 1 + 1 + 0 + + + + 02006001 + criminal + The criminal code system + none + 15 + 15 + 0 + + + + 02006002 + civil + The civil code system + none + 15 + 15 + 0 + + + + 02007000 + justice and rights + The equitable administration of laws and regulations + none + 1 + 1 + 0 + + + + 02007001 + civil rights + Rights of individuals under civil law + none + 9 + 9 + 0 + + + + 02008000 + trials + The process by which guilt or innocence, or right or wrong is determined and adjudged + none + 1 + 1 + 0 + + + + 02008001 + litigation + Taking disputed issues to court for settlement by judge and/or jury + none + 9 + 9 + 0 + + + + 02008002 + arbitration + Resolution of disputed issues by a neutral panel + none + 9 + 9 + 0 + + + + 02008003 + court preliminary + Pre-trial events including pleas, bail, motions, discovery, depositions. + none + 12 + 12 + 0 + + + + 02009000 + prosecution + Stories regarding activities and investigations by public prosecutors. + none + 1 + 1 + 0 + + + + 02009001 + defendant + The person on trial + none + 12 + 12 + 0 + + + + 02009002 + witness + A person who testifies + none + 12 + 12 + 0 + + + + 02010000 + organized crime + Crimes committed by gangs or criminal groups. + none + 1 + 1 + 0 + + + + 02011000 + international law + The system of laws embraced by all nations, such as the Geneva Convention, the International Law of the Seas, etc. + none + 1 + 1 + 0 + + + + 02011001 + international court or tribunal + The activities of international tribunals such as European court for human rights, Hague tribunal, International Court of Justice etc + none + 11 + 11 + 0 + + + + 02011002 + extradition + Legal transfer of criminals or suspects between countries + none + 15 + 15 + 0 + + + + 02012000 + corporate crime + Misdeeds of corporations and corporate officers + none + 1 + 1 + 0 + + + + 02012001 + fraud + Intentional deception that causes others to give up rights or property + none + 1 + 1 + 0 + + + + 02012002 + embezzlement + The intentional theft of money left in one's care + none + 1 + 1 + 0 + + + + 02012003 + restraint of trade + Interference in free competition in business and trade + none + 1 + 1 + 0 + + + + 02012004 + breach of contract + Rupture of legal agreements between companies, and with customers + none + 1 + 1 + 0 + + + + 02012005 + anti-trust crime + Violations of laws against monopolies + none + 1 + 1 + 0 + + + + 02012006 + corruption + General business misbehaviour + none + 15 + 15 + 0 + + + + 02012007 + bribery + Payments or benefits to influence the outcome of a legal case + none + 15 + 15 + 0 + + + + 02013000 + war crime + Crimes committed during a war or armed conflict, usually against civilians or POW's, including the prosecution of such crimes + none + 11 + 11 + 0 + + + + 02014000 + inquest + Formal investigation of sudden or unexpected death and the hearing to decide cause of death. + none + 17 + 17 + 0 + + + + 02015000 + inquiry + Formal hearing involving a disaster, political event etc. Eg rail crash, drug prescription scandal. + none + 17 + 17 + 0 + + + + 02016000 + tribunal + Formal hearing usually involving employment issues, property etc. + none + 17 + 17 + 0 + + + + 03000000 + disaster and accident + Man made and natural events resulting in loss of life or injury to living creatures and/or damage to inanimate objects or property. + none + 1 + 1 + 0 + + + + 03001000 + drought + A severe lack of water over a period of time + none + 1 + 1 + 0 + + + + 03002000 + earthquake + The shifting of the tectonic plates of the Earth, creating in some cases damage to structures + none + 1 + 1 + 0 + + + + 03003000 + famine + Severe lack of food for a large population + none + 1 + 1 + 0 + + + + 03004000 + fire + Ignition and consumption of materials through a combination of high heat and oxygen + none + 1 + 1 + 0 + + + + 03005000 + flood + Surfeit of water, caused by heavy rains or melting snow, usually in places where it's not wanted + none + 1 + 1 + 0 + + + + 03006000 + industrial accident + A mishap in a factory, a shop or an office, potentially harmful to humans + none + 1 + 1 + 0 + + + + 03006001 + structural failures + When a building, bridge or other structures collapse because of unexpected forces or poor design + none + 9 + 9 + 0 + + + + 03007000 + meteorological disaster + A weather-related disaster + none + 1 + 1 + 0 + + + + 03007001 + windstorms + A storm of high velocity but non-hurricane force movements of air with little or no rain or hail. Often highly destructive + none + 9 + 9 + 0 + + + + 03008000 + nuclear accident + A mishap involving radioactive materials + none + 1 + 1 + 0 + + + + 03009000 + pollution + Emissions of unwanted materials in areas where it can be harmful + none + 1 + 1 + 0 + + + + 03010000 + transport accident + An accident involving one or more vehicles + none + 1 + 1 + 0 + + + + 03010001 + road accident + Accidents on roads. + none + 1 + 1 + 0 + + + + 03010002 + railway accident + Accidents involving trains. + none + 1 + 1 + 0 + + + + 03010003 + air and space accident + Accidents involving craft in air or space. + none + 1 + 1 + 0 + + + + 03010004 + maritime accident + Accidents involving marine vessels. + none + 1 + 1 + 0 + + + + 03011000 + volcanic eruption + A rupture in the skin of the Earth allowing molten material to escape to the surface + none + 1 + 1 + 0 + + + + 03012000 + relief and aid organisation + Organizations set up to provide help to those in need because of lack of food, water or shelter + none + 1 + 1 + 0 + + + + 03013000 + accident (general) + Any unplanned event that causes unwanted consequences + none + 1 + 1 + 0 + + + + 03014000 + emergency incident + A sudden, unexpected event that requires immediate action + none + 1 + 1 + 0 + + + + 03014001 + explosion + Sudden eruptions, usually of chemical substances + none + 15 + 15 + 0 + + + + 03015000 + disaster (general) + Serious or sudden misfortune + none + 1 + 1 + 0 + + + + 03015001 + natural disasters + Destructive incidents caused by the very nature of nature -- hurricanes, earthquakes, floods etc + none + 9 + 9 + 0 + + + + 03015002 + avalanche/landslide + Sudden dislodging of massive amounts of snow or soil. + none + 15 + 15 + 0 + + + + 03016000 + emergency planning + Planning for actions to deal with sudden, unplanned events + none + 1 + 1 + 0 + + + + 03017000 + rescue + An operation to save people, animals or property from harm or danger. + none + 17 + 17 + 0 + + + + 04000000 + economy, business and finance + All matters concerning the planning, production and exchange of wealth. + none + 1 + 1 + 0 + + + + 04001000 + agriculture + The process of producing natural materials for consumption + none + 1 + 1 + 0 + + + + 04001001 + arable farming + Production of food in the ground + none + 1 + 1 + 0 + + + + 04001002 + fishing industry + Raising or gathering of fish + none + 1 + 1 + 0 + + + + 04001003 + forestry and timber + Production and collection and preparation of wood products for future use + none + 1 + 1 + 0 + + + + 04001004 + livestock farming + Raising of animals for food + none + 1 + 1 + 0 + + + + 04001005 + viniculture + Production of wines from the vines to the finish products + none + 1 + 1 + 0 + + + + 04001006 + aquaculture + Growing plants or animals in water for human consumption + none + 15 + 15 + 0 + + + + 04002000 + chemicals + Natural or manmade materials used to produce other materials + none + 1 + 1 + 0 + + + + 04002001 + biotechnology + The business of using engineering technology to study and solved problems of living organisms + none + 1 + 1 + 0 + + + + 04002002 + fertiliser + Natural or manmade materials used to encourage the growth of plants + none + 1 + 1 + 0 + + + + 04002003 + health and beauty product + Compilation of chemicals and other substances for use in enhancing ones looks or smell + none + 1 + 1 + 0 + + + + 04002004 + inorganic chemical + The branch of chemistry dealing with minerals and metals + none + 1 + 1 + 0 + + + + 04002005 + organic chemical + The branch of chemistry dealing with human, animal or carbon-based substances + none + 1 + 1 + 0 + + + + 04002006 + pharmaceutical + The production of medicines from various chemicals and natural substances + none + 1 + 1 + 0 + + + + 04002007 + synthetic and plastic + Chemicals used to produce plastics and other artificial substances to be used in manufacturing + none + 1 + 1 + 0 + + + + 04003000 + computing and information technology + Anything to do with the computing and/or transmission of information from one point to another. + none + 1 + 1 + 0 + + + + 04003001 + hardware + The physical devices used to provide computer services, such as monitors, hard drives, keyboards etc. but can also be used for equipment such as routers, servers and other network devices. + none + 1 + 1 + 0 + + + + 04003002 + networking + The interconnectivity between hardware that provides the medium for the transmission of data. + none + 1 + 1 + 0 + + + + 04003003 + satellite technology + Hardware and software that enables groundbased devices to send signals to each other via an orbiting satellite. + none + 1 + 1 + 0 + + + + 04003004 + semiconductors and active components + The basic components that together create working electronic devices such as computers + none + 1 + 1 + 0 + + + + 04003005 + software + Programming sets that, when installed on hardware, perform specified functions. + none + 1 + 1 + 0 + + + + 04003006 + telecommunication equipment + Devices such as telephone sets, voice/data switches, modems etc that facilitate point-to-point voice/data transmissions + none + 1 + 1 + 0 + + + + 04003007 + telecommunication service + Services provided by commercial companies that facilitate connections between telephones, pagers, computers + typo fixed in Explanation + 17 + 1 + 0 + + + + 04003008 + security + To encompass technical developments in hardware and software, basic research and related areas such as cyber security + none + 1 + 1 + 0 + + + + 04003009 + wireless technology + Transmission of information through means other than point-to-point wired hookups + none + 15 + 15 + 0 + + + + 04004000 + construction and property + All items pertaining to the construction and sale of property + none + 1 + 1 + 0 + + + + 04004001 + heavy construction + Large scale construction projects, construction of roads, dams, office/factory buildings, offshore and onshore structures, large sport stadiums + Explanation changed in V 15 + 15 + 1 + 0 + + + + 04004002 + house building + Construction of residences, for private use + none + 1 + 1 + 0 + + + + 04004003 + real estate + The buying and selling of properties of all types + none + 1 + 1 + 0 + + + + 04004004 + farms + Agricultural areas for the production of foodstuffs, including dairy products, fruits and livestock, such as cattle and fish + none + 9 + 9 + 0 + + + + 04004005 + land price + The price of land in specific zoned areas such as commercial, residential arable as provided by a responsible body + In Japan, government publishes lists of standard land prices every year as an economic barometer and Newspapers take up with a lot of space. + 12 + 12 + 0 + + + + 04004006 + renovation + Restoring properties/structures to a former better state by cleaning, repairing or rebuilding. + none + 15 + 15 + 0 + + + + 04004007 + design and engineering + Design and planning by Engineers, Architects etc. of roads, offices, factories, dams , offshore structures, + none + 15 + 15 + 0 + + + + 04005000 + energy and resource + Production of electrical power, and the water, air, sunlight, and fuels used to produce them + none + 1 + 1 + 0 + + + + 04005001 + alternative energy + Stories about the alternative energy business + none + 1 + 1 + 0 + + + + 04005002 + coal + Production and mining of anthracite and bituminous products for use in power production + none + 1 + 1 + 0 + + + + 04005003 + oil and gas - downstream activities + All matters concerning oil and gas, typically refining and distribution activities + none + 1 + 1 + 0 + + + + 04005004 + oil and gas - upstream activities + All matters concerning oil and gas, typically supply chain activities from the reservoir to the refinery gate + none + 1 + 1 + 0 + + + + 04005005 + nuclear power + Use of radioactive materials for power production + none + 1 + 1 + 0 + + + + 04005006 + electricity production and distribution + Primarily concerning the power line distribution system, but also the sale of electrical power at wholesale and retail levels + none + 1 + 1 + 0 + + + + 04005007 + waste management and pollution control + Stories about the business of waste management and pollution control + none + 1 + 1 + 0 + + + + 04005008 + water supply + Stories about the business of providing water for human use + none + 1 + 1 + 0 + + + + 04005009 + natural resources (general) + Articles about the general use of natural resources for business purposes, not focused on specific resources such as coal, oil, gas or water + none + 1 + 1 + 0 + + + + 04005010 + energy (general) + Articles about the energy industry, not focused on any specific sector + none + 1 + 1 + 0 + + + + 04005011 + natural gas + A natural resource, mainly methane in an flammable gaseous state, from the ground + none + 12 + 12 + 0 + + + + 04005012 + petrol + Distilled petroleum product used for automotive fuel, with or without additives + none + 12 + 12 + 0 + + + + 04005013 + diesel fuel + A distilled petroleum product heavier than gasoline used not only for trucks, marine engines, but in certain forms for home heating + none + 12 + 12 + 0 + + + + 04005014 + kerosene/paraffin + A light petroleum distillate used for cooking fuel, aircraft jet engines, lamps, heating and cleaning + none + 12 + 12 + 0 + + + + 04006000 + financial and business service + Services that transmit, safeguard, keep track of money or provide backup to commercial enterprises + none + 1 + 1 + 0 + + + + 04006001 + accountancy and auditing + Services provide balance sheet, budgets reconciliation and examine accuracy of financial statements + none + 1 + 1 + 0 + + + + 04006002 + banking + Services for storing, transmitting, receiving and delivery of cash moneys + none + 1 + 1 + 0 + + + + 04006003 + consultancy service + Providers of expert knowledge in a wide range of fields usually on a temporary, contract basis + none + 1 + 1 + 0 + + + + 04006004 + employment agency + A service helping people find jobs, and companies to find workers + none + 1 + 1 + 0 + + + + 04006005 + healthcare provider + Providers of medical services at all levels, including doctors, hospitals etc + none + 1 + 1 + 0 + + + + 04006006 + insurance + A risk taking venture that allows individuals to pay small amounts periodically to guard financially against unexpected events + none + 1 + 1 + 0 + + + + 04006007 + legal service + Lawyers and others who help companies and individuals deal with state, federal and local laws + none + 1 + 1 + 0 + + + + 04006008 + market research + A service that tries to determine what people want to buy + none + 1 + 1 + 0 + + + + 04006009 + stock broking + The buying and selling of company shares on behalf of individuals or other entities + none + 1 + 1 + 0 + + + + 04006010 + personal investing + Personal finance and investment + none + 1 + 1 + 0 + + + + 04006011 + market trend + Statistically significant consumer behaviour. + none + 1 + 1 + 0 + + + + 04006012 + shipping service + Companies that prepare and transport packages and documents for individuals or companies by any means, including postal services. + none + 1 + 1 + 0 + + + + 04006013 + personal service + Consumer service that is intangible e.g. beauty care as in hairdressing + none + 1 + 1 + 0 + + + + 04006014 + janitorial service + Companies that provide cleaning and similar services for homes and businesses. + none + 1 + 1 + 0 + + + + 04006015 + funeral parlour and crematorium + Companies that provide services for disposal of the dead + none + 1 + 1 + 0 + + + + 04006016 + rental service + Companies which provide rentals, including motor vehicles, tuxedos, tools, heavy equipment, and other supplies + none + 1 + 1 + 0 + + + + 04006017 + wedding service + Services and products related to the wedding industry + none + 1 + 1 + 0 + + + + 04006018 + personal finance + An individual's income and expenses + none + 9 + 9 + 0 + + + + 04006019 + personal income + Money that a person earns and is his/hers to keep or spend + none + 9 + 9 + 0 + + + + 04006020 + auction service + Sales by bidding + none + 15 + 15 + 0 + + + + 04006021 + printing/promotional service + Production of printed matter such as flyers, ads, signs etc + none + 15 + 15 + 0 + + + + 04006022 + investment service + Financial advisers, as opposed to stock dealers or consultants + none + 15 + 15 + 0 + + + + 04007000 + consumer goods + Items produced for and sold to individuals + none + 1 + 1 + 0 + + + + 04007001 + clothing + Items of apparel to wear + none + 1 + 1 + 0 + + + + 04007002 + department store + Stores largely devoted to the sale of clothing to individuals + none + 1 + 1 + 0 + + + + 04007003 + food + Fruits, vegetables, breads, meats for human consumption + none + 1 + 1 + 0 + + + + 04007004 + mail order + Items sold through and delivered by mail + none + 1 + 1 + 0 + + + + 04007005 + retail + The last stage in the sales chain + none + 1 + 1 + 0 + + + + 04007006 + speciality store + Retail outlets that specialize in categories such as shoes, coats, power tools, etc + none + 1 + 1 + 0 + + + + 04007007 + wholesale + The first link in the sales chain after production + none + 1 + 1 + 0 + + + + 04007008 + beverage + Liquid consumables, both alcoholic and non-alcoholic + none + 1 + 1 + 0 + + + + 04007009 + electronic commerce + Buying and selling items through the Internet + none + 1 + 1 + 0 + + + + 04007010 + luxury good + Leather bags, jewellery, haute couture, accessories etc + none + 1 + 1 + 0 + + + + 04007011 + non-durable good + Lighters, pens and stationery, tableware, watches, glasses etc + none + 1 + 1 + 0 + + + + 04007012 + toy + Children's plaything + none + 15 + 15 + 0 + + + + 04008000 + macro economics + Broad scale economics and the world or national level + none + 1 + 1 + 0 + + + + 04008001 + central bank + A country's major bank that sets interest rates, and provides transfer of funds between commercial banks + none + 1 + 1 + 0 + + + + 04008002 + consumer issue + Those issues, such as prices, inflation/deflation, quality of goods, at the retail sales level + none + 1 + 1 + 0 + + + + 04008003 + debt market + Market for trading debt instruments such as bonds, CDs, bankers acceptances, T bills, notes, IOUs etc + none + 1 + 1 + 0 + + + + 04008004 + economic indicator + Certain indexes, such as company inventories, the movement of prices that show whether the economy is improving or declining + none + 1 + 1 + 0 + + + + 04008005 + emerging market + Those markets that are struggling to enter the world economies and those requiring financial help from international lenders + none + 1 + 1 + 0 + + + + 04008006 + foreign exchange market + The trading of shekels, dinars, euros dollars etc around the world through regulated markets + none + 1 + 1 + 0 + + + + 04008007 + government aid + Supply of financial and other help by one government, usually to another + none + 1 + 1 + 0 + + + + 04008008 + government debt + The amount a government owes on bonds, services and for goods and services for which it has no ready cash + none + 1 + 1 + 0 + + + + 04008009 + interest rate + The amount of money one must pay to borrow money + none + 1 + 1 + 0 + + + + 04008010 + international economic institution + Entities such as UNIDO, World Bank, World Trade Organization, the Import-Expert Bank etc that deals at a world level + none + 1 + 1 + 0 + + + + 04008011 + international (foreign) trade + Trade of goods and services between nations + none + 1 + 1 + 0 + + + + 04008012 + loan market + The market where money is available to borrow, at certain rates of interest + none + 1 + 1 + 0 + + + + 04008013 + economic organization + Business, industrial and trade associations, societies and other private-sector groups. + none + 1 + 1 + 0 + + + + 04008014 + consumer confidence + Reports on consumer confidence in the economy. + none + 1 + 1 + 0 + + + + 04008015 + trade dispute + International dispute over trade barriers, cartels, dumping etc. + none + 1 + 1 + 0 + + + + 04008016 + inflation and deflation + An increase in the amount of money in circulation and thereby a rise in prices; deflation, tighter monetary policy causing lower prices + none + 9 + 9 + 0 + + + + 04008017 + prices + The monetary value of goods, services or stocks and bonds + none + 9 + 9 + 0 + + + + 04008018 + currency values + The value of one currency as measured against another + none + 9 + 9 + 0 + + + + 04008019 + budgets and budgeting + A method of balancing revenues against expenses + none + 9 + 9 + 0 + + + + 04008020 + credit and debt + Credit: the amount of money available to you, often by loan. Debt, the amount you owe. + none + 9 + 9 + 0 + + + + 04008021 + loans + An agreement by one individual or institution to temporarily disperse money to another, with an agreed rate and time for its return + none + 9 + 9 + 0 + + + + 04008022 + mortgages + The loan of money for the purpose of purchasing a property, whether land or building. Or, for homeowners to repair or maintain properties, often based on owner equity in a property + none + 9 + 9 + 0 + + + + 04008023 + financial markets + Institutions set up to trade the shares or other financial paper of companies or other organizations, can also include currency trading + none + 9 + 9 + 0 + + + + 04008024 + commodity markets + The bartering or trading of goods such as cotton, oil, coal, metals, etc + none + 9 + 9 + 0 + + + + 04008025 + investments + Speculative purchases of corporate instruments, of commodities, currencies, or parts thereof + none + 9 + 9 + 0 + + + + 04008026 + stocks + Corporate paper that gives an individual an ownership right to a part of a company's earnings + none + 9 + 9 + 0 + + + + 04008027 + bonds + Corporate or governmental paper representing the loan of money at a fixed rate and for a fixed time to that company or government + none + 9 + 9 + 0 + + + + 04008028 + mutual funds + Pools of shares or bonds for sale often grouped by investment intention, such as growth, income or security + none + 9 + 9 + 0 + + + + 04008029 + derivative securities + Financial instruments such as futures, swaps and options, used for risk management, whose characteristics and value depend upon the characteristics and value of an underlying instrument, such as a commodity, bond, equity or currency. + none + 9 + 9 + 0 + + + + 04008030 + imports + What is bought abroad and brought into a country for resale + none + 9 + 9 + 0 + + + + 04008031 + exports + What is produced or manufactured in your country and sent and sold elsewhere + none + 9 + 9 + 0 + + + + 04008032 + trade agreements + Government level agreements between countries for the sale and purchase of goods and services + none + 9 + 9 + 0 + + + + 04008033 + trade policy + Governmental decisions on tariffs, shipping, embargoes, and the types or kinds of goods and services to be imported and exported + none + 9 + 9 + 0 + + + + 04008034 + business enterprises + Organizations set up usually for profit-making purposes by creating and selling a product or service + none + 9 + 9 + 0 + + + + 04008035 + tariff + Fees placed on goods imported or exported, often punitive + none + 15 + 15 + 0 + + + + 04008036 + trade balance + The difference between the financial value of imports and exports + none + 15 + 15 + 0 + + + + 04009000 + market and exchange + Organized entities for buying and selling stocks, currencies, commodities and other goods + none + 1 + 1 + 0 + + + + 04009001 + energy + Stories related to energy trading and markets + none + 1 + 1 + 0 + + + + 04009002 + metal + Markets for trading base metals such as copper, aluminium, steel, zinc etc + none + 1 + 1 + 0 + + + + 04009003 + securities + Markets for trading types of company paper such as stocks and bonds + none + 1 + 1 + 0 + + + + 04009004 + soft commodity + Trading in commodities such as cotton, sugar, sorghum, soybeans etc. + none + 1 + 1 + 0 + + + + 04010000 + media + The various means of disseminating news and information to the public + none + 1 + 1 + 0 + + + + 04010001 + advertising + Methods of promoting goods and service to consumers through video, graphics, print text etc + none + 1 + 1 + 0 + + + + 04010002 + book + The business of producing and selling bound media, whether fiction or non-fiction + none + 1 + 1 + 0 + + + + 04010003 + cinema industry + Stories related to the business of cinema + none + 1 + 1 + 0 + + + + 04010004 + news agency + Commercial agencies for production and distribution of newsworthy events through print, broadcast, video or electronic media + none + 1 + 1 + 0 + + + + 04010005 + newspaper and magazine + The business of producing bound and unbound printed paper products for periodic distribution of news items + none + 1 + 1 + 0 + + + + 04010006 + online + The business of distributing news and information through computer networks for public consumption + none + 1 + 1 + 0 + + + + 04010007 + public relation + The job of promoting products and services through advertising campaigns and/or through person-to-person contact or through news releases + none + 1 + 1 + 0 + + + + 04010008 + radio industry + Stories related to the business of radio + none + 1 + 1 + 0 + + + + 04010009 + satellite and cable service + The business of transmitting of news, entertainment and information via satellite or cable television services + none + 1 + 1 + 0 + + + + 04010010 + television industry + Stories related to the business of television + none + 1 + 1 + 0 + + + + 04010011 + music industry + Recording, production, marketing of music + none + 12 + 12 + 0 + + + + 04011000 + manufacturing and engineering + Manufacturers of electrical, electronic and mechanical equipment but does not cover civil engineering. + Name changed, Explanation added in V 15 + 15 + 1 + 0 + + + + 04011001 + aerospace + Companies that assemble or manufacture components for airplanes and space ships. + Explanation added in V 15 + 15 + 15 + 0 + + + + 04011002 + automotive equipment + Companies that produce components for automobiles + Explanation added in V 15 + 15 + 15 + 0 + + + + 04011003 + defence equipment + Manufacturers of guns, tanks, cannons, ships etc for the military and non-military protection services + Explanation added in V 15 + 15 + 15 + 0 + + + + 04011004 + electrical appliance + Makers of large and small electrical goods for use in homes or business + Explanation added in V 15 + 15 + 15 + 0 + + + + 04011005 + heavy engineering + Manufacturers of cranes, bulldozers and the like for use in major construction projects + Explanation added in V 15 + 15 + 15 + 0 + + + + 04011006 + industrial component + Manufacturers of mechanical, electrical, electronic items needed in the manufacture of other items + Explanation added in V 15 + 15 + 15 + 0 + + + + 04011007 + instrument engineering + Manufacturers of instruments for calibration, measurement of things like speed, pressure, distance + Explanation added in V 15 + 15 + 15 + 0 + + + + 04011008 + shipbuilding + Manufacturers of ships, submarines, barges. + Explanation added in V 15 + 15 + 15 + 0 + + + + 04011009 + machine manufacturing + Manufacturers of turbines, engines, fans , pumps , motors and components for powered equipment. + Explanation added in V 15 + 15 + 15 + 0 + + + + 04012000 + metal and mineral + Production and refining of ores into metals + none + 1 + 1 + 0 + + + + 04012001 + building material + Manufacture of materials like wallboard, lumber wiring for the building industry + none + 1 + 1 + 0 + + + + 04012002 + gold and precious material + Mining, refining and sales of gold and other precious metals + none + 1 + 1 + 0 + + + + 04012003 + iron and steel + Mining, refining and sales of iron-based metals + none + 1 + 1 + 0 + + + + 04012004 + non ferrous metal + Mining, refining and sales of copper, zinc, aluminium, and other metals not based on iron + none + 1 + 1 + 0 + + + + 04012005 + mining + The industry of digging for metals, raw materials such as coal, or precious gems such as diamonds + none + 1 + 1 + 0 + + + + 04013000 + process industry + The business of turning raw materials into useable products + none + 1 + 1 + 0 + + + + 04013001 + distiller and brewer + Manufacture of alcoholic beverages + none + 1 + 1 + 0 + + + + 04013002 + food + The business of processing, distributing and selling for basic human consumption + none + 1 + 1 + 0 + + + + 04013003 + furnishings and furniture + Manufacture of furniture, wallpaper, paints and fabrics for interior decoration + none + 1 + 1 + 0 + + + + 04013004 + paper and packaging product + Production of paper material for writing, wrapping, printing, or packaging + none + 1 + 1 + 0 + + + + 04013005 + rubber product + Production of rubber based materials for gloves, protective coatings, hoses and the like + none + 1 + 1 + 0 + + + + 04013006 + soft drinks + Production of non-alcoholic drinks + none + 1 + 1 + 0 + + + + 04013007 + textile and clothing + Production of fabrics for furnishings and fixtures, and for clothing of various types + none + 1 + 1 + 0 + + + + 04013008 + tobacco + Growing, producing and sale of tobacco products + none + 1 + 1 + 0 + + + + 04014000 + tourism and leisure + Stories about the tourism and leisure industries + none + 1 + 1 + 0 + + + + 04014001 + casino and gambling + The business of providing outlets for various games of chance using cards, dice, spinning wheels to betting on animal races + none + 1 + 1 + 0 + + + + 04014002 + hotel and accommodation + The business of providing food and shelter to travellers + none + 1 + 1 + 0 + + + + 04014003 + recreational and sporting goods + Manufacture of goods for leisure activities + none + 1 + 1 + 0 + + + + 04014004 + restaurant and catering + The business of providing prepared foods for customers in groups large and small + none + 1 + 1 + 0 + + + + 04014005 + tour operator + Operators of trips either locally, as around town, or to other countries + none + 1 + 1 + 0 + + + + 04015000 + transport + The means of getting from one place to the other without walking + none + 1 + 1 + 0 + + + + 04015001 + air transport + Airplane and airport operations + none + 1 + 1 + 0 + + + + 04015002 + railway + The business of transporting people or cargo by rail + none + 1 + 1 + 0 + + + + 04015003 + road transport + The business of transport goods by trucks and highways + none + 1 + 1 + 0 + + + + 04015004 + waterway and maritime transport + Commercial movement of people or goods via boats, ships and water + none + 1 + 1 + 0 + + + + 04016000 + company information + Information about individual companies or business entities + none + 1 + 1 + 0 + + + + 04016001 + accounting and audit + Changes in choice of auditing firm. Reports on impact of changes in GAAP. + none + 1 + 1 + 0 + + + + 04016002 + annual and special corporate meeting + Announcements of upcoming meetings. Reports on meetings. + none + 1 + 1 + 0 + + + + 04016003 + annual report + Stories regarding availability or contents of annual company reports. + none + 1 + 1 + 0 + + + + 04016004 + antitrust issue + Stories regarding antitrust activities, monopoly regulation, etc. + none + 1 + 1 + 0 + + + + 04016005 + merger, acquisition and takeover + News on mergers, takeovers or acquisitions. + none + 1 + 1 + 0 + + + + 04016006 + analysts' comment + Stories containing stock analyst comments, analysis and recommendations. + none + 1 + 1 + 0 + + + + 04016007 + bankruptcy + News about actual bankruptcy filings. + none + 1 + 1 + 0 + + + + 04016008 + board of directors (appointment and change) + News regarding appointments to or changes in the board of directors for a company. + none + 1 + 1 + 0 + + + + 04016009 + buyback + News regarding stock buyback programs. This should be kept distinct from Stock Activity (see below). + none + 1 + 1 + 0 + + + + 04016010 + C.E.O. interview + Interviews with Chief Executive Officers. + none + 1 + 1 + 0 + + + + 04016011 + corporate officer + Appointments or changes in corporate officers. + none + 1 + 1 + 0 + + + + 04016012 + corporate profile + Stories that contain descriptive profiles of companies. + none + 1 + 1 + 0 + + + + 04016013 + contract + News about commercial contracts. + none + 1 + 1 + 0 + + + + 04016014 + defence contract + The award of government contracts for defence related activity. + none + 1 + 1 + 0 + + + + 04016015 + dividend announcement + Announcements regarding the disbursement of dividends. + none + 1 + 1 + 0 + + + + 04016016 + earnings forecast + Analyst prediction of company earnings. + none + 1 + 1 + 0 + + + + 04016017 + financially distressed company + News that a company is financially distressed - not yet having filed for bankruptcy. + none + 1 + 1 + 0 + + + + 04016018 + earnings + Any release of earnings results. + none + 1 + 1 + 0 + + + + 04016019 + financing and stock offering + Stories regarding new offerings of equity including initial public offerings. + none + 1 + 1 + 0 + + + + 04016020 + government contract + The award of government contracts not related to defence activity + none + 1 + 1 + 0 + + + + 04016021 + global expansion + Planned or actual openings of offices in countries for the first time. + none + 1 + 1 + 0 + + + + 04016022 + insider trading + Reports on the purchase or sales of stock by corporate officers or board members. + none + 1 + 1 + 0 + + + + 04016023 + joint venture + News regarding joint ventures between companies. (Not marketing related - see Marketing.) + none + 1 + 1 + 0 + + + + 04016024 + leveraged buyout + News about leveraged buyouts. + none + 1 + 1 + 0 + + + + 04016025 + layoffs and downsizing + Planned or actual reductions in the labour force. + none + 1 + 1 + 0 + + + + 04016026 + licensing agreement + Stories about licensing agreements between companies. + none + 1 + 1 + 0 + + + + 04016027 + litigation and regulation + Stories regarding corporate law including litigation and regulations. + none + 1 + 1 + 0 + + + + 04016028 + management change + Major appointments or changes in management below the level of corporate officer. + none + 1 + 1 + 0 + + + + 04016029 + marketing + Includes news regarding joint marketing agreements between companies, adoption of new product marketing strategies, etc. + none + 1 + 1 + 0 + + + + 04016030 + new product + Announcements of new products. + none + 1 + 1 + 0 + + + + 04016031 + patent, copyright and trademark + News related to patents, copyright and trademarks. + none + 1 + 1 + 0 + + + + 04016032 + plant closing + Announcements of planned or actual plant closings. + none + 1 + 1 + 0 + + + + 04016033 + plant opening + Announcements of planned or actual plant openings. + none + 1 + 1 + 0 + + + + 04016034 + privatisation + Stories regarding the privatisation (privatisation) of state run companies. + none + 1 + 1 + 0 + + + + 04016035 + proxy filing + Filings with regulatory agencies of proxy statements for upcoming shareholder votes. + none + 1 + 1 + 0 + + + + 04016036 + rating + Corporate and sovereign debt and credit ratings (e.g. SandP or Moody's) + none + 1 + 1 + 0 + + + + 04016037 + research and development + News about research and expenditure on new product development. + none + 1 + 1 + 0 + + + + 04016038 + quarterly or semiannual financial statement + Stories regarding the availability or contents of quarterly or semi-annual corporate reports. + none + 1 + 1 + 0 + + + + 04016039 + restructuring and recapitalisation + Stories involving the sale of company units, splits of existing companies into units under a holding company, etc. + none + 1 + 1 + 0 + + + + 04016040 + spin-off + Stories regarding the creation of new companies being spun off from existing companies. + none + 1 + 1 + 0 + + + + 04016041 + stock activity + Announcements of major stock events: splits, block trades, new highs or lows, etc. + none + 1 + 1 + 0 + + + + 04016042 + industrial production + Manufacture of durable and non-durable goods + none + 9 + 9 + 0 + + + + 04016043 + productivity + The cost of labour to produce an item of value, often measured as output per hour per person + none + 9 + 9 + 0 + + + + 04016044 + inventories + Goods not sold and held by the producer, wholesaler or retailer + none + 9 + 9 + 0 + + + + 04016045 + sales + Either the exchange of goods for money, or the practice of discounting prices to increase the amount of goods sold, or to get rid of outdated merchandise + none + 9 + 9 + 0 + + + + 04016046 + corporations + Business enterprises formally licensed with boards of directors and hierarchical structures of governance + none + 9 + 9 + 0 + + + + 04016047 + shareholders + Anyone holding a piece of paper issued by a company which changes in value and entitles them to dividends depending on the performance of the company + none + 9 + 9 + 0 + + + + 04016048 + corporate performance + How well a company performs, measured by its net earnings, its dividends its earnings per share and price/earnings ratio + none + 9 + 9 + 0 + + + + 04016049 + losses + When expenses exceed revenue + none + 9 + 9 + 0 + + + + 04016050 + credit ratings + Formal statements by certain rating agencies such as Standard and Poor's on the investment risk of a company, a country or enterprise + none + 9 + 9 + 0 + + + + 04016051 + stock splits + Issuing multiple shares for one share of stock. Usually occurs when the price of a stock has increased so much that its purchase price is not attractive. A reverse split is when one share is issued for multiple shares, to raise the per share value. + none + 9 + 9 + 0 + + + + 04016052 + stock options + An agreement to either buy or sell a stock when it meets a certain price + none + 9 + 9 + 0 + + + + 04016053 + recalls (products) + A decision by a company to take back or repair a defective product + none + 9 + 9 + 0 + + + + 04016054 + globalization + Doing business around the world + none + 9 + 9 + 0 + + + + 04016055 + consumers + Buyers of goods and services + none + 9 + 9 + 0 + + + + 04016056 + purchase + Items that companies buy, such as raw materials, office supplies etc. + none + 15 + 15 + 0 + + + + 04016057 + new service + New services added by a company, such as new flight routes, etc. + none + 15 + 15 + 0 + + + + 04017000 + economy (general) + Content of a general nature about trade and the economy + none + 1 + 1 + 0 + + + + 04017001 + economic policy + Government directed policy on production, taxes, tariffs and things that affect the direction and health of the economy + none + 9 + 9 + 0 + + + + 04018000 + business (general) + Content of a general nature about business + none + 1 + 1 + 0 + + + + 04018001 + institution + Either an established law, practice or system or an organization having a social, religious, educational or similar purpose such as hospital, school, prison + was 01018001 + 14 + 14 + 0 + + + + 04019000 + finance (general) + Content of a general nature about finance + none + 1 + 1 + 0 + + + + 04019001 + money and monetary policy + Government bank directed policy on the amount of money in circulation and the rate at which it can be loaned + none + 9 + 9 + 0 + + + + 05000000 + education + All aspects of furthering knowledge of human individuals from birth to death. + none + 1 + 1 + 0 + + + + 05001000 + adult education + Education provided for older students outside the usual age groups of 5-25 + none + 1 + 1 + 0 + + + + 05002000 + further education + Any form of education beyond basic education of several levels + none + 1 + 1 + 0 + + + + 05003000 + parent organisation + Groups of parents set up to support schools + none + 1 + 1 + 0 + + + + 05004000 + preschool + Education for children under the national compulsory education age + none + 1 + 1 + 0 + + + + 05005000 + school + A building or institution in which education of various sorts is provided + none + 1 + 1 + 0 + + + + 05005001 + elementary schools + Schools usually of a level from kindergarten through 11 or 12 years of age + none + 9 + 9 + 0 + + + + 05005002 + middle schools + Transitional school between elementary and high school, 12 through 13 years of age + none + 9 + 9 + 0 + + + + 05005003 + high schools + Pre-college/ university level education, 14 to 17 or 18 years of age, called freshman, sophomore, junior and senior + none + 9 + 9 + 0 + + + + 05006000 + teachers union + Organization of teachers for collective bargaining and other purposes + none + 1 + 1 + 0 + + + + 05007000 + university + Institutions of higher learning capable of providing doctorate degrees + none + 1 + 1 + 0 + + + + 05008000 + upbringing + Lessons learned from parents and others as one grows up + none + 1 + 1 + 0 + + + + 05009000 + entrance examination + Exams for entering colleges, universities, junior and senior high schools, and all other higher and lower education institutes, including cram schools, which help students prepare for exams for entry to prestigious schools. + none + 1 + 1 + 0 + + + + 05010000 + teaching and learning + Either end of the education equation + none + 9 + 9 + 0 + + + + 05010001 + students + People of any age in a structured environment, not necessarily a classroom, in order to learn something + none + 9 + 9 + 0 + + + + 05010002 + teachers + People with knowledge who can impart that knowledge to others + none + 9 + 9 + 0 + + + + 05010003 + curriculum + The courses offered by a learning institution and the regulation of those courses + none + 9 + 9 + 0 + + + + 05010004 + test/examination + A measurement of student accomplishment + none + 12 + 12 + 0 + + + + 05011000 + religious education + Instruction by any faith, in that faith or about other faiths, usually, but not always, conducted in schools run by religious bodies + none + 12 + 12 + 0 + + + + 05011001 + parochial school + A school run by the Roman Catholic faith + none + 12 + 12 + 0 + + + + 05011002 + seminary + A school of any faith specifically designed to train ministers + none + 12 + 12 + 0 + + + + 05011003 + yeshiva + A school for training rabbis + none + 12 + 12 + 0 + + + + 05011004 + madrasa + A school for teaching Islam + none + 12 + 12 + 0 + + + + 06000000 + environmental issue + All aspects of protection, damage, and condition of the ecosystem of the planet earth and its surroundings. + none + 1 + 1 + 0 + + + + 06001000 + renewable energy + Stories about the environmental impact of renewable energy, including solar, wind, hydro, biomass and geothermal + none + 1 + 1 + 0 + + + + 06002000 + conservation + Stories about preservation of wilderness areas, flora and fauna, including species extinction + none + 1 + 1 + 0 + + + + 06002001 + endangered species + Those species of wildlife in danger of disappearing, largely because of changes in environment, hunting, or weather + none + 9 + 9 + 0 + + + + 06002002 + ecosystem + A system of plants, animals and bacteria interrelated in its physical/chemical environment + none + 15 + 15 + 0 + + + + 06003000 + energy saving + Conservation of electrical, and other power sources + none + 1 + 1 + 0 + + + + 06004000 + environmental politics + The debate on environmental policy + none + 1 + 1 + 0 + + + + 06005000 + environmental pollution + Corruption of air, water, land etc. by harmful substances + none + 1 + 1 + 0 + + + + 06005001 + air pollution + Solid or gaseous matter affecting the quality of air that we breathe + none + 9 + 9 + 0 + + + + 06005002 + water pollution + Solids or liquids that corrupt the quality of water that could be used for drinking or irrigation + none + 9 + 9 + 0 + + + + 06006000 + natural resources + Stories about the environmental issues related to the exploitation of natural resources for human use + none + 1 + 1 + 0 + + + + 06006001 + land resources + That portion of a nation or state that is above water and available for development either for profit or for the general good of the public + none + 9 + 9 + 0 + + + + 06006002 + parks + Areas set aside and developed for public enjoyment and recreation, including commercial development such as theme parks + none + 9 + 9 + 0 + + + + 06006003 + forests + Open areas of trees either available for public enjoyment, or for commercial purposes + none + 9 + 9 + 0 + + + + 06006004 + wetlands + Areas generally marshy and not either under water or dry land. Often related to aquifers for water quality and/or wildlife + none + 9 + 9 + 0 + + + + 06006005 + mountains + Elevated land masses formed over the ages either by erosion, volcanic eruption, or movement of massive geographical formations called plates + none + 9 + 9 + 0 + + + + 06006006 + rivers + Moving water areas bounded by land that extend from earth sources and meander through land areas to join with other water areas. In smaller forms they are creeks, rivulets, streams etc + none + 9 + 9 + 0 + + + + 06006007 + oceans + Salt water masses separating continents or other major geographical masses. smaller forms are seas or lakes or ponds + none + 9 + 9 + 0 + + + + 06006008 + wildlife + All forms of animal life that have not been domesticated + none + 9 + 9 + 0 + + + + 06006009 + energy resources + Such resources as coal, gas, wind, sunlight etc., used to generate heat, electricity and power + none + 9 + 9 + 0 + + + + 06007000 + nature + Taken as a whole the natural environment of flora and fauna + none + 1 + 1 + 0 + + + + 06007001 + invasive species + Non-native plants, animals and other organisms that tend to take over native species + none + 15 + 15 + 0 + + + + 06008000 + population + People and their growth and development within a natural setting + none + 1 + 1 + 0 + + + + 06009000 + waste + Stories about the environmental impact of waste, including recycling efforts + none + 1 + 1 + 0 + + + + 06010000 + water + Stories concerning environmental issues about bodies of water, including oceans, lakes, streams and reservoirs, as well as ice, glaciers and forms of precipitation + none + 1 + 1 + 0 + + + + 06011000 + global warming + This category includes all issues relating to global warming including temperature research, remote sensing on temperature trends, debate on global warming, ways to reduce emissions and carbon trading. + none + 1 + 1 + 0 + + + + 06012000 + hazardous materials + Materials that are harmful to humans or animals if they are exposed to them. Includes radiation, poison gases, chemicals, heavy metals, PCBs, and certain plant products + none + 9 + 9 + 0 + + + + 06013000 + environmental cleanup + Processes whereby contaminated areas are cleaned of hazardous materials so they can be inhabited again by either people or animals. + none + 9 + 9 + 0 + + + + 07000000 + health + All aspects pertaining to the physical and mental welfare of human beings. + none + 1 + 1 + 0 + + + + 07001000 + disease + Any harmful or destructive condition + none + 1 + 1 + 0 + + + + 07001001 + communicable diseases + Diseases that can be transmitted from one person or animal to another + none + 9 + 9 + 0 + + + + 07001002 + virus diseases + Diseases caused by infection within cells by viruses + none + 9 + 9 + 0 + + + + 07001003 + AIDS + Acquired Immunity Deficiency Syndrome, an incurable disease caused by the human immunodeficiency virus + none + 9 + 9 + 0 + + + + 07001004 + cancer + A serious and often fatal disease caused when normal cells mutate into tumours + none + 9 + 9 + 0 + + + + 07001005 + heart disease + A degenerative and serious disease caused by narrowing of the arteries feeding the heart + none + 9 + 9 + 0 + + + + 07001006 + alzheimer's disease + A disorder of the brain leading to dementia + none + 9 + 9 + 0 + + + + 07001007 + animal diseases + Disorders affecting animals that do not necessarily endanger humans + none + 9 + 9 + 0 + + + + 07001008 + plant diseases + Disorders affecting plants caused either by parasites or environmental factors + none + 9 + 9 + 0 + + + + 07001009 + retrovirus + A family of RNA viruses such as those causing leukaemia and AIDS + typo fixed in Explanation + 17 + 15 + 0 + + + + 07002000 + epidemic and plague + An epidemic is a rapidly spreading condition in a community and a plague is usually a deadly disease of epidemic proportions + none + 1 + 1 + 0 + + + + 07003000 + health treatment + In general treatment of diseases and other conditions to produce wellness + none + 1 + 1 + 0 + + + + 07003001 + prescription drugs + Drugs that can be purchased only with a doctor's authorization + none + 9 + 9 + 0 + + + + 07003002 + dietary supplements + Nutrients taken in addition to food to bolster health + none + 9 + 9 + 0 + + + + 07003003 + diet + Controlled food consumption + none + 15 + 15 + 0 + + + + 07003004 + medical procedure/test + Any of a variety of treatments such as stress tests, catheterization, blood tests, computerised axial tomography scan or magnetic resonance imaging + typo fixed in Explanation + 17 + 15 + 0 + + + + 07003005 + therapy + Treatment of physical, mental or medical conditions by non-surgical means + typo fixed in Explanation + 17 + 15 + 0 + + + + 07004000 + health organisations + Includes stories about specific health organizations, including professional associations, non-profits and international groups + none + 1 + 1 + 0 + + + + 07005000 + medical research + Investigation into the causes and cures of diseases + none + 1 + 1 + 0 + + + + 07006000 + medical staff + Doctors, nurses, interns and others in a medical facility + none + 1 + 1 + 0 + + + + 07006001 + primary care physician + Patient's basic health care doctor - first point of call for all health related problems + none + 17 + 17 + 0 + + + + 07006002 + health-workers union + Issues involving industry groups for doctors, nurses, health workers etc. + none + 17 + 17 + 0 + + + + 07007000 + medicine + A substance used with the expectation that it will eliminate disease or illness + none + 1 + 1 + 0 + + + + 07007001 + herbal + Treatment based on the use of herbs and other plants to cure or alleviate disease symptoms + none + 1 + 1 + 0 + + + + 07007002 + holistic + Treatment of the whole person including mental and social factors rather than just the symptoms of the disease. + none + 1 + 1 + 0 + + + + 07007003 + western + The practice of diagnosis, treatment and prevention of disease based on modern scientific research in the western hemisphere. + none + 1 + 1 + 0 + + + + 07007004 + traditional Chinese + The practice of diagnosis, treatment and prevention of disease based on traditional methods developed in the orient. + none + 1 + 1 + 0 + + + + 07008000 + preventative medicine + Substances used to prevent diseases or illnesses + none + 1 + 1 + 0 + + + + 07008001 + vaccines + Medications designed to create immunity to diseases + none + 9 + 9 + 0 + + + + 07009000 + injury + A traumatic condition of the human body caused usually by outside forces + none + 1 + 1 + 0 + + + + 07010000 + hospital and clinic + Medical facilities for the treatment of illnesses and injury + none + 1 + 1 + 0 + + + + 07011000 + government health care + Health care provided by national governments + none + 1 + 1 + 0 + + + + 07011001 + medicare + A program of the U.S. government to provide health care to senior citizens + none + 9 + 9 + 0 + + + + 07011002 + medicaid + A program of the U.S. government to provide health care to needy citizens of all ages + none + 9 + 9 + 0 + + + + 07012000 + private health care + Health care provided by privately funded or insured organizations + none + 1 + 1 + 0 + + + + 07013000 + healthcare policy + Health-related policy decisions including what different countries are doing regarding prescription drug policies, AIDS, psychiatric care, health care funding and related topics. + none + 1 + 1 + 0 + + + + 07013001 + food safety + Issues relating to food cleanliness and contamination + none + 9 + 9 + 0 + + + + 07014000 + medical specialisation + The different medical specialist areas. + none + 1 + 1 + 0 + + + + 07014001 + geriatric + Research into aging and age-related issues including age-related illnesses, medical research, trends, geriatric medicine and related topics like age discrimination and health insurance for an ageing population. + none + 1 + 1 + 0 + + + + 07014002 + pediatrics + Research and medicine specifically for the young - includes premature babies, infant care, childhood disease and treatment - also teen-related health and behaviour problems. + none + 1 + 1 + 0 + + + + 07014003 + reproduction + This would include reproductive technologies like invitro fertilization and cloning as well as related debates. Sexual development matters and sexually transmitted diseases would also fall under this category. + none + 1 + 1 + 0 + + + + 07014004 + genetics + The science and research into genetic-base disease and cures for disease. This would include proteomics (the study of what proteins are produced by which genes and what those proteins do), general genetics and stem-cell research. + none + 1 + 1 + 0 + + + + 07014005 + obstetrics/gynecology + Specialty of female reproductive organs + none + 15 + 15 + 0 + + + + 07015000 + medical service + medical support for doctors, including blood tests and other medical tests on individuals, X-rays CAT scans MRIs etc. + none + 1 + 1 + 0 + + + + 07016000 + physical fitness + The condition of a person's cardio-vascular and muscular health. + none + 9 + 9 + 0 + + + + 07017000 + illness + Non-specific maladies such as stomach aches, headaches, flat feet, lumbago + none + 12 + 12 + 0 + + + + 07017001 + mental illness + Those illnesses affecting the mind + none + 15 + 15 + 0 + + + + 07017002 + eating disorder + Anorexia, bulimia, overeating and similar illnesses + none + 15 + 15 + 0 + + + + 07017003 + obesity + A condition of body weight generally considered 20 percent above the norm for gender, age, height and bone structure + none + 15 + 15 + 0 + + + + 07018000 + medical conditions + Various stages of disease, illness or injury + none + 15 + 15 + 0 + + + + 07019000 + patient + Issues which affect population in general as attendees at hospitals or doctors' surgeries. + none + 17 + 17 + 0 + + + + 08000000 + human interest + Lighter items about individuals, groups, animals or objects. + none + 1 + 1 + 0 + + + + 08001000 + animal + Stories involving animals of all types + none + 1 + 1 + 0 + + + + 08002000 + curiosity + Stories of an unusual nature that can raise questions or amuse + none + 1 + 1 + 0 + + + + 08003000 + people + Unusual stories about people of all levels + none + 1 + 1 + 0 + + + + 08003001 + advice + Letters and answers about personal problems that are publishable + none + 1 + 1 + 0 + + + + 08003002 + celebrity + News about celebrities, i.e. Madonna has a baby, Elton John sues his accountants etc. + none + 1 + 1 + 0 + + + + 08003003 + accomplishment + Achievements by individuals or groups, such as charitable fundraising, winning a competitive contest etc + none + 15 + 15 + 0 + + + + 08003004 + human mishap + Stories arising from silly/stupid human errors e.g. like forgetting to tie one end of a bungee cord + none + 15 + 15 + 0 + + + + 08003005 + fortune-telling + The forecasting of future events or the delineation of character by methods not ordinarily considered to have a rational basis + none + 17 + 17 + 0 + + + + 08004000 + mystery + Something unexplained or unknown + none + 1 + 1 + 0 + + + + 08005000 + society + Stories of well-known people + none + 1 + 1 + 0 + + + + 08005001 + ceremony + Rituals of a non-religious nature such as dedications, wreath layings, ship launchings etc + none + 15 + 15 + 0 + + + + 08005002 + death + The human interest aspects of the demise of a person + none + 17 + 17 + 0 + + + + 08005003 + funeral + The ceremony to intern the remains of a person + none + 17 + 17 + 0 + + + + 08005004 + estate bestowal + The distribution of the estate of a person according to their will and any disagreements between the heirs + none + 17 + 17 + 0 + + + + 08005005 + memorial + Commemorative ceremony or object - plaque, statue etc - in remembrance of a person. + none + 17 + 17 + 0 + + + + 08006000 + award and prize + Decorations, awards and prizes, including those given by the government. + none + 1 + 1 + 0 + + + + 08006001 + record + Non-sport achievement by an individual or group that sets a new record, such as most books read, holding your breath longest + none + 15 + 15 + 0 + + + + 08007000 + imperial and royal matters + News on imperial and royal family members, including matters on legal systems. + none + 1 + 1 + 0 + + + + 08008000 + plant + An organism of the kind exemplified by trees, shrubs, grasses, ferns, and mosses, typically growing in a permanent site + none + 17 + 17 + 0 + + + + 09000000 + labour + Social aspects, organizations, rules and conditions affecting the employment of human effort for the generation of wealth or provision of services and the economic support of the unemployed. + none + 1 + 1 + 0 + + + + 09001000 + apprentices + People who are in the work force at a learning level, serving under a master + none + 1 + 1 + 0 + + + + 09002000 + collective contract + Usually written contracts covering a specific class of worker + none + 1 + 1 + 0 + + + + 09002001 + contract issue-wages + Element of contracts and contract discussions centring on remuneration + none + 12 + 12 + 0 + + + + 09002002 + contract issue-healthcare + Element of contracts and contract discussions centring on health care issues + none + 12 + 12 + 0 + + + + 09002003 + contract issue-work rules + Element of contracts and contract discussions centring on rules affecting issues such as lunch and other breaks, work shifts, vacation scheduling, seniority, sick leave etc. + none + 12 + 12 + 0 + + + + 09003000 + employment + Paid labour + none + 1 + 1 + 0 + + + + 09003001 + labor market + A pool of people who are working or are seeking work + none + 9 + 9 + 0 + + + + 09003002 + job layoffs + The reduction of a company's work force through dismissal because of changing economic factors + none + 9 + 9 + 0 + + + + 09003003 + child labor + Employment of children, usually under the age of 18 + none + 9 + 9 + 0 + + + + 09003004 + occupations + Generally one's trade, profession or business although professions are usually such things as lawyers and doctors, and occupations are such as clerks or truckers + none + 9 + 9 + 0 + + + + 09004000 + labour dispute + Differences of opinion about work conditions, pay, etc + none + 1 + 1 + 0 + + + + 09005000 + labour legislation + Laws governing work and labour + none + 1 + 1 + 0 + + + + 09006000 + retirement + The years after work + none + 1 + 1 + 0 + + + + 09007000 + retraining + Providing a worker training in new skills when his old skills are no longer applicable + none + 1 + 1 + 0 + + + + 09008000 + strike + A job action involving cessation of work + none + 1 + 1 + 0 + + + + 09009000 + unemployment + Lack of paid work + none + 1 + 1 + 0 + + + + 09010000 + unions + Groups established to represent bodies of workers + none + 1 + 1 + 0 + + + + 09011000 + wage and pension + Parts of a salary divided for current income and future income + none + 1 + 1 + 0 + + + + 09011001 + employee benefits + Either benefits provided to an employee by a company, such as pensions, health insurance; or monetary compensation paid by a government to the jobless usually called unemployment benefits + none + 9 + 9 + 0 + + + + 09011002 + social security + FICA. Money paid by individual and companies into a government account to be paid out when that individual reaches a certain age + none + 9 + 9 + 0 + + + + 09012000 + work relations + The give and take between management and labour + none + 1 + 1 + 0 + + + + 09013000 + health and safety at work + Rules and procedures for guaranteeing the health of workers + none + 1 + 1 + 0 + + + + 09014000 + advanced training + Additional training to enhance current skills + none + 1 + 1 + 0 + + + + 09015000 + employer + The person who employs workers and pays the salaries and other benefits to workers + none + 1 + 1 + 0 + + + + 09016000 + employee + A person who trades his time and talent for money and other benefits + none + 1 + 1 + 0 + + + + 10000000 + lifestyle and leisure + Activities undertaken for pleasure, relaxation or recreation outside paid employment, including eating and travel. + none + 1 + 1 + 0 + + + + 10001000 + game + Contests generally for ones amusement + none + 1 + 1 + 0 + + + + 10001001 + Go + A strategic, deterministic Chinese board game played by alternately placing stones on a grid + Explanation changed in V17 + 17 + 17 + 0 + + + + 10001002 + chess + A game played on a chequered board with 16 pieces to each side with specific ranges of movement depending on their identity + typo fixed in Explanation + 17 + 1 + 0 + + + + 10001003 + bridge + A card game of four players who bet on the hands of each other, developed from Russian whist + none + 1 + 1 + 0 + + + + 10001004 + shogi + A strategic board games which is native to Japan and is often called Japanese chess + none + 17 + 17 + 0 + + + + 10002000 + gaming and lottery + Gambling, often involving selection of sets of numbers one expects to come up + none + 1 + 1 + 0 + + + + 10003000 + gastronomy + The art of good eating + none + 1 + 1 + 0 + + + + 10003001 + organic foods + Food which is grown using no artificial fertilizers or chemical compounds + none + 9 + 9 + 0 + + + + 10004000 + hobby + Various types of activities for amusement, such as collecting stamps, building models, quilting, crafts + none + 1 + 1 + 0 + + + + 10004001 + DIY + DIY - do it yourself. Normally the construction, repair or maintenance of residential property by an amateur + none + 17 + 17 + 0 + + + + 10004002 + shopping + Consumer purchasing and related trends, but not the business aspects of retailing + none + 17 + 17 + 0 + + + + 10004003 + gardening + The non-commercial aspects of landscaping, growing plants, trees and other vegetation that gives pleasure to the gardener and others + none + 17 + 17 + 0 + + + + 10005000 + holiday or vacation + Stories about leisure travel to a single location and/or country over a short period of time + none + 1 + 1 + 0 + + + + 10006000 + tourism + Stories about leisure travel involving visits to a number of locations and/or countries over an extended period of time, often as part of an organized group + none + 1 + 1 + 0 + + + + 10007000 + travel and commuting + Stories about transport options, travel networks, commuting, car pooling and business travel + none + 1 + 1 + 0 + + + + 10007001 + traffic + Traffic reports and/or warnings + none + 11 + 11 + 0 + + + + 10008000 + club and association + Organizations joined by individuals because of similar interests + none + 1 + 1 + 0 + + + + 10009000 + lifestyle (house and home) + Unique culture of ones own home + none + 1 + 1 + 0 + + + + 10010000 + leisure (general) + Activities carried out in ones' spare time + none + 1 + 1 + 0 + + + + 10011000 + public holiday + A day or days set off for celebration + none + 1 + 1 + 0 + + + + 10012000 + hunting + An activity involving the use of weapons or traps for the capturing of animals + none + 1 + 1 + 0 + + + + 10013000 + fishing + An activity involving the use of baits, lures, weapons and traps for the capture of aquatic species + none + 1 + 1 + 0 + + + + 10014000 + auto trends + The evolution of the automobile + none + 9 + 9 + 0 + + + + 10015000 + adventure + Expeditions, daring feats, exploration, record-breaking, risk-associated events + none + 17 + 17 + 0 + + + + 10016000 + beauty + Issues relating to improving one's appearance and attractiveness, including reviews of beauty products + none + 17 + 17 + 0 + + + + 10017000 + consumer issue + Shopping, products for the home, relevant surveys, product recalls + none + 17 + 17 + 0 + + + + 10018000 + wedding + The marriage ceremony and the events that surround it - showers, rehearsal, parties, honeymoon, etc. + none + 17 + 17 + 0 + + + + 11000000 + politics + Local, regional, national and international exercise of power, or struggle for power, and the relationships between governing bodies and states. + none + 1 + 1 + 0 + + + + 11001000 + defence + Anything involving the defence of one's own country + none + 1 + 1 + 0 + + + + 11001001 + veterans affairs + Care and provision for those who served in the military + none + 1 + 1 + 0 + + + + 11001002 + national security + The philosophy of securing a nation and its borders, as well as the well being of its citizens + none + 9 + 9 + 0 + + + + 11001003 + security measures + Means of making a nation, a state, a building or a person secure from harm and outside interference. + none + 9 + 9 + 0 + + + + 11001004 + armed Forces + Those employed by a government to conduct war, or to enforce the security of a nation + none + 9 + 9 + 0 + + + + 11001005 + military equipment + Equipment issued to members of the armed forces + none + 9 + 9 + 0 + + + + 11001006 + firearms + Anything that uses an explosive in a directed manner to propel an object that can maim or kill + none + 9 + 9 + 0 + + + + 11001007 + biological and chemical weapons + Devices using biological agents, or chemical mixtures to disable, maim or kill an opponent + none + 9 + 9 + 0 + + + + 11001008 + missile systems + Anything that propels an inert, explosive, biological or chemical object through the air with the aim of disabling, maiming or killing an opponent. + none + 9 + 9 + 0 + + + + 11001009 + nuclear weapons + Weapons that use controlled radioactivity from the decay of certain elements to disable, maim or kill an opponent + none + 9 + 9 + 0 + + + + 11002000 + diplomacy + The use of verbal and written skills for persuading others to your point of view + none + 1 + 1 + 0 + + + + 11002001 + summit + Includes meetings of leaders, foreign and finance ministers from the Group of Eight major nations and Group of Seven industrialized nations. + none + 1 + 1 + 0 + + + + 11002002 + international relations + Non-violent relations between nations through negotiation, treaty, or personal meetings + FormalName error fixed + 17 + 16 + 0 + + + + 11002003 + peace negotiations + Negotiations intended to bring an end to a conflict + FormalName error fixed + 17 + 16 + 0 + + + + 11002004 + alliances + Coalitions of like-minded groups formed to present a stronger force against any challenges + FormalName error fixed + 17 + 16 + 0 + + + + 11003000 + election + The selection of representatives by the casting of votes + none + 1 + 1 + 0 + + + + 11003001 + political candidates + Individuals who are chosen to stand for office + none + 9 + 9 + 0 + + + + 11003002 + political campaigns + Campaigns for public office + none + 9 + 9 + 0 + + + + 11003003 + campaign finance + The money that makes campaigns for public office possible + none + 9 + 9 + 0 + + + + 11003004 + national elections + Choosing individuals for government at a national level + none + 9 + 9 + 0 + + + + 11003005 + regional elections + Choosing individuals for government at a regional level + none + 9 + 9 + 0 + + + + 11003006 + local elections + Choosing individuals for government at the basic level, whether city, village or county + none + 9 + 9 + 0 + + + + 11003007 + voting + The act of selecting an individual you would like to represent your interests in government + none + 9 + 9 + 0 + + + + 11003008 + poll + Periodic measurement of a political candidate's standing with the public + none + 12 + 12 + 0 + + + + 11003009 + european elections + Choosing individuals for a body which is at a higher level than national government, e.g. European parliament + none + 12 + 12 + 0 + + + + 11003010 + primary + Preliminary elections on a local or regional basis leading up to a regional or national election + none + 15 + 15 + 0 + + + + 11004000 + espionage and intelligence + Covert collection of information + none + 1 + 1 + 0 + + + + 11005000 + foreign aid + Help provided by one nation to another + none + 1 + 1 + 0 + + + + 11005001 + economic sanction + Punitive actions taken by one country against another including trade restrictions, embargoes etc. + none + 15 + 15 + 0 + + + + 11006000 + government + The system for ruling a country + none + 1 + 1 + 0 + + + + 11006001 + civil and public service + The paid service by civilians for the government, and the often non-paid service of individuals for the benefit of others (public service) + none + 1 + 1 + 0 + + + + 11006002 + safety of citizens + Government policies to protect the well being of its citizens + none + 1 + 1 + 0 + + + + 11006003 + think tank + Group that undertakes political research and issue position papers, recommendations etc + none + 1 + 1 + 0 + + + + 11006004 + national government + The ruling body of a nation + none + 9 + 9 + 0 + + + + 11006005 + executive (government) + That portion of a ruling body involving the overall operation of government + none + 9 + 9 + 0 + + + + 11006006 + heads of state + Symbolic or actual chief representative of a nation, such as royalty, or president or emir, for example + none + 9 + 9 + 0 + + + + 11006007 + government departments + Divisions of a government that concentrate on specific areas such as health, welfare, economy or war + none + 9 + 9 + 0 + + + + 11006008 + public officials + Individuals, usually elected, who are in public service or commonly in the public eye. + none + 9 + 9 + 0 + + + + 11006009 + ministers (government) + Heads of various government departments at one level, also known as secretaries. At another level they form a legislative body. The chief minister is either prime minister or premier. + none + 9 + 9 + 0 + + + + 11006010 + public employees + People employed by a government at all levels + none + 9 + 9 + 0 + + + + 11006011 + privatisation + The privatisation of state-owned companies or property + none + 11 + 11 + 0 + + + + 11006012 + nationalisation + State takeover of private companies or property + none + 11 + 11 + 0 + + + + 11006013 + impeachment + The process of bringing a public official before a tribunal to answer charges of wrongdoing + none + 15 + 15 + 0 + + + + 11007000 + human rights + Rights entitled to be enjoyed by all citizens universally + none + 1 + 1 + 0 + + + + 11008000 + local authority + Authorities at city, county state or borough level + none + 1 + 1 + 0 + + + + 11009000 + parliament + The collective body of elected officials representing the people + none + 1 + 1 + 0 + + + + 11009001 + upper house + Senior chamber of a legislative body + none + 15 + 15 + 0 + + + + 11009002 + lower house + The lower chamber of a legislative body + none + 15 + 15 + 0 + + + + 11010000 + parties and movements + Covers both formally recognized and informal political associations + none + 1 + 1 + 0 + + + + 11010001 + non government organizations (NGO) + Groups officially outside of government that lobby, demonstrate or campaign on a wide range of issues such as economics, environment healthcare etc. + none + 9 + 9 + 0 + + + + 11011000 + refugee + A person seeking shelter in another country because of some fear of persecution in his own country + none + 1 + 1 + 0 + + + + 11012000 + regional authority + Government bodies at levels encompassing more than one jurisdiction, e.g. the Delaware River Basin Commission + none + 1 + 1 + 0 + + + + 11013000 + state budget and tax + The national budget as promulgated by the government + none + 1 + 1 + 0 + + + + 11013001 + public finance + The money of government used for paying for public programs and services and public debt + none + 9 + 9 + 0 + + + + 11014000 + treaty and international organisation-DEPRECATED + Formal bodies to regulate activities between nation states, often on the basis of written agreements + DEPRECATED in V 16, split to SubjectMatters 11027 and 11028 + 16 + 1 + 16 + + + + 11014001 + international relations-DEPRECATED + Non-violent relations between nations through negotiation, treaty, or personal meetings + moved to SubjectMatter 11002 in V16 + 16 + 9 + 16 + + + + 11014002 + peace negotiations-DEPRECATED + Negotiations intended to bring an end to a conflict + moved to SubjectMatter 11002 in V16 + 16 + 9 + 16 + + + + 11014003 + alliances-DEPRECATED + Coalitions of like-minded groups formed to present a stronger force against any challenges + moved to SubjectMatter 11002 in V16 + 16 + 9 + 16 + + + + 11015000 + constitution + Usually a written document setting forth the operations of a government and the rights of the citizens therein + none + 1 + 1 + 0 + + + + 11016000 + interior policy + Government policies affecting internal affairs of a country + none + 1 + 1 + 0 + + + + 11016001 + data protection + Efforts to protect personal information in either written, oral or electronic form + none + 1 + 1 + 0 + + + + 11016002 + housing and urban planning + Systematic planning of urban and suburban areas and the housing within those areas + none + 1 + 1 + 0 + + + + 11016003 + pension and welfare + Government policies affecting the well being of its citizens through unemployment benefits, state pensions and other similar payments + none + 1 + 1 + 0 + + + + 11016004 + personal weapon control + Government control of personal ownership of firearms and other offensive weapons, including control of weapons used for sports through licenses and other means + none + 1 + 1 + 0 + + + + 11016005 + indigenous people + Government policies toward indigenous peoples + none + 12 + 12 + 0 + + + + 11016006 + personal data collection + The collection, by government or other entities of information on individuals + none + 15 + 15 + 0 + + + + 11016007 + planning inquiries + Public hearings or planning inquiries on proposed constructions, e.g. Construction of water driven power station in a National Park. + none + 15 + 15 + 0 + + + + 11017000 + migration + Movement of one body of persons from one place to another + none + 1 + 1 + 0 + + + + 11018000 + citizens initiative and recall + Political suggestions by non-government officials for corrective action, or for changes in existing rules and regulations + none + 1 + 1 + 0 + + + + 11019000 + referenda + Political proposals, laws and actions suggested by non-government officials to be voted on by the entire voting body + none + 1 + 1 + 0 + + + + 11020000 + nuclear policy + Government policies as regards to use of nuclear fuels for power production or weapons + none + 1 + 1 + 0 + + + + 11021000 + lobbying + The attempt by non-government bodies and individual to affect the outcome of legislation through verbal, or other, persuasion + none + 1 + 1 + 0 + + + + 11022000 + regulatory policy and organisation + The rules and bodies, both national and international, that govern conflict of interest and good practice regulations. + none + 1 + 1 + 0 + + + + 11023000 + censorship + Attempts by any group to control freedoms of speech, religion, and ideas distributed in print, graphics, cyberspace and other ways. Does not include official standards such as cinema ratings, advertising and broadcast standards. + replaced by "freedom of press" in V 12, reintroduced in V13 + 13 + 13 + 0 + + + + 11024000 + politics (general) + The art or science of participating in the affairs of government, a state of political party + none + 9 + 9 + 0 + + + + 11024001 + political systems + Systems designed to provide order to government + none + 9 + 9 + 0 + + + + 11024002 + democracy + Government in which the people hold the power either directly, or through elected officials. + none + 9 + 9 + 0 + + + + 11024003 + political development + The creation and rise of political systems and the history of the people and nations that are associated with those systems. + none + 12 + 12 + 0 + + + + 11025000 + freedom of the press + Stories about mass media rights and freedoms, pressure and intimidation of the journalists, censorship in mass media, activities of government bodies, journalistic associations and/or organizations and other NGOs in regards to press freedom + replaced "censorship" in V12, added as new Topic in V13 + 13 + 13 + 0 + + + + 11026000 + freedom of religion + Stories about religious rights and freedoms, pressure and intimidation of the believers, censorship in mass media, activities of government bodies, journalistic associations and/or organizations and other NGOs in regards to freedom of belief and practice + none + 16 + 16 + 0 + + + + 11027000 + treaty + A treaty (as defined by the Vienna Convention on the Law of Treaties) is a written agreement between international entities that is binding under international law. + none + 16 + 16 + 0 + + + + 11028000 + international organisation + Includes organisations with members and functions that cross international borders, and may include intergovernmental organisations of sovereign nations. + none + 16 + 16 + 0 + + + + 12000000 + religion and belief + All aspects of human existence involving theology, philosophy, ethics and spirituality. + none + 1 + 1 + 0 + + + + 12001000 + cult and sect + Offshoots of established religious bodies, or small narrow-focused group promulgated by one or two individuals + none + 1 + 1 + 0 + + + + 12002000 + belief (faith) + The established beliefs of an individuals religion + none + 1 + 1 + 0 + + + + 12002001 + unificationism + The belief system of members of the Unification Church established by the Rev. Sun Myung Moon. + none + 11 + 11 + 0 + + + + 12002002 + scientology + Believe that man is a spiritual being endowed with abilities well beyond those which he normally envisages; he's able to solve his own problems, accomplish his goals and gain lasting happiness. + none + 11 + 11 + 0 + + + + 12003000 + freemasonry + A secret international society based on the principles of brotherhood, charity and mutual aid + none + 1 + 1 + 0 + + + + 12004000 + religion-DEPRECATED + Established theologies with fixed systems of belief + SubjectMatter deprecated, SubjectDetails moved to other SubjectMatter + 14 + 9 + 14 + + + + 12004001 + christianity-DEPRECATED + Those that use Jesus Christ and his teachings as their centre of belief + moved to 12009000 + 14 + 9 + 14 + + + + 12004002 + islam-DEPRECATED + Those who use Allah and his teachings as their centre of belief + moved to 12010000 + 14 + 9 + 14 + + + + 12004003 + judaism-DEPRECATED + A group believing in one god, basing their beliefs on written scriptures and the Talmud, including the first coming of the Messiah + moved to 12011000 + 14 + 9 + 14 + + + + 12004004 + buddhism-DEPRECATED + A major Asian religion founded by Buddha in the 6th century in India and preaching that right thinking and self denial will lead to a divine state without desire + moved to 12012000 + 14 + 9 + 14 + + + + 12004005 + hinduism-DEPRECATED + A religious and social system, believing in a caste system with the Brahmans the highest and untouchables the lowest. + moved to 12013000 + 14 + 9 + 14 + + + + 12005000 + church (organisation)-DEPRECATED + Generally an edifice identifiable as a place of worship for the Christian religion + moved to 12000001/SubjectQualifier + 14 + 1 + 14 + + + + 12005001 + religious facilities-DEPRECATED + Any facility where a group can carry out its religious rites whether it is a mosque, a church, a house or a tent + moved to 12000002/SubjectQualifier + 14 + 9 + 14 + + + + 12006000 + values + Personal levels of social behaviour + none + 1 + 1 + 0 + + + + 12006001 + ethics + A system of beliefs about acceptable behaviour + none + 9 + 9 + 0 + + + + 12006002 + corrupt practices + Any action which is harmful to others + none + 9 + 9 + 0 + + + + 12007000 + church and state relations + The legal and social division between religious institutions and the affairs of state + none + 9 + 9 + 0 + + + + 12008000 + philosophy + Different thoughts about the way the world works + none + 9 + 9 + 0 + + + + 12009000 + christianity + Those that use Jesus Christ and his teachings as their centre of belief + moved from 12004001 + 14 + 1 + 0 + + + + 12009001 + protestant + General term for christian churches and religious communities which developed through the reformation in the 16th century + none + 14 + 14 + 0 + + + + 12009002 + lutheran + Christians who follow the teaching of reformer Martin Luther + none + 14 + 14 + 0 + + + + 12009003 + reformed + Christians who follow the teaching of reformers Johannes Calvin and Ulrich Zwingli + none + 14 + 14 + 0 + + + + 12009004 + anglican + Members of the worldwide anglican communion which started in the 16th century in England as a breakaway church from the roman catholic church + none + 14 + 14 + 0 + + + + 12009005 + methodist + Followers of John and Charles Wesley who tried to reform the Church of England in the 18th century and turned into a separate church + none + 14 + 14 + 0 + + + + 12009006 + baptist + Members of a christian church which only baptises adults who truly believe in Christ + none + 14 + 14 + 0 + + + + 12009007 + mennonite + Members of a 16th century christian church which is against military service and baptising infants + none + 14 + 14 + 0 + + + + 12009009 + mormon + Members of a religious community which believes in the "Book of Mormon" and the revelations of founder M.J. Smith + none + 14 + 14 + 0 + + + + 12009010 + roman catholic + Biggest christian church worldwide tracing its origins back to Jesus Christ + none + 14 + 14 + 0 + + + + 12009011 + old catholic + Members of a catholic church which started in 1870 and denies the dogma of the infallibility of the pope + none + 14 + 14 + 0 + + + + 12009012 + orthodoxy + Eastern rite churches which are characterised by their continuity with the apostolic church, their liturgy and their territorial churches, mainly in eastern and south-eastern Europe and the Middle East + none + 14 + 14 + 0 + + + + 12009013 + salvation army + Christian community organised in a military fashion which does missionary and social work + none + 14 + 14 + 0 + + + + 12010000 + islam + Those who use Allah and his teachings as their centre of belief + moved from 12004002 + 14 + 14 + 0 + + + + 12011000 + judaism + A group believing in one god, basing their beliefs on written scriptures and the Talmud, including the first coming of the Messiah + moved from 12004003 + 14 + 14 + 0 + + + + 12012000 + buddhism + A major Asian religion founded by Buddha in the 6th century BC in India and preaching that right thinking and self denial will lead to a divine state without desire + moved from 12004004 + 14 + 14 + 0 + + + + 12013000 + hinduism + A religious and social system, believing in a caste system with the Brahmans the highest and untouchables the lowest. + moved from 12004005 + 14 + 14 + 0 + + + + 12014000 + religious festival or holiday + Holy day or day of observance in a religion which sometimes is a public holiday as well + none + 14 + 14 + 0 + + + + 12014001 + christmas + Christian festival in commemorating the birth of Jesus Christ + none + 14 + 14 + 0 + + + + 12014002 + easter + Christian festival in commemorating the resurrection of Jesus Christ + none + 14 + 14 + 0 + + + + 12014003 + pentecost + Christian festival, celebrated on the 50th day after Easter commemorating the descent of the Holy Spirit + none + 14 + 14 + 0 + + + + 12014004 + ramadan + Holy month of fasting in Islam + none + 14 + 14 + 0 + + + + 12014005 + yom kippur + Most solemn of Jewish religious holidays, observed on the 10th day of the lunar month of tishri (in the course of September and October, when Jews seek reconciliation with god + none + 14 + 14 + 0 + + + + 12015000 + religious leader + Person or persons who have a ritual, juridical or otherwise leading role in their respective church or religion + none + 14 + 14 + 0 + + + + 12015001 + pope + Head of the roman catholic church worldwide + none + 14 + 14 + 0 + + + + 12016000 + nature religion + Worship of natural elements like fire, water, trees, mountains + none + 14 + 14 + 0 + + + + 12017000 + taoism + Indigenous religio-philosophical tradition that has shaped Chinese life for more than 2000 years + none + 14 + 14 + 0 + + + + 12018000 + shintoism + Indigenous religious beliefs and practices of Japan. The word Shinto came into use in order to distinguish indigenous Japanese beliefs from Buddhism. + none + 14 + 14 + 0 + + + + 12019000 + sikhism + The religion of an Indian group, combining Hindu and Islamic elements, founded in the Punjab (or Panjab) in the late 15th century AD by Guru Nanak. + none + 14 + 14 + 0 + + + + 12020000 + jainism + A religion of India that teaches a path to spiritual purity and enlightenment through a disciplined mode of life founded upon the tradition of ahimsa, non-violence to all living creatures. It began in the 7th-5th century BC. + none + 14 + 14 + 0 + + + + 12021000 + parsasm + A religion in India following the Iranian prophet Zoroaster, mainly in Bombay, but also in Karachi (Pakistan). + none + 14 + 14 + 0 + + + + 12022000 + confucianism + The way of life propagated by Confucius in the 6th-5th century BC and followed by the Chinese people for more than 2000 years. Its influence has extended to Korea, Japan, and Vietnam. + none + 14 + 14 + 0 + + + + 12023000 + religious text + Scriptures holy or important for a church or religion + none + 14 + 14 + 0 + + + + 12023001 + bible + Sacred scriptures of Christianity consisting of the old and new testament + none + 14 + 14 + 0 + + + + 12023002 + qur'an + Holy book of Islam + none + 14 + 14 + 0 + + + + 12023003 + torah + Holy scriptures of Judaism + none + 14 + 14 + 0 + + + + 12024000 + interreligious dialogue + Any form of communication between religions + none + 14 + 14 + 0 + + + + 12025000 + religious event + News regarding a religious event but not a festival or holiday + none + 14 + 14 + 0 + + + + 12025001 + catholic convention + Reports concerning or from a catholic convention + none + 14 + 14 + 0 + + + + 12025002 + protestant convention + Reports concerning or from a protestant convention + none + 14 + 14 + 0 + + + + 12025004 + ritual + Established religious rituals such as mass, baptism, prayer meetings + none + 15 + 15 + 0 + + + + 12026000 + concordat + Treaty between the Holy See and another country for the regulation of ecclesiastical affairs in the territory of the latter + none + 14 + 14 + 0 + + + + 12027000 + ecumenism + Relations between christian churches + none + 14 + 14 + 0 + + + + 13000000 + science and technology + All aspects pertaining to human understanding of nature and the physical world and the development and application of this knowledge + none + 1 + 1 + 0 + + + + 13001000 + applied science + Stories about putting scientific knowledge to practical uses in the fields of the medical sciences, agriculture, domestic sciences as well as trades and crafts + none + 1 + 1 + 0 + + + + 13001001 + physics + The study of the properties and changes of matter + none + 9 + 9 + 0 + + + + 13001002 + chemistry + The study of the composition and reaction of substances + none + 9 + 9 + 0 + + + + 13001003 + cosmology + Study of the organization and structure of the universe + none + 15 + 15 + 0 + + + + 13001004 + particle physics + The study of elementary particles and atomic nuclei through the use of high-energy particles + none + 15 + 15 + 0 + + + + 13002000 + engineering + Stories about putting scientific knowledge to practical uses in the fields of civil, electrical, mechanical and chemical engineering + none + 1 + 1 + 0 + + + + 13002001 + material science + The study of materials used in manufacturing + none + 15 + 15 + 0 + + + + 13003000 + human science + Stories related to sociology, psychology, anthropology and political science + none + 1 + 1 + 0 + + + + 13003001 + social sciences + The study of people living in groups, as families, tribes and communities + none + 9 + 9 + 0 + + + + 13003002 + history + The study of human events of the past + none + 9 + 9 + 0 + + + + 13003003 + psychology + The study of the human mind and mental and emotional processes + none + 9 + 9 + 0 + + + + 13003004 + sociology + The study of human social relations, organization and change + none + 9 + 9 + 0 + + + + 13003005 + anthropology + The study of human beings in groups or societies + none + 9 + 9 + 0 + + + + 13004000 + natural science + Stories related to astronomy, astrophysics, physics, chemistry, earth sciences, palaeontology, biological sciences, botany and zoology, as well as mathematics + none + 1 + 1 + 0 + + + + 13004001 + geology + The study of Earth's physical processes + none + 9 + 9 + 0 + + + + 13004002 + paleontology + The study of ancient animals + none + 9 + 9 + 0 + + + + 13004003 + geography + The study of the surface of Earth and its political divisions + none + 9 + 9 + 0 + + + + 13004004 + botany + The study of plants + none + 9 + 9 + 0 + + + + 13004005 + zoology + The study of animals + none + 9 + 9 + 0 + + + + 13004006 + physiology + The study of vital processes of living organisms + none + 9 + 9 + 0 + + + + 13004007 + astronomy + The study of the stars and planets + none + 15 + 15 + 0 + + + + 13004008 + biology + The study of living organisms + none + 15 + 15 + 0 + + + + 13005000 + philosophical science + Stories related to philosophy, logic and ethics, among others + none + 1 + 1 + 0 + + + + 13006000 + research + Methodical investigation of events, procedures etc to explain why they occur, or to find solutions for problems + none + 1 + 1 + 0 + + + + 13006001 + survey + Examination of public attitudes on various subjects or issues, such as the quality of goods, the value of services etc. + none + 12 + 12 + 0 + + + + 13007000 + scientific exploration + Methodical land, sea and space journeys to discover new information about them + none + 1 + 1 + 0 + + + + 13008000 + space programme + The government's organized effort for the exploration of outer space and the bodies therein + none + 1 + 1 + 0 + + + + 13009000 + science (general) + Establishing and systematizing information about nature and the physical world through observation, experimentation and hypothesis + none + 1 + 1 + 0 + + + + 13010000 + technology (general) + The study of the practical or industrial arts, and applied sciences such as physics, hydrodynamics and thermodynamics + none + 1 + 1 + 0 + + + + 13010001 + rocketry + The development of rockets + none + 15 + 15 + 0 + + + + 13010002 + laser + The development and use of light amplification by stimulated emission of radiation + none + 15 + 15 + 0 + + + + 13011000 + standards + The rules, national and international, that govern science and technology. These might include international standards setting for equipment and interference standards. + none + 1 + 1 + 0 + + + + 13012000 + animal science + Science involving animals + none + 1 + 1 + 0 + + + + 13013000 + micro science + The multi-disciplinary areas of nanotechnology and Micro-Electrical Mechanical Systems. + none + 1 + 1 + 0 + + + + 13014000 + marine science + The multi-disciplinary research areas involving the worlds' waterways and oceans. This could include hyper-spectral sensing of ice flows, fisheries studies and underwater research. + none + 1 + 1 + 0 + + + + 13015000 + weather science + All scientific aspects of the weather and climate. + none + 1 + 1 + 0 + + + + 13016000 + electronics + The branch of engineering or physics concerned with the controlled flow of electrons or other carriers of electric charges, especially in semiconductor devices, including the design, manufacture, and maintenance of electronic devices + none + 1 + 1 + 0 + + + + 13017000 + identification technology + Includes biometrics, new computer-based identification cards, retinal scans, face scanning and mobile augmented reality systems (MARS) and other ways technology can identify individuals. Also technology vs. the privacy of personal information. + none + 1 + 1 + 0 + + + + 13018000 + mathematics + The study of quantities and shapes and their symbolic relationships. + none + 1 + 1 + 0 + + + + 13019000 + biotechnology + Manipulating natural organisms for scientific, medical or agricultural purposes + none + 9 + 9 + 0 + + + + 13020000 + agricultural research and technology + Pertaining to the growing of crops and management of farm animals + none + 9 + 9 + 0 + + + + 13021000 + nanotechnology + Manipulating objects at the molecular scale + none + 9 + 9 + 0 + + + + 13022000 + IT/computer sciences + The study and design of computer systems and networks. + none + 9 + 9 + 0 + + + + 13023000 + scientific institutions + Institutions that carry out or govern scientific work (e.g. National Academy of Arts and Sciences ) + none + 11 + 11 + 0 + + + + 14000000 + social issue + Aspects of the behaviour of humans affecting the quality of life. + none + 1 + 1 + 0 + + + + 14001000 + addiction + The habitual and often uncontrollable use of harmful substances such as alcohol, tobacco and pharmaceuticals or drugs + none + 1 + 1 + 0 + + + + 14002000 + charity + Philanthropic giving + none + 1 + 1 + 0 + + + + 14003000 + demographics + The study of people and here they live and how they interact + none + 1 + 1 + 0 + + + + 14003001 + population and census + Population is the number of people in a geographical region and census is the process of counting them + none + 9 + 9 + 0 + + + + 14003002 + immigration + Movement of individuals from one country to the other + none + 9 + 9 + 0 + + + + 14003003 + illegal immigrants + Movement of individuals from one country to the other by illicit means + none + 9 + 9 + 0 + + + + 14003004 + emigrants + People who leave their country of origin, their relationship with their country of origin and their association with fellow emigrants + none + 11 + 11 + 0 + + + + 14004000 + disabled + Being incapacitated either physically, emotionally or mentally + none + 1 + 1 + 0 + + + + 14005000 + euthanasia (also includes assisted suicide) + Voluntary death with the aid of another + none + 1 + 1 + 0 + + + + 14005001 + suicide + Death by one's own hand + none + 9 + 9 + 0 + + + + 14006000 + family + A group of individuals related by blood or marriage + none + 1 + 1 + 0 + + + + 14006001 + parent and child + Two or more individuals with a hierarchical familial relationship + none + 9 + 9 + 0 + + + + 14006002 + adoption + A legal process of bringing a child with no supporting parents into a supportive union + none + 9 + 9 + 0 + + + + 14006003 + marriage + The union of two individuals who pledge fidelity, respect and support for each other + none + 9 + 9 + 0 + + + + 14006004 + divorce + The process by which a marriage is dissolved + none + 9 + 9 + 0 + + + + 14006005 + sex + The classification of individuals as either male or female. Or conjugal relationship between two individuals. + none + 9 + 9 + 0 + + + + 14006006 + courtship + Preliminaries of wooing and winning a partner + none + 15 + 15 + 0 + + + + 14007000 + family planning + Conscious decisions and efforts involving reproduction + none + 1 + 1 + 0 + + + + 14008000 + health insurance + Insurance covering extraordinary medical costs + none + 1 + 1 + 0 + + + + 14009000 + homelessness + Lacking a fixed place of residence + none + 1 + 1 + 0 + + + + 14010000 + minority group + A group of people classified by race, language, religion or other characteristic numerically smaller than others of the same classification + none + 1 + 1 + 0 + + + + 14010001 + gays and lesbians + Those that consider themselves attracted to their same gender in an erotic or sensual or similar way. + none + 9 + 9 + 0 + + + + 14010002 + national or ethnic minority + Groups of people that form a minority on ethnic or national basis, their status, problems and relations to the majority + none + 11 + 11 + 0 + + + + 14011000 + pornography + Audio or visual depictions of various sex related acts considered outside accepted community standards + none + 1 + 1 + 0 + + + + 14012000 + poverty + Having insufficient resources to provide for basic services to oneself or family + none + 1 + 1 + 0 + + + + 14013000 + prostitution + Sex for sale, either male or female, and those who profit from it + none + 1 + 1 + 0 + + + + 14014000 + racism + Harmful attitudes toward another group based on racial differences + none + 1 + 1 + 0 + + + + 14015000 + welfare + Generally government help for those in need of food, housing health and other services + none + 1 + 1 + 0 + + + + 14016000 + abortion + Usually the planned disruption of the process of reproduction of human life + none + 1 + 1 + 0 + + + + 14017000 + missing person + A person who is not where they are expected to be for a period of time + none + 1 + 1 + 0 + + + + 14017001 + missing due to hostilities + People, both civilian and military, missing during or after hostilities + none + 11 + 11 + 0 + + + + 14018000 + long term care + Extensive health care because of serious illness or disability + none + 1 + 1 + 0 + + + + 14019000 + juvenile delinquency + Incidents involving perpetrators who are minors. + none + 1 + 1 + 0 + + + + 14020000 + nuclear radiation victims + Includes antinuclear movements and compensation for atomic blast victims. + none + 1 + 1 + 0 + + + + 14021000 + slavery + The involuntary servitude, outside of legal incarceration for statuary criminal offences, of men, women and children, including involuntary unpaid labour, coerced actions, child labour + none + 1 + 1 + 0 + + + + 14022000 + abusive behaviour + The maltreatment of one or more individuals by others through dehumanizing treatment including sexual or mental abuse, deprivation of sensory abilities, deprivation of physical needs, physical mistreatment including beatings, and other forms of torture + none + 1 + 1 + 0 + + + + 14023000 + death and dying + Dying is the route to death. Death is the state you are in when there are no signs that you can function as a human being either physically or mentally + none + 9 + 9 + 0 + + + + 14024000 + people + Individuals as a whole, sometimes broken down into various classes, such as indigenous people, people of class etc + none + 9 + 9 + 0 + + + + 14024001 + children + Immature people, usually up to the age of puberty + none + 9 + 9 + 0 + + + + 14024002 + infants + Those people from birth until ages of one or two, usually when they begin walking + none + 9 + 9 + 0 + + + + 14024003 + teen-agers + People aged 13 to 19 years of age + none + 9 + 9 + 0 + + + + 14024004 + adults + People aged 20 and above + none + 9 + 9 + 0 + + + + 14024005 + senior citizens + People aged 60 or 65 and older + none + 9 + 9 + 0 + + + + 14025000 + social issues (general) + Issues affecting a number of individuals in their daily lives like housing, food, education, personal relationships + none + 9 + 9 + 0 + + + + 14025001 + social conditions + Conditions under which people live in terms of housing, water supply, availability of education + none + 9 + 9 + 0 + + + + 14025002 + social problems + Issues affecting the lives of individuals such as housing, education nutrition, communication etc + none + 9 + 9 + 0 + + + + 14025003 + discrimination + Denial of services to one or more people because of race, colour, sexual identity, religion, political beliefs etc + none + 9 + 9 + 0 + + + + 14025004 + social services + Government supported programs to improve the well-being of individuals or groups of individuals + none + 9 + 9 + 0 + + + + 14025005 + death penalty policies + National or international polices regarding death sentences + none + 18 + 18 + 0 + + + + 14026000 + ordnance clearance + The removal or neutralization of ordnance such as landmines or cluster bombs, remaining after a war or armed conflict + none + 11 + 11 + 0 + + + + 14027000 + reconstruction + The reconstruction of economy, infrastructure and property, as well as life in general, after a war or natural disaster + none + 11 + 11 + 0 + + + + 15000000 + sport + Competitive exercise involving physical effort. Organizations and bodies involved in these activities. + none + 1 + 1 + 0 + + + + 15001000 + aero and aviation sport + Parachuting, freefall (parapente, delta-plane), gliding, aerostat, motorised flight (airplane, ultra light craft, helicopter) + none + 17 + 1 + 0 + + + + 15001001 + parachuting + Parachuting competitions: precision landings, voltige, individual and team + none + 1 + 1 + 0 + + + + 15001002 + sky diving + Parachuting competitions involving sky-diving + none + 1 + 1 + 0 + + + + 15002000 + alpine skiing + Skiing downhill on snow-covered slopes as fast as possible. The slopes contain intermediate gates which are spaced according to the discipline involved + none + 1 + 1 + 0 + + + + 15002001 + downhill + Skiing at top speed down a steep slope with interspersed turns but no gates. The fastest wins. + none + 1 + 1 + 0 + + + + 15002002 + giant slalom + Skiing down a slope, but with more turns and bends than in super-G skiing. The fastest wins. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15002003 + super G + Skiing down a steep slope, but with more turns and bends than in the downhill. The fastest wins. + none + 1 + 1 + 0 + + + + 15002004 + slalom + Skiers must zig-zag their way down a slope with closely positioned gates which they must negotiate. It is run over two legs with the combined fastest winning. + none + 1 + 1 + 0 + + + + 15002005 + combined + Race, usually competed over two days that combines a downhill leg and a slalom leg rewarding the most complete skiers. Combined fastest time wins. + none + 1 + 1 + 0 + + + + 15003000 + American football + Team ball game that opposes two teams that have attack sections and defence sections. Each attack goes up against the other defence and attempts to move an oval-shaped ball down the field and into the end-zone to mark a touchdown and earn points. + none + 1 + 1 + 0 + + + + 15003001 + (US) National Football League (NFL) (North American) + The association of professional American football teams + none + 1 + 1 + 0 + + + + 15003002 + CFL + The Canadian Football League (CFL), also known as Ligue Canadienne de Football (LCF), is a professional league located entirely in Canada that plays Canadian football. + re-added, with corresponding explanation + 18 + 1 + 0 + + + + 15003003 + AFL-DEPRECATED + The American Football League (AFL) was a professional league of American football that operated from 1960 to 1969. In 1970, the AFL merged with the National Football League. + explanation fixed - and code deprecated + 18 + 1 + 18 + + + + 15004000 + archery + Archers use bows and arrows to aim at targets 1.22 metres in diameter which are on average 70 metres distant. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15004001 + FITA / Outdoor target archery + The competition is held outdoors on an open (flat) field, at various fixed distances. The archery competition in the Olympic Games is a part of the FITA outdoor target archery program. + none + 1 + 1 + 0 + + + + 15004002 + crossbow shooting + Shooting with crossbow on targets from different distances + none + 11 + 11 + 0 + + + + 15005000 + athletics, track and field + Competitions involving foot races, jumping and throwing which can be on a track inside a stadium or on outside roads + none + 1 + 1 + 0 + + + + 15005001 + 100 m + Running over a distance of 100 metres with the fastest time winning + none + 1 + 1 + 0 + + + + 15005002 + 200 m + Running over a distance of 200 metres with the fastest time winning + none + 1 + 1 + 0 + + + + 15005003 + 400 m + Running over a distance of 400 metres with the fastest time winning + none + 1 + 1 + 0 + + + + 15005004 + 800 m + Running over a distance of 800 metres with the fastest time winning + none + 1 + 1 + 0 + + + + 15005005 + 1000 m + Running over a distance of 1000 metres with the fastest time winning + none + 1 + 1 + 0 + + + + 15005006 + 1500 m + Running over a distance of 1000 metres with the fastest time winning + none + 1 + 1 + 0 + + + + 15005007 + mile + Running over a distance of one mile with the fastest time winning + typo fixed in Explanation + 17 + 1 + 0 + + + + 15005008 + 2000 m + Running over a distance of 2000 metres with the fastest time winning + none + 1 + 1 + 0 + + + + 15005009 + 3000 m + Running over a distance of 3000 metres with the fastest time winning + none + 1 + 1 + 0 + + + + 15005010 + 5000 m + Running over a distance of 5000 metres with the fastest time winning + none + 1 + 1 + 0 + + + + 15005011 + 10,000 m + Running over a distance of 10,000 metres with the fastest time winning + none + 1 + 1 + 0 + + + + 15005012 + 20 km + Walking over a distance of 20 km on public roads with the fastest time winning + none + 1 + 1 + 0 + + + + 15005013 + one hour + Walking as far as possible in the time of one hour + none + 1 + 1 + 0 + + + + 15005014 + 25000 + Walking over a distance of 25km with the fastest time winning + none + 1 + 1 + 0 + + + + 15005015 + 30000 + Walking over a distance of 30kms with the fastest time winning + none + 1 + 1 + 0 + + + + 15005016 + 110 m hurdles + Race consisting of covering 110 metres as fast as possible while jumping over 10 hurdles placed on the track + none + 1 + 1 + 0 + + + + 15005017 + 400 m hurdles + Race consisting of covering 400 metres as fast as possible while jumping over 10 hurdles placed on the track + none + 1 + 1 + 0 + + + + 15005018 + 3000 m steeplechase + Race consisting of covering 3000 metres as fast as possible while jumping over 28 hurdles which are 91/4 centimetres high and seven water obstacles + none + 1 + 1 + 0 + + + + 15005019 + high jump + Competitors jump as high as possible over a bar which is raised each time they clear the height. The highest clearance wins. + none + 1 + 1 + 0 + + + + 15005020 + pole vault + Competitors use a flexible pole to propel themselves feet-first into the air and clear a bar which is raised higher at each round of jumps. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15005021 + long jump + Competitors build up speed over a short sprint and them attempt to jump as far forward as they can from a given point into sand trap. The longest jump wins. + none + 1 + 1 + 0 + + + + 15005022 + triple jump + Competitors build up speed over a short sprint and then attempt to jump as far forward as they can using a hop, skip and a jump technique. The longest jump wins. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15005023 + shot put + Competitors stand in a circle with a 2.13 metres diameter and attempt to throw a metal ball weighing 7.26 kg for men and 4kg for women as far as possible. The longest throw wins. + none + 1 + 1 + 0 + + + + 15005024 + discus throw + Competitors stand in a netted circle with a 2.50 metres diameter and with a turning motion attempt to throw a discus weighing 2kg for men and 1kg for women as far as possible. The longest throw wins. + none + 1 + 1 + 0 + + + + 15005025 + hammer throw + Competitors throw a hammer consisting of a metal ball, chain and handle as far as they can from a netted circle which is 2.13 metres in diameter. The hammer weighs 7.26 kg for men and 4 kg for women. + none + 1 + 1 + 0 + + + + 15005026 + javelin throw + Competitors in a specially-designated throwing area attempt to fling a spear-like javelin as far as possible. The javelin weighs 800 grammes for men and 600 grammes for women. + none + 1 + 1 + 0 + + + + 15005027 + decathlon + Individual men's competition which involves accumulating points in 10 different disciplines over two days: 1st day - 100m, long-jump, shot-putt, high-jump, 400m. 2nd day - 110m hurdles, discus, pole-vault, javelin and 1,500 metres. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15005028 + 4x100 m + Team race involving four runners each covering 100 metres. + none + 1 + 1 + 0 + + + + 15005029 + 4x200 m + Team race involving four runners each covering 200 metres. + none + 1 + 1 + 0 + + + + 15005030 + 4x400 m + Team race involving four runners each covering 400 metres. + none + 1 + 1 + 0 + + + + 15005031 + 4x800 m + Team race involving four runners each covering 800 metres. + none + 1 + 1 + 0 + + + + 15005032 + 4x1500 m + Team race involving four runners each covering 1500 metres. + none + 1 + 1 + 0 + + + + 15005033 + walk 1 h + One-hour long race where competitors must maintain at least one foot in contact with the ground and are not allowed to run. + none + 1 + 1 + 0 + + + + 15005034 + walk 2 h + Two-hour long walking race where competitors must maintain at least one foot in contact with the ground and are not allowed to run. + none + 1 + 1 + 0 + + + + 15005035 + 10 km walk + Walking race over 10 kilometres where competitors must maintain at least one foot in contact with the ground and are not allowed to run. + none + 1 + 1 + 0 + + + + 15005036 + 15 km walk + Walking race over 15 kilometres where competitors must maintain at least one foot in contact with the ground and are not allowed to run. + none + 1 + 1 + 0 + + + + 15005037 + 20 km walk + Walking race over 20 kilometres where competitors must maintain at least one foot in contact with the ground and are not allowed to run. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15005038 + 30 km walk + Walking race over 30 kilometres where competitors must maintain at least one foot in contact with the ground and are not allowed to run. + none + 1 + 1 + 0 + + + + 15005039 + 50 km walk + Walking race over 50 kilometres where competitors must maintain at least one foot in contact with the ground and are not allowed to run. + none + 1 + 1 + 0 + + + + 15005040 + 100 m hurdles + Sprint over a distance of 110 metres with competitors having to clear 10 hurdles placed in their way. + none + 1 + 1 + 0 + + + + 15005041 + 5 km walk + Walking race over 5 kilometres where competitors must maintain at least one foot in contact with the ground and are not allowed to run. + none + 1 + 1 + 0 + + + + 15005042 + heptathlon + Individual women's competition involving seven separate disciplines over two days. 1st day - 100m hurdles, high-jump, shot-putt, 200 metres. 2nd day - long-jump, javelin, 800 metres. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15005043 + 1500 m walk + Walking race over 1500 metres where competitors must maintain at least one foot in contact with the ground and are not allowed to run. + none + 1 + 1 + 0 + + + + 15005044 + 2000 m walk + Walking race over 2000 metres where competitors must maintain at least one foot in contact with the ground and are not allowed to run. + none + 1 + 1 + 0 + + + + 15005045 + 3000 m walk + Walking race over 3000 metres where competitors must maintain at least one foot in contact with the ground and are not allowed to run. + none + 1 + 1 + 0 + + + + 15005046 + 50 m + Short sprint race over 50 metres with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005047 + 50 m hurdles + Short sprint race over 50 metres interspersed with hurdles. + none + 1 + 1 + 0 + + + + 15005048 + 50 yards + Short sprint race over 50 yards with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005049 + 50 yard hurdles + Short sprint race over 50 yards interspersed with hurdles. + none + 1 + 1 + 0 + + + + 15005050 + 60 m + Short sprint race over 60 metres with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005051 + 60 m hurdles + Short sprint race over 60 metres interspersed with hurdles. + none + 1 + 1 + 0 + + + + 15005052 + 60 yards + Short sprint race over 60 yards with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005053 + 60 yard hurdles + Short sprint race over 60 yards interspersed with hurdles. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15005054 + 100 yards + Sprint race over 100 yards with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005055 + 100 yard hurdles + Sprint race over 100 yards interspersed with hurdles. + none + 1 + 1 + 0 + + + + 15005056 + 300 m + Race over 300 metres with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005057 + 300 yards + Race over 300 yards with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005058 + 440 yards + Race over 440 yards with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005059 + 500 m + Race over 500 metres with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005060 + 500 yards + Race over 500 yards with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005061 + 600 m + Race over 600 metres with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005062 + 600 yards + Race over 600 yards with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005063 + 880 yards + Race over 880 yards with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005064 + 1000 yards + Race over 1000 yards with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005065 + 2 miles + Race over two miles with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005066 + 3 miles + Race over three miles with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005067 + 6 miles + Race over six miles with the fastest time winning. + none + 1 + 1 + 0 + + + + 15005068 + 4x1 mile + Team Relay race with four runners on each team running for one mile. + none + 1 + 1 + 0 + + + + 15005069 + pentathlon + Only indoor, 60m hurdles, high jump, shot put, long jump, 800 m + none + 12 + 12 + 0 + + + + 15006000 + badminton + Two players or two teams of two compete by hitting a shuttlecock weighing approximately five grams over a high net. The aim for each player/team is to prevent the shuttlecock landing on their side of the court. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15007000 + baseball + A game between two teams of nine played on an enclosed ground. The team which scores the most points wins. A point is scored when a player runs around the ground marked out by four bases. + Explanation shortened + 17 + 1 + 0 + + + + 15007001 + Major League Baseball (North American Professional) - American League + Baseball league comprising 14 teams. + none + 1 + 1 + 0 + + + + 15007002 + Major League Baseball (North American Professional) - National League + Baseball league comprising 16 teams. + none + 1 + 1 + 0 + + + + 15007003 + Major League Baseball (North American Professional) - Special (e.g. All-Star, World Series) + Baseball competition other than the World Series. + none + 1 + 1 + 0 + + + + 15007004 + rubberball baseball + Sometimes called ''soft baseball,'' the game is played with a rubber baseball of varying degrees of hardness depending upon the age and level of the players. + none + 1 + 1 + 0 + + + + 15007005 + Major League Baseball Playoffs + Consists of several rounds of play to determine representatives to the U.S.-based World Series + none + 11 + 11 + 0 + + + + 15007006 + World Series + U.S.-based annual series of games between the top two teams of Major League Baseball to determine the overall champion + none + 11 + 11 + 0 + + + + 15008000 + basketball + Game played between two teams of five - points are scored by placing the large inflated ball into a net fixed on a ring 3.05m above the ground. + none + 1 + 1 + 0 + + + + 15008001 + National Basketball Association (North American Professional) + The NBA is the umbrella organisation running professional basketball in the United States. The NBA is made up of two conferences (east and west), four divisions (Atlantic and Central for the East, and Midwest and Pacific for the west). + typo fixed in Explanation + 17 + 1 + 0 + + + + 15008002 + professional - Women general + women's professional league + none + 1 + 1 + 0 + + + + 15008003 + Swiss netball + Similar to Basketball. Basket without a board. Mainly executed by women + none + 11 + 11 + 0 + + + + 15008004 + German netball + Same as Swiss Netball, but with specific German rules + none + 11 + 11 + 0 + + + + 15008005 + Dutch netball + Same as Swiss Netball, but with specific Dutch rule + none + 11 + 11 + 0 + + + + 15009000 + biathlon + A combination of cross country skiing and target shooting on a 12.5 K course in a pursuit format. + none + 1 + 1 + 0 + + + + 15009001 + 7.5 km + Timed cross country skiing race. Competitors set off at 30sec intervals for three circuits totalling 7.5km. + none + 1 + 1 + 0 + + + + 15009002 + 10 km + Sprint races for men, pursuit for women. + none + 1 + 1 + 0 + + + + 15009003 + 15 km + Individual women's race in sprint format staged over three laps with competitors setting off at intervals of a minute. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15009004 + 20 km + Individual men's race in sprint format staged over five laps with competitors setting off at intervals of a minute. + none + 1 + 1 + 0 + + + + 15009005 + 4x7.5 km relay + Teams consisting of four biathletes with each team covering a distance of 7.5km with two rounds of target shooting. + none + 1 + 1 + 0 + + + + 15009006 + 12.5 km pursuit + The start is determined by the results from the sprint. A race held over five laps with target shooting (standing or prone) + none + 1 + 1 + 0 + + + + 15010000 + billiards, snooker and pool + A game played on a flat table covered with a cloth (baize) where players hit balls according to specific rules using a wooden cue. + none + 1 + 1 + 0 + + + + 15010001 + 8 ball + A game using 15 balls and a white. The first player aims to pot the balls numbered 1-7 (solids) with the second player potting balls 9-15 (stripes). After that the first player to pot the black wins. + none + 1 + 1 + 0 + + + + 15010002 + 9 ball + A game played with nine balls numbered 1-9, and a white. On each turn the player must hit the lowest numbered ball. + none + 1 + 1 + 0 + + + + 15010003 + 14.1 + A player nominates the ball he is attempting to pot and into which pocket. He collects points for each successful hit. He continues until he makes a mistake. Before hitting the 15th ball, the 14 reds are set up again in the triangle. + Explanation shortened + 17 + 1 + 0 + + + + 15010004 + continuous-DEPRECATED + NA + DEPRECATED in V 16 + 16 + 1 + 16 + + + + 15010005 + other-DEPRECATED + NA + DEPRECATED in V 16 + 16 + 1 + 16 + + + + 15010006 + snooker + Two players using a cue and a white ball to "sink" other coloured balls in a correct order on a baize table and to cause an opponent to miss-hit by positioning the white ball in an inappropriate place - snookering. + none + 17 + 17 + 0 + + + + 15011000 + bobsleigh + In bobsleigh two or four persons race down a course sitting in a sled that consists of a main hull, a frame, two axles and sets of runners. The total time of all heats in a competition is added together to determine the winner. + none + 1 + 1 + 0 + + + + 15011001 + two-man sled + race consisting of a team of two competitors + none + 1 + 1 + 0 + + + + 15011002 + four-man sled + race consisting of a team of four competitors + none + 1 + 1 + 0 + + + + 15012000 + bowling + A game in which a player scores points by trying to knock down ten 'pins' using a ball - if unsuccessful the player has a second attempt. A game consists of ten frames. + none + 1 + 1 + 0 + + + + 15013000 + bowls and petanque + A game in which players throw bowls at a target, the winner being the player who lands closest. + none + 1 + 1 + 0 + + + + 15014000 + boxing + Combat sport in which two men/women fight using only their fists covered by padded gloves in a square ring measuring 6m a side. The fight is usually split into 12 rounds of three minutes each. + none + 1 + 1 + 0 + + + + 15014001 + super-heavyweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014002 + heavyweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014003 + cruiserweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014004 + light-heavyweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014005 + super-middleweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014006 + middleweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014007 + light-middleweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014008 + welterweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014009 + light-welterweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014010 + lightweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014011 + super-featherweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014012 + featherweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014013 + super-bantamweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014014 + bantamweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014015 + super-flyweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014016 + flyweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014017 + light flyweight + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014018 + straw + weight category which varies according to the federation + none + 1 + 1 + 0 + + + + 15014019 + IBF + International boxing federation + none + 1 + 1 + 0 + + + + 15014020 + WBA + World boxing association + none + 1 + 1 + 0 + + + + 15014021 + WBC + World boxing council + none + 1 + 1 + 0 + + + + 15014022 + WBO + World boxing organisation + none + 1 + 1 + 0 + + + + 15014023 + French boxing + Combat sport in which kicking with all parts of the feet are permitted and punching with the front of the fist is also allowed + none + 1 + 1 + 0 + + + + 15014024 + Thai boxing + Form of boxing involving punches with fists, feet, knees, elbows and legs. + none + 1 + 1 + 0 + + + + 15015000 + canoeing and kayaking + races in either 'white' or 'dead' water + none + 1 + 1 + 0 + + + + 15015001 + Slalom + White water course set out with gates consisting of two poles suspended vertically over the water. Competitors must negotiate the gates or face penalties + none + 1 + 1 + 0 + + + + 15015002 + 200 m + race held over 200m + none + 1 + 1 + 0 + + + + 15015003 + 500 m + race held over 500m + none + 1 + 1 + 0 + + + + 15015004 + 1000 m + race held over 1000m + none + 1 + 1 + 0 + + + + 15015005 + K1 + an enclosed boat with the competitor sitting on a fixed seat for one person using a double bladed paddle + none + 1 + 1 + 0 + + + + 15015006 + K2 + an enclosed boat with the competitor sitting on a fixed seat for two people using double bladed paddles. + none + 1 + 1 + 0 + + + + 15015007 + K4 + an enclosed boat with the competitor sitting on a fixed seat for four people using double bladed paddles. + none + 1 + 1 + 0 + + + + 15015008 + C1 + One-seater canoe (open boat with competitor using a single bladed paddle. + none + 1 + 1 + 0 + + + + 15015009 + C2 + Two-seater canoe (open boat) - competitors use a single bladed paddle. + none + 1 + 1 + 0 + + + + 15015010 + C4 + Four-seater canoe (open boat) with each competitor using a single bladed paddle. + none + 1 + 1 + 0 + + + + 15015011 + canoe sailing + A race involving a canoe equipped with a sail. + none + 1 + 1 + 0 + + + + 15015012 + pontoniering + Team sport, military tradition, similar to canoe regatta, in boats + none + 11 + 11 + 0 + + + + 15016000 + climbing + mountain sports + none + 1 + 1 + 0 + + + + 15016001 + mountaineering + Alpine climbing + none + 11 + 11 + 0 + + + + 15016002 + sport climbing + Sport climbing as a special category: individual competition, on an artificial wall with time measurement + none + 11 + 11 + 0 + + + + 15017000 + cricket + Ball sport involving two teams of 11 players, balls, bats and wickets. The aim is to score as many runs as possible, and to get the opposing team 'out'. A 'run' involves a player running between two wickets. The opposing team try to get their rivals 'out' + none + 1 + 1 + 0 + + + + 15018000 + curling + A game played on ice with large flat round stones. A player throws the stone, aiming at a target. Team mates of the player who has thrown the stone can sweep the ice in front of the stone to help smooth its path towards the target. + none + 1 + 1 + 0 + + + + 15018001 + icestock sport + Similar to curling, played on targets on ice, different stones with straight handle and different rules, played in alpine countries + none + 11 + 11 + 0 + + + + 15019000 + cycling + A race over a given distance on bicycles. + none + 1 + 1 + 0 + + + + 15019001 + track + A race staged on a track in a velodrome + none + 1 + 1 + 0 + + + + 15019002 + pursuit + Two cyclists or teams set off from midway down opposite straights and try to make up the gap between them. + none + 1 + 1 + 0 + + + + 15019003 + Olympic sprint + Qualifying race held over 200m. From the quarter-finals two cyclists go head-to-heads. By teams races consist of three cyclists from different countries. + none + 1 + 1 + 0 + + + + 15019004 + sprint + Races between two cyclists over two or three laps, with a timed sprint finish over the last 200m. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15019005 + Keirin + Sprint between six cyclists where a pacemaker on a moped gradually increases the pace over the first 1400m. When the pacemaker leaves the track the race develops into a sprint finish over the final 6-700m. + none + 1 + 1 + 0 + + + + 15019006 + points race + Cyclists aim to complete the highest number of laps. Bonus points are picked up in intermediate sprints held every 2500m. + none + 1 + 1 + 0 + + + + 15019007 + Madison race + A points race by teams comprising two cyclists in relay-format. + none + 1 + 1 + 0 + + + + 15019008 + 500 m time trial + Individual race against the clock over 500m for women. + none + 1 + 1 + 0 + + + + 15019009 + 1 km time trial + Individual race over 1000m against the clock for men. + none + 1 + 1 + 0 + + + + 15019010 + one hour + Competitors aim to complete as many kilometres as possible in one hour. + none + 1 + 1 + 0 + + + + 15019011 + road race + Road race with all the competitor starting en masse. + none + 1 + 1 + 0 + + + + 15019012 + road time trial + A race or stage against the clock with each cyclist setting off individually. + none + 1 + 1 + 0 + + + + 15019013 + staging race + A race disputed by teams with the classifications determined by the combined times over a day. + none + 1 + 1 + 0 + + + + 15019014 + cyclo-cross + Staged on various surfaces - earth, grass, sand or tarmac. + none + 1 + 1 + 0 + + + + 15019015 + Vtt + mountain bikes + none + 1 + 1 + 0 + + + + 15019016 + Vtt-cross + An endurance race on mountain bikes around a 10km circuit over various terrain and with different degrees of slopes. Competitors are not allowed any exterior help. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15019017 + Vtt-downhill + Individual mountain bike race against the clock staged on a downhill circuit featuring obstacles. + none + 1 + 1 + 0 + + + + 15019018 + bi-crossing + A race where competitors have to cover a circuit with obstacles as quickly as possible. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15019019 + trial + A timed race in which competitors on mountain bikes must negotiate tricky terrain and obstacles without putting their feet down. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15019020 + artistic cycling + Individual or teams on one or two bicycles in an arena. Points are awarded by a jury. + none + 11 + 11 + 0 + + + + 15019021 + cycle ball + Competitive team sport using bicycles. One team against another with two persons per team. The aim is for competitors to move the ball using the front and rear wheels without letting their feet touch the ground. + none + 11 + 11 + 0 + + + + 15020000 + dancing + Dancing competition where couples are judged on technique and interpretation. + none + 1 + 1 + 0 + + + + 15021000 + diving + Competitors dive off a fixed or spring board and are assessed by seven judges giving marks up to ten for their acrobatic moves. + none + 1 + 1 + 0 + + + + 15021001 + 10 m platform + Divers take off from a ten metre high platform. + none + 1 + 1 + 0 + + + + 15021002 + 10 m platform synchronised + Two competitors from the same team dive off at the same time from separate platforms. As well as being judged on the standard criteria they are also awarded marks for synchronisation. + none + 1 + 1 + 0 + + + + 15021003 + 3 m springboard + Divers dive from a three-metre high springboard. + none + 1 + 1 + 0 + + + + 15021004 + 3 m springboard synchronised + Two competitors from the same team dive off at the same time from separate three-metre high springboards. As well as being judged on the standard criteria they are also awarded marks for synchronisation. + none + 1 + 1 + 0 + + + + 15021005 + subaquatics + Sports like hockey held under water + typo fixed in Explanation + 17 + 1 + 0 + + + + 15021006 + scuba diving + Diving into different depths, with time measurement + none + 11 + 11 + 0 + + + + 15022000 + equestrian + Sport involving a horse and rider. + none + 1 + 1 + 0 + + + + 15022001 + three-day event + Equestrian event involving three disciplines - Dressage, cross-country and show jumping. + none + 1 + 1 + 0 + + + + 15022002 + dressage + A rider is judged on a series of moves at three different paces - walk, trot and gallop. + none + 1 + 1 + 0 + + + + 15022003 + jumping + A rider and horse attempt to jump a series of obstacles in an enclosed arena against the clock. + none + 1 + 1 + 0 + + + + 15022004 + cross country + Equestrian event held on a designated circuit in the countryside featuring artificial and natural obstacles. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15023000 + fencing + Combat sport using a sword or foil. + none + 1 + 1 + 0 + + + + 15023001 + epee + category of fencing using a weapon with a triangular cross-section blade and a large bell guard. + none + 1 + 1 + 0 + + + + 15023002 + foil + category of fencing using a weapon with a rectangular cross-section blade and a small bell guard. + none + 1 + 1 + 0 + + + + 15023003 + sabre + a fencing weapon with a flat blade and knuckle guard used with cutting or thrusting moves. + none + 1 + 1 + 0 + + + + 15024000 + field Hockey + A ball sport involving two teams of 11 players using curved sticks. The aim is to score as many goals as possible. + none + 1 + 1 + 0 + + + + 15024001 + roll hockey + Team sport similar to ice hockey, executed on 4 wheel roller skates with sticks and a ball + none + 11 + 11 + 0 + + + + 15025000 + figure Skating + To obtain the best marks possible from nine judges who award scores after two prepared sections - both skated to music - during which competitors must attempt to achieve the greatest possible harmony between artistic flair and technical precision. + none + 1 + 1 + 0 + + + + 15025001 + singles + The individual events comprise a short program which counts for 33.3% of the score, and the free skate which is worth 66.7%. + none + 1 + 1 + 0 + + + + 15025002 + pairs + The pairs event comprise a short program which counts for 33.3% of the score, and the free skate which is worth 66.7%. + none + 1 + 1 + 0 + + + + 15025003 + ice dance + Takes place over three days with, in order, two compulsory dances, the original dance (2min 30sec) and the free dance (4min). + none + 1 + 1 + 0 + + + + 15026000 + freestyle Skiing + Competitors perform a series of breathtaking acrobatic leaps from a prepared jump. Combined with moguls, jumps and ski ballet. + none + 1 + 1 + 0 + + + + 15026001 + moguls + Contestants attack a heavily moguled slope, performing technically challenging turns and jumps, while maintaining the most direct line from the top to the bottom of the hill. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15026002 + aerials + Competitors perform a series of aerial twists and turns from a prepared jump. + none + 1 + 1 + 0 + + + + 15026003 + artistic skiing + Competitors perform a series of artistic moves (jumps and twists) all set to music. The use of ski poles is permitted. + none + 1 + 1 + 0 + + + + 15027000 + golf + Competitors attempt to hit a small white ball with different clubs around a course of 18 holes varying in distance. The object is to make the fewest strokes possible. + none + 1 + 1 + 0 + + + + 15028000 + gymnastics + A sport consisting of a variety of disciplines in which gymnasts perform artistic and acrobatic moves on different apparatus. There are 6 disciplines for men and 4 for women. + none + 1 + 1 + 0 + + + + 15028001 + floor exercise + A gymnastics floor exercise on a 12m/sq matt. + none + 1 + 1 + 0 + + + + 15028002 + vault + gymnasts propel themselves by jumping on a trampoline after running quickly down a 25m lane + none + 1 + 1 + 0 + + + + 15028003 + pommel horse + Gymnasts perform an uninterrupted swing motion over a handled horse using balance and strength. + none + 1 + 1 + 0 + + + + 15028004 + uneven bars + Gymnasts run through an airborne routine swinging around and between the uneven bars. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15028005 + parallel bars + Gymnasts swing and turn with guile and grace around the parallel bars. + none + 1 + 1 + 0 + + + + 15028006 + horizontal bar + Gymnasts turn, spin and perform pirouettes around the horizontal bar. + none + 1 + 1 + 0 + + + + 15028007 + rings + Gymnasts perform feats of balance and strength from two suspended rings. + none + 1 + 1 + 0 + + + + 15028008 + beam + Gymnasts perform leaps and flips from the much feared balance beam just 10 cm wide. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15028009 + rhythmic + A mixture of dance and gymnastic moves. + typo fixed in Name + 17 + 1 + 0 + + + + 15028010 + clubs + Dance and gymnastic moves whilst juggling clubs. + none + 1 + 1 + 0 + + + + 15028011 + hoop + A hoop is rolled and thrown whilst performing a dance routine. + none + 1 + 1 + 0 + + + + 15028012 + ribbon + Gymnasts work through a pre-arranged routine whilst manipulating a spectacular length of ribbon. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15028013 + rope + Jump and figure movements are performed while a rope is manipulated. + none + 1 + 1 + 0 + + + + 15028014 + ball + An exercise based on suppleness of the body using a ball. + none + 1 + 1 + 0 + + + + 15028015 + trampoline + Competitors perform complicated twists and turns whilst bouncing on the trampoline. + none + 1 + 1 + 0 + + + + 15029000 + handball (team) + A ball game using the hands contested by two teams of seven trying to throw the ball into the opponents goal. + none + 1 + 1 + 0 + + + + 15030000 + horse racing, harness racing + Mounted horse races. + none + 1 + 1 + 0 + + + + 15030001 + flat racing + A horse race over a flat course. + none + 1 + 1 + 0 + + + + 15030002 + steeple chase + A mounted horse race over at least eight classic obstacles, four of which must be different, such as the water jump, spruce fences, mud walls etc. + none + 1 + 1 + 0 + + + + 15030003 + trotting + Horses pitched to a jockeyed buggy race in a trot round a flat course. + none + 1 + 1 + 0 + + + + 15030004 + cross country + A long distance race including rustic obstacles such as real fences, streams and fallen trees. + none + 1 + 1 + 0 + + + + 15031000 + ice hockey + Two teams of six heavily padded skaters try and outscore each other by hitting a puck into the opponents goal. + none + 1 + 1 + 0 + + + + 15031001 + National Hockey League (North American) + Teams from the US and Canada make up the North American continents top league. + none + 1 + 1 + 0 + + + + 15031002 + sledge hockey + Like ice hockey but instead of skates small sledges are used. Competitors move by pushing with the arms + none + 1 + 1 + 0 + + + + 15032000 + Jai Alai (Pelota) + Because of the game organization, the proper identification of a specific game may require the combination of 2 subject details + none + 1 + 1 + 0 + + + + 15032001 + fronton + The "fronton" known as "Fronton Place Libre" consists of a rectangular outdoor court plus a large pink shaped wall at one end. The two sides and the other end are left opened. + none + 1 + 1 + 0 + + + + 15032002 + jai-alai + A "Jaï-Alai" is an indoor fronton with a 56 meters long court which is used exclusively to play "chistera-ancha". Three walls are used in the game: the front, the back and the left hand wall. + none + 1 + 1 + 0 + + + + 15032003 + left wall + A "fronton with left hand wall" is an indoor fronton with a 36 meters long court where Pala or Main Nue are played. Three walls are used in the game: the front, the back and the left hand wall. + none + 1 + 1 + 0 + + + + 15032004 + trinquet + A "Trinquet" is an indoor fronton with a 28.5 meters long court surrounded by four walls. The four walls are used in the game. + none + 1 + 1 + 0 + + + + 15032005 + rebot + The "rebot" is the game played in a fronton "place libre" with 5 players in each team. They use a "chistera" (56 cm long and 12 cm large) or bare hands. + none + 1 + 1 + 0 + + + + 15032006 + chistera ancha + The "chistera-ancha" also called the "cesta punta" is the game played in a "jaï alai" with 1 or 2 players in each team. The players use a long curved basket called the "chistera" (68 cm long and 13 cm wide). + none + 1 + 1 + 0 + + + + 15032007 + chistera corta + The "chistera-corta" is the game played in a fronton "place libre" with left hand wall and 3 players in each team. The players use a long curved basket called the "chistera" (56 cm long and 12 cm wide). + none + 1 + 1 + 0 + + + + 15032008 + bare hand + The "Main Nue" (bare hand) is the ancestor of all Basque sports. + none + 1 + 1 + 0 + + + + 15032009 + pala-ancha + The "pala-ancha" is the game played in a fronton "place libre" with 2 players in each team. The players use a heavy wooden bat "the pala" (50 cm long and 20 cm wide). + none + 1 + 1 + 0 + + + + 15032010 + pala-corta + The "pala-corta" is the game played in a fronton with left hand wall and 2 players in each team. The players use a heavy wooden bat the "pala-corta" (50 cm long and 10 cm wide). The "pala" is the name for a heavy wooden bat. + Explanation shortened + 17 + 1 + 0 + + + + 15032011 + pasaka + The "pasaka" is the name of the game played in a trinquet by teams of 2 players facing each other on each side of a net where the pelota is hit between opponents. + none + 1 + 1 + 0 + + + + 15032012 + xare + The "xare", is the name of the game played in a trinquet by teams of 2 players. The players use a "xare" (or the Argentina bat) 55 cm long and 16 cm wide. + none + 1 + 1 + 0 + + + + 15033000 + judo + A defensive martial art. + none + 1 + 1 + 0 + + + + 15033001 + heavyweight + Open but usually over 100kg for men and over 78kg for women + none + 1 + 1 + 0 + + + + 15033002 + half-heavyweight + Up to 100kg for men and 78kg for women. + none + 1 + 1 + 0 + + + + 15033003 + middleweight + Up to 90kg for men and 70kg for women. + none + 1 + 1 + 0 + + + + 15033004 + half-middleweight + UP to 81kg for men and 63kg for women. + none + 1 + 1 + 0 + + + + 15033005 + half-lightweight + Up to 73kg for men and 57kg for women. + none + 1 + 1 + 0 + + + + 15033006 + lightweight + up to 66kg for men and 52kg for women. + none + 1 + 1 + 0 + + + + 15033007 + extra lightweight + Up to 60kg for men and 48kg for women. + none + 1 + 1 + 0 + + + + 15034000 + karate + A martial art where chops, punches, kicks and throws are used to defeat an opponent. + none + 1 + 1 + 0 + + + + 15034001 + sparring + Boxing without competition, with padded helmets + none + 1 + 1 + 0 + + + + 15034002 + formal exercise-DEPRECATED + NA + DEPRECATED in V 16 + 16 + 1 + 16 + + + + 15035000 + lacrosse + Two teams of helmeted and padded players try and outscore each other using a netted stick and hard ball. + none + 1 + 1 + 0 + + + + 15036000 + luge + Luge (French word for sled) is competed in singles or doubles. The competitor(s) lay on their back(s) on an open sled and race down a course. The competitor(s) and the sled must be in contact when passing the finishing line. + Explanation shortened + 17 + 1 + 0 + + + + 15036001 + singles + individual time trial event in a one seater luge + none + 1 + 1 + 0 + + + + 15036002 + doubles + time trial for a twin berth luge + none + 1 + 1 + 0 + + + + 15037000 + marathon + A road race where competitors run 42.195km, generally through city streets + none + 1 + 1 + 0 + + + + 15038000 + modern pentathlon + The Modern Pentathlon comprises five events run over a single day in the following order: shooting, fencing, swimming, horse riding and running. + none + 1 + 1 + 0 + + + + 15038001 + running + Pentathlon event + none + 1 + 1 + 0 + + + + 15038002 + shooting + Pentathlon event + none + 1 + 1 + 0 + + + + 15038003 + swimming + Pentathlon event + none + 1 + 1 + 0 + + + + 15038004 + fencing + Pentathlon event + none + 1 + 1 + 0 + + + + 15038005 + showjumping + Pentathlon event + none + 1 + 1 + 0 + + + + 15039000 + motor racing + Motor racing where speed and trusty mechanics are key + none + 1 + 1 + 0 + + + + 15039001 + Formula One + Single cockpit car racing where 20 or so competitors race head to head over varied circuits around the world to win Grand Prix points in an individual and constructors championship + none + 1 + 1 + 0 + + + + 15039002 + F3000 + Using less powerful motors than the Formula One, designated construction teams race over varied circuits the world over in speed races for individual and team honours over a season. + none + 1 + 1 + 0 + + + + 15039003 + endurance + Endurance races for a driver and co-pilot using specially built cars. + none + 1 + 1 + 0 + + + + 15039004 + Indy + North American top range professional league speed racing over circuits. + none + 1 + 1 + 0 + + + + 15039005 + CART + North American professional league speed racing. + none + 1 + 1 + 0 + + + + 15039006 + NHRA + North American professional league speed racing. + none + 1 + 1 + 0 + + + + 15039007 + NASCAR + North American professional league speed racing. + none + 1 + 1 + 0 + + + + 15039008 + TRUCKI + North American professional league speed racing. + none + 1 + 1 + 0 + + + + 15040000 + motor rallying + A season of endurance races over closed circuits including dirt tracks, roads and even snowy conditions featuring specials using adapted road cars with a driver and co-pilot. + none + 1 + 1 + 0 + + + + 15040001 + rallying + Stage races + none + 1 + 1 + 0 + + + + 15040002 + pursuit + Cross-country race with mass start, first half of the distance in classic and the other half in free style. + changed name and added explanation in V15 + 15 + 1 + 0 + + + + 15040003 + rallycross + Stage races over dirt tracks + none + 1 + 1 + 0 + + + + 15041000 + motorcycling + Races with 2, 3 or 4 wheels vehicles with a saddle and handlebars + none + 1 + 1 + 0 + + + + 15041001 + speed-Grand-Prix + A fast and furious race where every second counts + none + 1 + 1 + 0 + + + + 15041002 + enduro + A race of speed, endurance and regularity over varied surfaces such as through forests and on dirt tracks + none + 1 + 1 + 0 + + + + 15041003 + grass-track + A race competed on turf + none + 1 + 1 + 0 + + + + 15041004 + moto-ball + Team sport where drivers play a ball + none + 1 + 1 + 0 + + + + 15041005 + moto-cross + Raced over dirt tracks featuring severe mounds + none + 1 + 1 + 0 + + + + 15041006 + rallying + Races run over regular roads + none + 1 + 1 + 0 + + + + 15041007 + trial + A race of consistency and endurance over varied terrain + none + 1 + 1 + 0 + + + + 15041008 + endurance + A road race of consistency and endurance + none + 1 + 1 + 0 + + + + 15041009 + superbike + Engine size + none + 1 + 1 + 0 + + + + 15041010 + 125 cm3 + Engine size + none + 1 + 1 + 0 + + + + 15041011 + 250 cm3 + Engine size + none + 1 + 1 + 0 + + + + 15041012 + 500 cm3 + Engine size + none + 1 + 1 + 0 + + + + 15041013 + side-cars + Of different engine sizes but attached to a side car featuring a passenger + none + 1 + 1 + 0 + + + + 15041014 + motoGP + Capacity class 1000ccm + none + 12 + 12 + 0 + + + + 15042000 + netball + A woman's sport similar to basketball without a board behind the basket + typo fixed in Explanation + 17 + 1 + 0 + + + + 15043000 + nordic skiing + Practiced in snowy countryside and based on power and endurance. There are classic and free style events with mass or staggered starts. + none + 1 + 1 + 0 + + + + 15043001 + cross-country + Nordic ski race + none + 1 + 1 + 0 + + + + 15043002 + 5 km classical time + A 5km classic race in that the competitor keeps his skis parallel except on steep inclines where the scissor move is used + none + 1 + 1 + 0 + + + + 15043003 + 10 km classical style + A 10km classic race in that the competitor keeps his skis parallel except on steep inclines where the scissor move is used + none + 1 + 1 + 0 + + + + 15043004 + 10 km pursuit free style + Staggered start depending on positions with competitors using a skating like technique on skis + none + 1 + 1 + 0 + + + + 15043005 + 15 km classical style + A 15km race using the classical style of keeping skies parallel + none + 1 + 1 + 0 + + + + 15043006 + 15 km pursuit free style + 15km race with staggered start using free style technique similar to a skating motion + none + 1 + 1 + 0 + + + + 15043007 + 10 km + 15 km combined + 10km classic followed by 15km free-style race + none + 1 + 1 + 0 + + + + 15043008 + 30 km classical style + A 30km classic race in that the competitor keeps his skis parallel except on steep inclines where the scissor move is used + none + 1 + 1 + 0 + + + + 15043009 + 30km free style + A 30km free-style race where the most common style is the skate style where competitors slide and the skis do not need to be parallel + none + 1 + 1 + 0 + + + + 15043010 + 50 km free style + A 50km free style race where the most common style is the skate style where competitors slide and the skis do not need to be parallel + none + 1 + 1 + 0 + + + + 15043011 + 4x5 km relay + Teams of four competitors ski 5km each in relay fashion + none + 1 + 1 + 0 + + + + 15043012 + 4x10 km relay + Teams of four competitors ski 10km each in relay fashion + typo fixed in Explanation + 17 + 1 + 0 + + + + 15043013 + nordic combined + A two day competition combining the ski jump and a cross-country race. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15043014 + raid + NA + none + 1 + 1 + 0 + + + + 15043015 + 5 km pursuit free style + Cross-country skiing over a 5km course in a pursuit format + none + 1 + 1 + 0 + + + + 15043016 + 1.5 km sprint free + Cross-country skiing over a 1.5km course in a sprint format + none + 1 + 1 + 0 + + + + 15043017 + 50 km classic style + Cross-country skiing over a 50km course in a classic style format + none + 1 + 1 + 0 + + + + 15044000 + orienteering + An individual time-trial over a route marked out by beacons. The competitor has to search out and find in a specific order. The contestant makes his way with the help of a compass and map + none + 1 + 1 + 0 + + + + 15044001 + ski orienteering + An individual ski time-trial over a route marked out by beacons, that the competitor has to search out and find in a specific order. The contestant makes his way with the help of a compass and map + none + 1 + 1 + 0 + + + + 15045000 + polo + With the aid of a mallet two teams of four horsemen try and knock a bamboo ball into the opponents goal over a pitch 250m long and 150m wide. The game is divided into 4, 6, or 8 time periods of 7min 30sec called chukkas. + none + 1 + 1 + 0 + + + + 15046000 + power boating + Races between motor boats on rivers or lakes + none + 1 + 1 + 0 + + + + 15046001 + F1 + Sprint race + none + 1 + 1 + 0 + + + + 15046002 + F2 + Long distance race + none + 1 + 1 + 0 + + + + 15047000 + rowing + Boat racing usually on flat calm waters with boats for 1, 2, 4 or 8 rowers + none + 1 + 1 + 0 + + + + 15047001 + single sculls + Single person boats with two oars + none + 1 + 1 + 0 + + + + 15047002 + double sculls + Two person boats with two oars each + none + 1 + 1 + 0 + + + + 15047003 + quadruple sculls + Four person boats with two oars each and without a team mate to give directions + none + 1 + 1 + 0 + + + + 15047004 + coxless pair + Two person boats with just one oar each and without a team mate to give directions + none + 1 + 1 + 0 + + + + 15047005 + coxless four + Four person boats with just one oar each and without a team mate to give directions + none + 1 + 1 + 0 + + + + 15047006 + eight + Eight person boats with just one oar each and without a team mate to give directions + none + 1 + 1 + 0 + + + + 15047007 + lightweight + Where a weight category is imposed on competitors + none + 1 + 1 + 0 + + + + 15048000 + rugby league + Two teams of 13 compete on a pitch where they score tries and penalties by running with and passing an oval ball to be touched down behind the goal line or kicked between goal posts in a tough physical contest + none + 1 + 1 + 0 + + + + 15049000 + rugby union + Two teams of 15 compete on a pitch where they score tries and penalties by running with and passing an oval ball to be touched down behind the goal line or kicked between goal posts in a tough physical contest + none + 1 + 1 + 0 + + + + 15049001 + rugby 7 + A more fun and exciting variety where two teams of 7 compete on a pitch where they score tries and penalties by running with and passing an oval ball to be touched down behind the goal line or kicked between goal posts in a tough physical contest + none + 1 + 1 + 0 + + + + 15050000 + sailing + Sail boat racing over a route marked by buoys. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15050001 + Tornado + Boat Category: two man catamaran (21m/sq mainsail) Olympic sport + none + 1 + 1 + 0 + + + + 15050002 + soling + Boat Category: three man keel boat + none + 1 + 1 + 0 + + + + 15050003 + 49er + Boat Category: two man dinghy (8.23m/sq mainsail) Olympic sport + none + 1 + 1 + 0 + + + + 15050004 + Europe + Boat Category: one man dinghy (4.57m/sq mainsail) Olympic sport + none + 1 + 1 + 0 + + + + 15050005 + Laser + Boat Category: one man dinghy (4.6m/sq mainsail) Olympic sport + none + 1 + 1 + 0 + + + + 15050006 + 470 + Boat Category: two man dinghy (7.10m/sq mainsail) Olympic sport + none + 1 + 1 + 0 + + + + 15050007 + Finn + Boat Category: one man dinghy (10m/sq mainsail) Olympic sport + none + 1 + 1 + 0 + + + + 15050008 + Star + Boat Category: two man keel boat (7.10m/sq mainsail) Olympic sport + none + 1 + 1 + 0 + + + + 15050009 + flying dutchmann + Boat Category: two man dinghy + none + 1 + 1 + 0 + + + + 15050010 + 505 + Boat Category: two man dinghy + none + 1 + 1 + 0 + + + + 15050011 + staging race + Sea racing + none + 1 + 1 + 0 + + + + 15050012 + around the world + Open seas racing + none + 1 + 1 + 0 + + + + 15050013 + monohull + Single hull craft + none + 1 + 1 + 0 + + + + 15050014 + multihulls + Multi hull craft + none + 1 + 1 + 0 + + + + 15050015 + yngling + Olympic boat-class. A race around different courses in a boat of 6.35 metres (20ft 10in) long and 1.73 metres (5ft 8in) wide, crewed in Olympic competition only by women. The number of races and the length of the courses varies. + none + 12 + 12 + 0 + + + + 15050016 + mistral + Olympic boat class. A staged race using boats of the mistral type, which are 4.24 metres (13ft 11in) long and 1.3 metres (4ft 3in) wide. The number of races and the length of the courses varies. + none + 12 + 12 + 0 + + + + 15051000 + shooting + Precision sport using a hand gun, rifle or shotgun + none + 1 + 1 + 0 + + + + 15051001 + 10 m air rifle + Shooting event + none + 1 + 1 + 0 + + + + 15051002 + 10 m air pistol + Shooting event + none + 1 + 1 + 0 + + + + 15051003 + 10 m running target + Shooting event + none + 1 + 1 + 0 + + + + 15051004 + 25 m rapid fire pistol + Shooting event + none + 1 + 1 + 0 + + + + 15051005 + 25 m sport pistol + Shooting event + none + 1 + 1 + 0 + + + + 15051006 + 50 m free pistol + Shooting event + none + 1 + 1 + 0 + + + + 15051007 + 50 m free rifle prone + Shooting event + none + 1 + 1 + 0 + + + + 15051008 + 50 m free rifle 3x40 + Shooting event + none + 1 + 1 + 0 + + + + 15051009 + 50 m sport rifle 3x20 + Shooting event + none + 1 + 1 + 0 + + + + 15051010 + trap + Shooting event with moving targets + none + 1 + 1 + 0 + + + + 15051011 + double trap + Shooting event with two moving targets launched at the same time + none + 1 + 1 + 0 + + + + 15051012 + skeet + Shooting event with moving targets, competitor shoots from a series of positions + none + 1 + 1 + 0 + + + + 15052000 + ski jumping + Competitors descend a snow covered elevated ramp on skis and try to fly off it as far as possible, receiving marks for distance, style of flight and landing + typo fixed in Explanation + 17 + 1 + 0 + + + + 15052001 + K90 jump + Competitors jump from 70m and must clear 90m distance in their jump before scoring points for it + typo fixed in Explanation + 17 + 1 + 0 + + + + 15052002 + K120 jump + Competitors jump from 90m and must clear 120m distance in their jump before scoring points for it + none + 1 + 1 + 0 + + + + 15052003 + K180 (flying jump) + Competitors jump from 180m and must clear 180m in their jump before scoring points for it + none + 1 + 1 + 0 + + + + 15053000 + snow boarding + Practiced with a single board (rather than two skis) + none + 1 + 1 + 0 + + + + 15053001 + giant slalom + Knock-out head-to-head downhill racing + none + 1 + 1 + 0 + + + + 15053002 + half-pipe + Over a semi-cylindrical tube of 100m competitors must perform a series of moves that are marked for style by 5 judges + typo fixed in Explanation + 17 + 1 + 0 + + + + 15054000 + soccer + Two teams of eleven try to kick or head a ball into the opponents goal over a match usually of 90 minutes + none + 1 + 1 + 0 + + + + 15055000 + softball + Similar to baseball but with a larger and softer ball, a thinner bat, shorter gaps between bases and less innings + typo fixed in Explanation + 17 + 1 + 0 + + + + 15056000 + speed skating + Timed races competed by two skaters at a time on an oval ice track + none + 1 + 1 + 0 + + + + 15056001 + 500 m + Speed skating race over 500m + none + 1 + 1 + 0 + + + + 15056002 + 1000 m + Speed skating race over 1000m + none + 1 + 1 + 0 + + + + 15056003 + 1500 m + Speed skating race over 1500m + none + 1 + 1 + 0 + + + + 15056004 + 3000 m + Speed skating race over 3000m + none + 1 + 1 + 0 + + + + 15056005 + 5000 m + Speed skating race over 5000m + none + 1 + 1 + 0 + + + + 15056006 + 10000 m + Speed skating race over 10000m + none + 1 + 1 + 0 + + + + 15056007 + Short-track + Races of four or more skaters on an oval ice track. Qualifying, semi-finals and finals determine winners. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15056008 + st 500 m + Short track speed skate race over 500m + none + 1 + 1 + 0 + + + + 15056009 + st 1000m + Short track speed skate race over 1000m + none + 1 + 1 + 0 + + + + 15056010 + st 1500m + Short track speed skate race over 1500m + none + 1 + 1 + 0 + + + + 15056011 + st 3000m + Short track speed skate race over 3000m + none + 1 + 1 + 0 + + + + 15056012 + st 3000m relay + Short track relay speed skate race over 3000m + none + 1 + 1 + 0 + + + + 15056013 + st 5000m + Short track speed skate race over 5000m + none + 1 + 1 + 0 + + + + 15056014 + st 5000m relay + Short track relay speed skate race over 5000m + none + 1 + 1 + 0 + + + + 15057000 + speedway + Fast track + none + 1 + 1 + 0 + + + + 15058000 + sports organisations + Organisations responsible for a specific sport + typo fixed in Explanation + 17 + 1 + 0 + + + + 15058001 + IOC + International Olympic Committee + none + 1 + 1 + 0 + + + + 15058002 + international federation + A body responsible for the international coordination of a specific sport + none + 1 + 1 + 0 + + + + 15058003 + continental federation + A body responsible for the continental coordination of a specific sport + none + 1 + 1 + 0 + + + + 15058004 + national federation + A body responsible for the national coordination of a specific sport + none + 1 + 1 + 0 + + + + 15058005 + GAISF + General Association of International Sports Federations + none + 1 + 1 + 0 + + + + 15059000 + squash + A racket sport of strategy and endurance played by singles or doubles teams in a walled court with a small rubber ball + typo fixed in Explanation + 17 + 1 + 0 + + + + 15060000 + sumo wrestling + A combat sport of speed and rapidity with much ceremony where two contestants try to throw or slap a competitor out of a marked area. Generally practiced in Japan by large men. + none + 17 + 1 + 0 + + + + 15061000 + surfing + Water sport where contestants catch and ride waves upright on a surfboard + none + 1 + 1 + 0 + + + + 15062000 + swimming + A water sport where contestants swim as fast as possible in a given style and win races by being the first to touch home + none + 1 + 1 + 0 + + + + 15062001 + 50 m freestyle + Competitors cover 50m in any style, though front crawl is universally employed + none + 1 + 1 + 0 + + + + 15062002 + 100 m freestyle + Competitors cover 100m in any style, though front crawl is universally employed + none + 1 + 1 + 0 + + + + 15062003 + 200 m freestyle + Competitors cover 200m in any style, though front crawl is universally employed + none + 1 + 1 + 0 + + + + 15062004 + 400 m freestyle + Competitors cover 400m in any style, though front crawl is universally employed + none + 1 + 1 + 0 + + + + 15062005 + 800 m freestyle + Competitors cover 800m in any style, though front crawl is universally employed + none + 1 + 1 + 0 + + + + 15062006 + 1500 m freestyle + Competitors cover 1500m in any style, though front crawl is universally employed + none + 1 + 1 + 0 + + + + 15062007 + relay 4x50 m freestyle + Teams of four swimmers cover 50m freestyle in a 200m race + none + 1 + 1 + 0 + + + + 15062008 + relay 4x100 m freestyle + Teams of four swimmers cover 100m freestyle in a 400m race + none + 1 + 1 + 0 + + + + 15062009 + relay 4x200 m freestyle + Teams of four swimmers cover 200m freestyle in a 800m race + none + 1 + 1 + 0 + + + + 15062010 + 50 m backstroke + Competitors cover 50m in the backstroke style + none + 1 + 1 + 0 + + + + 15062011 + 100 m backstroke + Competitors cover 100m in the backstroke style + none + 1 + 1 + 0 + + + + 15062012 + 200 m backstroke + Competitors cover 200m in the backstroke style + none + 1 + 1 + 0 + + + + 15062013 + 50 m breaststroke + A 50m race in the breaststroke style, on the front, effecting forward and outward push movements with the arms and backward and outward pushes with the legs + none + 1 + 1 + 0 + + + + 15062014 + 100 m breaststroke + A 100m race in the breaststroke style, on the front, effecting forward and outward push movements with the arms and backward and outward pushes with the legs + none + 1 + 1 + 0 + + + + 15062015 + 200 m breaststroke + A 200m race in the breaststroke style, on the front, effecting forward and outward push movements with the arms and backward and outward pushes with the legs + none + 1 + 1 + 0 + + + + 15062016 + 50 m butterfly + A 50m butterfly race, swum on the front with the shoulders remaining parallel to the water both arms moving in simultaneous windmill fashion, the legs remain together and are moved in a flapping motion. The most physical of all styles. + none + 1 + 1 + 0 + + + + 15062017 + 100 m butterfly + A 100m butterfly race, swum on the front with the shoulders remaining parallel to the water both arms moving in simultaneous windmill fashion, the legs remain together and are moved in a flapping motion. The most physical of all styles + none + 1 + 1 + 0 + + + + 15062018 + 200 m butterfly + A 200m butterfly race, swum on the front with the shoulders remaining parallel to the water both arms moving in simultaneous windmill fashion, the legs remain together and are moved in a flapping motion. The most physical of all styles + none + 1 + 1 + 0 + + + + 15062019 + 100 m medley + Swimmers complete four laps, each in a different style and in this order: butterfly, backstroke, breaststroke and freestyle, covering a total of 100m. + none + 1 + 1 + 0 + + + + 15062020 + 200 m medley + Swimmers complete four laps, each in a different style and in this order: butterfly, backstroke, breaststroke and freestyle, covering a total of 200m. + none + 1 + 1 + 0 + + + + 15062021 + 400 m medley + Swimmers complete eight laps, two in each style and in this order: butterfly, backstroke, breaststroke and freestyle, covering a total of 400m. + none + 1 + 1 + 0 + + + + 15062022 + relay 4x50 m medlay + A relay team of four, each of whom completes a single lap and each in a different style in this order: backstroke, breaststroke, butterfly and freestyle in a race of 200m total. + none + 1 + 1 + 0 + + + + 15062023 + relay4x100 m medley + A relay team of four, each of whom completes two laps and each in a different style in this order: backstroke, breaststroke, butterfly and freestyle in a race of 400m total. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15062024 + short course + Races competed in a 25m length pool + none + 1 + 1 + 0 + + + + 15062025 + synchronised technical routine + Contestants obtain points from 10 sitting judges by executing certain synchronised artistic shapes and movements in the water. In the technical programme, competitors must execute a range of specific moves in a given order. + none + 1 + 1 + 0 + + + + 15062026 + synchronised free routine + In the free programme, music, movements and their order of execution are not restricted. + none + 1 + 1 + 0 + + + + 15063000 + table tennis + A racket sport for two or four (in doubles), who compete at a table divided by a net using a small bat to play a lightweight ball + typo fixed in Explanation + 17 + 1 + 0 + + + + 15064000 + Taekwon-Do + A martial art of Korean origin + none + 1 + 1 + 0 + + + + 15064001 + under 49 kg + Weight category + none + 1 + 1 + 0 + + + + 15064002 + under 58 kg + Weight category + none + 1 + 1 + 0 + + + + 15064003 + 49-57 kg + Weight category + none + 1 + 1 + 0 + + + + 15064004 + 58-68 kg + Weight category + none + 1 + 1 + 0 + + + + 15064005 + 57-67 kg + Weight category + none + 1 + 1 + 0 + + + + 15064006 + 68-80 kg + Weight category + none + 1 + 1 + 0 + + + + 15064007 + over 67 kg + Weight category + none + 1 + 1 + 0 + + + + 15064008 + over 80 kg + Weight category + none + 1 + 1 + 0 + + + + 15065000 + tennis + A sport where two players, four in doubles, equipped with a racket compete by hitting the ball over a net into the opponent's side of the court with the aim of putting it out of reach within the regulation lines, thus winning points. + none + 1 + 1 + 0 + + + + 15065001 + soft tennis + Tennis with a soft rubber ball. (Programme of National Sports Festival in Japan) + none + 12 + 12 + 0 + + + + 15066000 + triathlon + An endurance multi-sport where competitors first swim, then cycle and then run a road race. Distances vary according to the competition, the Olympic version being 1.5, 40 and 10km respectively. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15066001 + triathlon swimming + Triathlon event + none + 1 + 1 + 0 + + + + 15066002 + triathlon cycling + Triathlon event + none + 1 + 1 + 0 + + + + 15066003 + triathlon run + Triathlon event + none + 1 + 1 + 0 + + + + 15067000 + volleyball + Two teams of six record points by hitting a ball over a net into the opponent's half of the court, keeping it in the air at all times. Points are won when opponents fail to return the ball. + none + 1 + 1 + 0 + + + + 15067001 + beach volleyball + Two teams of two players compete on a sand court. Unlike indoor volleyball, points are scored only when the serving team wins a rally or forces an error. The sand surface makes it more physically demanding than volleyball. + none + 1 + 1 + 0 + + + + 15068000 + water polo + Played in a pool between two teams of 7, who must stay afloat and can only use one hand to pass the ball or swim with it before trying to throw it into the opponents net to score goals. + typo fixed in Explanation + 17 + 1 + 0 + + + + 15069000 + water skiing + On one or two skis contestants are pulled by a power boat along the water's surface + none + 1 + 1 + 0 + + + + 15069001 + slalom + Speed event where contestants round a course marked out by buoys + typo fixed in Explanation + 17 + 1 + 0 + + + + 15069002 + trick + Skiers perform a maximum of figures in a limited time period + none + 1 + 1 + 0 + + + + 15069003 + jump + Skiers perform as long a jump as possible from a ramp in the water + none + 1 + 1 + 0 + + + + 15069004 + combined + A combined event made up of the slalom, jump and trick + none + 1 + 1 + 0 + + + + 15070000 + weightlifting + A strength test where competitors lift as heavy a weight as possible + none + 1 + 1 + 0 + + + + 15070001 + snatch + The bar must be lifted from floor to above the head in one movement + none + 1 + 1 + 0 + + + + 15070002 + clean and jerk + The bar is first lifted to the shoulders and then jerk it above the head and keep it there while maintaining straight legs + none + 1 + 1 + 0 + + + + 15070003 + 48 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070004 + 53 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070005 + 63 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070006 + 75 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070007 + over 75 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070008 + 56 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070009 + 62 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070010 + 69 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070011 + 77 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070012 + 85 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070013 + 94 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070014 + 105 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070015 + over 105 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15070016 + powerlifting + A strength test where competitors lift as heavy a weight as possible + none + 1 + 1 + 0 + + + + 15071000 + windsurfing + Contestants must complete a marked out course as fast as possible on a windsurf board + none + 1 + 1 + 0 + + + + 15071001 + ocean + Races on the open seas + none + 1 + 1 + 0 + + + + 15071002 + lake + Races competed on lakes + none + 1 + 1 + 0 + + + + 15071003 + river + Races competed on rivers + none + 1 + 1 + 0 + + + + 15071004 + land + Races competed on land with a board equipped with wheels + typo fixed in Explanation + 17 + 1 + 0 + + + + 15072000 + wrestling + Combat sport where each wrestler attempts to win over his adversary, by holding both shoulders on the ground (fall) long enough to be in control. Points can also be decisive. + none + 1 + 1 + 0 + + + + 15072001 + freestyle + A style where leg holds are allowed + none + 1 + 1 + 0 + + + + 15072002 + greco-roman + A style where the only holds allowed are those between the head and the belt + none + 1 + 1 + 0 + + + + 15072003 + over 130 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15072004 + 130 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15072005 + 97 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15072006 + 85 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15072007 + 76 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15072008 + 69 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15072009 + 63 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15072010 + 58 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15072011 + 54 kg + Competitor weight category + none + 1 + 1 + 0 + + + + 15072012 + Swiss wrestling + Traditional Swiss sport similar to wrestling with specific rules + none + 11 + 11 + 0 + + + + 15073000 + sports event + Sports meeting + none + 1 + 1 + 0 + + + + 15073001 + Summer Olympics + Summer Olympics + none + 1 + 1 + 0 + + + + 15073002 + Winter Olympics + Winter Olympics + none + 1 + 1 + 0 + + + + 15073003 + Summer universiade + Summer universiade + none + 1 + 1 + 0 + + + + 15073004 + Winter Universiade + Winter Universiade + none + 1 + 1 + 0 + + + + 15073005 + Commonwealth Games + Commonwealth Games + none + 1 + 1 + 0 + + + + 15073006 + Winter Goodwill Games + Winter Goodwill Games + none + 1 + 1 + 0 + + + + 15073007 + Summer Asian Games + Summer Asian Games + none + 1 + 1 + 0 + + + + 15073008 + Winter Asian Games + Winter Asian Games + none + 1 + 1 + 0 + + + + 15073009 + Panamerican Games + Panamerican Games + none + 1 + 1 + 0 + + + + 15073010 + African Games + African Games + none + 1 + 1 + 0 + + + + 15073011 + Mediterranean Games + Mediterranean Games + none + 1 + 1 + 0 + + + + 15073012 + SouthEast Asiatic Games + SouthEast Asiatic Games + none + 1 + 1 + 0 + + + + 15073013 + PanPacific Games + PanPacific Games + none + 1 + 1 + 0 + + + + 15073014 + SouthPacific Games + SouthPacific Games + none + 1 + 1 + 0 + + + + 15073015 + PanArabic Games + PanArabic Games + none + 1 + 1 + 0 + + + + 15073016 + Summer Goodwill Games + Summer Goodwill Games + none + 1 + 1 + 0 + + + + 15073017 + World games + A competition featuring world class athletes + none + 1 + 1 + 0 + + + + 15073018 + World Cup + Sports meeting with competitors from the five continents + none + 1 + 1 + 0 + + + + 15073019 + intercontinental cup + Sports meeting bringing together competitors from different continents + typo fixed in Explanation + 17 + 1 + 0 + + + + 15073020 + continental cup + Sports meeting where competitors come from a single continent + none + 1 + 1 + 0 + + + + 15073021 + international cup + Sports meeting where competitors come from several nations + none + 1 + 1 + 0 + + + + 15073022 + National Cup + Sports meeting where competitors come from a single nation + none + 1 + 1 + 0 + + + + 15073023 + interregional cup + Sports meeting where competitors come from several regions + none + 1 + 1 + 0 + + + + 15073024 + regional cup + Sports meeting where competitors come from a single region + none + 1 + 1 + 0 + + + + 15073025 + league cup + A competition within a sports league + none + 1 + 1 + 0 + + + + 15073026 + world championship + A championship where competitors from the five continents take part + none + 1 + 1 + 0 + + + + 15073027 + intercontinental championship + A championship where competitors from the different continents take part + none + 1 + 1 + 0 + + + + 15073028 + continental championship 1st level + A championship where top level competitors from a single continent take part + none + 1 + 1 + 0 + + + + 15073029 + continental championship 2nd level + A championship where second string competitors from a single continent take part + none + 1 + 1 + 0 + + + + 15073030 + continental championship 3rd level + A championship where third string competitors from a single continent take part + none + 1 + 1 + 0 + + + + 15073031 + national championship 1st level + A championship where top level competitors from a single nation take part + none + 1 + 1 + 0 + + + + 15073032 + national championship 2nd level + A championship where second string competitors from a single continent take part + none + 1 + 1 + 0 + + + + 15073033 + national championship3rdlevel + A championship where third string competitors from a single continent take part + none + 1 + 1 + 0 + + + + 15073034 + national championship 4th level + A championship where fourth string competitors from a single continent take part + none + 1 + 1 + 0 + + + + 15073035 + regional championship + A championship where competitors from a single region take part + none + 1 + 1 + 0 + + + + 15073036 + Grand Prix + High level sports competition, most often motor racing + none + 1 + 1 + 0 + + + + 15073037 + intercontinental tournament + Tournament where competitors from several continents take part + none + 1 + 1 + 0 + + + + 15073038 + continental tournament + Tournament where competitors from a single continent take part + none + 1 + 1 + 0 + + + + 15073039 + international tournament + Tournament where competitors from several nations take part + none + 1 + 1 + 0 + + + + 15073040 + national tournament + Tournament where competitors from a single nation take part + none + 1 + 1 + 0 + + + + 15073041 + inter-nations competition + Tournament where athletes from several nations take part + none + 1 + 1 + 0 + + + + 15073042 + inter-clubs competition + Tournament where competitors from several clubs take part + none + 1 + 1 + 0 + + + + 15073043 + friendly competition + Sports played but not in a tournament + none + 1 + 1 + 0 + + + + 15073044 + all-stars competition + Competition between teams made up of invited stars + none + 1 + 1 + 0 + + + + 15073045 + exhibition + demonstration + none + 1 + 1 + 0 + + + + 15073046 + Super Bowl + The American football final that determines the champion + none + 9 + 9 + 0 + + + + 15073047 + paralympic games + Olympic style Games for athletes with a disability + none + 15 + 15 + 0 + + + + 15074000 + rodeo + A discipline where wild horses or bulls must be mounted and mastered + none + 1 + 1 + 0 + + + + 15074001 + barrel racing + Rodeo discipline + none + 1 + 1 + 0 + + + + 15074002 + calf roping + Rodeo discipline + none + 1 + 1 + 0 + + + + 15074003 + bull riding + Rodeo discipline + none + 1 + 1 + 0 + + + + 15074004 + bulldogging + Rodeo discipline + none + 1 + 1 + 0 + + + + 15074005 + saddle bronc + Rodeo discipline + none + 1 + 1 + 0 + + + + 15074006 + bareback + Rodeo discipline + none + 1 + 1 + 0 + + + + 15074007 + goat roping + Rodeo discipline + none + 1 + 1 + 0 + + + + 15075000 + mini golf sport + A game where balls must be holed on an artificial course in as few strokes from the club as possible + none + 1 + 1 + 0 + + + + 15076000 + bandy + Played outdoors on ice. The size of the ice rink is about the size of a soccer field. Skates like ice hockey. A small hard ball is used for playing. Players play with sticks, much like in ice hockey, but the sticks are shorter and more rounded. + Explanation shortened + 17 + 1 + 0 + + + + 15077000 + flying disc + A group of events all played with a flying plastic disc. The exact regulation for the disc is different in different events but it has to be unbroken of solid plastic and a production model with no modification. Flying disc is sometimes called Frisbee. + Explanation shortened + 17 + 1 + 0 + + + + 15077001 + ultimate + Team game. Played outdoors on soccer-size field with 7 players per team and indoors with 5 players per team. Games are played to a preset number of goals. Goals are scored by passing the disc to a team-member catching it inside the goal area. + Explanation shortened + 17 + 1 + 0 + + + + 15077002 + guts + Team game where two teams of 5 players each face each other. Teams take turns to throw the disc towards the other team. Points are scored if the opposing team does not catch the disc. + none + 1 + 1 + 0 + + + + 15077003 + overall + Not an event in itself but in most competitions with individual events the winner of the competition will be awarded to the player with the highest combined score in the events. + none + 1 + 1 + 0 + + + + 15077004 + distance + The object is to throw the disc as far as possible. Each player get five throws per turn. Throws are made downwind. World record is over 200 meters. + none + 1 + 1 + 0 + + + + 15077005 + discathon + The object is to throw and run a park course of about 1 kilometre. Four players compete in each heat. They have two discs each. They may also carry a third disc in reserve. Where one thrown disc stops the second disc must be thrown. + Explanation shortened + 17 + 1 + 0 + + + + 15077006 + DDC + Abbreviation for Double Disc Court. Two players per team in a square 13x13 metre. The teams start with one disc per team and throw at each other. Discs are thrown back and forth until one or both hit the ground. + Explanation shortened + 17 + 1 + 0 + + + + 15077007 + SCF + Abbreviation for Self Caught Flights. Divided into two sub events called MTA (Maximum Time Aloft) and TRC (Throw Run Catch). In both sub events the player throws a disc and then runs to catch it with one hand before it hits the ground. + Explanation shortened + 17 + 1 + 0 + + + + 15077008 + freestyle + A judged event where groups of two or three players perform as many tricks as possible. In competitions the judges can use either a ranking system or set scores on presentation, execution and difficulty. + none + 1 + 1 + 0 + + + + 15077009 + accuracy + Each player has 28 throws from various distances and angles to throw the disc through a goal 1.5 x 1.5 meters. World record is 25 of 28 possible. + none + 1 + 1 + 0 + + + + 15077010 + disc golf + Much like golf but played with discs instead of balls and clubs. Instead of a hole in the ground there is a metal basket with light metal chains to throw the disc at. Players often carry discs specialized for long throws, right or left bends. + Explanation shortened + 17 + 1 + 0 + + + + 15078000 + floorball + Played indoors in a court the size of a basketball court. 6 players per team, of which one is a who plays in a kneeling position without a stick like in ice hockey. The other players use plastic clubs and a light plastic ball to pass and shoot goals. + Explanation shortened + 17 + 1 + 0 + + + + 15079000 + casting + Using fishing equipment to hit a target and score points + none + 1 + 1 + 0 + + + + 15080000 + tug-of-war + Two teams pulling against each other on a rope + none + 1 + 1 + 0 + + + + 15081000 + croquette + Using mallets to hit a ball through hoops + none + 1 + 1 + 0 + + + + 15082000 + dog racing + Dogs racing around a track + none + 1 + 1 + 0 + + + + 15082001 + sled + Harnessed to a sled + none + 1 + 1 + 0 + + + + 15082002 + oval track + Pursuing an artificial rabbit around an oval track + none + 1 + 1 + 0 + + + + 15083000 + skeleton + In skeleton the competitor lays on his/hers stomach when racing down the course. The competitor must be on the sled when crossing the finishing line. The total time of all races in a competition is added together. + Explanation shortened + 17 + 1 + 0 + + + + 15084000 + Australian rules football + Football played under Australian rules + none + 1 + 1 + 0 + + + + 15085000 + Canadian football + Football played under Canadian rules + none + 1 + 1 + 0 + + + + 15086000 + duathlon + Duathlon + none + 11 + 11 + 0 + + + + 15087000 + hornuss + Swiss team sport with 16 or 18 men per team. A rubber puck is hit towards the field of the adversary team which tries to hit the puck in the air with a wooden board thrown in the air + none + 11 + 11 + 0 + + + + 15088000 + fist ball + Men's team sport similar to volleyball (with a much lower net) executed mainly in gymnastics clubs + none + 11 + 11 + 0 + + + + 15089000 + inline skating + Competitive sports using inline skates + none + 11 + 11 + 0 + + + + 15090000 + grass ski + Alpine skiing on roller skis and grass + none + 11 + 11 + 0 + + + + 15091000 + snowbiking + Individual sport on snow on a snow bike, the athlete has two mini skis, previous name: ski bob + none + 11 + 11 + 0 + + + + 15092000 + twirling + Team competition with majorettes and a jury + none + 11 + 11 + 0 + + + + 15093000 + kendo + Japanese traditional martial art using a bamboo sword, sometimes called Japanese fencing. (Programme of National Sports Festival in Japan) + none + 12 + 12 + 0 + + + + 15094000 + jukendo + Japanese traditional martial art using a model rifle made of wood. "Juken" means a rifle or gun with blade (bayonet). (Programme of National Sports Festival in Japan) + none + 12 + 12 + 0 + + + + 15095000 + naginata + Japanese traditional martial art using a pole sword made of wood. "Naginata" means a spear with a curved blade. (Programme of National Sports Festival in Japan) + none + 12 + 12 + 0 + + + + 15096000 + kyudo + Japanese traditional martial art using a bamboo bow and arrows, sometimes called Japanese archery. (Programme of National Sports Festival in Japan) + none + 12 + 12 + 0 + + + + 15097000 + kabaddi + The attacking side scores by touching, and the side to guard scores by capturing. The attacker continues calling it "kabaddi". + none + 12 + 12 + 0 + + + + 15098000 + sepak takraw + The game like volleyball which must not use a hand. The ball made of rattan is used. (Programme of National Sports Festival in Japan) + none + 12 + 12 + 0 + + + + 15099000 + wushu + Generally, Chinese traditional martial art. (Programme of National Sports Festival in Japan) + none + 12 + 12 + 0 + + + + 15100000 + darts + Two players compete by throwing metal darts at a wall-mounted circular board divided radially into segments of different scores + none + 17 + 17 + 0 + + + + 15101000 + bodybuilding + A person displays pronounced muscle tone and exaggerated muscle mass and definition for overall aesthetic effect + none + 17 + 17 + 0 + + + + 15102000 + sports disciplinary action + Actions, including fines and suspensions levied by sports organisations and teams + none + 18 + 18 + 0 + + + + 15103000 + sports awards + Awards and honors given by sports organisations or won by sports figures + none + 18 + 18 + 0 + + + + 16000000 + unrest, conflicts and war + Acts of socially or politically motivated protest and/or violence. + none + 1 + 1 + 0 + + + + 16001000 + act of terror + Act of violence, often deadly, designed to raise fear and anxiety in a population + none + 1 + 1 + 0 + + + + 16002000 + armed conflict + Disputes between opposing groups involving the use of weaponry, but not formally declared a war + none + 1 + 1 + 0 + + + + 16003000 + civil unrest + Dissatisfaction among the general population as evidenced by rallies, strikes, demonstrations or sabotage + none + 1 + 1 + 0 + + + + 16003001 + revolutions + An often violent change in a nation's system of government by internal forces that results in systematic social change. + none + 9 + 9 + 0 + + + + 16003002 + rebellions + Armed uprising by citizens of a nation with the intent to overthrow the government, without necessarily achieving social change + none + 9 + 9 + 0 + + + + 16003003 + political dissent + Disagreement between political groups, usually organized and sometimes resulting in imprisonment of the dissenters + none + 9 + 9 + 0 + + + + 16003004 + religious conflict + Conflicts involving religious differences + none + 9 + 9 + 0 + + + + 16003005 + social conflict + Conflicts involving social differences + none + 9 + 9 + 0 + + + + 16004000 + coup d'etat + The overthrow of an established government by an organized group, often the military or a political party + none + 1 + 1 + 0 + + + + 16005000 + guerrilla activity + Anti-government actions by clandestine groups using hit-and-run techniques or sabotage, kidnapping and the like + none + 1 + 1 + 0 + + + + 16005001 + bioterrorism + Use of biological agent to raise the level of fear within a population, whether deaths occur or not. + none + 9 + 9 + 0 + + + + 16005002 + bombings + Use of explosive devices against people, buildings or structures + none + 9 + 9 + 0 + + + + 16006000 + massacre + The death of a large group of people over a brief period of time + none + 1 + 1 + 0 + + + + 16006001 + genocide + Systematic killing of one clan, tribe or ethnic type by another + none + 9 + 9 + 0 + + + + 16007000 + riots + Violent, destructive demonstrations often involving injury to individuals and destruction of property + none + 1 + 1 + 0 + + + + 16008000 + demonstration + A public show of feeling or opinion, as by a mass meeting or parade + to version 9: violent demonstration + 11 + 11 + 0 + + + + 16009000 + war + A formal declaration of hostilities by one country against another + none + 1 + 1 + 0 + + + + 16009001 + civil war + Armed conflict between members of the same nation or geographical region, in some cases with a desire to divide the nation or region. + none + 9 + 9 + 0 + + + + 16009002 + international military intervention + Temporary use of international forces by invitation or by a decision of an outside body in another country or region for the purpose of resolving a crisis. + none + 9 + 9 + 0 + + + + 16009003 + prisoners and detainees + People captured and imprisoned by their enemy during war or armed conflict + none + 11 + 11 + 0 + + + + 16010000 + conflict (general) + A dispute which can be at several levels, + none + 1 + 1 + 0 + + + + 16010001 + peacekeeping force + Varied national military forces under unified international command to maintain order in disputed areas. + none + 15 + 15 + 0 + + + + 16011000 + crisis + Conflict of all kinds that rises to a level where, depending on events, governments can fall, war be declared or stock markets crash, or not + none + 1 + 1 + 0 + + + + 16012000 + weaponry + Armaments of all types used to conduct war + none + 1 + 1 + 0 + + + + 17000000 + weather + The study, reporting and prediction of meteorological phenomena. + none + 1 + 1 + 0 + + + + 17001000 + forecast + Prediction of the course of the weather in the future either near term or long term + none + 1 + 1 + 0 + + + + 17002000 + global change + The determination whether the Earth is getting warm, or colder, whether seas are rising or falling and the like + none + 1 + 1 + 0 + + + + 17003000 + report + Any distributed announcement about the weather + none + 1 + 1 + 0 + + + + 17003001 + weather news + General information about weather events + none + 12 + 12 + 0 + + + + 17004000 + statistic + Numerical facts about the weather such as temperature, barometric pressure, river levels, humidity, high and low tides and the like + none + 1 + 1 + 0 + + + + 17005000 + warning + Alerts to the general populace about severe weather coming their way + none + 1 + 1 + 0 + + + + diff --git a/libkexiv2/libkexiv2/version.h.cmake b/libkexiv2/libkexiv2/version.h.cmake new file mode 100644 index 00000000..497e208d --- /dev/null +++ b/libkexiv2/libkexiv2/version.h.cmake @@ -0,0 +1,32 @@ +/** =========================================================== + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2007-02-06 + * @brief Exiv2 library interface for KDE + * + * @author Copyright (C) 2007-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +#ifndef KEXIV2_VERSION_H +#define KEXIV2_VERSION_H + +static const char kexiv2_version[] = "${KEXIV2_LIB_VERSION_STRING}"; + +#define KEXIV2_VERSION ${KEXIV2_LIB_VERSION_ID} + +#endif // KEXIV2_VERSION_H diff --git a/libkexiv2/tests/CMakeLists.txt b/libkexiv2/tests/CMakeLists.txt new file mode 100644 index 00000000..447c4752 --- /dev/null +++ b/libkexiv2/tests/CMakeLists.txt @@ -0,0 +1,53 @@ +# =========================================================== +# +# This file is a part of digiKam project +# http://www.digikam.org +# +# @date 2006-09-15 +# @brief Exiv2 library interface for KDE +# +# @author Copyright (C) 2006-2012 by Gilles Caulier +# caulier dot gilles at gmail dot com +# +# This program is free software; you can redistribute it +# and/or modify it under the terms of the GNU General +# Public License as published by the Free Software Foundation; +# either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# ============================================================ + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libkexiv2) + +SET(setiptcpreview_SRCS setiptcpreview.cpp) +KDE4_ADD_EXECUTABLE(setiptcpreview NOGUI ${setiptcpreview_SRCS}) +TARGET_LINK_LIBRARIES(setiptcpreview kexiv2 ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}) + +SET(loadfromba_SRCS loadfromba.cpp) +KDE4_ADD_EXECUTABLE(loadfromba NOGUI ${loadfromba_SRCS}) +TARGET_LINK_LIBRARIES(loadfromba kexiv2 ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY}) + +SET(erasetag_SRCS erasetag.cpp) +KDE4_ADD_EXECUTABLE(erasetag NOGUI ${erasetag_SRCS}) +TARGET_LINK_LIBRARIES(erasetag kexiv2 ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY}) + +SET(printtagslist_SRCS printtagslist.cpp) +KDE4_ADD_EXECUTABLE(printtagslist NOGUI ${printtagslist_SRCS}) +TARGET_LINK_LIBRARIES(printtagslist kexiv2 ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY}) + +SET(usexmpsidecar_SRCS usexmpsidecar.cpp) +KDE4_ADD_EXECUTABLE(usexmpsidecar NOGUI ${usexmpsidecar_SRCS}) +TARGET_LINK_LIBRARIES(usexmpsidecar kexiv2 ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY}) + +SET(readimagewritexmpsidecar_SRCS readimagewritexmpsidecar.cpp) +KDE4_ADD_EXECUTABLE(readimagewritexmpsidecar NOGUI ${readimagewritexmpsidecar_SRCS}) +TARGET_LINK_LIBRARIES(readimagewritexmpsidecar kexiv2 ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY}) + +SET(setxmpface_SRCS setxmpface.cpp) +KDE4_ADD_EXECUTABLE(setxmpface NOGUI ${setxmpface_SRCS}) +TARGET_LINK_LIBRARIES(setxmpface kexiv2 ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY}) diff --git a/libkexiv2/tests/erasetag.cpp b/libkexiv2/tests/erasetag.cpp new file mode 100644 index 00000000..0ee9bf92 --- /dev/null +++ b/libkexiv2/tests/erasetag.cpp @@ -0,0 +1,66 @@ +/** =========================================================== + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-06-11 + * @brief a command line tool to tag from photo + * + * @author Copyright (C) 2009-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// Qt includes + +#include +#include + +// KDE includes + +#include "kdebug.h" + +// Local includes + +#include "kexiv2.h" + +using namespace KExiv2Iface; + +int main (int argc, char **argv) +{ + if(argc != 2) + { + kDebug() << "erasetag - erase tag from from image"; + kDebug() << "Usage: "; + return -1; + } + + QString filePath(argv[1]); + + KExiv2 meta; + meta.load(filePath); + meta.setWriteRawFiles(true); + bool b = meta.removeExifTag("Exif.OlympusIp.BlackLevel", false); + kDebug() << "Exif.OlympusIp.BlackLevel found = " << b; + + QByteArray ba = meta.getExifTagData("Exif.OlympusIp.BlackLevel"); + kDebug() << "Exif.OlympusIp.BlackLevel removed = " << ba.isEmpty(); + + if (b) + { + meta.applyChanges(); + } + + return 0; +} diff --git a/libkexiv2/tests/loadfromba.cpp b/libkexiv2/tests/loadfromba.cpp new file mode 100644 index 00000000..e73aa060 --- /dev/null +++ b/libkexiv2/tests/loadfromba.cpp @@ -0,0 +1,72 @@ +/** =========================================================== + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-06-11 + * @brief a command line tool to load metadata from byte array + * + * @author Copyright (C) 2009-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// Qt includes + +#include +#include +#include +#include +#include + +// KDE includes + +#include "kdebug.h" + +// Local includes + +#include "kexiv2.h" + +using namespace KExiv2Iface; + +int main (int argc, char **argv) +{ + if(argc != 2) + { + kDebug() << "loadfromba - test to load metadata from image as byte array"; + kDebug() << "Usage: "; + return -1; + } + + QString filePath(argv[1]); + QString baFile("ba.dat"); + + QImage image(filePath); + image.save(baFile, "PNG"); + + QFile file(baFile); + if ( !file.open(QIODevice::ReadOnly) ) + return false; + + QByteArray data; + data.resize(file.size()); + QDataStream stream( &file ); + stream.readRawData(data.data(), data.size()); + file.close(); + + KExiv2 meta; + meta.loadFromData(data); + + return 0; +} diff --git a/libkexiv2/tests/printtagslist.cpp b/libkexiv2/tests/printtagslist.cpp new file mode 100644 index 00000000..9864861d --- /dev/null +++ b/libkexiv2/tests/printtagslist.cpp @@ -0,0 +1,89 @@ +/** =========================================================== + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-07-12 + * @brief a command line tool to print all tags list supported by Exiv2 + * + * @author Copyright (C) 2009-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// Qt includes + +#include +#include + +// Local includes + +#include "kexiv2.h" + +using namespace KExiv2Iface; + +int main (int /*argc*/, char** /*argv*/) +{ + KExiv2 meta; + + qDebug() << "-- Standard Exif Tags -------------------------------------------------------------"; + KExiv2::TagsMap exiftags = meta.getStdExifTagsList(); + for (KExiv2::TagsMap::const_iterator it = exiftags.constBegin(); it != exiftags.constEnd(); ++it ) + { + QString key = it.key(); + QStringList values = it.value(); + QString name = values[0]; + QString title = values[1]; + QString desc = values[2]; + qDebug() << key << " :: " << name << " :: " << title << " :: " << desc; + } + + qDebug() << "-- Makernote Tags -----------------------------------------------------------------"; + KExiv2::TagsMap mntags = meta.getMakernoteTagsList(); + for (KExiv2::TagsMap::const_iterator it = mntags.constBegin(); it != mntags.constEnd(); ++it ) + { + QString key = it.key(); + QStringList values = it.value(); + QString name = values[0]; + QString title = values[1]; + QString desc = values[2]; + qDebug() << key << " :: " << name << " :: " << title << " :: " << desc; + } + + qDebug() << "-- Standard Iptc Tags -----------------------------------------------------------------"; + KExiv2::TagsMap iptctags = meta.getIptcTagsList(); + for (KExiv2::TagsMap::const_iterator it = iptctags.constBegin(); it != iptctags.constEnd(); ++it ) + { + QString key = it.key(); + QStringList values = it.value(); + QString name = values[0]; + QString title = values[1]; + QString desc = values[2]; + qDebug() << key << " :: " << name << " :: " << title << " :: " << desc; + } + + qDebug() << "-- Standard Xmp Tags -----------------------------------------------------------------"; + KExiv2::TagsMap xmptags = meta.getXmpTagsList(); + for (KExiv2::TagsMap::const_iterator it = xmptags.constBegin(); it != xmptags.constEnd(); ++it ) + { + QString key = it.key(); + QStringList values = it.value(); + QString name = values[0]; + QString title = values[1]; + QString desc = values[2]; + qDebug() << key << " :: " << name << " :: " << title << " :: " << desc; + } + + return 0; +} diff --git a/libkexiv2/tests/readimagewritexmpsidecar.cpp b/libkexiv2/tests/readimagewritexmpsidecar.cpp new file mode 100644 index 00000000..f6dd8e37 --- /dev/null +++ b/libkexiv2/tests/readimagewritexmpsidecar.cpp @@ -0,0 +1,61 @@ +/** =========================================================== + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2010-06-27 + * @brief a command line tool to test XMP sidecar functionality + * + * @author Copyright (C) 2010 by Jakob Malm + * jakob dot malm at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// Qt includes + +#include +#include + +// KDE includes + +#include "kdebug.h" + +// Local includes + +#include "kexiv2.h" + +using namespace KExiv2Iface; + +int main (int argc, char **argv) +{ + if(argc != 2) + { + kDebug() << "readimagewritecmpsidecar - read metadata from image and write to XMP sidecar"; + kDebug() << "Usage: "; + return -1; + } + + QString filePath(argv[1]); + + KExiv2 meta; + + // Read metadata from the image + meta.load(filePath); + + // Write metadata to XMP sidecar + meta.setMetadataWritingMode(KExiv2::WRITETOSIDECARONLY); + meta.save(filePath); + + return 0; +} diff --git a/libkexiv2/tests/setiptcpreview.cpp b/libkexiv2/tests/setiptcpreview.cpp new file mode 100644 index 00000000..e34c23ac --- /dev/null +++ b/libkexiv2/tests/setiptcpreview.cpp @@ -0,0 +1,82 @@ +/** =========================================================== + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2009-02-04 + * @brief a command line tool to set IPTC Preview + * + * @author Copyright (C) 2009-2012 by Gilles Caulier + * caulier dot gilles at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// Qt includes + +#include +#include +#include +#include + +// KDE includes + +#include "kdeversion.h" + +#include "qdebug.h" +#define PRINT_DEBUG qDebug() +#define ENDL + +// Local includes + +#include "kexiv2.h" + +using namespace KExiv2Iface; + +int main (int argc, char **argv) +{ + if(argc != 2) + { + PRINT_DEBUG << "setiptcpreview - update/add jpeg iptc preview to image" ENDL; + PRINT_DEBUG << "Usage: " ENDL; + return -1; + } + + QImage preview; + QString filePath(argv[1]); + KExiv2 meta(filePath); + + QImage image(filePath); + QMatrix matrix; + matrix.rotate(90); + image = image.transformed(matrix); + + QSize previewSize = image.size(); + previewSize.scale(1280, 1024, Qt::KeepAspectRatio); + + // Ensure that preview is not upscaled + if (previewSize.width() >= (int)image.width()) + preview = image.copy(); + else + preview = image.scaled(previewSize.width(), previewSize.height(), Qt::IgnoreAspectRatio).copy(); + + meta.setImagePreview(preview); + meta.applyChanges(); + + QImage preview2; + KExiv2 meta2(filePath); + meta2.getImagePreview(preview2); + preview2.save("preview.png", "PNG"); + + return 0; +} diff --git a/libkexiv2/tests/setxmpface.cpp b/libkexiv2/tests/setxmpface.cpp new file mode 100644 index 00000000..ac4436ed --- /dev/null +++ b/libkexiv2/tests/setxmpface.cpp @@ -0,0 +1,188 @@ +/** =========================================================== + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2013-02-21 + * @brief a command line tool to set faces in Picassa format + * + * @author Copyright (C) 2013 by Munteanu Veaceslav + * slavuttici at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// Qt includes + +#include +#include + +// KDE includes + +#include "kdebug.h" + +// Local includes + +#include "kexiv2.h" + +using namespace KExiv2Iface; + +bool setFaceTags(KExiv2& meta,const char* xmpTagName,const QMap& faces, + bool setProgramName) +{ + + Q_UNUSED(setProgramName); + meta.setXmpTagString(xmpTagName,QString(),KExiv2::XmpTagType(1),false); + + QString qxmpTagName(xmpTagName); + QString nameTagKey = qxmpTagName + QString("[%1]/mwg-rs:Name"); + QString typeTagKey = qxmpTagName + QString("[%1]/mwg-rs:Type"); + QString areaTagKey = qxmpTagName + QString("[%1]/mwg-rs:Area"); + QString areaxTagKey = qxmpTagName + QString("[%1]/mwg-rs:Area/stArea:x"); + QString areayTagKey = qxmpTagName + QString("[%1]/mwg-rs:Area/stArea:y"); + QString areawTagKey = qxmpTagName + QString("[%1]/mwg-rs:Area/stArea:w"); + QString areahTagKey = qxmpTagName + QString("[%1]/mwg-rs:Area/stArea:h"); + QString areanormTagKey = qxmpTagName + QString("[%1]/mwg-rs:Area/stArea:unit"); + + QMap::const_iterator it = faces.constBegin(); + int i =1; + while(it != faces.constEnd()) + { + qreal x,y,w,h; + it.value().getRect(&x,&y,&w,&h); + /** Set tag name **/ + meta.setXmpTagString(nameTagKey.arg(i).toLatin1(),it.key(), + KExiv2::XmpTagType(0),false); + /** Set tag type as Face **/ + meta.setXmpTagString(typeTagKey.arg(i).toLatin1(),QString("Face"), + KExiv2::XmpTagType(0),false); + /** Set tag Area, with xmp type struct **/ + meta.setXmpTagString(areaTagKey.arg(i).toLatin1(),QString(), + KExiv2::XmpTagType(2),false); + /** Set stArea:x inside Area structure **/ + meta.setXmpTagString(areaxTagKey.arg(i).toLatin1(),QString::number(x), + KExiv2::XmpTagType(0),false); + /** Set stArea:y inside Area structure **/ + meta.setXmpTagString(areayTagKey.arg(i).toLatin1(),QString::number(y), + KExiv2::XmpTagType(0),false); + /** Set stArea:w inside Area structure **/ + meta.setXmpTagString(areawTagKey.arg(i).toLatin1(),QString::number(w), + KExiv2::XmpTagType(0),false); + /** Set stArea:h inside Area structure **/ + meta.setXmpTagString(areahTagKey.arg(i).toLatin1(),QString::number(h), + KExiv2::XmpTagType(0),false); + /** Set stArea:unit inside Area structure as normalized **/ + meta.setXmpTagString(areanormTagKey.arg(i).toLatin1(),QString("normalized"), + KExiv2::XmpTagType(0),false); + + ++it; + ++i; + } + + return true; + +} + +void removeFaceTags(KExiv2& meta,const char* xmpTagName) +{ + QString qxmpTagName(xmpTagName); + QString regionTagKey = qxmpTagName + QString("[%1]"); + QString nameTagKey = qxmpTagName + QString("[%1]/mwg-rs:Name"); + QString typeTagKey = qxmpTagName + QString("[%1]/mwg-rs:Type"); + QString areaTagKey = qxmpTagName + QString("[%1]/mwg-rs:Area"); + QString areaxTagKey = qxmpTagName + QString("[%1]/mwg-rs:Area/stArea:x"); + QString areayTagKey = qxmpTagName + QString("[%1]/mwg-rs:Area/stArea:y"); + QString areawTagKey = qxmpTagName + QString("[%1]/mwg-rs:Area/stArea:w"); + QString areahTagKey = qxmpTagName + QString("[%1]/mwg-rs:Area/stArea:h"); + QString areanormTagKey = qxmpTagName + QString("[%1]/mwg-rs:Area/stArea:unit"); + + meta.removeXmpTag(xmpTagName,false); + bool dirty= true; + int i=1; + while(dirty) + { + dirty = false; + dirty |=meta.removeXmpTag(regionTagKey.arg(i).toLatin1(),false); + dirty |=meta.removeXmpTag(nameTagKey.arg(i).toLatin1(),false); + dirty |=meta.removeXmpTag(typeTagKey.arg(i).toLatin1(),false); + dirty |=meta.removeXmpTag(areaTagKey.arg(i).toLatin1(),false); + dirty |=meta.removeXmpTag(areaxTagKey.arg(i).toLatin1(),false); + dirty |=meta.removeXmpTag(areayTagKey.arg(i).toLatin1(),false); + dirty |=meta.removeXmpTag(areawTagKey.arg(i).toLatin1(),false); + dirty |=meta.removeXmpTag(areahTagKey.arg(i).toLatin1(),false); + dirty |=meta.removeXmpTag(areanormTagKey.arg(i).toLatin1(),false); + i++; + } +} +int main (int argc, char **argv) +{ + if(argc != 3) + { + kDebug() << "Adding a face rectangle to image"; + kDebug() << "Usage: "; + return -1; + } + + QString filePath(argv[2]); + + KExiv2Iface::KExiv2::initializeExiv2(); + KExiv2 meta; + meta.load(filePath); + meta.setWriteRawFiles(true); + + /** Add a random rectangle with facetag Bob **/ + QString name = "Bob Marley"; + float x =0.5; + float y =0.5; + float w = 60; + float h = 60; + + QRectF rect(x,y,w,h); + + QMap faces; + + faces[name] = rect; + + QString name2 = "Hello Kitty!"; + QRectF rect2(0.4,0.4,30,30); + + faces[name2] = rect2; + + bool g = meta.supportXmp(); + + kDebug() << "Image support XMP" << g; + + const QString bag = "Xmp.mwg-rs.Regions/mwg-rs:RegionList"; + + QString op(argv[1]); + + if(op == "add") + setFaceTags(meta,bag.toLatin1(),faces,false); + else + removeFaceTags(meta,bag.toLatin1()); + + meta.applyChanges(); + + QString recoverName = "Xmp.mwg-rs.Regions/mwg-rs:RegionList[1]/mwg-rs:Name"; + + KExiv2 meta2; + meta2.load(filePath); + meta2.setWriteRawFiles(true); + + QString nameR = meta2.getXmpTagString(recoverName.toLatin1(),false); + + kDebug() << "Saved name is:" << nameR; + + KExiv2Iface::KExiv2::cleanupExiv2(); + return 0; +} \ No newline at end of file diff --git a/libkexiv2/tests/usexmpsidecar.cpp b/libkexiv2/tests/usexmpsidecar.cpp new file mode 100644 index 00000000..295bfe20 --- /dev/null +++ b/libkexiv2/tests/usexmpsidecar.cpp @@ -0,0 +1,60 @@ +/** =========================================================== + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * @date 2010-06-27 + * @brief a command line tool to test XMP sidecar functionality + * + * @author Copyright (C) 2010 by Jakob Malm + * jakob dot malm at gmail dot com + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; + * either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * ============================================================ */ + +// Qt includes + +#include +#include + +// KDE includes + +#include "kdebug.h" + +// Local includes + +#include "kexiv2.h" + +using namespace KExiv2Iface; + +int main (int argc, char **argv) +{ + if(argc != 2) + { + kDebug() << "usexmpsidecar - read from and write to XMP sidecar"; + kDebug() << "Usage: "; + return -1; + } + + QString filePath(argv[1]); + + KExiv2 meta; + meta.setUseXMPSidecar4Reading(true); + meta.load(filePath); + // print some metadata + // add some metadata + // write changed metadata + // perhaps check to see if image file or XMP sidecar file was changed + + return 0; +} diff --git a/plasma/CMakeLists.txt b/plasma/CMakeLists.txt index 637ec1ed..7777b694 100644 --- a/plasma/CMakeLists.txt +++ b/plasma/CMakeLists.txt @@ -215,10 +215,6 @@ if(DL_LIBRARY) target_link_libraries(plasma ${DL_LIBRARY}) endif(DL_LIBRARY) -if(QT_QTOPENGL_FOUND) - target_link_libraries(plasma ${QT_QTOPENGL_LIBRARY}) -endif(QT_QTOPENGL_FOUND) - target_link_libraries(plasma LINK_INTERFACE_LIBRARIES kdeui kdecore ${QT_QTGUI_LIBRARY}) set_target_properties(plasma PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION})