Пример #1
0
    def get_image_data(self, z=0, fmt='RGBA', gl_format=gl.GL_RGBA):
        """Get the image data of this texture.
        Changes to the returned instance will not be reflected in this
        texture.
        :Parameters:
            `z` : int
                For 3D textures, the image slice to retrieve.
        :rtype: :py:class:`~pyglet.image.ImageData`
        """
        gl.glBindTexture(self.target, self.id)

        # # Always extract complete RGBA data.  Could check internalformat
        # # to only extract used channels. XXX
        # fmt = 'RGBA'
        # gl_format = gl.GL_RGBA

        gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
        buffer = (gl.GLubyte *
                  (self.width * self.height * self.images * len(fmt)))()
        gl.glGetTexImage(self.target, self.level, gl_format,
                         gl.GL_UNSIGNED_BYTE, buffer)

        data = pyglet.image.ImageData(self.width, self.height, fmt, buffer)
        if self.images > 1:
            data = data.get_region(0, z * self.height, self.width, self.height)
        return data
Пример #2
0
    def _drawLUTtoScreen(self):
        """(private) Used to set the LUT in Bits++ mode.

        Should not be needed by user if attached to a ``psychopy.visual.Window()``
        since this will automatically draw the LUT as part of the screen refresh.
        """
        #push the projection matrix and set to orthorgaphic
        GL.glMatrixMode(GL.GL_PROJECTION)
        GL.glPushMatrix()
        GL.glLoadIdentity()
        GL.glOrtho( 0, self.win.size[0],self.win.size[1], 0, 0, 1 )    #this also sets the 0,0 to be top-left
        #but return to modelview for rendering
        GL.glMatrixMode(GL.GL_MODELVIEW)
        GL.glLoadIdentity()

        #draw the pixels
        GL.glActiveTextureARB(GL.GL_TEXTURE0_ARB)
        GL.glEnable(GL.GL_TEXTURE_2D)
        GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
        GL.glActiveTextureARB(GL.GL_TEXTURE1_ARB)
        GL.glEnable(GL.GL_TEXTURE_2D)
        GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
        GL.glRasterPos2i(0,1)
        GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1)
        GL.glDrawPixels(len(self._HEADandLUT),1,
            GL.GL_RGB,GL.GL_UNSIGNED_BYTE,
            self._HEADandLUTstr)
        #GL.glDrawPixels(524,1, GL.GL_RGB,GL.GL_UNSIGNED_BYTE, self._HEADandLUTstr)
        #return to 3D mode (go and pop the projection matrix)
        GL.glMatrixMode( GL.GL_PROJECTION )
        GL.glPopMatrix()
        GL.glMatrixMode( GL.GL_MODELVIEW )
Пример #3
0
    def __init__(self, size: Tuple[int, int], component: int, data):
        self.width, self.height = size
        sized_format = (gl.GL_R8, gl.GL_RG8, gl.GL_RGB8,
                        gl.GL_RGBA8)[component - 1]
        self.format = (gl.GL_R, gl.GL_RG, gl.GL_RGB, gl.GL_RGBA)[component - 1]
        gl.glActiveTexture(gl.GL_TEXTURE0 +
                           0)  # If we need other texture unit...
        self.texture_id = texture_id = gl.GLuint()
        gl.glGenTextures(1, byref(self.texture_id))

        if self.texture_id.value == 0:
            raise ShaderException("Cannot create Texture.")

        gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture_id)
        gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
        gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)
        try:
            gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, sized_format, self.width,
                            self.height, 0, self.format, gl.GL_UNSIGNED_BYTE,
                            data)
        except gl.GLException:
            raise gl.GLException(
                f"Unable to create texture. {gl.GL_MAX_TEXTURE_SIZE} {size}")

        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)
        weakref.finalize(self, Texture.release, texture_id)
Пример #4
0
    def _drawLUTtoScreen(self):
        """(private) Used to set the LUT in 'bits++' mode.

        Should not be needed by user if attached to a
        ``psychopy.visual.Window()`` since this will automatically
        draw the LUT as part of the screen refresh.
        """
        # push the projection matrix and set to orthorgaphic
        GL.glMatrixMode(GL.GL_PROJECTION)
        GL.glPushMatrix()
        GL.glLoadIdentity()
        # this also sets the 0,0 to be top-left
        GL.glOrtho(0, self.win.size[0], self.win.size[1], 0, 0, 1)
        # but return to modelview for rendering
        GL.glMatrixMode(GL.GL_MODELVIEW)
        GL.glLoadIdentity()

        # draw the pixels
        GL.glActiveTextureARB(GL.GL_TEXTURE0_ARB)
        GL.glEnable(GL.GL_TEXTURE_2D)
        GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
        GL.glActiveTextureARB(GL.GL_TEXTURE1_ARB)
        GL.glEnable(GL.GL_TEXTURE_2D)
        GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
        GL.glRasterPos2i(0, 1)
        GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1)
        GL.glDrawPixels(len(self._HEADandLUT), 1, GL.GL_RGB,
                        GL.GL_UNSIGNED_BYTE, self._HEADandLUTstr)
        # GL.glDrawPixels(524,1, GL.GL_RGB,GL.GL_UNSIGNED_BYTE,
        #    self._HEADandLUTstr)
        # return to 3D mode (go and pop the projection matrix)
        GL.glMatrixMode(GL.GL_PROJECTION)
        GL.glPopMatrix()
        GL.glMatrixMode(GL.GL_MODELVIEW)
Пример #5
0
 def set_data(self, arr):
     arr = np.asarray(arr)
     self.src_format, self.dst_format = fmts_from_shape(arr.shape,
                                                        self._texture_dim)
     # Float is default type
     if arr.dtype == np.uint8:
         arr = np.ascontiguousarray(arr)
         self.src_type = gl.GL_UNSIGNED_BYTE
     elif arr.dtype == np.float32:
         arr = np.ascontiguousarray(arr)
         self.src_type = gl.GL_FLOAT
     else:
         arr = np.astype(np.float32)
         self.src_type = gl.GL_FLOAT
     self._arr = arr
     if self._id:
         gl.glDeleteTextures(1, gl.byref(self._id))
     id = gl.GLuint()
     gl.glGenTextures(1, gl.byref(id))
     self._id = id
     gl.glPixelStorei (gl.GL_UNPACK_ALIGNMENT, 1)
     gl.glPixelStorei (gl.GL_PACK_ALIGNMENT, 1)
     gl.glBindTexture (self.target, self._id)
     gl.glTexParameterf (self.target,
                         gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
     gl.glTexParameterf (self.target,
                         gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
     gl.glTexParameterf (self.target, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP)
     gl.glTexParameterf (self.target, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP)
     self._setup_tex()
     self.update()
Пример #6
0
    def _texture_2d(self, data):
        """Create a 2D texture"""
        # Make sure we unpack the pixel data with correct alignment
        # or we'll end up with corrupted textures
        gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, self._alignment)
        gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, self._alignment)

        # Create depth 2d texture
        if self._depth:
            gl.glTexImage2D(
                self._target,
                0,  # level
                gl.GL_DEPTH_COMPONENT24,
                self._width,
                self._height,
                0,
                gl.GL_DEPTH_COMPONENT,
                gl.GL_FLOAT,
                data,
            )
            self.compare_func = "<="
        # Create normal 2d texture
        else:
            try:
                format_info = pixel_formats[self._dtype]
            except KeyError:
                raise ValueError(
                    f"dype '{self._dtype}' not support. Supported types are : {tuple(pixel_formats.keys())}"
                )

            try:
                (
                    _format,
                    _internal_format,
                    self._type,
                    self._component_size,
                ) = format_info
                self._format = _format[self._components]
                self._internal_format = _internal_format[self._components]
                gl.glTexImage2D(
                    self._target,  # target
                    0,  # level
                    self._internal_format,  # internal_format
                    self._width,  # width
                    self._height,  # height
                    0,  # border
                    self._format,  # format
                    self._type,  # type
                    data,  # data
                )
            except gl.GLException as ex:
                raise gl.GLException(
                    (
                        f"Unable to create texture: {ex} : dtype={self._dtype} size={self.size} components={self._components} "
                        "MAX_TEXTURE_SIZE = {self.ctx.limits.MAX_TEXTURE_SIZE}"
                    )
                )
