TexturePtr TextSurface::create_opengl_texture(Cairo::RefPtr<Cairo::ImageSurface> surface) { assert(surface); TexturePtr texture = Texture::create_handle(GL_TEXTURE_2D); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ROW_LENGTH, surface->get_width()); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture->get_id()); assert_gl("Texture failure"); // flip RGBA to BGRA for(int y = 0; y < surface->get_height(); ++y) { uint8_t* pixels = surface->get_data() + surface->get_stride() * y; for(int x = 0; x < surface->get_width()*4; x += 4) { uint8_t r = pixels[x+0]; uint8_t g = pixels[x+1]; uint8_t b = pixels[x+2]; uint8_t a = pixels[x+3]; // removing pre-multiplayed alpha if (a != 0) { pixels[x+0] = static_cast<uint8_t>(b * 255 / a); pixels[x+1] = static_cast<uint8_t>(g * 255 / a); pixels[x+2] = static_cast<uint8_t>(r * 255 / a); } // debug foobar //if (pixels[x+3] == 0) // pixels[x+3] = 32; } } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->get_width(), surface->get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->get_data()); assert_gl("Texture failure"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); return texture; }
void glDrawCairoSurface(const Cairo::RefPtr<Cairo::ImageSurface> surface, const Vector2d &min, const Vector2d &max, const double z) { if (surface==0) return; int w = surface->get_width(); int h = surface->get_height(); unsigned char * data = surface->get_data(); GLuint texture; glGenTextures( 1, &texture ); glBindTexture( GL_TEXTURE_2D, texture ); // http://www.nullterminator.net/gltexture.html // select modulate to mix texture with color for shading glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); // when texture area is small, bilinear filter the closest mipmap glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); // when texture area is large, bilinear filter the original glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); // build our texture mipmaps gluBuild2DMipmaps( GL_TEXTURE_2D, GL_ALPHA, w, h, GL_ALPHA, GL_UNSIGNED_BYTE, data ); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2d(0.0,0.0); glVertex3d(min.x(),min.y(),z); glTexCoord2d(1.0,0.0); glVertex3d(max.x(),min.y(),z); glTexCoord2d(1.0,1.0); glVertex3d(max.x(),max.y(),z); glTexCoord2d(0.0,1.0); glVertex3d(min.x(),max.y(),z); glEnd(); glDisable(GL_TEXTURE_2D); glDeleteTextures( 1, &texture ); }
RefPtr<Gdk::Pixbuf> GetAsPixbuf(Cairo::RefPtr<Cairo::ImageSurface> sur) { ASSERT( sur->get_format() == Cairo::FORMAT_ARGB32 ); return Gdk::Pixbuf::create_from_data((const guint8*)sur->get_data(), Gdk::COLORSPACE_RGB, true, 8, sur->get_width(), sur->get_height(), sur->get_stride()); }
void ImageWidget::downsampleImageBuffer(unsigned newWidth, unsigned newHeight) { _imageSurface->flush(); const unsigned oldWidth = _imageSurface->get_width(), oldHeight = _imageSurface->get_height(); Cairo::RefPtr<Cairo::ImageSurface> newImageSurface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, newWidth, newHeight); unsigned char* newData = newImageSurface->get_data(); size_t rowStrideOfNew = newImageSurface->get_stride(); unsigned char *oldData = _imageSurface->get_data(); size_t rowStrideOfOld = _imageSurface->get_stride(); for(unsigned int y=0;y<newHeight;++y) { guint8* rowpointerToNew = newData + rowStrideOfNew * y; for(unsigned int x=0;x<newWidth;++x) { unsigned int r=0, g=0, b=0, a=0; const unsigned xOldStart = x * oldWidth / newWidth, xOldEnd = (x+1) * oldWidth / newWidth, yOldStart = y * oldHeight / newHeight, yOldEnd = (y+1) * oldHeight / newHeight; for(unsigned int yOld=yOldStart;yOld<yOldEnd;++yOld) { unsigned char *rowpointerToOld = oldData + rowStrideOfOld * yOld + xOldStart*4; for(unsigned int xOld=xOldStart;xOld<xOldEnd;++xOld) { r += (*rowpointerToOld); ++rowpointerToOld; g += (*rowpointerToOld); ++rowpointerToOld; b += (*rowpointerToOld); ++rowpointerToOld; a += (*rowpointerToOld); ++rowpointerToOld; } } const unsigned count = (xOldEnd - xOldStart) * (yOldEnd - yOldStart); (*rowpointerToNew) = (unsigned char) (r/count); ++rowpointerToNew; (*rowpointerToNew) = (unsigned char) (g/count); ++rowpointerToNew; (*rowpointerToNew) = (unsigned char) (b/count); ++rowpointerToNew; (*rowpointerToNew) = (unsigned char) (a/count); ++rowpointerToNew; } } _imageSurface = newImageSurface; _imageSurface->mark_dirty(); }
Image::Image(const Cairo::RefPtr<Cairo::ImageSurface>& image) : m_width(image->get_width()), m_height(image->get_height()) { unsigned char* data = image->get_data(); size_t length = image->get_width() * image->get_height(); for(size_t i = 0; i < length; ++i) { m_blue.push_back(static_cast<double>(data[i * 4])); m_green.push_back(static_cast<double>(data[i * 4 + 1])); m_red.push_back(static_cast<double>(data[i * 4 + 2])); } }
int getCairoSurfaceDatapoint(const Cairo::RefPtr<Cairo::ImageSurface> surface, const Vector2d &min, const Vector2d &max, const Vector2d &p) { if (surface==0) return 0; const int w = surface->get_stride(); const int h = surface->get_height(); const unsigned char * data = surface->get_data(); const Vector2d diag = max - min; const Vector2d relp = p - min; const int ipx = (int)(relp.x() / diag.x() * (double)w); const int ipy = (int)(relp.y() / diag.y() * (double)h); int value = data[ipy*w + ipx]; return value; }
Cairo::RefPtr<Cairo::ImageSurface> Image::to_cairo_image_surface() const { Cairo::RefPtr<Cairo::ImageSurface> surface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, m_width, m_height); unsigned char* rgb = surface->get_data(); for(size_t i = 0; i < m_width * m_height; ++i) { rgb[i * 4] = (m_blue[i]); rgb[i * 4 + 1] = (m_green[i]); rgb[i * 4 + 2] = (m_red[i]); rgb[i * 4 + 3] = 255; } return surface; }