PIL(pillow)のデータ構造ってどうなっている?
読み込んだデータは、どうなっている?
画像読み込み
from PIL import Image im = Image.open('sample20x15.bmp') im
print("画像モード = ",im.mode) print("画像サイズ(x,y) = ",im.size) print("pixel格納形式 = ",im.getbands()) print("pixel(0,0) = ",im.getpixel((0,0))) print("pixel(0,0)の形式 = ",type(im.getpixel((0,0)))) print("各チャンネルの形式 = ",type(im.getpixel((0,0))[0]),type(im.getpixel((0,0))[1]),type(im.getpixel((0,0))[2]))
画像モード = RGB
画像サイズ(x,y) = (20, 15)
pixel格納形式 = ('R', 'G', 'B')
pixel(0,0) = (200, 36, 179)
pixel(0,0)の形式 = <class 'tuple'>
各チャンネルの形式 = <class 'int'> <class 'int'> <class 'int'>
なるほど、なるほど。なら書き込みは
im.putpixel((0,0),(255,255,255)) print("[1] pixel(0,0) = ",im.getpixel((0,0))) im.putpixel((0,0),(256,256,256)) print("[2] pixel(0,0) = ",im.getpixel((0,0))) im.putpixel((0,0),(1000,-1000,0)) print("[3] pixel(0,0) = ",im.getpixel((0,0)))
[1] pixel(0,0) = (255, 255, 255)
[2] pixel(0,0) = (255, 255, 255)
[3] pixel(0,0) = (255, 0, 0)
データ形式がintとなっていたので意地悪して入力 各チャンネルR,G,Bは0~255までのuint8の範囲でそれ以外はmin,maxにまとまるという感じか
im.putpixel((20,15),(215,215,215)) print("[4] pixel(-1,0) = ",im.getpixel((20,15)))
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-4-b38936316c41> in <module>
----> 1 im.putpixel((20,15),(215,215,215))
2 print("[4] pixel(-1,0) = ",im.getpixel((20,15)))
h:\Anaconda3\lib\site-packages\PIL\Image.py in putpixel(self, xy, value)
1681 # RGB or RGBA value for a P image
1682 value = self.palette.getcolor(value)
-> 1683 return self.im.putpixel(xy, value)
1684
1685 def remap_palette(self, dest_map, source_palette=None):
IndexError: image index out of range
画像サイズが20x15なので(0~19,0~14)が範囲なのは分かる。よって(20,15)はErrorか。rangeエラーなのね
im.putpixel((-1,0),(111,111,111)) print("[5] pixel(-1,0) = ",im.getpixel((-1,0)))
[5] pixel(-1,0) = (111, 111, 111)
(-1,0)ってどこ?
print("[1] pixel(0,0) = ",im.getpixel((0,0))) print("[2] pixel(19,0) = ",im.getpixel((19,0))) print("[3] pixel(0,14) = ",im.getpixel((0,14))) print("[4] pixel(19,14) = ",im.getpixel((19,14)))
[1] pixel(0,0) = (255, 0, 0)
[2] pixel(19,0) = (111, 111, 111)
[3] pixel(0,14) = (147, 42, 197)
[4] pixel(19,14) = (49, 53, 230)
なるほど、Pythonの配列みたいにxy[-1][0]がxy[19][0]
という感じか
格納形式は?
print(type(im.tobytes())) print(im.tobytes())
<class 'bytes'>
b"\xff\x00\x00\xc5%\xb5\xc0%\xb6\xbc%\xb7\xb8&\xb9\xb3&\xbb\xad'\xbc\xa9(\xbe\xa4(\xbf\x9e)\xc2\x99)\xc4\x94*\xc5\x8e+\xc7\x89+\xc9\x84,\xcb~,\xccx-\xcfs.\xd0n.\xd2ooo\xc5$\xb4\xc1$\xb6\xbd%\xb7\xb8&\xb9\xb3'\xba\xae'\xbb\xa9(\xbe\xa4(\xbf\x9f(\xc1\x9a)\xc3\x94*\xc5\x90*\xc7\x8a+\xc8\x85+\xca\x7f,\xcdz-\xcet-\xd0n.\xd2i/\xd4c/\xd6\xc2$\xb5\xbe%\xb6\xb9&\xb8\xb5&\xba\xaf'\xbc\xaa(\xbd\xa6(\xbf\xa1(\xc1\x9c)\xc2\x96*\xc4\x90+\xc6\x8b+\xc8\x86+\xca\x80,\xcc{-\xceu-\xd0p.\xd1j.\xd4e/\xd5_0\xd7\xbe%\xb6\xba%\xb8\xb5&\xba\xb1'\xbb\xac'\xbc\xa7'\xbf\xa2)\xc0\x9c)\xc2\x97*\xc4\x91*\xc6\x8c*\xc8\x86+\xca\x81,\xcc|,\xcdv-\xcfq.\xd2k.\xd3f/\xd5a0\xd7\\0\xd8\xbb%\xb8\xb6&\xba\xb2'\xbb\xac'\xbd\xa8'\xbe\xa3(\xc0\x9d(\xc2\x98)\xc3\x92*\xc5\x8e+\xc7\x87+\xc9\x83,\xcb}-\xcdw.\xcfr-\xd0l.\xd3h/\xd5a0\xd6]1\xd8W1\xda\xb7&\xb9\xb3'\xbb\xad&\xbc\xa9'\xbe\xa4(\xc0\x9e(\xc1\x99*\xc3\x93*\xc5\x8f*\xc7\x89+\xc9\x83,\xcb~,\xccy-\xcfs.\xd0n/\xd2h.\xd4b/\xd6^0\xd7X0\xd9S1\xdb\xb4&\xba\xaf'\xbc\xaa'\xbe\xa4(\xbf\xa0)\xc2\x9a)\xc3\x95*\xc5\x8f+\xc6\x8a+\xc9\x85,\xca\x7f,\xccz-\xcet-\xd0o.\xd2j/\xd3d/\xd5_0\xd7Y0\xdaT1\xdbO2\xdd\xb0'\xbb\xab'\xbd\xa5'\xbf\xa0)\xc0\x9c)\xc2\x96)\xc4\x90*\xc6\x8c*\xc8\x85+\xca\x80,\xcc{-\xceu-\xcfp.\xd1k/\xd3e0\xd5_0\xd7[0\xd9U1\xdaP1\xddK2\xde\xab'\xbd\xa6(\xbf\xa2(\xc0\x9d)\xc2\x97)\xc4\x92*\xc6\x8c+\xc8\x87+\xc9\x82,\xcc|,\xcdw-\xd0q.\xd1l/\xd3f/\xd5a0\xd7\\1\xd9W1\xdaQ2\xdcL2\xdeG3\xdf\xa8(\xbe\xa3)\xc0\x9e)\xc2\x99)\xc4\x92*\xc6\x8d+\xc8\x88+\xc9\x82,\xcb},\xcdx-\xcfr-\xd0m.\xd3g/\xd4b/\xd6]0\xd8X1\xd9R1\xdcM2\xddH2\xdfC3\xe1\xa4(\xbf\x9e(\xc1\x99*\xc3\x94*\xc6\x8f+\xc6\x89+\xc9\x84,\xca\x7f,\xcdy-\xces.\xd0n.\xd2h/\xd4c/\xd6^0\xd8X0\xd9S2\xdbN2\xddI2\xdfD3\xe0?3\xe3\x9f(\xc1\x9a)\xc3\x95*\xc5\x90+\xc7\x8b*\xc9\x85+\xca\x7f,\xccz-\xceu.\xd0o.\xd2j.\xd4d/\xd6_0\xd7Z0\xd9T1\xdbO2\xdcJ2\xdfE2\xe0A3\xe2<4\xe3\x9c)\xc2\x96*\xc4\x91*\xc6\x8c+\xc8\x86+\xca\x81,\xcc{-\xceu-\xcfq.\xd2j/\xd3f/\xd5`0\xd7Z1\xd8U1\xdaP2\xdcK2\xdeF3\xe0B3\xe1=4\xe384\xe5\x97)\xc4\x92*\xc6\x8d+\xc7\x87,\xca\x81,\xcb|-\xcdw-\xcfq.\xd1k/\xd3f/\xd5a/\xd7\\0\xd8V1\xdbR1\xdcL2\xdeG2\xdfB3\xe1>4\xe394\xe455\xe5\x93*\xc5\x8e+\xc7\x89,\xc9\x82,\xca},\xcdx-\xcer.\xd0m.\xd2h/\xd4b/\xd6]0\xd8X0\xdaR1\xdcN1\xddI2\xdfC3\xe1?3\xe3;4\xe465\xe615\xe6"
分からんので、cls
im = Image.new('RGB',(20,15),color=(0,0,0)) print(im.tobytes().hex())
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
各ピクセルにでーたを書き込む
im.putpixel((0,0),(1,2,3)) # 左上(0,0) im.putpixel((19,14),(253,254,255)) # 右下(19,14) im.putpixel((1,0),(4,5,6)) # (0,1) x=1 im.putpixel((0,1),(7,8,9)) # (1,0) y=1 print(im.tobytes().hex())
010203040506000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070809000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fdfeff
なるほどR(0,0),G(0,0),B(0,0),R(1,0),G(1,0),B(1,0),.......R(0,1),G(0,1),B(0,1), ............. R(19,14),G(19,14),B(19,14) の順なのね
print('データのサイズ = ',len(im.tobytes()))
データのサイズ = 900
R,G,B=3 20x15 で3x20x15=900か
ならば
def getBytes2pixel(im,xy): x,y = xy w,h = im.size dat = im.tobytes() print(xy," = ",dat[3*(w*y+x)],dat[3*(w*y+x)+1],dat[3*(w*y+x)+2]) getBytes2pixel(im,(0,0)) getBytes2pixel(im,(19,14)) getBytes2pixel(im,(1,0)) getBytes2pixel(im,(0,1))
(0, 0) = 1 2 3
(19, 14) = 253 254 255
(1, 0) = 4 5 6
(0, 1) = 7 8 9
まとめると
スクリーンXY座標(左上原点)で(0,0)(1,0)(2,0)(3,0)...(19,0)(0,1)(1,1)(2,1).....(19,13)(19,14)
の順に並んでいて、アクセスはaddress = 3*(w*y+1)
でR=address[0], G=address[1], B=address[2]
な感じなのね
パレットカラーだと
p_im = im.quantize() # 256色インデックスカラー化 print("画像モード = ",p_im.mode) print("画像サイズ(x,y) = ",p_im.size) print("pixel格納形式 = ",p_im.getbands()) print("データサイス = ",len(p_im.tobytes())) print(p_im.tobytes().hex())
画像モード = P
画像サイズ(x,y) = (20, 15)
pixel格納形式 = ('P',)
データサイス = 300
030204040404040404040404040404040404040401040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040400
P*h*w
なので1*20*15=300
でピクセルの並びは同じ