Example #1
0
static int bochs_init(struct pci_slot_dev *pci_dev) {
	int ret;
	struct fb_info *info;
	size_t mmap_len;

	assert(pci_dev != NULL);

	info = fb_alloc();
	if (info == NULL) {
		return -ENOMEM;
	}

	memcpy(&info->fix, &bochs_fix_screeninfo, sizeof info->fix);
	fill_var(&info->var);

	info->ops = &bochs_ops;
	info->screen_base = (void *)(pci_dev->bar[0] & ~0xf); /* FIXME */
	mmap_len = binalign_bound(VBE_DISPI_MAX_XRES * VBE_DISPI_MAX_YRES * VBE_DISPI_MAX_BPP / 8, PAGE_SIZE());

	if (MAP_FAILED == mmap_device_memory(info->screen_base,
				mmap_len,
			       	PROT_READ|PROT_WRITE|PROT_NOCACHE,
				MAP_FIXED,
				(unsigned long) info->screen_base)) {
		return -EIO;
	}

	ret = fb_register(info);
	if (ret != 0) {
		fb_release(info);
		return ret;
	}

	return 0;
}
Example #2
0
void imlib_replace(image_t *img, const char *path, image_t *other, int scalar, bool hmirror, bool vflip, bool transpose, image_t *mask)
{
    bool in_place = img->data == other->data;
    image_t temp;

    if (in_place) {
        memcpy(&temp, other, sizeof(image_t));
        temp.data = fb_alloc(image_size(&temp));
        memcpy(temp.data, other->data, image_size(&temp));
        other = &temp;
    }

    imlib_replace_line_op_state_t state;
    state.hmirror = hmirror;
    state.vflip = vflip;
    state.mask = mask;
    state.transpose = transpose;
    imlib_image_operation(img, path, other, scalar, imlib_replace_line_op, &state);

    if (in_place) {
        fb_free();
    }

    if (transpose) {
        int w = img->w;
        int h = img->h;
        img->w = h;
        img->h = w;
    }
}
Example #3
0
void umm_init_x( size_t size ) {
  uint32_t UMM_MALLOC_CFG_HEAP_SIZE = (size / sizeof(size_t)) * sizeof(size_t);
  if (UMM_MALLOC_CFG_HEAP_SIZE < (sizeof(umm_block) * 128)) fb_alloc_fail();
  if (UMM_MALLOC_CFG_HEAP_SIZE > (sizeof(umm_block) * 32768)) UMM_MALLOC_CFG_HEAP_SIZE = sizeof(umm_block) * 32768;
  void *UMM_MALLOC_CFG_HEAP_ADDR = fb_alloc(UMM_MALLOC_CFG_HEAP_SIZE);
  /* init heap pointer and size, and memset it to 0 */
  umm_heap = (umm_block *)UMM_MALLOC_CFG_HEAP_ADDR;
  umm_numblocks = (UMM_MALLOC_CFG_HEAP_SIZE / sizeof(umm_block));
  memset(umm_heap, 0x00, UMM_MALLOC_CFG_HEAP_SIZE);

  /* setup initial blank heap structure */
  {
    /* index of the 0th `umm_block` */
    const unsigned short int block_0th = 0;
    /* index of the 1st `umm_block` */
    const unsigned short int block_1th = 1;
    /* index of the latest `umm_block` */
    const unsigned short int block_last = UMM_NUMBLOCKS - 1;

    /* setup the 0th `umm_block`, which just points to the 1st */
    UMM_NBLOCK(block_0th) = block_1th;
    UMM_NFREE(block_0th)  = block_1th;
    UMM_PFREE(block_0th)  = block_1th;

    /*
     * Now, we need to set the whole heap space as a huge free block. We should
     * not touch the 0th `umm_block`, since it's special: the 0th `umm_block`
     * is the head of the free block list. It's a part of the heap invariant.
     *
     * See the detailed explanation at the beginning of the file.
     */

    /*
     * 1th `umm_block` has pointers:
     *
     * - next `umm_block`: the latest one
     * - prev `umm_block`: the 0th
     *
     * Plus, it's a free `umm_block`, so we need to apply `UMM_FREELIST_MASK`
     *
     * And it's the last free block, so the next free block is 0.
     */
    UMM_NBLOCK(block_1th) = block_last | UMM_FREELIST_MASK;
    UMM_NFREE(block_1th)  = 0;
    UMM_PBLOCK(block_1th) = block_0th;
    UMM_PFREE(block_1th)  = block_0th;

    /*
     * latest `umm_block` has pointers:
     *
     * - next `umm_block`: 0 (meaning, there are no more `umm_blocks`)
     * - prev `umm_block`: the 1st
     *
     * It's not a free block, so we don't touch NFREE / PFREE at all.
     */
    UMM_NBLOCK(block_last) = 0;
    UMM_PBLOCK(block_last) = block_1th;
  }
}
Example #4
0
static int cirrus_init(struct pci_slot_dev *pci_dev) {
	int ret;
	struct fb_info *info;

	assert(pci_dev != NULL);

	info = fb_alloc();
	if (info == NULL) {
		return -ENOMEM;
	}

	memcpy(&info->fix, &cl_fix_screeninfo, sizeof(info->fix));
	memcpy(&info->var, &cl_default_var_screeninfo, sizeof(info->var));
	info->ops = &cl_ops;
	info->screen_base = (void *)(pci_dev->bar[0] & PCI_BASE_ADDR_IO_MASK);

	ret = fb_register(info);
	if (ret != 0) {
		fb_release(info);
		return ret;
	}

	return 0;
}
Example #5
0
void imlib_gamma_corr(image_t *img, float gamma, float contrast, float brightness)
{
    gamma = IM_DIV(1.0, gamma);
    switch(img->bpp) {
        case IMAGE_BPP_BINARY: {
            float pScale = COLOR_BINARY_MAX - COLOR_BINARY_MIN;
            float pDiv = 1 / pScale;
            int *p_lut = fb_alloc((COLOR_BINARY_MAX - COLOR_BINARY_MIN + 1) * sizeof(int));

            for (int i = COLOR_BINARY_MIN; i <= COLOR_BINARY_MAX; i++) {
                int p = ((fast_powf(i * pDiv, gamma) * contrast) + brightness) * pScale;
                p_lut[i] = IM_MIN(IM_MAX(p , COLOR_BINARY_MIN), COLOR_BINARY_MAX);
            }

            for (int y = 0, yy = img->h; y < yy; y++) {
                uint32_t *data = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
                for (int x = 0, xx = img->w; x < xx; x++) {
                    int dataPixel = IMAGE_GET_BINARY_PIXEL_FAST(data, x);
                    int p = p_lut[dataPixel];
                    IMAGE_PUT_BINARY_PIXEL_FAST(data, x, p);
                }
            }

            fb_free();
            break;
        }
        case IMAGE_BPP_GRAYSCALE: {
            float pScale = COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN;
            float pDiv = 1 / pScale;
            int *p_lut = fb_alloc((COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN + 1) * sizeof(int));

            for (int i = COLOR_GRAYSCALE_MIN; i <= COLOR_GRAYSCALE_MAX; i++) {
                int p = ((fast_powf(i * pDiv, gamma) * contrast) + brightness) * pScale;
                p_lut[i] = IM_MIN(IM_MAX(p , COLOR_GRAYSCALE_MIN), COLOR_GRAYSCALE_MAX);
            }

            for (int y = 0, yy = img->h; y < yy; y++) {
                uint8_t *data = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
                for (int x = 0, xx = img->w; x < xx; x++) {
                    int dataPixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(data, x);
                    int p = p_lut[dataPixel];
                    IMAGE_PUT_GRAYSCALE_PIXEL_FAST(data, x, p);
                }
            }

            fb_free();
            break;
        }
        case IMAGE_BPP_RGB565: {
            float rScale = COLOR_R5_MAX - COLOR_R5_MIN;
            float gScale = COLOR_G6_MAX - COLOR_G6_MIN;
            float bScale = COLOR_B5_MAX - COLOR_B5_MIN;
            float rDiv = 1 / rScale;
            float gDiv = 1 / gScale;
            float bDiv = 1 / bScale;
            int *r_lut = fb_alloc((COLOR_R5_MAX - COLOR_R5_MIN + 1) * sizeof(int));
            int *g_lut = fb_alloc((COLOR_G6_MAX - COLOR_G6_MIN + 1) * sizeof(int));
            int *b_lut = fb_alloc((COLOR_B5_MAX - COLOR_B5_MIN + 1) * sizeof(int));

            for (int i = COLOR_R5_MIN; i <= COLOR_R5_MAX; i++) {
                int r = ((fast_powf(i * rDiv, gamma) * contrast) + brightness) * rScale;
                r_lut[i] = IM_MIN(IM_MAX(r , COLOR_R5_MIN), COLOR_R5_MAX);
            }

            for (int i = COLOR_G6_MIN; i <= COLOR_G6_MAX; i++) {
                int g = ((fast_powf(i * gDiv, gamma) * contrast) + brightness) * gScale;
                g_lut[i] = IM_MIN(IM_MAX(g , COLOR_G6_MIN), COLOR_G6_MAX);
            }

            for (int i = COLOR_B5_MIN; i <= COLOR_B5_MAX; i++) {
                int b = ((fast_powf(i * bDiv, gamma) * contrast) + brightness) * bScale;
                b_lut[i] = IM_MIN(IM_MAX(b , COLOR_B5_MIN), COLOR_B5_MAX);
            }

            for (int y = 0, yy = img->h; y < yy; y++) {
                uint16_t *data = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
                for (int x = 0, xx = img->w; x < xx; x++) {
                    int dataPixel = IMAGE_GET_RGB565_PIXEL_FAST(data, x);
                    int r = r_lut[COLOR_RGB565_TO_R5(dataPixel)];
                    int g = g_lut[COLOR_RGB565_TO_G6(dataPixel)];
                    int b = b_lut[COLOR_RGB565_TO_B5(dataPixel)];
                    IMAGE_PUT_RGB565_PIXEL_FAST(data, x, COLOR_R5_G6_B5_TO_RGB565(r, g, b));
                }
            }

            fb_free();
            fb_free();
            fb_free();
            break;
        }
        default: {
            break;
        }
    }
}
Example #6
0
static mp_obj_t py_lcd_display(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
    image_t *arg_img = py_image_cobj(args[0]);
    PY_ASSERT_TRUE_MSG(IM_IS_MUTABLE(arg_img), "Image format is not supported.");

    rectangle_t rect;
    py_helper_keyword_rectangle_roi(arg_img, n_args, args, 1, kw_args, &rect);

    // Fit X.
    int l_pad = 0, r_pad = 0;
    if (rect.w > width) {
        int adjust = rect.w - width;
        rect.w -= adjust;
        rect.x += adjust / 2;
    } else if (rect.w < width) {
        int adjust = width - rect.w;
        l_pad = adjust / 2;
        r_pad = (adjust + 1) / 2;
    }

    // Fit Y.
    int t_pad = 0, b_pad = 0;
    if (rect.h > height) {
        int adjust = rect.h - height;
        rect.h -= adjust;
        rect.y += adjust / 2;
    } else if (rect.h < height) {
        int adjust = height - rect.h;
        t_pad = adjust / 2;
        b_pad = (adjust + 1) / 2;
    }

    switch (type) {
        case LCD_NONE:
            return mp_const_none;
        case LCD_SHIELD:
            lcd_write_command_byte(0x2C);
            uint8_t *zero = fb_alloc0(width*2);
            uint16_t *line = fb_alloc(width*2);
            for (int i=0; i<t_pad; i++) {
                lcd_write_data(width*2, zero);
            }
            for (int i=0; i<rect.h; i++) {
                if (l_pad) {
                    lcd_write_data(l_pad*2, zero); // l_pad < width
                }
                if (IM_IS_GS(arg_img)) {
                    for (int j=0; j<rect.w; j++) {
                        uint8_t pixel = IM_GET_GS_PIXEL(arg_img, (rect.x + j), (rect.y + i));
                        line[j] = IM_RGB565(IM_R825(pixel),IM_G826(pixel),IM_B825(pixel));
                    }
                    lcd_write_data(rect.w*2, (uint8_t *) line);
                } else {
                    lcd_write_data(rect.w*2, (uint8_t *)
                        (((uint16_t *) arg_img->pixels) +
                        ((rect.y + i) * arg_img->w) + rect.x));
                }
                if (r_pad) {
                    lcd_write_data(r_pad*2, zero); // r_pad < width
                }
            }
            for (int i=0; i<b_pad; i++) {
                lcd_write_data(width*2, zero);
            }
            fb_free();
            fb_free();
            return mp_const_none;
    }
    return mp_const_none;
}
Example #7
0
void imlib_remove_shadows(image_t *img, const char *path, image_t *other, int scalar, bool single)
{
    if (!single) {
        imlib_remove_shadows_line_op_state_t state;

        for (int i = 0; i < imlib_remove_shadows_kernel_size; i++) {
            state.img_lines[i] = fb_alloc(img->w * sizeof(uint16_t));
            state.other_lines[i] = fb_alloc(img->w * sizeof(uint16_t));
            state.out_lines[i] = fb_alloc(img->w * sizeof(uint16_t));
        }

        state.lines_processed = 0;

        imlib_image_operation(img, path, other, scalar, imlib_remove_shadows_line_op, &state);

        for (int i = 0; i < imlib_remove_shadows_kernel_size; i++) {
            fb_free();
            fb_free();
            fb_free();
        }
    } else {

        // Create Shadow Mask

        image_t temp_image;
        temp_image.w = img->w;
        temp_image.h = img->h;
        temp_image.bpp = img->bpp;
        temp_image.data = fb_alloc(image_size(img));

        memcpy(temp_image.data, img->data, image_size(img));

        rectangle_t r;
        r.x = 0;
        r.y = 0;
        r.w = temp_image.w;
        r.h = temp_image.h;

        histogram_t h;
        h.LBinCount = COLOR_L_MAX - COLOR_L_MIN + 1;
        h.ABinCount = COLOR_A_MAX - COLOR_A_MIN + 1;
        h.BBinCount = COLOR_B_MAX - COLOR_B_MIN + 1;
        h.LBins = fb_alloc(h.LBinCount * sizeof(float));
        h.ABins = fb_alloc(h.ABinCount * sizeof(float));
        h.BBins = fb_alloc(h.BBinCount * sizeof(float));
        imlib_get_histogram(&h, &temp_image, &r, NULL, false);

        statistics_t s;
        imlib_get_statistics(&s, temp_image.bpp, &h);

        int sum = 0;
        int mean = s.LMean * 0.8f;

        for (int y = 0, yy = temp_image.h; y < yy; y++) {
            uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp_image, y);

            for (int x = 0, xx = temp_image.w; x < xx; x++) {
                sum += COLOR_RGB565_TO_L(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x)) < mean;
            }
        }

        if (sum > ((temp_image.w * temp_image.h) / 20)) { // Don't do anything if the image is mostly flat.

            threshold_t t;
            imlib_get_threshold(&t, temp_image.bpp, &h);

            list_t thresholds;
            list_init(&thresholds, sizeof(color_thresholds_list_lnk_data_t));
            color_thresholds_list_lnk_data_t lnk_data;
            lnk_data.LMin = COLOR_L_MIN;
            lnk_data.AMin = COLOR_A_MIN;
            lnk_data.BMin = COLOR_B_MIN;
            lnk_data.LMax = t.LValue;
            lnk_data.AMax = COLOR_A_MAX;
            lnk_data.BMax = COLOR_B_MAX;
            list_push_back(&thresholds, &lnk_data);
            imlib_binary(&temp_image, &temp_image, &thresholds, false, false, NULL);
            list_free(&thresholds);

            imlib_erode(&temp_image, 3, 30, NULL);
            imlib_dilate(&temp_image, 1, 1, NULL);

            // Get Shadow Average

            image_t temp_image_2;
            temp_image_2.w = temp_image.w;
            temp_image_2.h = temp_image.h;
            temp_image_2.bpp = temp_image.bpp;
            temp_image_2.data = fb_alloc(image_size(&temp_image));

            memcpy(temp_image_2.data, temp_image.data, image_size(&temp_image));
            imlib_erode(&temp_image_2, 3, 48, NULL);

            int shadow_r_sum = 0;
            int shadow_g_sum = 0;
            int shadow_b_sum = 0;
            int shadow_count = 0;

            for (int y = 0, yy = temp_image_2.h; y < yy; y++) {
                uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp_image_2, y);
                uint16_t *row_ptr_2 = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);

                for (int x = 0, xx = temp_image_2.w; x < xx; x++) {
                    if (IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x)) {
                        int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr_2, x);
                        int r = COLOR_RGB565_TO_R8(pixel);
                        int g = COLOR_RGB565_TO_G8(pixel);
                        int b = COLOR_RGB565_TO_R8(pixel);
                        shadow_r_sum += r;
                        shadow_g_sum += g;
                        shadow_b_sum += b;
                        shadow_count += 1;
                    }
                }
            }

            memcpy(temp_image_2.data, temp_image.data, image_size(&temp_image));
            imlib_invert(&temp_image_2);
            imlib_erode(&temp_image_2, 5, 120, NULL);
            imlib_invert(&temp_image_2);
            imlib_b_xor(&temp_image_2, NULL, &temp_image, 0, NULL);
            imlib_erode(&temp_image_2, 2, 24, NULL);

            int not_shadow_r_sum = 0;
            int not_shadow_g_sum = 0;
            int not_shadow_b_sum = 0;
            int not_shadow_count = 0;

            for (int y = 0, yy = temp_image_2.h; y < yy; y++) {
                uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp_image_2, y);
                uint16_t *row_ptr_2 = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);

                for (int x = 0, xx = temp_image_2.w; x < xx; x++) {
                    if (IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x)) {
                        int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr_2, x);
                        int r = COLOR_RGB565_TO_R8(pixel);
                        int g = COLOR_RGB565_TO_G8(pixel);
                        int b = COLOR_RGB565_TO_R8(pixel);
                        not_shadow_r_sum += r;
                        not_shadow_g_sum += g;
                        not_shadow_b_sum += b;
                        not_shadow_count += 1;
                    }
                }
            }

            // Fill in the umbra... (inner part of the shadow)...

            memcpy(temp_image_2.data, temp_image.data, image_size(&temp_image));

            imlib_mean_filter(&temp_image, 2, false, 0, false, NULL);

            if (shadow_count && not_shadow_count) {

                float shadow_r_average = ((float) shadow_r_sum) / ((float) shadow_count);
                float shadow_g_average = ((float) shadow_g_sum) / ((float) shadow_count);
                float shadow_b_average = ((float) shadow_b_sum) / ((float) shadow_count);

                float not_shadow_r_average = ((float) not_shadow_r_sum) / ((float) not_shadow_count);
                float not_shadow_g_average = ((float) not_shadow_g_sum) / ((float) not_shadow_count);
                float not_shadow_b_average = ((float) not_shadow_b_sum) / ((float) not_shadow_count);

                float diff_r = not_shadow_r_average - shadow_r_average;
                float diff_g = not_shadow_g_average - shadow_g_average;
                float diff_b = not_shadow_b_average - shadow_b_average;

                for (int y = 0; y < img->h; y++) {
                    uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&temp_image, y);
                    uint16_t *row_ptr_2 = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);

                    for (int x = 0; x < img->w; x++) {
                        float alpha = ((float) (COLOR_RGB565_TO_Y(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x)) - COLOR_Y_MIN)) / ((float) (COLOR_Y_MAX - COLOR_Y_MIN));
                        int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr_2, x);
                        int r = COLOR_RGB565_TO_R8(pixel);
                        int g = COLOR_RGB565_TO_G8(pixel);
                        int b = COLOR_RGB565_TO_B8(pixel);

                        int r_new = IM_MIN(IM_MAX(r + (diff_r * alpha), COLOR_R8_MIN), COLOR_R8_MAX);
                        int g_new = IM_MIN(IM_MAX(g + (diff_g * alpha), COLOR_G8_MIN), COLOR_G8_MAX);
                        int b_new = IM_MIN(IM_MAX(b + (diff_b * alpha), COLOR_B8_MIN), COLOR_B8_MAX);
                        IMAGE_PUT_RGB565_PIXEL_FAST(row_ptr_2, x, COLOR_R8_G8_B8_TO_RGB565(r_new, g_new, b_new));
                    }
                }
            }

            // Fill in the penumbra... (outer part of the shadow)...

            memcpy(temp_image.data, temp_image_2.data, image_size(&temp_image_2));

            imlib_erode(&temp_image_2, 1, 8, NULL);
            imlib_b_xor(&temp_image, NULL, &temp_image_2, 0, NULL);
            imlib_dilate(&temp_image, 3, 0, NULL);
            imlib_median_filter(img, 2, 12, false, 0, false, &temp_image);

            fb_free(); // temp_image_2
        }

        fb_free(); // BBins
        fb_free(); // ABins
        fb_free(); // LBins

        fb_free(); // temp_image
    }
}
Example #8
0
// returns null pointer without error if size==0
void *fb_alloc0(uint32_t size)
{
    void *mem = fb_alloc(size);
    memset(mem, 0, size);
    return mem;
}
Example #9
0
static void imlib_erode_dilate(image_t *img, int ksize, int threshold, int e_or_d, image_t *mask)
{
    int brows = ksize + 1;
    image_t buf;
    buf.w = img->w;
    buf.h = brows;
    buf.bpp = img->bpp;

    switch(img->bpp) {
        case IMAGE_BPP_BINARY: {
            buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows);

            for (int y = 0, yy = img->h; y < yy; y++) {
                uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
                uint32_t *buf_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows));

                for (int x = 0, xx = img->w; x < xx; x++) {
                    int pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x);
                    IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, pixel);

                    if ((mask && (!image_get_mask_pixel(mask, x, y)))
                    || (pixel == e_or_d)) {
                        continue; // Short circuit.
                    }

                    int acc = e_or_d ? 0 : -1; // Don't count center pixel...

                    for (int j = -ksize; j <= ksize; j++) {
                        uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img,
                            IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));

                        for (int k = -ksize; k <= ksize; k++) {
                            acc += IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr,
                                IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
                        }
                    }

                    if (!e_or_d) {
                        // Preserve original pixel value... or clear it.
                        if (acc < threshold) IMAGE_CLEAR_BINARY_PIXEL_FAST(buf_row_ptr, x);
                    } else {
                        // Preserve original pixel value... or set it.
                        if (acc > threshold) IMAGE_SET_BINARY_PIXEL_FAST(buf_row_ptr, x);
                    }
                }

                if (y >= ksize) { // Transfer buffer lines...
                    memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, (y - ksize)),
                           IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)),
                           IMAGE_BINARY_LINE_LEN_BYTES(img));
                }
            }

            // Copy any remaining lines from the buffer image...
            for (int y = img->h - ksize, yy = img->h; y < yy; y++) {
                memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y),
                       IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows)),
                       IMAGE_BINARY_LINE_LEN_BYTES(img));
            }

            fb_free();
            break;
        }
        case IMAGE_BPP_GRAYSCALE: {
            buf.data = fb_alloc(IMAGE_GRAYSCALE_LINE_LEN_BYTES(img) * brows);

            for (int y = 0, yy = img->h; y < yy; y++) {
                uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
                uint8_t *buf_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&buf, (y % brows));

                for (int x = 0, xx = img->w; x < xx; x++) {
                    int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x);
                    IMAGE_PUT_GRAYSCALE_PIXEL_FAST(buf_row_ptr, x, pixel);

                    if ((mask && (!image_get_mask_pixel(mask, x, y)))
                    || (COLOR_GRAYSCALE_TO_BINARY(pixel) == e_or_d)) {
                        continue; // Short circuit.
                    }

                    int acc = e_or_d ? 0 : -1; // Don't count center pixel...

                    for (int j = -ksize; j <= ksize; j++) {
                        uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img,
                            IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));

                        for (int k = -ksize; k <= ksize; k++) {
                            acc += COLOR_GRAYSCALE_TO_BINARY(IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr,
                                IM_MIN(IM_MAX(x + k, 0), (img->w - 1))));
                        }
                    }

                    if (!e_or_d) {
                        // Preserve original pixel value... or clear it.
                        if (acc < threshold) IMAGE_PUT_GRAYSCALE_PIXEL_FAST(buf_row_ptr, x,
                                                                            COLOR_GRAYSCALE_BINARY_MIN);
                    } else {
                        // Preserve original pixel value... or set it.
                        if (acc > threshold) IMAGE_PUT_GRAYSCALE_PIXEL_FAST(buf_row_ptr, x,
                                                                            COLOR_GRAYSCALE_BINARY_MAX);
                    }
                }

                if (y >= ksize) { // Transfer buffer lines...
                    memcpy(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, (y - ksize)),
                           IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)),
                           IMAGE_GRAYSCALE_LINE_LEN_BYTES(img));
                }
            }

            // Copy any remaining lines from the buffer image...
            for (int y = img->h - ksize, yy = img->h; y < yy; y++) {
                memcpy(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y),
                       IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&buf, (y % brows)),
                       IMAGE_GRAYSCALE_LINE_LEN_BYTES(img));
            }

            fb_free();
            break;
        }
        case IMAGE_BPP_RGB565: {
            buf.data = fb_alloc(IMAGE_RGB565_LINE_LEN_BYTES(img) * brows);

            for (int y = 0, yy = img->h; y < yy; y++) {
                uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
                uint16_t *buf_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&buf, (y % brows));

                for (int x = 0, xx = img->w; x < xx; x++) {
                    int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x);
                    IMAGE_PUT_RGB565_PIXEL_FAST(buf_row_ptr, x, pixel);

                    if ((mask && (!image_get_mask_pixel(mask, x, y)))
                    || (COLOR_RGB565_TO_BINARY(pixel) == e_or_d)) {
                        continue; // Short circuit.
                    }

                    int acc = e_or_d ? 0 : -1; // Don't count center pixel...

                    for (int j = -ksize; j <= ksize; j++) {
                        uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img,
                            IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));

                        for (int k = -ksize; k <= ksize; k++) {
                            acc += COLOR_RGB565_TO_BINARY(IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr,
                                IM_MIN(IM_MAX(x + k, 0), (img->w - 1))));
                        }
                    }

                    if (!e_or_d) {
                        // Preserve original pixel value... or clear it.
                        if (acc < threshold) IMAGE_PUT_RGB565_PIXEL_FAST(buf_row_ptr, x,
                                                                         COLOR_RGB565_BINARY_MIN);
                    } else {
                        // Preserve original pixel value... or set it.
                        if (acc > threshold) IMAGE_PUT_RGB565_PIXEL_FAST(buf_row_ptr, x,
                                                                         COLOR_RGB565_BINARY_MAX);
                    }
                }

                if (y >= ksize) { // Transfer buffer lines...
                    memcpy(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, (y - ksize)),
                           IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)),
                           IMAGE_RGB565_LINE_LEN_BYTES(img));
                }
            }

            // Copy any remaining lines from the buffer image...
            for (int y = img->h - ksize, yy = img->h; y < yy; y++) {
                memcpy(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y),
                       IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&buf, (y % brows)),
                       IMAGE_RGB565_LINE_LEN_BYTES(img));
            }

            fb_free();
            break;
        }
        default: {
            break;
        }
    }
}
Example #10
0
// returns null pointer without error if passed size==0
void *fb_alloc0(uint32_t size)
{
    void *mem = fb_alloc(size);
    memset(mem, 0, size); // does nothing if size is zero.
    return mem;
}