/* Fill out buffer with the compressed format Ganesh expects from a colortable based bitmap. [palette (colortable) + indices]. At the moment Ganesh only supports 8bit version. If Ganesh allowed we others we could detect that the colortable.count is <= 16, and then repack the indices as nibbles to save RAM, but it would take more time (i.e. a lot slower than memcpy), so skipping that for now. Ganesh wants a full 256 palette entry, even though Skia's ctable is only as big as the colortable.count says it is. */ static void build_compressed_data(void* buffer, const SkBitmap& bitmap) { SkASSERT(SkBitmap::kIndex8_Config == bitmap.config()); SkAutoLockPixels alp(bitmap); if (!bitmap.readyToDraw()) { SkDEBUGFAIL("bitmap not ready to draw!"); return; } SkColorTable* ctable = bitmap.getColorTable(); char* dst = (char*)buffer; const int count = ctable->count(); SkDstPixelInfo dstPI; dstPI.fColorType = kRGBA_8888_SkColorType; dstPI.fAlphaType = kPremul_SkAlphaType; dstPI.fPixels = buffer; dstPI.fRowBytes = count * sizeof(SkPMColor); SkSrcPixelInfo srcPI; srcPI.fColorType = kPMColor_SkColorType; srcPI.fAlphaType = kPremul_SkAlphaType; srcPI.fPixels = ctable->lockColors(); srcPI.fRowBytes = count * sizeof(SkPMColor); srcPI.convertPixelsTo(&dstPI, count, 1); ctable->unlockColors(); // always skip a full 256 number of entries, even if we memcpy'd fewer dst += kGrColorTableSize; if ((unsigned)bitmap.width() == bitmap.rowBytes()) { memcpy(dst, bitmap.getPixels(), bitmap.getSize()); } else { // need to trim off the extra bytes per row size_t width = bitmap.width(); size_t rowBytes = bitmap.rowBytes(); const char* src = (const char*)bitmap.getPixels(); for (int y = 0; y < bitmap.height(); y++) { memcpy(dst, src, width); src += rowBytes; dst += width; } } }
bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB, SkColorTable* ctable) { if (srcInfo.dimensions() != dstInfo.dimensions()) { return false; } const int width = srcInfo.width(); const int height = srcInfo.height(); // Handle fancy alpha swizzling if both are ARGB32 if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel()) { SkDstPixelInfo dstPI; dstPI.fColorType = dstInfo.colorType(); dstPI.fAlphaType = dstInfo.alphaType(); dstPI.fPixels = dstPixels; dstPI.fRowBytes = dstRB; SkSrcPixelInfo srcPI; srcPI.fColorType = srcInfo.colorType(); srcPI.fAlphaType = srcInfo.alphaType(); srcPI.fPixels = srcPixels; srcPI.fRowBytes = srcRB; return srcPI.convertPixelsTo(&dstPI, width, height); } // If they agree on colorType and the alphaTypes are compatible, then we just memcpy. // Note: we've already taken care of 32bit colortypes above. if (srcInfo.colorType() == dstInfo.colorType()) { switch (srcInfo.colorType()) { case kRGB_565_SkColorType: case kAlpha_8_SkColorType: break; case kIndex_8_SkColorType: case kARGB_4444_SkColorType: if (srcInfo.alphaType() != dstInfo.alphaType()) { return false; } break; default: return false; } rect_memcpy(dstPixels, dstRB, srcPixels, srcRB, width * srcInfo.bytesPerPixel(), height); return true; } /* * Begin section where we try to change colorTypes along the way. Not all combinations * are supported. */ // Can no longer draw directly into 4444, but we can manually whack it for a few combinations if (kARGB_4444_SkColorType == dstInfo.colorType() && (kN32_SkColorType == srcInfo.colorType() || kIndex_8_SkColorType == srcInfo.colorType())) { if (srcInfo.alphaType() == kUnpremul_SkAlphaType) { // Our method for converting to 4444 assumes premultiplied. return false; } const SkPMColor* table = NULL; if (kIndex_8_SkColorType == srcInfo.colorType()) { if (NULL == ctable) { return false; } table = ctable->readColors(); } for (int y = 0; y < height; ++y) { DITHER_4444_SCAN(y); SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*)dstPixels; if (table) { const uint8_t* SK_RESTRICT srcRow = (const uint8_t*)srcPixels; for (int x = 0; x < width; ++x) { dstRow[x] = SkDitherARGB32To4444(table[srcRow[x]], DITHER_VALUE(x)); } } else { const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)srcPixels; for (int x = 0; x < width; ++x) { dstRow[x] = SkDitherARGB32To4444(srcRow[x], DITHER_VALUE(x)); } } dstPixels = (char*)dstPixels + dstRB; srcPixels = (const char*)srcPixels + srcRB; } return true; }