<commit_before># distutils: language = c++
# cython: c_string_type=unicode, c_string_encoding=utf8
# cython: embedsignature=True

from __future__ import print_function

from cpython.ref cimport PyObject, Py_INCREF
from cython.operator cimport dereference as deref

import numpy as np
cimport numpy as np
np.import_array()

import os
import sys
import warnings
from enum import Enum

cdef extern from "def_helper.h":
    cdef int _LIBRAW_HAS_FLAGS
    # the following flags are only usable if _LIBRAW_HAS_FLAGS is 1
    # (this is the case for libraw >= 0.15.4)
    cdef int _LIBRAW_USE_DNGLOSSYCODEC
    cdef int _LIBRAW_USE_OPENMP
    cdef int _LIBRAW_USE_LCMS
    cdef int _LIBRAW_USE_REDCINECODEC
    cdef int _LIBRAW_USE_RAWSPEED
    cdef int _LIBRAW_USE_DEMOSAIC_PACK_GPL2
    cdef int _LIBRAW_USE_DEMOSAIC_PACK_GPL3

cdef extern from "libraw.h":
    ctypedef unsigned short ushort
    
    # some #define's
    cdef int LIBRAW_MAJOR_VERSION
    cdef int LIBRAW_MINOR_VERSION
    cdef int LIBRAW_PATCH_VERSION
    
    cdef float LIBRAW_DEFAULT_AUTO_BRIGHTNESS_THRESHOLD
    
    cdef enum LibRaw_image_formats:
        LIBRAW_IMAGE_JPEG
        LIBRAW_IMAGE_BITMAP
    
    ctypedef struct libraw_image_sizes_t:
        ushort raw_height, raw_width
        ushort height, width
        ushort top_margin, left_margin
        ushort iheight, iwidth
        
    ctypedef struct libraw_colordata_t:
        float       cam_mul[4] 
        float       pre_mul[4] 

    ctypedef struct libraw_rawdata_t:
        ushort *raw_image
        libraw_colordata_t          color
        
    ctypedef struct libraw_output_params_t:
        unsigned    greybox[4]     # -A  x1 y1 x2 y2 
        unsigned    cropbox[4]     # -B x1 y1 x2 y2 
        double      aber[4]        # -C 
        double      gamm[6]        # -g 
        float       user_mul[4]    # -r mul0 mul1 mul2 mul3 
        unsigned    shot_select    # -s 
        float       bright         # -b 
        float       threshold      #  -n 
        int         half_size      # -h 
        int         four_color_rgb # -f 
        int         highlight      # -H 
        int         use_auto_wb    # -a 
        int         use_camera_wb  # -w 
        int         use_camera_matrix # +M/-M 
        int         output_color   # -o 
        char        *output_profile # -o 
        char        *camera_profile # -p 
        char        *bad_pixels    # -P 
        char        *dark_frame    # -K 
        int         output_bps     # -4 
        int         output_tiff    # -T 
        int         user_flip      # -t 
        int         user_qual      # -q 
        int         user_black     # -k 
        int        user_cblack[4]
        int        sony_arw2_hack
        int         user_sat       # -S 
        int         med_passes     # -m 
        float       auto_bright_thr 
        float       adjust_maximum_thr
        int         no_auto_bright # -W 
        int         use_fuji_rotate# -j 
        int         green_matching
        # DCB parameters 
        int         dcb_iterations
        int         dcb_enhance_fl
        int         fbdd_noiserd
        # VCD parameters 
        int         eeci_refine
        int         es_med_passes
        # AMaZE
        int         ca_correc
        float       cared
        float    cablue
        int cfaline
        float linenoise
        int cfa_clean
        float lclean
        float cclean
        int cfa_green
        float green_thresh
        int exp_correc
        float exp_shift
        float exp_preser
        # WF debanding 
        int   wf_debanding
        float wf_deband_treshold[4]
        # Raw speed 
        int use_rawspeed
        # Disable Auto-scale 
        int no_auto_scale
        # Disable interpolation
        int no_interpolation
        # Disable sRAW YCC to RGB conversion 
        int sraw_ycc
        # Force use x3f data decoding either if demosaic pack GPL2 enabled 
        int force_foveon_x3f

    ctypedef struct libraw_iparams_t:
        char        make[64]
        char        model[64]
    
        unsigned    raw_count
        unsigned    dng_version
        unsigned    is_foveon
        int         colors
    
        unsigned    filters
        char        xtrans[6][6]
        char        cdesc[5]
        
    ctypedef struct libraw_data_t:
        ushort                      (*image)[4]
        libraw_image_sizes_t        sizes
        libraw_iparams_t            idata
        libraw_output_params_t        params
