static SkStream* extract_argb8888_data(const SkBitmap& bitmap, const SkIRect& srcRect, bool extractAlpha, bool* isOpaque, bool* isTransparent) { SkStream* stream; if (extractAlpha) { stream = SkNEW_ARGS(SkMemoryStream, (srcRect.width() * srcRect.height())); } else { stream = SkNEW_ARGS(SkMemoryStream, (get_uncompressed_size(bitmap, srcRect))); } uint8_t* dst = (uint8_t*)stream->getMemoryBase(); for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { uint32_t* src = bitmap.getAddr32(0, y); for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { if (extractAlpha) { dst[0] = SkGetPackedA32(src[x]); *isOpaque &= dst[0] == SK_AlphaOPAQUE; *isTransparent &= dst[0] == SK_AlphaTRANSPARENT; dst++; } else { dst[0] = SkGetPackedR32(src[x]); dst[1] = SkGetPackedG32(src[x]); dst[2] = SkGetPackedB32(src[x]); dst += 3; } } } return stream; }
bool SkPDFImage::populate(SkPDFCatalog* catalog) { if (getState() == kUnused_State) { // Initializing image data for the first time. SkDynamicMemoryWStream dctCompressedWStream; if (!skip_compression(catalog) && fEncoder && get_uncompressed_size(fBitmap, fSrcRect) > 1) { SkBitmap subset; // Extract subset if (!fBitmap.extractSubset(&subset, fSrcRect)) { return false; } size_t pixelRefOffset = 0; SkAutoTUnref<SkData> data(fEncoder(&pixelRefOffset, subset)); if (data.get() && data->size() < get_uncompressed_size(fBitmap, fSrcRect)) { this->setData(data.get()); insertName("Filter", "DCTDecode"); insertInt("ColorTransform", kNoColorTransform); insertInt("Length", this->dataSize()); setState(kCompressed_State); return true; } } // Fallback method if (!fStreamValid) { SkAutoTUnref<SkStream> stream( extract_image_data(fBitmap, fSrcRect, fIsAlpha, NULL)); this->setData(stream); fStreamValid = true; } return INHERITED::populate(catalog); } else if (getState() == kNoCompression_State && !skip_compression(catalog) && (SkFlate::HaveFlate() || fEncoder)) { // Compression has not been requested when the stream was first created, // but the new catalog wants it compressed. if (!getSubstitute()) { SkPDFStream* substitute = SkNEW_ARGS(SkPDFImage, (*this)); setSubstitute(substitute); catalog->setSubstitute(this, substitute); } return false; } return true; }
static SkStream* extract_argb4444_data(const SkBitmap& bitmap, const SkIRect& srcRect, bool extractAlpha, bool* isOpaque, bool* isTransparent) { SkStream* stream; uint8_t* dst = NULL; if (extractAlpha) { const int alphaRowBytes = (srcRect.width() + 1) / 2; stream = SkNEW_ARGS(SkMemoryStream, (alphaRowBytes * srcRect.height())); } else { stream = SkNEW_ARGS(SkMemoryStream, (get_uncompressed_size(bitmap, srcRect))); } dst = (uint8_t*)stream->getMemoryBase(); for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { uint16_t* src = bitmap.getAddr16(0, y); int x; for (x = srcRect.fLeft; x + 1 < srcRect.fRight; x += 2) { if (extractAlpha) { dst[0] = (SkGetPackedA4444(src[x]) << 4) | SkGetPackedA4444(src[x + 1]); *isOpaque &= dst[0] == SK_AlphaOPAQUE; *isTransparent &= dst[0] == SK_AlphaTRANSPARENT; dst++; } else { dst[0] = (SkGetPackedR4444(src[x]) << 4) | SkGetPackedG4444(src[x]); dst[1] = (SkGetPackedB4444(src[x]) << 4) | SkGetPackedR4444(src[x + 1]); dst[2] = (SkGetPackedG4444(src[x + 1]) << 4) | SkGetPackedB4444(src[x + 1]); dst += 3; } } if (srcRect.width() & 1) { if (extractAlpha) { dst[0] = (SkGetPackedA4444(src[x]) << 4); *isOpaque &= dst[0] == (SK_AlphaOPAQUE & 0xF0); *isTransparent &= dst[0] == (SK_AlphaTRANSPARENT & 0xF0); dst++; } else { dst[0] = (SkGetPackedR4444(src[x]) << 4) | SkGetPackedG4444(src[x]); dst[1] = (SkGetPackedB4444(src[x]) << 4); dst += 2; } } } return stream; }
static SkStream* extract_index8_image(const SkBitmap& bitmap, const SkIRect& srcRect) { const int rowBytes = srcRect.width(); SkStream* stream = SkNEW_ARGS(SkMemoryStream, (get_uncompressed_size(bitmap, srcRect))); uint8_t* dst = (uint8_t*)stream->getMemoryBase(); for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { memcpy(dst, bitmap.getAddr8(srcRect.fLeft, y), rowBytes); dst += rowBytes; } return stream; }
static SkStream* extract_gray8_image(const SkBitmap& bitmap, const SkIRect& srcRect) { SkStream* stream = SkNEW_ARGS(SkMemoryStream, (get_uncompressed_size(bitmap, srcRect))); uint8_t* dst = (uint8_t*)stream->getMemoryBase(); for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { uint8_t* src = bitmap.getAddr8(0, y); for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { dst[0] = dst[1] = dst[2] = src[x]; dst += 3; } } return stream; }
static SkStream* extract_argb8888_data(const SkBitmap& bitmap, const SkIRect& srcRect, bool extractAlpha, bool* isOpaque, bool* isTransparent) { size_t streamSize = extractAlpha ? srcRect.width() * srcRect.height() : get_uncompressed_size(bitmap, srcRect); SkStream* stream = SkNEW_ARGS(SkMemoryStream, (streamSize)); uint8_t* dst = (uint8_t*)stream->getMemoryBase(); const SkUnPreMultiply::Scale* scaleTable = SkUnPreMultiply::GetScaleTable(); for (int y = srcRect.fTop; y < srcRect.fBottom; y++) { uint32_t* src = bitmap.getAddr32(0, y); for (int x = srcRect.fLeft; x < srcRect.fRight; x++) { SkPMColor c = src[x]; U8CPU alpha = SkGetPackedA32(c); if (extractAlpha) { *isOpaque &= alpha == SK_AlphaOPAQUE; *isTransparent &= alpha == SK_AlphaTRANSPARENT; *dst++ = alpha; } else { if (SK_AlphaTRANSPARENT == alpha) { // It is necessary to average the color component of // transparent pixels with their surrounding neighbors // since the PDF renderer may separately re-sample the // alpha and color channels when the image is not // displayed at its native resolution. Since an alpha of // zero gives no information about the color component, // the pathological case is a white image with sharp // transparency bounds - the color channel goes to black, // and the should-be-transparent pixels are rendered // as grey because of the separate soft mask and color // resizing. c = get_argb8888_neighbor_avg_color(bitmap, x, y); *dst++ = SkGetPackedR32(c); *dst++ = SkGetPackedG32(c); *dst++ = SkGetPackedB32(c); } else { SkUnPreMultiply::Scale s = scaleTable[alpha]; *dst++ = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c)); *dst++ = SkUnPreMultiply::ApplyScale(s, SkGetPackedG32(c)); *dst++ = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(c)); } } } } SkASSERT(dst == streamSize + (uint8_t*)stream->getMemoryBase()); return stream; }
static int fuse_unecm_getattr(const char *path, struct stat *stbuf) { int ret; LOG("GETATTR [%s]\n", path); if (path[0] == '/') { path++; } ret = fstatat(dir_fd, path, stbuf, AT_NO_AUTOMOUNT|AT_EMPTY_PATH); if (ret && errno == ENOENT) { if (need_ecm_uncompress(path)) { char tmp[PATH_MAX]; int fd; snprintf(tmp, PATH_MAX, "%s.ecm", path); ret = fstatat(dir_fd, tmp, stbuf, AT_NO_AUTOMOUNT); if (ret) { LOG("GETATTR fstatat failed [%s] %s\n", path, strerror(errno)); return -errno; } stbuf->st_size = get_uncompressed_size(tmp); LOG("GETATTR [%s] SUCCESS\n", path); return 0; } } if (ret) { LOG("GETATTR [%s] SUCCESS\n", path); return -errno; } LOG("GETATTR [%s] SUCCESS\n", path); return 0; }