Image Super Sampling tool using the Tensorflow library to upscale image in browser - tensorflow

I am unable to generate a super-sampled image and would like some advice.
The HTML, CSS, and JS are below for your review. As you can see, the goal is to enable a webpage visitor to upload a low-resolution image and generate and auto-download an enhanced image. This is meant to be done in the browser without using a database. The image will be stored in the browser, and the user should have a seamless experience.
HTML
<!-- HTML form that allows the user to select and upload an image file -->
<form>
<label for="image">Select an image:</label>
<input type="file" id="image" name="image" accept="image/jpeg, image/png">
<button class="upload-button" onclick="processImage()">Super Sample</button>
</form>
<!-- Canvas element to display the enhanced image -->
<canvas id="canvas"></canvas>
CSS
/* Global styles */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans- serif;
margin: 0;
background-color: #f3f3f3;
}
/* Styles for the form and canvas elements */
form {
display: flex;
flex-direction: column;
align-items: center;
margin: 50px;
}
label {
color: #333;
font-size: 16px;
}
input[type="file"] {
margin: 10px;
}
button {
margin: 10px;
padding: 10px;
background-color: #333;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
canvas {
border: 1px solid #333;
margin: 10px;
display: block;
}
/* Center the canvas element */
form, canvas {
text-align: center;
}
JS
// Load the TensorFlow.js library
import * as tf from '#tensorflow/tfjs';
// Load the MobileNet model
const model = await tf.loadLayersModel('https://storage.googleapis.com/tfjs- models/tfjs/mobilenet_v1_1.0_224/model.json');
// JavaScript function to process the image and update the download link
async function processImage() {
// Get the selected file from the input element
var file = document.getElementById("image").files[0];
// Check if the file is an image
if (!file.type.match("image.*")) {
alert("Please select an image file");
return;
}
// Create an image element to display the selected image
var image = new Image();
image.src = URL.createObjectURL(file);
// Set the canvas dimensions to the dimensions of the image
var canvas = document.getElementById("canvas");
canvas.width = image.width;
canvas.height = image.height;
// Draw the image on the canvas
var ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0, image.width, image.height);
// Convert the canvas to a tensor
var tensor = tf.browser.fromPixels(canvas);
// Resize the tensor to the size expected by the MobileNet model
var resized

Related

iText7 / iText7.pdfhtml - generating accessible tagged PDF from HTML results in incorrect tab order

Here's an HTML snippet:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
body {
font-family: Calibri,Arial,Tahoma,Helvetica,sans-serif;
color: black;
font-size: 12pt;
width: 595pt;
}
h1 {
color: #553c74;
font-size: 18pt;
font-weight: bold;
}
h1.title {
display: inline;
font-size: 28pt;
font-weight: bold;
color: #553c74;
}
h2 {
color: #553c74;
font-size: 16pt;
font-weight: bold;
}
h3 {
color: #00759b;
font-size: 12pt;
font-weight: bold;
}
h3.requiredAction {
color: black;
font-weight: bold;
margin-top: 21px;
}
.headingLeft {
float: left;
}
.contentRight {
float: left;
margin-left: 10px;
margin-top: 17px;
}
.topSection {
margin-top: 22px;
}
.clearBoth {
clear: both;
}
.symbolstandardmet {
color: #009639;
font-family: webdings;
font-size: 18pt;
}
.standardmet {
color: #009639;
}
.standard {
font-size: 16pt;
font-weight: bold;
margin-top: 0;
}
.pageBreakBefore {
margin-top: 0px;
}
.premisesAddress {
font-size: 18pt;
color: #553c74;
line-height: 0px;
}
.pageBreakBefore {
page-break-before: always;
}
#contentWrapperBody {
padding-left: 8pt;
padding-right: 45pt;
}
h1 {
display: inline-block;
}
#page:first {
margin-top: 170pt;
}
</style>
<title>Report</title>
</head>
<body id="contentWrapperBody">
<h1>Name:</h1>
<span id="lblAddress" class="premisesAddress">Address Line 1, Address line 2, City, Postcode</span>
<div class="clearBoth"></div>
<h2 class="headingLeft">Reference:</h2>
<div class="contentRight topSection">123456789</div>
<div class="clearBoth"></div>
<h2 class="headingLeft">Type:</h2>
<div class="contentRight topSection">The type</div>
<div class="clearBoth"></div>
<h2 class="headingLeft">Date:</h2>
<div class="contentRight topSection">12/04/2019</div>
<div class="clearBoth"></div>
<h2>Context</h2>
<div>
<p>A paragraph of context info here.</p>
</div>
<h2>Overall outcome</h2>
<h3>
<span id="lblOverallStandardsMet" class="standardmet"><span class="symbolstandardmet">a</span>Standards met</span>
</h3>
<h3 class="headingLeft requiredAction">Required Action:</h3>
<div class="contentRight topSection"><span id="lblRequiredAction">None</span></div>
<div class="clearBoth"></div>
<p>Follow this link to find out what the possible outcomes mean</p>
</body>
</html>
Here's the code:
public static class DocConverter
{
private const string fontWebdings = "~/content/fonts/webdings.ttf";
private const string fontCalibri = "~/content/fonts/calibrib.ttf";
[Flags]
public enum DocOptions
{
None = 0,
DisplayTitle = 1,
AddHeaderPageOne = 2,
AddHeaderAllPages = 4,
AddLineBottomEachPage = 8
}
public static byte[] ConvertToPdfWithTags(string html, string title, string docOptions)
{
DocOptions documentOptions = DocOptions.None;
if (!string.IsNullOrEmpty(docOptions))
{
int options;
if (int.TryParse(docOptions, out options))
documentOptions = (DocOptions)options;
}
PdfFontFactory.RegisterDirectory(System.Web.Hosting.HostingEnvironment.MapPath("~/content/fonts/"));
ConverterProperties props = new ConverterProperties();
FontProvider fp = new FontProvider();
fp.AddDirectory(System.Web.Hosting.HostingEnvironment.MapPath("~/content/fonts/"));
props.SetFontProvider(fp);
props.SetTagWorkerFactory(new DefaultTagWorkerFactory());
using (var workStream = new MemoryStream())
{
using (var pdfWriter = new PdfWriter(workStream, new WriterProperties().AddUAXmpMetadata().SetPdfVersion
(PdfVersion.PDF_2_0).SetFullCompressionMode(true)))
{
PdfDocument pdfDoc = new PdfDocument(pdfWriter);
pdfDoc.GetCatalog().SetLang(new PdfString("en-GB"));
pdfDoc.GetCatalog().SetViewerPreferences(new PdfViewerPreferences().SetDisplayDocTitle(true));
//This event handler used for adding background images. Also where I've tried setting the tab order on pdfPage
//if (documentOptions > 0)
// pdfDoc.AddEventHandler(PdfDocumentEvent.END_PAGE, new PublicReportHeaderFooter(documentOptions, title));
//Set meta tags
var pdfMetaData = pdfDoc.GetDocumentInfo();
pdfMetaData.AddCreationDate();
pdfMetaData.GetProducer();
pdfMetaData.SetCreator("iText Software");
//Set the document to be tagged
pdfDoc.SetTagged();
using (var document = HtmlConverter.ConvertToDocument(html, pdfDoc, props))
{
//Can do more with document here if necessary
}
//Returns the written-to MemoryStream containing the PDF.
return workStream.ToArray();
}
}
}
}
If I open up the resulting PDF in Acrobat Pro and do an accessibility report and check the reading order, it jumps from the name on the first line, to the context much further down, rather than being in top-bottom, left-right order :
It appears to be due to the "float: left" style on some of the elements, but I'm not sure how to get around it. I've tried playing with page.Put(PdfName.Tag, PdfName.S) and page.SetTabOrder(PdfName.S), putting in different parameters (C or R, for example), but these appear to make no difference. I'm using C# iText7 version 7.1.9 and iText7.pdfhtml version 2.1.6. Any help appreciated.
The more I look at the documentation, the more I think this is just a bug. The reading order in the accessible PDF should match the structural order of the HTML document by default, but the float: left styles seem to throw things out. I can't find a way to raise a bug in GitHub for this project, but I've found a workaround for anyone else with the issue, which is simply to add "float: left" to all other elements as necessary, along with
<div style="clear: both;"></div>
between the elements that don't actually need the float. This way the accessible tagged order comes out correctly. However, this did throw up another problem which was that the elements with "float: left" no longer appeared on a new page where "page-break-before: always" was also set. I had to add another empty div element before these elements with the page-break-before style set to fix this. Hopefully the iText people will see this and either fix these issues, if they're bugs, or respond with a better answer if I've just got things wrong.

