Ejemplo n.º 1
0
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;
}