Square image pixels

Im interested if anyone knows how to make an ofImage when drawn have square pixel in place of the feathered edges I currently see. When developing games in BGE there was a tool for disabling mipmaps that helped with this, does OF ofImage have anything for this?mips

1 Like

Welcome here Lumpology,

It seems that img.getTexture().setTextureMinMagFilter(GL_NEAREST, GL_NEAREST) works.

Example:

// ofApp.h
#pragma once
#include "ofMain.h"
class ofApp : public ofBaseApp{
public:
    void setup();
    void draw();
    ofImage img;
};

// ofApp.cpp
#include "ofApp.h"
void ofApp::setup()
{
    img.load( "img.jpg" ) ;
    img.getTexture().setTextureMinMagFilter( GL_NEAREST, GL_NEAREST ) ;
    ofSetRectMode( OF_RECTMODE_CENTER ) ;
}
void ofApp::draw()
{
    float scale = 40.f * ofNoise( ofGetElapsedTimef() ) ;
    img.draw(
        ofGetWidth() * 0.5f, ofGetHeight() * 0.5f,
        img.getWidth() * scale, img.getHeight() * scale
    ) ;
}
1 Like

Sadly it did not work for my sprite, any other ideas or thoughts about what im doing wrong? the only changes I made to my ofApp::setup are a change to the window size and framerate (in cast anyone asks) note my textures are 32x32

I guess we’re talking about scaling your images that produce the blurry effect? Cos if we’re talking simply drawing the ofImages in their 100% scale, I don’t believe they can ever be displayed that blurry, unless you offset their size or somehow force them to uneven floating point places.

You might also want to check if you’re using your ofImage to draw or ofTexture which is referenced thru ofImage::getTexture()… I would say texture is more on the OpenGL side, making it less pixel-perfect, and would rather use ofImage::draw(…) than ofTexture::draw(…)

Also, I would steer clear of using floats when working with pixel-perfect or scaled pixel-square images. Floats are the devil when it comes to purity of pixels, so you might as well want to cast to integers…

Never tried scaling images with Nearest Neighbor interpolation (raw pixel-squared) in OF, but what @lilive offers seems logical - to somehow tell openGL to use Nearest Neighbor interpolation.
Maybe there’s more to it than just img.getTexture().setTextureMinMagFilter(GL_NEAREST, GL_NEAREST) ?

1 Like

The following also works for me:

ofTexture tex;

//--------------------------------------------------------------
void ofApp::setup(){
    ofPixels pix;
    ofLoadImage(pix, "test.png");
    
    tex.loadData(pix);
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){
    ofBackground(255);

    if( ofGetKeyPressed(' ') ){
        tex.setTextureMinMagFilter(GL_NEAREST, GL_NEAREST);
    }else{
        tex.setTextureMinMagFilter(GL_LINEAR, GL_LINEAR);
    }
    tex.draw(200, 200, tex.getWidth()*6, tex.getHeight()*6);
}

When spacebar is pressed:

When it is not pressed ( default behavior ):

I think the fact you are pushing ofImages back into a vector could be causing them to get reallocated and that might be causing the min/mag filter to get reset. Try setting the min mag filter right before you draw the image. That might fix it.

4 Likes

That does seem to work, it concerns me a little drawing it every frame so I am going to do some experimenting. However is does seem to work now, thankyou theo

Alright this post is now concluded thankyou everyone for your input, it seems somethings where lost when implementing a vector, so to fix it I added a for loop at startup that incriments each part of the vector and applies the setting:

void vix_load_sprite(vix_sprite &sprite, string name, int end_sufix) {
	ofImage imgloader; string namer;
	for (int i = 0; i < end_sufix+1; i++) {
		namer = "stuff/" + name + "_" + to_string(i) + ".png";
		imgloader.load(namer);
		sprite.img.push_back(imgloader);
	}
	for (int i = 0; i < sprite.img.size(); i++) {
		sprite.img[i].getTexture().setTextureMinMagFilter(GL_NEAREST, GL_NEAREST);
	}
}
1 Like

Suggestion (not tested):

void vix_load_sprite(vix_sprite &sprite, string name, int end_sufix) {
	sprite.img.resize( end_sufix + 1 );
	int i = 0;
	for ( auto & img : sprite.img ) {
		namer = "stuff/" + name + "_" + to_string( i++ ) + ".png";
		img.load(namer);
		img.getTexture().setTextureMinMagFilter(GL_NEAREST, GL_NEAREST);
	}
}