Skip to content

Snappy1

  • Home
  • Android
  • What
  • How
  • Is
  • Can
  • Does
  • Do
  • Why
  • Are
  • Who
  • Toggle search form

[FIXED] android – Ellipse’s sides are being cut on large Bitmap?

Posted on November 11, 2022 By

Solution 1 :

Fixed by converting the following to double:

var p2k = (ry.toDouble() * ry.toDouble()) * ((xkp1.toDouble() + 0.5) * (xkp1.toDouble() + 0.5)) + (rx.toDouble() * rx.toDouble()) * ((ykp1.toDouble() - 1) * (ykp1.toDouble() - 1)) - ((rx.toDouble() * rx.toDouble()) * (ry.toDouble() * ry.toDouble()))

Problem :

I am creating a pixel art editor for Android, and recently I implemented an ellipse tool using the midpoint ellipse algorithm.

I would just like to emphasize that this tool works perfectly!

The only problem is, if I draw a large ellipse on a larger bitmap (of around 1000×1000 or more), the sides of the ellipse get cut, and there is some strange behaviour going on:

enter image description here

enter image description here

I am really confused why this is happening, and I would appreciate help.

Code for the midpoint ellipse algorithm:

package com.therealbluepandabear.pixapencil.algorithms

import com.therealbluepandabear.pixapencil.activities.canvas.canvascommands.overrideSetPixel
import com.therealbluepandabear.pixapencil.models.Coordinates

class MidpointEllipseAlgorithm(private val algorithmInfo: AlgorithmInfoParameter, private val xDEC: Boolean = false, private val yDEC: Boolean = false, private val filledMode: Boolean = false) {
    private val shouldLineIgnoreBrush = true

    private fun putPixel(p1: Coordinates, p2: Coordinates) {
        val xc = p1.x
        val yc = p1.y

        val x = p2.x
        val y = p2.y

        if (!xDEC && !yDEC) {
            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates(xc + x, yc + y),
                algorithmInfo.color
            )

            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates(xc + x, yc - y),
                algorithmInfo.color
            )

            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates(xc - x, yc - y),
                algorithmInfo.color
            )

            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates(xc - x, yc + y),
                algorithmInfo.color
            )

            if (filledMode) {
                val lineAlgorithmInstance = LineAlgorithm(algorithmInfo, shouldLineIgnoreBrush)

                lineAlgorithmInstance.compute(
                    Coordinates(xc + x, yc + y),
                    Coordinates(xc + x, yc - y),
                )

                lineAlgorithmInstance.compute(
                    Coordinates(xc - x, yc - y),
                    Coordinates(xc - x, yc + y),
                )
            }
        } else if (xDEC && !yDEC) {
            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates((xc + x) + 1, yc + y),
                algorithmInfo.color
            )

            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates((xc + x) + 1, yc - y),
                algorithmInfo.color
            )

            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates(xc - x, yc - y),
                algorithmInfo.color
            )

            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates(xc - x, yc + y),
                algorithmInfo.color
            )

            if (filledMode) {
                val lineAlgorithmInstance = LineAlgorithm(algorithmInfo, shouldLineIgnoreBrush)

                lineAlgorithmInstance.compute(
                    Coordinates((xc + x) + 1, yc + y),
                    Coordinates((xc + x) + 1, yc - y),
                )

                lineAlgorithmInstance.compute(
                    Coordinates(xc - x, yc - y),
                    Coordinates(xc - x, yc + y),
                )
            }
        } else if (!xDEC && yDEC) {
            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates(xc + x, (yc + y) + 1),
                algorithmInfo.color
            )

            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates(xc + x, yc - y),
                algorithmInfo.color
            )

            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates(xc - x, yc - y),
                algorithmInfo.color
            )

            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates(xc - x, (yc + y) + 1),
                algorithmInfo.color
            )

            if (filledMode) {
                val lineAlgorithmInstance = LineAlgorithm(algorithmInfo, shouldLineIgnoreBrush)

                lineAlgorithmInstance.compute(
                    Coordinates(xc + x, (yc + y) + 1),
                    Coordinates(xc + x, yc - y),
                )

                lineAlgorithmInstance.compute(
                    Coordinates(xc - x, yc - y),
                    Coordinates(xc - x, (yc + y) + 1),
                )
            }
        } else {
            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates((xc + x) + 1, (yc + y) + 1),
                algorithmInfo.color
            )

            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates((xc + x) + 1, yc - y),
                algorithmInfo.color
            )

            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates(xc - x, yc - y),
                algorithmInfo.color
            )

            algorithmInfo.canvasCommandsHelperInstance.overrideSetPixel(
                Coordinates(xc - x, (yc + y) + 1),
                algorithmInfo.color
            )

            if (filledMode) {
                val lineAlgorithmInstance = LineAlgorithm(algorithmInfo, shouldLineIgnoreBrush)

                lineAlgorithmInstance.compute(
                    Coordinates((xc + x) + 1, (yc + y) + 1),
                    Coordinates((xc + x) + 1, yc - y),
                )

                lineAlgorithmInstance.compute(
                    Coordinates(xc - x, yc - y),
                    Coordinates(xc - x, (yc + y) + 1),
                )
            }
        }
    }

    fun compute(p1: Coordinates, rx: Int, ry: Int) {
        val idp = Coordinates(0, ry)

        var xkp1 = idp.x
        var ykp1 = idp.y

        var lxkp1: Int
        var lykp1: Int

        var p1k = (ry * ry) + ((rx * rx) / 4) - (ry * (rx * rx))

        val incy = p1.y
        val incx = p1.x

        putPixel(Coordinates(incx, incy), Coordinates(xkp1, ykp1))

        while (
            (2 * (xkp1 + 1) * (ry * ry))
            <
            (2 * ykp1 * (rx * rx))
        ) {
            p1k += if (p1k >= 0) {
                xkp1++
                ykp1--

                lxkp1 = xkp1 - 1
                lykp1 = ykp1 + 1

                (ry * ry) + (2 * (lxkp1 + 1)) * (ry * ry) + (rx * rx) * ((ykp1 * ykp1) - (lykp1 * lykp1)) - (rx * rx) * (ykp1 - lykp1)
            } else {
                xkp1++

                lxkp1 = xkp1 - 1
                lykp1 = ykp1

                (ry * ry) + (2 * (lxkp1 + 1)) * (ry * ry) + (rx * rx) * ((ykp1 * ykp1) - (lykp1 * lykp1))
            }

            putPixel(Coordinates(incx, incy), Coordinates(xkp1, ykp1))
        }

        var p2k = (ry * ry) * ((xkp1 + 0.5) * (xkp1 + 0.5)) + (rx * rx) * ((ykp1 - 1) * (ykp1 - 1)) - ((rx * rx) * (ry * ry))

        while (
            ykp1 > 0
        ) {
            if (p2k >= 0) {
                ykp1--
                lykp1 = ykp1 + 1
                lxkp1 = xkp1

                p2k += (rx * rx) - 2 * (rx * rx) * (lykp1 - 1) + (ry * ry) * ((xkp1 * xkp1) - (lxkp1 * lxkp1))
            } else {
                xkp1++
                lxkp1 = xkp1 - 1
                ykp1--
                lykp1 = ykp1 + 1

                p2k += (rx * rx) - 2 * (rx * rx) * (lykp1 - 1) + (ry * ry) * ((xkp1 * xkp1) - (lxkp1 * lxkp1)) + (ry * ry) * (xkp1 - lxkp1)
            }

            putPixel(Coordinates(incx, incy), Coordinates(xkp1, ykp1))
        }
    }
}

