static void QT_StartAddVideoSamplesToMedia (const Rect *trackFrame, int rectx, int recty, ReportList *reports) { SCTemporalSettings gTemporalSettings; OSErr err = noErr; qtexport->ibuf = IMB_allocImBuf (rectx, recty, 32, IB_rect); qtexport->ibuf2 = IMB_allocImBuf (rectx, recty, 32, IB_rect); err = NewGWorldFromPtr( &qtexport->theGWorld, k32ARGBPixelFormat, trackFrame, NULL, NULL, 0, (Ptr)qtexport->ibuf->rect, rectx * 4 ); CheckError (err, "NewGWorldFromPtr error", reports); qtexport->thePixMap = GetGWorldPixMap(qtexport->theGWorld); LockPixels(qtexport->thePixMap); SCDefaultPixMapSettings (qtdata->theComponent, qtexport->thePixMap, true); // workaround for crash with H.264, which requires an upgrade to // the new callback based api for proper encoding, but that's not // really compatible with rendering out frames sequentially gTemporalSettings = qtdata->gTemporalSettings; if(qtdata->gSpatialSettings.codecType == kH264CodecType) { if(gTemporalSettings.temporalQuality != codecMinQuality) { BKE_reportf(reports, RPT_WARNING, "Only minimum quality compression supported for QuickTime H.264.\n"); gTemporalSettings.temporalQuality = codecMinQuality; } } SCSetInfo(qtdata->theComponent, scTemporalSettingsType, &gTemporalSettings); SCSetInfo(qtdata->theComponent, scSpatialSettingsType, &qtdata->gSpatialSettings); SCSetInfo(qtdata->theComponent, scDataRateSettingsType, &qtdata->aDataRateSetting); err = SCCompressSequenceBegin(qtdata->theComponent, qtexport->thePixMap, NULL, &qtexport->anImageDescription); CheckError (err, "SCCompressSequenceBegin error", reports ); }
static ImBuf *float_image_to_ibuf(libmv_FloatImage *float_image) { ImBuf *ibuf = IMB_allocImBuf(float_image->width, float_image->height, 32, 0); size_t size = (size_t)ibuf->x * (size_t)ibuf->y * float_image->channels * sizeof(float); ibuf->channels = float_image->channels; if ((ibuf->rect_float = MEM_mapallocN(size, "tracking grayscale image"))) { ibuf->mall |= IB_rectfloat; ibuf->flags |= IB_rectfloat; } memcpy(ibuf->rect_float, float_image->buffer, size); return ibuf; }
static ImBuf *make_sep_waveform_view_from_ibuf_float(ImBuf *ibuf) { ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect); int x, y; float *src = ibuf->rect_float; unsigned char *tgt = (unsigned char *) rval->rect; int w = ibuf->x + 3; int sw = ibuf->x / 3; int h = 515; float waveform_gamma = 0.2; unsigned char wtable[256]; wform_put_grid(tgt, w, h); for (x = 0; x < 256; x++) { wtable[x] = (unsigned char) (pow(((float) x + 1) / 256, waveform_gamma) * 255); } for (y = 0; y < ibuf->y; y++) { unsigned char *last_p[3] = {NULL, NULL, NULL}; for (x = 0; x < ibuf->x; x++) { int c; float *rgb = src + 4 * (ibuf->x * y + x); for (c = 0; c < 3; c++) { unsigned char *p = tgt; float v = rgb[c]; CLAMP(v, 0.0f, 1.0f); p += 4 * (w * ((int) (v * (h - 3)) + 1) + c * sw + x / 3 + 1); scope_put_pixel_single(wtable, p, c); p += 4 * w; scope_put_pixel_single(wtable, p, c); if (last_p[c] != NULL) { wform_put_line_single( w, last_p[c], p, c); } last_p[c] = p; } } } wform_put_border(tgt, w, h); return rval; }
// img must point to a array of RGBA data of size width*height void ImageBuff::plot(unsigned char *img, short width, short height, short x, short y, short mode) { struct ImBuf *tmpbuf; if (m_size[0] == 0 || m_size[1] == 0 || width <= 0 || height <= 0) return; if (!m_imbuf) { // allocate most basic imbuf, we will assign the rect buffer on the fly m_imbuf = IMB_allocImBuf(m_size[0], m_size[1], 0, 0); } tmpbuf = IMB_allocImBuf(width, height, 0, 0); // assign temporarily our buffer to the ImBuf buffer, we use the same format tmpbuf->rect = (unsigned int*)img; m_imbuf->rect = m_image; IMB_rectblend(m_imbuf, m_imbuf, tmpbuf, NULL, NULL, NULL, 0, x, y, x, y, 0, 0, width, height, (IMB_BlendMode)mode, false); // remove so that MB_freeImBuf will free our buffer m_imbuf->rect = NULL; tmpbuf->rect = NULL; IMB_freeImBuf(tmpbuf); }
static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int use_cineon, int flags, char colorspace[IM_MAX_SPACE]) { ImBuf *ibuf; LogImageFile *image; int width, height, depth; colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0); image = logImageOpenFromMemory(mem, size); if (image == 0) { printf("DPX/Cineon: error opening image.\n"); return 0; } logImageGetSize(image, &width, &height, &depth); if (width == 0 || height == 0) { logImageClose(image); return 0; } ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags); if (ibuf == 0) { logImageClose(image); return 0; } if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) { /* Conversion not possible (probably because the format is unsupported) */ logImageClose(image); MEM_freeN(ibuf); return 0; } logImageClose(image); ibuf->ftype = use_cineon ? CINEON : DPX; IMB_flipy(ibuf); if (flags & IB_rect) IMB_rect_from_float(ibuf); if (flags & IB_alphamode_detect) ibuf->flags |= IB_alphamode_premul; return ibuf; }
static struct ImBuf *make_vectorscope_view_from_ibuf_float(struct ImBuf * ibuf) { struct ImBuf * rval = IMB_allocImBuf(515, 515, 32, IB_rect); int x,y; float* src = ibuf->rect_float; char* tgt = (char*) rval->rect; float rgb[3], yuv[3]; int w = 515; int h = 515; float scope_gamma = 0.2; unsigned char wtable[256]; for (x = 0; x < 256; x++) { wtable[x] = (unsigned char) (pow(((float) x + 1)/256, scope_gamma)*255); } for (x = 0; x <= 255; x++) { vectorscope_put_cross(255 , 0,255 - x, tgt, w, h, 1); vectorscope_put_cross(255 , x, 0, tgt, w, h, 1); vectorscope_put_cross(255- x, 255, 0, tgt, w, h, 1); vectorscope_put_cross(0, 255, x, tgt, w, h, 1); vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1); vectorscope_put_cross(x, 0, 255, tgt, w, h, 1); } for (y = 0; y < ibuf->y; y++) { for (x = 0; x < ibuf->x; x++) { float * src1 = src + 4 * (ibuf->x * y + x); char * p; memcpy(rgb, src1, 3 * sizeof(float)); CLAMP(rgb[0], 0.0f, 1.0f); CLAMP(rgb[1], 0.0f, 1.0f); CLAMP(rgb[2], 0.0f, 1.0f); rgb_to_yuv(rgb, yuv); p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1)) + (int) ((yuv[1] * (w - 3) + 1))); scope_put_pixel(wtable, (unsigned char*)p); } } vectorscope_put_cross(0, 0, 0, tgt, w, h, 3); return rval; }
static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos) { /* note: allocImbuf returns zero'd memory, so regions outside image will * have zero alpha, and hence not be blended onto the image */ int w = ibufb->x, h = ibufb->y, destx = 0, desty = 0, srcx = pos[0], srcy = pos[1]; ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags); IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h); IMB_rectblend(clonebuf, clonebuf, ibufb, NULL, NULL, 0, destx, desty, destx, desty, destx, desty, w, h, IMB_BLEND_COPY_ALPHA); IMB_rectblend(clonebuf, clonebuf, ibuf, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, w, h, IMB_BLEND_COPY_RGB); return clonebuf; }
static struct ImBuf *make_waveform_view_from_ibuf_float(struct ImBuf * ibuf) { struct ImBuf * rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect); int x,y; float* src = ibuf->rect_float; unsigned char* tgt = (unsigned char*) rval->rect; int w = ibuf->x + 3; int h = 515; float waveform_gamma = 0.2; unsigned char wtable[256]; wform_put_grid(tgt, w, h); for (x = 0; x < 256; x++) { wtable[x] = (unsigned char) (pow(((float) x + 1)/256, waveform_gamma)*255); } for (y = 0; y < ibuf->y; y++) { unsigned char * last_p = NULL; for (x = 0; x < ibuf->x; x++) { float * rgb = src + 4 * (ibuf->x * y + x); float v = 1.0f * ( 0.299f*rgb[0] + 0.587f*rgb[1] + 0.114f*rgb[2]); unsigned char * p = tgt; CLAMP(v, 0.0f, 1.0f); p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1); scope_put_pixel(wtable, p); p += 4 * w; scope_put_pixel(wtable, p); if (last_p != NULL) { wform_put_line(w, last_p, p); } last_p = p; } } wform_put_border(tgt, w, h); return rval; }
static ImBuf *avi_fetchibuf(struct anim *anim, int position) { ImBuf *ibuf = NULL; int *tmp; int y; if (anim == NULL) { return NULL; } #if defined(_WIN32) && !defined(FREE_WINDOWS) if (anim->avistreams) { LPBITMAPINFOHEADER lpbi; if (anim->pgf) { lpbi = AVIStreamGetFrame(anim->pgf, position + AVIStreamStart(anim->pavi[anim->firstvideo])); if (lpbi) { ibuf = IMB_ibImageFromMemory((unsigned char *) lpbi, 100, IB_rect, anim->colorspace, "<avi_fetchibuf>"); //Oh brother... } } } else #endif { ibuf = IMB_allocImBuf(anim->x, anim->y, 24, IB_rect); tmp = AVI_read_frame(anim->avi, AVI_FORMAT_RGB32, position, AVI_get_stream(anim->avi, AVIST_VIDEO, 0)); if (tmp == NULL) { printf("Error reading frame from AVI: '%s'\n", anim->name); IMB_freeImBuf(ibuf); return NULL; } for (y = 0; y < anim->y; y++) { memcpy(&(ibuf->rect)[((anim->y - y) - 1) * anim->x], &tmp[y * anim->x], anim->x * 4); } MEM_freeN(tmp); } ibuf->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace); return ibuf; }
static int screenshot_exec(bContext *C, wmOperator *op) { ScreenshotData *scd = op->customdata; bool ok = false; if (scd == NULL) { /* when running exec directly */ screenshot_data_create(C, op); scd = op->customdata; } if (scd) { if (scd->dumprect) { ImBuf *ibuf; char path[FILE_MAX]; RNA_string_get(op->ptr, "filepath", path); BLI_path_abs(path, BKE_main_blendfile_path_from_global()); /* operator ensures the extension */ ibuf = IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0); ibuf->rect = scd->dumprect; /* crop to show only single editor */ if (!RNA_boolean_get(op->ptr, "full")) { screenshot_crop(ibuf, scd->crop); } if (scd->im_format.planes == R_IMF_PLANES_BW) { /* bw screenshot? - users will notice if it fails! */ IMB_color_to_bw(ibuf); } if (BKE_imbuf_write(ibuf, path, &scd->im_format)) { ok = true; } else { BKE_reportf(op->reports, RPT_ERROR, "Could not write image: %s", strerror(errno)); } IMB_freeImBuf(ibuf); } } screenshot_data_free(op); return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; }
static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf) { ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect); int x, y; char *src = (char *) ibuf->rect; char *tgt = (char *) rval->rect; float rgb[3], yuv[3]; int w = 515; int h = 515; float scope_gamma = 0.2; unsigned char wtable[256]; for (x = 0; x < 256; x++) { wtable[x] = (unsigned char) (pow(((float) x + 1) / 256, scope_gamma) * 255); } for (x = 0; x <= 255; x++) { vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1); vectorscope_put_cross(255, x, 0, tgt, w, h, 1); vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1); vectorscope_put_cross(0, 255, x, tgt, w, h, 1); vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1); vectorscope_put_cross(x, 0, 255, tgt, w, h, 1); } for (y = 0; y < ibuf->y; y++) { for (x = 0; x < ibuf->x; x++) { char *src1 = src + 4 * (ibuf->x * y + x); char *p; rgb[0] = (float)src1[0] / 255.0f; rgb[1] = (float)src1[1] / 255.0f; rgb[2] = (float)src1[2] / 255.0f; rgb_to_yuv_normalized(rgb, yuv); p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1)) + (int) ((yuv[1] * (w - 3) + 1))); scope_put_pixel(wtable, (unsigned char *)p); } } vectorscope_put_cross(0, 0, 0, tgt, w, h, 3); return rval; }
ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int view_id) { ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0); RenderView *rv = RE_RenderViewGetById(rr, view_id); /* if not exists, BKE_imbuf_write makes one */ ibuf->rect = (unsigned int *) rv->rect32; ibuf->rect_float = rv->rectf; ibuf->zbuf_float = rv->rectz; /* float factor for random dither, imbuf takes care of it */ ibuf->dither = rd->dither_intensity; /* prepare to gamma correct to sRGB color space * note that sequence editor can generate 8bpc render buffers */ if (ibuf->rect) { if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) { if (rd->im_format.depth == R_IMF_CHAN_DEPTH_8) { /* Higher depth bits are supported but not needed for current file output. */ ibuf->rect_float = NULL; } else { IMB_float_from_rect(ibuf); } } else { /* ensure no float buffer remained from previous frame */ ibuf->rect_float = NULL; } } /* color -> grayscale */ /* editing directly would alter the render view */ if (rd->im_format.planes == R_IMF_PLANES_BW) { ImBuf *ibuf_bw = IMB_dupImBuf(ibuf); IMB_color_to_bw(ibuf_bw); IMB_freeImBuf(ibuf); ibuf = ibuf_bw; } return ibuf; }
static struct ImBuf *make_histogram_view_from_ibuf_byte( struct ImBuf * ibuf) { struct ImBuf * rval = IMB_allocImBuf(515, 128, 32, IB_rect); int c,x,y; unsigned int n; unsigned char* src = (unsigned char*) ibuf->rect; unsigned int bins[3][256]; memset(bins, 0, 3 * 256* sizeof(unsigned int)); for (y = 0; y < ibuf->y; y++) { for (x = 0; x < ibuf->x; x++) { bins[0][*src++]++; bins[1][*src++]++; bins[2][*src++]++; src++; } } n = 0; for (c = 0; c < 3; c++) { for (x = 0; x < 256; x++) { if (bins[c][x] > n) { n = bins[c][x]; } } } for (c = 0; c < 3; c++) { for (x = 0; x < 256; x++) { draw_histogram_bar(rval, x*2+1, ((float) bins[c][x])/n, c); draw_histogram_bar(rval, x*2+2, ((float) bins[c][x])/n, c); } } wform_put_border((unsigned char*) rval->rect, rval->x, rval->y); return rval; }
static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int use_cineon, int flags, char colorspace[IM_MAX_SPACE]) { ImBuf *ibuf; LogImageFile *image; int width, height, depth; colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0); image = logImageOpenFromMemory(mem, size); if (image == NULL) { printf("DPX/Cineon: error opening image.\n"); return NULL; } logImageGetSize(image, &width, &height, &depth); ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags); if (ibuf == NULL) { logImageClose(image); return NULL; } if (!(flags & IB_test)) { if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) { logImageClose(image); IMB_freeImBuf(ibuf); return NULL; } IMB_flipy(ibuf); } logImageClose(image); ibuf->ftype = use_cineon ? CINEON : DPX; if (flags & IB_alphamode_detect) ibuf->flags |= IB_alphamode_premul; return ibuf; }
static ImBuf *make_waveform_view_from_ibuf_byte(ImBuf *ibuf) { ImBuf *rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect); int x, y; unsigned char *src = (unsigned char *) ibuf->rect; unsigned char *tgt = (unsigned char *) rval->rect; int w = ibuf->x + 3; int h = 515; float waveform_gamma = 0.2; unsigned char wtable[256]; wform_put_grid(tgt, w, h); for (x = 0; x < 256; x++) { wtable[x] = (unsigned char) (pow(((float) x + 1) / 256, waveform_gamma) * 255); } for (y = 0; y < ibuf->y; y++) { unsigned char *last_p = NULL; for (x = 0; x < ibuf->x; x++) { unsigned char *rgb = src + 4 * (ibuf->x * y + x); float v = (float)rgb_to_luma_byte(rgb) / 255.0f; unsigned char *p = tgt; p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1); scope_put_pixel(wtable, p); p += 4 * w; scope_put_pixel(wtable, p); if (last_p != NULL) { wform_put_line(w, last_p, p); } last_p = p; } } wform_put_border(tgt, w, h); return rval; }
static int screenshot_exec(bContext *C, wmOperator *op) { ScreenshotData *scd= op->customdata; if(scd == NULL) { /* when running exec directly */ screenshot_data_create(C, op); scd= op->customdata; } if(scd) { if(scd->dumprect) { Scene *scene= CTX_data_scene(C); ImBuf *ibuf; char path[FILE_MAX]; RNA_string_get(op->ptr, "filepath", path); BLI_strncpy(G.ima, path, sizeof(G.ima)); BLI_path_abs(path, G.main->name); /* BKE_add_image_extension() checks for if extension was already set */ if(scene->r.scemode & R_EXTENSION) if(strlen(path)<FILE_MAX-5) BKE_add_image_extension(path, scene->r.im_format.imtype); ibuf= IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0); ibuf->rect= scd->dumprect; /* crop to show only single editor */ if(!RNA_boolean_get(op->ptr, "full")) screenshot_crop(ibuf, scd->crop); BKE_write_ibuf(ibuf, path, &scene->r.im_format); IMB_freeImBuf(ibuf); } } screenshot_data_free(op); return OPERATOR_FINISHED; }
static ImBuf * movie_fetchibuf(struct anim * anim, int position) { ImBuf * ibuf; /* extern rectcpy(); */ int size; unsigned int *rect1, *rect2; if (anim == 0) return (0); ibuf = IMB_allocImBuf(anim->x, anim->y, 24, IB_rect); if ( mvReadFrames(anim->track, position, 1, ibuf->x * ibuf->y * sizeof(int), ibuf->rect ) != DM_SUCCESS ) { movie_printerror("mvReadFrames"); IMB_freeImBuf(ibuf); return(0); } /* if (anim->interlacing == DM_IMAGE_INTERLACED_EVEN) { rect1 = ibuf->rect + (ibuf->x * ibuf->y) - 1; rect2 = rect1 - ibuf->x; for (size = ibuf->x * (ibuf->y - 1); size > 0; size--){ *rect1-- = *rect2--; } } */ if (anim->interlacing == DM_IMAGE_INTERLACED_EVEN) { rect1 = ibuf->rect; rect2 = rect1 + ibuf->x; for (size = ibuf->x * (ibuf->y - 1); size > 0; size--){ *rect1++ = *rect2++; } } /*if (anim->orientation == DM_TOP_TO_BOTTOM) IMB_flipy(ibuf);*/ return(ibuf); }
static struct ImBuf *make_histogram_view_from_ibuf_float( struct ImBuf * ibuf) { struct ImBuf * rval = IMB_allocImBuf(515, 128, 32, IB_rect); int n,c,x,y; float* src = ibuf->rect_float; unsigned int bins[3][512]; memset(bins, 0, 3 * 256* sizeof(unsigned int)); for (y = 0; y < ibuf->y; y++) { for (x = 0; x < ibuf->x; x++) { bins[0][get_bin_float(*src++)]++; bins[1][get_bin_float(*src++)]++; bins[2][get_bin_float(*src++)]++; src++; } } draw_histogram_marker(rval, get_bin_float(0.0)); draw_histogram_marker(rval, get_bin_float(1.0)); n = 0; for (c = 0; c < 3; c++) { for (x = 0; x < 512; x++) { if (bins[c][x] > n) { n = bins[c][x]; } } } for (c = 0; c < 3; c++) { for (x = 0; x < 512; x++) { draw_histogram_bar(rval, x+1, (float) bins[c][x]/n, c); } } wform_put_border((unsigned char*) rval->rect, rval->x, rval->y); return rval; }
static int screenshot_exec(bContext *C, wmOperator *op) { ScreenshotData *scd = op->customdata; if (scd == NULL) { /* when running exec directly */ screenshot_data_create(C, op); scd = op->customdata; } if (scd) { if (scd->dumprect) { ImBuf *ibuf; char path[FILE_MAX]; RNA_string_get(op->ptr, "filepath", path); BLI_path_abs(path, G.main->name); /* operator ensures the extension */ ibuf = IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0); ibuf->rect = scd->dumprect; /* crop to show only single editor */ if (!RNA_boolean_get(op->ptr, "full")) screenshot_crop(ibuf, scd->crop); if (scd->im_format.planes == R_IMF_PLANES_BW) { /* bw screenshot? - users will notice if it fails! */ IMB_color_to_bw(ibuf); } BKE_imbuf_write(ibuf, path, &scd->im_format); IMB_freeImBuf(ibuf); } } screenshot_data_free(op); return OPERATOR_FINISHED; }
void GPC_Canvas:: MakeScreenShot( const char* filename ) { // copy image data unsigned char *pixels = new unsigned char[GetWidth() * GetHeight() * 4]; if (!pixels) { std::cout << "Cannot allocate pixels array" << std::endl; return; } glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, pixels); // initialize image file format data ImageFormatData im_format; BKE_imformat_defaults(&im_format); // create file path char path[FILE_MAX]; BLI_strncpy(path, filename, sizeof(path)); BLI_path_abs(path, G.main->name); BLI_path_frame(path, m_frame, 0); m_frame++; BKE_image_path_ensure_ext_from_imtype(path, im_format.imtype); // create and save imbuf ImBuf *ibuf = IMB_allocImBuf(GetWidth(), GetHeight(), 24, 0); ibuf->rect = (unsigned int*)pixels; BKE_imbuf_write_as(ibuf, path, &im_format, false); ibuf->rect = NULL; IMB_freeImBuf(ibuf); // clean up delete [] (pixels); }
struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect, const float *rectf, unsigned int w, unsigned int h) { ImBuf *ibuf = NULL; if (!(rect || rectf)) return NULL; ibuf = IMB_allocImBuf(w, h, 32, 0); if (rectf) { ibuf->rect_float = MEM_dupallocN(rectf); ibuf->flags |= IB_rectfloat; ibuf->mall |= IB_rectfloat; } if (rect) { ibuf->rect = MEM_dupallocN(rect); ibuf->flags |= IB_rect; ibuf->mall |= IB_rect; } return ibuf; }
static void imb_stereo3d_squeeze_rect(int *rect, 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_rect); IMB_buffer_byte_from_byte( (unsigned char *)ibuf->rect, (unsigned char *)rect, IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, width, height, width, width); IMB_scaleImBuf_threaded(ibuf, x, y); memcpy(rect, ibuf->rect, x * y * sizeof(unsigned int)); 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; }
/* does no zbuffers? */ ImBuf *IMB_dupImBuf(ImBuf *ibuf1) { ImBuf *ibuf2, tbuf; int flags = 0; int a, x, y; if (ibuf1 == NULL) return NULL; if (ibuf1->rect) flags |= IB_rect; if (ibuf1->rect_float) flags |= IB_rectfloat; x = ibuf1->x; y = ibuf1->y; if (ibuf1->flags & IB_fields) y *= 2; ibuf2 = IMB_allocImBuf(x, y, ibuf1->planes, flags); if (ibuf2 == NULL) return NULL; if (flags & IB_rect) memcpy(ibuf2->rect, ibuf1->rect, x * y * sizeof(int)); if (flags & IB_rectfloat) memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels * x * y * sizeof(float)); if (ibuf1->encodedbuffer) { ibuf2->encodedbuffersize = ibuf1->encodedbuffersize; if (imb_addencodedbufferImBuf(ibuf2) == false) { IMB_freeImBuf(ibuf2); return NULL; } memcpy(ibuf2->encodedbuffer, ibuf1->encodedbuffer, ibuf1->encodedsize); } /* silly trick to copy the entire contents of ibuf1 struct over to ibuf */ tbuf = *ibuf1; /* fix pointers */ tbuf.rect = ibuf2->rect; tbuf.rect_float = ibuf2->rect_float; tbuf.encodedbuffer = ibuf2->encodedbuffer; tbuf.zbuf = NULL; tbuf.zbuf_float = NULL; for (a = 0; a < IB_MIPMAP_LEVELS; a++) tbuf.mipmap[a] = NULL; tbuf.dds_data.data = NULL; /* set malloc flag */ tbuf.mall = ibuf2->mall; tbuf.c_handle = NULL; tbuf.refcounter = 0; /* for now don't duplicate metadata */ tbuf.metadata = NULL; tbuf.display_buffer_flags = NULL; tbuf.colormanage_cache = NULL; *ibuf2 = tbuf; return(ibuf2); }
struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags) { struct ImBuf * ibuf = 0; DirectDrawSurface dds(mem, size); /* reads header */ unsigned char bits_per_pixel; unsigned int *rect; Image img; unsigned int numpixels = 0; int col; unsigned char *cp = (unsigned char *) &col; Color32 pixel; Color32 *pixels = 0; if(!imb_is_a_dds(mem)) return (0); /* check if DDS is valid and supported */ if (!dds.isValid()) { /* no need to print error here, just testing if it is a DDS */ if(flags & IB_test) return (0); printf("DDS: not valid; header follows\n"); dds.printInfo(); return(0); } if (!dds.isSupported()) { printf("DDS: format not supported\n"); return(0); } if ((dds.width() > 65535) || (dds.height() > 65535)) { printf("DDS: dimensions too large\n"); return(0); } /* convert DDS into ImBuf */ // TODO use the image RGB or RGBA tag to determine the bits per pixel if (dds.hasAlpha()) bits_per_pixel = 32; else bits_per_pixel = 24; ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0); if (ibuf == 0) return(0); /* memory allocation failed */ ibuf->ftype = DDS; ibuf->profile = IB_PROFILE_SRGB; if ((flags & IB_test) == 0) { if (!imb_addrectImBuf(ibuf)) return(ibuf); if (ibuf->rect == 0) return(ibuf); rect = ibuf->rect; dds.mipmap(&img, 0, 0); /* load first face, first mipmap */ pixels = img.pixels(); numpixels = dds.width() * dds.height(); cp[3] = 0xff; /* default alpha if alpha channel is not present */ for (unsigned int i = 0; i < numpixels; i++) { pixel = pixels[i]; cp[0] = pixel.r; /* set R component of col */ cp[1] = pixel.g; /* set G component of col */ cp[2] = pixel.b; /* set B component of col */ if (bits_per_pixel == 32) cp[3] = pixel.a; /* set A component of col */ rect[i] = col; } IMB_flipy(ibuf); } return(ibuf); }
ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { 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; int i, bytesperpixel; if (imb_is_a_png(mem) == 0) return(NULL); /* both 8 and 16 bit PNGs are default to standard byte colorspace */ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); 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->ftype |= PNG_16BIT; 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--) { to_float[0] = from16[0] / 65535.0; to_float[1] = from16[1] / 65535.0; to_float[2] = from16[2] / 65535.0; to_float[3] = from16[3] / 65535.0; to_float += 4; from16 += 4; } break; case 3: for (i = ibuf->x * ibuf->y; i > 0; i--) { to_float[0] = from16[0] / 65535.0; to_float[1] = from16[1] / 65535.0; to_float[2] = from16[2] / 65535.0; to_float[3] = 1.0; to_float += 4; from16 += 3; } break; case 2: for (i = ibuf->x * ibuf->y; i > 0; i--) { to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0; to_float[3] = from16[1] / 65535.0; to_float += 4; from16 += 2; } break; case 1: for (i = ibuf->x * ibuf->y; i > 0; i--) { to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0; to_float[3] = 1.0; 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); if (row_pointers) MEM_freeN(row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return(ibuf); }
static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *maskb, const float lastpos[2], const float pos[2]) { ImagePaintState *s = ((ImagePaintState *)state); ImBuf *clonebuf = NULL, *frombuf, *tmpbuf = NULL; ImagePaintRegion region[4]; short torus = s->brush->flag & BRUSH_TORUS; short blend = s->blend; float *offset = s->brush->clone.offset; float liftpos[2]; float brush_alpha = BKE_brush_alpha_get(s->scene, s->brush); unsigned short mask_max = (unsigned short)(brush_alpha * 65535.0f); int bpos[2], blastpos[2], bliftpos[2]; int a, tot; paint_2d_convert_brushco(ibufb, pos, bpos); /* lift from canvas */ if (s->tool == PAINT_TOOL_SOFTEN) { paint_2d_lift_soften(s->canvas, ibufb, bpos, torus); } else if (s->tool == PAINT_TOOL_SMEAR) { if (lastpos[0] == pos[0] && lastpos[1] == pos[1]) return 0; paint_2d_convert_brushco(ibufb, lastpos, blastpos); paint_2d_lift_smear(s->canvas, ibufb, blastpos); } else if (s->tool == PAINT_TOOL_CLONE && s->clonecanvas) { liftpos[0] = pos[0] - offset[0] * s->canvas->x; liftpos[1] = pos[1] - offset[1] * s->canvas->y; paint_2d_convert_brushco(ibufb, liftpos, bliftpos); clonebuf = paint_2d_lift_clone(s->clonecanvas, ibufb, bliftpos); } frombuf = (clonebuf) ? clonebuf : ibufb; if (torus) { paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y); tot = paint_2d_torus_split_region(region, s->canvas, frombuf); } else { paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y); tot = 1; } if (s->do_masking) tmpbuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, 0); /* blend into canvas */ for (a = 0; a < tot; a++) { ED_imapaint_dirty_region(s->image, s->canvas, region[a].destx, region[a].desty, region[a].width, region[a].height); if (s->do_masking) { /* masking, find original pixels tiles from undo buffer to composite over */ int tilex, tiley, tilew, tileh, tx, ty; imapaint_region_tiles(s->canvas, region[a].destx, region[a].desty, region[a].width, region[a].height, &tilex, &tiley, &tilew, &tileh); for (ty = tiley; ty <= tileh; ty++) { for (tx = tilex; tx <= tilew; tx++) { /* retrieve original pixels + mask from undo buffer */ unsigned short *mask; int origx = region[a].destx - tx * IMAPAINT_TILE_SIZE; int origy = region[a].desty - ty * IMAPAINT_TILE_SIZE; if (s->canvas->rect_float) tmpbuf->rect_float = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask); else tmpbuf->rect = image_undo_find_tile(s->image, s->canvas, tx, ty, &mask); IMB_rectblend(s->canvas, tmpbuf, frombuf, mask, maskb, mask_max, region[a].destx, region[a].desty, origx, origy, region[a].srcx, region[a].srcy, region[a].width, region[a].height, blend); } } } else { /* no masking, composite brush directly onto canvas */ IMB_rectblend(s->canvas, s->canvas, frombuf, NULL, NULL, 0, region[a].destx, region[a].desty, region[a].destx, region[a].desty, region[a].srcx, region[a].srcy, region[a].width, region[a].height, blend); } } if (clonebuf) IMB_freeImBuf(clonebuf); if (tmpbuf) IMB_freeImBuf(tmpbuf); return 1; }
/* create imbuf with brush color */ static ImBuf *brush_painter_imbuf_new(BrushPainter *painter, int size) { Scene *scene = painter->scene; Brush *brush = painter->brush; rctf tex_mapping = painter->tex_mapping; rctf mask_mapping = painter->mask_mapping; struct ImagePool *pool = painter->pool; bool use_masking = painter->cache.use_masking; bool use_color_correction = painter->cache.use_color_correction; bool use_float = painter->cache.use_float; bool is_texbrush = painter->cache.is_texbrush; bool is_maskbrush = painter->cache.is_maskbrush; float alpha = (use_masking) ? 1.0f : BKE_brush_alpha_get(scene, brush); int radius = BKE_brush_size_get(scene, brush); int xoff = -size * 0.5f + 0.5f; int yoff = -size * 0.5f + 0.5f; int x, y, thread = 0; float brush_rgb[3]; /* allocate image buffer */ ImBuf *ibuf = IMB_allocImBuf(size, size, 32, (use_float) ? IB_rectfloat : IB_rect); /* get brush color */ if (brush->imagepaint_tool == PAINT_TOOL_DRAW) { copy_v3_v3(brush_rgb, brush->rgb); if (use_color_correction) srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb); } else { brush_rgb[0] = 1.0f; brush_rgb[1] = 1.0f; brush_rgb[2] = 1.0f; } /* fill image buffer */ for (y = 0; y < size; y++) { for (x = 0; x < size; x++) { /* sample texture and multiply with brush color */ float texco[3], rgba[4]; if (is_texbrush) { brush_imbuf_tex_co(&tex_mapping, x, y, texco); BKE_brush_sample_tex_3D(scene, brush, texco, rgba, thread, pool); /* TODO(sergey): Support texture paint color space. */ if (!use_float) { linearrgb_to_srgb_v3_v3(rgba, rgba); } mul_v3_v3(rgba, brush_rgb); } else { copy_v3_v3(rgba, brush_rgb); rgba[3] = 1.0f; } if (is_maskbrush) { brush_imbuf_tex_co(&mask_mapping, x, y, texco); rgba[3] *= BKE_brush_sample_masktex(scene, brush, texco, thread, pool); } /* when not using masking, multiply in falloff and strength */ if (!use_masking) { float xy[2] = {x + xoff, y + yoff}; float len = len_v2(xy); rgba[3] *= alpha * BKE_brush_curve_strength_clamp(brush, len, radius); } if (use_float) { /* write to float pixel */ float *dstf = ibuf->rect_float + (y * size + x) * 4; mul_v3_v3fl(dstf, rgba, rgba[3]); /* premultiply */ dstf[3] = rgba[3]; } else { /* write to byte pixel */ unsigned char *dst = (unsigned char *)ibuf->rect + (y * size + x) * 4; rgb_float_to_uchar(dst, rgba); dst[3] = FTOCHAR(rgba[3]); } } } return ibuf; }
struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags) { struct ImBuf* ibuf; RGBE* sline; fCOLOR fcol; float* rect_float; int found=0; int width=0, height=0; int x, y; unsigned char* ptr; char oriY[80], oriX[80]; if (imb_is_a_hdr((void*)mem)) { /* find empty line, next line is resolution info */ for (x=1;x<size;x++) { if ((mem[x-1]=='\n') && (mem[x]=='\n')) { found = 1; break; } } if (found && (x<(size + 2))) { if (sscanf((char *)&mem[x+1], "%79s %d %79s %d", (char*)&oriY, &height, (char*)&oriX, &width) != 4) return NULL; /* find end of this line, data right behind it */ ptr = (unsigned char *)strchr((char*)&mem[x+1], '\n'); ptr++; if (flags & IB_test) ibuf = IMB_allocImBuf(width, height, 32, 0); else ibuf = IMB_allocImBuf(width, height, 32, (flags & IB_rect)|IB_rectfloat); if (ibuf==NULL) return NULL; ibuf->ftype = RADHDR; ibuf->profile = IB_PROFILE_LINEAR_RGB; if (flags & IB_test) return ibuf; /* read in and decode the actual data */ sline = (RGBE*)MEM_mallocN(sizeof(RGBE)*width, "radhdr_read_tmpscan"); rect_float = (float *)ibuf->rect_float; for (y=0;y<height;y++) { ptr = freadcolrs(sline, ptr, width); if (ptr==NULL) { printf("HDR decode error\n"); MEM_freeN(sline); return ibuf; } for (x=0;x<width;x++) { /* convert to ldr */ RGBE2FLOAT(sline[x], fcol); *rect_float++ = fcol[RED]; *rect_float++ = fcol[GRN]; *rect_float++ = fcol[BLU]; *rect_float++ = 1.0f; } } MEM_freeN(sline); if (oriY[0]=='-') IMB_flipy(ibuf); if (flags & IB_rect) { IMB_rect_from_float(ibuf); } return ibuf; } //else printf("Data not found!\n"); } //else printf("Not a valid radiance HDR file!\n"); return NULL; }
struct ImBuf *imb_loadpng(unsigned char *mem, int size, int flags) { struct ImBuf *ibuf = 0; png_structp png_ptr; png_infop info_ptr; unsigned char *pixels = 0; png_bytepp row_pointers = 0; png_uint_32 width, height; int bit_depth, color_type; PNGReadStruct ps; unsigned char *from, *to; int i, bytesperpixel; if (imb_is_a_png(mem) == 0) return(0); 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 0; } 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 0; } ps.size = size; 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 (row_pointers) MEM_freeN(row_pointers); if (ibuf) IMB_freeImBuf(ibuf); return 0; } // 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); if (bit_depth == 16) { png_set_strip_16(png_ptr); bit_depth = 8; } 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, 0); if (ibuf) { ibuf->ftype = PNG; } else { printf("Couldn't allocate memory for PNG image\n"); } if (ibuf && ((flags & IB_test) == 0)) { 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_imginfo) { png_text* text_chunks; int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL); for(i = 0; i < count; i++) { IMB_imginfo_add_field(ibuf, text_chunks[i].key, text_chunks[i].text); ibuf->flags |= IB_imginfo; } } png_read_end(png_ptr, info_ptr); } // clean up MEM_freeN(pixels); MEM_freeN(row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return(ibuf); }