Omnibus commited on
Commit
708abdc
·
0 Parent(s):

Duplicate from Omnibus/Fernet-Encryption-QR

Browse files
Files changed (6) hide show
  1. .gitattributes +35 -0
  2. README.md +13 -0
  3. app.py +232 -0
  4. qr.py +72 -0
  5. requirements.txt +2 -0
  6. stegan.py +115 -0
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Fernet Encryption
3
+ emoji: 📊
4
+ colorFrom: pink
5
+ colorTo: green
6
+ sdk: gradio
7
+ sdk_version: 3.42.0
8
+ app_file: app.py
9
+ pinned: false
10
+ duplicated_from: Omnibus/Fernet-Encryption-QR
11
+ ---
12
+
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from cryptography.fernet import Fernet
3
+ from cryptography.hazmat.primitives import hashes
4
+ from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
5
+ import os
6
+ import base64
7
+ import hashlib
8
+ from pathlib import Path
9
+ import qr
10
+ import stegan
11
+
12
+ def create_key(passw):
13
+ key = passw.encode()
14
+ h = hashlib.new('sha256')
15
+ h.update(key)
16
+ key = h.hexdigest()
17
+ key = key.encode()
18
+ #salt = os.urandom(16)
19
+ salt = key
20
+ kdf = PBKDF2HMAC(
21
+ algorithm=hashes.SHA256(),
22
+ length=32,
23
+ salt=salt,
24
+ iterations=480000,
25
+ )
26
+ key = base64.urlsafe_b64encode(kdf.derive(key))
27
+ return key
28
+
29
+
30
+ def encrypt(passw,mes=None,img=None,doc=None):
31
+ #key = Fernet.generate_key()
32
+ key = create_key(passw)
33
+ fernet = Fernet(key)
34
+ enc_mes=None
35
+ enc_file=None
36
+ if mes != None and mes != "":
37
+ bytes_m = mes.encode()
38
+ enc_mes = fernet.encrypt(bytes_m)
39
+ enc_mes = f'{enc_mes}+aaa+'
40
+ if img != None:
41
+ with open(f'{img}', "rb") as image_file:
42
+ bytes_i = base64.b64encode(image_file.read())
43
+ if mes != None and mes != "":
44
+ im_bytes = fernet.encrypt(bytes_i)
45
+ enc_mes = f'{enc_mes}{im_bytes}+bbb+'
46
+ else:
47
+ im_bytes = fernet.encrypt(bytes_i)
48
+ enc_mes = f'{im_bytes}+bbb+'
49
+
50
+ #enc_qr = qr.make_qr(txt=(enc_mes.strip('"')))
51
+ qr_link = "https://omnibus-fernet-encryption-qr.hf.space"
52
+ enc_qr = stegan.conv_im(qr_link=qr_link,data=enc_mes)
53
+ if doc != None:
54
+
55
+ print(dir(doc))
56
+ print(doc.name)
57
+ #print(doc.file)
58
+ doc_name = doc.name
59
+ doc_name = doc_name.split("/",4)[4]
60
+ #bytes_d = doc.encode()
61
+
62
+ #doc = Path(doc)
63
+ with open(doc.name, "rb") as file:
64
+ # read all file data
65
+ file_data = file.read()
66
+ enc_doc = fernet.encrypt(file_data)
67
+ og_name = doc.name
68
+ og_end = og_name.split(".",1)[1]
69
+ og_front=og_name.split(".",1)[0]
70
+
71
+
72
+ enc_file=f'{doc.name}.ocrpt'
73
+ with open(enc_file, "wb") as file:
74
+ file.write(enc_doc)
75
+
76
+ return enc_mes,enc_file,enc_qr
77
+
78
+ def decrypt(passw,enc_in=None):
79
+ key = create_key(passw)
80
+ fernet = Fernet(key)
81
+ dec_im = None
82
+ mes_dec= None
83
+ enc_in=enc_in.strip('"')
84
+ print (f'enc_in :::: {enc_in}')
85
+
86
+ if "+aaa+" in enc_in:
87
+ mes1=enc_in.split("+aaa+",1)[0]
88
+ mes1=mes1.strip("b'").strip("'")
89
+ mes_bytes = bytes(mes1,'utf-8')
90
+ mes_dec = fernet.decrypt(mes_bytes).decode()
91
+ if "+bbb+" in enc_in:
92
+ mes12=enc_in.split("+aaa+",1)[1]
93
+ mes2=mes12.split("+bbb+",1)[0]
94
+ mes2=mes2.strip("b'").strip("'")
95
+ im_bytes = bytes(mes2,'utf-8')
96
+ print(f'im_bytes::{im_bytes}')
97
+
98
+ mes2 = fernet.decrypt(mes2).decode()
99
+ #base = bytes(decMessage, 'utf-8')
100
+ with open(f"finished_im.png", "wb") as fh:
101
+ #fh.write(base64.decodebytes(im_bytes))
102
+ fh.write(base64.decodebytes(bytes(mes2, 'utf-8')))
103
+ fh.close
104
+ dec_im = "finished_im.png"
105
+
106
+ if not "+aaa+" in enc_in:
107
+ if "+bbb+" in enc_in:
108
+ mes2 = enc_in.split("+bbb+",1)[0]
109
+ mes2=mes2.strip("b'").strip("'")
110
+ im_bytes = bytes(mes2,'utf-8')
111
+ print(f'im_bytes2::{im_bytes}')
112
+ mes2 = fernet.decrypt(mes2).decode()
113
+
114
+ #base = bytes(decMessage, 'utf-8')
115
+ with open(f"finished_im.png", "wb") as fh:
116
+ #fh.write(base64.decodebytes(im_bytes))
117
+ fh.write(base64.decodebytes(bytes(mes2, 'utf-8')))
118
+ fh.close
119
+ dec_im = "finished_im.png"
120
+ return(dec_im,mes_dec)
121
+
122
+ def decode_doc(passw,doc=None):
123
+ key = create_key(passw)
124
+ fernet = Fernet(key)
125
+ doc_name = doc.name
126
+ doc_name = doc_name.split("/",4)[4]
127
+ #bytes_d = doc.encode()
128
+
129
+ #doc = Path(doc)
130
+ with open(doc.name, "rb") as file:
131
+ # read all file data
132
+ file_data = file.read()
133
+ dec_doc = fernet.decrypt(file_data)
134
+ og_name = doc.name
135
+ og_end = og_name.split(".",1)[1]
136
+ og_front=og_name.split(".",1)[0]
137
+
138
+ dec_file = doc.name.strip(".ocrpt")
139
+ #enc_file=f'{doc.name}.ocrpt'
140
+ with open(dec_file, "wb") as file:
141
+ file.write(dec_doc)
142
+ return dec_file
143
+
144
+ def decode_qr(im,passw):
145
+ with open(f'{im}', "rb") as image_file:
146
+ bytes_i = base64.b64encode(image_file.read())
147
+ decode_qr = stegan.decode(im)
148
+ dec_im = decrypt(passw, enc_in=decode_qr)
149
+ '''
150
+ print(f'decoded QR::{decode_qr}')
151
+ key = create_key(passw)
152
+ fernet = Fernet(key)
153
+ dec_im = None
154
+ mes_dec= None
155
+ enc_in=decode_qr.strip('"')
156
+ print (f'enc_in :::: {enc_in}')
157
+
158
+ if "+aaa+" in enc_in:
159
+ mes1=enc_in.split("+aaa+",1)[0]
160
+ mes1=mes1.strip("b'").strip("'")
161
+ mes_bytes = bytes(mes1,'utf-8')
162
+ mes_dec = fernet.decrypt(mes_bytes).decode()
163
+ if "+bbb+" in enc_in:
164
+ mes12=enc_in.split("+aaa+",1)[1]
165
+ mes2=mes12.split("+bbb+",1)[0]
166
+ mes2=mes2.strip("b'").strip("'")
167
+ im_bytes = bytes(mes2,'utf-8')
168
+ print(f'im_bytes::{im_bytes}')
169
+
170
+ mes2 = fernet.decrypt(mes2).decode()
171
+ #base = bytes(decMessage, 'utf-8')
172
+ with open(f"finished_im.png", "wb") as fh:
173
+ #fh.write(base64.decodebytes(im_bytes))
174
+ fh.write(base64.decodebytes(bytes(mes2, 'utf-8')))
175
+ fh.close
176
+ dec_im = "finished_im.png"
177
+
178
+ if not "+aaa+" in enc_in:
179
+ if "+bbb+" in enc_in:
180
+ mes2 = enc_in.split("+bbb+",1)[0]
181
+ mes2=mes2.strip("b'").strip("'")
182
+ im_bytes = bytes(mes2,'utf-8')
183
+ print(f'im_bytes2::{im_bytes}')
184
+ mes2 = fernet.decrypt(mes2).decode()
185
+
186
+ #base = bytes(decMessage, 'utf-8')
187
+ with open(f"finished_im.png", "wb") as fh:
188
+ #fh.write(base64.decodebytes(im_bytes))
189
+ fh.write(base64.decodebytes(bytes(mes2, 'utf-8')))
190
+ fh.close
191
+ dec_im = "finished_im.png"
192
+ '''
193
+ return(dec_im,mes_dec)
194
+
195
+
196
+ with gr.Blocks() as app:
197
+ with gr.Tab("Encrypt"):
198
+ pass_in=gr.Textbox(label="Set Password")
199
+ with gr.Tab("String"):
200
+ mes = gr.Textbox(label = "Message")
201
+ with gr.Row():
202
+ im = gr.Image(type="filepath")
203
+ with gr.Tab("File"):
204
+ doc=gr.File()
205
+ enc_doc_out=gr.File()
206
+ en_btn = gr.Button("Encrypt")
207
+ enc_out = gr.Textbox(label="Encrypted Bytes")
208
+ enc_qr_out = gr.Image(label = "Encrypted QR")
209
+
210
+ with gr.Tab("Decrypt"):
211
+ pass_out = gr.Textbox(label="Enter Password")
212
+ with gr.Tab("String"):
213
+ enc_in = gr.Textbox(label="Encrypted Bytes")
214
+ d_btn = gr.Button("Decrypt")
215
+ d_txt = gr.Textbox(label="Decrypted")
216
+ d_im =gr.Image(label="Decrytped Image")
217
+ with gr.Tab("File"):
218
+ dec_doc_in = gr.File()
219
+ dec_doc_btn = gr.Button("Decrypt")
220
+ dec_doc_out=gr.File()
221
+ with gr.Tab("QR"):
222
+ dec_qr_im = gr.Image(type="filepath")
223
+ dec_qr_txt = gr.Textbox(label="Decrypted")
224
+ dec_qr_im_out =gr.Image(label="Decrytped Image")
225
+ dec_qr_btn = gr.Button("Decrypt")
226
+
227
+ dec_qr_btn.click(decode_qr,[dec_qr_im,pass_out],[dec_qr_im_out,dec_qr_txt])
228
+ dec_doc_btn.click(decode_doc,[pass_out,dec_doc_in],dec_doc_out)
229
+ en_btn.click(encrypt,[pass_in,mes,im,doc],[enc_out,enc_doc_out,enc_qr_out])
230
+ d_btn.click(decrypt,[pass_out,enc_in],[d_im,d_txt])
231
+ app.launch()
232
+
qr.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import qrcode as qr
3
+ import base64
4
+ import cv2
5
+ import os
6
+ from PIL import Image
7
+
8
+ def make_qr(txt=None,data=None,im_size=None):
9
+ if txt != None and txt != "" and data != None:
10
+ f = Image.open(f'{data}')
11
+ f.thumbnail((im_size,im_size))
12
+ f.save("tmp.jpg")
13
+ imr = open(f'tmp.jpg','rb')
14
+ out = f'{txt}+++{base64.b64encode(imr.read())}'
15
+ print (f'txt+data {out}')
16
+ img1 = qr.make(out,box_size=10,error_correction=qr.constants.ERROR_CORRECT_H)
17
+ img1.save("im.png")
18
+ return "im.png"
19
+ if txt == None or txt == "" and data != None:
20
+ f = Image.open(f'{data}')
21
+ f.thumbnail((im_size,im_size))
22
+ f.save("tmp1.jpg")
23
+ imr = open(f'tmp1.jpg','rb')
24
+ out = f'+++{base64.b64encode(imr.read())}'
25
+ print (f'data {out}')
26
+ img1 = qr.make(out,box_size=10,error_correction=qr.constants.ERROR_CORRECT_H)
27
+ img1.save("im1.png")
28
+ return "im1.png"
29
+
30
+ if txt != None and txt != "" and data == None:
31
+ out = f'{txt}'
32
+ print (f'txt {out}')
33
+ img1 = qr.make(out,box_size=10,error_correction=qr.constants.ERROR_CORRECT_H)
34
+ img1.save("im2.png")
35
+ return "im2.png"
36
+
37
+ def cnt_im_bytes(im,txt_cnt,im_size):
38
+ f = Image.open(f'{im}')
39
+ f.thumbnail((im_size,im_size))
40
+ f.save("tmp11.jpg")
41
+ im_cnt=os.stat('tmp11.jpg').st_size
42
+ print(im_cnt)
43
+ tot_cnt=im_cnt+int(txt_cnt)
44
+ return im_cnt,tot_cnt
45
+
46
+ def cnt_bytes(txt,im_cnt):
47
+ txt_cnt = (len(txt.encode('utf-8')))
48
+ tot_cnt = txt_cnt + int(im_cnt)
49
+ return txt_cnt, tot_cnt
50
+
51
+
52
+ def decode(im):
53
+
54
+ image = cv2.imread(f'{im}')
55
+ qrCodeDetector = cv2.QRCodeDetector()
56
+ decodedText, points, _ = qrCodeDetector.detectAndDecode(image)
57
+ if points is not None:
58
+ text = decodedText
59
+ else:
60
+ text = "No QR Code Found"
61
+ return text
62
+ def make_im(tx_str):
63
+ out = tx_str.split("+++b",1)[1]
64
+ out.replace("'","")
65
+ print(out)
66
+ decoded_data=base64.b64decode((out))
67
+
68
+ #write the decoded data back to original format in file
69
+ img_file = open('image.jpeg', 'wb')
70
+ img_file.write(decoded_data)
71
+ img_file.close()
72
+ return ('image.jpeg')
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ opencv-python
2
+ qrcode
stegan.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ import gradio as gr
3
+ import cv2
4
+ import numpy as np
5
+ import pandas as pd
6
+ from PIL import Image
7
+ import hashlib
8
+ import os
9
+ import uuid as uniq
10
+ from qr import make_qr
11
+ import math
12
+
13
+
14
+ def to_bin(data):
15
+ """Convert `data` to binary format as string"""
16
+ if isinstance(data, str):
17
+ return ''.join([ format(ord(i), "08b") for i in data ])
18
+ elif isinstance(data, bytes):
19
+ return ''.join([ format(i, "08b") for i in data ])
20
+ elif isinstance(data, np.ndarray):
21
+ return [ format(i, "08b") for i in data ]
22
+ elif isinstance(data, int) or isinstance(data, np.uint8):
23
+ return format(data, "08b")
24
+ else:
25
+ raise TypeError("Type not supported.")
26
+ def decode(image_name,txt=None):
27
+ BGRimage = cv2.imread(image_name)
28
+ image = cv2.cvtColor(BGRimage, cv2.COLOR_BGR2RGB)
29
+ #resultd = hashlib.sha256(txt.encode('utf-8')).hexdigest()
30
+ binary_data = ""
31
+ for row in image:
32
+ for pixel in row:
33
+ r, g, b = to_bin(pixel)
34
+ binary_data += r[-1]
35
+ binary_data += g[-1]
36
+ binary_data += b[-1]
37
+ all_bytes = [ binary_data[i: i+8] for i in range(0, len(binary_data), 8) ]
38
+ decoded_data = ""
39
+ for byte in all_bytes:
40
+ decoded_data += chr(int(byte, 2))
41
+ if decoded_data[-5:] == "=====":
42
+ break
43
+ p = decoded_data[:-5].split("#",1)[1].split("#",1)[0]
44
+ #if p == resultd:
45
+ this = decoded_data[:-5].split("#",1)[0].split("'",1)[1]
46
+ #base = bytes(this, 'utf-8')
47
+ #with open(f"finished_im{uniqnum}.png", "wb") as fh:
48
+ # fh.write(base64.decodebytes(bytes(this, 'utf-8')))
49
+ #fh.close
50
+ #return f"finished_im{uniqnum}.png"
51
+ return this
52
+
53
+ def encode(image_name, secret_data,txt=None):
54
+ BGRimage = cv2.imread(image_name)
55
+ image = cv2.cvtColor(BGRimage, cv2.COLOR_BGR2RGB)
56
+ n_bytes = image.shape[0] * image.shape[1] * 3 // 8
57
+ print("[*] Maximum bytes to encode:", n_bytes)
58
+ #resultp = hashlib.sha256(txt.encode('utf-8')).hexdigest()
59
+ secret_data1=secret_data
60
+ #secret_data1=f'{secret_data}#{resultp}'
61
+
62
+ while True:
63
+ if len(secret_data1) < (n_bytes):
64
+ secret_data1 = f'{secret_data1}#'
65
+ elif len(secret_data1) >= (n_bytes):
66
+ break
67
+ secret_data = secret_data1
68
+ if len(secret_data) > n_bytes:
69
+ return image_name, gr.Markdown.update("""<center><h3>Input image is too large""")
70
+ secret_data += "====="
71
+ data_index = 0
72
+ binary_secret_data = to_bin(secret_data)
73
+ data_len = len(binary_secret_data)
74
+ for row in image:
75
+ for pixel in row:
76
+ r, g, b = to_bin(pixel)
77
+ if data_index < data_len:
78
+ pixel[0] = int(r[:-1] + binary_secret_data[data_index], 2)
79
+ data_index += 1
80
+ if data_index < data_len:
81
+ pixel[1] = int(g[:-1] + binary_secret_data[data_index], 2)
82
+ data_index += 1
83
+ if data_index < data_len:
84
+ pixel[2] = int(b[:-1] + binary_secret_data[data_index], 2)
85
+ data_index += 1
86
+ if data_index >= data_len:
87
+ break
88
+ return image
89
+ def conv_im(qr_link,data):
90
+ uniqnum = uniq.uuid4()
91
+
92
+ byte_size = len(data)
93
+ print (f'bytes:{byte_size}')
94
+ data_pixels = byte_size*4
95
+ print (f'pixels:{data_pixels}')
96
+ #data_sq=data_pixels/2
97
+ data_sq = int(math.sqrt(data_pixels))
98
+ data_pad = data_sq+100
99
+ print (f'square image:{data_pad}x{data_pad}')
100
+
101
+ qr_im = make_qr(txt=qr_link)
102
+ img1 = Image.open(qr_im)
103
+ imgw = img1.size[0]
104
+ imgh = img1.size[1]
105
+ print (f'qr Size:{img1.size}')
106
+ #img1.thumbnail((imgw*4,imgh*4), Image.Resampling.LANCZOS)
107
+ img1 = img1.resize((int(data_pad),int(data_pad)), Image.Resampling.LANCZOS)
108
+ print (img1.size)
109
+ img1.save(f'tmpim{uniqnum}.png')
110
+
111
+ with open(f'tmpim{uniqnum}.png', "rb") as image_file:
112
+ encoded_string = base64.b64encode(image_file.read())
113
+ image_file.close()
114
+ im_out = encode(f'tmpim{uniqnum}.png',data)
115
+ return im_out