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 mdjvu_bitmap_t mdjvu_bitmap_clone(mdjvu_bitmap_t b) { mdjvu_bitmap_t result = mdjvu_bitmap_create(BMP->width, BMP->height); /* Using the fact that the 2d arrays by 2d_array() are really 1d ones */ memcpy(((Bitmap *) result)->data[0], BMP->data[0], ROW_SIZE * BMP->height); return result; }
/* This function does the same as interpret_runs_in_a_line(), * but on a rectangle. * Returns the rendered result. * Also clears it in pixels[][]. * `map' is cleared. */ static mdjvu_bitmap_t interpret_runs(int32 min_x, int32 max_x, int32 min_y, int32 max_y, unsigned char **map, unsigned char **pixels) { int32 w = max_x - min_x + 1; int32 h = max_y - min_y + 1; unsigned char *line_buf = (unsigned char *) malloc(w); mdjvu_bitmap_t bmp = mdjvu_bitmap_create(w, h); int32 y; for (y = min_y; y <= max_y; y++) { interpret_runs_in_a_line(min_x, max_x, map[y], line_buf, pixels[y]); mdjvu_bitmap_pack_row(bmp, line_buf, y - min_y); } free(line_buf); return bmp; }
MDJVU_IMPLEMENT mdjvu_bitmap_t mdjvu_get_erosion_mask(mdjvu_bitmap_t bmp) { int32 w = mdjvu_bitmap_get_width(bmp); int32 h = mdjvu_bitmap_get_height(bmp); mdjvu_bitmap_t result = mdjvu_bitmap_create(w, h); int32 i; unsigned char *u, *t, *l, *r; if (h < 3) return result; u = (unsigned char *) malloc(w); /* upper row */ t = (unsigned char *) malloc(w); /* this row */ l = (unsigned char *) malloc(w); /* lower row */ r = (unsigned char *) malloc(w); /* result */ mdjvu_bitmap_unpack_row_0_or_1(bmp, t, 0); mdjvu_bitmap_unpack_row_0_or_1(bmp, l, 1); for (i = 1; i < h - 1; i++) { unsigned char *tmp = u; u = t; t = l; l = tmp; mdjvu_bitmap_unpack_row_0_or_1(bmp, l, i + 1); get_erosion_candidates_in_a_row(r, u, t, l, w); mdjvu_bitmap_pack_row(result, r, i); } free(u); free(t); free(l); free(r); return result; }
static mdjvu_bitmap_t load_tiff(const char *path, int32 *presolution, mdjvu_error_t *perr, uint32 idx) { uint16 photometric; uint32 w, h; uint16 bits_per_sample = 0, samples_per_pixel = 0; float dpi; mdjvu_bitmap_t result; tsize_t scanline_size; unsigned char *scanline; uint32 i; TIFF *tiff = TIFFOpen(path, "r"); for ( i=0; tiff != NULL && i<idx; i++ ) { if (!TIFFReadDirectory(tiff)) break; } *perr = NULL; if (!tiff || i<idx) { *perr = mdjvu_get_error(mdjvu_error_fopen_read); return NULL; } /* test if bitonal */ TIFFGetFieldDefaulted(tiff, TIFFTAG_BITSPERSAMPLE, &bits_per_sample); TIFFGetFieldDefaulted(tiff, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel); if (bits_per_sample != 1 || samples_per_pixel != 1) { *perr = mdjvu_get_error(mdjvu_error_corrupted_tiff); TIFFClose(tiff); return NULL; } /* photometric */ photometric = PHOTOMETRIC_MINISWHITE; TIFFGetFieldDefaulted(tiff, TIFFTAG_PHOTOMETRIC, &photometric); /* image size */ if (!TIFFGetFieldDefaulted(tiff, TIFFTAG_IMAGEWIDTH, &w) || !TIFFGetFieldDefaulted(tiff, TIFFTAG_IMAGELENGTH, &h)) { *perr = mdjvu_get_error(mdjvu_error_corrupted_tiff); TIFFClose(tiff); return NULL; } /* get the resolution */ if (presolution && TIFFGetFieldDefaulted(tiff, TIFFTAG_XRESOLUTION, &dpi)) { *presolution = (int32) dpi; } result = mdjvu_bitmap_create(w, h); scanline_size = TIFFScanlineSize(tiff); if (scanline_size < mdjvu_bitmap_get_packed_row_size(result)) { *perr = mdjvu_get_error(mdjvu_error_corrupted_tiff); TIFFClose(tiff); mdjvu_bitmap_destroy(result); return NULL; } scanline = (unsigned char *) malloc(scanline_size); for (i = 0; i < h; i++) { if (TIFFReadScanline(tiff, (tdata_t)scanline, i, 0) < 0) { *perr = mdjvu_get_error(mdjvu_error_corrupted_tiff); TIFFClose(tiff); free(scanline); mdjvu_bitmap_destroy(result); return NULL; } if (photometric != PHOTOMETRIC_MINISWHITE) { /* invert the row */ int32 k; int32 s = (int32) scanline_size; for (k = 0; k < s; k++) scanline[k] = ~scanline[k]; } /* clear the padding bits */ if (scanline_size & 7) scanline[scanline_size - 1] &= ~(0xFF >> (scanline_size & 7)); memcpy(mdjvu_bitmap_access_packed_row(result, i), scanline, mdjvu_bitmap_get_packed_row_size(result)); } free(scanline); TIFFClose(tiff); return result; }
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; }