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; }
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; } } }
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 (!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); }
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); }
void GIFImageDecoder::initFrameBuffer(RGBA32Buffer& buffer, RGBA32Buffer* previousBuffer, bool compositeWithPreviousFrame) { // Initialize the frame rect in our buffer. IntRect frameRect(m_reader->frameXOffset(), m_reader->frameYOffset(), m_reader->frameWidth(), m_reader->frameHeight()); buffer.setRect(frameRect); bool isSubRect = (frameRect.x() > 0 || frameRect.y() > 0 || frameRect.width() < m_size.width() || frameRect.height() < m_size.height()); // Let's resize our buffer now to the correct width/height and then // initialize portions of it if needed. RGBA32Array& bytes = buffer.bytes(); // If the disposal method of the previous frame said to stick around, then we need // to copy that frame into our frame. We also dont want to have any impact on // anything outside our frame's rect, so if we don't overlay the entire image, // then also composite with the previous frame. if (previousBuffer && (compositeWithPreviousFrame || isSubRect)) { bytes = previousBuffer->bytes(); buffer.ensureHeight(m_size.height()); buffer.setHasAlpha(previousBuffer->hasAlpha()); } else // Resize to the width and height of the image. bytes.resize(m_size.width() * m_size.height()); if (isSubRect) { // We need to go ahead and initialize the first frame to make sure // that areas outside the subrect start off transparent. if (!previousBuffer) { bytes.fill(0); buffer.setHasAlpha(true); } else if (!compositeWithPreviousFrame) { // Now this is an interesting case. In the case where we fill // the entire image, we effectively do a full clear of the image (and thus // don't have to initialize anything in our buffer). // // However in the case where we only fill a piece of the image, two problems occur: // (1) We need to wipe out the area occupied by the previous frame, which // could also have been a subrect. // (2) Anything outside the previous frame's rect *and* outside our current // frame's rect should be left alone. // We have handled (2) by just initializing our buffer from the previous frame. // Our subrect will correctly overwrite the previous frame's contents as we // decode rows. However that still leaves the problem of having to wipe out // the area occupied by the previous frame that does not overlap with // the new frame. if (previousBuffer->rect() != frameRect) { // We have to clear out the entire previous subframe. bool sawAlpha = buffer.hasAlpha(); IntRect prevRect = previousBuffer->rect(); unsigned end = prevRect.y() + prevRect.height(); unsigned* src; for (unsigned i = prevRect.y(); i < end; i++) { unsigned* curr = buffer.bytes().data() + (i * m_size.width() + prevRect.x()); unsigned* end = curr + prevRect.width(); while (curr != end) { if (!sawAlpha) { sawAlpha = true; buffer.setHasAlpha(true); } RGBA32Buffer::setRGBA(*curr++, 0, 0, 0, 0); } } } } } // Update our status to be partially complete. buffer.setStatus(RGBA32Buffer::FramePartial); }