bool SkDisplacementMapEffect::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
                                   SkIRect* dst) const {
    SkIRect bounds = src;
    SkVector scale = SkVector::Make(fScale, fScale);
    ctm.mapVectors(&scale, 1);
    bounds.outset(SkScalarCeilToInt(scale.fX * SK_ScalarHalf),
                  SkScalarCeilToInt(scale.fY * SK_ScalarHalf));
    if (getColorInput()) {
        return getColorInput()->filterBounds(bounds, ctm, dst);
    }
    *dst = bounds;
    return true;
}
bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy,
                                            const SkBitmap& src,
                                            const SkMatrix& ctm,
                                            SkBitmap* dst,
                                            SkIPoint* offset) {
    SkBitmap displ, color = src;
    SkImageFilter* colorInput = getColorInput();
    SkImageFilter* displacementInput = getDisplacementInput();
    SkASSERT(NULL != displacementInput);
    if ((colorInput && !colorInput->filterImage(proxy, src, ctm, &color, offset)) ||
        !displacementInput->filterImage(proxy, src, ctm, &displ, offset)) {
        return false;
    }
    if ((displ.config() != SkBitmap::kARGB_8888_Config) ||
        (color.config() != SkBitmap::kARGB_8888_Config)) {
        return false;
    }

    SkAutoLockPixels alp_displacement(displ), alp_color(color);
    if (!displ.getPixels() || !color.getPixels()) {
        return false;
    }
    dst->setConfig(displ.config(), displ.width(), displ.height());
    dst->allocPixels();
    if (!dst->getPixels()) {
        return false;
    }

    computeDisplacement(fXChannelSelector, fYChannelSelector, fScale, dst, &displ, &color);

    return true;
}
bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy,
                                            const SkBitmap& src,
                                            const Context& ctx,
                                            SkBitmap* dst,
                                            SkIPoint* offset) const {
    SkBitmap displ = src, color = src;
    const SkImageFilter* colorInput = getColorInput();
    const SkImageFilter* displInput = getDisplacementInput();
    SkIPoint colorOffset = SkIPoint::Make(0, 0), displOffset = SkIPoint::Make(0, 0);
    if ((colorInput && !colorInput->filterImage(proxy, src, ctx, &color, &colorOffset)) ||
        (displInput && !displInput->filterImage(proxy, src, ctx, &displ, &displOffset))) {
        return false;
    }
    if ((displ.colorType() != kN32_SkColorType) ||
        (color.colorType() != kN32_SkColorType)) {
        return false;
    }
    SkIRect bounds;
    // Since computeDisplacement does bounds checking on color pixel access, we don't need to pad
    // the color bitmap to bounds here.
    if (!this->applyCropRect(ctx, color, colorOffset, &bounds)) {
        return false;
    }
    SkIRect displBounds;
    if (!this->applyCropRect(ctx, proxy, displ, &displOffset, &displBounds, &displ)) {
        return false;
    }
    if (!bounds.intersect(displBounds)) {
        return false;
    }
    SkAutoLockPixels alp_displacement(displ), alp_color(color);
    if (!displ.getPixels() || !color.getPixels()) {
        return false;
    }

    if (!dst->tryAllocPixels(color.info().makeWH(bounds.width(), bounds.height()))) {
        return false;
    }

    SkVector scale = SkVector::Make(fScale, fScale);
    ctx.ctm().mapVectors(&scale, 1);
    SkIRect colorBounds = bounds;
    colorBounds.offset(-colorOffset);

    computeDisplacement(fXChannelSelector, fYChannelSelector, scale, dst,
                        &displ, colorOffset - displOffset, &color, colorBounds);

    offset->fX = bounds.left();
    offset->fY = bounds.top();
    return true;
}
//Vores funktion, som bliver kaldt i while(1) loop'et. BestŒr at mange forskellige funktioner.
void getQuestion() {
	
    //F¿rst s¾tter vi v¾rdien needData til at v¾re lig med vores modtagData. Fordi PIC-2 sender tallet 1 til PIC-1 vil needData v¾re lig med 1.
    needData = modtagData();

    //Vi siger sŒ at needData skal v¾re 1 f¿r resten af funktionen kan bruges. Hvis vi ikke har fŒet et signal fra PIC-2 sŒ vil needData ikke v¾re 1 og derfor skal funktionen ikke g¿re noget.
	if(needData) {
        
        //Vi skal nu konvertere vores v¾rdi fra fotoresistoren til en v¾rdi som kan l¾ses af PIC'en.
		convertValAD();
        
        //Derefter skal vi definere hvad color er med et tal fra 1-6. 
        getColorInput();
        
        //Til sidst skal vi sende det tal til PIC-2
        sendInputToSecondPic();
	}
}
bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
                                             SkBitmap* result, SkIPoint* offset) const {
    SkBitmap colorBM = src;
    SkIPoint colorOffset = SkIPoint::Make(0, 0);
    if (getColorInput() && !getColorInput()->getInputResultGPU(proxy, src, ctx, &colorBM,
                                                               &colorOffset)) {
        return false;
    }
    SkBitmap displacementBM = src;
    SkIPoint displacementOffset = SkIPoint::Make(0, 0);
    if (getDisplacementInput() &&
        !getDisplacementInput()->getInputResultGPU(proxy, src, ctx, &displacementBM,
                                                   &displacementOffset)) {
        return false;
    }
    SkIRect bounds;
    // Since GrDisplacementMapEffect does bounds checking on color pixel access, we don't need to
    // pad the color bitmap to bounds here.
    if (!this->applyCropRect(ctx, colorBM, colorOffset, &bounds)) {
        return false;
    }
    SkIRect displBounds;
    if (!this->applyCropRect(ctx, proxy, displacementBM,
                             &displacementOffset, &displBounds, &displacementBM)) {
        return false;
    }
    if (!bounds.intersect(displBounds)) {
        return false;
    }
    GrTexture* color = colorBM.getTexture();
    GrTexture* displacement = displacementBM.getTexture();
    GrContext* context = color->getContext();

    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = bounds.width();
    desc.fHeight = bounds.height();
    desc.fConfig = kSkia8888_GrPixelConfig;

    SkAutoTUnref<GrTexture> dst(
        context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));

    if (!dst) {
        return false;
    }

    SkVector scale = SkVector::Make(fScale, fScale);
    ctx.ctm().mapVectors(&scale, 1);

    GrPaint paint;
    SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displacement);
    offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX),
                              SkIntToScalar(colorOffset.fY - displacementOffset.fY));

    paint.addColorProcessor(
        GrDisplacementMapEffect::Create(fXChannelSelector,
                                        fYChannelSelector,
                                        scale,
                                        displacement,
                                        offsetMatrix,
                                        color,
                                        colorBM.dimensions()))->unref();
    SkIRect colorBounds = bounds;
    colorBounds.offset(-colorOffset);
    SkMatrix matrix;
    matrix.setTranslate(-SkIntToScalar(colorBounds.x()),
                        -SkIntToScalar(colorBounds.y()));
    context->drawRect(dst->asRenderTarget(), GrClip::WideOpen(), paint, matrix,
                      SkRect::Make(colorBounds));
    offset->fX = bounds.left();
    offset->fY = bounds.top();
    WrapTexture(dst, bounds.width(), bounds.height(), result);
    return true;
}