diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 6994345313..07777a2ff2 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -1,225 +1,229 @@ project (krita-and-all-its-deps) # # Build all dependencies for Krita and finally Krita itself. # Parameters: EXTERNALS_DOWNLOAD_DIR place to download all packages # INSTALL_ROOT place to install everything to # MXE_TOOLCHAIN: the toolchain file to cross-compile using MXE # # Example usage: cmake ..\kritadeposx -DEXTERNALS_DOWNLOAD_DIR=/dev2/d -DINSTALL_ROOT=/dev2/i -DWIN64_BUILD=TRUE -DBOOST_LIBRARYDIR=/dev2/i/lib -G "Visual Studio 11 Win64" cmake_minimum_required(VERSION 2.8.6) if(NOT SUBMAKE_JOBS) set(SUBMAKE_JOBS 1) endif() if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) message(FATAL_ERROR "Compiling in the source directory is not supported. Use for example 'mkdir build; cd build; cmake ..'.") endif (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) # Tools must be obtained to work with: include (ExternalProject) # allow specification of a directory with pre-downloaded # requirements if(NOT IS_DIRECTORY ${EXTERNALS_DOWNLOAD_DIR}) message(FATAL_ERROR "No externals download dir set. Use -DEXTERNALS_DOWNLOAD_DIR") endif() if(NOT IS_DIRECTORY ${INSTALL_ROOT}) message(FATAL_ERROR "No install dir set. Use -DINSTALL_ROOT") endif() set(TOP_INST_DIR ${INSTALL_ROOT}) set(EXTPREFIX "${TOP_INST_DIR}") set(CMAKE_PREFIX_PATH "${EXTPREFIX}") if (${CMAKE_GENERATOR} STREQUAL "Visual Studio 14 2015 Win64") SET(GLOBAL_PROFILE -DCMAKE_MODULE_LINKER_FLAGS=/machine:x64 -DCMAKE_EXE_LINKER_FLAGS=/machine:x64 -DCMAKE_SHARED_LINKER_FLAGS=/machine:x64 -DCMAKE_STATIC_LINKER_FLAGS=/machine:x64 ) endif () message( STATUS "CMAKE_GENERATOR: ${CMAKE_GENERATOR}") message( STATUS "CMAKE_CL_64: ${CMAKE_CL_64}") set(GLOBAL_BUILD_TYPE RelWithDebInfo) set(GLOBAL_PROFILE ${GLOBAL_PROFILE} -DBUILD_TESTING=false) if (MINGW) option(QT_ENABLE_DEBUG_INFO "Build Qt with debug info included" OFF) option(QT_ENABLE_DYNAMIC_OPENGL "Build Qt with dynamic ANGLE support '-opengl dynamic -angle' (needs env var 'WindowsSdkDir' set to path of Windows 10 SDK)" ON) if (QT_ENABLE_DYNAMIC_OPENGL) if (DEFINED ENV{WindowsSdkDir}) message(STATUS "WindowsSdkDir is set to '$ENV{WindowsSdkDir}'") else (DEFINED ENV{WindowsSdkDir}) message(FATAL_ERROR "Environment variable 'WindowsSdkDir' not set! Please set it to path of Windows 10 SDK or disable QT_ENABLE_DYNAMIC_OPENGL") endif () endif () endif (MINGW) if (WIN32) option(USE_QT_TABLET_WINDOWS "Do not use Krita's forked Wintab and Windows Ink support on Windows, but leave everything to Qt." ON) endif () set(SECURITY_EXE_LINKER_FLAGS "") set(SECURITY_SHARED_LINKER_FLAGS "") set(SECURITY_MODULE_LINKER_FLAGS "") if (MINGW) option(USE_MINGW_HARDENING_LINKER "Enable DEP (NX), ASLR and high-entropy ASLR linker flags (mingw-w64)" ON) if (USE_MINGW_HARDENING_LINKER) set(SECURITY_EXE_LINKER_FLAGS "-Wl,--dynamicbase -Wl,--nxcompat -Wl,--disable-auto-image-base") set(SECURITY_SHARED_LINKER_FLAGS "-Wl,--dynamicbase -Wl,--nxcompat -Wl,--disable-auto-image-base") set(SECURITY_MODULE_LINKER_FLAGS "-Wl,--dynamicbase -Wl,--nxcompat -Wl,--disable-auto-image-base") if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") # Enable high-entropy ASLR for 64-bit # The image base has to be >4GB for HEASLR to be enabled. # The values used here are kind of arbitrary. set(SECURITY_EXE_LINKER_FLAGS "${SECURITY_EXE_LINKER_FLAGS} -Wl,--high-entropy-va -Wl,--image-base,0x140000000") set(SECURITY_SHARED_LINKER_FLAGS "${SECURITY_SHARED_LINKER_FLAGS} -Wl,--high-entropy-va -Wl,--image-base,0x180000000") set(SECURITY_MODULE_LINKER_FLAGS "${SECURITY_MODULE_LINKER_FLAGS} -Wl,--high-entropy-va -Wl,--image-base,0x180000000") set(GLOBAL_PROFILE ${GLOBAL_PROFILE} -DCMAKE_EXE_LINKER_FLAGS=${SECURITY_EXE_LINKER_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS=${SECURITY_SHARED_LINKER_FLAGS} -DCMAKE_MODULE_LINKER_FLAGS=${SECURITY_MODULE_LINKER_FLAGS} ) endif () else () message(WARNING "Linker Security Flags not enabled!") endif () endif () if (DEFINED EP_PREFIX) set_directory_properties(PROPERTIES EP_PREFIX ${EP_PREFIX}) endif () if (MSVC) message(FATAL_ERROR "Krita cannot be built with MSVC. See the README.md file!") endif() if (MINGW) set(PATCH_COMMAND myptch) endif() if (MSYS) set(PATCH_COMMAND patch) set(GLOBAL_PROFILE ${GLOBAL_PROFILE} -DCMAKE_TOOLCHAIN_FILE=${MXE_TOOLCHAIN} -DCMAKE_FIND_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_SYSTEM_INCLUDE_PATH=${CMAKE_PREFIX_PATH}/include -DCMAKE_INCLUDE_PATH=${CMAKE_PREFIX_PATH}/include -DCMAKE_LIBRARY_PATH=${CMAKE_PREFIX_PATH}/lib -DZLIB_ROOT=${CMAKE_PREFIX_PATH} ) set(GLOBAL_AUTOMAKE_PROFILE --host=i686-pc-mingw32 ) endif() if (APPLE) set(GLOBAL_PROFILE ${GLOBAL_PROFILE} -DCMAKE_MACOSX_RPATH=ON -DKDE_SKIP_RPATH_SETTINGS=ON -DBUILD_WITH_INSTALL_RPATH=ON -DAPPLE_SUPPRESS_X11_WARNING=ON) set(PATCH_COMMAND patch) endif () if (ANDROID) set (GLOBAL_PROFILE ${GLOBAL_PROFILE} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DANDROID_PLATFORM=${ANDROID_PLATFORM} -DANDROID_ABI=${ANDROID_ABI}) endif() if (UNIX AND NOT APPLE) set(LINUX true) set(PATCH_COMMAND patch) endif () function(TestCompileLinkPythonLibs OUTPUT_VARNAME) include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_INCLUDES ${PYTHON_INCLUDE_PATH}) set(CMAKE_REQUIRED_LIBRARIES ${PYTHON_LIBRARIES}) if (MINGW) set(CMAKE_REQUIRED_DEFINITIONS -D_hypot=hypot) endif () unset(${OUTPUT_VARNAME} CACHE) CHECK_CXX_SOURCE_COMPILES(" #include int main(int argc, char *argv[]) { Py_InitializeEx(0); }" ${OUTPUT_VARNAME}) endfunction() if (MINGW) option(ENABLE_PYTHON_DEPS "Enable Python deps (sip, pyqt)" ON) if (ENABLE_PYTHON_DEPS) if (ENABLE_PYTHON_2) message(FATAL_ERROR "Python 2.7 is not supported on Windows at the moment.") else(ENABLE_PYTHON_2) find_package(PythonInterp 3.6 EXACT) find_package(PythonLibs 3.6 EXACT) endif() if (PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) message(STATUS "Python requirements met.") TestCompileLinkPythonLibs(CAN_USE_PYTHON_LIBS) if (NOT CAN_USE_PYTHON_LIBS) message(FATAL_ERROR "Compiling with Python library failed, please check whether the architecture is correct!") endif () else (PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) message(FATAL_ERROR "Python requirements not met. To disable Python deps, set ENABLE_PYTHON_DEPS to OFF.") endif () endif () endif () # this list must be dependency-ordered if (ENABLE_PYTHON_DEPS OR NOT MINGW) add_subdirectory( ext_python ) endif () if (MINGW) add_subdirectory( ext_patch ) add_subdirectory( ext_png2ico ) endif () add_subdirectory( ext_lzma ) add_subdirectory( ext_iconv ) add_subdirectory( ext_gettext ) add_subdirectory( ext_zlib ) add_subdirectory( ext_boost ) add_subdirectory( ext_jpeg ) add_subdirectory( ext_tiff ) add_subdirectory( ext_png ) add_subdirectory( ext_eigen3 ) add_subdirectory( ext_expat ) # for exiv2 add_subdirectory( ext_exiv2 ) add_subdirectory( ext_ilmbase ) add_subdirectory( ext_lcms2 ) add_subdirectory( ext_openexr ) add_subdirectory( ext_openssl ) add_subdirectory( ext_vc ) add_subdirectory( ext_gsl ) add_subdirectory( ext_fftw3 ) add_subdirectory( ext_ocio ) +add_subdirectory( ext_openjpeg ) +if (MSVC) + add_subdirectory( ext_pthreads ) +endif (MSVC) add_subdirectory( ext_fontconfig) add_subdirectory( ext_freetype) add_subdirectory( ext_qt ) add_subdirectory( ext_poppler ) add_subdirectory( ext_libraw ) add_subdirectory( ext_frameworks ) if (ENABLE_PYTHON_DEPS OR NOT MINGW) add_subdirectory( ext_sip ) add_subdirectory( ext_pyqt ) endif () if (MINGW) add_subdirectory( ext_drmingw ) # add_subdirectory( ext_ffmpeg ) endif () if (NOT APPLE) add_subdirectory( ext_gmic ) endif () if(UNIX) add_subdirectory( ext_pkgconfig ) add_subdirectory( ext_heif ) endif() add_subdirectory(ext_giflib) add_subdirectory(ext_quazip) diff --git a/3rdparty/README.md b/3rdparty/README.md index f72f2b94c2..25675c7f48 100644 --- a/3rdparty/README.md +++ b/3rdparty/README.md @@ -1,269 +1,269 @@ # CMake external projects to build krita's dependencies on Linux, Windows or OSX If you need to build Krita's dependencies for the following reasons: * you develop on Windows and aren't using build-tools/windows/build.cmd or KDE's craft * you develop on OSX and aren't using the scripts in krita/packaging/osx or Homebrew * you want to build a generic, distro-agnostic version of Krita for Linux and aren't using the scripts in packaging/linux/appimage * you develop on Linux, but some dependencies aren't available for your distribution and aren't using the scripts in packaging/linux/appimage and you know what you're doing, you can use the following guide to build the dependencies that Krita needs. If you develop on Linux and your distribution has all dependencies available, YOU DO NOT NEED THIS GUIDE AND YOU SHOULD STOP READING NOW Otherwise you risk major confusion. ## Prerequisites Note: on all operating systems the entire procedure is done in a terminal window. 1. git: https://git-scm.com/downloads. Make sure git is in your path 2. CMake 3.3.2 or later: https://cmake.org/download/. Make sure cmake is in your path. * CMake 3.9 does not build Krita properly at the moment, please use 3.8 or 3.10 instead. 3. Make sure you have a compiler: * Linux: gcc, minimum version 4.8 * OSX: clang, you need to install xcode for this * Windows: mingw-w64 7.3 (by mingw-builds): https://sourceforge.net/projects/mingw-w64/ * The Files can be found under "Toolchains targetting Win64/Win32"/"Personal Builds". * For threading, select posix. * For exceptions, select seh (64-bit) or dwarf (32-bit). * Install mingw to something like C:\mingw; the full path must not contain any spaces. * Make sure mingw's bin folder is in your path. It might be a good idea to create a batch file which sets the path and start cmd. * MSVC is *not* supported at the moment. 4. On Windows, you will also need a release of Python 3.6 (*not* 3.7 or any other versions): https://www.python.org. Make sure to have that version of python.exe in your path. This version of Python will be used for two things: to configure Qt and to build the Python scripting module. Make sure that this version of Python comes first in your path. Do not set PYTHONHOME or PYTHONPATH. * Make sure that your Python will have the correct architecture for the version you are trying to build. If building for 32-bit target, you need the 32-bit release of Python. 5. On Windows, if you want to compile Qt with ANGLE support, you will need to install Windows 10 SDK and have the environment variable `WindowsSdkDir` set to it (typically `C:\Program Files (x86)\Windows Kits\10`) ## Setup your environment ## Prepare your directory layout 1. Make a toplevel build directory, say $HOME/dev or c:\dev. We'll refer to this directory as BUILDROOT. You can use a variable for this, on WINDOWS %BUILDROOT%, on OSX and Linux $BUILDROOT. You will have to replace a bare BUILDROOT with $BUILDROOT or %BUILDROOT% whenever you copy and paste a command, depending on your operating system. 2. Checkout krita in BUILDROOT ``` cd BUILDROOT git clone git://anongit.kde.org/krita.git ``` 3. Create the build directory ``` mkdir BUILDROOT/b ``` 4. Create the downloads directory ``` mkdir BUILDROOT/d ``` 5. Create the install directory ``` mkdir BUILDROOT/i ``` ## Prepare the externals build 1. Enter the BUILDROOT/b directory 2. Run cmake: * Linux: ``` export PATH=$BUILDROOT/i/bin:$PATH export PYTHONHOME=$BUILDROOT/i (only if you want to build your own python) cmake ../krita/3rdparty \ -DINSTALL_ROOT=$BUILDROOT/i \ -DEXTERNALS_DOWNLOAD_DIR=$BUILDROOT/d \ -DCMAKE_INSTALL_PREFIX=BUILDROOT/i ``` * OSX: ``` export PATH=$BUILDROOT/i/bin:$PATH export PYTHONHOME=$BUILDROOT/i (only if you want to build your own python) cmake ../krita/3rdparty/ \ -DCMAKE_INSTALL_PREFIX=$BUILDROOT/i \ -DEXTERNALS_DOWNLOAD_DIR=$BUILDROOT/d \ -DINSTALL_ROOT=$BUILDROOT/i ``` * Windows 32-bit / 64-bit: Note that the cmake command needs to point to your BUILDROOT like /dev/d, not c:\dev\d. ``` set PATH=%BUILDROOT%\i\bin\;%BUILDROOT%\i\lib;%PATH% cmake ..\krita\3rdparty -DEXTERNALS_DOWNLOAD_DIR=/dev/d -DINSTALL_ROOT=/dev/i -G "MinGW Makefiles" ``` - If you want to build Qt and some other dependencies with parallel jobs, add `-DSUBMAKE_JOBS=` to this cmake command where is the number of jobs to run (if your PC has 4 CPU cores, you might want to set it to 5). For other jobs, you might need to manually add a -- -j N option, where N is the number of jobs. - If you don't have Windows 10 SDK and don't want to build Qt with ANGLE, add `-DQT_ENABLE_DYNAMIC_OPENGL=OFF` to the CMake command line args. 3. Build the packages: On Windows: ``` cmake --build . --config RelWithDebInfo --target ext_patch cmake --build . --config RelWithDebInfo --target ext_png2ico ``` On OSX and Windows: ``` cmake --build . --config RelWithDebInfo --target ext_gettext cmake --build . --config RelWithDebInfo --target ext_openssl ``` On all operating systems: ``` cmake --build . --config RelWithDebInfo --target ext_qt cmake --build . --config RelWithDebInfo --target ext_zlib cmake --build . --config RelWithDebInfo --target ext_boost Note about boost: check if the headers are installed into i/include/boost, but not into i/include/boost-1.61/boost cmake --build . --config RelWithDebInfo --target ext_eigen3 cmake --build . --config RelWithDebInfo --target ext_exiv2 cmake --build . --config RelWithDebInfo --target ext_fftw3 cmake --build . --config RelWithDebInfo --target ext_ilmbase cmake --build . --config RelWithDebInfo --target ext_jpeg cmake --build . --config RelWithDebInfo --target ext_lcms2 cmake --build . --config RelWithDebInfo --target ext_ocio cmake --build . --config RelWithDebInfo --target ext_openexr ``` OSX Note: You need to first build openexr; that will fail; then you need to set the rpath for the two utilities correctly, then try to build openexr again. ``` install_name_tool -add_rpath $BUILD_ROOT/i/lib $BUILD_ROOT/b/ext_openexr/ext_openexr-prefix/src/ext_openexr-build/IlmImf/./b44ExpLogTable install_name_tool -add_rpath $BUILD_ROOT/i/lib $BUILD_ROOT/b/ext_openexr/ext_openexr-prefix/src/ext_openexr-build/IlmImf/./dwaLookups ``` On All operating systems ``` cmake --build . --config RelWithDebInfo --target ext_png cmake --build . --config RelWithDebInfo --target ext_tiff cmake --build . --config RelWithDebInfo --target ext_gsl cmake --build . --config RelWithDebInfo --target ext_vc cmake --build . --config RelWithDebInfo --target ext_libraw cmake --build . --config RelWithDebInfo --target ext_giflib - ``` + cmake --build . --config RelWithDebInfo --target ext_openjpeg On Linux (if you want to build your own SIP and PyQt instead of the system one) ``` cmake --build . --config RelWithDebInfo --target ext_sip cmake --build . --config RelWithDebInfo --target ext_pyqt ``` On Windows ``` cmake --build . --config RelWithDebInfo --target ext_freetype cmake --build . --config RelWithDebInfo --target ext_poppler ``` On Linux ``` cmake --build . --config RelWithDebInfo --target ext_kcrash ``` On Windows (if you want to include DrMingw for dumping backtrace on crash) ``` cmake --build . --config RelWithDebInfo --target ext_drmingw ``` On Windows (if you want to include Python scripting) ``` cmake --build . --config RelWithDebInfo --target ext_python cmake --build . --config RelWithDebInfo --target ext_sip cmake --build . --config RelWithDebInfo --target ext_pyqt ``` On Windows and Linux (if you want to include gmic-qt) ``` cmake --build . --config RelWithDebInfo --target ext_gmic ``` Linux Note: poppler should be buildable on Linux as well with a home-built freetype and fontconfig, but I don't know how to make fontconfig find freetype, and on Linux, fontconfig is needed for poppler. Poppler is needed for PDF import. OSX Note: In order to build fontconfig on macOS, you need to have pkg-config installed. You probably need homebrew for that... See http://macappstore.org/pkg-config/ . archives from: files.kde.org/krita/build/dependencies: On Windows and OSX ``` cmake --build . --config RelWithDebInfo --target ext_kwindowsystem ``` ## Build Krita 1. Make a krita build directory: mkdir BUILDROOT/build 2. Enter the BUILDROOT/build 3. Configure the build: On Windows ``` cmake ..\krita -G "MinGW Makefiles" -DBoost_DEBUG=OFF -DBOOST_INCLUDEDIR=c:\dev\i\include -DBOOST_DEBUG=ON -DBOOST_ROOT=c:\dev\i -DBOOST_LIBRARYDIR=c:\dev\i\lib -DCMAKE_INSTALL_PREFIX=c:\dev\i -DCMAKE_PREFIX_PATH=c:\dev\i -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DHAVE_MEMORY_LEAK_TRACKER=OFF -Wno-dev -DDEFINE_NO_DEPRECATED=1 ``` On Linux ``` cmake ../krita -DCMAKE_INSTALL_PREFIX=BUILDROOT/i -DDEFINE_NO_DEPRECATED=1 -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo # Troubleshooting: if you built your own SIP and CMake fails to find it, please set # the following environment variable to the SIP installation directory: export PYTHONPATH=$BUILDROOT/i/sip/ # If you also have KIO installed in the system, don't forget to disable it by bassing to cmake: # cmake -DCMAKE_DISABLE_FIND_PACKAGE_KF5KIO=true . ``` On OSX ``` cmake ../krita -DCMAKE_INSTALL_PREFIX=$BUILDROOT/i -DDEFINE_NO_DEPRECATED=1 -DBUILD_TESTING=OFF -DKDE4_BUILD_TESTS=OFF -DBUNDLE_INSTALL_DIR=$BUILDROOT/i/bin -DCMAKE_BUILD_TYPE=RelWithDebInfo ``` 4. Run the build: On Linux and OSX ``` make make install ``` On Windows (replace 4 with the number of jobs to run in parallel) ``` cmake --build . --target install -- -j4 ``` 6. Run krita: On Linux ``` BUILDROOT/i/bin/krita ``` On Windows ``` BUILDROOT\i\bin\krita.exe ``` On OSX ``` BUILDROOT/i/bin/krita.app/Contents/MacOS/krita ``` ## Packaging a Windows Build If you want to create a stripped down version of Krita to distribute, after building everything just run the packaging/windows/package-complete.cmd script. That script will copy the necessary files into the specified folder and leave out developer related files. After the script runs there will be two new ZIP files that contain a small portable version of Krita and a separate portable debug version. diff --git a/3rdparty/ext_openjpeg/CMakeLists.txt b/3rdparty/ext_openjpeg/CMakeLists.txt new file mode 100755 index 0000000000..3e34540089 --- /dev/null +++ b/3rdparty/ext_openjpeg/CMakeLists.txt @@ -0,0 +1,14 @@ +SET(PREFIX_ext_openjpeg "${EXTPREFIX}" ) +ExternalProject_Add( ext_openjpeg + DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR} + URL http://files.kde.org/krita/build/dependencies/openjpeg-version.2.1.tar.gz + URL_MD5 3e1c451c087f8462955426da38aa3b3d + + INSTALL_DIR ${PREFIX_ext_openjpeg} + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${PREFIX_ext_openjpeg} -DCMAKE_BUILD_TYPE=${GLOBAL_BUILD_TYPE} ${GLOBAL_PROFILE} + + UPDATE_COMMAND "" + ALWAYS 0 + DEPENDS ext_png ext_tiff ext_lcms2 ext_zlib +) + diff --git a/cmake/modules/FindOpenJPEG.cmake b/cmake/modules/FindOpenJPEG.cmake new file mode 100644 index 0000000000..ae859572e9 --- /dev/null +++ b/cmake/modules/FindOpenJPEG.cmake @@ -0,0 +1,56 @@ +# -*- cmake -*- + +# - Find OpenJPEG +# Find the OpenJPEG includes and library +# This module defines +# OPENJPEG_INCLUDE_DIR, where to find openjpeg.h, etc. +# OPENJPEG_LIBRARIES, the libraries needed to use OpenJPEG. +# OPENJPEG_FOUND, If false, do not try to use OpenJPEG. +# also defined, but not for general use are +# OPENJPEG_LIBRARY, where to find the OpenJPEG library. + +find_path(OPENJPEG_INCLUDE_DIR openjpeg.h +PATHS + /usr/local/include/openjpeg + /usr/local/include + /usr/include/openjpeg + /usr/include/openjpeg-1.5 + /usr/include +PATH_SUFFIXES + openjpeg-1.5 + openjpeg +) + +set(OPENJPEG_NAMES ${OPENJPEG_NAMES} openjpeg) +find_library(OPENJPEG_LIBRARY + NAMES ${OPENJPEG_NAMES} + PATHS + /usr/lib /usr/local/lib +) + +if (OPENJPEG_LIBRARY AND OPENJPEG_INCLUDE_DIR) + set(OPENJPEG_LIBRARIES ${OPENJPEG_LIBRARY}) + set(OPENJPEG_FOUND "YES") +else () + set(OPENJPEG_FOUND "NO") +endif () + + +if (OPENJPEG_FOUND) + if (NOT OPENJPEG_FIND_QUIETLY) + message(STATUS "Found OpenJPEG: ${OPENJPEG_LIBRARIES}") + endif () +else () + if (OPENJPEG_FIND_REQUIRED) + message(FATAL_ERROR "Could not find OpenJPEG library") + endif () +endif () + +# Deprecated declarations. +set (NATIVE_OPENJPEG_INCLUDE_PATH ${OPENJPEG_INCLUDE_DIR} ) +get_filename_component (NATIVE_OPENJPEG_LIB_PATH ${OPENJPEG_LIBRARY} PATH) + +mark_as_advanced( + OPENJPEG_LIBRARY + OPENJPEG_INCLUDE_DIR + ) diff --git a/plugins/impex/CMakeLists.txt b/plugins/impex/CMakeLists.txt index 51056ecf47..d69840f873 100644 --- a/plugins/impex/CMakeLists.txt +++ b/plugins/impex/CMakeLists.txt @@ -1,52 +1,56 @@ project(kritafilters) add_subdirectory(libkra) if(CMAKE_SIZEOF_VOID_P EQUAL 4) add_definitions( -DCPU_32_BITS ) endif() if(JPEG_FOUND AND HAVE_LCMS2) add_subdirectory(jpeg) endif() if(TIFF_FOUND) add_subdirectory(tiff) endif() if(PNG_FOUND) add_subdirectory(png) add_subdirectory(csv) endif() if(OPENEXR_FOUND) add_subdirectory(exr) endif() if(Poppler_Qt5_FOUND) add_subdirectory(pdf) endif() +if(OPENJPEG_FOUND) + add_subdirectory(jp2) +endif() + if(LIBRAW_FOUND) add_subdirectory(raw) endif() add_subdirectory(svg) add_subdirectory(qimageio) add_subdirectory(ora) add_subdirectory(xcf) add_subdirectory(psd) add_subdirectory(qml) add_subdirectory(tga) add_subdirectory(heightmap) add_subdirectory(brush) add_subdirectory(spriter) add_subdirectory(kra) if (GIF_FOUND) add_subdirectory(gif) endif() if (HEIF_FOUND) add_subdirectory(heif) endif() diff --git a/plugins/impex/jp2/CMakeLists.txt b/plugins/impex/jp2/CMakeLists.txt new file mode 100644 index 0000000000..0b885a99a7 --- /dev/null +++ b/plugins/impex/jp2/CMakeLists.txt @@ -0,0 +1,30 @@ +include_directories(SYSTEM ${OPENJPEG_INCLUDE_DIR}) + +set(libkritaconverter_LIB_SRCS + jp2_converter.cc +) + +set(kritajp2import_SOURCES + jp2_import.cc + ${libkritaconverter_LIB_SRCS} + ) + +add_library(kritajp2import MODULE ${kritajp2import_SOURCES}) + +target_link_libraries(kritajp2import kritaui ${OPENJPEG_LIBRARIES} ) + +install(TARGETS kritajp2import DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) + +set(kritajp2export_SOURCES + jp2_export.cc + ${libkritaconverter_LIB_SRCS} +) + +ki18n_wrap_ui(kritajp2export_SOURCES kis_wdg_options_jp2.ui ) + +add_library(kritajp2export MODULE ${kritajp2export_SOURCES}) + +target_link_libraries(kritajp2export kritaui ${OPENJPEG_LIBRARIES} ) + +install(TARGETS kritajp2export DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) +install( PROGRAMS krita_jp2.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) diff --git a/plugins/impex/jp2/jp2_converter.cc b/plugins/impex/jp2/jp2_converter.cc new file mode 100644 index 0000000000..11cc175634 --- /dev/null +++ b/plugins/impex/jp2/jp2_converter.cc @@ -0,0 +1,468 @@ +/* + * Copyright (c) 2009 Cyrille Berger + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 2.1 of the License. + * + * 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +#include "jp2_converter.h" + +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "kis_iterator_ng.h" + +jp2Converter::jp2Converter(KisDocument *doc) +{ + m_doc = doc; + m_stop = false; +} + +jp2Converter::~jp2Converter() +{ +} + +/** + * sample error callback expecting a FILE* client object + * */ +void +error_callback(const char *msg, void *client_data) +{ + FILE *stream = (FILE *) client_data; + fprintf(stream, "[ERROR] %s", msg); +} + +/** + * sample warning callback expecting a FILE* client object + * */ +void +warning_callback(const char *msg, void *client_data) +{ + FILE *stream = (FILE *) client_data; + fprintf(stream, "[WARNING] %s", msg); +} + +/** + * sample debug callback expecting no client object + * */ +void +info_callback(const char *msg, void *client_data) +{ + Q_UNUSED(client_data); + fprintf(stdout, "[INFO] %s", msg); +} + +KisImageBuilder_Result jp2Converter::decode(const QString &filename) +{ + // decompression parameters + opj_dparameters_t parameters; + opj_set_default_decoder_parameters(¶meters); + // Determine the type + parameters.decod_format = getFileFormat(filename); // TODO isn't there some magic code ? + if (parameters.decod_format == -1) { + return KisImageBuilder_RESULT_UNSUPPORTED; + } + // open the file + QFile fp(filename); + fp.open(QIODevice::ReadOnly); + QByteArray src = fp.readAll(); + fp.close(); + // Decode the file + opj_dinfo_t *dinfo = 0; + + bool hasColorSpaceInfo = false; + /* get a decoder handle */ + switch (parameters.decod_format) { + case J2K_CFMT: { + dinfo = opj_create_decompress(CODEC_J2K); + break; + } + case JP2_CFMT: { + dinfo = opj_create_decompress(CODEC_JP2); + hasColorSpaceInfo = true; + break; + } + case JPT_CFMT: { + dinfo = opj_create_decompress(CODEC_JPT); + break; + } + } + Q_ASSERT(dinfo); + + /* setup the decoder decoding parameters using user parameters */ + opj_setup_decoder(dinfo, ¶meters); + + /* open a byte stream */ + opj_cio_t *cio = opj_cio_open((opj_common_ptr) dinfo, (unsigned char*)src.data(), src.length()); + + // Setup an event manager + opj_event_mgr_t event_mgr; /* event manager */ + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = error_callback; + event_mgr.warning_handler = warning_callback; + event_mgr.info_handler = info_callback; + + /* catch events using our callbacks and give a local context */ + opj_set_event_mgr((opj_common_ptr) dinfo, &event_mgr, stderr); + + /* decode the stream and fill the image structure */ + opj_image_t *image = opj_decode(dinfo, cio); + + /* close the byte stream */ + opj_cio_close(cio); + if (!image) { + opj_destroy_decompress(dinfo); + return KisImageBuilder_RESULT_FAILURE; + } + + // Look for the colorspace + int components = image->numcomps; + if (image->numcomps == 0) { + opj_destroy_decompress(dinfo); + return KisImageBuilder_RESULT_FAILURE; + } + int bitdepth = image->comps[0].bpp; + for (int i = 1; i < components; ++i) { + if (image->comps[i].bpp != bitdepth) { + opj_destroy_decompress(dinfo); + return KisImageBuilder_RESULT_FAILURE; + } + } + dbgFile << "Image has " << components << " components and a bit depth of " << bitdepth << " for color space " << image->color_space; + if (bitdepth == 0) { + bitdepth = 8; + } + const KoColorSpace* colorSpace = 0; + QVector channelorder(components); + if (!hasColorSpaceInfo) { + if (components == 3) { + image->color_space = CLRSPC_SRGB; + } else if (components == 1) { + image->color_space = CLRSPC_GRAY; + } + } + switch (image->color_space) { + case CLRSPC_UNKNOWN: + break; + case CLRSPC_SRGB: { + if (bitdepth == 16) { + colorSpace = KoColorSpaceRegistry::instance()->rgb16(); + } else if (bitdepth == 8) { + colorSpace = KoColorSpaceRegistry::instance()->rgb8(); + } + if (components != 3) { + opj_destroy_decompress(dinfo); + return KisImageBuilder_RESULT_FAILURE; + } + channelorder[0] = KoBgrU16Traits::red_pos; + channelorder[1] = KoBgrU16Traits::green_pos; + channelorder[2] = KoBgrU16Traits::blue_pos; + break; + } + case CLRSPC_GRAY: { + if (bitdepth == 16) { + colorSpace = KoColorSpaceRegistry::instance()->colorSpace( GrayAColorModelID.id(), Integer16BitsColorDepthID.id(), ""); + } else if (bitdepth == 8) { + colorSpace = KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer8BitsColorDepthID.id(), ""); + } + if (components != 1) { + opj_destroy_decompress(dinfo); + return KisImageBuilder_RESULT_FAILURE; + } + channelorder[0] = 0; + break; + } + case CLRSPC_SYCC: { + if (bitdepth == 16) { + colorSpace = KoColorSpaceRegistry::instance()->colorSpace( "YUV", Integer16BitsColorDepthID.id(), ""); + } else if (bitdepth == 8) { + colorSpace = KoColorSpaceRegistry::instance()->colorSpace("YUV", Integer8BitsColorDepthID.id(), ""); + } + if (components != 3) { + opj_destroy_decompress(dinfo); + return KisImageBuilder_RESULT_FAILURE; + } + channelorder[0] = 0; + channelorder[1] = 1; + channelorder[2] = 2; + break; + } + default: + ; + } + if (!colorSpace) { + dbgFile << "No colors space found for that image"; + return KisImageBuilder_RESULT_FAILURE; + } + + // Create the image + if (m_image == 0) { + m_image = new KisImage(m_doc->createUndoStore(), image->x1, image->y1, colorSpace, "built image"); + } + + // Create the layer + KisPaintLayerSP layer = new KisPaintLayer(m_image.data(), m_image->nextLayerName(), OPACITY_OPAQUE_U8); + m_image->addNode(layer.data(), m_image->rootLayer().data()); + + // Set the data + int pos = 0; + KisHLineIteratorSP it = layer->paintDevice()->createHLineIteratorNG(0, 0, image->x1); + for (int v = 0; v < image->y1; ++v) { + if (bitdepth == 16) { + do { + quint16* px = reinterpret_cast(it->rawData()); + for (int i = 0; i < components; ++i) { + px[channelorder[i]] = image->comps[i].data[pos]; + } + colorSpace->setOpacity(it->rawData(), OPACITY_OPAQUE_U8, 1); + ++pos; + + } while (it->nextPixel()); + } else if (bitdepth == 8) { + do { + quint8* px = reinterpret_cast(it->rawData()); + for (int i = 0; i < components; ++i) { + px[channelorder[i]] = image->comps[i].data[pos]; + } + colorSpace->setOpacity(px, OPACITY_OPAQUE_U8, 1); + ++pos; + + } while (it->nextPixel()); + } + it->nextRow(); + } + + return KisImageBuilder_RESULT_OK; +} + + + +KisImageBuilder_Result jp2Converter::buildImage(const QString &filename) +{ + return decode(filename); +} + + +KisImageWSP jp2Converter::getImage() +{ + return m_image; +} + + +KisImageBuilder_Result jp2Converter::buildFile(const QString &filename, KisPaintLayerSP layer, const JP2ConvertOptions& options) +{ + if (!layer) + return KisImageBuilder_RESULT_INVALID_ARG; + + KisImageWSP kisimage = layer->image(); + if (!kisimage) + return KisImageBuilder_RESULT_EMPTY; + + // Init parameters + opj_cparameters_t parameters; + opj_set_default_encoder_parameters(¶meters); + parameters.cp_comment = (char*)"Created by Krita"; + parameters.subsampling_dx = 1; + parameters.subsampling_dy = 1; + parameters.cp_disto_alloc = 1; + parameters.tcp_numlayers = 1; + parameters.numresolution = options.numberresolution; + dbgFile << 100 - options.rate; + parameters.tcp_rates[0] = options.rate; + + + // Set the colorspace information + OPJ_COLOR_SPACE clrspc; + int components; + QVector channelorder; + if (layer->colorSpace()->colorModelId() == GrayAColorModelID || layer->colorSpace()->colorModelId() == GrayColorModelID) { + clrspc = CLRSPC_GRAY; + components = 1; + channelorder.resize(components); + channelorder[0] = 0; + } else if (layer->colorSpace()->colorModelId() == RGBAColorModelID) { + clrspc = CLRSPC_SRGB; + components = 3; + channelorder.resize(components); + channelorder[0] = KoBgrU16Traits::red_pos; + channelorder[1] = KoBgrU16Traits::green_pos; + channelorder[2] = KoBgrU16Traits::blue_pos; + } else { + QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Cannot export images in %1.\n", layer->colorSpace()->name())) ; + return KisImageBuilder_RESULT_FAILURE; + } + + int bitdepth; + if (layer->colorSpace()->colorDepthId() == Integer8BitsColorDepthID) { + bitdepth = 8; +// TODO OpenJpeg does not really support 16bits yet +// } else if (layer->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) { +// bitdepth = 16; + } else { + QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Cannot export images in %1.\n", layer->colorSpace()->name())) ; + return KisImageBuilder_RESULT_FAILURE; + } + + // Init the image + opj_image_cmptparm_t image_info[3]; + + int width = kisimage->width(); + int height = kisimage->height(); + for (int k = 0; k < components; k++) { + image_info[k].dx = 1; + image_info[k].dy = 1; + image_info[k].w = width; + image_info[k].h = height; + image_info[k].x0 = 0; + image_info[k].y0 = 0; + image_info[k].prec = 8; + image_info[k].bpp = bitdepth; + image_info[k].sgnd = 0; + } + opj_image_t *image = opj_image_create(components, image_info, clrspc); + image->x1 = width; + image->y1 = height; + image->x0 = 0; + image->y0 = 0; + + // Copy the data in the image + int pos = 0; + KisHLineIteratorSP it = layer->paintDevice()->createHLineIteratorNG(0, 0, image->x1); + for (int v = 0; v < height; ++v) { + if (bitdepth == 16) { + do { + quint16* px = reinterpret_cast(it->rawData()); + for (int i = 0; i < components; ++i) { + image->comps[i].data[pos] = px[channelorder[i]]; + } + ++pos; + + } while (it->nextPixel()); + } else if (bitdepth == 8) { + do { + quint8* px = reinterpret_cast(it->rawData()); + for (int i = 0; i < components; ++i) { + image->comps[i].data[pos] = px[channelorder[i]]; + } + ++pos; + + } while (it->nextPixel()); + } + it->nextRow(); + } + + // coding format + parameters.decod_format = getFileFormat(filename); // TODO isn't there some magic code ? + + // Decode the file + opj_cinfo_t *cinfo = 0; + + /* get a decoder handle */ + switch (parameters.decod_format) { + case J2K_CFMT: { + cinfo = opj_create_compress(CODEC_J2K); + break; + } + case JP2_CFMT: { + cinfo = opj_create_compress(CODEC_JP2); + break; + } + case JPT_CFMT: { + cinfo = opj_create_compress(CODEC_JPT); + break; + } + } + + if (!cinfo) { + // Could not create compression info object + return KisImageBuilder_RESULT_FAILURE; + } + + // Setup an event manager + opj_event_mgr_t event_mgr; /* event manager */ + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = error_callback; + event_mgr.warning_handler = warning_callback; + event_mgr.info_handler = info_callback; + + /* catch events using our callbacks and give a local context */ + opj_set_event_mgr((opj_common_ptr) cinfo, &event_mgr, stderr); + + + /* setup the encoder parameters using the current image and using user parameters */ + opj_setup_encoder(cinfo, ¶meters, image); + + opj_cio_t* cio = opj_cio_open((opj_common_ptr) cinfo, 0, 0); + + + /* encode the image */ + if (!opj_encode(cinfo, cio, image, parameters.index)) { + opj_cio_close(cio); + opj_destroy_compress(cinfo); + return KisImageBuilder_RESULT_FAILURE; + } + + // Write to the file + QFile fp(filename); + fp.open(QIODevice::WriteOnly); + int length = cio_tell(cio); + dbgFile << "Length of the file to save: " << length; + fp.write((char*)cio->buffer, length); + fp.close(); + + opj_cio_close(cio); + opj_destroy_compress(cinfo); + + return KisImageBuilder_RESULT_OK; +} + + +void jp2Converter::cancel() +{ + m_stop = true; +} + +int jp2Converter::getFileFormat(const QString &filename) const +{ + QString extension = QFileInfo(filename).suffix().toLower(); + if (extension == "j2k" || extension == "j2c") { + return J2K_CFMT; + } else if (extension == "jp2") { + return JP2_CFMT; + } else if (extension == "jpt") { + return JPT_CFMT; + } + return -1; +} + + diff --git a/plugins/impex/jp2/jp2_converter.h b/plugins/impex/jp2/jp2_converter.h new file mode 100644 index 0000000000..cb24aa7b24 --- /dev/null +++ b/plugins/impex/jp2/jp2_converter.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009 Cyrille Berger + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 2.1 of the License. + * + * 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +#ifndef _JP2_CONVERTER_H_ +#define _JP2_CONVERTER_H_ + +#include + +#include + +#include "kis_types.h" +#include +class KisDocument; + +struct JP2ConvertOptions { + int rate; + int numberresolution; +}; + +class jp2Converter : public QObject +{ + Q_OBJECT +private: + enum { + J2K_CFMT = 0, + JP2_CFMT = 1, + JPT_CFMT = 2 + }; +public: + jp2Converter(KisDocument *doc); + virtual ~jp2Converter(); +public: + KisImageBuilder_Result buildImage(const QString &filename); + KisImageBuilder_Result buildFile(const QString &filename, KisPaintLayerSP layer, const JP2ConvertOptions& options); + /** + * Retrieve the constructed image + */ + KisImageWSP getImage(); +private: + KisImageBuilder_Result decode(const QString &filename); +public Q_SLOTS: + virtual void cancel(); +private: + int getFileFormat(const QString &filename) const; +private: + KisImageWSP m_image; + KisDocument *m_doc; + bool m_stop; +}; + +#endif diff --git a/plugins/impex/jp2/jp2_export.cc b/plugins/impex/jp2/jp2_export.cc new file mode 100644 index 0000000000..a7f92b35a2 --- /dev/null +++ b/plugins/impex/jp2/jp2_export.cc @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2009 Cyrille Berger + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 2.1 of the License. + * + * 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +#include "jp2_export.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "jp2_converter.h" + +#include "ui_kis_wdg_options_jp2.h" + +class KisExternalLayer; + +K_PLUGIN_FACTORY_WITH_JSON(ExportFactory, "krita_jp2_export.json", registerPlugin();) + +jp2Export::jp2Export(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) +{ +} + +jp2Export::~jp2Export() +{ +} + +KisImportExportFilter::ConversionStatus jp2Export::convert(const QByteArray& from, const QByteArray& to) +{ + dbgFile << "JP2 export! From:" << from << ", To:" << to << ""; + + if (from != "application/x-krita") + return KisImportExportFilter::NotImplemented; + + KisDocument *input = inputDocument(); + QString filename = outputFile(); + + if (!input) + return KisImportExportFilter::NoDocumentCreated; + + KisImageWSP image = input->image(); + Q_CHECK_PTR(image); + + if (filename.isEmpty()) return KisImportExportFilter::FileNotFound; + + KoDialog* kdb = new KoDialog(0); + kdb->setWindowTitle(i18n("JPEG 2000 Export Options")); + kdb->setButtons(KoDialog::Ok | KoDialog::Cancel); + + Ui::WdgOptionsJP2 optionsJP2; + + QWidget* wdg = new QWidget(kdb); + optionsJP2.setupUi(wdg); + + QString filterConfig = KisConfig().exportConfiguration("JP2"); + KisPropertiesConfiguration cfg; + cfg.fromXML(filterConfig); + optionsJP2.numberResolutions->setValue(cfg.getInt("number_resolutions", 6)); + optionsJP2.qualityLevel->setValue(cfg.getInt("quality", 100)); + + kdb->setMainWidget(wdg); + QApplication::restoreOverrideCursor(); + + if (!getBatchMode()) { + if (kdb->exec() == QDialog::Rejected) { + return KisImportExportFilter::UserCancelled; + } + } + + JP2ConvertOptions options; + options.numberresolution = optionsJP2.numberResolutions->value(); + cfg.setProperty("number_resolutions", options.numberresolution); + options.rate = optionsJP2.qualityLevel->value(); + cfg.setProperty("quality", options.rate); + + KisConfig().setExportConfiguration("JP2", cfg); + + + // the image must be locked at the higher levels + KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); + jp2Converter kpc(input); + + KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); + KisPaintLayerSP l = new KisPaintLayer(image, "projection", OPACITY_OPAQUE_U8, pd); + + KisImageBuilder_Result res; + + if ((res = kpc.buildFile(filename, l, options)) == KisImageBuilder_RESULT_OK) { + dbgFile << "success !"; + return KisImportExportFilter::OK; + } + dbgFile << " Result =" << res; + return KisImportExportFilter::InternalError; +} + +#include + diff --git a/plugins/impex/jp2/jp2_export.h b/plugins/impex/jp2/jp2_export.h new file mode 100644 index 0000000000..d55ef897fe --- /dev/null +++ b/plugins/impex/jp2/jp2_export.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2009 Cyrille Berger + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 2.1 of the License. + * + * 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +#ifndef _JP2_EXPORT_H_ +#define _JP2_EXPORT_H_ + +#include + +#include + +class jp2Export : public KisImportExportFilter +{ + Q_OBJECT +public: + jp2Export(QObject *parent, const QVariantList &); + virtual ~jp2Export(); +public: + virtual KisImportExportFilter::ConversionStatus convert(const QByteArray& from, const QByteArray& to); +}; + +#endif diff --git a/plugins/impex/jp2/jp2_import.cc b/plugins/impex/jp2/jp2_import.cc new file mode 100644 index 0000000000..2cf66afa54 --- /dev/null +++ b/plugins/impex/jp2/jp2_import.cc @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2009 Cyrille Berger + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 2.1 of the License. + * + * 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +#include "jp2_import.h" + +#include +#include + +#include + +#include +#include + +#include "jp2_converter.h" + +K_PLUGIN_FACTORY_WITH_JSON(ImportFactory, "krita_jp2_import.json", registerPlugin();) + +jp2Import::jp2Import(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) +{ +} + +jp2Import::~jp2Import() +{ +} + +KisImportExportFilter::ConversionStatus jp2Import::convert(const QByteArray&, const QByteArray& to) +{ + dbgFile << "Importing using JP2Import!"; + + if (to != "application/x-krita") + return KisImportExportFilter::BadMimeType; + + KisDocument * doc = outputDocument(); + + if (!doc) + return KisImportExportFilter::NoDocumentCreated; + + QString filename = inputFile(); + + doc->prepareForImport(); + + if (!filename.isEmpty()) { + + jp2Converter ib(doc); + + switch (ib.buildImage(filename)) { + case KisImageBuilder_RESULT_UNSUPPORTED: + return KisImportExportFilter::NotImplemented; + break; + case KisImageBuilder_RESULT_INVALID_ARG: + return KisImportExportFilter::BadMimeType; + break; + case KisImageBuilder_RESULT_NO_URI: + case KisImageBuilder_RESULT_NOT_LOCAL: + return KisImportExportFilter::FileNotFound; + break; + case KisImageBuilder_RESULT_BAD_FETCH: + case KisImageBuilder_RESULT_EMPTY: + return KisImportExportFilter::ParsingError; + break; + case KisImageBuilder_RESULT_FAILURE: + return KisImportExportFilter::InternalError; + break; + case KisImageBuilder_RESULT_OK: + doc -> setCurrentImage(ib.getImage()); + return KisImportExportFilter::OK; + default: + break; + } + + } + return KisImportExportFilter::StorageCreationError; +} + +#include + diff --git a/plugins/impex/jp2/jp2_import.h b/plugins/impex/jp2/jp2_import.h new file mode 100644 index 0000000000..fd51b67f40 --- /dev/null +++ b/plugins/impex/jp2/jp2_import.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2009 Cyrille Berger + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 2.1 of the License. + * + * 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +#ifndef JP2_IMPORT_H_ +#define JP2_IMPORT_H_ + +#include + +#include + +class jp2Import : public KisImportExportFilter +{ + Q_OBJECT +public: + jp2Import(QObject *parent, const QVariantList &); + virtual ~jp2Import(); +public: + virtual KisImportExportFilter::ConversionStatus convert(const QByteArray& from, const QByteArray& to); +}; + +#endif diff --git a/plugins/impex/jp2/kis_wdg_options_jp2.ui b/plugins/impex/jp2/kis_wdg_options_jp2.ui new file mode 100644 index 0000000000..da40c9d2ea --- /dev/null +++ b/plugins/impex/jp2/kis_wdg_options_jp2.ui @@ -0,0 +1,146 @@ + + + WdgOptionsJP2 + + + + 0 + 0 + 400 + 300 + + + + + + + + + Compression + + + + + + + <html><head/><body><p>These settings determine how much information is lost during compression. Low: small files, bad quality. High: big files, good quality.</p></body></html> + + + 0 + + + 100 + + + 10 + + + 1 + + + 100 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + + + + + 100 + + + 0 + + + 100 + + + + + + + + + + + Number of resolutions: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 1 + + + 20 + + + 6 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + qualityLevel + valueChanged(int) + intQuality + setValue(int) + + + 322 + 22 + + + 367 + 19 + + + + + intQuality + valueChanged(int) + qualityLevel + setValue(int) + + + 373 + 21 + + + 328 + 18 + + + + + diff --git a/plugins/impex/jp2/krita_jp2.desktop b/plugins/impex/jp2/krita_jp2.desktop new file mode 100644 index 0000000000..e7ca394f71 --- /dev/null +++ b/plugins/impex/jp2/krita_jp2.desktop @@ -0,0 +1,120 @@ +[Desktop Entry] +Categories=Qt;KDE;Office;Graphics; +Exec=krita %u +GenericName=Application for Drawing and Handling of Images +GenericName[bg]=Приложение за рисуване и обработка на изображения +GenericName[bs]=Aplikacija za crtanje i upravljanje slikom +GenericName[ca]=Aplicació per a dibuix i modificació d'imatges +GenericName[ca@valencia]=Aplicació per a dibuix i modificació d'imatges +GenericName[da]=Tegne- og billedbehandlingsprogram +GenericName[de]=Programm zum Zeichnen und Bearbeiten von Bildern +GenericName[el]=Εφαρμογή για επεξεργασία και χειρισμό εικόνων +GenericName[en_GB]=Application for Drawing and Handling of Images +GenericName[eo]=Aplikaĵo por Desegnado kaj Mastrumado de Bildoj +GenericName[es]=Aplicación para dibujo y manipulación de imágenes +GenericName[et]=Joonistamise ja pilditöötluse rakendus +GenericName[eu]=Irudiak marrazteko eta manipulatzeko aplikazioa +GenericName[fa]=کاربرد برای ترسیم و به کار بردن تصاویر +GenericName[fi]=Ohjelma kuvien piirtämiseen ja käsittelyyn +GenericName[fr]=Application pour dessiner et manipuler des images +GenericName[fy]=Aplikaasje om ôfbyldings mei te tekenjen en te bewurkjen +GenericName[ga]=Feidhmchlár le haghaidh Líníochta agus Láimhseála Íomhánna +GenericName[gl]=Aplicativo de debuxo e edición de imaxes +GenericName[he]=יישום לצביעה וניהול תמונות +GenericName[hi]=छवियों को ड्रा करने तथा उन्हें प्रबन्धित करने का अनुप्रयोग +GenericName[hne]=फोटू मन ल ड्रा करे अउ ओ मन ल प्रबन्धित करे के अनुपरयोग +GenericName[hu]=Rajzoló és képkezelő +GenericName[is]=Teikni og myndvinnsluforrit +GenericName[it]=Applicazione di disegno e gestione di immagini +GenericName[kk]=Кескінді салу және өңдеу бағдарламасы +GenericName[ko]=그림 그리기 및 처리 프로그램 +GenericName[lv]=Programma zīmēšanai un attēlu apstrādei +GenericName[nb]=Program for tegning og bildehåndtering +GenericName[nds]=Programm för't Teken un Bildhanteren +GenericName[ne]=रेखाचित्र बनाउन र छविको ह्यान्डल गर्नका लागि अनुप्रयोग +GenericName[nl]=Toepassing om afbeeldingen te tekenen en te bewerken +GenericName[pl]=Program do rysowania i obróbki obrazów +GenericName[pt]=Aplicação de Desenho e Manipulação de Imagens +GenericName[pt_BR]=Aplicativo de desenho e manipulação de imagens +GenericName[ru]=Растровые изображения +GenericName[sk]=Aplikácia na kresnenie a manilupáciu s obrázkami +GenericName[sl]=Program za risanje in rokovanje s slikami +GenericName[sv]=Program för att rita och hantera bilder +GenericName[ta]=பிம்பங்களை கையாளுதல் மற்றும் வரைதலுக்கான பயன்னாடு +GenericName[tr]=Çizim ve Resim İşleme Uygulaması +GenericName[uk]=Програма для малювання і обробки зображень +GenericName[uz]=Rasm chizish dasturi +GenericName[uz@cyrillic]=Расм чизиш дастури +GenericName[wa]=Programe po dessiner et apougnî des imådjes +GenericName[x-test]=xxApplication for Drawing and Handling of Imagesxx +GenericName[zh_CN]=绘制和操纵图像的应用程序 +GenericName[zh_TW]=影像繪製與處理應用程式 +Icon=calligrakrita +MimeType=image/jp2; +Name=Krita +Name[af]=Krita +Name[bg]=Krita +Name[br]=Krita +Name[bs]=Krita +Name[ca]=Krita +Name[ca@valencia]=Krita +Name[cs]=Krita +Name[cy]=Krita +Name[da]=Krita +Name[de]=Krita +Name[el]=Krita +Name[en_GB]=Krita +Name[eo]=Krita +Name[es]=Krita +Name[et]=Krita +Name[eu]=Krita +Name[fi]=Krita +Name[fr]=Krita +Name[fy]=Krita +Name[ga]=Krita +Name[gl]=Krita +Name[he]=Krita +Name[hi]=केरिता +Name[hne]=केरिता +Name[hr]=Krita +Name[hu]=Krita +Name[ia]=Krita +Name[is]=Krita +Name[it]=Krita +Name[kk]=Krita +Name[ko]=Krita +Name[lt]=Krita +Name[lv]=Krita +Name[mr]=क्रिटा +Name[ms]=Krita +Name[nb]=Krita +Name[nds]=Krita +Name[ne]=क्रिता +Name[nl]=Krita +Name[pl]=Krita +Name[pt]=Krita +Name[pt_BR]=Krita +Name[ro]=Krita +Name[ru]=Krita +Name[se]=Krita +Name[sk]=Krita +Name[sl]=Krita +Name[sv]=Krita +Name[ta]=கிரிட்டா +Name[tg]=Krita +Name[tr]=Krita +Name[ug]=Krita +Name[uk]=Krita +Name[uz]=Krita +Name[uz@cyrillic]=Krita +Name[wa]=Krita +Name[xh]=Krita +Name[x-test]=xxKritaxx +Name[zh_CN]=Krita +Name[zh_TW]=繪圖_Krita +StartupNotify=true +Terminal=false +Type=Application +X-KDE-SubstituteUID=false +X-KDE-Username= +NoDisplay=true diff --git a/plugins/impex/jp2/krita_jp2_export.json b/plugins/impex/jp2/krita_jp2_export.json new file mode 100644 index 0000000000..5b91b4d7b0 --- /dev/null +++ b/plugins/impex/jp2/krita_jp2_export.json @@ -0,0 +1,13 @@ +{ + "Icon": "", + "Id": "Krita jp2 Export Filter", + "Type": "Service", + "X-KDE-Export": "image/jp2", + "X-KDE-Import": "application/x-krita", + "X-KDE-Library": "kritajp2export", + "X-KDE-ServiceTypes": [ + "Krita/FileFilter" + ], + "X-KDE-Weight": "1", + "X-KDE-Extensions" : "jp2" +} diff --git a/plugins/impex/jp2/krita_jp2_import.json b/plugins/impex/jp2/krita_jp2_import.json new file mode 100644 index 0000000000..ade36b72cd --- /dev/null +++ b/plugins/impex/jp2/krita_jp2_import.json @@ -0,0 +1,13 @@ +{ + "Icon": "", + "Id": "Krita jp2 Import Filter", + "Type": "Service", + "X-KDE-Export": "application/x-krita", + "X-KDE-Import": "image/jp2", + "X-KDE-Library": "kritajp2import", + "X-KDE-ServiceTypes": [ + "Krita/FileFilter" + ], + "X-KDE-Weight": "1", + "X-KDE-Extensions" : "jp2" +}