static void initializeWithData(ZPTexture *texture, zpColor *imageData, zpInt32 imageWidth, zpInt32 imageHeight) { ZPObject_initialize((ZPObject *)texture); texture->supertype = ZPObject_prototype(); // overrides of super-object functions texture->destroy = (void (*)(ZPObject *))&destroy; texture->typeName = (const char *(*)(ZPObject *))&typeName; texture->getHardwareIdentifier = &getHardwareIdentifier; zpInt32 textureWidth = nextPowerOf2(imageWidth); zpInt32 textureHeight = nextPowerOf2(imageHeight); zpInt32 textureSize = maximumTextureSize(); if (textureWidth > textureSize) { ZPLog("warning: image width (%d) exceeds maximum texture size (%d)", imageWidth, textureSize); textureWidth = textureSize; } if (textureHeight > textureSize) { ZPLog("warning: image height (%d) exceeds maximum texture size (%d)", imageHeight, textureSize); textureHeight = textureSize; } zpInt32 imageSize = imageWidth * imageHeight; texture->_imageData = malloc(imageSize * sizeof(zpColor)); memcpy(texture->_imageData, imageData, imageSize * sizeof(zpColor)); texture->_width = textureWidth; texture->_height = textureHeight; texture->_hardwareIdentifier = kZPTextureUninitializedHardwareIdentifier; }
Surface renderStringPow2( const string &str, const Font &font, const ColorA &color, Vec2i *actualSize, float *baselineOffset ) { Vec2i pixelSize, pow2PixelSize; { // render "invisible" to a dummy context to determine string width Surface temp( 1, 1, true, SurfaceChannelOrder::RGBA ); ::CGContextRef cgContext = cocoa::createCgBitmapContext( temp ); ::CGContextSelectFont( cgContext, font.getName().c_str(), font.getSize(), kCGEncodingMacRoman ); ::CGContextSetTextDrawingMode( cgContext, kCGTextInvisible ); ::CGPoint startPoint = ::CGContextGetTextPosition( cgContext ); ::CGContextShowText( cgContext, str.c_str(), str.length() ); ::CGPoint endPoint = ::CGContextGetTextPosition( cgContext ); pixelSize = Vec2i( math<float>::ceil( endPoint.x - startPoint.x ), math<float>::ceil( font.getAscent() - font.getDescent() ) ); ::CGContextRelease( cgContext ); } pow2PixelSize = Vec2i( nextPowerOf2( pixelSize.x ), nextPowerOf2( pixelSize.y ) ); Surface result( pow2PixelSize.x, pow2PixelSize.y, true ); ::CGContextRef cgContext = cocoa::createCgBitmapContext( result ); ip::fill( &result, ColorA( 0, 0, 0, 0 ) ); ::CGContextSelectFont( cgContext, font.getName().c_str(), font.getSize(), kCGEncodingMacRoman ); ::CGContextSetTextDrawingMode( cgContext, kCGTextFill ); ::CGContextSetRGBFillColor( cgContext, color.r, color.g, color.b, color.a ); ::CGContextSetTextPosition( cgContext, 0, -font.getDescent() + 1 ); ::CGContextShowText( cgContext, str.c_str(), str.length() ); if( baselineOffset ) *baselineOffset = font.getDescent(); if( actualSize ) *actualSize = pixelSize; ::CGContextRelease( cgContext ); return result; }
static Texture* addTexture(MAHandle image, GLuint handle) { int imageWidth = EXTENT_X(maGetImageSize(image)); int imageHeight = EXTENT_Y(maGetImageSize(image)); textures[numTextures].glTexture = handle; textures[numTextures].maTexture = image; textures[numTextures].imageWidth = imageWidth; textures[numTextures].imageHeight = imageHeight; textures[numTextures].textureWidth = nextPowerOf2(1, imageWidth); textures[numTextures].textureHeight = nextPowerOf2(1, imageHeight); textures[numTextures].textureWidthInv = 0x10000/textures[numTextures].textureWidth; textures[numTextures].textureHeightInv = 0x10000/textures[numTextures].textureHeight; // cache texture coordinates (for the most common case, drawImage). textures[numTextures].textureCoords[0] = 0; textures[numTextures].textureCoords[1] = 0; textures[numTextures].textureCoords[2] = imageWidth; textures[numTextures].textureCoords[3] = 0; textures[numTextures].textureCoords[4] = imageWidth; textures[numTextures].textureCoords[5] = imageHeight; textures[numTextures].textureCoords[6] = 0; textures[numTextures].textureCoords[7] = imageHeight; numTextures++; //printf("Added texture. Num textures: %d\n", numTextures); return &textures[numTextures-1]; }
int main() { printf("\n%d\n", nextPowerOf2(5)); printf("\n%d\n", nextPowerOf2(2)); printf("\n%d\n", nextPowerOf2(19)); printf("\n%d\n", nextPowerOf2(33)); printf("\n%d\n", nextPowerOf2(0)); return 0; }
void Canvas::validateSize( int & _width, int & _height ) const { if( mTexResizeMode == TRM_PT_CONST_SIZE || mTexResizeMode == TRM_PT_VIEW_REQUESTED || mTexResizeMode == TRM_PT_VIEW_ALL ) { _width = nextPowerOf2( _width ); _height = nextPowerOf2( _height ); } }
void LLPluginClassMedia::setSizeInternal(void) { if((mSetMediaWidth > 0) && (mSetMediaHeight > 0)) { mRequestedMediaWidth = mSetMediaWidth; mRequestedMediaHeight = mSetMediaHeight; } else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0)) { mRequestedMediaWidth = mNaturalMediaWidth; mRequestedMediaHeight = mNaturalMediaHeight; } else { mRequestedMediaWidth = mDefaultMediaWidth; mRequestedMediaHeight = mDefaultMediaHeight; } // Save these for size/interest calculations mFullMediaWidth = mRequestedMediaWidth; mFullMediaHeight = mRequestedMediaHeight; if(mAllowDownsample) { switch(mPriority) { case PRIORITY_SLEEP: case PRIORITY_LOW: // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit)) { mRequestedMediaWidth /= 2; mRequestedMediaHeight /= 2; } break; default: // Don't adjust texture size break; } } if(mAutoScaleMedia) { mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth); mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight); } if(mRequestedMediaWidth > 2048) mRequestedMediaWidth = 2048; if(mRequestedMediaHeight > 2048) mRequestedMediaHeight = 2048; }
FramebufferTexture::FramebufferTexture(GLuint width, GLuint height, GLenum type) { m_width = width; m_height = height; m_p2width = nextPowerOf2(width); m_p2height = nextPowerOf2(height); glGenTextures(1, &m_texId); glBindTexture(GL_TEXTURE_2D, m_texId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, type, m_p2width, m_p2height, 0, type, GL_UNSIGNED_BYTE, 0); }
void ConstQ::genSparseKernel() { // get frequencies of min and max Note minFreq = noteNum2Freq((float)minNote); maxFreq = noteNum2Freq((float)maxNote); // get Q value and the number of total constant Q bins Q = 1./(pow(2.,(1./bpo)) - 1); constQBins = ceil(bpo * log2(maxFreq/minFreq)); // memory alloc for sparkernel bins sparkernel = new sparKernel[constQBins]; fftLength = nextPowerOf2((unsigned int) ceil(Q * fs/minFreq)); // fft setup fft = kiss_fft_alloc(fftLength, 0, NULL, NULL); fftr = kiss_fftr_alloc(fftLength, 0, NULL, NULL); for (int k=constQBins; k > 0; k--){ double centerFreq = (minFreq * pow(2,(float(k-1)/bpo))); int upperBound = ceil(centerFreq * pow(2, 1./12) * fftLength/fs); int lowerBound = floor(centerFreq * pow(2, -1./12) * fftLength/fs); sparkernel[k-1].s = lowerBound; sparkernel[k-1].e = upperBound; sparkernel[k-1].cpx = new kiss_fft_cpx[upperBound - lowerBound]; } pthread_create(&thread, NULL, ConstQ::sparseKernelThread, this); }
size_t nearestPowerOf2(size_t v) { const size_t n = nextPowerOf2(v); const size_t p = previousPowerOf2(v); if ( n - v < v - p ) return n; else return p; }
void NgramVector::Reserve(size_t capacity) { // Reserve index table and value vector with specified capacity. if (capacity != _words.length()) { _Reindex(nextPowerOf2(capacity + capacity/4)); _words.resize(capacity); _hists.resize(capacity); } }
/** * @brief makePowerOf2 * @param ints */ static void makePowerOf2(vector<double>& ints) { mz_uint n = ints.size(); if ( ! isPowerOf2( n ) ) { mz_uint new_s = nextPowerOf2( n ); while ( ints.size() != new_s ) { ints.push_back( 0.0 ); } } }
void LLPluginClassMedia::setLowPrioritySizeLimit(int size) { int power = nextPowerOf2(size); if(mLowPrioritySizeLimit != power) { mLowPrioritySizeLimit = power; // This may affect the calculated size, so recalculate it here. setSizeInternal(); } }
void NgramVector::Deserialize(FILE *inFile) { _length = ReadUInt64(inFile); ReadVector(inFile, _words); ReadVector(inFile, _hists); _Reindex(nextPowerOf2(_length + _length / 4)); // Build truncated view into words and hists. _wordsView.attach(_words); _histsView.attach(_hists); }
void MonitorNode::initialize() { if( ! mWindowSize ) mWindowSize = getFramesPerBlock(); else if( ! isPowerOf2( mWindowSize ) ) mWindowSize = nextPowerOf2( static_cast<uint32_t>( mWindowSize ) ); for( size_t ch = 0; ch < getNumChannels(); ch++ ) mRingBuffers.emplace_back( mWindowSize * mRingBufferPaddingFactor ); mCopiedBuffer = Buffer( mWindowSize, getNumChannels() ); }
void MonitorSpectralNode::initialize() { MonitorNode::initialize(); if( mFftSize < mWindowSize ) mFftSize = mWindowSize; if( ! isPowerOf2( mFftSize ) ) mFftSize = nextPowerOf2( static_cast<uint32_t>( mFftSize ) ); mFft = unique_ptr<dsp::Fft>( new dsp::Fft( mFftSize ) ); mFftBuffer = audio::Buffer( mFftSize ); mBufferSpectral = audio::BufferSpectral( mFftSize ); mMagSpectrum.resize( mFftSize / 2 ); if( ! mWindowSize ) mWindowSize = mFftSize; else if( ! isPowerOf2( mWindowSize ) ) mWindowSize = nextPowerOf2( static_cast<uint32_t>( mWindowSize ) ); mWindowingTable = makeAlignedArray<float>( mWindowSize ); generateWindow( mWindowType, mWindowingTable.get(), mWindowSize ); }
int TextureFont::LoadFont(char *fontlocation,int pointsize) { if(!Face.LoadFace(fontlocation,pointsize)){return FALSE;} //Load Face from fontfile with reqd pointsize pt=pointsize; TexWidth= pt*24; TexHeight= pt*24; int penX=0,penY=pt*2; InitTexture(); //Initialize Texture Memory and Texture Parameters for(int i=32;i<127;i++) //Run through all valid characters { FT_Bitmap bitmap = Face.LoadGlyphBitmap(i); //Load Bitmap of Character with charcode 'i' int width = bitmap.width;width = nextPowerOf2(width); //Get Width of bitmap glyph int height = bitmap.rows;height = nextPowerOf2(height); //Get Height of bitmap glyph if(penX+Face.getAdvance() >=(TexWidth-1)) //Check boundary conditions {penY=penY+Face.getAscent()+10;penX=0;} //Go to next line if(penY+height>=TexHeight-1) //Check boundary conditions return TRUE; //Max no of characters filled so end GLubyte *glyphdata = PrepareGlyph(bitmap,width,height); glTexSubImage2D(GL_TEXTURE_2D,0,penX ,penY - Face.getHoriBearing(),width,height,GL_LUMINANCE_ALPHA,GL_UNSIGNED_BYTE,glyphdata); delete[] glyphdata; TexGlyphs[i] = new Glyph(penX ,penY - Face.getHoriBearing(),bitmap.width,bitmap.rows,Face.getHoriBearing(),Face.getAdvance()); penX=penX+Face.getAdvance()+4; } //InitVBOExtensions(); //for(int i=32;i<127;i++) //CreateVBO(i); return TRUE; }
void SuperHashTable::init(unsigned initsize) { if (initsize==0) initsize = InitialTableSize; #ifdef HASHSIZE_POWER2 //size should be a power of 2 initsize = nextPowerOf2(initsize); #endif tablesize = initsize; tablecount = 0; table = (void * *) checked_malloc(initsize*sizeof(void *),-602); memset(table,0,initsize*sizeof(void *)); cache = 0; #ifdef TRACE_HASH search_tot = 0; search_num = 0; #endif }
GLTextureGlyph::GLTextureGlyph(int offx, int offy, int width, int height, u8* data, bool mipmap) : mOffsetX(offx) , mOffsetY(offy) , mWidth(width) , mHeight(height) { // Make a texture sized at a power of 2. Require them to be 8x8 // to prevent some funky texture flickering rendering glitches. #undef max #undef min mTexWidth = std::max(8, nextPowerOf2(mWidth)); mTexHeight = std::max(8, nextPowerOf2(mHeight)); // Get a unique texture name for our new texture glGenTextures(1, &mTexName); const int size = mTexWidth * mTexHeight; u8* pixels = new u8[size]; memset(pixels, 0, size); for (int row = 0; row < mHeight; ++row) { memcpy(pixels + mTexWidth * row, data + mWidth * row, mWidth); } delete[] data; data = 0; // This is basically an expansion of pixels into Luminance/Alpha. u8* la = new u8[size * 2]; for (int i = 0; i < size; ++i) { la[i * 2 + 0] = (pixels[i] ? 255 : 0); la[i * 2 + 1] = pixels[i]; } delete[] pixels; pixels = 0; // Generate a 2D texture with our image data glBindTexture(GL_TEXTURE_2D, mTexName); if (mipmap) { gluBuild2DMipmaps( GL_TEXTURE_2D, 2, mTexWidth, mTexHeight, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, la); } else { glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, mTexWidth, mTexHeight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, la); } delete[] la; la = 0; // Setup clamping and our min/mag filters glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); }
int LLPluginClassMedia::getTextureHeight() const { return nextPowerOf2(mTextureHeight); }
int LLPluginClassMedia::getTextureWidth() const { return nextPowerOf2(mTextureWidth); }
void LLPluginClassMedia::idle_impl(void) { if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL)) { // Can't process a size change at this time } else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight)) { // Calculate the correct size for the media texture mRequestedTextureHeight = mRequestedMediaHeight; if(mPadding < 0) { // negative values indicate the plugin wants a power of 2 mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth); } else { mRequestedTextureWidth = mRequestedMediaWidth; if(mPadding > 1) { // Pad up to a multiple of the specified number of bytes per row int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth; int pad = rowbytes % mPadding; if(pad != 0) { rowbytes += mPadding - pad; } if(rowbytes % mRequestedTextureDepth == 0) { mRequestedTextureWidth = rowbytes / mRequestedTextureDepth; } else { LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL; } } } // Size change has been requested but not initiated yet. size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth; // Add an extra line for padding, just in case. newsize += mRequestedTextureWidth * mRequestedTextureDepth; if(newsize != mTextureSharedMemorySize) { if(!mTextureSharedMemoryName.empty()) { // Tell the plugin to remove the old memory segment mPlugin->removeSharedMemory(mTextureSharedMemoryName); mTextureSharedMemoryName.clear(); } mTextureSharedMemorySize = newsize; mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize); if(!mTextureSharedMemoryName.empty()) { void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName); // clear texture memory to avoid random screen visual fuzz from uninitialized texture data memset( addr, 0x00, newsize ); // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin, // so it may not be worthwhile. // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight); } } // This is our local indicator that a change is in progress. mTextureWidth = -1; mTextureHeight = -1; mMediaWidth = -1; mMediaHeight = -1; // This invalidates any existing dirty rect. resetDirty(); // Send a size change message to the plugin { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change"); message.setValue("name", mTextureSharedMemoryName); message.setValueS32("width", mRequestedMediaWidth); message.setValueS32("height", mRequestedMediaHeight); message.setValueS32("texture_width", mRequestedTextureWidth); message.setValueS32("texture_height", mRequestedTextureHeight); message.setValueReal("background_r", mBackgroundColor.mV[VX]); message.setValueReal("background_g", mBackgroundColor.mV[VY]); message.setValueReal("background_b", mBackgroundColor.mV[VZ]); message.setValueReal("background_a", mBackgroundColor.mV[VW]); mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue. LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL; } } }
void ConstQ::genSparseKernel() { // get frequencies of min and max Note minFreq = noteNum2Freq((float)minNote); maxFreq = noteNum2Freq((float)maxNote); // get Q value and the number of total constant Q bins Q = 1./(pow(2.,(1./bpo)) - 1); constQBins = ceil(bpo * log2(maxFreq/minFreq)); anglestep = 2*M_PI*Q; // memory alloc for sparkernel bins sparkernel = new sparKernel[constQBins]; fftLength = nextPowerOf2((unsigned int) ceil(Q * fs/minFreq)); // fftw setup cin = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * fftLength); memset(cin, 0, sizeof(fftwf_complex) * fftLength); cout = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * fftLength); c2c = fftwf_plan_dft_1d(fftLength, cin, cout, FFTW_FORWARD, FFTW_ESTIMATE); fin = (float *) fftwf_malloc(sizeof(float) * fftLength); r2c = fftwf_plan_dft_r2c_1d(fftLength, fin, cout, FFTW_ESTIMATE); centerFreqz = new float[constQBins]; for (int k=constQBins; k > 0; k--) { centerFreqz[k-1] = (float) (minFreq * pow(2,(float(k-1)/bpo))); sparkernel[k-1].s = floor(centerFreqz[k] * pow(2, -1./12) * fftLength/fs); sparkernel[k-1].e = ceil(centerFreqz[k] * pow(2, 1./12) * fftLength/fs); std::cout<<"k: "<< k << "\n"; sparkernel[k-1].cpx = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * (sparkernel[k-1].e - sparkernel[k-1].s)); //new complex_t[sparkernel[k-1].e - sparkernel[k-1].s]; } pthread_create(&thread, NULL, ConstQ::sparseKernelThread, this); // std::complex <float> *tempKernel; // tempKernel = reinterpret_cast<std::complex <float> *> (cin); // std::complex <float> *specKernel; // specKernel = reinterpret_cast<std::complex <float> *> (cout); // std::complex <float> *sparKernel; // for (int k=constQBins; k > 0; k--){ // progress = 1.0/constQBins * (constQBins - k); // float centerFreq = (minFreq * pow(2,(float(k-1)/bpo))); // int length = ceil(Q * fs / centerFreq); // for(int n=0; n<length; n++){ // std::complex <float> cpx(0, (2*M_PI*Q*n/length)); // cpx = exp(cpx); // float hwin = HAMMING(n, length) / length; // tempKernel[n] = hwin * cpx; // } // fftwf_execute(c2c); // int upperBound = ceil(centerFreq * pow(2, 1./12) * fftLength/fs); // int lowerBound = floor(centerFreq * pow(2, -1./12) * fftLength/fs); // sparkernel[k-1].s = lowerBound; // sparkernel[k-1].e = upperBound; // sparkernel[k-1].cpx = (fftwf_complex *) // fftwf_malloc(sizeof(fftwf_complex) * (upperBound - lowerBound)); // sparKernel = // reinterpret_cast<std::complex <float> *> (sparkernel[k-1].cpx); // // cut under the threshold, Conjugate and scaling // for(int i=lowerBound; i<upperBound; i++){ // if (abs(specKernel[i]) > thresh) // sparKernel[i-lowerBound] = conj(specKernel[i] / (float)fftLength); // else // sparKernel[i-lowerBound] = 0; // } // } // fftwf_destroy_plan(c2c); // no more needed // progress = 1.0; }
size_t DeviceManagerOpenSl::getFramesPerBlock( const DeviceRef &device ) { // Nodes require frames per block to to be power of 2, and most android devices don't want power of 2 blocksizes // So we round up, OutputDeviceNodeOpenSl will ask for hardware block size directly. size_t framesPerBlockHardware = getFramesPerBlockHardware( device ); size_t framesPerBlockPow2 = ( isPowerOf2( framesPerBlockHardware ) ? framesPerBlockHardware : nextPowerOf2( framesPerBlockHardware ) ); CI_LOG_I( "framesPerBlockHardware: " << framesPerBlockHardware << ", framesPerBlockPow2: " << framesPerBlockPow2 ); return framesPerBlockPow2; }
// Returns the "name" of a generated texture (in OpenGl names are unsigned integers). // Remember to free texture when no longer needed by calling glDeleteTextures // Returns ZERO_GL if not OK GLuint drawImageTextureFactory(int xOffset, int yOffset, int width, int height) { GLuint textureId=ZERO_GL; printf("drawImageTextureFactory %d %d %d %d\n", xOffset, yOffset, width, height); unsigned char *ptr=drawImageLoader->imagePixels; const int bpp=drawImageLoader->bytesPerPixel; // In openGL ES textures must have size that is a power of 2. height=nextPowerOf2(height); width=nextPowerOf2(width); size_t s = width*height*bpp; unsigned char *tmp=(unsigned char *)malloc(s); // free is to be done later in this method assert(tmp!=NULL); memset(tmp,0,s); for(int x=0;x<width;++x) { for(int y=0;y<height;++y) { const int ii = x + y*(width); const int jj = xOffset + x + y*(drawImageLoader->imageWidth); const int i = ii * bpp; const int j = jj * bpp; tmp[i]=ptr[j+0]; tmp[i+1]=ptr[j+1]; tmp[i+2]=ptr[j+2]; tmp[i+3]=ptr[j+3]; } } glGenTextures( 1, &textureId ); glBindTexture( GL_TEXTURE_2D, textureId ); #ifndef __EMSCRIPTEN__ glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_REPEAT ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT ); gluBuild2DMipmaps( GL_TEXTURE_2D, drawImageLoader->iFormat, width, height, drawImageLoader->gFormat, GL_UNSIGNED_BYTE, tmp); #else // these affect how this texture is drawn later on... glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //glTexImage2D(GL_TEXTURE_2D, 0, d->iFormat, d->imageWidth, d->imageHeight, 0, d->gFormat, GL_UNSIGNED_BYTE, d->imagePixels); glTexImage2D(GL_TEXTURE_2D, 0, drawImageLoader->iFormat, width, height, 0, drawImageLoader->gFormat, GL_UNSIGNED_BYTE, tmp); #endif free(tmp); return textureId; // Remember to free texture when no longer needed by calling glDeleteTextures }
// Compute the filter, similar to Octave's fir2(n, f, m, grid_n, ramp_n, window); // Window and result must be of size n + 1. // grid_n: length of ideal frequency response function // ramp_n: transition width for jumps in filter response // defaults to grid_n/20; a wider ramp gives wider transitions // but has better stopband characteristics. void generateFirFilter(unsigned n, double w, const double* window, double* result) { // make sure grid is big enough for the window // the grid must be at least (n+1)/2 // for all filters where the order is a power of two minus 1, grid_n = n+1; unsigned grid_n = nextPowerOf2(n + 1); unsigned ramp_n = 2; // grid_n / 20; // Apply ramps to discontinuities // this is a low pass filter // maybe we can omit the "w, 0" point? // I did observe a small difference double f[] = {0.0, w-ramp_n/grid_n/2.0, w, w+ramp_n/grid_n/2.0, 1.0}; double m[] = {1.0, 1.0, 0.0, 0.0, 0.0}; // grid is a 1-D array with grid_n+1 points. Values are 1 in filter passband, 0 otherwise double* grid = (double*) malloc((grid_n + 1) * sizeof(double)); // interpolate between grid points interpolate(f, m, 5 /* length of f and m arrays */ , grid_n+1, grid); // the grid we do an ifft on is: // grid appended with grid_n*2 zeros // appended with original grid values from indices grid_n..2, i.e., the values in reverse order // (note, arrays start at 1 in octave!) // the input for the ifft is of size 4*grid_n // input = [grid ; zeros(grid_n*2,1) ;grid(grid_n:-1:2)]; fftwf_complex* cinput = (fftwf_complex*) fftwf_malloc(grid_n*4*sizeof(fftwf_complex)); fftwf_complex* coutput = (fftwf_complex*) fftwf_malloc(grid_n*4*sizeof(fftwf_complex)); if(cinput == NULL || coutput == NULL) { fprintf(stderr, "Cannot allocate buffer to generate FIR filter. Exiting\n"); exit(-1); } // wipe imaginary part for(unsigned i=0; i<grid_n*4; i++) { cinput[i][1] = 0.0; } // copy first part of grid for(unsigned i=0; i<grid_n+1; i++) { cinput[i][0] = float(grid[i]); } // append zeros for(unsigned i=grid_n+1; i<=grid_n*3; i++) { cinput[i][0] = 0.0; } // now append the grid in reverse order for(unsigned i=grid_n-1, index=0; i >=1; i--, index++) { cinput[grid_n*3+1 + index][0] = float(grid[i]); } fftwf_plan plan = fftwf_plan_dft_1d(grid_n*4, cinput, coutput, FFTW_BACKWARD, FFTW_ESTIMATE); fftwf_execute(plan); unsigned index = 0; for(unsigned i=4*grid_n-n; i<4*grid_n; i+=2) { result[index] = coutput[i][0]; index++; } for(unsigned i=1; i<=n; i+=2) { result[index] = coutput[i][0]; index++; } fftwf_destroy_plan(plan); fftwf_free(cinput); fftwf_free(coutput); // multiply with window for(unsigned i=0; i<=n; i++) { result[i] *= window[i]; } // normalize double factor = result[n/2]; for(unsigned i=0; i<=n; i++) { result[i] /= factor; } free(grid); }
/* * Get raw PPM (Portable Pixel Map) image from file. * Image buffer padded so its width and height are powers of 2. * Each "pixel" is 4 bytes wide and holds RGBA components (all alpha * components are set to 255). */ static void getppm(char *fname, Image *image) { FILE *f; static char buf[100]; GLboolean gotSize, gotMax; int r, c; int w,h, lW,lH; GLubyte (*rgba)[4]; if ((f = fopen(fname, "rb")) == NULL) { perror(fname); exit(-1); } if (fgets(buf, sizeof(buf), f) == NULL || strncmp("P6", buf, 2) != 0) { fprintf(stderr, "Bogus magic string for raw PPM file '%s'!\n", fname); exit(-1); } for (gotSize = gotMax = GL_FALSE; !gotMax; ) { if (fgets(buf, sizeof(buf), f) == NULL) { fprintf(stderr, "Error parsing header for PPM file '%s'!\n", fname); exit(-1); } if (buf[0] == '#') continue; if (!gotSize) { if (sscanf(buf, "%d %d", &w, &h) != 2 || w <= 0 || h <= 0) { fprintf(stderr, "Bogus size for for PPM file '%s'!\n", fname); exit(-1); } gotSize = GL_TRUE; } else { int max; if (sscanf(buf, "%d", &max) != 1 || max < 2 || max > 255) { fprintf(stderr, "Bogus max intensity for PPM file '%s'!\n", fname); exit(-1); } gotMax = GL_TRUE; } } lW = nextPowerOf2(w); lH = nextPowerOf2(h); if ((rgba = (GLubyte (*)[4]) calloc(lW*lH,4)) == NULL) { perror("calloc() image"); exit(-1); } for (r = 0; r < h; r++) for (c = 0; c < w; c++) { unsigned char rgb[3]; int index; if (fread(rgb, 1, 3, f) != 3) { if (ferror(f)) perror(fname); else fprintf(stderr, "Unexpected EOF: %s\n", fname); exit(-1); } index = r*lW + c; rgba[index][0] = rgb[0]; rgba[index][1] = rgb[1]; rgba[index][2] = rgb[2]; rgba[index][3] = 255; } fclose(f); image->w = w; image->h = h; image->lW = lW; image->lH = lH; image->smin = 0.0; image->smax = ((GLfloat) w)/lW; image->tmin = ((GLfloat) h)/lH; image->tmax = 0.0; image->rgba = rgba; }