Пример #7
0
    def _updateFrameTexture(self):
        if self._nextFrameT is None:
            # movie has no current position, need to reset the clock
            # to zero in order to have the timing logic work
            # otherwise the video stream would skip frames until the
            # time since creating the movie object has passed
            self._videoClock.reset()
            self._nextFrameT = 0

        #only advance if next frame (half of next retrace rate)
        if self._nextFrameT > self.duration:
            self._onEos()
        elif (self._numpyFrame is not None) and \
            (self._nextFrameT > (self._videoClock.getTime()-self._retraceInterval/2.0)):
            return None
        self._numpyFrame = self._mov.get_frame(self._nextFrameT)
        useSubTex=self.useTexSubImage2D
        if self._texID is None:
            self._texID = GL.GLuint()
            GL.glGenTextures(1, ctypes.byref(self._texID))
            useSubTex=False

        #bind the texture in openGL
        GL.glEnable(GL.GL_TEXTURE_2D)
        GL.glBindTexture(GL.GL_TEXTURE_2D, self._texID)#bind that name to the target
        GL.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_WRAP_S,GL.GL_REPEAT) #makes the texture map wrap (this is actually default anyway)
        GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1)  # data from PIL/numpy is packed, but default for GL is 4 bytes
        #important if using bits++ because GL_LINEAR
        #sometimes extrapolates to pixel vals outside range
        if self.interpolate:
            GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR)
            GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR)
            if useSubTex is False:
                GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB8,
                    self._numpyFrame.shape[1],self._numpyFrame.shape[0], 0,
                    GL.GL_RGB, GL.GL_UNSIGNED_BYTE, self._numpyFrame.ctypes)
            else:
                GL.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0,
                    self._numpyFrame.shape[1], self._numpyFrame.shape[0],
                    GL.GL_RGB, GL.GL_UNSIGNED_BYTE, self._numpyFrame.ctypes)

        else:
            GL.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_NEAREST)
            GL.glTexParameteri(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_NEAREST)
            if useSubTex is False:
                GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB8,
                                self._numpyFrame.shape[1],self._numpyFrame.shape[0], 0,
                                GL.GL_BGR, GL.GL_UNSIGNED_BYTE, self._numpyFrame.ctypes)
            else:
                GL.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0,
                    self._numpyFrame.shape[1], self._numpyFrame.shape[0],
                    GL.GL_BGR, GL.GL_UNSIGNED_BYTE, self._numpyFrame.ctypes)
        GL.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE)#?? do we need this - think not!

        if not self.status==PAUSED:
            self._nextFrameT += self._frameInterval
Пример #8
0
def attach_input(in_data, in_size):
    # Load input
    gl.glBindTexture(gl.GL_TEXTURE_3D, input_texture)
    glTypeFromNp = {
        np.dtype('uint8'): gl.GL_UNSIGNED_BYTE,
        np.dtype('uint16'): gl.GL_UNSIGNED_SHORT,
        np.dtype('uint32'): gl.GL_UNSIGNED_INT,
        np.dtype('float32'): gl.GL_FLOAT
    }
    gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)
    gl.glTexImage3D(gl.GL_TEXTURE_3D, 0, gl.GL_RED, in_size[0], in_size[1],
                    in_size[2], 0, gl.GL_RED, glTypeFromNp[in_data.dtype],
                    ctypes.c_void_p(in_data.ctypes.data))
Пример #9
0
    def read(self, level: int = 0, alignment: int = 1) -> bytearray:
        """
        Read the contents of the texture.

        :param int level:  The texture level to read
        :param int alignment: Alignment of the start of each row in memory in number of bytes. Possible values: 1,2,4
        :rtype: bytearray
        """
        gl.glBindTexture(self._target, self._glo)
        gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, alignment)

        buffer = (gl.GLubyte * (self.width * self.height * self._component_size * self._components))()
        gl.glGetTexImage(gl.GL_TEXTURE_2D, level, self._format, self._type, buffer)

        return bytearray(buffer)
Пример #10
0
 def get_layer_preview_texture(self, layer, colors, size=(32, 32)):
     w, h = layer.size
     size = w, h
     texture = Texture(size,
                       params={gl.GL_TEXTURE_MIN_FILTER: gl.GL_LINEAR})
     texture.clear()
     data = as_rgba(layer.get_data(self.drawing.frame), colors)
     gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 4)
     gl.glTextureSubImage2D(
         texture.name,
         0,
         0,
         0,
         w,
         h,  # min(w, bw), min(w, bh),
         gl.GL_RGBA,
         gl.GL_UNSIGNED_BYTE,
         data.tobytes("F"))
     return texture
Пример #11
0
def build_kernel(size=256):
    # From GPU Gems
    # Chapter 24. High-Quality Filtering
    # Kevin Bjorke, NVIDIA
    # http://http.developer.nvidia.com/GPUGems/gpugems_ch24.html
    #
    # Mitchell Netravali Reconstruction Filter
    # a = 1.0, b = 0.0  - cubic B-spline
    # B = 1/3, b = 1/3  - recommended
    # a = 0.5, b = 0.0  - Catmull-Rom spline
    def MitchellNetravali(x, a=1, b=0):
        x = math.fabs(x)
        if x < 1.0:
            return ((12-9*a-6*b) *x*x*x + (-18+12*a+6*b)*x*x + (6-2*a))/6.0
        elif x < 2.0:
            return ((-a-6*b)*x*x*x + (6*a+30*b)*x*x + (-12*a-48*b)*x + (8*a+24*b))/6.0
        else:
            return 0
    
    data = (gl.GLfloat*(4*size))()
    for i in range(size):
        x = i/float(size-1)
        data[i*4+0] = MitchellNetravali(x+1)
        data[i*4+1] = MitchellNetravali(x)
        data[i*4+2] = MitchellNetravali(1-x)
        data[i*4+3] = MitchellNetravali(2-x)
    texid = gl.GLuint()
    gl.glGenTextures(1, ctypes.byref(texid))
    kernel = texid.value
    gl.glPixelStorei (gl.GL_UNPACK_ALIGNMENT, 1)
    gl.glPixelStorei (gl.GL_PACK_ALIGNMENT, 1)
    gl.glBindTexture (gl.GL_TEXTURE_1D, texid)
    gl.glTexParameterf (gl.GL_TEXTURE_1D,
                        gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
    gl.glTexParameterf (gl.GL_TEXTURE_1D,
                        gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
    gl.glTexParameterf (gl.GL_TEXTURE_1D,
                        gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP)
    gl.glTexParameterf (gl.GL_TEXTURE_1D,
                        gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP)
    gl.glTexImage1D (gl.GL_TEXTURE_1D,  0, gl.GL_RGBA16, size, 0,
                     gl.GL_RGBA, gl.GL_FLOAT, data)
    return kernel
Пример #12
0
 def get_brush_preview_texture(self, brush, colors=None, size=(8, 8)):
     colors = colors or self.drawing.palette.as_tuple()
     bw, bh = brush.size
     w, h = size
     w, h = size = max(w, bw), max(h, bh)
     texture = Texture(size)
     texture.clear()
     data = as_rgba(brush.data, colors).tobytes("F")
     gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 4)
     gl.glTextureSubImage2D(
         texture.name,
         0,
         max(0, w // 2 - bw // 2),
         max(0, h // 2 - bh // 2),
         bw,
         bh,  # min(w, bw), min(w, bh),
         gl.GL_RGBA,
         gl.GL_UNSIGNED_BYTE,
         data)
     return texture
Пример #13
0
    def write(self,
              data: Union[bytes, Buffer],
              level: int = 0,
              viewport=None) -> None:
        """Write byte data to the texture. This can be bytes or a :py:class:`~arcade.gl.Buffer`.

        :param Union[bytes,Buffer] data: bytes or a Buffer with data to write
        :param int level: The texture level to write
        :param tuple viewport: The are of the texture to write. 2 or 4 component tuple
        """
        # TODO: Support writing to layers using viewport + alignment
        if self._samples > 0:
            raise ValueError("Writing to multisample textures not supported")

        x, y, w, h = 0, 0, self._width, self._height
        if viewport:
            if len(viewport) == 2:
                w, h = viewport
            elif len(viewport) == 4:
                x, y, w, h = viewport
            else:
                raise ValueError("Viewport must be of length 2 or 4")

        if isinstance(data, Buffer):
            gl.glBindBuffer(gl.GL_PIXEL_UNPACK_BUFFER, data.glo)
            gl.glActiveTexture(gl.GL_TEXTURE0)
            gl.glBindTexture(self._target, self._glo)
            gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
            gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)
            gl.glTexSubImage2D(self._target, level, x, y, w, h, self._format,
                               self._type, 0)
            gl.glBindBuffer(gl.GL_PIXEL_UNPACK_BUFFER, 0)
        else:
            byte_size, data = data_to_ctypes(data)
            gl.glActiveTexture(gl.GL_TEXTURE0)
            gl.glBindTexture(self._target, self._glo)
            gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
            gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)
            gl.glTexSubImage2D(
                self._target,  # target
                level,  # level
                x,  # x offset
                y,  # y offset
                w,  # width
                h,  # height
                self._format,  # format
                self._type,  # type
                data,  # pixel data
            )
Пример #14
0
def create_point_texture(size, feather=0):
	"""Create and load a circular grayscale image centered in a square texture
	with a width and height of size. The radius of the circle is size / 2.
	Since size is used as the texture width and height, it should typically
	be a power of two.

	Feather determines the softness of the edge of the circle. The default,
	zero, creates a hard edged circle. Larger feather values create softer
	edges for blending. The point at the center of the texture is always
	white.

	Return the OpenGL texture name (id) for the resulting texture. This
	value can be passed directy to a texturizer or glBindTexture
	"""
	from pyglet import gl

	assert feather >= 0, 'Expected feather value >= 0'
	coords = range(size)
	texel = (gl.GLfloat * size**2)()
	r = size / 2.0
	c = feather + 1.0

	for y in coords:
		col = y * size
		for x in coords:
			d = math.sqrt((x - r)**2 + (y - r)**2)
			if d < r and (1.0 - 1.0 / (d / r - 1.0)) < 100:
				texel[x + col] = c**2 / c**(1.0 - 1.0 / (d / r - 1.0))
			else:
				texel[x + col] = 0
	id = gl.GLuint()
	gl.glGenTextures(1, ctypes.byref(id))
	gl.glBindTexture(gl.GL_TEXTURE_2D, id.value)
	gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 4)
	gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_LUMINANCE, size, size, 0,
		gl.GL_LUMINANCE, gl.GL_FLOAT, ctypes.byref(texel))
	gl.glFlush()
	return id.value
