Demo cordova application reverse image search

mohamad wael
6 min readJan 21, 2021

--

This application uses google reverse image search , in order to try and guess what an image represents . It simply returns the text found in the topstuff element , returned by google , when submitting an image , to google reverse image search .

To create this application , execute these commands :

$ cordova create what-is-this-img com.twiserandom.mobileapps.demo.whatIsThisImg "What is this img"$ cordova platform add ios
$ cordova platform add android
$ cordova plugin add cordova-plugin-camera
$ cordova plugin add cordova-plugin-file-transfer

Edit www/index.html to look like this :

<!DOCTYPE html><html>
<head >
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" >
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
<meta name="color-scheme" content="light dark">
<title>What is this img ?</title>
</head>
<body >
<div id="wisThisImgApp">
</div>
<script src="cordova.js"></script>
<script src="js/imgSearchBtn.js"></script>
<script src="js/imgSearchForm.js"></script>
<script src="js/searchResult.js"></script>
<script src="js/wisThisImgApp.js"></script>
<script src="js/googleImageSearch.js"></script>
<script src="js/index.js"></script>
<script>
window.addEventListener('load', wisThisImgApp );
</script>

</body>
</html>

Edit www/js/index.js , to look like this :

/*File : www/js/index.js .*/document.addEventListener('deviceready', onDeviceReady, false );let isDeviceReady = false;function onDeviceReady( ){
isDeviceReady = true ; }
function userSelectionMade( ){function cameraSuccess(imageURI ){
switch(searchPreferences.searchProvider ){
case searchOptions.searchProvider.googleImageSearch:
googleImageSearch(imageURI );
break; } }
function cameraFailure(errorMsg ){
togleIsSearchPerformed( );
toggleSearch_ResultMessage(errorMsg );}
if(isDeviceReady && !searchPreferences.isSearchPerformed ){
togleIsSearchPerformed( );
toggleSearch_ResultMessage( );
let pictureOptions = { } ;
if(searchPreferences.imageSource == searchOptions.imageSource.Gallery )
pictureOptions = {sourceType: Camera.PictureSourceType.PHOTOLIBRARY }
navigator
.camera
.getPicture(cameraSuccess ,
cameraFailure ,
pictureOptions ); } }

Add the following javascript files :

www/js/imgSearchBtn.js

/*File : www/js/imgSearchBtn.js .*/function imgSearchBtn(){
let style = `
#imgSearchBtn{
background-color: white;
color : black;
text-align: center;
font-size : 1.625rem;
margin-top : 0.25rem;
margin-bottom: 0.75rem;
border-radius: 20% 30% 5% 5%;
box-shadow: 0px 0px 0.25rem 0.25rem black;
text-shadow: -0.0625rem -0.0625rem 0.125rem black ; } `;


let html = `
<div
id="imgSearchBtn"
onclick="userSelectionMade( )" >
Search </div>`;
return {
html : html ,
style : style } }

www/js/imgSearchForm.js

/*File : www/js/imgSearchForm.js*/function imageSource(){let style = `
#imageSource{
display: flex;
flex-wrap: wrap;
border-bottom: 0.0625rem solid;
border-top: 0.0625rem dashed;
margin-bottom: 1rem;
padding: 0.375rem 0px 0.5rem;
justify-content: center; }
#imageSourceTitle{
padding-bottom: 0.25rem;
font-family: monospace;
font-size: 1.375rem;
text-align: center;
margin-bottom: 0.25rem;
width: 100%;
align-content: center; }
.imageSourceName{
margin-right: 0.375rem; }`;
let html =`
<div
id="imageSource" >
<p
id="imageSourceTitle">
Image Source </p>

<span
class="imageSourceName">
Camera </span>
<input
oninput="imageSourceSelected(this );"
style="margin-right: 20%;"
type="radio"
value="${searchOptions.imageSource.Camera}"
name="imageSource"
checked >
<span
class="imageSourceName" >
Gallery </span>
<input
oninput="imageSourceSelected(this );"
type="radio"
value="${searchOptions.imageSource.Gallery}"
name="imageSource">
</div> `;
let script = `function imageSourceSelected(inputElem ){
switch(inputElem.value ){
case searchOptions.imageSource.Gallery:
searchPreferences.imageSource = searchOptions.imageSource.Gallery;
break;
case searchOptions.imageSource.Camera:
searchPreferences.imageSource = searchOptions.imageSource.Camera;
break; } }`;
return{
html: html,
style: style ,
script: script } }
function searchProvider( ){
let style= `
#searchProviders{
display: flex;
flex-wrap: wrap;
border-bottom: 0.0625rem solid;
border-top: 0.0625rem dashed;
margin-bottom: 1rem;
padding: 0.5rem 0px 0.5rem;
justify-content: center }
#searchProvidersTitle{
padding-bottom: 0.375rem;
font-family: monospace;
font-size: 1.375rem;
text-align: center;
margin-bottom: 0.5rem;
width: 100%;
align-content: center; }
#searchProvidersOptions{
width: 100%;
margin: 0px 0.625rem;
color: black; }
#googleImageSearch{
background-color: white;
padding-top: 0.125rem;
padding-left: 0.1875rem;
padding-bottom: 0.25rem;
box-shadow: 0px 0px 0.25rem 0.25rem white; }
#bingImageSearch{
background-color: black;
color: white;
padding-top: 0.4375rem;
padding-bottom: 0.3125rem;
padding-left: 0.5rem;
border: 0.0625rem solid; }
#yandexImageSearch{
background-color: white;
padding-top: 0.3125rem;
padding-bottom: 0.3125rem;
padding-left: 1rem; }
#notYetImplemented{
background-color: black;
color: white;
border: 0.0625rem solid;
padding-top: 0.4375rem;
padding-bottom: 0.3125rem;
padding-left: 1.625rem; }`;
let html=`
<div
id = "searchProviders" >
<p
id = "searchProvidersTitle" >
Search Providers </p>

<div
id = "searchProvidersOptions" >
<p
id = "googleImageSearch"
data-option-value = "${searchOptions.searchProvider.googleImageSearch}" >
Google Image Search &#x2714; </p>
<p
id = "bingImageSearch"
data-option-value = "${searchOptions.searchProvider.bingImageSearch}" >
Bing Image Search </p>
<p
id = "yandexImageSearch"
data-option-value = "${searchOptions.searchProvider.yandexImageSearch}" >
Yandex Image Search </p>
<p
id="notYetImplemented"
data-option-value = "${searchOptions.searchProvider.notYetImplemented}" >
&#x1F556; Not Yet Implemented </p>
</div>
</div>`;
return{
style : style ,
html : html } }
function searchForm( ){
let html=`
<form
id="imgSearchForm"
onsubmit="return false;" >
</form>`;
return{
html : html ,
id: "imgSearchForm",
childrens :[
imageSource() ,
searchProvider()
] }}

