Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit432a235

Browse files
gh-118271: Support more options for reading/writing images in Tkinter
* Add PhotoImage.read() to read an image from a file.* Add PhotoImage.data() to get the image data.* Add background and grayscale parameters to PhotoImage.write().
1 parent7d369d4 commit432a235

File tree

4 files changed

+222
-16
lines changed

4 files changed

+222
-16
lines changed

‎Doc/whatsnew/3.13.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,12 @@ tkinter
791791
:class:`tkinter.ttk.Style`.
792792
(Contributed by Serhiy Storchaka in:gh:`68166`.)
793793

794+
* Add the:class:`!PhotoImage` methods:meth:`!read` to read
795+
an image from a file and:meth:`!data` to get the image data.
796+
Add *background* and *grayscale* parameters to:class:`!PhotoImage` method
797+
:meth:`!write`.
798+
(Contributed by Serhiy Storchaka in:gh:`118271`.)
799+
794800
traceback
795801
---------
796802

‎Lib/test/test_tkinter/test_images.py

Lines changed: 101 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,50 @@ def test_get(self):
356356
self.assertRaises(tkinter.TclError,image.get,16,15)
357357
self.assertRaises(tkinter.TclError,image.get,15,16)
358358

359+
deftest_read(self):
360+
# Due to the Tk bug https://core.tcl-lang.org/tk/tktview/1576528
361+
# the -from option does not work correctly for GIF and PNG files.
362+
# Use the PPM file for this test.
363+
testfile=support.findfile('python.ppm',subdir='tkinterdata')
364+
image=tkinter.PhotoImage(master=self.root,file=testfile)
365+
366+
image2=tkinter.PhotoImage(master=self.root)
367+
image2.read(testfile)
368+
self.assertEqual(image2.type(),'photo')
369+
self.assertEqual(image2.width(),16)
370+
self.assertEqual(image2.height(),16)
371+
self.assertEqual(image2.get(0,0),image.get(0,0))
372+
self.assertEqual(image2.get(4,6),image.get(4,6))
373+
374+
self.assertRaises(tkinter.TclError,image2.read,self.testfile,'ppm')
375+
376+
image2=tkinter.PhotoImage(master=self.root)
377+
image2.read(testfile,from_=(2,3,14,11))
378+
self.assertEqual(image2.width(),12)
379+
self.assertEqual(image2.height(),8)
380+
self.assertEqual(image2.get(0,0),image.get(2,3))
381+
self.assertEqual(image2.get(11,7),image.get(13,10))
382+
self.assertEqual(image2.get(2,4),image.get(2+2,4+3))
383+
384+
image2=tkinter.PhotoImage(master=self.root,file=testfile)
385+
self.assertEqual(image2.width(),16)
386+
self.assertEqual(image2.height(),16)
387+
image2.read(testfile,from_=(2,3,14,11),shrink=True)
388+
self.assertEqual(image2.width(),12)
389+
self.assertEqual(image2.height(),8)
390+
self.assertEqual(image2.get(0,0),image.get(2,3))
391+
self.assertEqual(image2.get(11,7),image.get(13,10))
392+
self.assertEqual(image2.get(2,4),image.get(2+2,4+3))
393+
394+
image2=tkinter.PhotoImage(master=self.root)
395+
image2.read(testfile,from_=(2,3,14,11),to=(3,6))
396+
self.assertEqual(image2.type(),'photo')
397+
self.assertEqual(image2.width(),15)
398+
self.assertEqual(image2.height(),14)
399+
self.assertEqual(image2.get(0+3,0+6),image.get(2,3))
400+
self.assertEqual(image2.get(11+3,7+6),image.get(13,10))
401+
self.assertEqual(image2.get(2+3,4+6),image.get(2+2,4+3))
402+
359403
deftest_write(self):
360404
filename=os_helper.TESTFN
361405
importlocale
@@ -367,26 +411,78 @@ def test_write(self):
367411

368412
image.write(filename)
369413
image2=tkinter.PhotoImage('::img::test2',master=self.root,
370-
format='ppm',
371-
file=filename)
414+
format='ppm',file=filename)
372415
self.assertEqual(str(image2),'::img::test2')
373416
self.assertEqual(image2.type(),'photo')
374417
self.assertEqual(image2.width(),16)
375418
self.assertEqual(image2.height(),16)
376419
self.assertEqual(image2.get(0,0),image.get(0,0))
377-
self.assertEqual(image2.get(15,8),image.get(15,8))
420+
self.assertEqual(image2.get(4,6),image.get(4,6))
378421

