Ybuffer* Ybuffer_init(int initiallength) { char *data; Ybuffer *membuf; membuf = (Ybuffer*) Ymem_malloc(sizeof(Ybuffer)); if (membuf == NULL) { return NULL; } if (initiallength <= 0) { membuf->data = NULL; membuf->datalen = 0; membuf->dataincr = 64; } else { data = (char*) Ymem_malloc(initiallength); if (data == NULL) { Ymem_free(membuf); return NULL; } membuf->data = data; membuf->datalen = initiallength; membuf->dataincr = initiallength; } membuf->pos = 0; membuf->status = YBUFFER_STATUS_OK; return membuf; }
/* Preload data from file */ char* LoadDataFromFile(const char *filename, size_t *length) { int fd; struct stat statbuf; size_t flen = 0; char *fbase = NULL; char *p; size_t rem; ssize_t readlen; fd = open(filename, O_RDONLY); if (fd == -1) { return NULL; } /* Load image content in memory, to get rid of any risk of I/O and cache effect during benchmark */ fstat(fd, &statbuf); flen = statbuf.st_size; if (flen == 0) { close(fd); return NULL; } fbase = (char*) Ymem_malloc(flen); if (fbase == NULL) { close(fd); return NULL; } p = fbase; rem = flen; while (rem > 0) { readlen = read(fd, p, rem); if (readlen < 0) { free(fbase); close(fd); return NULL; } p += readlen; rem -= readlen; } close(fd); if (length != NULL) { *length = flen; } return fbase; }
static boolean APP1_handler (j_decompress_ptr cinfo) { int length; int i; unsigned char *data = NULL; if (cinfo == NULL) { return FALSE; } length = jpeg_getc(cinfo) << 8; length += jpeg_getc(cinfo); if (length < 2) { return FALSE; } length -= 2; /* Read marker data in memory. Also get sure buffer is null terminated Null terminates buffer to make it printable for debugging */ data = Ymem_malloc(length + 1); if (data == NULL) { return FALSE; } for (i = 0; i < length; i++) { data[i] = (unsigned char) jpeg_getc(cinfo); } data[length] = '\0'; int l = strlen(XMP_MARKER); if (length >= l + 1 && memcmp(data, XMP_MARKER, l) == 0 && data[l] == '\0') { VbitmapXmp xmp; Vbitmap *vbitmap = (Vbitmap*) cinfo->client_data; char *xmpbuf = (char*) (data + l + 1); int xmplen = length - (l + 1); /* Parse XML data */ if (parseXMP(&xmp, xmpbuf, xmplen) == YMAGINE_OK) { if (vbitmap != NULL) { VbitmapSetXMP(vbitmap, &xmp); } } } Ymem_free(data); return TRUE; }
int VbitmapRegionSelect(Vbitmap *vbitmap, int xmin, int ymin, int width, int height) { if (vbitmap == NULL) return YMAGINE_ERROR; if (vbitmap->region == NULL) { vbitmap->region = Ymem_malloc(sizeof(Vrect)); } // Checking again for NULL in case Ymem_malloc failed if (vbitmap->region != NULL) { vbitmap->region->x = xmin; vbitmap->region->y = ymin; vbitmap->region->width = (width < 0) ? 0 : width; vbitmap->region->height = (height < 0) ? 0 : height; return YMAGINE_OK; } return YMAGINE_ERROR; }
int getThemeColors(Vbitmap *vbitmap, int ncol, int *colors, int *scores) { int ncolors = 0; int i; if (vbitmap == NULL || ncol <= 0) { return 0; } Vcolor *vcolors = Ymem_malloc(ncol * sizeof(Vcolor)); if (vcolors != NULL) { ncolors = quantizeWithOptions(vbitmap, ncol, vcolors, scores, YMAGINE_THEME_SATURATION); for (i = 0; i < ncolors; i++) { colors[i] = RGBA(vcolors[i].red, vcolors[i].green, vcolors[i].blue, vcolors[i].alpha); } Ymem_free(vcolors); } return ncolors; }
static int TransformerPrepare(Transformer *transformer) { int pitch; void *tmpptr; unsigned char* alignedptr = NULL; int nlines; int alignment = 8; int i; YBOOL convolution; if (transformer == NULL) { return YMAGINE_ERROR; } convolution = transformer->convmode != TRANSFORMER_CONVOLUTION_NONE; if (transformer->srcrect.width <= 0 || transformer->srcrect.height <= 0) { /* No region set by caller, default to full input */ transformer->srcrect.x = 0; transformer->srcrect.y = 0; transformer->srcrect.width = transformer->srcw; transformer->srcrect.height = transformer->srch; } transformer->destrect.x = 0; transformer->destrect.y = 0; transformer->destrect.width = transformer->destw; transformer->destrect.height = transformer->desth; /* Intersect source region with actual window */ if (transformer->srcrect.width < 0) { transformer->srcrect.width = 0; } if (transformer->srcrect.height < 0) { transformer->srcrect.height = 0; } if (transformer->srcrect.x < 0) { transformer->srcrect.width += transformer->srcrect.x; transformer->srcrect.x = 0; } if (transformer->srcrect.y < 0) { transformer->srcrect.height += transformer->srcrect.y; transformer->srcrect.y = 0; } if (transformer->srcrect.x + transformer->srcrect.width > transformer->srcw) { transformer->srcrect.width = transformer->srcw - transformer->srcrect.x; } if (transformer->srcrect.y + transformer->srcrect.height > transformer->srch) { transformer->srcrect.height = transformer->srch - transformer->srcrect.y; } if (transformer->srcrect.x >= transformer->srcw || transformer->srcrect.y >= transformer->srch || transformer->srcrect.width <= 0 || transformer->srcrect.height <= 0 || transformer->srcrect.x + transformer->srcrect.width < 0 || transformer->srcrect.y + transformer->srcrect.height < 0) { /* Empty region */ transformer->srcrect.x = 0; transformer->srcrect.y = 0; transformer->srcrect.width = 0; transformer->srcrect.height = 0; } transformer->srcbpp = colorBpp(transformer->srcmode); transformer->destbpp = colorBpp(transformer->destmode); /* Allocate a working buffer large enough to contain at least 2 full lines at the output resolution, plus one working line */ nlines = 3; if (convolution) { /* allocates 3 more line convolution buffer for 3x3 convolution. we may get better cache performance when convolution buffer is allocated together with working buffer (closer to working buffer in memory). */ nlines += 3; } pitch = transformer->destw * transformer->destbpp; if (pitch % alignment) { pitch += alignment - (pitch % alignment); } if (pitch > 0) { tmpptr = Ymem_malloc_aligned(alignment, pitch * nlines, (void**) &alignedptr); if (tmpptr == NULL) { return YMAGINE_ERROR; } transformer->destbuf = tmpptr; transformer->destaligned = alignedptr; transformer->destpitch = pitch; /* Lines */ transformer->scaledbuf = alignedptr + transformer->destpitch * 0; transformer->curbuf = alignedptr + transformer->destpitch * 1; transformer->tmpbuf = alignedptr + transformer->destpitch * 2; if (convolution) { transformer->convcprev = alignedptr + transformer->destpitch * 3; transformer->convcur = alignedptr + transformer->destpitch * 4; transformer->convnext = alignedptr + transformer->destpitch * 5; } } /* Pre-compute offset table for line scaling */ if (transformer->destrect.width != transformer->srcrect.width && transformer->destrect.width > 0) { transformer->bltmap = (int*) Ymem_malloc(transformer->destrect.width * sizeof(int)); if (transformer->bltmap != NULL) { bltLinePrepare(transformer->bltmap, transformer->destrect.width, transformer->srcrect.width); } } if (transformer->statsmode > 0) { if (transformer->srcrect.width > 0 && transformer->srcrect.height > 0) { int nchannels; if (transformer->srcmode == VBITMAP_COLOR_GRAYSCALE) { nchannels = 1; } else if (transformer->srcmode == VBITMAP_COLOR_RGB) { nchannels = 3; } else if (transformer->srcmode == VBITMAP_COLOR_RGBA) { nchannels = 4; } else { nchannels = 0; } if (nchannels > 0) { transformer->statsbuf = Ymem_malloc(256 * nchannels * sizeof(int)); if (transformer->statsbuf != NULL) { transformer->histlum = transformer->statsbuf; for (i = 0; i < 256; i++) { transformer->histlum[i] = 0; } if (nchannels >= 3) { transformer->histr = transformer->statsbuf + 256 * 1; transformer->histg = transformer->statsbuf + 256 * 2; transformer->histb = transformer->statsbuf + 256 * 3; for (i = 0; i < 256; i++) { transformer->histr[i] = 0; transformer->histg[i] = 0; transformer->histb[i] = 0; } } } transformer->statscount = 0; } } } return YMAGINE_OK; }
/* Methods */ int VbitmapResize(Vbitmap *vbitmap, int width, int height) { if (vbitmap == NULL) { return YMAGINE_ERROR; } if (width <= 0 || height <= 0) { return YMAGINE_ERROR; } if (width == vbitmap->width && height == vbitmap->height) { /* Size not changed, ignore */ return YMAGINE_OK; } if (vbitmap->bitmaptype == VBITMAP_NONE) { vbitmap->width = width; vbitmap->height = height; return YMAGINE_OK; } if (vbitmap->bitmaptype == VBITMAP_ANDROID) { AndroidBitmapInfo bitmapinfo; jobject jbitmap; jobject jbitmapref; int ret; JNIEnv *jenv = getEnv(vbitmap); if (jenv == NULL) { return YMAGINE_ERROR; } jbitmap = createAndroidBitmap(jenv, width, height); if (jbitmap == NULL) { return YMAGINE_ERROR; } ret = AndroidBitmap_getInfo(jenv, jbitmap, &bitmapinfo); if (ret < 0 || bitmapinfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888 || bitmapinfo.width != width || bitmapinfo.height != height) { return YMAGINE_ERROR; } jbitmapref = (*jenv)->NewGlobalRef(jenv, jbitmap); if (jbitmapref == NULL) { return YMAGINE_ERROR; } /* Replace Bitmap */ if (vbitmap->jbitmap != NULL) { if (vbitmap->jkeepref) { (*jenv)->DeleteGlobalRef(jenv, vbitmap->jbitmap); vbitmap->jkeepref = 0; } vbitmap->jbitmap = NULL; } #if VBITMAP_ENABLE_GLOBAL_REF vbitmap->jbitmap = jbitmapref; vbitmap->jkeepref = 1; #else vbitmap->jbitmap = jbitmap; vbitmap->jkeepref = 0; (*jenv)->DeleteGlobalRef(jenv, jbitmapref); #endif vbitmap->width = bitmapinfo.width; vbitmap->height = bitmapinfo.height; vbitmap->pitch = bitmapinfo.stride; return YMAGINE_OK; } if (vbitmap->bitmaptype == VBITMAP_MEMORY) { int bpp = colorBpp(VbitmapColormode(vbitmap)); int pitch = width * bpp; unsigned char *pixels = NULL; if (pitch > 0) { pixels = Ymem_malloc(pitch * height); } if (pixels == NULL) { return YMAGINE_ERROR; } if (vbitmap->pixels != NULL) { Ymem_free(vbitmap->pixels); } vbitmap->pixels = pixels; vbitmap->width = width; vbitmap->height = height; vbitmap->pitch = pitch; return YMAGINE_OK; } if (vbitmap->bitmaptype == VBITMAP_STATIC) { /* Can't resize a static bitmap */ return YMAGINE_ERROR; } return YMAGINE_ERROR; }
/* A fast, yet not gaussian blurring algorithm. To approximate gaussian blur accurately, one can call blurSuperfast with a small radius and higher number of iterations */ int Ymagine_blurSuperfast(unsigned char *pix, int w, int h, int pitch, int colormode, int radius, int niter) { unsigned char *dv = NULL; int *vbuf = NULL; unsigned char *rgba = NULL; int wm, hm; int wh; int div; unsigned char *r, *g, *b, *a; int rsum, gsum, bsum, asum;; int x, y; int i, n; int p, p1, p2; int yi, zi, yw; int maxwh; int *vmin; int *vmax; int alpha = 255; int alpha2 = 255; int rc = YMAGINE_ERROR; int bpp; int roffset, goffset, boffset, aoffset; int premultiply = 0; if (radius <= 0 || niter <= 0) { return YMAGINE_OK; } if (w <= 0 || h <= 0) { return YMAGINE_OK; } switch (colormode) { case VBITMAP_COLOR_RGBA: bpp = 4; roffset = 0; goffset = 1; boffset = 2; aoffset = 3; premultiply = 0; break; case VBITMAP_COLOR_rgbA: bpp = 4; roffset = 0; goffset = 1; boffset = 2; aoffset = 3; premultiply = 1; break; case VBITMAP_COLOR_ARGB: bpp = 4; roffset = 1; goffset = 2; boffset = 3; aoffset = 0; premultiply = 0; break; case VBITMAP_COLOR_Argb: bpp = 4; roffset = 1; goffset = 2; boffset = 3; aoffset = 0; premultiply = 1; break; case VBITMAP_COLOR_RGB: bpp = 3; roffset = 0; goffset = 1; boffset = 2; aoffset = -1; premultiply = 0; break; default: return YMAGINE_ERROR; } maxwh = MAX(w, h); wm = w - 1; hm = h - 1; wh = w * h; div = radius + radius + 1; /* TODO: dont recalculate if calling multiple time with same radius */ dv = (unsigned char*) Ymem_malloc(256*div*sizeof(dv[0])); if (dv == NULL) { goto cleanup; } for (i = 0 ; i < 256 * div; i++) { dv[i] = (i / div); } vbuf = (int*) Ymem_malloc(maxwh * sizeof(vbuf[0]) * 2); if (vbuf == NULL) { goto cleanup; } rgba = Ymem_malloc(wh * 4); if (rgba == NULL) { goto cleanup; } r = rgba; g = r + wh; b = g + wh; a = b + wh; vmin = vbuf; vmax = vbuf + maxwh; for (n = 0; n < niter; n++) { yw = 0; /* Vertical pass */ for (y = 0; y < h; y++) { rsum = 0; gsum = 0; bsum = 0; asum = 0; yi = y * pitch; zi = y * w; for (i = -radius; i <= radius; i++) { p = yi + (MIN(wm, MAX(i,0)) * bpp); if (aoffset >= 0) { alpha = pix[p + aoffset]; } if (alpha == 255 || premultiply) { rsum += pix[p + roffset]; gsum += pix[p + goffset]; bsum += pix[p + boffset]; } else if (alpha != 0) { rsum += (pix[p + roffset] * alpha) / 255; gsum += (pix[p + goffset] * alpha) / 255; bsum += (pix[p + boffset] * alpha) / 255; } asum += alpha; } for (x = 0; x < w; x++) { r[zi] = dv[rsum]; g[zi] = dv[gsum]; b[zi] = dv[bsum]; a[zi] = dv[asum]; if (y == 0) { vmin[x] = MIN(x+radius+1, wm); vmax[x] = MAX(x-radius, 0); } p1 = yw + (vmin[x] * bpp); p2 = yw + (vmax[x] * bpp); if (aoffset >= 0) { alpha = pix[p1 + aoffset]; alpha2 = pix[p2 + aoffset]; } if ((alpha == 255 && alpha2 == 255) || premultiply) { rsum += pix[p1 + roffset] - pix[p2 + roffset]; gsum += pix[p1 + goffset] - pix[p2 + goffset]; bsum += pix[p1 + boffset] - pix[p2 + boffset]; } else { rsum += (pix[p1 + roffset] * alpha) / 255 - (pix[p2 + roffset] * alpha2) / 255; gsum += (pix[p1 + goffset] * alpha) / 255 - (pix[p2 + goffset] * alpha2) / 255; bsum += (pix[p1 + boffset] * alpha) / 255 - (pix[p2 + boffset] * alpha2) / 255; } asum += alpha - alpha2; zi++; } yw += pitch; } /* Horizontal pass */ for (x = 0; x < w; x++) { rsum = 0; gsum = 0; bsum = 0; asum = 0; for (i = -radius; i <= radius; i++) { yi = MIN(MAX(0,i),hm) * w + x; rsum += r[yi]; gsum += g[yi]; bsum += b[yi]; asum += a[yi]; } yi = x * bpp; for (y = 0; y < h; y++) { pix[yi + roffset] = dv[rsum]; pix[yi + goffset] = dv[gsum]; pix[yi + boffset] = dv[bsum]; if (aoffset >= 0) { pix[yi + aoffset] = dv[asum]; } if (x == 0) { vmin[y] = MIN(y+radius+1, hm)*w; vmax[y] = MAX(y-radius, 0)*w; } p1 = x + vmin[y]; p2 = x + vmax[y]; if (aoffset >= 0) { alpha = a[p1]; alpha2 = a[p2]; } rsum += r[p1] - r[p2]; gsum += g[p1] - g[p2]; bsum += b[p1] - b[p2]; if (alpha != alpha2) { asum += alpha - alpha2; } yi += pitch; } } } rc = YMAGINE_OK; cleanup: if (rgba != NULL) { Ymem_free(rgba); rgba = NULL; } if (vbuf != NULL) { Ymem_free(vbuf); vbuf = NULL; } if (dv != NULL) { Ymem_free(dv); dv = NULL; } return rc; }