Is there a way in selenium through which we can verify that the image displayed is correct and is not chaged with same file name - image-processing

I am automating an application where I need to verify the cover Image of a book.
I encoutered a situation where the cover image changed and my script was not able to report this, since the the image source remained same.

You could check that the hash of the targeted image doesn't change. Here is an example to compute the hash of an image with Selenium / Python:
from selenium import webdriver
JS_GET_IMAGE_HASH = """
var hash = 0, ele = arguments[0], xhr = new XMLHttpRequest();
var src = ele.src || window.getComputedStyle(ele).backgroundImage;
xhr.open('GET', src.match(/https?:[^\"')]+/)[0], false);
xhr.send();
for (var i = 0, buffer = xhr.response; i < buffer.length; i++)
hash = (((hash << 5) - hash) + buffer.charCodeAt(i)) | 0;
return hash.toString(16).toUpperCase();
"""
driver = webdriver.Firefox()
driver.get("https://www.google.co.uk/")
# get the logo
ele_image = driver.find_element_by_id("hplogo")
# compute the hash of the logo
image_hash = driver.execute_script(JS_GET_IMAGE_HASH, ele_image)
# print the hash code
print image_hash
Or with Selenium / Java:
final String JS_GET_IMAGE_HASH =
"var hash = 0, ele = arguments[0], xhr = new XMLHttpRequest(); " +
"var src = ele.src || window.getComputedStyle(ele).backgroundImage; " +
"xhr.open('GET', src.match(/https?:[^\"')]+/)[0], false); " +
"xhr.send(); " +
"for (var i = 0, buffer = xhr.response; i < buffer.length; i++) " +
" hash = (((hash << 5) - hash) + buffer.charCodeAt(i)) | 0; " +
"return hash.toString(16).toUpperCase(); ";
WebDriver driver = new FirefoxDriver();
JavascriptExecutor js = (JavascriptExecutor)driver;
driver.get("https://www.google.co.uk/");
// get the logo
WebElement ele_image = driver.findElement(By.id("hplogo"));
// compute the hash of the logo
String image_hash = (String)js.executeScript(JS_GET_IMAGE_HASH, ele_image);
// print the hash code
System.out.println(image_hash);

You could solve this without any image processing by calculating file checksums.

Related

Extract URL from copied text in Google Sheets [duplicate]