379422
image.write(filename,format='gif',from_coords=(4,6,6,9))
380423
image3=tkinter.PhotoImage('::img::test3',master=self.root,
381-
format='gif',
382-
file=filename)
424+
format='gif',file=filename)
383425
self.assertEqual(str(image3),'::img::test3')
384426
self.assertEqual(image3.type(),'photo')
385427
self.assertEqual(image3.width(),2)
386428
self.assertEqual(image3.height(),3)
387429
self.assertEqual(image3.get(0,0),image.get(4,6))
388430
self.assertEqual(image3.get(1,2),image.get(5,8))
389431

432+
image.write(filename,background='#ff0000')
433+
image4=tkinter.PhotoImage('::img::test4',master=self.root,
434+
format='ppm',file=filename)
435+
self.assertEqual(image4.get(0,0), (255,0,0))
436+
self.assertEqual(image4.get(4,6),image.get(4,6))
437+
438+
image.write(filename,grayscale=True)
439+
image5=tkinter.PhotoImage('::img::test5',master=self.root,
440+
format='ppm',file=filename)
441+
c=image5.get(4,6)
442+
self.assertTrue(c[0]==c[1]==c[2],c)
443+
444+
deftest_data(self):
445+
image=self.create()
446+
447+
data=image.data()
448+
self.assertIsInstance(data,tuple)
449+
forrowindata:
450+
self.assertIsInstance(row,str)
451+
self.assertEqual(data[6].split()[4],'#%02x%02x%02x'%image.get(4,6))
452+
453+
data=image.data('ppm')
454+
image2=tkinter.PhotoImage('::img::test2',master=self.root,
455+
format='ppm',data=data)
456+
self.assertEqual(str(image2),'::img::test2')
457+
self.assertEqual(image2.type(),'photo')
458+
self.assertEqual(image2.width(),16)
459+
self.assertEqual(image2.height(),16)
460+
self.assertEqual(image2.get(0,0),image.get(0,0))
461+
self.assertEqual(image2.get(4,6),image.get(4,6))
462+
463+
data=image.data(format='gif',from_=(4,6,6,9))
464+
image3=tkinter.PhotoImage('::img::test3',master=self.root,
465+
format='gif',data=data)
466+
self.assertEqual(str(image3),'::img::test3')
467+
self.assertEqual(image3.type(),'photo')
468+
self.assertEqual(image3.width(),2)
469+
self.assertEqual(image3.height(),3)
470+
self.assertEqual(image3.get(0,0),image.get(4,6))
471+
self.assertEqual(image3.get(1,2),image.get(5,8))
472+
473+
data=image.data('ppm',background='#ff0000')
474+
image4=tkinter.PhotoImage('::img::test4',master=self.root,
475+
format='ppm',data=data)
476+
self.assertEqual(image4.get(0,0), (255,0,0))
477+
self.assertEqual(image4.get(4,6),image.get(4,6))
478+
479+
data=image.data('ppm',grayscale=True)
480+
image5=tkinter.PhotoImage('::img::test5',master=self.root,
481+
format='ppm',data=data)
482+
c=image5.get(4,6)
483+
self.assertTrue(c[0]==c[1]==c[2],c)
484+
485+
390486
deftest_transparency(self):
391487
image=self.create()
392488
self.assertEqual(image.transparency_get(0,0),True)

‎Lib/tkinter/__init__.py

