Action Page

We have successfully created our Main page previously. Now let us Create the two Action Modes Encoding and Decoding in our Steganography project. Start with the Action class which gets called by the main class for encoding and decoding respectively.

Create "class ActionClass(tk.Frame):" (action_class). We will create another window and configure its title, size and color. Here we are creating a window at Top Level so we can add this window at the top of any other window. And set the custom Background canvas.

    

from tkinter import Frame, Label, StringVar, Radiobutton, messagebox, NW, CENTER
from tkinter.filedialog import askopenfilename
import tkinter as tk
from PIL import ImageTk, Image
from stegano import lsb
from stegano import exifHeader as a_stegano
from Util.app_constant import AppConstant
from Util.util import Util
from custom_design.roundBackgroundFrame import RoundBackgroundFrame
from custom_design.customentrysimple import CustomEntrySimple
from custom_design.roundedbutton import RoundedButton

    
class ActionClass(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)

        self.label_img = None
        self.import_path = None
        self.fileopen = ""
        self.root = tk.Toplevel()
        self.root.configure(bg="#585858")
        self.root.resizable(width=0, height=0)
        win_width = 1280
        print(1280 * 56.25 / 100)
        win_height = int(1280 * 56.25 / 100)
        self.root.geometry(str(win_width) + "x" + str(win_height))
        Util.center(self.root)
        self.root.attributes('-alpha', 1.0)

        width = win_width * 90 / 100
        height = win_height * 90 / 100

        self.width = width
        self.height = height
        cornerradius = 40
        padding = 0
        color = "#FFFFFF"

        screen_width = self.winfo_screenwidth()
        screen_height = self.winfo_screenheight()
        Util.set_font_size(screen_width, screen_height, win_width, win_height)

        bg_canvas = RoundBackgroundFrame(self.root, width, height, padding, cornerradius, color, "#585858")
        bg_canvas.place(width=width, height=height, x=win_width / 2 - width / 2, y=win_height / 2 - height / 2)


    

    

Once the window and background is created, we will create a frame with some reduced dimensions



        frame_width = width * 98 / 100
        frame_height = height * 96 / 100

        self.base_frame = Frame(self.root, width=frame_width, height=frame_height, bg=color)
        bg_canvas.create_window(frame_width / 100, frame_height * 2 / 100, anchor=NW, window=self.base_frame)

        add_line_border(self.base_frame, color, frame_height, frame_width)




Here, we will create a action function "def get_action_mode(self, action):" inside the ActionClass for encoding and decoding Ui.




def get_action_mode(self, action):
        if "encode" == action:
            self.encode(self.base_frame, self.width, self.height)
            self.root.title("ENCODE")
        else:
            self.decode(self.base_frame, self.width, self.height)
            self.root.title("DECODE")




Now, Before anything else, Lets define few functions used for both encoding and decoding. write these function above the class "ActionClass(tk.Frame):"



# font_size = 16
button_font = ("Lucida Grande", AppConstant.FONT_SIZE - 6)


def add_search_frame(base_frame, color, height, width, pos_x):
    sfw = width * 50 / 100
    sfh = height * 50 / 100
    picure_label = tk.LabelFrame(base_frame, text="Picture", font=button_font, pady=sfw * 2 / 100,
                                 padx=sfw * 2 / 100, bg=color)
    picure_label.place(width=sfw, height=sfh, x=pos_x, y=height * 30 / 100)
    return picure_label


def add_action_frame(base_frame, color, height, width, pos_x):
    afw = width * 35 / 100
    afh = height * 71 / 100
    label_frame_action = tk.LabelFrame(base_frame, text="Actions", font=button_font, pady=afw * 2 / 100,
                                       padx=afw * 1 / 100, bg=color)
    label_frame_action.place(width=afw, height=afh, x=pos_x, y=height * 0.12)
    return label_frame_action


