MDJVU_IMPLEMENT mdjvu_bitmap_t mdjvu_bitmap_crop (mdjvu_bitmap_t b, int32 left, int32 top, int32 w, int32 h) { if (left == 0 && top == 0 && w == BMP->width && h == BMP->height) { return mdjvu_bitmap_clone(b); } else { mdjvu_bitmap_t result; int32 i = top, count = h; unsigned char *buf; assert(left >= 0); assert(left + w <= BMP->width); assert(top >= 0); assert(top + h <= BMP->height); result = mdjvu_bitmap_create(w, h); buf = (unsigned char *) malloc(BMP->width); while (count--) { mdjvu_bitmap_unpack_row(b, buf, i); mdjvu_bitmap_pack_row(result, buf + left, i - top); i++; } free(buf); return result; } }
MDJVU_IMPLEMENT void mdjvu_bitmap_unpack_all (mdjvu_bitmap_t b, unsigned char **data) { int32 i = 0, h = BMP->height; for (i = 0; i < h; i++) { mdjvu_bitmap_unpack_row(b, data[i], i); } }
static void add_to_image(mdjvu_image_t image, mdjvu_bitmap_t bitmap, int32 dpi, mdjvu_split_options_t opt, int32 blit_shift_x, int32 blit_shift_y, int big) { int32 max_shape_size = opt ? * (int32 *) opt : 0; int32 width = mdjvu_bitmap_get_width(bitmap); int32 height = mdjvu_bitmap_get_height(bitmap); unsigned char **buf, **window_base, **window_buf, **map; int32 window_shift = 0, y = 0, i; if (!max_shape_size) max_shape_size = dpi; if (max_shape_size > height) max_shape_size = height; /* n-th line will be unpacked into buf[n % max_shape_size] + 1. * ( +1 is to make the left margin) * buf[max_shape_size] will always be blank. * * window_base[window_shift - 1] * points to buf[max_shape_size] + 1 (blank line) - top margin * window_base[window_shift + max_shape_size] * points to buf[max_shape_size] + 1 (blank line) - bottom margin * window_base[window_shift + i] * points to buf[(window_shift + i) % max_shape_size] + 1. */ /* map has the right margin of 1 */ map = mdjvu_create_2d_array(width + 1, max_shape_size); /* buf has left, right and bottom margins of 1 */ buf = mdjvu_create_2d_array(width + 2, max_shape_size + 1); window_buf = (unsigned char **) malloc(2 * (max_shape_size + 2) * sizeof(unsigned char *)); window_base = window_buf + 1; /* Unpack initial portion of the bitmap; bind the window to the buffer */ for (i = 0; i < max_shape_size; i++) { window_base[i] = window_base[max_shape_size + i] = buf[i] + 1; mdjvu_bitmap_unpack_row(bitmap, buf[i] + 1, i); } /* Setup top and bottom white margins */ window_base[-1] = window_base[2 * max_shape_size - 1] = buf[max_shape_size] + 1; /* The "window moving" loop. * We're moving a (width x max_shape_size) window through the image. */ while(1) { /* Extract some shapes from the window * (shapes touching the topmost row will be affected). */ unsigned char *top_margin_save = /* make the top margin */ window_base[window_shift - 1]; /* (save what was there) */ unsigned char *bot_margin_save = /* same with the bottom margin */ window_base[window_shift + max_shape_size]; int32 old_window_shift; window_base[window_shift - 1] = buf[max_shape_size] + 1; /* clear them */ window_base[window_shift + max_shape_size] = buf[max_shape_size] + 1; process_row(window_base + window_shift, map, /* index of a row to process: */ 0, width, max_shape_size, image, 0, y, max_shape_size, blit_shift_x, blit_shift_y, dpi, opt, big); window_base[window_shift - 1] = top_margin_save; /* restore margins */ window_base[window_shift + max_shape_size] = bot_margin_save; /* Shift the window */ y++; old_window_shift = window_shift; window_shift = y % max_shape_size; if (y + max_shape_size > height) break; /* Unpack a new row into the bottom window row */ mdjvu_bitmap_unpack_row(bitmap, buf[old_window_shift] + 1, y + max_shape_size - 1); } /* Process the last window fully */ for (i = 0; y + i < height; i++) { process_row(window_base + window_shift, map, /* index of a row to process: */ i, width, max_shape_size, image, 0, y, max_shape_size, blit_shift_x, blit_shift_y, dpi, opt, big); } /* Clean up */ free(window_buf); mdjvu_destroy_2d_array(map); mdjvu_destroy_2d_array(buf); }
MDJVU_IMPLEMENT mdjvu_bitmap_t mdjvu_average(mdjvu_bitmap_t *bitmaps, int32 n, int32 *cx, int32 *cy) { int32 i; int32 min_x = 0, min_y = 0, max_x_plus_1 = 0, max_y_plus_1 = 0; int32 *buf; int32 buf_w, buf_h; unsigned char *row; int32 tmp_x, tmp_y; int32 threshold = n / 2; mdjvu_bitmap_t result; if (n == 1) { return mdjvu_bitmap_clone(bitmaps[0]); } for (i = 0; i < n; i++) { int32 w = mdjvu_bitmap_get_width(bitmaps[i]); int32 h = mdjvu_bitmap_get_height(bitmaps[i]); int32 ncx = cx[i] / MDJVU_CENTER_QUANT; int32 ncy = cy[i] / MDJVU_CENTER_QUANT; assert(ncx >= 0 && ncx < w); assert(ncy >= 0 && ncy < h); if (-ncx < min_x) min_x = -ncx; if (-ncy < min_y) min_y = -ncy; if (w-ncx > max_x_plus_1) max_x_plus_1 = w-ncx; if (h-ncy > max_y_plus_1) max_y_plus_1 = h-ncy; } buf_w = max_x_plus_1 - min_x; buf_h = max_y_plus_1 - min_y; buf = (int32 *) calloc(buf_w * buf_h, sizeof(int32)); row = (unsigned char *) malloc(buf_w); /* Now adding the bitmaps to the buffer */ for (i = 0; i < n; i++) { int32 w = mdjvu_bitmap_get_width(bitmaps[i]); int32 h = mdjvu_bitmap_get_height(bitmaps[i]); int32 sx = min_x + cx[i] / MDJVU_CENTER_QUANT, sy = min_y + cy[i] / MDJVU_CENTER_QUANT; int32 x, y; for (y = 0; y < h; y++) { int32 *buf_row = buf + buf_w * (y - sy); mdjvu_bitmap_unpack_row(bitmaps[i], row, y); for (x = 0; x < w; x++) { if (row[x]) buf_row[x - sx]++; } } } result = mdjvu_bitmap_create(buf_w, buf_h); for (i = 0; i < buf_h; i++) { int32 j; for (j = 0; j < buf_w; j++) { row[j] = ( buf[i * buf_w + j] > threshold ? 1 : 0 ); } mdjvu_bitmap_pack_row(result, row, i); } mdjvu_bitmap_remove_margins(result, &tmp_x, &tmp_y); free(row); free(buf); return result; }