Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/cycles/blender/blender_mesh.cpp3
-rw-r--r--intern/cycles/blender/blender_shader.cpp12
-rw-r--r--intern/cycles/render/image.cpp30
-rw-r--r--intern/cycles/render/image.h8
-rw-r--r--intern/cycles/render/nodes.cpp64
-rw-r--r--intern/cycles/render/nodes.h4
-rw-r--r--intern/cycles/util/util_texture.h12
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/intern/image.c24
-rw-r--r--source/blender/blenloader/intern/versioning_260.c1
-rw-r--r--source/blender/blenloader/intern/versioning_280.c11
-rw-r--r--source/blender/editors/space_image/image_buttons.c10
-rw-r--r--source/blender/imbuf/IMB_imbuf.h3
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h8
-rw-r--r--source/blender/imbuf/intern/colormanagement.c35
-rw-r--r--source/blender/imbuf/intern/divers.c17
-rw-r--r--source/blender/imbuf/intern/readimage.c16
-rw-r--r--source/blender/makesdna/DNA_image_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_image.c27
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c3
-rw-r--r--source/blender/render/intern/source/imagetexture.c6
21 files changed, 200 insertions, 100 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 1b47c4123e3..2a5c163aaeb 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -292,7 +292,6 @@ static void create_mesh_volume_attribute(
VoxelAttribute *volume_data = attr->data_voxel();
ImageMetaData metadata;
bool animated = false;
- bool use_alpha = true;
volume_data->manager = image_manager;
volume_data->slot = image_manager->add_image(Attribute::standard_name(std),
@@ -301,7 +300,7 @@ static void create_mesh_volume_attribute(
frame,
INTERPOLATION_LINEAR,
EXTENSION_CLIP,
- use_alpha,
+ IMAGE_ALPHA_AUTO,
u_colorspace_raw,
metadata);
}
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index f42a15706e7..13097f6bf8e 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -90,6 +90,12 @@ template<typename NodeType> static ExtensionType get_image_extension(NodeType &b
return (ExtensionType)validate_enum_value(value, EXTENSION_NUM_TYPES, EXTENSION_REPEAT);
}
+static ImageAlphaType get_image_alpha_type(BL::Image &b_image)
+{
+ int value = b_image.alpha_mode();
+ return (ImageAlphaType)validate_enum_value(value, IMAGE_ALPHA_NUM_TYPES, IMAGE_ALPHA_AUTO);
+}
+
/* Graph */
static BL::NodeSocket get_node_output(BL::Node &b_node, const string &name)
@@ -655,7 +661,7 @@ static ShaderNode *add_node(Scene *scene,
image->colorspace = get_enum_identifier(colorspace_ptr, "name");
image->animated = b_image_node.image_user().use_auto_refresh();
- image->use_alpha = b_image.use_alpha();
+ image->alpha_type = get_image_alpha_type(b_image);
/* TODO: restore */
/* TODO(sergey): Does not work properly when we change builtin type. */
@@ -703,7 +709,7 @@ static ShaderNode *add_node(Scene *scene,
env->colorspace = get_enum_identifier(colorspace_ptr, "name");
env->animated = b_env_node.image_user().use_auto_refresh();
- env->use_alpha = b_image.use_alpha();
+ env->alpha_type = get_image_alpha_type(b_image);
/* TODO: restore */
/* TODO(sergey): Does not work properly when we change builtin type. */
@@ -868,7 +874,7 @@ static ShaderNode *add_node(Scene *scene,
point_density->builtin_data,
point_density->interpolation,
EXTENSION_CLIP,
- true,
+ IMAGE_ALPHA_AUTO,
u_colorspace_raw);
}
node = point_density;
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 6301b416724..160e7d9ff1e 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -299,12 +299,12 @@ static bool image_equals(ImageManager::Image *image,
void *builtin_data,
InterpolationType interpolation,
ExtensionType extension,
- bool use_alpha,
+ ImageAlphaType alpha_type,
ustring colorspace)
{
return image->filename == filename && image->builtin_data == builtin_data &&
image->interpolation == interpolation && image->extension == extension &&
- image->use_alpha == use_alpha && image->colorspace == colorspace;
+ image->alpha_type == alpha_type && image->colorspace == colorspace;
}
int ImageManager::add_image(const string &filename,
@@ -313,7 +313,7 @@ int ImageManager::add_image(const string &filename,
float frame,
InterpolationType interpolation,
ExtensionType extension,
- bool use_alpha,
+ ImageAlphaType alpha_type,
ustring colorspace,
ImageMetaData &metadata)
{
@@ -338,14 +338,15 @@ int ImageManager::add_image(const string &filename,
/* Fnd existing image. */
for (slot = 0; slot < images[type].size(); slot++) {
img = images[type][slot];
- if (img && image_equals(
- img, filename, builtin_data, interpolation, extension, use_alpha, colorspace)) {
+ if (img &&
+ image_equals(
+ img, filename, builtin_data, interpolation, extension, alpha_type, colorspace)) {
if (img->frame != frame) {
img->frame = frame;
img->need_load = true;
}
- if (img->use_alpha != use_alpha) {
- img->use_alpha = use_alpha;
+ if (img->alpha_type != alpha_type) {
+ img->alpha_type = alpha_type;
img->need_load = true;
}
if (img->colorspace != colorspace) {
@@ -399,7 +400,7 @@ int ImageManager::add_image(const string &filename,
img->interpolation = interpolation;
img->extension = extension;
img->users = 1;
- img->use_alpha = use_alpha;
+ img->alpha_type = alpha_type;
img->colorspace = colorspace;
img->mem = NULL;
@@ -445,7 +446,7 @@ void ImageManager::remove_image(const string &filename,
void *builtin_data,
InterpolationType interpolation,
ExtensionType extension,
- bool use_alpha,
+ ImageAlphaType alpha_type,
ustring colorspace)
{
size_t slot;
@@ -457,7 +458,7 @@ void ImageManager::remove_image(const string &filename,
builtin_data,
interpolation,
extension,
- use_alpha,
+ alpha_type,
colorspace)) {
remove_image(type_index_to_flattened_slot(slot, (ImageDataType)type));
return;
@@ -474,7 +475,7 @@ void ImageManager::tag_reload_image(const string &filename,
void *builtin_data,
InterpolationType interpolation,
ExtensionType extension,
- bool use_alpha,
+ ImageAlphaType alpha_type,
ustring colorspace)
{
for (size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
@@ -484,7 +485,7 @@ void ImageManager::tag_reload_image(const string &filename,
builtin_data,
interpolation,
extension,
- use_alpha,
+ alpha_type,
colorspace)) {
images[type][slot]->need_load = true;
break;
@@ -516,7 +517,8 @@ bool ImageManager::file_load_image_generic(Image *img, unique_ptr<ImageInput> *i
/* For typical RGBA images we let OIIO convert to associated alpha,
* but some types we want to leave the RGB channels untouched. */
const bool associate_alpha = !(ColorSpaceManager::colorspace_is_data(img->colorspace) ||
- img->use_alpha == false);
+ img->alpha_type == IMAGE_ALPHA_IGNORE ||
+ img->alpha_type == IMAGE_ALPHA_CHANNEL_PACKED);
if (!associate_alpha) {
config.attribute("oiio:UnassociatedAlpha", 1);
@@ -692,7 +694,7 @@ bool ImageManager::file_load_image(Image *img,
}
/* Disable alpha if requested by the user. */
- if (img->use_alpha == false) {
+ if (img->alpha_type == IMAGE_ALPHA_IGNORE) {
for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
pixels[i * 4 + 3] = one;
}
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 70d7fd3632d..ed2780f8471 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -83,7 +83,7 @@ class ImageManager {
float frame,
InterpolationType interpolation,
ExtensionType extension,
- bool use_alpha,
+ ImageAlphaType alpha_type,
ustring colorspace,
ImageMetaData &metadata);
void add_image_user(int flat_slot);
@@ -92,13 +92,13 @@ class ImageManager {
void *builtin_data,
InterpolationType interpolation,
ExtensionType extension,
- bool use_alpha,
+ ImageAlphaType alpha_type,
ustring colorspace);
void tag_reload_image(const string &filename,
void *builtin_data,
InterpolationType interpolation,
ExtensionType extension,
- bool use_alpha,
+ ImageAlphaType alpha_type,
ustring colorspace);
bool get_image_metadata(const string &filename,
void *builtin_data,
@@ -147,7 +147,7 @@ class ImageManager {
ImageMetaData metadata;
ustring colorspace;
- bool use_alpha;
+ ImageAlphaType alpha_type;
bool need_load;
bool animated;
float frame;
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 3905189c8b0..c5b0f6a1e79 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -210,7 +210,13 @@ NODE_DEFINE(ImageTextureNode)
SOCKET_STRING(filename, "Filename", ustring());
SOCKET_STRING(colorspace, "Colorspace", u_colorspace_auto);
- SOCKET_BOOLEAN(use_alpha, "Use Alpha", true);
+ static NodeEnum alpha_type_enum;
+ alpha_type_enum.insert("auto", IMAGE_ALPHA_AUTO);
+ alpha_type_enum.insert("unassociated", IMAGE_ALPHA_UNASSOCIATED);
+ alpha_type_enum.insert("associated", IMAGE_ALPHA_ASSOCIATED);
+ alpha_type_enum.insert("channel_packed", IMAGE_ALPHA_CHANNEL_PACKED);
+ alpha_type_enum.insert("ignore", IMAGE_ALPHA_IGNORE);
+ SOCKET_ENUM(alpha_type, "Alpha Type", alpha_type_enum, IMAGE_ALPHA_AUTO);
static NodeEnum interpolation_enum;
interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
@@ -257,7 +263,7 @@ ImageTextureNode::~ImageTextureNode()
{
if (image_manager) {
image_manager->remove_image(
- filename.string(), builtin_data, interpolation, extension, use_alpha, colorspace);
+ filename.string(), builtin_data, interpolation, extension, alpha_type, colorspace);
}
}
@@ -300,12 +306,12 @@ void ImageTextureNode::compile(SVMCompiler &compiler)
0,
interpolation,
extension,
- use_alpha,
+ alpha_type,
colorspace,
metadata);
is_float = metadata.is_float;
compress_as_srgb = metadata.compress_as_srgb;
- colorspace = metadata.colorspace;
+ known_colorspace = metadata.colorspace;
}
if (slot != -1) {
@@ -317,7 +323,8 @@ void ImageTextureNode::compile(SVMCompiler &compiler)
}
if (!alpha_out->links.empty()) {
const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) ||
- use_alpha == false);
+ alpha_type == IMAGE_ALPHA_CHANNEL_PACKED ||
+ alpha_type == IMAGE_ALPHA_IGNORE);
if (unassociate_alpha) {
flags |= NODE_IMAGE_ALPHA_UNASSOCIATE;
@@ -378,29 +385,30 @@ void ImageTextureNode::compile(OSLCompiler &compiler)
0,
interpolation,
extension,
- use_alpha,
+ alpha_type,
colorspace,
metadata);
}
is_float = metadata.is_float;
compress_as_srgb = metadata.compress_as_srgb;
- colorspace = metadata.colorspace;
+ known_colorspace = metadata.colorspace;
}
if (slot == -1) {
- compiler.parameter_texture("filename", filename, colorspace);
+ compiler.parameter_texture("filename", filename, known_colorspace);
}
else {
compiler.parameter_texture("filename", slot);
}
const bool unassociate_alpha = !(ColorSpaceManager::colorspace_is_data(colorspace) ||
- use_alpha == false);
+ alpha_type == IMAGE_ALPHA_CHANNEL_PACKED ||
+ alpha_type == IMAGE_ALPHA_IGNORE);
compiler.parameter(this, "projection");
compiler.parameter(this, "projection_blend");
- compiler.parameter("convert_from_srgb", compress_as_srgb);
- compiler.parameter("ignore_alpha", !use_alpha);
+ compiler.parameter("compress_as_srgb", compress_as_srgb);
+ compiler.parameter("ignore_alpha", alpha_type == IMAGE_ALPHA_IGNORE);
compiler.parameter("unassociate_alpha", !alpha_out->links.empty() && unassociate_alpha);
compiler.parameter("is_float", is_float);
compiler.parameter(this, "interpolation");
@@ -420,7 +428,13 @@ NODE_DEFINE(EnvironmentTextureNode)
SOCKET_STRING(filename, "Filename", ustring());
SOCKET_STRING(colorspace, "Colorspace", u_colorspace_auto);
- SOCKET_BOOLEAN(use_alpha, "Use Alpha", true);
+ static NodeEnum alpha_type_enum;
+ alpha_type_enum.insert("auto", IMAGE_ALPHA_AUTO);
+ alpha_type_enum.insert("unassociated", IMAGE_ALPHA_UNASSOCIATED);
+ alpha_type_enum.insert("associated", IMAGE_ALPHA_ASSOCIATED);
+ alpha_type_enum.insert("channel_packed", IMAGE_ALPHA_CHANNEL_PACKED);
+ alpha_type_enum.insert("ignore", IMAGE_ALPHA_IGNORE);
+ SOCKET_ENUM(alpha_type, "Alpha Type", alpha_type_enum, IMAGE_ALPHA_AUTO);
static NodeEnum interpolation_enum;
interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
@@ -457,7 +471,7 @@ EnvironmentTextureNode::~EnvironmentTextureNode()
{
if (image_manager) {
image_manager->remove_image(
- filename.string(), builtin_data, interpolation, EXTENSION_REPEAT, use_alpha, colorspace);
+ filename.string(), builtin_data, interpolation, EXTENSION_REPEAT, alpha_type, colorspace);
}
}
@@ -498,12 +512,12 @@ void EnvironmentTextureNode::compile(SVMCompiler &compiler)
0,
interpolation,
EXTENSION_REPEAT,
- use_alpha,
+ alpha_type,
colorspace,
metadata);
is_float = metadata.is_float;
compress_as_srgb = metadata.compress_as_srgb;
- colorspace = metadata.colorspace;
+ known_colorspace = metadata.colorspace;
}
if (slot != -1) {
@@ -558,17 +572,17 @@ void EnvironmentTextureNode::compile(OSLCompiler &compiler)
0,
interpolation,
EXTENSION_REPEAT,
- use_alpha,
+ alpha_type,
colorspace,
metadata);
}
is_float = metadata.is_float;
compress_as_srgb = metadata.compress_as_srgb;
- colorspace = metadata.colorspace;
+ known_colorspace = metadata.colorspace;
}
if (slot == -1) {
- compiler.parameter_texture("filename", filename, colorspace);
+ compiler.parameter_texture("filename", filename, known_colorspace);
}
else {
compiler.parameter_texture("filename", slot);
@@ -576,8 +590,8 @@ void EnvironmentTextureNode::compile(OSLCompiler &compiler)
compiler.parameter(this, "projection");
compiler.parameter(this, "interpolation");
- compiler.parameter("convert_from_srgb", compress_as_srgb);
- compiler.parameter("ignore_alpha", !use_alpha);
+ compiler.parameter("compress_as_srgb", compress_as_srgb);
+ compiler.parameter("ignore_alpha", alpha_type == IMAGE_ALPHA_IGNORE);
compiler.parameter("is_float", is_float);
compiler.add(this, "node_environment_texture");
}
@@ -1490,8 +1504,12 @@ PointDensityTextureNode::PointDensityTextureNode() : ShaderNode(node_type)
PointDensityTextureNode::~PointDensityTextureNode()
{
if (image_manager) {
- image_manager->remove_image(
- filename.string(), builtin_data, interpolation, EXTENSION_CLIP, true, ustring());
+ image_manager->remove_image(filename.string(),
+ builtin_data,
+ interpolation,
+ EXTENSION_CLIP,
+ IMAGE_ALPHA_AUTO,
+ ustring());
}
}
@@ -1524,7 +1542,7 @@ void PointDensityTextureNode::add_image()
0,
interpolation,
EXTENSION_CLIP,
- true,
+ IMAGE_ALPHA_AUTO,
u_colorspace_raw,
metadata);
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 3dd84ad8dca..6b21be88663 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -100,10 +100,10 @@ class ImageTextureNode : public ImageSlotTextureNode {
}
/* Parameters. */
- bool use_alpha;
ustring filename;
void *builtin_data;
ustring colorspace;
+ ImageAlphaType alpha_type;
NodeImageProjection projection;
InterpolationType interpolation;
ExtensionType extension;
@@ -141,10 +141,10 @@ class EnvironmentTextureNode : public ImageSlotTextureNode {
}
/* Parameters. */
- bool use_alpha;
ustring filename;
void *builtin_data;
ustring colorspace;
+ ImageAlphaType alpha_type;
NodeEnvironmentProjection projection;
InterpolationType interpolation;
bool animated;
diff --git a/intern/cycles/util/util_texture.h b/intern/cycles/util/util_texture.h
index 5ce16e0095a..d43852480d1 100644
--- a/intern/cycles/util/util_texture.h
+++ b/intern/cycles/util/util_texture.h
@@ -59,6 +59,18 @@ typedef enum ImageDataType {
IMAGE_DATA_NUM_TYPES
} ImageDataType;
+/* Alpha types
+ * How to treat alpha in images. */
+typedef enum ImageAlphaType {
+ IMAGE_ALPHA_UNASSOCIATED = 0,
+ IMAGE_ALPHA_ASSOCIATED = 1,
+ IMAGE_ALPHA_CHANNEL_PACKED = 2,
+ IMAGE_ALPHA_IGNORE = 3,
+ IMAGE_ALPHA_AUTO = 4,
+
+ IMAGE_ALPHA_NUM_TYPES,
+} ImageAlphaType;
+
#define IMAGE_DATA_TYPE_SHIFT 3
#define IMAGE_DATA_TYPE_MASK 0x7
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 5d659d63e27..077bbce2264 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -27,7 +27,7 @@
* \note Use #STRINGIFY() rather than defining with quotes.
*/
#define BLENDER_VERSION 280
-#define BLENDER_SUBVERSION 69
+#define BLENDER_SUBVERSION 70
/** Several breakages with 280, e.g. collections vs layers. */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index d59ead25396..9960994400f 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -502,6 +502,12 @@ static void image_init_color_management(Image *ima)
if (ibuf->flags & IB_alphamode_premul) {
ima->alpha_mode = IMA_ALPHA_PREMUL;
}
+ else if (ibuf->flags & IB_alphamode_channel_packed) {
+ ima->alpha_mode = IMA_ALPHA_CHANNEL_PACKED;
+ }
+ else if (ibuf->flags & IB_alphamode_ignore) {
+ ima->alpha_mode = IMA_ALPHA_IGNORE;
+ }
else {
ima->alpha_mode = IMA_ALPHA_STRAIGHT;
}
@@ -3592,16 +3598,18 @@ static void image_initialize_after_load(Image *ima, ImBuf *UNUSED(ibuf))
static int imbuf_alpha_flags_for_image(Image *ima)
{
- int flag = 0;
-
- if (ima->flag & IMA_IGNORE_ALPHA) {
- flag |= IB_ignore_alpha;
- }
- else if (ima->alpha_mode == IMA_ALPHA_PREMUL) {
- flag |= IB_alphamode_premul;
+ switch (ima->alpha_mode) {
+ case IMA_ALPHA_STRAIGHT:
+ return 0;
+ case IMA_ALPHA_PREMUL:
+ return IB_alphamode_premul;
+ case IMA_ALPHA_CHANNEL_PACKED:
+ return IB_alphamode_channel_packed;
+ case IMA_ALPHA_IGNORE:
+ return IB_alphamode_ignore;
}
- return flag;
+ return 0;
}
/* the number of files will vary according to the stereo format */
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 77ef27182f2..7b0aab99aea 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -1808,6 +1808,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
Image *image = blo_do_versions_newlibadr(fd, tex->id.lib, tex->ima);
if (image && (image->flag & IMA_DO_PREMUL) == 0) {
+ const int IMA_IGNORE_ALPHA = (1 << 12);
image->flag |= IMA_IGNORE_ALPHA;
}
}
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 7ba0eb7b791..13ccc374073 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -3450,6 +3450,17 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 70)) {
+ /* New image alpha modes. */
+ LISTBASE_FOREACH (Image *, image, &bmain->images) {
+ const int IMA_IGNORE_ALPHA = (1 << 12);
+ if (image->flag & IMA_IGNORE_ALPHA) {
+ image->alpha_mode = IMA_ALPHA_IGNORE;
+ image->flag &= ~IMA_IGNORE_ALPHA;
+ }
+ }
+ }
+
{
/* Versioning code until next subversion bump goes here. */
}
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 68af854e367..9f429329597 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -42,6 +42,7 @@
#include "RE_pipeline.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -995,10 +996,11 @@ void uiTemplateImage(uiLayout *layout,
if (has_alpha) {
col = uiLayoutColumn(layout, false);
- uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
- row = uiLayoutRow(col, false);
- uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_alpha"));
- uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
+ uiItemR(col, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
+
+ /* Alpha mode has no effect for non-color data. */
+ bool is_data = IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name);
+ uiLayoutSetActive(col, !is_data);
}
if (ima->source == IMA_SRC_MOVIE) {
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 674dc61cd9e..8574f33bce6 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -476,6 +476,9 @@ int imb_get_anim_type(const char *name);
*/
bool IMB_isfloat(struct ImBuf *ibuf);
+/* Do byte/float and colorspace conversions need to take alpha into account? */
+bool IMB_alpha_affects_rgb(const struct ImBuf *ibuf);
+
/* create char buffer, color corrected if necessary, for ImBufs that lack one */
void IMB_rect_from_float(struct ImBuf *ibuf);
void IMB_float_from_rect(struct ImBuf *ibuf);
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 0f2529e261a..61aa1f401a0 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -285,10 +285,12 @@ enum {
IB_alphamode_premul = 1 << 12,
/** if this flag is set, alpha mode would be guessed from file */
IB_alphamode_detect = 1 << 13,
+ /* alpha channel is unrelated to RGB and should not affect it */
+ IB_alphamode_channel_packed = 1 << 14,
/** ignore alpha on load and substitute it with 1.0f */
- IB_ignore_alpha = 1 << 14,
- IB_thumbnail = 1 << 15,
- IB_multiview = 1 << 16,
+ IB_alphamode_ignore = 1 << 15,
+ IB_thumbnail = 1 << 16,
+ IB_multiview = 1 << 17,
};
/** \} */
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index ba0f10446a1..8a10af7e184 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -1057,13 +1057,19 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace)
if (ibuf->rect_float) {
const char *to_colorspace = global_role_scene_linear;
+ const bool predivide = IMB_alpha_affects_rgb(ibuf);
if (ibuf->rect) {
imb_freerectImBuf(ibuf);
}
- IMB_colormanagement_transform(
- ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, true);
+ IMB_colormanagement_transform(ibuf->rect_float,
+ ibuf->x,
+ ibuf->y,
+ ibuf->channels,
+ from_colorspace,
+ to_colorspace,
+ predivide);
}
}
@@ -1405,6 +1411,7 @@ typedef struct DisplayBufferThread {
int channels;
float dither;
bool is_data;
+ bool predivide;
const char *byte_colorspace;
const char *float_colorspace;
@@ -1469,6 +1476,7 @@ static void display_buffer_init_handle(void *handle_v,
handle->channels = channels;
handle->dither = dither;
handle->is_data = is_data;
+ handle->predivide = IMB_alpha_affects_rgb(ibuf);
handle->byte_colorspace = init_data->byte_colorspace;
handle->float_colorspace = init_data->float_colorspace;
@@ -1486,6 +1494,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle,
bool is_data = handle->is_data;
bool is_data_display = handle->cm_processor->is_data_result;
+ bool predivide = handle->predivide;
if (!handle->buffer) {
unsigned char *byte_buffer = handle->byte_buffer;
@@ -1534,7 +1543,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle,
if (!is_data && !is_data_display) {
IMB_colormanagement_transform(
- linear_buffer, width, height, channels, from_colorspace, to_colorspace, true);
+ linear_buffer, width, height, channels, from_colorspace, to_colorspace, predivide);
}
*is_straight_alpha = false;
@@ -1590,13 +1599,13 @@ static void *do_display_buffer_apply_thread(void *handle_v)
}
}
else {
- bool is_straight_alpha, predivide;
+ bool is_straight_alpha;
float *linear_buffer = MEM_mallocN(((size_t)channels) * width * height * sizeof(float),
"color conversion linear buffer");
display_buffer_apply_get_linear_buffer(handle, height, linear_buffer, &is_straight_alpha);
- predivide = is_straight_alpha == false;
+ bool predivide = handle->predivide && (is_straight_alpha == false);
if (is_data) {
/* special case for data buffers - no color space conversions,
@@ -2178,6 +2187,7 @@ void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer,
/* TODO(brecht): make this multithreaded, or at least process in batches. */
const unsigned char *in_buffer = (unsigned char *)ibuf->rect;
+ const bool use_premultiply = IMB_alpha_affects_rgb(ibuf);
for (int y = 0; y < height; y++) {
const size_t in_offset = (offset_y + y) * ibuf->x + offset_x;
@@ -2192,11 +2202,13 @@ void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer,
rgba_uchar_to_float(pixel, in);
OCIO_processorApplyRGB(processor, pixel);
linearrgb_to_srgb_v3_v3(pixel, pixel);
- mul_v3_fl(pixel, pixel[3]);
+ if (use_premultiply) {
+ mul_v3_fl(pixel, pixel[3]);
+ }
rgba_float_to_uchar(out, pixel);
}
}
- else {
+ else if (use_premultiply) {
/* Premultiply only. */
for (int x = 0; x < width; x++, in += 4, out += 4) {
out[0] = (in[0] * in[3]) >> 8;
@@ -2205,6 +2217,15 @@ void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer,
out[3] = in[3];
}
}
+ else {
+ /* Copy only. */
+ for (int x = 0; x < width; x++, in += 4, out += 4) {
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+ }
+ }
}
}
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 1e16f0975e2..aa49453d68c 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -96,6 +96,12 @@ MINLINE void float_to_byte_dither_v4(
b[3] = unit_float_to_uchar_clamp(f[3]);
}
+/* Test if colorspace conversions of pixels in buffer need to take into account alpha. */
+bool IMB_alpha_affects_rgb(const ImBuf *ibuf)
+{
+ return (ibuf->flags & IB_alphamode_channel_packed) == 0;
+}
+
/* float to byte pixels, output 4-channel RGBA */
void IMB_buffer_byte_from_float(uchar *rect_to,
const float *rect_from,
@@ -728,16 +734,19 @@ void IMB_rect_from_float(ImBuf *ibuf)
buffer = MEM_dupallocN(ibuf->rect_float);
/* first make float buffer in byte space */
+ const bool predivide = IMB_alpha_affects_rgb(ibuf);
IMB_colormanagement_transform(buffer,
ibuf->x,
ibuf->y,
ibuf->channels,
from_colorspace,
ibuf->rect_colorspace->name,
- true);
+ predivide);
/* convert from float's premul alpha to byte's straight alpha */
- IMB_unpremultiply_rect_float(buffer, ibuf->channels, ibuf->x, ibuf->y);
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ IMB_unpremultiply_rect_float(buffer, ibuf->channels, ibuf->x, ibuf->y);
+ }
/* convert float to byte */
IMB_buffer_byte_from_float((unsigned char *)ibuf->rect,
@@ -802,7 +811,9 @@ void IMB_float_from_rect(ImBuf *ibuf)
rect_float, ibuf->x, ibuf->y, ibuf->channels, ibuf->rect_colorspace, false);
/* byte buffer is straight alpha, float should always be premul */
- IMB_premultiply_rect_float(rect_float, ibuf->channels, ibuf->x, ibuf->y);
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ IMB_premultiply_rect_float(rect_float, ibuf->channels, ibuf->x, ibuf->y);
+ }
if (ibuf->rect_float == NULL) {
ibuf->rect_float = rect_float;
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index 9297227bc87..d9f3c7ec6bb 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -61,20 +61,16 @@ static void imb_handle_alpha(ImBuf *ibuf,
}
bool is_data = (colorspace && IMB_colormanagement_space_name_is_data(colorspace));
- int alpha_flags;
+ int alpha_flags = (flags & IB_alphamode_detect) ? ibuf->flags : flags;
- if (flags & IB_alphamode_detect) {
- alpha_flags = ibuf->flags & IB_alphamode_premul;
- }
- else {
- alpha_flags = flags & IB_alphamode_premul;
- }
-
- if (is_data) {
+ if (is_data || (flags & IB_alphamode_channel_packed)) {
/* Don't touch alpha. */
+ ibuf->flags |= IB_alphamode_channel_packed;
}
- else if (flags & IB_ignore_alpha) {
+ else if (flags & IB_alphamode_ignore) {
+ /* Make opaque. */
IMB_rectfill_alpha(ibuf, 1.0f);
+ ibuf->flags |= IB_alphamode_ignore;
}
else {
if (alpha_flags & IB_alphamode_premul) {
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index 3e42aa17492..6141472125f 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -178,7 +178,7 @@ enum {
/** For image user, but these flags are mixed. */
IMA_USER_FRAME_IN_RANGE = (1 << 10),
IMA_VIEW_AS_RENDER = (1 << 11),
- IMA_IGNORE_ALPHA = (1 << 12),
+ IMA_FLAG_UNUSED_12 = (1 << 12), /* cleared */
IMA_DEINTERLACE = (1 << 13),
IMA_USE_VIEWS = (1 << 14),
IMA_FLAG_UNUSED_15 = (1 << 15), /* cleared */
@@ -233,6 +233,8 @@ enum {
enum {
IMA_ALPHA_STRAIGHT = 0,
IMA_ALPHA_PREMUL = 1,
+ IMA_ALPHA_CHANNEL_PACKED = 2,
+ IMA_ALPHA_IGNORE = 3,
};
#endif
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 40c8c7e1582..c033e393625 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -680,12 +680,26 @@ static void rna_def_image(BlenderRNA *brna)
"STRAIGHT",
0,
"Straight",
- "Transparent RGB and alpha pixels are unmodified"},
+ "Store RGB and alpha channels separately with alpha acting as a mask, also known as "
+ "unassociated alpha. Commonly used by image editing applications and file formats like "
+ "PNG"},
{IMA_ALPHA_PREMUL,
"PREMUL",
0,
"Premultiplied",
- "Transparent RGB pixels are multiplied by the alpha channel"},
+ "Store RGB channels with alpha multipled in, also known as associated alpha. The natural "
+ "format for renders and used by file formats like OpenEXR"},
+ {IMA_ALPHA_CHANNEL_PACKED,
+ "CHANNEL_PACKED",
+ 0,
+ "Channel Packed",
+ "Different images are packed in the RGB and alpha channels, and they should not "
+ "affect each other. Channel packing is commonly used by game engines to save memory"},
+ {IMA_ALPHA_IGNORE,
+ "NONE",
+ 0,
+ "None",
+ "Ignore alpha channel from the file and make image fully opaque"},
{0, NULL, 0, NULL, NULL},
};
@@ -744,15 +758,6 @@ static void rna_def_image(BlenderRNA *brna)
"Apply render part of display transformation when displaying this image on the screen");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
- prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMA_IGNORE_ALPHA);
- RNA_def_property_ui_text(
- prop,
- "Use Alpha",
- "Use the alpha channel information from the image or make image fully opaque");
- RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update");
-
prop = RNA_def_property(srna, "use_deinterlace", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_DEINTERLACE);
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index 8086bb2e15d..786386bb63e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -184,7 +184,8 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
* that if we blend the color with a transparent shader using alpha as
* a factor, we don't multiply alpha into the color twice. */
if (out[1].hasoutput &&
- !IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) {
+ !(ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) ||
+ IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name))) {
GPU_link(mat, "tex_color_alpha_unpremultiply", out[0].link, &out[0].link);
}
else {
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index c147794dae7..1aa16dc1019 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -233,7 +233,7 @@ int imagewrap(Tex *tex,
/* keep this before interpolation [#29761] */
if (ima) {
- if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
+ if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) {
if ((tex->imaflag & TEX_CALCALPHA) == 0) {
texres->talpha = true;
}
@@ -1056,7 +1056,7 @@ static int imagewraposa_aniso(Tex *tex,
image_mipmap_test(tex, ibuf);
if (ima) {
- if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
+ if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) {
if ((tex->imaflag & TEX_CALCALPHA) == 0) {
texres->talpha = 1;
}
@@ -1512,7 +1512,7 @@ int imagewraposa(Tex *tex,
image_mipmap_test(tex, ibuf);
if (ima) {
- if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
+ if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) {
if ((tex->imaflag & TEX_CALCALPHA) == 0) {
texres->talpha = true;
}