potrace_bitmap_t *bitmapFromImage(const QImage &image, int threshold) { // De momento no implementamos que la imagen no tenga alpha channel // Q_ASSERT(image.hasAlphaChannel()); potrace_bitmap_t *bitmap = bm_new(image.width(), image.height()); int pi = 0; for(int i = 0; i < image.byteCount(); i += 4) { int x = pi % image.width(); int y = pi / image.width(); int p; if(image.hasAlphaChannel()) { p = (image.bits()[i+3] > threshold)? 1 : 0; } else { p = (image.bits()[i] > threshold)? 0 : 1; } BM_PUT(bitmap, x, y, p); ++pi; } return bitmap; }
/* Convert greymap to bitmap by using cutoff threshold c (0=black, 1=white). On error, return NULL with errno set. */ static potrace_bitmap_t *threshold(greymap_t *gm, double c) { int w, h; potrace_bitmap_t *bm_out = NULL; double c1; int x, y; double p; w = gm->w; h = gm->h; /* allocate output bitmap */ bm_out = bm_new(w, h); if (!bm_out) { return NULL; } /* thresholding */ c1 = c * 255; for (y=0; y<h; y++) { for (x=0; x<w; x++) { p = GM_UGET(gm, x, y); BM_UPUT(bm_out, x, y, p < c1); } } return bm_out; }
/* duplicate the given bitmap. Return NULL on error with errno set. */ potrace_bitmap_t *bm_dup(const potrace_bitmap_t *bm) { potrace_bitmap_t *bm1 = bm_new(bm->w, bm->h); size_t size = (size_t)bm->dy * (size_t)bm->h * (size_t)BM_WORDSIZE; if (!bm1) { return NULL; } memcpy(bm1->map, bm->map, size); return bm1; }
/** Initialize the memory pointed at by sg. * @note The creator and created thread ID's may be equal. */ static void sg_init(Segment* const sg, DrdThreadId const creator, DrdThreadId const created) { Segment* creator_sg; ThreadId vg_created = DrdThreadIdToVgThreadId(created); tl_assert(sg); tl_assert(creator == DRD_INVALID_THREADID || IsValidDrdThreadId(creator)); creator_sg = (creator != DRD_INVALID_THREADID ? thread_get_segment(creator) : 0); sg->next = 0; sg->prev = 0; sg->refcnt = 1; if (vg_created != VG_INVALID_THREADID && VG_(get_SP)(vg_created) != 0) sg->stacktrace = VG_(record_ExeContext)(vg_created, 0); else sg->stacktrace = 0; if (creator_sg) vc_copy(&sg->vc, &creator_sg->vc); else vc_init(&sg->vc, 0, 0); vc_increment(&sg->vc, created); sg->bm = bm_new(); if (drd_trace_segment) { char msg[256]; VG_(snprintf)(msg, sizeof(msg), "New segment for thread %d/%d for vc ", creator != VG_INVALID_THREADID ? DrdThreadIdToVgThreadId(creator) : DRD_INVALID_THREADID, creator); vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), &sg->vc); VG_(message)(Vg_UserMsg, "%s", msg); } }
int main() { int i, j; bitmatrix bm = bm_new(MAX, MAX); // writing for (i = 0; i < MAX; i++) { for (j = 0; j < MAX; j++) { bm_set(bm, i, j, i == j); } } // reading for (i = 0; i < MAX; i++) { for (j = 0; j < MAX; j++) { assert(bm_get(bm, i, j) == (i == j)); } } bm_free(bm); }
int main() { int x, y, i; potrace_bitmap_t *bm; potrace_param_t *param; potrace_path_t *p; potrace_state_t *st; int n, *tag; potrace_dpoint_t(*c)[3]; /* create a bitmap */ bm = bm_new(WIDTH, HEIGHT); if (!bm) { fprintf(stderr, "Error allocating bitmap: %s\n", strerror(errno)); return 1; } /* fill the bitmap with some pattern */ for (y = 0; y < HEIGHT; y++) { for (x = 0; x < WIDTH; x++) { BM_PUT(bm, x, y, ((x * x + y * y * y) % 10000 < 5000) ? 1 : 0); } } /* set tracing parameters, starting from defaults */ param = potrace_param_default(); if (!param) { fprintf(stderr, "Error allocating parameters: %s\n", strerror(errno)); return 1; } param->turdsize = 0; /* trace the bitmap */ st = potrace_trace(param, bm); if (!st || st->status != POTRACE_STATUS_OK) { fprintf(stderr, "Error tracing bitmap: %s\n", strerror(errno)); return 1; } bm_free(bm); /* output vector data, e.g. as a rudimentary EPS file */ printf("%%!PS-Adobe-3.0 EPSF-3.0\n"); printf("%%%%BoundingBox: 0 0 %d %d\n", WIDTH, HEIGHT); printf("gsave\n"); /* draw each curve */ p = st->plist; while (p != NULL) { n = p->curve.n; tag = p->curve.tag; c = p->curve.c; printf("%f %f moveto\n", c[n - 1][2].x, c[n - 1][2].y); for (i = 0; i < n; i++) { switch (tag[i]) { case POTRACE_CORNER: printf("%f %f lineto\n", c[i][1].x, c[i][1].y); printf("%f %f lineto\n", c[i][2].x, c[i][2].y); break; case POTRACE_CURVETO: printf("%f %f %f %f %f %f curveto\n", c[i][0].x, c[i][0].y, c[i][1].x, c[i][1].y, c[i][2].x, c[i][2].y); break; } } /* at the end of a group of a positive path and its negative children, fill. */ if (p->next == NULL || p->next->sign == '+') { printf("0 setgray fill\n"); } p = p->next; } printf("grestore\n"); printf("%%EOF\n"); potrace_state_free(st); potrace_param_free(param); return 0; }
JNIEXPORT jobject JNICALL Java_com_jiangpeng_android_antrace_Utils_traceImage(JNIEnv* env, jobject thiz, jobject bitmap) { AndroidBitmapInfo info; int ret = 0; void* src_pixels = 0; if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) { return NULL; } if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { return NULL; } if ((ret = AndroidBitmap_lockPixels(env, bitmap, &src_pixels)) < 0) { return NULL; } potrace_param_t* param_t = potrace_param_default(); param_t->turdsize = 15; param_t->opttolerance = 0.8; potrace_bitmap_t* bmp_t = bm_new(info.width, info.height); //memcpy(bmp_t->map, src_pixels, bmp_t->dy * bmp_t->h * BM_WORDSIZE); const int kShiftBits = 20; const int32_t kRedRatio = static_cast<int32_t>((1 << kShiftBits) * 0.21f); const int32_t kGreenRatio = static_cast<int32_t>((1 << kShiftBits) * 0.71f); const int32_t kBlueRatio = static_cast<int32_t>((1 << kShiftBits) * 0.07f); for (uint32_t scan_line = 0; scan_line < info.height; scan_line++) { pixel32_t* src = reinterpret_cast<pixel32_t*>(src_pixels); pixel32_t* src_line_end = src + info.width; int x = 0; while (src < src_line_end) { int32_t src_red = src->rgba8[0]; int32_t src_green = src->rgba8[1]; int32_t src_blue = src->rgba8[2]; int32_t src_alpha = src->rgba8[3]; int32_t dst_color = (kRedRatio * src_red + kGreenRatio * src_green + kBlueRatio * src_blue) >> kShiftBits; if (dst_color > 128) { BM_PUT(bmp_t, x, info.height - 1 - scan_line, 1); } else { BM_PUT(bmp_t, x, info.height - 1 - scan_line, 0); } src++; ++x; } src_pixels = reinterpret_cast<char*>(src_pixels) + info.stride; } if(s_state != NULL) { potrace_state_free(s_state); s_state = NULL; } s_state = potrace_trace(param_t, bmp_t); potrace_param_free(param_t); bm_free(bmp_t); AndroidBitmap_unlockPixels(env, bitmap); if (!s_state || s_state->status != POTRACE_STATUS_OK) { return NULL; } potrace_path_t* start = s_state->plist; jobject prev = 0; jclass cls = env->FindClass("com/jiangpeng/android/antrace/Objects/path"); jobject retPath = 0; for(potrace_path_t* n = start; n != 0; n = n->next) { jobject path = createPath(env, n); if(retPath == 0) { retPath = path; } if(prev != 0) { jfieldID fid = env->GetFieldID(cls, "next", "Lcom/jiangpeng/android/antrace/Objects/path;"); env->SetObjectField(prev, fid, path); env->DeleteLocalRef(prev); } prev = path; } env->DeleteLocalRef(cls); return retPath; }
static void *interpolate_cubic(greymap_t *gm, int s, int bilevel, double c) { int w, h; double4 *poly = NULL; /* poly[s][4]: fixed interpolation polynomials */ double p[4]; /* four current points */ double4 *window = NULL; /* window[s][4]: current state */ double t, v; int k, l, i, j, x, y; double c1 = 0; greymap_t *gm_out = NULL; potrace_bitmap_t *bm_out = NULL; SAFE_MALLOC(poly, s, double4); SAFE_MALLOC(window, s, double4); w = gm->w; h = gm->h; /* allocate output bitmap/greymap */ if (bilevel) { bm_out = bm_new(w*s, h*s); if (!bm_out) { goto malloc_error; } bm_clear(bm_out, 0); c1 = c * 255; } else { gm_out = gm_new(w*s, h*s); if (!gm_out) { goto malloc_error; } } /* pre-calculate interpolation polynomials */ for (k=0; k<s; k++) { t = k/(double)s; poly[k][0] = 0.5 * t * (t-1) * (1-t); poly[k][1] = -(t+1) * (t-1) * (1-t) + 0.5 * (t-1) * (t-2) * t; poly[k][2] = 0.5 * (t+1) * t * (1-t) - t * (t-2) * t; poly[k][3] = 0.5 * t * (t-1) * t; } /* interpolate */ for (y=0; y<h; y++) { x=0; for (i=0; i<4; i++) { for (j=0; j<4; j++) { p[j] = GM_BGET(gm, x+i-1, y+j-1); } for (k=0; k<s; k++) { window[k][i] = 0.0; for (j=0; j<4; j++) { window[k][i] += poly[k][j] * p[j]; } } } while (1) { for (l=0; l<s; l++) { for (k=0; k<s; k++) { v = 0.0; for (i=0; i<4; i++) { v += window[k][i] * poly[l][i]; } if (bilevel) { BM_UPUT(bm_out, x*s+l, y*s+k, v < c1); } else { GM_UPUT(gm_out, x*s+l, y*s+k, v); } } } x++; if (x>=w) { break; } for (i=0; i<3; i++) { for (k=0; k<s; k++) { window[k][i] = window[k][i+1]; } } i=3; for (j=0; j<4; j++) { p[j] = GM_BGET(gm, x+i-1, y+j-1); } for (k=0; k<s; k++) { window[k][i] = 0.0; for (j=0; j<4; j++) { window[k][i] += poly[k][j] * p[j]; } } } } free(poly); free(window); if (bilevel) { return (void *)bm_out; } else { return (void *)gm_out; } malloc_error: free(poly); free(window); return NULL; }
static void *interpolate_linear(greymap_t *gm, int s, int bilevel, double c) { int p00, p01, p10, p11; int i, j, x, y; double xx, yy, av; double c1 = 0; int w, h; double p0, p1; greymap_t *gm_out = NULL; potrace_bitmap_t *bm_out = NULL; w = gm->w; h = gm->h; /* allocate output bitmap/greymap */ if (bilevel) { bm_out = bm_new(w*s, h*s); if (!bm_out) { return NULL; } bm_clear(bm_out, 0); c1 = c * 255; } else { gm_out = gm_new(w*s, h*s); if (!gm_out) { return NULL; } } /* interpolate */ for (i=0; i<w; i++) { for (j=0; j<h; j++) { p00 = GM_BGET(gm, i, j); p01 = GM_BGET(gm, i, j+1); p10 = GM_BGET(gm, i+1, j); p11 = GM_BGET(gm, i+1, j+1); if (bilevel) { /* treat two special cases which are very common */ if (p00 < c1 && p01 < c1 && p10 < c1 && p11 < c1) { for (x=0; x<s; x++) { for (y=0; y<s; y++) { BM_UPUT(bm_out, i*s+x, j*s+y, 1); } } continue; } if (p00 >= c1 && p01 >= c1 && p10 >= c1 && p11 >= c1) { continue; } } /* the general case */ for (x=0; x<s; x++) { xx = x/(double)s; p0 = p00*(1-xx) + p10*xx; p1 = p01*(1-xx) + p11*xx; for (y=0; y<s; y++) { yy = y/(double)s; av = p0*(1-yy) + p1*yy; if (bilevel) { BM_UPUT(bm_out, i*s+x, j*s+y, av < c1); } else { GM_UPUT(gm_out, i*s+x, j*s+y, av); } } } } } if (bilevel) { return (void *)bm_out; } else { return (void *)gm_out; } }
/** Compute a bitmap that represents the union of all memory accesses of all * segments that are unordered to the current segment of the thread tid. */ static void thread_compute_danger_set(struct bitmap** danger_set, const DrdThreadId tid) { Segment* p; tl_assert(0 <= (int)tid && tid < DRD_N_THREADS && tid != DRD_INVALID_THREADID); tl_assert(tid == s_drd_running_tid); s_update_danger_set_count++; s_danger_set_bitmap_creation_count -= bm_get_bitmap_creation_count(); s_danger_set_bitmap2_creation_count -= bm_get_bitmap2_creation_count(); if (*danger_set) { bm_delete(*danger_set); } *danger_set = bm_new(); if (s_trace_danger_set) { char msg[256]; VG_(snprintf)(msg, sizeof(msg), "computing danger set for thread %d/%d with vc ", DrdThreadIdToVgThreadId(tid), tid); vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), &s_threadinfo[tid].last->vc); VG_(message)(Vg_UserMsg, "%s", msg); } p = s_threadinfo[tid].last; { unsigned j; if (s_trace_danger_set) { char msg[256]; VG_(snprintf)(msg, sizeof(msg), "danger set: thread [%d] at vc ", tid); vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), &p->vc); VG_(message)(Vg_UserMsg, "%s", msg); } for (j = 0; j < sizeof(s_threadinfo) / sizeof(s_threadinfo[0]); j++) { if (j != tid && IsValidDrdThreadId(j)) { const Segment* q; for (q = s_threadinfo[j].last; q; q = q->prev) { if (! vc_lte(&q->vc, &p->vc) && ! vc_lte(&p->vc, &q->vc)) { if (s_trace_danger_set) { char msg[256]; VG_(snprintf)(msg, sizeof(msg), "danger set: [%d] merging segment ", j); vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), &q->vc); VG_(message)(Vg_UserMsg, "%s", msg); } bm_merge2(*danger_set, q->bm); } else { if (s_trace_danger_set) { char msg[256]; VG_(snprintf)(msg, sizeof(msg), "danger set: [%d] ignoring segment ", j); vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg), &q->vc); VG_(message)(Vg_UserMsg, "%s", msg); } } } } } } s_danger_set_bitmap_creation_count += bm_get_bitmap_creation_count(); s_danger_set_bitmap2_creation_count += bm_get_bitmap2_creation_count(); if (0 && s_trace_danger_set) { VG_(message)(Vg_UserMsg, "[%d] new danger set:", tid); bm_print(*danger_set); VG_(message)(Vg_UserMsg, "[%d] end of new danger set.", tid); } }