void GifDecoder::setPixels(uint32_t* act) { int32_t pixelNum = width * height; uint32_t* dest = new uint32_t[pixelNum]; // fill in starting image contents based on last image's dispose code if (lastDispose > 0) { if (lastDispose == 3) { // use image before last int32_t n = frameCount - 2; if (n > 0) { lastBitmap = getFrame(n - 1); } else { lastBitmap = NULL; } } if (lastBitmap != NULL) { memcpy(dest, lastBitmap, pixelNum * 4); // copy pixels if (lastDispose == 2) { // fill last image rect area with background color int32_t c = 0; if (!transparency) { c = lastBgColor; } for (int32_t i = 0; i < lrh; i++) { int32_t n1 = (lry + i) * width + lrx; int32_t n2 = n1 + lrw; for (int32_t k = n1; k < n2; k++) { dest[k] = c; } } } } } // copy each source line to the appropriate place in the destination int32_t pass = 1; int32_t inc = 8; int32_t iline = 0; for (int32_t i = 0; i < ih; i++) { int32_t line = i; if (interlace) { if (iline >= ih) { pass++; switch (pass) { case 2: iline = 4; break; case 3: iline = 2; inc = 4; break; case 4: iline = 1; inc = 2; break; default: break; } } line = iline; iline += inc; } line += iy; if (line < height) { int32_t k = line * width; int32_t dx = k + ix; // start of line in dest int32_t dlim = dx + iw; // end of dest line if ((k + width) < dlim) { dlim = k + width; // past dest edge } int32_t sx = i * iw; // start of line in source while (dx < dlim) { // map color and insert in destination int32_t index = ((int32_t) pixels[sx++]) & 0xff; int32_t c = act[index]; if (c != 0) { dest[dx] = c; } dx++; } } } frames.push_back(GifFrame(dest, delay)); image = dest; }
void AnimatedImage::extractGifData(const GifFileType *gifFile) { PixelAccessor *pa = NULL; GifFrame *frame = NULL; try { m_size.cx = gifFile->SWidth; m_size.cy = gifFile->SHeight; m_workPr = new PixRect(m_device, PIXRECT_TEXTURE, m_size); TRACE_NEW(m_workPr); const int imageCount = gifFile->ImageCount; ColorMapObject *gfColorMap = gifFile->SColorMap; const GifColorType &colorType = gfColorMap->Colors[gifFile->SBackGroundColor]; const int bitsPerPixel = gfColorMap->BitsPerPixel; m_backgroundColor = D3DCOLOR_RGBA(colorType.Red, colorType.Green, colorType.Blue,255); for(int k = 0; k < gifFile->ExtensionBlockCount; k++) { const ExtensionBlock &block = gifFile->ExtensionBlocks[k]; switch(block.Function) { case COMMENT_EXT_FUNC_CODE: m_comment += format(_T("%*.*s"), block.ByteCount, block.ByteCount, block.Bytes); break; case APPLICATION_EXT_FUNC_CODE: parseApplicationBlock(block.Bytes, block.ByteCount); break; } } m_frameTable.setCapacity(imageCount); for(int i = 0; i < imageCount; i++) { SavedImage &image = gifFile->SavedImages[i]; m_frameTable.add(GifFrame()); frame = &m_frameTable.last(); String imageComment; for(int k = 0; k < image.ExtensionBlockCount; k++) { const ExtensionBlock &block = image.ExtensionBlocks[k]; switch(block.Function) { case COMMENT_EXT_FUNC_CODE: imageComment += format(_T("%*.*s"), block.ByteCount, block.ByteCount, block.Bytes); break; case APPLICATION_EXT_FUNC_CODE: parseApplicationBlock(block.Bytes, block.ByteCount); break; } } if(imageComment.length() > 0) { m_comment += _T("\n") + imageComment; } frame->m_owner = this; frame->m_rect.left = image.ImageDesc.Left; frame->m_rect.top = image.ImageDesc.Top; frame->m_rect.right = image.ImageDesc.Left + image.ImageDesc.Width; frame->m_rect.bottom = image.ImageDesc.Top + image.ImageDesc.Height; frame->m_srcRect = CRect(0,0, image.ImageDesc.Width, image.ImageDesc.Height); int transparentColor = NO_TRANSPARENT_COLOR; GraphicsControlBlock gcb; if(DGifSavedExtensionToGCB((GifFileType*)gifFile, i, &gcb) == GIF_OK) { frame->m_disposalMode = gcb.DisposalMode; frame->m_delayTime = max(60,10*gcb.DelayTime); if((transparentColor = gcb.TransparentColor) != NO_TRANSPARENT_COLOR) { frame->m_useTransparency = true; } } const CSize sz = frame->m_rect.Size(); frame->m_pr = new PixRect(m_device, PIXRECT_TEXTURE, sz, D3DPOOL_SYSTEMMEM, D3DFMT_A8R8G8B8); TRACE_NEW(frame->m_pr); const ColorMapObject *colorMap = image.ImageDesc.ColorMap ? image.ImageDesc.ColorMap : gfColorMap; const GifColorType *colors = colorMap->Colors; const GifPixelType *pixelp = image.RasterBits; pa = frame->m_pr->getPixelAccessor(0 /*D3DLOCK_NOSYSLOCK | D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOOVERWRITE*/); for(CPoint p(0,0); p.y < sz.cy; p.y++) { for(p.x = 0; p.x < sz.cx; p.x++) { const int entry = *(pixelp++); if((entry == transparentColor) && frame->m_useTransparency) { pa->setPixel(p, D3DCOLOR_RGBA(0,0,0,0)); } else { const GifColorType &mapEntry = colors[entry]; pa->setPixel(p, D3DCOLOR_RGBA(mapEntry.Red, mapEntry.Green, mapEntry.Blue, 255)); } } } frame->m_pr->releasePixelAccessor(); pa = NULL; // frame.m_pr->moveToPool(D3DPOOL_DEFAULT); } } catch(...) { if(pa) { frame->m_pr->releasePixelAccessor(); } unload(); throw; } }