Merge pull request #136 from guzba/master

migrate public api to rgbx
This commit is contained in:
treeform 2021-02-25 16:13:50 -08:00 committed by GitHub
commit 22aace7a5e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 86 additions and 118 deletions

View file

@ -190,7 +190,7 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
elif fill == "none":
result.fill = ColorRGBA()
else:
result.fill = parseHtmlColor(fill).rgba.toPremultipliedAlpha()
result.fill = parseHtmlColor(fill).rgba
if stroke == "":
discard # Inherit
@ -199,7 +199,7 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
elif stroke == "none":
result.stroke = ColorRGBA()
else:
result.stroke = parseHtmlColor(stroke).rgba.toPremultipliedAlpha()
result.stroke = parseHtmlColor(stroke).rgba
result.shouldStroke = true
if strokeWidth == "":

View file

@ -35,7 +35,7 @@ type
bmIntersectMask
bmExcludeMask
Blender* = proc(backdrop, source: ColorRGBA): ColorRGBA
Blender* = proc(backdrop, source: ColorRGBX): ColorRGBX
## Function signature returned by blender.
Masker* = proc(backdrop, source: uint8): uint8
## Function signature returned by masker.
@ -166,7 +166,7 @@ proc SetSat(C: Color, s: float32): Color {.inline.} =
if satC > 0:
result = (C - min([C.r, C.g, C.b])) * s / satC
proc blendNormal(backdrop, source: ColorRGBA): ColorRGBA =
proc blendNormal(backdrop, source: ColorRGBX): ColorRGBX =
if backdrop.a == 0:
return source
if source.a == 255:
@ -180,7 +180,7 @@ proc blendNormal(backdrop, source: ColorRGBA): ColorRGBA =
result.b = source.b + ((backdrop.b.uint32 * k) div 255).uint8
result.a = blendAlpha(backdrop.a, source.a)
proc blendDarken(backdrop, source: ColorRGBA): ColorRGBA =
proc blendDarken(backdrop, source: ColorRGBX): ColorRGBX =
proc blend(
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
): uint8 {.inline.} =
@ -194,7 +194,7 @@ proc blendDarken(backdrop, source: ColorRGBA): ColorRGBA =
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
result.a = blendAlpha(backdrop.a, source.a)
proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA =
proc blendMultiply(backdrop, source: ColorRGBX): ColorRGBX =
proc blend(
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
): uint8 {.inline.} =
@ -209,7 +209,7 @@ proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA =
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
result.a = blendAlpha(backdrop.a, source.a)
# proc blendLinearBurn(backdrop, source: ColorRGBA): ColorRGBA =
# proc blendLinearBurn(backdrop, source: ColorRGBX): ColorRGBX =
# let
# backdrop = backdrop.toStraightAlpha()
# source = source.toStraightAlpha()
@ -219,7 +219,7 @@ proc blendMultiply(backdrop, source: ColorRGBA): ColorRGBA =
# result = alphaFix(backdrop, source, result)
# result = result.toPremultipliedAlpha()
proc blendColorBurn(backdrop, source: ColorRGBA): ColorRGBA =
proc blendColorBurn(backdrop, source: ColorRGBX): ColorRGBX =
let
backdrop = backdrop.toStraightAlpha()
source = source.toStraightAlpha()
@ -230,13 +230,13 @@ proc blendColorBurn(backdrop, source: ColorRGBA): ColorRGBA =
0
else:
255 - min(255, (255 * (255 - backdrop)) div source).uint8
result.r = blend(backdrop.r, source.r)
result.g = blend(backdrop.g, source.g)
result.b = blend(backdrop.b, source.b)
result = alphaFix(backdrop, source, result)
result = result.toPremultipliedAlpha()
var blended: ColorRGBA
blended.r = blend(backdrop.r, source.r)
blended.g = blend(backdrop.g, source.g)
blended.b = blend(backdrop.b, source.b)
result = alphaFix(backdrop, source, blended).toPremultipliedAlpha()
proc blendLighten(backdrop, source: ColorRGBA): ColorRGBA =
proc blendLighten(backdrop, source: ColorRGBX): ColorRGBX =
proc blend(
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
): uint8 {.inline.} =
@ -250,13 +250,13 @@ proc blendLighten(backdrop, source: ColorRGBA): ColorRGBA =
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
result.a = blendAlpha(backdrop.a, source.a)
proc blendScreen(backdrop, source: ColorRGBA): ColorRGBA =
proc blendScreen(backdrop, source: ColorRGBX): ColorRGBX =
result.r = screen(backdrop.r, source.r)
result.g = screen(backdrop.g, source.g)
result.b = screen(backdrop.b, source.b)
result.a = blendAlpha(backdrop.a, source.a)
# proc blendLinearDodge(backdrop, source: ColorRGBA): ColorRGBA =
# proc blendLinearDodge(backdrop, source: ColorRGBX): ColorRGBX =
# let
# backdrop = backdrop.toStraightAlpha()
# source = source.toStraightAlpha()
@ -266,7 +266,7 @@ proc blendScreen(backdrop, source: ColorRGBA): ColorRGBA =
# result = alphaFix(backdrop, source, result)
# result = result.toPremultipliedAlpha()
proc blendColorDodge(backdrop, source: ColorRGBA): ColorRGBA =
proc blendColorDodge(backdrop, source: ColorRGBX): ColorRGBX =
let
backdrop = backdrop.toStraightAlpha()
source = source.toStraightAlpha()
@ -277,19 +277,19 @@ proc blendColorDodge(backdrop, source: ColorRGBA): ColorRGBA =
255
else:
min(255, (255 * backdrop) div (255 - source)).uint8
result.r = blend(backdrop.r, source.r)
result.g = blend(backdrop.g, source.g)
result.b = blend(backdrop.b, source.b)
result = alphaFix(backdrop, source, result)
result = result.toPremultipliedAlpha()
var blended: ColorRGBA
blended.r = blend(backdrop.r, source.r)
blended.g = blend(backdrop.g, source.g)
blended.b = blend(backdrop.b, source.b)
result = alphaFix(backdrop, source, blended).toPremultipliedAlpha()
proc blendOverlay(backdrop, source: ColorRGBA): ColorRGBA =
proc blendOverlay(backdrop, source: ColorRGBX): ColorRGBX =
result.r = hardLight(source.r, source.a, backdrop.r, backdrop.a)
result.g = hardLight(source.g, source.a, backdrop.g, backdrop.a)
result.b = hardLight(source.b, source.a, backdrop.b, backdrop.a)
result.a = blendAlpha(backdrop.a, source.a)
proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
proc blendSoftLight(backdrop, source: ColorRGBX): ColorRGBX =
# proc softLight(backdrop, source: int32): uint8 {.inline.} =
# ## Pegtop
# (
@ -301,6 +301,7 @@ proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
backdrop = backdrop.toStraightAlpha()
source = source.toStraightAlpha()
var rgba: ColorRGBA
when defined(amd64) and not defined(pixieNoSimd):
let
vb = mm_setr_ps(
@ -316,11 +317,11 @@ proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
vm = ((v255 - v2 * vs) * vb * vb) / v255sq + (v2 * vs * vb) / v255
values = cast[array[4, uint32]](mm_cvtps_epi32(vm))
result.r = values[0].uint8
result.g = values[1].uint8
result.b = values[2].uint8
rgba.r = values[0].uint8
rgba.g = values[1].uint8
rgba.b = values[2].uint8
# proc alphaFix(backdrop, source, mixed: ColorRGBA): ColorRGBA {.inline.} =
# proc alphaFix(backdrop, source, mixed: ColorRGBX): ColorRGBX {.inline.} =
# if backdrop.a == 0 and source.a == 0:
# return
# let
@ -345,10 +346,10 @@ proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
mm_cvtps_epi32((t0 * vs + t1 * vm + t2 * vb) / va / v255)
)
result.r = final[0].uint8
result.g = final[1].uint8
result.b = final[2].uint8
result.a = a.uint8
rgba.r = final[0].uint8
rgba.g = final[1].uint8
rgba.b = final[2].uint8
rgba.a = a.uint8
else:
let
b = backdrop.color
@ -358,17 +359,17 @@ proc blendSoftLight(backdrop, source: ColorRGBA): ColorRGBA =
blended.g = softLight(b.g, s.g)
blended.b = softLight(b.b, s.b)
blended = alphaFix(b, s, blended)
result = blended.rgba
rgba = blended.rgba
result = result.toPremultipliedAlpha()
result = rgba
proc blendHardLight(backdrop, source: ColorRGBA): ColorRGBA =
proc blendHardLight(backdrop, source: ColorRGBX): ColorRGBX =
result.r = hardLight(backdrop.r, backdrop.a, source.r, source.a)
result.g = hardLight(backdrop.g, backdrop.a, source.g, source.a)
result.b = hardLight(backdrop.b, backdrop.a, source.b, source.a)
result.a = blendAlpha(backdrop.a, source.a)
proc blendDifference(backdrop, source: ColorRGBA): ColorRGBA =
proc blendDifference(backdrop, source: ColorRGBX): ColorRGBX =
proc blend(
backdropColor, backdropAlpha, sourceColor, sourceAlpha: uint8
): uint8 {.inline.} =
@ -384,7 +385,7 @@ proc blendDifference(backdrop, source: ColorRGBA): ColorRGBA =
result.b = blend(backdrop.b, backdrop.a, source.b, source.a)
result.a = blendAlpha(backdrop.a, source.a)
proc blendExclusion(backdrop, source: ColorRGBA): ColorRGBA =
proc blendExclusion(backdrop, source: ColorRGBX): ColorRGBX =
proc blend(backdrop, source: uint32): uint8 {.inline.} =
let v = (backdrop + source).int32 - ((2 * backdrop * source) div 255).int32
max(0, v).uint8
@ -393,62 +394,62 @@ proc blendExclusion(backdrop, source: ColorRGBA): ColorRGBA =
result.b = blend(backdrop.b.uint32, source.b.uint32)
result.a = blendAlpha(backdrop.a, source.a)
proc blendColor(backdrop, source: ColorRGBA): ColorRGBA =
proc blendColor(backdrop, source: ColorRGBX): ColorRGBX =
let
backdrop = backdrop.toStraightAlpha().color
source = source.toStraightAlpha().color
blended = SetLum(source, Lum(backdrop))
result = alphaFix(backdrop, source, blended).rgba.toPremultipliedAlpha()
proc blendLuminosity(backdrop, source: ColorRGBA): ColorRGBA =
proc blendLuminosity(backdrop, source: ColorRGBX): ColorRGBX =
let
backdrop = backdrop.toStraightAlpha().color
source = source.toStraightAlpha().color
blended = SetLum(backdrop, Lum(source))
result = alphaFix(backdrop, source, blended).rgba.toPremultipliedAlpha()
proc blendHue(backdrop, source: ColorRGBA): ColorRGBA =
proc blendHue(backdrop, source: ColorRGBX): ColorRGBX =
let
backdrop = backdrop.toStraightAlpha().color
source = source.toStraightAlpha().color
blended = SetLum(SetSat(source, Sat(backdrop)), Lum(backdrop))
result = alphaFix(backdrop, source, blended).rgba.toPremultipliedAlpha()
proc blendSaturation(backdrop, source: ColorRGBA): ColorRGBA =
proc blendSaturation(backdrop, source: ColorRGBX): ColorRGBX =
let
backdrop = backdrop.toStraightAlpha().color
source = source.toStraightAlpha().color
blended = SetLum(SetSat(backdrop, Sat(source)), Lum(backdrop))
result = alphaFix(backdrop, source, blended).rgba.toPremultipliedAlpha()
proc blendMask(backdrop, source: ColorRGBA): ColorRGBA =
proc blendMask(backdrop, source: ColorRGBX): ColorRGBX =
let k = source.a.uint32
result.r = ((backdrop.r * k) div 255).uint8
result.g = ((backdrop.g * k) div 255).uint8
result.b = ((backdrop.b * k) div 255).uint8
result.a = ((backdrop.a * k) div 255).uint8
proc blendSubtractMask(backdrop, source: ColorRGBA): ColorRGBA =
proc blendSubtractMask(backdrop, source: ColorRGBX): ColorRGBX =
let a = (backdrop.a.uint32 * (255 - source.a)) div 255
result.r = ((backdrop.r * a) div 255).uint8
result.g = ((backdrop.g * a) div 255).uint8
result.b = ((backdrop.b * a) div 255).uint8
result.a = a.uint8
proc blendIntersectMask(backdrop, source: ColorRGBA): ColorRGBA =
proc blendIntersectMask(backdrop, source: ColorRGBX): ColorRGBX =
blendMask(backdrop, source)
proc blendExcludeMask(backdrop, source: ColorRGBA): ColorRGBA =
proc blendExcludeMask(backdrop, source: ColorRGBX): ColorRGBX =
let a = max(backdrop.a, source.a).uint32 - min(backdrop.a, source.a)
result.r = ((backdrop.r * a) div 255).uint8
result.g = ((backdrop.g * a) div 255).uint8
result.b = ((backdrop.b * a) div 255).uint8
result.a = a.uint8
proc blendOverwrite(backdrop, source: ColorRGBA): ColorRGBA =
proc blendOverwrite(backdrop, source: ColorRGBX): ColorRGBX =
source
# proc blendWhite(backdrop, source: ColorRGBA): ColorRGBA =
# proc blendWhite(backdrop, source: ColorRGBX): ColorRGBX =
# ## For testing
# rgba(255, 255, 255, 255)