The problem only exists in the MidpointEllipseAlgorithm, so it’s been isolated. The overrideSetPixel function is not causing this behaviour because when I replace it with a simple Bitmap.setPixel the problem still exists. But, although it’s been isolated, I am confused why this is happening.

READ  [FIXED] geolocation - is there any way to read "select mock location app" from Android developer settings?
Powered by Inline Related Posts

If you draw the ellipse on smaller canvases this behaviour isn’t getting demonstrated, it works perfectly. It’s only if you draw an ellipse of a sufficient size on a large bitmap where this behaviour is demonstrated.

Any help or directions as to why it’s being ‘cut’ like this on large bitmaps would be appreciated. It’s one of those issues where you have absolutely no clue why it’s happening, it’s completely nonsensical as the algorithm itself has been reviewed by my peers and it is to a high standard. I have tried for a couple of hours to fix it by adjusting variables and inequalities but I have no clue where it’s coming from, I even compared my algorithm code to the ones online and still, even if I replace it I get the issue.

Comments

Comment posted by Matt Timmermans

In some places you multiplying 4 coordinates like

Android Tags:algorithm, android, android-bitmap, android-graphics, graphics

Post navigation

Previous Post: [FIXED] Android ACTION_VIEW intent is not opening urls in non-browser apps like twitter and instagram
Next Post: [FIXED] android – Check if activity is active, and if active pass data from service to activity?

Related Posts

[FIXED] Can i use APK of one android app in another? Android
[FIXED] android – Firebase database failing to update Android
[FIXED] java – How to Resize and Reposition ‘ImageView’ by Screen Scale remain its ratio Android
[FIXED] android – How to open any URL inside an app with flutter by tapping on image or card? Android
[FIXED] Button on bottom of image with parameter adjustViewBounds Android studio Android
[FIXED] android – Why do my containers size bigger than the screen size that causes the SingleChildScrollView() to scroll when the keyboard is down? Android

Archives

  • March 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022

Categories

  • ¿Cómo
  • ¿Cuál
  • ¿Cuándo
  • ¿Cuántas
  • ¿Cuánto
  • ¿Qué
  • Android
  • Are
  • At
  • C'est
  • Can
  • Comment
  • Did
  • Do
  • Does
  • Est-ce
  • Est-il
  • For
  • Has
  • Hat
  • How
  • In
  • Is
  • Ist
  • Kann
  • Où
  • Pourquoi
  • Quand
  • Quel
  • Quelle
  • Quelles
  • Quels
  • Qui
  • Should
  • Sind
  • Sollte
  • Uncategorized
  • Wann
  • Warum
  • Was
  • Welche
  • Welchen
  • Welcher
  • Welches
  • Were
  • What
  • What's
  • When
  • Where
  • Which
  • Who
  • Who's
  • Why
  • Wie
  • Will
  • Wird
  • Wo
  • Woher
  • you can create a selvedge edge: You can make the edges of garter stitch more smooth by slipping the first stitch of every row.2022-02-04
  • you really only need to know two patterns: garter stitch

Recent Posts

  • What color are dead flea eggs?
  • What is Indiana vine?
  • What’s the downside of a Chromebook?
  • Is phosphide the same as phosphorus?
  • Why do you need an S bend?

Recent Comments

No comments to show.

Copyright © 2023 Snappy1.

Powered by PressBook Grid Dark theme