www/js/searchResult.js

/*File : www/js/searchResult.js .*/function searchResult( ){
let componentGlobalName = 'searchResult' ;
let style=`
#searchResult{
text-align:center; }`;
let html=`
<div
id = "searchResult" >
</div>`;
let script=`
function toggleSearch_ResultMessage(result ){
result = result || "Performing search" ;
this.innerText = result ; }

toggleSearch_ResultMessage = toggleSearch_ResultMessage.bind(document.getElementById('${componentGlobalName}' ) );`;
return{
style : style ,
html : html ,
script : script }; }

www/js/googleImageSearch.js

function googleImageSearch(imageURI ){postImgGoogle(imageURI );function postImgError(fileTransferError ){
toggleSearch_ResultMessage(JSON.stringify(fileTransferError , null , 4 ) );
togleIsSearchPerformed( ); }

function postImgSuccess(fileUploadResult ){
let domParser = new DOMParser( );
let domDocument = domParser.parseFromString(fileUploadResult.response , 'text/html' );
let topSuggestion_Element = domDocument.getElementById("topstuff" );
toggleSearch_ResultMessage(topSuggestion_Element
.textContent
.trim( )
.split("\n" )
.pop( )
.trim( ) );
togleIsSearchPerformed( ); }function postImgGoogle(imageURI){
let googleImageUploadUrl = encodeURI("https://www.google.com/searchbyimage/upload" );
let options = new FileUploadOptions();
options.fileKey = "encoded_image";
options.fileName = "encoded_image";
var params = {
image_url : "" ,
image_content : "",
filename : "",
hl : "en" };
options.params = params;
let fileTransfer = new FileTransfer();
fileTransfer
.upload(
imageURI ,
googleImageUploadUrl ,
postImgSuccess,
postImgError,
options ); } }

Edit the file config.xml in the root of your app , to look like this :

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.twiserandom.mobileapps.demo.whatIsThisImg" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>What is this img</name>
<description>
A sample Apache Cordova application that responds to the deviceready event.
</description>
<author email="dev@cordova.apache.org" href="http://cordova.io">
Apache Cordova Team
</author>
<content src="index.html" />
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<platform name="android">
<allow-intent href="market:*" />
</platform>
<platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
</platform>
<!-- Android manifest permission internet -->
<config-file target="AndroidManifest.xml" parent="/manifest" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
</config-file>
<!-- IOS camera access , for cordova camera plugin -->
<edit-config target="NSCameraUsageDescription" file="*-Info.plist" mode="merge">
<string>need camera access to take pictures</string>
</edit-config>
<edit-config target="NSPhotoLibraryUsageDescription" file="*-Info.plist" mode="merge">
<string>need photo library access to get pictures from there</string>
</edit-config>
<edit-config target="NSLocationWhenInUseUsageDescription" file="*-Info.plist" mode="merge">
<string>need location access to find things nearby</string>
</edit-config>
<edit-config target="NSPhotoLibraryAddUsageDescription" file="*-Info.plist" mode="merge">
<string>need photo library access to save pictures there</string>
</edit-config>
<preference name="CameraUsesGeolocation" value="false" />
<!-- IOS camera access , for cordova camera plugin -->
</widget>

Now you can run the application , by using :

$ cordova emulate android 
$ cordova emulate ios

Originally published at https://twiserandom.com on January 21, 2021.

--

--

No responses yet