예제 #1
0
/*
 *  High quality is implemented by performing up-right scale-only filtering and then
 *  using bilerp for any remaining transformations.
 */
bool SkDefaultBitmapControllerState::processHQRequest(const SkBitmap& origBitmap) {
    if (fQuality != kHigh_SkFilterQuality) {
        return false;
    }
    
    // Our default return state is to downgrade the request to Medium, w/ or w/o setting fBitmap
    // to a valid bitmap. If we succeed, we will set this to Low instead.
    fQuality = kMedium_SkFilterQuality;
    
    if (kN32_SkColorType != origBitmap.colorType() || !cache_size_okay(origBitmap, fInvMatrix) ||
        fInvMatrix.hasPerspective())
    {
        return false; // can't handle the reqeust
    }
    
    SkScalar invScaleX = fInvMatrix.getScaleX();
    SkScalar invScaleY = fInvMatrix.getScaleY();
    if (fInvMatrix.getType() & SkMatrix::kAffine_Mask) {
        SkSize scale;
        if (!fInvMatrix.decomposeScale(&scale)) {
            return false;
        }
        invScaleX = scale.width();
        invScaleY = scale.height();
    }
    if (SkScalarNearlyEqual(invScaleX, 1) && SkScalarNearlyEqual(invScaleY, 1)) {
        return false; // no need for HQ
    }
    
    SkScalar trueDestWidth  = origBitmap.width() / invScaleX;
    SkScalar trueDestHeight = origBitmap.height() / invScaleY;
    SkScalar roundedDestWidth = SkScalarRoundToScalar(trueDestWidth);
    SkScalar roundedDestHeight = SkScalarRoundToScalar(trueDestHeight);
    
    if (!SkBitmapCache::Find(origBitmap, roundedDestWidth, roundedDestHeight, &fResultBitmap)) {
        SkAutoPixmapUnlock src;
        if (!origBitmap.requestLock(&src)) {
            return false;
        }
        if (!SkBitmapScaler::Resize(&fResultBitmap, src.pixmap(), SkBitmapScaler::RESIZE_BEST,
                                    roundedDestWidth, roundedDestHeight,
                                    SkResourceCache::GetAllocator())) {
            return false; // we failed to create fScaledBitmap
        }
        
        SkASSERT(fResultBitmap.getPixels());
        fResultBitmap.setImmutable();
        SkBitmapCache::Add(origBitmap, roundedDestWidth, roundedDestHeight, fResultBitmap);
    }
    
    SkASSERT(fResultBitmap.getPixels());
    
    fInvMatrix.postScale(roundedDestWidth / origBitmap.width(),
                         roundedDestHeight / origBitmap.height());
    fQuality = kLow_SkFilterQuality;
    return true;
}
예제 #2
0
void SkBinaryWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
    // Record the width and height. This way if readBitmap fails a dummy bitmap can be drawn at the
    // right size.
    this->writeInt(bitmap.width());
    this->writeInt(bitmap.height());

    // Record information about the bitmap in one of two ways, in order of priority:
    // 1. If there is a function for encoding bitmaps, use it to write an encoded version of the
    //    bitmap. After writing a boolean value of false, signifying that a heap was not used, write
    //    the size of the encoded data. A non-zero size signifies that encoded data was written.
    // 2. Call SkBitmap::flatten. After writing a boolean value of false, signifying that a heap was
    //    not used, write a zero to signify that the data was not encoded.

    // Write a bool to indicate that we did not use an SkBitmapHeap. That feature is deprecated.
    this->writeBool(false);

    SkPixelRef* pixelRef = bitmap.pixelRef();
    if (pixelRef) {
        // see if the pixelref already has an encoded version
        SkAutoDataUnref existingData(pixelRef->refEncodedData());
        if (existingData.get() != nullptr) {
            // Assumes that if the client did not set a serializer, they are
            // happy to get the encoded data.
            if (!fPixelSerializer || fPixelSerializer->useEncodedData(existingData->data(),
                                                                      existingData->size())) {
                write_encoded_bitmap(this, existingData, bitmap.pixelRefOrigin());
                return;
            }
        }

        // see if the caller wants to manually encode
        SkAutoPixmapUnlock result;
        if (fPixelSerializer && bitmap.requestLock(&result)) {
            SkAutoDataUnref data(fPixelSerializer->encode(result.pixmap()));
            if (data.get() != nullptr) {
                // if we have to "encode" the bitmap, then we assume there is no
                // offset to share, since we are effectively creating a new pixelref
                write_encoded_bitmap(this, data, SkIPoint::Make(0, 0));
                return;
            }
        }
    }

    this->writeUInt(0); // signal raw pixels
    SkBitmap::WriteRawPixels(this, bitmap);
}
예제 #3
0
SkData* SkImage::encode(SkPixelSerializer* serializer) const {
    DefaultSerializer defaultSerializer;
    SkPixelSerializer* effectiveSerializer = serializer ? serializer : &defaultSerializer;

    SkAutoTUnref<SkData> encoded(this->refEncoded());
    if (encoded && effectiveSerializer->useEncodedData(encoded->data(), encoded->size())) {
        return encoded.detach();
    }

    SkBitmap bm;
    SkAutoPixmapUnlock apu;
    if (as_IB(this)->getROPixels(&bm) && bm.requestLock(&apu)) {
        const SkPixmap& pmap = apu.pixmap();
        return effectiveSerializer->encodePixels(pmap.info(), pmap.addr(), pmap.rowBytes());
    }

    return nullptr;
}
예제 #4
0
sk_sp<SkPDFObject> SkPDFCreateBitmapObject(sk_sp<SkImage> image,
                                           SkPixelSerializer* pixelSerializer) {
    SkASSERT(image);
    sk_sp<SkData> data(image->refEncoded());
    SkJFIFInfo info;
    if (data && SkIsJFIF(data.get(), &info) &&
        (!pixelSerializer ||
         pixelSerializer->useEncodedData(data->data(), data->size()))) {
        // If there is a SkPixelSerializer, give it a chance to
        // re-encode the JPEG with more compression by returning false
        // from useEncodedData.
        bool yuv = info.fType == SkJFIFInfo::kYCbCr;
        if (info.fSize == image->dimensions()) {  // Sanity check.
            // hold on to data, not image.
            #ifdef SK_PDF_IMAGE_STATS
            gJpegImageObjects.fetch_add(1);
            #endif
            return sk_make_sp<PDFJpegBitmap>(info.fSize, data.get(), yuv);
        }
    }

    if (pixelSerializer) {
        SkBitmap bm;
        SkAutoPixmapUnlock apu;
        if (as_IB(image.get())->getROPixels(&bm) && bm.requestLock(&apu)) {
            data.reset(pixelSerializer->encode(apu.pixmap()));
            if (data && SkIsJFIF(data.get(), &info)) {
                bool yuv = info.fType == SkJFIFInfo::kYCbCr;
                if (info.fSize == image->dimensions()) {  // Sanity check.
                    return sk_make_sp<PDFJpegBitmap>(info.fSize, data.get(), yuv);
                }
            }
        }
    }

    sk_sp<SkPDFObject> smask;
    if (!image_compute_is_opaque(image.get())) {
        smask = sk_make_sp<PDFAlphaBitmap>(image);
    }
    #ifdef SK_PDF_IMAGE_STATS
    gRegularImageObjects.fetch_add(1);
    #endif
    return sk_make_sp<PDFDefaultBitmap>(std::move(image), std::move(smask));
}
예제 #5
0
파일: SkImage.cpp 프로젝트: YangchenVR/skia
SkData* SkImage::encode(SkPixelSerializer* serializer) const {
    SkAutoTUnref<SkPixelSerializer> defaultSerializer;
    SkPixelSerializer* effectiveSerializer = serializer;
    if (!effectiveSerializer) {
        defaultSerializer.reset(SkImageEncoder::CreatePixelSerializer());
        SkASSERT(defaultSerializer.get());
        effectiveSerializer = defaultSerializer.get();
    }
    SkAutoTUnref<SkData> encoded(this->refEncoded());
    if (encoded && effectiveSerializer->useEncodedData(encoded->data(), encoded->size())) {
        return encoded.detach();
    }

    SkBitmap bm;
    SkAutoPixmapUnlock apu;
    if (as_IB(this)->getROPixels(&bm) && bm.requestLock(&apu)) {
        return effectiveSerializer->encode(apu.pixmap());
    }

    return nullptr;
}
예제 #6
0
/*
 *  High quality is implemented by performing up-right scale-only filtering and then
 *  using bilerp for any remaining transformations.
 */
