/* byte to byte pixels, input and output 4-channel RGBA */ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from) { float tmp[4]; int x, y; /* we need valid profiles */ BLI_assert(profile_to != IB_PROFILE_NONE); BLI_assert(profile_from != IB_PROFILE_NONE); /* always RGBA input */ for (y = 0; y < height; y++) { const uchar *from = rect_from + stride_from * y * 4; uchar *to = rect_to + stride_to * y * 4; if (profile_to == profile_from) { /* same profile, copy */ memcpy(to, from, sizeof(uchar) * 4 * width); } else if (profile_to == IB_PROFILE_LINEAR_RGB) { /* convert to sRGB to linear */ if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { rgba_uchar_to_float(tmp, from); srgb_to_linearrgb_predivide_v4(tmp, tmp); rgba_float_to_uchar(to, tmp); } } else { for (x = 0; x < width; x++, from += 4, to += 4) { rgba_uchar_to_float(tmp, from); srgb_to_linearrgb_v4(tmp, tmp); rgba_float_to_uchar(to, tmp); } } } else if (profile_to == IB_PROFILE_SRGB) { /* convert from linear to sRGB */ if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { rgba_uchar_to_float(tmp, from); linearrgb_to_srgb_predivide_v4(tmp, tmp); rgba_float_to_uchar(to, tmp); } } else { for (x = 0; x < width; x++, from += 4, to += 4) { rgba_uchar_to_float(tmp, from); linearrgb_to_srgb_v4(tmp, tmp); rgba_float_to_uchar(to, tmp); } } } } }
void blf_draw_buffer__start(FontBLF *font) { FontBufInfoBLF *buf_info = &font->buf_info; buf_info->col_char[0] = buf_info->col_init[0] * 255; buf_info->col_char[1] = buf_info->col_init[1] * 255; buf_info->col_char[2] = buf_info->col_init[2] * 255; buf_info->col_char[3] = buf_info->col_init[3] * 255; if (buf_info->display) { copy_v4_v4(buf_info->col_float, buf_info->col_init); IMB_colormanagement_display_to_scene_linear_v3(buf_info->col_float, buf_info->display); } else { srgb_to_linearrgb_v4(buf_info->col_float, buf_info->col_init); } }
/* Sanity checks are done by BLF_draw_buffer() */ void blf_font_buffer(FontBLF *font, const char *str) { unsigned int c; GlyphBLF *g, *g_prev = NULL; FT_Vector delta; int pen_x = (int)font->pos[0], pen_y = 0; size_t i = 0; GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; /* buffer specific vars */ FontBufInfoBLF *buf_info = &font->buf_info; float b_col_float[4]; const unsigned char b_col_char[4] = { (unsigned char)(buf_info->col[0] * 255), (unsigned char)(buf_info->col[1] * 255), (unsigned char)(buf_info->col[2] * 255), (unsigned char)(buf_info->col[3] * 255)}; unsigned char *cbuf; int chx, chy; int y, x; float a, *fbuf; BLF_KERNING_VARS(font, has_kerning, kern_mode); blf_font_ensure_ascii_table(font); /* another buffer specific call for color conversion */ if (buf_info->display) { copy_v4_v4(b_col_float, buf_info->col); IMB_colormanagement_display_to_scene_linear_v3(b_col_float, buf_info->display); } else { srgb_to_linearrgb_v4(b_col_float, buf_info->col); } while (str[i]) { BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); if (UNLIKELY(c == BLI_UTF8_ERR)) break; if (UNLIKELY(g == NULL)) continue; if (has_kerning) BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x); chx = pen_x + ((int)g->pos_x); chy = (int)font->pos[1] + g->height; if (g->pitch < 0) { pen_y = (int)font->pos[1] + (g->height - (int)g->pos_y); } else { pen_y = (int)font->pos[1] - (g->height - (int)g->pos_y); } if ((chx + g->width) >= 0 && chx < buf_info->w && (pen_y + g->height) >= 0 && pen_y < buf_info->h) { /* don't draw beyond the buffer bounds */ int width_clip = g->width; int height_clip = g->height; int yb_start = g->pitch < 0 ? 0 : g->height - 1; if (width_clip + chx > buf_info->w) width_clip -= chx + width_clip - buf_info->w; if (height_clip + pen_y > buf_info->h) height_clip -= pen_y + height_clip - buf_info->h; /* drawing below the image? */ if (pen_y < 0) { yb_start += (g->pitch < 0) ? -pen_y : pen_y; height_clip += pen_y; pen_y = 0; } if (buf_info->fbuf) { int yb = yb_start; for (y = ((chy >= 0) ? 0 : -chy); y < height_clip; y++) { for (x = ((chx >= 0) ? 0 : -chx); x < width_clip; x++) { a = *(g->bitmap + x + (yb * g->pitch)) / 255.0f; if (a > 0.0f) { float alphatest; fbuf = buf_info->fbuf + buf_info->ch * ((chx + x) + ((pen_y + y) * buf_info->w)); if (a >= 1.0f) { fbuf[0] = b_col_float[0]; fbuf[1] = b_col_float[1]; fbuf[2] = b_col_float[2]; fbuf[3] = (alphatest = (fbuf[3] + (b_col_float[3]))) < 1.0f ? alphatest : 1.0f; } else { fbuf[0] = (b_col_float[0] * a) + (fbuf[0] * (1.0f - a)); fbuf[1] = (b_col_float[1] * a) + (fbuf[1] * (1.0f - a)); fbuf[2] = (b_col_float[2] * a) + (fbuf[2] * (1.0f - a)); fbuf[3] = (alphatest = (fbuf[3] + (b_col_float[3] * a))) < 1.0f ? alphatest : 1.0f; } } } if (g->pitch < 0) yb++; else yb--; } } if (buf_info->cbuf) { int yb = yb_start; for (y = 0; y < height_clip; y++) { for (x = 0; x < width_clip; x++) { a = *(g->bitmap + x + (yb * g->pitch)) / 255.0f; if (a > 0.0f) { int alphatest; cbuf = buf_info->cbuf + buf_info->ch * ((chx + x) + ((pen_y + y) * buf_info->w)); if (a >= 1.0f) { cbuf[0] = b_col_char[0]; cbuf[1] = b_col_char[1]; cbuf[2] = b_col_char[2]; alphatest = (int)cbuf[3] + (int)b_col_char[3]; if (alphatest < 255) { cbuf[3] = (unsigned char)(alphatest); } else { cbuf[3] = 255; } } else { cbuf[0] = (unsigned char)((b_col_char[0] * a) + (cbuf[0] * (1.0f - a))); cbuf[1] = (unsigned char)((b_col_char[1] * a) + (cbuf[1] * (1.0f - a))); cbuf[2] = (unsigned char)((b_col_char[2] * a) + (cbuf[2] * (1.0f - a))); alphatest = ((int)cbuf[3] + (int)((b_col_float[3] * a) * 255.0f)); if (alphatest < 255) { cbuf[3] = (unsigned char)(alphatest); } else { cbuf[3] = 255; } } } } if (g->pitch < 0) yb++; else yb--; } } } pen_x += g->advance_i; g_prev = g; } }
/* float to float pixels, output 4-channel RGBA */ void IMB_buffer_float_from_float(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) { int x, y; /* we need valid profiles */ BLI_assert(profile_to != IB_PROFILE_NONE); BLI_assert(profile_from != IB_PROFILE_NONE); if (channels_from == 1) { /* single channel input */ for (y = 0; y < height; y++) { const float *from = rect_from + ((size_t)stride_from) * y; float *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from++, to += 4) { to[0] = to[1] = to[2] = to[3] = from[0]; } } } else if (channels_from == 3) { /* RGB input */ for (y = 0; y < height; y++) { const float *from = rect_from + ((size_t)stride_from) * y * 3; float *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* no color space conversion */ for (x = 0; x < width; x++, from += 3, to += 4) { copy_v3_v3(to, from); to[3] = 1.0f; } } else if (profile_to == IB_PROFILE_LINEAR_RGB) { /* convert from sRGB to linear */ for (x = 0; x < width; x++, from += 3, to += 4) { srgb_to_linearrgb_v3_v3(to, from); to[3] = 1.0f; } } else if (profile_to == IB_PROFILE_SRGB) { /* convert from linear to sRGB */ for (x = 0; x < width; x++, from += 3, to += 4) { linearrgb_to_srgb_v3_v3(to, from); to[3] = 1.0f; } } } } else if (channels_from == 4) { /* RGBA input */ for (y = 0; y < height; y++) { const float *from = rect_from + ((size_t)stride_from) * y * 4; float *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* same profile, copy */ memcpy(to, from, sizeof(float) * ((size_t)4) * width); } else if (profile_to == IB_PROFILE_LINEAR_RGB) { /* convert to sRGB to linear */ if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { srgb_to_linearrgb_predivide_v4(to, from); } } else { for (x = 0; x < width; x++, from += 4, to += 4) { srgb_to_linearrgb_v4(to, from); } } } else if (profile_to == IB_PROFILE_SRGB) { /* convert from linear to sRGB */ if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { linearrgb_to_srgb_predivide_v4(to, from); } } else { for (x = 0; x < width; x++, from += 4, to += 4) { linearrgb_to_srgb_v4(to, from); } } } } } }
/* float to byte pixels, output 4-channel RGBA */ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, int channels_from, float dither, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from) { float tmp[4]; int x, y; DitherContext *di = NULL; float inv_width = 1.0f / width; float inv_height = 1.0f / height; /* we need valid profiles */ BLI_assert(profile_to != IB_PROFILE_NONE); BLI_assert(profile_from != IB_PROFILE_NONE); if (dither) { di = create_dither_context(dither); } for (y = 0; y < height; y++) { float t = y * inv_height; if (channels_from == 1) { /* single channel input */ const float *from = rect_from + ((size_t)stride_from) * y; uchar *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from++, to += 4) { to[0] = to[1] = to[2] = to[3] = unit_float_to_uchar_clamp(from[0]); } } else if (channels_from == 3) { /* RGB input */ const float *from = rect_from + ((size_t)stride_from) * y * 3; uchar *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* no color space conversion */ for (x = 0; x < width; x++, from += 3, to += 4) { rgb_float_to_uchar(to, from); to[3] = 255; } } else if (profile_to == IB_PROFILE_SRGB) { /* convert from linear to sRGB */ for (x = 0; x < width; x++, from += 3, to += 4) { linearrgb_to_srgb_v3_v3(tmp, from); rgb_float_to_uchar(to, tmp); to[3] = 255; } } else if (profile_to == IB_PROFILE_LINEAR_RGB) { /* convert from sRGB to linear */ for (x = 0; x < width; x++, from += 3, to += 4) { srgb_to_linearrgb_v3_v3(tmp, from); rgb_float_to_uchar(to, tmp); to[3] = 255; } } } else if (channels_from == 4) { /* RGBA input */ const float *from = rect_from + ((size_t)stride_from) * y * 4; uchar *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { float straight[4]; /* no color space conversion */ if (dither && predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { premul_to_straight_v4_v4(straight, from); float_to_byte_dither_v4(to, straight, di, (float)x * inv_width, t); } } else if (dither) { for (x = 0; x < width; x++, from += 4, to += 4) { float_to_byte_dither_v4(to, from, di, (float)x * inv_width, t); } } else if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { premul_to_straight_v4_v4(straight, from); rgba_float_to_uchar(to, straight); } } else { for (x = 0; x < width; x++, from += 4, to += 4) { rgba_float_to_uchar(to, from); } } } else if (profile_to == IB_PROFILE_SRGB) { /* convert from linear to sRGB */ unsigned short us[4]; float straight[4]; if (dither && predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { premul_to_straight_v4_v4(straight, from); linearrgb_to_srgb_ushort4(us, from); ushort_to_byte_dither_v4(to, us, di, (float)x * inv_width, t); } } else if (dither) { for (x = 0; x < width; x++, from += 4, to += 4) { linearrgb_to_srgb_ushort4(us, from); ushort_to_byte_dither_v4(to, us, di, (float)x * inv_width, t); } } else if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { premul_to_straight_v4_v4(straight, from); linearrgb_to_srgb_ushort4(us, from); ushort_to_byte_v4(to, us); } } else { for (x = 0; x < width; x++, from += 4, to += 4) { linearrgb_to_srgb_ushort4(us, from); ushort_to_byte_v4(to, us); } } } else if (profile_to == IB_PROFILE_LINEAR_RGB) { /* convert from sRGB to linear */ if (dither && predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { srgb_to_linearrgb_predivide_v4(tmp, from); float_to_byte_dither_v4(to, tmp, di, (float)x * inv_width, t); } } else if (dither) { for (x = 0; x < width; x++, from += 4, to += 4) { srgb_to_linearrgb_v4(tmp, from); float_to_byte_dither_v4(to, tmp, di, (float)x * inv_width, t); } } else if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { srgb_to_linearrgb_predivide_v4(tmp, from); rgba_float_to_uchar(to, tmp); } } else { for (x = 0; x < width; x++, from += 4, to += 4) { srgb_to_linearrgb_v4(tmp, from); rgba_float_to_uchar(to, tmp); } } } } } if (dither) { clear_dither_context(di); } }
struct ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags){ struct ImBuf *ibuf = NULL; png_structp png_ptr; png_infop info_ptr; unsigned char *pixels = NULL; unsigned short *pixels16 = NULL; png_bytepp row_pointers = NULL; png_uint_32 width, height; int bit_depth, color_type; PNGReadStruct ps; unsigned char *from, *to; unsigned short *from16; float *to_float; float tmp[4]; int i, bytesperpixel; if (imb_is_a_png(mem) == 0) return(NULL); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { printf("Cannot png_create_read_struct\n"); return NULL; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); printf("Cannot png_create_info_struct\n"); return NULL; } ps.size = size; /* XXX, 4gig limit! */ ps.data = mem; ps.seek = 0; png_set_read_fn(png_ptr, (void *) &ps, ReadData); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); if (pixels) MEM_freeN(pixels); if (pixels16) MEM_freeN(pixels16); if (row_pointers) MEM_freeN(row_pointers); if (ibuf) IMB_freeImBuf(ibuf); return NULL; } // png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); bytesperpixel = png_get_channels(png_ptr, info_ptr); switch (color_type) { case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: break; case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { bytesperpixel = 4; } else { bytesperpixel = 3; } break; case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: if (bit_depth < 8) { png_set_expand(png_ptr); bit_depth = 8; } break; default: printf("PNG format not supported\n"); longjmp(png_jmpbuf(png_ptr), 1); } ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0); if (ibuf) { ibuf->ftype = PNG; if (bit_depth == 16) ibuf->profile = IB_PROFILE_LINEAR_RGB; else ibuf->profile = IB_PROFILE_SRGB; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) { int unit_type; png_uint_32 xres, yres; if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) if (unit_type == PNG_RESOLUTION_METER) { ibuf->ppm[0] = xres; ibuf->ppm[1] = yres; } } } else { printf("Couldn't allocate memory for PNG image\n"); } if (ibuf && ((flags & IB_test) == 0)) { if (bit_depth == 16) { imb_addrectfloatImBuf(ibuf); png_set_swap(png_ptr); pixels16 = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(png_uint_16), "pixels"); if (pixels16 == NULL) { printf("Cannot allocate pixels array\n"); longjmp(png_jmpbuf(png_ptr), 1); } // allocate memory for an array of row-pointers row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_uint_16p), "row_pointers"); if (row_pointers == NULL) { printf("Cannot allocate row-pointers array\n"); longjmp(png_jmpbuf(png_ptr), 1); } // set the individual row-pointers to point at the correct offsets for (i = 0; i < ibuf->y; i++) { row_pointers[ibuf->y - 1 - i] = (png_bytep) ((png_uint_16 *)pixels16 + (i * ibuf->x) * bytesperpixel); } png_read_image(png_ptr, row_pointers); // copy image data to_float = ibuf->rect_float; from16 = pixels16; switch (bytesperpixel) { case 4: for (i = ibuf->x * ibuf->y; i > 0; i--) { tmp[0] = from16[0] / 65535.0; tmp[1] = from16[1] / 65535.0; tmp[2] = from16[2] / 65535.0; tmp[3] = from16[3] / 65535.0; srgb_to_linearrgb_v4(to_float, tmp); to_float += 4; from16 += 4; } break; case 3: for (i = ibuf->x * ibuf->y; i > 0; i--) { tmp[0] = from16[0] / 65535.0; tmp[1] = from16[1] / 65535.0; tmp[2] = from16[2] / 65535.0; tmp[3] = 1.0; srgb_to_linearrgb_v4(to_float, tmp); to_float += 4; from16 += 3; } break; case 2: for (i = ibuf->x * ibuf->y; i > 0; i--) { tmp[0] = tmp[1] = tmp[2] = from16[0] / 65535.0; tmp[3] = from16[1] / 65535.0; srgb_to_linearrgb_v4(to_float, tmp); to_float += 4; from16 += 2; } break; case 1: for (i = ibuf->x * ibuf->y; i > 0; i--) { tmp[0] = tmp[1] = tmp[2] = from16[0] / 65535.0; tmp[3] = 1.0; srgb_to_linearrgb_v4(to_float, tmp); to_float += 4; from16++; } break; } } else { imb_addrectImBuf(ibuf); pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels"); if (pixels == NULL) { printf("Cannot allocate pixels array\n"); longjmp(png_jmpbuf(png_ptr), 1); } // allocate memory for an array of row-pointers row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers"); if (row_pointers == NULL) { printf("Cannot allocate row-pointers array\n"); longjmp(png_jmpbuf(png_ptr), 1); } // set the individual row-pointers to point at the correct offsets for (i = 0; i < ibuf->y; i++) { row_pointers[ibuf->y - 1 - i] = (png_bytep) ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char)); } png_read_image(png_ptr, row_pointers); // copy image data to = (unsigned char *) ibuf->rect; from = pixels; switch (bytesperpixel) { case 4: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; to[3] = from[3]; to += 4; from += 4; } break; case 3: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; to[3] = 0xff; to += 4; from += 3; } break; case 2: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = to[1] = to[2] = from[0]; to[3] = from[1]; to += 4; from += 2; } break; case 1: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = to[1] = to[2] = from[0]; to[3] = 0xff; to += 4; from++; } break; } } if (flags & IB_metadata) { png_text *text_chunks; int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL); for (i = 0; i < count; i++) { IMB_metadata_add_field(ibuf, text_chunks[i].key, text_chunks[i].text); ibuf->flags |= IB_metadata; } } png_read_end(png_ptr, info_ptr); } // clean up if (pixels) MEM_freeN(pixels); if (pixels16) MEM_freeN(pixels16); MEM_freeN(row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return(ibuf); }
void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, const float col[4], struct ColorManagedDisplay *display, int x1, int y1, int x2, int y2) { int i, j; float a; /* alpha */ float ai; /* alpha inverted */ float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */ if ((!rect && !rectf) || (!col) || col[3] == 0.0f) return; /* sanity checks for coords */ CLAMP(x1, 0, width); CLAMP(x2, 0, width); CLAMP(y1, 0, height); CLAMP(y2, 0, height); if (x1 > x2) SWAP(int, x1, x2); if (y1 > y2) SWAP(int, y1, y2); if (x1 == x2 || y1 == y2) return; a = col[3]; ai = 1 - a; aich = ai / 255.0f; if (rect) { unsigned char *pixel; unsigned char chr = 0, chg = 0, chb = 0; float fr = 0, fg = 0, fb = 0; const int alphaint = FTOCHAR(a); if (a == 1.0f) { chr = FTOCHAR(col[0]); chg = FTOCHAR(col[1]); chb = FTOCHAR(col[2]); } else { fr = col[0] * a; fg = col[1] * a; fb = col[2] * a; } for (j = 0; j < y2 - y1; j++) { for (i = 0; i < x2 - x1; i++) { pixel = rect + 4 * (((y1 + j) * width) + (x1 + i)); if (pixel >= rect && pixel < rect + (4 * (width * height))) { if (a == 1.0f) { pixel[0] = chr; pixel[1] = chg; pixel[2] = chb; pixel[3] = 255; } else { int alphatest; pixel[0] = (char)((fr + ((float)pixel[0] * aich)) * 255.0f); pixel[1] = (char)((fg + ((float)pixel[1] * aich)) * 255.0f); pixel[2] = (char)((fb + ((float)pixel[2] * aich)) * 255.0f); pixel[3] = (char)((alphatest = ((int)pixel[3] + alphaint)) < 255 ? alphatest : 255); } } } } } if (rectf) { float col_conv[4]; float *pixel; if (display) { copy_v4_v4(col_conv, col); IMB_colormanagement_display_to_scene_linear_v3(col_conv, display); } else { srgb_to_linearrgb_v4(col_conv, col); } for (j = 0; j < y2 - y1; j++) { for (i = 0; i < x2 - x1; i++) { pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i)); if (a == 1.0f) { pixel[0] = col_conv[0]; pixel[1] = col_conv[1]; pixel[2] = col_conv[2]; pixel[3] = 1.0f; } else { float alphatest; pixel[0] = (col_conv[0] * a) + (pixel[0] * ai); pixel[1] = (col_conv[1] * a) + (pixel[1] * ai); pixel[2] = (col_conv[2] * a) + (pixel[2] * ai); pixel[3] = (alphatest = (pixel[3] + a)) < 1.0f ? alphatest : 1.0f; } } } } }