Страницы

вторник, 8 апреля 2014 г.

IMSH: Convert to black and white. SIOD interfacing

See more http://chiselapp.com/user/p4v31/repository/imsh/home

This is the example of "converting to black and white" algorithm (dummy implementation). It uses threahold value of RGB-vector length to "decide" what color to use: white or black:
int algo_bw(IMG *img, int threshold)
{
    RGBQUAD rgb;
    unsigned int row, col, width, height;
    double rgbl, maxrgbl;

    width = FreeImage_GetWidth(img);
    height = FreeImage_GetHeight(img);

    assert(img && width && height);

    maxrgbl = sqrt(255.*255. + 255.*255. + 255.*255.);

    for (row = 0; row < height; row++) {
        for (col = 0; col < width; col++) {
            FreeImage_GetPixelColor(img, col, row, &rgb);
            rgbl = RGBLEN(&rgb);
            if (rgbl*100/maxrgbl > threshold) {
                // light
                FreeImage_SetPixelColor(img, col, row, (RGBQUAD*)&RGB_WHITE);
            } else {
                // dark
                FreeImage_SetPixelColor(img, col, row, (RGBQUAD*)&RGB_BLACK);
            }
        }
    }
    return (0);
}
It uses FreeImage library. Idea is simple: detect length of RGB vector then compares it with some threshold value and set output pixel to white (if length of vector is less then threshold) or to black value. Here is example how to use SIOD. First, we create some wrapper:
LISP img_bw(LISP img, LISP threshold)
{
    IMG *_img = NULL;
    long _threshold;

    _img = LISP2IMG(img);
    _threshold = get_c_long(threshold);
    if (!algo_bw(_img, (int)_threshold))
        return (a_true_value());
    else return (NIL);
}
LISP2IMG is converter of LISP object into IMG C structure:
static IMG* LISP2IMG(LISP ptr)
{
    if (NTYPEP(ptr, tc_img)) err("not a IMG", ptr);
    if (!ptr->storage_as.string.data) err("IMG deallocated", ptr);
    else return ((IMG*)ptr->storage_as.string.data);
}
IMG is typedef of FIBITMAP (FreeImage type for images). Then we should register it as SIOD function:
init_subr_2("img_bw", img_bw);
but only after initialization of SIOD library:
long _kind;
tc_img = allocate_user_tc();
set_gc_hooks(tc_img, NULL, NULL, NULL, _img_gc_free, &_kind);
set_print_hooks(tc_img, _img_print);
init_storage();
init_subrs();
init_trace();
And then we can use it in SIOD-Scheme script:
(define b (img_open "pic1.jpg"))
(img_bw b)
(img_save b "out/bw.jpg")
Saving and loading of images are implemented as:
LISP img_open(LISP fname)
{
    IMG *img = NULL;
    LISP res;
    long intflag;
    char *_fname;
    FREE_IMAGE_FORMAT fif;

    _fname = get_c_string(fname);

    intflag = no_interrupt(1);
    fif = FreeImage_GetFileType(_fname, 0);
    if (fif == FIF_UNKNOWN) {
        fif = FreeImage_GetFIFFromFilename(_fname);
        if (fif == FIF_UNKNOWN) {
            // fif can not be determined
            res = err(__func__, llast_c_errmsg(-1));
            goto end;
        }
    }
    img = FreeImage_Load(fif, _fname, 0);
    if (!img) {
        res = err(__func__, llast_c_errmsg(-1));
    } else {
        res = cons(NIL, NIL);
        res->type = tc_img;
        res->storage_as.string.data = (char*)img;
    }
end:
    no_interrupt(intflag);
    return (res);
}

/** Save IMG to file
*/
LISP img_save(LISP img, LISP fname)
{
    IMG *_img = NULL;
    LISP res;
    long intflag;
    char *_fname;
    FREE_IMAGE_FORMAT fif;

    _img = LISP2IMG(img);
    _fname = get_c_string(fname);

    intflag = no_interrupt(1);
    fif = FreeImage_GetFIFFromFilename(_fname);
    if (fif == FIF_UNKNOWN) {
        res = err(__func__, llast_c_errmsg(-1));
        goto end;
    }
    if (!FreeImage_Save(fif, _img, _fname, 0)) {
        res = err(__func__, llast_c_errmsg(-1));
        goto end;
    } else {
        res = a_true_value();
    }
end:
    no_interrupt(intflag);
    return (res);
}

вторник, 4 марта 2014 г.

How to return value from C macro

Usually I use variable name in C macro as out parameter (it's standard way in Tcl, for example). But there is another way, something like in functional languages, with expression. See:
#define GETX(X) ({ \
        int x = (X)*2; \
        x; \
        })

void main()
{
    printf("%d\n", GETX(56));
}
This example shows hot to return value from GETX(), which really is expression. Works in GCC :)