#         unsigned int                progress_flags
#         unsigned int                process_warnings
        libraw_colordata_t          color
#         libraw_imgother_t           other
#         libraw_thumbnail_t          thumbnail
        libraw_rawdata_t            rawdata
#         void                *parent_class

    ctypedef struct libraw_processed_image_t:
        LibRaw_image_formats type
        ushort height, width, colors, bits
        unsigned int  data_size 
        unsigned char data[1] # this is the image data, no idea why [1]

    cdef cppclass LibRaw:
        libraw_data_t imgdata
        LibRaw()
        int open_file(const char *fname)
        int unpack()
        int COLOR(int row, int col)
        int raw2image()
        int dcraw_process()
        libraw_processed_image_t* dcraw_make_mem_image(int *errcode)
        void dcraw_clear_mem(libraw_processed_image_t* img)
        void free_image()
        const char* strerror(int p)
        void recycle()

libraw_version = (LIBRAW_MAJOR_VERSION, LIBRAW_MINOR_VERSION, LIBRAW_PATCH_VERSION)

if _LIBRAW_HAS_FLAGS:
    flags = {'DNGLOSSYCODEC': bool(_LIBRAW_USE_DNGLOSSYCODEC),
             'OPENMP': bool(_LIBRAW_USE_OPENMP),
             'LCMS': bool(_LIBRAW_USE_LCMS),
             'REDCINECODEC': bool(_LIBRAW_USE_REDCINECODEC),
             'RAWSPEED': bool(_LIBRAW_USE_RAWSPEED),
             'DEMOSAIC_PACK_GPL2': bool(_LIBRAW_USE_DEMOSAIC_PACK_GPL2),
             'DEMOSAIC_PACK_GPL3': bool(_LIBRAW_USE_DEMOSAIC_PACK_GPL3),
             }
else:
    flags = None

