static sk_sp<SkShader> make_shader0(SkIPoint* size) {
    SkBitmap    bm;
    size->set(2, 2);
    SkPMColor color0 = SkPreMultiplyARGB(0x80, 0x80, 0xff, 0x80);
    SkPMColor color1 = SkPreMultiplyARGB(0x40, 0xff, 0x00, 0xff);
    bm.allocN32Pixels(size->fX, size->fY);
    bm.eraseColor(color0);
    uint32_t* pixels = (uint32_t*) bm.getPixels();
    pixels[0] = pixels[2] = color0;
    pixels[1] = pixels[3] = color1;

    return SkShader::MakeBitmapShader(bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
}
Exemplo n.º 2
0
/**
 *  Interprets c as an unpremultiplied color, and returns the
 *  premultiplied equivalent.
 */
static SkPMColor premultiply_unpmcolor(SkPMColor c) {
    U8CPU a = SkGetPackedA32(c);
    U8CPU r = SkGetPackedR32(c);
    U8CPU g = SkGetPackedG32(c);
    U8CPU b = SkGetPackedB32(c);
    return SkPreMultiplyARGB(a, r, g, b);
}
Exemplo n.º 3
0
void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace)
{
    const uint8_t* lookUpTable = ColorSpaceUtilities::getConversionLUT(dstColorSpace, srcColorSpace);
    if (!lookUpTable)
        return;

    // FIXME: Disable color space conversions on accelerated canvases (for now).
    if (context()->isAccelerated() || !isSurfaceValid())
        return;

    const SkBitmap& bitmap = m_surface->bitmap();
    if (bitmap.isNull())
        return;

    ASSERT(bitmap.colorType() == kN32_SkColorType);
    IntSize size = m_surface->size();
    SkAutoLockPixels bitmapLock(bitmap);
    for (int y = 0; y < size.height(); ++y) {
        uint32_t* srcRow = bitmap.getAddr32(0, y);
        for (int x = 0; x < size.width(); ++x) {
            SkColor color = SkPMColorToColor(srcRow[x]);
            srcRow[x] = SkPreMultiplyARGB(
                SkColorGetA(color),
                lookUpTable[SkColorGetR(color)],
                lookUpTable[SkColorGetG(color)],
                lookUpTable[SkColorGetB(color)]);
        }
    }
}
// Set a bitmap shader that mimics dashing by width-on, width-off.
// Returns false if it could not succeed (e.g. there was an existing shader)
static bool setBitmapDash(SkPaint* paint, int width) {
    if (width <= 0 || paint->getShader())
        return false;

    SkColor c = paint->getColor();

    SkBitmap bm;
    bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 1);
    bm.allocPixels();
    bm.lockPixels();

    // set the ON pixel
    *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c),
                                            SkColorGetG(c), SkColorGetB(c));
    // set the OFF pixel
    *bm.getAddr32(1, 0) = 0;
    bm.unlockPixels();

    SkMatrix matrix;
    matrix.setScale(SkIntToScalar(width), SK_Scalar1);

    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
                                               SkShader::kClamp_TileMode);
    s->setLocalMatrix(matrix);

    paint->setShader(s)->unref();
    return true;
}
void SkMatrixConvolutionImageFilter::filterPixels(const SkBitmap& src, SkBitmap* result, const SkIRect& rect) {
    for (int y = rect.fTop; y < rect.fBottom; ++y) {
        SkPMColor* dptr = result->getAddr32(rect.fLeft, y);
        for (int x = rect.fLeft; x < rect.fRight; ++x) {
            SkScalar sumA = 0, sumR = 0, sumG = 0, sumB = 0;
            for (int cy = 0; cy < fKernelSize.fHeight; cy++) {
                for (int cx = 0; cx < fKernelSize.fWidth; cx++) {
                    SkPMColor s = PixelFetcher::fetch(src, x + cx - fTarget.fX, y + cy - fTarget.fY);
                    SkScalar k = fKernel[cy * fKernelSize.fWidth + cx];
                    if (convolveAlpha) {
                        sumA += SkScalarMul(SkIntToScalar(SkGetPackedA32(s)), k);
                    }
                    sumR += SkScalarMul(SkIntToScalar(SkGetPackedR32(s)), k);
                    sumG += SkScalarMul(SkIntToScalar(SkGetPackedG32(s)), k);
                    sumB += SkScalarMul(SkIntToScalar(SkGetPackedB32(s)), k);
                }
            }
            int a = convolveAlpha
                    ? SkClampMax(SkScalarFloorToInt(SkScalarMul(sumA, fGain) + fBias), 255)
                    : 255;
            int r = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumR, fGain) + fBias), a);
            int g = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumG, fGain) + fBias), a);
            int b = SkClampMax(SkScalarFloorToInt(SkScalarMul(sumB, fGain) + fBias), a);
            if (!convolveAlpha) {
                a = SkGetPackedA32(PixelFetcher::fetch(src, x, y));
                *dptr++ = SkPreMultiplyARGB(a, r, g, b);
            } else {
                *dptr++ = SkPackARGB32(a, r, g, b);
            }
        }
    }
}
Exemplo n.º 6
0
static void convertToIndex666(const SkBitmap& src, SkBitmap* dst) {
    SkColorTable* ctable = new SkColorTable(216);
    SkPMColor* colors = ctable->lockColors();
    // rrr ggg bbb
    for (int r = 0; r < 6; r++) {
        int rr = conv6ToByte(r);
        for (int g = 0; g < 6; g++) {
            int gg = conv6ToByte(g);
            for (int b = 0; b < 6; b++) {
                int bb = conv6ToByte(b);
                *colors++ = SkPreMultiplyARGB(0xFF, rr, gg, bb);
            }
        }
    }
    ctable->unlockColors(true);
    dst->setConfig(SkBitmap::kIndex8_Config, src.width(), src.height());
    dst->allocPixels(ctable);
    ctable->unref();

    SkAutoLockPixels alps(src);
    SkAutoLockPixels alpd(*dst);

    for (int y = 0; y < src.height(); y++) {
        const SkPMColor* srcP = src.getAddr32(0, y);
        uint8_t* dstP = dst->getAddr8(0, y);
        for (int x = src.width() - 1; x >= 0; --x) {
            *dstP++ = compute666Index(*srcP++);
        }
    }
}
Exemplo n.º 7
0
static void convert_to_index666(const SkBitmap& src, SkBitmap* dst) {
    SkPMColor storage[216];
    SkPMColor* colors = storage;
    // rrr ggg bbb
    for (int r = 0; r < 6; r++) {
        int rr = conv_6_to_byte(r);
        for (int g = 0; g < 6; g++) {
            int gg = conv_6_to_byte(g);
            for (int b = 0; b < 6; b++) {
                int bb = conv_6_to_byte(b);
                *colors++ = SkPreMultiplyARGB(0xFF, rr, gg, bb);
            }
        }
    }
    SkColorTable* ctable = new SkColorTable(storage, 216);
    dst->allocPixels(SkImageInfo::Make(src.width(), src.height(),
                                       kIndex_8_SkColorType, kOpaque_SkAlphaType),
                     NULL, ctable);
    ctable->unref();

    SkAutoLockPixels alps(src);
    SkAutoLockPixels alpd(*dst);

    for (int y = 0; y < src.height(); y++) {
        const SkPMColor* srcP = src.getAddr32(0, y);
        uint8_t* dstP = dst->getAddr8(0, y);
        for (int x = src.width() - 1; x >= 0; --x) {
            *dstP++ = compute_666_index(*srcP++);
        }
    }
}
Exemplo n.º 8
0
void
skia_set_palette(const uint8_t *palette)
{
    LOGI("skia_set_palette");

    if(!g_color_table) {
        g_color_table.reset(new SkColorTable(256));
    }

    SkPMColor *color_table = g_color_table->lockColors();
    color_table[0] = SkPreMultiplyARGB(0, 0, 0, 0);
    for (int i = 1; i < 256; i++) {
        color_table[i] = SkPreMultiplyARGB(255, palette[i*3], palette[i*3+1], palette[i*3+2]);
    }
    g_color_table->unlockColors(true);
}
Exemplo n.º 9
0
static SkShader* make_shader0(SkIPoint* size) {
    SkBitmap    bm;
    size->set(2, 2);
    bm.setConfig(SkBitmap::kARGB_8888_Config, size->fX, size->fY);
    SkPMColor color0 = SkPreMultiplyARGB(0x80, 0x80, 0xff, 0x80);
    SkPMColor color1 = SkPreMultiplyARGB(0x40, 0xff, 0x00, 0xff);
    bm.allocPixels();
    bm.eraseColor(color0);
    bm.lockPixels();
    uint32_t* pixels = (uint32_t*) bm.getPixels();
    pixels[0] = pixels[2] = color0;
    pixels[1] = pixels[3] = color1;
    bm.unlockPixels();

    return SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
                                            SkShader::kRepeat_TileMode);
}
Exemplo n.º 10
0
SkPMColor SkPreMultiplyColor(SkColor c) {
    unsigned a = SkColorGetA(c);
    unsigned r = SkColorGetR(c);
    unsigned g = SkColorGetG(c);
    unsigned b = SkColorGetB(c);

    return SkPreMultiplyARGB(a, r, g, b);
}
Exemplo n.º 11
0
/**
 * First, make sure that writing an 8-bit RGBA KTX file and then
 * reading it produces the same bitmap.
 */
