bool ImageSource::frameHasAlphaAtIndex(size_t index)
{
#ifdef ANDROID_ANIMATED_GIF
    if (m_decoder.m_gifDecoder) {
        if (!m_decoder.m_gifDecoder->supportsAlpha())
            return false;

        RGBA32Buffer* buffer =
                m_decoder.m_gifDecoder->frameBufferAtIndex(index);
        if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
            return false;

        return buffer->hasAlpha();
    }
#else
    SkASSERT(0 == index);
#endif

    if (NULL == m_decoder.m_image)
        return true;    // if we're not sure, assume the worse-case
    const PrivateAndroidImageSourceRec& decoder = *m_decoder.m_image;
    // if we're 16bit, we know even without all the data available
    if (decoder.bitmap().getConfig() == SkBitmap::kRGB_565_Config)
        return false;

    if (!decoder.fAllDataReceived)
        return true;    // if we're not sure, assume the worse-case
    
    return !decoder.bitmap().isOpaque();
}
示例#2
0
bool ImageSource::frameIsCompleteAtIndex(size_t index)
{
    if (!m_decoder)
        return false;

    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    return buffer && buffer->status() == RGBA32Buffer::FrameComplete;
}
NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
{
    if (!m_decoder)
        return 0;

    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
        return 0;
    
    return buffer->asNewNativeImage();
}
示例#4
0
float ImageSource::frameDurationAtIndex(size_t index)
{
    if (!m_decoder)
        return 0;

    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
        return 0;

    return buffer->duration() / 1000.0f;
}
示例#5
0
bool ImageSource::frameHasAlphaAtIndex(size_t index)
{
    if (!m_decoder || !m_decoder->supportsAlpha())
        return false;

    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
        return false;

    return buffer->hasAlpha();
}
示例#6
0
NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
{
    if (!m_decoder)
        return 0;

    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
        return 0;
    
    IntRect imageRect = buffer->rect();
    unsigned char* bytes = (unsigned char*)buffer->bytes().data();
    long colorSize = buffer->bytes().size();
    
    typedef wxPixelData<wxBitmap, wxAlphaPixelFormat> PixelData;

    int width = size().width();
    int height = size().height();

    wxBitmap* bmp = new wxBitmap(width, height, 32);
    PixelData data(*bmp);
    
    int rowCounter = 0;
    long pixelCounter = 0;
    
    PixelData::Iterator p(data);
    
    PixelData::Iterator rowStart = p; 
    
    // NB: It appears that the data is in BGRA format instead of RGBA format.
    // This code works properly on both ppc and intel, meaning the issue is
    // likely not an issue of byte order getting mixed up on different archs. 
    for (long i = 0; i < buffer->bytes().size()*4; i+=4) {
        p.Red() = bytes[i+2];
        p.Green() = bytes[i+1];
        p.Blue() = bytes[i+0];
        p.Alpha() = bytes[i+3];
        
        p++;

        pixelCounter++;
        if ( (pixelCounter % width ) == 0 ) {
            rowCounter++;
            p = rowStart;
            p.MoveTo(data, 0, rowCounter);
        }

    }

    bmp->UseAlpha();
    ASSERT(bmp->IsOk());
    return bmp;
}
bool ImageSource::frameIsCompleteAtIndex(size_t index)
{
#ifdef ANDROID_ANIMATED_GIF
    if (m_decoder.m_gifDecoder) {
        RGBA32Buffer* buffer =
                m_decoder.m_gifDecoder->frameBufferAtIndex(index);
        return buffer && buffer->status() == RGBA32Buffer::FrameComplete;
    }
#else
    SkASSERT(0 == index);
#endif
	return m_decoder.m_image && m_decoder.m_image->fAllDataReceived;
}
示例#8
0
RGBA32Buffer* BMPImageDecoder::frameBufferAtIndex(size_t index)
{
    if (index)
        return 0;

    if (m_frameBufferCache.isEmpty())
        m_frameBufferCache.resize(1);

    RGBA32Buffer* buffer = &m_frameBufferCache.first();
    if (buffer->status() != RGBA32Buffer::FrameComplete)
        decode(false);
    return buffer;
}
RGBA32Buffer* RxIImageDecoder::frameBufferAtIndex(size_t index)
{
    if (index)
        return 0;

    RGBA32Buffer* frame = getUntouchedFrameBufferAtIndex(index);

    if (!frame)
        return 0;

    if (frame->status() != RGBA32Buffer::FrameComplete)
        decode(false);
    return frame;
}
示例#10
0
NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
{
    if (!m_decoder)
        return 0;

    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
        return 0;

    return cairo_image_surface_create_for_data((unsigned char*)buffer->bytes().data(),
                                               CAIRO_FORMAT_ARGB32,
                                               size().width(),
                                               buffer->height(),
                                               size().width()*4);
}
float ImageSource::frameDurationAtIndex(size_t index)
{
    if (!m_decoder)
        return 0;

    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
        return 0;

    float duration = buffer->duration() / 1000.0f;

    // Follow other ports (and WinIE's) behavior to slow annoying ads that
    // specify a 0 duration.
    if (duration < 0.051f)
        return 0.100f;
    return duration;
}
示例#12
0
NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
{
    if (!m_decoder)
        return 0;

    // Note that the buffer can have NULL bytes even when it is marked as
    // non-empty. It seems "FrameEmpty" is only set before the frame has been
    // initialized. If it is decoded and it happens to be empty, it will be
    // marked as "FrameComplete" but will still have NULL bytes.
    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
        return 0;

    // Copy the bitmap.  The pixel data is refcounted internally by SkBitmap, so
    // this doesn't cost much.  
    return buffer->asNewNativeImage();
}
示例#13
0
float ImageSource::frameDurationAtIndex(size_t index)
{
    if (!m_decoder)
        return 0;

    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
        return 0;

    // Many annoying ads specify a 0 duration to make an image flash as quickly
    // as possible.  We follow WinIE's behavior and use a duration of 100 ms
    // for any frames that specify a duration of <= 50 ms.  See
    // <http://bugs.webkit.org/show_bug.cgi?id=14413> or Radar 4051389 for
    // more.
    const float duration = buffer->duration() / 1000.0f;
    return (duration < 0.051f) ? 0.100f : duration;
}
示例#14
0
NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
{
    if (!initialized())
        return 0;

    if (!m_decoder)
        return 0;

    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
        return 0;

    // Cairo does not like zero height images.
    // If we have a zero height image, just pretend we don't have enough data yet.
    if (!buffer->height())
        return 0;
    /* <lab126> */
    struct timespec startTime;
    KINDLE_BEGIN(Kindle_Debug_Perf)
    clock_gettime(CLOCK_MONOTONIC, &startTime);
    KINDLE_END()

    if (m_imageDitherType == USE_SIMPLE_ALGORITHM) {
        int imageWidth = size().width();
        int imageHeight = buffer->height();
        if(!dither_inited)
            for(int i=0; i<3333; i++)
                dither_buffer[i]=rand()%17;
        for (int n = 0; n < imageHeight; n++)
        {
            for (int m = 0; m < imageWidth; m++)
            {
                int rgb=buffer->bytes().data()[ (n*imageWidth) + m ];
                int r = (rgb >> 16) & 0xff;
                int g = (rgb >> 8) & 0xff;
                int b = rgb & 0xff;
                int gray = (r == g && g == b) ?  r : ((77 * r + 150 * g + 29 * b) >> 8);
                dither_index=(dither_index+1)%3333;
                int ngray=gray+dither_buffer[dither_index];
                ngray-=ngray%17;
                if(ngray>0xff) ngray=0xff;
                buffer->bytes().data()[ (n*imageWidth) + m ] =   (rgb&STRIP_ALPHA)|(ngray<<16)|(ngray<<8)|ngray;
            }
        }
    }
示例#15
0
NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
{
    if (!m_decoder)
        return 0;

    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
        return 0;
        
    DEBUG( "ImageSource::createFrameAtIndex() %i %i %i\n",
    	size().width(), buffer->height(), buffer->bytes().size() );
    
    os::Bitmap* pcBitmap = new os::Bitmap( size().width(), buffer->height(), os::CS_RGBA32 );
    memcpy( pcBitmap->LockRaster(), reinterpret_cast<unsigned char*>(buffer->bytes().data()),
    			 ( buffer->height() * size().width() ) * 4  );
	pcBitmap->UnlockRaster();    			 
    return( pcBitmap );
}
NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
{
    if (!initialized())
        return 0;

    if (!m_decoder)
        return 0;

    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
        return 0;

    // Cairo does not like zero height images.
    // If we have a zero height image, just pretend we don't have enough data yet.
    if (!size().height())
        return 0;

    return buffer->asNewNativeImage();
}
SkBitmapRef* ImageSource::createFrameAtIndex(size_t index)
{
#ifdef ANDROID_ANIMATED_GIF
    if (m_decoder.m_gifDecoder) {
        RGBA32Buffer* buffer =
                m_decoder.m_gifDecoder->frameBufferAtIndex(index);
        if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
            return 0;
        SkBitmap& bitmap = buffer->bitmap();
        SkPixelRef* pixelRef = bitmap.pixelRef();
        if (pixelRef)
            pixelRef->setURI(m_decoder.m_url);
        return new SkBitmapRef(bitmap);
    }
#else
    SkASSERT(index == 0);
#endif
    SkASSERT(m_decoder.m_image != NULL);
    m_decoder.m_image->ref();
    return m_decoder.m_image;
}
float ImageSource::frameDurationAtIndex(size_t index)
{
    float duration = 0;
#ifdef ANDROID_ANIMATED_GIF
    if (m_decoder.m_gifDecoder) {
        RGBA32Buffer* buffer
                = m_decoder.m_gifDecoder->frameBufferAtIndex(index);
        if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
            return 0;
        duration = buffer->duration() / 1000.0f;
    }
#else
    SkASSERT(index == 0);
#endif

    // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
    // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
    // a duration of <= 10 ms. See gfxImageFrame::GetTimeout in Gecko or Radar 4051389 for more.
    if (duration <= 0.010f)
        duration = 0.100f;
    return duration;
}
示例#19
0
NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
{
    if (!initialized())
        return 0;

    if (!m_decoder)
        return 0;

    RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
    if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
        return 0;

    // Cairo does not like zero height images.
    // If we have a zero height image, just pretend we don't have enough data yet.
    if (!buffer->height())
        return 0;

    return cairo_image_surface_create_for_data((unsigned char*)buffer->bytes().data(),
                                               CAIRO_FORMAT_ARGB32,
                                               size().width(),
                                               buffer->height(),
                                               size().width()*4);
}
    bool decode(const Vector<char>& data, RxIImageDecoder::RxIFormat fmt)
    {
        int i = 0;
        int j = 0;
        bool result = false;
        RGBA32Buffer* frameBuffer = 0;
        unsigned char* rgbData = 0;

        if (!m_memoryManager)
            return false;

        m_memoryReader = new MemReader((unsigned char*)data.data(), data.size());

        // The rest of the code expects that the first 8 bytes has already been read.
        // The signature for these files is 8 bytes.

        m_memoryReader->SetOffset(8);


        switch (fmt) {
        case RxIImageDecoder::FormatRdi:
            m_rxi = RdiBirth(m_memoryManager, m_memoryReader);
            break;
        case RxIImageDecoder::FormatRgi:
            m_rxi = RgiBirth(m_memoryManager, m_memoryReader);
            break;
        case RxIImageDecoder::FormatRpi:
            m_rxi = RpiBirth(m_memoryManager, m_memoryReader);
            break;
        case RxIImageDecoder::FormatRwi:
            m_rxi = RwiBirth(m_memoryManager, m_memoryReader);
            break;
        case RxIImageDecoder::FormatUnknown:
            ASSERT_NOT_REACHED();
            break;
        }

        if (!m_rxi) {
            delete m_memoryReader;
            m_memoryReader = 0;
            return false;
        }
        m_format = fmt;

        switch (fmt) {
        case RxIImageDecoder::FormatRdi:
            result = RdiGetWH(m_rxi, &m_w, &m_h);
            break;
        case RxIImageDecoder::FormatRgi:
            result = RgiGetWH(m_rxi, &m_w, &m_h);
            break;
        case RxIImageDecoder::FormatRpi:
            result = RpiGetWH(m_rxi, &m_w, &m_h);
            break;
        case RxIImageDecoder::FormatRwi:
            result = RwiGetWH(m_rxi, &m_w, &m_h);
            break;
        case RxIImageDecoder::FormatUnknown:
            ASSERT_NOT_REACHED();
            break;
        }

        if (!result) {
            delete m_memoryReader;
            m_memoryReader = 0;
            return false;
        }

        // We can fill in the size now that the header is available.
        if (!m_decoder->setSize(m_w, m_h))
            return m_decoder->setFailed();

        frameBuffer = m_decoder->getUntouchedFrameBufferAtIndex(0);

        if (!frameBuffer) {
            delete m_memoryReader;
            m_memoryReader = 0;
            m_sizeInitialized = false;
            return false;
        }

        if (frameBuffer->status() == RGBA32Buffer::FrameEmpty) {
            if (!frameBuffer->setSize(m_w, m_h))
                return m_decoder->setFailed();
            frameBuffer->setStatus(RGBA32Buffer::FramePartial);

            if ( fmt == RxIImageDecoder::FormatRpi ) {
                // RPI format has alpha which we must support.
                frameBuffer->setHasAlpha(true);
            } else {
                frameBuffer->setHasAlpha(false);
            }
            // the frame always fills the entire image.
            frameBuffer->setRect(IntRect(IntPoint(0, 0), m_decoder->size()));
        }

        // note that we don't cleanup frameBuffer at all since we didn't allocate it.
        if ( fmt == RxIImageDecoder::FormatRgi ) {
            rgbData = (unsigned char*) malloc(m_w * m_h * 3);
        } else if ( fmt == RxIImageDecoder::FormatRpi ) {
            // extra channel is for alpha
            rgbData = (unsigned char*) malloc(m_w * m_h * 4);
        }

        MemWriter mw(m_w * m_h * 3);
        switch (fmt) {
        case RxIImageDecoder::FormatRdi:
            result = RdiGetRGB(m_rxi, &mw);
            break;
        case RxIImageDecoder::FormatRgi:
            result = RgiGetRGB(m_rxi, rgbData);
            break;
        case RxIImageDecoder::FormatRpi:
            result = RpiGetRGB(m_rxi, rgbData);
            break;
        case RxIImageDecoder::FormatRwi:
            result = RwiGetRGB(m_rxi, &mw);
            break;
        case RxIImageDecoder::FormatUnknown:
            ASSERT_NOT_REACHED();
            break;
        }

        if (result) {
            unsigned char* ptr = 0;
            if ((fmt == RxIImageDecoder::FormatRdi) || (fmt == RxIImageDecoder::FormatRwi))
                ptr = (unsigned char*)mw.GetBuffer();
            else
                ptr = rgbData;

            for (i = 0; i < m_h; ++i) {
                for (j = 0; j < m_w; ++j) {
                    unsigned char r, g, b;
                    unsigned char a = 0xFF;
                    r = *ptr;
                    ptr++;
                    g = *ptr;
                    ptr++;
                    b = *ptr;
                    ptr++;
                    if ( fmt == RxIImageDecoder::FormatRpi ) {
                        a = *ptr;
                        ptr++;
                    }
                    frameBuffer->setRGBA(j, i, r, g, b, a);
                }
            }
        }
        m_decoder->rxiComplete();

        // cleaning up
        free(rgbData);
        rgbData = 0;
        delete m_memoryReader;
        m_memoryReader = 0;
        m_sizeInitialized = false;

        switch (fmt) {
        case RxIImageDecoder::FormatRdi:
            RdiDeath(m_rxi);
            break;
        case RxIImageDecoder::FormatRgi:
            RgiDeath(m_rxi);
            break;
        case RxIImageDecoder::FormatRpi:
            RpiDeath(m_rxi);
            break;
        case RxIImageDecoder::FormatRwi:
            RwiDeath(m_rxi);
            break;
        case RxIImageDecoder::FormatUnknown:
            ASSERT_NOT_REACHED();
            break;
        }
        m_rxi = 0;
        return true;
    }