From 64cfab293d69dbd326875cb79c53507375260aee Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Thu, 25 Feb 2021 17:56:52 -0600 Subject: [PATCH] migrate public api to rgbx --- experiments/svg_cairo.nim | 4 +- src/pixie/blends.nim | 91 ++++++++++++++++++----------------- src/pixie/common.nim | 35 +------------- src/pixie/fileformats/bmp.nim | 4 +- src/pixie/fileformats/png.nim | 6 ++- src/pixie/fileformats/svg.nim | 4 +- src/pixie/images.nim | 30 ++++++------ src/pixie/internal.nim | 4 +- src/pixie/paints.nim | 4 +- src/pixie/paths.nim | 12 ++--- tests/test_images.nim | 10 ++-- 11 files changed, 86 insertions(+), 118 deletions(-) diff --git a/experiments/svg_cairo.nim b/experiments/svg_cairo.nim index 768896c..cb14fb6 100644 --- a/experiments/svg_cairo.nim +++ b/experiments/svg_cairo.nim @@ -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 == "": diff --git a/src/pixie/blends.nim b/src/pixie/blends.nim index 72c7246..2af2546 100644 --- a/src/pixie/blends.nim +++ b/src/pixie/blends.nim @@ -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) diff --git a/src/pixie/common.nim b/src/pixie/common.nim index 5158209..2166998 100644 --- a/src/pixie/common.nim +++ b/src/pixie/common.nim @@ -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 diff --git a/src/pixie/fileformats/bmp.nim b/src/pixie/fileformats/bmp.nim index 2f0feb4..f4e11a6 100644 --- a/src/pixie/fileformats/bmp.nim +++ b/src/pixie/fileformats/bmp.nim @@ -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)) diff --git a/src/pixie/fileformats/png.nim b/src/pixie/fileformats/png.nim index 8251c8e..adac912 100644 --- a/src/pixie/fileformats/png.nim +++ b/src/pixie/fileformats/png.nim @@ -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. diff --git a/src/pixie/fileformats/svg.nim b/src/pixie/fileformats/svg.nim index ae69d60..c380cf4 100644 --- a/src/pixie/fileformats/svg.nim +++ b/src/pixie/fileformats/svg.nim @@ -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 == "": diff --git a/src/pixie/images.nim b/src/pixie/images.nim index a4ca175..eb475fa 100644 --- a/src/pixie/images.nim +++ b/src/pixie/images.nim @@ -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() diff --git a/src/pixie/internal.nim b/src/pixie/internal.nim index 154e258..7ec78ef 100644 --- a/src/pixie/internal.nim +++ b/src/pixie/internal.nim @@ -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): diff --git a/src/pixie/paints.nim b/src/pixie/paints.nim index 66eb544..32daa68 100644 --- a/src/pixie/paints.nim +++ b/src/pixie/paints.nim @@ -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. diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim index 777c9da..cf7489a 100644 --- a/src/pixie/paths.nim +++ b/src/pixie/paths.nim @@ -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, diff --git a/tests/test_images.nim b/tests/test_images.nim index 8771366..e51e74b 100644 --- a/tests/test_images.nim +++ b/tests/test_images.nim @@ -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)