예제 #1
0
/*
 * API to manage shader effects
 */
static void
TransformerReleaseCallback(void *ptr)
{
  Transformer *transformer = (Transformer*)ptr;

  if (transformer == NULL) {
    return;
  }

  if (transformer->destbuf != NULL) {
    Ymem_free(transformer->destbuf);
    transformer->destbuf = NULL;
    transformer->destaligned = NULL;
  }

  if (transformer->bltmap != NULL) {
    Ymem_free(transformer->bltmap);
    transformer->bltmap = NULL;
  }

  if (transformer->statsbuf != NULL) {
    Ymem_free(transformer->statsbuf);
    transformer->statsbuf = NULL;
  }

  Ymem_free(transformer);
}
예제 #2
0
static void
vbitmap_release_callback(void *ptr)
{
  Vbitmap *vbitmap;

  if (ptr == NULL) {
    return;
  }

  vbitmap = (Vbitmap*)ptr;

  if (vbitmap->bitmaptype == VBITMAP_MEMORY) {
    if (vbitmap->pixels != NULL) {
      Ymem_free(vbitmap->pixels);
    }
    if (vbitmap->region != NULL) {
      Ymem_free(vbitmap->region);
    }
  }
  if (vbitmap->bitmaptype == VBITMAP_ANDROID) {
    if (vbitmap->jbitmap != NULL) {
      if (vbitmap->jkeepref) {
        JNIEnv *jenv = getEnv(vbitmap);
        if (jenv != NULL) {
          (*jenv)->DeleteGlobalRef(jenv, vbitmap->jbitmap);
        }
      }
      vbitmap->jbitmap = NULL;
    }
  }

  Ymem_free(vbitmap);
}
예제 #3
0
파일: ybuffer.c 프로젝트: cwnga/ygloo-yosal
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;
}
예제 #4
0
파일: ybuffer.c 프로젝트: cwnga/ygloo-yosal
void
Ybuffer_fini(Ybuffer *stream)
{
  char *data;

  data = Ybuffer_detach(stream, NULL);
  if (data != NULL) {
    Ymem_free(data);
  }

}
예제 #5
0
int
VbitmapRegionReset(Vbitmap *vbitmap)
{
    if (vbitmap != NULL) {
        if (vbitmap->region != NULL) {
            Ymem_free(vbitmap->region);
            vbitmap->region = NULL;
        }
        return YMAGINE_OK;
    }
    return YMAGINE_ERROR;
}
예제 #6
0
YOSAL_OBJECT_END

