/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h, bool is_data) { const float *rect_float; uchar *rect_byte; int profile_from = IB_PROFILE_LINEAR_RGB; /* verify we have a float buffer */ if (ibuf->rect_float == NULL || buffer == NULL) return; /* create byte rect if it didn't exist yet */ if (ibuf->rect == NULL) imb_addrectImBuf(ibuf); /* do conversion */ rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels; rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4; if (is_data) { /* exception for non-color data, just copy float */ IMB_buffer_float_from_float(buffer, rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, 0, w, h, w, ibuf->x); /* and do color space conversion to byte */ IMB_buffer_byte_from_float(rect_byte, rect_float, 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, true, w, h, ibuf->x, w); } else { IMB_buffer_float_from_float(buffer, rect_float, ibuf->channels, IB_PROFILE_SRGB, profile_from, true, w, h, w, ibuf->x); IMB_buffer_float_unpremultiply(buffer, w, h); /* XXX: need to convert to image buffer's rect space */ IMB_buffer_byte_from_float(rect_byte, buffer, 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, w, h, ibuf->x, w); } /* ensure user flag is reset */ ibuf->userflags &= ~IB_RECT_INVALID; }
static void imb_buffer_float_from_float_thread_do(void *data_v, int start_scanline, int num_scanlines) { FloatToFloatThreadData *data = (FloatToFloatThreadData *)data_v; size_t offset_from = ((size_t)start_scanline) * data->stride_from * data->channels_from; size_t offset_to = ((size_t)start_scanline) * data->stride_to * data->channels_from; IMB_buffer_float_from_float(data->rect_to + offset_to, data->rect_from + offset_from, data->channels_from, data->profile_to, data->profile_from, data->predivide, data->width, num_scanlines, data->stride_to, data->stride_from); }
void IMB_buffer_float_from_float_threaded(float *rect_to, const float *rect_from, int channels_from, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from) { if (((size_t)width) * height < 64 * 64) { IMB_buffer_float_from_float(rect_to, rect_from, channels_from, profile_to, profile_from, predivide, width, height, stride_to, stride_from); } else { FloatToFloatThreadData data; data.rect_to = rect_to; data.rect_from = rect_from; data.channels_from = channels_from; data.profile_to = profile_to; data.profile_from = profile_from; data.predivide = predivide; data.width = width; data.stride_to = stride_to; data.stride_from = stride_from; IMB_processor_apply_threaded_scanlines(height, imb_buffer_float_from_float_thread_do, &data); } }
static void imb_stereo3d_squeeze_rectf(float *rectf, Stereo3dFormat *s3d, const size_t x, const size_t y, const size_t channels) { ImBuf *ibuf; size_t width, height; if (ELEM(s3d->display_mode, S3D_DISPLAY_SIDEBYSIDE, S3D_DISPLAY_TOPBOTTOM) == false) return; if ((s3d->flag & S3D_SQUEEZED_FRAME) == 0) return; /* creates temporary imbuf to store the rectf */ IMB_stereo3d_write_dimensions(s3d->display_mode, false, x, y, &width, &height); ibuf = IMB_allocImBuf(width, height, channels, IB_rectfloat); IMB_buffer_float_from_float( ibuf->rect_float, rectf, channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false, width, height, width, width); IMB_scaleImBuf_threaded(ibuf, x, y); memcpy(rectf, ibuf->rect_float, x * y * sizeof(float[4])); IMB_freeImBuf(ibuf); }
static bool write_external_bake_pixels( const char *filepath, BakePixel pixel_array[], float *buffer, const int width, const int height, const int margin, ImageFormatData *im_format, const bool is_noncolor) { ImBuf *ibuf = NULL; bool ok = false; bool is_float; is_float = im_format->depth > 8; /* create a new ImBuf */ ibuf = IMB_allocImBuf(width, height, im_format->planes, (is_float ? IB_rectfloat : IB_rect)); if (!ibuf) return false; /* populates the ImBuf */ if (is_float) { IMB_buffer_float_from_float( ibuf->rect_float, buffer, ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false, ibuf->x, ibuf->y, ibuf->x, ibuf->x); } else { if (!is_noncolor) { const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); const char *to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf); IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false); } IMB_buffer_byte_from_float( (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, ibuf->x, ibuf->y, ibuf->x, ibuf->x); } /* margins */ if (margin > 0) { char *mask_buffer = NULL; const size_t num_pixels = (size_t)width * (size_t)height; mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask"); RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer); RE_bake_margin(ibuf, mask_buffer, margin); if (mask_buffer) MEM_freeN(mask_buffer); } if ((ok = BKE_imbuf_write(ibuf, filepath, im_format))) { #ifndef WIN32 chmod(filepath, S_IRUSR | S_IWUSR); #endif //printf("%s saving bake map: '%s'\n", __func__, filepath); } /* garbage collection */ IMB_freeImBuf(ibuf); return ok; }
static bool write_internal_bake_pixels( Image *image, BakePixel pixel_array[], float *buffer, const int width, const int height, const int margin, const bool is_clear, const bool is_noncolor) { ImBuf *ibuf; void *lock; bool is_float; char *mask_buffer = NULL; const size_t num_pixels = (size_t)width * (size_t)height; ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); if (!ibuf) return false; if (margin > 0 || !is_clear) { mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask"); RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer); } is_float = (ibuf->flags & IB_rectfloat); /* colormanagement conversions */ if (!is_noncolor) { const char *from_colorspace; const char *to_colorspace; from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); if (is_float) to_colorspace = IMB_colormanagement_get_float_colorspace(ibuf); else to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf); if (from_colorspace != to_colorspace) IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false); } /* populates the ImBuf */ if (is_clear) { if (is_float) { IMB_buffer_float_from_float( ibuf->rect_float, buffer, ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false, ibuf->x, ibuf->y, ibuf->x, ibuf->x); } else { IMB_buffer_byte_from_float( (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, ibuf->x, ibuf->y, ibuf->x, ibuf->x); } } else { if (is_float) { IMB_buffer_float_from_float_mask( ibuf->rect_float, buffer, ibuf->channels, ibuf->x, ibuf->y, ibuf->x, ibuf->x, mask_buffer); } else { IMB_buffer_byte_from_float_mask( (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, false, ibuf->x, ibuf->y, ibuf->x, ibuf->x, mask_buffer); } } /* margins */ if (margin > 0) RE_bake_margin(ibuf, mask_buffer, margin); ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_BITMAPDIRTY; if (ibuf->rect_float) ibuf->userflags |= IB_RECT_INVALID; /* force mipmap recalc */ if (ibuf->mipmap[0]) { ibuf->userflags |= IB_MIPMAP_INVALID; imb_freemipmapImBuf(ibuf); } BKE_image_release_ibuf(image, ibuf, NULL); if (mask_buffer) MEM_freeN(mask_buffer); return true; }