void GLContext::drawImage(const Image& image, const Vec4f& pos, const Vec2f& align, bool topToBottom) { const Vec2i& imgSize = image.getSize(); if (imgSize.min() <= 0) return; Buffer& buf = image.getBuffer(); ImageFormat format = image.getFormat().getGLFormat(); const ImageFormat::StaticFormat* sf = format.getStaticFormat(); glActiveTexture(GL_TEXTURE0); const Vec2i& texSize = bindTempTexture(imgSize); // Format is not supported by GL => convert and upload. if (image.getFormat() != format || image.getStride() != imgSize.x * format.getBPP()) { Image converted(imgSize, format); converted = image; glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, imgSize.x, imgSize.y, sf->glFormat, sf->glType, converted.getPtr()); } // Data is already on the GPU => transfer to the texture. else if (buf.getOwner() == Buffer::GL || (buf.getOwner() == Buffer::Cuda && (buf.getHints() & Buffer::Hint_CudaGL) != 0)) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf.getGLBuffer()); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, imgSize.x, imgSize.y, sf->glFormat, sf->glType, NULL); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); } // Otherwise => upload. else { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, imgSize.x, imgSize.y, sf->glFormat, sf->glType, buf.getPtr()); } // Determine orientation. Vec4f posLo = m_vgXform * pos; Vec2f posRange = Vec2f(imgSize) * m_viewScale * posLo.w; posLo -= Vec4f(align * posRange, 0.0f, 0.0f); Vec2f posHi = posLo.getXY() + posRange; if (topToBottom) swap(posLo.y, posHi.y); // Draw texture. glPushAttrib(GL_ENABLE_BIT); glDisable(GL_CULL_FACE); drawTexture(0, posLo, posHi, Vec2f(0.0f), Vec2f(imgSize) / Vec2f(texSize)); glPopAttrib(); checkErrors(); }
Image* FW::importBinaryImage(InputStream& stream) { // ImageHeader. char formatID[9]; stream.readFully(formatID, 8); formatID[8] = '\0'; if (String(formatID) != "BinImage") { setError("Not a binary image file!"); return NULL; } S32 version; stream >> version; if (version != 1) { setError("Unsupported binary image version!"); return NULL; } S32 width, height, bpp, numChannels; stream >> width >> height >> bpp >> numChannels; if (width < 0 || height < 0 || bpp < 0 || numChannels < 0) { setError("Corrupt binary image data!"); return NULL; } // Array of ImageChannel. ImageFormat format; for (int i = 0; i < numChannels; i++) { S32 ctype, cformat; ImageFormat::Channel c; stream >> ctype >> cformat >> c.wordOfs >> c.wordSize >> c.fieldOfs >> c.fieldSize; if (ctype < 0 || cformat < 0 || cformat >= ImageFormat::ChannelFormat_Max || c.wordOfs < 0 || (c.wordSize != 1 && c.wordSize != 2 && c.wordSize != 4) || c.fieldOfs < 0 || c.fieldSize <= 0 || c.fieldOfs + c.fieldSize > c.wordSize * 8 || (cformat == ImageFormat::ChannelFormat_Float && c.fieldSize != 32)) { setError("Corrupt binary image data!"); return NULL; } c.type = (ImageFormat::ChannelType)ctype; c.format = (ImageFormat::ChannelFormat)cformat; format.addChannel(c); } if (bpp != format.getBPP()) { setError("Corrupt binary image data!"); return NULL; } // Image data. Image* image = new Image(Vec2i(width, height), format); stream.readFully(image->getMutablePtr(), width * height * bpp); // Handle errors. if (hasError()) { delete image; return NULL; } return image; }