View file

@ -14,7 +14,7 @@ proc lerp*(a, b: uint8, t: float32): uint8 {.inline.} =
let t = round(t * 255).uint32
((a * (255 - t) + b * t) div 255).uint8
proc lerp*(a, b: ColorRGBA, t: float32): ColorRGBA {.inline.} =
proc lerp*(a, b: ColorRGBX, t: float32): ColorRGBX {.inline.} =
## Linearly interpolate between a and b using t.
let x = round(t * 255).uint32
result.r = ((a.r.uint32 * (255 - x) + b.r.uint32 * x) div 255).uint8
@ -28,36 +28,3 @@ func lerp*(a, b: Color, v: float32): Color {.inline.} =
result.g = lerp(a.g, b.g, v)
result.b = lerp(a.b, b.b, v)
result.a = lerp(a.a, b.a, v)
proc toPremultipliedAlpha*(c: ColorRGBA): ColorRGBA {.inline.} =
## Converts a color to premultiplied alpha from straight alpha.
result.r = ((c.r.uint32 * c.a.uint32) div 255).uint8
result.g = ((c.g.uint32 * c.a.uint32) div 255).uint8
result.b = ((c.b.uint32 * c.a.uint32) div 255).uint8
result.a = c.a
proc toStraightAlpha*(c: ColorRGBA): ColorRGBA {.inline.} =
## Converts a color from premultiplied alpha to straight alpha.
result = c
if result.a != 0 and result.a != 255:
let multiplier = ((255 / c.a.float32) * 255).uint32
result.r = ((result.r.uint32 * multiplier) div 255).uint8
result.g = ((result.g.uint32 * multiplier) div 255).uint8
result.b = ((result.b.uint32 * multiplier) div 255).uint8
proc toPremultipliedAlpha*(c: Color): Color {.inline.} =
## Converts a color to premultiplied alpha from straight alpha.
result.r = c.r * c.a
result.g = c.g * c.a
result.b = c.b * c.a
result.a = c.a
proc toStraightAlpha*(c: Color): Color {.inline.} =
## Converts a color from premultiplied alpha to straight alpha.
if c.a != 0 and c.a != 1:
result = c
else:
result.r = c.r / c.a
result.g = c.g / c.a
result.b = c.b / c.a
result.a = c.a

