程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python tips teach you to draw in Excel in Python

編輯:Python

I've seen a lot of headlines before , Say which country someone has insisted on self-study for many years excel Drawing a picture , The results are stunning . I admire their patience very much . But as a programmer , Naturally, I have to challenge myself . This demand , We can finish it in ten minutes !

The basic idea

The basic idea to realize this requirement is to read the color value of each pixel of the picture , And then to excel Each cell in the is filled with color . So the main use is PIL、openpyxl These two libraries .

PIL Use

PIL yes Python It is a very common library for image processing , The function is also very powerful , All you need here is PIL A small part of the functions in .

from PIL import Image
img = Image.open(img_path) # Read the picture
width, height = img.size # Get image size
r, g, b = img.getpixel((w - 1, h - 1)) # Get pixel color value 

Image.open() yes PIL Function to open a picture inside , Support multiple picture types img_path Is the picture path , Can be a relative path , It could be an absolute path img.size Is to get pictures size attribute , Contains the width and height of the picture img.getpixel() Is a function to get the color value of the picture , You need to pass in a tuple or list, The value is the pixel coordinate xy

openpyxl Use

openpyxl Almost Python The most fully functional operation in excel The library of files , Only a small part of its functions are needed here .

import openpyxl
from openpyxl.styles import fills
workbook = openpyxl.Workbook()
worksheet = workbook.active
cell.fill = fills.PatternFill(fill_type="solid", fgColor=hex_rgb)
workbook.save(out_file)

openpyxl.Workbook() Create a new one excel file workbook.active Activate a worksheet cell.fill = fills.PatternFill(fill_type="solid", fgColor=hex_rgb) Fill a cell ,fill_type="solid" Is the fill type ,fgColor=hex_rgb Is the fill color workbook.save() Save the file , You need to pass in the file name to save

Write a piece of code

The core that needs to be used to write this drawing requirement is the one described above PIL Follow openpyxl Several uses of . But when actually writing , There will be other problems , such as :

