diff --git a/Applications/Picture Edit.app/Localizations/English.lang b/Applications/Picture Edit.app/Localizations/English.lang index 972e7f08..0056dfc0 100644 --- a/Applications/Picture Edit.app/Localizations/English.lang +++ b/Applications/Picture Edit.app/Localizations/English.lang @@ -6,6 +6,7 @@ path = "Path: ", save = "Save", saveAs = "Save as", + ok = "Ok", cancel = "Cancel", fileName = "File name", newPicture = "New picture", @@ -35,7 +36,7 @@ "F - braille tool", " ", "X - switch colors", - "D - make colors B/W", + "D - reset drawing colors", }, tool1 = "Selection tool allows you to select preferred area on image and to perform some operations on it. Green dots mean start and end points (for example, it needs to line rasterization)", fill = "Fill", @@ -65,5 +66,24 @@ eraseSym = "Erase symbol:", tool7 = "Text tool allows you to type some text data with selected primary color right on your image! It's time to say \"ur mom gay\" to everyone <3", tool8 = "Fill tool allows you to automatically fill areas with selected primary color just like in Paint. Oh God, where is my RAM...?", - tool9 = "Braille tool allows you to draw pixels with Braille symbols on your image. Select preferred mini-pixels via menu above, configure transparency affecting and \"Let's go fellas!\"" -} \ No newline at end of file + tool9 = "Braille tool allows you to draw pixels with Braille symbols on your image. Select preferred mini-pixels via menu above, configure transparency affecting and \"Let's go fellas!\"", + image = "Image", + edit = "Edit", + rotate90 = "Rotate by 90 degrees", + rotate180 = "Rotate by 180 degrees", + rotate270 = "Rotate by 270 degrees", + flipVertical = "Flip vertical", + flipHorizontal = "Flip horizontal", + hueSaturation = "Hue/Saturation", + colorBalance = "Color balance", + photoFilter = "Photo filter", + invertColors = "Invert colors", + blackWhite = "Black and white", + gaussianBlur = "Gaussian blur", + hue = "Hue: ", + saturation = "Saturation: ", + brightness = "Brightness: ", + filterColor = "Filter color", + transparency = "Transparency: ", + force = "Force" +} diff --git a/Applications/Picture Edit.app/Localizations/Russian.lang b/Applications/Picture Edit.app/Localizations/Russian.lang index 4aa907b7..65d54d23 100644 --- a/Applications/Picture Edit.app/Localizations/Russian.lang +++ b/Applications/Picture Edit.app/Localizations/Russian.lang @@ -6,6 +6,7 @@ path = "Путь: ", save = "Сохранить", saveAs = "Сохранить как", + ok = "Ok", cancel = "Отмена", fileName = "Имя файла", newPicture = "Новое изображение", @@ -35,7 +36,7 @@ "F - символы брайля", " ", "X - поменять цвета", - "D - убрать цвет в изображении", + "D - сбросить цвета рисованияы", }, tool1 = "Инструмент выделения способен выделять отдельные участки изображения и делать с ними определенные действия. Зелеными точками обозначается начало и конец выделения (полезно для растеризации линии)", fill = "Залить", @@ -50,7 +51,7 @@ tool4 = "Инструмент пипетка позволяет получать первичный и вторичный цвет выбранного пикселя. Вы можете выбрать, какие цвета захватывать.", pickBack = "Захватывать фон:", pickFor = "Захватывать перед:", - tool5 = "Классический инструмент кисть прозволяет рисовать на изображении с указанным радиусом и прозрачностью. Вы можете выбрать, что будет рисоваться. Также можно выбрать символ, которым будет рисовать кисть, иначе она будет рисовать пустым символом.", + tool5 = "Классический инструмент кисть позволяет рисовать на изображении с указанным радиусом и прозрачностью. Вы можете выбрать, что будет рисоваться. Также можно выбрать символ, которым будет рисовать кисть, иначе она будет рисовать пустым символом.", drawBack = "Рисовать на фоне:", drawFor = "Рисовать на пер.:", drawAlpha = "Изменять прозр.:", @@ -65,5 +66,24 @@ eraseSym = "Стирать символ:", tool7 = "Инструмент текста позволяет писать текст с указанным первичным и вторичным цветом прямо на изображении! Время сказать всем \"твоя мама гей\" <3", tool8 = "Инструмент заливка позволяет автоматически заполнять зоны с указанным первичным и вторичным цветом, как это делает Paint. О боже, а где вся оперативка...?", - tool9 = "Утилита Брайля позволяет рисовать пиксели с помощью шрифта Брайля. Выберите мини-пиксели в свойствах, настройте прозрачность и поехали!" -} \ No newline at end of file + tool9 = "Инструмент Брайля позволяет рисовать пиксели с помощью шрифта Брайля. Выберите мини-пиксели в свойствах, настройте прозрачность и поехали!", + image = "Изображение", + edit = "Редактировать", + rotate90 = "Повернуть на 90 градусов", + rotate180 = "Повернуть на 180 градусов", + rotate270 = "Повернуть на 270 градусов", + flipVertical = "Отразить по вертикали", + flipHorizontal = "Отразить по горизонтали", + hueSaturation = "Тон/Насыщенность", + colorBalance = "Цветовой баланс", + photoFilter = "Фотофильтр", + invertColors = "Инвертировать цвета", + blackWhite = "Черно-белый фильтр", + gaussianBlur = "Размытие по Гауссу", + hue = "Тон: ", + saturation = "Насыщенность: ", + brightness = "Яркость: ", + filterColor = "Цвет фильтра", + transparency = "Прозрачность: ", + force = "Сила: " +} diff --git a/Applications/Picture Edit.app/Main.lua b/Applications/Picture Edit.app/Main.lua index 1d53e20e..aed64928 100644 --- a/Applications/Picture Edit.app/Main.lua +++ b/Applications/Picture Edit.app/Main.lua @@ -134,7 +134,6 @@ window.sidebarLayout.eventHandler = function(workspace, object, e1, e2, e3, e4, end window.sidebarLayout:setMargin(1, 1, h, v) - workspace:draw() end end @@ -146,7 +145,6 @@ for i = 1, #config.recentColors do local button = recentColorsContainer:addChild(GUI.button(x, y, 2, 1, 0x0, 0x0, 0x0, 0x0, " ")) button.onTouch = function() window.primaryColorSelector.color = config.recentColors[i] - workspace:draw() end x = x + 2 @@ -199,7 +197,6 @@ local function onToolTouch(index) aboutToolTextBox.height = #aboutToolTextBox.lines end - workspace:draw() end local tools = filesystem.list(toolsPath) @@ -277,7 +274,6 @@ end local function swapColors() window.primaryColorSelector.color, window.secondaryColorSelector.color = window.secondaryColorSelector.color, window.primaryColorSelector.color - workspace:draw() end local function colorSelectorDraw(object) @@ -292,7 +288,7 @@ window.secondaryColorSelector = window:addChild(GUI.colorSelector(3, 1, 5, 2, 0x window.primaryColorSelector = window:addChild(GUI.colorSelector(2, 1, 5, 2, 0x000000, " ")) window.secondaryColorSelector.draw, window.primaryColorSelector.draw = colorSelectorDraw, colorSelectorDraw -window.swapColorsButton = window:addChild(GUI.button(1, 1, window.toolsList.width, 1, nil, 0x696969, nil, 0xA5A5A5, ">")) +window.swapColorsButton = window:addChild(GUI.button(1, 1, window.toolsList.width, 1, nil, 0x696969, nil, 0xA5A5A5, " ←→")) window.swapColorsButton.onTouch = swapColors local function setSavePath(path) @@ -346,7 +342,6 @@ local function saveAs() filesystemDialog.onSubmit = function(path) save(path) - workspace:draw() end end @@ -365,6 +360,7 @@ end local function new() local container = GUI.addBackgroundContainer(workspace, true, true, locale.newPicture) + container.panel.eventHandler = nil local layout = container.layout:addChild(GUI.layout(1, 1, 36, 3, 1, 1)) layout:setDirection(1, 1, GUI.DIRECTION_HORIZONTAL) @@ -378,23 +374,23 @@ local function new() layout:addChild(GUI.text(1, 1, 0x696969, " x ")) local heightInput = addInput("", locale.height) widthInput.width, heightInput.width = 16, 17 - - container.panel.eventHandler = function(workspace, panel, e1) - if e1 == "touch" then - if - widthInput.text:match("%d+") and - heightInput.text:match("%d+") - then - newNoGUI(tonumber(widthInput.text), tonumber(heightInput.text), nil) - window.image.reposition() - end - - container:remove() - workspace:draw() + + container.layout:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.ok)).onTouch = function() + if + widthInput.text:match("%d+") and + heightInput.text:match("%d+") + then + newNoGUI(tonumber(widthInput.text), tonumber(heightInput.text), nil) + window.image.reposition() end + + container:remove() + end + + container.layout:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.cancel)).onTouch = function() + container:remove() end - workspace:draw() end local function open() @@ -409,7 +405,6 @@ local function open() loadImage(path) window.image.reposition() - workspace:draw() end end @@ -484,9 +479,7 @@ fileItem:addItem(locale.new, false, "^N").onTouch = new fileItem:addSeparator() -fileItem:addItem(locale.open, false, "^O").onTouch = function() - open() -end +fileItem:addItem(locale.open, false, "^O").onTouch = open local fileItemSubMenu = fileItem:addSubMenuItem(locale.openRecent, #config.recentFiles == 0) for i = 1, #config.recentFiles do @@ -494,17 +487,23 @@ for i = 1, #config.recentFiles do loadImage(config.recentFiles[i]) window.image.reposition() - workspace:draw() end end fileItem:addItem(locale.openFromURL).onTouch = function() local container = GUI.addBackgroundContainer(workspace, true, true, locale.openFromURL) + container.panel.eventHandler = nil local input = container.layout:addChild(GUI.input(1, 1, 36, 3, 0xE1E1E1, 0x696969, 0x969696, 0xE1E1E1, 0x2D2D2D, "", "http://example.com/test.pic")) - input.onInputFinished = function() + local okBut = container.layout:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.ok)) + local cancelBut = container.layout:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.cancel)) + + okBut.onTouch = function() if #input.text > 0 then input:remove() + okBut:remove() + cancelBut:remove() + container.layout:addChild(GUI.label(1, 1, container.width, 1, 0x969696, locale.downloading):setAlignment(GUI.ALIGNMENT_HORIZONTAL_CENTER, GUI.ALIGNMENT_VERTICAL_TOP)) workspace:draw() @@ -523,11 +522,14 @@ fileItem:addItem(locale.openFromURL).onTouch = function() GUI.alert(reason) end - workspace:draw() + else + container:remove() end end - - workspace:draw() + + cancelBut.onTouch = function() + container:remove() + end end fileItem:addSeparator() @@ -541,28 +543,163 @@ fileItem:addItem(locale.saveAs, false, "^⇧S").onTouch = saveAs menu:addItem(locale.view).onTouch = function() local container = GUI.addBackgroundContainer(workspace, true, true, locale.view) + container.panel.eventHandler = nil local colorSelector1 = container.layout:addChild(GUI.colorSelector(1, 1, 36, 3, config.transparencyBackground, locale.transBack)) local colorSelector2 = container.layout:addChild(GUI.colorSelector(1, 1, 36, 3, config.transparencyForeground, locale.transFor)) - - container.panel.eventHandler = function(workspace, object, e1) - if e1 == "touch" then - config.transparencyBackground, config.transparencyForeground = colorSelector1.color, colorSelector2.color + + container.layout:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.ok)).onTouch = function() + config.transparencyBackground, config.transparencyForeground = colorSelector1.color, colorSelector2.color - container:remove() - workspace:draw() - saveConfig() - end + container:remove() + saveConfig() end + + container.layout:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.cancel)).onTouch = function() + container:remove() + end +end - workspace:draw() +local imageItem = menu:addContextMenuItem(locale.image) + +imageItem:addItem(locale.flipVertical).onTouch = function() + window.image.data = image.flipVertically(window.image.data) +end + +imageItem:addItem(locale.flipHorizontal).onTouch = function() + window.image.data = image.flipHorizontally(window.image.data) +end + +imageItem:addSeparator() + +imageItem:addItem(locale.rotate90).onTouch = function() + window.image.data = image.rotate(window.image.data, 90) + window.image.width = window.image.data[1] + window.image.height = window.image.data[2] + window.image.reposition() +end + +imageItem:addItem(locale.rotate180).onTouch = function() + window.image.data = image.rotate(window.image.data, 180) + window.image.width = window.image.data[1] + window.image.height = window.image.data[2] + window.image.reposition() +end + +imageItem:addItem(locale.rotate270).onTouch = function() + window.image.data = image.rotate(window.image.data, 270) + window.image.width = window.image.data[1] + window.image.height = window.image.data[2] + window.image.reposition() +end + +local editItem = menu:addContextMenuItem(locale.edit) + +editItem:addItem(locale.hueSaturation).onTouch = function() + local container = GUI.addBackgroundContainer(workspace, true, true, locale.hueSaturation) + container.layout:setSpacing(1, 1, 2) + container.panel.eventHandler = nil + + local hue = container.layout:addChild(GUI.slider(1, 1, 50, 0x66DB80, 0x0, 0xFFFFFF, 0xAAAAAA, -360, 360, 0, true, locale.hue)) + local satur = container.layout:addChild(GUI.slider(1, 1, 50, 0x66DB80, 0x0, 0xFFFFFF, 0xAAAAAA, -100, 100, 0, true, locale.saturation)) + local bright = container.layout:addChild(GUI.slider(1, 1, 50, 0x66DB80, 0x0, 0xFFFFFF, 0xAAAAAA, -100, 100, 0, true, locale.brightness)) + hue.roundValues = true + satur.roundValues = true + bright.roundValues = true + + local buttonsLay = container.layout:addChild(GUI.layout(1, 1, 30, 7, 1, 1)) + + buttonsLay:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.ok)).onTouch = function() + window.image.data = image.hueSaturationBrightness(window.image.data, hue.value, satur.value/100, bright.value/100) + container:remove() + end + + buttonsLay:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.cancel)).onTouch = function() + container:remove() + end +end + +editItem:addItem(locale.colorBalance).onTouch = function() + local container = GUI.addBackgroundContainer(workspace, true, true, locale.colorBalance) + container.layout:setSpacing(1, 1, 2) + container.panel.eventHandler = nil + + local r = container.layout:addChild(GUI.slider(1, 1, 50, 0x66DB80, 0x0, 0xFF0000, 0xAAAAAA, -255, 255, 0, true, "R: ")) + local g = container.layout:addChild(GUI.slider(1, 1, 50, 0x66DB80, 0x0, 0x00FF00, 0xAAAAAA, -255, 255, 0, true, "G: ")) + local b = container.layout:addChild(GUI.slider(1, 1, 50, 0x66DB80, 0x0, 0x0000FF, 0xAAAAAA, -255, 255, 0, true, "B: ")) + r.roundValues = true + g.roundValues = true + b.roundValues = true + + local buttonsLay = container.layout:addChild(GUI.layout(1, 1, 30, 7, 1, 1)) + + buttonsLay:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.ok)).onTouch = function() + window.image.data = image.colorBalance(window.image.data, math.floor(r.value), math.floor(g.value), math.floor(b.value)) + container:remove() + end + + buttonsLay:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.cancel)).onTouch = function() + container:remove() + end +end + +editItem:addItem(locale.photoFilter).onTouch = function() + local container = GUI.addBackgroundContainer(workspace, true, true, locale.photoFilter) + container.layout:setSpacing(1, 1, 2) + container.panel.eventHandler = nil + + local filterColor = container.layout:addChild(GUI.colorSelector(1, 1, 30, 3, 0x333333, locale.filterColor)) + local transparency = container.layout:addChild(GUI.slider(1, 1, 50, 0x66DB80, 0x0, 0xFFFFFF, 0xAAAAAA, 0, 1, 0.5, true, locale.transparency)) + + local buttonsLay = container.layout:addChild(GUI.layout(1, 1, 30, 7, 1, 1)) + + buttonsLay:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.ok)).onTouch = function() + window.image.data = image.photoFilter(window.image.data, filterColor.color, transparency.value) + container:remove() + end + + buttonsLay:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.cancel)).onTouch = function() + container:remove() + end +end + +editItem:addSeparator() + +editItem:addItem(locale.invertColors).onTouch = function() + window.image.data = image.invert(window.image.data) +end + +editItem:addItem(locale.blackWhite).onTouch = function() + window.image.data = image.blackAndWhite(window.image.data) +end + +editItem:addSeparator() + +editItem:addItem(locale.gaussianBlur).onTouch = function() + local container = GUI.addBackgroundContainer(workspace, true, true, locale.gaussianBlur) + container.layout:setSpacing(1, 1, 2) + container.panel.eventHandler = nil + + local radius = container.layout:addChild(GUI.slider(1, 1, 50, 0x66DB80, 0x0, 0xFFFFFF, 0xAAAAAA, 0, 5, 2.5, true, locale.radius)) + local force = container.layout:addChild(GUI.slider(1, 1, 50, 0x66DB80, 0x0, 0xFFFFFF, 0xAAAAAA, 0, 1, 0.5, true, locale.force)) + radius.roundValues = true + + local buttonsLay = container.layout:addChild(GUI.layout(1, 1, 30, 7, 1, 1)) + + buttonsLay:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.ok)).onTouch = function() + window.image.data = image.gaussianBlur(window.image.data, math.floor(radius.value), force.value) + container:remove() + end + + buttonsLay:addChild(GUI.button(1, 1, 30, 3, 0xFFFFFF, 0x555555, 0x880000, 0xFFFFFF, locale.cancel)).onTouch = function() + container:remove() + end end menu:addItem(locale.hotkeys).onTouch = function() local container = GUI.addBackgroundContainer(workspace, true, true, locale.hotkeys) container.layout:addChild(GUI.textBox(1, 1, 36, 1, nil, 0x969696, locale.hotkeysText, 1, 0, 0, true, true)).eventHandler = nil - workspace:draw() end window.currentToolOverlay = window:addChild(GUI.container(1, 1, 1, 1)) diff --git a/Libraries/Image.lua b/Libraries/Image.lua index d0e1f3f9..aff14d89 100755 --- a/Libraries/Image.lua +++ b/Libraries/Image.lua @@ -456,6 +456,161 @@ function image.blend(picture, blendColor, transparency) return newPicture end +function image.rotate(picture, angle) + local function copyPixel(newPic, oldPic, index) + table.insert(newPic, oldPic[index]) + table.insert(newPic, oldPic[index + 1]) + table.insert(newPic, oldPic[index + 2]) + table.insert(newPic, oldPic[index + 3]) + end + + if angle == 90 then + local newPicture = {picture[2], picture[1]} + for i = 1, picture[2] do + for j = picture[1], 1, -1 do + local index = image.getIndex(i, j, picture[2]) + copyPixel(newPicture, picture, index) + end + end + return newPicture + elseif angle == 180 then + local newPicture = {picture[1], picture[2]} + for j = picture[1], 1, -1 do + for i = picture[2], 1, -1 do + local index = image.getIndex(i, j, picture[2]) + copyPixel(newPicture, picture, index) + end + end + return newPicture + elseif angle == 270 then + local newPicture = {picture[2], picture[1]} + for i = picture[2], 1, -1 do + for j = 1, picture[1] do + local index = image.getIndex(i, j, picture[2]) + copyPixel(newPicture, picture, index) + end + end + return newPicture + else + error("Can't rotate image: angle must be 90, 180 or 270 degrees.") + end +end + +function image.gaussianBlur(picture, radius, force) + local function createConvolutionMatrix(maximumValue, matrixSize) + local delta = maximumValue / matrixSize + local matrix = {} + for y = 1, matrixSize do + for x = 1, matrixSize do + local value = ((x - 1) * delta + (y - 1) * delta) / 2 + matrix[y] = matrix[y] or {} + matrix[y][x] = value + end + end + return matrix + end + + local function spreadPixelToSpecifiedCoordinates(picture, xCoordinate, yCoordinate, matrixValue, startBackground, startForeground, startAlpha, startSymbol) + local matrixBackground, matrixForeground, matrixAlpha, matrixSymbol = image.get(picture, xCoordinate, yCoordinate) + + if matrixBackground and matrixForeground then + local newBackground = color.blend(startBackground, matrixBackground, matrixValue) + local newForeground = matrixSymbol == " " and newBackground or color.blend(startForeground, matrixForeground, matrixValue) + + image.set(picture, xCoordinate, yCoordinate, newBackground, newForeground, 0x00, matrixSymbol) + end + end + + local function spreadColorToOtherPixels(picture, xStart, yStart, matrix) + local startBackground, startForeground, startAlpha, startSymbol = image.get(picture, xStart, yStart) + local xCoordinate, yCoordinate + for yMatrix = 2, #matrix do + for xMatrix = 2, #matrix[yMatrix] do + xCoordinate, yCoordinate = xStart - xMatrix + 1, yStart - yMatrix + 1 + spreadPixelToSpecifiedCoordinates(picture, xCoordinate, yCoordinate, matrix[yMatrix][xMatrix], startBackground, startForeground, startAlpha, startSymbol) + xCoordinate, yCoordinate = xStart + xMatrix - 1, yStart + yMatrix - 1 + spreadPixelToSpecifiedCoordinates(picture, xCoordinate, yCoordinate, matrix[yMatrix][xMatrix], startBackground, startForeground, startAlpha, startSymbol) + end + end + end + + local matrix = createConvolutionMatrix(force or 0x55, radius) + for y = 1, picture[2] do + for x = 1, picture[1] do + spreadColorToOtherPixels(picture, x, y, matrix) + end + end + return picture +end + +function image.hueSaturationBrightness(picture, hue, saturation, brightness) + local function calculateBrightnessChanges(colr) + local h, s, b = color.integerToHSB(colr) + b = b + brightness; if b < 0 then b = 0 elseif b > 1 then b = 1 end + s = s + saturation; if s < 0 then s = 0 elseif s > 1 then s = 1 end + h = h + hue; if h < 0 then h = 0 elseif h > 360 then h = 360 end + return color.HSBToInteger(h, s, b) + end + + for i = 3, #picture, 4 do + picture[i] = calculateBrightnessChanges(picture[i]) + picture[i + 1] = calculateBrightnessChanges(picture[i + 1]) + end + + return picture +end + +function image.hue(picture, hue) + return image.hueSaturationBrightness(picture, hue, 0, 0) +end + +function image.saturation(picture, saturation) + return image.hueSaturationBrightness(picture, 0, saturation, 0) +end + +function image.brightness(picture, brightness) + return image.hueSaturationBrightness(picture, 0, 0, brightness) +end + +function image.blackAndWhite(picture) + return image.hueSaturationBrightness(picture, 0, -1, 0) +end + +function image.colorBalance(picture, r, g, b) + local function calculateRGBChanges(colr) + local rr, gg, bb = color.integerToRGB(colr) + rr = rr + r; gg = gg + g; bb = bb + b + if rr < 0 then rr = 0 elseif rr > 255 then rr = 255 end + if gg < 0 then gg = 0 elseif gg > 255 then gg = 255 end + if bb < 0 then bb = 0 elseif bb > 255 then bb = 255 end + return color.RGBToInteger(rr, gg, bb) + end + + for i = 3, #picture, 4 do + picture[i] = calculateRGBChanges(picture[i]) + picture[i + 1] = calculateRGBChanges(picture[i + 1]) + end + + return picture +end + +function image.invert(picture) + for i = 3, #picture, 4 do + picture[i] = 0xffffff - picture[i] + picture[i + 1] = 0xffffff - picture[i + 1] + end + return picture +end + +function image.photoFilter(picture, colr, transparency) + if transparency < 0 then transparency = 0 elseif transparency > 1 then transparency = 1 end + for i = 3, #picture, 4 do + picture[i] = color.blend(picture[i], colr, transparency) + picture[i + 1] = color.blend(picture[i + 1], colr, transparency) + end + return picture +end + -------------------------------------------------------------------------------- return image