package ONO::FW::Edu::Apps::Modules::EightBit;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2022-2026 Jos Kirps and The Joopita Project [ASBL]
# Copyright (C) 2011-2022 Jos Kirps and Joopita Research ASBL
# Copyright (C) 2006-2011 Jos Kirps and The Joopita Project
# Copyright (C) 2001-2006 Jos Kirps and The WobbleWolf Project
#
# This file, as well as many other parts of the ONO Software Project or
# related elements, are FREE SOFTWARE available under the ARTISTIC LICENSE 2.0.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# For the full license, see /ono/osr/license/LICENSE.txt, or write to
# jos_AT_kirps_DOT_com or contact_AT_joopita_DOT_com.
#
################################################################################
# END OF COPYRIGHT / LICENSE, HERE COMES THE CODE ... #
################################################################################
#: This module is a front end application module wrapper that has been
#: created for the Morzino Project (morzino.com) and that has been released
#: as Open Source software.
#:
#: Note that this is NOT a self-contained application, it is only a wrapper
#: that makes heavy use of the ONO Perl Framework application engine.
use strict;
use ONO::IO;
use ONO::DB;
use ONO::Lib::Basic;
use Encode;
use ONO::Render;
use ONO::ToolBox::Auth;
use ONO::ToolBox::Upload;
use ONO::Lib::Lang::LangKitEdu;
use ONO::FW::User::Init;
use ONO::Lib::DateTime::ToolBox;
use ONO::Lib::Image::Drawing;
use ONO::Lib::Web::Upload;
use ONO::Lib::Code::RandomID;
use ONO::FW::Apps::Core;
use ONO::FW::Apps::Core::Graphics;
use ONO::FW::Edu::Apps::Modules::Drawing;
use ONO::FW::Edu::Apps::ToolBox;
use ONO::Lib::UI::ColorPicker;
use ONO::Lib::UI::Range;
use ONO::Lib::Parser;
sub play {
my (
$self,
$option,
$vars_ref,
$HTTP,
$BASE,
) = @_;
################################################################
# INIT - BEGIN
################################################################
my (
$db,
$community,
$action_url,
$form,
$format,
$canvas,
$pdfkey,
$sec,$min,$hour,
$mday,$mon,$year,
$wday,$yday,$timestamp,
$lang,
$BLK_ref,
$vars_ref,
) = ONO::FW::Apps::Core->init($vars_ref);
my %vars = %$vars_ref;
my %BLK = %$BLK_ref;
my ($HEAD,$WEB);
my (
$vpath,
$lang,$domain,$community,
$sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$timestamp,
$script_url,$action_url,$form
) = ONO::FW::User::Init->getvar(\%vars);
ONO::FW::Apps::Core->now("","eightbit",$vars{'app_lang'});
my $action_url = qq~$ENV{'SCRIPT_NAME'}?app_lang=$vars{'app_lang'}&~;
my @txt = (
"You need to be logged in if you'd like to select or upload custom images.",
"Select a file stored on the platform.",
"Upload a file from your computer or device.",
"Pixelation",
);
if ($vars{'app_lang'} eq "de") {
@txt = (
"Du musst angemeldet sein, wenn du eigene Bilder auswählen oder hochladen möchtest.",
"Wähle ein auf der Plattform gespeichertes Bild aus.",
"Lade eine Datei von deinem Computer oder Gerät hoch.",
"Pixelierung",
);
}
if ($vars{'app_lang'} eq "lu") {
@txt = (
"Du muss ageloggt sinn wanns de eege Biller auswielen oder eropluede wëlls.",
"Wiel e Bild, dat op der Plattform gespäichert ass.",
"Lued eng Datei vun dengem Computer oder Apparat erop.",
"Pixelatioun",
);
}
if ($vars{'app_lang'} eq "fr") {
@txt = (
"Vous devez être connecté si vous souhaitez sélectionner ou télécharger des images personnalisées.",
"Sélectionnez un fichier stocké sur la plateforme.",
"Importez un fichier depuis votre ordinateur ou appareil.",
"Pixelation",
);
}
###################################################################
# DRAW
###################################################################
my $CSSJS = ONO::Render->cssjs($BASE);
# $CSSJS .= ONO::Lib::Image::Drawing->cssjs($BASE);
my $UPLOAD_SCRIPTS = ONO::Lib::Web::Upload->scripts($vars{'app_lang'});
if ($BASE) {
$UPLOAD_SCRIPTS =~ s~src="/ono/osr/~src="$BASE/ono/osr/~g;
$UPLOAD_SCRIPTS =~ s~href="/ono/osr/~href="$BASE/ono/osr/~g;
}
$CSSJS .= $UPLOAD_SCRIPTS;
if ($vars{'username'} && $vars{'ono_lib_image_drawing_target_folder'} && $vars{'ono_lib_image_drawing_data'} =~ s~^data:image/png;base64,~~) {
my $FILE;
if ($vars{'ono_lib_image_drawing_target_folder'} eq "user_documents_images") {
$FILE = "media/users/".ONO::IO->deepdir($vars{'username'})."/$vars{'username'}/documents/images";
}
if ($vars{'ono_lib_image_drawing_target_folder'} =~ m~^virclass_(.*?)_class$~) {
my $virclass = $1;
$virclass =~ s~[^0-9]~~gi;
foreach my $line (ONO::DB->select($db,"${community}_school_virclass_relationships","username = '$vars{'username'}' AND virclass = '$virclass'")) {
my @col = ONO::DB->readcols($line);
$FILE = "media/virclass/$virclass/class/$vars{'username'}/documents/images";
}
}
if ($FILE) {
$vars{'ono_lib_image_drawing_save_success'} = ONO::Lib::Image::Drawing->save("$FILE/$vars{'ono_lib_image_drawing_filename'}.png",$vars{'ono_lib_image_drawing_data'});
}
}
my @txts = ONO::Lib::Image::Drawing->txts($lang);
my $SUCCESS;
if ($vars{'ono_lib_image_drawing_save_success'}) {
$SUCCESS = ONO::Lib::Image::Drawing->success($BLK{'Done'},$txts[3],$BLK{'ok'});
}
my $DIRS = ONO::FW::Edu::Apps::Modules::Drawing->get_dirs($db,$community,$vars{'username'});
my $SAVE = ONO::Lib::Image::Drawing->savebox(\@txts,$BLK_ref,$vars_ref,"",$DIRS,"pixel_image");
my $SAVE2;
my $SAVEBUTTON = ONO::Lib::Image::Drawing->savebutton("$BLK{'save'} / $BLK{'download'}","button_green");
my $SAVEBOXES = ONO::Lib::Image::Drawing->saveboxes($SAVE,$SAVE2,$lang,$BLK_ref,$BASE);
my $SAVESCRIPT = ONO::Lib::Image::Drawing->savescript_generic();
my $RANGE = ONO::Lib::UI::Range->range("pixelation",8,1,32,0.1,$txt[3]);
my $DEFAULT_IMG = "$BASE/ono/osr/images/demo/switzerland/001.jpg";
my $SELECT_UPLOAD = qq~<div class="lightred">$txt[0]</div>
<div class="inline mt10">
<a href="javascript:void(0);" onclick="onojs_hide('eightbit_selupload_box');onojs_trans('eightbit_selupload_but',100);" class="button_green">$BLK{'ok'}</a>
</div>
~;
my $SELBUTTON = qq~<div class="trans30"><a href="javascript:void(0);" class="button_yellow mb10">$BLK{'upload'} / $BLK{'select'}</a></div>~;
my ($USER_IMAGE_DISPLAY,$UPLOAD_IMAGE_DISPLAY,$SELECT_IMAGE_DISPLAY,@UPLOADED_FILES,$SELECT_FILES,$WINDOW);
if ($vars{'username'}) {
$SELBUTTON = qq~<a href="javascript:void(0);" onclick="onojs_block('eightbit_selupload_box');onojs_trans('eightbit_selupload_but',50);"
class="button_yellow mb10">$BLK{'upload'} / $BLK{'select'}</a>
~;
my ($USER_IMG) = ONO::FW::User::Init->getuserimage($vars{'username'},"",256,"",$vars_ref);
if ($USER_IMG =~ m~images/users/~) {
$DEFAULT_IMG = "$BASE/$USER_IMG";
$USER_IMAGE_DISPLAY = qq~<div onclick="onojs_setvalue('urlInput','$DEFAULT_IMG');updateImage();">
<div style="width:100px;height:68px;background-image:url('$DEFAULT_IMG');background-size:cover;background-repeat:no-repeat;background-position:center"></div>
</div>
~;
}
if (ONO::IO->exists("tmp/var/app_eightbit/$vars{'username'}")) {
foreach my $file (sort ONO::IO->dir("tmp/var/app_eightbit/$vars{'username'}")) {
if ($file =~ /^$year$mon$mday\_(.*)\.(jpg|png|gif)/) {
$DEFAULT_IMG = "$BASE/tmp/var/app_eightbit/$vars{'username'}/$file";
@UPLOADED_FILES = (@UPLOADED_FILES,$DEFAULT_IMG);
$UPLOAD_IMAGE_DISPLAY = qq~<div onclick="onojs_setvalue('urlInput','$DEFAULT_IMG');updateImage();">
<div style="width:100px;height:68px;background-image:url('$DEFAULT_IMG');
background-size:cover;background-repeat:no-repeat;background-position:center"></div>
</div>
~;
}
}
}
my $ID = ONO::Lib::Code::RandomID->make(4);
my $http = ONO::IO->http;
my $UPLOAD_URL = "$http://$ENV{'SERVER_NAME'}$BASE/cgi-bin/local/perl/$community/ajax/rawdata.pl?mode=plupload&area=var&dir=app_eightbit/$vars{'username'}&";
$UPLOAD_URL .= "force_filename=$year$mon$mday-$hour$min$sec-$ID&media_ext_mode=tmp";
my $UPLOAD = ONO::Lib::Web::Upload->window(
qq~<form action="$ENV{'SCRIPT_NAME'}" method="post" enctype="multipart/form-data">
<input type="hidden" name="app_lang" value="$vars{'app_lang'}">
<table class="wide_table">
<tr>
<td></td>
<td style="padding-top:10px">
<input type="submit" name="$BLK{'upload'}" value="$BLK{'upload'}" class="button_green">
<a href="javascript:void(0);" onclick="onojs_hide('upload_box');"
class="button_red">$BLK{'cancel'}</a>
</td>
</tr>
</table>
</form>
~,
"$action_url",
$UPLOAD_URL,"",ONO::ToolBox::Upload->file_extensions("i"),"",640,460,90,\%vars,$lang,$BLK_ref,"I",
);
my ($SELECT,$counter);
foreach my $file (@UPLOADED_FILES) {
if ($counter < 12) {
$counter++;
$SELECT .= qq~<a href="javascript:void(0);" onclick="onojs_setvalue('urlInput','$file');updateImage();">
<div class="block64 fl ml5 mb5" style="height:48px;background-image:url('$file');background-size:cover"></div>
</a>
~;
}
}
$SELECT_UPLOAD = qq~<table class="default_table">
<tr>
<td class="bold">$txt[1]</td>
</tr>
<tr>
<td>$SELECT</td>
</tr>
<tr>
<td>
<div class="ml20 mt5">
<a href="javascript:void(0);" onclick="onojs_block('select_box');" class="button_green">$BLK{'more'} ($BLK{'my_files'}...)</a>
</div>
</td>
</tr>
<tr>
<td class="p5"></td>
</tr>
<tr>
<td class="bold">$txt[2]</td>
</tr>
<tr>
<td>
<div class="ml20 mt5">
<a href="javascript:void(0);" onclick="onojs_block('upload_box');" class="button_green">$BLK{'upload'}</a>
</div>
</td>
</tr>
</table>
<div id="upload_box" class="box_green abs hide" style="top:20px;left:20px">
<a href="javascript:void(0);" onclick="onojs_hide('upload_box');"><img class="close" src="$BASE/ono/osr/images/icons/crystal/32x32/ono/close.png" alt="close button"></a>
<h3>$BLK{'Upload'}</h3>
<div class="box_paper">
$UPLOAD
</div>
</div>
~;
my $USER_DIR = "media/users/".ONO::IO->deepdir($vars{'username'})."/$vars{'username'}/public";
my $counter;
foreach my $dir (ONO::IO->dir($USER_DIR,"","","","RX")) {
if ($counter < 100) {
foreach my $file (ONO::IO->dir("$USER_DIR/$dir")) {
if ($file !~ /^\./ && $file =~ /\.(jpg|png)/i && $counter < 100) {
$counter++;
my $show_file = ONO::Lib::Basic->shortstring("$dir/$file",36);
$SELECT_FILES .= qq~<option value="$dir/$file">$show_file</option>~;
}
}
}
}
if ($vars{'eightbit_select_user_file'} && ONO::IO->exists("$USER_DIR/$vars{'eightbit_select_user_file'}")) {
$DEFAULT_IMG = "$BASE/$USER_DIR/$vars{'eightbit_select_user_file'}";
$SELECT_IMAGE_DISPLAY = qq~<div onclick="onojs_setvalue('urlInput','$DEFAULT_IMG');updateImage();">
<div style="width:100px;height:68px;background-image:url('$DEFAULT_IMG');
background-size:cover;background-repeat:no-repeat;background-position:center"></div>
</div>
~;
}
$WINDOW = qq~<div id="eightbit_selupload_box" class="box_fabric abs hide w50" style="top:20px;left:40px;max-width:480px">
<a href="javascript:void(0);" onclick="onojs_hide('eightbit_selupload_box');onojs_trans('eightbit_selupload_but',100);">
<img class="close" src="$BASE/ono/osr/images/icons/crystal/32x32/ono/close.png" alt="close button">
</a>
<h3>$BLK{'Select'} / $BLK{'upload'}</h3>
<div class="box_paper">
$SELECT_UPLOAD
</div>
</div>
<div id="select_box" class="box_fabric w50 abs hide" style="top:40px;left:60px;max-width:480px">
<a href="javascript:void(0);" onclick="onojs_hide('select_box');">
<img class="close" src="$BASE/ono/osr/images/icons/crystal/32x32/ono/close.png" alt="close button">
</a>
<h3>$BLK{'Select'}</h3>
<div class="box_paper">
<form action="$ENV{'SCRIPT_NAME'}" method="post" enctype="multipart/form-data">
<input type="hidden" name="app_lang" value="$vars{'app_lang'}">
<table class="default_table">
<tr>
<td><img class="block32" src="$BASE/ono/osr/images/icons/crystal/32x32/filesystems/folder.png" alt=""></td>
<td>/$USER_DIR</td>
</tr>
<tr>
<td></td>
<td>
<div class="select"><select name="eightbit_select_user_file">
<option value="">$BLK{'select'}...</option>
<option value="">----</option>
$SELECT_FILES
</select></div>
$SELECT_FILES
</td>
</tr>
<tr>
<td></td>
<td>$BLK{'submit_select'}</td>
</tr>
</table>
</form>
</div>
</div>
~;
}
my $EIGHT = qq~<div class="rel bg_fabric" style="width:920px;height:480px">
<div class="abs" style="top:0px;left:0px;width:920px">
<div class="bg_paper bo abs" style="top:8px;left:10px"><canvas id="ono-drawing-canvas" style="display:block"></canvas></div>
$SAVEBOXES
$SUCCESS
</div>
<div class="abs" style="top:6px;left:700px;width:210px">
<table class="wide_table">
<tr>
<td class="w50">
<div onclick="onojs_setvalue('urlInput','$BASE/ono/osr/images/demo/switzerland/001.jpg');updateImage();">
<img class="block" src="$BASE/ono/osr/images/demo/switzerland/001.jpg" style="width:100%;height:auto" alt="">
</div>
</td>
<td class="w50">
<div onclick="onojs_setvalue('urlInput','$BASE/ono/osr/images/demo/switzerland/010.jpg');updateImage();">
<img class="block" src="$BASE/ono/osr/images/demo/switzerland/010.jpg" style="width:100%;height:auto" alt="">
</div>
</td>
</tr>
<tr>
<td class="w50">
<div onclick="onojs_setvalue('urlInput','$BASE/ono/osr/images/demo/denmark/001.jpg');updateImage();">
<img class="block" src="$BASE/ono/osr/images/demo/denmark/001.jpg" style="width:100%;height:auto" alt="">
</div>
</td>
<td class="w50">
<div onclick="onojs_setvalue('urlInput','$BASE/ono/osr/images/demo/denmark/004.jpg');updateImage();">
<img class="block" src="$BASE/ono/osr/images/demo/denmark/004.jpg" style="width:100%;height:auto" alt="">
</div>
</td>
</tr>
<tr>
<td>
<div onclick="onojs_setvalue('urlInput','$BASE/images/mz100/demo/001.jpg');updateImage();">
<img class="block" src="$BASE/images/mz100/demo/001.jpg" style="width:100%;height:auto" alt="">
</div>
</td>
<td>
$USER_IMAGE_DISPLAY
</td>
</tr>
<tr>
<td>
$UPLOAD_IMAGE_DISPLAY
</td>
<td>
$SELECT_IMAGE_DISPLAY
</td>
</tr>
</table>
<div class="hide">
<input type="url" class="form-control" id="urlInput">
<button id="submitImage">Upload</button>
</div>
<div class="mt20">
$RANGE
</div>
<div id="eightbit_selupload_but" class="mt20">
$SELBUTTON
$SAVEBUTTON
</div>
</div>
</div>
<input type="hidden" name="ono_lib_image_drawing_data" id="ono_lib_image_drawing_data_id" class="w95">
$SAVESCRIPT
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() { updateImage() });
document.getElementById('submitImage').addEventListener("click", updateImage);
document.getElementById('ono_range_pixelation_id').addEventListener("input", updateImage);
function updateImage() {
var val = document.getElementById('ono_range_pixelation_number').value;
var img = new Image();
var defaultImage = '$DEFAULT_IMG';
img.onload = function() {eightBit(document.getElementById('ono-drawing-canvas'),img,val)};
var url = document.getElementById("urlInput").value;
img.src = url || defaultImage;
}
/**
* 8bit
* <https://github.com/rogeriopvl>
* \@license MIT
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root.eightBit = factory();
}
} (this, function () {
/**
* Draws a pixelated version of an image in a given canvas
* \@param {object} canvas - a canvas object
* \@param {object} image - an image HTMLElement object
* \@param {number} scale - the scale factor: between 0 and 100
*/
var eightBit = function (canvas, image, scale) {
scale *= 0.01;
canvas.width = 680;
canvas.height = 460;
var scaledW = canvas.width * scale;
var scaledH = canvas.height * scale;
var ctx = canvas.getContext('2d');
ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;
var ratio = 1;
var ratio2 = 1;
var ratio3 = 1;
var ratio4 = 1;
if (image.width > 680) {
ratio = 1*image.width/680;
}
if (image.height > 460) {
ratio2 = 1*image.height/460;
}
if (ratio2 > ratio) {
ratio = ratio2;
}
if (image.width < 680 && image.height < 460) {
ratio3 = 1/image.width*680;
if (image.height*ratio3 > 460) {
ratio3 = 1/image.height*460;
}
}
ctx.drawImage(image, 0, 0, scaledW, scaledH);
ctx.drawImage(canvas, 0, 0, scaledW*ratio, scaledH*ratio, 0, 0, image.width*ratio3, image.height*ratio3);
};
return eightBit;
}));
</script>
~;
# my ($status,$WINDOW) = ONO::Lib::Parser->parse($WINDOW,$vars_ref);
$WINDOW =~ s~##OPEN##~\[~g;
$WINDOW =~ s~##CLOSE##~\]~g;
if (ONO::IO->devstation) {
# $EIGHT = qq~<div class="bo" style="width:920px;height:480px;border:1px solid #999999">$EIGHT</div>~;
}
print qq~Content-Type: text/html; charset=UTF-8\n\n
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="Generator" content="ONO App Engine">
$CSSJS
</head>
<body style="margin:0px;padding:0px">
<form id="ono_lib_image_drawing_form" method="post">
<input type="hidden" name="app_lang" value="$vars{'app_lang'}">
$EIGHT
</form>
$WINDOW
</body>
</html>
~;
}
###################################################################
#### THAT'S IT :-D
###################################################################
1;
__END__