cdef class RawPy:
    cdef LibRaw* p
        
    def __cinit__(self):
        self.p = new LibRaw()
        
    def __dealloc__(self):
        del self.p
    
    def open_file(self, path):
        self.handleError(self.p.open_file(_chars(path)))
        if libraw_version < (0,15):
            self.path = path
            # libraw < 0.15 requires calling open_file & unpack for multiple calls to dcraw_process
            # with different parameters, therefore we remember the fact that this is freshly opened
            self.needs_reopening = False
        
    def unpack(self):
        self.handleError(self.p.unpack())
        
    @property
    def raw_image(self):
        """Bayer-pattern RAW image, one channel."""
        cdef ushort* raw = self.p.imgdata.rawdata.raw_image
        if raw == NULL:
            return None
        cdef np.npy_intp shape[2]
        shape[0] = <np.npy_intp> self.p.imgdata.sizes.raw_height
        shape[1] = <np.npy_intp> self.p.imgdata.sizes.raw_width
        return np.PyArray_SimpleNewFromData(2, shape, np.NPY_USHORT, raw)
            
    cpdef ushort rawvalue(self, int row, int column):
        """
        Return RAW value at given position relative to visible area of image
        (see visible_size_raw()).        
        """
        cdef ushort* raw = self.p.imgdata.rawdata.raw_image
        cdef ushort top_margin = self.p.imgdata.sizes.top_margin
        cdef ushort left_margin = self.p.imgdata.sizes.left_margin
        cdef ushort raw_width = self.p.imgdata.sizes.raw_width
        return raw[(row+top_margin)*raw_width + column + left_margin]
    
    @property
    def visible_size_raw(self):
        return self.p.imgdata.sizes.height, self.p.imgdata.sizes.width
    
    @property
    def num_colors(self):
        """
        Number of colors.
        Note that e.g. for RGBG this can be 3 or 4, depending on the camera model,
        as some use two different greens. 
        """
        return self.p.imgdata.idata.colors
    
    @property
    def color_desc(self):
        """
        String description of colors numbered from 0 to 3 (RGBG,RGBE,GMCY, or GBTG).
        Note that same letters may not refer strictly to the same color.
        There are cameras with two different greens for example.
        """
        return self.p.imgdata.idata.cdesc
    
    cpdef int rawcolor(self, int row, int column):
        """
        Return color index for the given RAW pixel location.
        """
        return self.p.COLOR(row, column)
    
    @property
    def rawcolors(self):
        """
        An array of color indices for each pixel in the RAW image.
        Equivalent to calling rawcolor(y,x) for each pixel.
        """
        if self.p.imgdata.idata.filters < 1000:
            raise NotImplementedError
        cdef int n = 4
        cdef np.ndarray pattern = np.empty((n, n), dtype=np.uint8)
        cdef int y, x
        for y in range(n):
            for x in range(n):
                pattern[y,x] = self.p.COLOR(y, x)
        cdef int height = self.p.imgdata.sizes.raw_height
        cdef int width = self.p.imgdata.sizes.raw_width
        return np.tile(pattern, (height/n, width/n))
       
    @property
    def camera_whitebalance(self):
        """
        White balance coefficients (as shot). Either read from file or calculated.
        """
        return [self.p.imgdata.rawdata.color.cam_mul[0],
                self.p.imgdata.rawdata.color.cam_mul[1],
                self.p.imgdata.rawdata.color.cam_mul[2],
                self.p.imgdata.rawdata.color.cam_mul[3]]
        
    @property
    def daylight_whitebalance(self):
        """
        White balance coefficients for daylight (daylight balance). 
        Either read from file, or calculated on the basis of file data, 
        or taken from hardcoded constants.
        """
        return [self.p.imgdata.rawdata.color.pre_mul[0],
                self.p.imgdata.rawdata.color.pre_mul[1],
                self.p.imgdata.rawdata.color.pre_mul[2],
                self.p.imgdata.rawdata.color.pre_mul[3]]
    
    def raw2image(self):
        """
        This function allocates buffer for postprocessing (self.image) and fills
        it with data layout compatible with LibRaw 0.13/0.14 and below.
        If the buffer is already allocated, it will be free()ed and allocated again.

        This function should be called only if your code do postprocessing stage.
        If you use LibRaw's postprocessing calls (see below) you don't need to call raw2image().
        """
        self.handleError(self.p.raw2image())
    
    @property
    def image(self):
        cdef np.npy_intp shape[2]
        shape[0] = <np.npy_intp> self.p.imgdata.sizes.iheight
        shape[1] = <np.npy_intp> self.p.imgdata.sizes.iwidth
        return [np.PyArray_SimpleNewFromData(2, shape, np.NPY_USHORT, self.p.imgdata.image[0]),
                np.PyArray_SimpleNewFromData(2, shape, np.NPY_USHORT, self.p.imgdata.image[1]),
                np.PyArray_SimpleNewFromData(2, shape, np.NPY_USHORT, self.p.imgdata.image[2]),
                np.PyArray_SimpleNewFromData(2, shape, np.NPY_USHORT, self.p.imgdata.image[3])]
                
    def dcraw_process(self, params=None, **kw):
        if params is None:
            params = Params(**kw)
        self.applyParams(params)
        self.handleError(self.p.dcraw_process())
        
    def dcraw_make_mem_image(self):
        cdef int errcode = 0
        cdef libraw_processed_image_t* img = self.p.dcraw_make_mem_image(&errcode)
        self.handleError(errcode)
        if img.type != LIBRAW_IMAGE_BITMAP:
            raise NotImplementedError
        wrapped = processed_image_wrapper()
        wrapped.set_data(self, img)
        ndarr = wrapped.__array__()
        return ndarr
                
    def postprocess(self, params=None, **kw):
        """
        Return post-processed image as numpy array.  
        """
        if libraw_version < (0,15):
            if self.needs_reopening:
                self.p.recycle()
                self.open_file(self.path)
                self.unpack()
            self.needs_reopening = True
        self.dcraw_process(params, **kw)
        return self.dcraw_make_mem_image()
        
    cdef applyParams(self, params):
        if params is None:
            return
        cdef libraw_output_params_t* p = &self.p.imgdata.params
        p.user_qual = params.user_qual
        p.use_camera_wb = params.use_camera_wb
        p.use_auto_wb = params.use_auto_wb
        if params.user_mul:
            for i in range(4):
                p.user_mul[i] = params.user_mul[i]
        p.output_color = params.output_color
        p.output_bps = params.output_bps
        p.user_flip = params.user_flip
        p.user_black = params.user_black
        p.user_sat = params.user_sat
        p.no_auto_bright = params.no_auto_bright
        p.auto_bright_thr = params.auto_bright_thr
        p.adjust_maximum_thr = params.adjust_maximum_thr
        p.exp_correc = params.exp_correc
        p.exp_shift = params.exp_shift
        p.exp_preser = params.exp_preser
        if params.bad_pixels:
            p.bad_pixels = params.bad_pixels
        else:
            p.bad_pixels = NULL<commit_msg>issue warning for repeated postprocessing on older libraw versions<commit_after># distutils: language = c++
