All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.ru.casperix.multiplatform.util.PixelMapDrawer.kt Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
package ru.casperix.multiplatform.util

import ru.casperix.math.color.float32.Color4f
import ru.casperix.math.color.uint8.Color4b
import ru.casperix.math.vector.int32.Vector2i
import ru.casperix.math.vector.vectorOf
import ru.casperix.misc.max
import ru.casperix.renderer.pixel_map.PixelMap

object PixelMapDrawer {
    val bytesPerPixel = 4

    fun drawImage(
        receiverImage: PixelMap,
        receiverPosition: Vector2i,
        sourceImage: PixelMap,
        sourcePosition: Vector2i,
        areaSize: Vector2i,
        alphaBlending: Boolean
    ) {
        for (y in 0 until areaSize.y) {
            val targetOffset = Vector2i(0, y)
            val sourceOffset = sourcePosition + targetOffset
            blitRow(
                receiverImage,
                receiverPosition + targetOffset,
                sourceImage,
                sourceOffset,
                areaSize.x,
                alphaBlending
            )
        }
    }

    fun fillColor(
        receiverImage: PixelMap,
        receiverPosition: Vector2i,
        sourceColor: Color4b,
        receiverSize: Vector2i,
        alphaBlending: Boolean
    ) {
        for (y in 0 until receiverSize.y) {
            val targetOffset = Vector2i(0, y)
            blitRow(receiverImage, receiverPosition + targetOffset, sourceColor, receiverSize.x, alphaBlending)
        }
    }

    fun blitRow(
        receiverImage: PixelMap,
        receiverPosition: Vector2i,
        sourceImage: PixelMap,
        sourcePosition: Vector2i,
        width: Int,
        alphaBlending: Boolean
    ) {
        if (width <= 0) {

        } else if (sourcePosition.y < 0 || sourcePosition.y >= sourceImage.height || receiverPosition.y < 0 || receiverPosition.y >= receiverImage.height) {

        } else if (sourcePosition.x < 0) {
            val offset = -sourcePosition.x
            blitRow(
                receiverImage,
                receiverPosition,
                sourceImage,
                Vector2i(0, sourcePosition.y),
                width - offset,
                alphaBlending
            )
        } else if (sourcePosition.x + width > sourceImage.width) {
            val widthNext = sourceImage.width - sourcePosition.x
            blitRow(receiverImage, receiverPosition, sourceImage, sourcePosition, widthNext, alphaBlending)
        } else if (receiverPosition.x < 0) {
            val offset = -receiverPosition.x
            blitRow(
                receiverImage,
                Vector2i(0, receiverPosition.y),
                sourceImage,
                sourcePosition,
                width - offset,
                alphaBlending
            )
        } else if (receiverPosition.x + width > receiverImage.width) {
            val widthNext = receiverImage.width - receiverPosition.x
            blitRow(receiverImage, receiverPosition, sourceImage, sourcePosition, widthNext, alphaBlending)
        } else {

            val sourceColorOffset = (sourcePosition.x + sourcePosition.y * sourceImage.width)
            val sourceOffset = bytesPerPixel * sourceColorOffset
            val sourceLength = bytesPerPixel * width
            val sourceBytes = sourceImage.bytes.data.sliceArray(sourceOffset until (sourceOffset + sourceLength))
            val receiverColorOffset = (receiverPosition.x + receiverPosition.y * receiverImage.width)

            if (alphaBlending) {
                val sourceMap = sourceImage.RGBA() ?: return
                val receiverMap = receiverImage.RGBA() ?: return

                (0 until width).forEach { offset ->
                    val sourceColor = sourceMap.get(sourcePosition + vectorOf(offset, 0))
                    val receiverColor = receiverMap.get(receiverPosition + vectorOf(offset, 0))

                    val outputColor = blend(receiverColor, sourceColor)

                    receiverMap.set(receiverPosition + vectorOf(offset, 0), outputColor)
                }
            } else {
                val receiverOffset = bytesPerPixel * receiverColorOffset
                sourceBytes.copyInto(receiverImage.bytes.data, receiverOffset, 0, sourceLength)
//				receiverImage.bytes.data.put(receiverOffset, sourceBytes, 0, sourceLength)
            }
        }
    }

    fun blitRow(
        targetImage: PixelMap,
        targetPosition: Vector2i,
        sourceColor: Color4b,
        width: Int,
        alphaBlending: Boolean
    ) {
        if (width <= 0) {

        } else if (targetPosition.y < 0 || targetPosition.y >= targetImage.height) {

        } else if (targetPosition.x < 0) {
            val offset = -targetPosition.x
            blitRow(targetImage, Vector2i(0, targetPosition.y), sourceColor, width - offset, alphaBlending)
        } else if (targetPosition.x + width >= targetImage.width) {
            val widthNext = targetImage.width - targetPosition.x - 1
            blitRow(targetImage, targetPosition, sourceColor, widthNext, alphaBlending)
        } else {
            val RGBA = targetImage.RGBA() ?: return

            val targetOffset = bytesPerPixel * (targetPosition.x + targetPosition.y * targetImage.width)
            (0 until width).forEach { byteOffset ->
                val byteIndex = targetOffset + byteOffset * 4
                RGBA.set(targetPosition + Vector2i(byteOffset, 0), sourceColor)

                if (alphaBlending) {
                    TODO()//					blend(targetImage.data.getInt(byteIndex), sourceColor.value)
                }
            }
        }
    }

    fun blend(lastValue: Color4b, nextValue: Color4b): Color4b {
        val last = lastValue.toColor4f()
        val next = nextValue.toColor4f()

        val W1 = 1f - next.alpha
        val W2 = next.alpha

        val output = Color4f(
            last.red * W1 + next.red * W2,
            last.green * W1 + next.green * W2,
            last.blue * W1 + next.blue * W2,
            max(last.alpha, next.alpha),
        )

        return output.toColorCode().toColor4b()
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy