def png(self, file, scale=1, module_color=(0, 0, 0, 255), background=(255, 255, 255, 255), quiet_zone=4): """This method writes the QR code out as an PNG image. The resulting PNG has a bit depth of 1. The file parameter is used to specify where to write the image to. It can either be an writable stream or a file path. .. note:: This method depends on the pypng module to actually create the PNG file. This method will write the given *file* out as a PNG file. The file can be either a string file path, or a writable stream. The file will not be automatically closed if a stream is given. The *scale* parameter sets how large to draw a single module. By default one pixel is used to draw a single module. This may make the code too small to be read efficiently. Increasing the scale will make the code larger. Only integer scales are usable. This method will attempt to coerce the parameter into an integer (e.g. 2.5 will become 2, and '3' will become 3). You can use the :py:meth:`get_png_size` method to calculate the actual pixel size of the resulting PNG image. The *module_color* parameter sets what color to use for the encoded modules (the black part on most QR codes). The *background* parameter sets what color to use for the background (the white part on most QR codes). If either parameter is set, then both must be set or a ValueError is raised. Colors should be specified as either a list or a tuple of length 3 or 4. The components of the list must be integers between 0 and 255. The first three member give the RGB color. The fourth member gives the alpha component, where 0 is transparent and 255 is opaque. Note, many color combinations are unreadable by scanners, so be judicious. The *quiet_zone* parameter sets how wide the quiet zone around the code should be. According to the standard this should be 4 modules. It is left settable because such a wide quiet zone is unnecessary in many applications where the QR code is not being printed. Example: >>> code = pyqrcode.create('Are you suggesting coconuts migrate?') >>> code.png('swallow.png', scale=5) >>> code.png('swallow.png', scale=5, module_color=(0x66, 0x33, 0x0), #Dark brown background=(0xff, 0xff, 0xff, 0x88)) #50% transparent white """ builder._png(self.code, self.version, file, scale, module_color, background, quiet_zone)
def png(self, file, scale=1, module_color=(0, 0, 0, 255), background=(255, 255, 255, 255), quiet_zone=4): """这个实例方法是把二维码写成一个 PNG 图片文件。 作为 PNG 结果会有1个深度。 其中 `file` 位置参数是用来描述图片存储到哪里,参数值即可以是 一种可写的流数据,也可以是一个文件路径。 .. note:: 这个方法的使用要依赖 `pypng` 模块,所以要安装模块后才能真正建立 PNG 文件。 这个方法会把给出的 *file* 参数值写成一个 PNG 文件。 参数值可以是字符串文件路径,也可以是一个可写的流数据。 如果使用流数据的话,参数 `file` 不会自动关闭。 其中 *scale* 参数是设置对一个数据块要绘制多大。 默认参数值是一个数据块绘制1个像素。这也许会让二维码看起来太小, 导致无法有效读取二维码。增加 `scale` 参数值会让二维码变大。 参数值只可以使用整数。这个方法会把参数值都变成整数(例如, 2.5会变成2,3会变成3)。 你可以使用 :py:meth:`get_png_size` 方法来计算 PNG 图片的实际像素大小。 其中 *module_color* 参数是设置用什么颜色来对数据块进行编码。 (绝大部分二维码数据块都是黑色)。 其中 *background* 参数是设置背景色(大部分二维码用白色)。 如果设置这两个参数中的一个,那就都要手动分配参数值, 否则会抛出 `ValueError` 例外错误。颜色值应该描述成列表或元组, 长度为3或4,其中每个元素值是0到255的整数。 三个元素长度的参数值是 RGB 色,四个元素长度的参数值 RGBA 色, 增加了一个透明度,alpha 成份,0表示透明,255表示不透明。 注意,许多颜色组合都是无法被二维码扫描器读取的,所以慎用着色特性。 其中 *quiet_zone* 无噪点区域参数是设置二维码周围的宽度。 根据二维码标准,这个宽度应该是4个数据块。保留成可设置是因为 许多应用程序不需要这个无噪点区域宽度,因为很少需要打印二维码。 Example: >>> code = pyqrcode.create('Are you suggesting coconuts migrate?') >>> code.png('swallow.png', scale=5) >>> code.png('swallow.png', scale=5, module_color=(0x66, 0x33, 0x0), #Dark brown background=(0xff, 0xff, 0xff, 0x88)) #50% transparent white """ builder._png(self.code, self.version, file, scale, module_color, background, quiet_zone)
def __init__(self, data, filename): version = 19 mode = 'binary' error = 'M' """See :py:class:`pyqrcode.QRCode` for information on the parameters.""" #Set what data we are going to use to generate #the QR code self.data = data #Check that the user passed in a valid mode if mode in tables.modes: self.mode = tables.modes[mode] else: raise ValueError('{0} is not a valid mode.'.format(mode)) #Check that the user passed in a valid error level if error in tables.error_level: self.error = tables.error_level[error] else: raise ValueError('{0} is not a valid error ' 'level.'.format(error)) if 1 <= version <= 40: self.version = version else: raise ValueError("Illegal version {0}, version must be between " "1 and 40.".format(version)) #Look up the proper row for error correction code words self.error_code_words = tables.eccwbi[version][self.error] #This property will hold the binary string as it is built self.buffer = io.StringIO() #Create the binary data block cleaned = bytes.hex(bytes.fromhex(data)) bytestream = ('{0:0' + str(len(cleaned) * 4) + 'b}').format( int(cleaned, 16)) self.buffer.write(bytestream) data = [ int(''.join(x), 2) for x in self.grouper(8, self.buffer.getvalue()) ] #This is the error information for the code error_info = tables.eccwbi[self.version][self.error] #This will hold our data blocks data_blocks = [] #This will hold our error blocks error_blocks = [] #Some codes have the data sliced into two different sized blocks #for example, first two 14 word sized blocks, then four 15 word #sized blocks. This means that slicing size can change over time. data_block_sizes = [error_info[2]] * error_info[1] if error_info[3] != 0: data_block_sizes.extend([error_info[4]] * error_info[3]) #For every block of data, slice the data into the appropriate #sized block current_byte = 0 for n_data_blocks in data_block_sizes: data_blocks.append(data[current_byte:current_byte + n_data_blocks]) current_byte += n_data_blocks #I am not sure about the test after the "and". This was added to #fix a bug where after delimit_words padded the bit stream, a zero #byte ends up being added. After checking around, it seems this extra #byte is supposed to be chopped off, but I cannot find that in the #standard! I am adding it to solve the bug, I believe it is correct. if current_byte < len(data): raise ValueError('Too much data for this code version.') #DEBUG CODE!!!! #Print out the data blocks #print('Data Blocks:\n{0}'.format(data_blocks)) #Calculate the error blocks for n, block in enumerate(data_blocks): error_blocks.append(self.make_error_block(block, n)) #DEBUG CODE!!!! #Print out the error blocks #print('Error Blocks:\n{0}'.format(error_blocks)) #Buffer we will write our data blocks into data_buffer = io.StringIO() #Add the data blocks #Write the buffer such that: block 1 byte 1, block 2 byte 1, etc. largest_block = max(error_info[2], error_info[4]) + error_info[0] for i in range(largest_block): for block in data_blocks: if i < len(block): data_buffer.write(self.binary_string(block[i], 8)) #Add the error code blocks. #Write the buffer such that: block 1 byte 1, block 2 byte 2, etc. for i in range(error_info[0]): for block in error_blocks: data_buffer.write(self.binary_string(block[i], 8)) self.buffer = data_buffer #Create the actual QR code self.make_code() _png(self.code, version, filename, 6, (0, 0, 0, 255), (255, 255, 255, 255), 4)