Пример #15
0
def create_point_texture(size, feather=0):
	"""Create and load a circular grayscale image centered in a square texture
	with a width and height of size. The radius of the circle is size / 2. 
	Since size is used as the texture width and height, it should typically
	be a power of two.

	Feather determines the softness of the edge of the circle. The default,
	zero, creates a hard edged circle. Larger feather values create softer
	edges for blending. The point at the center of the texture is always
	white.

	Return the OpenGL texture name (id) for the resulting texture. This
	value can be passed directy to a texturizer or glBindTexture
	"""
	from pyglet import gl

	assert feather >= 0, 'Expected feather value >= 0'
	coords = range(size)
	texel = (gl.GLfloat * size**2)()
	r = size / 2.0
	c = feather + 1.0

	for y in coords:
		col = y * size
		for x in coords:
			d = math.sqrt((x - r)**2 + (y - r)**2)
			if d < r and (1.0 - 1.0 / (d / r - 1.0)) < 100:
				texel[x + col] = c**2 / c**(1.0 - 1.0 / (d / r - 1.0))
			else:
				texel[x + col] = 0
	id = gl.GLuint()
	gl.glGenTextures(1, ctypes.byref(id))
	gl.glBindTexture(gl.GL_TEXTURE_2D, id.value)
	gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 4)
	gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_LUMINANCE, size, size, 0, 
		gl.GL_LUMINANCE, gl.GL_FLOAT, ctypes.byref(texel))
	gl.glFlush()
	return id.value
Пример #16
0
    def create_texobject(self, color_table, format=gl.GL_RGB,
                         internalformat=gl.GL_RGB):

        k = (tuple(color_table), format, internalformat)
        texobj = self._texobjects.get(k)
        if texobj:
            return texobj

        width = {
            gl.GL_RGB: 3,
            gl.GL_RGBA: 4,
            gl.GL_LUMINANCE: 1,
            gl.GL_LUMINANCE_ALPHA: 2}[format]


        texobj = gl.GLuint()
        gl.glGenTextures( 1, ctypes.byref(texobj) )

        gl.glEnable( gl.GL_TEXTURE_1D )
        gl.glBindTexture( gl.GL_TEXTURE_1D, texobj )

        gl.glTexEnvi( gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, gl.GL_DECAL )
        gl.glTexParameteri( gl.GL_TEXTURE_1D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST )
        gl.glTexParameteri( gl.GL_TEXTURE_1D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST )
        gl.glTexParameteri( gl.GL_TEXTURE_1D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP )
        gl.glPixelStorei( gl.GL_UNPACK_ALIGNMENT, 1 )
        gl.glTexImage1D( gl.GL_TEXTURE_1D, 0, internalformat, width, 0, format,
                         gl.GL_UNSIGNED_BYTE, color_table )

        group = TextureBindGroup(texobj, target=gl.GL_TEXTURE_1D,
                                 parent=tex_enable_group_1D(target=gl.GL_TEXTURE_1D))
        #group = CellShaderGroup(texobj, color_table, width,
        #        format, internalformat)
        self._texobjects[k] = texobj
        self._defaultgroups[texobj.value] = group

        return texobj
Пример #17
0
def load_textures(file_name: str,
                  image_location_list: PointList,
                  mirrored: bool=False,
                  flipped: bool=False,
                  scale: float=1) -> List['Texture']:
    """
    Load a set of textures off of a single image file.

    Note, if the code is to load only part of the image, the given x, y
    coordinates will start with the origin (0, 0) in the upper left of the
    image. When drawing, Arcade uses (0, 0)
    in the lower left corner when drawing. Be careful about this reversal.

    For a longer explanation of why computers sometimes start in the upper
    left, see:
    http://programarcadegames.com/index.php?chapter=introduction_to_graphics&lang=en#section_5

    Args:
        :file_name: Name of the file.
        :image_location_list: List of image locations. Each location should be
         a list of four floats. ``[x, y, width, height]``.
        :mirrored=False: If set to true, the image is mirrored left to right.
        :flipped=False: If set to true, the image is flipped upside down.
    Returns:
        :list: List of textures loaded.
    Raises:
        :SystemError:
    """
    source_image = PIL.Image.open(file_name)

    source_image_width, source_image_height = source_image.size
    texture_info_list = []
    for image_location in image_location_list:
        x, y, width, height = image_location

        if width <= 0:
            raise ValueError("Texture has a width of {}, must be > 0."
                             .format(width))
        if x > source_image_width:
            raise ValueError("Can't load texture starting at an x of {} "
                             "when the image is only {} across."
                             .format(x, source_image_width))
        if y > source_image_height:
            raise ValueError("Can't load texture starting at an y of {} "
                             "when the image is only {} high."
                             .format(y, source_image_height))
        if x + width > source_image_width:
            raise ValueError("Can't load texture ending at an x of {} "
                             "when the image is only {} wide."
                             .format(x + width, source_image_width))
        if y + height > source_image_height:
            raise ValueError("Can't load texture ending at an y of {} "
                             "when the image is only {} high."
                             .format(y + height, source_image_height))

        image = source_image.crop((x, y, x + width, y + height))
        # image = _trim_image(image)

        if mirrored:
            image = PIL.ImageOps.mirror(image)

        if flipped:
            image = PIL.ImageOps.flip(image)

        image_width, image_height = image.size

        texture = gl.GLuint(0)
        gl.glGenTextures(1, ctypes.byref(texture))

        gl.glBindTexture(gl.GL_TEXTURE_2D, texture)
        gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)

        gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT)
        gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT)

        gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR)
        gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER,
                           gl.GL_LINEAR_MIPMAP_LINEAR)

        image_width *= scale
        image_height *= scale

        texture_info_list.append(Texture(texture, width, height, image_location))

    return texture_info_list
Пример #18
0
def main():
    t = time.time()

    parser = argparse.ArgumentParser()
    parser.add_argument('--tex',
                        help='input tiff file (*.tiff for sequence)',
                        default='')
    parser.add_argument('--in_box',
                        help='--insize x y z w h d',
                        type=int,
                        nargs=6,
                        default=[0, 0, 0, 0, 0, 0])
    parser.add_argument('--code',
                        help='--code "return texture(tex,p).r;"',
                        default='return texture(tex,p).r;')
    parser.add_argument('--size',
                        help='--size w h d',
                        nargs=3,
                        type=int,
                        default=[0, 0, 0])
    parser.add_argument('--seam',
                        help='--seam dd',
                        nargs=1,
                        type=int,
                        default=10)
    parser.add_argument('--compress',
                        help='compression level',
                        type=int,
                        default=2)
    parser.add_argument('out_tiff', help='output tiff file', type=str)
    args = parser.parse_args()

    seam = args.seam
    if '*' in args.tex:
        import os
        dr = os.path.split(args.tex)[0] + '/'
        print(dr, os.path.isdir(dr))
        seq = tifffile.TiffSequence(args.tex)
        in_data = seq.asarray()
        print(in_data.shape, in_data.dtype)
        print(in_data[0][0][0])
        # in_data = in_data.astype(np.uint32)
        # print(in_data[0][0][0])
    elif os.path.isfile(args.tex):
        in_data = tifffile.imread(args.tex)
    else:
        in_data = np.zeros((1, 1, 1), dtype=np.uint32)
    if len(in_data.shape) != 3:
        print('Not a 3D grayscale tiff:', in_data.shape)
    # if len(in_data.shape)==4:
    # 	print('Using red channel')

    in_d, in_h, in_w = in_data.shape
    in_size = in_w, in_h, in_d
    bx, by, bz, bw, bh, bd = args.in_box
    bw = in_w - bx if bw == 0 or bx + bw > in_w else bw
    bh = in_h - by if bh == 0 or by + bh > in_h else bh
    bd = in_d - bz if bd == 0 or bz + bd > in_d else bd

    time_loaded = time.time()
    print('Loading input {} took {:.2f} seconds'.format(
        in_size, time_loaded - t))
    if (bw, bh, bd) != in_size:
        print('Clipping to [{},{})x[{},{})x[{},{})'.format(
            bx, bx + bw, by, by + bh, bz, bz + bd))
        in_size = (bw, bh, bd)
        in_w, in_h, in_d = in_size
        in_data = in_data[bz:bz + bd, by:by + bh, bx:bx + bw]

    out_w, out_h, out_d = args.size
    out_w = in_w if out_w <= 0 else out_w
    out_h = in_h if out_h <= 0 else out_h
    out_d = in_d if out_d <= 0 else out_d
    out_size = (out_w, out_h, out_d)

    pixPerZ = in_w * in_h
    zPerBatch = SAFE_TEX_SIZE // pixPerZ - 2 * seam
    batches = [(i, i + zPerBatch) for i in range(0, in_d, zPerBatch)]

    setup_framebuffer()
    setup_render_program(args.code)
    setup_render_vertexbuffer()
    time_setup = time.time()
    print('Setup took {:.2f} seconds'.format(time_setup - time_loaded))

    time_buffered = time_setup
    warned = False
    out_batches = []
    for z0, z1 in batches:
        z0 = max(0, z0)
        z1 = min(in_d, z1)
        z0s = max(0, z0 - seam)
        z1s = min(in_d, z1 + seam)

        batch_out_d = out_d * (z1 - z0) / in_d
        if not warned and batch_out_d != int(batch_out_d) and len(batches) > 1:
            warned = True
            print(
                'Warning: input/output Z-dimension mismatch while using multiple batches'
            )
        batch_out_d = int(batch_out_d)
        batch_in_size = (in_w, in_h, z1s - z0s)
        batch_out_size = (out_w, out_h, batch_out_d)

        attach_input(in_data[z0s:z1s], batch_in_size)
        attach_output(batch_out_size)
        time_transfer = time.time()
        print('Texture transfer {} took {:.2f} seconds'.format(
            (z0s, z0, z1, z1s), time_transfer - time_buffered))

        render_to_texture(batch_in_size, batch_out_size, (z0 - z0s, z1 - z0s))
        time_rendered = time.time()
        print('Rendering took {:.2f} seconds'.format(time_rendered -
                                                     time_transfer))

        buf = (gl.GLubyte * (out_w * out_h * batch_out_d))()
        gl.glBindTexture(gl.GL_TEXTURE_3D, rendered_texture)
        gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
        gl.glGetTexImage(gl.GL_TEXTURE_3D, 0, gl.GL_RED, gl.GL_UNSIGNED_BYTE,
                         buf)
        out_batches.append(
            np.frombuffer(buf, dtype=np.uint8).reshape(
                (batch_out_d, out_h, out_w)))

        time_buffered = time.time()
        print('Buffering took {:.2f} seconds'.format(time_buffered -
                                                     time_rendered))

    out_data = np.concatenate(out_batches)
    time_cat = time.time()
    print('Concatenating took {:.2f} seconds'.format(time_cat - time_buffered))

    # export
    t = time.time()
    tifffile.imwrite(args.out_tiff,
                     out_data,
                     bigtiff=True,
                     compress=args.compress,
                     photometric='minisblack',
                     metadata={
                         'title': str(out_data.shape),
                         'code': str(args.code)
                     })
    time_exported = time.time()
    print('Exporting took {:.2f} seconds; size {:.2f} MB'.format(
        time_exported - t,
        os.path.getsize(args.out_tiff) / 1024**2))