Adding scroll down button to Shopify custom theme

I am customizing shopify motion theme. I added a scroll down svg on bottom of the slider. But having problem with scrolling down to the next section
I have added the scroll down button with that code;
div.hero__image-wrapper:after {
content: url({{ "icon-scroll-down.svg" | asset_url }}) ;
position: absolute;
display: block;
z-index: 34560;
bottom: 20px;
left: 48%;
font-size: 2em;
border-radius: 1em;
font-weight: bold;
border: 3px solid gray;
padding: 0.1em 0.1em 0;
animation-name: color_change;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#keyframes color_change {
0% { color: gray; bottom:20px;}
10% { color: black; bottom:10px;}
20% { color: gray; bottom:20px;}
100%{ color: gray; bottom:20px;}
}
But currently it's only an icon. I need to make it scroll to down
I would do it with JS instead. Let's assume your button is an actual element instead of pseudo ::after:
<div class="scroll-down-button"></div>
.scroll-down-button {
// whatever style you prefer
}
Then the JS code would look like this:
(function() {
// Get the button element
var button = document.querySelector('.scroll-down-button');
// Get current section
var currentSection = button.closest('.shopify-section');
// Get next section (the very next element after current section container)
var nextSection = currentSection.nextSibling();
// Get the coordinates of the next section
var nextSectionCoordinates = nextSection.getBoundingClientRect();
// Get the top Y axis coordinates of next section
var nextSectionTop = nextSectionCoordinates.top;
// Scroll to the top of next section (0 means no scroll on X axis)
window.scrollTo(0, nextSectionTop);
})();
The above is not tested, so let me know if it doesn't work or you can console.log any values. You should get the idea though!