def add_line_border(base_frame, color, height, width):
    line_canvas = tk.Canvas(base_frame, bg=color, borderwidth=0, relief="flat", highlightthickness=0)
    line_canvas.place(width=width - 4, height=5, x=2, y=height * 10 / 100)
    line_canvas.create_line(0, 0, width, 0, fill="#787878")

    line_canvas2 = tk.Canvas(base_frame, bg=color, borderwidth=0, relief="flat", highlightthickness=0)
    line_canvas2.place(width=width - 4, height=5, x=2, y=height * 90 / 100)
    line_canvas2.create_line(0, 0, width, 0, fill="#787878")


def add_heading_label(base_frame, color, height, width, heading_tv):
    label_heading = Label(base_frame, text=heading_tv, anchor=CENTER, bg=color, relief="flat",
                          font=("Lucida Grande", AppConstant.FONT_SIZE + 6))
    label_heading.place(width=width * 90 / 100, height=height * 7 / 100, x=width * 5 / 100, y=height * 1 / 100)




Create a class "class CustomEntrySimple(tk.Canvas):" in the "custom_design" folder.



from tkinter import *
import tkinter as tk


class CustomEntrySimple(tk.Canvas):

    def __init__(self, parent, width, height, font, color, text):
        tk.Canvas.__init__(self, parent, borderwidth=0, relief="flat", highlightthickness=0, bg=color)

        self.width = width
        self.height = height
        self.color = color

        self.create_text(6, 5, anchor=W, font=font, text=text, fill="#000000")
        self.create_line(5, height - 8, width - 5, height - 8, fill="#808080")

        frame = Frame(parent,width=width * 95 / 100, height=height * 50 / 100)
        self.entry = Entry(frame, bg=color, bd=0, highlightthickness=0, font=font)

        self.entry.place(relwidth=1, relheight=1, x=0, y=0)

        self.create_window(6, height / 2 - (height * 50 / 100) / 2, anchor=NW, window=frame)
        self.update()

        (x0, y0, x1, y1) = self.bbox("all")
        width = (x1 - x0)
        height = (y1 - y0)
        self.configure(width=width, height=height)





Encoding
Encoding UI

