void Texture :: configure(AlloArrayHeader& header) { switch (header.dimcount) { case 1: target(TEXTURE_1D); break; case 2: target(TEXTURE_2D); break; case 3: target(TEXTURE_3D); break; default: AL_WARN("invalid array dimensions for texture"); return; } switch (header.dimcount) { case 3: depth(header.dim[2]); case 2: height(header.dim[1]); case 1: width(header.dim[0]); break; } switch (header.components) { case 1: format(Graphics::LUMINANCE); break; // alpha or luminance? case 2: format(Graphics::LUMINANCE_ALPHA); break; case 3: format(Graphics::RGB); break; case 4: format(Graphics::RGBA); break; default: AL_WARN("invalid array component count for texture"); return; } switch (header.type) { case AlloUInt8Ty: type(Graphics::UBYTE); break; case AlloSInt8Ty: type(Graphics::BYTE); break; case AlloUInt16Ty: type(Graphics::SHORT); break; case AlloSInt16Ty: type(Graphics::USHORT); break; case AlloUInt32Ty: type(Graphics::INT); break; case AlloSInt32Ty: type(Graphics::UINT); break; case AlloFloat32Ty: type(Graphics::FLOAT); break; case AlloFloat64Ty: type(Graphics::DOUBLE); break; default: AL_WARN("invalid array type for texture"); return; } // reconfigure internal array to match: mArray.configure(header); mParamsUpdated = true; }
ProtoApp& ProtoApp::resourceDir(const std::string& dir, bool searchBack){ std::string modDir = dir; if(searchBack){ if(!al::File::searchBack(modDir)){ AL_WARN("Could not find %s", modDir.c_str()); exit(0); } } mResourceDir = modDir; if(mResourceDir[mResourceDir.size()-1] != AL_FILE_DELIMITER){ mResourceDir += AL_FILE_DELIMITER_STR; } return *this; }
int glob(const std::string& regex, FileList& result, bool recursive=true) { std::regex e(regex); if (dir && APR_SUCCESS == check_apr(apr_dir_open(&dir, dirname.c_str(), mPool))) { // iterate over directory: while (APR_SUCCESS == (apr_dir_read(&dirent, APR_FINFO_TYPE|APR_FINFO_NAME, dir))) { //printf("test %s %s\n", dirname.c_str(), dirent.name); if (dirent.filetype == APR_REG && dirent.name && std::regex_match(dirname+dirent.name,e) ) { FilePath res; res.file(dirent.name); res.path(dirname); result.add(res); } else if (recursive && dirent.filetype == APR_DIR && dirent.name && dirent.name[0] != '.') { Path path(dirname + dirent.name + AL_FILE_DELIMITER); path.glob(regex, result, true); } } } else { AL_WARN("couldn't open directory %s", dirname.c_str()); } return result.count(); }
bool find(const std::string& name, FilePath& result, bool recursive=true) { bool found = false; if (dir && APR_SUCCESS == check_apr(apr_dir_open(&dir, dirname.c_str(), mPool))) { // iterate over directory: while ((!found) && APR_SUCCESS == (apr_dir_read(&dirent, APR_FINFO_TYPE|APR_FINFO_NAME, dir))) { //printf("test %s %s\n", dirname.c_str(), dirent.name); if (dirent.filetype == APR_REG && dirent.name && std::string(dirent.name) == name) { result.file(dirent.name); result.path(dirname); found = true; break; } else if (recursive && dirent.filetype == APR_DIR && dirent.name && dirent.name[0] != '.') { Path path(dirname + dirent.name + AL_FILE_DELIMITER); found = path.find(name, result, true); } } } else { AL_WARN("couldn't open directory %s", dirname.c_str()); } return found; }
virtual bool load(const std::string& filename, Array &lat) { FREE_IMAGE_FORMAT type = FreeImage_GetFIFFromFilename(filename.c_str()); if(type == FIF_UNKNOWN) { AL_WARN("image format not recognized: %s", filename.c_str()); return false; } if(!FreeImage_FIFSupportsReading(type)) { AL_WARN("image format not supported: %s", filename.c_str()); return false; } destroy(); mImage = FreeImage_Load(type, filename.c_str(), 0); if (mImage == NULL) { AL_WARN("image failed to load: %s", filename.c_str()); return false; } FREE_IMAGE_COLOR_TYPE colorType = FreeImage_GetColorType(mImage); switch(colorType) { case FIC_MINISBLACK: case FIC_MINISWHITE: { FIBITMAP *res = FreeImage_ConvertToGreyscale(mImage); FreeImage_Unload(mImage); mImage = res; } break; case FIC_PALETTE: { if(FreeImage_IsTransparent(mImage)) { FIBITMAP *res = FreeImage_ConvertTo32Bits(mImage); FreeImage_Unload(mImage); mImage = res; } else { FIBITMAP *res = FreeImage_ConvertTo24Bits(mImage); FreeImage_Unload(mImage); mImage = res; } } break; case FIC_CMYK: { AL_WARN("CMYK images currently not supported"); return false; } break; default: break; } // flip vertical for OpenGL: //FreeImage_FlipVertical(mImage); //Freeimage is not tightly packed, so we use //a custom method instead of one of the Matrix //utility methods int planes = getPlanes(); AlloTy ty = getDataType(); int w, h; getDim(w, h); lat.format(planes, ty, w, h); Image::Format format = Image::getFormat(planes); switch(format) { case Image::LUMINANCE: { char *o_pix = (char *)(lat.data.ptr); int rowstride = lat.header.stride[1]; for(unsigned j = 0; j < lat.header.dim[1]; ++j) { char *pix = (char *)FreeImage_GetScanLine(mImage, j); memcpy(o_pix, pix, rowstride); o_pix += rowstride; } } break; case Image::RGB: { switch(lat.header.type) { case AlloUInt8Ty: { char *bp = (char *)(lat.data.ptr); int rowstride = lat.header.stride[1]; for(unsigned j = 0; j < lat.header.dim[1]; ++j) { RGBTRIPLE * pix = (RGBTRIPLE *)FreeImage_GetScanLine(mImage, j); Image::RGBPix<uint8_t> *o_pix = (Image::RGBPix<uint8_t> *)(bp + j*rowstride); for(unsigned i=0; i < lat.header.dim[0]; ++i) { o_pix->r = pix->rgbtRed; o_pix->g = pix->rgbtGreen; o_pix->b = pix->rgbtBlue; ++pix; ++o_pix; } } } break; case AlloFloat32Ty: { char *o_pix = (char *)(lat.data.ptr); int rowstride = lat.header.stride[1]; for(unsigned j = 0; j < lat.header.dim[1]; ++j) { char *pix = (char *)FreeImage_GetScanLine(mImage, j); memcpy(o_pix, pix, rowstride); o_pix += rowstride; } } break; default: break; } } break; case Image::RGBA: { switch(lat.header.type) { case AlloUInt8Ty: { char *bp = (char *)(lat.data.ptr); int rowstride = lat.header.stride[1]; for(unsigned j = 0; j < lat.header.dim[1]; ++j) { RGBQUAD *pix = (RGBQUAD *)FreeImage_GetScanLine(mImage, j); Image::RGBAPix<uint8_t> *o_pix = (Image::RGBAPix<uint8_t> *)(bp + j*rowstride); for(unsigned i=0; i < lat.header.dim[0]; ++i) { o_pix->r = pix->rgbRed; o_pix->g = pix->rgbGreen; o_pix->b = pix->rgbBlue; o_pix->a = pix->rgbReserved; ++pix; ++o_pix; } } } break; case AlloFloat32Ty: { char *o_pix = (char *)(lat.data.ptr); int rowstride = lat.header.stride[1]; for(unsigned j = 0; j < lat.header.dim[1]; ++j) { char *pix = (char *)FreeImage_GetScanLine(mImage, j); memcpy(o_pix, pix, rowstride); o_pix += rowstride; } } break; default: break; } } break; default: AL_WARN("image data not understood"); destroy(); return false; } return true; }
virtual bool save(const std::string& filename, const Array& lat) { // check existing image type FREE_IMAGE_FORMAT type = FreeImage_GetFIFFromFilename(filename.c_str()); if(type == FIF_UNKNOWN) { AL_WARN("image format not recognized: %s", filename.c_str()); return false; } if(!FreeImage_FIFSupportsWriting(type)) { AL_WARN("image format not supported: %s", filename.c_str()); return false; } destroy(); const AlloArrayHeader& header = lat.header; int w = header.dim[0]; int h = (header.dimcount > 1) ? header.dim[1] : 1; Image::Format format = Image::getFormat(header.components); switch(format) { case Image::RGB: { switch(header.type) { case AlloUInt8Ty: { int bpp = header.stride[0]; mImage = FreeImage_AllocateT(FIT_BITMAP, w, h, bpp*8); char *bp = (char *)(lat.data.ptr); int rowstride = header.stride[1]; for(unsigned j = 0; j < header.dim[1]; ++j) { // copy Array row to image buffer /*memcpy( FreeImage_GetScanLine(mImage, j), bp + j*rowstride, w*3 );*/ RGBTRIPLE *pix = (RGBTRIPLE *)FreeImage_GetScanLine(mImage, j); Image::RGBPix<uint8_t> *o_pix = (Image::RGBPix<uint8_t> *)(bp + j*rowstride); for(unsigned i=0; i < header.dim[0]; ++i) { pix->rgbtRed = o_pix->r; pix->rgbtGreen = o_pix->g; pix->rgbtBlue = o_pix->b; ++pix; ++o_pix; } } } break; default: AL_WARN("input matrix type not supported"); break; } } break; case Image::RGBA: { switch(header.type) { case AlloUInt8Ty: { int bpp = header.stride[0]; mImage = FreeImage_AllocateT(FIT_BITMAP, w, h, bpp*8); char *bp = (char *)(lat.data.ptr); int rowstride = header.stride[1]; for(unsigned j = 0; j < header.dim[1]; ++j) { // copy Array row to image buffer /*memcpy( FreeImage_GetScanLine(mImage, j), bp + j*rowstride, w*4 );*/ RGBQUAD *pix = (RGBQUAD *)FreeImage_GetScanLine(mImage, j); Image::RGBAPix<uint8_t> *o_pix = (Image::RGBAPix<uint8_t> *)(bp + j*rowstride); for(unsigned i=0; i < header.dim[0]; ++i) { pix->rgbRed = o_pix->r; pix->rgbGreen = o_pix->g; pix->rgbBlue = o_pix->b; pix->rgbReserved = o_pix->a; ++pix; ++o_pix; } } } break; default: AL_WARN("input matrix type not supported"); return false; } } break; default: { AL_WARN("input matrix format not supported"); return false; } } if (mImage == NULL) { AL_WARN("image could not be understood"); return false; } return FreeImage_Save(type, mImage, filename.c_str(), 0); }
void Texture :: submit(const void * pixels, uint32_t align) { Graphics::error(id(), "Texture::submit (initial)"); validate(); determineTarget(); // is this necessary? surely the target is already set! sendParams(false); glActiveTexture(GL_TEXTURE0); Graphics::error(id(), "Texture::submit (glActiveTexture)"); glEnable(target()); Graphics::error(id(), "Texture::submit (glEnable(texture target))"); glBindTexture(target(), id()); Graphics::error(id(), "Texture::submit (glBindTexture)"); // set glPixelStore according to layout: glPixelStorei(GL_UNPACK_ALIGNMENT, mUnpack); Graphics::error(id(), "Texture::submit (glPixelStorei set)"); // void glTexImage3D( // GLenum target, GLint level, GLenum internalformat, // GLsizei width, GLsizei height, GLsizei depth, // GLint border, GLenum format, GLenum type, const GLvoid *pixels // ); // // internal format is important // // TODO: complete the derivation, probably do it elsewhere... // if(type() == Graphics::FLOAT || type() == Graphics::DOUBLE){ // switch(numComponents()){ // case 1: intFmt = GL_LUMINANCE32F_ARB; break; // case 2: intFmt = GL_LUMINANCE_ALPHA32F_ARB; break; // case 3: intFmt = GL_RGB32F_ARB; break; // case 4: intFmt = GL_RGBA32F_ARB; break; // default:; // } // } else { // // the old way - let the GPU decide: // intFmt = numComponents(); // } int intFmt; // Use specified texel format, if defined if(mTexelFormat){ intFmt = mTexelFormat; } // Derive internal texel format from texture data format. // By default, we can just use the texture data format. In cases where // there is no corresponding texel format, just hand in the number of // components. else{ if( format() == Graphics::RED || format() == Graphics::GREEN || format() == Graphics::BLUE ){ intFmt = 1; } else if(format() == Graphics::BGRA){ intFmt = 4; } else{ intFmt = format(); } } switch(mTarget){ case GL_TEXTURE_1D: glTexImage1D(mTarget, 0, intFmt, width(), 0, format(), type(), pixels); break; case GL_TEXTURE_2D: glTexImage2D(mTarget, 0, intFmt, width(), height(), 0, format(), type(), pixels); break; case GL_TEXTURE_3D: glTexImage3D(mTarget, 0, intFmt, width(), height(), depth(), 0, format(), type(), pixels); break; default: AL_WARN("invalid texture target %d", mTarget); } Graphics::error(id(), "Texture::submit (glTexImage)"); // set alignment back to default glPixelStorei(GL_UNPACK_ALIGNMENT, 4); Graphics::error(id(), "Texture::submit (glPixelStorei unset)"); // // OpenGL may have changed the internal format to one it supports: // GLint format; // glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &format); // if (format != mInternalFormat) { // printf("converted from %X to %X format\n", mInternalFormat, format); // mInternalFormat = format; // } //printf("submitted texture data %p\n", pixels); glDisable(target()); glBindTexture(target(), 0); Graphics::error(id(), "Texture::submit (glBindTexture 0)"); }
void Texture :: submit(const Array& src, bool reconfigure) { // if (src.type() != AlloUInt8Ty) { // printf("submit failed: only uint8_t arrays are supported\n"); // return; // } if (reconfigure) { // reconfigure texture from array switch (src.dimcount()) { case 1: target(TEXTURE_1D); break; case 2: target(TEXTURE_2D); break; case 3: target(TEXTURE_3D); break; default: AL_WARN("invalid array dimensions for texture"); return; } switch (src.dimcount()) { case 3: depth(src.depth()); case 2: height(src.height()); case 1: width(src.width()); break; } switch (src.components()) { case 1: format(Graphics::LUMINANCE); break; // alpha or luminance? case 2: format(Graphics::LUMINANCE_ALPHA); break; case 3: format(Graphics::RGB); break; case 4: format(Graphics::RGBA); break; default: AL_WARN("invalid array component count for texture"); return; } switch (src.type()) { case AlloUInt8Ty: type(Graphics::UBYTE); break; case AlloSInt8Ty: type(Graphics::BYTE); break; case AlloUInt16Ty: type(Graphics::SHORT); break; case AlloSInt16Ty: type(Graphics::USHORT); break; case AlloUInt32Ty: type(Graphics::INT); break; case AlloSInt32Ty: type(Graphics::UINT); break; case AlloFloat32Ty: type(Graphics::FLOAT); break; case AlloFloat64Ty: type(Graphics::DOUBLE); break; default: AL_WARN("invalid array type for texture"); return; } // reformat internal array to match: if (!mArray.isFormat(src)) mArray.format(src); //printf("configured to target=%X(%dD), type=%X(%X), format=%X, align=(%d)\n", mTarget, src.dimcount(), type(), src.type(), mFormat, src.alignment()); } else { if (src.width() != width()) { AL_WARN("submit failed: source array width does not match"); return; } if (target() != TEXTURE_1D) { if (height() && src.height() != height()) { AL_WARN("submit failed: source array height does not match"); return; } if (target() == TEXTURE_3D) { if (depth() && src.depth() != depth()) { AL_WARN("submit failed: source array depth does not match"); return; } } } if (Graphics::toDataType(src.type()) != type()) { AL_WARN("submit failed: source array type does not match texture"); return; } switch (format()) { case Graphics::ALPHA: case Graphics::LUMINANCE: if (src.components() != 1) { AL_WARN("submit failed: source array component count does not match (got %d, should be 1)", src.components()); return; } break; case Graphics::LUMINANCE_ALPHA: if (src.components() != 2) { AL_WARN("submit failed: source array component count does not match (got %d, should be 2)", src.components()); return; } break; case Graphics::RGB: if (src.components() != 3) { AL_WARN("submit failed: source array component count does not match (got %d, should be 3)", src.components()); return; } break; case Graphics::RGBA: if (src.components() != 4) { AL_WARN("submit failed: source array component count does not match (got %d, should be 4)", src.components()); return; } break; default: break; } } submit(src.data.ptr, src.alignment()); }
void Texture :: allocate(const Array& src, bool reconfigure) { if (reconfigure) { //printf("allocating & reconfiguring %p from\n", this); src.print(); // reconfigure texture from array: switch (src.dimcount()) { case 1: target(TEXTURE_1D); break; case 2: target(TEXTURE_2D); break; case 3: target(TEXTURE_3D); break; default: AL_WARN("invalid array dimensions for texture"); return; } // reconfigure size: switch (src.dimcount()) { case 3: depth(src.depth()); case 2: height(src.height()); case 1: width(src.width()); break; default: AL_WARN("texture array must have 1, 2 or 3 dimenions"); return; } // reconfigure components // (only if necessary - no need to lose e.g. // mFormat = DEPTH_COMPONENT if we are only changing size) if (Graphics::numComponents(mFormat) != src.components()) { switch (src.components()) { case 1: format(Graphics::LUMINANCE); break; // alpha or luminance? case 2: format(Graphics::LUMINANCE_ALPHA); break; case 3: format(Graphics::RGB); break; case 4: format(Graphics::RGBA); break; default: AL_WARN("invalid array component count for texture"); return; } } mArray.format(src); //printf("allocating & reconfigured %p\n", this); mArray.print(); // re-allocate array: allocate(src.alignment()); //printf("allocated & reconfigured %p\n", this); //mArray.print(); } else { // TODO: read the source into the dst without changing dst layout //printf("allocating without reconfiguring %p\n", this); // ensure that array matches texture: if (!src.isFormat(mArray.header)) { AL_WARN("couldn't allocate array, mismatch format"); mArray.print(); src.print(); return; } // re-allocate array: allocate(); } //src.print(); //mArray.print(); // copy data: memcpy(mArray.data.ptr, src.data.ptr, src.size()); //printf("copied to mArray %p\n", this); }
extern "C" void al_main_native_enter(al_sec interval) { AL_WARN("Win32 native loop not yet implemented"); }
extern "C" void al_main_native_attach(al_sec interval) { AL_WARN("Linux native loop not yet implemented"); }
virtual bool save(const std::string& filename, const Array& arr, int compressFlags) { // check existing image type FREE_IMAGE_FORMAT fileType = FreeImage_GetFIFFromFilename(filename.c_str()); if(fileType == FIF_UNKNOWN) { AL_WARN("image format not recognized: %s", filename.c_str()); return false; } if(!FreeImage_FIFSupportsWriting(fileType)) { AL_WARN("image format not supported: %s", filename.c_str()); return false; } Image::Format format = Image::getFormat(arr.components()); if(FIF_JPEG == fileType && (Image::RGBA == format || Image::LUMALPHA == format)) { AL_WARN("cannot save JPEG with alpha channel; use 24-bit RGB or 8-bit grayscale/luminance"); return false; } unsigned w = arr.dim(0); unsigned h = (arr.dimcount() > 1) ? arr.dim(1) : 1; int bpp = arr.stride(0)*8; // bits/pixel resize(w,h,bpp); if (mImage == NULL) { AL_WARN("image could not be understood"); return false; } const int rowstride = arr.stride(1); //printf("w=%d, h=%d, bpp=%d, stride=%d\n", w,h,bpp,rowstride); switch(format) { case Image::LUMINANCE: switch(arr.type()) { case AlloUInt8Ty: { char *bp = (char *)(arr.data.ptr); for(unsigned j = 0; j < h; ++j) { memcpy( FreeImage_GetScanLine(mImage, j), bp + j*rowstride, w ); } } break; default: AL_WARN("input Array component type not supported"); return false; } break; // TODO: must save as RGBA /*case Image::LUMALPHA: switch(header.type) { case AlloUInt8Ty: { char *bp = (char *)(arr.data.ptr); for(unsigned j = 0; j < h; ++j) { memcpy( FreeImage_GetScanLine(mImage, j), bp + j*rowstride, w*2 ); } } break; default: AL_WARN("input Array component type not supported"); return false; } break;*/ /* According to the FreeImage documentation ("Pixel access functions"): "When accessing to individual color components of a 24- or 32-bit DIB, you should always use FreeImage macros or RGBTRIPLE / RGBQUAD structures in order to write OS independent code. */ case Image::RGB: { switch(arr.type()) { case AlloUInt8Ty: { //printf("FreeImageImpl: save uint8/RGB\n"); char *bp = (char *)(arr.data.ptr); for(unsigned j = 0; j < h; ++j) { RGBTRIPLE * dst = (RGBTRIPLE *)FreeImage_GetScanLine(mImage, j); const Image::RGBPix<uint8_t> * src = (const Image::RGBPix<uint8_t> *)(bp + j*rowstride); for(unsigned i=0; i < w; ++i) { dst[i].rgbtRed = src[i].r; dst[i].rgbtGreen= src[i].g; dst[i].rgbtBlue = src[i].b; } } } break; default: AL_WARN("input Array component type not supported"); return false; } } break; case Image::RGBA: { switch(arr.type()) { case AlloUInt8Ty: { char *bp = (char *)(arr.data.ptr); for(unsigned j = 0; j < h; ++j) { RGBQUAD * dst = (RGBQUAD *)FreeImage_GetScanLine(mImage, j); const Image::RGBAPix<uint8_t> * src = (const Image::RGBAPix<uint8_t> *)(bp + j*rowstride); for(unsigned i=0; i < w; ++i) { dst[i].rgbRed = src[i].r; dst[i].rgbGreen = src[i].g; dst[i].rgbBlue = src[i].b; dst[i].rgbReserved= src[i].a; } } } break; default: AL_WARN("input Array component type not supported"); return false; } } break; default: { AL_WARN("input Array component format not supported"); return false; } } int flags; int compressAmt = compressFlags & 127; int quality = 100-(compressAmt<=100?compressAmt:100); switch(fileType) { case FIF_BMP: flags = compressAmt >= 50 ? BMP_SAVE_RLE : BMP_DEFAULT; break; case FIF_EXR: flags = compressAmt >= 50 ? EXR_DEFAULT : EXR_NONE; break; case FIF_JPEG: // default: JPEG_QUALITYGOOD|JPEG_SUBSAMPLING_420 /*if(compressAmt <= 25) flags = JPEG_QUALITYSUPERB; else if(compressAmt <= 50) flags = JPEG_QUALITYGOOD; else if(compressAmt <= 75) flags = JPEG_QUALITYAVERAGE; else flags = JPEG_QUALITYBAD;*/ flags = quality; break; case FIF_J2K: case FIF_JP2: flags = int(double(quality)*5.11 + 1); // convert [0,100] -> [1,512] break; case FIF_PNG: // default: PNG_Z_DEFAULT_COMPRESSION (= 6) compressAmt = (compressAmt + 5) / 10; if(compressAmt != 0) flags = compressAmt>=9 ? 9 : compressAmt; else flags = PNG_Z_NO_COMPRESSION; break; case FIF_TIFF: flags = compressAmt >= 50 ? TIFF_DEFAULT : TIFF_NONE; break; case FIF_TARGA: flags = compressAmt >= 50 ? TARGA_SAVE_RLE : TARGA_DEFAULT; break; default: flags = 0; } return FreeImage_Save(fileType, mImage, filename.c_str(), flags); }