diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index e144f4189..81a7f699f 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -35,7 +35,20 @@ jobs: echo "Running apt update." sudo apt update echo "Installing dependencies with apt." - DEBIAN_FRONTEND=noninteractive sudo apt install -y cmake libgtk-3-dev libgtkmm-3.0-dev liblensfun-dev librsvg2-dev liblcms2-dev libfftw3-dev libiptcdata0-dev libtiff5-dev libcanberra-gtk3-dev liblensfun-bin libexpat1-dev libbrotli-dev zlib1g-dev libinih-dev adwaita-icon-theme-full + DEBIAN_FRONTEND=noninteractive sudo apt install -y cmake libgtk-3-dev libgtkmm-3.0-dev liblensfun-dev librsvg2-dev liblcms2-dev libfftw3-dev libiptcdata0-dev libtiff5-dev libcanberra-gtk3-dev liblensfun-bin libexpat1-dev libbrotli-dev zlib1g-dev libinih-dev adwaita-icon-theme-full gettext libarchive-tools zstd libgif-dev libwebp-dev libwebpdemux2 + + - name: Install makedeb + run: | + echo "Installing makedeb..." + curl -Ss -qgb "" -fLC - --retry 3 --retry-delay 3 -o makedeb.deb \ + "https://github.com/makedeb/makedeb/releases/download/v16.1.0-beta1/makedeb-beta_16.1.0-beta1_amd64_focal.deb" + DEBIAN_FRONTEND=noninteractive sudo dpkg -i makedeb.deb + + - name: Install libjxl + working-directory: tools/makedeb + run: | + echo "Building and installing libjxl..." + makedeb -si --no-confirm -p PKGBUILD.libjxl - name: Install Exiv2 run: | diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5cb91e47a..7d58d2f7f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -41,7 +41,17 @@ jobs: echo "Running apt update." sudo apt update echo "Installing dependencies with apt." - DEBIAN_FRONTEND=noninteractive sudo apt install -y cmake libgtk-3-dev libgtkmm-3.0-dev liblensfun-dev librsvg2-dev liblcms2-dev libfftw3-dev libiptcdata0-dev libtiff5-dev libcanberra-gtk3-dev liblensfun-bin libexiv2-dev + DEBIAN_FRONTEND=noninteractive sudo apt install -y cmake libgtk-3-dev libgtkmm-3.0-dev liblensfun-dev librsvg2-dev liblcms2-dev libfftw3-dev libiptcdata0-dev libtiff5-dev libcanberra-gtk3-dev liblensfun-bin libexiv2-dev libtcmalloc-minimal4 libhwy0 libhwy-dev + + - name: Install libjxl + run: | + echo "Downloading and installing libjxl..." + VERSION_UBUNTU=22.04 + VERSION_JXL=0.10.2 + curl -Ss -qgb "" -fLC - --retry 3 --retry-delay 3 -o libjxl-debs.tar.gz \ + "https://github.com/libjxl/libjxl/releases/download/v${VERSION_JXL}/jxl-debs-amd64-ubuntu-${VERSION_UBUNTU}-v${VERSION_JXL}.tar.gz" + tar xf libjxl-debs.tar.gz + DEBIAN_FRONTEND=noninteractive sudo dpkg -i jxl_${VERSION_JXL}_amd64.deb libjxl-dev_${VERSION_JXL}_amd64.deb libjxl_${VERSION_JXL}_amd64.deb - name: Configure build run: | diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 8755f7c66..ad16f96d5 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -25,7 +25,7 @@ jobs: mkdir build date +%s > build/stamp brew uninstall --ignore-dependencies libtiff - brew install libtiff gtk+3 gtkmm3 gtk-mac-integration adwaita-icon-theme libsigc++@2 little-cms2 libiptcdata fftw lensfun expat pkgconfig llvm shared-mime-info exiv2 | tee -a depslog + brew install libtiff gtk+3 gtkmm3 gtk-mac-integration adwaita-icon-theme libsigc++@2 little-cms2 libiptcdata fftw lensfun expat pkgconfig llvm shared-mime-info exiv2 jpeg-xl | tee -a depslog date -u echo "----====Pourage====----" cat depslog | grep Pouring diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index e5f4ce166..950b20aad 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -53,6 +53,7 @@ jobs: fftw:p lensfun:p libiptcdata:p + libjxl:p exiv2:p - name: Configure build diff --git a/AboutThisBuild.txt.in b/AboutThisBuild.txt.in index 4d8f4f3fe..7c42f244e 100644 --- a/AboutThisBuild.txt.in +++ b/AboutThisBuild.txt.in @@ -6,8 +6,9 @@ Compiler: ${COMPILER_INFO} Processor: ${PROC_LABEL} System: ${SYSTEM} Bit depth: ${PROC_BIT_DEPTH} -Gtkmm: V${GTKMM_VERSION} -Lensfun: V${LENSFUN_VERSION} +Gtkmm: ${GTKMM_VERSION} +Lensfun: ${LENSFUN_VERSION} +libjxl: ${JXL_VERSION} Build type: ${BUILD_TYPE} Build flags: ${CXX_FLAGS} Link flags: ${LFLAGS} diff --git a/CMakeLists.txt b/CMakeLists.txt index 051d215e2..7696270ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -247,6 +247,9 @@ set(TCMALLOC_LIB_DIR "" CACHE PATH "Custom path for the tcmalloc library") +set(WITH_JXL "AUTO" CACHE STRING "Build with JPEG XL support") +set_property(CACHE WITH_JXL PROPERTY STRINGS AUTO ON OFF) + # Set installation directories: if(WIN32 OR APPLE) if(BUILD_BUNDLE) @@ -552,6 +555,32 @@ if(WITH_SYSTEM_KLT) find_package(KLT REQUIRED) endif() +if(WITH_JXL AND NOT WITH_JXL STREQUAL "AUTO") + set(JXL_REQUIRED "REQUIRED") +else() + set(JXL_REQUIRED "") +endif() +pkg_check_modules(JXL ${JXL_REQUIRED} IMPORTED_TARGET libjxl) +pkg_check_modules(JXLTHREADS ${JXL_REQUIRED} IMPORTED_TARGET libjxl_threads) +if(JXL_FOUND) + if(WITH_JXL OR WITH_JXL STREQUAL "AUTO") + add_definitions(-DLIBJXL) + list(APPEND JXL_INCLUDE_DIRS ${JXLTHREADS_INCLUDE_DIRS}) + list(APPEND JXL_LIBRARIES ${JXLTHREADS_LIBRARIES}) + else() + message(STATUS " JXL support disabled by WITH_JXL = ${WITH_JXL}") + string(APPEND JXL_VERSION " - Disabled") + set(JXL_INCLUDE_DIRS "") + set(JXL_LIBRARIES "") + set(JXLTHREADS_INCLUDE_DIRS "") + set(JXLTHREADS_LIBRARIES "") + endif() +elseif(WITH_JXL STREQUAL "AUTO") + set(JXL_VERSION "Disabled, Auto") +else() + set(JXL_VERSION "Disabled") +endif() + # Check for libcanberra-gtk3 (sound events on Linux): if(UNIX AND (NOT APPLE)) option(USE_LIBCANBERRA "Build with libcanberra" ON) @@ -732,6 +761,7 @@ if(NOT APPLE) -DGTKMM_VERSION:STRING=${GTKMM_VERSION} -DOPTION_OMP:STRING=${OPTION_OMP} -DWITH_MYFILE_MMAP:STRING=${WITH_MYFILE_MMAP} + -DJXL_VERSION:STRING=${JXL_VERSION} -DLENSFUN_VERSION:STRING=${LENSFUN_VERSION}) endif() @@ -761,6 +791,7 @@ elseif(APPLE) -DGTKMM_VERSION:STRING=${GTKMM_VERSION} -DOPTION_OMP:STRING=${OPTION_OMP} -DWITH_MYFILE_MMAP:STRING=${WITH_MYFILE_MMAP} + -DJXL_VERSION:STRING=${JXL_VERSION} -DLENSFUN_VERSION:STRING=${LENSFUN_VERSION} -P ${PROJECT_SOURCE_DIR}/UpdateInfo.cmake) else() diff --git a/rtdata/languages/Catala b/rtdata/languages/Catala index 03353cdb7..bc95d7546 100644 --- a/rtdata/languages/Catala +++ b/rtdata/languages/Catala @@ -555,6 +555,7 @@ PROFILEPANEL_TOOLTIPSAVE;Desa l'actual com a perfil.\nCtrl-click per sele PROGRESSBAR_LOADING;Carregant imatge... PROGRESSBAR_LOADINGTHUMBS;Carregant minifotos... PROGRESSBAR_LOADJPEG;Carregant fitxer JPEG... +PROGRESSBAR_LOADJXL;Carregant fitxer JXL... PROGRESSBAR_LOADPNG;Carregant fitxer PNG... PROGRESSBAR_LOADTIFF;Carregant fitxer TIFF... PROGRESSBAR_PROCESSING;Processant imatge... diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified) index 53aca2046..bf485e4cd 100644 --- a/rtdata/languages/Chinese (Simplified) +++ b/rtdata/languages/Chinese (Simplified) @@ -1244,6 +1244,7 @@ PROGRESSBAR_LINEDENOISE;线状噪点过滤... PROGRESSBAR_LOADING;图片加载中... PROGRESSBAR_LOADINGTHUMBS;读取缩略图... PROGRESSBAR_LOADJPEG;JPEG文件加载中... +PROGRESSBAR_LOADJXL;JXL文件加载中... PROGRESSBAR_LOADPNG;PNG文件加载中... PROGRESSBAR_LOADTIFF;TIFF文件加载中... PROGRESSBAR_NOIMAGES;未找到图片 diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech index 232c094e0..995f089db 100644 --- a/rtdata/languages/Czech +++ b/rtdata/languages/Czech @@ -1306,6 +1306,7 @@ PROGRESSBAR_LINEDENOISE;Filtr linkového rušení… PROGRESSBAR_LOADING;Načítání obrázku... PROGRESSBAR_LOADINGTHUMBS;Načítání náhledů... PROGRESSBAR_LOADJPEG;Načítání JPEG... +PROGRESSBAR_LOADJXL;Načítání JXL... PROGRESSBAR_LOADPNG;Načítání PNG... PROGRESSBAR_LOADTIFF;Načítání TIFF... PROGRESSBAR_NOIMAGES;Složka neobsahuje obrázky diff --git a/rtdata/languages/Dansk b/rtdata/languages/Dansk index ed2e32616..e42f0bc83 100644 --- a/rtdata/languages/Dansk +++ b/rtdata/languages/Dansk @@ -1224,6 +1224,7 @@ PROGRESSBAR_LINEDENOISE;Linje støjfilter... PROGRESSBAR_LOADING;Indlæser billede... PROGRESSBAR_LOADINGTHUMBS;Indlæser thumbnails... PROGRESSBAR_LOADJPEG; Indlæser JPEG fil... +PROGRESSBAR_LOADJXL; Indlæser JXL fil... PROGRESSBAR_LOADPNG; Indlæser PNG fil... PROGRESSBAR_LOADTIFF;Indlæser TIFF fil... PROGRESSBAR_NOIMAGES;Ingen billeder fundet diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 84c52d64f..677efd8e0 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -2147,6 +2147,7 @@ PROGRESSBAR_LINEDENOISE;Linienrauschfilter... PROGRESSBAR_LOADING;Lade Bild... PROGRESSBAR_LOADINGTHUMBS;Lade Miniaturbilder... PROGRESSBAR_LOADJPEG;Lade JPEG... +PROGRESSBAR_LOADJXL;Lade JXL... PROGRESSBAR_LOADPNG;Lade PNG... PROGRESSBAR_LOADTIFF;Lade TIFF... PROGRESSBAR_NOIMAGES;Keine Bilder gefunden diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index f03dbd1af..37ccdc48f 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -2259,6 +2259,7 @@ TP_WBALANCE_PATCHLABEL_TOOLTIP;Display number of read colours (max=237).\nDispla !PROGRESSBAR_LOADING;Loading image... !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... !PROGRESSBAR_LOADJPEG;Loading JPEG file... +!PROGRESSBAR_LOADJXL;Loading JXL file... !PROGRESSBAR_LOADPNG;Loading PNG file... !PROGRESSBAR_LOADTIFF;Loading TIFF file... !PROGRESSBAR_NOIMAGES;No images found diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index 329925625..079713ac1 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -2082,6 +2082,7 @@ !PROGRESSBAR_LOADING;Loading image... !PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... !PROGRESSBAR_LOADJPEG;Loading JPEG file... +!PROGRESSBAR_LOADJXL;Loading JXL file... !PROGRESSBAR_LOADPNG;Loading PNG file... !PROGRESSBAR_LOADTIFF;Loading TIFF file... !PROGRESSBAR_NOIMAGES;No images found diff --git a/rtdata/languages/Espanol (Castellano) b/rtdata/languages/Espanol (Castellano) index 32b5791dc..9f9cc48bf 100644 --- a/rtdata/languages/Espanol (Castellano) +++ b/rtdata/languages/Espanol (Castellano) @@ -2006,6 +2006,7 @@ PROGRESSBAR_LINEDENOISE;Filtro de ruido de línea... PROGRESSBAR_LOADING;Cargando imagen... PROGRESSBAR_LOADINGTHUMBS;Cargando miniaturas... PROGRESSBAR_LOADJPEG;Cargando archivo JPEG... +PROGRESSBAR_LOADJXL;Cargando archivo JXL... PROGRESSBAR_LOADPNG;Cargando archivo PNG... PROGRESSBAR_LOADTIFF;Cargando archivo TIFF... PROGRESSBAR_NOIMAGES;No se encuentran imágenes diff --git a/rtdata/languages/Espanol (Latin America) b/rtdata/languages/Espanol (Latin America) index 9d5e352bd..816b237c6 100644 --- a/rtdata/languages/Espanol (Latin America) +++ b/rtdata/languages/Espanol (Latin America) @@ -1253,6 +1253,7 @@ PROFILEPANEL_TOOLTIPSAVE;Guardar perfil actual.\nCtrl-click para seleccio PROGRESSBAR_LOADING;Abriendo imagen... PROGRESSBAR_LOADINGTHUMBS;Cargando miniaturas... PROGRESSBAR_LOADJPEG;Abriendo archivo JPEG... +PROGRESSBAR_LOADJXL;Abriendo archivo JXL... PROGRESSBAR_LOADPNG;Abriendo archivo PNG... PROGRESSBAR_LOADTIFF;Abriendo archivo TIFF... PROGRESSBAR_NOIMAGES;No se han encontrado imágenes diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 33ffc861c..53e478f78 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -1210,6 +1210,7 @@ PROFILEPANEL_TOOLTIPSAVE;Enregistrer le profil actuel\nCTRL-clic pour sé PROGRESSBAR_LOADING;Chargement de l'Image... PROGRESSBAR_LOADINGTHUMBS;Chargement des vignettes... PROGRESSBAR_LOADJPEG;Chargement du fichier JPEG... +PROGRESSBAR_LOADJXL;Chargement du fichier JXL... PROGRESSBAR_LOADPNG;Chargement du fichier PNG... PROGRESSBAR_LOADTIFF;Chargement du fichier TIFF... PROGRESSBAR_NOIMAGES;Pas d'image trouvée diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano index 5ef63de7b..8e1f6124d 100644 --- a/rtdata/languages/Italiano +++ b/rtdata/languages/Italiano @@ -2088,6 +2088,7 @@ PROGRESSBAR_LINEDENOISE;Filtro antirumore di linea... PROGRESSBAR_LOADING;Caricamento immagine... PROGRESSBAR_LOADINGTHUMBS;Caricamento miniature... PROGRESSBAR_LOADJPEG;Caricamento JPEG... +PROGRESSBAR_LOADJXL;Caricamento JXL... PROGRESSBAR_LOADPNG;Caricamento PNG... PROGRESSBAR_LOADTIFF;Caricamento TIFF... PROGRESSBAR_NOIMAGES;Nessuna immagine trovata diff --git a/rtdata/languages/Japanese b/rtdata/languages/Japanese index 8bfbf0f42..290e42b57 100644 --- a/rtdata/languages/Japanese +++ b/rtdata/languages/Japanese @@ -2005,6 +2005,7 @@ PROGRESSBAR_LINEDENOISE;ラインノイズフィルタ。。。 PROGRESSBAR_LOADING;画像読み込み中... PROGRESSBAR_LOADINGTHUMBS;サムネイルの読み込み... PROGRESSBAR_LOADJPEG;JPEGファイル読み込み中... +PROGRESSBAR_LOADJXL;JXLファイル読み込み中... PROGRESSBAR_LOADPNG;PNGファイル読み込み中... PROGRESSBAR_LOADTIFF;TIFFファイル読み込み中... PROGRESSBAR_NOIMAGES;画像が見つかりません diff --git a/rtdata/languages/Magyar b/rtdata/languages/Magyar index 07ab9784b..8336efda8 100644 --- a/rtdata/languages/Magyar +++ b/rtdata/languages/Magyar @@ -1084,6 +1084,7 @@ PROGRESSBAR_LINEDENOISE;Sorzajszűrő... PROGRESSBAR_LOADING;Kép betöltése... PROGRESSBAR_LOADINGTHUMBS;Előnézeti képek betöltése... PROGRESSBAR_LOADJPEG;JPEG fájl betöltése... +PROGRESSBAR_LOADJXL;JXL fájl betöltése... PROGRESSBAR_LOADPNG;PNG fájl betöltése... PROGRESSBAR_LOADTIFF;TIFF fájl betöltése... PROGRESSBAR_NOIMAGES;Nem találhatóak képek diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands index a0418e70c..af2862781 100644 --- a/rtdata/languages/Nederlands +++ b/rtdata/languages/Nederlands @@ -1242,6 +1242,7 @@ PROGRESSBAR_LINEDENOISE;Lijnruisfilter... PROGRESSBAR_LOADING;Afbeelding laden... PROGRESSBAR_LOADINGTHUMBS;Miniaturen laden... PROGRESSBAR_LOADJPEG;Laden JPEG-bestand... +PROGRESSBAR_LOADJXL;Laden JXL-bestand... PROGRESSBAR_LOADPNG;Laden PNG-bestand... PROGRESSBAR_LOADTIFF;Laden TIFF-bestand... PROGRESSBAR_NOIMAGES;Geen afbeeldingen diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish index 94df4424f..7ad5c1792 100644 --- a/rtdata/languages/Polish +++ b/rtdata/languages/Polish @@ -1192,6 +1192,7 @@ PROGRESSBAR_LINEDENOISE;Liniowy filtr szumu... PROGRESSBAR_LOADING;Wczytywanie obrazu... PROGRESSBAR_LOADINGTHUMBS;Wczytywanie miniatur... PROGRESSBAR_LOADJPEG;Ładowanie pliku JPEG... +PROGRESSBAR_LOADJXL;Ładowanie pliku JXL... PROGRESSBAR_LOADPNG;Ładowanie pliku PNG... PROGRESSBAR_LOADTIFF;Ładowanie pliku TIFF... PROGRESSBAR_NOIMAGES;Nie znaleziono żadnych obrazów diff --git a/rtdata/languages/Portugues b/rtdata/languages/Portugues index 77ffcaf40..e037c565c 100644 --- a/rtdata/languages/Portugues +++ b/rtdata/languages/Portugues @@ -1197,6 +1197,7 @@ PROFILEPANEL_TOOLTIPSAVE;Guardar o perfil atual.\nCtrl-click para selecio PROGRESSBAR_LOADING;A carregar a imagem... PROGRESSBAR_LOADINGTHUMBS;A carregar as miniaturas... PROGRESSBAR_LOADJPEG;A carregar o ficheiro JPEG... +PROGRESSBAR_LOADJXL;A carregar o ficheiro JXL... PROGRESSBAR_LOADPNG;A carregar o ficheiro PNG... PROGRESSBAR_LOADTIFF;A carregar o ficheiro TIFF... PROGRESSBAR_NOIMAGES;Não foi encontrada nenhuma imagem diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil) index c22207212..133205a09 100644 --- a/rtdata/languages/Portugues (Brasil) +++ b/rtdata/languages/Portugues (Brasil) @@ -1207,6 +1207,7 @@ PROGRESSBAR_LINEDENOISE;Filtro de ruído de linha... PROGRESSBAR_LOADING;Carregando imagem... PROGRESSBAR_LOADINGTHUMBS;Carregando miniaturas... PROGRESSBAR_LOADJPEG;Carregando arquivo JPEG... +PROGRESSBAR_LOADJXL;Carregando arquivo JXL... PROGRESSBAR_LOADPNG;Carregando arquivo PNG... PROGRESSBAR_LOADTIFF;Carregando arquivo TIFF... PROGRESSBAR_NOIMAGES;Nenhuma imagem encontrada diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian index 74a08f2d3..de0846e01 100644 --- a/rtdata/languages/Russian +++ b/rtdata/languages/Russian @@ -843,6 +843,7 @@ PROFILEPANEL_TOOLTIPSAVE;Сохранить текущий профиль\nCt PROGRESSBAR_LOADING;Загрузка изображения... PROGRESSBAR_LOADINGTHUMBS;Загрузка миниатюр... PROGRESSBAR_LOADJPEG;Чтение JPEG файла... +PROGRESSBAR_LOADJXL;Чтение JXL файла... PROGRESSBAR_LOADPNG;Чтение PNG файла... PROGRESSBAR_LOADTIFF;Чтение TIFF файла... PROGRESSBAR_NOIMAGES;Изображения не найдены diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters) index 1cf1086bf..15bb90737 100644 --- a/rtdata/languages/Serbian (Cyrilic Characters) +++ b/rtdata/languages/Serbian (Cyrilic Characters) @@ -670,6 +670,7 @@ PROFILEPANEL_TOOLTIPSAVE;Чува тренутни профил PROGRESSBAR_LOADING;Учитавам слику... PROGRESSBAR_LOADINGTHUMBS;Учитавам приказе... PROGRESSBAR_LOADJPEG;Учитавам JPEG датотеку... +PROGRESSBAR_LOADJPEG;Учитавам JXL датотеку... PROGRESSBAR_LOADPNG;Учитавам PNG датотеку... PROGRESSBAR_LOADTIFF;Учитавам TIFF датотеку... PROGRESSBAR_NOIMAGES;Нису пронађене слике diff --git a/rtdata/languages/Slovenian b/rtdata/languages/Slovenian index 84ea9e72e..1ba151693 100644 --- a/rtdata/languages/Slovenian +++ b/rtdata/languages/Slovenian @@ -1221,6 +1221,7 @@ PROGRESSBAR_LINEDENOISE;Filter linijskega šuma... PROGRESSBAR_LOADING;Nalagam sliko... PROGRESSBAR_LOADINGTHUMBS;Nalagam predogledne sličice... PROGRESSBAR_LOADJPEG;Nalagam datoteko JPEG... +PROGRESSBAR_LOADJXL;Nalagam datoteko JXL... PROGRESSBAR_LOADPNG;Nalagam datoteko PNG... PROGRESSBAR_LOADTIFF;Nalagam datoteko TIFF... PROGRESSBAR_NOIMAGES;Ne najdem nobene slike diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish index 0ff9f831f..edbeb9e3a 100644 --- a/rtdata/languages/Swedish +++ b/rtdata/languages/Swedish @@ -911,6 +911,7 @@ PROFILEPANEL_TOOLTIPSAVE;Spara nuvarande profil.\nCtrl-klicka för att v PROGRESSBAR_LOADING;Laddar bild... PROGRESSBAR_LOADINGTHUMBS;Laddar miniatyrbilder... PROGRESSBAR_LOADJPEG;Laddar JPEG-fil... +PROGRESSBAR_LOADJXL;Laddar JXL-fil... PROGRESSBAR_LOADPNG;Laddar PNG-fil... PROGRESSBAR_LOADTIFF;Laddar TIFF-fil... PROGRESSBAR_NOIMAGES;Inga bilder funna. diff --git a/rtdata/languages/default b/rtdata/languages/default index dfd7e76b7..75d060dec 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -2151,6 +2151,7 @@ PROGRESSBAR_LINEDENOISE;Line noise filter... PROGRESSBAR_LOADING;Loading image... PROGRESSBAR_LOADINGTHUMBS;Loading thumbnails... PROGRESSBAR_LOADJPEG;Loading JPEG file... +PROGRESSBAR_LOADJXL;Loading JXL file... PROGRESSBAR_LOADPNG;Loading PNG file... PROGRESSBAR_LOADTIFF;Loading TIFF file... PROGRESSBAR_NOIMAGES;No images found diff --git a/rtdata/options/options.lin b/rtdata/options/options.lin index fbd8bc6cb..2a96c6997 100644 --- a/rtdata/options/options.lin +++ b/rtdata/options/options.lin @@ -12,8 +12,8 @@ MultiUser=true [File Browser] # Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include) -ParseExtensions=3fr;arw;arq;cr2;cr3;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;ori;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; -ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;1;1;1;1;1;1;1;1;1;1;1; +ParseExtensions=3fr;arw;arq;cr2;cr3;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;jxl;kdc;mef;mos;mrw;nef;nrw;orf;ori;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; +ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;1;1;1;1;1;1;1;1;1;1;1; [Output] PathTemplate=%p1/converted/%f diff --git a/rtdata/options/options.osx b/rtdata/options/options.osx index ef68d7144..eff9cd8d9 100644 --- a/rtdata/options/options.osx +++ b/rtdata/options/options.osx @@ -13,8 +13,8 @@ UseSystemTheme=false [File Browser] # Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include) -ParseExtensions=3fr;arw;arq;cr2;cr3;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;ori;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; -ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;1;1;1;1;1;1;1;1;1;1;1; +ParseExtensions=3fr;arw;arq;cr2;cr3;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;jxl;kdc;mef;mos;mrw;nef;nrw;orf;ori;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; +ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;1;1;1;1;1;1;1;1;1;1;1; [Output] PathTemplate=%p1/converted/%f diff --git a/rtdata/options/options.win b/rtdata/options/options.win index 00b74d07f..e3f43343e 100644 --- a/rtdata/options/options.win +++ b/rtdata/options/options.win @@ -14,8 +14,8 @@ UseSystemTheme=false [File Browser] # Image filename extensions to be looked for, and their corresponding search state (0/1 -> skip/include) -ParseExtensions=3fr;arw;arq;cr2;cr3;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;kdc;mef;mos;mrw;nef;nrw;orf;ori;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; -ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;1;1;1;1;1;1;1;1;1;1;1; +ParseExtensions=3fr;arw;arq;cr2;cr3;crf;crw;dcr;dng;fff;iiq;jpg;jpeg;jxl;kdc;mef;mos;mrw;nef;nrw;orf;ori;pef;png;raf;raw;rw2;rwl;rwz;sr2;srf;srw;tif;tiff;x3f; +ParseExtensionsEnabled=1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;1;1;1;1;1;1;1;1;1;1;1; [Output] PathTemplate=%p1/converted/%f diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 6f329f7be..5d87310b9 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -45,6 +45,9 @@ endif() if(EXIV2_INCLUDE_DIRS) include_directories("${EXIV2_INCLUDE_DIRS}") endif() +if(JXL_INCLUDE_DIRS) + include_directories("${JXL_INCLUDE_DIRS}") +endif() link_directories( "${EXPAT_LIBRARY_DIRS}" @@ -246,6 +249,7 @@ target_link_libraries(rtengine ${RSVG_LIBRARIES} ${KLT_LIBRARIES} ${EXIV2_LIBRARIES} + ${JXL_LIBRARIES} ) if(OpenMP_FOUND) diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index f096213dc..04bdbfb93 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -25,6 +25,11 @@ #include #include +#ifdef LIBJXL +#include "jxl/decode_cxx.h" +#include "jxl/resizable_parallel_runner_cxx.h" +#endif + #include #include #include @@ -823,6 +828,171 @@ int ImageIO::loadTIFF (const Glib::ustring &fname) return IMIO_SUCCESS; } +#ifdef LIBJXL +#define _PROFILE_ JXL_COLOR_PROFILE_TARGET_ORIGINAL +// adapted from libjxl +int ImageIO::loadJXL(const Glib::ustring &fname) +{ + if (pl) { + pl->setProgressStr("PROGRESSBAR_LOADJXL"); + pl->setProgress(0.0); + } + + std::vector icc_profile; + std::vector buffer; + std::size_t buffer_size = 0; + + JxlBasicInfo info = {}; + JxlPixelFormat format = {}; + + format.num_channels = 3; + format.data_type = JXL_TYPE_FLOAT; + format.endianness = JXL_NATIVE_ENDIAN; + format.align = 0; + + std::vector const compressed = getFileData(fname); + + if (compressed.empty()) { + std::cerr << "Error: loadJXL failed to get data from file" << std::endl; + return IMIO_READERROR; + } + + // multi-threaded parallel runner. + auto runner = JxlResizableParallelRunnerMake(nullptr); + + auto dec = JxlDecoderMake(nullptr); + + if (JXL_DEC_SUCCESS != + JxlDecoderSubscribeEvents(dec.get(), JXL_DEC_BASIC_INFO | + JXL_DEC_COLOR_ENCODING | + JXL_DEC_FULL_IMAGE)) { + std::cerr << "Error: JxlDecoderSubscribeEvents failed" << std::endl; + return IMIO_HEADERERROR; + } + + if (JXL_DEC_SUCCESS != + JxlDecoderSetParallelRunner(dec.get(), JxlResizableParallelRunner, + runner.get())) { + std::cerr << "Error: JxlDecoderSetParallelRunner failed" << std::endl; + return IMIO_HEADERERROR; + } + + // grand decode loop... + JxlDecoderSetInput(dec.get(), compressed.data(), compressed.size()); + + while (true) { + JxlDecoderStatus status = JxlDecoderProcessInput(dec.get()); + + if (status == JXL_DEC_BASIC_INFO) { + if (JXL_DEC_SUCCESS != JxlDecoderGetBasicInfo(dec.get(), &info)) { + std::cerr << "Error: JxlDecoderGetBasicInfo failed" << std::endl; + return IMIO_HEADERERROR; + } + + JxlResizableParallelRunnerSetThreads( + runner.get(), + JxlResizableParallelRunnerSuggestThreads(info.xsize, info.ysize)); + } else if (status == JXL_DEC_COLOR_ENCODING) { + // check for ICC profile + deleteLoadedProfileData(); + embProfile = nullptr; + std::size_t icc_size = 0; + + if (JXL_DEC_SUCCESS != +#if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0) + JxlDecoderGetICCProfileSize(dec.get(), &format, _PROFILE_, &icc_size) +#else + JxlDecoderGetICCProfileSize(dec.get(), _PROFILE_, &icc_size) +#endif + ) { + std::cerr << "Warning: JxlDecoderGetICCProfileSize failed" << std::endl; + } + + if (icc_size > 0) { + icc_profile.resize(icc_size); + + if (JXL_DEC_SUCCESS != +#if JPEGXL_NUMERIC_VERSION < JPEGXL_COMPUTE_NUMERIC_VERSION(0, 9, 0) + JxlDecoderGetColorAsICCProfile( + dec.get(), &format, _PROFILE_, + icc_profile.data(), icc_profile.size()) +#else + JxlDecoderGetColorAsICCProfile( + dec.get(), _PROFILE_, + icc_profile.data(), icc_profile.size()) +#endif + ) { + std::cerr << "Warning: JxlDecoderGetColorAsICCProfile failed" << std::endl; + } else { + embProfile = cmsOpenProfileFromMem(icc_profile.data(), + icc_profile.size()); + } + } else { + std::cerr << "Warning: Empty ICC data." << std::endl; + } + } else if (status == JXL_DEC_NEED_IMAGE_OUT_BUFFER) { + // Note: If assert is triggered, change to assignment. + // We want maximum bit depth from the decoder, + // regardless of the original encoding intent. + assert(format.data_type == JXL_TYPE_FLOAT); + + if (JXL_DEC_SUCCESS != + JxlDecoderImageOutBufferSize(dec.get(), &format, &buffer_size)) { + std::cerr << "Error: JxlDecoderImageOutBufferSize failed" << std::endl; + return IMIO_READERROR; + } + + buffer.resize(buffer_size); + + if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer(dec.get(), &format, buffer.data(), buffer.size())) { + std::cerr << "Error: JxlDecoderSetImageOutBuffer failed" << std::endl; + return IMIO_READERROR; + } + } else if (status == JXL_DEC_FULL_IMAGE || + status == JXL_DEC_FRAME) { + // Nothing to do. If the image is an animation, more full frames + // may be decoded. This example only keeps the first one. + break; + } else if (status == JXL_DEC_SUCCESS) { + // Decoding complete. Decoder will be released automatically. + break; + } else if (status == JXL_DEC_NEED_MORE_INPUT) { + std::cerr << "Error: Decoder needs more input data" << std::endl; + return IMIO_READERROR; + } else if (status == JXL_DEC_ERROR) { + std::cerr << "Error: Decoder error" << std::endl; + return IMIO_READERROR; + } else { + std::cerr << "Error: Unknown decoder status" << std::endl; + return IMIO_READERROR; + } + } // end grand decode loop + + std::size_t width = info.xsize; + std::size_t height = info.ysize; + + allocate(width, height); + + std::size_t line_length = width * 3 * 4; + + for (std::size_t row = 0; row < height; ++row) { + setScanline(row, buffer.data() + (row * line_length), 32); + + if (pl && !(row % 100)) { + pl->setProgress((double)(row + 1) / height); + } + } + + if (pl) { + pl->setProgressStr("PROGRESSBAR_READY"); + pl->setProgress(1.0); + } + + return IMIO_SUCCESS; +} +#undef _PROFILE_ +#endif // LIBJXL + int ImageIO::loadPPMFromMemory(const char* buffer, int width, int height, bool swap, int bps) { allocate (width, height); @@ -1311,6 +1481,10 @@ int ImageIO::load (const Glib::ustring &fname) return loadPNG (fname); } else if (hasJpegExtension(fname)) { return loadJPEG (fname); +#ifdef LIBJXL + } else if (hasJxlExtension(fname)) { + return loadJXL(fname); +#endif } else if (hasTiffExtension(fname)) { return loadTIFF (fname); } else { diff --git a/rtengine/imageio.h b/rtengine/imageio.h index 813bfcc61..3703839b2 100644 --- a/rtengine/imageio.h +++ b/rtengine/imageio.h @@ -90,6 +90,10 @@ public: int load (const Glib::ustring &fname); int save (const Glib::ustring &fname) const; +#ifdef LIBJXL + int loadJXL (const Glib::ustring &fname); +#endif + int loadPNG (const Glib::ustring &fname); int loadJPEG (const Glib::ustring &fname); int loadTIFF (const Glib::ustring &fname); diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc index 435f2f9a0..32961f975 100644 --- a/rtengine/stdimagesource.cc +++ b/rtengine/stdimagesource.cc @@ -90,6 +90,12 @@ void StdImageSource::getSampleFormat (const Glib::ustring &fname, IIOSampleForma if (result == IMIO_SUCCESS) { return; } +#ifdef LIBJXL + } else if (hasJxlExtension(fname)) { + sFormat = IIOSF_FLOAT32; + sArrangement = IIOSA_CHUNKY; + return; +#endif } else if (hasTiffExtension(fname)) { int result = ImageIO::getTIFFSampleFormat (fname, sFormat, sArrangement); diff --git a/rtengine/utils.cc b/rtengine/utils.cc index 0674c9806..6a8321d1c 100644 --- a/rtengine/utils.cc +++ b/rtengine/utils.cc @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include "rt_math.h" #include "utils.h" @@ -222,6 +224,23 @@ void vflip(unsigned char* img, int w, int h) } } +std::vector getFileData(const Glib::ustring &filename) +{ + try { + const std::string fn = Glib::filename_from_utf8(filename); + std::ifstream instream(fn, std::ios::in | std::ios::binary); + + std::vector contents( + (std::istreambuf_iterator(instream)), + std::istreambuf_iterator()); + + instream.close(); + return contents; + } catch (...) { + return {}; + } +} + Glib::ustring getFileExtension(const Glib::ustring& filename) { const Glib::ustring::size_type lastdot_pos = filename.find_last_of('.'); @@ -237,6 +256,13 @@ bool hasJpegExtension(const Glib::ustring& filename) return extension == "jpg" || extension == "jpeg"; } +#ifdef LIBJXL +bool hasJxlExtension(const Glib::ustring& filename) +{ + return getFileExtension(filename) == "jxl"; +} +#endif + bool hasTiffExtension(const Glib::ustring& filename) { const Glib::ustring extension = getFileExtension(filename); diff --git a/rtengine/utils.h b/rtengine/utils.h index e0097d76e..5dec93f51 100644 --- a/rtengine/utils.h +++ b/rtengine/utils.h @@ -18,6 +18,8 @@ */ #pragma once +#include + #include #include @@ -43,6 +45,8 @@ constexpr typename std::underlying_type::type toUnderlying(ENUM value) return static_cast::type>(value); } +std::vector getFileData(const Glib::ustring &filename); + // Return lower case extension without the "." or "" if the given name contains no "." Glib::ustring getFileExtension(const Glib::ustring& filename); // Return true if file has .jpeg or .jpg extension (ignoring case) @@ -52,6 +56,11 @@ bool hasTiffExtension(const Glib::ustring& filename); // Return true if file has .png extension (ignoring case) bool hasPngExtension(const Glib::ustring& filename); +#ifdef LIBJXL +// Return true if file has .jxl extension (ignoring case) +bool hasJxlExtension(const Glib::ustring& filename); +#endif + void swab(const void* from, void* to, ssize_t n); } diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 7ee4d3da1..228592a70 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -226,13 +226,12 @@ Glib::ustring Thumbnail::xmpSidecarPath(const Glib::ustring &imagePath) return rtengine::Exiv2Metadata::xmpSidecarPath(imagePath); } -void Thumbnail::_generateThumbnailImage () +void Thumbnail::_generateThumbnailImage() { - // delete everything loaded into memory delete tpp; tpp = nullptr; - delete [] lastImg; + delete[] lastImg; lastImg = nullptr; tw = options.maxThumbnailWidth; th = options.maxThumbnailHeight; @@ -249,64 +248,55 @@ void Thumbnail::_generateThumbnailImage () cfs.exifValid = false; cfs.timeValid = false; - if (ext == "jpg" || ext == "jpeg") { - infoFromImage (fname); - tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal, pparams->wb.observer); + // RAW works like this: + // 1. if we are here it's because we aren't in the cache so load the JPG + // image out of the RAW. Mark as "quick". + // 2. if we don't find that then just grab the real image. + bool quick = false; + + rtengine::eSensorType sensorType = rtengine::ST_NONE; + + if (initial_ && options.internalThumbIfUntouched) { + quick = true; + tpp = rtengine::Thumbnail::loadQuickFromRaw(fname, sensorType, tw, th, 1, TRUE); + } + + if (!tpp) { + quick = false; + tpp = rtengine::Thumbnail::loadFromRaw(fname, sensorType, tw, th, 1, pparams->wb.equal, pparams->wb.observer, TRUE, &(pparams->raw)); + } + + cfs.sensortype = sensorType; + + if (tpp) { + cfs.format = FT_Raw; + cfs.thumbImgType = quick ? CacheImageData::QUICK_THUMBNAIL : CacheImageData::FULL_THUMBNAIL; + infoFromImage(fname); + + if (!quick) { + cfs.width = tpp->full_width; + cfs.height = tpp->full_height; + } + } + + if (!tpp) { + // this will load formats supported by imagio (jpg, png, jxl, and tiff) + tpp = rtengine::Thumbnail::loadFromImage(fname, tw, th, -1, pparams->wb.equal, pparams->wb.observer); if (tpp) { - cfs.format = FT_Jpeg; - } - } else if (ext == "png") { - tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal, pparams->wb.observer); - - if (tpp) { - cfs.format = FT_Png; - } - } else if (ext == "tif" || ext == "tiff") { - infoFromImage (fname); - tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal, pparams->wb.observer); - - if (tpp) { - cfs.format = FT_Tiff; - } - } else { - // RAW works like this: - // 1. if we are here it's because we aren't in the cache so load the JPG - // image out of the RAW. Mark as "quick". - // 2. if we don't find that then just grab the real image. - bool quick = false; - - rtengine::eSensorType sensorType = rtengine::ST_NONE; - if ( initial_ && options.internalThumbIfUntouched) { - quick = true; - tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, sensorType, tw, th, 1, TRUE); - } - - if ( tpp == nullptr ) { - quick = false; - tpp = rtengine::Thumbnail::loadFromRaw (fname, sensorType, tw, th, 1, pparams->wb.equal, pparams->wb.observer, TRUE, &(pparams->raw)); - } - - cfs.sensortype = sensorType; - if (tpp) { - cfs.format = FT_Raw; - cfs.thumbImgType = quick ? CacheImageData::QUICK_THUMBNAIL : CacheImageData::FULL_THUMBNAIL; - infoFromImage (fname); - if (!quick) { - cfs.width = tpp->full_width; - cfs.height = tpp->full_height; - } + cfs.format = FT_Custom; + infoFromImage(fname); } } if (tpp) { tpp->getAutoWBMultipliers(cfs.redAWBMul, cfs.greenAWBMul, cfs.blueAWBMul); - _saveThumbnail (); + _saveThumbnail(); cfs.supported = true; - cfs.save (getCacheFileName ("data", ".txt")); + cfs.save(getCacheFileName("data", ".txt")); - generateExifDateTimeStrings (); + generateExifDateTimeStrings(); } } @@ -761,10 +751,10 @@ rtengine::IImage8* Thumbnail::processThumbImage (const rtengine::procparams::Pro MyMutex::MyLock lock(mutex); - if ( tpp == nullptr ) { + if (!tpp) { _loadThumbnail(); - if ( tpp == nullptr ) { + if (!tpp) { return nullptr; } } @@ -798,7 +788,7 @@ rtengine::IImage8* Thumbnail::upgradeThumbImage (const rtengine::procparams::Pro _generateThumbnailImage(); - if ( tpp == nullptr ) { + if (!tpp) { return nullptr; } @@ -1004,7 +994,7 @@ void Thumbnail::_loadThumbnail(bool firstTrial) _loadThumbnail (false); } - if (tpp == nullptr) { + if (!tpp) { return; } } else if (!succ) { diff --git a/tools/makedeb/PKGBUILD.libjxl b/tools/makedeb/PKGBUILD.libjxl new file mode 100644 index 000000000..b63801812 --- /dev/null +++ b/tools/makedeb/PKGBUILD.libjxl @@ -0,0 +1,41 @@ +# Maintainer: RawTherapee Developers + +_pkgname="libjxl" +pkgname="$_pkgname" +pkgver='0.10.2' +pkgrel='1' +pkgdesc='JPEG XL image format reference implementation' +url='https://github.com/libjxl/libjxl' +license=('BSD') +arch=('amd64') + +depends=('libgif-dev' 'libjpeg-dev' 'libopenexr-dev' 'libpng-dev' 'libwebp-dev') +makedepends=('cmake' 'pkg-config' 'libbrotli-dev' 'libgflags-dev') + +_pkgsrc="$_pkgname" +source=("git+$url.git#tag=v$pkgver") +sha256sums=('SKIP') + +prepare() { + cd "$_pkgsrc" + git submodule update --init --recursive --depth 1 --recommend-shallow +} + +build() { + local _cmake_options=( + -B build + -S "$_pkgsrc" + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_INSTALL_PREFIX='/usr' + -DJPEGXL_FORCE_SYSTEM_BROTLI=ON + -DBUILD_TESTING=OFF + -Wno-dev + ) + + cmake "${_cmake_options[@]}" + cmake --build build --parallel +} + +package() { + DESTDIR="$pkgdir" cmake --install build +}