Не зная вашей целевой платформы, настоятельно рекомендуется какое-то аппаратное ускорение. OpenGL 2.0+ (или ES 2.0+), скорее всего, поможет - используя GLSL, вы получите язык C-стиля, в котором вам будет интересна поставка фрагментированной программы, которую GPU должен делать для каждого пикселя на основе на входных текстурах, чтобы произвести цвет для вывода. То, куда вы выводите, является неявным, но вы можете вывести на изображение, а затем впоследствии использовать это изображение в качестве входных данных, что бы сразу увязалось с вашей идеей (2). В зависимости от конкретного оборудования, на которое вы нацеливаетесь, может быть уместно, что Direct3d имеет очень похожую конструкцию в HLSL, а NVidia предоставляет более проприетарный эквивалент, называемый Cg, который, я думаю, в настоящее время может компилироваться в GLSL или HLSL.
В противном случае: идея (1) - это разумный ход, особенно если пользователю разрешено открывать изображения произвольного размера. Это приводит к тому, что затраченное время зависит от размера кисти, а не от изображения. Вы должны быть достаточно точными в своем мышлении, если вы делаете вещи с точностью до субпикселя.
Идея (2) потенциально имеет прецизионные последствия (особенно если они связаны с оборудованием) Чтобы поддерживать те же самые результаты, очевидно, что ваши промежуточные буферы должны быть с той же точностью, что и ваши промежуточные переменные, что в типичном ориентированном на потребителя приложении для рисования часто означает, что входные данные для файлов имеют размер 8 бит на канал / канал, но промежуточное хранилище должно быть не менее 16 бит на дюйм / канал, если вы не хотите, чтобы ошибки накапливались. Это, вероятно, будет самым большим потенциальным барьером для аппаратного ускорения, так как старое оборудование имеет тенденцию ограничивать вас промежуточными буферами 8bpp / channel. Современное оборудование может создавать буферы с плавающей запятой приличной точности.
Возможно получить преимущество от предварительного вычисления на слоях, которые будут применены впоследствии, но информация на пиксель, как правило, должна быть более сложной, чем просто цвет, и может оказаться не более простой, чем просто сохранение исходных буферов. Вероятно, разумно сделать оптимизацию глазка. Таким образом, если у вас есть два аддитивных слоя друг на друге, вы можете легко заменить их одним аддитивным слоем. То же самое для двух мультипликативных или двух XOR. Таким образом, вы реализуете цикл, который просматривает очередь эффектов, находит все шаблоны, которые он знает, как превратить в более простую форму, и выполняет эти замены. И повторять до тех пор, пока замены не будут найдены. В целях оптимизации вы можете захотеть реализовать некоторые составные операции, которые не предлагаются непосредственно пользователю. Хотя, опять же, вам нужно учитывать точность.
В общем случае, при обычном смешивании, применяемом ко всем слоям, вы в конечном итоге получите одну операцию для произвольного числа слоев выше.