From b86d914dd0d9e890af957f7aecbd0deca1da5b11 Mon Sep 17 00:00:00 2001 From: treeform Date: Wed, 25 Nov 2020 22:32:50 -0800 Subject: [PATCH] Add the uber draw. --- src/pixie/blends.nim | 26 ++ src/pixie/draw.nim | 145 ++++++++++ src/pixie/images.nim | 252 +++++++++++++++++- tests/benchmark_draw.nim | 49 +++- tests/images/bench.drawInPlace.bmNormal.png | Bin 0 -> 342 bytes .../bench.drawUberCopy.Smooth.bmNormal.png | Bin 0 -> 377 bytes tests/images/bench.drawUberCopy.bmNormal.png | Bin 0 -> 342 bytes .../bench.drawUberInPlace.Smooth.bmNormal.png | Bin 0 -> 377 bytes .../images/bench.drawUberInPlace.bmNormal.png | Bin 0 -> 342 bytes 9 files changed, 461 insertions(+), 11 deletions(-) create mode 100644 src/pixie/draw.nim create mode 100644 tests/images/bench.drawInPlace.bmNormal.png create mode 100644 tests/images/bench.drawUberCopy.Smooth.bmNormal.png create mode 100644 tests/images/bench.drawUberCopy.bmNormal.png create mode 100644 tests/images/bench.drawUberInPlace.Smooth.bmNormal.png create mode 100644 tests/images/bench.drawUberInPlace.bmNormal.png diff --git a/src/pixie/blends.nim b/src/pixie/blends.nim index 162809e..5d430e6 100644 --- a/src/pixie/blends.nim +++ b/src/pixie/blends.nim @@ -674,3 +674,29 @@ proc mix2*(blendMode: BlendMode, dest, src: ColorRGBA): ColorRGBA {.inline.} = of bmSubtractMask: blendSubtractMask(dest, src) of bmIntersectMask: blendIntersectMask(dest, src) of bmExcludeMask: blendExcludeMask(dest, src) + + +proc mixStatic*(blendMode: static[BlendMode], dest, src: ColorRGBA): ColorRGBA {.inline.} = + when blendMOde == bmNormal: blendNormal(dest, src) + elif blendMOde == bmDarken: blendDarken(dest, src) + elif blendMOde == bmMultiply: blendMultiply(dest, src) + elif blendMOde == bmLinearBurn: blendLinearBurn(dest, src) + elif blendMOde == bmColorBurn: blendColorBurn(dest, src) + elif blendMOde == bmLighten: blendLighten(dest, src) + elif blendMOde == bmScreen: blendScreen(dest, src) + elif blendMOde == bmLinearDodge: blendLinearDodge(dest, src) + elif blendMOde == bmColorDodge: blendColorDodge(dest, src) + elif blendMOde == bmOverlay: blendOverlay(dest, src) + elif blendMOde == bmSoftLight: blendSoftLight(dest, src) + elif blendMOde == bmHardLight: blendHardLight(dest, src) + elif blendMOde == bmDifference: blendDifference(dest, src) + elif blendMOde == bmExclusion: blendExclusion(dest, src) + elif blendMOde == bmHue: blendHue(dest, src) + elif blendMOde == bmSaturation: blendSaturation(dest, src) + elif blendMOde == bmColor: blendColor(dest, src) + elif blendMOde == bmLuminosity: blendLuminosity(dest, src) + elif blendMOde == bmMask: blendMask(dest, src) + elif blendMOde == bmOverwrite: blendOverwrite(dest, src) + elif blendMOde == bmSubtractMask: blendSubtractMask(dest, src) + elif blendMOde == bmIntersectMask: blendIntersectMask(dest, src) + elif blendMOde == bmExcludeMask: blendExcludeMask(dest, src) diff --git a/src/pixie/draw.nim b/src/pixie/draw.nim new file mode 100644 index 0000000..830653b --- /dev/null +++ b/src/pixie/draw.nim @@ -0,0 +1,145 @@ +import chroma, blends, vmath, common, images + +proc drawUberTemplate( + a: Image, + b: Image, + c: Image, + mat: Mat3, + lines: array[4, Segment], + blendMode: BlendMode, + inPlace: bool, + smooth: bool, +) = + for y in 0 ..< a.height: + var + xMin = 0 + xMax = 0 + hasIntersection = false + for yOffset in [0.float32, 1]: + var scanLine = segment( + vec2(-100000, y.float32 + yOffset), + vec2(10000, y.float32 + yOffset) + ) + for l in lines: + var at: Vec2 + if intersects(l, scanLine, at): + if hasIntersection: + xMin = min(xMin, at.x.floor.int) + xMax = max(xMax, at.x.ceil.int) + else: + hasIntersection = true + xMin = at.x.floor.int + xMax = at.x.ceil.int + + xMin = xMin.clamp(0, a.width) + xMax = xMax.clamp(0, a.width) + + # for x in 0 ..< xMin: + # result.setRgbaUnsafe(x, y, a.getRgbaUnsafe(x, y)) + if xMin > 0: + copyMem(c.getAddr(0, y), a.getAddr(0, y), 4*xMin) + + for x in xMin ..< xMax: + let srcPos = start + stepX * float32(x) + stepY * float32(y) + #let srcPos = matInv * vec2(x.float32 + h, y.float32 + h) + var rgba = a.getRgbaUnsafe(x, y) + let rgba2 = b.getRgbaFn(srcPos.x - h, srcPos.y - h) + rgba = mixer(rgba, rgba2) + c.setRgbaUnsafe(x, y, rgba) + + #for x in xMax ..< a.width: + # result.setRgbaUnsafe(x, y, a.getRgbaUnsafe(x, y)) + if a.width - xMax > 0: + copyMem(c.getAddr(xMax, y), a.getAddr(xMax, y), 4*(a.width - xMax)) + +proc drawUber*(a: Image, b: Image, c: Image, mat: Mat3, blendMode: BlendMode, inPlace: bool) = + ## Draws one image onto another using matrix with color blending. + + var + matInv = mat.inverse() + # compute movement vectors + h = 0.5.float32 + start = matInv * vec2(0 + h, 0 + h) + stepX = matInv * vec2(1 + h, 0 + h) - start + stepY = matInv * vec2(0 + h, 1 + h) - start + minFilterBy2 = max(stepX.length, stepY.length) + b = b + + let corners = [ + mat * vec2(0, 0), + mat * vec2(b.width.float32, 0), + mat * vec2(b.width.float32, b.height.float32), + mat * vec2(0, b.height.float32) + ] + + let lines = [ + segment(corners[0], corners[1]), + segment(corners[1], corners[2]), + segment(corners[2], corners[3]), + segment(corners[3], corners[0]) + ] + + while minFilterBy2 > 2.0: + b = b.minifyBy2() + start /= 2 + stepX /= 2 + stepY /= 2 + minFilterBy2 /= 2 + matInv = matInv * scale(vec2(0.5, 0.5)) + + proc getRgbaUnsafe(a: Image, x, y: float32): ColorRGBA {.inline.} = + a.getRgbaUnsafe(x.round.int, y.round.int) + + if stepX.length == 1.0 and stepY.length == 1.0 and + mat[2, 0].fractional == 0.0 and mat[2, 1].fractional == 0.0: + #echo "copy non-smooth" + case blendMode + of bmNormal: forBlend(blendNormal, getRgbaUnsafe) + of bmDarken: forBlend(blendDarken, getRgbaUnsafe) + of bmMultiply: forBlend(blendMultiply, getRgbaUnsafe) + of bmLinearBurn: forBlend(blendLinearBurn, getRgbaUnsafe) + of bmColorBurn: forBlend(blendColorBurn, getRgbaUnsafe) + of bmLighten: forBlend(blendLighten, getRgbaUnsafe) + of bmScreen: forBlend(blendScreen, getRgbaUnsafe) + of bmLinearDodge: forBlend(blendLinearDodge, getRgbaUnsafe) + of bmColorDodge: forBlend(blendColorDodge, getRgbaUnsafe) + of bmOverlay: forBlend(blendOverlay, getRgbaUnsafe) + of bmSoftLight: forBlend(blendSoftLight, getRgbaUnsafe) + of bmHardLight: forBlend(blendHardLight, getRgbaUnsafe) + of bmDifference: forBlend(blendDifference, getRgbaUnsafe) + of bmExclusion: forBlend(blendExclusion, getRgbaUnsafe) + of bmHue: forBlend(blendHue, getRgbaUnsafe) + of bmSaturation: forBlend(blendSaturation, getRgbaUnsafe) + of bmColor: forBlend(blendColor, getRgbaUnsafe) + of bmLuminosity: forBlend(blendLuminosity, getRgbaUnsafe) + of bmMask: forBlend(blendMask, getRgbaUnsafe) + of bmOverwrite: forBlend(blendOverwrite, getRgbaUnsafe) + of bmSubtractMask: forBlend(blendSubtractMask, getRgbaUnsafe) + of bmIntersectMask: forBlend(blendIntersectMask, getRgbaUnsafe) + of bmExcludeMask: forBlend(blendExcludeMask, getRgbaUnsafe) + else: + #echo "copy smooth" + case blendMode + of bmNormal: forBlend(blendNormal, getRgbaSmooth) + of bmDarken: forBlend(blendDarken, getRgbaSmooth) + of bmMultiply: forBlend(blendMultiply, getRgbaSmooth) + of bmLinearBurn: forBlend(blendLinearBurn, getRgbaSmooth) + of bmColorBurn: forBlend(blendColorBurn, getRgbaSmooth) + of bmLighten: forBlend(blendLighten, getRgbaSmooth) + of bmScreen: forBlend(blendScreen, getRgbaSmooth) + of bmLinearDodge: forBlend(blendLinearDodge, getRgbaSmooth) + of bmColorDodge: forBlend(blendColorDodge, getRgbaSmooth) + of bmOverlay: forBlend(blendOverlay, getRgbaSmooth) + of bmSoftLight: forBlend(blendSoftLight, getRgbaSmooth) + of bmHardLight: forBlend(blendHardLight, getRgbaSmooth) + of bmDifference: forBlend(blendDifference, getRgbaSmooth) + of bmExclusion: forBlend(blendExclusion, getRgbaSmooth) + of bmHue: forBlend(blendHue, getRgbaSmooth) + of bmSaturation: forBlend(blendSaturation, getRgbaSmooth) + of bmColor: forBlend(blendColor, getRgbaSmooth) + of bmLuminosity: forBlend(blendLuminosity, getRgbaSmooth) + of bmMask: forBlend(blendMask, getRgbaSmooth) + of bmOverwrite: forBlend(blendOverwrite, getRgbaSmooth) + of bmSubtractMask: forBlend(blendSubtractMask, getRgbaSmooth) + of bmIntersectMask: forBlend(blendIntersectMask, getRgbaSmooth) + of bmExcludeMask: forBlend(blendExcludeMask, getRgbaSmooth) diff --git a/src/pixie/images.nim b/src/pixie/images.nim index fafb417..21a664a 100644 --- a/src/pixie/images.nim +++ b/src/pixie/images.nim @@ -6,6 +6,11 @@ type width*, height*: int data*: seq[ColorRGBA] +proc draw*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal): Image +proc drawInPlace*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal) +proc draw*(a: Image, b: Image, pos = vec2(0, 0), blendMode = bmNormal): Image +proc drawInPlace*(a: Image, b: Image, pos = vec2(0, 0), blendMode = bmNormal) + proc newImage*(width, height: int): Image = ## Creates a new image with appropriate dimensions. result = Image() @@ -439,7 +444,7 @@ proc drawStepper*(a: Image, b: Image, mat: Mat3, blendMode: BlendMode): Image = of bmIntersectMask: forBlend(blendIntersectMask, getRgbaSmooth) of bmExcludeMask: forBlend(blendExcludeMask, getRgbaSmooth) -proc draw*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal): Image = +#proc draw*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal): Image = ## Draws one image onto another using matrix with color blending. # Decide which ones of the draws best fit current parameters. @@ -454,12 +459,9 @@ proc draw*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal): Image = #return drawCorrect(a, b, mat, blendMode) - return drawStepper(a, b, mat, blendMode) + #return drawStepper(a, b, mat, blendMode) -proc draw*(a: Image, b: Image, pos = vec2(0, 0), blendMode = bmNormal): Image = - a.draw(b, translate(pos), blendMode) - -proc drawInPlace*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal) = +proc drawStepper*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal) = ## Draws one image onto another using matrix with color blending. var @@ -588,9 +590,6 @@ proc drawInPlace*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal) = of bmIntersectMask: forBlend(blendIntersectMask, getRgbaSmooth) of bmExcludeMask: forBlend(blendExcludeMask, getRgbaSmooth) -proc drawInPlace*(a: Image, b: Image, pos = vec2(0, 0), blendMode = bmNormal) = - a.drawInPlace(b, translate(pos), blendMode) - proc blur*(image: Image, radius: float32): Image = ## Applies Gaussian blur to the image given a radius. let radius = (radius).int @@ -724,3 +723,238 @@ proc sharpOpacity*(image: Image): Image = result.setRgbaUnsafe(x, y, rgba(0, 0, 0, 0)) else: result.setRgbaUnsafe(x, y, rgba(255, 255, 255, 255)) + +const h = 0.5.float32 + +proc drawUberStatic( + a, b, c: Image, + start, stepX, stepY: Vec2, + lines: array[0..3, Segment], + blendMode: static[BlendMode], + inPlace: static[bool], + smooth: static[bool], +) = + + for y in 0 ..< a.height: + var + xMin = 0 + xMax = 0 + hasIntersection = false + for yOffset in [0.float32, 1]: + var scanLine = segment( + vec2(-100000, y.float32 + yOffset), + vec2(10000, y.float32 + yOffset) + ) + for l in lines: + var at: Vec2 + if intersects(l, scanLine, at): + if hasIntersection: + xMin = min(xMin, at.x.floor.int) + xMax = max(xMax, at.x.ceil.int) + else: + hasIntersection = true + xMin = at.x.floor.int + xMax = at.x.ceil.int + + xMin = xMin.clamp(0, a.width) + xMax = xMax.clamp(0, a.width) + + when blendMode == bmIntersectMask: + if xMin > 0: + zeroMem(c.getAddr(0, y), 4*xMin) + else: + when not inPlace: + # for x in 0 ..< xMin: + # result.setRgbaUnsafe(x, y, a.getRgbaUnsafe(x, y)) + if xMin > 0: + copyMem(c.getAddr(0, y), a.getAddr(0, y), 4*xMin) + + for x in xMin ..< xMax: + let srcPos = start + stepX * float32(x) + stepY * float32(y) + let + xFloat = srcPos.x - h + yFloat = srcPos.y - h + var rgba = a.getRgbaUnsafe(x, y) + var rgba2 = + when smooth: + b.getRgbaSmooth(xFloat, yFloat) + else: + b.getRgbaUnsafe(xFloat.round.int, yFloat.round.int) + rgba = blendMode.mixStatic(rgba, rgba2) + c.setRgbaUnsafe(x, y, rgba) + + when blendMode == bmIntersectMask: + if a.width - xMax > 0: + zeroMem(c.getAddr(xMax, y), 4*(a.width - xMax)) + else: + when not inPlace: + #for x in xMax ..< a.width: + # result.setRgbaUnsafe(x, y, a.getRgbaUnsafe(x, y)) + if a.width - xMax > 0: + copyMem(c.getAddr(xMax, y), a.getAddr(xMax, y), 4*(a.width - xMax)) + + +proc drawUberInner*(a: Image, b: Image, c: Image, mat: Mat3, blendMode: BlendMode, inPlace: bool) = + ## Draws one image onto another using matrix with color blending. + + var + matInv = mat.inverse() + # compute movement vectors + start = matInv * vec2(0 + h, 0 + h) + stepX = matInv * vec2(1 + h, 0 + h) - start + stepY = matInv * vec2(0 + h, 1 + h) - start + minFilterBy2 = max(stepX.length, stepY.length) + b = b + + let corners = [ + mat * vec2(0, 0), + mat * vec2(b.width.float32, 0), + mat * vec2(b.width.float32, b.height.float32), + mat * vec2(0, b.height.float32) + ] + + let lines = [ + segment(corners[0], corners[1]), + segment(corners[1], corners[2]), + segment(corners[2], corners[3]), + segment(corners[3], corners[0]) + ] + + while minFilterBy2 > 2.0: + b = b.minifyBy2() + start /= 2 + stepX /= 2 + stepY /= 2 + minFilterBy2 /= 2 + matInv = matInv * scale(vec2(0.5, 0.5)) + + var smooth = not(stepX.length == 1.0 and stepY.length == 1.0 and + mat[2, 0].fractional == 0.0 and mat[2, 1].fractional == 0.0) + + if inPlace == true: + + if not smooth: + #echo "copy non-smooth" + case blendMode + of bmNormal: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmNormal, true, false) + of bmDarken: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmDarken, true, false) + of bmMultiply: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmMultiply, true, false) + of bmLinearBurn: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLinearBurn, true, false) + of bmColorBurn: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmColorBurn, true, false) + of bmLighten: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLighten, true, false) + of bmScreen: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmScreen, true, false) + of bmLinearDodge: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLinearDodge, true, false) + of bmColorDodge: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmColorDodge, true, false) + of bmOverlay: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmOverlay, true, false) + of bmSoftLight: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmSoftLight, true, false) + of bmHardLight: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmHardLight, true, false) + of bmDifference: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmDifference, true, false) + of bmExclusion: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmExclusion, true, false) + of bmHue: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmHue, true, false) + of bmSaturation: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmSaturation, true, false) + of bmColor: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmColor, true, false) + of bmLuminosity: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLuminosity, true, false) + of bmMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmMask, true, false) + of bmOverwrite: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmOverwrite, true, false) + of bmSubtractMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmSubtractMask, true, false) + of bmIntersectMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmIntersectMask, true, false) + of bmExcludeMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmExcludeMask, true, false) + else: + case blendMode + of bmNormal: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmNormal, true, true) + of bmDarken: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmDarken, true, true) + of bmMultiply: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmMultiply, true, true) + of bmLinearBurn: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLinearBurn, true, true) + of bmColorBurn: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmColorBurn, true, true) + of bmLighten: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLighten, true, true) + of bmScreen: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmScreen, true, true) + of bmLinearDodge: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLinearDodge, true, true) + of bmColorDodge: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmColorDodge, true, true) + of bmOverlay: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmOverlay, true, true) + of bmSoftLight: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmSoftLight, true, true) + of bmHardLight: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmHardLight, true, true) + of bmDifference: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmDifference, true, true) + of bmExclusion: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmExclusion, true, true) + of bmHue: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmHue, true, true) + of bmSaturation: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmSaturation, true, true) + of bmColor: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmColor, true, true) + of bmLuminosity: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLuminosity, true, true) + of bmMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmMask, true, true) + of bmOverwrite: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmOverwrite, true, true) + of bmSubtractMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmSubtractMask, true, true) + of bmIntersectMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmIntersectMask, true, true) + of bmExcludeMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmExcludeMask, true, true) + + else: + + if not smooth: + #echo "copy non-smooth" + case blendMode + of bmNormal: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmNormal, false, false) + of bmDarken: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmDarken, false, false) + of bmMultiply: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmMultiply, false, false) + of bmLinearBurn: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLinearBurn, false, false) + of bmColorBurn: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmColorBurn, false, false) + of bmLighten: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLighten, false, false) + of bmScreen: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmScreen, false, false) + of bmLinearDodge: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLinearDodge, false, false) + of bmColorDodge: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmColorDodge, false, false) + of bmOverlay: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmOverlay, false, false) + of bmSoftLight: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmSoftLight, false, false) + of bmHardLight: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmHardLight, false, false) + of bmDifference: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmDifference, false, false) + of bmExclusion: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmExclusion, false, false) + of bmHue: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmHue, false, false) + of bmSaturation: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmSaturation, false, false) + of bmColor: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmColor, false, false) + of bmLuminosity: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLuminosity, false, false) + of bmMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmMask, false, false) + of bmOverwrite: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmOverwrite, false, false) + of bmSubtractMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmSubtractMask, false, false) + of bmIntersectMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmIntersectMask, false, false) + of bmExcludeMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmExcludeMask, false, false) + else: + case blendMode + of bmNormal: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmNormal, false, true) + of bmDarken: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmDarken, false, true) + of bmMultiply: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmMultiply, false, true) + of bmLinearBurn: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLinearBurn, false, true) + of bmColorBurn: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmColorBurn, false, true) + of bmLighten: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLighten, false, true) + of bmScreen: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmScreen, false, true) + of bmLinearDodge: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLinearDodge, false, true) + of bmColorDodge: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmColorDodge, false, true) + of bmOverlay: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmOverlay, false, true) + of bmSoftLight: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmSoftLight, false, true) + of bmHardLight: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmHardLight, false, true) + of bmDifference: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmDifference, false, true) + of bmExclusion: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmExclusion, false, true) + of bmHue: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmHue, false, true) + of bmSaturation: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmSaturation, false, true) + of bmColor: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmColor, false, true) + of bmLuminosity: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmLuminosity, false, true) + of bmMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmMask, false, true) + of bmOverwrite: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmOverwrite, false, true) + of bmSubtractMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmSubtractMask, false, true) + of bmIntersectMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmIntersectMask, false, true) + of bmExcludeMask: drawUberStatic(a, b, c, start, stepX, stepY, lines, bmExcludeMask, false, true) + +proc drawUberInPlace*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal) = + a.drawUberInner(b, a, mat, blendMode, true) + +proc drawUberCopy*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal): Image = + var c = newImageNoInit(a.width, a.height) + a.drawUberInner(b, c, mat, blendMode, false) + return c + +proc draw*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal): Image = + drawUberCOpy(a, b, mat, blendMode) + +proc draw*(a: Image, b: Image, pos = vec2(0, 0), blendMode = bmNormal): Image = + a.draw(b, translate(pos), blendMode) + +proc drawInPlace*(a: Image, b: Image, mat: Mat3, blendMode = bmNormal) = + drawUberInPlace(a, b, mat, blendMode) + +proc drawInPlace*(a: Image, b: Image, pos = vec2(0, 0), blendMode = bmNormal) = + a.drawInPlace(b, translate(pos), blendMode) diff --git a/tests/benchmark_draw.nim b/tests/benchmark_draw.nim index b7ade6b..30fbb58 100644 --- a/tests/benchmark_draw.nim +++ b/tests/benchmark_draw.nim @@ -79,12 +79,57 @@ timeIt "drawStepper bmNormal": timeIt "drawInPlace bmNormal": var tmp = 0 + var a: Image for i in 0 ..< 1000: - var a = newImageFill(100, 100, rgba(255, 0, 0, 255)) + a = newImageFill(100, 100, rgba(255, 0, 0, 255)) var b = newImageFill(100, 100, rgba(0, 255, 0, 255)) a.drawInPlace(b, translate(vec2(25, 25)), bmNormal) tmp += a.width * a.height - #a.writeFile("tests/images/bench.drawStepper.bmNormal.png") + a.writeFile("tests/images/bench.drawInPlace.bmNormal.png") + echo tmp + +timeIt "drawUberCopy bmNormal": + var tmp = 0 + var c: Image + for i in 0 ..< 1000: + var a = newImageFill(100, 100, rgba(255, 0, 0, 255)) + var b = newImageFill(100, 100, rgba(0, 255, 0, 255)) + c = a.drawUberCopy(b, translate(vec2(25, 25)), bmNormal) + tmp += c.width * c.height + c.writeFile("tests/images/bench.drawUberCopy.bmNormal.png") + echo tmp + +timeIt "drawUberInPlace bmNormal": + var tmp = 0 + var a: Image + for i in 0 ..< 1000: + a = newImageFill(100, 100, rgba(255, 0, 0, 255)) + var b = newImageFill(100, 100, rgba(0, 255, 0, 255)) + a.drawUberInPlace(b, translate(vec2(25, 25)), bmNormal) + tmp += a.width * a.height + a.writeFile("tests/images/bench.drawUberInPlace.bmNormal.png") + echo tmp + +timeIt "drawUberCopy Smooth bmNormal": + var tmp = 0 + var c: Image + for i in 0 ..< 1000: + var a = newImageFill(100, 100, rgba(255, 0, 0, 255)) + var b = newImageFill(100, 100, rgba(0, 255, 0, 255)) + c = a.drawUberCopy(b, translate(vec2(25.2, 25.2)), bmNormal) + tmp += c.width * c.height + c.writeFile("tests/images/bench.drawUberCopy.Smooth.bmNormal.png") + echo tmp + +timeIt "drawUberInPlace Smooth bmNormal": + var tmp = 0 + var a: Image + for i in 0 ..< 1000: + a = newImageFill(100, 100, rgba(255, 0, 0, 255)) + var b = newImageFill(100, 100, rgba(0, 255, 0, 255)) + a.drawUberInPlace(b, translate(vec2(25.2, 25.2)), bmNormal) + tmp += a.width * a.height + a.writeFile("tests/images/bench.drawUberInPlace.Smooth.bmNormal.png") echo tmp # timeIt "drawBlend bmSaturation": diff --git a/tests/images/bench.drawInPlace.bmNormal.png b/tests/images/bench.drawInPlace.bmNormal.png new file mode 100644 index 0000000000000000000000000000000000000000..ec3debd708e6cdeddc056de8aba1ec3c66647c31 GIT binary patch literal 342 zcmeAS@N?(olHy`uVBq!ia0vp^DImh%v-DC{WI1|zY$95{b+M`PhZ+=w%sg|^+$gRY~vJC_UKVCY&yb0U&e{> v&ASg9ZT?gB`mfPvtAACe>jjAN*)!&X@Q>$~aV$9j3{nP9S3j3^P6h%v-DC{WI1|zY$95{b+M`PhZ+=w%sg|^+$gRY~vJC_UKVCY&yb0U&e{> v&ASg9ZT?gB`mfPvtAACe>jjAN*)!&X@Q>$~aV$9j3{nP9S3j3^P6