Now lets define the function for Encoding UI and its code for its implementation. write it inside the ActionClass.

    

    def encode(self, enc, width, height):
        color = "#FFFFFF"
        button_size = width * 11 / 100

        add_heading_label(enc, color, height, width, "Encoding")

        action_frame = add_action_frame(enc, color, height, width, width*3/100)

        image_frame = add_search_frame(enc, color, height, width, width*45/100)

        # image frame wxh
        sfw = width * 40 / 100
        sfh = height * 40 / 100

        left_frame = Frame(image_frame, bg='light grey')
        left_frame.place(x=sfw * 10 / 100, y=sfh * 3 / 100, height=sfh, width=sfw)



        ## image_frame items..
        ## code for opening the imported file as shown in the image

        def openfile(self):
            self.fileopen = askopenfilename(initialdir="/Desktop", title="select file",
                                            filetypes=(("jpeg,png files", "*jpg *png"), ("all files", "*.*")))

            # imagee = ImageTk.PhotoImage(Image.open(self.fileopen))
            raw_image = Image.open(self.fileopen)
            image2 = raw_image.resize((int(sfw), int(sfh)), Image.ANTIALIAS)
            resized_image = ImageTk.PhotoImage(image2)

            self.import_path = Label(enc, text=self.fileopen, bg=color, bd=0, highlightthickness=0,
                                     font=("Lucida Grande", AppConstant.FONT_SIZE - 6))
            self.import_path.place(x=width * 51 / 100, y=height * 26 / 100, height=21, width=sfw)

            self.label_img = Label(image_frame, image=resized_image)
            self.label_img.image = resized_image
            self.label_img.place(x=sfw * 10 / 100, y=sfh * 3 / 100, height=sfh, width=sfw)

            # img.place(x=20, y=50)


        ## Import Button,openfile

        encbutton = RoundedButton(enc, button_size, button_size / 3, "#ffffff", "images/button3.png", "Import Picture",
                                  font=("Lucida Grande", AppConstant.FONT_SIZE - 4), command=lambda: openfile(self))
        encbutton.place(x=width * 65 / 100, y=height * 18 / 100)





        ## action_frame Items
        afw = width * 35 / 100
        afh = height * 75 / 100

        self.entrysecmes = CustomEntrySimple(action_frame, afw * 70 / 100, 50, ("Lucida Grande", AppConstant.FONT_SIZE - 6),
                                             color,
                                             "Enter Your Secret Message: ")
        self.entrysecmes.place(x=afw * 14 / 100, y=afh * 10 / 100)

        self.entrysave = CustomEntrySimple(action_frame, afw * 70 / 100, 50, ("Lucida Grande", AppConstant.FONT_SIZE - 6), color,
                                           "Save File As: ")
        self.entrysave.place(x=afw * 14 / 100, y=afh * 30 / 100)

        secimg = StringVar()
        radio1 = Radiobutton(action_frame, text='jpeg', value='jpeg', bg="#718d8f", fg="black", variable=secimg,
                             tristatevalue=1)
        radio1.place(x=afw * 30 / 100, y=afh * 50 / 100)

        radio2 = Radiobutton(action_frame, text='png', value='png', bg="#718d8f", fg="black", variable=secimg,
                             tristatevalue=0)
        radio2.place(x=afw * 50 / 100, y=afh * 50 / 100)


        ## Encoding 

        def encode():
            var = ""
            if self.fileopen == "":
                var += "Please Import any picture.\n"
            if self.entrysave.entry.get() == "" or self.entrysave.entry.get() == " ":
                var += "Please enter a name to save the picture.\n"
            if self.entrysecmes.entry.get() == "" or self.entrysecmes.entry.get() == " ":
                var += "Please Enter your secret message.\n"
            if (self.fileopen == "" or
                    self.entrysave.entry.get() == ""
                    or self.entrysecmes.entry.get() == ""
                    or self.entrysave.entry.get() == " "
                    or self.entrysecmes.entry.get() == " "):
                messagebox.showwarning("Error Message", var)
            else:
                if secimg.get() == "jpeg":
                    inimage = self.fileopen
                    response = messagebox.askyesno("Confirm", "Do you want to encode ?")
                    if response == 1:
                        a_stegano.hide(inimage, 'encodedImages/' + self.entrysave.entry.get() + '.jpg',
                                       self.entrysecmes.entry.get())
                        messagebox.showinfo("Success", "Successfully encoded " + self.entrysave.entry.get() + ".jpeg")
                        self.clear_all_encode_items()
                    else:
                        messagebox.showwarning("Failed", "unsuccessful")
                elif secimg.get() == "png":
                    inimage = self.fileopen
                    response = messagebox.askyesno("Confirm", "Do you want to encode ?")
                    if response == 1:
                        lsb.hide(inimage, message=self.entrysecmes.entry.get()).save(
                            'encodedImages/' + self.entrysave.entry.get() + '.png')
                        self.clear_all_encode_items()
                        messagebox.showinfo("Success", "Successfully encoded " + self.entrysave.entry.get() + ".png")
                    else:
                        messagebox.showwarning("Failed", "unsuccessful")
                else:
                    messagebox.showwarning("Error Message", "Please Image format. (Png or Jpeg)")

        ## Encode Button
        encode_btn = RoundedButton(action_frame, button_size, button_size / 3, "#ffffff", "images/desk_green.png",
                                  "ENCODE",
                                  font=("Lucida Grande", AppConstant.FONT_SIZE - 4), command=encode)
        encode_btn.place(x=afw * 30 / 100, y=afh * 70 / 100)

    ## To clear all the entry fields after Encoding successfully
    def clear_all_encode_items(self):
        self.import_path.config(text='')
        self.label_img.config(image='')
        self.entrysecmes.entry.delete(0, 'end')
        self.entrysave.entry.delete(0, 'end')                

    




    
Decoding
Decoding UI

Now we will define the function for Dencoding UI and its code for its implementation. write it inside the ActionClass.



