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:
Diffstat (limited to 'source/blender')
-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
14 files changed, 115 insertions, 52 deletions
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;
}