Пример #19
0
def render_drawing(drawing, highlighted_layer=None):
    """
    This function has the job of rendering a drawing to a framebuffer.
    """

    offscreen_buffer = _get_offscreen_buffer(drawing.size)

    colors = _get_colors(drawing.palette.as_tuple())

    with vao, offscreen_buffer, draw_program:
        w, h = offscreen_buffer.size
        gl.glViewport(0, 0, w, h)

        gl.glEnable(gl.GL_BLEND)
        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
        gl.glClearBufferfv(gl.GL_COLOR, 0, EMPTY_COLOR)

        overlay = drawing.overlay
        overlay_texture = _get_overlay_texture(overlay.size)

        if overlay.dirty.get(0) and overlay.lock.acquire(timeout=0.01):
            # Since we're drawing in a separate thread, we need to be very careful
            # when accessing the overlay, otherwise we can get nasty problems.
            # While we have the lock, the thread won't draw, so we can safely copy data.
            # The acquire timeout is a compromise; on one hand, we don't wait
            # so long that the user feels stutter, on the other hand,
            # if we never wait, and the draw thread is very busy, we might
            # not get to update for a long time.
            rect = overlay.dirty[0]
            subimage = overlay.get_subimage(rect)
            data = subimage.tobytes("F")  # TODO Is this making another copy?

            # Now update the texture with the changed part of the layer.
            try:
                gl.glTextureSubImage2D(overlay_texture.name, 0, *rect.points,
                                       gl.GL_RGBA_INTEGER, gl.GL_UNSIGNED_BYTE,
                                       data)

                overlay.dirty.pop(0)
                overlay.lock.release()  # Allow layer to change again.
            except gl.lib.GLException as e:
                logging.error(str(e))

        frame = drawing.frame
        for layer in drawing.layers:

            if highlighted_layer and highlighted_layer != layer:
                continue

            # TODO might be a good optimization to draw the layers above and
            # above into two separate textures, so we don't have
            # to iterate over them all every frame. Also cuts down on the
            # number of textures in GPU memory.
            # Assumes the non-current textures don't change though.

            layer_texture = _get_layer_texture(layer, frame)
            if layer.dirty.get(frame) and layer.lock.acquire(timeout=0.03):
                rect = layer.dirty[frame]
                subimage = layer.get_subimage(rect, frame)
                data = subimage.tobytes("F")
                gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT,
                                 1)  # Needed for writing 8bit data
                gl.glTextureSubImage2D(layer_texture.name, 0, *rect.points,
                                       gl.GL_RED_INTEGER, gl.GL_UNSIGNED_BYTE,
                                       data)
                gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 4)
                layer.dirty.pop(frame)
                layer.lock.release()

            if not layer.visible and highlighted_layer != layer:
                continue

            with layer_texture:
                if layer == drawing.current:
                    # The overlay is combined with the layer
                    with overlay_texture:
                        # TODO is it possible to send the palette without converting
                        # to float first?
                        gl.glUniform1f(1, 1)
                        gl.glUniform4fv(2, 256, colors)
                        gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)
                else:
                    with _get_empty_texture(drawing.size):
                        gl.glUniform1f(1, 1)
                        gl.glUniform4fv(2, 256, colors)
                        gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)

        gl.glDisable(gl.GL_BLEND)
    return offscreen_buffer
Пример #20
0
def createTexImage2D(width,
                     height,
                     target=GL.GL_TEXTURE_2D,
                     level=0,
                     internalFormat=GL.GL_RGBA8,
                     pixelFormat=GL.GL_RGBA,
                     dataType=GL.GL_FLOAT,
                     data=None,
                     unpackAlignment=4,
                     texParameters=()):
    """Create a 2D texture in video memory. This can only create a single 2D
    texture with targets GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE.

    Parameters
    ----------
    width : :obj:`int`
        Texture width in pixels.
    height : :obj:`int`
        Texture height in pixels.
    target : :obj:`int`
        The target texture should only be either GL_TEXTURE_2D or
        GL_TEXTURE_RECTANGLE.
    level : :obj:`int`
        LOD number of the texture, should be 0 if GL_TEXTURE_RECTANGLE is the
        target.
    internalFormat : :obj:`int`
        Internal format for texture data (e.g. GL_RGBA8, GL_R11F_G11F_B10F).
    pixelFormat : :obj:`int`
        Pixel data format (e.g. GL_RGBA, GL_DEPTH_STENCIL)
    dataType : :obj:`int`
        Data type for pixel data (e.g. GL_FLOAT, GL_UNSIGNED_BYTE).
    data : :obj:`ctypes` or :obj:`None`
        Ctypes pointer to image data. If None is specified, the texture will be
        created but pixel data will be uninitialized.
    unpackAlignment : :obj:`int`
        Alignment requirements of each row in memory. Default is 4.
    texParameters : :obj:`list` of :obj:`tuple` of :obj:`int`
        Optional texture parameters specified as a list of tuples. These values
        are passed to 'glTexParameteri'. Each tuple must contain a parameter
        name and value. For example, texParameters=[(GL.GL_TEXTURE_MIN_FILTER,
        GL.GL_LINEAR), (GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR)]

    Returns
    -------
    :obj:`TexImage2D`
        A TexImage2D descriptor.

    Notes
    -----
    The 'userData' field of the returned descriptor is a dictionary that can
    be used to store arbitrary data associated with the texture.

    Previous textures are unbound after calling 'createTexImage2D'.

    Examples
    --------
    import pyglet.gl as GL  # using Pyglet for now

    # empty texture
    textureDesc = createTexImage2D(1024, 1024, internalFormat=GL.GL_RGBA8)

    # load texture data from an image file using Pillow and NumPy
    from PIL import Image
    import numpy as np
    im = Image.open(imageFile)  # 8bpp!
    im = im.transpose(Image.FLIP_TOP_BOTTOM)  # OpenGL origin is at bottom
    im = im.convert("RGBA")
    pixelData = np.array(im).ctypes  # convert to ctypes!

    width = pixelData.shape[1]
    height = pixelData.shape[0]
    textureDesc = gltools.createTexImage2D(
        texture_array.shape[1],
        texture_array.shape[0],
        internalFormat=GL.GL_RGBA,
        pixelFormat=GL.GL_RGBA,
        dataType=GL.GL_UNSIGNED_BYTE,
        data=texture_array.ctypes,
        unpackAlignment=1,
        texParameters=[(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR),
                       (GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR)])

    GL.glBindTexture(GL.GL_TEXTURE_2D, textureDesc.id)

    """
    width = int(width)
    height = int(height)

    if width <= 0 or height <= 0:
        raise ValueError("Invalid image dimensions {} x {}.".format(
            width, height))

    if target == GL.GL_TEXTURE_RECTANGLE:
        if level != 0:
            raise ValueError("Invalid level for target GL_TEXTURE_RECTANGLE, "
                             "must be 0.")
        GL.glEnable(GL.GL_TEXTURE_RECTANGLE)

    colorTexId = GL.GLuint()
    GL.glGenTextures(1, ctypes.byref(colorTexId))
    GL.glBindTexture(target, colorTexId)
    GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, int(unpackAlignment))
    GL.glTexImage2D(target, level, internalFormat, width, height, 0,
                    pixelFormat, dataType, data)

    # apply texture parameters
    if texParameters:
        for pname, param in texParameters:
            GL.glTexParameteri(target, pname, param)

    GL.glBindTexture(target, 0)

    return TexImage2D(colorTexId, target, width, height, internalFormat,
                      pixelFormat, dataType, unpackAlignment, 1, False, dict())
