As I receive numerous questions concerning the custom pattern JavaScript interface of LectureNotes and how to implement specific patterns, I thought that it might be helpful to post my replies here, which should allow to easily copy them. Please feel invited to post additional ones!
First, a so-called isometric pattern that is quoted at the app's help page (where the code lines are commented)
Code:
width = LN.getWidth();
height = LN.getHeight();
scale = LN.getScale();
step = width / 150 + scale * width / 25;
LN.setStrokeWidth(width / 1000);
for (x = 0; x < width; x += step)
LN.drawLine(x, 0, x, height);
stepX = 2 * step;
stepY = 1.1547 * step;
x1 = 0; y1 = step;
x2 = stepX; y2 = 0;
while ((x1 < width) && (y2 < height)) {
LN.drawLine(x1, y1, x2, y2);
if (y1 < height)
y1 += stepY;
else
x1 += stepX;
if (x2 < width)
x2 += stepX;
else
y2 += stepY;
}
x1 = x2 - stepX; y1 = 0;
y2 = step;
while ((x2 > 0) && (y1 < height)) {
LN.drawLine(x1, y1, x2, y2);
if (x1 > 0)
x1 -= stepX;
else
y1 += stepY;
if (y2 < height)
y2 += stepY;
else
x2 -= stepX;
}
and a simple additional one that places a page number centered at the page bottom
Code:
width = LN.getWidth();
height = LN.getHeight();
page = LN.getPage();
LN.setTextSize(0.02 * width);
LN.setTextAlign(0);
LN.drawText("Page " + page, 0.5 * width, 0.95 * height);
Some more, an eternal calender, one month per page, starting January 2012
Code:
year = 2012;
months = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"];
monthdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
month = LN.getPage() - 1;
year += Math.floor(month / 12);
month2 = month % 12;
month = month + 1;
days = monthdays[month2];
if ((month == 2) && (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)))
days++;
if (month <= 2)
year2 = year - 1;
else
year2 = year;
c = Math.floor(year2 / 100);
y = year2 % 100;
m = ((month + 9) % 12) + 1;
w = (1 + Math.floor(2.6 * m - 0.2) + y +
Math.floor(y / 4) + Math.floor(c / 4) - 2 * c + 7 * 100) % 7;
width = LN.getWidth();
height = LN.getHeight();
size = Math.min(width, height);
stepx = width / 8;
stepy = height / 8;
LN.setTextSize(0.025 * size);
for (d = 0; d < 7; d++)
LN.drawText(weekdays[d], (d + 0.6) * stepx, 1.4 * stepy);
LN.setTextSize(0.05 * size);
LN.setTextAlign(-1);
LN.drawText(months[month2] + " " + year, 7.5 * stepx, 0.25 * stepy + 0.05 * size);
LN.setTextAlign(1);
l = 0;
for (d = 1; d <= days; d++) {
LN.drawText(d, stepx * (w + 0.6), stepy * (l + 2.4));
if ((++w == 7) && (d != days)) {
w = 0;
l++;
}
}
for (x = 0.5 * stepx; x < width; x += stepx)
LN.drawLine(x, 1.5 * stepy, x, (l + 2.5) * stepy);
for (y = 1.5 * stepy; y < (l + 3) * stepy; y += stepy)
LN.drawLine(0.5 * stepx, y, 7.5 * stepx, y);
and another simple one, a checkered pattern in which every fifth line is thicker
Code:
width = LN.getWidth();
height = LN.getHeight();
scale = LN.getScale();
LN.drawCheckeredPattern(scale, false);
LN.setStrokeWidth(0.002 * width);
step = width / 150 + scale * width / 25;
for(y = step / 2; y < height; y += 5 * step) {
LN.drawLine(0, y, width, y);
}
for(x = step / 2; x < width; x += 5 * step) {
LN.drawLine(x, 0, x, height);
}
Today two examples for writing music, a simple one
Code:
width = LN.getWidth();
height = LN.getHeight();
LN.setStrokeWidth(0.001 * width);
left = 0.05 * width;
right = 0.95 * width;
step = 0.005 * height;
for(y = 0.05 * height; y < 0.95 * height; y += 0.05 * height) {
LN.drawLine(left, y, right, y);
LN.drawLine(left, y + step, right, y + step);
LN.drawLine(left, y + 2 * step, right, y + 2 * step);
LN.drawLine(left, y + 3 * step, right, y + 3 * step);
LN.drawLine(left, y + 4 * step, right, y + 4 * step);
LN.drawLine(left, y, left, y + 4 * step);
LN.drawLine(right, y, right, y + 4 * step);
}
and a double one
Code:
width = LN.getWidth();
height = LN.getHeight();
LN.setStrokeWidth(0.001 * width);
left = 0.05 * width;
right = 0.95 * width;
step = 0.005 * height;
for(y = 0.05 * height; y < 0.9 * height; y += 0.1 * height) {
LN.drawLine(left, y, right, y);
LN.drawLine(left, y + step, right, y + step);
LN.drawLine(left, y + 2 * step, right, y + 2 * step);
LN.drawLine(left, y + 3 * step, right, y + 3 * step);
LN.drawLine(left, y + 4 * step, right, y + 4 * step);
LN.drawLine(left, y + 9 * step, right, y + 9 * step);
LN.drawLine(left, y + 10 * step, right, y + 10 * step);
LN.drawLine(left, y + 11 * step, right, y + 11 * step);
LN.drawLine(left, y + 12 * step, right, y + 12 * step);
LN.drawLine(left, y + 13 * step, right, y + 13 * step);
LN.drawLine(left, y, left, y + 13 * step);
LN.drawLine(right, y, right, y + 4 * step);
LN.drawLine(right, y + 9 * step, right, y + 13 * step);
}
(step size etc. can easily be adjusted).
Since v1.16.13, there is an additional JavaScript command LN.setColor(r, g, b) that allows to use colors other then the one chosen in the dialog. This allows now, for instance, a ruled pattern with a red line on the left side
Code:
width = LN.getWidth();
height = LN.getHeight();
LN.drawRuledPattern(LN.getScale(), false);
LN.setStrokeWidth(0.002 * width);
LN.setColor(1, 0, 0);
LN.drawLine(0.05 * width, 0, 0.05 * width, height);
isometric problems
acadoid said:
As I receive numerous questions concerning the custom pattern JavaScript interface of LectureNotes and how to implement specific patterns, I thought that it might be helpful to post my replies here, which should allow to easily copy them. Please fell invited to post additional on;
Click to expand...
Click to collapse
I love this app. I am using it on a Galaxy Note 10.1. The isometric script give an error message that it takes too long and aborts. Thought you would want to know.
By the way, I tested it three times using cut ans paste. Once from the help page, and twice from here.
Keep up the good work.
@RETIEF: To double-check, I copied and paste the content shown in this thread, and it works. Note, however, that on my Samsung Galaxy Note 10.1 (for instance in difference to my Lenovo ThinkPad Tablet), the copy/paste converts a `new line´ into nothing (instead of a space), this causes problems, for instance `else y1´ becomes `elsey1´, which is wrong. Please check whether this is causing the problem in your case.
Attempt to fix calendar
acadoid said:
@RETIEF: To double-check, I copied and paste the content shown in this thread, and it works. Note, however, that on my Samsung Galaxy Note 10.1 (for instance in difference to my Lenovo ThinkPad Tablet), the copy/paste converts a `new line´ into nothing (instead of a space), this causes problems, for instance `else y1´ becomes `elsey1´, which is wrong. Please check whether this is causing the problem in your case.
Click to expand...
Click to collapse
I didn't have that exact problem, but the if else structures left out lines in the paste so that that all read if (xxxxx); else ;next line.
I manually edited the script to match exactly what was posted here and I still get the same error message. This is for the isometric code.
On the calendar code, if I use a task killer (I use the factory Samsung one), I can get the code to load and execute if I stopped on January. But if I left the document later in the year, I get the same error message.
I'm no coder (at least not since the Fortran G and Turbo Pascal days), but I wounder if extending the process time a second would solve the problem.
Like I said. I'm no coder.
In any case, I appreciate your help. I'm sure you have better things to do.
@RETIEF: All the posted codes work fine on my Samsung Galaxy Note 10.1. I can increase the maximal time, but I do not think that this is the problem. Have you tried to share such page or export it to PDF? In these cases, the maximal waiting time is ten times longer (these operations are not time critical), so if you get an abort message there, then something is wrong in your code.
If you drop me an email, I can send the code as email attachment to you, this will exclude all possible sources of error.
PMed you with address. Didn't now your address.
acadoid said:
@RETIEF: All the posted codes work fine on my Samsung Galaxy Note 10.1. I can increase the maximal time, but I do not think that this is the problem. Have you tried to share such page or export it to PDF? In these cases, the maximal waiting time is ten times longer (these operations are not time critical), so if you get an abort message there, then something is wrong in your code.
If you drop me an email, I can send the code as email attachment to you, this will exclude all possible sources of error.
Click to expand...
Click to collapse
see the PM
Edit. I get a partial rendering in landscape mode before abort. I get horizontal lines, and one diagonal in the upper left.
Isometric paper
Thanks for the e-mail. It works like a champ. I've talked with a lot of developers in my time, but you are the most responsive and responsible I have ever had the pleasure to know. Thanks.
@RETIEF: Curious, the text in the post above is copied and pasted from the same file. In any case, glad that it works.
Heye acadoid. Really dig the app, but im looking for something with type capabilities as well. Are you thinking about implementng this at all?
I am familiar with other apps, but some offer too much and have strange and annoying options (freenote) or great simple user and user friendly text environments with no drawing capabilities(jotterpad hd).
@jewnersey: LectureNotes has a text drawing tool for typed text, but this is intended for a keyword or a small phrase, not for longer text. To improve in this respect is on my agenda.
Note that this is not quite the right thread, there are several general threads on LectureNotes, this one is specific for custom paper pattern.
Week-by-week calendar
Below is a calendar which shows one week at a time. The width of the paper should be twice the height for this calendar to look right.
Editable parameters:
line 1 through 3: Starting date of the calendar
line 9 through 19: text sizes, margins, size of free space on weekdays, start and end hour of weekdays, a few colors
I made this for myself, and thought I might as well share it in case someone else can make use of it. I also uploaded a couple of screenshots.
Thanks for giving us the opportunity of making custom backgrounds!
Code:
year = 2012;
month = 11;
day = 20;
relativeWeek = LN.getPage()-1;
width = LN.getWidth();
height = LN.getHeight();
headertext = height * 0.05;
headerheight = height * 0.10;
toplineheight = headerheight + headertext;
leftmargin = height * 0.1;
rightmargin = leftmargin;
noteSpace = height * 0.2;
startHour = 7;
endHour = 17;
defaultColor = [150,150,150];
headlineColor = [0,0,0];
weekColors = [[208,0,250],[0,200,240],[92,255,1],[255,255,0],[255,146,1],[255,9,32],[255,25,145]];
monthdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
months = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"];
weekdays = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)))
monthdays[1] = 29;
/* calculate what date the first monday is */
year2 = year;
if (month <= 2)
--year2;
c = Math.floor(year2 / 100);
y = year2 % 100;
m = ((month + 9) % 12) + 1;
firstweekday = (Math.floor(2.6 * m - 0.2) + y + Math.floor(y / 4) + Math.floor(c / 4) - 2 * c + 7 * 100) % 7;
/* 0 is monday */
firstmonday = (7 - firstweekday) % 7 + 1;
/* convert day and month so that they represent the monday of the user inputted week */
if (day < firstmonday) {
--month;
if (month == 0) {
month = 12;
--year;
monthdays[1] = 28;
if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)))
monthdays[1] = 29;
}
day = monthdays[month-1] + firstmonday - 7;
} else {
day = firstmonday + 7*Math.floor((day-firstmonday)/7);
}
/* work out the year, month, day and week of the current sheet */
day += 7*relativeWeek;
while (day > monthdays[month-1]) {
day -= monthdays[month-1];
++month;
if (month == 13) {
month = 1;
++year;
monthdays[1] = 28;
if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)))
monthdays[1] = 29;
}
}
/* calculate the week number of user input */
totalDays = day;
for (i = 0; i < month-1; ++i)
totalDays += monthdays[i];
week = Math.ceil(totalDays/7);
/* Make colors for each day */
stepx = (width-leftmargin-rightmargin)/6;
i = 0;
for (x = leftmargin; x-leftmargin <= 5.5*stepx; x += stepx) {
/* create lines for each half hour */
if (x-leftmargin < 4.5*stepx) {
y = toplineheight+headertext*1.1;
LN.setColor( weekColors[i][0]/255, weekColors[i][1]/255, weekColors[i][2]/255 );
LN.drawFilledRect( x, toplineheight, x+stepx, y );
} else {
y1 = toplineheight+headertext*1.1;
y2 = (toplineheight+height)/2+headertext*1.1;
LN.setColor( weekColors[i][0]/255, weekColors[i][1]/255, weekColors[i][2]/255 );
LN.drawFilledRect( x, toplineheight, x+stepx, y1 );
++i;
LN.setColor( weekColors[i][0]/255, weekColors[i][1]/255, weekColors[i][2]/255 );
LN.drawFilledRect( x, (toplineheight+height)/2, x+stepx, y2 );
}
LN.setStrokeWidth(4);
++i;
}
/* Reset color */
LN.setColor( defaultColor[0]/255, defaultColor[1]/255, defaultColor[2]/255 );
/* Drawing the main lines */
stepx = (width-leftmargin-rightmargin)/6;
stepy = (height-toplineheight-headertext*1.01-noteSpace)/(2+endHour-startHour);
LN.setTextAlign(1);
LN.setTextSize(stepy*0.9);
for (x = leftmargin; x-leftmargin < 6.5*stepx; x += stepx) {
LN.drawLine(x, toplineheight, x, height);
if (x-leftmargin < 5.5*stepx) {
/* create lines for each half hour */
LN.setStrokeWidth(1);
if (x-leftmargin < 4.5*stepx) {
i = -2;
for (y = toplineheight+headertext*1.1; y < height-noteSpace; y += stepy) {
LN.drawLine(x, y, x+stepx, y);
if (++i > 0) {
LN.drawText(startHour+i-1, x, y-stepy*0.05);
LN.drawLine(x+LN.getTextWidth(startHour+i-1), y-stepy/2, x+stepx, y-stepy/2);
}
}
} else {
LN.drawLine(x, toplineheight+headertext*1.1, x+stepx, toplineheight+headertext*1.1);
LN.drawLine(x, (toplineheight+height)/2+headertext*1.1, x+stepx, (toplineheight+height)/2+headertext*1.1);
}
LN.setStrokeWidth(4);
}
}
LN.drawLine(leftmargin, toplineheight, width-rightmargin, toplineheight);
LN.drawLine(leftmargin+5*stepx, (toplineheight+height)/2, width-rightmargin, (toplineheight+height)/2);
/* Write which week it is */
LN.setTextSize(headertext);
LN.setColor( headlineColor[0]/255, headlineColor[1]/255, headlineColor[2]/255 );
LN.setTextAlign(-1);
LN.drawText("Week " + week, width-rightmargin, headerheight);
oldMonth = month;
oldYear = year;
LN.setTextAlign(0);
for (i = 0; i < 7; ++i){
if (day > monthdays[month-1]) {
day -= monthdays[month-1];
++month;
if (month == 13) {
month = 1;
++year;
monthdays[1] = 28;
if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)))
monthdays[1] = 29;
}
}
if (i < 6) {
LN.drawText(day + " " + weekdays[i], leftmargin + stepx * (i + 0.5), toplineheight+headertext );
} else {
LN.drawText(day + " " + weekdays[i], leftmargin + stepx * (i - 0.5), (toplineheight+height)/2+headertext );
}
++day;
}
LN.setTextAlign(1);
if (oldMonth == month)
LN.drawText(months[month-1], leftmargin, headerheight );
else {
LN.drawText(months[oldMonth-1] + " / " + months[month-1], leftmargin, headerheight );
}
LN.setTextAlign(0);
if (oldYear == year)
LN.drawText(year, leftmargin+(width-leftmargin-rightmargin)/2, headerheight );
else {
LN.drawText(oldYear + " / " + year, leftmargin+(width-leftmargin-rightmargin)/2, headerheight );
}
Thanks for the Weekly Calendar
Thanks for this post. It took a couple of edits to get it perfect on my note 10.1, but I like it. Thanks for your work and sharing.:good:
Egenskaper said:
Below is a calendar which shows one week at a time. The width of the paper should be twice the height for this calendar to look right.
Editable parameters:
Click to expand...
Click to collapse
RETIEF said:
Thanks for this post. It took a couple of edits to get it perfect on my note 10.1, but I like it. Thanks for your work and sharing.:good:
Click to expand...
Click to collapse
Just turned on to LectureNotes and this Forum will make me appreciate it all the more.
page x of y
The programmer added the funtion LNgetNumberOfPages();
My custom pattern is checkered and shoes the number of pages (page x of y) at the bottom:
width = LN.getWidth();
height = LN.getHeight();
page = LN.getPage ();
pages = LN.getNumberOfPages();
scale = LN.getScale ();
LN.drawCheckeredPattern (scale, false);
LN.setColor (1, 1, 1);
LN.drawFilledRect(width/2-0.07*width, height-0.025*height, width/2+0.07*width, height);
LN.setColor (0.4, 0.4,0.4);
LN.setTextSize (0.02 * width);
LN.setTextAlign (0);
LN.drawText("Seite " + page + " von " + pages , 0.5*width, 0.99*height);
Hope you like it as well.
Thanks
Thanks. This works well. Anyone skilled enough to make one that is checkered with every fifth line bold or red?
tech.towan said:
The programmer added the funtion LNgetNumberOfPages();
My custom pattern is checkered and shoes the number of pages (page x of y) at the bottom:
width = LN.getWidth();
height = LN.getHeight();
page = LN.getPage ();
pages = LN.getNumberOfPages();
scale = LN.getScale ();
LN.drawCheckeredPattern (scale, false);
LN.setColor (1, 1, 1);
LN.drawFilledRect(width/2-0.07*width, height-0.025*height, width/2+0.07*width, height);
LN.setColor (0.4, 0.4,0.4);
LN.setTextSize (0.02 * width);
LN.setTextAlign (0);
LN.drawText("Seite " + page + " von " + pages , 0.5*width, 0.99*height);
Hope you like it as well.
Click to expand...
Click to collapse
@RETIEF: Try
Code:
width = LN.getWidth();
height = LN.getHeight();
scale = LN.getScale();
LN.drawCheckeredPattern(scale, false);
LN.setStrokeWidth(0.002 * width);
step = width / 150 + scale * width / 25;
for(y = step / 2; y < height; y += 5 * step) {
LN.drawLine(0, y, width, y);
}
for(x = step / 2; x < width; x += 5 * step) {
LN.drawLine(x, 0, x, height);
}
This draws a thicker line every fifth line, the scale of the pattern is controlled by the slider in the notebook settings dialog. To get red lines, add a
Code:
LN.setColor(1, 0, 0);
after the LN.setStrokeWidth.
thanks
this is perfect. Thanks.
acadoid said:
@RETIEF: Try
Code:
width = LN.getWidth();
height = LN.getHeight();
scale = LN.getScale();
LN.drawCheckeredPattern(scale, false);
LN.setStrokeWidth(0.002 * width);
step = width / 150 + scale * width / 25;
for(y = step / 2; y < height; y += 5 * step) {
LN.drawLine(0, y, width, y);
}
for(x = step / 2; x < width; x += 5 * step) {
LN.drawLine(x, 0, x, height);
}
This draws a thicker line every fifth line, the scale of the pattern is controlled by the slider in the notebook settings dialog. To get red lines, add a
Code:
LN.setColor(1, 0, 0);
after the LN.setStrokeWidth.
Click to expand...
Click to collapse
Related
i'm korean photon q user, sorry for my bad english.
i bought Photon Q 2weeks ago on Ebay,
and i applied "SIM CARD MOD" it works perfect.
but touchscreen smoothness and sensitivity is dissatisfied for me..
i want to change touchscreen setting, and i found the solution.
modifying touchscreen driver in kernel source.
i refer to the "MXT224E Protocol Guide" (google it)
tested one by one all register on [TOUCH_ACQUIRESETTING_T8], [TOUCH_MULTITOUCHSCREEN_T9] Function.
For example, [TOUCH_MULTITOUCHSCREEN_T9] can set like this.
Code:
in "drivers/input/touchscreen/atmxt.c"
~~~~
if (entry[3] < 21) {
atmxt_dbg(dd, ATMXT_DBG3,
"%s: Only 10-bit resolution is available.\n", __func__);
} else {
if (reg[19] >= 0x04)
dd->data->res[0] = true;
if (reg[21] >= 0x04)
dd->data->res[1] = true;
}
// MOT
reg[0] = 139; //CTRL!
// reg[1] = ; //XORIGIN!
// reg[2] = ; //YORIGIN!
// reg[3] = ; //XSIZE! 19
// reg[4] = ; //YSIZE! 11
reg[5] = 0; //AKSFG
reg[6] = 70; //BLEN
reg[7] = 23; //TCHTHR
reg[8] = 2 ; //TCHDI
reg[9] = 1 ; //ORIENT
reg[10] = 0; //MRGTIMEOUT
reg[11] = 2; //MOVHYSTI
reg[12] = 1; //MOVHYSTN
reg[13] = 63; //MOVFILTER
reg[14] = 10; //NUM-TOUCH
reg[15] = 5; // HYSTERISIS MERGE
reg[16] = 40; // THRESHOLD MERGE
reg[17] = 7; // AMPLITUDE HYSTERESIS
reg[18] = 255; //XRANGE
reg[19] = 3; //XRANGE
reg[20] = 255; //YRANGE
reg[21] = 3; //YRANGE
// reg[22] =3; // XLOCLIP
// reg[23] =248; // XHICLIP
// reg[24] =28; // YLOCLIP
// reg[25] =17; // YHICLIP
reg[26] = 225; //XEDGECTRL
reg[27] = 50; //XEDGEDIST
reg[28] = 172; //YEDGECTRL
reg[29] = 80; //YEDGEDIST
reg[30] = 18; //JUMPLIMIT
reg[31] = 10; //TCHHYST
reg[32] = 40; //XPITCH
reg[33] = 40; //YPITCH
reg[34] = 0; //NEXTTCHDI
atmxt_save_data9_fail:
return err;
}
i attached "Touchscreen Tuned" Kernel flashable zip file.
(based on CM-Kernel source, "motorola_msm8960-common")
it works on CM11-SNAPSHOT-M12. "moto_msm8960_jbbl"
IT IS NOT a perfect solution.
if you want more smoothness and sensitivity, modify that values.
Disclaimer
First off all, thanks to showp1984 for his original sweep2wake, based on which, this has been made.
I am a newbie in linux kernel programming, I did spend considerable amount of time, working with others to know about how touch input works. In many places, code will be useless, or there may be better way of implementation. Based on my understanding, I coded this.
This was originally made for a specific device, so I will try to explain wherever possible, so that it becomes easier for someone to implement in case they are interested.
This post does not show how to add hooks in touch panel driver and display driver.
Gestures Available
Swipe Left
Swipe Right
Swipe Up
Swipe Down
Swipe Forward Diagonally
Swipe Backward Diagonally
Draw 'L'
Draw 'V'
Commits
Initial Commit - https://github.com/corphish/android_kernel_sony_msm8930_lp/commit/dae03796da1f8ce97ed41c1b150b18741ac75f24 (Please read the extended description, as I have explained there what I have done)
Fixes - https://github.com/corphish/android_kernel_sony_msm8930_lp/commit/73562680a73956af105bffc0f2d1e7815a375677
Walkthrough
First off all I modified detect_sweep2wake function.
Code:
static bool detect_sweep2wake(int x, int y, int id)
{
key = KEY_POWER;
if (id == 255 && s2w_touch_count > 10) {
int x = s2w_coord_nature();
if(x) {
if(x == 1) {
if(s2w_right) {
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 2) {
if(s2w_left){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 3) {
if(s2w_up){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 4) {
if(s2w_down){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 5) {
if(s2w_fwd_diag){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 6) {
if(s2w_bck_diag){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 7) {
if(s2w_l){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
if(x == 8) {
if(s2w_v){
s2w_coord_reset();
doubletap2wake_reset();
return true;
}
}
//pr_info("%s returned true\n",__func__);
}
} else {
//doubletap2wake_reset();
s2w_coord_dump(x, y);
direction_vector_calc();
new_touch(x, y);
}
if (ktime_to_ms(ktime_get())-tap_time_pre > D2W_TIME){
s2w_coord_reset();
doubletap2wake_reset();
}
//pr_info("%s returned false\n",__func__);
return false;
}
It now takes id as parameters as well.
id here is the touch id which is returned when we lift off contact from touch.
Do note that for this device, the id returned when we lift off contact from touch is 255, it will be different for different devices.
What this new detect_sweep2wake fn does is, it tests whether the id returned is that id (touch id which is returned when we lift off contact from touch) and the touch count is greater than a specific number or not.
The specific touch count is used to detect continuous touches (swipes).
If true, it calls for gesture detection function, if true, returns true, if false returns false.
If false, it dumps co-ordinates. Co-ordinates are dumped to 2 variables (x,y) and previous data is stored in (x_prev,y_prev). The first values of touch (the touch co-ordinates on first touch) is stored separately as well.
Then direction_vector_calc is called, which tests the nature of co-ordinates with respect to the previous one.
Code:
void direction_vector_calc(void) {
int tot = 0;
if(s2w_coord_count > 1) {
if(x > x_pre) {
dir[0]++; //right
tot++;
} else if (x < x_pre) {
dir[1]++; //left
tot++;
}
if(y < y_pre) {
dir[2]++; //up
tot++;
} else if (y > y_pre) {
dir[3]++; //down
tot++;
}
//To determine whether both x and y co-ordinates have changed from previous input or not and act accordingly.
if(tot > 1)
multiple_dir++;
//To determine max deviation in x coord.
if(x > max_x)
max_x = x;
//To determine min deviation in x coord.
if(x < min_x)
min_x = x;
//To determine max deviation in y coord.
if(y > max_y)
max_y = y;
//To determine min deviation in y coord.
if(y < min_y)
min_y = y;
} else {
min_y = y;
min_x = x;
max_x = x;
max_y = y;
}
}
At times, there maybe cases that a co-ordinate differs from its previous co-ordinate by 2 directions. This functions take care of that too.
The readings are stored in an array an then tested by gesture detection logic.
The working of gesture_detection is explained in the extended description of this commit.
Code:
int s2w_coord_nature(void)
{
int i = 0;
pr_info("%s:Recieved count - %d\n",__func__,s2w_touch_count);
pr_info("%s:max_x-%d\n",__func__,max_x);
pr_info("%s:max_y-%d\n",__func__,max_y);
pr_info("%s:min_x-%d\n",__func__,min_x);
pr_info("%s:min_y-%d\n",__func__,min_y);
/*This function detects the nature of sweep input, and on the basis of following, it returns -
1 - sweep right
2 - sweep left
3 - sweep up
4 - sweep down*/
pr_info("%s:multiple_dir - %d\n",__func__,multiple_dir);
for(i = 0; i < 4; i++ )
pr_info("%s:dir[%d] - %d\n",__func__,i,dir[i]);
if (abs(x - x_first) > 150 && abs(y - y_first) < 50 && abs(max_y - y) < 50) {
if(dir[0] > s2w_touch_count/2) {
pr_info("%s:Sweep right\n",__func__);
return 1;
}
else if(dir[1] > s2w_touch_count/2) {
pr_info("%s:Sweep left\n",__func__);
return 2;
}
}
if (abs(y - y_first) > 150 && abs(x - x_first) < 50 && abs(max_x - x) < 50) {
if(dir[2] > s2w_touch_count/2) {
pr_info("%s:Sweep up\n",__func__);
return 3;
}
else if(dir[3] > s2w_touch_count/2) {
pr_info("%s:Sweep down\n",__func__);
return 4;
}
}
if(abs(x - x_first) > 100 && abs(y - y_first) > 100 && (multiple_dir == s2w_touch_count - 1)) {
if(x > x_first) {
pr_info("%s:Forward diagonal swipe!!\n",__func__);
return 5;
}//forward diagonal swipe!!
else if(x < x_first) {
pr_info("%s:Backward diagonal swipe!!\n",__func__);
return 6;
}//backward diagonal swipe!!
}
if(abs(x - x_first) > 100 && abs(y - y_first) > 100 && (multiple_dir < s2w_touch_count - 1) && dir[0] > s2w_touch_count/3 && dir[3] > s2w_touch_count/3) {
pr_info("%s:Draw 'L'\n",__func__);
return 7;
}
if(abs(x - x_first) > 80 && abs(y - y_first) < 50 && dir[2] > s2w_touch_count/3 && dir[3] > s2w_touch_count/3 && (multiple_dir < s2w_touch_count - 1)) {
pr_info("%s:Draw 'V'\n",__func__);
return 8;
}
s2w_coord_reset();
return 0;
}
If swipe matches any gesture, it returns corresponding value, else returns 0.
About toggling, I created separate files for each gesture. Also, to simplify things, I had added a master switch for these gestures.
I also made an app for this to control these toggles - Gesture Control 1.4
Credits
showp1984 - Without his works, this is just nothing.
thewisenerd - It is for this guy, I know what I know about touch panels.
I am only posting here because it wont allow me to post in the other forums.
i am taking a photo with my app then rotating if needed then resizing. after that i am saving the new rotated and scaled down pic to the sd card. the photo does rotate and the byte size changes but when i view the new photo it still has the same dimensions as the orginal photo.
my resizing and saving calls are
Code:
//resize for preview
using (var bitmap = _file.Path.LoadAndResizeBitmap(300, 225))
{
//resize for saving
Bitmap resized = _file.Path.LoadAndResizeBitmap(800, 600);
BitmapHelpers.saveBitmap(resized,_user_id,_dateStr);
//shows preview resize
photo.SetImageBitmap(ConvertToBitmap(bitmap));
}
public static Bitmap LoadAndResizeBitmap(this string fileName, int width, int height)
{
//First we get the diamensions of the file on disk
BitmapFactory.Options options = new BitmapFactory.Options { InJustDecodeBounds = true };
BitmapFactory.DecodeFile(fileName, options);
//Next we calculate the ratio that we need to resize the image by
//in order to fit the requested dimensions.
int outHeight = options.OutHeight;
int outWidth = options.OutWidth;
int inSampleSize = 1;
if (outHeight > height || outWidth > width)
{
inSampleSize = outWidth > outHeight
? outHeight / height : outWidth / width;
}
//Now we will load the image
options.InSampleSize = inSampleSize;
options.InJustDecodeBounds = false;
Bitmap resizedBitmap = BitmapFactory.DecodeFile(fileName, options);
// Images are being saved in landscape, so rotate them back to portrait if they were taken in portrait
Matrix mtx = new Matrix();
Android.Media.ExifInterface exif = new Android.Media.ExifInterface(fileName);
string orientation = exif.GetAttribute(Android.Media.ExifInterface.TagOrientation);
switch (orientation)
{
case "6": // portrait
mtx.PreRotate(90);
resizedBitmap = Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, mtx, false);
mtx.Dispose();
mtx = null;
break;
case "1": // landscape
//mtx.PreRotate(-90);
//resizedBitmap = Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, mtx, false);
//mtx.Dispose();
//mtx = null;
break;
default:
mtx.PreRotate(90);
resizedBitmap = Bitmap.CreateBitmap(resizedBitmap, 0, 0, resizedBitmap.Width, resizedBitmap.Height, mtx, false);
mtx.Dispose();
mtx = null;
break;
}
return resizedBitmap;
}
public static void saveBitmap(Bitmap bitmap, int userId, String dateStr)
{
var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
String fileName = "bb_" + userId + "_" + dateStr + "_new.jpg";
var filePath = System.IO.Path.Combine(sdCardPath, fileName);
var stream = new FileStream(filePath, FileMode.Create);
bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, stream);
stream.Close();
}
when it does the first _file.Path.LoadAndResizeBitmap(300, 225) the inSampleSize is 3 and returns new height,width of 640,360
when it does _file.Path.LoadAndResizeBitmap(800, 600) the inSampleSize is 1 and returns original values of 1280,720
I am using google vision library for face detection. Face detection is perfect and I get all the info like vertices, angles like eulerY, eulerZ.
I want to draw mask on face, drawing is ok but the face mask is not following the face position as it should, the position is not correct. Here is my edited code to draw face mask on googly eyes project.
Here is my source code:
package com.google.android.gms.samples.vision.face.googlyeyes;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.google.android.gms.samples.vision.face.googlyeyes.ui.camera.GraphicOverlay;
import com.google.android.gms.vision.face.Face;
import java.util.HashMap;
/**
* Graphics class for rendering Googly Eyes on a graphic overlay given the current eye positions.
*/
class GooglyEyesGraphic extends GraphicOverlay.Graphic {
private Paint mEyeWhitesPaint;
private Paint mEyeIrisPaint;
private Paint mEyeOutlinePaint;
private Paint mEyeLidPaint;
Paint mBoxPaint;
Context mContext;
private static final float BOX_STROKE_WIDTH = 20.0 f;
FrameLayout frameLayout;
ImageView imageView;
// Bitmap bmpOriginal;
//==============================================================================================
// Methods
//==============================================================================================
GooglyEyesGraphic(GraphicOverlay overlay, Context mContext) {
super(overlay);
this.mContext = mContext;
mEyeWhitesPaint = new Paint();
mEyeWhitesPaint.setColor(Color.WHITE);
mEyeWhitesPaint.setStyle(Paint.Style.FILL);
mEyeLidPaint = new Paint();
mEyeLidPaint.setColor(Color.YELLOW);
mEyeLidPaint.setStyle(Paint.Style.FILL);
mEyeIrisPaint = new Paint();
mEyeIrisPaint.setColor(Color.BLACK);
mEyeIrisPaint.setStyle(Paint.Style.FILL);
mEyeOutlinePaint = new Paint();
mEyeOutlinePaint.setColor(Color.BLACK);
mEyeOutlinePaint.setStyle(Paint.Style.STROKE);
mEyeOutlinePaint.setStrokeWidth(5);
mBoxPaint = new Paint();
mBoxPaint.setColor(Color.MAGENTA);
mBoxPaint.setStyle(Paint.Style.STROKE);
mBoxPaint.setStrokeWidth(BOX_STROKE_WIDTH);
mBoxPaint.setAlpha(40);
LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = li.inflate(R.layout.mask_layout, null);
imageView = (ImageView) view.findViewById(R.id.flMaskIV);
frameLayout = (FrameLayout) view.findViewById(R.id.frameLayout);
}
private volatile Face mFace;
/**
* Updates the eye positions and state from the detection of the most recent frame. Invalidates
* the relevant portions of the overlay to trigger a redraw.
*/
void updateEyes(PointF leftPosition, boolean leftOpen,
PointF rightPosition, boolean rightOpen, Face mFace) {
if (facesList.containsKey(mFace.getId())) {
PointF pointF1 = facesList.get(mFace.getId()).getPosition();
PointF pointF2 = mFace.getPosition();
double x = Math.sqrt(Math.pow(pointF2.x - pointF1.x, 2) - Math.pow(pointF2.y - pointF1.y, 2));
if (x < 0)
x = (-1 * x);
if (x < 10)
return;
Log.e("face Called", "FaceCalled");
}
this.mFace = mFace;
facesList.put(mFace.getId(), mFace);
postInvalidate();
}
public HashMap < Integer, Face > facesList = new HashMap < > ();
/**
* Draws the current eye state to the supplied canvas. This will draw the eyes at the last
* reported position from the tracker, and the iris positions according to the physics
* simulations for each iris given motion and other forces.
*/
@override
public void draw(Canvas canvas) {
if (mFace == null)
return;
// if (facesList.containsKey(mFace.getId())) {
// PointF pointF1 = facesList.get(mFace.getId()).getPosition();
// PointF pointF2 = mFace.getPosition();
//
// double x = Math.sqrt(Math.pow(pointF2.x - pointF1.x, 2) - Math.pow(pointF2.y - pointF1.y, 2));
// if (x < 0)
// x = (-1 * x);
// if (x < 10)
// return;
// Log.e("face Called", "FaceCalled");
//
// }
//
// facesList.put(mFace.getId(), mFace);
if (this.canvas == null)
this.canvas = canvas;
applyMask();
}
Drawable drawable;
Canvas canvas;
private void applyMask() {
if (canvas == null)
return;
// Log.e("mFace.getEulerY()", "mFace.getEulerY()=> " + mFace.getEulerY());
if (GooglyEyesActivity.maskImgView != null) {
GooglyEyesActivity.maskImgView.setVisibility(View.GONE);
GooglyEyesActivity.maskImgView.setImageResource(GooglyEyesActivity.currEmoticonID);
}
float x = translateX(mFace.getPosition().x + mFace.getWidth() / 2);
float y = translateY(mFace.getPosition().y + mFace.getHeight() / 2);
// Draws a bounding box around the face.
float xOffset = scaleX(mFace.getWidth() / 2.0 f);
float yOffset = scaleY(mFace.getHeight() / 2.0 f);
float left = x - xOffset - 50;
float top = y - (yOffset) - 50;
float right = x + xOffset + 50;
float bottom = y + (yOffset) + 50;
// canvas.drawRect((int) left, (int) top, (int) right, (int) bottom, mBoxPaint);
drawable = GooglyEyesActivity.maskImgView.getDrawable();
///////////////////
canvas.save();
canvas.translate(left, top);
// frameLayout.setX(left);
// frameLayout.setY(top);
Rect rect = new Rect((int) left, (int) top, (int) right, (int) bottom);
frameLayout.measure(rect.width(), rect.height());
frameLayout.setLayoutParams(new LinearLayout.LayoutParams(rect.width(), rect.height()));
frameLayout.layout(0, 0, (int) right, (int) bottom);
frameLayout.setClipBounds(rect);
imageView.setLayoutParams(new FrameLayout.LayoutParams(rect.width(), rect.height()));
imageView.setRotationY(mFace.getEulerY());
imageView.setRotation(mFace.getEulerZ());
imageView.setImageDrawable(drawable);
frameLayout.draw(canvas);
canvas.restore();
}
}
Also i need to add animations so i tried using dlib library to get landmarks points and draw it using opengl but in opengl i dont have any function to populate the vertice array i am getting from dlib. As the dlib landmarks are in points but the array there is not in such a way. Any help will be appreciated for both scenarios.
Thank you in advance.
Thanks.
aijaz070110 said:
I am using google vision library for face detection. Face detection is perfect and I get all the info like vertices, angles like eulerY, eulerZ.
I want to draw mask on face, drawing is ok but the face mask is not following the face position as it should, the position is not correct. Here is my edited code to draw face mask on googly eyes project.
Here is my source code:
[...]
Also i need to add animations so i tried using dlib library to get landmarks points and draw it using opengl but in opengl i dont have any function to populate the vertice array i am getting from dlib. As the dlib landmarks are in points but the array there is not in such a way. Any help will be appreciated for both scenarios.
Thank you in advance.
Thanks.
Click to expand...
Click to collapse
Do you have any progress on this?
Hello everyone,
I just published a simple game but I think it has been very good. At least my kids love it.https://play.google.com/store/apps/details?id=com.ham.game.memo
I have mixed two concepts: the memory game of matching classic images with the wordle, that is, a daily game board and the possibility of sharing the result on Social Networks,
Download and comments are appreciated.
For anyone that could be interested this is the source code how i convert the drawable tiles to a image like wordle style:
public static Bitmap getImageMemo(Context context) {
// base
Drawable blank = null;
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
if(MemoColors.dark)
blank = App.context().getResources().getDrawable( R.drawable.keyback, App.context().getTheme());
else
blank = App.context().getResources().getDrawable( R.drawable.keyback_light, App.context().getTheme());
} else {
blank = ContextCompat.getDrawable(App.context(), R.drawable.keyback_light);
}
// create image
int margin = 2;
int piece = 48;
Bitmap image = Bitmap.createBitmap((int) piece * 5 + margin * 4, piece * 6 + margin * 5, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(image);
int pTop = 0, pLeft = 0;
for(int row=1; row < 7; row++)
{
for(int col=1; col < 6; col++)
{
Drawable drawable = blank;
if(getActualWord(row, col) < 0)
drawable = MemoIcons.getIconByIndex(MemoIcons.getFamily("robots"), getIconToday(row, col));
drawable.setBounds(pLeft, pTop, pLeft+piece, pTop+piece);
drawable.draw(canvas);
pLeft += piece+margin;
}
pLeft = 0;
pTop += piece+margin;
}
return image;
}
seems very nicely designed.. will give it a try.. thx!