# cython: c_string_type=unicode, c_string_encoding=utf8
# cython: embedsignature=True

from __future__ import print_function

from cpython.ref cimport PyObject, Py_INCREF
from cython.operator cimport dereference as deref

import numpy as np
cimport numpy as np
np.import_array()

import os
import sys
import warnings
from enum import Enum

cdef extern from "def_helper.h":
    cdef int _LIBRAW_HAS_FLAGS
    # the following flags are only usable if _LIBRAW_HAS_FLAGS is 1
    # (this is the case for libraw >= 0.15.4)
    cdef int _LIBRAW_USE_DNGLOSSYCODEC
    cdef int _LIBRAW_USE_OPENMP
    cdef int _LIBRAW_USE_LCMS
    cdef int _LIBRAW_USE_REDCINECODEC
    cdef int _LIBRAW_USE_RAWSPEED
    cdef int _LIBRAW_USE_DEMOSAIC_PACK_GPL2
    cdef int _LIBRAW_USE_DEMOSAIC_PACK_GPL3

cdef extern from "libraw.h":
    ctypedef unsigned short ushort
    
    # some #define's
    cdef int LIBRAW_MAJOR_VERSION
    cdef int LIBRAW_MINOR_VERSION
    cdef int LIBRAW_PATCH_VERSION
    
    cdef float LIBRAW_DEFAULT_AUTO_BRIGHTNESS_THRESHOLD
    
    cdef enum LibRaw_image_formats:
        LIBRAW_IMAGE_JPEG
        LIBRAW_IMAGE_BITMAP
    
    ctypedef struct libraw_image_sizes_t:
        ushort raw_height, raw_width
        ushort height, width
        ushort top_margin, left_margin
        ushort iheight, iwidth
        
    ctypedef struct libraw_colordata_t:
        float       cam_mul[4] 
        float       pre_mul[4] 

    ctypedef struct libraw_rawdata_t:
        ushort *raw_image
        libraw_colordata_t          color
        
    ctypedef struct libraw_output_params_t:
        unsigned    greybox[4]     # -A  x1 y1 x2 y2 
        unsigned    cropbox[4]     # -B x1 y1 x2 y2 
        double      aber[4]        # -C 
        double      gamm[6]        # -g 
        float       user_mul[4]    # -r mul0 mul1 mul2 mul3 
        unsigned    shot_select    # -s 
        float       bright         # -b 
        float       threshold      #  -n 
        int         half_size      # -h 
        int         four_color_rgb # -f 
        int         highlight      # -H 
        int         use_auto_wb    # -a 
        int         use_camera_wb  # -w 
        int         use_camera_matrix # +M/-M 
        int         output_color   # -o 
        char        *output_profile # -o 
        char        *camera_profile # -p 
        char        *bad_pixels    # -P 
        char        *dark_frame    # -K 
        int         output_bps     # -4 
        int         output_tiff    # -T 
        int         user_flip      # -t 
        int         user_qual      # -q 
        int         user_black     # -k 
        int        user_cblack[4]
        int        sony_arw2_hack
        int         user_sat       # -S 
        int         med_passes     # -m 
        float       auto_bright_thr 
        float       adjust_maximum_thr
        int         no_auto_bright # -W 
        int         use_fuji_rotate# -j 
        int         green_matching
        # DCB parameters 
        int         dcb_iterations
        int         dcb_enhance_fl
        int         fbdd_noiserd
        # VCD parameters 
        int         eeci_refine
        int         es_med_passes
        # AMaZE
        int         ca_correc
        float       cared
        float    cablue
        int cfaline
        float linenoise
        int cfa_clean
        float lclean
        float cclean
        int cfa_green
        float green_thresh
        int exp_correc
        float exp_shift
        float exp_preser
        # WF debanding 
        int   wf_debanding
        float wf_deband_treshold[4]
        # Raw speed 
        int use_rawspeed
        # Disable Auto-scale 
        int no_auto_scale
        # Disable interpolation
        int no_interpolation
        # Disable sRAW YCC to RGB conversion 
        int sraw_ycc
        # Force use x3f data decoding either if demosaic pack GPL2 enabled 
        int force_foveon_x3f

    ctypedef struct libraw_iparams_t:
        char        make[64]
        char        model[64]
    
        unsigned    raw_count
        unsigned    dng_version
        unsigned    is_foveon
        int         colors
    
        unsigned    filters
        char        xtrans[6][6]
        char        cdesc[5]
        
    ctypedef struct libraw_data_t:
        ushort                      (*image)[4]
        libraw_image_sizes_t        sizes
        libraw_iparams_t            idata
        libraw_output_params_t        params