Пример #21
0
    def _updateFrameTexture(self):
        """Update texture pixel store to contain the present frame. Decoded
        frame image samples are streamed to the texture buffer.

        """
        if self._nextFrameT is None or self._nextFrameT < 0:
            # movie has no current position (or invalid position -JK),
            # need to reset the clock to zero in order to have the
            # timing logic work otherwise the video stream would skip
            # frames until the time since creating the movie object has passed
            self._videoClock.reset()
            self._nextFrameT = 0.0

        # only advance if next frame (half of next retrace rate)
        if self._nextFrameT > self.duration:
            self._onEos()
        elif self._numpyFrame is not None:
            if self._nextFrameT > (self._videoClock.getTime() -
                                   self._retraceInterval / 2.0):
                return None

        while self._nextFrameT <= (self._videoClock.getTime() -
                                   self._frameInterval * 2):
            self.nDroppedFrames += 1
            if self.nDroppedFrames <= reportNDroppedFrames:
                logging.warning(
                    "{}: Video catchup needed, advancing self._nextFrameT from"
                    " {} to {}".format(self._videoClock.getTime(),
                                       self._nextFrameT,
                                       self._nextFrameT + self._frameInterval))
            if self.nDroppedFrames == reportNDroppedFrames:
                logging.warning(
                    "Max reportNDroppedFrames reached, will not log any more dropped frames"
                )

            self._nextFrameT += self._frameInterval

        try:
            self._numpyFrame = self._mov.get_frame(self._nextFrameT)
        except OSError:
            if self.autoLog:
                logging.warning(
                    "Frame {} not found, moving one frame and trying again".
                    format(self._nextFrameT),
                    obj=self)
            self._nextFrameT += self._frameInterval
            self._updateFrameTexture()
        useSubTex = self.useTexSubImage2D
        if self._texID is None:
            self._texID = GL.GLuint()
            GL.glGenTextures(1, ctypes.byref(self._texID))
            useSubTex = False

        GL.glActiveTexture(GL.GL_TEXTURE0)
        # bind that name to the target
        GL.glBindTexture(GL.GL_TEXTURE_2D, self._texID)
        # bind the texture in openGL
        GL.glEnable(GL.GL_TEXTURE_2D)
        # makes the texture map wrap (this is actually default anyway)
        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)
        # data from PIL/numpy is packed, but default for GL is 4 bytes
        GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1)
        # important if using bits++ because GL_LINEAR
        # sometimes extrapolates to pixel vals outside range
        if self.interpolate:
            GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER,
                               GL.GL_LINEAR)
            GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER,
                               GL.GL_LINEAR)
            if useSubTex is False:
                GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB8,
                                self._numpyFrame.shape[1],
                                self._numpyFrame.shape[0], 0, GL.GL_RGB,
                                GL.GL_UNSIGNED_BYTE, self._numpyFrame.ctypes)
            else:
                GL.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0,
                                   self._numpyFrame.shape[1],
                                   self._numpyFrame.shape[0], GL.GL_RGB,
                                   GL.GL_UNSIGNED_BYTE,
                                   self._numpyFrame.ctypes)
        else:
            GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER,
                               GL.GL_NEAREST)
            GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER,
                               GL.GL_NEAREST)
            if useSubTex is False:
                GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB8,
                                self._numpyFrame.shape[1],
                                self._numpyFrame.shape[0], 0, GL.GL_BGR,
                                GL.GL_UNSIGNED_BYTE, self._numpyFrame.ctypes)
            else:
                GL.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0,
                                   self._numpyFrame.shape[1],
                                   self._numpyFrame.shape[0], GL.GL_BGR,
                                   GL.GL_UNSIGNED_BYTE,
                                   self._numpyFrame.ctypes)
        GL.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE,
                     GL.GL_MODULATE)  # ?? do we need this - think not!

        if self.status == PLAYING:
            self._nextFrameT += self._frameInterval
Пример #22
0
def load_textures(file_name: str,
                  image_location_list: PointList,
                  mirrored: bool = False,
                  flipped: bool = False,
                  scale: float = 1) -> List['Texture']:
    """
    Load a set of textures off of a single image file.

    Args:
        :file_name: Name of the file.
        :image_location_list: List of image locations. Each location should be
         a list of four floats. ``[x, y, width, height]``.
        :mirrored=False: If set to true, the image is mirrored left to right.
        :flipped=False: If set to true, the image is flipped upside down.
    Returns:
        :list: List of textures loaded.
    Raises:
        :SystemError:
    """
    source_image = PIL.Image.open(file_name)

    source_image_width, source_image_height = source_image.size
    texture_info_list = []
    for image_location in image_location_list:
        x, y, width, height = image_location

        if width <= 0:
            raise ValueError(
                "Texture has a width of {}, must be > 0.".format(width))
        if x > source_image_width:
            raise ValueError("Can't load texture starting at an x of {} "
                             "when the image is only {} across.".format(
                                 x, source_image_width))
        if y > source_image_height:
            raise ValueError("Can't load texture starting at an y of {} "
                             "when the image is only {} high.".format(
                                 y, source_image_height))
        if x + width > source_image_width:
            raise ValueError("Can't load texture ending at an x of {} "
                             "when the image is only {} wide.".format(
                                 x + width, source_image_width))
        if y + height > source_image_height:
            raise ValueError("Can't load texture ending at an y of {} "
                             "when the image is only {} high.".format(
                                 y + height, source_image_height))

        image = source_image.crop((x, y, x + width, y + height))
        # image = _trim_image(image)

        if mirrored:
            image = PIL.ImageOps.mirror(image)

        if flipped:
            image = PIL.ImageOps.flip(image)

        image_width, image_height = image.size

        texture = gl.GLuint(0)
        gl.glGenTextures(1, ctypes.byref(texture))

        gl.glBindTexture(gl.GL_TEXTURE_2D, texture)
        gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)

        gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S,
                           gl.GL_REPEAT)
        gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T,
                           gl.GL_REPEAT)

        gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER,
                           gl.GL_LINEAR)
        gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER,
                           gl.GL_LINEAR_MIPMAP_LINEAR)

        image_width *= scale
        image_height *= scale

        texture_info_list.append(Texture(texture, width, height))

    return texture_info_list
Пример #23
0
def load_texture(file_name: str,
                 x: float = 0,
                 y: float = 0,
                 width: float = 0,
                 height: float = 0,
                 mirrored: bool = False,
                 flipped: bool = False,
                 scale: float = 1) -> arcade.Texture:
    """
    Load image from disk and create a texture.

    Args:
        :filename (str): Name of the file to that holds the texture.
        :x (float): X position of the crop area of the texture.
        :y (float): Y position of the crop area of the texture.
        :width (float): Width of the crop area of the texture.
        :height (float): Height of the crop area of the texture.
        :scale (float): Scale factor to apply on the new texture.
    Returns:
        The new texture.
    Raises:
        None

    >>> import arcade
    >>> arcade.open_window(800,600,"Drawing Example")
    >>> name = "arcade/examples/images/meteorGrey_big1.png"
    >>> texture1 = load_texture(name, 1, 1, 50, 50)
    >>> texture2 = load_texture(name, 1, 1, 50, 50)

    >>> texture = load_texture(name, 200, 1, 50, 50)
    Traceback (most recent call last):
    ...
    ValueError: Can't load texture starting at an x of 200 when the image is only 101 across.

    >>> texture = load_texture(name, 1, 50, 50, 50)
    Traceback (most recent call last):
    ...
    ValueError: Can't load texture ending at an y of 100 when the image is only 84 high.

    >>> texture = load_texture(name, 1, 150, 50, 50)
    Traceback (most recent call last):
    ...
    ValueError: Can't load texture starting at an y of 150 when the image is only 84 high.

    >>> texture = load_texture(name, 0, 0, 400, 50)
    Traceback (most recent call last):
    ...
    ValueError: Can't load texture ending at an x of 400 when the image is only 101 wide.

    >>> arcade.close_window()
    """

    # See if we already loaded this file, and we can just use a cached version.
    cache_name = "{}{}{}{}{}{}{}{}".format(file_name, x, y, width, height,
                                           scale, flipped, mirrored)
    if cache_name in load_texture.texture_cache:
        return load_texture.texture_cache[cache_name]

    source_image = PIL.Image.open(file_name)

    source_image_width, source_image_height = source_image.size

    if x != 0 or y != 0 or width != 0 or height != 0:
        if x > source_image_width:
            raise ValueError("Can't load texture starting at an x of {} "
                             "when the image is only {} across.".format(
                                 x, source_image_width))
        if y > source_image_height:
            raise ValueError("Can't load texture starting at an y of {} "
                             "when the image is only {} high.".format(
                                 y, source_image_height))
        if x + width > source_image_width:
            raise ValueError("Can't load texture ending at an x of {} "
                             "when the image is only {} wide.".format(
                                 x + width, source_image_width))
        if y + height > source_image_height:
            raise ValueError("Can't load texture ending at an y of {} "
                             "when the image is only {} high.".format(
                                 y + height, source_image_height))

        image = source_image.crop((x, y, x + width, y + height))
    else:
        image = source_image

    # image = _trim_image(image)
    if mirrored:
        image = PIL.ImageOps.mirror(image)

    if flipped:
        image = PIL.ImageOps.flip(image)

    image_width, image_height = image.size
    image_bytes = image.convert("RGBA").tobytes("raw", "RGBA", 0, -1)

    texture = gl.GLuint(0)
    gl.glGenTextures(1, ctypes.byref(texture))

    gl.glBindTexture(gl.GL_TEXTURE_2D, texture)
    gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)

    gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT)
    gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT)

    gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER,
                       gl.GL_NEAREST)
    gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER,
                       gl.GL_NEAREST)
    glu.gluBuild2DMipmaps(gl.GL_TEXTURE_2D, gl.GL_RGBA, image_width,
                          image_height, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE,
                          image_bytes)

    image_width *= scale
    image_height *= scale

    result = Texture(texture, image_width, image_height)
    load_texture.texture_cache[cache_name] = result
    return result