bool SkDefaultBitmapControllerState::processHQRequest(const SkBitmapProvider& provider) {
    if (fQuality != kHigh_SkFilterQuality) {
        return false;
    }

    // Our default return state is to downgrade the request to Medium, w/ or w/o setting fBitmap
    // to a valid bitmap. If we succeed, we will set this to Low instead.
    fQuality = kMedium_SkFilterQuality;

    if (kN32_SkColorType != provider.info().colorType() || !cache_size_okay(provider, fInvMatrix) ||
            fInvMatrix.hasPerspective())
    {
        return false; // can't handle the reqeust
    }

    SkScalar invScaleX = fInvMatrix.getScaleX();
    SkScalar invScaleY = fInvMatrix.getScaleY();
    if (fInvMatrix.getType() & SkMatrix::kAffine_Mask) {
        SkSize scale;
        if (!fInvMatrix.decomposeScale(&scale)) {
            return false;
        }
        invScaleX = scale.width();
        invScaleY = scale.height();
    }
    if (SkScalarNearlyEqual(invScaleX, 1) && SkScalarNearlyEqual(invScaleY, 1)) {
        return false; // no need for HQ
    }

#ifndef SK_SUPPORT_LEGACY_HQ_DOWNSAMPLING
    if (invScaleX > 1 || invScaleY > 1) {
        return false; // only use HQ when upsampling
    }
#endif

    const int dstW = SkScalarRoundToScalar(provider.width() / invScaleX);
    const int dstH = SkScalarRoundToScalar(provider.height() / invScaleY);
    const SkBitmapCacheDesc desc = provider.makeCacheDesc(dstW, dstH);

    if (!SkBitmapCache::FindWH(desc, &fResultBitmap)) {
        SkBitmap orig;
        if (!provider.asBitmap(&orig)) {
            return false;
        }
        SkAutoPixmapUnlock src;
        if (!orig.requestLock(&src)) {
            return false;
        }
        if (!SkBitmapScaler::Resize(&fResultBitmap, src.pixmap(), kHQ_RESIZE_METHOD,
                                    dstW, dstH, SkResourceCache::GetAllocator())) {
            return false; // we failed to create fScaledBitmap
        }

        SkASSERT(fResultBitmap.getPixels());
        fResultBitmap.setImmutable();
        if (!provider.isVolatile()) {
            if (SkBitmapCache::AddWH(desc, fResultBitmap)) {
                provider.notifyAddedToCache();
            }
        }
    }

    SkASSERT(fResultBitmap.getPixels());

    fInvMatrix.postScale(SkIntToScalar(dstW) / provider.width(),
                         SkIntToScalar(dstH) / provider.height());
    fQuality = kLow_SkFilterQuality;
    return true;
}
예제 #7
0
void SkWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
    // Record the width and height. This way if readBitmap fails a dummy bitmap can be drawn at the
    // right size.
    this->writeInt(bitmap.width());
    this->writeInt(bitmap.height());

    // Record information about the bitmap in one of three ways, in order of priority:
    // 1. If there is an SkBitmapHeap, store it in the heap. The client can avoid serializing the
    //    bitmap entirely or serialize it later as desired. A boolean value of true will be written
    //    to the stream to signify that a heap was used.
    // 2. If there is a function for encoding bitmaps, use it to write an encoded version of the
    //    bitmap. After writing a boolean value of false, signifying that a heap was not used, write
    //    the size of the encoded data. A non-zero size signifies that encoded data was written.
    // 3. Call SkBitmap::flatten. After writing a boolean value of false, signifying that a heap was
    //    not used, write a zero to signify that the data was not encoded.
    bool useBitmapHeap = fBitmapHeap != NULL;
    // Write a bool: true if the SkBitmapHeap is to be used, in which case the reader must use an
    // SkBitmapHeapReader to read the SkBitmap. False if the bitmap was serialized another way.
    this->writeBool(useBitmapHeap);
    if (useBitmapHeap) {
        SkASSERT(NULL == fPixelSerializer);
        int32_t slot = fBitmapHeap->insert(bitmap);
        fWriter.write32(slot);
        // crbug.com/155875
        // The generation ID is not required information. We write it to prevent collisions
        // in SkFlatDictionary.  It is possible to get a collision when a previously
        // unflattened (i.e. stale) instance of a similar flattenable is in the dictionary
        // and the instance currently being written is re-using the same slot from the
        // bitmap heap.
        fWriter.write32(bitmap.getGenerationID());
        return;
    }

    SkPixelRef* pixelRef = bitmap.pixelRef();
    if (pixelRef) {
        // see if the pixelref already has an encoded version
        SkAutoDataUnref existingData(pixelRef->refEncodedData());
        if (existingData.get() != NULL) {
            // Assumes that if the client did not set a serializer, they are
            // happy to get the encoded data.
            if (!fPixelSerializer || fPixelSerializer->useEncodedData(existingData->data(),
                                                                      existingData->size())) {
                write_encoded_bitmap(this, existingData, bitmap.pixelRefOrigin());
                return;
            }
        }

        // see if the caller wants to manually encode
        SkAutoPixmapUnlock result;
        if (fPixelSerializer && bitmap.requestLock(&result)) {
            const SkPixmap& pmap = result.pixmap();
            SkASSERT(NULL == fBitmapHeap);
            SkAutoDataUnref data(fPixelSerializer->encodePixels(pmap.info(),
                                                                pmap.addr(),
                                                                pmap.rowBytes()));
            if (data.get() != NULL) {
                // if we have to "encode" the bitmap, then we assume there is no
                // offset to share, since we are effectively creating a new pixelref
                write_encoded_bitmap(this, data, SkIPoint::Make(0, 0));
                return;
            }
        }
    }

    this->writeUInt(0); // signal raw pixels
    SkBitmap::WriteRawPixels(this, bitmap);
}