#         unsigned int                progress_flags
#         unsigned int                process_warnings
        libraw_colordata_t          color
#         libraw_imgother_t           other
#         libraw_thumbnail_t          thumbnail
        libraw_rawdata_t            rawdata
#         void                *parent_class

    ctypedef struct libraw_processed_image_t:
        LibRaw_image_formats type
        ushort height, width, colors, bits
        unsigned int  data_size 
        unsigned char data[1] # this is the image data, no idea why [1]

    cdef cppclass LibRaw:
        libraw_data_t imgdata
        LibRaw()
        int open_file(const char *fname)
        int unpack()
        int COLOR(int row, int col)
        int raw2image()
        int dcraw_process()
        libraw_processed_image_t* dcraw_make_mem_image(int *errcode)
        void dcraw_clear_mem(libraw_processed_image_t* img)
        void free_image()
        const char* strerror(int p)
        void recycle()

libraw_version = (LIBRAW_MAJOR_VERSION, LIBRAW_MINOR_VERSION, LIBRAW_PATCH_VERSION)

if _LIBRAW_HAS_FLAGS:
    flags = {'DNGLOSSYCODEC': bool(_LIBRAW_USE_DNGLOSSYCODEC),
             'OPENMP': bool(_LIBRAW_USE_OPENMP),
             'LCMS': bool(_LIBRAW_USE_LCMS),
             'REDCINECODEC': bool(_LIBRAW_USE_REDCINECODEC),
             'RAWSPEED': bool(_LIBRAW_USE_RAWSPEED),
             'DEMOSAIC_PACK_GPL2': bool(_LIBRAW_USE_DEMOSAIC_PACK_GPL2),
             'DEMOSAIC_PACK_GPL3': bool(_LIBRAW_USE_DEMOSAIC_PACK_GPL3),
             }
