Example #1
0
/* Special case code for gray -> rgb */
static inline void
fz_paint_affine_alpha_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int alpha, byte *hp)
{
    while (w--)
    {
        int ui = u >> 16;
        int vi = v >> 16;
        if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
        {
            int uf = u & 0xffff;
            int vf = v & 0xffff;
            byte *a = sample_nearest(sp, sw, sh, 2, ui, vi);
            byte *b = sample_nearest(sp, sw, sh, 2, ui+1, vi);
            byte *c = sample_nearest(sp, sw, sh, 2, ui, vi+1);
            byte *d = sample_nearest(sp, sw, sh, 2, ui+1, vi+1);
            int y = bilerp(a[1], b[1], c[1], d[1], uf, vf);
            int x = bilerp(a[0], b[0], c[0], d[0], uf, vf);
            int t;
            x = fz_mul255(x, alpha);
            y = fz_mul255(y, alpha);
            t = 255 - y;
            dp[0] = x + fz_mul255(dp[0], t);
            dp[1] = x + fz_mul255(dp[1], t);
            dp[2] = x + fz_mul255(dp[2], t);
            dp[3] = y + fz_mul255(dp[3], t);
            if (hp)
                hp[0] = y + fz_mul255(hp[0], t);
        }
        dp += 4;
        if (hp)
            hp++;
        u += fa;
        v += fb;
    }
}
static inline void
fz_paint_affine_color_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *color, byte *hp)
{
	int n1 = n - 1;
	int sa = color[n1];
	int k;

	while (w--)
	{
		int ui = u >> 16;
		int vi = v >> 16;
		if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
		{
			int uf = u & 0xffff;
			int vf = v & 0xffff;
			byte *a = sample_nearest(sp, sw, sh, 1, ui, vi);
			byte *b = sample_nearest(sp, sw, sh, 1, ui+1, vi);
			byte *c = sample_nearest(sp, sw, sh, 1, ui, vi+1);
			byte *d = sample_nearest(sp, sw, sh, 1, ui+1, vi+1);
			int ma = bilerp(a[0], b[0], c[0], d[0], uf, vf);
			int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
			for (k = 0; k < n1; k++)
				dp[k] = FZ_BLEND(color[k], dp[k], masa);
			dp[n1] = FZ_BLEND(255, dp[n1], masa);
			if (hp)
				hp[0] = FZ_BLEND(255, hp[0], masa);
		}
		dp += n;
		if (hp)
			hp++;
		u += fa;
		v += fb;
	}
}
Example #3
0
static inline void
fz_paint_affine_alpha_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *hp)
{
    int k;
    int n1 = n-1;

    while (w--)
    {
        int ui = u >> 16;
        int vi = v >> 16;
        if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
        {
            int uf = u & 0xffff;
            int vf = v & 0xffff;
            byte *a = sample_nearest(sp, sw, sh, n, ui, vi);
            byte *b = sample_nearest(sp, sw, sh, n, ui+1, vi);
            byte *c = sample_nearest(sp, sw, sh, n, ui, vi+1);
            byte *d = sample_nearest(sp, sw, sh, n, ui+1, vi+1);
            int xa = bilerp(a[n1], b[n1], c[n1], d[n1], uf, vf);
            int t;
            xa = fz_mul255(xa, alpha);
            t = 255 - xa;
            for (k = 0; k < n1; k++)
            {
                int x = bilerp(a[k], b[k], c[k], d[k], uf, vf);
                dp[k] = fz_mul255(x, alpha) + fz_mul255(dp[k], t);
            }
            dp[n1] = xa + fz_mul255(dp[n1], t);
            if (hp)
                hp[0] = xa + fz_mul255(hp[0], t);
        }
        dp += n;
        if (hp)
            hp++;
        u += fa;
        v += fb;
    }
}
Example #4
0
static void
interppixel_NDC_clamped (const ImageBuf &buf, float x, float y, float *pixel,
                         bool envlatlmode)
{
    int fx = buf.spec().full_x;
    int fy = buf.spec().full_y;
    int fw = buf.spec().full_width;
    int fh = buf.spec().full_height;
    x = static_cast<float>(fx) + x * static_cast<float>(fw);
    y = static_cast<float>(fy) + y * static_cast<float>(fh);

    const int maxchannels = 64;  // Reasonable guess
    float p[4][maxchannels];
    DASSERT (buf.spec().nchannels <= maxchannels && 
             "You need to increase maxchannels");
    int n = std::min (buf.spec().nchannels, maxchannels);
    x -= 0.5f;
    y -= 0.5f;
    int xtexel, ytexel;
    float xfrac, yfrac;
    xfrac = floorfrac (x, &xtexel);
    yfrac = floorfrac (y, &ytexel);
    // Clamp
    int xnext = Imath::clamp (xtexel+1, buf.xmin(), buf.xmax());
    int ynext = Imath::clamp (ytexel+1, buf.ymin(), buf.ymax());
    xnext = Imath::clamp (xnext, buf.xmin(), buf.xmax());
    ynext = Imath::clamp (ynext, buf.ymin(), buf.ymax());

    // Get the four texels
    buf.getpixel (xtexel, ytexel, p[0], n);
    buf.getpixel (xnext, ytexel, p[1], n);
    buf.getpixel (xtexel, ynext, p[2], n);
    buf.getpixel (xnext, ynext, p[3], n);
    if (envlatlmode) {
        // For latlong environment maps, in order to conserve energy, we
        // must weight the pixels by sin(t*PI) because pixels closer to
        // the pole are actually less area on the sphere. Doing this
        // wrong will tend to over-represent the high latitudes in
        // low-res MIP levels.  We fold the area weighting into our
        // linear interpolation by adjusting yfrac.
        float w0 = (1.0f - yfrac) * sinf ((float)M_PI * (ytexel+0.5f)/(float)fh);
        float w1 = yfrac * sinf ((float)M_PI * (ynext+0.5f)/(float)fh);
        yfrac = w0 / (w0 + w1);
    }
    // Bilinearly interpolate
    bilerp (p[0], p[1], p[2], p[3], xfrac, yfrac, n, pixel);
}
Example #5
0
float Noise2::
operator()(float x, float y) const
{
   float floorx=std::floor(x), floory=std::floor(y);
   int i=(int)floorx, j=(int)floory;
   const Vec2f &n00=basis[hash_index(i,j)];
   const Vec2f &n10=basis[hash_index(i+1,j)];
   const Vec2f &n01=basis[hash_index(i,j+1)];
   const Vec2f &n11=basis[hash_index(i+1,j+1)];
   float fx=x-floorx, fy=y-floory;
   float sx=fx*fx*fx*(10-fx*(15-fx*6)),
         sy=fy*fy*fy*(10-fy*(15-fy*6));
   return bilerp(    fx*n00[0] +     fy*n00[1],
                 (fx-1)*n10[0] +     fy*n10[1],
                     fx*n01[0] + (fy-1)*n01[1],
                 (fx-1)*n11[0] + (fy-1)*n11[1],
                 sx, sy);
}
Example #6
0
void
ImageBuf::interppixel (float x, float y, float *pixel) const
{
    const int maxchannels = 64;  // Reasonable guess
    float p[4][maxchannels];
    DASSERT (spec().nchannels <= maxchannels && 
             "You need to increase maxchannels in ImageBuf::interppixel");
    int n = std::min (spec().nchannels, maxchannels);
    x -= 0.5f;
    y -= 0.5f;
    int xtexel, ytexel;
    float xfrac, yfrac;
    xfrac = floorfrac (x, &xtexel);
    yfrac = floorfrac (y, &ytexel);
    getpixel (xtexel, ytexel, p[0], n);
    getpixel (xtexel+1, ytexel, p[1], n);
    getpixel (xtexel, ytexel+1, p[2], n);
    getpixel (xtexel+1, ytexel+1, p[3], n);
    bilerp (p[0], p[1], p[2], p[3], xfrac, yfrac, n, pixel);
}
Example #7
0
bool SkPatchUtils::getVertexData(SkPatchUtils::VertexData* data, const SkPoint cubics[12],
                   const SkColor colors[4], const SkPoint texCoords[4], int lodX, int lodY) {
    if (lodX < 1 || lodY < 1 || NULL == cubics || NULL == data) {
        return false;
    }

    // check for overflow in multiplication
    const int64_t lodX64 = (lodX + 1),
                   lodY64 = (lodY + 1),
                   mult64 = lodX64 * lodY64;
    if (mult64 > SK_MaxS32) {
        return false;
    }
    data->fVertexCount = SkToS32(mult64);

    // it is recommended to generate draw calls of no more than 65536 indices, so we never generate
    // more than 60000 indices. To accomplish that we resize the LOD and vertex count
    if (data->fVertexCount > 10000 || lodX > 200 || lodY > 200) {
        SkScalar weightX = static_cast<SkScalar>(lodX) / (lodX + lodY);
        SkScalar weightY = static_cast<SkScalar>(lodY) / (lodX + lodY);

        // 200 comes from the 100 * 2 which is the max value of vertices because of the limit of
        // 60000 indices ( sqrt(60000 / 6) that comes from data->fIndexCount = lodX * lodY * 6)
        lodX = static_cast<int>(weightX * 200);
        lodY = static_cast<int>(weightY * 200);
        data->fVertexCount = (lodX + 1) * (lodY + 1);
    }
    data->fIndexCount = lodX * lodY * 6;
    
    data->fPoints = SkNEW_ARRAY(SkPoint, data->fVertexCount);
    data->fIndices = SkNEW_ARRAY(uint16_t, data->fIndexCount);
    
    // if colors is not null then create array for colors
    SkPMColor colorsPM[kNumCorners];
    if (NULL != colors) {
        // premultiply colors to avoid color bleeding.
        for (int i = 0; i < kNumCorners; i++) {
            colorsPM[i] = SkPreMultiplyColor(colors[i]);
        }
        data->fColors = SkNEW_ARRAY(uint32_t, data->fVertexCount);
    }
    
    // if texture coordinates are not null then create array for them
    if (NULL != texCoords) {
        data->fTexCoords = SkNEW_ARRAY(SkPoint, data->fVertexCount);
    }
    
    SkPoint pts[kNumPtsCubic];
    SkPatchUtils::getBottomCubic(cubics, pts);
    FwDCubicEvaluator fBottom(pts);
    SkPatchUtils::getTopCubic(cubics, pts);
    FwDCubicEvaluator fTop(pts);
    SkPatchUtils::getLeftCubic(cubics, pts);
    FwDCubicEvaluator fLeft(pts);
    SkPatchUtils::getRightCubic(cubics, pts);
    FwDCubicEvaluator fRight(pts);
    
    fBottom.restart(lodX);
    fTop.restart(lodX);
    
    SkScalar u = 0.0f;
    int stride = lodY + 1;
    for (int x = 0; x <= lodX; x++) {
        SkPoint bottom = fBottom.next(), top = fTop.next();
        fLeft.restart(lodY);
        fRight.restart(lodY);
        SkScalar v = 0.f;
        for (int y = 0; y <= lodY; y++) {
            int dataIndex = x * (lodY + 1) + y;
            
            SkPoint left = fLeft.next(), right = fRight.next();
            
            SkPoint s0 = SkPoint::Make((1.0f - v) * top.x() + v * bottom.x(),
                                       (1.0f - v) * top.y() + v * bottom.y());
            SkPoint s1 = SkPoint::Make((1.0f - u) * left.x() + u * right.x(),
                                       (1.0f - u) * left.y() + u * right.y());
            SkPoint s2 = SkPoint::Make(
                                       (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].x()
                                                     + u * fTop.getCtrlPoints()[3].x())
                                       + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].x()
                                              + u * fBottom.getCtrlPoints()[3].x()),
                                       (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].y()
                                                     + u * fTop.getCtrlPoints()[3].y())
                                       + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].y()
                                              + u * fBottom.getCtrlPoints()[3].y()));
            data->fPoints[dataIndex] = s0 + s1 - s2;
            
            if (NULL != colors) {
                uint8_t a = uint8_t(bilerp(u, v,
                                   SkScalar(SkColorGetA(colorsPM[kTopLeft_Corner])),
                                   SkScalar(SkColorGetA(colorsPM[kTopRight_Corner])),
                                   SkScalar(SkColorGetA(colorsPM[kBottomLeft_Corner])),
                                   SkScalar(SkColorGetA(colorsPM[kBottomRight_Corner]))));
                uint8_t r = uint8_t(bilerp(u, v,
                                   SkScalar(SkColorGetR(colorsPM[kTopLeft_Corner])),
                                   SkScalar(SkColorGetR(colorsPM[kTopRight_Corner])),
                                   SkScalar(SkColorGetR(colorsPM[kBottomLeft_Corner])),
                                   SkScalar(SkColorGetR(colorsPM[kBottomRight_Corner]))));
                uint8_t g = uint8_t(bilerp(u, v,
                                   SkScalar(SkColorGetG(colorsPM[kTopLeft_Corner])),
                                   SkScalar(SkColorGetG(colorsPM[kTopRight_Corner])),
                                   SkScalar(SkColorGetG(colorsPM[kBottomLeft_Corner])),
                                   SkScalar(SkColorGetG(colorsPM[kBottomRight_Corner]))));
                uint8_t b = uint8_t(bilerp(u, v,
                                   SkScalar(SkColorGetB(colorsPM[kTopLeft_Corner])),
                                   SkScalar(SkColorGetB(colorsPM[kTopRight_Corner])),
                                   SkScalar(SkColorGetB(colorsPM[kBottomLeft_Corner])),
                                   SkScalar(SkColorGetB(colorsPM[kBottomRight_Corner]))));
                data->fColors[dataIndex] = SkPackARGB32(a,r,g,b);
            }
            
            if (NULL != texCoords) {
                data->fTexCoords[dataIndex] = SkPoint::Make(
                                            bilerp(u, v, texCoords[kTopLeft_Corner].x(),
                                                   texCoords[kTopRight_Corner].x(),
                                                   texCoords[kBottomLeft_Corner].x(),
                                                   texCoords[kBottomRight_Corner].x()),
                                            bilerp(u, v, texCoords[kTopLeft_Corner].y(),
                                                   texCoords[kTopRight_Corner].y(),
                                                   texCoords[kBottomLeft_Corner].y(),
                                                   texCoords[kBottomRight_Corner].y()));
                
            }
            
            if(x < lodX && y < lodY) {
                int i = 6 * (x * lodY + y);
                data->fIndices[i] = x * stride + y;
                data->fIndices[i + 1] = x * stride + 1 + y;
                data->fIndices[i + 2] = (x + 1) * stride + 1 + y;
                data->fIndices[i + 3] = data->fIndices[i];
                data->fIndices[i + 4] = data->fIndices[i + 2];
                data->fIndices[i + 5] = (x + 1) * stride + y;
            }
            v = SkScalarClampMax(v + 1.f / lodY, 1);
        }
        u = SkScalarClampMax(u + 1.f / lodX, 1);
    }
    return true;

}