2010-03-28 17 views
1

Je veux mettre à l'échelle une image en utilisant OpenGL, quelqu'un peut-il me fournir un tel code sur la façon de faire cela? PS, j'utilise JGL comme une bibliothèque openGL pour Java.Comment mettre à l'échelle une image en utilisant OpenGL (JGL)?

+0

Étendre sur "redimensionner une image". – genpfault

+0

Pourriez-vous s'il vous plaît expliquer plus? –

+1

Je (et peut-être d'autres) n'ai aucune idée de ce que vous voulez dire quand vous dites que vous voulez "mettre à l'échelle une image".Je suppose que vous pourriez vouloir rendre un quad texturé avec une transformation d'échelle à un FBO, puis relire le framebuffer, mais je n'en ai aucune idée. – genpfault

Répondre

1

Je serai bref sur ce point, que vous pouvez trouver des tutoriels pour à peu près toutes les parties de la solution.

Vous devez charger votre image à partir du disque, et créer une texture.

Vous devez créer un objet framebuffer (OIR) avec les dimensions cibles souhaitées (dans votre cas, double largeur, double hauteur). Rendre le FBO actif pour le rendu.

Rendu un quad fullscreen avec votre texture appliquée.

Lire le résultat en utilisant glReadPixels().

Et que c'est ... le matériel texturemapping prendra soin pour vous redimensionnant. Mais il sera probablement plus lent que s'il est fait sur le CPU, en particulier pour "scaling 2x".

EDIT: comme demandé par OP, il est nécessaire d'inclure le code source.

Alors ... pour charger une image en Java, vous choisiriez ceci:

BufferedImage img; 
try { 
    img = ImageIO.read(new File("myLargeImage.jpg")); 
} catch (IOException e) { /* ... */ } 
int w = img.getWidth(), h = img.getHeight(); 

Pour JGL, on peut vouloir convertir une image en un tableau:

byte [][][] imageData = new byte[img.getWidth()][img.getHeight()][3]; // alloc buffer for RGB data 
for(int y = 0; y < h; ++ y) { 
    for(int x = 0; x < w; ++ x) { 
     int RGBA = img.getRGB(x, y); 
     imageData[x][y][0] = RGBA & 0xff; 
     imageData[x][y][1] = (RGBA >> 8) & 0xff; 
     imageData[x][y][2] = (RGBA >> 16) & 0xff; 
    } 
} 

Remarque qu'il pourrait aussi y avoir un canal alpha (pour la transparence) et que cela sera probablement assez lent. On pourrait également utiliser:

int[] rgbaData = img.GetRGB(0, 0, w, h, new int[w * h], 0, w); 

Mais cela ne retourne pas les données dans le bon format attendu par JGL. Mauvais chance. Ensuite, vous devez remplir une texture:

int[] texId = {0}; 
gl.glGenTextures(1, texId); // generate texture id for your texture (can skip this line) 
gl.glEnable(GL.GL_TEXTURE_2D); 
gl.glBindTexture(GL.GL_TEXTURE_2D, texId[0]); // bind the texture 
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); // set alignment of data in memory (a good thing to do before glTexImage) 
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP); 
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP); // set clamp (GL_CLAMP_TO_EDGE would be better) 
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); 
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); // set linear filtering (so you can scale your image) 
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB, w, h, 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, imageData); // upload image data to the texture 

Une fois que vous avez une texture, vous pouvez dessiner des choses. Faisons l'image resample vos:

int newW = ..., newH = ...; // fill-in your values 
gl.glViewport(0, 0, newW, newH); // set viewport 

gl.glMatrixMode(GL.GL_MODELVIEW); 
gl.glLoadIdentity(); 
gl.glMatrixMode(GL.GL_PROJECTION); 
gl.glLoadIdentity(); 
gl.glColor3f(1.0f, 1.0f, 1.0f); // set "white" color 
gl.glDisable(GL.GL_CULL_FACE); // disable backface culling 
gl.glDisable(GL.GL_LIGHTING); // disable lighting 
gl.glDisable(GL.GL_DEPTH_TEST); // disable depth test 
// setup OpenGL so that it renders texture colors without modification (some of that is not required by default) 

gl.glBegin(GL_QUADS); 
gl.glTexCoord2f(0.0f, 1.0f); 
gl.glVertex2f(-1.0f, -1.0f); 
gl.glTexCoord2f(1.0f, 1.0f); 
gl.glVertex2f(+1.0f, -1.0f); 
gl.glTexCoord2f(1.0f, 0.0f); 
gl.glVertex2f(+1.0f, +1.0f); 
gl.glTexCoord2f(0.0f, 0.0f); 
gl.glVertex2f(-1.0f, +1.0f); 
gl.glEnd(); 
// draw a fullscreen quad with your texture on it (scaling is performed here) 

Maintenant que l'image réduite est rendu, tout ce qui doit être fait, est de le télécharger. Ensuite, les données peuvent être converties en image tamponnée de la même manière que l'image d'entrée img a été convertie en imageData.

Notez que je gl variable qui est une instance de la classe GL. Mettez le code dans un exemple JGL et cela devrait fonctionner. Un mot de prudence, JGL ne semble pas supporter les objets framebuffer, de sorte que vous êtes limité par la taille de l'image de sortie par votre taille de fenêtre OpenGL (tenter de créer des images plus grandes se traduira par des bordures noires). Il peut être résolu en utilisant le rendu multi-passes (restituez votre mosaïque d'images par mosaïque et assemblez l'image complète en mémoire).