// DaToPic - Data To Picture Transcoder
// =============================================
#light
open System
open System.Drawing
open System.Drawing.Imaging
open System.IO
open System.Text
open System.Threading
open System.Threading.Tasks
open System.Windows.Forms
// =============================================
// =============================================
let MaxFileNameSize = 0xff // 255
let FileVersion = 0x01 // 1
let DefaultExt = ".png"
let mutable DefaultImgRes = new Point(1600, 1600)
let HandShake = Color.FromArgb(0xff, 0x04, 0x09, 0x56)
type AlphaFlags =
static member ALL = 0xff // Read all
static member END = 0x00 // Read nothing
static member R = 0x11 // Read red
static member RG = 0x22 // Read red, green
// =============================================
(* Calculate the amount of bytes the can be stored in an image of the specified resolution *)
let CalcImgBytes x y mult =
(x * y) * mult
(* Calculate the amount of images that will be needed to store the data *)
let CalcNumOfImgsRequired (dataBytes:int) (imgBytes:int) =
let headerSize = 16 + MaxFileNameSize + 1
let amount = (float dataBytes) / (float imgBytes) |> ceil |> int
if ((float (dataBytes + (amount * headerSize))) / (float imgBytes) |> ceil |> int > amount) then amount + 1
else amount
(* Break an sequence into a sequence of array's *)
let Break n (s:seq<_>) = seq {
use e = s.GetEnumerator()
while e.MoveNext() do
let i = ref 0
yield [|
yield e.Current
i := !i + 1
while !i < n && e.MoveNext() do
yield e.Current
i := !i + 1 |]
}
(* Generates the header data that contains the needed info *)
let CreateHeader part totalParts fileVersion (fileName:string) =
let GetColor (b:byte[]) =
match b.Length with
| 0 -> Color.FromArgb(0x00, 0x00, 0x00, 0x00)
| 1 -> Color.FromArgb(int b.[0], 0x00, 0x00, 0x00)
| 2 -> Color.FromArgb(int b.[0], int b.[1], 0x00, 0x00)
| 3 -> Color.FromArgb(int b.[0], int b.[1], int b.[2], 0x00)
| _ -> Color.FromArgb(int b.[0], int b.[1], int b.[2], int b.[3])
if (fileName.Length > MaxFileNameSize) then
let msg = "File name length must be " + string MaxFileNameSize + " or smaller and bigger than 0"
let fn = "fileName"
raise(new ArgumentOutOfRangeException(fn, fileName.Length, msg))
else
[| HandShake; HandShake; HandShake |]
|> fun colors -> Array.append colors [|Color.FromArgb(MaxFileNameSize, part, totalParts, fileVersion)|]
|> fun colors -> (colors, Break 4 (Encoding.UTF8.GetBytes(fileName) |> Seq.ofArray))
|> fun (colors, bytes) -> (colors, [for item in bytes -> GetColor item])
|> fun (colors, colors') -> Array.append colors (Array.ofList colors')
(* Generates a 'usable' filename *)
let DoCorrectFileName (fileInfo:FileInfo) =
if (fileInfo.Name.Length > MaxFileNameSize) then
if (fileInfo.Name.Contains(".")) then
fileInfo.Extension.ToCharArray()
|> fun chars -> Array.append chars (fileInfo.Name.ToCharArray(0, MaxFileNameSize - (fileInfo.Extension.Length - 1)))
|> fun chars -> new String(chars)
else
fileInfo.Name.ToCharArray(0, MaxFileNameSize)
|> fun chars -> new String(chars)
else
fileInfo.Name.ToCharArray()
|> fun chars -> Array.append chars [|for i in 0 .. MaxFileNameSize - chars.Length - 1 -> '\x00'|]
|> fun chars -> new String(chars)
(* Creates ready to use data out of which we can generate our images *)
let CreateImages file targetDirectory =
let fileInfo = new FileInfo(file)
let fileName = DoCorrectFileName fileInfo
let numOfImgs = CalcNumOfImgsRequired (int fileInfo.Length) (CalcImgBytes DefaultImgRes.X DefaultImgRes.Y 3)
[for i in [ 0 .. numOfImgs - 1 ] -> async {
let header = CreateHeader (i+1) numOfImgs FileVersion fileName
use bmp = new Bitmap(DefaultImgRes.X, DefaultImgRes.Y, PixelFormat.Format32bppArgb)
use fs = fileInfo.OpenRead()
let GetX y = if (y = 0) then header.Length - 1 else 0
// Set file stream offset
fs.Position <- int64 ((((bmp.Width * bmp.Height) - header.Length) * 3) * i)
// Write header
for x in [ 0 .. header.Length - 1 ] do bmp.SetPixel(x, 0, header.[x])
// Bytes to pixels
for y in [ 0 .. bmp.Height - 1 ] do
for x in [ GetX y .. bmp.Width - 1 ] do
match ((fs.Length - 1L) - fs.Position) with
| 0L -> bmp.SetPixel(x, y, Color.FromArgb(AlphaFlags.END, 0x00, 0x00, 0x00))
| 1L -> bmp.SetPixel(x, y, Color.FromArgb(AlphaFlags.R, fs.ReadByte(), 0x00, 0x00))
| 2L -> bmp.SetPixel(x, y, Color.FromArgb(AlphaFlags.RG, fs.ReadByte(), fs.ReadByte(), 0x00))
| _ -> bmp.SetPixel(x, y, Color.FromArgb(AlphaFlags.ALL, fs.ReadByte(), fs.ReadByte(), fs.ReadByte()))
let savePath = (*targetDirectory + "\\" +*) DateTime.Now.Ticks.ToString("x") + DefaultExt
bmp.Save(savePath)
return savePath}]
|> Async.Parallel
|> Async.RunSynchronously
(* Creates ready to use data out of which we can generate our images *)
let CreateImages2 file targetDirectory =
let fileInfo = new FileInfo(file)
let fileName = DoCorrectFileName fileInfo
let numOfImgs = CalcNumOfImgsRequired (int fileInfo.Length) (CalcImgBytes DefaultImgRes.X DefaultImgRes.Y 3)
let headerLength = (CreateHeader 1 numOfImgs FileVersion fileName).Length
use fs = fileInfo.OpenRead()
let buffers = File.ReadAllBytes(file)
|> Seq.ofArray
|> Break (((DefaultImgRes.X * DefaultImgRes.Y) - headerLength) * 3)
|> Array.ofSeq
|> fun b -> [for i in 0 .. numOfImgs - 1 -> async{return (b.[i], CreateHeader (i + 1) numOfImgs FileVersion fileName)}]
|> Async.Parallel
|> Async.RunSynchronously
[for b, h in buffers -> async {
use bmp = new Bitmap(DefaultImgRes.X, DefaultImgRes.Y, PixelFormat.Format32bppArgb)
// implementation....
let savePath = (*targetDirectory + "\\" +*) DateTime.Now.Ticks.ToString("x") + DefaultExt
//bmp.Save(savePath)
//[ savePath ]
//|> (fun s -> List.append s savedFiles)
//|> loop (i + 1)
return savePath}]
|> Async.Parallel
|> Async.RunSynchronously
(* Creates ready to use data out of which we can generate our images *)
let CreateImages3 file targetDirectory =
let fileInfo = new FileInfo(file)
let fileName = DoCorrectFileName fileInfo
let numOfImgs = CalcNumOfImgsRequired (int fileInfo.Length) (CalcImgBytes DefaultImgRes.X DefaultImgRes.Y 3)
Parallel.For(0, numOfImgs - 1, (fun i ->
let header = CreateHeader (i+1) numOfImgs FileVersion fileName
use bmp = new Bitmap(DefaultImgRes.X, DefaultImgRes.Y, PixelFormat.Format32bppArgb)
use g = Graphics.FromImage(bmp)
use fs = fileInfo.OpenRead()
let GetX y = if (y = 0) then header.Length - 1 else 0
fs.Position <- int64 ((((bmp.Width * bmp.Height) - header.Length) * 3) * i)
// Write header
for x in [ 0 .. header.Length - 1 ] do bmp.SetPixel(x, 0, header.[x])
//printfn "Processing Image %i of %i" (i + 1) numOfImgs
for y in [ 0 .. DefaultImgRes.Y - 1 ] do
for x in [ 0 .. DefaultImgRes.X - 1 ] do
match ((fs.Length - 1L) - fs.Position) with
| 0L -> g.DrawRectangle(new Pen(Color.FromArgb(AlphaFlags.END, 0x00, 0x00, 0x00)), x, y, 1, 1)
| 1L -> g.DrawRectangle(new Pen(Color.FromArgb(AlphaFlags.R, fs.ReadByte(), 0x00, 0x00)), x, y, 1, 1)
| 2L -> g.DrawRectangle(new Pen(Color.FromArgb(AlphaFlags.RG, fs.ReadByte(), fs.ReadByte(), 0x00)), x, y, 1, 1)
| _ -> g.DrawRectangle(new Pen(Color.FromArgb(AlphaFlags.ALL, fs.ReadByte(), fs.ReadByte(), fs.ReadByte())), x, y, 1, 1)
let savePath = (*targetDirectory + @"\" +*) DateTime.Now.Ticks.ToString("x") + DefaultExt
bmp.Save(savePath)
))
let CreateImages file =
let fileInfo = new FileInfo(file)
let fileName = DoCorrectFileName fileInfo
let numOfImgs = CalcNumOfImgsRequired (int fileInfo.Length) (CalcImgBytes DefaultImgRes.X DefaultImgRes.Y 3)
[for i in [ 0 .. numOfImgs - 1 ] -> async {
let header = CreateHeader (i+1) numOfImgs FileVersion fileName
use fs = fileInfo.OpenRead()
use bmp = new Bitmap(DefaultImgRes.X, DefaultImgRes.Y, PixelFormat.Format32bppArgb)
let fpx = new FastPixel(bmp)
fs.Position <- int64 ((((DefaultImgRes.X * DefaultImgRes.Y) - header.Length) * 3) * i)
let length = ((DefaultImgRes.X * DefaultImgRes.Y) - header.Length) * 3
let count = ref 0
let buffer' = ref (Array.create (length + 1) 0x00uy)
let GetX y = if (y = 0) then header.Length - 1 else 0
let realLength = fs.Read(!buffer', 0, (!buffer').Length)
let buffer = (!buffer').[0 .. realLength - 1]
|> Seq.ofArray
|> Break 3
|> Array.ofSeq
// Set file stream offset and free temp buffer
buffer' := Array.empty<byte>
fpx.Lock()
// Write header
for x in [ 0 .. header.Length - 1 ] do fpx.SetPixel(x, 0, header.[x])
// Bytes to pixels
for y in [ 0 .. DefaultImgRes.Y - 1 ] do
for x in [ GetX y .. DefaultImgRes.X - 1 ] do
if (!count < buffer.Length) then
match (buffer.[!count].Length) with
| 3 -> fpx.SetBytes(x, y, byte AlphaFlags.ALL, buffer.[!count].[0], buffer.[!count].[1], buffer.[!count].[2])
| 2 -> fpx.SetBytes(x, y, byte AlphaFlags.RG, buffer.[!count].[0], buffer.[!count].[1], 0x00uy)
| 1 -> fpx.SetBytes(x, y, byte AlphaFlags.R, buffer.[!count].[0], 0x00uy, 0x00uy)
| _ -> fpx.SetBytes(x, y, byte AlphaFlags.END, 0x00uy, 0x00uy, 0x00uy)
count := !count + 1
else
fpx.SetBytes(x, y, byte AlphaFlags.END, 0x00uy, 0x00uy, 0x00uy)
fpx.Unlock(true)
return bmp}]
|> Async.Parallel
|> Async.RunSynchronously
<?
$im = new ImageContainer('file.txt','image');
$im->CreateSplit(1024*50);//50kb split.
/*
Note: this is filesized splits not the output image size, the output size will depend on compression, if its text you can expect a output size of roughly 20% of the file
else if its actually binary you can expect around 20% overhead.
*/
$im2 = new ImageContainerExtract('image0.png');
$im2->Extract_File('php://output');
error_reporting(E_ALL);
class ImageContainer {
private $file = '';
private $number_total = 0;
private $out = '';
function ImageContainer($file,$out){
$this->file = $file;
if(!file_exists($file)){
throw new Exception('File does not exist');
}
$this->out = $out;
}
function CreateSplit($split){
$fs = filesize($this->file);
if($split>$fs){
$split = $fs;
}
$this->number_total = ceil($fs/$split);//Total number of splits
$fp = fopen($this->file,'rb');
$i = 0;
while($fs>0){
$h = $w = floor(sqrt($split));
$h += ceil((sqrt($split)-$w)/$w);
$fs -= $h*$w;
$this->file2image($i,$fp,$this->out.$i.'.png',$w,$h,$split);
$i++;
}
fclose($fp);
}
function file2image($split_no,$fp,$image,$w,$h,$split){
$header = '[I]'.dechex($split_no).'.'.dechex($this->number_total).'.'.base64_encode(basename($this->file)).'|';
if(strlen($header)>$w*$h-$split){
$h++;
}
$gd = imagecreate($w,$h);
$color = array();
for($i=0;$i<=255;$i++){
$color[$i] = imagecolorallocate($gd,$i,$i,$i);
}
$wc = $hc =0;
for($hc=0;$hc<$h;$hc++){
for($wc=0;$wc<$w;$wc++){
$r = '';
if($header) {
$r=$header{0};
$header = substr($header,1);
}else $r = fread($fp,1);
imagesetpixel($gd,$wc,$hc,$color[ord($r)]);
}
}
imagepng($gd,$image,9,PNG_NO_FILTER);
imagedestroy($gd);
}
}
class ImageContainerExtract {
private $file = '';
private $efile = '';
private $data = array();
private $parts = 1;
function ImageContainerExtract($file){
$this->file = $file;
$this->data[0] = $this->decode_image_raw($file);
$part_number = $this->ReadHeader(0,true);
if($part_number!==0){
throw new Exception('Not first part.');
}
for($i=1;$i<$this->parts;$i++){
$filen = str_replace('0.png',$i.'.png',$file);
$this->data[$i] = $this->decode_image_raw($filen);
}
}
function ReadHeader($index,$strip=true){
$mark = substr($this->data[$index],0,3);
switch($mark){
case '[I]':
$endof = strpos($this->data[$index],'|');
$header = substr($this->data[$index],0,$endof);
if($strip){
$this->data[$index] = substr($this->data[$index],$endof+1);
}
list($part_number,$this->parts,$this->efile) = explode('.',$header);
$part_number = hexdec($part_number);
$this->parts = hexdec($this->parts);
$this->efile = base64_decode($this->efile);
return $part_number;
break;
}
}
function decode_image_raw($image){
$ret = '';
$gd = imagecreatefrompng($image);
list($w,$h) = getimagesize($image);
for($ih=0;$ih<$h;$ih++){
for($iw=0;$iw<$w;$iw++){
$rgb = imagecolorat($gd,$iw,$ih);
$ret .= chr($rgb);
}
}
imagedestroy($gd);
return $ret;
}
function Extract_File(){
$fp = fopen($this->efile,'wb');
foreach($this->data as $d){
fwrite($fp,$d);
}
fclose($fp);
}
}
?>
let l = (float (new FileInfo(f)).Length) / float 1024
let mb = (float (new FileInfo(f)).Length) / float 1024 / float 1024
let s = DateTime.Now
CreateImages f t
|> ignore
let e = DateTime.Now
printfn "Operation took %s seconds @ %s KB/s (%s MB)!" (e.Subtract(s).TotalSeconds.ToString("n")) ((l / e.Subtract(s).TotalSeconds).ToString("n")) (mb.ToString("n"))
<?
ini_set('memory_limit','2G');
set_time_limit(0);
file_put_contents('file.txt',str_repeat('-',1024*1024*50));
$start = time();
$im = new ImageContainer('file.txt','image');
$im->CreateSplit(1024*1024*1024);//1gb split.
/*
Note: this is filesized splits not the output image size, the output size will depend on compression, if its text you can expect a output size of roughly 20% of the file
else if its actually binary you can expect around 20% overhead.
*/
die('Time (sec): '.(time()-$start));
$im2 = new ImageContainerExtract('image0.png');
$im2->Extract_File('php://output');
error_reporting(E_ALL);
class ImageContainer {
private $file = '';
private $number_total = 0;
private $out = '';
function ImageContainer($file,$out){
$this->file = $file;
if(!file_exists($file)){
throw new Exception('File does not exist');
}
$this->out = $out;
}
function CreateSplit($split){
$fs = filesize($this->file);
if($split>$fs){
$split = $fs;
}
$this->number_total = ceil($fs/$split);//Total number of splits
$fp = fopen($this->file,'rb');
$i = 0;
while($fs>0){
$h = $w = floor(sqrt($split));
$h += ceil((sqrt($split)-$w)/$w);
$fs -= $h*$w;
$this->file2image($i,$fp,$this->out.$i.'.png',$w,$h,$split);
$i++;
}
fclose($fp);
}
function file2image($split_no,$fp,$image,$w,$h,$split){
$header = '[I]'.dechex($split_no).'.'.dechex($this->number_total).'.'.base64_encode(basename($this->file)).'|';
if(strlen($header)>$w*$h-$split){
$h++;
}
$gd = imagecreate($w,$h);
$color = array();
for($i=0;$i<=255;$i++){
$color[$i] = imagecolorallocate($gd,$i,$i,$i);
}
$wc = $hc =0;
for($hc=0;$hc<$h;$hc++){
for($wc=0;$wc<$w;$wc++){
$r = '';
if($header) {
$r=$header{0};
$header = substr($header,1);
}else $r = fread($fp,1);
imagesetpixel($gd,$wc,$hc,$color[ord($r)]);
}
}
imagepng($gd,$image,9,PNG_NO_FILTER);
imagedestroy($gd);
}
}
class ImageContainerExtract {
private $file = '';
private $efile = '';
private $data = array();
private $parts = 1;
function ImageContainerExtract($file){
$this->file = $file;
$this->data[0] = $this->decode_image_raw($file);
$part_number = $this->ReadHeader(0,true);
if($part_number!==0){
throw new Exception('Not first part.');
}
for($i=1;$i<$this->parts;$i++){
$filen = str_replace('0.png',$i.'.png',$file);
$this->data[$i] = $this->decode_image_raw($filen);
}
}
function ReadHeader($index,$strip=true){
$mark = substr($this->data[$index],0,3);
switch($mark){
case '[I]':
$endof = strpos($this->data[$index],'|');
$header = substr($this->data[$index],0,$endof);
if($strip){
$this->data[$index] = substr($this->data[$index],$endof+1);
}
list($part_number,$this->parts,$this->efile) = explode('.',$header);
$part_number = hexdec($part_number);
$this->parts = hexdec($this->parts);
$this->efile = base64_decode($this->efile);
return $part_number;
break;
}
}
function decode_image_raw($image){
$ret = '';
$gd = imagecreatefrompng($image);
list($w,$h) = getimagesize($image);
for($ih=0;$ih<$h;$ih++){
for($iw=0;$iw<$w;$iw++){
$rgb = imagecolorat($gd,$iw,$ih);
$ret .= chr($rgb);
}
}
imagedestroy($gd);
return $ret;
}
function Extract_File(){
$fp = fopen($this->efile,'wb');
foreach($this->data as $d){
fwrite($fp,$d);
}
fclose($fp);
}
}
?>
Reach 1000's of webmasters, hosts & affiliates. Banner & sponsored-thread slots available.
Contact us