quran / quran_android

a quran reading application for android
http://android.quran.com
GNU General Public License v3.0
1.99k stars 882 forks source link

Ayah Detection - Calculate ratio of pre defined 1920 Quran images to different screen sizes #1277

Closed MustafaKhaled closed 4 years ago

MustafaKhaled commented 4 years ago

I have a problem with calculating the ratio between Quran images (1920 width) with different screen sizes in ayah detection feature. Suppose mobile screen size is Width 1080 Height 2190

Quran Images size Width 1920 Height 3106

My calculations go like : positionX1920/:screen_width -> between minX and maxX(In the database) positionY3106/:screen_height -> between minY and maxY(In the database)

I failed to map the select coordinates to its Ayah in the database to highlight the ayah. Is something still missing in calculating the ratio between different screen sizes and original Quran images?

ahmedre commented 4 years ago

if i recall, the values in the database that are generated (minX, minY to maxX, maxY) are the bounds of the ayah on that page for that width.

you can compute the height and width that the page will be displayed at. based on that, find the ratio of the height compared to the actual image height and the width compared to the actual image width. then just multiply the width ratio by the minX and maxX and the height ratio by the minY and maxY to get the proper positions.

if you're on Android, i think ImageView helps you with this - set your image in the view, and then call getImageMatrix() - you can then apply that Matrix on the actual coordinates to get the mapped coordinates (you can use the mapRect method on Matrix for this).

MustafaKhaled commented 4 years ago

Yes, I'm working for an Android Application. I'll show you the calculation I'm using now, and it gonna be pretty appreciated if you check it.

In order to detect Ayah, I used the approach to find which ayah is being pressed and then I can use canvas to draw the highlighted rectangle. Suppose we are in Page 3, so the query should be like the following:

SELECT * FROM glyphs WHERE :positionX*1920/:screen_width BETWEEN min_x AND max_x AND :positionY*3106/:screen_height BETWEEN min_y AND max_y AND page_number=3

where positionX is the X-coordinate where the user tapped on the screen. positionY is the Y-coordinate where the user tapped on the screen.

This approach does not work as expected, sometimes it maps to a wrong ayah, and sometimes it returns 0 records.

What I have understand from the ayahinfo table in the database it contains coordinates of each word within the ayah. i.e. Ayah maybe contains 10 words , so we should found 10 records for this Ayah. Each should contains minX, maxX, minY and maxY. am I doing right? or maybe something misunderstand? Your support is really appreciated

murtraja commented 4 years ago

As you can see here, there are very small gaps between the "words" so I suspect that this might be causing the issue with returning 0 records.

There is a tool available that may help you in debugging such issues. In your case use images=1920 as a parameter

ahmedre commented 4 years ago

thanks @murtraja - closing for now, please re-open if you still have issues.

MustafaKhaled commented 4 years ago

Thanks, @murtraja for your support. The problem is not confined in pixels between words, it's sometimes get wrong ayah number after tapping on the screen.

So, I'll show how could I solve this problem in order to make all benefit. 1) I invoke a function called getAyah() which takes user click coordinates and try to figure out the ayah tapped. @Query("@Query("SELECT * FROM glyphs WHERE :positionX BETWEEN min_x AND max_x AND :positionY BETWEEN min_y AND max_y AND page_number=3 LIMIT 1") fun getAyah( positionX: Double, positionY: Double ): List<AyahInformation>

2) Invoke another function called highlightAyah() , this takes ayah number resulted from previous query and get all positions of ayah number. @Query("SELECT * FROM glyphs WHERE :positionX BETWEEN min_x AND max_x AND :positionY BETWEEN min_y AND max_y AND page_number=3 LIMIT 1") fun getAyah( positionX: Double, positionY: Double ): List<AyahInformation>

3) Make the imageView scale fitXY