changes noticed while working on bindings

This commit is contained in:
Ryan Oldenburg 2021-08-11 19:35:59 -05:00
parent 390f9b95c4
commit a95d1f546b
9 changed files with 52 additions and 67 deletions

View file

@ -69,10 +69,6 @@ proc encodeMask*(mask: Mask, fileFormat: FileFormat): string =
else:
raise newException(PixieError, "Unsupported file format")
proc writeFile*(image: Image, filePath: string, fileFormat: FileFormat) =
## Writes an image to a file.
writeFile(filePath, image.encodeImage(fileFormat))
proc writeFile*(image: Image, filePath: string) =
## Writes an image to a file.
let fileFormat = case splitFile(filePath).ext.toLowerAscii():
@ -81,11 +77,7 @@ proc writeFile*(image: Image, filePath: string) =
of ".jpg", ".jpeg": ffJpg
else:
raise newException(PixieError, "Unsupported file extension")
image.writeFile(filePath, fileformat)
proc writeFile*(mask: Mask, filePath: string, fileFormat: FileFormat) =
## Writes an mask to a file.
writeFile(filePath, mask.encodeMask(fileFormat))
writeFile(filePath, image.encodeImage(fileFormat))
proc writeFile*(mask: Mask, filePath: string) =
## Writes a mask to a file.
@ -95,7 +87,7 @@ proc writeFile*(mask: Mask, filePath: string) =
of ".jpg", ".jpeg": ffJpg
else:
raise newException(PixieError, "Unsupported file extension")
mask.writeFile(filePath, fileformat)
writeFile(filePath, mask.encodeMask(fileFormat))
proc fillRect*(
mask: Mask,

View file

@ -421,10 +421,8 @@ proc decodePng*(data: string): Image =
var pixels = decodeImageData(header, palette, transparency, imageData)
pixels.toPremultipliedAlpha()
result = Image()
result.width = header.width
result.height = header.height
result.data = cast[seq[ColorRGBX]](pixels)
result = newImage(header.width, header.height)
copyMem(result.data[0].addr, pixels[0].addr, pixels.len * 4)
proc encodePng*(width, height, channels: int, data: pointer, len: int): string =
## Encodes the image data into the PNG file format.

View file

@ -71,6 +71,10 @@ proc `[]`*(image: Image, x, y: int): ColorRGBX {.inline.} =
if image.inside(x, y):
return image.getRgbaUnsafe(x, y)
proc getColor*(image: Image, x, y: int): Color =
## Gets a color at (x, y) or returns transparent black if outside of bounds.
image[x, y].color()
proc setRgbaUnsafe*(image: Image, x, y: int, color: SomeColor) {.inline.} =
## Sets a color from (x, y) coordinates.
## * No bounds checking *
@ -83,6 +87,10 @@ proc `[]=`*(image: Image, x, y: int, color: SomeColor) {.inline.} =
if image.inside(x, y):
image.setRgbaUnsafe(x, y, color.asRgbx())
proc setColor*(image: Image, x, y: int, color: Color) =
## Sets a color at (x, y) or does nothing if outside of bounds.
image[x, y] = color.rgbx()
proc fillUnsafe*(data: var seq[ColorRGBX], color: SomeColor, start, len: int) =
## Fills the image data with the parameter color starting at index start and
## continuing for len indices.
@ -807,7 +815,7 @@ proc drawUber(a, b: Image | Mask, mat = mat3(), blendMode = bmNormal) =
zeroMem(a.data[a.dataIndex(xMax, y)].addr, 4 * (a.width - xMax))
proc draw*(
a, b: Image, transform: Vec2 | Mat3 = vec2(), blendMode = bmNormal
a, b: Image, transform: Mat3 = mat3(), blendMode = bmNormal
) {.inline.} =
## Draws one image onto another using matrix with color blending.
when type(transform) is Vec2:
@ -816,7 +824,7 @@ proc draw*(
a.drawUber(b, transform, blendMode)
proc draw*(
a, b: Mask, transform: Vec2 | Mat3 = vec2(), blendMode = bmMask
a, b: Mask, transform: Mat3 = mat3(), blendMode = bmMask
) {.inline.} =
## Draws a mask onto a mask using a matrix with color blending.
when type(transform) is Vec2:
@ -825,7 +833,7 @@ proc draw*(
a.drawUber(b, transform, blendMode)
proc draw*(
image: Image, mask: Mask, transform: Vec2 | Mat3 = vec2(), blendMode = bmMask
image: Image, mask: Mask, transform: Mat3 = mat3(), blendMode = bmMask
) {.inline.} =
## Draws a mask onto an image using a matrix with color blending.
when type(transform) is Vec2:
@ -834,7 +842,7 @@ proc draw*(
image.drawUber(mask, transform, blendMode)
proc draw*(
mask: Mask, image: Image, transform: Vec2 | Mat3 = vec2(), blendMode = bmMask
mask: Mask, image: Image, transform: Mat3 = mat3(), blendMode = bmMask
) {.inline.} =
## Draws a image onto a mask using a matrix with color blending.
when type(transform) is Vec2:
@ -860,25 +868,14 @@ proc resize*(srcImage: Image, width, height: int): Image =
bmOverwrite
)
proc shift*(target: Image | Mask, offset: Vec2) =
## Shifts the target by offset.
if offset != vec2(0, 0):
let copy = target.copy() # Copy to read from
# Reset target for being drawn to
when type(target) is Image:
target.fill(rgbx(0, 0, 0, 0))
else:
target.fill(0)
target.draw(copy, offset, bmOverwrite) # Draw copy at offset
proc shadow*(
image: Image, offset: Vec2, spread, blur: float32, color: SomeColor
): Image =
## Create a shadow of the image with the offset, spread and blur.
let mask = image.newMask()
mask.shift(offset)
let
mask = image.newMask()
shifted = newMask(mask.width, mask.height)
shifted.draw(mask, translate(offset), bmOverwrite)
mask.spread(spread)
mask.blur(blur)
result = newImage(mask.width, mask.height)

View file

@ -50,10 +50,14 @@ proc getValueUnsafe*(mask: Mask, x, y: int): uint8 {.inline.} =
result = mask.data[mask.width * y + x]
proc `[]`*(mask: Mask, x, y: int): uint8 {.inline.} =
## Gets a pixel at (x, y) or returns transparent black if outside of bounds.
## Gets a value at (x, y) or returns transparent black if outside of bounds.
if mask.inside(x, y):
return mask.getValueUnsafe(x, y)
proc getValue*(mask: Mask, x, y: int): uint8 {.inline.} =
## Gets a value at (x, y) or returns transparent black if outside of bounds.
mask[x, y]
proc setValueUnsafe*(mask: Mask, x, y: int, value: uint8) {.inline.} =
## Sets a value from (x, y) coordinates.
## * No bounds checking *
@ -66,6 +70,10 @@ proc `[]=`*(mask: Mask, x, y: int, value: uint8) {.inline.} =
if mask.inside(x, y):
mask.setValueUnsafe(x, y, value)
proc setValue*(mask: Mask, x, y: int, value: uint8) {.inline.} =
## Sets a value at (x, y) or does nothing if outside of bounds.
mask[x, y] = value
proc minifyBy2*(mask: Mask, power = 1): Mask =
## Scales the mask down by an integer scale.
if power < 0:

View file

@ -25,8 +25,8 @@ type
ColorStop* = object
## Color stop on a gradient curve.
color*: ColorRGBX ## Color of the stop
position*: float32 ## Gradient Stop position 0..1.
color*: ColorRGBX ## Color of the stop.
position*: float32 ## Gradient stop position 0..1.
SomePaint* = string | Paint | SomeColor
@ -96,12 +96,9 @@ proc gradientPut(
color = color.applyOpacity(paint.opacity)
image.setRgbaUnsafe(x, y, color.rgba.rgbx())
proc fillGradientLinear*(image: Image, paint: Paint) =
proc fillGradientLinear(image: Image, paint: Paint) =
## Fills a linear gradient.
if paint.kind != pkGradientLinear:
raise newException(PixieError, "Paint kind must be " & $pkGradientLinear)
if paint.gradientHandlePositions.len != 2:
raise newException(PixieError, "Linear gradient requires 2 handles")
@ -121,12 +118,9 @@ proc fillGradientLinear*(image: Image, paint: Paint) =
t = toLineSpace(at, to, xy)
image.gradientPut(paint, x, y, t, paint.gradientStops)
proc fillGradientRadial*(image: Image, paint: Paint) =
proc fillGradientRadial(image: Image, paint: Paint) =
## Fills a radial gradient.
if paint.kind != pkGradientRadial:
raise newException(PixieError, "Paint kind must be " & $pkGradientRadial)
if paint.gradientHandlePositions.len != 3:
raise newException(PixieError, "Radial gradient requires 3 handles")
@ -155,12 +149,9 @@ proc fillGradientRadial*(image: Image, paint: Paint) =
t = (mat * xy).length()
image.gradientPut(paint, x, y, t, paint.gradientStops)
proc fillGradientAngular*(image: Image, paint: Paint) =
proc fillGradientAngular(image: Image, paint: Paint) =
## Fills an angular gradient.
if paint.kind != pkGradientAngular:
raise newException(PixieError, "Paint kind must be " & $pkGradientAngular)
if paint.gradientHandlePositions.len != 3:
raise newException(PixieError, "Angular gradient requires 2 handles")
@ -182,3 +173,16 @@ proc fillGradientAngular*(image: Image, paint: Paint) =
angle = normalize(xy - center).angle()
t = (angle + gradientAngle + PI / 2).fixAngle() / 2 / PI + 0.5
image.gradientPut(paint, x, y, t, paint.gradientStops)
proc fillGradient*(image: Image, paint: Paint) =
## Fills with the Paint gradient.
case paint.kind:
of pkGradientLinear:
image.fillGradientLinear(paint)
of pkGradientRadial:
image.fillGradientRadial(paint)
of pkGradientAngular:
image.fillGradientAngular(paint)
else:
raise newException(PixieError, "Paint must be a gradient")

View file

@ -1813,12 +1813,8 @@ proc fillPath*(
fill.draw(paint.image, paint.imageMat)
of pkImageTiled:
fill.drawTiled(paint.image, paint.imageMat)
of pkGradientLinear:
fill.fillGradientLinear(paint)
of pkGradientRadial:
fill.fillGradientRadial(paint)
of pkGradientAngular:
fill.fillGradientAngular(paint)
of pkGradientLinear, pkGradientRadial, pkGradientAngular:
fill.fillGradient(paint)
paint.opacity = savedOpacity
@ -1909,12 +1905,8 @@ proc strokePath*(
fill.draw(paint.image, paint.imageMat)
of pkImageTiled:
fill.drawTiled(paint.image, paint.imageMat)
of pkGradientLinear:
fill.fillGradientLinear(paint)
of pkGradientRadial:
fill.fillGradientRadial(paint)
of pkGradientAngular:
fill.fillGradientAngular(paint)
of pkGradientLinear, pkGradientRadial, pkGradientAngular:
fill.fillGradient(paint)
paint.opacity = savedOpacity

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 B

View file

@ -43,7 +43,7 @@ block:
a.fill(rgba(255, 0, 0, 255))
b.fill(rgba(0, 255, 0, 255))
a.draw(b, vec2(0, 0))
a.draw(b, translate(vec2(0, 0)))
a.writeFile("tests/images/flipped1.png")
a.flipVertical()

View file

@ -75,12 +75,6 @@ block:
a.draw(b)
writeFile("tests/images/masks/imageMaskedMask.png", a.encodePng())
block:
let a = newMask(100, 100)
a.fill(255)
a.shift(vec2(10, 10))
writeFile("tests/images/masks/shifted.png", a.encodePng())
block:
let path = newPath()
path.rect(40, 40, 20, 20)