Как можно написать этот базовый оператор PAINT на JavaScript?

В BASIC есть команда PAINT, которая выглядит так:

PAINT (column, row), color, color-stop

Он берет координаты x/y в качестве отправной точки и начинает заполнять его и окружающие пиксели цветом, пока не достигнет цвета, определенного в color-stop. Пример со значениями может быть:

PAINT (200, 400), 4, 6

QuickBasic использует значения от 0 до 15 для представления разных цветов. Каждый из этих цветов имеет эквивалентное шестнадцатеричное значение.

В строках, предшествующих PAINT, обычно есть линии, круги и т. д., нарисованные другим цветом (ограничивающий цвет), которые устанавливают границы того, сколько места на экране может фактически использовать команда PAINT.

Любые идеи о том, как сделать что-то подобное в JavaScript?


person Dave Mackey    schedule 23.11.2016    source источник
comment
Выполните DFS/BFS в точке внутри canvas.getImageData developer.mozilla. org/en-US/docs/Web/API/   -  person Isaac    schedule 23.11.2016
comment
Похоже, это относится только к прямоугольникам?   -  person Dave Mackey    schedule 23.11.2016
comment
получить весь прямоугольник, выполнить DFS из точки на этой карте во всех направлениях, пока не достигнете границы, сохранить запись границы, установить пиксели в пределах этой границы   -  person Isaac    schedule 23.11.2016
comment
en.wikipedia.org/wiki/Flood_fill   -  person Isaac    schedule 23.11.2016
comment
Спасибо! Это полезно. Похоже, мне нужна немного другая заливка границ... хочу посмотреть, что я могу найти на этом, не так сильно, как заливка границ, как заливка заливкой.   -  person Dave Mackey    schedule 23.11.2016
comment
Вам когда-нибудь удавалось достичь того, к чему вы стремились? Я мог бы помочь переделать код, который я предоставил для ваших целей после работы.   -  person Robert Talada    schedule 14.05.2018


Ответы (1)


Я адаптировал решение, которое нашел здесь: http://www.williammalone.com/articles/html5-canvas-javascript-paint-bucket-tool/

Он работает как линия сканирования и создает узлы для возврата сканирования в другом направлении, когда его путь заблокирован, это «пиксельный стек».

В общем, все хорошие решения, которые я видел, включают создание стека заблокированных мест для возврата, из которых путь алгоритма заполнения по существу разветвляется.

        function fill(startX,startY,fcol,bcol,vram){
            // This function adapted from code at:
            // http://www.williammalone.com/articles/html5-canvas-javascript-paint-bucket-tool/
            // and https://github.com/williammalone/HTML5-Paint-Bucket-Tool/blob/master/html5-canvas-paint-bucket.js
            // Copyright 2010 William Malone (www.williammalone.com)
            //
            // Thanks William, yours works better than mine did. :)
            //
            // Licensed under the Apache License, Version 2.0 (the "License");
            // you may not use this fill function except in compliance with the License.
            // You may obtain a copy of the License at
            //
            //   http://www.apache.org/licenses/LICENSE-2.0
            //
            // Unless required by applicable law or agreed to in writing, software
            // distributed under the License is distributed on an "AS IS" BASIS,
            // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
            // See the License for the specific language governing permissions and
            // limitations under the License.

            var pixelStack = [[startX, startY]];
            var startColor = point(startX,startY,vram);

            while(pixelStack.length)
            {
              var newPos, x, y, pixelPos, reachLeft, reachRight;
              newPos = pixelStack.pop();
              x = newPos[0];
              y = newPos[1];

              pixelPos = (y*canvasWidth + x);
              while(y-- >= 25 && matchStartColor(pixelPos,startColor,vram))
              {
                pixelPos -= canvasWidth;
              }
              pixelPos += canvasWidth;
              ++y;
              reachLeft = false;
              reachRight = false;
              while(y++ < canvasHeight-1 && matchStartColor(pixelPos,startColor,vram))
              {
                colorPixel(pixelPos,fcol,vram);

                if(x > 0)
                {
                  if(matchStartColor(pixelPos - 1,startColor,vram))
                  {
                    if(!reachLeft){
                      pixelStack.push([x - 1, y]);
                      reachLeft = true;
                    }
                  }
                  else if(reachLeft)
                  {
                    reachLeft = false;
                  }
                }

                if(x < canvasWidth-1)
                {
                  if(matchStartColor(pixelPos + 1,startColor,vram))
                  {
                    if(!reachRight)
                    {
                      pixelStack.push([x + 1, y]);
                      reachRight = true;
                    }
                  }
                  else if(reachRight)
                  {
                    reachRight = false;
                  }
                }

                pixelPos += canvasWidth;
              }
            }

            function matchStartColor(pixelPos,startColor,vram)
            {
              return (vram[pixelPos]==startColor);
            }

            function colorPixel(pixelPos,col,vram)
            {
              pset(pixelPos%320,Math.floor(pixelPos/320),col,vram)
            }
        }
person Robert Talada    schedule 04.05.2018
comment
Чтобы удовлетворить любое любопытство, этот код использовался в моей попытке портировать редактор спрайтов SCREEN 13 на JavaScript. Если вы хотите увидеть его в использовании, зайдите на: robtalada.com/apps/entity-editor7 (или 8, или какая версия у меня сейчас) - person Robert Talada; 04.05.2018