|
1 | | -import cv2 #imports opencv, make sure that you have opencv installed |
2 | | -import numpy as np #imports numpy and makes it be called with np because lazy |
3 | | -import os #imports os, needed for reading file size |
| 1 | +import cv2 |
| 2 | +import numpy as np |
| 3 | +import os |
4 | 4 |
|
5 | | -def create_video(output_video_path, inputf, width=1280, height=720, frame_rate=12, pix=5): #change the width and height however you like, width is the width, height is the height and pix is the bit size in pixels (you need to check if your desired height and width can be divided with pix, if not change pix or height and width) |
6 | | - with open(inputf, 'rb') as file: #declares file as the input file |
| 5 | +def create_video(output_video_path, inputf, width=1280, height=720, frame_rate=12, pix=5): #change the width and height however you like, pix is the size of each bit in pixels (to resist compression, 5 means each bit is 5x5) |
| 6 | + with open(inputf, 'rb') as file: |
7 | 7 | size = os.path.getsize(inputf) #gets the size of the file |
8 | | - print(size) #prints the size |
9 | | - chunk = int(width*height/(pix*pix)) #get the chunk, or in better terms how many bits a single frame can contain |
| 8 | + print(size) |
| 9 | + chunk = int(width*height/(pix*pix)) #get the chunk, basically how many bits a single frame can contain |
10 | 10 | width1 = width #i could just divide height1 and width1 directly, but it breaks compatibility since i need to swap all the var names and im lazy |
11 | | - height1 = height #i could just divide height1 and width1 directly, but it breaks compatibility since i need to swap all the var names and im lazy |
12 | | - width = int(width / pix) #i could just divide height1 and width1 directly, but it breaks compatibility since i need to swap all the var names and im lazy |
13 | | - height = int(height / pix) #i could just divide height1 and width1 directly, but it breaks compatibility since i need to swap all the var names and im lazy |
14 | | - add = height * width #declares add so that basically i dont need to multiply height and width over and over when trying to add the elapsed bits |
| 11 | + height1 = height |
| 12 | + width = int(width / pix) |
| 13 | + height = int(height / pix) |
| 14 | + add = height * width |
15 | 15 | total_bits = size * 8 #gets the total bits |
16 | | - print(total_bits) #prints the total bits amount |
17 | | - if total_bits <= chunk: #if the file fits in one frame or less, then set the bits amount to the chunk |
18 | | - total_bits = chunk #sets bit length as the chunk if previous condition is true |
19 | | - print(total_bits) #prints bit length if the condition is true, for debugging purposes (kinda useless) |
| 16 | + print(total_bits) |
| 17 | + if total_bits < chunk: #if the file fits in less than one frame, set the bits amount to the chunk |
| 18 | + total_bits = chunk |
| 19 | + print(total_bits) |
20 | 20 | total_frames = int(np.ceil(total_bits / (width * height))) #gets the total frames amount |
21 | | - print(total_frames) #prints the total frames |
| 21 | + if (size*8) % (width*height) == 0: #if the file does NOT leave a gap then it makes an empty 1st frame |
| 22 | + total_frames += 1 |
| 23 | + print(total_frames) |
22 | 24 | fourcc = cv2.VideoWriter_fourcc(*'png ') #codec (fourcc) |
23 | | - index = 0 #this number is totally useless except for the fact that it prints how many buts it has converted, updates each frame |
24 | | - video_writer = cv2.VideoWriter(output_video_path, fourcc, frame_rate, (width1, height1), isColor=False) #DONT SWAP WIDTH1 AND HEIGHT1, OTHERWISE OPENCV GETS REAL MAD AND IT WILL MURDER YOUR HOPES AND DREAMS BY NOT CREATING THE VIDEO (empty video file) AND TELL YOU NOTHING ABOUT WHY IT HAPPENED |
| 25 | + index = 0 |
| 26 | + video_writer = cv2.VideoWriter(output_video_path, fourcc, frame_rate, (width1, height1), isColor=False) #DONT SWAP WIDTH1 AND HEIGHT1, OTHERWISE OPENCV GETS REAL MAD |
25 | 27 | m = 1 #just an indicator to check if the first frame has been done, m=1 = no, m=0 = yes |
26 | | - for _ in range(total_frames): #do the frames after the 1st |
27 | | - if m == 0: #checks if the 1st frame is done, it is important |
28 | | - frame = np.zeros((height, width), dtype=np.uint8) #create the frame |
| 28 | + for _ in range(total_frames): |
| 29 | + if m == 0: |
| 30 | + frame = np.zeros((height, width), dtype=np.uint8) |
29 | 31 | content = file.read(int(chunk / 8)) #read the portion of the file needed to fill 1 frame (resulting in less ram usage), the divide by 8 is there since chunk represents of the bits that can fit in one frame, and this converts it into bytes |
30 | | - content = ''.join(format(byte, '08b') for byte in content) #converts content into a string otherwise the program will get pretty mad |
| 32 | + content = ''.join(format(byte, '08b') for byte in content) |
31 | 33 | values = np.array([int(content[bit2]) * 255 for bit2 in range (chunk)]) #basically if it is reading a 1 it will multiply it by 255, resulting in 255 (white), otherwise it'll multiply 0 by 255 resulting in 0 (black) |
32 | | - values = values.reshape(-1) #idk what it does honestly, afaik it reshapes values into a 1d array |
33 | | - index += add #increments index by the amount of bits it has converted |
34 | | - print(f"{index} 1") #prints the bits it has converted in total, if you get the bits amount of the file and compare it with the output you can get a pseudo progress percentage |
35 | | - frame.flat = values #writes the bits to the frame right after flattening the frame into a 1d picture |
| 34 | + values = values.reshape(-1) #vectoring stuff, efficiency reasons |
| 35 | + index += add |
| 36 | + print(f"{index} 1") |
| 37 | + frame.flat = values |
36 | 38 | frame = frame.reshape((height, width)) #converts the frame back into 2d |
37 | | - frame = cv2.resize(frame, (width1, height1), interpolation=cv2.INTER_NEAREST) #enlargens the frame back into the original resolution, instead of writing each bit (it will take longer if i do the latter) |
38 | | - video_writer.write(frame) #writes the frame instead of caching it in ram, resulting in less ram usage |
39 | | - else: #PRETTY SMART STUFF, I SUGGEST TO NOT EDIT (except the one that declares size2, but it still works as it is tho, so maybe dont change it) |
40 | | - frame = np.zeros((height, width), dtype=np.uint8) #create the frame |
41 | | - size2 = size * 8 #converts the total bytes amount into bits, didnt want to use the other variable because uhh idk feel free to change it i did not test it |
42 | | - size3 = size2 % chunk #gets the bits it needs to write |
43 | | - temp = chunk - size3 #gets the padding bits it will write at the beginning of the 1st frame, this is basically why i split the stuff that makes the 1st frame from the others |
44 | | - print(temp) |
45 | | - content = file.read(int(size3 / 8)) #read the bits needed for the 1st frame |
46 | | - binary_data = '0' * (temp - 1) #creates the padding 0s (except for the last 0 where it is swapped for a 1, for decoding purposes) |
47 | | - binary_data += '1' #puts the 1 at the end of the padding, i made room specifically for that |
48 | | - content = ''.join(format(byte, '08b') for byte in content) #converts content into a string otherwise the program will get pretty mad |
49 | | - binary_data += content #appends at the end the data itself |
50 | | - values = np.array([int(binary_data[bit]) * 255 for bit in range(chunk)]) #basically if it is reading a 1 it will multiply it by 255, resulting in 255 (white), otherwise it'll multiply 0 by 255 resulting in 0 (black) |
51 | | - values = values.reshape(-1) #idk what it does honestly, afaik it reshapes values into a 1d array |
52 | | - index += add #increments index by the amount of bits it has converted |
53 | | - print(f"{index} 0") #prints the bits it has converted in the 1st frame |
54 | | - frame.flat = values #writes the bits to the frame right after flattening the frame into a 1d picture |
55 | | - frame = frame.reshape((height, width)) #converts the frame back into 2d |
56 | | - frame = cv2.resize(frame, (width1, height1), interpolation=cv2.INTER_NEAREST) #enlargens the frame back into the original resolution |
57 | | - video_writer.write(frame) #writes the frame instead of caching it in ram, resulting in less ram usage |
58 | | - m = 0 #changes the indicator to say that the 1st frame has been done |
| 39 | + frame = cv2.resize(frame, (width1, height1), interpolation=cv2.INTER_NEAREST) #enlargens the frame back into the original resolution, instead of writing each bit, this is to resist compression |
| 40 | + video_writer.write(frame) |
| 41 | + else: |
| 42 | + if (size*8) % (width*height) == 0: #if the file does NOT leave a gap then i'm making an empty 1st frame |
| 43 | + temp = chunk |
| 44 | + frame = np.zeros((height, width), dtype=np.uint8) |
| 45 | + binary_data = '0' * (temp - 1) |
| 46 | + binary_data += '1' |
| 47 | + print(temp) |
| 48 | + values = np.array([int(binary_data[bit]) * 255 for bit in range(chunk)]) |
| 49 | + values = values.reshape(-1) |
| 50 | + frame.flat = values |
| 51 | + frame = frame.reshape((height, width)) |
| 52 | + frame = cv2.resize(frame, (width1, height1), interpolation=cv2.INTER_NEAREST) |
| 53 | + video_writer.write(frame) |
| 54 | + m = 0 |
| 55 | + else: |
| 56 | + frame = np.zeros((height, width), dtype=np.uint8) |
| 57 | + size2 = size * 8 |
| 58 | + size3 = size2 % chunk #gets the bits it needs to write |
| 59 | + temp = chunk - size3 #gets the padding bits it will write at the beginning of the 1st frame |
| 60 | + print(temp) |
| 61 | + content = file.read(int(size3 / 8)) #read the bits needed for the 1st frame |
| 62 | + binary_data = '0' * (temp - 1) #creates the padding 0s (except for the last 0 where it is swapped for a 1, for decoding purposes) |
| 63 | + binary_data += '1' |
| 64 | + content = ''.join(format(byte, '08b') for byte in content) |
| 65 | + binary_data += content |
| 66 | + values = np.array([int(binary_data[bit]) * 255 for bit in range(chunk)]) |
| 67 | + values = values.reshape(-1) #vectoring stuff, efficiency reasons |
| 68 | + index += add |
| 69 | + print(f"{index} 0") |
| 70 | + frame.flat = values #writes the bits to the frame right after flattening the frame into a 1d picture |
| 71 | + frame = frame.reshape((height, width)) #converts the frame back into 2d |
| 72 | + frame = cv2.resize(frame, (width1, height1), interpolation=cv2.INTER_NEAREST) #enlargens the frame back into the original resolution, it's to resist compression |
| 73 | + video_writer.write(frame) |
| 74 | + m = 0 |
59 | 75 | video_writer.release() |
60 | 76 |
|
61 | | -if __name__ == "__main__": #checks if the program has already been run |
62 | | - input_file_path = "/home/ema/Desktop/bk foot lettuce2.txt" #replace with the path to your input file |
63 | | - output_video_path = "/home/ema/Desktop/Out1.avi" #replace with the desired output video path |
64 | | - create_video(output_video_path, input_file_path) #calls create_video function |
| 77 | +if __name__ == "__main__": |
| 78 | + input_file_path = "input.txt" #replace with the path to your input file |
| 79 | + output_video_path = "output.avi" #replace with the desired output video path |
| 80 | + create_video(output_video_path, input_file_path) |
65 | 81 |
|
66 | 82 |
|
0 commit comments