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; }
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; }