Discussion:
[file2png] Convert (encrypted) binary data to .png images and back
Add Reply
Stefan Claas
2024-12-29 03:05:58 UTC
Reply
Permalink
Hi all,

here is a Python3 implementation of my file2png program,
available here: https://github.com/706f6c6c7578/file2png

Hope you find it useful, when for example uploading such
images to platforms like X, which does not compress .png
images, as I have tested!

import argparse
import math
import os
import struct
from PIL import Image
import sys

def encode_file(input_stream, output_stream):
data = input_stream.read()
file_size = len(data)
pixel_count = (file_size + 8) // 3
dimension = math.ceil(math.sqrt(pixel_count))

img = Image.new('RGBA', (dimension, dimension), (0, 0, 0, 255))
pixels = img.load()

size_buf = struct.pack('<Q', file_size)
x, y = 0, 0

for i in range(0, 8, 3):
r = size_buf[i]
g = size_buf[i+1] if i+1 < 8 else 0
b = size_buf[i+2] if i+2 < 8 else 0
pixels[x, y] = (r, g, b, 255)
x += 1
if x >= dimension:
x = 0
y += 1

for i in range(0, len(data), 3):
r = data[i]
g = data[i+1] if i+1 < len(data) else 0
b = data[i+2] if i+2 < len(data) else 0
pixels[x, y] = (r, g, b, 255)
x += 1
if x >= dimension:
x = 0
y += 1

img.save(output_stream, format='PNG')

def decode_file(input_stream, output_stream):
img = Image.open(input_stream)
pixels = img.load()
width, height = img.size

size_buf = bytearray(8)
pixel_index = 0
for i in range(0, 8, 3):
x = pixel_index % width
y = pixel_index // width
r, g, b, _ = pixels[x, y]
size_buf[i] = r
if i+1 < 8:
size_buf[i+1] = g
if i+2 < 8:
size_buf[i+2] = b
pixel_index += 1

file_size = struct.unpack('<Q', size_buf)[0]
data = bytearray(file_size)

data_index = 0
start_pixel = (8 + 2) // 3
for y in range(start_pixel // width, height):
start_x = 0 if y != start_pixel // width else start_pixel % width
for x in range(start_x, width):
if data_index >= file_size:
break
r, g, b, _ = pixels[x, y]
data[data_index] = r
if data_index + 1 < file_size:
data[data_index+1] = g
if data_index + 2 < file_size:
data[data_index+2] = b
data_index += 3

output_stream.write(data[:file_size])

def main():
parser = argparse.ArgumentParser(description="file2png - Convert any file to PNG and back")
parser.add_argument("-d", action="store_true", help="decode PNG to file")
parser.add_argument("input", nargs="?", default="-", help="Input file (default: stdin)")
parser.add_argument("output", nargs="?", default="-", help="Output file (default: stdout)")

args = parser.parse_args()

input_stream = sys.stdin.buffer if args.input == "-" else open(args.input, "rb")
output_stream = sys.stdout.buffer if args.output == "-" else open(args.output, "wb")

try:
if args.d:
decode_file(input_stream, output_stream)
else:
encode_file(input_stream, output_stream)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
finally:
if input_stream is not sys.stdin.buffer:
input_stream.close()
if output_stream is not sys.stdout.buffer:
output_stream.close()

if __name__ == "__main__":
main()
--
Regards
Stefan
Rich
2024-12-30 20:35:58 UTC
Reply
Permalink
Post by Stefan Claas
Hi all,
here is a Python3 implementation of my file2png program, available
here: https://github.com/706f6c6c7578/file2png
Hope you find it useful, when for example uploading such images to
platforms like X, which does not compress .png images, as I have
tested!
PNG compression is lossless, so it should not matter if the PNG is
compressed, you should get back the same bytes that went in.

Now, if instead you mean "rescale" (reduce/increase size) or other
transformations (RGBI to RGB or RGB to indexed) then those
transformations may alter the content such that you do not get back
what you put in.
Stefan Claas
2024-12-31 12:44:36 UTC
Reply
Permalink
Post by Rich
Post by Stefan Claas
Hi all,
here is a Python3 implementation of my file2png program, available
here: https://github.com/706f6c6c7578/file2png
Hope you find it useful, when for example uploading such images to
platforms like X, which does not compress .png images, as I have
tested!
PNG compression is lossless, so it should not matter if the PNG is
compressed, you should get back the same bytes that went in.
Now, if instead you mean "rescale" (reduce/increase size) or other
transformations (RGBI to RGB or RGB to indexed) then those
transformations may alter the content such that you do not get back
what you put in.
I remember taht facebook/Meta did something with .png in the past and
it did not work, but it was not rescaling etc.
--
Happy New Year 2025
Stefan
Rich
2024-12-31 23:15:00 UTC
Reply
Permalink
Post by Stefan Claas
Post by Rich
Post by Stefan Claas
Hi all,
here is a Python3 implementation of my file2png program, available
here: https://github.com/706f6c6c7578/file2png
Hope you find it useful, when for example uploading such images to
platforms like X, which does not compress .png images, as I have
tested!
PNG compression is lossless, so it should not matter if the PNG is
compressed, you should get back the same bytes that went in.
Now, if instead you mean "rescale" (reduce/increase size) or other
transformations (RGBI to RGB or RGB to indexed) then those
transformations may alter the content such that you do not get back
what you put in.
I remember taht facebook/Meta did something with .png in the past and
it did not work, but it was not rescaling etc.
There's only one compression algorithm in the PNG standard, zlib, which
itself is lossless.

But there are a lot of "transformations" that could be done on a PNG
that would result in modification of the actual image bytes inside.
Given the potential cost savings to a company with the scale of
facebook/meta from even a few percentage of saved space on uploaded
PNG's from "optimizing" them, it would not be surprising to learn they
were doing something to them that changed the stored bytes.

Loading...