DEF_TEST(KtxReadWrite, reporter) {

    // Random number generator with explicit seed for reproducibility
    SkRandom rand(0x1005cbad);

    SkBitmap bm8888;
    bool pixelsAllocated = bm8888.allocN32Pixels(128, 128);
    REPORTER_ASSERT(reporter, pixelsAllocated);

    uint8_t *pixels = reinterpret_cast<uint8_t*>(bm8888.getPixels());
    REPORTER_ASSERT(reporter, NULL != pixels);

    if (NULL == pixels) {
        return;
    }
    
    uint8_t *row = pixels;
    for (int y = 0; y < bm8888.height(); ++y) {        
        for (int x = 0; x < bm8888.width(); ++x) {
            uint8_t a = rand.nextRangeU(0, 255);
            uint8_t r = rand.nextRangeU(0, 255);
            uint8_t g = rand.nextRangeU(0, 255);
            uint8_t b = rand.nextRangeU(0, 255);

            SkPMColor &pixel = *(reinterpret_cast<SkPMColor*>(row + x*sizeof(SkPMColor)));
            pixel = SkPreMultiplyARGB(a, r, g, b);
        }
        row += bm8888.rowBytes();
    }
    REPORTER_ASSERT(reporter, !(bm8888.empty()));

    SkAutoDataUnref encodedData(SkImageEncoder::EncodeData(bm8888, SkImageEncoder::kKTX_Type, 0));
    REPORTER_ASSERT(reporter, NULL != encodedData);

    SkAutoTUnref<SkMemoryStream> stream(SkNEW_ARGS(SkMemoryStream, (encodedData)));
    REPORTER_ASSERT(reporter, NULL != stream);

    SkBitmap decodedBitmap;
    bool imageDecodeSuccess = SkImageDecoder::DecodeStream(stream, &decodedBitmap);
    REPORTER_ASSERT(reporter, imageDecodeSuccess);

    REPORTER_ASSERT(reporter, decodedBitmap.colorType() == bm8888.colorType());
    REPORTER_ASSERT(reporter, decodedBitmap.alphaType() == bm8888.alphaType());
    REPORTER_ASSERT(reporter, decodedBitmap.width() == bm8888.width());
    REPORTER_ASSERT(reporter, decodedBitmap.height() == bm8888.height());
    REPORTER_ASSERT(reporter, !(decodedBitmap.empty()));

    uint8_t *decodedPixels = reinterpret_cast<uint8_t*>(decodedBitmap.getPixels());
    REPORTER_ASSERT(reporter, NULL != decodedPixels);
    REPORTER_ASSERT(reporter, decodedBitmap.getSize() == bm8888.getSize());

    if (NULL == decodedPixels) {
        return;
    }

    REPORTER_ASSERT(reporter, memcmp(decodedPixels, pixels, decodedBitmap.getSize()) == 0);
}
bool SkPopplerRasterizePDF(SkStream* pdf, SkBitmap* output) {
  size_t size = pdf->getLength();
  SkAutoFree buffer(sk_malloc_throw(size));
  pdf->read(buffer.get(), size);

  SkAutoTDelete<poppler::document> doc(
      poppler::document::load_from_raw_data((const char*)buffer.get(), size));
  if (!doc.get() || doc->is_locked()) {
    return false;
  }

  SkAutoTDelete<poppler::page> page(doc->create_page(0));
  poppler::page_renderer renderer;
  poppler::image image = renderer.render_page(page.get());

  if (!image.is_valid() || image.format() != poppler::image::format_argb32) {
    return false;
  }

  int width = image.width(), height = image.height();
  size_t rowSize = image.bytes_per_row();
  char *imgData = image.data();

  SkBitmap bitmap;
  bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
  if (!bitmap.allocPixels()) {
    return false;
  }
  bitmap.eraseColor(SK_ColorWHITE);
  SkPMColor* bitmapPixels = (SkPMColor*)bitmap.getPixels();

  // do pixel-by-pixel copy to deal with RGBA ordering conversions
  for (int y = 0; y < height; y++) {
    char *rowData = imgData;
    for (int x = 0; x < width; x++) {
      uint8_t a = rowData[3];
      uint8_t r = rowData[2];
      uint8_t g = rowData[1];
      uint8_t b = rowData[0];

      *bitmapPixels = SkPreMultiplyARGB(a, r, g, b);

      bitmapPixels++;
      rowData += 4;
    }
    imgData += rowSize;
  }

  output->swap(bitmap);

  return true;
}
Exemplo n.º 13
0
/**
 * Next test is to see whether or not reading an unpremultiplied KTX file accurately
 * creates a premultiplied buffer...
 */