I have a sheet where hyperlink is set in cell, but not through formula. When clicked on the cell, in "fx" bar it only shows the value.
I searched on web but everywhere, the info is to extract hyperlink by using getFormula().
But in my case there is no formula set at all.
I can see hyperlink as you can see in image, but it's not there in "formula/fx" bar.
How to get hyperlink of that cell using Apps Script or any formula?
When a cell has only one URL, you can retrieve the URL from the cell using the following simple script.
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var url = sheet.getRange("A2").getRichTextValue().getLinkUrl(); //removed empty parentheses after getRange in line 2
Source: https://gist.github.com/tanaikech/d39b4b5ccc5a1d50f5b8b75febd807a6
When Excel file including the cells with the hyperlinks is converted to Google Spreadsheet, such situation can be also seen. In my case, I retrieve the URLs using Sheets API. A sample script is as follows. I think that there might be several solutions. So please think of this as one of them.
When you use this script, please enable Sheets API at Advanced Google Services and API console. You can see about how to enable Sheets API at here.
Sample script:
var spreadsheetId = "### spreadsheetId ###";
var res = Sheets.Spreadsheets.get(spreadsheetId, {ranges: "Sheet1!A1:A10", fields: "sheets/data/rowData/values/hyperlink"});
var sheets = res.sheets;
for (var i = 0; i < sheets.length; i++) {
var data = sheets[i].data;
for (var j = 0; j < data.length; j++) {
var rowData = data[j].rowData;
for (var k = 0; k < rowData.length; k++) {
var values = rowData[k].values;
for (var l = 0; l < values.length; l++) {
Logger.log(values[l].hyperlink) // You can see the URL here.
}
}
}
}
Note:
Please set spreadsheetId.
Sheet1!A1:A10 is a sample. Please set the range for your situation.
In this case, each element of rowData is corresponding to the index of row. Each element of values is corresponding to the index of column.
References:
Method: spreadsheets.get
If this was not what you want, please tell me. I would like to modify it.
Hey all,
I hope this helps you save some dev time, as it was a rather slippery one to pin down...
This custom function will take all hyperlinks in a Google Sheets cell, and return them as text formatted based on the second parameter as either [JSON|HTML|NAMES_ONLY|URLS_ONLY].
Parameters:
cellRef : You must provide an A1 style cell reference to a cell.
Hint: To do this within a cell without hard-coding
a string reference, you can use the CELL function.
eg: "=linksToTEXT(CELL("address",C3))"
style : Defines the formatting of the output string.
Valid arguments are : [JSON|HTML|NAMES_ONLY|URLS_ONLY].
Sample Script
/**
* Custom Google Sheet Function to convert rich-text
* links into Readable links.
* Author: Isaac Dart ; 2022-01-25
*
* Params
* cellRef : You must provide an A1 style cell reference to a cell.
* Hint: To do this within a cell without hard-coding
* a string reference, you can use the CELL function.
* eg: "=linksToTEXT(CELL("address",C3))"
*
* style : Defines the formatting of the output string.
* Valid arguments are : [JSON|HTML|NAMES_ONLY|URLS_ONLY].
*
*/
function convertCellLinks(cellRef = "H2", style = "JSON") {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var cell = sheet.getRange(cellRef).getCell(1,1);
var runs = cell.getRichTextValue().getRuns();
var ret = "";
var lf = String.fromCharCode(10);
runs.map(r => {
var _url = r.getLinkUrl();
var _text = r.getText();
if (_url !== null && _text !== null) {
_url = _url.trim(); _text = _text.trim();
if (_url.length > 0 && _text.length > 0) {
switch(style.toUpperCase()) {
case "HTML": ret += '' + _text + '}' + lf; break;
case "TEXT": ret += _text + ' : "' + _url + '"' + lf; break;
case "NAMES_ONLY" : ret += _text + lf; break;
case "URLS_ONLY" : ret += _url + lf; break;
//JSON default : ...
default: ret += (ret.length>0?(','+ lf): '') +'{name : "' + _text + '", url : "' + _url + '"}' ; break;
}
ret += lf;
}
}
});
if (style.toUpperCase() == "JSON") ret = '[' + ret + ']';
//Logger.log(ret);
return ret;
}
Cheers,
Isaac
I tried solution 2:
var urls = sheet.getRange('A1:A10').getRichTextValues().map( r => r[0].getLinkUrl() ) ;
I got some links, but most of them yielded null.
I made a shorter version of solution 1, which yielded all the links.
const id = SpreadsheetApp.getActive().getId() ;
let res = Sheets.Spreadsheets.get(id,
{ranges: "Sheet1!A1:A10", fields: "sheets/data/rowData/values/hyperlink"});
var urls = res.sheets[0].data[0].rowData.map(r => r.values[0].hyperlink) ;

Is there a way to generate an SRT file (or similar) using Google Cloud Speech?