Lines changed: 111 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4304,17 +4304,117 @@ def put(self, data, to=None):
43044304
to=to[1:]
43054305
args=args+ ('-to',)+tuple(to)
43064306
self.tk.call(args)
4307-
# XXX read
4308-
4309-
defwrite(self,filename,format=None,from_coords=None):
4310-
"""Write image to file FILENAME in FORMAT starting from
4311-
position FROM_COORDS."""
4312-
args= (self.name,'write',filename)
4313-
ifformat:
4314-
args=args+ ('-format',format)
4315-
iffrom_coords:
4316-
args=args+ ('-from',)+tuple(from_coords)
4317-
self.tk.call(args)
4307+
4308+
defread(self,filename,format=None,*,from_=None,to=None,shrink=False):
4309+
"""Reads image data from the file named FILENAME into the image.
4310+
4311+
The FORMAT option specifies the format of the image data in the
4312+
file.
4313+
4314+
The FROM_ option specifies a rectangular sub-region of the image
4315+
file data to be copied to the destination image. It must be a tuple
4316+
or a list of 1 to 4 integers (x1, y1, x2, y2). (x1, y1) and
4317+
(x2, y2) specify diagonally opposite corners of the rectangle. If
4318+
x2 and y2 are not specified, the default value is the bottom-right
4319+
corner of the source image. The default, if this option is not
4320+
specified, is the whole of the image in the image file.
4321+
4322+
The TO option specifies the coordinates of the top-left corner of
4323+
the region of the image into which data from filename are to be
4324+
read. The default is (0, 0).
4325+
4326+
If SHRINK is true, the size of the destination image will be
4327+
reduced, if necessary, so that the region into which the image file
4328+
data are read is at the bottom-right corner of the image.
4329+
"""
4330+
options= ()
4331+
ifformatisnotNone:
4332+
options+= ('-format',format)
4333+
iffrom_isnotNone:
4334+
options+= ('-from',*from_)
4335+
ifshrink:
4336+
options+= ('-shrink',)
4337+
iftoisnotNone:
4338+
options+= ('-to',*to)
4339+
self.tk.call(self.name,'read',filename,*options)
4340+
4341+
defwrite(self,filename,format=None,from_coords=None,*,
4342+
background=None,grayscale=False):
4343+
"""Writes image data from the image to a file named FILENAME.
4344+
4345+
The FORMAT option specifies the name of the image file format
4346+
handler to be used to write the data to the file. If this option
4347+
is not given, the format is guessed from the file extension.
4348+
4349+
The FROM_COORDS option specifies a rectangular region of the image
4350+
to be written to the image file. It must be a tuple or a list of 1
4351+
to 4 integers (x1, y1, x2, y2). If only x1 and y1 are specified,
4352+
the region extends from (x1,y1) to the bottom-right corner of the
4353+
image. If all four coordinates are given, they specify diagonally
4354+
opposite corners of the rectangular region. The default, if this
4355+
option is not given, is the whole image.
4356+
4357+
If BACKGROUND is specified, the data will not contain any
4358+
transparency information. In all transparent pixels the color will
4359+
be replaced by the specified color.
4360+
4361+
If GRAYSCALE is true, the data will not contain color information.
4362+
All pixel data will be transformed into grayscale.
4363+
"""
4364+
options= ()
4365+
ifformatisnotNone:
4366+
options+= ('-format',format)
4367+
iffrom_coordsisnotNone:
4368+
options+= ('-from',*from_coords)
4369+
ifgrayscale:
4370+
options+= ('-grayscale',)
4371+
ifbackgroundisnotNone:
4372+
options+= ('-background',background)
4373+
self.tk.call(self.name,'write',filename,*options)
4374+
4375+
defdata(self,format=None,*,from_=None,
4376+
background=None,grayscale=False):
4377+
"""Returns image data.
4378+
4379+
The FORMAT option specifies the name of the image file format
4380+
handler to be used. If this option is not given, this method uses
4381+
a format that consists of a tuple (one element per row) of strings
4382+
containings space separated (one element per pixel/column) colors
4383+
in “#RRGGBB” format (where RR is a pair of hexadecimal digits for
4384+
the red channel, GG for green, and BB for blue).
4385+
4386+
The FROM_ option specifies a rectangular region of the image
4387+
to be returned. It must be a tuple or a list of 1 to 4 integers
4388+
(x1, y1, x2, y2). If only x1 and y1 are specified, the region
4389+
extends from (x1,y1) to the bottom-right corner of the image. If
4390+
all four coordinates are given, they specify diagonally opposite
4391+
corners of the rectangular region, including (x1, y1) and excluding
4392+
(x2, y2). The default, if this option is not given, is the whole
4393+
image.
4394+
4395+
If BACKGROUND is specified, the data will not contain any
4396+
transparency information. In all transparent pixels the color will
4397+
be replaced by the specified color.
4398+
4399+
If GRAYSCALE is true, the data will not contain color information.
4400+
All pixel data will be transformed into grayscale.
4401+
"""
4402+
options= ()
4403+
ifformatisnotNone:
4404+
optionsoptions+= ('-format',format)
4405+
iffrom_isnotNone:
4406+
optionsoptions+= ('-from',*from_)
4407+
ifgrayscale:
4408+
optionsoptions+= ('-grayscale',)
4409+
ifbackgroundisnotNone:
4410+
optionsoptions+= ('-background',background)
4411+
data=self.tk.call(self.name,'data',*options)
4412+
ifisinstance(data,str):# For wantobjects = 0.
4413+
ifformatisNone:
4414+
data=self.tk.splitlist(data)
4415+
else:
4416+
data=bytes(data,'latin1')
4417+
returndata
43184418

43194419
deftransparency_get(self,x,y):
43204420
"""Return True if the pixel at x,y is transparent."""
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Add the:class:`!PhotoImage` methods:meth:`~tkinter.PhotoImage.read` to
2+
read an image from a file and:meth:`~tkinter.PhotoImage.data` to get the
3+
image data. Add *background* and *grayscale* parameters to
4+
:class:`!PhotoImage` method:meth:`~tkinter.PhotoImage.write`.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp