Заставьте Подушку генерировать изображение с типом TrueColor, в то время как я использую только черный и белый
Я генерирую изображения, используя Python 3.6.6 и Pillow == 5.3.0. Все изображения имеют формат JPEG и цветовой режим RGB.
Когда я сделаю изображение с цветами, оно выйдет с Type: TrueColor
(и с глубиной канала: красный: 8-битный зеленый: 8-битный синий: 8-битный)
Когда я использую только черно-белое изображение, Type: Grayscale
(и с глубиной канала: серый: 8 бит)
Поскольку я пытаюсь использовать службу печати, которая принимает только мои цветные изображения, я хочу сделать черно-белые изображения TrueColor
изображение, даже если у них не будет других цветов (RGB).
Могу я просто сделать это?
Или делает TrueColor
изображение означает, что значения RGB не могут быть все 0?
Я не понимаю, как я могу сделать это в подушке. Мой предпочтительный способ - применять это, когда я генерирую изображение в своем коде Python.
Альтернативой может быть преобразование изображения с помощью инструмента (я работаю в Ubuntu 18.04 и использую ImageMagick и ffmpeg). Я попробовал следующее, но ничего не помогло. Выходной файл имеет те же метаданные, что и исходный.
convert -type TrueColor original_file.jpeg converted_file.jpeg
convert -type TrueColor -depth 8 original_file.jpeg converted_file.jpeg
РЕДАКТИРОВАТЬ & Пример
Вот код Python для создания двух изображений в одинаковом режиме (RGB).
from PIL import Image, ImageDraw
white = (255, 255, 255)
black = (0, 0, 0)
red = (230, 25, 75)
def draw_line(file_name, line_color):
"""
Draw a 400x400 image with a white background and one
diagonal line of the given 'line_color'
"""
image = Image.new(mode='RGB', size=(400, 400), color=white)
draw = ImageDraw.Draw(image)
draw.line(xy=((100, 100), (300, 300)), fill=line_color, width=5)
image.save(fp=file_name, format='JPEG')
draw_line(file_name='black_line.jpeg', line_color=black
draw_line(file_name='red_line.jpeg', line_color=red)
Изображение с черной линией будет иметь Type: Grayscale
и тот, с красной линией Type: TrueColor
, Обратите внимание, что ColorSpace является sRGB в обоих случаях, а глубина 8-битная.
identify black_line.jpeg
black_line.jpeg JPEG 400x400 400x400+0+0 8-bit sRGB 5.12KB 0.000u 0:00.000
identify -verbose black_line.jpeg
Type: Grayscale
Colorspace: sRGB
Depth: 8-bit
Channel depth:
gray: 8-bit
identify red_line.jpeg
red_line.jpeg JPEG 400x400 400x400+0+0 8-bit sRGB 5.26KB 0.000u 0:00.000
identify -verbose red_line.jpeg
Type: TrueColor
Colorspace: sRGB
Depth: 8-bit
Channel depth:
red: 8-bit
green: 8-bit
blue: 8-bit
Поэтому мой вопрос: могу ли я создавать изображения с помощью подушки, чтобы независимо от того, какие цвета я использовал, они всегда выглядели одинаково type: TrueColor
с 3 каналами? Так что даже в том случае, когда я рисую черную линию на белом фоне.
(ПРИМЕЧАНИЕ: когда я нарисую красную линию с шириной по умолчанию 1, он будет иметь Type: Palette
вместо TrueColor
)
Попытка конвертировать в TrueColor
convert black_line.jpeg -type truecolor black_line_tc.jpeg
identify -verbose black_line_tc.jpeg |grep Type
Type: Grayscale
Таким образом, он не будет преобразовывать тип в TrueColor. Я сделал различия в идентифицирующих выходных данных, но нет никакой существенной разницы в отношении channel_depth / colorspace / type и т. Д., Поэтому я не буду публиковать выходные данные.
identify -verbose black_line.jpeg > identity_black.txt
identify -verbose black_line_tc.jpeg > identity_black_tc.txt
diff identity_black.txt identity_black_tc.txt
3 ответа
Работает для меня. В тестах ниже:
BW-RGB.jpg
изображение плазмы в оттенках серого (с каналами RGB), экспортированное из GimpBW-Grey.jpg
такое же изображение в чистом оттенках серого (один канал), экспортированное из Gimp
И.М. identify
говорит:
BW-Grey.jpg JPEG 400x400 400x400+0+0 8-bit Gray 256c 48.2KB 0.010u 0:00.000
BW-RGB.jpg JPEG 400x400 400x400+0+0 8-bit sRGB 49.1KB 0.010u 0:00.019
И если я использую:
convert BW-Grey.jpg -type TrueColor BW-Converted.jpg
И.М. identify
говорит:
BW-Converted.jpg JPEG 400x400 400x400+0+0 8-bit sRGB 54.1KB 0.000u 0:00.000
Так что результат действительно RGB. Обратите внимание, что размер файлов RGB и оттенков серого не очень отличается, что ожидается. Цветное изображение сохраняется в виде трех кадров, черно-белого и двухцветного, но для изображения в оттенках серого (R=G=B) эти два цветовых изображения имеют одно единое однородное значение и поэтому сжимаются очень хорошо.
PS: на Linux вы можете подтвердить IM identify
сообщить с использованием file
Команда: она сообщает один кадр в полутоновых изображениях и три в цветных.
Обновленный ответ
Я экспериментировал с этим, и это кажется очень неуправляемым - по крайней мере, мной!
Я попытался добавить несколько случайных красных, зеленых и синих одиночных пикселей к вашему изображению тут и там, но, похоже, в ближайшее время тип не изменится на TrueColour.
Затем я попытался добавить и вычесть крошечное количество случайного шума для всех пикселей и добился некоторого прогресса, но изображение становится "ощутимо несчастным" до того, как ImageMagick признает, что это TrueColour. Подавление подвыборки в кодировщике JPEG и повышение качества помогают немного - но не сильно.
Я обнаружил, что должен был увеличить N
(количество шума) до 9, прежде чем ImageMagick согласился, что изображение было TrueColour. Вы можете поэкспериментировать, поэтому вот код:
#!/usr/bin/env python3
from PIL import Image, ImageDraw
import numpy as np
def makeTrueColour(image):
"""
Force image to TrueColour by 'slightly distorting' greys.
Distortion means adding a tiny random amount of noise (0-N) to pixels that will not
"burn out" (i.e. exceed 255) as a result, and also subtracting a similar tiny
random amount of noise from pixels from pixels that will not underflow as a result.
If N=1, this means less than 0.4% error - hopefully imperceptible.
"""
N = 1
w, h = image.size
ni = np.array(image)
# Mask of pixels that will not exceed 255 by adding N
okpix = (ni <= (255 - N))
# Make additive noise in those pixels
noise = np.random.randint(0,N+1,size=(h,w,3),dtype=np.uint8) * okpix
ni += noise
# Mask of pixels big enough to subtract N
okpix = (ni >= N)
# Make subtractive noise in those pixels
noise = np.random.randint(0,N+1,size=(h,w,3),dtype=np.uint8) * okpix
ni -= noise
return(Image.fromarray(ni))
image = Image.new(mode='RGB', size=(400, 400), color=(255,255,255))
draw = ImageDraw.Draw(image)
draw.line(xy=((100, 100), (300, 300)), fill=(0,0,0), width=5)
tc = makeTrueColour(image)
tc.save('result.jpg',subsample=0,quality=95)
# This just counts the unique colours in "tc" - you don't need it
T = np.array(tc)
print(len(np.unique(T.reshape(-1, T.shape[2]), axis=0)) )
Оригинальный ответ
Я не уверен, что понимаю. Вот что я получаю, когда делаю RGB-изображение:
from PIL import Image
import numpy as np
# Make a fully black image
im = np.zeros([480,640,3], dtype=np.uint8)
# Save as RGB
Image.fromarray(im).save('resultRGB.jpg')
# Save as greyscale
Image.fromarray(grey).convert('L').save('resultGRAY.jpg')
Теперь я смотрю на них с помощью ImageMagick и получаю именно то, что ожидаю:
identify result*jpg
resultGRAY.jpg JPEG 640x480 640x480+0+0 8-bit Gray 256c 3932B 0.000u 0:00.000
resultRGB.jpg JPEG 640x480 640x480+0+0 8-bit sRGB 5427B 0.000u 0:00.000
На что ты надеялся? Пожалуйста, нажмите edit
под свой оригинальный вопрос и приведите контрпример.
Вот пример принудительного преобразования одноканального изображения JPG в градациях серого в 3-канальное изображение sRGB с цветовым пространством с использованием ImageMagick.
Здесь я создаю градиент серого. Затем используйте Imagemagick identifier -verbose, и оно будет отображаться как цветное пространство Grey. Exiftool подтверждает это как 1 канал (компонент цвета) с 8 битами.
convert -size 256x256 gradient: grad.jpg
identify -verbose grad.jpg
Image: grad.jpg
Format: JPEG (Joint Photographic Experts Group JFIF format)
Mime type: image/jpeg
Class: PseudoClass
Geometry: 256x256+0+0
Units: Undefined
Colorspace: Gray
Type: Grayscale
Base type: Undefined
Endianess: Undefined
Depth: 8-bit
Channel depth:
gray: 8-bit
...
exiftool -s -ee -g1 -u -n -D grad.jpg
...
- BitsPerSample : 8
- ColorComponents : 1
...
Теперь я использую truetype -type для преобразования изображения в градациях серого в цветовое пространство RGB. ImageMagick говорит, что цветовое пространство RGB и exiftool показывают, что это 3 канала (цветовые компоненты) каждый из 8 бит.
convert grad.jpg -type truecolor grad_tc.jpg
Fredericks-Mac-mini:desktop fred$ identify -verbose grad_tc.jpg
Image: grad_tc.jpg
Format: JPEG (Joint Photographic Experts Group JFIF format)
Mime type: image/jpeg
Class: DirectClass
Geometry: 256x256+0+0
Units: Undefined
Colorspace: sRGB
Type: Grayscale
Base type: Undefined
Endianess: Undefined
Depth: 8-bit
Channel depth:
red: 8-bit
green: 8-bit
blue: 8-bit
...
exiftool -s -ee -g1 -u -n -D grad_tc.jpg
...
- BitsPerSample : 8
- ColorComponents : 3
...
Я подозреваю, что PIL определяет цветовое пространство тем, сколько каналов вы используете при чтении или создании изображения. Извините, я не очень знаком с PIL. Но если этого не произойдет, то вы можете передать его в numpy, чтобы сделать его 3 канала. Затем верните его в ПИЛ.