In order to generate subtitles for my videos, I converted them to audio files and used the Cloud Speech-to-Text. It works, but it only generates transcriptions, whereas what I need is a *.srt/*.vtt/similar file.
What I need is what YouTube does: to generate transcriptions and sync them with the video, like a subtitle format, ie.: transcriptions with the times when captions should appear.
Although I could upload them to YouTube and then download their auto-generated captions, it doesn't seem very correct.
Is there a way to generate an SRT file (or similar) using Google Cloud Speech?
There's no way really to do this directly from the Speech-to-Text API. What you could try to do is some post-processing on the speech recognition result.
For example, here's a request to the REST API using a model meant to transcribe video, with a public google-provided sample file:
curl -s -H "Content-Type: application/json" \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
https://speech.googleapis.com/v1p1beta1/speech:longrunningrecognize \
--data "{
'config': {
'encoding': 'LINEAR16',
'sampleRateHertz': 16000,
'languageCode': 'en-US',
'enableWordTimeOffsets': true,
'enableAutomaticPunctuation': true,
'model': 'video'
},
'audio': {
'uri':'gs://cloud-samples-tests/speech/Google_Gnome.wav'
}
}"
The above uses asynchronous recognition (speech:longrunningrecognize), which is more fitting for larger files. Enabling punctuation ('enableAutomaticPunctuation': true) in combination with the start and end times of words ('enableWordTimeOffsets': true) near the start and end of each sentence (which you'd also have to convert from nanos to timestamps) could allow you to provide a text file in the srt format. You would probably also have to include some rules about the maximum length of a sentence appearing on the screen at any given time.
The above should not be too difficult to implement, however, there's a strong possibility that you would still encounter timing/synchronization issues.
There is no way to do it using Google Cloud itself buy as suggested you may post-process the result.
In this file I have made a quick code that kind of does the job. You may want to adapt it to your needs:
function convertGSTTToSRT(string) {
var obj = JSON.parse(string);
var i = 1;
var result = ''
for (const line of obj.response.results) {
result += i++;
result += '\n'
var word = line.alternatives[0].words[0]
var time = convertSecondStringToRealtime(word.startTime);
result += formatTime(time) + ' --> '
var word = line.alternatives[0].words[line.alternatives[0].words.length - 1]
time = convertSecondStringToRealtime(word.endTime);
result += formatTime(time) + '\n'
result += line.alternatives[0].transcript + '\n\n'
}
return result;
}
function formatTime(time) {
return String(time.hours).padStart(2, '0')+ ':' + String(time.minutes).padStart(2, '0') + ':' +
String(time.seconds).padStart(2, '0') + ',000';
}
function convertSecondStringToRealtime(string) {
var seconds = string.substring(0, string.length - 1);
var hours = Math.floor(seconds / 3600);
var minutes = Math.floor(seconds % 3600 / 60);
seconds = Math.floor(seconds % 3600 % 60);
return {
hours, minutes, seconds
}
}
here is the code I used
import math
import json
import datetime
def to_hms(s):
m, s = divmod(s, 60)
h, m = divmod(m, 60)
return '{}:{:0>2}:{:0>2}'.format(h, m, s)
def srt_generation(filepath, filename):
filename = 'DL_BIRTHDAY'
with open('{}{}.json'.format(filepath, filename), 'r') as file:
data = file.read()
results = json.loads(data)['response']['annotationResults'][0]['speechTranscriptions']
processed_results = []
counter = 1
lines = []
wordlist = []
for transcription in results:
alternative = transcription['alternatives'][0]
if alternative.has_key('transcript'):
# print(counter)
# lines.append(counter)
tsc = alternative['transcript']
stime = alternative['words'][0]['startTime'].replace('s','').split('.')
etime = alternative['words'][-1]['endTime'].replace('s','').split('.')
if(len(stime) == 1):
stime.append('000')
if(len(etime) == 1):
etime.append('000')
lines.append('{}\n{},{} --> {},{}\n{}\n\n\n'.format(counter, to_hms(int(stime[0])), stime[1], to_hms(int(etime[0])), etime[1],tsc.encode('ascii', 'ignore')))
counter = counter+1
wordlist.extend(alternative['words'])
srtfile = open('{}{}.srt'.format(filepath, filename), 'wr')
srtfile.writelines(lines)
srtfile.close()
## Now generate 3 seconds duration chunks of those words.
lines = []
counter = 1
strtime =0
entime = 0
words = []
standardDuration = 3
srtcounter = 1
for word in wordlist:
stime = word['startTime'].replace('s','').split('.')
etime = word['endTime'].replace('s','').split('.')
if(len(stime) == 1):
stime.append('000 ')
if(len(etime) == 1):
etime.append('000')
if(counter == 1):
strtime = '{},{}'.format(stime[0], stime[1])
entime = '{},{}'.format(etime[0], etime[1])
words.append(word['word'])
else:
tempstmime = int(stime[0])
tempentime = int(etime[0])
stimearr = strtime.split(',')
etimearr = entime.split(',')
if(tempentime - int(strtime.split(',')[0]) > standardDuration ):
transcript = ' '.join(words)
lines.append('{}\n{},{} --> {},{}\n{}\n\n\n'.format(srtcounter, to_hms(int(stimearr[0])), stimearr[1], to_hms(int(etimearr[0])), etimearr[1],transcript.encode('ascii', 'ignore')))
srtcounter = srtcounter+1
words = []
strtime = '{},{}'.format(stime[0], stime[1])
entime = '{},{}'.format(etime[0], etime[1])
words.append(' ')
words.append(word['word'])
else:
words.append(' ')
words.append(word['word'])
entime = '{},{}'.format(etime[0], etime[1])
counter = counter +1
if(len(words) > 0):
tscp = ' '.join(words)
stimearr = strtime.split(',')
etimearr = entime.split(',')
lines.append('{}\n{},{} --> {},{}\n{}\n\n\n'.format(srtcounter, to_hms(int(stimearr[0])), stimearr[1], to_hms(int(etimearr[0])), etimearr[1],tscp.encode('ascii', 'ignore')))
srtfile = open('{}{}_3_Sec_Custom.srt'.format(filepath, filename), 'wr')
srtfile.writelines(lines)
srtfile.close()
Use this request parameter "enable_word_time_offsets: True" to get the time stamps for the word groups. Then create an srt programmatically.
If you require a *.vtt file, here is a snippet to convert the API response received from GCP speech-to-text client into a valid *.vtt. Some answers above are for *.srt so sharing this here.
const client = new speech.SpeechClient();
const [response] = await client.recognize(request);
createVTT(response);
function createVTT(response) {
const wordsArray = response.results[0].alternatives[0].words;
let VTT = '';
let buffer = [];
const phraseLength = 10;
let startPointer = '00:00:00';
let endPointer = '00:00:00';
VTT += 'WEBVTT\n\n';
wordsArray.forEach((wordItem) => {
const { startTime, endTime, word } = wordItem;
const start = startTime.seconds;
const end = endTime.seconds;
if (buffer.length === 0) {
// first word of the phrase
startPointer = secondsToFormat(start);
}
if (buffer.length < phraseLength) {
buffer.push(word);
}
if (buffer.length === phraseLength) {
endPointer = secondsToFormat(end);
const phrase = buffer.join(' ');
VTT += `${startPointer + ' --> ' + endPointer}\n`;
VTT += `${phrase}\n\n`;
buffer = [];
}
});
if (buffer.length) {
// handle the left over buffer items
const lastItem = wordsArray[wordsArray.length - 1];
const end = lastItem.endTime.seconds;
endPointer = secondsToFormat(end);
const phrase = buffer.join(' ');
VTT += `${startPointer + ' --> ' + endPointer}\n`;
VTT += `${phrase}\n\n`;
}
return VTT;
}
function secondsToFormat(seconds) {
const timeHours = Math.floor(seconds / 3600)
.toString()
.padStart(2, '0');
const timeMinutes = Math.floor(seconds / 60)
.toString()
.padStart(2, '0');
const timeSeconds = (seconds % 60).toString().padStart(2, '0');
const formattedTime = timeHours + ':' + timeMinutes + ':' + timeSeconds + '.000';
return formattedTime;
}
Note: enableWordTimeOffsets: true must be set but that's already answered above. This answer is for people who want .vtt copy.
Hope this was helpful to someone :)

Can not add a list in document object using iTextSharp

public ActionResult PartTimeFacultyCourseLoadReport()
{
var teacherStatistics = (from t in db.Teachers
join c in db.Courses
on t.Id equals c.TeacherId into cGroup
where t.Status == "Part Time"
orderby t.Designation descending
select new
{
TeacherInfo = t,
CourseInfo = from cg in cGroup
orderby cg.Code ascending
select cg
}).ToList();
List<TeacherStatistics> teacherStatisticses = new List<TeacherStatistics>();
int count = 0;
foreach (var teacherStatistic in teacherStatistics)
{
TeacherStatistics aTeacherStatistics = new TeacherStatistics();
aTeacherStatistics.Name = teacherStatistic.TeacherInfo.Name;
aTeacherStatistics.Designation = teacherStatistic.TeacherInfo.Designation;
aTeacherStatistics.NumberOfCourse = teacherStatistic.TeacherInfo.NumberOfCourse;
count = 0;
foreach (var courseInfo in teacherStatistic.CourseInfo)
{
if (count != 0)
{
aTeacherStatistics.Courses += ", ";
}
aTeacherStatistics.Courses += courseInfo.Code;
aTeacherStatistics.Courses += "(";
aTeacherStatistics.Courses += courseInfo.Section;
aTeacherStatistics.Courses += ")";
count++;
}
teacherStatisticses.Add(aTeacherStatistics);
}
var document = new Document(PageSize.A4, 50, 50, 25, 25);
var output = new MemoryStream();
var writer = PdfWriter.GetInstance(document, output);
document.Open();
var data = teacherStatisticses.ToList();
document.Add(data);
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment; filename=PartTimeFaculty.pdf");
Response.BinaryWrite(output.ToArray());
document.Close();
return View(teacherStatisticses);
}
I want to pass a list named 'teacherStatisticses' through document object for making a PDF. My code doesn't work. It showed me following Error -
Argument 1: cannot convert from 'System.Collections.Generic.List' to 'iTextSharp.text.IElement'
I assume that you are using some version of itextpdf for the PDF generation.
The error is in the line:
document.Add(data);
There is no way to add plain .NET objects into the PDF document. I can not predict the structure of PDF which you`d like to achieve, but the code mentioned above could be written as:
foreach(var teacher in teacherStatistics)
{
var paragraph = new Paragraph(teacher.ToString()); // instead of teacher.ToString() should be some code which translates teacherStatistics projection to the string representation
document.Add(paragraph);
}
//not tested
A lot of useful samples could be found at
http://developers.itextpdf.com/examples
Basic tutorial for the itextpdf:
http://developers.itextpdf.com/content/itext-7-jump-start-tutorial/chapter-1-introducing-basic-building-blocks

Printing in Openlayers 3 (pdf)

I have made a printing tools for openlayers 3 which prints in PDF format. Here is my code to print in pdf.
var dims = {
a0: [1189, 841],
a1: [841, 594],
a2: [594, 420],
a3: [420, 297],
a4: [297, 210],
a5: [210, 148]
};
var exportElement = document.getElementById('export-pdf');
exportElement.addEventListener('click', function(e) {
if (exportElement.className.indexOf('disabled') > -1) {
return;
}
exportElement.className += ' disabled';
var format = document.getElementById('format').value;
var resolution = document.getElementById('resolution').value;
var buttonLabelElement = document.getElementById('button-label');
var label = buttonLabelElement.innerText;
var dim = dims[format];
var width = Math.round(dim[0] * resolution / 25.4);
var height = Math.round(dim[1] * resolution / 25.4);
var size = /** #type {ol.Size} */ (map.getSize());
var extent = map.getView().calculateExtent(size);
map.once('postcompose', function(event) {
//var tileQueue = map.getTileQueue();
// To prevent potential unexpected division-by-zero
// behaviour, tileTotalCount must be larger than 0.
//var tileTotalCount = tileQueue.getCount() || 1;
var interval;
interval = setInterval(function() {
//var tileCount = tileQueue.getCount();
//var ratio = 1 - tileCount / tileTotalCount;
//buttonLabelElement.innerText = ' ' + (100 * ratio).toFixed(1) + '%';
//if (ratio == 1 && !tileQueue.getTilesLoading()) {
clearInterval(interval);
buttonLabelElement.innerText = label;
var canvas = event.context.canvas;
var data = canvas.toDataURL('image/jpeg');
var pdf = new jsPDF('landscape', undefined, format);
pdf.addImage(data, 'JPEG', 0, 0, dim[0], dim[1]);
pdf.save('map.pdf');
map.setSize(size);
map.getView().fitExtent(extent, size);
map.renderSync();
exportElement.className =
exportElement.className.replace(' disabled', '');
// }
}, 100);
});
map.setSize([width, height]);
map.getView().fitExtent(extent, /** #type {ol.Size} */ (map.getSize()));
map.renderSync();
}, false);
I can print in PDF when I have only OSM Layer but when I add local layers from my geoserver I can't print anything and the whole application is freezed.
Can anyone tell me what am I doing wrong here?
I am using jspdf to print pdf.
AJ
Your problem is that you load imagery from other domains, and haven't configured them for CORS. See https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image for a description on cross origin image use.
In order to get data out of the canvas, all images put into it must be from the same domain or transmitted with the appropriate Access-Control-Allow-Origin header.
I would investigate how to set up your server to serve the map imagery with those headers. You should also take a look at the crossOrigin option on your ol3 sources.
There is few solutions for CORS.
Very simple solution is to proxy OSM requests through your backend server (user <-> backend <-> OSM), but then we have little more server load.