DEF_TEST(KtxReadUnpremul, reporter) {

    static const uint8_t kHalfWhiteKTX[] = {
        0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, // First twelve bytes is magic
        0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A, // KTX identifier string
        0x01, 0x02, 0x03, 0x04, // Then magic endian specifier
        0x01, 0x14, 0x00, 0x00, // uint32_t fGLType;
        0x01, 0x00, 0x00, 0x00, // uint32_t fGLTypeSize;
        0x08, 0x19, 0x00, 0x00, // uint32_t fGLFormat;
        0x58, 0x80, 0x00, 0x00, // uint32_t fGLInternalFormat;
        0x08, 0x19, 0x00, 0x00, // uint32_t fGLBaseInternalFormat;
        0x02, 0x00, 0x00, 0x00, // uint32_t fPixelWidth;
        0x02, 0x00, 0x00, 0x00, // uint32_t fPixelHeight;
        0x00, 0x00, 0x00, 0x00, // uint32_t fPixelDepth;
        0x00, 0x00, 0x00, 0x00, // uint32_t fNumberOfArrayElements;
        0x01, 0x00, 0x00, 0x00, // uint32_t fNumberOfFaces;
        0x01, 0x00, 0x00, 0x00, // uint32_t fNumberOfMipmapLevels;
        0x00, 0x00, 0x00, 0x00, // uint32_t fBytesOfKeyValueData;
        0x10, 0x00, 0x00, 0x00, // image size: 2x2 image of RGBA = 4 * 4 = 16 bytes
        0xFF, 0xFF, 0xFF, 0x80, // Pixel 1
        0xFF, 0xFF, 0xFF, 0x80, // Pixel 2
        0xFF, 0xFF, 0xFF, 0x80, // Pixel 3
        0xFF, 0xFF, 0xFF, 0x80};// Pixel 4

    SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(kHalfWhiteKTX, sizeof(kHalfWhiteKTX)));
    REPORTER_ASSERT(reporter, stream);

    SkBitmap decodedBitmap;
    bool imageDecodeSuccess = SkImageDecoder::DecodeStream(stream, &decodedBitmap);
    if (!imageDecodeSuccess) {
        ERRORF(reporter, "failed to decode the KTX stream");
        return;
    }

    REPORTER_ASSERT(reporter, decodedBitmap.colorType() == kN32_SkColorType);
    REPORTER_ASSERT(reporter, decodedBitmap.alphaType() == kPremul_SkAlphaType);
    REPORTER_ASSERT(reporter, decodedBitmap.width() == 2);
    REPORTER_ASSERT(reporter, decodedBitmap.height() == 2);
    REPORTER_ASSERT(reporter, !(decodedBitmap.empty()));

    uint8_t *decodedPixels = reinterpret_cast<uint8_t*>(decodedBitmap.getPixels());
    REPORTER_ASSERT(reporter, decodedPixels);

    uint8_t *row = decodedPixels;
    for (int j = 0; j < decodedBitmap.height(); ++j) {
        for (int i = 0; i < decodedBitmap.width(); ++i) {
            SkPMColor pixel = *(reinterpret_cast<SkPMColor*>(row + i*sizeof(SkPMColor)));
            REPORTER_ASSERT(reporter, SkPreMultiplyARGB(0x80, 0xFF, 0xFF, 0xFF) == pixel);
        }
        row += decodedBitmap.rowBytes();
    }
}
Exemplo n.º 14
0
SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade(
        const SkPoint& point, StitchData& stitchData) const {
    SkPoint newPoint;
    fMatrix.mapPoints(&newPoint, &point, 1);
    newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
    newPoint.fY = SkScalarRoundToScalar(newPoint.fY);

    U8CPU rgba[4];
    for (int channel = 3; channel >= 0; --channel) {
        rgba[channel] = SkScalarFloorToInt(255 *
            calculateTurbulenceValueForPoint(channel, stitchData, newPoint));
    }
    return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
}
Exemplo n.º 15
0
void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, 
                  const SkBitmap& bitmap, const IntSize& size)
{
    ASSERT(sourceRect.width() > 0);
    ASSERT(sourceRect.height() > 0);

    int originX = sourceRect.x();
    int destX = destPoint.x() + sourceRect.x();
    ASSERT(destX >= 0);
    ASSERT(destX < size.width());
    ASSERT(originX >= 0);
    ASSERT(originX < sourceRect.right());

    int endX = destPoint.x() + sourceRect.right();
    ASSERT(endX <= size.width());

    int numColumns = endX - destX;

    int originY = sourceRect.y();
    int destY = destPoint.y() + sourceRect.y();
    ASSERT(destY >= 0);
    ASSERT(destY < size.height());
    ASSERT(originY >= 0);
    ASSERT(originY < sourceRect.bottom());

    int endY = destPoint.y() + sourceRect.bottom();
    ASSERT(endY <= size.height());
    int numRows = endY - destY;

    ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
    SkAutoLockPixels bitmapLock(bitmap);

    unsigned srcBytesPerRow = 4 * source->width();

    const unsigned char* srcRow = source->data()->data()->data() + originY * srcBytesPerRow + originX * 4;

    for (int y = 0; y < numRows; ++y) {
        uint32_t* destRow = bitmap.getAddr32(destX, destY + y);
        for (int x = 0; x < numColumns; ++x) {
            const unsigned char* srcPixel = &srcRow[x * 4];
            if (multiplied == Unmultiplied)
                destRow[x] = SkPreMultiplyARGB(srcPixel[3], srcPixel[0],
                                               srcPixel[1], srcPixel[2]);
            else
                destRow[x] = SkPackARGB32(srcPixel[3], srcPixel[0],
                                          srcPixel[1], srcPixel[2]);
        }
        srcRow += srcBytesPerRow;
    }
}
Exemplo n.º 16
0
void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect,
                               const IntPoint& destPoint)
{
    ASSERT(sourceRect.width() > 0);
    ASSERT(sourceRect.height() > 0);

    int originx = sourceRect.x();
    int destx = destPoint.x() + sourceRect.x();
    ASSERT(destx >= 0);
    ASSERT(destx < m_size.width());
    ASSERT(originx >= 0);
    ASSERT(originx < sourceRect.right());

    int endx = destPoint.x() + sourceRect.right();
    ASSERT(endx <= m_size.width());

    int numColumns = endx - destx;

    int originy = sourceRect.y();
    int desty = destPoint.y() + sourceRect.y();
    ASSERT(desty >= 0);
    ASSERT(desty < m_size.height());
    ASSERT(originy >= 0);
    ASSERT(originy < sourceRect.bottom());

    int endy = destPoint.y() + sourceRect.bottom();
    ASSERT(endy <= m_size.height());
    int numRows = endy - desty;

    const SkBitmap& bitmap = *context()->platformContext()->bitmap();
    ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
    SkAutoLockPixels bitmapLock(bitmap);

    unsigned srcBytesPerRow = 4 * source->width();

    const unsigned char* srcRow = source->data()->data().data() +
        originy * srcBytesPerRow + originx * 4;

    for (int y = 0; y < numRows; ++y) {
        uint32_t* destRow = bitmap.getAddr32(destx, desty + y);
        for (int x = 0; x < numColumns; ++x) {
            const unsigned char* srcPixel = &srcRow[x * 4];
            destRow[x] = SkPreMultiplyARGB(srcPixel[3], srcPixel[0],
                                           srcPixel[1], srcPixel[2]);
        }
        srcRow += srcBytesPerRow;
    }
}
Exemplo n.º 17
0
void DragImage::dissolveToFraction(float fraction)
{
    m_bitmap.setAlphaType(kPremul_SkAlphaType);
    SkAutoLockPixels lock(m_bitmap);

    for (int row = 0; row < m_bitmap.height(); ++row) {
        for (int column = 0; column < m_bitmap.width(); ++column) {
            uint32_t* pixel = m_bitmap.getAddr32(column, row);
            *pixel = SkPreMultiplyARGB(
                SkColorGetA(*pixel) * fraction,
                SkColorGetR(*pixel),
                SkColorGetG(*pixel),
                SkColorGetB(*pixel));
        }
    }
}
Exemplo n.º 18
0
static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_premul(
        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) {

    // Use the masks to decode to the destination
    SkPMColor* dstPtr = (SkPMColor*) dstRow;
    INIT_RESULT_ALPHA;
    for (int i = 0; i < 3*width; i += 3) {
        uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16;
        uint8_t red = masks->getRed(p);
        uint8_t green = masks->getGreen(p);
        uint8_t blue = masks->getBlue(p);
        uint8_t alpha = masks->getAlpha(p);
        UPDATE_RESULT_ALPHA(alpha);
        dstPtr[i/3] = SkPreMultiplyARGB(alpha, red, green, blue);
    }
    return COMPUTE_RESULT_ALPHA;
}
void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
{
    const SkBitmap& bitmap = *context()->platformContext()->bitmap();
    if (bitmap.isNull())
        return;

    ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
    SkAutoLockPixels bitmapLock(bitmap);
    for (int y = 0; y < m_size.height(); ++y) {
        uint32_t* srcRow = bitmap.getAddr32(0, y);
        for (int x = 0; x < m_size.width(); ++x) {
            SkColor color = SkPMColorToColor(srcRow[x]);
            srcRow[x] = SkPreMultiplyARGB(SkColorGetA(color),
                                          lookUpTable[SkColorGetR(color)],
                                          lookUpTable[SkColorGetG(color)],
                                          lookUpTable[SkColorGetB(color)]);
        }
    }
}
Exemplo n.º 20
0
static void setBitmapDash(SkPaint* paint, int width) {
    SkColor c = paint->getColor();

    SkBitmap bm;
    bm.allocN32Pixels(2, 1);
    bm.lockPixels();
    *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c),
                                            SkColorGetG(c), SkColorGetB(c));
    *bm.getAddr32(1, 0) = 0;
    bm.unlockPixels();

    SkMatrix matrix;
    matrix.setScale(SkIntToScalar(width), SK_Scalar1);

    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
                                               SkShader::kClamp_TileMode, &matrix);

    paint->setShader(s)->unref();
}
Exemplo n.º 21
0
template <bool doSwapRB, AlphaVerb doAlpha> uint32_t convert32(uint32_t c) {
    if (doSwapRB) {
        c = SkSwizzle_RB(c);
    }

    // Lucky for us, in both RGBA and BGRA, the alpha component is always in the same place, so
    // we can perform premul or unpremul the same way without knowing the swizzles for RGB.
    switch (doAlpha) {
        case kNothing_AlphaVerb:
            // no change
            break;
        case kPremul_AlphaVerb:
            c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c),
                                  SkGetPackedG32(c), SkGetPackedB32(c));
            break;
        case kUnpremul_AlphaVerb:
            c = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(c);
            break;
    }
    return c;
}
Exemplo n.º 22
0
DragImageRef dissolveDragImageToFraction(DragImageRef image, float fraction)
{
    if (!image)
        return 0;

    image->bitmap->setIsOpaque(false);
    image->bitmap->lockPixels();

    for (int row = 0; row < image->bitmap->height(); ++row) {
        for (int column = 0; column < image->bitmap->width(); ++column) {
            uint32_t* pixel = image->bitmap->getAddr32(column, row);
            *pixel = SkPreMultiplyARGB(SkColorGetA(*pixel) * fraction,
                                       SkColorGetR(*pixel),
                                       SkColorGetG(*pixel),
                                       SkColorGetB(*pixel));
        }
    }

    image->bitmap->unlockPixels();

    return image;
}
Exemplo n.º 23
0
bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
                                 SkBitmap::Config prefConfig, Mode mode) {
//    SkAutoTrace    apr("SkPNGImageDecoder::onDecode");

    /* Create and initialize the png_struct with the desired error handler
    * functions.  If you want to use the default stderr and longjump method,
    * you can supply NULL for the last three parameters.  We also supply the
    * the compiler header file version, so that we know if the application
    * was compiled with a compatible version of the library.  */
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
        NULL, sk_error_fn, NULL);
    //   png_voidp user_error_ptr, user_error_fn, user_warning_fn);
    if (png_ptr == NULL) {
        return false;
    }

    /* Allocate/initialize the memory for image information. */
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
        return false;
    }

    PNGAutoClean autoClean(png_ptr, info_ptr);

    /* Set error handling if you are using the setjmp/longjmp method (this is
    * the normal method of doing things with libpng).  REQUIRED unless you
    * set up your own error handlers in the png_create_read_struct() earlier.
    */
    if (setjmp(png_jmpbuf(png_ptr))) {
        return false;
    }

    /* If you are using replacement read functions, instead of calling
    * png_init_io() here you would call:
    */
    png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn);
    /* where user_io_ptr is a structure you want available to the callbacks */
    /* If we have already read some of the signature */
