Example #1
0
static gboolean masks_form_is_in_roi(dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece,
                                     dt_masks_form_t *form, const dt_iop_roi_t *roi_in,
                                     const dt_iop_roi_t *roi_out)
{
  // we get the area for the form
  int fl, ft, fw, fh;

  if(!dt_masks_get_area(self, piece, form, &fw, &fh, &fl, &ft)) return FALSE;

  // is the form outside of the roi?
  fw *= roi_in->scale, fh *= roi_in->scale, fl *= roi_in->scale, ft *= roi_in->scale;
  if(ft >= roi_out->y + roi_out->height || ft + fh <= roi_out->y || fl >= roi_out->x + roi_out->width
     || fl + fw <= roi_out->x)
    return FALSE;

  return TRUE;
}
Example #2
0
void process (struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, void *i, void *o, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out)
{
    dt_iop_spots_params_t *d = (dt_iop_spots_params_t *)piece->data;
    dt_develop_blend_params_t *bp = self->blend_params;

    const int ch = piece->colors;
    const float *in = (float *)i;
    float *out = (float *)o;

    // we don't modify most of the image:
#ifdef _OPENMP
    #pragma omp parallel for schedule(static) default(none) shared(out,in,roi_in,roi_out)
#endif
    for (int k=0; k<roi_out->height; k++)
    {
        float *outb = out + ch*k*roi_out->width;
        const float *inb =  in + ch*roi_in->width*(k+roi_out->y-roi_in->y) + ch*(roi_out->x-roi_in->x);
        memcpy(outb, inb, sizeof(float)*roi_out->width*ch);
    }

    // iterate through all forms
    dt_masks_form_t *grp = dt_masks_get_from_id(self->dev,bp->mask_id);
    int pos=0;
    if (grp && (grp->type & DT_MASKS_GROUP))
    {
        GList *forms = g_list_first(grp->points);
        while(forms)
        {
            dt_masks_point_group_t *grpt = (dt_masks_point_group_t *)forms->data;
            //we get the spot
            dt_masks_form_t *form = dt_masks_get_from_id(self->dev,grpt->formid);
            if (!form)
            {
                forms = g_list_next(forms);
                pos++;
                continue;
            }
            //we get the area for the form
            int fl,ft,fw,fh;
            if (!dt_masks_get_area(self,piece,form,&fw,&fh,&fl,&ft))
            {
                forms = g_list_next(forms);
                pos++;
                continue;
            }

            //if the form is outside the roi, we just skip it
            fw *= roi_in->scale, fh *= roi_in->scale, fl *= roi_in->scale, ft *= roi_in->scale;
            if (ft>=roi_out->y+roi_out->height || ft+fh<=roi_out->y || fl>=roi_out->x+roi_out->width || fl+fw<=roi_out->x)
            {
                forms = g_list_next(forms);
                pos++;
                continue;
            }
            if (d->clone_algo[pos] == 1 && (form->type & DT_MASKS_CIRCLE))
            {
                dt_masks_point_circle_t *circle = (dt_masks_point_circle_t *)g_list_nth_data(form->points,0);
                // convert from world space:
                const int rad = circle->radius* MIN(piece->buf_in.width, piece->buf_in.height)*roi_in->scale;
                const int posx  = (circle->center[0] * piece->buf_in.width)*roi_in->scale - rad;
                const int posy  = (circle->center[1] * piece->buf_in.height)*roi_in->scale - rad;
                const int posx_source = (form->source[0]*piece->buf_in.width)*roi_in->scale - rad;
                const int posy_source = (form->source[1]*piece->buf_in.height)*roi_in->scale - rad;
                const int dx = posx-posx_source;
                const int dy = posy-posy_source;
                fw = fh = 2*rad;

                // convert from world space:
                float filter[2*rad + 1];

                if(rad > 0)
                {
                    for(int k=-rad; k<=rad; k++)
                    {
                        const float kk = 1.0f - fabsf(k/(float)rad);
                        filter[rad + k] = kk*kk*(3.0f - 2.0f*kk);
                    }
                }
                else
                {
                    filter[0] = 1.0f;
                }
                for (int yy=posy ; yy<posy+fh; yy++)
                {
                    //we test if we are inside roi_out
                    if (yy<roi_out->y || yy>=roi_out->y+roi_out->height) continue;
                    //we test if the source point is inside roi_in
                    if (yy-dy<roi_in->y || yy-dy>=roi_in->y+roi_in->height) continue;
                    for (int xx=posx ; xx<posx+fw; xx++)
                    {
                        //we test if we are inside roi_out
                        if (xx<roi_out->x || xx>=roi_out->x+roi_out->width) continue;
                        //we test if the source point is inside roi_in
                        if (xx-dx<roi_in->x || xx-dx>=roi_in->x+roi_in->width) continue;

                        const float f = filter[xx-posx+1]*filter[yy-posy+1];
                        for(int c=0; c<ch; c++)
                            out[4*(roi_out->width*(yy-roi_out->y) + xx-roi_out->x) + c] =
                                out[4*(roi_out->width*(yy-roi_out->y) + xx-roi_out->x) + c] * (1.0f-f) +
                                in[4*(roi_in->width*(yy-posy+posy_source-roi_in->y) + xx-posx+posx_source-roi_in->x) + c] * f;
                    }
                }
            }
            else
            {
                //we get the mask
                float *mask;
                int posx,posy,width,height;
                dt_masks_get_mask(self,piece,form,&mask,&width,&height,&posx,&posy);
                int fts = posy*roi_in->scale, fhs = height*roi_in->scale, fls = posx*roi_in->scale, fws = width*roi_in->scale;
                //now we search the delta with the source
                int dx,dy;
                dx=dy=0;
                if (form->type & DT_MASKS_PATH)
                {
                    dt_masks_point_path_t *pt = (dt_masks_point_path_t *)g_list_nth_data(form->points,0);
                    dx = pt->corner[0]*roi_in->scale*piece->buf_in.width - form->source[0]*roi_in->scale*piece->buf_in.width;
                    dy = pt->corner[1]*roi_in->scale*piece->buf_in.height - form->source[1]*roi_in->scale*piece->buf_in.height;
                }
                else if (form->type & DT_MASKS_CIRCLE)
                {
                    dt_masks_point_circle_t *pt = (dt_masks_point_circle_t *)g_list_nth_data(form->points,0);
                    dx = pt->center[0]*roi_in->scale*piece->buf_in.width - form->source[0]*roi_in->scale*piece->buf_in.width;
                    dy = pt->center[1]*roi_in->scale*piece->buf_in.height - form->source[1]*roi_in->scale*piece->buf_in.height;
                }
                if (dx!=0 || dy!=0)
                {
                    //now we do the pixel clone
                    for (int yy=fts+1 ; yy<fts+fhs-1; yy++)
                    {
                        //we test if we are inside roi_out
                        if (yy<roi_out->y || yy>=roi_out->y+roi_out->height) continue;
                        //we test if the source point is inside roi_in
                        if (yy-dy<roi_in->y || yy-dy>=roi_in->y+roi_in->height) continue;
                        for (int xx=fls+1 ; xx<fls+fws-1; xx++)
                        {
                            //we test if we are inside roi_out
                            if (xx<roi_out->x || xx>=roi_out->x+roi_out->width) continue;
                            //we test if the source point is inside roi_in
                            if (xx-dx<roi_in->x || xx-dx>=roi_in->x+roi_in->width) continue;

                            float f = mask[((int)((yy-fts)/roi_in->scale))*width + (int)((xx-fls)/roi_in->scale)];  //we can add the opacity here

                            for(int c=0; c<ch; c++)
                                out[4*(roi_out->width*(yy-roi_out->y) + xx-roi_out->x) + c] =
                                    out[4*(roi_out->width*(yy-roi_out->y) + xx-roi_out->x) + c] * (1.0f-f) +
                                    in[4*(roi_in->width*(yy-dy-roi_in->y) + xx-dx-roi_in->x) + c] * f;
                        }
                    }
                }
                free(mask);
            }
            pos++;
            forms = g_list_next(forms);
        }
    }
}
Example #3
0
void modify_roi_in(struct dt_iop_module_t *self, struct dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi_out, dt_iop_roi_t *roi_in)
{
    *roi_in = *roi_out;

    int roir = roi_in->width+roi_in->x;
    int roib = roi_in->height+roi_in->y;
    int roix = roi_in->x;
    int roiy = roi_in->y;

    //dt_iop_spots_params_t *d = (dt_iop_spots_params_t *)piece->data;
    dt_develop_blend_params_t *bp = self->blend_params;

    // We iterate through all spots or polygons
    dt_masks_form_t *grp = dt_masks_get_from_id(darktable.develop,bp->mask_id);
    if (grp && (grp->type & DT_MASKS_GROUP))
    {
        GList *forms = g_list_first(grp->points);
        while(forms)
        {
            dt_masks_point_group_t *grpt = (dt_masks_point_group_t *)forms->data;
            //we get the spot
            dt_masks_form_t *form = dt_masks_get_from_id(self->dev,grpt->formid);
            if (form)
            {
                //we get the area for the form
                int fl,ft,fw,fh;
                if (!dt_masks_get_area(self,piece,form,&fw,&fh,&fl,&ft))
                {
                    forms = g_list_next(forms);
                    continue;
                }

                //if the form is outside the roi, we just skip it
                fw *= roi_in->scale, fh *= roi_in->scale, fl *= roi_in->scale, ft *= roi_in->scale;
                if (ft>=roi_out->y+roi_out->height || ft+fh<=roi_out->y || fl>=roi_out->x+roi_out->width || fl+fw<=roi_out->x)
                {
                    forms = g_list_next(forms);
                    continue;
                }

                //we get the area for the source
                if (!dt_masks_get_source_area(self,piece,form,&fw,&fh,&fl,&ft))
                {
                    forms = g_list_next(forms);
                    continue;
                }
                fw *= roi_in->scale, fh *= roi_in->scale, fl *= roi_in->scale, ft *= roi_in->scale;

                //we enlarge the roi if needed
                roiy = fminf(ft,roiy);
                roix = fminf(fl,roix);
                roir = fmaxf(fl+fw,roir);
                roib = fmaxf(ft+fh,roib);
            }
            forms = g_list_next(forms);
        }
    }

    //now we set the values
    roi_in->x = CLAMP(roix, 0, piece->pipe->iwidth*roi_in->scale-1);
    roi_in->y = CLAMP(roiy, 0, piece->pipe->iheight*roi_in->scale-1);
    roi_in->width = CLAMP(roir-roi_in->x, 1, piece->pipe->iwidth*roi_in->scale-roi_in->x);
    roi_in->height = CLAMP(roib-roi_in->y, 1, piece->pipe->iheight*roi_in->scale-roi_in->y);
}