Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
S
scanqrwhitecopy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wanglei
scanqrwhitecopy
Commits
f2427763
Commit
f2427763
authored
Jan 20, 2025
by
wanglei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
..
parent
b4eb4a7a
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
375 additions
and
2 deletions
+375
-2
SimilarBean.kt
app/src/main/java/com/base/scanqrclear/bean/SimilarBean.kt
+10
-0
ActivityJumpHelps.kt
.../main/java/com/base/scanqrclear/luma/ActivityJumpHelps.kt
+1
-1
BaseActivity2.kt
app/src/main/java/com/base/scanqrclear/luma/BaseActivity2.kt
+1
-1
ImageHelpers.kt
app/src/main/java/com/base/scanqrclear/luma/ImageHelpers.kt
+138
-0
activity_similar_photos.xml
app/src/main/res/layout/activity_similar_photos.xml
+123
-0
item_similar_photos.xml
app/src/main/res/layout/item_similar_photos.xml
+77
-0
item_similar_photos_child.xml
app/src/main/res/layout/item_similar_photos_child.xml
+25
-0
icon_s.png
app/src/main/res/mipmap-xxhdpi/icon_s.png
+0
-0
icon_xuanzhong_photo_on.png
app/src/main/res/mipmap-xxhdpi/icon_xuanzhong_photo_on.png
+0
-0
icon_n.png
app/src/main/res/mipmap-xxxhdpi/icon_n.png
+0
-0
No files found.
app/src/main/java/com/base/scanqrclear/bean/SimilarBean.kt
0 → 100644
View file @
f2427763
package
com.base.scanqrclear.bean
data class
SimilarBean
(
val
url
:
String
,
val
hashCode
:
String
,
val
avgPixel
:
Int
,
val
size
:
Long
,
var
isSelect
:
Boolean
,
var
items
:
MutableList
<
SimilarBean
>
=
mutableListOf
()
)
\ No newline at end of file
app/src/main/java/com/base/scanqrclear/luma/ActivityJumpHelps.kt
View file @
f2427763
...
@@ -27,7 +27,7 @@ object ActivityJumpHelps {
...
@@ -27,7 +27,7 @@ object ActivityJumpHelps {
// R.string.app_manager -> AppManagerActivity.start(context)
// R.string.app_manager -> AppManagerActivity.start(context)
// R.string.large_files -> requestPermission(context, launcher) { LargeFileCleanActivity.start(context) }
// R.string.large_files -> requestPermission(context, launcher) { LargeFileCleanActivity.start(context) }
// R.string.image_compressor -> requestPermission(context, launcher) { PhotoCompressionActivity.start(context) }
// R.string.image_compressor -> requestPermission(context, launcher) { PhotoCompressionActivity.start(context) }
// R.string.similar_photos -> requestPermission(context, launcher) { SimilarPhotosActivity.start(context) }
// R.string.similar_photos -> requestPermission(context, launcher) {
com.base.scanqrclear.luma.
SimilarPhotosActivity.start(context) }
}
}
}
}
...
...
app/src/main/java/com/base/scanqrclear/luma/BaseActivity2.kt
View file @
f2427763
...
@@ -228,7 +228,7 @@ open class BaseActivity2 : AppCompatActivity() {
...
@@ -228,7 +228,7 @@ open class BaseActivity2 : AppCompatActivity() {
// is CleanJunkActivity -> exit(ExitType.CLEAN)
// is CleanJunkActivity -> exit(ExitType.CLEAN)
// is LargeFileCleanActivity -> exit(ExitType.LARGE_FILE)
// is LargeFileCleanActivity -> exit(ExitType.LARGE_FILE)
// is com.base.scanqrclear.luma.ScreenshotCleanActivity -> exit(ExitType.SCREENSHOT)
// is com.base.scanqrclear.luma.ScreenshotCleanActivity -> exit(ExitType.SCREENSHOT)
// is SimilarPhotosActivity -> exit(ExitType.SIMILAR_PHOTOS)
// is
com.base.scanqrclear.luma.
SimilarPhotosActivity -> exit(ExitType.SIMILAR_PHOTOS)
// is com.base.scanqrclear.luma.WhatsappCleanActivity -> exit(ExitType.WHATSAPP)
// is com.base.scanqrclear.luma.WhatsappCleanActivity -> exit(ExitType.WHATSAPP)
// is PhotoCompressionActivity -> exit(ExitType.PHOTO_COMPRESSION)
// is PhotoCompressionActivity -> exit(ExitType.PHOTO_COMPRESSION)
// else -> finishOrToMain()
// else -> finishOrToMain()
...
...
app/src/main/java/com/base/scanqrclear/luma/ImageHelpers.kt
0 → 100644
View file @
f2427763
package
com.base.scanqrclear.luma
import
android.graphics.Bitmap
import
android.graphics.BitmapFactory
import
android.graphics.Color
import
android.media.ThumbnailUtils
import
com.base.scanqrclear.bean.SimilarBean
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
import
java.io.File
import
kotlin.math.pow
object
ImageHelpers
{
private
fun
loadBitmapFromFile
(
path
:
String
):
Bitmap
?
{
val
bitmap
=
BitmapFactory
.
decodeFile
(
path
)
if
(
bitmap
.
width
<=
0
||
bitmap
.
height
<=
0
)
{
return
null
}
val
options
=
BitmapFactory
.
Options
()
options
.
inJustDecodeBounds
=
true
BitmapFactory
.
decodeFile
(
path
,
options
)
if
(
options
.
outHeight
==
-
1
||
options
.
outWidth
==
-
1
)
{
return
null
}
var
inSampleSize
=
(
0.5f
+
options
.
outHeight
.
toFloat
()
/
bitmap
.
height
.
toFloat
()).
coerceAtLeast
(
0.5f
+
options
.
outWidth
.
toFloat
()
/
bitmap
.
width
.
toFloat
())
.
toInt
()
inSampleSize
+=
1
options
.
inSampleSize
=
inSampleSize
.
coerceAtLeast
(
1
)
options
.
inJustDecodeBounds
=
false
return
BitmapFactory
.
decodeFile
(
path
,
options
)
}
suspend
fun
createImage
(
path
:
String
):
SimilarBean
?
{
return
withContext
(
Dispatchers
.
IO
)
{
try
{
val
width
=
8
val
height
=
8
val
source
=
loadBitmapFromFile
(
path
)
val
thumb
=
ThumbnailUtils
.
extractThumbnail
(
source
,
width
,
height
)
val
pixels
=
IntArray
(
width
*
height
)
for
(
i
in
0
until
width
)
{
for
(
j
in
0
until
height
)
{
pixels
[
i
*
height
+
j
]
=
rgbToGray
(
thumb
.
getPixel
(
i
,
j
))
}
}
val
avgPixel
=
average
(
pixels
)
val
comps
=
IntArray
(
width
*
height
)
for
(
i
in
comps
.
indices
)
{
if
(
pixels
[
i
]
>=
avgPixel
)
{
comps
[
i
]
=
1
}
else
{
comps
[
i
]
=
0
}
}
val
hashCode
=
StringBuffer
()
var
i
=
0
while
(
i
<
comps
.
size
)
{
val
result
=
comps
[
i
]
*
2.0
.
pow
(
3.0
).
toInt
()
+
(
comps
[
i
+
1
]
*
2.0
.
pow
(
2.0
)
.
toInt
())
+
(
comps
[
i
+
2
]
*
2.0
.
pow
(
1.0
).
toInt
())
+
comps
[
i
+
3
]
hashCode
.
append
(
binaryToHex
(
result
))
i
+=
4
}
recycleBitmap
(
thumb
)
recycleBitmap
(
source
)
return
@withContext
SimilarBean
(
path
,
hashCode
.
toString
(),
avgPixel
,
File
(
path
).
length
(),
false
)
}
catch
(
_
:
Exception
)
{
return
@withContext
null
}
}
}
private
fun
rgbToGray
(
pixels
:
Int
):
Int
{
val
red
=
Color
.
red
(
pixels
)
val
green
=
Color
.
green
(
pixels
)
val
blue
=
Color
.
blue
(
pixels
)
return
(
0.3
*
red
+
0.59
*
green
+
0.11
*
blue
).
toInt
()
}
private
fun
average
(
pixels
:
IntArray
):
Int
{
return
(
pixels
.
sumOf
{
it
}.
toFloat
()
/
pixels
.
size
).
toInt
()
}
private
fun
recycleBitmap
(
thumb
:
Bitmap
?)
{
if
(
thumb
?.
isRecycled
==
false
)
{
thumb
.
recycle
()
}
}
fun
similarCondition
(
first
:
SimilarBean
,
second
:
SimilarBean
):
Boolean
{
return
hammingDistance
(
first
.
hashCode
,
second
.
hashCode
)
<=
6
&&
(
first
.
avgPixel
.
toFloat
()
/
second
.
avgPixel
)
in
0.8
..
1.0
}
private
fun
hammingDistance
(
sourceHashCode
:
String
,
hashCode
:
String
):
Int
{
var
difference
=
0
for
(
i
in
sourceHashCode
.
indices
)
{
if
(
sourceHashCode
[
i
]
!=
hashCode
[
i
])
{
difference
++
}
}
return
difference
}
private
fun
binaryToHex
(
binary
:
Int
)
=
when
(
binary
)
{
0
->
'0'
1
->
'1'
2
->
'2'
3
->
'3'
4
->
'4'
5
->
'5'
6
->
'6'
7
->
'7'
8
->
'8'
9
->
'9'
10
->
'a'
11
->
'b'
12
->
'c'
13
->
'd'
14
->
'e'
15
->
'f'
else
->
' '
}
}
\ No newline at end of file
app/src/main/res/layout/activity_similar_photos.xml
0 → 100644
View file @
f2427763
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@color/color_f7fafa"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:id=
"@+id/cl_top"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:background=
"@drawable/gradient_background"
app:layout_constraintTop_toTopOf=
"parent"
>
<androidx.appcompat.widget.LinearLayoutCompat
android:id=
"@+id/ll_title"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:gravity=
"center_vertical"
android:orientation=
"horizontal"
android:paddingTop=
"6dp"
android:paddingBottom=
"6dp"
app:layout_constraintTop_toTopOf=
"parent"
>
<FrameLayout
android:id=
"@+id/fl_back"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"11dp"
android:padding=
"4dp"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
>
<androidx.appcompat.widget.AppCompatImageView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:src=
"@mipmap/icon_return_bar_nor"
/>
</FrameLayout>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"@string/similar_photos"
android:textColor=
"@color/white"
android:textSize=
"20sp"
android:textStyle=
"bold"
app:layout_constraintBottom_toBottomOf=
"@id/fl_back"
app:layout_constraintStart_toEndOf=
"@id/fl_back"
app:layout_constraintTop_toTopOf=
"@id/fl_back"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id=
"@+id/cl_select"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:background=
"@color/white"
app:layout_constraintTop_toBottomOf=
"@id/cl_top"
>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginVertical=
"13dp"
android:layout_marginStart=
"15dp"
android:text=
"@string/auto_select"
android:textColor=
"@color/black"
android:textSize=
"18sp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/iv_select"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginEnd=
"24dp"
android:src=
"@mipmap/icon_n"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.base.scanqrclear.luma.NativeView
android:id=
"@+id/ad_native"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginHorizontal=
"15dp"
android:layout_marginTop=
"10dp"
android:visibility=
"gone"
app:layout_constraintTop_toBottomOf=
"@id/cl_select"
/>
<androidx.recyclerview.widget.RecyclerView
android:id=
"@+id/rv_photo"
android:layout_width=
"match_parent"
android:layout_height=
"0dp"
android:layout_marginBottom=
"20dp"
android:scrollbars=
"none"
app:layout_constraintBottom_toTopOf=
"@id/tv_delete"
app:layout_constraintTop_toBottomOf=
"@id/ad_native"
/>
<TextView
android:id=
"@+id/tv_delete"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginHorizontal=
"30dp"
android:layout_marginBottom=
"55dp"
android:background=
"@drawable/gradient_not_clickable"
android:gravity=
"center"
android:paddingVertical=
"12dp"
android:text=
"@string/delete"
android:textColor=
"@color/white"
android:textSize=
"18sp"
android:textStyle=
"bold"
app:layout_constraintBottom_toBottomOf=
"parent"
/>
<include
android:id=
"@+id/animation"
layout=
"@layout/custom_animation"
android:visibility=
"gone"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
app/src/main/res/layout/item_similar_photos.xml
0 → 100644
View file @
f2427763
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"8dp"
>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/tv_occupies"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"7dp"
android:text=
"@string/occupies"
android:textColor=
"@color/color_9b9595"
android:textSize=
"14sp"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id=
"@+id/tv_size"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"7dp"
android:text=
"0B"
android:textColor=
"@color/color_9b9595"
android:textSize=
"14sp"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintStart_toEndOf=
"@id/tv_occupies"
/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id=
"@+id/cl_large"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
app:layout_constraintTop_toBottomOf=
"@id/tv_occupies"
>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/iv_first_photo"
android:layout_width=
"200dp"
android:layout_height=
"200dp"
android:layout_marginTop=
"4dp"
android:layout_marginStart=
"15dp"
android:src=
"@color/black"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
/>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/iv_select"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"10dp"
android:layout_marginEnd=
"8dp"
android:src=
"@mipmap/icon_weixuanzhong_photo_off"
app:layout_constraintTop_toTopOf=
"@id/iv_first_photo"
app:layout_constraintEnd_toEndOf=
"@id/iv_first_photo"
/>
<androidx.recyclerview.widget.RecyclerView
android:id=
"@+id/rv_large_photo"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"4dp"
android:layout_marginEnd=
"15dp"
android:scrollbars=
"none"
android:nestedScrollingEnabled=
"false"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toEndOf=
"@id/iv_first_photo"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id=
"@+id/rv_photo"
android:layout_width=
"match_parent"
android:layout_height=
"0dp"
android:paddingHorizontal=
"15dp"
android:paddingBottom=
"10dp"
android:scrollbars=
"none"
android:nestedScrollingEnabled=
"false"
app:layout_constraintTop_toBottomOf=
"@id/cl_large"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
app/src/main/res/layout/item_similar_photos_child.xml
0 → 100644
View file @
f2427763
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/iv_photo"
android:layout_width=
"80dp"
android:layout_height=
"73dp"
android:layout_marginTop=
"4dp"
android:src=
"@color/color_9b9595"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
/>
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/iv_select"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"10dp"
android:layout_marginEnd=
"8dp"
android:src=
"@mipmap/icon_weixuanzhong_photo_off"
app:layout_constraintTop_toTopOf=
"@id/iv_photo"
app:layout_constraintEnd_toEndOf=
"@id/iv_photo"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
app/src/main/res/mipmap-xxhdpi/icon_s.png
0 → 100644
View file @
f2427763
2.82 KB
app/src/main/res/mipmap-xxhdpi/icon_xuanzhong_photo_on.png
0 → 100644
View file @
f2427763
6.69 KB
app/src/main/res/mipmap-xxxhdpi/icon_n.png
0 → 100644
View file @
f2427763
2.71 KB
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment