MagickGetImagePixels в GraphicsMagick странный - PullRequest
0 голосов
/ 28 ноября 2018

Я пытаюсь создать код C, который выполняет простое изменение размера.

Вот мой код, используемый

#include <stdlib.h>
#include <wand/wand_api.h>

struct ARRAY_BUFFER
{
    void *data;
    unsigned int height;
    unsigned int width;
    int color_type;
    int bit_depth;
};

ExceptionType
check_result(const MagickWand* wand) {
    char *description;
    ExceptionType severity;
    description=MagickGetException(wand, &severity);
    printf("%s %s\n", GetMagickModule(), description);
    if(severity >= 400)
        return 1;
    return 0;
}

int
resize(struct ARRAY_BUFFER* buffer_in,
       struct ARRAY_BUFFER* buffer_out)
{
    MagickWand *wand = NewMagickWand();
    unsigned int status;

    status = MagickSetSize(wand, buffer_in->width, buffer_in->height);
    if(!status) {
        ExceptionType e = check_result(wand);
        if(e >= 400) return 1;
    }

    status = MagickReadImage(wand, "xc:none");
    if(!status) {
        ExceptionType e = check_result(wand);
        if(e >= 400) return 1;
    }

    status = MagickSetImagePixels(wand, 0, 0, buffer_in->width, buffer_in->height, "RGB", CharPixel, buffer_in->data);
    if(!status) {
        ExceptionType e = check_result(wand);
        if(e >= 400) return 1;
    }

    status = MagickResizeImage(wand, buffer_out->width, buffer_out->height, LanczosFilter, 1);
    if(!status) {
        ExceptionType e = check_result(wand);
        if(e >= 400) return 1;
    }
    status = MagickGetImagePixels(wand, 0, 0, buffer_out->width, buffer_out->height, "RGB", CharPixel, buffer_out->data);
    if(!status) {
        ExceptionType e = check_result(wand);
        if(e >= 400) return 1;
    }
    // This line is for deugging
    MagickWriteImage(wand, "test.png");
    return 0;
}

Если я извлекаю выходной буфер, кажется, что изображение повреждено.На рисунке ниже представлено исходное изображение и изображение с измененным размером, которое сохраняется из внешней библиотеки.

Исходное изображение:

The original image

Сгенерированное изображение из выходного буфера:

Generated image from output buffer

Изображение с измененным размером, сохраненное GM:

Resized image saved by GM

Проблема, очевидно, связана с проблемой битовой глубины или типа данных, но я не смог найтилюбое руководство по этой проблеме в Интернете.Есть какой-то трюк, который я не знал?

(добавлено)
Это мой код Python, который строится на структуру изображения из буфера C

_lib = os.path.join(os.path.dirname(__file__), 'libimage.so')
_lib = ctypes.cdll.LoadLibrary(_lib)
class BYTE_BUFFER(ctypes.Structure):
    _fields_ = [
        ('data', ctypes.c_void_p),
        ('size', ctypes.c_size_t),
    ]
class ARRAY_BUFFER(ctypes.Structure):
    _fields_ = [
        ('data', ctypes.c_void_p),
        ('height', ctypes.c_uint),
        ('width', ctypes.c_uint),
        ('color_type', ctypes.c_int),
        ('bit_depth', ctypes.c_int),
    ]

_lib.resize.argtypes = [
        ctypes.POINTER(ARRAY_BUFFER),
        ctypes.POINTER(ARRAY_BUFFER),
    ]
_lib.resize.restype = ctypes.c_int


def resize(array: np.ndarray, height: int, width: int):
    bit_depth, color_type = _get_array_header(array)
    array_length = height * width * (bit_depth // 8) * 3

    array_buffer = ARRAY_BUFFER(
        array.ctypes.data_as(ctypes.c_void_p),
        array.shape[0],
        array.shape[1],
        __COLOR_TYPE__[color_type],
        bit_depth,
    )
    array_buffer_out = ARRAY_BUFFER(
        ctypes.cast((ctypes.c_uint32 * array_length)(), ctypes.c_void_p),
        height,
        width,
        0,
        0,
    )

    code = _lib.resize(ctypes.byref(array_buffer), ctypes.byref(array_buffer_out))
    if code:
        raise RuntimeError('Resizing failed')

    array_string = (ctypes.c_byte * array_length).from_address(array_buffer.data)
    array = np.frombuffer(array_string, dtype='=u' + str(bit_depth // 8))
    array = np.resize(array, [height, width, 3])
    array = array.squeeze()
    return array
...