DustJs - Helpers rendering

I start with DustJs in KrakenJs environment and i have some troubles with Dust helpers.
In fact, i want to create a helper that can create for me a simple bootstrap button.
Here is my code :
var dust = require('dustjs-linkedin');
if (!dust.helpers)
dust.helpers = {};
dust.helpers.bootstrapButton = function (chunk, context, bodies, params) {
var body = bodies.block || '',
options = params || {},
btnStyle = options.style || 'default',
btnClass = options.class || '',
btnSize = options.size || '';
btnStyle = 'btn btn-' + btnStyle;
if (btnSize)
btnSize = 'btn-' + btnSize;
return chunk.write('<button class="' + btnClass + btnStyle + btnSize + '">' + body + '</button>');
};
And when i call this helper i have the render function for body instead of the final text for body (button content : "function body_3(chk,ctx){ctx=ctx.shiftBlocks(blocks);return chk.write("test");}")
I tried to user chunk.render but i have an error because my final html is not a function like body.
Do you have any idea ?
Regards,
Guillaume
The body is an unevaluated chunk which you need to evaluate before you can concatenate it with your strings.
var curChunk = chunk.data.join(); // Capture anything in chunk prior to this helper
chunk.data = []; // Empty current chunk
var body = bodies.block(chunk).data.join() || '', // Evaluate block and make a string of it
.......
return chunk.write(curChunk + '<button class="' + btnClass + btnStyle + btnSize + '">' + body + '</button>'); // Prefix output with any earlier chunk contents and then build your tag.

Resources