ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags) { ImBuf *ibuf; ImFileType *type; if(mem == NULL) { printf("Error in ibImageFromMemory: NULL pointer\n"); return NULL; } for(type=IMB_FILE_TYPES; type->is_a; type++) { if(type->load) { ibuf= type->load(mem, size, flags); if(ibuf) { if(flags & IB_premul) { IMB_premultiply_alpha(ibuf); ibuf->flags |= IB_premul; } return ibuf; } } } fprintf(stderr, "Unknown fileformat\n"); return NULL; }
/** Handle deferred (lazy) loading/generation of preview image, if needed. * For now, only used with file thumbnails. */ void BKE_previewimg_ensure(PreviewImage *prv, const int size) { if (prv->use_deferred) { const bool do_icon = ((size == ICON_SIZE_ICON) && !prv->rect[ICON_SIZE_ICON]); const bool do_preview = ((size == ICON_SIZE_PREVIEW) && !prv->rect[ICON_SIZE_PREVIEW]); if (do_icon || do_preview) { ImBuf *thumb; char *prv_deferred_data = PRV_DEFERRED_DATA(prv); int source = prv_deferred_data[0]; char *path = &prv_deferred_data[1]; int icon_w, icon_h; thumb = IMB_thumb_manage(path, THB_LARGE, source); if (thumb) { /* PreviewImage assumes premultiplied alhpa... */ IMB_premultiply_alpha(thumb); if (do_preview) { prv->w[ICON_SIZE_PREVIEW] = thumb->x; prv->h[ICON_SIZE_PREVIEW] = thumb->y; prv->rect[ICON_SIZE_PREVIEW] = MEM_dupallocN(thumb->rect); prv->flag[ICON_SIZE_PREVIEW] &= ~(PRV_CHANGED | PRV_USER_EDITED); } if (do_icon) { if (thumb->x > thumb->y) { icon_w = ICON_RENDER_DEFAULT_HEIGHT; icon_h = (thumb->y * icon_w) / thumb->x + 1; } else if (thumb->x < thumb->y) { icon_h = ICON_RENDER_DEFAULT_HEIGHT; icon_w = (thumb->x * icon_h) / thumb->y + 1; } else { icon_w = icon_h = ICON_RENDER_DEFAULT_HEIGHT; } IMB_scaleImBuf(thumb, icon_w, icon_h); prv->w[ICON_SIZE_ICON] = icon_w; prv->h[ICON_SIZE_ICON] = icon_h; prv->rect[ICON_SIZE_ICON] = MEM_dupallocN(thumb->rect); prv->flag[ICON_SIZE_ICON] &= ~(PRV_CHANGED | PRV_USER_EDITED); } IMB_freeImBuf(thumb); } } } }
static void imb_handle_alpha(ImBuf *ibuf, int flags, char colorspace[IM_MAX_SPACE], char effective_colorspace[IM_MAX_SPACE]) { int alpha_flags; if (colorspace) { if (ibuf->rect) { /* byte buffer is never internally converted to some standard space, * store pointer to it's color space descriptor instead */ ibuf->rect_colorspace = colormanage_colorspace_get_named(effective_colorspace); } BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE); } if (flags & IB_alphamode_detect) alpha_flags = ibuf->flags & IB_alphamode_premul; else alpha_flags = flags & IB_alphamode_premul; if (flags & IB_ignore_alpha) { IMB_rectfill_alpha(ibuf, 1.0f); } else { if (alpha_flags & IB_alphamode_premul) { if (ibuf->rect) { IMB_unpremultiply_alpha(ibuf); } else { /* pass, floats are expected to be premul */ } } else { if (ibuf->rect_float) { IMB_premultiply_alpha(ibuf); } else { /* pass, bytes are expected to be straight */ } } } /* OCIO_TODO: in some cases it's faster to do threaded conversion, * but how to distinguish such cases */ colormanage_imbuf_make_linear(ibuf, effective_colorspace); }
static void init_internal_icons(void) { // bTheme *btheme = UI_GetTheme(); ImBuf *b16buf = NULL, *b32buf = NULL; int x, y, icontype; #if 0 // temp disabled if ((btheme != NULL) && btheme->tui.iconfile[0]) { char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons"); char iconfilestr[FILE_MAX]; if (icondir) { BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile); bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL); /* if the image is missing bbuf will just be NULL */ if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) { printf("\n***WARNING***\nIcons file %s too small.\nUsing built-in Icons instead\n", iconfilestr); IMB_freeImBuf(bbuf); bbuf = NULL; } } else { printf("%s: 'icons' data path not found, continuing\n", __func__); } } #endif if (b16buf == NULL) b16buf = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_icons16_png, datatoc_blender_icons16_png_size, IB_rect, NULL, "<blender icons>"); if (b16buf) IMB_premultiply_alpha(b16buf); if (b32buf == NULL) b32buf = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_icons32_png, datatoc_blender_icons32_png_size, IB_rect, NULL, "<blender icons>"); if (b32buf) IMB_premultiply_alpha(b32buf); if (b16buf && b32buf) { /* free existing texture if any */ if (icongltex.id) { glDeleteTextures(1, &icongltex.id); icongltex.id = 0; } /* we only use a texture for cards with non-power of two */ if (GPU_non_power_of_two_support()) { glGenTextures(1, &icongltex.id); if (icongltex.id) { int level = 2; icongltex.w = b32buf->x; icongltex.h = b32buf->y; icongltex.invw = 1.0f / b32buf->x; icongltex.invh = 1.0f / b32buf->y; glBindTexture(GL_TEXTURE_2D, icongltex.id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, b32buf->x, b32buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b32buf->rect); glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, b16buf->x, b16buf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, b16buf->rect); while (b16buf->x > 1) { ImBuf *nbuf = IMB_onehalf(b16buf); glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, nbuf->x, nbuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nbuf->rect); level++; IMB_freeImBuf(b16buf); b16buf = nbuf; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); if (glGetError() == GL_OUT_OF_MEMORY) { glDeleteTextures(1, &icongltex.id); icongltex.id = 0; } } } } if (icongltex.id) icontype = ICON_TYPE_TEXTURE; else icontype = ICON_TYPE_BUFFER; if (b32buf) { for (y = 0; y < ICON_GRID_ROWS; y++) { for (x = 0; x < ICON_GRID_COLS; x++) { def_internal_icon(b32buf, BIFICONID_FIRST + y * ICON_GRID_COLS + x, x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN, y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN, ICON_GRID_W, icontype); } } } def_internal_vicon(VICO_VIEW3D_VEC, vicon_view3d_draw); def_internal_vicon(VICO_EDIT_VEC, vicon_edit_draw); def_internal_vicon(VICO_EDITMODE_VEC_DEHLT, vicon_editmode_dehlt_draw); def_internal_vicon(VICO_EDITMODE_VEC_HLT, vicon_editmode_hlt_draw); def_internal_vicon(VICO_DISCLOSURE_TRI_RIGHT_VEC, vicon_disclosure_tri_right_draw); def_internal_vicon(VICO_DISCLOSURE_TRI_DOWN_VEC, vicon_disclosure_tri_down_draw); def_internal_vicon(VICO_MOVE_UP_VEC, vicon_move_up_draw); def_internal_vicon(VICO_MOVE_DOWN_VEC, vicon_move_down_draw); def_internal_vicon(VICO_X_VEC, vicon_x_draw); def_internal_vicon(VICO_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw); IMB_freeImBuf(b16buf); IMB_freeImBuf(b32buf); }
static void icon_preview_startjob(void *customdata, short *stop, short *do_update) { ShaderPreview *sp = customdata; if (sp->pr_method == PR_ICON_DEFERRED) { PreviewImage *prv = sp->owner; ImBuf *thumb; char *deferred_data = PRV_DEFERRED_DATA(prv); int source = deferred_data[0]; char *path = &deferred_data[1]; // printf("generating deferred %d×%d preview for %s\n", sp->sizex, sp->sizey, path); thumb = IMB_thumb_manage(path, THB_LARGE, source); if (thumb) { /* PreviewImage assumes premultiplied alhpa... */ IMB_premultiply_alpha(thumb); icon_copy_rect(thumb, sp->sizex, sp->sizey, sp->pr_rect); IMB_freeImBuf(thumb); } } else { ID *id = sp->id; short idtype = GS(id->name); if (idtype == ID_IM) { Image *ima = (Image *)id; ImBuf *ibuf = NULL; ImageUser iuser = {NULL}; /* ima->ok is zero when Image cannot load */ if (ima == NULL || ima->ok == 0) return; /* setup dummy image user */ iuser.ok = iuser.framenr = 1; iuser.scene = sp->scene; /* elubie: this needs to be changed: here image is always loaded if not * already there. Very expensive for large images. Need to find a way to * only get existing ibuf */ ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); if (ibuf == NULL || ibuf->rect == NULL) { BKE_image_release_ibuf(ima, ibuf, NULL); return; } icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); *do_update = true; BKE_image_release_ibuf(ima, ibuf, NULL); } else if (idtype == ID_BR) { Brush *br = (Brush *)id; br->icon_imbuf = get_brush_icon(br); memset(sp->pr_rect, 0x88, sp->sizex * sp->sizey * sizeof(unsigned int)); if (!(br->icon_imbuf) || !(br->icon_imbuf->rect)) return; icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect); *do_update = true; } else { /* re-use shader job */ shader_preview_startjob(customdata, stop, do_update); /* world is rendered with alpha=0, so it wasn't displayed * this could be render option for sky to, for later */ if (idtype == ID_WO) { set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); } else if (idtype == ID_MA) { Material *ma = (Material *)id; if (ma->material_type == MA_TYPE_HALO) set_alpha((char *)sp->pr_rect, sp->sizex, sp->sizey, 255); } } } }
/* * Use the libTIFF scanline API to read a TIFF image. * This method is most flexible and can handle multiple different bit depths * and RGB channel orderings. */ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul) { ImBuf *tmpibuf; int success= 0; short bitspersample, spp, config; size_t scanline; int ib_flag=0, row, chan; float *fbuf=NULL; unsigned short *sbuf=NULL; TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitspersample); TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); /* number of 'channels' */ TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config); imb_read_tiff_resolution(ibuf, image); scanline = TIFFScanlineSize(image); if (bitspersample == 32) { ib_flag = IB_rectfloat; fbuf = (float *)_TIFFmalloc(scanline); } else if (bitspersample == 16) { ib_flag = IB_rectfloat; sbuf = (unsigned short *)_TIFFmalloc(scanline); } else { ib_flag = IB_rect; } tmpibuf= IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, ib_flag); /* simple RGBA image */ if (!(bitspersample == 32 || bitspersample == 16)) { success |= TIFFReadRGBAImage(image, ibuf->x, ibuf->y, tmpibuf->rect, 0); } /* contiguous channels: RGBRGBRGB */ else if (config == PLANARCONFIG_CONTIG) { for (row = 0; row < ibuf->y; row++) { int ib_offset = ibuf->x*ibuf->y*4 - ibuf->x*4 * (row+1); if (bitspersample == 32) { success |= TIFFReadScanline(image, fbuf, row, 0); scanline_contig_32bit(tmpibuf->rect_float+ib_offset, fbuf, ibuf->x, spp); } else if (bitspersample == 16) { success |= TIFFReadScanline(image, sbuf, row, 0); scanline_contig_16bit(tmpibuf->rect_float+ib_offset, sbuf, ibuf->x, spp); } } /* separate channels: RRRGGGBBB */ } else if (config == PLANARCONFIG_SEPARATE) { /* imbufs always have 4 channels of data, so we iterate over all of them * but only fill in from the TIFF scanline where necessary. */ for (chan = 0; chan < 4; chan++) { for (row = 0; row < ibuf->y; row++) { int ib_offset = ibuf->x*ibuf->y*4 - ibuf->x*4 * (row+1); if (bitspersample == 32) { if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ fill_vn_fl(fbuf, ibuf->x, 1.0f); else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */ success |= TIFFReadScanline(image, fbuf, row, 0); else success |= TIFFReadScanline(image, fbuf, row, chan); scanline_separate_32bit(tmpibuf->rect_float+ib_offset, fbuf, ibuf->x, chan); } else if (bitspersample == 16) { if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ fill_vn_ushort(sbuf, ibuf->x, 65535); else if (chan >= spp) /* for grayscale, duplicate first channel into G and B */ success |= TIFFReadScanline(image, fbuf, row, 0); else success |= TIFFReadScanline(image, sbuf, row, chan); scanline_separate_16bit(tmpibuf->rect_float+ib_offset, sbuf, ibuf->x, chan); } } } } if (bitspersample == 32) _TIFFfree(fbuf); else if (bitspersample == 16) _TIFFfree(sbuf); if (success) { ibuf->profile = (bitspersample==32)?IB_PROFILE_LINEAR_RGB:IB_PROFILE_SRGB; // Code seems to be not needed for 16 bits tif, on PPC G5 OSX (ton) if (bitspersample < 16) if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(tmpibuf); if (premul) { IMB_premultiply_alpha(tmpibuf); ibuf->flags |= IB_premul; } /* assign rect last */ if (tmpibuf->rect_float) ibuf->rect_float= tmpibuf->rect_float; else ibuf->rect= tmpibuf->rect; ibuf->mall |= ib_flag; ibuf->flags |= ib_flag; tmpibuf->mall &= ~ib_flag; } IMB_freeImBuf(tmpibuf); return success; }