Пример #24
0
    def blit_to_texture(self, target, level, x, y, z, internalformat=None):
        '''Draw this image to to the currently bound texture at `target`.

        If `internalformat` is specified, glTexImage is used to initialise
        the texture; otherwise, glTexSubImage is used to update a region.
        '''

        data_format = self.format
        data_pitch = abs(self._current_pitch)

        # Determine pixel format from format string
        matrix = None
        format, type = self._get_gl_format_and_type(data_format)
        if format is None:
            if (len(data_format) in (3, 4)
                    and gl.gl_info.have_extension('GL_ARB_imaging')):

                # Construct a color matrix to convert to GL_RGBA
                def component_column(component):
                    try:
                        pos = 'RGBA'.index(component)
                        return [0] * pos + [1] + [0] * (3 - pos)
                    except ValueError:
                        return [0, 0, 0, 0]

                # pad to avoid index exceptions
                lookup_format = data_format + 'XXX'
                matrix = (component_column(lookup_format[0]) +
                          component_column(lookup_format[1]) +
                          component_column(lookup_format[2]) +
                          component_column(lookup_format[3]))
                format = {3: gl.GL_RGB, 4: gl.GL_RGBA}.get(len(data_format))
                type = gl.GL_UNSIGNED_BYTE

                gl.glMatrixMode(gl.GL_COLOR)
                gl.glPushMatrix()
                gl.glLoadMatrixf((gl.GLfloat * 16)(*matrix))
            else:
                # Need to convert data to a standard form
                data_format = {
                    1: 'L',
                    2: 'LA',
                    3: 'RGB',
                    4: 'RGBA'
                }.get(len(data_format))
                format, type = self._get_gl_format_and_type(data_format)

        # Workaround: don't use GL_UNPACK_ROW_LENGTH
        if gl.current_context._workaround_unpack_row_length:
            data_pitch = self.width * len(data_format)

        # Get data in required format (hopefully will be the same format it's
        # already in, unless that's an obscure format, upside-down or the
        # driver is old).
        data = self._convert(data_format, data_pitch)

        if data_pitch & 0x1:
            alignment = 1
        elif data_pitch & 0x2:
            alignment = 2
        else:
            alignment = 4
        row_length = data_pitch / len(data_format)
        gl.glPushClientAttrib(gl.GL_CLIENT_PIXEL_STORE_BIT)
        gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, alignment)
        gl.glPixelStorei(gl.GL_UNPACK_ROW_LENGTH, row_length)
        self._apply_region_unpack()
        gl.glTexParameteri(target, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE)
        gl.glTexParameteri(target, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE)
        gl.glTexParameteri(target, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR)
        gl.glTexParameteri(target, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR)

        if target == gl.GL_TEXTURE_3D:
            assert not internalformat
            gl.glTexSubImage3D(target, level, x, y, z, self.width, self.height,
                               1, format, type, data)
        elif internalformat:
            gl.glTexImage2D(target, level, internalformat, self.width,
                            self.height, 0, format, type, data)
        else:
            gl.glTexSubImage2D(target, level, x, y, self.width, self.height,
                               format, type, data)
        gl.glPopClientAttrib()

        if matrix:
            gl.glPopMatrix()
            gl.glMatrixMode(gl.GL_MODELVIEW)
Пример #25
0
    def _updateFrameTexture(self):
        if self._nextFrameT is None:
            # movie has no current position, need to reset the clock
            # to zero in order to have the timing logic work
            # otherwise the video stream would skip frames until the
            # time since creating the movie object has passed
            self._videoClock.reset()
            self._nextFrameT = 0

        # only advance if next frame (half of next retrace rate)
        if self._nextFrameT > self.duration:
            self._onEos()
        elif self._numpyFrame is not None:
            if self._nextFrameT > (self._videoClock.getTime() -
                                   old_div(self._retraceInterval, 2.0)):
                return None
        self._numpyFrame = self._mov.get_frame(self._nextFrameT)
        useSubTex = self.useTexSubImage2D
        if self._texID is None:
            self._texID = GL.GLuint()
            GL.glGenTextures(1, ctypes.byref(self._texID))
            useSubTex = False

        # bind the texture in openGL
        GL.glEnable(GL.GL_TEXTURE_2D)
        # bind that name to the target
        GL.glBindTexture(GL.GL_TEXTURE_2D, self._texID)
        # makes the texture map wrap (this is actually default anyway)
        GL.glTexParameteri(
            GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT)
        # data from PIL/numpy is packed, but default for GL is 4 bytes
        GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1)
        # important if using bits++ because GL_LINEAR
        # sometimes extrapolates to pixel vals outside range
        if self.interpolate:
            GL.glTexParameteri(
                GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR)
            GL.glTexParameteri(
                GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR)
            if useSubTex is False:
                GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB8,
                                self._numpyFrame.shape[1],
                                self._numpyFrame.shape[0], 0,
                                GL.GL_RGB, GL.GL_UNSIGNED_BYTE,
                                self._numpyFrame.ctypes)
            else:
                GL.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0,
                                   self._numpyFrame.shape[1],
                                   self._numpyFrame.shape[0],
                                   GL.GL_RGB, GL.GL_UNSIGNED_BYTE,
                                   self._numpyFrame.ctypes)
        else:
            GL.glTexParameteri(
                GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST)
            GL.glTexParameteri(
                GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST)
            if useSubTex is False:
                GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB8,
                                self._numpyFrame.shape[1],
                                self._numpyFrame.shape[0], 0,
                                GL.GL_BGR, GL.GL_UNSIGNED_BYTE,
                                self._numpyFrame.ctypes)
            else:
                GL.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0,
                                   self._numpyFrame.shape[1],
                                   self._numpyFrame.shape[0],
                                   GL.GL_BGR, GL.GL_UNSIGNED_BYTE,
                                   self._numpyFrame.ctypes)
        GL.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE,
                     GL.GL_MODULATE)  # ?? do we need this - think not!

        if not self.status == PAUSED:
            self._nextFrameT += self._frameInterval