Stage not resizing on orientation change

Am creating an image editor library with the support of KinetiJS.
In my html,
<div id="editorarea" class="fill">
<div id="imageContainerDiv" class="imageContainerDiv" >
<div>....</div>
<div>....</div>
<div id='rotateouterDiv' class='rotateouterDiv' >
<textarea placeholder='Enter You Text here' id='inputField' name='graffiti' class='textContainerMob'></textarea>
</div>
<div id='imageContainer'></div>
</div>
</div>
Then creating a stage
_kineticStage = new editor._Stage({
container : 'imageContainer',
width : $('#editorarea').width(),
height : $('#editorarea').height()
});
Kinetic.Util.extend(editor._Stage, Kinetic.Stage);
And adding an image,
_kineticImage = new editor._Image({
x : 0,
image : img,
y : 0,
draggable : true,
});
layer.add(_kineticImage);
The CSS applied is,
#editorarea {
width: 100%;
height: 80%;
margin-top: .1%;
min-height: 70%%;
display: block;
border-width: 2px;
border-style: solid;
}
.fill {
min-height: 85%;
height: 90%;
}
.imageContainerDiv {
width: 100%;
height: 100%;
z-index: 0;
left: 0;
right: 0;
background-color: #FFF;
display: block;
background-image: url(../images/back_pattern.png);
background-repeat: repeat;
overflow: hidden;
}
The textarea should be on the top of the image. In this case, I placed that div containing the textarea using the #media queries, for supporting different screen size and orientation.
The issue occurs when following the steps: load the page in portrait, then change the device orientation to landscape. Then the position of textarea is not correct. This is because the kinetic stage is not properly resizing on orientation change (only the area with image).
Can anyone help me to resize it properly? This should work in touch devices.
Thanks...

Google Maps API simple Debugging