View file

@ -1,4 +1,4 @@
import chroma, flatty/binny, pixie/common, pixie/images, pixie/internal
import chroma, flatty/binny, pixie/common, pixie/images
# See: https://en.wikipedia.org/wiki/BMP_file_format
@ -48,8 +48,6 @@ proc decodeBmp*(data: string): Image =
offset += 3
result[x, result.height - y - 1] = rgba
result.data.toPremultipliedAlpha()
proc decodeBmp*(data: seq[uint8]): Image {.inline.} =
## Decodes bitmap data into an Image.
decodeBmp(cast[string](data))

View file

@ -407,11 +407,13 @@ proc decodePng*(data: seq[uint8]): Image =
if prevChunkType != "IEND":
failInvalid()
var pixels = decodeImageData(header, palette, transparency, imageData)
pixels.toPremultipliedAlpha()
result = Image()
result.width = header.width
result.height = header.height
result.data = decodeImageData(header, palette, transparency, imageData)
result.data.toPremultipliedAlpha()
result.data = cast[seq[ColorRGBX]](pixels)
proc decodePng*(data: string): Image {.inline.} =
## Decodes the PNG data into an Image.

View file

@ -81,7 +81,7 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
elif fill == "none":
result.fill = ColorRGBA()
else:
result.fill = parseHtmlColor(fill).rgba.toPremultipliedAlpha()
result.fill = parseHtmlColor(fill).rgba
if stroke == "":
discard # Inherit
@ -90,7 +90,7 @@ proc decodeCtx(inherited: Ctx, node: XmlNode): Ctx =
elif stroke == "none":
result.stroke = ColorRGBA()
else:
result.stroke = parseHtmlColor(stroke).rgba.toPremultipliedAlpha()
result.stroke = parseHtmlColor(stroke).rgba
result.shouldStroke = true
if strokeWidth == "":