Пример #26
0
    def __init__(self,
                 ctx: 'Context',
                 size: Tuple[int, int],
                 *,
                 components: int = 4,
                 dtype: str = 'f1',
                 data: Any = None,
                 filter: Tuple[gl.GLuint, gl.GLuint] = None,
                 wrap_x: gl.GLuint = None,
                 wrap_y: gl.GLuint = None):
        """
        A texture can be created with or without initial data.
        NOTE: Currently does not support multisample textures even
        thought ``samples`` is exposed.

        :param Context ctx: The context the object belongs to
        :param Tuple[int, int] size: The size of the texture
        :param int components: The number of components (1: R, 2: RG, 3: RGB, 4: RGBA)
        :param str dtype: The data type of each component: f1, f2, f4 / i1, i2, i4 / u1, u2, u4
        :param Any data: The byte data of the texture. bytes or anything supporting the buffer protocol.
        :param Tuple[gl.GLuint, gl.GLuint] filter: The minification/magnification filter of the texture
        :param gl.GLuint wrap_s
        :param data: The texture data (optional)
        """
        self._ctx = ctx
        self._width, self._height = size
        self._dtype = dtype
        self._components = components
        self._target = gl.GL_TEXTURE_2D
        self._samples = 0
        # Default filters for float and integer textures
        if 'f' in self.dtype:
            self._filter = gl.GL_LINEAR, gl.GL_LINEAR
        else:
            self._filter = gl.GL_NEAREST, gl.GL_NEAREST
        self._wrap_x = gl.GL_REPEAT
        self._wrap_y = gl.GL_REPEAT

        if components not in [1, 2, 3, 4]:
            raise ValueError("Components must be 1, 2, 3 or 4")

        try:
            format_info = self._formats[self._dtype]
        except KeyError:
            raise ValueError(
                f"dype '{dtype}' not support. Supported types are : {tuple(self._formats.keys())}"
            )

        gl.glActiveTexture(
            gl.GL_TEXTURE0)  # Create textures in the default channel (0)

        self._glo = glo = gl.GLuint()
        gl.glGenTextures(1, byref(self._glo))

        if self._glo.value == 0:
            raise RuntimeError(
                "Cannot create Texture. OpenGL failed to generate a texture id"
            )

        gl.glBindTexture(self._target, self._glo)
        gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
        gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)

        if data is not None:
            byte_length, data = data_to_ctypes(data)

        try:
            _format, _internal_format, self._type, self._component_size = format_info
            self._format = _format[components]
            self._internal_format = _internal_format[components]
            gl.glTexImage2D(
                self._target,  # target
                0,  # level
                self._internal_format,  # internal_format
                self._width,  # width
                self._height,  # height
                0,  # border
                self._format,  # format
                self._type,  # type
                data  # data
            )
        except gl.GLException as ex:
            raise gl.GLException((
                f"Unable to create texture: {ex} : dtype={dtype} size={size} components={components} "
                "MAX_TEXTURE_SIZE = {self.ctx.limits.MAX_TEXTURE_SIZE}"))

        self.filter = filter or self._filter
        self.wrap_x = wrap_x or self._wrap_x
        self.wrap_y = wrap_y or self._wrap_y

        self.ctx.stats.incr('texture')
        weakref.finalize(self, Texture.release, self._ctx, glo)
Пример #27
0
def load_texture(file_name, x=0, y=0, width=0, height=0, scale=1):
    """
    Load image from disk and create a texture.

    Args:
        :filename (str): Name of the file to that holds the texture.
    Returns:
        Integer identifier for the new texture.
    Raises:
        None

    >>> import arcade
    >>> arcade.open_window("Drawing Example", 800, 600)
    >>> name = "examples/images/meteorGrey_big1.png"
    >>> texture = load_texture(name, 1, 1, 50, 50)
    >>> arcade.close_window()
    """

    # See if we already loaded this file, and we can just use a cached version.
    if file_name in load_texture.texture_cache:
        return load_texture.texture_cache[file_name]

    source_image = PIL.Image.open(file_name)

    source_image_width, source_image_height = source_image.size

    if x != 0 or y != 0 or width != 0 or height != 0:
        if x > source_image_width:
            raise SystemError("Can't load texture starting at an x of {} "
                              "when the image is only {} across."
                              .format(x, source_image_width))
        if y > source_image_height:
            raise SystemError("Can't load texture starting at an y of {} "
                              "when the image is only {} high."
                              .format(y, source_image_height))
        if x + width > source_image_width:
            raise SystemError("Can't load texture ending at an x of {} "
                              "when the image is only {} wide."
                              .format(x + width, source_image_width))
        if y + height > source_image_height:
            raise SystemError("Can't load texture ending at an y of {} "
                              "when the image is only {} high."
                              .format(y + height, source_image_height))

        image = source_image.crop((x, y, x + width, y + height))
    else:
        image = source_image

    # image = _trim_image(image)

    image_width, image_height = image.size
    image_bytes = image.convert("RGBA").tobytes("raw", "RGBA", 0, -1)

    texture = GL.GLuint(0)
    GL.glGenTextures(1, ctypes.byref(texture))

    GL.glBindTexture(GL.GL_TEXTURE_2D, texture)
    GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1)

    # Appveyor work-around
    appveyor = True
    if not appveyor:
        GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S,
                           GL.GL_CLAMP_TO_BORDER)
        GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T,
                           GL.GL_CLAMP_TO_BORDER)
    else:
        GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S,
                           GL.GL_REPEAT)
        GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T,
                           GL.GL_REPEAT)

    GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER,
                       GL.GL_LINEAR)
    GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER,
                       GL.GL_LINEAR_MIPMAP_LINEAR)
    GLU.gluBuild2DMipmaps(GL.GL_TEXTURE_2D, GL.GL_RGBA,
                          image_width, image_height,
                          GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, image_bytes)

    image_width *= scale
    image_height *= scale

    result = Texture(texture, image_width, image_height)
    load_texture.texture_cache[file_name] = result
    return result
Пример #28
0
def render_view(window):
    """ Render the current view to a texture. """

    drawing = window.drawing
    view = window.view

    changed = False

    # Update the overlay with the current stroke
    overlay = view.overlay
    w, h, d = view.shape
    size = w, h
    overlay_texture = _get_overlay_texture(size)
    if overlay.dirty and overlay.lock.acquire(timeout=0.01):
        rect = overlay.dirty
        x0, y0, x1, y1 = rect.box()
        overlay_data = overlay.data[x0:x1, y0:y1].tobytes("F")
        gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT,
                         1)  # Needed for writing 8bit data
        gl.glTextureSubImage2D(overlay_texture.name, 0, *rect.position,
                               *rect.size, gl.GL_RGBA_INTEGER,
                               gl.GL_UNSIGNED_BYTE, overlay_data)
        gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 4)
        overlay.dirty = None
        overlay.lock.release()
        changed = True

    # Update the image texture
    data = drawing.data
    drawing_texture = _get_3d_texture(data.shape)
    if drawing.dirty:
        with drawing.lock:
            update_data = data[drawing.dirty].tobytes(order="F")
            sx, sy, sz = drawing.dirty
            drawing.dirty = None
        sw = sx.stop - sx.start
        sh = sy.stop - sy.start
        sd = sz.stop - sz.start
        gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT,
                         1)  # Needed for writing 8bit data
        gl.glTextureSubImage3D(drawing_texture.name, 0, sx.start, sy.start,
                               sz.start, sw, sh, sd, gl.GL_RED_INTEGER,
                               gl.GL_UNSIGNED_BYTE, update_data)
        gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 4)
        changed = True

    # Render everything to the offscreen buffer

    # TODO we actually should not have to redraw the offscreen_buffer unless something has changed
    # (e.g. drawing, overlay, palette or cursor)

    offscreen_buffer = _get_offscreen_buffer(size)
    colors = _get_colors(drawing.palette.colors)

    vao = _get_vao()
    draw_program = _get_program()
    empty_texture = _get_empty_texture(size)

    cursor_pos = d - view.index - 1  # TODO why?

    other_layer_alpha = 0.3 if view.show_only_current_layer or view.layer_being_switched else 1.0

    T = _get_transform(view.rotation)

    with vao, offscreen_buffer:

        gl.glEnable(gl.GL_BLEND)
        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
        gl.glViewport(0, 0, w, h)
        gl.glClearBufferfv(gl.GL_COLOR, 0, EMPTY_COLOR)

        with draw_program, drawing_texture:

            gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE, (gl.GLfloat * 16)(*T))
            gl.glUniform3f(1, *view.direction)
            gl.glUniform4fv(5, 256, colors)

            # Draw the layers below the current one
            if cursor_pos < d - 1:
                with empty_texture:
                    gl.glUniform1f(2, other_layer_alpha)
                    gl.glUniform2i(3, cursor_pos + 1, d)
                    gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)

            # Draw the current layer + overlay
            with overlay_texture:
                gl.glUniform1f(2, 1)
                gl.glUniform2i(3, cursor_pos, cursor_pos + 1)
                gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)

            # Draw the layers on top
            if cursor_pos > 0:
                with empty_texture:
                    gl.glUniform1f(2, other_layer_alpha)
                    gl.glUniform2i(3, 0, cursor_pos)
                    gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)

    return offscreen_buffer