//  png_set_sig_bytes(png_ptr, 0 /* sig_read */ );

    // hookup our peeker so we can see any user-chunks the caller may be interested in
    png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"", 0);
    if (this->getPeeker()) {
        png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_read_user_chunk);
    }

    /* The call to png_read_info() gives us all of the information from the
    * PNG file before the first IDAT (image data chunk). */
    png_read_info(png_ptr, info_ptr);
    png_uint_32 origWidth, origHeight;
    int bit_depth, color_type, interlace_type;
    png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth, &color_type,
        &interlace_type, int_p_NULL, int_p_NULL);

    SkBitmap::Config    config;
    bool                hasAlpha = false;
    bool                doDither = this->getDitherImage();
    
    // check for sBIT chunk data, in case we should disable dithering because
    // our data is not truely 8bits per component
    if (doDither) {
#if 0
        SkDebugf("----- sBIT %d %d %d %d\n", info_ptr->sig_bit.red,
                 info_ptr->sig_bit.green, info_ptr->sig_bit.blue,
                 info_ptr->sig_bit.alpha);
#endif
        // 0 seems to indicate no information available
        if (pos_le(info_ptr->sig_bit.red, SK_R16_BITS) &&
                pos_le(info_ptr->sig_bit.green, SK_G16_BITS) &&
                pos_le(info_ptr->sig_bit.blue, SK_B16_BITS)) {
            doDither = false;
        }
    }
    
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        config = SkBitmap::kIndex8_Config;  // defer sniffing for hasAlpha
    } else {
        png_color_16p   transColor;
        
        png_get_tRNS(png_ptr, info_ptr, NULL, NULL, &transColor);
        
        if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ||
                PNG_COLOR_TYPE_RGB_ALPHA == color_type ||
                PNG_COLOR_TYPE_GRAY_ALPHA == color_type) {
            hasAlpha = true;
            config = SkBitmap::kARGB_8888_Config;
        } else {    // we get to choose the config
            config = prefConfig;
            if (config == SkBitmap::kNo_Config) {
                config = SkImageDecoder::GetDeviceConfig();
            }
            if (config != SkBitmap::kRGB_565_Config &&
                    config != SkBitmap::kARGB_4444_Config) {
                config = SkBitmap::kARGB_8888_Config;
            }
        }
    }
    
    if (!this->chooseFromOneChoice(config, origWidth, origHeight)) {
        return false;
    }
    
    const int sampleSize = this->getSampleSize();
    SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);

    decodedBitmap->setConfig(config, sampler.scaledWidth(),
                             sampler.scaledHeight(), 0);
    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
        return true;
    }
    
    // from here down we are concerned with colortables and pixels

    /* tell libpng to strip 16 bit/color files down to 8 bits/color */
    if (bit_depth == 16) {
        png_set_strip_16(png_ptr);
    }
    /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
    * byte into separate bytes (useful for paletted and grayscale images). */
    if (bit_depth < 8) {
        png_set_packing(png_ptr);
    }
    /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
        png_set_gray_1_2_4_to_8(png_ptr);
    }

    /* Make a grayscale image into RGB. */
    if (color_type == PNG_COLOR_TYPE_GRAY ||
            color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
        png_set_gray_to_rgb(png_ptr);
    }

    // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype
    // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
    // draw lots faster if we can flag the bitmap has being opaque
    bool reallyHasAlpha = false;

    SkColorTable* colorTable = NULL;

    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        int num_palette;
        png_colorp palette;
        png_bytep trans;
        int num_trans;

        png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
        
        /*  BUGGY IMAGE WORKAROUND
            
            We hit some images (e.g. fruit_.png) who contain bytes that are == colortable_count
            which is a problem since we use the byte as an index. To work around this we grow
            the colortable by 1 (if its < 256) and duplicate the last color into that slot.
        */
        int colorCount = num_palette + (num_palette < 256);

        colorTable = SkNEW_ARGS(SkColorTable, (colorCount));

        SkPMColor* colorPtr = colorTable->lockColors();
        if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
            png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
            hasAlpha = (num_trans > 0);
        } else {
            num_trans = 0;
            colorTable->setFlags(colorTable->getFlags() | SkColorTable::kColorsAreOpaque_Flag);
        }        
        // check for bad images that might make us crash
        if (num_trans > num_palette) {
            num_trans = num_palette;
        }

        int index = 0;
        int transLessThanFF = 0;

        for (; index < num_trans; index++) {
            transLessThanFF |= (int)*trans - 0xFF;
            *colorPtr++ = SkPreMultiplyARGB(*trans++, palette->red, palette->green, palette->blue);
            palette++;
        }
        reallyHasAlpha |= (transLessThanFF < 0);

        for (; index < num_palette; index++) {
            *colorPtr++ = SkPackARGB32(0xFF, palette->red, palette->green, palette->blue);
            palette++;
        }

        // see BUGGY IMAGE WORKAROUND comment above
        if (num_palette < 256) {
            *colorPtr = colorPtr[-1];
        }
        colorTable->unlockColors(true);
    }
    
    SkAutoUnref aur(colorTable);

    if (!this->allocPixelRef(decodedBitmap, colorTable)) {
        delete colorTable;
        return false;
    }
    
    SkAutoLockPixels alp(*decodedBitmap);

    /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