else:
    flags = None

cdef class RawPy:
    cdef LibRaw* p
    cdef bint needs_reopening
        
    def __cinit__(self):
        self.p = new LibRaw()
        
    def __dealloc__(self):
        del self.p
    
    def open_file(self, path):
        self.handleError(self.p.open_file(_chars(path)))
        if libraw_version < (0,15):
            # libraw < 0.15 requires calling open_file & unpack for multiple calls to dcraw_process
            # with different parameters, therefore we remember the fact that this is freshly opened
            # and issue a warning in postprocess if needed
            self.needs_reopening = False
        
    def unpack(self):
        self.handleError(self.p.unpack())
        
    @property
    def raw_image(self):
        """Bayer-pattern RAW image, one channel."""
        cdef ushort* raw = self.p.imgdata.rawdata.raw_image
        if raw == NULL:
            return None
        cdef np.npy_intp shape[2]
        shape[0] = <np.npy_intp> self.p.imgdata.sizes.raw_height
        shape[1] = <np.npy_intp> self.p.imgdata.sizes.raw_width
        return np.PyArray_SimpleNewFromData(2, shape, np.NPY_USHORT, raw)
            
    cpdef ushort rawvalue(self, int row, int column):
        """
        Return RAW value at given position relative to visible area of image
        (see visible_size_raw()).        
        """
        cdef ushort* raw = self.p.imgdata.rawdata.raw_image
        cdef ushort top_margin = self.p.imgdata.sizes.top_margin
        cdef ushort left_margin = self.p.imgdata.sizes.left_margin
        cdef ushort raw_width = self.p.imgdata.sizes.raw_width
        return raw[(row+top_margin)*raw_width + column + left_margin]
    
    @property
    def visible_size_raw(self):
        return self.p.imgdata.sizes.height, self.p.imgdata.sizes.width
    
    @property
    def num_colors(self):
        """
        Number of colors.
        Note that e.g. for RGBG this can be 3 or 4, depending on the camera model,
        as some use two different greens. 
        """
        return self.p.imgdata.idata.colors
    
    @property
    def color_desc(self):
        """
        String description of colors numbered from 0 to 3 (RGBG,RGBE,GMCY, or GBTG).
        Note that same letters may not refer strictly to the same color.
        There are cameras with two different greens for example.
        """
        return self.p.imgdata.idata.cdesc
    
    cpdef int rawcolor(self, int row, int column):
        """
        Return color index for the given RAW pixel location.
        """
        return self.p.COLOR(row, column)
    
    @property
    def rawcolors(self):
        """
        An array of color indices for each pixel in the RAW image.
        Equivalent to calling rawcolor(y,x) for each pixel.
        """
        if self.p.imgdata.idata.filters < 1000:
            raise NotImplementedError
        cdef int n = 4
        cdef np.ndarray pattern = np.empty((n, n), dtype=np.uint8)
        cdef int y, x
        for y in range(n):
            for x in range(n):
                pattern[y,x] = self.p.COLOR(y, x)
        cdef int height = self.p.imgdata.sizes.raw_height
        cdef int width = self.p.imgdata.sizes.raw_width
        return np.tile(pattern, (height/n, width/n))
       
    @property
    def camera_whitebalance(self):
        """
        White balance coefficients (as shot). Either read from file or calculated.
        """
        return [self.p.imgdata.rawdata.color.cam_mul[0],
                self.p.imgdata.rawdata.color.cam_mul[1],
                self.p.imgdata.rawdata.color.cam_mul[2],
                self.p.imgdata.rawdata.color.cam_mul[3]]
        
    @property
    def daylight_whitebalance(self):
        """
        White balance coefficients for daylight (daylight balance). 
        Either read from file, or calculated on the basis of file data, 
        or taken from hardcoded constants.
        """
        return [self.p.imgdata.rawdata.color.pre_mul[0],
                self.p.imgdata.rawdata.color.pre_mul[1],
                self.p.imgdata.rawdata.color.pre_mul[2],
                self.p.imgdata.rawdata.color.pre_mul[3]]
    
    def raw2image(self):
        """
        This function allocates buffer for postprocessing (self.image) and fills
        it with data layout compatible with LibRaw 0.13/0.14 and below.
        If the buffer is already allocated, it will be free()ed and allocated again.

        This function should be called only if your code do postprocessing stage.
        If you use LibRaw's postprocessing calls (see below) you don't need to call raw2image().
        """
        self.handleError(self.p.raw2image())
    
    @property
    def image(self):
        cdef np.npy_intp shape[2]
        shape[0] = <np.npy_intp> self.p.imgdata.sizes.iheight
        shape[1] = <np.npy_intp> self.p.imgdata.sizes.iwidth
        return [np.PyArray_SimpleNewFromData(2, shape, np.NPY_USHORT, self.p.imgdata.image[0]),
                np.PyArray_SimpleNewFromData(2, shape, np.NPY_USHORT, self.p.imgdata.image[1]),
                np.PyArray_SimpleNewFromData(2, shape, np.NPY_USHORT, self.p.imgdata.image[2]),
                np.PyArray_SimpleNewFromData(2, shape, np.NPY_USHORT, self.p.imgdata.image[3])]
                
    def dcraw_process(self, params=None, **kw):
        if libraw_version < (0,15):
            if self.needs_reopening:
                warnings.warn('Repeated postprocessing with libraw<0.15 may require reopening/unpacking')
            self.needs_reopening = True
        if params is None:
            params = Params(**kw)
        self.applyParams(params)
        self.handleError(self.p.dcraw_process())
        
    def dcraw_make_mem_image(self):
        cdef int errcode = 0
        cdef libraw_processed_image_t* img = self.p.dcraw_make_mem_image(&errcode)
        self.handleError(errcode)
        if img.type != LIBRAW_IMAGE_BITMAP:
            raise NotImplementedError
        wrapped = processed_image_wrapper()
        wrapped.set_data(self, img)
        ndarr = wrapped.__array__()
        return ndarr
                
    def postprocess(self, params=None, **kw):
        """
        Return post-processed image as numpy array.  
        """
        self.dcraw_process(params, **kw)
        return self.dcraw_make_mem_image()
        
    cdef applyParams(self, params):
        if params is None:
            return
        cdef libraw_output_params_t* p = &self.p.imgdata.params
        p.user_qual = params.user_qual
        p.use_camera_wb = params.use_camera_wb
        p.use_auto_wb = params.use_auto_wb
        if params.user_mul:
            for i in range(4):
                p.user_mul[i] = params.user_mul[i]
        p.output_color = params.output_color
        p.output_bps = params.output_bps
        p.user_flip = params.user_flip
        p.user_black = params.user_black
        p.user_sat = params.user_sat
        p.no_auto_bright = params.no_auto_bright
        p.auto_bright_thr = params.auto_bright_thr
        p.adjust_maximum_thr = params.adjust_maximum_thr
        p.exp_correc = params.exp_correc
        p.exp_shift = params.exp_shift
        p.exp_preser = params.exp_preser
        if params.bad_pixels:
            p.bad_pixels = params.bad_pixels
        else:
            p.bad_pixels = NULL
{'fraction_non_alphanumeric': 0.0691358024691358, 'fraction_numerical': 0.007744107744107744, 'mean_word_length': 1.8176451986929483, 'pattern_counts': {'":': 4, '<': 20, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2161052', 'n_tokens_mistral': 8683, 'n_tokens_neox': 8304, 'n_words': 2026}