Как создать изображение с волшебной палочкой из строки необработанных данных в Python

У меня есть необработанная строка данных, например, так:

raw_data = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3300005CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3300002BFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9500B158DFFFF3300002BFFFFFFFFFFFFFFFFFFFFFFFFFFFFB200000003FFFF3300002BFFFFFFFFFFFFFFFFFFFFFFFFFFFFB100000002FFFF3300002BFFFFFFFFFFFFFFFFFFFFFFFFFFFFF643040B80FFFF3300002BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF3300002BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3300002BFFED843913051B59D1FFFFFFFFFFFF03000184FFFF3300002BAB0F00000000000007BBFFFFFFFFFF03000057FFFF330000080100000000000000001DF8FFFFFFFF03000057FFFF330000000042A9D4D08D0D000000ADFFFFFFFF03000057FFFF330000059DFFFFFFFFFFAA00000070FFFFFFFF03000057FFFF3300002BFFFFFFFFFFFFFA05000051FFFFFFFF03000057FFFF3300002BFFFFFFFFFFFFFF18000045FFFFFFFF03000057FFFF3300002BFFFFFFFFFFFFFF1B000043FFFFFFFF03000057FFFF3300002BFFFFFFFFFFFFFF1B000043FFFFFFFF03000057FFFF3300002BFFFFFFFFFFFFFF1B000043FFFFFFFF03000057"

Мне было интересно, как можно создать из него видимый .png.

Я попытался использовать класс Image.

with wand.image.Image (???) as img:

но я не уверен, что поставить в скобках. Я пробовал file=raw_data, width=25,height=25,depth=8

Что бы я ни пробовал, это дает мне ошибку.

Любые идеи?


person Tom    schedule 10.10.2017    source источник
comment
Не зная всех подробностей об используемом хранилище, вы мало что сможете сделать. Так что же это за необработанные данные? Битмап нравится? C-упорядочение против Fortran-упорядочения? Сколько каналов? Битовая глубина? Ах хорошо; разрешение (x против y) тоже.   -  person sascha    schedule 10.10.2017
comment
как мне это узнать? кстати я его генерирую?   -  person Tom    schedule 10.10.2017
comment
Зачем кому-то создавать что-то подобное? Но что ж... да... если вы их создали, то, наверное, должны знать все подробности.   -  person sascha    schedule 10.10.2017


Ответы (1)


Вам нужно будет преобразовать строку в байты и реализовать метод ImageMagick MagickImportImagePixels C-API.

import binascii
import ctypes

from wand.api import library
from wand.image import Image
from wand.color import Color

# Map C-API to Python
# -------------------
# magick-image.h
# WandExport MagickBooleanType MagickImportImagePixels(MagickWand *wand,
#   const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
#   const char *map,const StorageType storage,const void *pixels)
library.MagickImportImagePixels.argtypes = (ctypes.c_void_p,
                                            ctypes.c_ssize_t,
                                            ctypes.c_ssize_t,
                                            ctypes.c_size_t,
                                            ctypes.c_size_t,
                                            ctypes.c_char_p,
                                            ctypes.c_int,
                                            ctypes.c_void_p)


# Map enum StorageType
StorageType = ('undefined', 'char', 'double', 'float',
               'integer', 'long', 'quantum', 'short')

# Extend wand.image.Image to implement import_pixels method
class MyImage(Image):
    def import_pixels(self, blob, pixel_format='RGBA', pixel_size='char'):
        storage_type = StorageType.index(pixel_size)
        library.MagickImportImagePixels(self.wand,
                                        0,
                                        0,
                                        self.width,
                                        self.height,
                                        pixel_format.encode(),
                                        storage_type,
                                        blob)
# Usage
raw_data_string = 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3300005CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3300002BFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9500B158DFFFF3300002BFFFFFFFFFFFFFFFFFFFFFFFFFFFFB200000003FFFF3300002BFFFFFFFFFFFFFFFFFFFFFFFFFFFFB100000002FFFF3300002BFFFFFFFFFFFFFFFFFFFFFFFFFFFFF643040B80FFFF3300002BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF3300002BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3300002BFFED843913051B59D1FFFFFFFFFFFF03000184FFFF3300002BAB0F00000000000007BBFFFFFFFFFF03000057FFFF330000080100000000000000001DF8FFFFFFFF03000057FFFF330000000042A9D4D08D0D000000ADFFFFFFFF03000057FFFF330000059DFFFFFFFFFFAA00000070FFFFFFFF03000057FFFF3300002BFFFFFFFFFFFFFA05000051FFFFFFFF03000057FFFF3300002BFFFFFFFFFFFFFF18000045FFFFFFFF03000057FFFF3300002BFFFFFFFFFFFFFF1B000043FFFFFFFF03000057FFFF3300002BFFFFFFFFFFFFFF1B000043FFFFFFFF03000057FFFF3300002BFFFFFFFFFFFFFF1B000043FFFFFFFF03000057'
raw_data_bytes = binascii.unhexlify(raw_data_string)

with MyImage(width=25, height=25, background=Color('WHITE')) as img:
    img.import_pixels(raw_data_bytes, pixel_format='R', pixel_size='char')
    img.save(filename='output.png')

output.png

Как указано в комментариях, вы будете нести ответственность за знание/определение макета канала (например, RGBA, BGR, ARBG и т. д.), размер типа данных (например, char/short/int/long или float/double), данные -макет потока (например, чересстрочный), и, конечно же, фактическая ширина/высота ожидаемый образ.

person emcconville    schedule 10.10.2017
comment
большое спасибо, это работает. Почему возникает ошибка сегментации, когда я использую RGBA в качестве формата пикселей? - person Tom; 10.10.2017
comment
Это будет переполнение буфера. У вас есть буфер из 625 8-битных целых чисел — этого достаточно, чтобы покрыть один цветовой канал. Для полного RGBA вам понадобится 25(width) x 25(height) * 4(rgba) = 2500 - person emcconville; 10.10.2017