text: # coding: utf-8
  
  """
  IMPORTS
  """
  import cv2
  import numpy as np
  import math
  import re, sys
  
  
  """
  FUNÇÕES
  """
  def bitPlaneImage(image, height, width, bitPlane):
      # copia a imagem para gerar os resultados
      resultRed, resultGreen, resultBlue = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY), cv2.cvtColor(image, cv2.COLOR_BGR2GRAY), cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
      for y in range(height):
          for x in range(width):
              # obtém as intensidades de cada cor do pixel
              red, green, blue = image[x][y]
  
              # converte as intensidades das cores para binário
              binaryRed, binaryGreen, binaryBlue = (bin(red)[2:]).zfill(8), (bin(green)[2:]).zfill(8), (bin(blue)[2:]).zfill(8)
  
              # obtém o bit do pixel atual no plano de bits especificado
              resultRed[x][y], resultGreen[x][y], resultBlue[x][y] = int(binaryRed[7-bitPlane])*255, int(binaryGreen[7-bitPlane])*255, int(binaryBlue[7-bitPlane])*255
      
      # retorna plano de bits de cada cor da imagem
      return resultRed, resultGreen, resultBlue
  
  def encode(image, height, width, message, bitPlane):
      # converte a mensagem para códigos ASCII
      binaryMessage = ""
      for c in message:
          binaryMessage += (str(bin(ord(c)))[2:]).zfill(8)
      
      # copia a imagem para gerar o resultado
      result = np.copy(image)
  
      # insere a mensagem codificada na imagem
      y, k = 0, 0
      while (y < height and k < len(binaryMessage)):
          x = 0
          while (x < width and k < len(binaryMessage)):
              z = 0
              while (z < len(result[y][x]) and k < len(binaryMessage)):
                  # obtém intensidade da cor atual do pixel
                  intensity = result[y][x][z]
  
                  # converte intensidade da cor atual para binário
                  binaryIntensity = (bin(intensity)[2:]).zfill(8)
  
                  # insere bit da mensagem codificada na intensidade atual
                  binaryIntensity = binaryIntensity[:7-bitPlane] + str(binaryMessage[k]) + binaryIntensity[7-bitPlane+1:]
                  k += 1
  
                  # insere a nova intensidade no pixel
                  result[y][x][z] = int(binaryIntensity, 2)
  
                  # avanca para a proxima cor do pixel
                  z += 1
              x += 1
          y += 1
      
      # retorn imagem com mensagem codificada
      return result, len(binaryMessage)
  
  
  """
  FLUXO PRINCIPAL
  """
  # checa argumentos passados para o programa
  if (len(sys.argv) != 5 or
      (not re.compile("\w*\.png").match(sys.argv[1])) or
      (not re.compile("\w*\.txt").match(sys.argv[2])) or
      sys.argv[3] not in ["0", "1", "2"] or
      (not re.compile("\w*\.png").match(sys.argv[4]))):
      print("Uso: python3 codificar.py <imagem de entrada>.png <texto>.txt <plano de bits> <imagem de saída>.png")
      print("Em que <plano de bits> pode ser 0, 1 ou 2.")
      sys.exit(0)
  
  # obtém a imagem
  imageFile = sys.argv[1]
  imageFileName = imageFile.split(".")[0]
  image = cv2.imread(imageFile, cv2.IMREAD_UNCHANGED)
  
  # obtém a mensagem a ser codificada
  messageFile = open(sys.argv[2], "r")
  message = "".join(messageFile.readlines())
  
  # verifica se a mensagem cabe na imagem selecionada
  height, width, channels = image.shape
  messageLength = len(message)
  maxLength = (height * width * 3) // 8
  if (messageLength > maxLength):
      print("A mensagem selecionada não pode ser inserida em sua totalidade na imagem selecionada.")
      print("Tamanho da mensagem selecionada:", messageLength)
      print("Tamanho máximo permitido:", maxLength)
      sys.exit(0)
  
  # obtém o plano de bits no qual a mensagem será codificada
  bitPlane = int(sys.argv[3])
  
  # codifica a mensagem na imagem
  result, messageSize = encode(image, height, width, message, bitPlane)
  
  # mostra os planos de bits 7, 2, 1 e 0 para cada imagem
  for bp in [7, 2, 1, 0]:
      # mostra o plano de bits onde a mensagem foi inserida da imagem original
      if (bp == bitPlane):
          bitPlaneOriginalRed, bitPlaneOriginalGreen, bitPlaneOriginalBlue = bitPlaneImage(image, height, width, bp)
          cv2.imshow(str(bp) + "o plano de bits da cor vermelha da imagem de entrada", bitPlaneOriginalRed)
          cv2.imshow(str(bp) + "o plano de bits da cor verde da imagem de entrada", bitPlaneOriginalGreen)
          cv2.imshow(str(bp) + "o plano de bits da cor azul da imagem de entrada", bitPlaneOriginalBlue)
  
      bitPlaneRed, bitPlaneGreen, bitPlaneBlue = bitPlaneImage(result, height, width, bp)
      cv2.imshow(str(bp) + "o plano de bits da cor vermelha da imagem de saida", bitPlaneRed)
      cv2.imshow(str(bp) + "o plano de bits da cor verde da imagem de saida", bitPlaneGreen)
      cv2.imshow(str(bp) + "o plano de bits da cor azul da imagem de saida", bitPlaneBlue)
      cv2.waitKey(0)
      cv2.destroyAllWindows()
  
  # obtém o nome do arquivo de imagem de saída
  resultFileName = sys.argv[4]
  
  # salva a imagem com a mensagem codificada
  cv2.imwrite(resultFileName, result)
  print("Imagem com mensagem codificada salva no arquivo " + resultFileName + ".")
  print("Quantidade de caracteres codificados:", messageSize)
  