File indexing completed on 2024-05-12 05:46:37

0001 #-----------------------------------------------------------------------------
0002 # Channels to Layers
0003 # Copyright (C) 2019 - Grum999
0004 # -----------------------------------------------------------------------------
0005 # This program is free software: you can redistribute it and/or modify
0006 # it under the terms of the GNU General Public License as published by
0007 # the Free Software Foundation, either version 3 of the License, or
0008 # (at your option) any later version.
0009 #
0010 # This program is distributed in the hope that it will be useful,
0011 # but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0013 # See the GNU General Public License for more details.
0014 #
0015 # You should have received a copy of the GNU General Public License
0016 # along with this program.
0017 # If not, see https://www.gnu.org/licenses/
0018 # -----------------------------------------------------------------------------
0019 # A Krita plugin designed to split channels from a layer to sub-layers
0020 # . RGB
0021 # . CMY
0022 # . CMYK
0023 # . RGB as greayscale values
0024 # . CMY as greayscale values
0025 # . CMYK as greayscale values
0026 # -----------------------------------------------------------------------------
0027 
0028 import re
0029 from krita import (
0030         Extension,
0031         InfoObject,
0032         Node,
0033         Selection
0034     )
0035 from PyQt5.Qt import *
0036 from PyQt5 import QtCore
0037 from PyQt5.QtCore import (
0038         pyqtSlot,
0039         QBuffer,
0040         QByteArray,
0041         QIODevice
0042     )
0043 from PyQt5.QtGui import (
0044         QColor,
0045         QImage,
0046         QPixmap,
0047     )
0048 from PyQt5.QtWidgets import (
0049         QApplication,
0050         QCheckBox,
0051         QComboBox,
0052         QDialog,
0053         QDialogButtonBox,
0054         QFormLayout,
0055         QGroupBox,
0056         QHBoxLayout,
0057         QLabel,
0058         QLineEdit,
0059         QMessageBox,
0060         QProgressBar,
0061         QProgressDialog,
0062         QVBoxLayout,
0063         QWidget
0064     )
0065 
0066 
0067 PLUGIN_VERSION = '1.1.0'
0068 
0069 EXTENSION_ID = 'pykrita_channels2layers'
0070 PLUGIN_MENU_ENTRY = i18n('Channels to layers')
0071 PLUGIN_DIALOG_TITLE = "{0} - {1}".format(i18n('Channels to layers'), PLUGIN_VERSION)
0072 
0073 # Define DialogBox types
0074 DBOX_INFO = 'i'
0075 DBOX_WARNING ='w'
0076 
0077 
0078 # Define Output modes
0079 OUTPUT_MODE_RGB = i18n('RGB Colors')
0080 OUTPUT_MODE_CMY = i18n('CMY Colors')
0081 OUTPUT_MODE_CMYK = i18n('CMYK Colors')
0082 OUTPUT_MODE_LRGB = i18n('RGB Grayscale levels')
0083 OUTPUT_MODE_LCMY = i18n('CMY Grayscale levels')
0084 OUTPUT_MODE_LCMYK = i18n('CMYK Grayscale levels')
0085 
0086 OUTPUT_PREVIEW_MAXSIZE = 320
0087 
0088 # Define original layer action
0089 ORIGINAL_LAYER_KEEPUNCHANGED = i18n('Unchanged')
0090 ORIGINAL_LAYER_KEEPVISIBLE = i18n('Visible')
0091 ORIGINAL_LAYER_KEEPHIDDEN = i18n('Hidden')
0092 ORIGINAL_LAYER_REMOVE = i18n('Remove')
0093 
0094 # define dialog option minimum dimension
0095 DOPT_MIN_WIDTH = OUTPUT_PREVIEW_MAXSIZE * 5 + 200
0096 DOPT_MIN_HEIGHT = 480
0097 
0098 
0099 
0100 OUTPUT_MODE_NFO = {
0101     OUTPUT_MODE_RGB : {
0102         'description' : 'Extract channels (Red, Green, Blue) and create a colored layer per channel',
0103         'groupLayerName' : 'RGB',
0104         'layers' : [
0105                     {
0106                         'color' : 'B',
0107                         'process': [
0108                                 {
0109                                     'action' : 'duplicate',
0110                                     'value' : '@original'
0111                                 },
0112                                 {
0113                                     'action' : 'new',
0114                                     'value' : {
0115                                                 'type' : 'filllayer',
0116                                                 'color' :  QColor(Qt.blue)
0117                                             }
0118                                 },
0119                                 {
0120                                     'action' : 'blending mode',
0121                                     'value' : 'inverse_subtract'
0122                                 },
0123                                 {
0124                                     'action' : 'merge down',
0125                                     'value' : None
0126                                 },
0127                                 {
0128                                     'action' : 'blending mode',
0129                                     'value' : 'add'
0130                                 }
0131                             ]
0132                     },
0133                     {
0134                         'color' : 'G',
0135                         'process': [
0136                                 {
0137                                     'action' : 'duplicate',
0138                                     'value' : '@original'
0139                                 },
0140                                 {
0141                                     'action' : 'new',
0142                                     'value' : {
0143                                                 'type' : 'filllayer',
0144                                                 'color' :  QColor(Qt.green)
0145                                             }
0146                                 },
0147                                 {
0148                                     'action' : 'blending mode',
0149                                     'value' : 'inverse_subtract'
0150                                 },
0151                                 {
0152                                     'action' : 'merge down',
0153                                     'value' : None
0154                                 },
0155                                 {
0156                                     'action' : 'blending mode',
0157                                     'value' : 'add'
0158                                 }
0159                             ]
0160                     },
0161                     {
0162                         'color' : 'R',
0163                         'process': [
0164                                 {
0165                                     'action' : 'duplicate',
0166                                     'value' : '@original'
0167                                 },
0168                                 {
0169                                     'action' : 'new',
0170                                     'value' : {
0171                                                 'type' : 'filllayer',
0172                                                 'color' :  QColor(Qt.red)
0173                                             }
0174                                 },
0175                                 {
0176                                     'action' : 'blending mode',
0177                                     'value' : 'inverse_subtract'
0178                                 },
0179                                 {
0180                                     'action' : 'merge down',
0181                                     'value' : None
0182                                 },
0183                                 {
0184                                     'action' : 'blending mode',
0185                                     'value' : 'add'
0186                                 }
0187                             ]
0188                     }
0189                 ]
0190     },
0191     OUTPUT_MODE_CMY : {
0192         'description' : 'Extract channels (Cyan, Mangenta, Yellow) and create a colored layer per channel',
0193         'groupLayerName' : 'CMY',
0194         'layers' : [
0195                     {
0196                         'color' : 'Y',
0197                         'process': [
0198                                 {
0199                                     'action' : 'duplicate',
0200                                     'value' : '@original'
0201                                 },
0202                                 {
0203                                     'action' : 'new',
0204                                     'value' : {
0205                                                 'type' : 'filllayer',
0206                                                 'color' :  QColor(Qt.yellow)
0207                                             }
0208                                 },
0209                                 {
0210                                     'action' : 'blending mode',
0211                                     'value' : 'add'
0212                                 },
0213                                 {
0214                                     'action' : 'merge down',
0215                                     'value' : None
0216                                 },
0217                                 {
0218                                     'action' : 'blending mode',
0219                                     'value' : 'multiply'
0220                                 }
0221                             ]
0222                     },
0223                     {
0224                         'color' : 'M',
0225                         'process': [
0226                                 {
0227                                     'action' : 'duplicate',
0228                                     'value' : '@original'
0229                                 },
0230                                 {
0231                                     'action' : 'new',
0232                                     'value' : {
0233                                                 'type' : 'filllayer',
0234                                                 'color' :  QColor(Qt.magenta)
0235                                             }
0236                                 },
0237                                 {
0238                                     'action' : 'blending mode',
0239                                     'value' : 'add'
0240                                 },
0241                                 {
0242                                     'action' : 'merge down',
0243                                     'value' : None
0244                                 },
0245                                 {
0246                                     'action' : 'blending mode',
0247                                     'value' : 'multiply'
0248                                 }
0249                             ]
0250                     },
0251                     {
0252                         'color' : 'C',
0253                         'process': [
0254                                 {
0255                                     'action' : 'duplicate',
0256                                     'value' : '@original'
0257                                 },
0258                                 {
0259                                     'action' : 'new',
0260                                     'value' : {
0261                                                 'type' : 'filllayer',
0262                                                 'color' :  QColor(Qt.cyan)
0263                                             }
0264                                 },
0265                                 {
0266                                     'action' : 'blending mode',
0267                                     'value' : 'add'
0268                                 },
0269                                 {
0270                                     'action' : 'merge down',
0271                                     'value' : None
0272                                 },
0273                                 {
0274                                     'action' : 'blending mode',
0275                                     'value' : 'multiply'
0276                                 }
0277                             ]
0278                     }
0279                 ]
0280     },
0281     OUTPUT_MODE_CMYK : {
0282         'description' : 'Extract channels (Cyan, Mangenta, Yellow, Black) and create a colored layer per channel',
0283         'groupLayerName' : 'CMYK',
0284         'layers' : [
0285                     {
0286                         'color' : 'K',
0287                         'process': [
0288                                 {
0289                                     'action' : 'duplicate',
0290                                     'value' : '@original'
0291                                 },
0292                                 {
0293                                     'action' : 'filter',
0294                                     'value' : 'name=desaturate;type=5'  # desaturate method = max
0295                                 }
0296                             ]
0297                     },
0298                     {
0299                         'color' : 'Y',
0300                         'process': [
0301                                 {
0302                                     'action' : 'duplicate',
0303                                     'value' : '@original'
0304                                 },
0305                                 {
0306                                     'action' : 'new',
0307                                     'value' : {
0308                                                 'type' : 'filllayer',
0309                                                 'color' :  QColor(Qt.yellow)
0310                                             }
0311                                 },
0312                                 {
0313                                     'action' : 'blending mode',
0314                                     'value' : 'add'
0315                                 },
0316                                 {
0317                                     'action' : 'merge down',
0318                                     'value' : None
0319                                 },
0320                                 {
0321                                     'action' : 'duplicate',
0322                                     'value' : '@K'
0323                                 },
0324                                 {
0325                                     'action' : 'blending mode',
0326                                     'value' : 'divide'
0327                                 },
0328                                 {
0329                                     'action' : 'merge down',
0330                                     'value' : None
0331                                 },
0332                                 {
0333                                     'action' : 'blending mode',
0334                                     'value' : 'multiply'
0335                                 }
0336                             ]
0337                     },
0338                     {
0339                         'color' : 'M',
0340                         'process': [
0341                                 {
0342                                     'action' : 'duplicate',
0343                                     'value' : '@original'
0344                                 },
0345                                 {
0346                                     'action' : 'new',
0347                                     'value' : {
0348                                                 'type' : 'filllayer',
0349                                                 'color' :  QColor(Qt.magenta)
0350                                             }
0351                                 },
0352                                 {
0353                                     'action' : 'blending mode',
0354                                     'value' : 'add'
0355                                 },
0356                                 {
0357                                     'action' : 'merge down',
0358                                     'value' : None
0359                                 },
0360                                 {
0361                                     'action' : 'duplicate',
0362                                     'value' : '@K'
0363                                 },
0364                                 {
0365                                     'action' : 'blending mode',
0366                                     'value' : 'divide'
0367                                 },
0368                                 {
0369                                     'action' : 'merge down',
0370                                     'value' : None
0371                                 },
0372                                 {
0373                                     'action' : 'blending mode',
0374                                     'value' : 'multiply'
0375                                 }
0376                             ]
0377                     },
0378                     {
0379                         'color' : 'C',
0380                         'process': [
0381                                 {
0382                                     'action' : 'duplicate',
0383                                     'value' : '@original'
0384                                 },
0385                                 {
0386                                     'action' : 'new',
0387                                     'value' : {
0388                                                 'type' : 'filllayer',
0389                                                 'color' :  QColor(Qt.cyan)
0390                                             }
0391                                 },
0392                                 {
0393                                     'action' : 'blending mode',
0394                                     'value' : 'add'
0395                                 },
0396                                 {
0397                                     'action' : 'merge down',
0398                                     'value' : None
0399                                 },
0400                                 {
0401                                     'action' : 'duplicate',
0402                                     'value' : '@K'
0403                                 },
0404                                 {
0405                                     'action' : 'blending mode',
0406                                     'value' : 'divide'
0407                                 },
0408                                 {
0409                                     'action' : 'merge down',
0410                                     'value' : None
0411                                 },
0412                                 {
0413                                     'action' : 'blending mode',
0414                                     'value' : 'multiply'
0415                                 }
0416                             ]
0417                     }
0418                 ]
0419     },
0420     OUTPUT_MODE_LRGB : {
0421         'description' : 'Extract channels (Red, Green, Blue) and create a grayscale layer per channel',
0422         'groupLayerName' : 'RGB[GS]',
0423         'layers' : [
0424                     {
0425                         'color' : 'B',
0426                         'process': [
0427                                 {
0428                                     'action' : 'duplicate',
0429                                     'value' : '@original'
0430                                 },
0431                                 {
0432                                     'action' : 'new',
0433                                     'value' : {
0434                                                 'type' : 'filllayer',
0435                                                 'color' :  QColor(Qt.blue)
0436                                             }
0437                                 },
0438                                 {
0439                                     'action' : 'blending mode',
0440                                     'value' : 'inverse_subtract'
0441                                 },
0442                                 {
0443                                     'action' : 'merge down',
0444                                     'value' : None
0445                                 },
0446                                 {
0447                                     'action' : 'blending mode',
0448                                     'value' : 'add'
0449                                 },
0450                                 {
0451                                     'action' : 'filter',
0452                                     'value' : 'name=desaturate;type=5'  # desaturate method = max
0453                                 }
0454                             ]
0455                     },
0456                     {
0457                         'color' : 'G',
0458                         'process': [
0459                                 {
0460                                     'action' : 'duplicate',
0461                                     'value' : '@original'
0462                                 },
0463                                 {
0464                                     'action' : 'new',
0465                                     'value' : {
0466                                                 'type' : 'filllayer',
0467                                                 'color' :  QColor(Qt.green)
0468                                             }
0469                                 },
0470                                 {
0471                                     'action' : 'blending mode',
0472                                     'value' : 'inverse_subtract'
0473                                 },
0474                                 {
0475                                     'action' : 'merge down',
0476                                     'value' : None
0477                                 },
0478                                 {
0479                                     'action' : 'blending mode',
0480                                     'value' : 'add'
0481                                 },
0482                                 {
0483                                     'action' : 'filter',
0484                                     'value' : 'name=desaturate;type=5'  # desaturate method = max
0485                                 }
0486                             ]
0487                     },
0488                     {
0489                         'color' : 'R',
0490                         'process': [
0491                                 {
0492                                     'action' : 'duplicate',
0493                                     'value' : '@original'
0494                                 },
0495                                 {
0496                                     'action' : 'new',
0497                                     'value' : {
0498                                                 'type' : 'filllayer',
0499                                                 'color' :  QColor(Qt.red)
0500                                             }
0501                                 },
0502                                 {
0503                                     'action' : 'blending mode',
0504                                     'value' : 'inverse_subtract'
0505                                 },
0506                                 {
0507                                     'action' : 'merge down',
0508                                     'value' : None
0509                                 },
0510                                 {
0511                                     'action' : 'blending mode',
0512                                     'value' : 'add'
0513                                 },
0514                                 {
0515                                     'action' : 'filter',
0516                                     'value' : 'name=desaturate;type=5'  # desaturate method = max
0517                                 }
0518                             ]
0519                     }
0520                 ]
0521     },
0522     OUTPUT_MODE_LCMY : {
0523         'description' : 'Extract channels (Cyan, Mangenta, Yellow) and create a grayscale layer per channel',
0524         'groupLayerName' : 'CMY[GS]',
0525         'layers' : [
0526                     {
0527                         'color' : 'Y',
0528                         'process': [
0529                                 {
0530                                     'action' : 'duplicate',
0531                                     'value' : '@original'
0532                                 },
0533                                 {
0534                                     'action' : 'new',
0535                                     'value' : {
0536                                                 'type' : 'filllayer',
0537                                                 'color' :  QColor(Qt.yellow)
0538                                             }
0539                                 },
0540                                 {
0541                                     'action' : 'blending mode',
0542                                     'value' : 'add'
0543                                 },
0544                                 {
0545                                     'action' : 'merge down',
0546                                     'value' : None
0547                                 },
0548                                 {
0549                                     'action' : 'blending mode',
0550                                     'value' : 'add'
0551                                 },
0552                                 {
0553                                     'action' : 'filter',
0554                                     'value' : 'name=desaturate;type=4'  # desaturate method = min
0555                                 }
0556                             ]
0557                     },
0558                     {
0559                         'color' : 'M',
0560                         'process': [
0561                                 {
0562                                     'action' : 'duplicate',
0563                                     'value' : '@original'
0564                                 },
0565                                 {
0566                                     'action' : 'new',
0567                                     'value' : {
0568                                                 'type' : 'filllayer',
0569                                                 'color' :  QColor(Qt.magenta)
0570                                             }
0571                                 },
0572                                 {
0573                                     'action' : 'blending mode',
0574                                     'value' : 'add'
0575                                 },
0576                                 {
0577                                     'action' : 'merge down',
0578                                     'value' : None
0579                                 },
0580                                 {
0581                                     'action' : 'blending mode',
0582                                     'value' : 'add'
0583                                 },
0584                                 {
0585                                     'action' : 'filter',
0586                                     'value' : 'name=desaturate;type=4'  # desaturate method = min
0587                                 }
0588                             ]
0589                     },
0590                     {
0591                         'color' : 'C',
0592                         'process': [
0593                                 {
0594                                     'action' : 'duplicate',
0595                                     'value' : '@original'
0596                                 },
0597                                 {
0598                                     'action' : 'new',
0599                                     'value' : {
0600                                                 'type' : 'filllayer',
0601                                                 'color' :  QColor(Qt.cyan)
0602                                             }
0603                                 },
0604                                 {
0605                                     'action' : 'blending mode',
0606                                     'value' : 'add'
0607                                 },
0608                                 {
0609                                     'action' : 'merge down',
0610                                     'value' : None
0611                                 },
0612                                 {
0613                                     'action' : 'blending mode',
0614                                     'value' : 'add'
0615                                 },
0616                                 {
0617                                     'action' : 'filter',
0618                                     'value' : 'name=desaturate;type=4'  # desaturate method = min
0619                                 }
0620                             ]
0621                     }
0622                 ]
0623     },
0624     OUTPUT_MODE_LCMYK : {
0625         'description' : 'Extract channels (Cyan, Mangenta, Yellow, Black) and create a grayscale layer per channel',
0626         'groupLayerName' : 'CMYK[GS]',
0627         'layers' : [
0628                     {
0629                         'color' : 'K',
0630                         'process': [
0631                                 {
0632                                     'action' : 'duplicate',
0633                                     'value' : '@original'
0634                                 },
0635                                 {
0636                                     'action' : 'filter',
0637                                     'value' : 'name=desaturate;type=5'  # desaturate method = max
0638                                 }
0639                             ]
0640                     },
0641                     {
0642                         'color' : 'Y',
0643                         'process': [
0644                                 {
0645                                     'action' : 'duplicate',
0646                                     'value' : '@original'
0647                                 },
0648                                 {
0649                                     'action' : 'new',
0650                                     'value' : {
0651                                                 'type' : 'filllayer',
0652                                                 'color' :  QColor(Qt.yellow)
0653                                             }
0654                                 },
0655                                 {
0656                                     'action' : 'blending mode',
0657                                     'value' : 'add'
0658                                 },
0659                                 {
0660                                     'action' : 'merge down',
0661                                     'value' : None
0662                                 },
0663                                 {
0664                                     'action' : 'duplicate',
0665                                     'value' : '@K'
0666                                 },
0667                                 {
0668                                     'action' : 'blending mode',
0669                                     'value' : 'divide'
0670                                 },
0671                                 {
0672                                     'action' : 'merge down',
0673                                     'value' : None
0674                                 },
0675                                 {
0676                                     'action' : 'blending mode',
0677                                     'value' : 'multiply'
0678                                 },
0679                                 {
0680                                     'action' : 'filter',
0681                                     'value' : 'name=desaturate;type=4'  # desaturate method = min
0682                                 }
0683                             ]
0684                     },
0685                     {
0686                         'color' : 'M',
0687                         'process': [
0688                                 {
0689                                     'action' : 'duplicate',
0690                                     'value' : '@original'
0691                                 },
0692                                 {
0693                                     'action' : 'new',
0694                                     'value' : {
0695                                                 'type' : 'filllayer',
0696                                                 'color' :  QColor(Qt.magenta)
0697                                             }
0698                                 },
0699                                 {
0700                                     'action' : 'blending mode',
0701                                     'value' : 'add'
0702                                 },
0703                                 {
0704                                     'action' : 'merge down',
0705                                     'value' : None
0706                                 },
0707                                 {
0708                                     'action' : 'duplicate',
0709                                     'value' : '@K'
0710                                 },
0711                                 {
0712                                     'action' : 'blending mode',
0713                                     'value' : 'divide'
0714                                 },
0715                                 {
0716                                     'action' : 'merge down',
0717                                     'value' : None
0718                                 },
0719                                 {
0720                                     'action' : 'blending mode',
0721                                     'value' : 'multiply'
0722                                 },
0723                                 {
0724                                     'action' : 'filter',
0725                                     'value' : 'name=desaturate;type=4'  # desaturate method = min
0726                                 }
0727                             ]
0728                     },
0729                     {
0730                         'color' : 'C',
0731                         'process': [
0732                                 {
0733                                     'action' : 'duplicate',
0734                                     'value' : '@original'
0735                                 },
0736                                 {
0737                                     'action' : 'new',
0738                                     'value' : {
0739                                                 'type' : 'filllayer',
0740                                                 'color' :  QColor(Qt.cyan)
0741                                             }
0742                                 },
0743                                 {
0744                                     'action' : 'blending mode',
0745                                     'value' : 'add'
0746                                 },
0747                                 {
0748                                     'action' : 'merge down',
0749                                     'value' : None
0750                                 },
0751                                 {
0752                                     'action' : 'duplicate',
0753                                     'value' : '@K'
0754                                 },
0755                                 {
0756                                     'action' : 'blending mode',
0757                                     'value' : 'divide'
0758                                 },
0759                                 {
0760                                     'action' : 'merge down',
0761                                     'value' : None
0762                                 },
0763                                 {
0764                                     'action' : 'blending mode',
0765                                     'value' : 'multiply'
0766                                 },
0767                                 {
0768                                     'action' : 'filter',
0769                                     'value' : 'name=desaturate;type=4'  # desaturate method = min
0770                                 }
0771                             ]
0772                     }
0773                 ]
0774     }
0775 }
0776 
0777 TRANSLATIONS_DICT = {
0778     'colorDepth' : {
0779         'U8' : '8bits',
0780         'U16' : '16bits',
0781         'F16' : '16bits floating point',
0782         'F32' : '32bits floating point'
0783     },
0784     'colorModel' : {
0785         'A' : 'Alpha mask',
0786         'RGBA' : 'RGB with alpha channel',
0787         'XYZA' : 'XYZ with alpha channel',
0788         'LABA' : 'LAB with alpha channel',
0789         'CMYKA' : 'CMYK with alpha channel',
0790         'GRAYA' : 'Gray with alpha channel',
0791         'YCbCrA' : 'YCbCr with alpha channel'
0792     },
0793     'layerType' : {
0794         'paintlayer' : 'Paint layer',
0795         'grouplayer' : 'Group layer',
0796         'filelayer' : 'File layer',
0797         'filterlayer' : 'Filter layer',
0798         'filllayer' : 'Fill layer',
0799         'clonelayer' : 'Clone layer',
0800         'vectorlayer' : 'Vector layer',
0801         'transparencymask' : 'Transparency mask',
0802         'filtermask' : 'Filter mask',
0803         'transformmask': 'Transform mask',
0804         'selectionmask': 'Selection mask',
0805         'colorizemask' : 'Colorize mask'
0806     }
0807 }
0808 
0809 
0810 
0811 
0812 class ChannelsToLayers(Extension):
0813 
0814     def __init__(self, parent):
0815         # Default options
0816         self.__outputOptions = {
0817                 'outputMode': OUTPUT_MODE_RGB,
0818                 'originalLayerAction': ORIGINAL_LAYER_KEEPHIDDEN,
0819                 'layerGroupName': '{mode}-{source:name}',
0820                 'layerColorName': '{mode}[{color:short}]-{source:name}'
0821             }
0822 
0823         self.__sourceDocument = None
0824         self.__sourceLayer = None
0825 
0826         # Always initialise the superclass.
0827         # This is necessary to create the underlying C++ object
0828         super().__init__(parent)
0829         self.parent = parent
0830 
0831 
0832     def setup(self):
0833         pass
0834 
0835 
0836     def createActions(self, window):
0837         action = window.createAction(EXTENSION_ID, PLUGIN_MENU_ENTRY, "tools/scripts")
0838         action.triggered.connect(self.action_triggered)
0839 
0840     def dBoxMessage(self, msgType, msg):
0841         """Simplified function for DialogBox 'OK' message"""
0842         if msgType == DBOX_WARNING:
0843             QMessageBox.warning(
0844                     QWidget(),
0845                     PLUGIN_DIALOG_TITLE,
0846                     i18n(msg)
0847                 )
0848         else:
0849             QMessageBox.information(
0850                     QWidget(),
0851                     PLUGIN_DIALOG_TITLE,
0852                     i18n(msg)
0853                 )
0854 
0855 
0856     def action_triggered(self):
0857         """Action called when script is executed from Kitra menu"""
0858         if self.checkCurrentLayer():
0859             if self.openDialogOptions():
0860                 self.run()
0861 
0862 
0863     def translateDictKey(self, key, value):
0864         """Translate key from dictionnary (mostly internal Krita internal values) to human readable values"""
0865         returned = i18n('Unknown')
0866 
0867         if key in TRANSLATIONS_DICT.keys():
0868             if value in TRANSLATIONS_DICT[key].keys():
0869                 returned = i18n(TRANSLATIONS_DICT[key][value])
0870 
0871         return returned
0872 
0873 
0874     def checkCurrentLayer(self):
0875         """Check if current layer is valid
0876            - A document must be opened
0877            - Active layer properties must be:
0878              . Layer type:  a paint layer
0879              . Color model: RGBA
0880              . Color depth: 8bits
0881         """
0882         self.__sourceDocument = Application.activeDocument()
0883         # Check if there's an active document
0884         if self.__sourceDocument is None:
0885             self.dBoxMessage(DBOX_WARNING, "There's no active document!")
0886             return False
0887 
0888         self.__sourceLayer = self.__sourceDocument.activeNode()
0889 
0890         # Check if current layer can be processed
0891         if self.__sourceLayer.type() != "paintlayer" or self.__sourceLayer.colorModel() != "RGBA" or self.__sourceLayer.colorDepth() != "U8":
0892             self.dBoxMessage(DBOX_WARNING, "Selected layer must be a 8bits RGBA Paint Layer!"
0893                                            "\n\nCurrent layer '{0}' properties:"
0894                                            "\n- Layer type: {1}"
0895                                            "\n- Color model: {2} ({3})"
0896                                            "\n- Color depth: {4}"
0897                                            "\n\n> Action is cancelled".format(self.__sourceLayer.name(),
0898                                                                          self.translateDictKey('layerType', self.__sourceLayer.type()),
0899                                                                          self.__sourceLayer.colorModel(), self.translateDictKey('colorModel', self.__sourceLayer.colorModel()),
0900                                                                          self.translateDictKey('colorDepth', self.__sourceLayer.colorDepth())
0901                             ))
0902             return False
0903 
0904         return True
0905 
0906 
0907 
0908     def toQImage(self, layerNode, rect=None):
0909         """Return `layerNode` content as a QImage (as ARGB32)
0910 
0911         The `rect` value can be:
0912         - None, in this case will return all `layerNode` content
0913         - A QRect() object, in this case return `layerNode` content reduced to given rectangle bounds
0914         """
0915         srcRect = layerNode.bounds()
0916 
0917         if len(layerNode.childNodes()) == 0:
0918             projectionMode = False
0919         else:
0920             projectionMode = True
0921 
0922         if projectionMode == True:
0923             img = QImage(layerNode.projectionPixelData(srcRect.left(), srcRect.top(), srcRect.width(), srcRect.height()), srcRect.width(), srcRect.height(), QImage.Format_ARGB32)
0924         else:
0925             img = QImage(layerNode.pixelData(srcRect.left(), srcRect.top(), srcRect.width(), srcRect.height()), srcRect.width(), srcRect.height(), QImage.Format_ARGB32)
0926 
0927         return img.scaled(rect.width(), rect.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
0928 
0929 
0930     def openDialogOptions(self):
0931         """Open dialog box to let user define channel extraction options"""
0932 
0933         tmpDocument = None
0934         previewBaSrc = QByteArray()
0935         lblPreview = [QLabel(), QLabel(), QLabel(), QLabel()]
0936         lblPreviewLbl = [QLabel(), QLabel(), QLabel(), QLabel()]
0937 
0938 
0939         # ----------------------------------------------------------------------
0940         # Define signal and slots for UI widgets
0941         @pyqtSlot('QString')
0942         def ledLayerGroupName_Changed(value):
0943             self.__outputOptions['layerGroupName'] = value
0944 
0945         @pyqtSlot('QString')
0946         def ledLayerColorName_Changed(value):
0947             self.__outputOptions['layerColorName'] = value
0948 
0949         @pyqtSlot('QString')
0950         def cmbOutputMode_Changed(value):
0951             self.__outputOptions['outputMode'] = value
0952             buildPreview()
0953 
0954         @pyqtSlot('QString')
0955         def cmbOriginalLayerAction_Changed(value):
0956             self.__outputOptions['originalLayerAction'] = value
0957 
0958         def buildPreview():
0959             pbProgress.setVisible(True)
0960 
0961             backupValue = self.__outputOptions['layerColorName']
0962             self.__outputOptions['layerColorName'] = '{color:long}'
0963 
0964             # create a temporary document to work
0965             tmpDocument = Application.createDocument(imgThumbSrc.width(), imgThumbSrc.height(), "tmp", "RGBA", "U8", "", 120.0)
0966 
0967             # create a layer used as original layer
0968             originalLayer = tmpDocument.createNode("Original", "paintlayer")
0969             tmpDocument.rootNode().addChildNode(originalLayer, None)
0970             # and set original image content
0971             originalLayer.setPixelData(previewBaSrc, 0, 0, tmpDocument.width(), tmpDocument.height())
0972 
0973             # execute process
0974             groupLayer = self.process(tmpDocument, originalLayer, pbProgress)
0975 
0976             self.__outputOptions['layerColorName'] = backupValue
0977 
0978             originalLayer.setVisible(False)
0979             groupLayer.setVisible(True)
0980 
0981             for layer in groupLayer.childNodes():
0982                 layer.setBlendingMode('normal')
0983                 layer.setVisible(False)
0984             tmpDocument.refreshProjection()
0985 
0986             index = 0
0987             for layer in groupLayer.childNodes():
0988                 layer.setVisible(True)
0989                 tmpDocument.refreshProjection()
0990 
0991                 lblPreview[index].setPixmap(QPixmap.fromImage(tmpDocument.projection(0, 0, tmpDocument.width(), tmpDocument.height())))
0992                 lblPreviewLbl[index].setText("<i>{0}</i>".format(layer.name()))
0993                 layer.setVisible(False)
0994 
0995                 index+=1
0996 
0997             if index > 3:
0998                 lblPreview[3].setVisible(True)
0999                 lblPreviewLbl[3].setVisible(True)
1000             else:
1001                 lblPreview[3].setVisible(False)
1002                 lblPreviewLbl[3].setVisible(False)
1003 
1004 
1005             tmpDocument.close()
1006 
1007             pbProgress.setVisible(False)
1008 
1009 
1010         # ----------------------------------------------------------------------
1011         # Create dialog box
1012         dlgMain = QDialog(Application.activeWindow().qwindow())
1013         dlgMain.setWindowTitle(PLUGIN_DIALOG_TITLE)
1014         # resizeable with minimum size
1015         dlgMain.setSizeGripEnabled(True)
1016         dlgMain.setMinimumSize(DOPT_MIN_WIDTH, DOPT_MIN_HEIGHT)
1017         dlgMain.setModal(True)
1018 
1019         # ......................................................................
1020         # main dialog box, container
1021         vbxMainContainer = QVBoxLayout(dlgMain)
1022 
1023         # main dialog box, current layer name
1024         lblLayerName = QLabel("{0} <b><i>{1}</i></b>".format(i18n("Processing layer"), self.__sourceLayer.name()))
1025         lblLayerName.setFixedHeight(30)
1026         vbxMainContainer.addWidget(lblLayerName)
1027 
1028         # main dialog box, groupbox for layers options
1029         gbxLayersMgt = QGroupBox("Layers management")
1030         vbxMainContainer.addWidget(gbxLayersMgt)
1031 
1032         # main dialog box, groupbox for output options
1033         gbxOutputResults = QGroupBox("Output results")
1034         vbxMainContainer.addWidget(gbxOutputResults)
1035 
1036         vbxMainContainer.addStretch()
1037 
1038         # main dialog box, OK/Cancel buttons
1039         dbbxOkCancel = QDialogButtonBox(dlgMain)
1040         dbbxOkCancel.setOrientation(QtCore.Qt.Horizontal)
1041         dbbxOkCancel.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
1042         dbbxOkCancel.accepted.connect(dlgMain.accept)
1043         dbbxOkCancel.rejected.connect(dlgMain.reject)
1044         vbxMainContainer.addWidget(dbbxOkCancel)
1045 
1046         # ......................................................................
1047         # create layout for groupbox "Layers management"
1048         flLayersMgt = QFormLayout()
1049         gbxLayersMgt.setLayout(flLayersMgt)
1050 
1051         ledLayerGroupName = QLineEdit()
1052         ledLayerGroupName.setText(self.__outputOptions['layerGroupName'])
1053         ledLayerGroupName.textChanged.connect(ledLayerGroupName_Changed)
1054         flLayersMgt.addRow(i18nc('The name for a new group layer; the generated layers will be placed in this group.', 'New layer group name'), ledLayerGroupName)
1055 
1056         ledLayerColorName = QLineEdit()
1057         ledLayerColorName.setText(self.__outputOptions['layerColorName'])
1058         ledLayerColorName.textChanged.connect(ledLayerColorName_Changed)
1059         flLayersMgt.addRow(i18nc('Defines how the name for each layer created from the channel is generated.', 'New layers color name'), ledLayerColorName)
1060 
1061         cmbOriginalLayerAction = QComboBox()
1062         cmbOriginalLayerAction.addItems([
1063                 ORIGINAL_LAYER_KEEPUNCHANGED,
1064                 ORIGINAL_LAYER_KEEPVISIBLE,
1065                 ORIGINAL_LAYER_KEEPHIDDEN,
1066                 ORIGINAL_LAYER_REMOVE
1067             ])
1068         cmbOriginalLayerAction.setCurrentText(self.__outputOptions['originalLayerAction'])
1069         cmbOriginalLayerAction.currentTextChanged.connect(cmbOriginalLayerAction_Changed)
1070         flLayersMgt.addRow(i18n("Original layer"), cmbOriginalLayerAction)
1071 
1072         # ......................................................................
1073         # create layout for groupbox "Output results"
1074         flOutputResults = QFormLayout()
1075         gbxOutputResults.setLayout(flOutputResults)
1076 
1077         cmbOutputMode = QComboBox()
1078         cmbOutputMode.addItems([
1079                 OUTPUT_MODE_RGB,
1080                 OUTPUT_MODE_CMY,
1081                 OUTPUT_MODE_CMYK,
1082                 OUTPUT_MODE_LRGB,
1083                 OUTPUT_MODE_LCMY,
1084                 OUTPUT_MODE_LCMYK
1085             ])
1086         cmbOutputMode.setCurrentText(self.__outputOptions['outputMode'])
1087         cmbOutputMode.currentTextChanged.connect(cmbOutputMode_Changed)
1088         flOutputResults.addRow(i18n("Mode"), cmbOutputMode)
1089 
1090         vbxPreviewLblContainer = QHBoxLayout()
1091         flOutputResults.addRow('', vbxPreviewLblContainer)
1092         vbxPreviewContainer = QHBoxLayout()
1093         flOutputResults.addRow('', vbxPreviewContainer)
1094 
1095         # add preview progressbar
1096         pbProgress = QProgressBar()
1097         pbProgress.setFixedHeight(8)
1098         pbProgress.setTextVisible(False)
1099         pbProgress.setVisible(False)
1100         pbProgress.setRange(0, 107)
1101         flOutputResults.addRow('', pbProgress)
1102 
1103 
1104         imageRatio = self.__sourceDocument.width() / self.__sourceDocument.height()
1105         rect = QRect(0, 0, OUTPUT_PREVIEW_MAXSIZE, OUTPUT_PREVIEW_MAXSIZE)
1106 
1107         # always ensure that final preview width and/or height is lower or equal than OUTPUT_PREVIEW_MAXSIZE
1108         if imageRatio < 1:
1109             # width < height
1110             rect.setWidth(int(imageRatio * OUTPUT_PREVIEW_MAXSIZE))
1111         else:
1112             # width >= height
1113             rect.setHeight(int(OUTPUT_PREVIEW_MAXSIZE / imageRatio))
1114 
1115         imgThumbSrc = self.toQImage(self.__sourceLayer, rect)
1116 
1117         previewBaSrc.resize(imgThumbSrc.byteCount())
1118         ptr = imgThumbSrc.bits()
1119         ptr.setsize(imgThumbSrc.byteCount())
1120         previewBaSrc = QByteArray(ptr.asstring())
1121 
1122 
1123         lblPreviewSrc = QLabel()
1124         lblPreviewSrc.setPixmap(QPixmap.fromImage(imgThumbSrc))
1125         lblPreviewSrc.setFixedHeight(imgThumbSrc.height() + 4)
1126         lblPreviewSrc.setFixedWidth(imgThumbSrc.width() + 4)
1127         vbxPreviewContainer.addWidget(lblPreviewSrc)
1128 
1129         lblPreviewLblSrc = QLabel(i18nc("the original layer", "Original"))
1130         lblPreviewLblSrc.setFixedWidth(imgThumbSrc.width() + 4)
1131         vbxPreviewLblContainer.addWidget(lblPreviewLblSrc)
1132 
1133 
1134         vbxPreviewLblContainer.addWidget(QLabel(" "))
1135         vbxPreviewContainer.addWidget(QLabel(">"))
1136 
1137         lblPreview[3].setPixmap(QPixmap.fromImage(imgThumbSrc))
1138         lblPreview[3].setFixedHeight(imgThumbSrc.height() + 4)
1139         lblPreview[3].setFixedWidth(imgThumbSrc.width() + 4)
1140         vbxPreviewContainer.addWidget(lblPreview[3])
1141 
1142         lblPreviewLbl[3] = QLabel(i18n("<i>Cyan</i>"))
1143         lblPreviewLbl[3].setIndent(10)
1144         lblPreviewLbl[3].setFixedWidth(imgThumbSrc.width() + 4)
1145         vbxPreviewLblContainer.addWidget(lblPreviewLbl[3])
1146 
1147 
1148         lblPreview[2] = QLabel()
1149         lblPreview[2].setPixmap(QPixmap.fromImage(imgThumbSrc))
1150         lblPreview[2].setFixedHeight(imgThumbSrc.height() + 4)
1151         lblPreview[2].setFixedWidth(imgThumbSrc.width() + 4)
1152         vbxPreviewContainer.addWidget(lblPreview[2])
1153 
1154         lblPreviewLbl[2] = QLabel(i18n("<i>Magenta</i>"))
1155         lblPreviewLbl[2].setIndent(10)
1156         lblPreviewLbl[2].setFixedWidth(imgThumbSrc.width() + 4)
1157         vbxPreviewLblContainer.addWidget(lblPreviewLbl[2])
1158 
1159 
1160         lblPreview[1] = QLabel()
1161         lblPreview[1].setPixmap(QPixmap.fromImage(imgThumbSrc))
1162         lblPreview[1].setFixedHeight(imgThumbSrc.height() + 4)
1163         lblPreview[1].setFixedWidth(imgThumbSrc.width() + 4)
1164         vbxPreviewContainer.addWidget(lblPreview[1])
1165 
1166         lblPreviewLbl[1] = QLabel(i18n("<i>Yellow</i>"))
1167         lblPreviewLbl[1].setIndent(10)
1168         lblPreviewLbl[1].setFixedWidth(imgThumbSrc.width() + 4)
1169         vbxPreviewLblContainer.addWidget(lblPreviewLbl[1])
1170 
1171 
1172         lblPreview[0] = QLabel()
1173         lblPreview[0].setPixmap(QPixmap.fromImage(imgThumbSrc))
1174         lblPreview[0].setFixedHeight(imgThumbSrc.height() + 4)
1175         lblPreview[0].setFixedWidth(imgThumbSrc.width() + 4)
1176         vbxPreviewContainer.addWidget(lblPreview[0])
1177 
1178         lblPreviewLbl[0] = QLabel(i18n("<i>Black</i>"))
1179         lblPreviewLbl[0].setIndent(10)
1180         lblPreviewLbl[0].setFixedWidth(imgThumbSrc.width() + 4)
1181         vbxPreviewLblContainer.addWidget(lblPreviewLbl[0])
1182 
1183 
1184         vbxPreviewLblContainer.addStretch()
1185         vbxPreviewContainer.addStretch()
1186 
1187         buildPreview()
1188 
1189         returned = dlgMain.exec_()
1190 
1191         return returned
1192 
1193 
1194     def progressNext(self, pProgress):
1195         """Update progress bar"""
1196         if pProgress is not None:
1197             stepCurrent=pProgress.value()+1
1198             pProgress.setValue(stepCurrent)
1199             QApplication.instance().processEvents()
1200 
1201 
1202     def run(self):
1203         """Run process for current layer"""
1204 
1205         pdlgProgress = QProgressDialog(self.__outputOptions['outputMode'], None, 0, 100, Application.activeWindow().qwindow())
1206         pdlgProgress.setWindowTitle(PLUGIN_DIALOG_TITLE)
1207         pdlgProgress.setMinimumSize(640, 200)
1208         pdlgProgress.setModal(True)
1209         pdlgProgress.show()
1210 
1211         self.process(self.__sourceDocument, self.__sourceLayer, pdlgProgress)
1212 
1213         pdlgProgress.close()
1214 
1215 
1216 
1217 
1218     def process(self, pDocument, pOriginalLayer, pProgress):
1219         """Process given layer with current options"""
1220 
1221         self.layerNum = 0
1222         document = pDocument
1223         originalLayer = pOriginalLayer
1224         parentGroupLayer = None
1225         currentProcessedLayer = None
1226         originalLayerIsVisible = originalLayer.visible()
1227 
1228 
1229         def getLayerByName(parent, value):
1230             """search and return a layer by name, within given parent group"""
1231             if parent == None:
1232                 return document.nodeByName(value)
1233 
1234             for layer in parent.childNodes():
1235                 if layer.name() == value:
1236                     return layer
1237 
1238             return None
1239 
1240 
1241         def duplicateLayer(currentProcessedLayer, value):
1242             """Duplicate layer from given name
1243                New layer become active layer
1244             """
1245 
1246             newLayer = None
1247             srcLayer = None
1248             srcName = re.match("^@(.*)", value)
1249 
1250             if not srcName is None:
1251                 # reference to a specific layer
1252                 if srcName[1] == 'original':
1253                     # original layer currently processed
1254                     srcLayer = originalLayer
1255                 else:
1256                     # a color layer previously built (and finished)
1257                     srcLayer = getLayerByName(parentGroupLayer, parseLayerName(self.__outputOptions['layerColorName'], srcName[1]))
1258             else:
1259                 # a layer with a fixed name
1260                 srcLayer = document.nodeByName(parseLayerName(value, ''))
1261 
1262 
1263             if not srcLayer is None:
1264                 newLayer = srcLayer.duplicate()
1265 
1266                 self.layerNum+=1
1267                 newLayer.setName("c2l-w{0}".format(self.layerNum))
1268 
1269                 parentGroupLayer.addChildNode(newLayer, currentProcessedLayer)
1270                 return newLayer
1271             else:
1272                 return None
1273 
1274 
1275         def newLayer(currentProcessedLayer, value):
1276             """Create a new layer of given type
1277                New layer become active layer
1278             """
1279 
1280             newLayer = None
1281 
1282             if value is None or not value['type'] in ['filllayer']:
1283                 # given type for new layer is not valid
1284                 # currently only one layer type is implemented
1285                 return None
1286 
1287             if value['type'] == 'filllayer':
1288                 infoObject = InfoObject();
1289                 infoObject.setProperty("color", value['color'])
1290                 selection = Selection();
1291                 selection.select(0, 0, document.width(), document.height(), 255)
1292 
1293                 newLayer = document.createFillLayer(value['color'].name(), "color", infoObject, selection)
1294 
1295 
1296             if newLayer:
1297                 self.layerNum+=1
1298                 newLayer.setName("c2l-w{0}".format(self.layerNum))
1299 
1300                 parentGroupLayer.addChildNode(newLayer, currentProcessedLayer)
1301 
1302                 # Need to force generator otherwise, information provided when creating layer seems to not be taken in
1303                 # account
1304                 newLayer.setGenerator("color", infoObject)
1305 
1306                 return newLayer
1307             else:
1308                 return None
1309 
1310 
1311         def mergeDown(currentProcessedLayer, value):
1312             """Merge current layer with layer below"""
1313             if currentProcessedLayer is None:
1314                 return None
1315 
1316             newLayer = currentProcessedLayer.mergeDown()
1317             # note:
1318             #   when layer is merged down:
1319             #   - a new layer seems to be created (reference to 'down' layer does not match anymore layer in group)
1320             #   - retrieved 'newLayer' reference does not match to new layer resulting from merge
1321             #   - activeNode() in document doesn't match to new layer resulting from merge
1322             #   maybe it's norpmal, maybe not...
1323             #   but the only solution to be able to work on merged layer (with current script) is to consider that from
1324             #   parent node, last child match to last added layer and then, to our merged layer
1325             currentProcessedLayer = parentGroupLayer.childNodes()[-1]
1326             # for an unknown reason, merged layer bounds are not corrects... :'-(
1327             currentProcessedLayer.cropNode(0, 0, document.width(), document.height())
1328             return currentProcessedLayer
1329 
1330 
1331         def applyBlendingMode(currentProcessedLayer, value):
1332             """Set blending mode for current layer"""
1333             if currentProcessedLayer is None or value is None or value == '':
1334                 return False
1335 
1336             currentProcessedLayer.setBlendingMode(value)
1337             return True
1338 
1339 
1340         def applyFilter(currentProcessedLayer, value):
1341             """Apply filter to layer"""
1342             if currentProcessedLayer is None or value is None or value == '':
1343                 return None
1344 
1345             filterName = re.match("name=([^;]+)", value)
1346 
1347             if filterName is None:
1348                 return None
1349 
1350             filter = Application.filter(filterName.group(1))
1351             filterConfiguration = filter.configuration()
1352 
1353             for parameter in value.split(';'):
1354                 parameterName = re.match("^([^=]+)=(.*)", parameter)
1355 
1356                 if not parameterName is None and parameterName != 'name':
1357                     filterConfiguration.setProperty(parameterName.group(1), parameterName.group(2))
1358 
1359             filter.setConfiguration(filterConfiguration)
1360             filter.apply(currentProcessedLayer, 0, 0, document.width(), document.height())
1361 
1362             return currentProcessedLayer
1363 
1364 
1365         def parseLayerName(value, color):
1366             """Parse layer name"""
1367 
1368             returned = value
1369 
1370             returned = returned.replace("{source:name}", originalLayer.name())
1371             returned = returned.replace("{mode}", OUTPUT_MODE_NFO[self.__outputOptions['outputMode']]['groupLayerName'])
1372             returned = returned.replace("{color:short}", color)
1373             if color == "C":
1374                 returned = returned.replace("{color:long}", i18n("Cyan"))
1375             elif color == "M":
1376                 returned = returned.replace("{color:long}", i18n("Magenta"))
1377             elif color == "Y":
1378                 returned = returned.replace("{color:long}", i18n("Yellow"))
1379             elif color == "K":
1380                 returned = returned.replace("{color:long}", i18n("Black"))
1381             elif color == "R":
1382                 returned = returned.replace("{color:long}", i18n("Red"))
1383             elif color == "G":
1384                 returned = returned.replace("{color:long}", i18n("Green"))
1385             elif color == "B":
1386                 returned = returned.replace("{color:long}", i18n("Blue"))
1387             else:
1388                 returned = returned.replace("{color:long}", "")
1389 
1390             return returned
1391 
1392 
1393         if document is None or originalLayer is None:
1394             # should not occurs, but...
1395             return None
1396 
1397         if not pProgress is None:
1398             stepTotal = 4
1399             for layer in OUTPUT_MODE_NFO[self.__outputOptions['outputMode']]['layers']:
1400                 stepTotal+=len(layer['process'])
1401 
1402             pProgress.setRange(0, stepTotal)
1403 
1404 
1405         if originalLayerIsVisible == False:
1406             originalLayer.setVisible(True)
1407 
1408         # ----------------------------------------------------------------------
1409         # Create new group layer
1410         parentGroupLayer = document.createGroupLayer(parseLayerName(self.__outputOptions['layerGroupName'], ''))
1411 
1412         self.progressNext(pProgress)
1413 
1414         currentProcessedLayer = None
1415 
1416         for layer in OUTPUT_MODE_NFO[self.__outputOptions['outputMode']]['layers']:
1417             for process in layer['process']:
1418                 if process['action'] == 'duplicate':
1419                     currentProcessedLayer = duplicateLayer(currentProcessedLayer, process['value'])
1420                 elif process['action'] == 'new':
1421                     currentProcessedLayer = newLayer(currentProcessedLayer, process['value'])
1422                 elif process['action'] == 'merge down':
1423                     currentProcessedLayer = mergeDown(currentProcessedLayer, process['value'])
1424                     pass
1425                 elif process['action'] == 'blending mode':
1426                     applyBlendingMode(currentProcessedLayer, process['value'])
1427                 elif process['action'] == 'filter':
1428                     applyFilter(currentProcessedLayer, process['value'])
1429 
1430                 self.progressNext(pProgress)
1431 
1432             if not currentProcessedLayer is None:
1433                 # rename currentProcessedLayer
1434                 currentProcessedLayer.setName(parseLayerName(self.__outputOptions['layerColorName'], layer['color']))
1435 
1436         document.rootNode().addChildNode(parentGroupLayer, originalLayer)
1437         self.progressNext(pProgress)
1438 
1439         if self.__outputOptions['originalLayerAction'] == ORIGINAL_LAYER_KEEPVISIBLE:
1440             originalLayer.setVisible(True)
1441         elif self.__outputOptions['originalLayerAction'] == ORIGINAL_LAYER_KEEPHIDDEN:
1442             originalLayer.setVisible(False)
1443         elif self.__outputOptions['originalLayerAction'] == ORIGINAL_LAYER_REMOVE:
1444             originalLayer.remove()
1445         else:
1446             # ORIGINAL_LAYER_KEEPUNCHANGED
1447             originalLayer.setVisible(originalLayerIsVisible)
1448 
1449 
1450         self.progressNext(pProgress)
1451 
1452         document.refreshProjection()
1453         self.progressNext(pProgress)
1454 
1455         document.setActiveNode(parentGroupLayer)
1456 
1457         return parentGroupLayer
1458 
1459 
1460 #ChannelsToLayers(Krita.instance()).process(Application.activeDocument(), Application.activeDocument().activeNode(), None)
1461 #ChannelsToLayers(Krita.instance()).action_triggered()