Esempio n. 1
0
/**
 * \brief Initializes our filter.
 *
 * \param args The arguments passed in from the command line go here. This
 *             filter expects only a single argument telling it where the PGM
 *             or PPM file that describes the logo region is.
 *
 * This sets up our instance variables and parses the arguments to the filter.
 */
static int vf_open(vf_instance_t *vf, char *args)
{
  vf->priv = safe_malloc(sizeof(vf_priv_s));
  vf->uninit = uninit;

  /* Load our filter image. */
  if (args)
    vf->priv->filter = load_pgm(args);
  else
  {
    mp_msg(MSGT_VFILTER, MSGL_ERR, "[vf]remove_logo usage: remove_logo=/path/to/filter_image_file.pgm\n");
    free(vf->priv);
    return 0;
  }

  if (vf->priv->filter == NULL)
  {
    /* Error message was displayed by load_pgm(). */
    free(vf->priv);
    return 0;
  }

  /* Create the scaled down filter image for the chroma planes. */
  convert_mask_to_strength_mask(vf, vf->priv->filter);
  vf->priv->half_size_filter = generate_half_size_image(vf, vf->priv->filter);

  /* Now that we know how many masks we need (the info is in vf), we can generate the masks. */
  initialize_masks(vf);

  /* Calculate our bounding rectangles, which determine in what region the logo resides for faster processing. */
  calculate_bounding_rectangle(&vf->priv->bounding_rectangle_posx1, &vf->priv->bounding_rectangle_posy1,
                               &vf->priv->bounding_rectangle_posx2, &vf->priv->bounding_rectangle_posy2,
                                vf->priv->filter);
  calculate_bounding_rectangle(&vf->priv->bounding_rectangle_half_size_posx1,
                               &vf->priv->bounding_rectangle_half_size_posy1,
                               &vf->priv->bounding_rectangle_half_size_posx2,
                               &vf->priv->bounding_rectangle_half_size_posy2,
                                vf->priv->half_size_filter);

  vf->config=config;
  vf->put_image=put_image;
  vf->query_format=query_format;
  return 1;
}
Esempio n. 2
0
static av_cold int init(AVFilterContext *ctx, const char *args)
{
    RemovelogoContext *removelogo = ctx->priv;
    int ***mask;
    int ret = 0;
    int a, b, c, w, h;
    int full_max_mask_size, half_max_mask_size;

    if (!args) {
        av_log(ctx, AV_LOG_ERROR, "An image file must be specified as argument\n");
        return AVERROR(EINVAL);
    }

    /* Load our mask image. */
    if ((ret = load_mask(&removelogo->full_mask_data, &w, &h, args, ctx)) < 0)
        return ret;
    removelogo->mask_w = w;
    removelogo->mask_h = h;

    convert_mask_to_strength_mask(removelogo->full_mask_data, w, w, h,
                                  16, &full_max_mask_size);

    /* Create the scaled down mask image for the chroma planes. */
    if (!(removelogo->half_mask_data = av_mallocz(w/2 * h/2)))
        return AVERROR(ENOMEM);
    generate_half_size_image(removelogo->full_mask_data, w,
                             removelogo->half_mask_data, w/2,
                             w, h, &half_max_mask_size);

    removelogo->max_mask_size = FFMAX(full_max_mask_size, half_max_mask_size);

    /* Create a circular mask for each size up to max_mask_size. When
       the filter is applied, the mask size is determined on a pixel
       by pixel basis, with pixels nearer the edge of the logo getting
       smaller mask sizes. */
    mask = (int ***)av_malloc(sizeof(int **) * (removelogo->max_mask_size + 1));
    if (!mask)
        return AVERROR(ENOMEM);

    for (a = 0; a <= removelogo->max_mask_size; a++) {
        mask[a] = (int **)av_malloc(sizeof(int *) * ((a * 2) + 1));
        if (!mask[a])
            return AVERROR(ENOMEM);
        for (b = -a; b <= a; b++) {
            mask[a][b + a] = (int *)av_malloc(sizeof(int) * ((a * 2) + 1));
            if (!mask[a][b + a])
                return AVERROR(ENOMEM);
            for (c = -a; c <= a; c++) {
                if ((b * b) + (c * c) <= (a * a)) /* Circular 0/1 mask. */
                    mask[a][b + a][c + a] = 1;
                else
                    mask[a][b + a][c + a] = 0;
            }
        }
    }
    removelogo->mask = mask;

    /* Calculate our bounding rectangles, which determine in what
     * region the logo resides for faster processing. */
    ff_calculate_bounding_box(&removelogo->full_mask_bbox, removelogo->full_mask_data, w, w, h, 0);
    ff_calculate_bounding_box(&removelogo->half_mask_bbox, removelogo->half_mask_data, w/2, w/2, h/2, 0);

#define SHOW_LOGO_INFO(mask_type)                                       \
    av_log(ctx, AV_LOG_VERBOSE, #mask_type " x1:%d x2:%d y1:%d y2:%d max_mask_size:%d\n", \
           removelogo->mask_type##_mask_bbox.x1, removelogo->mask_type##_mask_bbox.x2, \
           removelogo->mask_type##_mask_bbox.y1, removelogo->mask_type##_mask_bbox.y2, \
           mask_type##_max_mask_size);
    SHOW_LOGO_INFO(full);
    SHOW_LOGO_INFO(half);

    return 0;
}