void MultilayerColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { if (this->m_imageFloatBuffer == NULL) { zero_v4(output); } else { if (this->m_numberOfChannels == 4) { switch (sampler) { case COM_PS_NEAREST: nearest_interpolation_color(this->m_buffer, NULL, output, x, y); break; case COM_PS_BILINEAR: bilinear_interpolation_color(this->m_buffer, NULL, output, x, y); break; case COM_PS_BICUBIC: bicubic_interpolation_color(this->m_buffer, NULL, output, x, y); break; } } else { int yi = y; int xi = x; if (xi < 0 || yi < 0 || (unsigned int)xi >= this->getWidth() || (unsigned int)yi >= this->getHeight()) zero_v4(output); else { int offset = (yi * this->getWidth() + xi) * 3; copy_v3_v3(output, &this->m_imageFloatBuffer[offset]); } } } }
void MovieClipBaseOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { ImBuf *ibuf = this->m_movieClipBuffer; if (ibuf == NULL || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) { zero_v4(output); } else if (ibuf->rect == NULL && ibuf->rect_float == NULL) { /* Happens for multilayer exr, i.e. */ zero_v4(output); } else { switch (sampler) { case COM_PS_NEAREST: nearest_interpolation_color(ibuf, NULL, output, x, y); break; case COM_PS_BILINEAR: bilinear_interpolation_color(ibuf, NULL, output, x, y); break; case COM_PS_BICUBIC: bicubic_interpolation_color(ibuf, NULL, output, x, y); break; } } }
void ImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { int ix = x, iy = y; if (this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) { zero_v4(output); } else if (ix < 0 || iy < 0 || ix >= this->m_buffer->x || iy >= this->m_buffer->y) { zero_v4(output); } else { sampleImageAtLocation(this->m_buffer, x, y, sampler, true, output); } }
void RenderLayersBaseProg::executePixel(float output[4], float x, float y, PixelSampler sampler) { #if 0 const RenderData *rd = this->m_rd; int dx = 0, dy = 0; if (rd->mode & R_BORDER && rd->mode & R_CROP) { /* see comment in executeRegion describing coordinate mapping, * here it simply goes other way around */ int full_width = rd->xsch * rd->size / 100; int full_height = rd->ysch * rd->size / 100; dx = rd->border.xmin * full_width - (full_width - this->getWidth()) / 2.0f; dy = rd->border.ymin * full_height - (full_height - this->getHeight()) / 2.0f; } int ix = x - dx; int iy = y - dy; #else int ix = x; int iy = y; #endif if (this->m_inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) { zero_v4(output); } else { doInterpolation(output, ix, iy, sampler); } }
static void node_composit_exec_dilateerode(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { /* stack order in: mask */ /* stack order out: mask */ if (out[0]->hasoutput == 0) return; /* input no image? then only color operation */ if (in[0]->data == NULL) { zero_v4(out[0]->vec); } else { /* make output size of input image */ CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_VAL); CompBuf *stackbuf = dupalloc_compbuf(cbuf); short i; if (node->custom2 > 0) { // positive, dilate for (i = 0; i < node->custom2; i++) morpho_dilate(stackbuf); } else if (node->custom2 < 0) { // negative, erode for (i = 0; i > node->custom2; i--) morpho_erode(stackbuf); } if (cbuf != in[0]->data) free_compbuf(cbuf); out[0]->data = stackbuf; } }
CBData *BKE_colorband_element_add(struct ColorBand *coba, float position) { if (coba->tot == MAXCOLORBAND) { return NULL; } else { CBData *xnew; xnew = &coba->data[coba->tot]; xnew->pos = position; if (coba->tot != 0) { BKE_colorband_evaluate(coba, position, &xnew->r); } else { zero_v4(&xnew->r); } } coba->tot++; coba->cur = coba->tot - 1; BKE_colorband_update_sort(coba); return coba->data + coba->cur; }
void ScreenLensDistortionOperation::executePixel(float output[4], int x, int y, void *data) { MemoryBuffer *buffer = (MemoryBuffer *)data; float xy[2] = { (float)x, (float)y }; float uv[2]; get_uv(xy, uv); float uv_dot = len_squared_v2(uv); int count[3] = { 0, 0, 0 }; float delta[3][2]; float sum[4] = { 0, 0, 0, 0 }; bool valid_r = get_delta(uv_dot, m_k4[0], uv, delta[0]); bool valid_g = get_delta(uv_dot, m_k4[1], uv, delta[1]); bool valid_b = get_delta(uv_dot, m_k4[2], uv, delta[2]); if (valid_r && valid_g && valid_b) { accumulate(buffer, 0, 1, uv_dot, uv, delta, sum, count); accumulate(buffer, 1, 2, uv_dot, uv, delta, sum, count); if (count[0]) output[0] = 2.0f * sum[0] / (float)count[0]; if (count[1]) output[1] = 2.0f * sum[1] / (float)count[1]; if (count[2]) output[2] = 2.0f * sum[2] / (float)count[2]; /* set alpha */ output[3] = 1.0f; } else { zero_v4(output); } }
void BokehBlurOperation::executePixel(float output[4], int x, int y, void *data) { float color_accum[4]; float tempBoundingBox[4]; float bokeh[4]; this->m_inputBoundingBoxReader->readSampled(tempBoundingBox, x, y, COM_PS_NEAREST); if (tempBoundingBox[0] > 0.0f) { float multiplier_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; MemoryBuffer *inputBuffer = (MemoryBuffer *)data; float *buffer = inputBuffer->getBuffer(); int bufferwidth = inputBuffer->getWidth(); int bufferstartx = inputBuffer->getRect()->xmin; int bufferstarty = inputBuffer->getRect()->ymin; const float max_dim = max(this->getWidth(), this->getHeight()); int pixelSize = this->m_size * max_dim / 100.0f; zero_v4(color_accum); if (pixelSize < 2) { this->m_inputProgram->readSampled(color_accum, x, y, COM_PS_NEAREST); multiplier_accum[0] = 1.0f; multiplier_accum[1] = 1.0f; multiplier_accum[2] = 1.0f; multiplier_accum[3] = 1.0f; } int miny = y - pixelSize; int maxy = y + pixelSize; int minx = x - pixelSize; int maxx = x + pixelSize; miny = max(miny, inputBuffer->getRect()->ymin); minx = max(minx, inputBuffer->getRect()->xmin); maxy = min(maxy, inputBuffer->getRect()->ymax); maxx = min(maxx, inputBuffer->getRect()->xmax); int step = getStep(); int offsetadd = getOffsetAdd() * COM_NUM_CHANNELS_COLOR; float m = this->m_bokehDimension / pixelSize; for (int ny = miny; ny < maxy; ny += step) { int bufferindex = ((minx - bufferstartx) * COM_NUM_CHANNELS_COLOR) + ((ny - bufferstarty) * COM_NUM_CHANNELS_COLOR * bufferwidth); for (int nx = minx; nx < maxx; nx += step) { float u = this->m_bokehMidX - (nx - x) * m; float v = this->m_bokehMidY - (ny - y) * m; this->m_inputBokehProgram->readSampled(bokeh, u, v, COM_PS_NEAREST); madd_v4_v4v4(color_accum, bokeh, &buffer[bufferindex]); add_v4_v4(multiplier_accum, bokeh); bufferindex += offsetadd; } } output[0] = color_accum[0] * (1.0f / multiplier_accum[0]); output[1] = color_accum[1] * (1.0f / multiplier_accum[1]); output[2] = color_accum[2] * (1.0f / multiplier_accum[2]); output[3] = color_accum[3] * (1.0f / multiplier_accum[3]); } else { this->m_inputProgram->readSampled(output, x, y, COM_PS_NEAREST); } }
void CropImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) { this->m_inputOperation->readSampled(output, (x + this->m_xmin), (y + this->m_ymin), sampler); } else { zero_v4(output); } }
void ImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { if ((this->m_imageFloatBuffer == NULL && this->m_imageByteBuffer == NULL) || x < 0 || y < 0 || x >= this->getWidth() || y >= this->getHeight() ) { zero_v4(output); } else { sampleImageAtLocation(this->m_buffer, x, y, sampler, true, output); } }
void CropOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { if ((x < this->m_xmax && x >= this->m_xmin) && (y < this->m_ymax && y >= this->m_ymin)) { this->m_inputOperation->readSampled(output, x, y, sampler); } else { zero_v4(output); } }
static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, int p) { ParticleThreadContext *ctx= thread->ctx; MFace *mface; mface = ctx->dm->getTessFaceDataArray(ctx->dm, CD_MFACE); int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ /* TODO_PARTICLE - use original index */ pa->num = ctx->index[p]; zero_v4(pa->fuv); if (pa->num != DMCACHE_NOTFOUND && pa->num < ctx->dm->getNumVerts(ctx->dm)) { /* This finds the first face to contain the emitting vertex, * this is not ideal, but is mostly fine as UV seams generally * map to equal-colored parts of a texture */ for (int i = 0; i < ctx->dm->getNumTessFaces(ctx->dm); i++, mface++) { if (ELEM(pa->num, mface->v1, mface->v2, mface->v3, mface->v4)) { unsigned int *vert = &mface->v1; for (int j = 0; j < 4; j++, vert++) { if (*vert == pa->num) { pa->fuv[j] = 1.0f; break; } } break; } } } #if ONLY_WORKING_WITH_PA_VERTS if (ctx->tree) { KDTreeNearest ptn[3]; int w, maxw; psys_particle_on_dm(ctx->dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0); BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1); maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3); for (w=0; w<maxw; w++) { pa->verts[w]=ptn->num; } } #endif if (rng_skip_tot > 0) /* should never be below zero */ BLI_rng_skip(thread->rng, rng_skip_tot); }
void ConvolutionFilterOperation::executePixel(float output[4], int x, int y, void * /*data*/) { float in1[4]; float in2[4]; int x1 = x - 1; int x2 = x; int x3 = x + 1; int y1 = y - 1; int y2 = y; int y3 = y + 1; CLAMP(x1, 0, getWidth() - 1); CLAMP(x2, 0, getWidth() - 1); CLAMP(x3, 0, getWidth() - 1); CLAMP(y1, 0, getHeight() - 1); CLAMP(y2, 0, getHeight() - 1); CLAMP(y3, 0, getHeight() - 1); float value[4]; this->m_inputValueOperation->read(value, x2, y2, NULL); const float mval = 1.0f - value[0]; zero_v4(output); this->m_inputOperation->read(in1, x1, y1, NULL); madd_v4_v4fl(output, in1, this->m_filter[0]); this->m_inputOperation->read(in1, x2, y1, NULL); madd_v4_v4fl(output, in1, this->m_filter[1]); this->m_inputOperation->read(in1, x3, y1, NULL); madd_v4_v4fl(output, in1, this->m_filter[2]); this->m_inputOperation->read(in1, x1, y2, NULL); madd_v4_v4fl(output, in1, this->m_filter[3]); this->m_inputOperation->read(in2, x2, y2, NULL); madd_v4_v4fl(output, in2, this->m_filter[4]); this->m_inputOperation->read(in1, x3, y2, NULL); madd_v4_v4fl(output, in1, this->m_filter[5]); this->m_inputOperation->read(in1, x1, y3, NULL); madd_v4_v4fl(output, in1, this->m_filter[6]); this->m_inputOperation->read(in1, x2, y3, NULL); madd_v4_v4fl(output, in1, this->m_filter[7]); this->m_inputOperation->read(in1, x3, y3, NULL); madd_v4_v4fl(output, in1, this->m_filter[8]); output[0] = output[0] * value[0] + in2[0] * mval; output[1] = output[1] * value[0] + in2[1] * mval; output[2] = output[2] * value[0] + in2[2] * mval; output[3] = output[3] * value[0] + in2[3] * mval; /* Make sure we don't return negative color. */ output[0] = max(output[0], 0.0f); output[1] = max(output[1], 0.0f); output[2] = max(output[2], 0.0f); output[3] = max(output[3], 0.0f); }
static void move_stack(bNodeStack *to, bNodeStack *from) { if (to != from) { copy_v4_v4(to->vec, from->vec); to->data = from->data; to->datatype = from->datatype; to->is_copy = from->is_copy; zero_v4(from->vec); from->data = NULL; from->datatype = 0; from->is_copy = 0; } }
void RenderLayersProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler) { unsigned int offset; int width = this->getWidth(), height = this->getHeight(); int ix = x, iy = y; if (ix < 0 || iy < 0 || ix >= width || iy >= height) { if (this->m_elementsize == 1) { output[0] = 0.0f; } else if (this->m_elementsize == 3) { zero_v3(output); } else { zero_v4(output); } return; } switch (sampler) { case COM_PS_NEAREST: { offset = (iy * width + ix) * this->m_elementsize; if (this->m_elementsize == 1) { output[0] = this->m_inputBuffer[offset]; } else if (this->m_elementsize == 3) { copy_v3_v3(output, &this->m_inputBuffer[offset]); } else { copy_v4_v4(output, &this->m_inputBuffer[offset]); } break; } case COM_PS_BILINEAR: BLI_bilinear_interpolation_fl( this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); break; case COM_PS_BICUBIC: BLI_bicubic_interpolation_fl( this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); break; } }
static GPUTexture *create_flame_spectrum_texture(void) { #define SPEC_WIDTH 256 #define FIRE_THRESH 7 #define MAX_FIRE_ALPHA 0.06f #define FULL_ON_FIRE 100 GPUTexture *tex; int i, j, k; float *spec_data = MEM_mallocN(SPEC_WIDTH * 4 * sizeof(float), "spec_data"); float *spec_pixels = MEM_mallocN(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels"); blackbody_temperature_to_rgb_table(spec_data, SPEC_WIDTH, 1500, 3000); for (i = 0; i < 16; i++) { for (j = 0; j < 16; j++) { for (k = 0; k < SPEC_WIDTH; k++) { int index = (j * SPEC_WIDTH * 16 + i * SPEC_WIDTH + k) * 4; if (k >= FIRE_THRESH) { spec_pixels[index] = (spec_data[k * 4]); spec_pixels[index + 1] = (spec_data[k * 4 + 1]); spec_pixels[index + 2] = (spec_data[k * 4 + 2]); spec_pixels[index + 3] = MAX_FIRE_ALPHA * ( (k > FULL_ON_FIRE) ? 1.0f : (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH)); } else { zero_v4(&spec_pixels[index]); } } } } tex = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL); MEM_freeN(spec_data); MEM_freeN(spec_pixels); #undef SPEC_WIDTH #undef FIRE_THRESH #undef MAX_FIRE_ALPHA #undef FULL_ON_FIRE return tex; }
void NodeOperationBuilder::add_input_constant_value(NodeOperationInput *input, NodeInput *node_input) { switch (input->getDataType()) { case COM_DT_VALUE: { float value; if (node_input && node_input->getbNodeSocket()) value = node_input->getEditorValueFloat(); else value = 0.0f; SetValueOperation *op = new SetValueOperation(); op->setValue(value); addOperation(op); addLink(op->getOutputSocket(), input); break; } case COM_DT_COLOR: { float value[4]; if (node_input && node_input->getbNodeSocket()) node_input->getEditorValueColor(value); else zero_v4(value); SetColorOperation *op = new SetColorOperation(); op->setChannels(value); addOperation(op); addLink(op->getOutputSocket(), input); break; } case COM_DT_VECTOR: { float value[3]; if (node_input && node_input->getbNodeSocket()) node_input->getEditorValueVector(value); else zero_v3(value); SetVectorOperation *op = new SetVectorOperation(); op->setVector(value); addOperation(op); addLink(op->getOutputSocket(), input); break; } } }
void PlaneDistortWarpImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { float uv[2]; float deriv[2][2]; if (this->m_motion_blur_samples == 1) { warpCoord(x, y, this->m_samples[0].perspectiveMatrix, uv, deriv); m_pixelReader->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1]); } else { zero_v4(output); for (int sample = 0; sample < this->m_motion_blur_samples; ++sample) { float color[4]; warpCoord(x, y, this->m_samples[sample].perspectiveMatrix, uv, deriv); m_pixelReader->readFiltered(color, uv[0], uv[1], deriv[0], deriv[1]); add_v4_v4(output, color); } mul_v4_fl(output, 1.0f / (float)this->m_motion_blur_samples); } }
void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool) { TexResult texres; ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, NULL, pool); if (UNLIKELY(ibuf == NULL)) { zero_v4(result); return; } if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) ibuf->rect+= (ibuf->x*ibuf->y); texres.talpha = true; /* boxsample expects to be initialized */ boxsample(ibuf, fx, fy, fx + dx, fy + dy, &texres, 0, 1); copy_v4_v4(result, &texres.tr); if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) ibuf->rect-= (ibuf->x*ibuf->y); ima->flag|= IMA_USED_FOR_RENDER; BKE_image_pool_release_ibuf(ima, ibuf, pool); }
/* BICUBIC INTERPOLATION */ BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, const float *float_buffer, unsigned char *byte_output, float *float_output, int width, int height, int components, float u, float v) { int i, j, n, m, x1, y1; float a, b, w, wx, wy[4], out[4]; /* sample area entirely outside image? */ if (ceil(u) < 0 || floor(u) > width - 1 || ceil(v) < 0 || floor(v) > height - 1) { if (float_output) float_output[0] = float_output[1] = float_output[2] = float_output[3] = 0.0f; if (byte_output) byte_output[0] = byte_output[1] = byte_output[2] = byte_output[3] = 0; return; } i = (int)floor(u); j = (int)floor(v); a = u - (float)i; b = v - (float)j; zero_v4(out); /* Optimized and not so easy to read */ /* avoid calling multiple times */ wy[0] = P(b - (-1)); wy[1] = P(b - 0); wy[2] = P(b - 1); wy[3] = P(b - 2); for (n = -1; n <= 2; n++) { x1 = i + n; CLAMP(x1, 0, width - 1); wx = P((float)n - a); for (m = -1; m <= 2; m++) { float data[4]; y1 = j + m; CLAMP(y1, 0, height - 1); /* normally we could do this */ /* w = P(n-a) * P(b-m); */ /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */ w = wx * wy[m + 1]; if (float_output) { const float *float_data = float_buffer + width * y1 * components + components * x1; vector_from_float(float_data, data, components); } else { const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; vector_from_byte(byte_data, data, components); } if (components == 1) { out[0] += data[0] * w; } else if (components == 3) { out[0] += data[0] * w; out[1] += data[1] * w; out[2] += data[2] * w; } else { out[0] += data[0] * w; out[1] += data[1] * w; out[2] += data[2] * w; out[3] += data[3] * w; } } } /* Done with optimized part */ #if 0 /* older, slower function, works the same as above */ for (n = -1; n <= 2; n++) { for (m = -1; m <= 2; m++) { x1 = i + n; y1 = j + m; if (x1 > 0 && x1 < width && y1 > 0 && y1 < height) { float data[4]; if (float_output) { const float *float_data = float_buffer + width * y1 * components + components * x1; vector_from_float(float_data, data, components); } else { const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; vector_from_byte(byte_data, data, components); } if (components == 1) { out[0] += data[0] * P(n - a) * P(b - m); } else if (components == 3) { out[0] += data[0] * P(n - a) * P(b - m); out[1] += data[1] * P(n - a) * P(b - m); out[2] += data[2] * P(n - a) * P(b - m); } else { out[0] += data[0] * P(n - a) * P(b - m); out[1] += data[1] * P(n - a) * P(b - m); out[2] += data[2] * P(n - a) * P(b - m); out[3] += data[3] * P(n - a) * P(b - m); } } } } #endif if (float_output) { if (components == 1) { float_output[0] = out[0]; } else if (components == 3) { copy_v3_v3(float_output, out); } else { copy_v4_v4(float_output, out); } } else { if (components == 1) { byte_output[0] = (unsigned char)(out[0] + 0.5f); } else if (components == 3) { byte_output[0] = (unsigned char)(out[0] + 0.5f); byte_output[1] = (unsigned char)(out[1] + 0.5f); byte_output[2] = (unsigned char)(out[2] + 0.5f); } else { byte_output[0] = (unsigned char)(out[0] + 0.5f); byte_output[1] = (unsigned char)(out[1] + 0.5f); byte_output[2] = (unsigned char)(out[2] + 0.5f); byte_output[3] = (unsigned char)(out[3] + 0.5f); } } }
/** * Filtering method based on * "Creating raster omnimax images from multiple perspective views using the elliptical weighted average filter" * by Ned Greene and Paul S. Heckbert (1986) */ void MemoryBuffer::readEWA(float result[4], const float uv[2], const float derivatives[2][2], PixelSampler sampler) { zero_v4(result); int width = this->getWidth(), height = this->getHeight(); if (width == 0 || height == 0) return; float u = uv[0], v = uv[1]; float Ux = derivatives[0][0], Vx = derivatives[1][0], Uy = derivatives[0][1], Vy = derivatives[1][1]; float A, B, C, F, ue, ve; ellipse_params(Ux, Uy, Vx, Vy, A, B, C, F, ue, ve); /* Note: highly eccentric ellipses can lead to large texture space areas to filter! * This is limited somewhat by the EWA_WTS size in the loop, but a nicer approach * could be the one found in * "High Quality Elliptical Texture Filtering on GPU" * by Pavlos Mavridis and Georgios Papaioannou * in which the eccentricity of the ellipse is clamped. */ int U0 = (int)u; int V0 = (int)v; /* pixel offset for interpolation */ float ufac = u - floorf(u), vfac = v - floorf(v); /* filter size */ int u1 = (int)(u - ue); int u2 = (int)(u + ue); int v1 = (int)(v - ve); int v2 = (int)(v + ve); /* sane clamping to avoid unnecessarily huge loops */ /* note: if eccentricity gets clamped (see above), * the ue/ve limits can also be lowered accordingly */ if (U0 - u1 > EWA_MAXIDX) u1 = U0 - EWA_MAXIDX; if (u2 - U0 > EWA_MAXIDX) u2 = U0 + EWA_MAXIDX; if (V0 - v1 > EWA_MAXIDX) v1 = V0 - EWA_MAXIDX; if (v2 - V0 > EWA_MAXIDX) v2 = V0 + EWA_MAXIDX; float DDQ = 2.0f * A; float U = u1 - U0; float ac1 = A * (2.0f * U + 1.0f); float ac2 = A * U * U; float BU = B * U; float sum = 0.0f; for (int v = v1; v <= v2; ++v) { float V = v - V0; float DQ = ac1 + B * V; float Q = (C * V + BU) * V + ac2; for (int u = u1; u <= u2; ++u) { if (Q < F) { float tc[4]; const float wt = EWA_WTS[CLAMPIS((int)Q, 0, EWA_MAXIDX)]; switch (sampler) { case COM_PS_NEAREST: read(tc, u, v); break; case COM_PS_BILINEAR: readBilinear(tc, (float)u + ufac, (float)v + vfac); break; case COM_PS_BICUBIC: readBilinear(tc, (float)u + ufac, (float)v + vfac); break; /* XXX no readBicubic method yet */ default: zero_v4(tc); break; } madd_v4_v4fl(result, tc, wt); sum += wt; } Q += DQ; DQ += DDQ; } } mul_v4_fl(result, (sum != 0.0f ? 1.0f / sum : 0.0f)); }
/* used by node view too */ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_default_view, int channels, int x, int y, const unsigned char cp[4], const float fp[4], int *zp, float *zpf) { char str[256]; float dx = 6; /* text colors */ /* XXX colored text not allowed in Blender UI */ #if 0 unsigned char red[3] = {255, 50, 50}; unsigned char green[3] = {0, 255, 0}; unsigned char blue[3] = {100, 100, 255}; #else unsigned char red[3] = {255, 255, 255}; unsigned char green[3] = {255, 255, 255}; unsigned char blue[3] = {255, 255, 255}; #endif float hue = 0, sat = 0, val = 0, lum = 0, u = 0, v = 0; float col[4], finalcol[4]; glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); /* noisy, high contrast make impossible to read if lower alpha is used. */ glColor4ub(0, 0, 0, 190); glRecti(0.0, 0.0, BLI_rcti_size_x(&ar->winrct) + 1, 20); glDisable(GL_BLEND); BLF_size(blf_mono_font, 11, 72); glColor3ub(255, 255, 255); BLI_snprintf(str, sizeof(str), "X:%-4d Y:%-4d |", x, y); // UI_DrawString(6, 6, str); // works ok but fixed width is nicer. BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); if (zp) { glColor3ub(255, 255, 255); BLI_snprintf(str, sizeof(str), " Z:%-.4f |", 0.5f + 0.5f * (((float)*zp) / (float)0x7fffffff)); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } if (zpf) { glColor3ub(255, 255, 255); BLI_snprintf(str, sizeof(str), " Z:%-.3f |", *zpf); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } if (channels >= 3) { glColor3ubv(red); if (fp) BLI_snprintf(str, sizeof(str), " R:%-.5f", fp[0]); else if (cp) BLI_snprintf(str, sizeof(str), " R:%-3d", cp[0]); else BLI_snprintf(str, sizeof(str), " R:-"); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); glColor3ubv(green); if (fp) BLI_snprintf(str, sizeof(str), " G:%-.5f", fp[1]); else if (cp) BLI_snprintf(str, sizeof(str), " G:%-3d", cp[1]); else BLI_snprintf(str, sizeof(str), " G:-"); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); glColor3ubv(blue); if (fp) BLI_snprintf(str, sizeof(str), " B:%-.5f", fp[2]); else if (cp) BLI_snprintf(str, sizeof(str), " B:%-3d", cp[2]); else BLI_snprintf(str, sizeof(str), " B:-"); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); if (channels == 4) { glColor3ub(255, 255, 255); if (fp) BLI_snprintf(str, sizeof(str), " A:%-.4f", fp[3]); else if (cp) BLI_snprintf(str, sizeof(str), " A:%-3d", cp[3]); else BLI_snprintf(str, sizeof(str), "- "); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } if (color_manage && channels == 4) { float pixel[4]; if (use_default_view) IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, NULL, &scene->display_settings); else IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, &scene->view_settings, &scene->display_settings); BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", pixel[0], pixel[1], pixel[2]); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } } /* color rectangle */ if (channels == 1) { if (fp) { col[0] = col[1] = col[2] = fp[0]; } else if (cp) { col[0] = col[1] = col[2] = (float)cp[0] / 255.0f; } else { col[0] = col[1] = col[2] = 0.0f; } col[3] = 1.0f; } else if (channels == 3) { if (fp) { copy_v3_v3(col, fp); } else if (cp) { rgb_uchar_to_float(col, cp); } else { zero_v3(col); } col[3] = 1.0f; } else if (channels == 4) { if (fp) copy_v4_v4(col, fp); else if (cp) { rgba_uchar_to_float(col, cp); } else { zero_v4(col); } } else { BLI_assert(0); zero_v4(col); } if (color_manage) { if (use_default_view) IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings); else IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings); } else { copy_v4_v4(finalcol, col); } glDisable(GL_BLEND); glColor3fv(finalcol); dx += 5; glBegin(GL_QUADS); glVertex2f(dx, 3); glVertex2f(dx, 17); glVertex2f(dx + 30, 17); glVertex2f(dx + 30, 3); glEnd(); /* draw outline */ glColor3ub(128, 128, 128); glBegin(GL_LINE_LOOP); glVertex2f(dx, 3); glVertex2f(dx, 17); glVertex2f(dx + 30, 17); glVertex2f(dx + 30, 3); glEnd(); dx += 35; glColor3ub(255, 255, 255); if (channels == 1) { if (fp) { rgb_to_hsv(fp[0], fp[0], fp[0], &hue, &sat, &val); rgb_to_yuv(fp[0], fp[0], fp[0], &lum, &u, &v); } else if (cp) { rgb_to_hsv((float)cp[0] / 255.0f, (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, &hue, &sat, &val); rgb_to_yuv((float)cp[0] / 255.0f, (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, &lum, &u, &v); } BLI_snprintf(str, sizeof(str), "V:%-.4f", val); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); BLI_snprintf(str, sizeof(str), " L:%-.4f", lum); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } else if (channels >= 3) { if (fp) { rgb_to_hsv(fp[0], fp[1], fp[2], &hue, &sat, &val); rgb_to_yuv(fp[0], fp[1], fp[2], &lum, &u, &v); } else if (cp) { rgb_to_hsv((float)cp[0] / 255.0f, (float)cp[1] / 255.0f, (float)cp[2] / 255.0f, &hue, &sat, &val); rgb_to_yuv((float)cp[0] / 255.0f, (float)cp[1] / 255.0f, (float)cp[2] / 255.0f, &lum, &u, &v); } BLI_snprintf(str, sizeof(str), "H:%-.4f", hue); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); BLI_snprintf(str, sizeof(str), " S:%-.4f", sat); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); BLI_snprintf(str, sizeof(str), " V:%-.4f", val); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); BLI_snprintf(str, sizeof(str), " L:%-.4f", lum); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } (void)dx; }
void RenderLayersProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { #if 0 const RenderData *rd = this->m_rd; int dx = 0, dy = 0; if (rd->mode & R_BORDER && rd->mode & R_CROP) { /* see comment in executeRegion describing coordinate mapping, * here it simply goes other way around */ int full_width = rd->xsch * rd->size / 100; int full_height = rd->ysch * rd->size / 100; dx = rd->border.xmin * full_width - (full_width - this->getWidth()) / 2.0f; dy = rd->border.ymin * full_height - (full_height - this->getHeight()) / 2.0f; } int ix = x - dx; int iy = y - dy; #endif #ifndef NDEBUG { const DataType data_type = this->getOutputSocket()->getDataType(); int actual_element_size = this->m_elementsize; int expected_element_size; if (data_type == COM_DT_VALUE) { expected_element_size = 1; } else if (data_type == COM_DT_VECTOR) { expected_element_size = 3; } else if (data_type == COM_DT_COLOR) { expected_element_size = 4; } else { expected_element_size = 0; BLI_assert(!"Something horribly wrong just happened"); } BLI_assert(expected_element_size == actual_element_size); } #endif if (this->m_inputBuffer == NULL) { int elemsize = this->m_elementsize; if (elemsize == 1) { output[0] = 0.0f; } else if (elemsize == 3) { zero_v3(output); } else { BLI_assert(elemsize == 4); zero_v4(output); } } else { doInterpolation(output, x, y, sampler); } }
void BLI_ewa_filter(const int width, const int height, const bool intpol, const bool use_alpha, const float uv[2], const float du[2], const float dv[2], ewa_filter_read_pixel_cb read_pixel_cb, void *userdata, float result[4]) { /* scaling dxt/dyt by full resolution can cause overflow because of huge A/B/C and esp. F values, * scaling by aspect ratio alone does the opposite, so try something in between instead... */ const float ff2 = (float)width, ff = sqrtf(ff2), q = (float)height / ff; const float Ux = du[0] * ff, Vx = du[1] * q, Uy = dv[0] * ff, Vy = dv[1] * q; float A = Vx * Vx + Vy * Vy; float B = -2.0f * (Ux * Vx + Uy * Vy); float C = Ux * Ux + Uy * Uy; float F = A * C - B * B * 0.25f; float a, b, th, ecc, a2, b2, ue, ve, U0, V0, DDQ, U, ac1, ac2, BU, d; int u, v, u1, u2, v1, v2; /* The so-called 'high' quality ewa method simply adds a constant of 1 to both A & C, * so the ellipse always covers at least some texels. But since the filter is now always larger, * it also means that everywhere else it's also more blurry then ideally should be the case. * So instead here the ellipse radii are modified instead whenever either is too low. * Use a different radius based on interpolation switch, just enough to anti-alias when interpolation is off, * and slightly larger to make result a bit smoother than bilinear interpolation when interpolation is on * (minimum values: const float rmin = intpol ? 1.f : 0.5f;) */ const float rmin = (intpol ? 1.5625f : 0.765625f) / ff2; BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc); if ((b2 = b * b) < rmin) { if ((a2 = a * a) < rmin) { B = 0.0f; A = C = rmin; F = A * C; } else { b2 = rmin; radangle2imp(a2, b2, th, &A, &B, &C, &F); } } ue = ff * sqrtf(C); ve = ff * sqrtf(A); d = (float)(EWA_MAXIDX + 1) / (F * ff2); A *= d; B *= d; C *= d; U0 = uv[0] * (float)width; V0 = uv[1] * (float)height; u1 = (int)(floorf(U0 - ue)); u2 = (int)(ceilf(U0 + ue)); v1 = (int)(floorf(V0 - ve)); v2 = (int)(ceilf(V0 + ve)); /* sane clamping to avoid unnecessarily huge loops */ /* note: if eccentricity gets clamped (see above), * the ue/ve limits can also be lowered accordingly */ if (U0 - (float)u1 > EWA_MAXIDX) u1 = (int)U0 - EWA_MAXIDX; if ((float)u2 - U0 > EWA_MAXIDX) u2 = (int)U0 + EWA_MAXIDX; if (V0 - (float)v1 > EWA_MAXIDX) v1 = (int)V0 - EWA_MAXIDX; if ((float)v2 - V0 > EWA_MAXIDX) v2 = (int)V0 + EWA_MAXIDX; /* Early output check for cases the whole region is outside of the buffer. */ if ((u2 < 0 || u1 >= width) || (v2 < 0 || v1 >= height)) { zero_v4(result); return; } U0 -= 0.5f; V0 -= 0.5f; DDQ = 2.0f * A; U = (float)u1 - U0; ac1 = A * (2.0f * U + 1.0f); ac2 = A * U * U; BU = B * U; d = 0.0f; zero_v4(result); for (v = v1; v <= v2; ++v) { const float V = (float)v - V0; float DQ = ac1 + B * V; float Q = (C * V + BU) * V + ac2; for (u = u1; u <= u2; ++u) { if (Q < (float)(EWA_MAXIDX + 1)) { float tc[4]; const float wt = EWA_WTS[(Q < 0.0f) ? 0 : (unsigned int)Q]; read_pixel_cb(userdata, u, v, tc); madd_v3_v3fl(result, tc, wt); result[3] += use_alpha ? tc[3] * wt : 0.0f; d += wt; } Q += DQ; DQ += DDQ; } } /* d should hopefully never be zero anymore */ d = 1.0f / d; mul_v3_fl(result, d); /* clipping can be ignored if alpha used, texr->ta already includes filtered edge */ result[3] = use_alpha ? result[3] * d : 1.0f; }
/* used by node view too */ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_default_view, int channels, int x, int y, const unsigned char cp[4], const float fp[4], const float linearcol[4], int *zp, float *zpf) { rcti color_rect; char str[256]; int dx = 6; const int dy = 0.3f * UI_UNIT_Y; /* text colors */ /* XXX colored text not allowed in Blender UI */ #if 0 unsigned char red[3] = {255, 50, 50}; unsigned char green[3] = {0, 255, 0}; unsigned char blue[3] = {100, 100, 255}; #else unsigned char red[3] = {255, 255, 255}; unsigned char green[3] = {255, 255, 255}; unsigned char blue[3] = {255, 255, 255}; #endif float hue = 0, sat = 0, val = 0, lum = 0, u = 0, v = 0; float col[4], finalcol[4]; glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); /* noisy, high contrast make impossible to read if lower alpha is used. */ glColor4ub(0, 0, 0, 190); glRecti(0.0, 0.0, BLI_rcti_size_x(&ar->winrct) + 1, UI_UNIT_Y); glDisable(GL_BLEND); BLF_size(blf_mono_font, 11 * U.pixelsize, U.dpi); glColor3ub(255, 255, 255); BLI_snprintf(str, sizeof(str), "X:%-4d Y:%-4d |", x, y); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); if (zp) { glColor3ub(255, 255, 255); BLI_snprintf(str, sizeof(str), " Z:%-.4f |", 0.5f + 0.5f * (((float)*zp) / (float)0x7fffffff)); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); } if (zpf) { glColor3ub(255, 255, 255); BLI_snprintf(str, sizeof(str), " Z:%-.3f |", *zpf); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); } if (channels >= 3) { glColor3ubv(red); if (fp) BLI_snprintf(str, sizeof(str), " R:%-.5f", fp[0]); else if (cp) BLI_snprintf(str, sizeof(str), " R:%-3d", cp[0]); else BLI_snprintf(str, sizeof(str), " R:-"); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); glColor3ubv(green); if (fp) BLI_snprintf(str, sizeof(str), " G:%-.5f", fp[1]); else if (cp) BLI_snprintf(str, sizeof(str), " G:%-3d", cp[1]); else BLI_snprintf(str, sizeof(str), " G:-"); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); glColor3ubv(blue); if (fp) BLI_snprintf(str, sizeof(str), " B:%-.5f", fp[2]); else if (cp) BLI_snprintf(str, sizeof(str), " B:%-3d", cp[2]); else BLI_snprintf(str, sizeof(str), " B:-"); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); if (channels == 4) { glColor3ub(255, 255, 255); if (fp) BLI_snprintf(str, sizeof(str), " A:%-.4f", fp[3]); else if (cp) BLI_snprintf(str, sizeof(str), " A:%-3d", cp[3]); else BLI_snprintf(str, sizeof(str), "- "); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); } if (color_manage) { float rgba[4]; copy_v3_v3(rgba, linearcol); if (channels == 3) rgba[3] = 1.0f; else rgba[3] = linearcol[3]; if (use_default_view) IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings); else IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, &scene->view_settings, &scene->display_settings); BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", rgba[0], rgba[1], rgba[2]); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); } } /* color rectangle */ if (channels == 1) { if (fp) { col[0] = col[1] = col[2] = fp[0]; } else if (cp) { col[0] = col[1] = col[2] = (float)cp[0] / 255.0f; } else { col[0] = col[1] = col[2] = 0.0f; } col[3] = 1.0f; } else if (channels == 3) { copy_v3_v3(col, linearcol); col[3] = 1.0f; } else if (channels == 4) { copy_v4_v4(col, linearcol); } else { BLI_assert(0); zero_v4(col); } if (color_manage) { if (use_default_view) IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings); else IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings); } else { copy_v4_v4(finalcol, col); } glDisable(GL_BLEND); dx += 0.25f * UI_UNIT_X; BLI_rcti_init(&color_rect, dx, dx + (1.5f * UI_UNIT_X), 0.15f * UI_UNIT_Y, 0.85f * UI_UNIT_Y); if (channels == 4) { rcti color_rect_half; int color_quater_x, color_quater_y; color_rect_half = color_rect; color_rect_half.xmax = BLI_rcti_cent_x(&color_rect); glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); color_rect_half = color_rect; color_rect_half.xmin = BLI_rcti_cent_x(&color_rect); color_quater_x = BLI_rcti_cent_x(&color_rect_half); color_quater_y = BLI_rcti_cent_y(&color_rect_half); glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255); glRecti(color_rect_half.xmin, color_rect_half.ymin, color_rect_half.xmax, color_rect_half.ymax); glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255); glRecti(color_quater_x, color_quater_y, color_rect_half.xmax, color_rect_half.ymax); glRecti(color_rect_half.xmin, color_rect_half.ymin, color_quater_x, color_quater_y); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(UNPACK3(finalcol), fp ? fp[3] : (cp[3] / 255.0f)); glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); glDisable(GL_BLEND); } else { glColor3fv(finalcol); glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); } /* draw outline */ glColor3ub(128, 128, 128); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); dx += 1.75f * UI_UNIT_X; glColor3ub(255, 255, 255); if (channels == 1) { if (fp) { rgb_to_hsv(fp[0], fp[0], fp[0], &hue, &sat, &val); rgb_to_yuv(fp[0], fp[0], fp[0], &lum, &u, &v); } else if (cp) { rgb_to_hsv((float)cp[0] / 255.0f, (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, &hue, &sat, &val); rgb_to_yuv((float)cp[0] / 255.0f, (float)cp[0] / 255.0f, (float)cp[0] / 255.0f, &lum, &u, &v); } BLI_snprintf(str, sizeof(str), "V:%-.4f", val); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); BLI_snprintf(str, sizeof(str), " L:%-.4f", lum); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); } else if (channels >= 3) { rgb_to_hsv(finalcol[0], finalcol[1], finalcol[2], &hue, &sat, &val); rgb_to_yuv(finalcol[0], finalcol[1], finalcol[2], &lum, &u, &v); BLI_snprintf(str, sizeof(str), "H:%-.4f", hue); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); BLI_snprintf(str, sizeof(str), " S:%-.4f", sat); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); BLI_snprintf(str, sizeof(str), " V:%-.4f", val); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); BLI_snprintf(str, sizeof(str), " L:%-.4f", lum); BLF_position(blf_mono_font, dx, dy, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str, sizeof(str)); } (void)dx; }
/* Generic texture sampler for 3D painting systems. point has to be either in * region space mouse coordinates, or 3d world coordinates for 3D mapping. * * rgba outputs straight alpha. */ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br, const float point[3], float rgba[4], const int thread, struct ImagePool *pool) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; MTex *mtex = &br->mtex; float intensity = 1.0; bool hasrgb = false; if (!mtex->tex) { intensity = 1; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { /* Get strength by feeding the vertex * location directly into a texture */ hasrgb = externtex(mtex, point, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); } else if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) { float rotation = -mtex->rot; float point_2d[2] = {point[0], point[1]}; float x, y; float co[3]; x = point_2d[0] - br->stencil_pos[0]; y = point_2d[1] - br->stencil_pos[1]; if (rotation > 0.001f || rotation < -0.001f) { const float angle = atan2f(y, x) + rotation; const float flen = sqrtf(x * x + y * y); x = flen * cosf(angle); y = flen * sinf(angle); } if (fabsf(x) > br->stencil_dimension[0] || fabsf(y) > br->stencil_dimension[1]) { zero_v4(rgba); return 0.0f; } x /= (br->stencil_dimension[0]); y /= (br->stencil_dimension[1]); co[0] = x; co[1] = y; co[2] = 0.0f; hasrgb = externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); } else { float rotation = -mtex->rot; float point_2d[2] = {point[0], point[1]}; float x = 0.0f, y = 0.0f; /* Quite warnings */ float invradius = 1.0f; /* Quite warnings */ float co[3]; if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { /* keep coordinates relative to mouse */ rotation += ups->brush_rotation; x = point_2d[0] - ups->tex_mouse[0]; y = point_2d[1] - ups->tex_mouse[1]; /* use pressure adjusted size for fixed mode */ invradius = 1.0f / ups->pixel_radius; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) { /* leave the coordinates relative to the screen */ /* use unadjusted size for tiled mode */ invradius = 1.0f / BKE_brush_size_get(scene, br); x = point_2d[0]; y = point_2d[1]; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) { rotation += ups->brush_rotation; /* these contain a random coordinate */ x = point_2d[0] - ups->tex_mouse[0]; y = point_2d[1] - ups->tex_mouse[1]; invradius = 1.0f / ups->pixel_radius; } x *= invradius; y *= invradius; /* it is probably worth optimizing for those cases where * the texture is not rotated by skipping the calls to * atan2, sqrtf, sin, and cos. */ if (rotation > 0.001f || rotation < -0.001f) { const float angle = atan2f(y, x) + rotation; const float flen = sqrtf(x * x + y * y); x = flen * cosf(angle); y = flen * sinf(angle); } co[0] = x; co[1] = y; co[2] = 0.0f; hasrgb = externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); } intensity += br->texture_sample_bias; if (!hasrgb) { rgba[0] = intensity; rgba[1] = intensity; rgba[2] = intensity; rgba[3] = 1.0f; } /* For consistency, sampling always returns color in linear space */ else if (ups->do_linear_conversion) { IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, ups->colorspace); } return intensity; }
static void paint_2d_lift_soften(ImagePaintState *s, ImBuf *ibuf, ImBuf *ibufb, int *pos, const short tile) { bool sharpen = (s->painter->cache.invert ^ ((s->brush->flag & BRUSH_DIR_IN) != 0)); float threshold = s->brush->sharp_threshold; int x, y, xi, yi, xo, yo, xk, yk; float count; int out_off[2], in_off[2], dim[2]; int diff_pos[2]; float outrgb[4]; float rgba[4]; BlurKernel *kernel = s->blurkernel; dim[0] = ibufb->x; dim[1] = ibufb->y; in_off[0] = pos[0]; in_off[1] = pos[1]; out_off[0] = out_off[1] = 0; if (!tile) { IMB_rectclip(ibuf, ibufb, &in_off[0], &in_off[1], &out_off[0], &out_off[1], &dim[0], &dim[1]); if ((dim[0] == 0) || (dim[1] == 0)) return; } /* find offset inside mask buffers to sample them */ sub_v2_v2v2_int(diff_pos, out_off, in_off); for (y = 0; y < dim[1]; y++) { for (x = 0; x < dim[0]; x++) { /* get input pixel */ xi = in_off[0] + x; yi = in_off[1] + y; count = 0.0; if (tile) { paint_2d_ibuf_tile_convert(ibuf, &xi, &yi, tile); if (xi < ibuf->x && xi >= 0 && yi < ibuf->y && yi >= 0) paint_2d_ibuf_rgb_get(ibuf, xi, yi, rgba); else zero_v4(rgba); } else { /* coordinates have been clipped properly here, it should be safe to do this */ paint_2d_ibuf_rgb_get(ibuf, xi, yi, rgba); } zero_v4(outrgb); for (yk = 0; yk < kernel->side; yk++) { for (xk = 0; xk < kernel->side; xk++) { count += paint_2d_ibuf_add_if(ibuf, xi + xk - kernel->pixel_len, yi + yk - kernel->pixel_len, outrgb, tile, kernel->wdata[xk + yk * kernel->side]); } } if (count > 0.0f) { mul_v4_fl(outrgb, 1.0f / (float)count); if (sharpen) { /* subtract blurred image from normal image gives high pass filter */ sub_v3_v3v3(outrgb, rgba, outrgb); /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid * colored speckles appearing in final image, and also to check for threshold */ outrgb[0] = outrgb[1] = outrgb[2] = IMB_colormanagement_get_luminance(outrgb); if (fabsf(outrgb[0]) > threshold) { float mask = BKE_brush_alpha_get(s->scene, s->brush); float alpha = rgba[3]; rgba[3] = outrgb[3] = mask; /* add to enhance edges */ blend_color_add_float(outrgb, rgba, outrgb); outrgb[3] = alpha; } else copy_v4_v4(outrgb, rgba); } } else copy_v4_v4(outrgb, rgba); /* write into brush buffer */ xo = out_off[0] + x; yo = out_off[1] + y; paint_2d_ibuf_rgb_set(ibufb, xo, yo, 0, outrgb); } } }
void draw_image_info(ARegion *ar, int color_manage, int channels, int x, int y, char *cp, float *fp, int *zp, float *zpf) { char str[256]; float dx= 6; /* text colors */ /* XXX colored text not allowed in Blender UI */ #if 0 unsigned char red[3] = {255, 50, 50}; unsigned char green[3] = {0, 255, 0}; unsigned char blue[3] = {100, 100, 255}; #else unsigned char red[3] = {255, 255, 255}; unsigned char green[3] = {255, 255, 255}; unsigned char blue[3] = {255, 255, 255}; #endif float hue=0, sat=0, val=0, lum=0, u=0, v=0; float col[4], finalcol[4]; glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); /* noisy, high contrast make impossible to read if lower alpha is used. */ glColor4ub(0, 0, 0, 190); glRecti(0.0, 0.0, ar->winrct.xmax - ar->winrct.xmin + 1, 20); glDisable(GL_BLEND); BLF_size(blf_mono_font, 11, 72); glColor3ub(255, 255, 255); sprintf(str, "X:%-4d Y:%-4d |", x, y); // UI_DrawString(6, 6, str); // works ok but fixed width is nicer. BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); if(zp) { glColor3ub(255, 255, 255); sprintf(str, " Z:%-.4f |", 0.5f+0.5f*(((float)*zp)/(float)0x7fffffff)); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } if(zpf) { glColor3ub(255, 255, 255); sprintf(str, " Z:%-.3f |", *zpf); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } if(channels >= 3) { glColor3ubv(red); if (fp) sprintf(str, " R:%-.4f", fp[0]); else if (cp) sprintf(str, " R:%-3d", cp[0]); else sprintf(str, " R:-"); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); glColor3ubv(green); if (fp) sprintf(str, " G:%-.4f", fp[1]); else if (cp) sprintf(str, " G:%-3d", cp[1]); else sprintf(str, " G:-"); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); glColor3ubv(blue); if (fp) sprintf(str, " B:%-.4f", fp[2]); else if (cp) sprintf(str, " B:%-3d", cp[2]); else sprintf(str, " B:-"); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); if(channels == 4) { glColor3ub(255, 255, 255); if (fp) sprintf(str, " A:%-.4f", fp[3]); else if (cp) sprintf(str, " A:%-3d", cp[3]); else sprintf(str, "- "); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } } /* color rectangle */ if (channels==1) { if (fp) col[0] = col[1] = col[2] = fp[0]; else if (cp) col[0] = col[1] = col[2] = (float)cp[0]/255.0f; else col[0] = col[1] = col[2] = 0.0f; } else if (channels==3) { if (fp) copy_v3_v3(col, fp); else if (cp) { col[0] = (float)cp[0]/255.0f; col[1] = (float)cp[1]/255.0f; col[2] = (float)cp[2]/255.0f; } else zero_v3(col); } else if (channels==4) { if (fp) copy_v4_v4(col, fp); else if (cp) { col[0] = (float)cp[0]/255.0f; col[1] = (float)cp[1]/255.0f; col[2] = (float)cp[2]/255.0f; col[3] = (float)cp[3]/255.0f; } else zero_v4(col); } if (color_manage) { linearrgb_to_srgb_v3_v3(finalcol, col); finalcol[3] = col[3]; } else { copy_v4_v4(finalcol, col); } glDisable(GL_BLEND); glColor3fv(finalcol); dx += 5; glBegin(GL_QUADS); glVertex2f(dx, 3); glVertex2f(dx, 17); glVertex2f(dx+30, 17); glVertex2f(dx+30, 3); glEnd(); dx += 35; glColor3ub(255, 255, 255); if(channels == 1) { if (fp) { rgb_to_hsv(fp[0], fp[0], fp[0], &hue, &sat, &val); rgb_to_yuv(fp[0], fp[0], fp[0], &lum, &u, &v); } else if (cp) { rgb_to_hsv((float)cp[0]/255.0f, (float)cp[0]/255.0f, (float)cp[0]/255.0f, &hue, &sat, &val); rgb_to_yuv((float)cp[0]/255.0f, (float)cp[0]/255.0f, (float)cp[0]/255.0f, &lum, &u, &v); } sprintf(str, "V:%-.4f", val); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); sprintf(str, " L:%-.4f", lum); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } else if(channels >= 3) { if (fp) { rgb_to_hsv(fp[0], fp[1], fp[2], &hue, &sat, &val); rgb_to_yuv(fp[0], fp[1], fp[2], &lum, &u, &v); } else if (cp) { rgb_to_hsv((float)cp[0]/255.0f, (float)cp[1]/255.0f, (float)cp[2]/255.0f, &hue, &sat, &val); rgb_to_yuv((float)cp[0]/255.0f, (float)cp[1]/255.0f, (float)cp[2]/255.0f, &lum, &u, &v); } sprintf(str, "H:%-.4f", hue); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); sprintf(str, " S:%-.4f", sat); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); sprintf(str, " V:%-.4f", val); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); sprintf(str, " L:%-.4f", lum); BLF_position(blf_mono_font, dx, 6, 0); BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } (void)dx; }
float BKE_brush_sample_masktex(const Scene *scene, Brush *br, const float point[2], const int thread, struct ImagePool *pool) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; MTex *mtex = &br->mask_mtex; float rgba[4], intensity; if (!mtex->tex) { return 1.0f; } if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) { float rotation = -mtex->rot; float point_2d[2] = {point[0], point[1]}; float x, y; float co[3]; x = point_2d[0] - br->mask_stencil_pos[0]; y = point_2d[1] - br->mask_stencil_pos[1]; if (rotation > 0.001f || rotation < -0.001f) { const float angle = atan2f(y, x) + rotation; const float flen = sqrtf(x * x + y * y); x = flen * cosf(angle); y = flen * sinf(angle); } if (fabsf(x) > br->mask_stencil_dimension[0] || fabsf(y) > br->mask_stencil_dimension[1]) { zero_v4(rgba); return 0.0f; } x /= (br->mask_stencil_dimension[0]); y /= (br->mask_stencil_dimension[1]); co[0] = x; co[1] = y; co[2] = 0.0f; externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); } else { float rotation = -mtex->rot; float point_2d[2] = {point[0], point[1]}; float x = 0.0f, y = 0.0f; /* Quite warnings */ float invradius = 1.0f; /* Quite warnings */ float co[3]; if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { /* keep coordinates relative to mouse */ rotation += ups->brush_rotation_sec; x = point_2d[0] - ups->mask_tex_mouse[0]; y = point_2d[1] - ups->mask_tex_mouse[1]; /* use pressure adjusted size for fixed mode */ invradius = 1.0f / ups->pixel_radius; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) { /* leave the coordinates relative to the screen */ /* use unadjusted size for tiled mode */ invradius = 1.0f / BKE_brush_size_get(scene, br); x = point_2d[0]; y = point_2d[1]; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) { rotation += ups->brush_rotation_sec; /* these contain a random coordinate */ x = point_2d[0] - ups->mask_tex_mouse[0]; y = point_2d[1] - ups->mask_tex_mouse[1]; invradius = 1.0f / ups->pixel_radius; } x *= invradius; y *= invradius; /* it is probably worth optimizing for those cases where * the texture is not rotated by skipping the calls to * atan2, sqrtf, sin, and cos. */ if (rotation > 0.001f || rotation < -0.001f) { const float angle = atan2f(y, x) + rotation; const float flen = sqrtf(x * x + y * y); x = flen * cosf(angle); y = flen * sinf(angle); } co[0] = x; co[1] = y; co[2] = 0.0f; externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); } CLAMP(intensity, 0.0f, 1.0f); switch (br->mask_pressure) { case BRUSH_MASK_PRESSURE_CUTOFF: intensity = ((1.0f - intensity) < ups->size_pressure_value) ? 1.0f : 0.0f; break; case BRUSH_MASK_PRESSURE_RAMP: intensity = ups->size_pressure_value + intensity * (1.0f - ups->size_pressure_value); break; default: break; } return intensity; }
void DespeckleOperation::executePixel(float output[4], int x, int y, void * /*data*/) { float w = 0.0f; float color_org[4]; float color_mid[4]; float color_mid_ok[4]; float in1[4]; int x1 = x - 1; int x2 = x; int x3 = x + 1; int y1 = y - 1; int y2 = y; int y3 = y + 1; CLAMP(x1, 0, getWidth() - 1); CLAMP(x2, 0, getWidth() - 1); CLAMP(x3, 0, getWidth() - 1); CLAMP(y1, 0, getHeight() - 1); CLAMP(y2, 0, getHeight() - 1); CLAMP(y3, 0, getHeight() - 1); float value[4]; this->m_inputValueOperation->read(value, x2, y2, NULL); // const float mval = 1.0f - value[0]; this->m_inputOperation->read(color_org, x2, y2, NULL); #define TOT_DIV_ONE 1.0f #define TOT_DIV_CNR (float)M_SQRT1_2 #define WTOT (TOT_DIV_ONE * 4 + TOT_DIV_CNR * 4) #define COLOR_ADD(fac) \ { \ madd_v4_v4fl(color_mid, in1, fac); \ if (color_diff(in1, color_org, this->m_threshold)) { \ w += fac; \ madd_v4_v4fl(color_mid_ok, in1, fac); \ } \ } zero_v4(color_mid); zero_v4(color_mid_ok); this->m_inputOperation->read(in1, x1, y1, NULL); COLOR_ADD(TOT_DIV_CNR) this->m_inputOperation->read(in1, x2, y1, NULL); COLOR_ADD(TOT_DIV_ONE) this->m_inputOperation->read(in1, x3, y1, NULL); COLOR_ADD(TOT_DIV_CNR) this->m_inputOperation->read(in1, x1, y2, NULL); COLOR_ADD(TOT_DIV_ONE) #if 0 this->m_inputOperation->read(in2, x2, y2, NULL); madd_v4_v4fl(color_mid, in2, this->m_filter[4]); #endif this->m_inputOperation->read(in1, x3, y2, NULL); COLOR_ADD(TOT_DIV_ONE) this->m_inputOperation->read(in1, x1, y3, NULL); COLOR_ADD(TOT_DIV_CNR) this->m_inputOperation->read(in1, x2, y3, NULL); COLOR_ADD(TOT_DIV_ONE) this->m_inputOperation->read(in1, x3, y3, NULL); COLOR_ADD(TOT_DIV_CNR) mul_v4_fl(color_mid, 1.0f / (4.0f + (4.0f * (float)M_SQRT1_2))); // mul_v4_fl(color_mid, 1.0f / w); if ((w != 0.0f) && ((w / WTOT) > (this->m_threshold_neighbor)) && color_diff(color_mid, color_org, this->m_threshold)) { mul_v4_fl(color_mid_ok, 1.0f / w); interp_v4_v4v4(output, color_org, color_mid_ok, value[0]); } else { copy_v4_v4(output, color_org); } }