1.getpixel() The color value obtained is rgb Decimal , but fills.PatternFill Inside fgColor` The color value received by the parameter is a hexadecimal value

This problem is actually the conversion of decimal to hexadecimal , It's easy to solve

def int_to_16(num):
num1 = hex(num).replace('0x', '')
num2 = num1 if len(num1) > 1 else '0' + num1 # When there is only one digit, fill in zero in front
return num2

2.excel The default cell is rectangular , Change to square so that the picture will not deform

if h == 1:
_w = cell.column
_h = cell.col_idx
# Adjust column width
worksheet.column_dimensions[_w].width = 1
# Adjust row height
worksheet.row_dimensions[h].height = 6
 There is a double for loop , The outer layer is `width`, The inner layer is `height`, Is a column of fill colors , So judge `if h == 1`, Avoid adjusting column width multiple times .

3.excel A limited number of styles are supported

This is a serious problem . If you directly operate the high-definition large picture , The last output excel When the file is opened , It may prompt us that there is a problem with the file , Need automatic repair .

But when it's repaired , You will find that all the colors filled have disappeared !

Error message

At first, I thought it was because too many rows and columns were used .

After searching the information, we found that ,13 edition excel The number of lines supported is 1048576, The maximum number of columns is 16384, The number of cells we use is far from the limit .

After changing the picture 、 Replace excel edition , Modify the code and other insufficient tests , To find the cause of the problem .

It's because ,excel The original form of is composed of multiple xml file , The fill colors are stored in a style.xml In the document , When the file is too large, an error will be reported when opening .

So in order to solve this problem , There are two solutions , The first is to reduce the picture , The second is to reduce the color of the picture . When reducing the picture, it has the function of reducing the color of the picture , The method of reducing the color of the picture can be grayed out 、 Binarization and other methods .

On the whole , Is the need to control the number of colors * Number of cells < threshold (3300w about ).

MAX_WIDTH = 300
MAX_HEIGHT = 300
def resize(img):
w, h = img.size
if w > MAX_WIDTH:
h = MAX_WIDTH / w * h
w = MAX_WIDTH
if h > MAX_HEIGHT:
w = MAX_HEIGHT / h * w
h = MAX_HEIGHT
return img.resize((int(w), int(h)), Image.ANTIALIAS)

Final effect

The sky is full of people , Open the last output excel You can already see the effect !

So , Everything works Python Problem solved , In the end Python To solve .

All the code

# draw_excel.py
from PIL import Image
import openpyxl
from openpyxl.styles import fills
import os
MAX_WIDTH = 300
MAX_HEIGHT = 300
def resize(img):
w, h = img.size
if w > MAX_WIDTH:
h = MAX_WIDTH / w * h
w = MAX_WIDTH
if h > MAX_HEIGHT:
w = MAX_HEIGHT / h * w
h = MAX_HEIGHT
return img.resize((int(w), int(h)), Image.ANTIALIAS)
def int_to_16(num):
num1 = hex(num).replace('0x', '')
num2 = num1 if len(num1) > 1 else '0' + num1
return num2
def draw_jpg(img_path):
img_pic = resize(Image.open(img_path))
img_name = os.path.basename(img_path)
out_file = './result/' + img_name.split('.')[0] + '.xlsx'
if os.path.exists(out_file):
os.remove(out_file)
workbook = openpyxl.Workbook()
worksheet = workbook.active
width, height = img_pic.size
for w in range(1, width + 1):
for h in range(1, height + 1):
if img_pic.mode == 'RGB':
r, g, b = img_pic.getpixel((w - 1, h - 1))
elif img_pic.mode == 'RGBA':
r, g, b, a = img_pic.getpixel((w - 1, h - 1))
hex_rgb = int_to_16(r) + int_to_16(g) + int_to_16(b)
cell = worksheet.cell(column=w, row=h)
if h == 1:
_w = cell.column
_h = cell.col_idx
# Adjust column width
worksheet.column_dimensions[_w].width = 1
# Adjust row height
worksheet.row_dimensions[h].height = 6
cell.fill = fills.PatternFill(fill_type="solid", fgColor=hex_rgb)
print('write in:', w, ' | all:', width + 1)
print('saving...')
workbook.save(out_file)
print('success!')
if __name__ == '__main__':
draw_jpg('mona-lisa.jpg')

attach =

The above said Number of colors * Number of cells < threshold (2564 about ) When , There may be doubts , This 2564 How did you get it .

This, of course, is what I got from the test .

Since there are two variables: the number of colors and the number of cells , So naturally, there should be more than two test methods . A number of observed colors , The number of observation cells .

But I only did one test of the number of colors here .( The biggest reason is to generate tens of thousands of lines * Tens of thousands of trains excel It's been a long time ... lazy ...)

 count = 0
MAX_WIDTH = 255
for w in range(1, MAX_WIDTH + 1):
for h in range(1, MAX_WIDTH + 1):
cell = worksheet.cell(column=w, row=h)
if h == 1:
_w = cell.column
_h = cell.col_idx
# Adjust column width
worksheet.column_dimensions[_w].width = 1
# Adjust row height
worksheet.row_dimensions[h].height = 6
if count < 255 ** 3:
back = int_to_16(num=count)
back = '0' * (6 - len(back)) + back
else:
back = ''.join([int_to_16(random.randint(0, 255)) for _ in range(3)])
cell.fill = fills.PatternFill(fill_type="solid", fgColor=back)
count += 1

count Is the variable that records the color , Make sure that each color does not repeat , But at present, computers RGB The color represented is at most 256^3 Kind of Through adjustment MAX_WIDTH To test excel The threshold of

Finally, the generated test excel as follows :

... It's a little nice .!??

Last

Due to limited energy ,~ lazy ~, Limited ability ~ food ~, So there is no test for a single color , There may also be other methods that do not have the limit of this threshold .


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved