WIP: α channel #119257

Draft
Peter Kovář wants to merge 2 commits from PEAK/blender:main into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
9 changed files with 108 additions and 2 deletions

View File

@ -120,6 +120,9 @@ int BKE_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options)
return IMB_FTYPE_WEBP;
}
#endif
if (imtype == R_IMF_IMTYPE_JXL) {
return IMB_FTYPE_JXL;
}
r_options->quality = 90;
return IMB_FTYPE_JPG;
@ -176,6 +179,9 @@ char BKE_ftype_to_imtype(const int ftype, const ImbFormatOptions *options)
return R_IMF_IMTYPE_WEBP;
}
#endif
if (ftype == IMB_FTYPE_JXL) {
return R_IMF_IMTYPE_JXL;
}
return R_IMF_IMTYPE_JPEG90;
}
@ -211,6 +217,7 @@ bool BKE_imtype_supports_quality(const char imtype)
case R_IMF_IMTYPE_JP2:
case R_IMF_IMTYPE_AVIJPEG:
case R_IMF_IMTYPE_WEBP:
case R_IMF_IMTYPE_JXL:
return true;
}
return false;
@ -224,6 +231,7 @@ bool BKE_imtype_requires_linear_float(const char imtype)
case R_IMF_IMTYPE_RADHDR:
case R_IMF_IMTYPE_OPENEXR:
case R_IMF_IMTYPE_MULTILAYER:
case R_IMF_IMTYPE_JXL:
return true;
}
return false;
@ -251,6 +259,7 @@ char BKE_imtype_valid_channels(const char imtype, bool write_file)
case R_IMF_IMTYPE_JP2:
case R_IMF_IMTYPE_DPX:
case R_IMF_IMTYPE_WEBP:
case R_IMF_IMTYPE_JXL:
chan_flag |= IMA_CHAN_FLAG_RGBA;
break;
}
@ -264,6 +273,7 @@ char BKE_imtype_valid_channels(const char imtype, bool write_file)
case R_IMF_IMTYPE_RAWTGA:
case R_IMF_IMTYPE_TIFF:
case R_IMF_IMTYPE_IRIS:
case R_IMF_IMTYPE_JXL:
chan_flag |= IMA_CHAN_FLAG_BW;
break;
}
@ -291,6 +301,8 @@ char BKE_imtype_valid_depths(const char imtype)
return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16;
case R_IMF_IMTYPE_PNG:
return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_16;
case R_IMF_IMTYPE_JXL:
return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_10 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_32;
/* Most formats are 8bit only. */
default:
return R_IMF_CHAN_DEPTH_8;
@ -308,6 +320,9 @@ char BKE_imtype_from_arg(const char *imtype_arg)
if (STREQ(imtype_arg, "JPEG")) {
return R_IMF_IMTYPE_JPEG90;
}
if (STREQ(imtype_arg, "JXL")) {
return R_IMF_IMTYPE_JXL;
}
if (STREQ(imtype_arg, "RAWTGA")) {
return R_IMF_IMTYPE_RAWTGA;
}
@ -450,6 +465,9 @@ static int image_path_ext_from_imformat_impl(const char imtype,
r_ext[ext_num++] = ".webp";
}
#endif
else if (imtype == R_IMF_IMTYPE_JXL) {
r_ext[ext_num++] = ".jxl";
}
else {
/* Handles: #R_IMF_IMTYPE_AVIRAW, #R_IMF_IMTYPE_AVIJPEG, #R_IMF_IMTYPE_JPEG90 etc. */
r_ext[ext_num++] = ".jpg";
@ -711,6 +729,10 @@ void BKE_image_format_to_imbuf(ImBuf *ibuf, const ImageFormatData *imf)
ibuf->foptions.quality = quality;
}
#endif
else if (imtype == R_IMF_IMTYPE_JXL) {
ibuf->ftype = IMB_FTYPE_JXL;
ibuf->foptions.quality = quality;
}
else {
/* #R_IMF_IMTYPE_JPEG90, etc. default to JPEG. */
if (quality < 10) {
@ -839,6 +861,10 @@ void BKE_image_format_from_imbuf(ImageFormatData *im_format, const ImBuf *imbuf)
im_format->quality = quality;
}
#endif
else if (ftype == IMB_FTYPE_JXL) {
im_format->imtype = R_IMF_IMTYPE_JXL;
im_format->quality = quality;
}
else {
im_format->imtype = R_IMF_IMTYPE_JPEG90;

View File

@ -29,6 +29,7 @@ set(SRC
intern/format_bmp.cc
intern/format_dds.cc
intern/format_hdr.cc
intern/format_jxl.cc
intern/format_png.cc
intern/format_psd.cc
intern/format_svg.cc

View File

@ -43,6 +43,7 @@ enum eImbFileType {
#ifdef WITH_WEBP
IMB_FTYPE_WEBP = 14,
#endif
IMB_FTYPE_JXL = 15,
};
typedef enum IMB_Timecode_Type {

View File

@ -149,6 +149,19 @@ ImBuf *imb_thumbnail_jpeg(const char *filepath,
/** \} */
/* -------------------------------------------------------------------- */
/** \name Format: JPEG XL (#IMB_FTYPE_JXL)
* \{ */
bool imb_is_a_jxl(const unsigned char *buf, size_t size);
ImBuf *imb_load_jxl(const unsigned char *mem,
size_t size,
int flags,
char colorspace[IM_MAX_SPACE]);
bool imb_save_jxl(ImBuf *ibuf, const char *filepath, int flags);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Format: BMP (#IMB_FTYPE_BMP)
* \{ */

View File

@ -34,6 +34,18 @@ const ImFileType IMB_FILE_TYPES[] = {
/*filetype*/ IMB_FTYPE_JPG,
/*default_save_role*/ COLOR_ROLE_DEFAULT_BYTE,
},
{
/*init*/ nullptr,
/*exit*/ nullptr,
/*is_a*/ imb_is_a_jxl,
/*load*/ imb_load_jxl,
/*load_filepath*/ nullptr,
/*load_filepath_thumbnail*/ nullptr,
/*save*/ imb_save_jxl,
/*flag*/ IM_FTYPE_FLOAT,
/*filetype*/ IMB_FTYPE_JXL,
/*default_save_role*/ COLOR_ROLE_DEFAULT_FLOAT,
},
{
/*init*/ nullptr,
/*exit*/ nullptr,

View File

@ -0,0 +1,50 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup imbuf
*/
#include "oiio/openimageio_support.hh"
#include "IMB_filetype.hh"
#include "IMB_imbuf_types.hh"
OIIO_NAMESPACE_USING
using namespace blender::imbuf;
extern "C" {
bool imb_is_a_jxl(const uchar *mem, size_t size)
{
return imb_oiio_check(mem, size, "jxl");
}
ImBuf *imb_load_jxl(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
ImageSpec config, spec;
ReadContext ctx{mem, size, "jxl", IMB_FTYPE_JXL, flags};
ImBuf *ibuf = imb_oiio_read(ctx, config, colorspace, spec);
if (ibuf) {
if (flags & IB_rect) {
IMB_rect_from_float(ibuf);
}
}
return ibuf;
}
bool imb_save_jxl(ImBuf *ibuf, const char *filepath, int flags)
{
const int file_channels = ibuf->planes >> 3;
const TypeDesc data_format = TypeDesc::FLOAT;
WriteContext ctx = imb_create_write_context("jxl", ibuf, flags);
ImageSpec file_spec = imb_create_write_spec(ctx, file_channels, data_format);
return imb_oiio_write(ctx, filepath, file_spec);
}
}

View File

@ -45,7 +45,7 @@ extern "C" {
#define UTIL_DEBUG 0
const char *imb_ext_image[] = {
".png", ".tga", ".bmp", ".jpg", ".jpeg", ".sgi", ".rgb", ".rgba", ".tif", ".tiff", ".tx",
".png", ".tga", ".bmp", ".jpg", ".jpeg", ".jxl", ".sgi", ".rgb", ".rgba", ".tif", ".tiff", ".tx",
#ifdef WITH_OPENJPEG
".jp2", ".j2c",
#endif

View File

@ -505,7 +505,7 @@ enum {
R_IMF_IMTYPE_PSD = 34,
R_IMF_IMTYPE_WEBP = 35,
R_IMF_IMTYPE_AV1 = 36,
R_IMF_IMTYPE_JXL = 37,
R_IMF_IMTYPE_INVALID = 255,
};

View File

@ -287,6 +287,8 @@ const EnumPropertyItem rna_enum_curve_fit_method_items[] = {
{R_IMF_IMTYPE_PNG, "PNG", ICON_FILE_IMAGE, "PNG", "Output image in PNG format"},
#define R_IMF_ENUM_JPEG \
{R_IMF_IMTYPE_JPEG90, "JPEG", ICON_FILE_IMAGE, "JPEG", "Output image in JPEG format"},
#define R_IMF_ENUM_JXL \
{R_IMF_IMTYPE_JXL, "JXL", ICON_FILE_IMAGE, "JPEG XL", "Output image in JPEG XL format"},
#define R_IMF_ENUM_TAGA \
{R_IMF_IMTYPE_TARGA, "TARGA", ICON_FILE_IMAGE, "Targa", "Output image in Targa format"},
#define R_IMF_ENUM_TAGA_RAW \
@ -364,6 +366,7 @@ const EnumPropertyItem rna_enum_curve_fit_method_items[] = {
R_IMF_ENUM_PNG \
R_IMF_ENUM_JPEG \
R_IMF_ENUM_JPEG2K \
R_IMF_ENUM_JXL \
R_IMF_ENUM_TAGA \
R_IMF_ENUM_TAGA_RAW \
RNA_ENUM_ITEM_SEPR_COLUMN, R_IMF_ENUM_CINEON R_IMF_ENUM_DPX R_IMF_ENUM_EXR_MULTILAYER \