Пример #29
0
    def blit_to_texture(self, target, level, x, y, z, internalformat=None):
        '''Draw this image to to the currently bound texture at `target`.

        If `internalformat` is specified, glTexImage is used to initialise
        the texture; otherwise, glTexSubImage is used to update a region.
        '''

        data_format = self.format
        data_pitch = abs(self._current_pitch)

        # Determine pixel format from format string
        matrix = None
        format, type = self._get_gl_format_and_type(data_format)
        if format is None:
            if (len(data_format) in (3, 4) and
                gl.gl_info.have_extension('GL_ARB_imaging')):
                # Construct a color matrix to convert to GL_RGBA
                def component_column(component):
                    try:
                        pos = 'RGBA'.index(component)
                        return [0] * pos + [1] + [0] * (3 - pos)
                    except ValueError:
                        return [0, 0, 0, 0]
                # pad to avoid index exceptions
                lookup_format = data_format + 'XXX'
                matrix = (component_column(lookup_format[0]) +
                          component_column(lookup_format[1]) +
                          component_column(lookup_format[2]) +
                          component_column(lookup_format[3]))
                format = {
                    3: gl.GL_RGB,
                    4: gl.GL_RGBA}.get(len(data_format))
                type = gl.GL_UNSIGNED_BYTE

                gl.glMatrixMode(gl.GL_COLOR)
                gl.glPushMatrix()
                gl.glLoadMatrixf((gl.GLfloat * 16)(*matrix))
            else:
                # Need to convert data to a standard form
                data_format = {
                    1: 'L',
                    2: 'LA',
                    3: 'RGB',
                    4: 'RGBA'}.get(len(data_format))
                format, type = self._get_gl_format_and_type(data_format)

        # Workaround: don't use GL_UNPACK_ROW_LENGTH
        if gl.current_context._workaround_unpack_row_length:
            data_pitch = self.width * len(data_format)

        # Get data in required format (hopefully will be the same format it's
        # already in, unless that's an obscure format, upside-down or the
        # driver is old).
        data = self._convert(data_format, data_pitch)

        if data_pitch & 0x1:
            alignment = 1
        elif data_pitch & 0x2:
            alignment = 2
        else:
            alignment = 4
        row_length = data_pitch / len(data_format)
        gl.glPushClientAttrib(gl.GL_CLIENT_PIXEL_STORE_BIT)
        gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, alignment)
        gl.glPixelStorei(gl.GL_UNPACK_ROW_LENGTH, row_length)
        self._apply_region_unpack()
        gl.glTexParameteri(target, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE)
        gl.glTexParameteri(target, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE)
        gl.glTexParameteri(target, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR)
        gl.glTexParameteri(target, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR)


        if target == gl.GL_TEXTURE_3D:
            assert not internalformat
            gl.glTexSubImage3D(target, level,
                            x, y, z,
                            self.width, self.height, 1,
                            format, type,
                            data)
        elif internalformat:
            gl.glTexImage2D(target, level,
                         internalformat,
                         self.width, self.height,
                         0,
                         format, type,
                         data)
        else:
            gl.glTexSubImage2D(target, level,
                            x, y,
                            self.width, self.height,
                            format, type,
                            data)
        gl.glPopClientAttrib()

        if matrix:
            gl.glPopMatrix()
            gl.glMatrixMode(gl.GL_MODELVIEW)
Пример #30
0
def load_texture(file_name: str, x: float=0, y: float=0,
                 width: float=0, height: float=0,
                 mirrored: bool=False,
                 flipped: bool=False,
                 scale: float=1) -> Texture:
    """
    Load image from disk and create a texture.

    Note, if the code is to load only part of the image, the given x, y
    coordinates will start with the origin (0, 0) in the upper left of the
    image. When drawing, Arcade uses (0, 0)
    in the lower left corner when drawing. Be careful about this reversal.

    For a longer explanation of why computers sometimes start in the upper
    left, see:
    http://programarcadegames.com/index.php?chapter=introduction_to_graphics&lang=en#section_5

    Args:
        :filename (str): Name of the file to that holds the texture.
        :x (float): X position of the crop area of the texture.
        :y (float): Y position of the crop area of the texture.
        :width (float): Width of the crop area of the texture.
        :height (float): Height of the crop area of the texture.
        :scale (float): Scale factor to apply on the new texture.
    Returns:
        The new texture.
    Raises:
        None

    >>> import arcade
    >>> arcade.open_window(800,600,"Drawing Example")
    >>> name = "arcade/examples/images/meteorGrey_big1.png"
    >>> texture1 = load_texture(name, 1, 1, 50, 50)
    >>> texture2 = load_texture(name, 1, 1, 50, 50)

    >>> texture = load_texture(name, 200, 1, 50, 50)
    Traceback (most recent call last):
    ...
    ValueError: Can't load texture starting at an x of 200 when the image is only 101 across.

    >>> texture = load_texture(name, 1, 50, 50, 50)
    Traceback (most recent call last):
    ...
    ValueError: Can't load texture ending at an y of 100 when the image is only 84 high.

    >>> texture = load_texture(name, 1, 150, 50, 50)
    Traceback (most recent call last):
    ...
    ValueError: Can't load texture starting at an y of 150 when the image is only 84 high.

    >>> texture = load_texture(name, 0, 0, 400, 50)
    Traceback (most recent call last):
    ...
    ValueError: Can't load texture ending at an x of 400 when the image is only 101 wide.

    >>> arcade.close_window()
    """

    # See if we already loaded this file, and we can just use a cached version.
    cache_name = "{}{}{}{}{}{}{}{}".format(file_name, x, y, width, height, scale, flipped, mirrored)
    if cache_name in load_texture.texture_cache:
        return load_texture.texture_cache[cache_name]

    source_image = PIL.Image.open(file_name)

    source_image_width, source_image_height = source_image.size

    if x != 0 or y != 0 or width != 0 or height != 0:
        if x > source_image_width:
            raise ValueError("Can't load texture starting at an x of {} "
                             "when the image is only {} across."
                             .format(x, source_image_width))
        if y > source_image_height:
            raise ValueError("Can't load texture starting at an y of {} "
                             "when the image is only {} high."
                             .format(y, source_image_height))
        if x + width > source_image_width:
            raise ValueError("Can't load texture ending at an x of {} "
                             "when the image is only {} wide."
                             .format(x + width, source_image_width))
        if y + height > source_image_height:
            raise ValueError("Can't load texture ending at an y of {} "
                             "when the image is only {} high."
                             .format(y + height, source_image_height))

        image = source_image.crop((x, y, x + width, y + height))
    else:
        image = source_image

    # image = _trim_image(image)
    if mirrored:
        image = PIL.ImageOps.mirror(image)

    if flipped:
        image = PIL.ImageOps.flip(image)

    image_width, image_height = image.size
    # image_bytes = image.convert("RGBA").tobytes("raw", "RGBA", 0, -1)

    texture = gl.GLuint(0)
    gl.glGenTextures(1, ctypes.byref(texture))

    gl.glBindTexture(gl.GL_TEXTURE_2D, texture)
    gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)

    gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S,
                       gl.GL_REPEAT)
    gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T,
                       gl.GL_REPEAT)

    gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER,
                       gl.GL_LINEAR)
    gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER,
                       gl.GL_LINEAR_MIPMAP_LINEAR)
    # glu.gluBuild2DMipmaps(gl.GL_TEXTURE_2D, gl.GL_RGBA,
    #                       image_width, image_height,
    #                       gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, image_bytes)

    image_width *= scale
    image_height *= scale

    result = Texture(texture, image_width, image_height, file_name)
    load_texture.texture_cache[cache_name] = result
    return result
Пример #31
0
def load_textures(file_name, image_location_list,
                  mirrored=False, flipped=False):
    """
    Load a set of textures off of a single image file.

    Args:
        :file_name: Name of the file.
        :image_location_list: List of image locations. Each location should be
         a list of four numbers. ``[x, y, width, height]``.
        :mirrored=False: If set to true, the image is mirrored left to right.
        :flipped=False: If set to true, the image is flipped upside down.
    Returns:
        :list: List of textures loaded.
    Raises:
        :SystemError:

    >>> import arcade
    >>> arcade.open_window("Drawing Example", 800, 600)
    >>> image_location_list = [[591, 5, 64, 93],
    ...                        [655, 10, 75, 88],
    ...                        [730, 7, 54, 91],
    ...                        [784, 3, 59, 95],
    ...                        [843, 6, 56, 92]]
    >>> texture_info_list = arcade.load_textures( \
"examples/images/character_sheet.png", image_location_list)
    >>> arcade.close_window()
    """
    source_image = PIL.Image.open(file_name)

    source_image_width, source_image_height = source_image.size
    texture_info_list = []
    for image_location in image_location_list:
        x, y, width, height = image_location

        if x > source_image_width:
            raise SystemError("Can't load texture starting at an x of {} "
                              "when the image is only {} across."
                              .format(x, source_image_width))
        if y > source_image_height:
            raise SystemError("Can't load texture starting at an y of {} "
                              "when the image is only {} high."
                              .format(y, source_image_height))
        if x + width > source_image_width:
            raise SystemError("Can't load texture ending at an x of {} "
                              "when the image is only {} wide."
                              .format(x + width, source_image_width))
        if y + height > source_image_height:
            raise SystemError("Can't load texture ending at an y of {} "
                              "when the image is only {} high."
                              .format(y + height, source_image_height))

        image = source_image.crop((x, y, x + width, y + height))
        # image = _trim_image(image)

        if mirrored:
            image = PIL.ImageOps.mirror(image)

        if flipped:
            image = PIL.ImageOps.flip(image)

        image_width, image_height = image.size
        image_bytes = image.convert("RGBA").tobytes("raw", "RGBA", 0, -1)

        texture = GL.GLuint(0)
        GL.glGenTextures(1, ctypes.byref(texture))

        GL.glBindTexture(GL.GL_TEXTURE_2D, texture)
        GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1)

        # Appveyor work-around
        appveyor = True
        if not appveyor:
            GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S,
                               GL.GL_CLAMP_TO_BORDER)
            GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T,
                               GL.GL_CLAMP_TO_BORDER)
        else:
            GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S,
                               GL.GL_REPEAT)
            GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T,
                               GL.GL_REPEAT)

        GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER,
                           GL.GL_LINEAR)
        GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER,
                           GL.GL_LINEAR_MIPMAP_LINEAR)
        GLU.gluBuild2DMipmaps(GL.GL_TEXTURE_2D, GL.GL_RGBA,
                              image_width, image_height,
                              GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, image_bytes)

        texture_info_list.append(Texture(texture, width, height))

    return texture_info_list