int VbitmapBpp(Vbitmap *vbitmap) { if (vbitmap == NULL) { return 0; } return colorBpp(VbitmapColormode(vbitmap)); }
YOPTIMIZE_SPEED int YmagineMergeLine(unsigned char *destpixels, int destmode, int destweight, const unsigned char *srcpixels, int srcmode, int srcweight, int width) { int bpp; int rc = YMAGINE_ERROR; if (destweight < 0 || srcweight < 0 || destpixels == NULL || srcpixels == NULL) { return rc; } if (destmode != srcmode) { /* now only supports merge lines with same color mode */ return rc; } bpp = colorBpp(destmode); if (srcweight == 0) { /* Nothing to do */ rc = YMAGINE_OK; } else if (destweight == 0) { memcpy(destpixels, srcpixels, width * bpp * sizeof(unsigned char)); rc = YMAGINE_OK; } else { switch (destmode) { case VBITMAP_COLOR_GRAYSCALE: rc = mergeLine(destpixels, destweight, srcpixels, srcweight, width, 1, -1, 0); break; case VBITMAP_COLOR_RGB: rc = mergeLine(destpixels, destweight, srcpixels, srcweight, width, 3, -1, 0); break; case VBITMAP_COLOR_RGBA: rc = mergeLine(destpixels, destweight, srcpixels, srcweight, width, 4, 3, 0); break; case VBITMAP_COLOR_rgbA: rc = mergeLine(destpixels, destweight, srcpixels, srcweight, width, 4, 3, 1); break; case VBITMAP_COLOR_ARGB: rc = mergeLine(destpixels, destweight, srcpixels, srcweight, width, 4, 0, 0); break; case VBITMAP_COLOR_Argb: rc = mergeLine(destpixels, destweight, srcpixels, srcweight, width, 4, 0, 1); break; default: rc = mergeLine(destpixels, destweight, srcpixels, srcweight, width, bpp, -1, 0); break; } } return rc; }
int TransformerSetBitmap(Transformer *transformer, Vbitmap *vbitmap, int offsetx, int offsety) { int rc = YMAGINE_OK; if (transformer == NULL) { return YMAGINE_ERROR; } if (transformer->obitmap != NULL) { VbitmapUnlock(transformer->obitmap); } if (vbitmap != NULL) { rc = VbitmapLock(vbitmap); if (rc != YMAGINE_OK) { vbitmap = NULL; } } transformer->obitmap = vbitmap; if (vbitmap == NULL) { transformer->obitmap = NULL; transformer->obuffer = NULL; transformer->owidth = 0; transformer->oheight = 0; transformer->opitch = 0; transformer->omode = VBITMAP_COLOR_RGBA; transformer->obpp = 0; transformer->offsetx = 0; transformer->offsety = 0; } else { transformer->obitmap = vbitmap; transformer->obuffer = VbitmapBuffer(vbitmap); transformer->owidth = VbitmapWidth(vbitmap); transformer->oheight = VbitmapHeight(vbitmap); transformer->opitch = VbitmapPitch(vbitmap); transformer->omode = VbitmapColormode(vbitmap); transformer->obpp = colorBpp(transformer->omode); transformer->offsetx = offsetx; transformer->offsety = offsety; } return rc; }
Transformer* TransformerCreate() { Transformer* transformer; transformer = (Transformer*) yobject_create(sizeof(Transformer), TransformerReleaseCallback); if (transformer == NULL) { return NULL; } transformer->srcw = 0; transformer->srch = 0; transformer->destw = 0; transformer->desth = 0; transformer->nexty = 0; transformer->nextyf = YFIXED_ZERO; transformer->cury = transformer->nexty; transformer->curyf = transformer->nextyf; transformer->desty = -1; transformer->stashedweight = YFIXED_ZERO; transformer->srcrect.x = 0; transformer->srcrect.y = 0; transformer->srcrect.width = 0; transformer->srcrect.height = 0; transformer->destrect.x = 0; transformer->destrect.y = 0; transformer->destrect.width = 0; transformer->destrect.height = 0; /* 3x3 convolution */ transformer->convmode = TRANSFORMER_CONVOLUTION_NONE; transformer->convlinecount = 0; transformer->convcprev = NULL; transformer->convcur = NULL; transformer->convnext = NULL; /* transformer state */ transformer->srcline = -1; transformer->srcmode = VBITMAP_COLOR_RGBA; transformer->srcbpp = colorBpp(transformer->srcmode); transformer->destmode = VBITMAP_COLOR_RGBA; transformer->destbpp = colorBpp(transformer->destmode); transformer->destpitch = 0; transformer->destbuf = NULL; transformer->destaligned = NULL; transformer->statsmode = 0; transformer->statscount = 0; transformer->statsbuf = NULL; transformer->histr = NULL; transformer->histg = NULL; transformer->histb = NULL; transformer->histlum = NULL; transformer->scaledbuf = NULL; transformer->curbuf = NULL; transformer->tmpbuf = NULL; transformer->bltmap = NULL; transformer->obitmap = NULL; TransformerSetBitmap(transformer, NULL, 0, 0); transformer->shader = NULL; transformer->sharpen = 0.0f; /* Transformer writer callback */ transformer->writer = NULL; transformer->writerdata = NULL; return transformer; }
static YOPTIMIZE_SPEED int bltLineExt(unsigned char *opixels, int owidth, int oformat, const unsigned char *ipixels, int iwidth, int iformat, int *map) { int ibpp, obpp; int ialphaidx; int oalphaidx; if (owidth <= 0) { return YMAGINE_OK; } if (iwidth <= 0) { return YMAGINE_ERROR; } ibpp = colorBpp(iformat); obpp = colorBpp(oformat); if (owidth == iwidth) { if (iformat == oformat) { /* Neither scaling or color transformation */ memcpy(opixels, ipixels, owidth * obpp); return YMAGINE_OK; } /* No scaling but color conversion */ if (iformat == VBITMAP_COLOR_RGB) { if (oformat == VBITMAP_COLOR_rgbA || oformat == VBITMAP_COLOR_RGBA) { RGBtoRGBA(opixels, ipixels, iwidth); if (oformat == VBITMAP_COLOR_rgbA) { premultiplyRGBA(opixels, owidth, obpp); } return YMAGINE_OK; } if (oformat == VBITMAP_COLOR_Argb || oformat == VBITMAP_COLOR_ARGB) { RGBtoARGB(opixels, ipixels, iwidth); if (oformat == VBITMAP_COLOR_Argb) { premultiplyARGB(opixels, owidth, obpp); } return YMAGINE_OK; } } if (iformat == VBITMAP_COLOR_RGBA) { if (oformat == VBITMAP_COLOR_ARGB) { memcpy(opixels, ipixels, owidth * obpp); RGBAtoARGB(opixels, owidth, obpp); return YMAGINE_OK; } if (oformat == VBITMAP_COLOR_Argb) { memcpy(opixels, ipixels, owidth * obpp); RGBAtoARGB(opixels, owidth, obpp); premultiplyARGB(opixels, owidth, obpp); return YMAGINE_OK; } if (oformat == VBITMAP_COLOR_rgbA) { memcpy(opixels, ipixels, owidth * obpp); premultiplyRGBA(opixels, owidth, obpp); return YMAGINE_OK; } } } if (iformat != oformat) { int valid = 0; /* Only support a limited set of colorspace conversions */ if (oformat == VBITMAP_COLOR_RGBA|| oformat == VBITMAP_COLOR_ARGB || oformat == VBITMAP_COLOR_rgbA || oformat == VBITMAP_COLOR_Argb || oformat == VBITMAP_COLOR_RGB) { if (iformat == VBITMAP_COLOR_RGBA|| iformat == VBITMAP_COLOR_ARGB || iformat == VBITMAP_COLOR_rgbA || iformat == VBITMAP_COLOR_Argb || iformat == VBITMAP_COLOR_RGB || iformat == VBITMAP_COLOR_CMYK) { valid = 1; } } if (!valid) { return YMAGINE_ERROR; } } if (iformat == VBITMAP_COLOR_RGB && oformat == VBITMAP_COLOR_RGBA) { scaleLine(opixels, owidth, VBITMAP_COLOR_RGBA, 4, 3, ipixels, iwidth, VBITMAP_COLOR_RGB, 3, -1, map); } else if (iformat == VBITMAP_COLOR_RGB && oformat == VBITMAP_COLOR_rgbA) { scaleLine(opixels, owidth, VBITMAP_COLOR_rgbA, 4, 3, ipixels, iwidth, VBITMAP_COLOR_RGB, 3, -1, map); } else if (iformat == VBITMAP_COLOR_RGBA && oformat == VBITMAP_COLOR_RGBA) { scaleLine(opixels, owidth, VBITMAP_COLOR_RGBA, 4, 3, ipixels, iwidth, VBITMAP_COLOR_RGBA, 4, 3, map); } else if (iformat == VBITMAP_COLOR_RGBA && oformat == VBITMAP_COLOR_rgbA) { scaleLine(opixels, owidth, VBITMAP_COLOR_RGBA, 4, 3, ipixels, iwidth, VBITMAP_COLOR_rgbA, 4, 3, map); } else { if (iformat == VBITMAP_COLOR_RGBA) { ialphaidx = 3; } else { ialphaidx = -1; } if (oformat == VBITMAP_COLOR_RGBA) { oalphaidx = 3; } else { oalphaidx = -1; } scaleLine(opixels, owidth, oformat, obpp, oalphaidx, ipixels, iwidth, iformat, ibpp, ialphaidx, map); } return YMAGINE_OK; }
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; }
int Vbitmap_sobel(Vbitmap *outbitmap, Vbitmap *vbitmap) { int width; int height; int pitch; int bpp; unsigned char *pixels; int owidth; int oheight; int opitch; int obpp; unsigned char *opixels; int i, j; unsigned char *inp; unsigned char *outp; if (vbitmap == NULL) { return YMAGINE_ERROR; } if (VbitmapLock(vbitmap) >= 0) { pixels = VbitmapBuffer(vbitmap); width = VbitmapWidth(vbitmap); height = VbitmapHeight(vbitmap); pitch = VbitmapPitch(vbitmap); bpp = colorBpp(VbitmapColormode(vbitmap)); if (VbitmapLock(outbitmap) >= 0) { opixels = VbitmapBuffer(outbitmap); owidth = VbitmapWidth(outbitmap); oheight = VbitmapHeight(outbitmap); opitch = VbitmapPitch(outbitmap); obpp = colorBpp(VbitmapColormode(outbitmap)); if (width != owidth || height != oheight) { VbitmapUnlock(outbitmap); if (VbitmapResize(outbitmap, width, height) == YMAGINE_OK) { if (VbitmapLock(outbitmap) < 0) { VbitmapUnlock(vbitmap); return YMAGINE_ERROR; } opixels = VbitmapBuffer(outbitmap); owidth = VbitmapWidth(outbitmap); oheight = VbitmapHeight(outbitmap); opitch = VbitmapPitch(outbitmap); obpp = colorBpp(VbitmapColormode(outbitmap)); } } if (width == owidth && height == oheight && bpp >= 3) { for (j = 0; j < height; j++) { inp = pixels + pitch * j; outp = opixels + opitch * j; outp[0] = EnergySobel(inp, bpp, pitch, 0, j, width, height); outp += obpp; inp += bpp; if (j != 0 && j != height-1) { for (i = 1; i < width - 1; i++) { outp[0] = EnergySobelFast(inp, bpp, pitch); outp += obpp; inp += bpp; } } else { for (i = 1; i < width - 1; i++) { outp[0] = EnergySobel(inp, bpp, pitch, i, j, width, height); outp += obpp; inp += bpp; } } outp[0] = EnergySobel(inp, bpp, pitch, width - 1, j, width, height); } if (obpp >= 3) { for (j = 0; j < height; j++) { outp = opixels + opitch * j; for (i = 0; i < width; i++) { outp[1] = outp[0]; outp[2] = outp[0]; if (obpp == 4) { outp[0] = 0xff; } outp += obpp; } } } } VbitmapUnlock(outbitmap); } VbitmapUnlock(vbitmap); } return YMAGINE_OK; }