/*--------------------------------------------------------------------------- Captures the contents of the frame buffer object for streaming purposes. Returns true if the frame was successfully captured. If the Wait flag is set, the function with use a blocking mutex lock on the Frame texture. ---------------------------------------------------------------------------*/ bool Filter::Capture(Texture &Frame, bool Wait) { if (!Ready()) {return false;} MutexControl Mutex(Frame.GetMutexHandle()); if (!Wait && !Mutex.LockRequest()) {return false;} else {Mutex.Lock();} vector2u Res = Frame.Resolution(); if (Res.U != ViewPort.C2 || Res.V != ViewPort.C3 || Frame.DataType() != Texture::TypeRGB) { Res.Set(ViewPort.C2, ViewPort.C3); Frame.Create(Res, Texture::TypeRGB); } glBindFramebuffer(GL_READ_FRAMEBUFFER, FBOID); glReadPixels(0, 0, Res.U, Res.V, Frame.DataFormat(), Frame.DataCompType(), Frame.Pointer()); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); #if defined (DEBUG) GLenum Error = glGetError(); if (Error != GL_NO_ERROR) {throw dexception("OpenGL generated an error: %s", Debug::ErrorGL(Error));} #endif return true; }
/*--------------------------------------------------------------------------- Updates the texture object in video memory with data from another texture. Assumes Bind( ) was called prior. ---------------------------------------------------------------------------*/ void Texture::Update(const Texture &obj) { if (ID < 1 || obj.Size() < 1 || Type != obj.DataType()) {return;} const vector2u TexRes = obj.Resolution(); if (Res.U != TexRes.U || Res.V != TexRes.V) {return;} glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Res.U, Res.V, Format, CompType, obj.Pointer()); glGenerateMipmap(GL_TEXTURE_2D); }
/*--------------------------------------------------------------------------- Saves a PNG file. Image : Image to save. Path : Path to image file, relative to the current working directory. Compress : Specifies the compression level to use for encoding. ---------------------------------------------------------------------------*/ void PNG::Save(const Texture &Image, const std::string &Path, CompLevel Compress) { Destroy(); //Important - set class to writing mode Mode = PNG::ModeWrite; vector2u Res = Image.Resolution(); if (Res.U < 1 || Res.V < 1) {return;} #if defined (WINDOWS) if (fopen_s(&File, Path.c_str(), "wb") != 0) {throw dexception("Failed to open file: %s.", Path.c_str());} #else File = fopen(Path.c_str(), "wb"); if (File == nullptr) {throw dexception("Failed to open file: %s.", Path.c_str());} #endif PngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (PngPtr == nullptr) {throw dexception("png_create_write_struct( ) failed.");} InfoPtr = png_create_info_struct(PngPtr); if (InfoPtr == nullptr) {throw dexception("png_create_info_struct( ) failed.");} if (setjmp(png_jmpbuf(PngPtr))) {throw dexception("setjmp( ) failed.");} png_init_io(PngPtr, File); png_set_compression_level(PngPtr, (int)Compress); int BitDepth, ColourType; switch (Image.DataType()) { case Texture::TypeAlpha : BitDepth = 8; ColourType = PNG_COLOR_TYPE_GRAY; break; case Texture::TypeLum : BitDepth = 8; ColourType = PNG_COLOR_TYPE_GRAY; break; case Texture::TypeDepth : BitDepth = 16; ColourType = PNG_COLOR_TYPE_GRAY; break; case Texture::TypeRGB : BitDepth = 8; ColourType = PNG_COLOR_TYPE_RGB; break; case Texture::TypeRGBA : BitDepth = 8; ColourType = PNG_COLOR_TYPE_RGB_ALPHA; break; default : throw dexception("Unsupported image type."); break; } png_set_IHDR(PngPtr, InfoPtr, (png_uint_32)Res.U, (png_uint_32)Res.V, BitDepth, ColourType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_sRGB(PngPtr, InfoPtr, PNG_sRGB_INTENT_ABSOLUTE); png_set_sRGB_gAMA_and_cHRM(PngPtr, InfoPtr, PNG_sRGB_INTENT_ABSOLUTE); png_color_16 BackGnd; BackGnd.red = 0; BackGnd.green = 0; BackGnd.blue = 0; png_set_bKGD(PngPtr, InfoPtr, &BackGnd); png_text PngText[2]; memset(PngText, 0, sizeof(PngText)); PngText[0].compression = PNG_TEXT_COMPRESSION_NONE; PngText[0].key = const_cast<png_charp>("Software"); PngText[0].text = const_cast<png_charp>(AppName); PngText[0].text_length = strlen(PngText[0].text); PngText[1].compression = PNG_TEXT_COMPRESSION_NONE; PngText[1].key = const_cast<png_charp>("Author"); PngText[1].text = const_cast<png_charp>(AppAuthor); PngText[1].text_length = strlen(PngText[1].text); png_set_text(PngPtr, InfoPtr, PngText, 2); png_write_info(PngPtr, InfoPtr); //Populate row pointer array Rows.Create((usize)Res.V); for (uiter I = 0; I < (usize)Res.V; I++) { Rows[I] = Image.Address(0, I); } //Encode png_write_image(PngPtr, Rows.Pointer()); png_write_end(PngPtr, nullptr); //Clean up Destroy(); }