mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-04 19:10:09 +01:00
Add the raw bitmap access classes and various bits of magic.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@72356 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
4
TODO.txt
4
TODO.txt
@@ -112,9 +112,6 @@ other dev stuff
|
||||
created/used that should not be done before there is an application
|
||||
object.
|
||||
|
||||
* Should the functions created for things like addCppMethod be
|
||||
marked static? How about using inline?
|
||||
|
||||
* Move PyEvent and PyCommandEvent classes to an etg script and build them
|
||||
using extractor objects so they will be seen by the document generator and
|
||||
others.
|
||||
@@ -130,7 +127,6 @@ other dev stuff
|
||||
* PseudoDC (not actually an ETG script, probably a .sip)
|
||||
* msgout
|
||||
* quantize
|
||||
* rawbmp
|
||||
* richmsgdlg (requires wrappers for wxGenericMessageDialog)
|
||||
* valgen (No. It could probably be reimplemented in Python easier than wrapping)
|
||||
* valnum (No. Ditto)
|
||||
|
||||
@@ -25,8 +25,6 @@ Functions and Classes Modifications
|
||||
AboutBox :func:`adv.AboutBox <AboutBox>`
|
||||
AboutDialogInfo :class:`adv.AboutDialogInfo`
|
||||
AcceleratorEntry_Create ``MISSING``
|
||||
AlphaPixelData ``MISSING``
|
||||
AlphaPixelData_Accessor ``MISSING``
|
||||
ANIHandler ``MISSING``
|
||||
App_CleanUp ``MISSING``
|
||||
ArtProvider_Delete :meth:`ArtProvider.Delete`
|
||||
@@ -307,8 +305,6 @@ MutexGuiLeave ``MISSING``
|
||||
MutexGuiLocker ``MISSING``
|
||||
NamedColour :class:`Colour`
|
||||
NativeEncodingInfo ``MISSING``
|
||||
NativePixelData ``MISSING``
|
||||
NativePixelData_Accessor ``MISSING``
|
||||
NcPaintEvent ``MISSING``
|
||||
Notebook_GetClassDefaultAttributes :meth:`Notebook.GetClassDefaultAttributes <Window.GetClassDefaultAttributes>`
|
||||
NotebookEvent :class:`BookCtrlEvent`
|
||||
@@ -318,7 +314,6 @@ NullFileTypeInfo ``MISSING``
|
||||
NumberEntryDialog ``MISSING``
|
||||
Panel_GetClassDefaultAttributes :meth:`Panel.GetClassDefaultAttributes <Window.GetClassDefaultAttributes>`
|
||||
PCXHandler ``MISSING``
|
||||
PixelDataBase ``MISSING``
|
||||
PlatformInformation_GetOperatingSystemDirectory :meth:`PlatformInfo.GetOperatingSystemDirectory`
|
||||
PNGHandler ``MISSING``
|
||||
PNMHandler ``MISSING``
|
||||
|
||||
@@ -87,6 +87,7 @@ INCLUDES = [ # base and core stuff
|
||||
'imaglist',
|
||||
'overlay',
|
||||
'renderer',
|
||||
'rawbmp',
|
||||
|
||||
# more core
|
||||
'accel',
|
||||
|
||||
292
etg/rawbmp.py
Normal file
292
etg/rawbmp.py
Normal file
@@ -0,0 +1,292 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# Name: etg/rawbmp.py
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# Created: 14-Aug-2012
|
||||
# Copyright: (c) 2012 by Total Control Software
|
||||
# License: wxWindows License
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
import etgtools
|
||||
import etgtools.tweaker_tools as tools
|
||||
from etgtools import (ClassDef, MethodDef, ParamDef, TypedefDef, WigCode,
|
||||
CppMethodDef, PyMethodDef)
|
||||
|
||||
PACKAGE = "wx"
|
||||
MODULE = "_core"
|
||||
NAME = "rawbmp" # Base name of the file to generate to for this script
|
||||
DOCSTRING = ""
|
||||
|
||||
# The classes and/or the basename of the Doxygen XML files to be processed by
|
||||
# this script.
|
||||
ITEMS = [ ]
|
||||
|
||||
# NOTE: It is intentional that there are no items in the ITEMS list. This is
|
||||
# because we will not be loading any classes from the doxygen XML files here,
|
||||
# but rather will be constructing the extractor objects here in this module
|
||||
# instead.
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def run():
|
||||
# Parse the XML file(s) building a collection of Extractor objects
|
||||
module = etgtools.ModuleDef(PACKAGE, MODULE, NAME, DOCSTRING)
|
||||
etgtools.parseDoxyXML(module, ITEMS)
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
# Tweak the parsed meta objects in the module object as needed for
|
||||
# customizing the generated code and docstrings.
|
||||
|
||||
module.addHeaderCode("#include <wx/rawbmp.h>")
|
||||
|
||||
addPixelDataBaseClass(module)
|
||||
|
||||
addPixelDataClass(module, 'wxNativePixelData', 'wxBitmap', bpp=24,
|
||||
doc="""\
|
||||
NativePixelData: A class providing direct access to a wx.Bitmap's
|
||||
internal data without alpha channel (RGB).
|
||||
""")
|
||||
addPixelDataClass(module, 'wxAlphaPixelData', 'wxBitmap', bpp=32,
|
||||
doc="""\
|
||||
AlphaPixelData: A class providing direct access to a wx.Bitmap's
|
||||
internal data including the alpha channel (RGBA).
|
||||
""")
|
||||
#addPixelDataClass(module, 'wxImagePixelData', 'wxImage', bpp=32,
|
||||
# doc="""\
|
||||
# ImagePixelData: A class providing direct access to a wx.Image's
|
||||
# internal data usign the same api as the other PixelData classes.
|
||||
# """)
|
||||
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
tools.doCommonTweaks(module)
|
||||
tools.runGenerators(module)
|
||||
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def addPixelDataBaseClass(module):
|
||||
# wxPixelDataBase is the common base class of the other pixel data classes
|
||||
cls = ClassDef(name='wxPixelDataBase', items=[
|
||||
MethodDef(
|
||||
name='wxPixelDataBase', isCtor=True, protection='protected'),
|
||||
MethodDef(
|
||||
type='wxPoint', name='GetOrigin', isConst=True,
|
||||
briefDoc="Return the origin of the area this pixel data represents."),
|
||||
MethodDef(
|
||||
type='int', name='GetWidth', isConst=True,
|
||||
briefDoc="Return the width of the area this pixel data represents."),
|
||||
MethodDef(
|
||||
type='int', name='GetHeight', isConst=True,
|
||||
briefDoc="Return the height of the area this pixel data represents."),
|
||||
MethodDef(
|
||||
type='wxSize', name='GetSize', isConst=True,
|
||||
briefDoc="Return the size of the area this pixel data represents."),
|
||||
MethodDef(
|
||||
type='int', name='GetRowStride', isConst=True,
|
||||
briefDoc="Returns the distance between the start of one row to the start of the next row."),
|
||||
])
|
||||
|
||||
# TODO: Try to remember why I chose to do it this way instead of direclty
|
||||
# returning an instance of the Iterator and giving it the methods needed
|
||||
# to be a Python iterator...
|
||||
|
||||
# TODO: Determine how much of a performance difference not using the
|
||||
# PixelFacade class would make. Not using the __iter__ makes about 0.02
|
||||
# seconds difference per 100x100 bmp in samples/rawbmp/rawbmp1.py...
|
||||
|
||||
cls.addPyMethod('__iter__', '(self)',
|
||||
doc="""\
|
||||
Create and return an iterator/generator object for traversing
|
||||
this pixel data object.
|
||||
""",
|
||||
body="""\
|
||||
width = self.GetWidth()
|
||||
height = self.GetHeight()
|
||||
pixels = self.GetPixels() # this is the C++ iterator
|
||||
|
||||
# This class is a facade over the pixels object (using the one
|
||||
# in the enclosing scope) that only allows Get() and Set() to
|
||||
# be called.
|
||||
class PixelFacade(object):
|
||||
def Get(self):
|
||||
return pixels.Get()
|
||||
def Set(self, *args, **kw):
|
||||
return pixels.Set(*args, **kw)
|
||||
def __str__(self):
|
||||
return str(self.Get())
|
||||
def __repr__(self):
|
||||
return 'pixel(%d,%d): %s' % (x,y,self.Get())
|
||||
X = property(lambda self: x)
|
||||
Y = property(lambda self: y)
|
||||
|
||||
pf = PixelFacade()
|
||||
for y in xrange(height):
|
||||
pixels.MoveTo(self, 0, y)
|
||||
for x in xrange(width):
|
||||
# We always generate the same pf instance, but it
|
||||
# accesses the pixels object which we use to iterate
|
||||
# over the pixel buffer.
|
||||
yield pf
|
||||
pixels.nextPixel()
|
||||
""")
|
||||
|
||||
module.addItem(cls)
|
||||
|
||||
|
||||
|
||||
def addPixelDataClass(module, pd, img, bpp, doc=""):
|
||||
# This function creates a ClassDef for a PixelData class defined in C++.
|
||||
# The C++ versions are template instantiations, so this allows this
|
||||
# create nearly identical classes and just substitute the image class
|
||||
# name and the pixel data class name.
|
||||
|
||||
#itrName = 'Iterator'
|
||||
|
||||
itrName = pd + '_Accessor'
|
||||
module.addHeaderCode('typedef %s::Iterator %s;' % (pd, itrName))
|
||||
|
||||
|
||||
# First generate the class and methods for the PixelData class
|
||||
cls = ClassDef(name=pd, bases=['wxPixelDataBase'], briefDoc=doc, items=[
|
||||
MethodDef(name=pd, isCtor=True, items=[
|
||||
ParamDef(type=img+'&', name='bmp')],
|
||||
overloads=[
|
||||
MethodDef(name=pd, isCtor=True, items=[
|
||||
ParamDef(type=img+'&', name='bmp'),
|
||||
ParamDef(type='const wxRect&', name='rect')]),
|
||||
|
||||
MethodDef(name=pd, isCtor=True, items=[
|
||||
ParamDef(type=img+'&', name='bmp'),
|
||||
ParamDef(type='const wxPoint&', name='pt' ),
|
||||
ParamDef(type='const wxSize&', name='sz' )]),
|
||||
]),
|
||||
|
||||
MethodDef(name='~'+pd, isDtor=True),
|
||||
|
||||
MethodDef(type=itrName, name='GetPixels', isConst=True),
|
||||
|
||||
CppMethodDef('int', '__nonzero__', '()',
|
||||
body="""\
|
||||
return (int)self->operator bool();
|
||||
"""),
|
||||
])
|
||||
|
||||
# add this class to the module
|
||||
module.addItem(cls)
|
||||
|
||||
|
||||
# Now do the class and methods for its C++ Iterator class
|
||||
icls = ClassDef(name=itrName, items=[
|
||||
# Constructors
|
||||
MethodDef(name=itrName, isCtor=True, items=[
|
||||
ParamDef(name='data', type=pd+'&')],
|
||||
overloads=[
|
||||
MethodDef(name=itrName, isCtor=True, items=[
|
||||
ParamDef(name='bmp', type=img+'&'),
|
||||
ParamDef(name='data', type=pd+'&')]),
|
||||
MethodDef(name=itrName, isCtor=True)]),
|
||||
|
||||
MethodDef(name='~'+itrName, isDtor=True),
|
||||
|
||||
# Methods
|
||||
MethodDef(type='void', name='Reset', items=[
|
||||
ParamDef(type='const %s&' % pd, name='data')]),
|
||||
|
||||
MethodDef(type='bool', name='IsOk', isConst=True),
|
||||
|
||||
CppMethodDef('int', '__nonzero__', '()',
|
||||
body="""\
|
||||
return (int)self->IsOk();
|
||||
"""),
|
||||
|
||||
MethodDef(type='void', name='Offset', items=[
|
||||
ParamDef(type='const %s&' % pd, name='data'),
|
||||
ParamDef(type='int', name='x'),
|
||||
ParamDef(type='int', name='y')]),
|
||||
|
||||
MethodDef(type='void', name='OffsetX', items=[
|
||||
ParamDef(type='const %s&' % pd, name='data'),
|
||||
ParamDef(type='int', name='x')]),
|
||||
|
||||
MethodDef(type='void', name='OffsetY', items=[
|
||||
ParamDef(type='const %s&' % pd, name='data'),
|
||||
ParamDef(type='int', name='y')]),
|
||||
|
||||
MethodDef(type='void', name='MoveTo', items=[
|
||||
ParamDef(type='const %s&' % pd, name='data'),
|
||||
ParamDef(type='int', name='x'),
|
||||
ParamDef(type='int', name='y')]),
|
||||
|
||||
# should this return the iterator?
|
||||
CppMethodDef('void', 'nextPixel', '()', body="++(*self);"),
|
||||
|
||||
# NOTE: For now I'm not wrapping the Red, Green, Blue and Alpha
|
||||
# functions because I can't hide the premultiplying needed on wxMSW
|
||||
# if only the individual components are wrapped, plus it would mean 3
|
||||
# or 4 trips per pixel from Python to C++ instead of just one.
|
||||
# Instead I'll add the Set and Get functions below and put the
|
||||
# premultiplying in there.
|
||||
])
|
||||
|
||||
assert bpp in [24, 32]
|
||||
|
||||
if bpp == 24:
|
||||
icls.addCppMethod('void', 'Set', '(byte red, byte green, byte blue)',
|
||||
body="""\
|
||||
self->Red() = red;
|
||||
self->Green() = green;
|
||||
self->Blue() = blue;
|
||||
""")
|
||||
|
||||
icls.addCppMethod('PyObject*', 'Get', '()',
|
||||
body="""\
|
||||
wxPyThreadBlocker blocker;
|
||||
PyObject* rv = PyTuple_New(3);
|
||||
PyTuple_SetItem(rv, 0, PyInt_FromLong(self->Red()));
|
||||
PyTuple_SetItem(rv, 1, PyInt_FromLong(self->Green()));
|
||||
PyTuple_SetItem(rv, 2, PyInt_FromLong(self->Blue()));
|
||||
return rv;
|
||||
""")
|
||||
|
||||
elif bpp == 32:
|
||||
icls.addCppMethod('void', 'Set', '(byte red, byte green, byte blue, byte alpha)',
|
||||
body="""\
|
||||
self->Red() = wxPy_premultiply(red, alpha);
|
||||
self->Green() = wxPy_premultiply(green, alpha);
|
||||
self->Blue() = wxPy_premultiply(blue, alpha);
|
||||
self->Alpha() = alpha;
|
||||
""")
|
||||
|
||||
icls.addCppMethod('PyObject*', 'Get', '()',
|
||||
body="""\
|
||||
wxPyThreadBlocker blocker;
|
||||
PyObject* rv = PyTuple_New(4);
|
||||
int red = self->Red();
|
||||
int green = self->Green();
|
||||
int blue = self->Blue();
|
||||
int alpha = self->Alpha();
|
||||
|
||||
PyTuple_SetItem(rv, 0, PyInt_FromLong( wxPy_unpremultiply(red, alpha) ));
|
||||
PyTuple_SetItem(rv, 1, PyInt_FromLong( wxPy_unpremultiply(green, alpha) ));
|
||||
PyTuple_SetItem(rv, 2, PyInt_FromLong( wxPy_unpremultiply(blue, alpha) ));
|
||||
PyTuple_SetItem(rv, 3, PyInt_FromLong( alpha ));
|
||||
return rv;
|
||||
""")
|
||||
|
||||
|
||||
|
||||
# add it to the main pixel data class as a nested class
|
||||
#cls.insertItem(0, icls)
|
||||
|
||||
# It's really a nested class, but we're pretending that it isn't (see the
|
||||
# typedef above) so add it at the module level instead.
|
||||
module.addItem(icls)
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
|
||||
163
samples/rawbmp/rawbmp1.py
Normal file
163
samples/rawbmp/rawbmp1.py
Normal file
@@ -0,0 +1,163 @@
|
||||
|
||||
import sys
|
||||
import wx
|
||||
|
||||
# use the numpy code instead of the raw access code for comparison
|
||||
USE_NUMPY = False
|
||||
|
||||
# time the execution of making a bitmap?
|
||||
TIMEIT = False
|
||||
PASSES = 100
|
||||
|
||||
# how big to make the bitmaps
|
||||
DIM = 100
|
||||
|
||||
# should we use a wx.GraphicsContext for painting?
|
||||
TEST_GC = False
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# attempt to import a numeric module if requested to
|
||||
|
||||
if USE_NUMPY:
|
||||
try:
|
||||
import numpy
|
||||
def makeByteArray(shape):
|
||||
return numpy.empty(shape, numpy.uint8)
|
||||
numtype = 'numpy'
|
||||
except ImportError:
|
||||
USE_NUMPY = False
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
class TestPanel(wx.Panel):
|
||||
def __init__(self, parent, log):
|
||||
self.log = log
|
||||
wx.Panel.__init__(self, parent, -1)
|
||||
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
||||
|
||||
if TIMEIT:
|
||||
import timeit
|
||||
timeit.s = self # Put self in timeit's global namespace as
|
||||
# 's' so it can be found in the code
|
||||
# snippets being tested.
|
||||
if not USE_NUMPY:
|
||||
t = timeit.Timer("bmp = s.MakeBitmap(10, 20, 30)")
|
||||
else:
|
||||
t = timeit.Timer("bmp = s.MakeBitmap2(10, 20, 30)")
|
||||
log.write("Timing...\n")
|
||||
num = PASSES
|
||||
tm = t.timeit(num)
|
||||
log.write("%d passes creating %dx%d images in %f seconds\n"
|
||||
"\t%f seconds per pass " % (num, DIM,DIM, tm, tm/num))
|
||||
|
||||
if not USE_NUMPY:
|
||||
log.write("using raw access\n")
|
||||
self.redBmp = self.MakeBitmap(178, 34, 34)
|
||||
self.greenBmp = self.MakeBitmap( 35, 142, 35)
|
||||
self.blueBmp = self.MakeBitmap( 0, 0, 139)
|
||||
else:
|
||||
log.write("using %s\n" % numtype)
|
||||
self.redBmp = self.MakeBitmap2(178, 34, 34)
|
||||
self.greenBmp = self.MakeBitmap2( 35, 142, 35)
|
||||
self.blueBmp = self.MakeBitmap2( 0, 0, 139)
|
||||
|
||||
|
||||
def OnPaint(self, evt):
|
||||
dc = wx.PaintDC(self)
|
||||
if not TEST_GC:
|
||||
dc.DrawBitmap(self.redBmp, 50, 50, True)
|
||||
dc.DrawBitmap(self.greenBmp, 110, 110, True)
|
||||
dc.DrawBitmap(self.blueBmp, 170, 50, True)
|
||||
self.log.write("using wx.DC\n")
|
||||
else:
|
||||
gc = wx.GraphicsContext.Create(dc)
|
||||
gc.DrawBitmap(self.redBmp, 50, 50, DIM,DIM)
|
||||
gc.DrawBitmap(self.greenBmp, 110, 110, DIM,DIM)
|
||||
gc.DrawBitmap(self.blueBmp, 170, 50, DIM,DIM)
|
||||
self.log.write("using wx.GraphicsContext\n")
|
||||
|
||||
|
||||
def MakeBitmap(self, red, green, blue, alpha=128):
|
||||
# Create the bitmap that we will stuff pixel values into using
|
||||
# the raw bitmap access classes.
|
||||
bmp = wx.Bitmap(DIM, DIM, 32)
|
||||
|
||||
# Create an object that facilitates access to the bitmap's
|
||||
# pixel buffer
|
||||
pixelData = wx.AlphaPixelData(bmp)
|
||||
if not pixelData:
|
||||
raise RuntimeError("Failed to gain raw access to bitmap data.")
|
||||
|
||||
# We have two ways to access each pixel, first we'll use an
|
||||
# iterator to set every pixel to the colour and alpha values
|
||||
# passed in.
|
||||
for pixel in pixelData:
|
||||
pixel.Set(red, green, blue, alpha)
|
||||
|
||||
# This block of code is another way to do the same as above,
|
||||
# but with the accessor interface instead of the Python
|
||||
# iterator. It is a bit faster than the above because it
|
||||
# avoids the iterator/generator magic, but it is not nearly as
|
||||
# 'clean' looking ;-)
|
||||
#pixels = pixelData.GetPixels()
|
||||
#for y in xrange(DIM):
|
||||
# pixels.MoveTo(pixelData, 0, y)
|
||||
# for x in xrange(DIM):
|
||||
# pixels.Set(red, green, blue, alpha)
|
||||
# pixels.nextPixel()
|
||||
|
||||
|
||||
|
||||
# Next we'll use the pixel accessor to set the border pixels
|
||||
# to be fully opaque
|
||||
pixels = pixelData.GetPixels()
|
||||
for x in xrange(DIM):
|
||||
pixels.MoveTo(pixelData, x, 0)
|
||||
pixels.Set(red, green, blue, wx.ALPHA_OPAQUE)
|
||||
pixels.MoveTo(pixelData, x, DIM-1)
|
||||
pixels.Set(red, green, blue, wx.ALPHA_OPAQUE)
|
||||
for y in xrange(DIM):
|
||||
pixels.MoveTo(pixelData, 0, y)
|
||||
pixels.Set(red, green, blue, wx.ALPHA_OPAQUE)
|
||||
pixels.MoveTo(pixelData, DIM-1, y)
|
||||
pixels.Set(red, green, blue, wx.ALPHA_OPAQUE)
|
||||
|
||||
return bmp
|
||||
|
||||
|
||||
def MakeBitmap2(self, red, green, blue, alpha=128):
|
||||
# Make an array of bytes that is DIM*DIM in size, with enough
|
||||
# slots for each pixel to have a RGB and A value
|
||||
arr = makeByteArray( (DIM,DIM, 4) )
|
||||
|
||||
# just some indexes to keep track of which byte is which
|
||||
R, G, B, A = range(4)
|
||||
|
||||
# initialize all pixel values to the values passed in
|
||||
arr[:,:,R] = red
|
||||
arr[:,:,G] = green
|
||||
arr[:,:,B] = blue
|
||||
arr[:,:,A] = alpha
|
||||
|
||||
# Set the alpha for the border pixels to be fully opaque
|
||||
arr[0, 0:DIM, A] = wx.ALPHA_OPAQUE # first row
|
||||
arr[DIM-1, 0:DIM, A] = wx.ALPHA_OPAQUE # last row
|
||||
arr[0:DIM, 0, A] = wx.ALPHA_OPAQUE # first col
|
||||
arr[0:DIM, DIM-1, A] = wx.ALPHA_OPAQUE # last col
|
||||
|
||||
# finally, use the array to create a bitmap
|
||||
bmp = wx.Bitmap.FromBufferRGBA(DIM, DIM, arr)
|
||||
return bmp
|
||||
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = wx.App()
|
||||
frm = wx.Frame(None, title="RawBitmap Test", size=(500,350))
|
||||
pnl = TestPanel(frm, sys.stdout)
|
||||
frm.Show()
|
||||
app.MainLoop()
|
||||
|
||||
36
unittests/test_rawbmp.py
Normal file
36
unittests/test_rawbmp.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import imp_unittest, unittest
|
||||
import wtc
|
||||
import wx
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
class rawbmp_Tests(wtc.WidgetTestCase):
|
||||
|
||||
def test_rawbmp1(self):
|
||||
DIM = 100
|
||||
red = 10
|
||||
green = 20
|
||||
blue = 30
|
||||
alpha = 128
|
||||
|
||||
bmp = wx.Bitmap(DIM, DIM, 32)
|
||||
pixelData = wx.AlphaPixelData(bmp)
|
||||
self.assertTrue(pixelData)
|
||||
|
||||
# Test using the __iter__ generator
|
||||
for pixel in pixelData:
|
||||
pixel.Set(red, green, blue, alpha)
|
||||
|
||||
# This block of code is another way to do the same as above
|
||||
pixels = pixelData.GetPixels()
|
||||
for y in xrange(DIM):
|
||||
pixels.MoveTo(pixelData, 0, y)
|
||||
for x in xrange(DIM):
|
||||
pixels.Set(red, green, blue, alpha)
|
||||
pixels.nextPixel()
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user