bitconverter / app.py
wenjun99's picture
Update app.py
e59d9f1 verified
raw
history blame
6 kB
import streamlit as st
from PIL import Image
import numpy as np
import pandas as pd
# Simple app: convert user input into ASCII codes and binary labels
def string_to_binary_labels(s: str) -> list[int]:
bits: list[int] = []
for char in s:
ascii_code = ord(char)
char_bits = [(ascii_code >> bit) & 1 for bit in range(7, -1, -1)]
bits.extend(char_bits)
return bits
def image_to_binary_labels(img: Image.Image, max_pixels: int = 256) -> list[int]:
img = img.convert("RGB")
img.thumbnail((int(np.sqrt(max_pixels)), int(np.sqrt(max_pixels))))
img_array = np.array(img)
flat = img_array.flatten()
binarized = [(pixel >> bit) & 1 for pixel in flat for bit in range(7, -1, -1)]
return binarized
def binary_labels_to_image(binary_labels: list[int], width: int = None, height: int = None) -> Image.Image:
total_pixels = len(binary_labels)
if width is None or height is None:
side = int(np.ceil(np.sqrt(total_pixels)))
width = height = side
needed_pixels = width * height
if total_pixels < needed_pixels:
binary_labels += [0] * (needed_pixels - total_pixels)
array = np.array(binary_labels, dtype=np.uint8) * 255
image_array = array.reshape((height, width))
img = Image.fromarray(image_array, mode='L')
return img
def binary_labels_to_rgb_image(binary_labels: list[int], width: int = None, height: int = None) -> Image.Image:
total_pixels = len(binary_labels) // 24
if width is None or height is None:
side = int(np.ceil(np.sqrt(total_pixels)))
width = height = side
needed_pixels = width * height
needed_bits = needed_pixels * 24
if len(binary_labels) < needed_bits:
binary_labels += [0] * (needed_bits - len(binary_labels))
pixels = []
for i in range(0, needed_bits, 24):
r_bits = binary_labels[i:i+8]
g_bits = binary_labels[i+8:i+16]
b_bits = binary_labels[i+16:i+24]
r = sum(b << (7-j) for j, b in enumerate(r_bits))
g = sum(b << (7-j) for j, b in enumerate(g_bits))
b = sum(b << (7-j) for j, b in enumerate(b_bits))
pixels.append((r, g, b))
array = np.array(pixels, dtype=np.uint8).reshape((height, width, 3))
img = Image.fromarray(array, mode='RGB')
return img
mutation_site_headers = [
3244, 3297, 3350, 3399, 3455, 3509, 3562, 3614,
3665, 3720, 3773, 3824, 3879, 3933, 3985, 4039,
4089, 4145, 4190, 4245, 4298, 4349, 4402, 4455,
4510, 4561, 4615, 4668, 4720, 4773, 4828, 4882
]
st.title("ASCII & Binary Label Converter")
tab1, tab2 = st.tabs(["Text to Binary Labels", "Image to Binary Labels"])
with tab1:
st.write("Enter text to see its ASCII codes and corresponding binary labels:")
user_input = st.text_input("Text Input", value="DNA")
if user_input:
ascii_codes = [ord(c) for c in user_input]
binary_labels = string_to_binary_labels(user_input)
st.subheader("ASCII Codes")
st.write(ascii_codes)
st.subheader("Binary Labels per Character")
grouped_chars = [binary_labels[i:i+8] for i in range(0, len(binary_labels), 8)]
for idx, bits in enumerate(grouped_chars):
st.write(f"'{user_input[idx]}' → {bits}")
st.subheader("Binary Labels (32-bit groups)")
num_groups = (len(binary_labels) + 31) // 32
table_data = []
for grp_idx in range(num_groups):
start = grp_idx * 32
end = start + 32
group = binary_labels[start:end]
if len(group) < 32:
group += [0] * (32 - len(group))
edited_sites = sum(group)
row = group + [edited_sites]
table_data.append(row)
df = pd.DataFrame(table_data, columns=[str(h) for h in mutation_site_headers] + ["Edited Sites"])
st.dataframe(df)
st.download_button(
label="Download Binary Labels as CSV",
data=','.join(str(b) for b in binary_labels),
file_name="binary_labels.csv",
mime="text/csv"
)
with tab2:
st.write("Upload an image (JPG or PNG) to convert it into binary labels:")
uploaded_file = st.file_uploader("Choose an image file", type=["jpg", "jpeg", "png"])
if uploaded_file is not None:
img = Image.open(uploaded_file)
st.image(img, caption="Uploaded Image", use_column_width=True)
max_pixels = st.slider("Max number of pixels to encode", min_value=32, max_value=2056, value=1024, step=32)
binary_labels = image_to_binary_labels(img, max_pixels=max_pixels)
st.subheader("Binary Labels from Image")
num_groups = (len(binary_labels) + 31) // 32
table_data = []
for grp_idx in range(num_groups):
start = grp_idx * 32
end = start + 32
group = binary_labels[start:end]
if len(group) < 32:
group += [0] * (32 - len(group))
edited_sites = sum(group)
row = group + [edited_sites]
table_data.append(row)
df = pd.DataFrame(table_data, columns=[str(h) for h in mutation_site_headers] + ["Edited Sites"])
st.dataframe(df)
st.download_button(
label="Download Image Binary Labels as CSV",
data=','.join(str(b) for b in binary_labels),
file_name="image_binary_labels.csv",
mime="text/csv"
)
st.subheader("Reconstruct Image from Binary Labels")
option = st.radio("Choose Reconstruction Mode", ["Grayscale", "True Color (RGB)"])
if st.button("Reconstruct Image"):
if option == "Grayscale":
reconstructed_img = binary_labels_to_image(binary_labels)
else:
reconstructed_img = binary_labels_to_rgb_image(binary_labels)
st.image(reconstructed_img, caption="Reconstructed Image", use_column_width=True)
# Future: integrate DNA editor mapping for each mutation site here