Results 1 to 2 of 2

Thread: OpenGL Image Tiling Interpolation Problem

  1. #1
    Join Date
    Feb 2010
    Posts
    14
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: OpenGL Image Tiling Interpolation Problem

    Hi,

    i have a frame grabber (at 30+ FPS) that give me images with sizes of 2560x2048 with RGB data in 8 Bit and 10 or 12 Bit data. A Single Texture is to large (really low performance) for older PC and a waste of memory. I wrote my own class derived from QGLWidget that shows me that image with zoom and so on. I am really happy that i t works because i never used openGL before. But then i interpolate i get some uggly artifacts at the tile borders.

    I spend two days to find my bug, but i really dont know that is wrong and if you have some hints how i can optimize it i would be really happy.

    The important methods are

    newImageData - called from frame grabber thread and copies image to tiles
    copyToTextureTile - copy image area to tile
    paintGL - does the painting
    drawTexture - draw the image tiles

    Here my classes, cames in next post.

    Qt Code:
    1. #include "GUIPixmapView.h"
    2.  
    3. #define TILESIZE 128
    4. #define TILEBUFFERSIZE TILESIZE * TILESIZE * 4 * 2
    5.  
    6. class GUIGL3DView : public GUIOpenGLView
    7. {
    8. Q_OBJECT
    9.  
    10. public:
    11. GUIGL3DView(GUIGLPixmapView & iPixmapView, const QGLFormat & iFormat, QWidget * iParent = NULL);
    12.  
    13. void newImageData();
    14.  
    15. protected:
    16. void paintGL();
    17.  
    18. private:
    19. struct TextureTile
    20. {
    21. unsigned char data[TILEBUFFERSIZE];
    22. size_t offsetX;
    23. size_t offsetY;
    24. size_t width;
    25. size_t height;
    26. size_t tileX;
    27. size_t tileY;
    28. GLuint textureID;
    29.  
    30. TextureTile()
    31. : offsetX(0)
    32. , offsetY(0)
    33. , width(0)
    34. , height(0)
    35. , tileX(-1)
    36. , tileY(-1)
    37. , textureID(0)
    38. {
    39. glGenTextures(1, &textureID);
    40. }
    41.  
    42. ~TextureTile()
    43. {
    44. // delete texture
    45. if(textureID != 0)
    46. glDeleteTextures(1, &textureID);
    47. }
    48. };
    49.  
    50. struct TextureData
    51. {
    52. QList<TextureTile*> tiles;
    53. size_t usedTiles;
    54. size_t bytesPerSample;
    55. size_t samplesPerPixel;
    56. size_t bitsPerSample;
    57.  
    58. TextureData()
    59. : usedTiles(0)
    60. , bytesPerSample(0)
    61. , samplesPerPixel(0)
    62. , bitsPerSample(0)
    63. {}
    64.  
    65. ~TextureData()
    66. {
    67. for(int i = 0; i < tiles.count(); i++)
    68. delete tiles.at(i);
    69. }
    70. };
    71.  
    72. TextureData mImageTexture;
    73. GLint mTileSize;
    74.  
    75. void copyToTextureTile(TextureTile & oTile, int x, int y, void * iSrcBuffer, size_t iWidth, size_t iHeight, size_t iBytesPerPixel);
    76.  
    77. void drawLine();
    78.  
    79. void drawTexture(TextureData & iTextureData);
    80. };
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. GUIGL3DView::GUIGL3DView(GUIGLPixmapView & iPixmapView, const QGLFormat & iFormat, QWidget * iParent)
    2. : GUIOpenGLView(iPixmapView, iFormat, iParent)
    3. , mImageTexture()
    4. , mTileSize(0)
    5. {
    6. }
    7.  
    8. void GUIGL3DView::newImageData()
    9. {
    10. if(mTileSize == 0)
    11. {
    12. mTileSize;
    13. glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &mTileSize);
    14. mTileSize = qMax(TILESIZE, mTileSize);
    15.  
    16. if(mTileSize < TILESIZE)
    17. guiApp.showMessage(eInformation, tr("Warning your PC does not support textures with size of 2048 or more pixels. Textures size is set to %1 pixel. We can not ensure correct image representation.").arg(mTileSize));
    18. }
    19.  
    20. // image values
    21. const unsigned int imageWidth = mPixmapView.pixmapWidth();
    22. const unsigned int imageHeight = mPixmapView.pixmapHeight();
    23.  
    24. // get needed tile count
    25. const int xTiles = (imageWidth+(mTileSize-1))/mTileSize;
    26. const int yTiles = (imageHeight+(mTileSize-1))/mTileSize;
    27. const int tilesNeeded = yTiles * xTiles;
    28.  
    29. // create missing tiles
    30. const int additionalTilesNeeded = tilesNeeded - mImageTexture.tiles.count();
    31. for(int i = 0; i < additionalTilesNeeded; i++)
    32. {
    33. TextureTile * newImageTile = new TextureTile();
    34. mImageTexture.tiles.append(newImageTile);
    35. }
    36.  
    37. //remember number of currently used tiles
    38. mImageTexture.usedTiles = tilesNeeded;
    39.  
    40. //create Texture
    41. if(mPixmapView.isExposureWarningEnabled() || !mPixmapView.pixmapIsNull())
    42. {
    43. // we only need to draw exposure or image, because exposure pixmap contains image data
    44. QImage image;
    45. if(mPixmapView.isExposureWarningEnabled())
    46. image = mPixmapView.mExposurePixmap.toImage();
    47. else
    48. image = mPixmapView.pixmap().toImage();
    49.  
    50. const QImage::Format format = image.format();
    51. if(format == QImage::Format_Invalid)
    52. return;
    53.  
    54. mImageTexture.bytesPerSample = 1;
    55. mImageTexture.samplesPerPixel = 4;
    56. mImageTexture.bitsPerSample = 8;
    57.  
    58. // copy texture to tiles
    59. for(int x = 0; x < xTiles; x++)
    60. for(int y = 0; y < yTiles; y++)
    61. copyToTextureTile(*mImageTexture.tiles.at(y * xTiles + x), x, y, image.scanLine(0), image.width(), image.height(), mImageTexture.samplesPerPixel * mImageTexture.bytesPerSample);
    62. }
    63. else
    64. {
    65. ImageData data = mPixmapView.imageData();
    66. if(data.imageBuffer)
    67. {
    68. mImageTexture.bytesPerSample = data.bytesPerSample;
    69. mImageTexture.samplesPerPixel = data.samplesPerPixel;
    70. mImageTexture.bitsPerSample = data.bitsPerSample;
    71.  
    72. // copy texture to tiles
    73. for(int x = 0; x < xTiles; x++)
    74. for(int y = 0; y < yTiles; y++)
    75. copyToTextureTile(*mImageTexture.tiles.at(y * xTiles + x), x, y, mPixmapView.imageData().imageBuffer, imageWidth, imageHeight, mImageTexture.samplesPerPixel * mImageTexture.bytesPerSample);
    76. }
    77. }
    78. }
    79.  
    80. void GUIGL3DView::copyToTextureTile(TextureTile & oTile, int iX, int iY, void * iSrcBuffer, size_t iSrcWidth, size_t iSrcHeight, size_t iBytesPerPixel)
    81. {
    82. oTile.tileX = iX;
    83. oTile.tileY = iY;
    84. oTile.offsetX = iX * mTileSize;
    85. oTile.offsetY = iY * mTileSize;
    86.  
    87. const size_t endX = oTile.offsetX + mTileSize;
    88. const size_t endY = oTile.offsetY + mTileSize;
    89.  
    90. if(endX > iSrcWidth)
    91. oTile.width = iSrcWidth - oTile.offsetX;
    92. else
    93. oTile.width = mTileSize;
    94.  
    95. if(endY > iSrcHeight)
    96. oTile.height = iSrcHeight - oTile.offsetY;
    97. else
    98. oTile.height = mTileSize;
    99.  
    100. const int srcBytesPerLine = iSrcWidth * iBytesPerPixel;
    101. const int dstBytesPerLine = mTileSize * iBytesPerPixel;
    102.  
    103. const size_t srcFromX = oTile.offsetX;
    104. const size_t srcFromY = oTile.offsetY;
    105. const size_t srcWidth = oTile.width;
    106. const size_t srcHeight = oTile.height;
    107.  
    108. { // copy tile data
    109. unsigned char * source = (unsigned char*)iSrcBuffer + srcFromY * srcBytesPerLine + srcFromX * iBytesPerPixel;
    110. unsigned char * destination = (unsigned char*)oTile.data;
    111. const size_t bytesToCopy = srcWidth * iBytesPerPixel;
    112. for(size_t y = 0; y < srcHeight; y++)
    113. {
    114. memcpy(destination, source, bytesToCopy);
    115. source += srcBytesPerLine;
    116. destination += dstBytesPerLine;
    117. }
    118. }
    119. }
    120.  
    121. void GUIGL3DView::paintGL()
    122. {
    123. if(mPixmapView.isPaintBlocked())
    124. return;
    125.  
    126. glViewport(0,0, width(), height());
    127.  
    128. qglClearColor(mBackgroundColor);
    129. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    130.  
    131. drawTexture(mImageTexture);
    132.  
    133. checkErrors();
    134. }
    135.  
    136. void GUIGL3DView::drawTexture(TextureData & iTextureData)
    137. {
    138. if(iTextureData.usedTiles <= 0)
    139. return;
    140.  
    141. // set projection - disable z-axis
    142. glMatrixMode(GL_PROJECTION);
    143.  
    144. //clear projection matrix
    145. glLoadIdentity();
    146.  
    147. //Creating an orthoscopic view matrix
    148. glOrtho(0, width(), height(), 0, -1, 1);
    149.  
    150. //Define how alpha blending will work and enable alpha blending.
    151. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    152. glEnable(GL_BLEND);
    153.  
    154. //Disabling the depth test (z will not be used to tell what object
    155. //will be shown above another, only the order in which I draw them.)
    156. glDisable(GL_DEPTH_TEST);
    157.  
    158. // create image format data
    159. GLenum channels = GL_RGB;
    160. if(iTextureData.samplesPerPixel == 1)
    161. channels = GL_LUMINANCE;
    162. if(iTextureData.samplesPerPixel == 4)
    163. channels = GL_RGBA;
    164.  
    165. GLenum dataType = GL_UNSIGNED_BYTE;
    166. if(iTextureData.bytesPerSample == 2)
    167. dataType = GL_UNSIGNED_SHORT;
    168.  
    169. // get image data
    170. const float imageWidth = mPixmapView.pixmapWidth();
    171. const float imageHeight = mPixmapView.pixmapHeight();
    172.  
    173. // center image
    174. const float viewLeft = (width() - imageWidth * mZoom)/2;
    175. const float viewTop = (height() - imageHeight * mZoom)/2;
    176.  
    177. // move image to respect sliders
    178. const float offsetX = mPixmapView.mHScroll->isVisible() ? mPixmapView.mHScroll->value() : 0;
    179. const float offsetY = mPixmapView.mVScroll->isVisible() ? mPixmapView.mVScroll->value() : 0;
    180. glTranslatef(-offsetX * mZoom, -offsetY * mZoom, 0);
    181.  
    182. // image start in upper left corner
    183. if(viewLeft < 0)
    184. glTranslatef(-viewLeft, 0, 0);
    185.  
    186. if(viewTop < 0)
    187. glTranslatef(0, -viewTop, 0);
    188.  
    189. // enable texturing
    190. glEnable(GL_TEXTURE_2D);
    191.  
    192. // set scaling factor
    193. if(mImageTexture.bytesPerSample == 1)
    194. setScale(1.0);
    195. else
    196. setScale(1 << (16 - mImageTexture.bitsPerSample));
    197.  
    198. // draw tiles
    199. const float tileSize = mTileSize * mZoom;
    200. for(size_t i = 0; i < iTextureData.usedTiles; i++)
    201. {
    202. TextureTile * tile = iTextureData.tiles.at(i);
    203.  
    204. //specify texture to use
    205. glBindTexture(GL_TEXTURE_2D, tile->textureID);
    206.  
    207. // set texturing parameters
    208. if(mPixmapView.isInterpolationEnabled() || mZoom <= 1.0)
    209. {
    210. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    211. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    212. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    213. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    214. }
    215. else
    216. {
    217. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    218. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    219. }
    220.  
    221. // send texture to graphic card
    222. glTexImage2D(GL_TEXTURE_2D, 0, channels, mTileSize, mTileSize, 0, channels, dataType, tile->data);
    223.  
    224. // get tile coordinates
    225. const float tileTop = viewTop + tile->tileY * tileSize;
    226. const float tileLeft = viewLeft + tile->tileX * tileSize;
    227.  
    228. float tileBottom = viewTop + (tile->tileY + 1) * tileSize;
    229. if(tile->height != mTileSize)
    230. tileBottom = tileTop + tile->height * mZoom;
    231.  
    232. float tileRight = viewLeft + (tile->tileX + 1) * tileSize;
    233. if(tile->width != mTileSize)
    234. tileRight = tileLeft + tile->width * mZoom;
    235.  
    236. const float sourceBottom = (float)(tile->height) / (float) mTileSize;
    237. const float sourceRight = (float)(tile->width) / (float) mTileSize;
    238.  
    239. glBegin(GL_QUADS);
    240. glTexCoord2f(sourceRight, 0);
    241. glVertex3f(tileRight , tileTop, 0); //ro
    242.  
    243. glTexCoord2f(0, 0);
    244. glVertex3f(tileLeft, tileTop, 0); //lo
    245.  
    246. glTexCoord2f(0, sourceBottom);
    247. glVertex3f(tileLeft, tileBottom, 0); //lu
    248.  
    249. glTexCoord2f(sourceRight, sourceBottom);
    250. glVertex3f(tileRight, tileBottom, 0); //ru
    251. glEnd();
    252. }
    253. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Feb 2010
    Posts
    14
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: OpenGL Image Tiling Interpolation Problem

    Found the Problem!!! Have to give the texture a Border line so openGl can interpolate to and give him correct texture coordinates.

Similar Threads

  1. Axis problem with tiling QWTplots
    By dtakeshita in forum Qwt
    Replies: 7
    Last Post: 6th December 2010, 11:00
  2. Replies: 0
    Last Post: 7th March 2010, 13:13
  3. resizing an image without interpolation
    By mattei in forum Qt Programming
    Replies: 3
    Last Post: 9th December 2009, 11:10
  4. Tiling with OpenGL and textures
    By soxs060389 in forum Qt Programming
    Replies: 1
    Last Post: 25th September 2009, 21:06
  5. QGraphicsView/Item Tiling Problem
    By tomf in forum Qt Programming
    Replies: 4
    Last Post: 29th August 2008, 08:58

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.