def decode(self, dec, width, height):

    ## UI
        color = "#FFFFFF"
        button_size = width * 11 / 100

        add_heading_label(dec, color, height, width, "Decoding")

        action_frame = add_action_frame(dec, color, height, width, width*60/100)

        image_frame = add_search_frame(dec, color, height, width, width*3/100)

        ## image_frame wxh
        sfw = width * 40 / 100
        sfh = height * 40 / 100

        left_frame = Frame(image_frame, bg='light grey')
        left_frame.place(x=sfw * 10 / 100, y=sfh * 3 / 100, height=sfh, width=sfw)

        afw = width * 35 / 100
        afh = height * 75 / 100

        secimg = StringVar()
        radio1 = Radiobutton(action_frame, text='jpeg', value='jpeg', bg="#718d8f", fg="black", variable=secimg,
                             tristatevalue=1)
        radio1.place(x=afw * 33 / 100, y=afh * 6 / 100)

        radio2 = Radiobutton(action_frame, text='png', value='png', bg="#718d8f", fg="black", variable=secimg,
                             tristatevalue=0)
        radio2.place(x=afw * 53 / 100, y=afh * 6 / 100)

        self.message_frame = tk.LabelFrame(action_frame, text="Your Secret Message is: ", font=button_font,
                                           pady=afw * 2 / 100,
                                           padx=afw * 1 / 100, bg=color)
        self.message_frame.place(x=afw * 8 / 100, y=afh * 50 / 100, width=afw * 80 / 100, height=afh / 3)

        ## import image for decoding

        def openfile(self):
            self.fileopen = askopenfilename(initialdir="/Desktop", title="select file",
                                            filetypes=(("jpeg files, png file", "*jpg *png"), ("all files", "*.*")))
            # imagee = ImageTk.PhotoImage(Image.open(self.fileopen))

            raw_img = Image.open(self.fileopen)
            image2 = raw_img.resize((int(sfw), int(sfh)), Image.ANTIALIAS)
            resized_img = ImageTk.PhotoImage(image2)

            self.output_path = Label(dec, text=self.fileopen, bg=color, bd=0, highlightthickness=0)
            self.output_path.place(x=width * 8 / 100, y=height * 26 / 100, height=21, width=sfw)

            self.output_image = Label(image_frame, image=resized_img)
            self.output_image.image = resized_img
            self.output_image.place(x=sfw * 10 / 100, y=sfh * 3 / 100, height=sfh, width=sfw)

    ## decoded message.

        def deimg():
            global message
            if self.fileopen != "":
                if secimg.get() == "png":
                    message = lsb.reveal(self.fileopen)
                elif secimg.get() == "jpeg":
                    message = a_stegano.reveal(self.fileopen)
                else:
                    messagebox.showwarning("Error", "Choose image format, Png or Jpeg")
            else:
                messagebox.showwarning("Error", "Import any Image")

            if message:
                message_output = Label(self.message_frame, text=message,
                                       font=("Lucida Grande", AppConstant.FONT_SIZE - 6))
                message_output.place(x=2.6, y=0, width=afw * 75 / 100, height=afh / 4)
            else:
                messagebox.showwarning("Error", "No message Found")

    #import button
        impButton = RoundedButton(dec, button_size, button_size / 3, "#ffffff", "images/button3.png", "Import Picture",
                                  font=("Lucida Grande", AppConstant.FONT_SIZE - 4), command=lambda: openfile(self))
        impButton.place(x=width * 21.7 / 100, y=height * 18 / 100)


    #decode button
        decode_btn = RoundedButton(action_frame, button_size, button_size / 3, "#ffffff", "images/desk_green.png",
                                  "DECODE", font=("Lucida Grande", AppConstant.FONT_SIZE - 4), command=deimg)
        decode_btn.place(x=afw * 33/ 100, y=afh * 27 / 100)







At last we will manage closing of window

    
    def on_closing():
            self.destroy()
            args[0].deiconify()

        self.root.protocol("WM_DELETE_WINDOW", on_closing)
                       


Programmer Mirta is for learning and training. Projects might be simple to improve learning. Projects are constantly reviewed to avoid errors, but we cannot assure full correctness of all content. While using Programmer Mitra, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 2021 by Programmer Mitra. All Rights Reserved.