I want to use the google maps API to:
-search for an address on a map
-place a marker on a map and drag it
Combining some pieces of code i came up with this (apparently it is not working). Can somebody pleasy debug me?:D
Thanks!
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map-canvas {
height: 100%;
margin: 50px;
padding: 0px
}
.controls {
margin-top: 16px;
border: 1px solid transparent;
border-radius: 2px 0 0 2px;
box-sizing: border-box;
-moz-box-sizing: border-box;
height: 32px;
outline: none;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
#pac-input {
background-color: #fff;
padding: 0 11px 0 13px;
width: 400px;
font-family: Roboto;
font-size: 15px;
font-weight: 300;
text-overflow: ellipsis;
}
#pac-input:focus {
border-color: #4d90fe;
margin-left: -1px;
padding-left: 14px; /* Regular padding-left + 1. */
width: 401px;
}
.pac-container {
font-family: Roboto;
}
#type-selector {
color: #fff;
background-color: #4d90fe;
padding: 5px 11px 0px 11px;
}
#type-selector label {
font-family: Roboto;
font-size: 13px;
font-weight: 300;
}
}
</style>
<title>Places search box</title>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places"></script>
<script>
// This example adds a search box to a map, using the Google Place Autocomplete
// feature. People can enter geographical searches. The search box will return a
// pick list containing a mix of places and predicted search terms.
function initialize() {
var markers = [];
var map = new google.maps.Map(document.getElementById('map-canvas'), {
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var defaultBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(-33.8902, 151.1759),
new google.maps.LatLng(-33.8474, 151.2631));
map.fitBounds(defaultBounds);
// Create the search box and link it to the UI element.
var input = /** #type {HTMLInputElement} */(
document.getElementById('pac-input'));
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
var searchBox = new google.maps.places.SearchBox(
/** #type {HTMLInputElement} */(input));
// [START region_getplaces]
// Listen for the event fired when the user selects an item from the
// pick list. Retrieve the matching places for that item.
google.maps.event.addListener(searchBox, 'places_changed', function() {
var places = searchBox.getPlaces();
if (places.length == 0) {
return;
}
for (var i = 0, marker; marker = markers[i]; i++) {
marker.setMap(null);
}
// For each place, get the icon, place name, and location.
markers = [];
var bounds = new google.maps.LatLngBounds();
for (var i = 0, place; place = places[i]; i++) {
var image = {
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(25, 25)
};
// Create a marker for each place.
var marker = new google.maps.Marker({
map: map,
icon: image,
title: place.name,
position: place.geometry.location
});
markers.push(marker);
bounds.extend(place.geometry.location);
}
map.fitBounds(bounds);
});
// [END region_getplaces]
// Bias the SearchBox results towards places that are within the bounds of the
// current map's viewport.
google.maps.event.addListener(map, 'bounds_changed', function() {
var bounds = map.getBounds();
searchBox.setBounds(bounds);
});
}
function addMyMarker()
{ //function that will add markers on button click
var marker = new google.maps.Marker({
position:mapCenter,
map: map,
draggable:true,
animation: google.maps.Animation.DROP,
title:"This a new marker!",
icon: "http://maps.google.com/mapfiles/ms/micons/blue.png"
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<style>
#target {
width: 345px;
}
</style>
<script type="text/javascript">
function addMyMarker()
{ //function that will add markers on button click
var marker = new google.maps.Marker({
position:mapCenter,
map: map,
draggable:true,
animation: google.maps.Animation.DROP,
title:"This a new marker!",
icon: "http://maps.google.com/mapfiles/ms/micons/blue.png"
});
}
</script>
</head>
<body>
<button id="drop" onClick="addMyMarker()">Drop Markers</button>
<input id="pac-input" class="controls" type="text" placeholder="Search Box">
<div id="map-canvas"></div>
</body>
</html>
First, make the map variable global, so you can access it from any function. Then make sure that you define the mapCenter (globally), like this:
new google.maps.LatLng(-33.8902, 151.1759)
Then make sure that you have only one addMyMarker function (just remove the second one).

Populate a input[type=file] with drag and drop without ajax [duplicate]

I have a web site with a regular <input type="file"> file upload, POSTing the data to the backend when the form is submitted.
I would like to progressively enhance the form so that you can drop a file from outside the browser anywhere in the viewport (not just on the file input field, as built into some browsers) to upload it.
Whether or not the form autosubmits isn't important. So if the drag-and-drop only selects the file in the file field, without starting an upload, that's fine. I don't need support for multiple files. I don't need to show upload progress, thumbnails or anything fancy.
I know there are JS libs that support drag-and-drop uploads, but they all seem to upload via AJAX. I could do that, but then I would need to modify the backend and frontend to handle upload errors, redirect and show the right messages on success and so on.
I want a progressive enhancement that doesn't require any backend changes. It should happen synchronously using the form in the page. JS is fine, as long as the upload happens "in the foreground". Synchronous AJAX would not work, of course.
Although not really "synchronous" (JavaScript execution won't actually halt), you can set the files selected by <input type="file"> programatically. In fact, such elements and dragging share their file backend implementation (File and FileList instances), so it's really straight-forward. What's more, due to both frontends using FileLists, dragging multiple files work just as seamlessly.
This works in Chrome (using jQuery): http://jsfiddle.net/qMmPr/.
$(document).on("dragover drop", function(e) {
e.preventDefault(); // allow dropping and don't navigate to file on drop
}).on("drop", function(e) {
$("input[type='file']")
.prop("files", e.originalEvent.dataTransfer.files) // put files into element
.closest("form")
.submit(); // autosubmit as well
});
Thanks to #pimvdb comment, I came up with a pretty elegant solution.
Since drag and dropping on the <input type="file" /> works, why not making it full-screen on dragstart to make sure the user can't miss it? Anyway he is dragging so his intentions are clear at this moment.
Here's a demo: https://jsfiddle.net/08wbo4um
NB: unfortunately this doesn't seem to work in an iframe, but it does work on an actual page. You can still apprehend the behavior.
Here's the snippet:
$('input[type="file"]').on('change', function(e){
var fileName = e.target.files[0].name;
if (fileName) {
$(e.target).parent().attr('data-message', fileName);
}
});
$(document).on('drag dragstart dragend dragover dragenter dragleave drop', function(e) {
if ($('input[type="file"]').length) {
if (['dragover', 'dragenter'].indexOf(e.type) > -1) {
if (window.dragTimeout)
clearTimeout(window.dragTimeout);
$('body').addClass('dragged');
} else if (['dragleave', 'drop'].indexOf(e.type) > -1) {
// Without the timeout, some dragleave events are triggered
// when the :after appears, making it blink...
window.dragTimeout = setTimeout(function() {
$('body').removeClass('dragged');
}, 100);
}
}
});
h3, p {
text-align: center;
}
.form-group {
margin: 30px;
}
.file-upload .form-control {
height: 150px;
outline: 1px dashed #ccc;
outline-offset: -15px;
background-color: #eee;
}
.file-upload .form-control:before {
content: "\f093";
font: normal normal normal 14px/1 FontAwesome;
font-size: 3em;
left: 0;
right: 0;
display: block;
margin: 20px auto;
text-align: center;
}
.file-upload .form-control:after {
content: attr(data-message);
left: 0;
right: 0;
bottom: 0;
text-align: center;
display: block;
}
.file-upload .form-control input[type="file"] {
cursor: pointer;
opacity: 0;
width: 100%;
height: 100%;
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
}
body.dragged .file-upload .form-control input[type="file"] {
/* Make sure it is full screen, whatever the position absolute container */
position: fixed;
top: -50vh;
bottom: -50vh;
left: -50vw;
right: -50vw;
height: 200vh;
width: 200vw;
z-index: 10002;
}
body:after {
content: 'You can drop the file. :-)';
font-size: 2em;
text-align: center;
line-height: 100vh;
position: absolute;
top: 10px;
bottom: 10px;
left: 10px;
right: 10px;
background-color: #eee;
z-index: 10000;
border-radius: 4px;
border: thin solid #ccc;
visibility: hidden;
opacity: 0;
transition: visibility 0s, opacity 0.5s ease;
}
body.dragged:after {
opacity: 1;
visibility: visible;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<h3>Drag N Drop file upload without AJAX Demo</h3>
<p>Try drag and dropping a file. :-)</p>
<div class="form-group file-upload" required="required">
<label class="cols-sm-2 control-label" for="document_file">File Upload</label><br>
<div class="cols-sm-10">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-file" aria-hidden="true"></i></span>
<div class="form-control" data-message="Click to select file or drag n drop it here">
<input required="required" title="Click to select file or drag n drop it here" type="file" name="document[file]" id="document_file">
</div>
</div>
</div>
</div>
It can be done by turning autoUpload to false, collecting the files in an array, then on form submit do a single ajax call with all the files together with the form data, as described here.