TheAcharya / MarkerData

The avant-garde Marker extraction application crafted for Final Cut Pro
https://markerdata.theacharya.co
MIT License
22 stars 1 forks source link

Adding white border to Colour Swatch #71

Closed IAmVigneswaran closed 2 months ago

IAmVigneswaran commented 2 months ago

@DenDmitriev You can update us with relevant code to add white border to the image palette strip.

Thank you.

DenDmitriev commented 2 months ago

I'll add a border later in my GrabShot code. You can pick up the code from there. I'll write about it here.

IAmVigneswaran commented 2 months ago

I'll add a border later in my GrabShot code. You can pick up the code from there. I'll write about it here.

Thank you!

DenDmitriev commented 2 months ago

I added the ability to create flower rims. The code can be viewed here https://github.com/DenDmitriev/GrabShot/blob/e201097495d839a9096e17da8c2a0797086ea445/GrabShot/Service/ImageRenderService/ImageMergeOperation.swift#L93-L190

    static func createContextRectangle(colors: [Color], width: Int, height: Int, border: Int? = nil, borderColor: CGColor? = nil) -> CGContext? {
        var widthBorder = border ?? .zero
        // Check size border
        if widthBorder > width / 10, !(0...99 ~= widthBorder), widthBorder > width / 3 {
            widthBorder = .zero
        }
        let countSegments = colors.count
        let widthTotalBorder = widthBorder * (countSegments - 1) + 2 * widthBorder
        let widthColors = width - widthTotalBorder
        let widthSegment = widthColors / countSegments
        let remainder = widthColors % colors.count

        let borderColor = borderColor ?? CGColor(srgbRed: 1, green: 1, blue: 1, alpha: 1.0) // white
        let borderColorAsUInt = Self.cgColorToUInt32(borderColor)

        let colorsAsUInt = colors.map { cgColorToUInt32($0.cgColor ?? CGColor(srgbRed: 0, green: 0, blue: 0, alpha: 1))}

        // Pixel line 1D
        var pixelsOnLine: [UInt32] = []
        pixelsOnLine.reserveCapacity(width)

        guard
            width >= countSegments
        else { return nil }

        let createBorder = widthBorder > .zero
        colorsAsUInt.forEach { colorAsUInt in
            if createBorder {
                for _ in Array(1...widthBorder) {
                    pixelsOnLine.append(borderColorAsUInt)
                }
            }
            for _ in Array(1...widthSegment) {
                pixelsOnLine.append(colorAsUInt)
            }
        }
        // Add colors if has remainder pixels 1D
        if remainder != 0,
           let lastColor = colorsAsUInt.last {
            Array(1...remainder).forEach { _ in
                pixelsOnLine.append(lastColor)
            }
        }
        // Close line 1D with border
        if createBorder {
            for _ in Array(1...widthBorder) {
                pixelsOnLine.append(borderColorAsUInt)
            }
        }

        // Rectangle pixels 2D
        var pixels: [UInt32] = []
        pixels.reserveCapacity(width * height)
        // Add top border
        if createBorder {
            let borderLine: [UInt32] = Array(repeating: borderColorAsUInt, count: width * Int(widthBorder))
            pixels.append(contentsOf: borderLine)
        }
        // Add colors rectangles with separator
        let heightColors = createBorder ? (height - (widthBorder * 2)) : height
        for _ in Array(1...heightColors) {
            pixels += pixelsOnLine
        }
        // Add bottom border
        if createBorder {
            let borderLine: [UInt32] = Array(repeating: borderColorAsUInt, count: width * Int(widthBorder))
            pixels.append(contentsOf: borderLine)
        }

        let mutableBufferPointer =  pixels.withUnsafeMutableBufferPointer { pixelsPtr in
            return pixelsPtr.baseAddress
        }

        let bytesPerRow = width * 4

        let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue

        let context = CGContext(
            data: mutableBufferPointer,
            width: width,
            height: height,
            bitsPerComponent: 8,
            bytesPerRow: bytesPerRow,
            space: CGColorSpaceCreateDeviceRGB(),
            bitmapInfo: bitmapInfo
        )

        return context
    }

    private static func cgColorToUInt32(_ cgColor: CGColor) -> UInt32 {
        let red255   = UInt32(cgColor.red * 255)
        let green255 = UInt32(cgColor.green * 255)
        let blue255  = UInt32(cgColor.blue * 255)
        let alpha255 = UInt32(cgColor.alpha * 255)
        let colorAsUInt: UInt32 = (red255 << 24) | (green255 << 16) | (blue255 << 8) | (alpha255 << 0)
        return colorAsUInt
    }
milanvarady commented 2 months ago

@IAmVigneswaran I have added an option for the border. How thick should it be? Currently, it is 5 pixels wide and the color is white. It looks like this:

Marker Data Demo_V6_00_03_12_20

IAmVigneswaran commented 2 months ago

@milanvarady Let's hardcode this white border option. User's don't have to fiddle with this. Yes, 5px looks about right.

IAmVigneswaran commented 2 months ago

@DenDmitriev Thank you for providing the necessary code.