JPG 还是 PNG 和内存结构有关系吗?还是只是保存到硬盘的时候,才有区别?
我最近在使用 selenium
做一个网页自动截屏的服务, 保存的截图需要保存为 jpg 文件
有两个相关的 api
selenium/webdriver/remote/webdriver.py
def get_screenshot_as_png(self) -> bytes: """
Gets the screenshot of the current window as a binary data.
:Usage:
::
driver.get_screenshot_as_png()
"""
return b64decode(self.get_screenshot_as_base64().encode('ascii'))
def get_screenshot_as_base64(self) -> str:
"""
Gets the screenshot of the current window as a base64 encoded string
which is useful in embedded images in HTML.
:Usage:
::
driver.get_screenshot_as_base64()
"""
return self.execute(Command.SCREENSHOT)['value']
一个是 get_screenshot_as_png
,另一个是 get_screenshot_as_base64
get_screenshot_as_png
中也是调用了 get_screenshot_as_base64
我就有问题了,这里的 get_screenshot_as_png
就是对 get_screenshot_as_base64
的结果做了简单的 decode
和 encode
这样就得到 PNG
了?那我怎么的到 JPG
呢?
难道 get_screenshot_as_base64
返回的 base64 其实就是 PNG 编解码后的 base64?
我本来想的是,图片都是三维矩阵,只有在保存到硬盘的时候,才分 png
、jpg
这些,是这样的吗?
还是说因为 PNG 是无损的,所以简单的编解码就好了,JPG 要有损压缩,才需要后续特殊处理?
回答:
自己解决了
我的需求:我会获得 png 的 stream (type 为 bytes),我要把 png 上传到 oss,但是 png 太大了,就像转成 jpg 再上传到 oss 中
但是,简中互联网上的教程都是,教你怎么把『内存中的 png』 变成 『硬盘上的 jpg』
这是非常愚蠢的!
我需要的是:『内存中的 png』 变成 『内存中的 jpg』
简单的来讲,就是我希望,使用 python 把 png 转成 jpg 并压缩这个过程全程发生在 RAM 中,而不涉及任何硬盘读写
所以,我写了下面的代码:
import unittestfrom loguru import logger
from mark import BASE_DIR
from pathlib import Path
from PIL import Image
from PIL.Image import Image as PIL_Image
import sys
import io
def png_stream_2_png_image(png_stream: bytes) -> PIL_Image:
file_like_obj = io.BytesIO(png_stream)
png_image = Image.open(file_like_obj)
return png_image
def png_image_2_jpg_stream(png_image: PIL_Image, quality=100) -> bytes:
assert png_image.format == 'PNG'
file_like_obj = io.BytesIO()
png_image = png_image.convert('RGB') # PNG 是 RGBA,多了一个透明通道,JPG不支持透明通道
png_image.save(file_like_obj, format='JPEG', quality=quality)
stream = file_like_obj.getvalue()
return stream
def png_stream_2_jpg_stream(png_stream: bytes, quality=100) -> bytes:
"""
png_stream into png_imgae
png_imgae into jpg_stream
"""
png_image = png_stream_2_png_image(png_stream)
jpg_stream = png_image_2_jpg_stream(png_image, quality)
return jpg_stream
def png_image_2_png_stream(png_image: PIL_Image) -> bytes:
assert png_image.format == 'PNG'
file_like_obj = io.BytesIO()
png_image.save(file_like_obj, format='PNG')
stream = file_like_obj.getvalue()
return stream
class TestCompress(unittest.TestCase):
def test_compress_on_memory_2(self):
"""
python -m unittest testing.test_compress.TestCompress.test_compress_on_memory_2
"""
src_file_path = BASE_DIR/'static/img/94dcb906ff774e7ab4d6e8b1abcc147b.jpg'
png_image = Image.open(src_file_path)
png_stream = png_image_2_png_stream(png_image)
jpg_stream = png_image_2_jpg_stream(png_image, quality=50)
# logger.debug(png_stream)
logger.debug(type(png_stream))
logger.debug(len(png_stream))
logger.debug(type(jpg_stream))
logger.debug(len(jpg_stream))
logger.debug(f'压缩比: {round(len(jpg_stream)/len(png_stream)*100)}%')
输出结果如下:
─➤ python -m unittest testing.test_compress.TestCompress.test_compress_on_memory_22022-07-15 13:05:31.375 | DEBUG | testing.test_compress:test_compress_on_memory_2:59 - <class 'bytes'>
2022-07-15 13:05:31.375 | DEBUG | testing.test_compress:test_compress_on_memory_2:60 - 1075380
2022-07-15 13:05:31.375 | DEBUG | testing.test_compress:test_compress_on_memory_2:62 - <class 'bytes'>
2022-07-15 13:05:31.375 | DEBUG | testing.test_compress:test_compress_on_memory_2:63 - 172836
2022-07-15 13:05:31.375 | DEBUG | testing.test_compress:test_compress_on_memory_2:65 - 压缩比: 16%
回答:
JPG 和 PNG 是两种编码,需要 JPG 的话自己转换一下。
from PIL import Imageim = Image.open("in.jpg")
rgb_im = im.convert('RGB')
rgb_im.save('out.jpg')
回答:
比如1920×1080的图片,在内存里一般都是一个1920×1080×3的字节数组,也可能是1920×1080×4(包含透明通道的话)。
3代表的是rgb三通道,每个像素由rgb三通道决定,它们取值在0-255之间。 而且一般不用三维矩阵,比如opencv中就使用一维数组去保存图片,类似第一个像素点是a[0] a[1] a[2], 第二个像素点是a[3] a[4] a[5]。
当需要保存到磁盘时,为了解决存储空间,才会以png/jpg等格式编码压缩大小。
b64decode(self.get_screenshot_as_base64().encode('ascii'))
上边这一行,返回值是字节数组,应该和png/jpg格式无关才对。你可以看一下返回的字节数组的长度,如果能被1920 * 1080(屏幕分辨率)整除,应该就是和png/jpg格式无关。
回答:
图片要显示,在内存中为了方便直接显示,一般都是解码开的图形数据啦,这可以认为无压缩的原始数据,只有在保存为图片格式时才进行编码保存。
你想要保存为jpg,可以png转jpg格式,这个有第三方库支持的。
以上是 JPG 还是 PNG 和内存结构有关系吗?还是只是保存到硬盘的时候,才有区别? 的全部内容, 来源链接: utcz.com/p/938508.html