bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels) { const GIFFrameReader* frameReader = m_reader->frame_reader; // The pixel data and coordinates supplied to us are relative to the frame's // origin within the entire image size, i.e. // (frameReader->x_offset, frameReader->y_offset). There is no guarantee // that (rowEnd - rowBuffer) == (size().width() - frameReader->x_offset), so // we must ensure we don't run off the end of either the source data or the // row's X-coordinates. int xBegin = upperBoundScaledX(frameReader->x_offset); int yBegin = upperBoundScaledY(frameReader->y_offset + rowNumber); int xEnd = lowerBoundScaledX(std::min(xBegin + static_cast<int>(rowEnd - rowBuffer), size().width()) - 1, xBegin + 1) + 1; int yEnd = lowerBoundScaledY(std::min(yBegin + static_cast<int>(repeatCount), size().height()) - 1, yBegin + 1) + 1; if (!rowBuffer || (xBegin < 0) || (yBegin < 0) || (xEnd <= xBegin) || (yEnd <= yBegin)) return true; // Get the colormap. const unsigned char* colorMap; unsigned colorMapSize; if (frameReader->is_local_colormap_defined) { colorMap = frameReader->local_colormap; colorMapSize = (unsigned)frameReader->local_colormap_size; } else { colorMap = m_reader->global_colormap; colorMapSize = m_reader->global_colormap_size; } if (!colorMap) return true; // Initialize the frame if necessary. RGBA32Buffer& buffer = m_frameBufferCache[frameIndex]; if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex)) return false; // Write one row's worth of data into the frame. for (int x = xBegin; x < xEnd; ++x) { const unsigned char sourceValue = *(rowBuffer + (m_scaled ? m_scaledColumns[x] : x) - frameReader->x_offset); if ((!frameReader->is_transparent || (sourceValue != frameReader->tpixel)) && (sourceValue < colorMapSize)) { const size_t colorIndex = static_cast<size_t>(sourceValue) * 3; buffer.setRGBA(x, yBegin, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255); } else { m_currentBufferSawAlpha = true; // We may or may not need to write transparent pixels to the buffer. // If we're compositing against a previous image, it's wrong, and if // we're writing atop a cleared, fully transparent buffer, it's // unnecessary; but if we're decoding an interlaced gif and // displaying it "Haeberli"-style, we must write these for passes // beyond the first, or the initial passes will "show through" the // later ones. if (writeTransparentPixels) buffer.setRGBA(x, yBegin, 0, 0, 0, 0); } } // Tell the frame to copy the row data if need be. if (repeatCount > 1) buffer.copyRowNTimes(xBegin, xEnd, yBegin, yEnd); return true; }
void LightSource::init(const std::string& vertexPath, const std::string& fragmentPath) { shadowShader.compileShaders(vertexPath, fragmentPath, " "); shadowShader.addAttribute("vertexPosition"); shadowShader.linkShaders(); initTex(); initFrameBuffer(); }
int main(int argc, char** argv) { fullscreen = false; grab = false; quit = false; initScreen(); initFrameBuffer(); createGLContext(); createColorMap(); createWindow(); createBlankCursor(); int x = 0; while(x<5000) { renderFrame(); updateWindowTitle(); x++; } /* Cleanup glXDestroyWindow(display, glxwindow); xcb_destroy_window(connection, window); glXDestroyContext(display, context); XCloseDisplay(display); */ return 0; }
void GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels) { // The pixel data and coordinates supplied to us are relative to the frame's // origin within the entire image size, i.e. // (m_reader->frameXOffset(), m_reader->frameYOffset()). int x = m_reader->frameXOffset(); const int y = m_reader->frameYOffset() + rowNumber; // Sanity-check the arguments. if ((rowBuffer == 0) || (y >= size().height())) return; // Get the colormap. unsigned colorMapSize; unsigned char* colorMap; m_reader->getColorMap(colorMap, colorMapSize); if (!colorMap) return; // Initialize the frame if necessary. RGBA32Buffer& buffer = m_frameBufferCache[frameIndex]; if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex)) return; // Write one row's worth of data into the frame. There is no guarantee that // (rowEnd - rowBuffer) == (size().width() - m_reader->frameXOffset()), so // we must ensure we don't run off the end of either the source data or the // row's X-coordinates. for (unsigned char* sourceAddr = rowBuffer; (sourceAddr != rowEnd) && (x < size().width()); ++sourceAddr, ++x) { const unsigned char sourceValue = *sourceAddr; if ((!m_reader->isTransparent() || (sourceValue != m_reader->transparentPixel())) && (sourceValue < colorMapSize)) { const size_t colorIndex = static_cast<size_t>(sourceValue) * 3; buffer.setRGBA(x, y, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255); } else { m_currentBufferSawAlpha = true; // We may or may not need to write transparent pixels to the buffer. // If we're compositing against a previous image, it's wrong, and if // we're writing atop a cleared, fully transparent buffer, it's // unnecessary; but if we're decoding an interlaced gif and // displaying it "Haeberli"-style, we must write these for passes // beyond the first, or the initial passes will "show through" the // later ones. if (writeTransparentPixels) buffer.setRGBA(x, y, 0, 0, 0, 0); } } // Tell the frame to copy the row data if need be. if (repeatCount > 1) buffer.copyRowNTimes(m_reader->frameXOffset(), x, y, std::min(y + static_cast<int>(repeatCount), size().height())); }
bool OffscreenRenderer::makeCurrent(int width, int height, bool sampleBuffers) { ASSERT(mainGlWidget); // Considering weak graphics cards glClear is faster when the color and depth buffers are not greater then they have to be. // So we create an individual buffer for each size in demand. std::unordered_map<unsigned int, Buffer>::iterator it = renderBuffers.find(width << 16 | height << 1 | (sampleBuffers ? 1 : 0)); if(it == renderBuffers.end()) { Buffer& buffer = renderBuffers[width << 16 | height << 1 | (sampleBuffers ? 1 : 0)]; #ifdef FIX_MACOS_BROKEN_TEXTURES_ON_NVIDIA_BUG if(!initFrameBuffer(width, height, buffer)) if(!initPixelBuffer(width, height, sampleBuffers, buffer)) #else if(!initPixelBuffer(width, height, sampleBuffers, buffer)) if(!initFrameBuffer(width, height, buffer)) #endif initHiddenWindow(width, height, buffer); return true; } else { Buffer& buffer = it->second; if(buffer.pbuffer) return buffer.pbuffer->makeCurrent(); if(buffer.frameBufferId) { mainGlWidget->makeCurrent(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, buffer.frameBufferId); return true; } if(buffer.glWidget) buffer.glWidget->makeCurrent(); else mainGlWidget->makeCurrent(); return true; } }
void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod) { // Initialize the frame if necessary. Some GIFs insert do-nothing frames, // in which case we never reach haveDecodedRow() before getting here. RGBA32Buffer& buffer = m_frameBufferCache[frameIndex]; IntRect& rect = m_rects[frameIndex]; if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex)) return; buffer.setStatus(RGBA32Buffer::FrameComplete); buffer.setDuration(frameDuration); buffer.setDisposalMethod(disposalMethod); if (!m_currentBufferSawAlpha) { // The whole frame was non-transparent, so it's possible that the entire // resulting buffer was non-transparent, and we can setHasAlpha(false). if (rect.contains(IntRect(IntPoint(), size()))) buffer.setHasAlpha(false); else if (frameIndex > 0) { // Tricky case. This frame does not have alpha only if everywhere // outside its rect doesn't have alpha. To know whether this is // true, we check the start state of the frame -- if it doesn't have // alpha, we're safe. // // First skip over prior DisposeOverwritePrevious frames (since they // don't affect the start state of this frame) the same way we do in // initFrameBuffer(). const RGBA32Buffer* prevBuffer = &m_frameBufferCache[--frameIndex]; const IntRect* prevRect = &m_rects[frameIndex]; while ((frameIndex > 0) && (prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwritePrevious)) { prevBuffer = &m_frameBufferCache[--frameIndex]; prevRect = &m_rects[frameIndex]; } // Now, if we're at a DisposeNotSpecified or DisposeKeep frame, then // we can say we have no alpha if that frame had no alpha. But // since in initFrameBuffer() we already copied that frame's alpha // state into the current frame's, we need do nothing at all here. // // The only remaining case is a DisposeOverwriteBgcolor frame. If // it had no alpha, and its rect is contained in the current frame's // rect, we know the current frame has no alpha. if ((prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwriteBgcolor) && !prevBuffer->hasAlpha() && rect.contains(*prevRect)) buffer.setHasAlpha(false); } } }
ImageFrame* WEBPImageDecoder::frameBufferAtIndex(size_t index) { if (index >= frameCount()) return 0; ImageFrame& frame = m_frameBufferCache[index]; if (frame.status() == ImageFrame::FrameComplete) return &frame; Vector<size_t> framesToDecode; size_t frameToDecode = index; do { framesToDecode.append(frameToDecode); frameToDecode = m_frameBufferCache[frameToDecode].requiredPreviousFrameIndex(); } while (frameToDecode != kNotFound && m_frameBufferCache[frameToDecode].status() != ImageFrame::FrameComplete); ASSERT(m_demux); for (size_t i = framesToDecode.size(); i > 0; --i) { size_t frameIndex = framesToDecode[i - 1]; if ((m_formatFlags & ANIMATION_FLAG) && !initFrameBuffer(frameIndex)) return 0; WebPIterator webpFrame; if (!WebPDemuxGetFrame(m_demux, frameIndex + 1, &webpFrame)) return 0; PlatformInstrumentation::willDecodeImage("WEBP"); decode(webpFrame.fragment.bytes, webpFrame.fragment.size, false, frameIndex); PlatformInstrumentation::didDecodeImage(); WebPDemuxReleaseIterator(&webpFrame); if (failed()) return 0; // We need more data to continue decoding. if (m_frameBufferCache[frameIndex].status() != ImageFrame::FrameComplete) break; } // It is also a fatal error if all data is received and we have decoded all // frames available but the file is truncated. if (index >= m_frameBufferCache.size() - 1 && isAllDataReceived() && m_demux && m_demuxState != WEBP_DEMUX_DONE) setFailed(); frame.notifyBitmapIfPixelsChanged(); return &frame; }
LRESULT CALLBACK WndProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) { HDC dstDc; PAINTSTRUCT paintInfo; BOOL result; switch (msg) { case WM_CREATE: if (initFrameBuffer()) return -1; if (!SetTimer(window, SCREEN_UPDATE_TIMER_ID, USER_TIMER_MINIMUM, NULL)) { reportSysError(_T("Failed to create the display update timer.")); return -1; } break; case WM_DESTROY: deinitialize(); PostQuitMessage(exitCode); break; case WM_KEYDOWN: if (wParam == VK_ESCAPE) DestroyWindow(window); break; case WM_TIMER: InvalidateRect(window, NULL, FALSE); break; case WM_PAINT: dstDc = BeginPaint(window, &paintInfo); updateScreen(); BitBlt(dstDc, - (int) bufOffset, 0, WIDTH, HEIGHT, bufDc, 0, 0, SRCCOPY); EndPaint(window, &paintInfo); updateFps(); break; default: return DefWindowProc(window, msg, wParam, lParam); } return 0; }
void WEBPImageDecoder::decode(size_t index) { if (failed()) return; Vector<size_t> framesToDecode; size_t frameToDecode = index; do { framesToDecode.append(frameToDecode); frameToDecode = m_frameBufferCache[frameToDecode].requiredPreviousFrameIndex(); } while (frameToDecode != kNotFound && m_frameBufferCache[frameToDecode].getStatus() != ImageFrame::FrameComplete); ASSERT(m_demux); for (auto i = framesToDecode.rbegin(); i != framesToDecode.rend(); ++i) { if ((m_formatFlags & ANIMATION_FLAG) && !initFrameBuffer(*i)) return; WebPIterator webpFrame; if (!WebPDemuxGetFrame(m_demux, *i + 1, &webpFrame)) { setFailed(); } else { decodeSingleFrame(webpFrame.fragment.bytes, webpFrame.fragment.size, *i); WebPDemuxReleaseIterator(&webpFrame); } if (failed()) return; // We need more data to continue decoding. if (m_frameBufferCache[*i].getStatus() != ImageFrame::FrameComplete) break; if (m_purgeAggressively) clearCacheExceptFrame(*i); } // It is also a fatal error if all data is received and we have decoded all // frames available but the file is truncated. if (index >= m_frameBufferCache.size() - 1 && isAllDataReceived() && m_demux && m_demuxState != WEBP_DEMUX_DONE) setFailed(); }
bool GIFImageDecoder::frameComplete(size_t frameIndex) { // Initialize the frame if necessary. Some GIFs insert do-nothing frames, // in which case we never reach haveDecodedRow() before getting here. ImageFrame& buffer = m_frameBufferCache[frameIndex]; if ((buffer.status() == ImageFrame::FrameEmpty) && !initFrameBuffer(frameIndex)) return false; // initFrameBuffer() has already called setFailed(). buffer.setStatus(ImageFrame::FrameComplete); if (!m_currentBufferSawAlpha) { // The whole frame was non-transparent, so it's possible that the entire // resulting buffer was non-transparent, and we can setHasAlpha(false). if (buffer.originalFrameRect().contains(IntRect(IntPoint(), size()))) { buffer.setHasAlpha(false); buffer.setRequiredPreviousFrameIndex(notFound); } else if (buffer.requiredPreviousFrameIndex() != notFound) { // Tricky case. This frame does not have alpha only if everywhere // outside its rect doesn't have alpha. To know whether this is // true, we check the start state of the frame -- if it doesn't have // alpha, we're safe. const ImageFrame* prevBuffer = &m_frameBufferCache[buffer.requiredPreviousFrameIndex()]; ASSERT(prevBuffer->disposalMethod() != ImageFrame::DisposeOverwritePrevious); // Now, if we're at a DisposeNotSpecified or DisposeKeep frame, then // we can say we have no alpha if that frame had no alpha. But // since in initFrameBuffer() we already copied that frame's alpha // state into the current frame's, we need do nothing at all here. // // The only remaining case is a DisposeOverwriteBgcolor frame. If // it had no alpha, and its rect is contained in the current frame's // rect, we know the current frame has no alpha. if ((prevBuffer->disposalMethod() == ImageFrame::DisposeOverwriteBgcolor) && !prevBuffer->hasAlpha() && buffer.originalFrameRect().contains(prevBuffer->originalFrameRect())) buffer.setHasAlpha(false); } } return true; }
void GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, // Pointer to single scanline temporary buffer unsigned char* rowEnd, unsigned rowNumber, // The row index unsigned repeatCount) // How many times to repeat the row { // Resize to the width and height of the image. RGBA32Buffer& buffer = m_frameBufferCache[frameIndex]; RGBA32Buffer* previousBuffer = (frameIndex > 0) ? &m_frameBufferCache[frameIndex-1] : 0; bool compositeWithPreviousFrame = previousBuffer && previousBuffer->includeInNextFrame(); if (buffer.status() == RGBA32Buffer::FrameEmpty) initFrameBuffer(buffer, previousBuffer, compositeWithPreviousFrame); if (rowBuffer == 0) return; unsigned colorMapSize; unsigned char* colorMap; m_reader->getColorMap(colorMap, colorMapSize); if (!colorMap) return; // The buffers that we draw are the entire image's width and height, so a final output frame is // width * height RGBA32 values in size. // // A single GIF frame, however, can be smaller than the entire image, i.e., it can represent some sub-rectangle // within the overall image. The rows we are decoding are within this // sub-rectangle. This means that if the GIF frame's sub-rectangle is (x,y,w,h) then row 0 is really row // y, and each row goes from x to x+w. unsigned dstPos = (m_reader->frameYOffset() + rowNumber) * m_size.width() + m_reader->frameXOffset(); unsigned* dst = buffer.bytes().data() + dstPos; unsigned* currDst = dst; unsigned char* currentRowByte = rowBuffer; bool hasAlpha = m_reader->isTransparent(); bool sawAlpha = false; while (currentRowByte != rowEnd) { if ((!hasAlpha || *currentRowByte != m_reader->transparentPixel()) && *currentRowByte < colorMapSize) { unsigned colorIndex = *currentRowByte * 3; unsigned red = colorMap[colorIndex]; unsigned green = colorMap[colorIndex + 1]; unsigned blue = colorMap[colorIndex + 2]; RGBA32Buffer::setRGBA(*currDst, red, green, blue, 255); } else { if (!sawAlpha) { sawAlpha = true; buffer.setHasAlpha(true); } if (!compositeWithPreviousFrame) RGBA32Buffer::setRGBA(*currDst, 0, 0, 0, 0); } currDst++; currentRowByte++; } if (repeatCount > 1) { // Copy the row |repeatCount|-1 times. unsigned size = (currDst - dst) * sizeof(unsigned); unsigned width = m_size.width(); unsigned* end = buffer.bytes().data() + width * m_size.height(); currDst = dst + width; for (unsigned i = 1; i < repeatCount; i++) { if (currDst + size > end) // Protect against a buffer overrun from a bogus repeatCount. break; memcpy(currDst, dst, size); currDst += width; } } // Our partial height is rowNumber + 1, e.g., row 2 is the 3rd row, so that's a height of 3. // Adding in repeatCount - 1 to rowNumber + 1 works out to just be rowNumber + repeatCount. buffer.ensureHeight(rowNumber + repeatCount); }
bool GIFImageDecoder::haveDecodedRow(size_t frameIndex, const Vector<unsigned char>& rowBuffer, size_t width, size_t rowNumber, unsigned repeatCount, bool writeTransparentPixels) { const GIFFrameContext* frameContext = m_reader->frameContext(frameIndex); // The pixel data and coordinates supplied to us are relative to the frame's // origin within the entire image size, i.e. // (frameContext->xOffset, frameContext->yOffset). There is no guarantee // that width == (size().width() - frameContext->xOffset), so // we must ensure we don't run off the end of either the source data or the // row's X-coordinates. int xBegin = frameContext->xOffset; int yBegin = frameContext->yOffset + rowNumber; int xEnd = std::min(static_cast<int>(frameContext->xOffset + width), size().width()); int yEnd = std::min(static_cast<int>(frameContext->yOffset + rowNumber + repeatCount), size().height()); if (rowBuffer.isEmpty() || (xBegin < 0) || (yBegin < 0) || (xEnd <= xBegin) || (yEnd <= yBegin)) return true; // Get the colormap. const unsigned char* colorMap; unsigned colorMapSize; if (frameContext->isLocalColormapDefined) { colorMap = m_reader->localColormap(frameContext); colorMapSize = m_reader->localColormapSize(frameContext); } else { colorMap = m_reader->globalColormap(); colorMapSize = m_reader->globalColormapSize(); } if (!colorMap) return true; // Initialize the frame if necessary. ImageFrame& buffer = m_frameBufferCache[frameIndex]; if ((buffer.status() == ImageFrame::FrameEmpty) && !initFrameBuffer(frameIndex)) return false; ImageFrame::PixelData* currentAddress = buffer.getAddr(xBegin, yBegin); // Write one row's worth of data into the frame. for (int x = xBegin; x < xEnd; ++x) { const unsigned char sourceValue = rowBuffer[x - frameContext->xOffset]; if ((!frameContext->isTransparent || (sourceValue != frameContext->tpixel)) && (sourceValue < colorMapSize)) { const size_t colorIndex = static_cast<size_t>(sourceValue) * 3; buffer.setRGBA(currentAddress, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255); } else { m_currentBufferSawAlpha = true; // We may or may not need to write transparent pixels to the buffer. // If we're compositing against a previous image, it's wrong, and if // we're writing atop a cleared, fully transparent buffer, it's // unnecessary; but if we're decoding an interlaced gif and // displaying it "Haeberli"-style, we must write these for passes // beyond the first, or the initial passes will "show through" the // later ones. if (writeTransparentPixels) buffer.setRGBA(currentAddress, 0, 0, 0, 0); } ++currentAddress; } // Tell the frame to copy the row data if need be. if (repeatCount > 1) buffer.copyRowNTimes(xBegin, xEnd, yBegin, yEnd); return true; }
bool GIFImageDecoder::haveDecodedRow(size_t frameIndex, GIFRow::const_iterator rowBegin, size_t width, size_t rowNumber, unsigned repeatCount, bool writeTransparentPixels) { const GIFFrameContext* frameContext = m_reader->frameContext(frameIndex); // The pixel data and coordinates supplied to us are relative to the frame's // origin within the entire image size, i.e. // (frameContext->xOffset, frameContext->yOffset). There is no guarantee // that width == (size().width() - frameContext->xOffset), so // we must ensure we don't run off the end of either the source data or the // row's X-coordinates. const int xBegin = frameContext->xOffset(); const int yBegin = frameContext->yOffset() + rowNumber; const int xEnd = std::min(static_cast<int>(frameContext->xOffset() + width), size().width()); const int yEnd = std::min(static_cast<int>(frameContext->yOffset() + rowNumber + repeatCount), size().height()); if (!width || (xBegin < 0) || (yBegin < 0) || (xEnd <= xBegin) || (yEnd <= yBegin)) return true; const GIFColorMap::Table& colorTable = frameContext->localColorMap().isDefined() ? frameContext->localColorMap().table() : m_reader->globalColorMap().table(); if (colorTable.isEmpty()) return true; GIFColorMap::Table::const_iterator colorTableIter = colorTable.begin(); // Initialize the frame if necessary. ImageFrame& buffer = m_frameBufferCache[frameIndex]; if ((buffer.status() == ImageFrame::FrameEmpty) && !initFrameBuffer(frameIndex)) return false; const size_t transparentPixel = frameContext->transparentPixel(); GIFRow::const_iterator rowEnd = rowBegin + (xEnd - xBegin); ImageFrame::PixelData* currentAddress = buffer.getAddr(xBegin, yBegin); // We may or may not need to write transparent pixels to the buffer. // If we're compositing against a previous image, it's wrong, and if // we're writing atop a cleared, fully transparent buffer, it's // unnecessary; but if we're decoding an interlaced gif and // displaying it "Haeberli"-style, we must write these for passes // beyond the first, or the initial passes will "show through" the // later ones. // // The loops below are almost identical. One writes a transparent pixel // and one doesn't based on the value of |writeTransparentPixels|. // The condition check is taken out of the loop to enhance performance. // This optimization reduces decoding time by about 15% for a 3MB image. if (writeTransparentPixels) { for (; rowBegin != rowEnd; ++rowBegin, ++currentAddress) { const size_t sourceValue = *rowBegin; if ((sourceValue != transparentPixel) && (sourceValue < colorTable.size())) { *currentAddress = colorTableIter[sourceValue]; } else { *currentAddress = 0; m_currentBufferSawAlpha = true; } } } else { for (; rowBegin != rowEnd; ++rowBegin, ++currentAddress) { const size_t sourceValue = *rowBegin; if ((sourceValue != transparentPixel) && (sourceValue < colorTable.size())) *currentAddress = colorTableIter[sourceValue]; else m_currentBufferSawAlpha = true; } } // Tell the frame to copy the row data if need be. if (repeatCount > 1) buffer.copyRowNTimes(xBegin, xEnd, yBegin, yEnd); buffer.setPixelsChanged(true); return true; }
void resize(int width,int height) { releaseFrameBuffer(&frameBuffer); initFrameBuffer(&frameBuffer,width,height); scrw=width; scrh=height; }
//-------------------------------------------------------------- void testApp::setup(){ ofDisableArbTex(); ofSetTextureWrap(); //configure FBO initFrameBuffer(); //camera config #ifdef KINECT context.setupUsingXMLFile(); image.setup(&context); depth.setup(&context); xn::DepthGenerator& depthGen = depth.getXnDepthGenerator(); xn::ImageGenerator& imageGen = image.getXnImageGenerator(); XnStatus ret = xnSetViewPoint(depthGen, imageGen); cout << "Using kinect" << endl; #else //ofSetLogLevel(OF_LOG_VERBOSE); //grabber.listDevices(); //grabber.setDeviceID(7); if(grabber.initGrabber(640, 480)){ cout << "Using grabber" << endl; } else { cout << "MASSIVE FAIL" <<endl; } #endif convert.allocate(640, 480); //conversion of camera image to grayscale gray.allocate(640, 480); //grayscale tracking image kinectImage.allocate(640, 480); //image from kinect kinectDepthImage.allocate(640, 480); //Depth image from kinect finalMaskImage.allocate(640, 480);; //final composition mask sceneDepthImage.allocate(640, 480);; //scenes depthmap image finalImage.allocate(640, 480); sceneImage.allocate(640,480); pixelBuf = new unsigned char[640*480]; //temp buffer for kinect depth strea colorPixelBuf = new unsigned char[640*480*3]; //temp buffer for kinect image sceneDepthBuf = new unsigned short[640 * 480]; //depth buffer from our rendered scene kinectDepthBuf = new unsigned short[640 * 480]; //camera image buffer finalBuf = new unsigned char[640 * 480]; //final mask buffer finalImageBuf = new unsigned char[640 * 480 * 3]; //final Image buffer sceneBuffer = new unsigned char[640 * 480 * 3]; //copy of the scene in the FBO bDraw = false; //tracker = new ARToolKitPlus::TrackerSingleMarkerImpl<6,6,6, 1, 8>(width,height); tracker = new ARToolKitPlus::TrackerMultiMarkerImpl<6,6,6, 1, 64>(width,height); tracker->setPixelFormat(ARToolKitPlus::PIXEL_FORMAT_LUM); //markerboard_480-499.cfg if( !tracker->init( (const char *)ofToDataPath("bluedot.cfg").c_str(), (const char *)ofToDataPath("conf.cfg").c_str(), 1.0f, 1000.0f) ) // load std. ARToolKit camera file { printf("ERROR: init() failed\n"); delete tracker; return; } // the marker in the BCH test image has a thin border... tracker->setBorderWidth(0.125f); // set a threshold. alternatively we could also activate automatic thresholding //tracker->setThreshold(150); tracker->activateAutoThreshold(true); // let's use lookup-table undistortion for high-speed // note: LUT only works with images up to 1024x1024 tracker->setUndistortionMode(ARToolKitPlus::UNDIST_LUT); // RPP is more robust than ARToolKit's standard pose estimator tracker->setPoseEstimator(ARToolKitPlus::POSE_ESTIMATOR_RPP); tracker->setImageProcessingMode(ARToolKitPlus::IMAGE_FULL_RES); // switch to simple ID based markers // use the tool in tools/IdPatGen to generate markers tracker->setMarkerMode(ARToolKitPlus::MARKER_ID_SIMPLE); netThread = new NetworkThread(this); netThread->start(); //load textures ofDisableArbTex(); ofSetTextureWrap(); textures[0].loadImage("grass.png"); textures[1].loadImage("cobble.png"); textures[2].loadImage("dirt.png"); textures[3].loadImage("lava.png"); textures[4].loadImage("rock.png"); textures[5].loadImage("sand.png"); textures[6].loadImage("snow.png"); textures[7].loadImage("tree.png"); textures[8].loadImage("leaves.png"); mapWidth = 20; mapHeight = 20; mapDepth = 20; mapLocked = false; //fill our 3d vector with 20x20x20 mapLocked = true; array3D.resize(mapWidth); for (int i = 0; i < mapWidth; ++i) { array3D[i].resize(mapHeight); for (int j = 0; j < mapHeight; ++j) array3D[i][j].resize(mapDepth); } //create block face data and clear map Block b; vList[0] = ofxVec3f(0.0f, 0.0f, -1.0f); vList[1] = ofxVec3f(-1.0f, 0.0f, -1.0f); vList[2] = ofxVec3f(-1.0f, 0.0f, 0.0f); vList[3] = ofxVec3f(0.0f, 0.0f, 0.0f); vList[4] = ofxVec3f(-1.0f, -1.0f, 0.0f); vList[5] = ofxVec3f(0.0f, -1.0f, 0.0f); vList[6] = ofxVec3f(0.0f, -1.0f, -1.0f); vList[7] = ofxVec3f(-1.0f, -1.0f, -1.0f); //vertex indices for faces const static int faceVals[6][4] = { {2, 1, 0, 3}, //top {5, 4, 2, 3}, //front {0, 6, 5, 3},//right {4, 7, 1, 2},//left {5, 6, 7, 5},//bottom {0, 1, 7, 6} //back }; for(int x=0; x < mapWidth; x++){ for(int y=0; y < mapHeight; y++){ for(int z=0; z < mapDepth; z++){ b.type = NONE; b.textured = false; b.visMask = VIS_TOP; for(int a = 0; a < 6; a++){ for (int c = 0; c < 4; c++){ b.faceList[a][c] = faceVals[a][c]; } } array3D[x][y][z] = b; } } } //add some test blocks to play with when offline b.type = GRASS; b.textured = true; b.textureRef = 0; b.visMask = 63; array3D[1][1][5] = b; array3D[2][1][5] = b; array3D[3][1][5] = b; array3D[4][1][5] = b; array3D[5][1][5] = b; array3D[6][1][5] = b; //testBlock = b; //run the face visibility and normal calculations updateVisibility(); //dont draw the gui guiDraw = false; //scale and offset for map mapScale = 1.0f; offset.x = -100.0f; offset.y = 100.0f; scVal = 1.0f; //used as light colour (when lights eventually work) sceneWhiteLevel = ofColor(255,255,255); #ifdef SYPHON //start up syphon and set framerate mainOutputSyphonServer.setName("Minecraft"); #endif ofSetFrameRate(60); //try and set up some lights light light = { {0,50,0,1}, //position (the final 1 means the light is positional) {1,1,1,1}, //diffuse {0,0,0,1}, //specular {0,0,0,1} //ambient }; light0 = light; glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); //glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,0); //sets lighting to one-sided glLightfv(GL_LIGHT0, GL_POSITION, light0.pos); doLights(); //turn on backface culling glEnable(GL_CULL_FACE); }
void GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, // Pointer to single scanline temporary buffer unsigned char* rowEnd, unsigned rowNumber, // The row index unsigned repeatCount, // How many times to repeat the row bool writeTransparentPixels) { // Initialize the frame if necessary. RGBA32Buffer& buffer = m_frameBufferCache[frameIndex]; if (buffer.status() == RGBA32Buffer::FrameEmpty) initFrameBuffer(frameIndex); // 7/13/09 CSidhall - Alloc fail handling if(!buffer.bytes().data()) return; // Do nothing for bogus data. if (rowBuffer == 0 || static_cast<int>(m_reader->frameYOffset() + rowNumber) >= m_size.height()) return; unsigned colorMapSize; unsigned char* colorMap; m_reader->getColorMap(colorMap, colorMapSize); if (!colorMap) return; // The buffers that we draw are the entire image's width and height, so a final output frame is // width * height RGBA32 values in size. // // A single GIF frame, however, can be smaller than the entire image, i.e., it can represent some sub-rectangle // within the overall image. The rows we are decoding are within this // sub-rectangle. This means that if the GIF frame's sub-rectangle is (x,y,w,h) then row 0 is really row // y, and each row goes from x to x+w. unsigned dstPos = (m_reader->frameYOffset() + rowNumber) * m_size.width() + m_reader->frameXOffset(); unsigned* dst = buffer.bytes().data() + dstPos; unsigned* dstEnd = dst + m_size.width() - m_reader->frameXOffset(); unsigned* currDst = dst; unsigned char* currentRowByte = rowBuffer; while (currentRowByte != rowEnd && currDst < dstEnd) { if ((!m_reader->isTransparent() || *currentRowByte != m_reader->transparentPixel()) && *currentRowByte < colorMapSize) { unsigned colorIndex = *currentRowByte * 3; unsigned red = colorMap[colorIndex]; unsigned green = colorMap[colorIndex + 1]; unsigned blue = colorMap[colorIndex + 2]; RGBA32Buffer::setRGBA(*currDst, red, green, blue, 255); } else { m_currentBufferSawAlpha = true; // We may or may not need to write transparent pixels to the buffer. // If we're compositing against a previous image, it's wrong, and if // we're writing atop a cleared, fully transparent buffer, it's // unnecessary; but if we're decoding an interlaced gif and // displaying it "Haeberli"-style, we must write these for passes // beyond the first, or the initial passes will "show through" the // later ones. if (writeTransparentPixels) RGBA32Buffer::setRGBA(*currDst, 0, 0, 0, 0); } currDst++; currentRowByte++; } if (repeatCount > 1) { // Copy the row |repeatCount|-1 times. unsigned num = currDst - dst; unsigned size = num * sizeof(unsigned); unsigned width = m_size.width(); unsigned* end = buffer.bytes().data() + width * m_size.height(); currDst = dst + width; for (unsigned i = 1; i < repeatCount; i++) { if (currDst + num > end) // Protect against a buffer overrun from a bogus repeatCount. break; memcpy(currDst, dst, size); currDst += width; } } // Our partial height is rowNumber + 1, e.g., row 2 is the 3rd row, so that's a height of 3. // Adding in repeatCount - 1 to rowNumber + 1 works out to just be rowNumber + repeatCount. buffer.ensureHeight(rowNumber + repeatCount); }