static void
vformat_release_callback(void *ptr)
{
  Vformat *vformat;

  if (ptr == NULL) {
    return;
  }

  vformat = (Vformat*) ptr;

  Ymem_free(vformat);
}
예제 #7
0
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;
}
예제 #8
0
파일: ybuffer.c 프로젝트: cwnga/ygloo-yosal
char*
Ybuffer_detach(Ybuffer *stream, int *datalen)
{
  char *data;

  if (stream == NULL) {
    data = NULL;
    if (datalen != NULL) {
      *datalen = 0;
    }
  } else {
    data = stream->data;
    if (datalen != NULL) {
      *datalen = stream->pos;
    }
    Ymem_free(stream);
  }

  return data;
}
예제 #9
0
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;
}
예제 #10
0
파일: webp.c 프로젝트: alexnj/ygloo-ymagine
static int
WEBPDecode(WEBPDec* pSrc, Vbitmap *vbitmap,
           YmagineFormatOptions *options)
{
  int contentSize;
  int origWidth = 0;
  int origHeight = 0;
  int quality;
  unsigned char header[WEBP_HEADER_SIZE + 32];
  int headerlen;
  int toRead;
  unsigned char *input = NULL;
  int inputlen;
  int oformat;
  int opitch;
  unsigned char *odata;
  int rc;
  Vrect srcrect;
  Vrect destrect;
  WebPIDecoder* idec;

  if (options == NULL) {
    /* Options argument is mandatory */
    return 0;
  }

  headerlen = YchannelRead(pSrc->channel, (char *) header, sizeof(header));
  if (headerlen < WEBP_HEADER_SIZE) {
    return 0;
  }

  /* Check WEBP header */
  contentSize = WebpCheckHeader((const char*) header, headerlen);
  if (contentSize <= 0) {
    return 0;
  }

  if (WebPGetInfo(header, headerlen, &origWidth, &origHeight) == 0) {
    ALOGD("invalid VP8 header");
    return 0;
  }

  if (origWidth <= 0 || origHeight <= 0) {
    return 0;
  }

  if (YmagineFormatOptions_invokeCallback(options, YMAGINE_IMAGEFORMAT_WEBP,
                                          origWidth, origHeight) != YMAGINE_OK) {
    return 0;
  }

  if (YmaginePrepareTransform(vbitmap, options,
                              origWidth, origHeight,
                              &srcrect, &destrect) != YMAGINE_OK) {
    return 0;
  }

#if YMAGINE_DEBUG_WEBP
  ALOGD("size: %dx%d req: %dx%d %s -> output: %dx%d",
        origWidth, origHeight,
        destrect.width, destrect.height,
        (options->scalemode == YMAGINE_SCALE_CROP) ? "crop" :
        (options->scalemode == YMAGINE_SCALE_FIT ? "fit" : "letterbox"),
        destrect.width, destrect.height);
#endif

  if (vbitmap != NULL) {
    if (options->resizable) {
      destrect.x = 0;
      destrect.y = 0;
      if (VbitmapResize(vbitmap, destrect.width, destrect.height) != YMAGINE_OK) {
        return 0;
      }
    }
    if (VbitmapType(vbitmap) == VBITMAP_NONE) {
      /* Decode bounds only, return positive number (number of lines) on success */
      return VbitmapHeight(vbitmap);
    }
  }

  pSrc->bitmap = vbitmap;

  inputlen = contentSize;
  toRead = inputlen - headerlen;

  rc = VbitmapLock(vbitmap);
  if (rc != YMAGINE_OK) {
    ALOGE("VbitmapLock() failed (code %d)", rc);
    rc = YMAGINE_ERROR;
  } else {
    odata = VbitmapBuffer(vbitmap);
    opitch = VbitmapPitch(vbitmap);
    oformat = VbitmapColormode(vbitmap);

    pSrc->inwidth = origWidth;
    pSrc->inheight = origHeight;
    pSrc->outwidth = destrect.width;
    pSrc->outheight = destrect.height;

    if (odata == NULL) {
      ALOGD("failed to get reference to pixel buffer");
      rc = YMAGINE_ERROR;
   } else {
      WebPDecoderConfig config;
      int supported = 1;
      int webpcolorspace;

      switch(oformat) {
      case VBITMAP_COLOR_RGBA:
        webpcolorspace = MODE_RGBA;
        break;
      case VBITMAP_COLOR_RGB:
        webpcolorspace = MODE_RGB;
        break;
      case VBITMAP_COLOR_rgbA:
        webpcolorspace = MODE_rgbA;
        break;
      case VBITMAP_COLOR_ARGB:
        webpcolorspace = MODE_ARGB;
        break;
      case VBITMAP_COLOR_Argb:
        webpcolorspace = MODE_Argb;
        break;
      case VBITMAP_COLOR_GRAYSCALE:
      case VBITMAP_COLOR_YUV:
      case VBITMAP_COLOR_CMYK:
      case VBITMAP_COLOR_YCbCr:
      default:
        supported = 0;
        break;
      }

      if (!supported) {
        ALOGD("currently only support RGB, RGBA webp decoding");
        rc = YMAGINE_ERROR;
      } else {
        pSrc->isdirect = 1;
        pSrc->outformat = oformat;
        pSrc->outbpp = VbitmapBpp(vbitmap);
        pSrc->outstride = opitch;
        pSrc->outbuffer = odata + destrect.x * pSrc->outbpp + destrect.y * pSrc->outstride;

        WebPInitDecoderConfig(&config);

        quality = YmagineFormatOptions_normalizeQuality(options);
        if (quality < 90) {
          config.options.no_fancy_upsampling = 1;
        }
        if (quality < 60) {
          config.options.bypass_filtering = 1;
        }
        config.options.use_threads = 1;

        if (srcrect.x != 0 || srcrect.y != 0 || srcrect.width != origWidth || srcrect.height != origHeight) {
          /* Crop on source */
          config.options.use_cropping = 1;
          config.options.crop_left = srcrect.x;
          config.options.crop_top = srcrect.y;
          config.options.crop_width = srcrect.width;
          config.options.crop_height = srcrect.height;
        }
        if (pSrc->outwidth != pSrc->inwidth || pSrc->outheight != pSrc->inheight) {
          config.options.use_scaling = 1;
          config.options.scaled_width = pSrc->outwidth;
          config.options.scaled_height = pSrc->outheight;
        }

        rc = YMAGINE_ERROR;

        // Specify the desired output colorspace:
        config.output.colorspace = webpcolorspace;

        // Have config.output point to an external buffer:
        config.output.u.RGBA.rgba = (uint8_t*) pSrc->outbuffer;
        config.output.u.RGBA.stride = pSrc->outstride;
        config.output.u.RGBA.size = pSrc->outstride * pSrc->outheight;
        config.output.is_external_memory = 1;

        idec = WebPIDecode(NULL, 0, &config);
        if (idec != NULL) {
          VP8StatusCode status;

          status = WebPIAppend(idec, header, headerlen);
          if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {
            int bytes_remaining = toRead;
            int bytes_read;
            int bytes_req;
            unsigned char rbuf[8192];

            // See WebPIUpdate(idec, buffer, size_of_transmitted_buffer);
            bytes_req = sizeof(rbuf);
            while (bytes_remaining > 0) {
              if (bytes_req > bytes_remaining) {
                bytes_req = bytes_remaining;
              }
              bytes_read = YchannelRead(pSrc->channel, rbuf, bytes_req);
              if (bytes_read <= 0) {
                break;
              }
              status = WebPIAppend(idec, (uint8_t*) rbuf, bytes_read);
              if (status == VP8_STATUS_OK) {
                rc = YMAGINE_OK;
                break;
              } else if (status == VP8_STATUS_SUSPENDED) {
                if (bytes_remaining > 0) {
                  bytes_remaining -= bytes_read;
                }
              } else {
                /* error */
                break;
              }
              // The above call decodes the current available buffer.
              // Part of the image can now be refreshed by calling
              // WebPIDecGetRGB()/WebPIDecGetYUVA() etc.
            }
          }
        }

        // the object doesn't own the image memory, so it can now be deleted.
        WebPIDelete(idec);
        WebPFreeDecBuffer(&config.output);
      }
    }

    VbitmapUnlock(vbitmap);
  }

  if (input) {
    Ymem_free((char*) input);
  }
  if (!pSrc->isdirect) {
    Ymem_free(pSrc->outbuffer);
  }

  if (rc == YMAGINE_OK) {
    return origHeight;
  }

  return 0;
}
예제 #11
0
/* 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;
}
예제 #12
0
/*
 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;
}