//  if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
//      ; // png_set_swap_alpha(png_ptr);

    /* swap bytes of 16 bit files to least significant byte first */
    //   png_set_swap(png_ptr);

    /* Add filler (or alpha) byte (before/after each RGB triplet) */
    if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) {
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
    }

    /* Turn on interlace handling.  REQUIRED if you are not using
    * png_read_image().  To see how to handle interlacing passes,
    * see the png_read_row() method below:
    */
    const int number_passes = interlace_type != PNG_INTERLACE_NONE ? 
                        png_set_interlace_handling(png_ptr) : 1;

    /* Optional call to gamma correct and add the background to the palette
    * and update info structure.  REQUIRED if you are expecting libpng to
    * update the palette for you (ie you selected such a transform above).
    */
    png_read_update_info(png_ptr, info_ptr);

    if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) {
        for (int i = 0; i < number_passes; i++) {
            for (png_uint_32 y = 0; y < origHeight; y++) {
                uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
                png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
            }
        }
    } else {
        SkScaledBitmapSampler::SrcConfig sc;
        int srcBytesPerPixel = 4;
        
        if (SkBitmap::kIndex8_Config == config) {
            sc = SkScaledBitmapSampler::kIndex;
            srcBytesPerPixel = 1;
        } else if (hasAlpha) {
            sc = SkScaledBitmapSampler::kRGBA;
        } else {
            sc = SkScaledBitmapSampler::kRGBX;
        }

        SkAutoMalloc storage(origWidth * srcBytesPerPixel);
        const int height = decodedBitmap->height();

        for (int i = 0; i < number_passes; i++) {
            if (!sampler.begin(decodedBitmap, sc, doDither)) {
                return false;
            }

            uint8_t* srcRow = (uint8_t*)storage.get();
            skip_src_rows(png_ptr, srcRow, sampler.srcY0());

            for (int y = 0; y < height; y++) {
                uint8_t* tmp = srcRow;
                png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
                reallyHasAlpha |= sampler.next(srcRow);
                if (y < height - 1) {
                    skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
                }
            }
            
            // skip the rest of the rows (if any)
            png_uint_32 read = (height - 1) * sampler.srcDY() +
                               sampler.srcY0() + 1;
            SkASSERT(read <= origHeight);
            skip_src_rows(png_ptr, srcRow, origHeight - read);
        }

        if (hasAlpha && !reallyHasAlpha) {
            SkDEBUGF(("Image doesn't really have alpha [%d %d]\n",
                      origWidth, origHeight));
        }
    }

    /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
    png_read_end(png_ptr, info_ptr);

    decodedBitmap->setIsOpaque(!reallyHasAlpha);
    return true;
}
Exemplo n.º 24
0
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ApplyGamma, reporter, ctxInfo) {
    GrContext* context = ctxInfo.grContext();
    static const int kW = 256;
    static const int kH = 256;
    static const size_t kRowBytes = sizeof(uint32_t) * kW;

    GrSurfaceDesc baseDesc;
    baseDesc.fConfig = kRGBA_8888_GrPixelConfig;
    baseDesc.fWidth = kW;
    baseDesc.fHeight = kH;

    const SkImageInfo ii = SkImageInfo::MakeN32Premul(kW, kH);

    SkAutoTMalloc<uint32_t> srcPixels(kW * kH);
    for (int y = 0; y < kH; ++y) {
        for (int x = 0; x < kW; ++x) {
            srcPixels.get()[y*kW+x] = SkPreMultiplyARGB(x, y, x, 0xFF);
        }
    }

    SkBitmap bm;
    bm.installPixels(ii, srcPixels.get(), kRowBytes);

    SkAutoTMalloc<uint32_t> read(kW * kH);

    // We allow more error on GPUs with lower precision shader variables.
    float error = context->caps()->shaderCaps()->floatPrecisionVaries() ? 1.2f : 0.5f;

    for (auto toSRGB : { false, true }) {
        sk_sp<SkSurface> dst(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii));

        if (!dst) {
            ERRORF(reporter, "Could not create surfaces for copy surface test.");
            continue;
        }

        SkCanvas* dstCanvas = dst->getCanvas();

        dstCanvas->clear(SK_ColorRED);
        dstCanvas->flush();

        SkPaint gammaPaint;
        gammaPaint.setBlendMode(SkBlendMode::kSrc);
        gammaPaint.setColorFilter(toSRGB ? SkColorFilter::MakeLinearToSRGBGamma()
                                         : SkColorFilter::MakeSRGBToLinearGamma());

        dstCanvas->drawBitmap(bm, 0, 0, &gammaPaint);
        dstCanvas->flush();

        sk_memset32(read.get(), 0, kW * kH);
        if (!dstCanvas->readPixels(ii, read.get(), kRowBytes, 0, 0)) {
            ERRORF(reporter, "Error calling readPixels");
            continue;
        }

        bool abort = false;
        // Validate that pixels were copied/transformed correctly.
        for (int y = 0; y < kH && !abort; ++y) {
            for (int x = 0; x < kW && !abort; ++x) {
                uint32_t r = read.get()[y * kW + x];
                uint32_t s = srcPixels.get()[y * kW + x];
                uint32_t expected;
                if (!check_gamma(s, r, toSRGB, error, &expected)) {
                    ERRORF(reporter, "Expected dst %d,%d to contain 0x%08x "
                           "from src 0x%08x and mode %s. Got %08x", x, y, expected, s,
                           toSRGB ? "ToSRGB" : "ToLinear", r);
                    abort = true;
                    break;
                }
            }
        }
    }
}