View file

@ -9,7 +9,7 @@ type
Image* = ref object
## Image object that holds bitmap data in RGBA format.
width*, height*: int
data*: seq[ColorRGBA]
data*: seq[ColorRGBX]
when defined(release):
{.push checks: off.}
@ -22,7 +22,7 @@ proc newImage*(width, height: int): Image =
result = Image()
result.width = width
result.height = height
result.data = newSeq[ColorRGBA](width * height)
result.data = newSeq[ColorRGBX](width * height)
proc wh*(image: Image): Vec2 {.inline.} =
## Return with and height as a size vector.
@ -44,31 +44,31 @@ proc inside*(image: Image, x, y: int): bool {.inline.} =
proc dataIndex*(image: Image, x, y: int): int {.inline.} =
image.width * y + x
proc getRgbaUnsafe*(image: Image, x, y: int): ColorRGBA {.inline.} =
proc getRgbaUnsafe*(image: Image, x, y: int): ColorRGBX {.inline.} =
## Gets a color from (x, y) coordinates.
## * No bounds checking *
## Make sure that x, y are in bounds.
## Failure in the assumptions will case unsafe memory reads.
result = image.data[image.width * y + x]
proc `[]`*(image: Image, x, y: int): ColorRGBA {.inline.} =
proc `[]`*(image: Image, x, y: int): ColorRGBX {.inline.} =
## Gets a pixel at (x, y) or returns transparent black if outside of bounds.
if image.inside(x, y):
return image.getRgbaUnsafe(x, y)
proc setRgbaUnsafe*(image: Image, x, y: int, rgba: ColorRGBA) {.inline.} =
proc setRgbaUnsafe*(image: Image, x, y: int, rgba: ColorRGBX) {.inline.} =
## Sets a color from (x, y) coordinates.
## * No bounds checking *
## Make sure that x, y are in bounds.
## Failure in the assumptions will case unsafe memory writes.
image.data[image.dataIndex(x, y)] = rgba
proc `[]=`*(image: Image, x, y: int, rgba: ColorRGBA) {.inline.} =
proc `[]=`*(image: Image, x, y: int, rgba: ColorRGBX) {.inline.} =
## Sets a pixel at (x, y) or does nothing if outside of bounds.
if image.inside(x, y):
image.setRgbaUnsafe(x, y, rgba)
proc fillUnsafe*(data: var seq[ColorRGBA], rgba: ColorRGBA, start, len: int) =
proc fillUnsafe*(data: var seq[ColorRGBX], rgba: ColorRGBX, start, len: int) =
## Fills the image data with the parameter color starting at index start and
## continuing for len indices.
@ -97,7 +97,7 @@ proc fillUnsafe*(data: var seq[ColorRGBA], rgba: ColorRGBA, start, len: int) =
for j in i ..< start + len:
data[j] = rgba
proc fill*(image: Image, rgba: ColorRgba) {.inline.} =
proc fill*(image: Image, rgba: ColorRGBX) {.inline.} =
## Fills the image with the parameter color.
fillUnsafe(image.data, rgba, 0, image.data.len)
@ -187,7 +187,7 @@ proc minifyBy2*(image: Image, power = 1): Image =
c = src.getRgbaUnsafe(x * 2 + 1, y * 2 + 1)
d = src.getRgbaUnsafe(x * 2 + 0, y * 2 + 1)
let color = rgba(
let color = rgbx(
((a.r.uint32 + b.r + c.r + d.r) div 4).uint8,
((a.g.uint32 + b.g + c.g + d.g) div 4).uint8,
((a.b.uint32 + b.b + c.b + d.b) div 4).uint8,
@ -217,7 +217,7 @@ proc applyOpacity*(target: Image | Mask, opacity: float32) =
if opacity == 0:
when type(target) is Image:
target.fill(rgba(0, 0, 0, 0))
target.fill(rgbx(0, 0, 0, 0))
else:
target.fill(0)
return
@ -458,7 +458,7 @@ proc newMask*(image: Image): Mask =
for j in i ..< image.data.len:
result.data[j] = image.data[j].a
proc getRgbaSmooth*(image: Image, x, y: float32, wrapped = false): ColorRGBA =
proc getRgbaSmooth*(image: Image, x, y: float32, wrapped = false): ColorRGBX =
## Gets a interpolated color with float point coordinates.
## Pixes outside the image are transparent.
let
@ -473,7 +473,7 @@ proc getRgbaSmooth*(image: Image, x, y: float32, wrapped = false): ColorRGBA =
x1 = (x + 1)
y1 = (y + 1)
var x0y0, x1y0, x0y1, x1y1: ColorRGBA
var x0y0, x1y0, x0y1, x1y1: ColorRGBX
if wrapped:
x0y0 = image.getRgbaUnsafe(x0 mod image.width, y0 mod image.height)
x1y0 = image.getRgbaUnsafe(x1 mod image.width, y0 mod image.height)
@ -642,7 +642,7 @@ proc drawUber(a, b: Image | Mask, mat = mat3(), blendMode = bmNormal) =
else: # b is a Mask
let
sample = b.getValueSmooth(xFloat, yFloat)
blended = blender(backdrop, rgba(0, 0, 0, sample))
blended = blender(backdrop, rgbx(0, 0, 0, sample))
a.setRgbaUnsafe(x, y, blended)
else: # a is a Mask
let backdrop = a.getValueUnsafe(x, y)
@ -729,7 +729,7 @@ proc drawUber(a, b: Image | Mask, mat = mat3(), blendMode = bmNormal) =
else: # b is a Mask
let
sample = b.getValueUnsafe(xFloat.int, yFloat.int)
blended = blender(backdrop, rgba(0, 0, 0, sample))
blended = blender(backdrop, rgbx(0, 0, 0, sample))
a.setRgbaUnsafe(x, y, blended)
else: # a is a Mask
let backdrop = a.getValueUnsafe(x, y)
@ -812,7 +812,7 @@ proc shift*(target: Image | Mask, offset: Vec2) =
target.draw(copy, offset, bmOverwrite) # Draw copy at offset
proc shadow*(
image: Image, offset: Vec2, spread, blur: float32, color: ColorRGBA
image: Image, offset: Vec2, spread, blur: float32, color: ColorRGBX
): Image =
## Create a shadow of the image with the offset, spread and blur.
let mask = image.newMask()

View file

@ -3,7 +3,7 @@ import chroma
when defined(amd64) and not defined(pixieNoSimd):
import nimsimd/sse2
proc toStraightAlpha*(data: var seq[ColorRGBA]) =
proc toStraightAlpha*(data: var seq[ColorRGBA | ColorRGBX]) =
## Converts an image from premultiplied alpha to straight alpha.
## This is expensive for large images.
for c in data.mitems:
@ -14,7 +14,7 @@ proc toStraightAlpha*(data: var seq[ColorRGBA]) =
c.g = ((c.g.uint32 * multiplier) div 255).uint8
c.b = ((c.b.uint32 * multiplier) div 255).uint8
proc toPremultipliedAlpha*(data: var seq[ColorRGBA]) =
proc toPremultipliedAlpha*(data: var seq[ColorRGBA | ColorRGBX]) =
## Converts an image to premultiplied alpha from straight alpha.
var i: int
when defined(amd64) and not defined(pixieNoSimd):

View file

@ -1,4 +1,4 @@
import blends, chroma, common, images, vmath
import blends, chroma, images, vmath
type
PaintKind* = enum
@ -13,7 +13,7 @@ type
## Paint used to fill paths.
case kind*: PaintKind
of pkSolid:
color*: ColorRGBA ## Color to fill with.
color*: ColorRGBX ## Color to fill with.
of pkImage, pkImageTiled:
image*: Image ## Image to fill with.
imageMat*: Mat3 ## Matrix of the filled image.

View file

@ -1105,7 +1105,7 @@ template computeCoverages(
proc fillShapes(
image: Image,
shapes: seq[seq[Vec2]],
color: ColorRGBA,
color: ColorRGBX,
windingRule: WindingRule,
blendMode: BlendMode
) =
@ -1418,7 +1418,7 @@ proc parseSomePath(
proc fillPath*(
image: Image,
path: SomePath,
color: ColorRGBA,
color: ColorRGBX,
windingRule = wrNonZero,
blendMode = bmNormal
) {.inline.} =
@ -1428,7 +1428,7 @@ proc fillPath*(
proc fillPath*(
image: Image,
path: SomePath,
color: ColorRGBA,
color: ColorRGBX,
transform: Vec2 | Mat3,
windingRule = wrNonZero,
blendMode = bmNormal
@ -1488,7 +1488,7 @@ proc fillPath*(
case paint.kind:
of pkSolid:
fill.fill(paint.color.toPremultipliedAlpha())
fill.fill(paint.color)
of pkImage:
fill.draw(paint.image, paint.imageMat)
of pkImageTiled:
@ -1520,7 +1520,7 @@ proc fillPath*(
proc strokePath*(
image: Image,
path: SomePath,
color: ColorRGBA,
color: ColorRGBX,
strokeWidth = 1.0,
lineCap = lcButt,
lineJoin = ljMiter,
@ -1535,7 +1535,7 @@ proc strokePath*(
proc strokePath*(
image: Image,
path: SomePath,
color: ColorRGBA,
color: ColorRGBX,
transform: Vec2 | Mat3,
strokeWidth = 1.0,
lineCap = lcButt,

View file

@ -30,10 +30,10 @@ block:
block:
let image = newImage(100, 100)
image.fill(rgba(200, 200, 200, 200))
image.fill(rgbx(200, 200, 200, 200))
image.applyOpacity(0.5)
doAssert image[0, 0] == rgba(100, 100, 100, 100)
doAssert image[88, 88] == rgba(100, 100, 100, 100)
doAssert image[0, 0] == rgbx(100, 100, 100, 100)
doAssert image[88, 88] == rgbx(100, 100, 100, 100)
block:
let
@ -101,6 +101,6 @@ block:
block:
let a = newImage(100, 100)
a.fill(rgba(50, 100, 150, 200))
a.fill(rgbx(50, 100, 150, 200))
a.invert()
doAssert a[0, 0] == rgba(44, 33, 22, 55)
doAssert a[0, 0] == rgbx(44, 33, 22, 55)