Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
I
ImageVideoBanner
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
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
jiangjiantao
ImageVideoBanner
Commits
b6da758b
Commit
b6da758b
authored
Nov 10, 2021
by
jiangjiantao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新版banner
parent
8552baff
Hide whitespace changes
Inline
Side-by-side
Showing
48 changed files
with
5501 additions
and
608 deletions
+5501
-608
build.gradle
build.gradle
+1
-1
build.gradle
imageVideoBanner/build.gradle
+10
-12
AndroidManifest.xml
imageVideoBanner/src/main/AndroidManifest.xml
+0
-1
DetailActivity.java
...main/java/com/widget/imagevideobanner/DetailActivity.java
+0
-1
MainActivity.java
...c/main/java/com/widget/imagevideobanner/MainActivity.java
+5
-11
MediaBean.java
...main/java/com/widget/imagevideobanner/bean/MediaBean.java
+45
-17
BitmapCache.java
...n/java/com/widget/imagevideobanner/cache/BitmapCache.java
+4
-4
BLogUtil.java
...c/main/java/com/widget/imagevideobanner/log/BLogUtil.java
+24
-0
FileUtils.java
.../main/java/com/widget/imagevideobanner/log/FileUtils.java
+33
-38
PlayerManager.java
...ava/com/widget/imagevideobanner/player/PlayerManager.java
+0
-136
DateUtils.java
...ain/java/com/widget/imagevideobanner/utils/DateUtils.java
+367
-0
QRCodeUtil.java
...in/java/com/widget/imagevideobanner/utils/QRCodeUtil.java
+217
-0
ResourceUtils.java
...java/com/widget/imagevideobanner/utils/ResourceUtils.java
+109
-0
TransformationUtils.java
...om/widget/imagevideobanner/utils/TransformationUtils.java
+34
-0
BarcodeFormat.java
...om/widget/imagevideobanner/utils/zxing/BarcodeFormat.java
+77
-0
BitArray.java
...ava/com/widget/imagevideobanner/utils/zxing/BitArray.java
+298
-0
BitMatrix.java
...va/com/widget/imagevideobanner/utils/zxing/BitMatrix.java
+273
-0
BlockPair.java
...va/com/widget/imagevideobanner/utils/zxing/BlockPair.java
+37
-0
ByteMatrix.java
...a/com/widget/imagevideobanner/utils/zxing/ByteMatrix.java
+98
-0
CharacterSetECI.java
.../widget/imagevideobanner/utils/zxing/CharacterSetECI.java
+103
-0
EncodeHintType.java
...m/widget/imagevideobanner/utils/zxing/EncodeHintType.java
+104
-0
Encoder.java
...java/com/widget/imagevideobanner/utils/zxing/Encoder.java
+595
-0
ErrorCorrectionLevel.java
...et/imagevideobanner/utils/zxing/ErrorCorrectionLevel.java
+60
-0
FormatException.java
.../widget/imagevideobanner/utils/zxing/FormatException.java
+36
-0
FormatInformation.java
...idget/imagevideobanner/utils/zxing/FormatInformation.java
+157
-0
GenericGF.java
...va/com/widget/imagevideobanner/utils/zxing/GenericGF.java
+166
-0
GenericGFPoly.java
...om/widget/imagevideobanner/utils/zxing/GenericGFPoly.java
+225
-0
MaskUtil.java
...ava/com/widget/imagevideobanner/utils/zxing/MaskUtil.java
+221
-0
MatrixUtil.java
...a/com/widget/imagevideobanner/utils/zxing/MatrixUtil.java
+475
-0
Mode.java
...in/java/com/widget/imagevideobanner/utils/zxing/Mode.java
+102
-0
QRCode.java
.../java/com/widget/imagevideobanner/utils/zxing/QRCode.java
+96
-0
QRCodeWriter.java
...com/widget/imagevideobanner/utils/zxing/QRCodeWriter.java
+108
-0
ReaderException.java
.../widget/imagevideobanner/utils/zxing/ReaderException.java
+43
-0
ReedSolomonEncoder.java
...dget/imagevideobanner/utils/zxing/ReedSolomonEncoder.java
+74
-0
Version.java
...java/com/widget/imagevideobanner/utils/zxing/Version.java
+485
-0
Writer.java
.../java/com/widget/imagevideobanner/utils/zxing/Writer.java
+57
-0
WriterException.java
.../widget/imagevideobanner/utils/zxing/WriterException.java
+38
-0
ImageSubView.java
...n/java/com/widget/imagevideobanner/view/ImageSubView.java
+84
-0
ImageVideoBanner.java
...va/com/widget/imagevideobanner/view/ImageVideoBanner.java
+130
-43
SampleCoverVideo.java
...va/com/widget/imagevideobanner/view/SampleCoverVideo.java
+271
-0
VideoSubView.java
...n/java/com/widget/imagevideobanner/view/VideoSubView.java
+69
-0
ViewPager.java
...main/java/com/widget/imagevideobanner/view/ViewPager.java
+1
-1
VpVideoView.java
...in/java/com/widget/imagevideobanner/view/VpVideoView.java
+0
-298
guide_defaut.png
imageVideoBanner/src/main/res/drawable-mdpi/guide_defaut.png
+0
-0
layout_exo_player_view.xml
...ideoBanner/src/main/res/layout/layout_exo_player_view.xml
+0
-15
layout_player_view.xml
imageVideoBanner/src/main/res/layout/layout_player_view.xml
+6
-30
video_layout_cover.xml
imageVideoBanner/src/main/res/layout/video_layout_cover.xml
+163
-0
default_guide.mp4
imageVideoBanner/src/main/res/raw/default_guide.mp4
+0
-0
No files found.
build.gradle
View file @
b6da758b
...
@@ -7,7 +7,7 @@ buildscript {
...
@@ -7,7 +7,7 @@ buildscript {
jcenter
()
jcenter
()
}
}
dependencies
{
dependencies
{
classpath
'com.android.tools.build:gradle:3.5.
2
'
classpath
'com.android.tools.build:gradle:3.5.
1
'
// NOTE: Do not place your application dependencies here; they belong
// NOTE: Do not place your application dependencies here; they belong
...
...
imageVideoBanner/build.gradle
View file @
b6da758b
apply
plugin:
'com.android.
application
'
apply
plugin:
'com.android.
library
'
android
{
android
{
compileSdkVersion
28
compileSdkVersion
28
defaultConfig
{
defaultConfig
{
minSdkVersion
22
minSdkVersion
18
targetSdkVersion
22
targetSdkVersion
22
versionCode
1
versionCode
1
versionName
"1.0"
versionName
"1.0"
...
@@ -21,17 +21,15 @@ dependencies {
...
@@ -21,17 +21,15 @@ dependencies {
implementation
fileTree
(
dir:
'libs'
,
include:
[
'*.jar'
])
implementation
fileTree
(
dir:
'libs'
,
include:
[
'*.jar'
])
implementation
'com.android.support:appcompat-v7:28.0.0'
implementation
'com.android.support:appcompat-v7:28.0.0'
implementation
'com.android.support.constraint:constraint-layout:1.1.0'
implementation
'com.android.support.constraint:constraint-layout:1.1.0'
implementation
'com.github.bumptech.glide:glide:
4.9
.0'
implementation
'com.github.bumptech.glide:glide:
3.7
.0'
//当需要FFmpegMediaMetadataRetriever时必选
//当需要FFmpegMediaMetadataRetriever时必选
implementation
'com.github.wseemann:FFmpegMediaMetadataRetriever-armeabi-v7a:1.0.14'
implementation
'com.github.wseemann:FFmpegMediaMetadataRetriever-armeabi-v7a:1.0.14'
implementation
'com.wang.avi:library:2.1.3'
implementation
'com.wang.avi:library:2.1.3'
implementation
(
'com.shuyu:GSYVideoPlayer:6.0.1'
)
{
// implementation 'com.google.android.exoplayer:exoplayer:2.13.3'
exclude
module:
'support-v4'
exclude
group:
'com.android.support'
//视频播放组件
}
api
'com.google.android.exoplayer:exoplayer-core:2.7.2'
// api 'jp.wasabeef:glide-transformations:4.0.0'
api
'com.google.android.exoplayer:exoplayer-dash:2.7.2'
api
'com.alibaba:fastjson:1.2.8'
api
'com.google.android.exoplayer:exoplayer-ui:2.7.2'
api
'com.blankj:utilcode:1.30.0'
api
'jp.wasabeef:glide-transformations:4.0.0'
}
}
imageVideoBanner/src/main/AndroidManifest.xml
View file @
b6da758b
...
@@ -8,7 +8,6 @@
...
@@ -8,7 +8,6 @@
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
<application
<application
android:name=
".BaseApplication"
android:allowBackup=
"true"
android:allowBackup=
"true"
android:icon=
"@mipmap/ic_launcher"
android:icon=
"@mipmap/ic_launcher"
android:label=
"@string/app_name"
android:label=
"@string/app_name"
...
...
imageVideoBanner/src/main/java/com/widget/imagevideobanner/DetailActivity.java
View file @
b6da758b
...
@@ -12,7 +12,6 @@ import java.util.List;
...
@@ -12,7 +12,6 @@ import java.util.List;
public
class
DetailActivity
extends
AppCompatActivity
{
public
class
DetailActivity
extends
AppCompatActivity
{
private
List
<
MediaBean
>
list
=
new
ArrayList
<>();
@Override
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
...
...
imageVideoBanner/src/main/java/com/widget/imagevideobanner/MainActivity.java
View file @
b6da758b
...
@@ -29,31 +29,25 @@ public class MainActivity extends AppCompatActivity {
...
@@ -29,31 +29,25 @@ public class MainActivity extends AppCompatActivity {
MediaBean
mediaBean
=
new
MediaBean
();
MediaBean
mediaBean
=
new
MediaBean
();
mediaBean
.
setUrl
(
"https://hh-oss-html.miyapay.com/hhops/picture/16045733014903c31992a674f.png"
);
mediaBean
.
setUrl
(
"https://hh-oss-html.miyapay.com/hhops/picture/16045733014903c31992a674f.png"
);
mediaBean
.
set
Res
Type
(
TYPE_IMAGE
);
mediaBean
.
setType
(
TYPE_IMAGE
);
list
.
add
(
mediaBean
);
list
.
add
(
mediaBean
);
MediaBean
mediaBean2
=
new
MediaBean
();
MediaBean
mediaBean2
=
new
MediaBean
();
mediaBean2
.
setUrl
(
"https://hh-oss-html.miyapay.com/hhops/picture/1611112341654cffdd7b004bb.png"
);
mediaBean2
.
setUrl
(
"https://hh-oss-html.miyapay.com/hhops/picture/1611112341654cffdd7b004bb.png"
);
mediaBean2
.
set
Res
Type
(
TYPE_IMAGE
);
mediaBean2
.
setType
(
TYPE_IMAGE
);
list
.
add
(
mediaBean2
);
list
.
add
(
mediaBean2
);
// String basePath = "http://miya-hz.oss-cn-shanghai.aliyuncs.com/huihua-test/face-pay/archive/";
// String basePath = "http://miya-hz.oss-cn-shanghai.aliyuncs.com/huihua-test/face-pay/archive/";
String
basePath
=
Environment
.
getExternalStorageDirectory
().
getPath
()+
"/"
;
String
basePath
=
Environment
.
getExternalStorageDirectory
().
getPath
()+
"/"
;
MediaBean
mediaBean3
=
new
MediaBean
();
MediaBean
mediaBean3
=
new
MediaBean
();
mediaBean3
.
setUrl
(
basePath
+
"shu.mp4"
);
mediaBean3
.
setUrl
(
basePath
+
"shu.mp4"
);
mediaBean3
.
setCover
(
basePath
+
"shu.jpeg"
);
mediaBean3
.
setType
(
TYPE_VIDEO
);
mediaBean3
.
setWidth
(
1080
);
mediaBean3
.
setHeight
(
1440
);
mediaBean3
.
setResType
(
TYPE_VIDEO
);
list
.
add
(
mediaBean3
);
list
.
add
(
mediaBean3
);
MediaBean
mediaBean4
=
new
MediaBean
();
MediaBean
mediaBean4
=
new
MediaBean
();
mediaBean4
.
setUrl
(
basePath
+
"heng.mp4"
);
mediaBean4
.
setUrl
(
basePath
+
"heng.mp4"
);
mediaBean4
.
setCover
(
basePath
+
"heng.jpeg"
);
mediaBean4
.
setType
(
TYPE_VIDEO
);
mediaBean4
.
setWidth
(
1440
);
mediaBean4
.
setHeight
(
1080
);
mediaBean4
.
setResType
(
TYPE_VIDEO
);
list
.
add
(
mediaBean4
);
list
.
add
(
mediaBean4
);
banner
.
bindData
(
list
);
banner
.
bindData
(
list
);
...
...
imageVideoBanner/src/main/java/com/widget/imagevideobanner/bean/MediaBean.java
View file @
b6da758b
package
com
.
widget
.
imagevideobanner
.
bean
;
package
com
.
widget
.
imagevideobanner
.
bean
;
import
android.
support.annotation.Nullable
;
import
android.
content.Context
;
import
android.text.TextUtils
;
import
android.text.TextUtils
;
import
com.widget.imagevideobanner.R
;
import
com.widget.imagevideobanner.utils.ResourceUtils
;
import
java.io.Serializable
;
import
java.io.Serializable
;
/**
/**
...
@@ -15,12 +18,24 @@ public class MediaBean implements Serializable {
...
@@ -15,12 +18,24 @@ public class MediaBean implements Serializable {
private
String
url
;
private
String
url
;
//资源类型
//资源类型
private
int
resT
ype
;
private
int
t
ype
;
//视频的封面
//视频的封面
private
String
cover
;
private
String
cover
;
private
int
width
;
private
int
width
;
private
int
height
;
private
int
height
;
private
boolean
looping
;
public
MediaBean
()
{
}
public
MediaBean
(
String
url
,
int
type
,
String
cover
,
int
width
,
int
height
)
{
this
.
url
=
url
;
this
.
type
=
type
;
this
.
cover
=
cover
;
this
.
width
=
width
;
this
.
height
=
height
;
}
public
String
getUrl
()
{
public
String
getUrl
()
{
return
url
;
return
url
;
...
@@ -30,12 +45,12 @@ public class MediaBean implements Serializable {
...
@@ -30,12 +45,12 @@ public class MediaBean implements Serializable {
this
.
url
=
url
;
this
.
url
=
url
;
}
}
public
int
get
Res
Type
()
{
public
int
getType
()
{
return
resT
ype
;
return
t
ype
;
}
}
public
void
set
ResType
(
int
resT
ype
)
{
public
void
set
Type
(
int
t
ype
)
{
this
.
resType
=
resT
ype
;
this
.
type
=
t
ype
;
}
}
public
String
getCover
()
{
public
String
getCover
()
{
...
@@ -61,27 +76,40 @@ public class MediaBean implements Serializable {
...
@@ -61,27 +76,40 @@ public class MediaBean implements Serializable {
public
void
setHeight
(
int
height
)
{
public
void
setHeight
(
int
height
)
{
this
.
height
=
height
;
this
.
height
=
height
;
}
}
public
boolean
isLooping
()
{
return
looping
;
}
public
void
setLooping
(
boolean
looping
)
{
this
.
looping
=
looping
;
}
/**
* 默认资源
* @param context
* @return
*/
public
static
MediaBean
getDefaultMedia
(
Context
context
){
MediaBean
mediaBean
=
new
MediaBean
();
mediaBean
.
setType
(
TYPE_IMAGE
);
mediaBean
.
setUrl
(
ResourceUtils
.
imageTranslateUri
(
context
,
R
.
drawable
.
guide_defaut
));
mediaBean
.
setWidth
(
1080
);
mediaBean
.
setHeight
(
1186
);
return
mediaBean
;
}
@Override
@Override
public
boolean
equals
(
@Nullable
Object
obj
)
{
public
boolean
equals
(
Object
obj
)
{
if
(!(
obj
instanceof
MediaBean
))
if
(!(
obj
instanceof
MediaBean
))
return
false
;
return
false
;
MediaBean
mediaBean
=
(
MediaBean
)
obj
;
MediaBean
mediaBean
=
(
MediaBean
)
obj
;
return
resType
==
mediaBean
.
resT
ype
return
type
==
mediaBean
.
t
ype
&&
width
==
mediaBean
.
width
&&
width
==
mediaBean
.
width
&&
height
==
mediaBean
.
height
&&
height
==
mediaBean
.
height
&&
TextUtils
.
equals
(
url
,
mediaBean
.
url
)
&&
TextUtils
.
equals
(
url
,
mediaBean
.
url
)
&&
TextUtils
.
equals
(
cover
,
mediaBean
.
cover
);
&&
TextUtils
.
equals
(
cover
,
mediaBean
.
cover
);
}
}
public
boolean
isNull
()
{
if
(
resType
==
TYPE_IMAGE
)
{
return
TextUtils
.
isEmpty
(
url
)
;
}
return
(
width
==
0
)
||
(
height
==
0
)
||
TextUtils
.
isEmpty
(
cover
)
||
TextUtils
.
isEmpty
(
url
)
;
}
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/cache/BitmapCache.java
View file @
b6da758b
...
@@ -11,7 +11,7 @@ import android.util.LruCache;
...
@@ -11,7 +11,7 @@ import android.util.LruCache;
import
com.widget.imagevideobanner.BuildConfig
;
import
com.widget.imagevideobanner.BuildConfig
;
import
com.widget.imagevideobanner.cache.disk.DiskLruCache
;
import
com.widget.imagevideobanner.cache.disk.DiskLruCache
;
import
com.widget.imagevideobanner.log.B
annerLogFileUtils
;
import
com.widget.imagevideobanner.log.B
LogUtil
;
import
com.widget.imagevideobanner.utils.BitmapUtils
;
import
com.widget.imagevideobanner.utils.BitmapUtils
;
import
com.widget.imagevideobanner.utils.MD5Util
;
import
com.widget.imagevideobanner.utils.MD5Util
;
import
com.widget.imagevideobanner.utils.ThrowableUtils
;
import
com.widget.imagevideobanner.utils.ThrowableUtils
;
...
@@ -80,12 +80,12 @@ public class BitmapCache {
...
@@ -80,12 +80,12 @@ public class BitmapCache {
size
=
bitmap
.
getAllocationByteCount
()
/
1024
;
size
=
bitmap
.
getAllocationByteCount
()
/
1024
;
}
}
Log
.
e
(
TAG
,
"已经加入内存缓存 size ="
+
size
);
Log
.
e
(
TAG
,
"已经加入内存缓存 size ="
+
size
);
B
annerLogFileUtils
.
writeL
og
(
"已经加入内存缓存 size ="
+
size
);
B
LogUtil
.
l
og
(
"已经加入内存缓存 size ="
+
size
);
return
size
;
return
size
;
}
}
@Override
@Override
protected
void
entryRemoved
(
boolean
evicted
,
String
key
,
Bitmap
oldValue
,
Bitmap
newValue
)
{
protected
void
entryRemoved
(
boolean
evicted
,
String
key
,
Bitmap
oldValue
,
Bitmap
newValue
)
{
B
annerLogFileUtils
.
writeL
og
(
"内存缓存移除 key ="
+
key
);
B
LogUtil
.
l
og
(
"内存缓存移除 key ="
+
key
);
Log
.
e
(
TAG
,
"内存缓存移除 key ="
+
key
);
Log
.
e
(
TAG
,
"内存缓存移除 key ="
+
key
);
//todo bitmap复用
//todo bitmap复用
oldValue
.
recycle
();
oldValue
.
recycle
();
...
@@ -173,7 +173,7 @@ public class BitmapCache {
...
@@ -173,7 +173,7 @@ public class BitmapCache {
putBitmap2Disk
(
blurkey
,
blurBitmap
);
putBitmap2Disk
(
blurkey
,
blurBitmap
);
}
catch
(
Exception
e
){
}
catch
(
Exception
e
){
e
.
printStackTrace
();
e
.
printStackTrace
();
B
annerLogFileUtils
.
writeL
og
(
"截取视频首帧出错 url ="
+
url
+
"出错原因是:"
+
ThrowableUtils
.
getFullStackTrace
(
e
));
B
LogUtil
.
l
og
(
"截取视频首帧出错 url ="
+
url
+
"出错原因是:"
+
ThrowableUtils
.
getFullStackTrace
(
e
));
}
}
}
}
});
});
...
...
imageVideoBanner/src/main/java/com/widget/imagevideobanner/log/BLogUtil.java
0 → 100644
View file @
b6da758b
package
com
.
widget
.
imagevideobanner
.
log
;
import
com.blankj.utilcode.util.LogUtils
;
import
com.widget.imagevideobanner.utils.DateUtils
;
import
java.util.Date
;
public
class
BLogUtil
{
private
static
LogWriteListener
mLogWriteListener
;
public
static
void
setBLogWriteListener
(
LogWriteListener
bLogWriteListener
)
{
mLogWriteListener
=
bLogWriteListener
;
}
public
static
void
log
(
final
String
input
)
{
LogUtils
.
e
(
input
);
if
(
null
!=
mLogWriteListener
)
{
mLogWriteListener
.
onLogWriteListener
(
DateUtils
.
format18
(
new
Date
())
+
input
+
"\n"
);
}
}
public
interface
LogWriteListener
{
void
onLogWriteListener
(
String
msg
);
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/log/
BannerLog
FileUtils.java
→
imageVideoBanner/src/main/java/com/widget/imagevideobanner/log/FileUtils.java
View file @
b6da758b
package
com
.
widget
.
imagevideobanner
.
log
;
package
com
.
widget
.
imagevideobanner
.
log
;
import
android.annotation.SuppressLint
;
import
android.content.Context
;
import
android.os.Environment
;
import
android.os.Environment
;
import
android.text.TextUtils
;
import
android.text.TextUtils
;
import
java.io.File
;
import
java.io.File
;
import
java.io.FileNotFoundException
;
import
java.io.FileOutputStream
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStreamWriter
;
import
java.io.OutputStreamWriter
;
import
java.nio.charset.
Charset
;
import
java.nio.charset.
StandardCharsets
;
import
java.text.SimpleDateFormat
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
java.util.Date
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
public
class
BannerLogFileUtils
{
/**
* 日志打印
*/
public
class
FileUtils
{
private
static
ExecutorService
sExecutor
;
@SuppressLint
(
"SimpleDateFormat"
)
private
static
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
);
private
static
final
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
);
private
static
final
String
BANNER_LOG_DIR
=
Environment
.
getExternalStorageDirectory
().
getPath
()
+
File
.
separator
+
"miyaterminal"
+
File
.
separator
+
"log"
+
File
.
separator
+
"bannererr.log"
;
static
{
public
static
void
writeFileLog
(
String
filePath
,
String
input
)
{
File
logFiles
=
new
File
(
BANNER_LOG_DIR
);
if
(!
logFiles
.
exists
())
{
logFiles
.
mkdirs
();
}
}
public
static
void
writeLog
(
final
String
input
)
{
if
(
sExecutor
==
null
)
{
sExecutor
=
Executors
.
newSingleThreadExecutor
();
}
sExecutor
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
writeFileLog
(
input
);
}
});
}
private
static
void
writeFileLog
(
String
input
)
{
if
(
TextUtils
.
isEmpty
(
input
))
{
if
(
TextUtils
.
isEmpty
(
input
))
{
return
;
return
;
}
}
...
@@ -53,10 +32,10 @@ public class BannerLogFileUtils {
...
@@ -53,10 +32,10 @@ public class BannerLogFileUtils {
FileOutputStream
fos
=
null
;
FileOutputStream
fos
=
null
;
OutputStreamWriter
writer
=
null
;
OutputStreamWriter
writer
=
null
;
try
{
try
{
File
logFile
=
new
File
(
BANNER_LOG_DIR
);
File
logFile
=
new
File
(
filePath
);
if
(!
logFile
.
exists
()
&&
!
logFile
.
createNewFile
())
return
;
if
(!
logFile
.
exists
()
&&
!
logFile
.
createNewFile
())
return
;
fos
=
new
FileOutputStream
(
logFile
,
true
);
fos
=
new
FileOutputStream
(
logFile
,
true
);
writer
=
new
OutputStreamWriter
(
fos
,
Charset
.
forName
(
"utf-8"
)
);
writer
=
new
OutputStreamWriter
(
fos
,
StandardCharsets
.
UTF_8
);
writer
.
write
(
input
);
writer
.
write
(
input
);
writer
.
flush
();
writer
.
flush
();
writer
.
close
();
writer
.
close
();
...
@@ -80,8 +59,24 @@ public class BannerLogFileUtils {
...
@@ -80,8 +59,24 @@ public class BannerLogFileUtils {
}
}
}
}
public
static
File
getDownloadDir
(
Context
context
)
{
File
downloadDir
=
null
;
if
(
Environment
.
getExternalStorageState
().
equals
(
Environment
.
MEDIA_MOUNTED
))
{
if
(
context
.
getExternalCacheDir
()
!=
null
){
downloadDir
=
new
File
(
context
.
getExternalCacheDir
(),
"VIDEO-AD"
);
}
}
else
{
if
(
context
.
getCacheDir
()
!=
null
){
downloadDir
=
new
File
(
context
.
getCacheDir
(),
"VIDEO-AD"
);
}
}
if
(
downloadDir
==
null
){
downloadDir
=
new
File
(
Environment
.
getExternalStorageDirectory
().
getAbsolutePath
(),
"VIDEO-AD"
);
}
if
(!
downloadDir
.
exists
())
{
downloadDir
.
mkdirs
();
}
return
downloadDir
;
}
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/player/PlayerManager.java
deleted
100755 → 0
View file @
8552baff
package
com
.
widget
.
imagevideobanner
.
player
;
import
android.app.Application
;
import
android.net.Uri
;
import
android.util.Log
;
import
android.view.LayoutInflater
;
import
com.google.android.exoplayer2.DefaultLoadControl
;
import
com.google.android.exoplayer2.ExoPlayerFactory
;
import
com.google.android.exoplayer2.SimpleExoPlayer
;
import
com.google.android.exoplayer2.source.ExtractorMediaSource
;
import
com.google.android.exoplayer2.source.MediaSource
;
import
com.google.android.exoplayer2.trackselection.DefaultTrackSelector
;
import
com.google.android.exoplayer2.ui.PlayerView
;
import
com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory
;
import
com.google.android.exoplayer2.upstream.FileDataSourceFactory
;
import
com.google.android.exoplayer2.upstream.cache.Cache
;
import
com.google.android.exoplayer2.upstream.cache.CacheDataSinkFactory
;
import
com.google.android.exoplayer2.upstream.cache.CacheDataSource
;
import
com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory
;
import
com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor
;
import
com.google.android.exoplayer2.upstream.cache.SimpleCache
;
import
com.google.android.exoplayer2.util.Util
;
import
com.widget.imagevideobanner.BaseApplication
;
import
com.widget.imagevideobanner.R
;
import
java.io.File
;
import
java.util.HashMap
;
public
class
PlayerManager
{
private
ExtractorMediaSource
.
Factory
networkMediaSourceFactory
;
private
ExtractorMediaSource
.
Factory
localMediaSourceFactory
;
public
SimpleExoPlayer
exoPlayer
;
public
PlayerView
playerView
;
public
String
playUrl
;
private
static
PlayerManager
mInstance
;
private
HashMap
<
String
,
MediaSource
>
mediaSourceHashMap
=
new
HashMap
<>();
public
PlayerManager
()
{
Application
application
=
BaseApplication
.
getApplication
();
buildLocalMediaSourceFactory
(
application
);
buildNetworkMediaSourceFactory
(
application
);
buildPlayerAndView
(
application
);
}
private
void
buildPlayerAndView
(
Application
application
){
//创建exoplayer播放器实例
exoPlayer
=
ExoPlayerFactory
.
newSimpleInstance
(
application
,
//视频的音视频轨道如何加载,使用默认的轨道选择器
new
DefaultTrackSelector
(),
//视频缓存控制逻辑,使用默认的即可
new
DefaultLoadControl
());
//加载咱们布局层级优化之后的能够展示视频画面的View
playerView
=
(
PlayerView
)
LayoutInflater
.
from
(
application
).
inflate
(
R
.
layout
.
layout_exo_player_view
,
null
,
false
);
//别忘记 把播放器实例 和 playerView,controlView相关联
//如此视频画面才能正常显示,播放进度条才能自动更新
playerView
.
setPlayer
(
exoPlayer
);
}
private
void
buildNetworkMediaSourceFactory
(
Application
application
){
DefaultHttpDataSourceFactory
dataSourceFactory
=
new
DefaultHttpDataSourceFactory
(
Util
.
getUserAgent
(
application
,
application
.
getPackageName
()));
//创建缓存,指定缓存位置,和缓存策略,为最近最少使用原则,最大为200m
Cache
cache
=
new
SimpleCache
(
application
.
getCacheDir
(),
new
LeastRecentlyUsedCacheEvictor
(
1024
*
1024
*
200
));
//把缓存对象cache和负责缓存数据读取、写入的工厂类CacheDataSinkFactory 相关联
CacheDataSinkFactory
cacheDataSinkFactory
=
new
CacheDataSinkFactory
(
cache
,
Long
.
MAX_VALUE
);
CacheDataSourceFactory
cacheDataSourceFactory
=
new
CacheDataSourceFactory
(
cache
,
dataSourceFactory
,
new
FileDataSourceFactory
(),
cacheDataSinkFactory
,
CacheDataSource
.
FLAG_BLOCK_ON_CACHE
,
null
);
networkMediaSourceFactory
=
new
ExtractorMediaSource
.
Factory
(
cacheDataSourceFactory
);
}
private
void
buildLocalMediaSourceFactory
(
Application
application
){
FileDataSourceFactory
fileDataSourceFactory
=
new
FileDataSourceFactory
();
//创建缓存,指定缓存位置,和缓存策略,为最近最少使用原则,最大为200m
Cache
cache
=
new
SimpleCache
(
application
.
getCacheDir
(),
new
LeastRecentlyUsedCacheEvictor
(
1024
*
1024
*
200
));
//把缓存对象cache和负责缓存数据读取、写入的工厂类CacheDataSinkFactory 相关联
CacheDataSinkFactory
cacheDataSinkFactory
=
new
CacheDataSinkFactory
(
cache
,
Long
.
MAX_VALUE
);
CacheDataSourceFactory
cacheDataSourceFactory
=
new
CacheDataSourceFactory
(
cache
,
fileDataSourceFactory
,
new
FileDataSourceFactory
(),
cacheDataSinkFactory
,
CacheDataSource
.
FLAG_BLOCK_ON_CACHE
,
new
CacheDataSource
.
EventListener
()
{
@Override
public
void
onCachedBytesRead
(
long
cacheSizeBytes
,
long
cachedBytesRead
)
{
Log
.
e
(
"###视频缓存 "
,
"cachedBytesRead ="
+
cachedBytesRead
+
"cacheSizeBytes = "
+
cacheSizeBytes
);
}
});
localMediaSourceFactory
=
new
ExtractorMediaSource
.
Factory
(
cacheDataSourceFactory
);
}
public
static
PlayerManager
getInstance
(){
if
(
mInstance
==
null
)
{
synchronized
(
PlayerManager
.
class
)
{
if
(
mInstance
==
null
)
{
mInstance
=
new
PlayerManager
();
}
}
}
return
mInstance
;
}
/**
* 切换与播放器exoplayer 绑定的exoplayerView。用于页面切换视频无缝续播的场景
* @param newPlayerView
* @param attach
*/
public
void
switchPlayerView
(
PlayerView
newPlayerView
,
boolean
attach
)
{
playerView
.
setPlayer
(
attach
?
null
:
exoPlayer
);
newPlayerView
.
setPlayer
(
attach
?
exoPlayer
:
null
);
}
public
MediaSource
createMediaSource
(
String
url
)
{
if
(
mediaSourceHashMap
.
containsKey
(
url
)){
return
mediaSourceHashMap
.
get
(
url
);
}
MediaSource
mediaSource
=
null
;
if
(
url
.
contains
(
"http"
)){
return
networkMediaSourceFactory
.
createMediaSource
(
Uri
.
parse
(
url
));
}
else
{
mediaSource
=
localMediaSourceFactory
.
createMediaSource
(
Uri
.
fromFile
(
new
File
(
url
)));
}
mediaSourceHashMap
.
put
(
url
,
mediaSource
);
return
mediaSource
;
}
}
\ No newline at end of file
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/DateUtils.java
0 → 100644
View file @
b6da758b
package
com
.
widget
.
imagevideobanner
.
utils
;
import
com.blankj.utilcode.util.StringUtils
;
import
java.text.ParseException
;
import
java.text.SimpleDateFormat
;
import
java.util.Calendar
;
import
java.util.Date
;
/**
* 日期相关工具类
*/
public
class
DateUtils
{
public
static
final
String
DF_YYYYMMDD
=
"yyyyMMdd"
;
public
static
final
String
DF_YYMMDD
=
"yyMMdd"
;
public
static
final
String
DF_YYYY_MM_DD
=
"yyyy-MM-dd"
;
public
static
final
String
DF_YYYY_MM_DD2
=
"yyyy/MM/dd"
;
public
static
final
String
DF_YYYYMMDDHHMMSS
=
"yyyyMMddHHmmss"
;
public
static
final
String
DF_YYYY_MM_DDHHMMSS
=
"yyyy-MM-dd HH:mm:ss"
;
public
static
final
String
DF_HHMMSS
=
"HHmmss"
;
public
static
final
String
DF_HHMMSS2
=
"HH:mm:ss"
;
public
static
final
String
DF_CN_YYYY_MM_DD
=
"yyyy年MM月dd日"
;
public
static
final
String
DF_HHMM
=
"HH:mm"
;
/**
* 带ms的时间戳,与poshub对接时添加
*/
public
static
final
String
DF_YYYY_MM_DD_HHMMSSSS
=
"yyyy-MM-dd HH:mm:ss.SSS"
;
private
static
final
String
TAG
=
"DateUtils"
;
/**
* 将日期转换成yyyy-MM-dd HH:mm:ss.SSS字符串
*
* @return yyyy-MM-dd HH:mm:ss.SSS
*/
public
static
String
format17
(
Date
date
)
{
return
format
(
date
,
DF_YYYY_MM_DD_HHMMSSSS
);
}
/**
* 将日期转换成字符串
*
* @param date
* @param format
* @return
*/
public
static
String
format
(
Date
date
,
String
format
)
{
if
(
date
==
null
)
{
throw
new
IllegalArgumentException
(
"Param date is null!"
);
}
if
(
StringUtils
.
isEmpty
(
format
))
{
throw
new
IllegalArgumentException
(
"Param format is blank!"
);
}
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
format
);
return
sdf
.
format
(
date
);
}
/**
* 将日期转换成yyyyMMddHHmmss字符串
*
* @param date
* @return
*/
public
static
String
format14
(
Date
date
)
{
return
format
(
date
,
DF_YYYYMMDDHHMMSS
);
}
/**
* 将日期转换成yyyy-MM-dd- HH:mm:ss字符串
*
* @param date
* @return
*/
public
static
String
format18
(
Date
date
)
{
return
format
(
date
,
DF_YYYY_MM_DDHHMMSS
);
}
public
static
String
format8
(
Date
date
)
{
return
format
(
date
,
DF_YYYYMMDD
);
}
public
static
String
format6
(
Date
date
)
{
return
format
(
date
,
DF_YYMMDD
);
}
public
static
String
format10
(
Date
date
)
{
return
format
(
date
,
DF_YYYY_MM_DD
);
}
public
static
String
formatCN
(
Date
date
)
{
return
format
(
date
,
DF_CN_YYYY_MM_DD
);
}
public
static
String
formatCustom
(
Date
date
,
String
style
)
{
return
format
(
date
,
style
);
}
public
static
Date
parse8
(
String
dateStr
)
throws
ParseException
{
return
parse
(
dateStr
,
DF_YYYYMMDD
);
}
public
static
Date
parse10
(
String
dateStr
)
throws
ParseException
{
return
parse
(
dateStr
,
DF_YYYY_MM_DD
);
}
/**
* 返回当前日期 yyyyMMdd格式 字符串
*
* @return
*/
public
static
String
getNow8
()
{
return
format8
(
new
Date
());
}
/**
* 返回当前日期 yyyyMMdd格式 字符串
*
* @return
*/
public
static
String
getNow6
()
{
return
format6
(
new
Date
());
}
/**
* 返回当前日期 yyyyMMdd格式 字符串
*
* @return
*/
public
static
String
getNow10
()
{
return
format10
(
new
Date
());
}
/**
* 获取当天0点 date对象
*
* @return
*/
public
static
Date
getToday
()
{
Date
today
=
null
;
try
{
today
=
parse
(
getNow8
(),
DF_YYYYMMDD
);
}
catch
(
ParseException
e
)
{
today
=
new
Date
();
}
return
today
;
}
/**
* 根据时间的字符串转成Date对象
* yyyy-MM-dd HH:mm:ss
*
* @return
*/
public
static
Date
getDateByDateString
(
String
dateStr
)
{
Date
today
=
null
;
try
{
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
DF_YYYY_MM_DDHHMMSS
);
return
sdf
.
parse
(
dateStr
);
}
catch
(
ParseException
e
)
{
//unreachable
today
=
new
Date
();
}
return
today
;
}
/**
* 将不同格式的 String 转换成 时间戳
*
* @param str
* @param formatStyle
* @return
*/
public
static
long
stringToLong
(
String
str
,
String
formatStyle
)
throws
ParseException
{
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
formatStyle
);
return
sdf
.
parse
(
str
).
getTime
();
//毫秒
}
/**
* 根据时间的字符串转成Date对象
* yyyy-MM-dd HH:mm:ss
*
* @return
*/
public
static
Date
getDateByDateString2
(
String
dateStr
)
{
Date
today
=
null
;
try
{
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
DF_YYYYMMDDHHMMSS
);
return
sdf
.
parse
(
dateStr
);
}
catch
(
ParseException
e
)
{
today
=
new
Date
();
}
return
today
;
}
public
static
String
getDateStringByTimeStamp
(
long
timestamp
)
{
Calendar
c
=
Calendar
.
getInstance
();
c
.
setTimeInMillis
(
timestamp
);
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
DF_YYYY_MM_DDHHMMSS
);
return
sdf
.
format
(
c
.
getTime
());
}
/**
* 获取当年1月1日0点 date对象
*
* @return
*/
public
static
Date
getNowYear
()
{
Date
year
=
null
;
try
{
String
format
=
"yyyy"
;
year
=
parse
(
format
(
new
Date
(),
format
),
format
);
}
catch
(
ParseException
e
)
{
//unreachable
year
=
new
Date
();
}
return
year
;
}
/**
* 获取当月1号0点 date对象
*
* @return
*/
public
static
Date
getNowMonth
()
{
Date
month
=
null
;
try
{
String
format
=
"yyyy-MM"
;
month
=
parse
(
format
(
new
Date
(),
format
),
format
);
}
catch
(
ParseException
e
)
{
//unreachable
month
=
new
Date
();
}
return
month
;
}
public
static
int
getMonthSpace
(
Date
date1
,
Date
date2
)
{
Calendar
c1
=
Calendar
.
getInstance
();
Calendar
c2
=
Calendar
.
getInstance
();
c1
.
setTime
(
date1
);
c2
.
setTime
(
date2
);
int
result
=
c2
.
get
(
Calendar
.
YEAR
)
-
c1
.
get
(
Calendar
.
YEAR
);
return
result
==
0
?
1
:
Math
.
abs
(
result
);
}
public
static
int
getYearSpace4Now
(
String
date
)
throws
ParseException
{
Calendar
c1
=
Calendar
.
getInstance
();
Calendar
c2
=
Calendar
.
getInstance
();
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
"yyyyMM"
);
c1
.
setTime
(
new
Date
());
c2
.
setTime
(
sdf
.
parse
(
date
));
int
result
=
c2
.
get
(
Calendar
.
YEAR
)
-
c1
.
get
(
Calendar
.
YEAR
);
return
result
==
0
?
1
:
Math
.
abs
(
result
);
}
public
static
Date
parse
(
String
dateStr
,
String
format
)
throws
ParseException
{
SimpleDateFormat
sdf
=
new
SimpleDateFormat
(
format
);
return
sdf
.
parse
(
dateStr
);
}
/**
* @return 获取当前月第一天:
*/
public
static
Date
getFirstDateOfCurrentMonth
()
{
Calendar
c
=
Calendar
.
getInstance
();
c
.
add
(
Calendar
.
MONTH
,
0
);
c
.
set
(
Calendar
.
DAY_OF_MONTH
,
1
);
//设置为1号,当前日期既为本月第一天
try
{
return
parse
(
format8
(
c
.
getTime
()),
DF_YYYYMMDD
);
}
catch
(
ParseException
e
)
{
return
null
;
}
}
/**
* @return 获取下月第一天:
*/
public
static
Date
getFirstDateOfNextMonth
()
{
Calendar
c
=
Calendar
.
getInstance
();
c
.
add
(
Calendar
.
MONTH
,
1
);
c
.
set
(
Calendar
.
DAY_OF_MONTH
,
1
);
//设置为1号,当前日期既为本月第一天
try
{
return
parse
(
format8
(
c
.
getTime
()),
DF_YYYYMMDD
);
}
catch
(
ParseException
e
)
{
return
null
;
}
}
/**
* @return 获取当前月最后一天
*/
public
static
Date
getListDateOfCurrentMonth
()
{
Calendar
c
=
Calendar
.
getInstance
();
c
.
set
(
Calendar
.
DAY_OF_MONTH
,
c
.
getActualMaximum
(
Calendar
.
DAY_OF_MONTH
));
try
{
return
parse
(
format8
(
c
.
getTime
()),
DF_YYYYMMDD
);
}
catch
(
ParseException
e
)
{
return
null
;
}
}
/**
* @return 当月的总天数
*/
public
static
int
getCurrentMonthDay
()
{
Calendar
a
=
Calendar
.
getInstance
();
a
.
set
(
Calendar
.
DATE
,
1
);
a
.
roll
(
Calendar
.
DATE
,
-
1
);
int
maxDate
=
a
.
get
(
Calendar
.
DATE
);
return
maxDate
;
}
/**
* 计算时间间隔
*
* @param fDate 上次时间
* @param oDate 本次时间
* @return 精确到天
*/
public
static
int
getIntervalDays
(
Date
fDate
,
Date
oDate
)
{
if
(
fDate
==
null
||
oDate
==
null
)
{
return
-
1
;
}
try
{
fDate
=
parse
(
format8
(
fDate
),
DF_YYYYMMDD
);
oDate
=
parse
(
format8
(
oDate
),
DF_YYYYMMDD
);
}
catch
(
ParseException
e
)
{
}
long
nd
=
1000
*
24
*
60
*
60
;
//一天的毫秒数
//获得两个时间的毫秒时间差异
long
diff
=
oDate
.
getTime
()
-
fDate
.
getTime
();
Long
day
=
diff
/
nd
;
//计算差多少天
return
day
.
intValue
();
}
/**
* @param date
* @return
* @throws ParseException
*/
public
static
Date
getDate8
(
Date
date
)
{
try
{
return
parse8
(
format8
(
date
));
}
catch
(
ParseException
e
)
{
//unreachable
}
return
null
;
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/QRCodeUtil.java
0 → 100644
View file @
b6da758b
package
com
.
widget
.
imagevideobanner
.
utils
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.graphics.Color
;
import
android.support.annotation.ColorInt
;
import
android.support.annotation.Nullable
;
import
android.text.TextUtils
;
import
com.widget.imagevideobanner.utils.zxing.BarcodeFormat
;
import
com.widget.imagevideobanner.utils.zxing.BitMatrix
;
import
com.widget.imagevideobanner.utils.zxing.EncodeHintType
;
import
com.widget.imagevideobanner.utils.zxing.QRCodeWriter
;
import
com.widget.imagevideobanner.utils.zxing.WriterException
;
import
java.util.Hashtable
;
/**
* @ClassName: QRCodeUtil
* @Description: 二维码工具类
*/
public
class
QRCodeUtil
{
/**
* 创建二维码位图
*
* @param content 字符串内容
* @param size 位图宽&高(单位:px)
* @return
*/
@Nullable
public
static
Bitmap
createQRCodeBitmap
(
@Nullable
String
content
,
int
size
){
return
createQRCodeBitmap
(
content
,
size
,
"UTF-8"
,
"H"
,
"4"
,
Color
.
BLACK
,
Color
.
WHITE
,
null
,
null
,
0
F
);
}
/**
* 创建二维码位图 (自定义黑、白色块颜色)
*
* @param content 字符串内容
* @param size 位图宽&高(单位:px)
* @param color_black 黑色色块的自定义颜色值
* @param color_white 白色色块的自定义颜色值
* @return
*/
@Nullable
public
static
Bitmap
createQRCodeBitmap
(
@Nullable
String
content
,
int
size
,
@ColorInt
int
color_black
,
@ColorInt
int
color_white
){
return
createQRCodeBitmap
(
content
,
size
,
"UTF-8"
,
"H"
,
"4"
,
color_black
,
color_white
,
null
,
null
,
0
F
);
}
/**
* 创建二维码位图 (带Logo小图片)
*
* @param content 字符串内容
* @param size 位图宽&高(单位:px)
* @param logoBitmap logo图片
* @param logoPercent logo小图片在二维码图片中的占比大小,范围[0F,1F]。超出范围->默认使用0.2F
* @return
*/
@Nullable
public
static
Bitmap
createQRCodeBitmap
(
String
content
,
int
size
,
@Nullable
Bitmap
logoBitmap
,
float
logoPercent
){
return
createQRCodeBitmap
(
content
,
size
,
"UTF-8"
,
"H"
,
"4"
,
Color
.
BLACK
,
Color
.
WHITE
,
null
,
logoBitmap
,
logoPercent
);
}
/**
* 创建二维码位图 (Bitmap颜色代替黑色) 注意!!!注意!!!注意!!! 选用的Bitmap图片一定不能有白色色块,否则会识别不出来!!!
*
* @param content 字符串内容
* @param size 位图宽&高(单位:px)
* @param targetBitmap 目标图片 (如果targetBitmap != null, 黑色色块将会被该图片像素色值替代)
* @return
*/
@Nullable
public
static
Bitmap
createQRCodeBitmap
(
String
content
,
int
size
,
Bitmap
targetBitmap
){
return
createQRCodeBitmap
(
content
,
size
,
"UTF-8"
,
"H"
,
"4"
,
Color
.
BLACK
,
Color
.
WHITE
,
targetBitmap
,
null
,
0
F
);
}
/**
* 创建二维码位图 (支持自定义配置和自定义样式)
*
* @param content 字符串内容
* @param size 位图宽&高(单位:px)
* @param margin 空白边距 (可修改,要求:整型且>=0), 传null时,zxing源码默认使用"4"。
* @param color_black 黑色色块的自定义颜色值
* @param color_white 白色色块的自定义颜色值
* @param targetBitmap 目标图片 (如果targetBitmap != null, 黑色色块将会被该图片像素色值替代)
* @param logoBitmap logo小图片
* @param logoPercent logo小图片在二维码图片中的占比大小,范围[0F,1F],超出范围->默认使用0.2F。
* @return
*/
@Nullable
public
static
Bitmap
createQRCodeBitmap
(
@Nullable
String
content
,
int
size
,
@Nullable
String
character_set
,
@Nullable
String
error_correction
,
@Nullable
String
margin
,
@ColorInt
int
color_black
,
@ColorInt
int
color_white
,
@Nullable
Bitmap
targetBitmap
,
@Nullable
Bitmap
logoBitmap
,
float
logoPercent
){
/** 1.参数合法性判断 */
if
(
TextUtils
.
isEmpty
(
content
)){
// 字符串内容判空
return
null
;
}
if
(
size
<=
0
){
// 宽&高都需要>0
return
null
;
}
try
{
/** 2.设置二维码相关配置,生成BitMatrix(位矩阵)对象 */
Hashtable
<
EncodeHintType
,
String
>
hints
=
new
Hashtable
<>();
if
(!
TextUtils
.
isEmpty
(
character_set
))
{
hints
.
put
(
EncodeHintType
.
CHARACTER_SET
,
character_set
);
// 字符转码格式设置
}
if
(!
TextUtils
.
isEmpty
(
error_correction
)){
hints
.
put
(
EncodeHintType
.
ERROR_CORRECTION
,
error_correction
);
// 容错级别设置
}
if
(!
TextUtils
.
isEmpty
(
margin
)){
hints
.
put
(
EncodeHintType
.
MARGIN
,
margin
);
// 空白边距设置
}
BitMatrix
bitMatrix
=
new
QRCodeWriter
().
encode
(
content
,
BarcodeFormat
.
QR_CODE
,
size
,
size
,
hints
);
/** 3.根据BitMatrix(位矩阵)对象为数组元素赋颜色值 */
if
(
targetBitmap
!=
null
){
targetBitmap
=
Bitmap
.
createScaledBitmap
(
targetBitmap
,
size
,
size
,
false
);
}
int
[]
pixels
=
new
int
[
size
*
size
];
for
(
int
y
=
0
;
y
<
size
;
y
++){
for
(
int
x
=
0
;
x
<
size
;
x
++){
if
(
bitMatrix
.
get
(
x
,
y
)){
// 黑色色块像素设置
if
(
targetBitmap
!=
null
)
{
pixels
[
y
*
size
+
x
]
=
targetBitmap
.
getPixel
(
x
,
y
);
}
else
{
pixels
[
y
*
size
+
x
]
=
color_black
;
}
}
else
{
// 白色色块像素设置
pixels
[
y
*
size
+
x
]
=
color_white
;
}
}
}
/** 4.创建Bitmap对象,根据像素数组设置Bitmap每个像素点的颜色值,之后返回Bitmap对象 */
Bitmap
bitmap
=
Bitmap
.
createBitmap
(
size
,
size
,
Bitmap
.
Config
.
ARGB_8888
);
bitmap
.
setPixels
(
pixels
,
0
,
size
,
0
,
0
,
size
,
size
);
/** 5.为二维码添加logo小图标 */
if
(
logoBitmap
!=
null
){
return
addLogo
(
bitmap
,
logoBitmap
,
logoPercent
);
}
return
bitmap
;
}
catch
(
WriterException
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
/**
* 向一张图片中间添加logo小图片(图片合成)
*
* @param srcBitmap 原图片
* @param logoBitmap logo图片
* @param logoPercent 百分比 (用于调整logo图片在原图片中的显示大小, 取值范围[0,1], 传值不合法时使用0.2F)
* 原图片是二维码时,建议使用0.2F,百分比过大可能导致二维码扫描失败。
* @return
*/
@Nullable
private
static
Bitmap
addLogo
(
@Nullable
Bitmap
srcBitmap
,
@Nullable
Bitmap
logoBitmap
,
float
logoPercent
){
/** 1. 参数合法性判断 */
if
(
srcBitmap
==
null
){
return
null
;
}
if
(
logoBitmap
==
null
){
return
srcBitmap
;
}
if
(
logoPercent
<
0
F
||
logoPercent
>
1
F
){
logoPercent
=
0.2
F
;
}
/** 2. 获取原图片和Logo图片各自的宽、高值 */
int
srcWidth
=
srcBitmap
.
getWidth
();
int
srcHeight
=
srcBitmap
.
getHeight
();
int
logoWidth
=
logoBitmap
.
getWidth
();
int
logoHeight
=
logoBitmap
.
getHeight
();
/** 3. 计算画布缩放的宽高比 */
float
scaleWidth
=
srcWidth
*
logoPercent
/
logoWidth
;
float
scaleHeight
=
srcHeight
*
logoPercent
/
logoHeight
;
/** 4. 使用Canvas绘制,合成图片 */
Bitmap
bitmap
=
Bitmap
.
createBitmap
(
srcWidth
,
srcHeight
,
Bitmap
.
Config
.
ARGB_8888
);
Canvas
canvas
=
new
Canvas
(
bitmap
);
canvas
.
drawBitmap
(
srcBitmap
,
0
,
0
,
null
);
canvas
.
scale
(
scaleWidth
,
scaleHeight
,
srcWidth
/
2
,
srcHeight
/
2
);
canvas
.
drawBitmap
(
logoBitmap
,
srcWidth
/
2
-
logoWidth
/
2
,
srcHeight
/
2
-
logoHeight
/
2
,
null
);
return
bitmap
;
}
/**
* 创建二维码位图
*
* @param content 字符串内容
* @param size 位图宽&高(单位:px)
* @param margin 空白边距 (可修改,要求>=0)
* @return
*/
@Nullable
public
static
Bitmap
createQRCodeBitmap
(
@Nullable
String
content
,
int
size
,
String
margin
)
{
return
createQRCodeBitmap
(
content
,
size
,
"UTF-8"
,
"H"
,
margin
,
Color
.
BLACK
,
Color
.
WHITE
,
null
,
null
,
0
F
);
}
}
\ No newline at end of file
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/ResourceUtils.java
0 → 100644
View file @
b6da758b
package
com
.
widget
.
imagevideobanner
.
utils
;
import
android.content.ContentResolver
;
import
android.content.Context
;
import
android.content.res.Resources
;
import
android.graphics.Bitmap
;
import
android.graphics.BitmapFactory
;
import
android.net.Uri
;
import
android.text.TextUtils
;
import
com.widget.imagevideobanner.bean.MediaBean
;
import
com.widget.imagevideobanner.log.BLogUtil
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
wseemann.media.FFmpegMediaMetadataRetriever
;
public
class
ResourceUtils
{
/**
* drawable 转成 uri
*
* @param context
* @param resId
* @return
*/
public
static
String
imageTranslateUri
(
Context
context
,
int
resId
)
{
Resources
r
=
context
.
getResources
();
Uri
uri
=
Uri
.
parse
(
ContentResolver
.
SCHEME_ANDROID_RESOURCE
+
"://"
+
r
.
getResourcePackageName
(
resId
)
+
"/"
+
r
.
getResourceTypeName
(
resId
)
+
"/"
+
r
.
getResourceEntryName
(
resId
));
return
uri
.
toString
();
}
/**
* 解析宽高
*/
public
static
void
resolveVideo
(
MediaBean
mediaBean
)
{
BLogUtil
.
log
(
"截取视频第一帧开始"
);
if
(
TextUtils
.
isEmpty
(
mediaBean
.
getUrl
()))
{
return
;
}
File
tempFile
=
new
File
(
mediaBean
.
getUrl
());
if
(!
tempFile
.
exists
())
{
return
;
}
//信息是全的
if
(!
TextUtils
.
isEmpty
(
mediaBean
.
getCover
())
&&
mediaBean
.
getWidth
()
!=
0
&&
mediaBean
.
getHeight
()
!=
0
)
{
return
;
}
//配置了缩略图 但是没配置宽高
String
cover
=
!
TextUtils
.
isEmpty
(
mediaBean
.
getCover
())?
mediaBean
.
getCover
()
:
mediaBean
.
getUrl
().
substring
(
0
,
mediaBean
.
getUrl
().
lastIndexOf
(
"."
))
+
".png"
;
File
file
=
new
File
(
cover
);
if
(
file
.
exists
())
{
mediaBean
.
setCover
(
cover
);
if
(
mediaBean
.
getWidth
()
==
0
||
mediaBean
.
getHeight
()
==
0
)
{
BitmapFactory
.
Options
options
=
new
BitmapFactory
.
Options
();
options
.
inJustDecodeBounds
=
true
;
BitmapFactory
.
decodeFile
(
cover
,
options
);
int
outWidth
=
options
.
outWidth
;
int
outHeight
=
options
.
outHeight
;
mediaBean
.
setWidth
(
outWidth
);
mediaBean
.
setHeight
(
outHeight
);
}
return
;
}
FFmpegMediaMetadataRetriever
mmr
=
null
;
Bitmap
bmp
=
null
;
try
{
mmr
=
new
FFmpegMediaMetadataRetriever
();
mmr
.
setDataSource
(
mediaBean
.
getUrl
());
mmr
.
extractMetadata
(
FFmpegMediaMetadataRetriever
.
METADATA_KEY_ALBUM
);
mmr
.
extractMetadata
(
FFmpegMediaMetadataRetriever
.
METADATA_KEY_ARTIST
);
bmp
=
mmr
.
getFrameAtTime
();
FileOutputStream
out
=
new
FileOutputStream
(
cover
);
bmp
.
compress
(
Bitmap
.
CompressFormat
.
PNG
,
100
,
out
);
mediaBean
.
setCover
(
cover
);
mediaBean
.
setWidth
(
bmp
.
getWidth
());
mediaBean
.
setHeight
(
bmp
.
getHeight
());
BLogUtil
.
log
(
"截取视频第一帧结束"
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
BLogUtil
.
log
(
"截取视频第一帧异常"
+
ThrowableUtils
.
getFullStackTrace
(
e
));
}
finally
{
if
(
null
!=
bmp
)
bmp
.
recycle
();
if
(
null
!=
mmr
)
mmr
.
release
();
}
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/TransformationUtils.java
0 → 100644
View file @
b6da758b
package
com
.
widget
.
imagevideobanner
.
utils
;
import
android.graphics.Bitmap
;
import
android.view.ViewGroup
;
import
android.widget.ImageView
;
import
com.bumptech.glide.request.target.ImageViewTarget
;
/**
* 设置图片等比缩放
*/
public
class
TransformationUtils
extends
ImageViewTarget
<
Bitmap
>
{
private
ImageView
target
;
public
TransformationUtils
(
ImageView
target
)
{
super
(
target
);
this
.
target
=
target
;
}
@Override
protected
void
setResource
(
Bitmap
resource
)
{
view
.
setImageBitmap
(
resource
);
//获取原图的宽高
int
width
=
resource
.
getWidth
();
int
height
=
resource
.
getHeight
();
//获取imageView的宽
int
imageViewWidth
=
target
.
getWidth
();
//计算缩放比例
float
sy
=
(
float
)
(
imageViewWidth
*
0.1
)
/
(
float
)
(
width
*
0.1
);
//计算图片等比例放大后的高
int
imageViewHeight
=
(
int
)
(
height
*
sy
);
ViewGroup
.
LayoutParams
params
=
target
.
getLayoutParams
();
params
.
height
=
imageViewHeight
;
target
.
setLayoutParams
(
params
);
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/BarcodeFormat.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* Enumerates barcode formats known to this package. Please keep alphabetized.
*
* @author Sean Owen
*/
public
enum
BarcodeFormat
{
/** Aztec 2D barcode format. */
AZTEC
,
/** CODABAR 1D format. */
CODABAR
,
/** Code 39 1D format. */
CODE_39
,
/** Code 93 1D format. */
CODE_93
,
/** Code 128 1D format. */
CODE_128
,
/** Data Matrix 2D barcode format. */
DATA_MATRIX
,
/** EAN-8 1D format. */
EAN_8
,
/** EAN-13 1D format. */
EAN_13
,
/** ITF (Interleaved Two of Five) 1D format. */
ITF
,
/** MaxiCode 2D barcode format. */
MAXICODE
,
/** PDF417 format. */
PDF_417
,
/** QR Code 2D barcode format. */
QR_CODE
,
/** RSS 14 */
RSS_14
,
/** RSS EXPANDED */
RSS_EXPANDED
,
/** UPC-A 1D format. */
UPC_A
,
/** UPC-E 1D format. */
UPC_E
,
/** UPC/EAN extension format. Not a stand-alone format. */
UPC_EAN_EXTENSION
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/BitArray.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
import
java.util.Arrays
;
/**
* <p>A simple, fast array of bits, represented compactly by an array of ints internally.</p>
*
* @author Sean Owen
*/
public
final
class
BitArray
implements
Cloneable
{
private
int
[]
bits
;
private
int
size
;
public
BitArray
()
{
this
.
size
=
0
;
this
.
bits
=
new
int
[
1
];
}
public
BitArray
(
int
size
)
{
this
.
size
=
size
;
this
.
bits
=
makeArray
(
size
);
}
// For testing only
BitArray
(
int
[]
bits
,
int
size
)
{
this
.
bits
=
bits
;
this
.
size
=
size
;
}
public
int
getSize
()
{
return
size
;
}
public
int
getSizeInBytes
()
{
return
(
size
+
7
)
/
8
;
}
private
void
ensureCapacity
(
int
size
)
{
if
(
size
>
bits
.
length
*
32
)
{
int
[]
newBits
=
makeArray
(
size
);
System
.
arraycopy
(
bits
,
0
,
newBits
,
0
,
bits
.
length
);
this
.
bits
=
newBits
;
}
}
/**
* @param i bit to get
* @return true iff bit i is set
*/
public
boolean
get
(
int
i
)
{
return
(
bits
[
i
/
32
]
&
(
1
<<
(
i
&
0x1F
)))
!=
0
;
}
/**
* Sets bit i.
*
* @param i bit to set
*/
public
void
set
(
int
i
)
{
bits
[
i
/
32
]
|=
1
<<
(
i
&
0x1F
);
}
/**
* Flips bit i.
*
* @param i bit to set
*/
public
void
flip
(
int
i
)
{
bits
[
i
/
32
]
^=
1
<<
(
i
&
0x1F
);
}
/**
* @param from first bit to check
* @return index of first bit that is set, starting from the given index, or size if none are set
* at or beyond this given index
* @see #getNextUnset(int)
*/
public
int
getNextSet
(
int
from
)
{
if
(
from
>=
size
)
{
return
size
;
}
int
bitsOffset
=
from
/
32
;
int
currentBits
=
bits
[
bitsOffset
];
// mask off lesser bits first
currentBits
&=
~((
1
<<
(
from
&
0x1F
))
-
1
);
while
(
currentBits
==
0
)
{
if
(++
bitsOffset
==
bits
.
length
)
{
return
size
;
}
currentBits
=
bits
[
bitsOffset
];
}
int
result
=
(
bitsOffset
*
32
)
+
Integer
.
numberOfTrailingZeros
(
currentBits
);
return
result
>
size
?
size
:
result
;
}
/**
* @param from index to start looking for unset bit
* @return index of next unset bit, or {@code size} if none are unset until the end
* @see #getNextSet(int)
*/
public
int
getNextUnset
(
int
from
)
{
if
(
from
>=
size
)
{
return
size
;
}
int
bitsOffset
=
from
/
32
;
int
currentBits
=
~
bits
[
bitsOffset
];
// mask off lesser bits first
currentBits
&=
~((
1
<<
(
from
&
0x1F
))
-
1
);
while
(
currentBits
==
0
)
{
if
(++
bitsOffset
==
bits
.
length
)
{
return
size
;
}
currentBits
=
~
bits
[
bitsOffset
];
}
int
result
=
(
bitsOffset
*
32
)
+
Integer
.
numberOfTrailingZeros
(
currentBits
);
return
result
>
size
?
size
:
result
;
}
/**
* Sets a block of 32 bits, starting at bit i.
*
* @param i first bit to set
* @param newBits the new value of the next 32 bits. Note again that the least-significant bit
* corresponds to bit i, the next-least-significant to i+1, and so on.
*/
public
void
setBulk
(
int
i
,
int
newBits
)
{
bits
[
i
/
32
]
=
newBits
;
}
/**
* Clears all bits (sets to false).
*/
public
void
clear
()
{
int
max
=
bits
.
length
;
for
(
int
i
=
0
;
i
<
max
;
i
++)
{
bits
[
i
]
=
0
;
}
}
public
void
appendBit
(
boolean
bit
)
{
ensureCapacity
(
size
+
1
);
if
(
bit
)
{
bits
[
size
/
32
]
|=
1
<<
(
size
&
0x1F
);
}
size
++;
}
/**
* Appends the least-significant bits, from value, in order from most-significant to
* least-significant. For example, appending 6 bits from 0x000001E will append the bits
* 0, 1, 1, 1, 1, 0 in that order.
*
* @param value {@code int} containing bits to append
* @param numBits bits from value to append
*/
public
void
appendBits
(
int
value
,
int
numBits
)
{
if
(
numBits
<
0
||
numBits
>
32
)
{
throw
new
IllegalArgumentException
(
"Num bits must be between 0 and 32"
);
}
ensureCapacity
(
size
+
numBits
);
for
(
int
numBitsLeft
=
numBits
;
numBitsLeft
>
0
;
numBitsLeft
--)
{
appendBit
(((
value
>>
(
numBitsLeft
-
1
))
&
0x01
)
==
1
);
}
}
public
void
appendBitArray
(
BitArray
other
)
{
int
otherSize
=
other
.
size
;
ensureCapacity
(
size
+
otherSize
);
for
(
int
i
=
0
;
i
<
otherSize
;
i
++)
{
appendBit
(
other
.
get
(
i
));
}
}
public
void
xor
(
BitArray
other
)
{
if
(
size
!=
other
.
size
)
{
throw
new
IllegalArgumentException
(
"Sizes don't match"
);
}
for
(
int
i
=
0
;
i
<
bits
.
length
;
i
++)
{
// The last int could be incomplete (i.e. not have 32 bits in
// it) but there is no problem since 0 XOR 0 == 0.
bits
[
i
]
^=
other
.
bits
[
i
];
}
}
/**
*
* @param bitOffset first bit to start writing
* @param array array to write into. Bytes are written most-significant byte first. This is the opposite
* of the internal representation, which is exposed by {@link #getBitArray()}
* @param offset position in array to start writing
* @param numBytes how many bytes to write
*/
public
void
toBytes
(
int
bitOffset
,
byte
[]
array
,
int
offset
,
int
numBytes
)
{
for
(
int
i
=
0
;
i
<
numBytes
;
i
++)
{
int
theByte
=
0
;
for
(
int
j
=
0
;
j
<
8
;
j
++)
{
if
(
get
(
bitOffset
))
{
theByte
|=
1
<<
(
7
-
j
);
}
bitOffset
++;
}
array
[
offset
+
i
]
=
(
byte
)
theByte
;
}
}
/**
* @return underlying array of ints. The first element holds the first 32 bits, and the least
* significant bit is bit 0.
*/
public
int
[]
getBitArray
()
{
return
bits
;
}
/**
* Reverses all bits in the array.
*/
public
void
reverse
()
{
int
[]
newBits
=
new
int
[
bits
.
length
];
// reverse all int's first
int
len
=
(
size
-
1
)
/
32
;
int
oldBitsLen
=
len
+
1
;
for
(
int
i
=
0
;
i
<
oldBitsLen
;
i
++)
{
long
x
=
bits
[
i
];
x
=
((
x
>>
1
)
&
0x55555555
L
)
|
((
x
&
0x55555555
L
)
<<
1
);
x
=
((
x
>>
2
)
&
0x33333333
L
)
|
((
x
&
0x33333333
L
)
<<
2
);
x
=
((
x
>>
4
)
&
0x0f0f0f0f
L
)
|
((
x
&
0x0f0f0f0f
L
)
<<
4
);
x
=
((
x
>>
8
)
&
0x00ff00ff
L
)
|
((
x
&
0x00ff00ff
L
)
<<
8
);
x
=
((
x
>>
16
)
&
0x0000ffff
L
)
|
((
x
&
0x0000ffff
L
)
<<
16
);
newBits
[
len
-
i
]
=
(
int
)
x
;
}
// now correct the int's if the bit size isn't a multiple of 32
if
(
size
!=
oldBitsLen
*
32
)
{
int
leftOffset
=
oldBitsLen
*
32
-
size
;
int
currentInt
=
newBits
[
0
]
>>>
leftOffset
;
for
(
int
i
=
1
;
i
<
oldBitsLen
;
i
++)
{
int
nextInt
=
newBits
[
i
];
currentInt
|=
nextInt
<<
(
32
-
leftOffset
);
newBits
[
i
-
1
]
=
currentInt
;
currentInt
=
nextInt
>>>
leftOffset
;
}
newBits
[
oldBitsLen
-
1
]
=
currentInt
;
}
bits
=
newBits
;
}
private
static
int
[]
makeArray
(
int
size
)
{
return
new
int
[(
size
+
31
)
/
32
];
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(!(
o
instanceof
BitArray
))
{
return
false
;
}
BitArray
other
=
(
BitArray
)
o
;
return
size
==
other
.
size
&&
Arrays
.
equals
(
bits
,
other
.
bits
);
}
@Override
public
int
hashCode
()
{
return
31
*
size
+
Arrays
.
hashCode
(
bits
);
}
@Override
public
String
toString
()
{
StringBuilder
result
=
new
StringBuilder
(
size
);
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
if
((
i
&
0x07
)
==
0
)
{
result
.
append
(
' '
);
}
result
.
append
(
get
(
i
)
?
'X'
:
'.'
);
}
return
result
.
toString
();
}
@Override
public
BitArray
clone
()
{
return
new
BitArray
(
bits
.
clone
(),
size
);
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/BitMatrix.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
import
java.util.Arrays
;
/**
* <p>Represents a 2D matrix of bits. In function arguments below, and throughout the common
* module, x is the column position, and y is the row position. The ordering is always x, y.
* The origin is at the top-left.</p>
*
* <p>Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins
* with a new int. This is done intentionally so that we can copy out a row into a BitArray very
* efficiently.</p>
*
* <p>The ordering of bits is row-major. Within each int, the least significant bits are used first,
* meaning they represent lower x values. This is compatible with BitArray's implementation.</p>
*
* @author Sean Owen
* @author dswitkin@google.com (Daniel Switkin)
*/
public
final
class
BitMatrix
implements
Cloneable
{
private
final
int
width
;
private
final
int
height
;
private
final
int
rowSize
;
private
final
int
[]
bits
;
// A helper to construct a square matrix.
public
BitMatrix
(
int
dimension
)
{
this
(
dimension
,
dimension
);
}
public
BitMatrix
(
int
width
,
int
height
)
{
if
(
width
<
1
||
height
<
1
)
{
throw
new
IllegalArgumentException
(
"Both dimensions must be greater than 0"
);
}
this
.
width
=
width
;
this
.
height
=
height
;
this
.
rowSize
=
(
width
+
31
)
/
32
;
bits
=
new
int
[
rowSize
*
height
];
}
private
BitMatrix
(
int
width
,
int
height
,
int
rowSize
,
int
[]
bits
)
{
this
.
width
=
width
;
this
.
height
=
height
;
this
.
rowSize
=
rowSize
;
this
.
bits
=
bits
;
}
public
static
BitMatrix
parse
(
String
stringRepresentation
,
String
setString
,
String
unsetString
)
{
if
(
stringRepresentation
==
null
)
{
throw
new
IllegalArgumentException
();
}
boolean
[]
bits
=
new
boolean
[
stringRepresentation
.
length
()];
int
bitsPos
=
0
;
int
rowStartPos
=
0
;
int
rowLength
=
-
1
;
int
nRows
=
0
;
int
pos
=
0
;
while
(
pos
<
stringRepresentation
.
length
())
{
if
(
stringRepresentation
.
charAt
(
pos
)
==
'\n'
||
stringRepresentation
.
charAt
(
pos
)
==
'\r'
)
{
if
(
bitsPos
>
rowStartPos
)
{
if
(
rowLength
==
-
1
)
{
rowLength
=
bitsPos
-
rowStartPos
;
}
else
if
(
bitsPos
-
rowStartPos
!=
rowLength
)
{
throw
new
IllegalArgumentException
(
"row lengths do not match"
);
}
rowStartPos
=
bitsPos
;
nRows
++;
}
pos
++;
}
else
if
(
stringRepresentation
.
substring
(
pos
,
pos
+
setString
.
length
()).
equals
(
setString
))
{
pos
+=
setString
.
length
();
bits
[
bitsPos
]
=
true
;
bitsPos
++;
}
else
if
(
stringRepresentation
.
substring
(
pos
,
pos
+
unsetString
.
length
()).
equals
(
unsetString
))
{
pos
+=
unsetString
.
length
();
bits
[
bitsPos
]
=
false
;
bitsPos
++;
}
else
{
throw
new
IllegalArgumentException
(
"illegal character encountered: "
+
stringRepresentation
.
substring
(
pos
));
}
}
// no EOL at end?
if
(
bitsPos
>
rowStartPos
)
{
if
(
rowLength
==
-
1
)
{
rowLength
=
bitsPos
-
rowStartPos
;
}
else
if
(
bitsPos
-
rowStartPos
!=
rowLength
)
{
throw
new
IllegalArgumentException
(
"row lengths do not match"
);
}
nRows
++;
}
BitMatrix
matrix
=
new
BitMatrix
(
rowLength
,
nRows
);
for
(
int
i
=
0
;
i
<
bitsPos
;
i
++)
{
if
(
bits
[
i
])
{
matrix
.
set
(
i
%
rowLength
,
i
/
rowLength
);
}
}
return
matrix
;
}
/**
* <p>Gets the requested bit, where true means black.</p>
*
* @param x The horizontal component (i.e. which column)
* @param y The vertical component (i.e. which row)
* @return value of given bit in matrix
*/
public
boolean
get
(
int
x
,
int
y
)
{
int
offset
=
y
*
rowSize
+
(
x
/
32
);
return
((
bits
[
offset
]
>>>
(
x
&
0x1f
))
&
1
)
!=
0
;
}
/**
* <p>Sets the given bit to true.</p>
*
* @param x The horizontal component (i.e. which column)
* @param y The vertical component (i.e. which row)
*/
public
void
set
(
int
x
,
int
y
)
{
int
offset
=
y
*
rowSize
+
(
x
/
32
);
bits
[
offset
]
|=
1
<<
(
x
&
0x1f
);
}
/**
* <p>Flips the given bit.</p>
*
* @param x The horizontal component (i.e. which column)
* @param y The vertical component (i.e. which row)
*/
public
void
flip
(
int
x
,
int
y
)
{
int
offset
=
y
*
rowSize
+
(
x
/
32
);
bits
[
offset
]
^=
1
<<
(
x
&
0x1f
);
}
/**
* Clears all bits (sets to false).
*/
public
void
clear
()
{
int
max
=
bits
.
length
;
for
(
int
i
=
0
;
i
<
max
;
i
++)
{
bits
[
i
]
=
0
;
}
}
/**
* <p>Sets a square region of the bit matrix to true.</p>
*
* @param left The horizontal position to begin at (inclusive)
* @param top The vertical position to begin at (inclusive)
* @param width The width of the region
* @param height The height of the region
*/
public
void
setRegion
(
int
left
,
int
top
,
int
width
,
int
height
)
{
if
(
top
<
0
||
left
<
0
)
{
throw
new
IllegalArgumentException
(
"Left and top must be nonnegative"
);
}
if
(
height
<
1
||
width
<
1
)
{
throw
new
IllegalArgumentException
(
"Height and width must be at least 1"
);
}
int
right
=
left
+
width
;
int
bottom
=
top
+
height
;
if
(
bottom
>
this
.
height
||
right
>
this
.
width
)
{
throw
new
IllegalArgumentException
(
"The region must fit inside the matrix"
);
}
for
(
int
y
=
top
;
y
<
bottom
;
y
++)
{
int
offset
=
y
*
rowSize
;
for
(
int
x
=
left
;
x
<
right
;
x
++)
{
bits
[
offset
+
(
x
/
32
)]
|=
1
<<
(
x
&
0x1f
);
}
}
}
/**
* @return The width of the matrix
*/
public
int
getWidth
()
{
return
width
;
}
/**
* @return The height of the matrix
*/
public
int
getHeight
()
{
return
height
;
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(!(
o
instanceof
BitMatrix
))
{
return
false
;
}
BitMatrix
other
=
(
BitMatrix
)
o
;
return
width
==
other
.
width
&&
height
==
other
.
height
&&
rowSize
==
other
.
rowSize
&&
Arrays
.
equals
(
bits
,
other
.
bits
);
}
@Override
public
int
hashCode
()
{
int
hash
=
width
;
hash
=
31
*
hash
+
width
;
hash
=
31
*
hash
+
height
;
hash
=
31
*
hash
+
rowSize
;
hash
=
31
*
hash
+
Arrays
.
hashCode
(
bits
);
return
hash
;
}
/**
* @return string representation using "X" for set and " " for unset bits
*/
@Override
public
String
toString
()
{
return
toString
(
"X "
,
" "
);
}
/**
* @param setString representation of a set bit
* @param unsetString representation of an unset bit
* @return string representation of entire matrix utilizing given strings
*/
public
String
toString
(
String
setString
,
String
unsetString
)
{
return
buildToString
(
setString
,
unsetString
,
"\n"
);
}
/**
* @param setString representation of a set bit
* @param unsetString representation of an unset bit
* @param lineSeparator newline character in string representation
* @return string representation of entire matrix utilizing given strings and line separator
* @deprecated call {@link #toString(String, String)} only, which uses \n line separator always
*/
@Deprecated
public
String
toString
(
String
setString
,
String
unsetString
,
String
lineSeparator
)
{
return
buildToString
(
setString
,
unsetString
,
lineSeparator
);
}
private
String
buildToString
(
String
setString
,
String
unsetString
,
String
lineSeparator
)
{
StringBuilder
result
=
new
StringBuilder
(
height
*
(
width
+
1
));
for
(
int
y
=
0
;
y
<
height
;
y
++)
{
for
(
int
x
=
0
;
x
<
width
;
x
++)
{
result
.
append
(
get
(
x
,
y
)
?
setString
:
unsetString
);
}
result
.
append
(
lineSeparator
);
}
return
result
.
toString
();
}
@Override
public
BitMatrix
clone
()
{
return
new
BitMatrix
(
width
,
height
,
rowSize
,
bits
.
clone
());
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/BlockPair.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
final
class
BlockPair
{
private
final
byte
[]
dataBytes
;
private
final
byte
[]
errorCorrectionBytes
;
BlockPair
(
byte
[]
data
,
byte
[]
errorCorrection
)
{
dataBytes
=
data
;
errorCorrectionBytes
=
errorCorrection
;
}
public
byte
[]
getDataBytes
()
{
return
dataBytes
;
}
public
byte
[]
getErrorCorrectionBytes
()
{
return
errorCorrectionBytes
;
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/ByteMatrix.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* JAVAPORT: The original code was a 2D array of ints, but since it only ever gets assigned
* -1, 0, and 1, I'm going to use less memory and go with bytes.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public
final
class
ByteMatrix
{
private
final
byte
[][]
bytes
;
private
final
int
width
;
private
final
int
height
;
public
ByteMatrix
(
int
width
,
int
height
)
{
bytes
=
new
byte
[
height
][
width
];
this
.
width
=
width
;
this
.
height
=
height
;
}
public
int
getHeight
()
{
return
height
;
}
public
int
getWidth
()
{
return
width
;
}
public
byte
get
(
int
x
,
int
y
)
{
return
bytes
[
y
][
x
];
}
/**
* @return an internal representation as bytes, in row-major order. array[y][x] represents point (x,y)
*/
public
byte
[][]
getArray
()
{
return
bytes
;
}
public
void
set
(
int
x
,
int
y
,
byte
value
)
{
bytes
[
y
][
x
]
=
value
;
}
public
void
set
(
int
x
,
int
y
,
int
value
)
{
bytes
[
y
][
x
]
=
(
byte
)
value
;
}
public
void
set
(
int
x
,
int
y
,
boolean
value
)
{
bytes
[
y
][
x
]
=
(
byte
)
(
value
?
1
:
0
);
}
public
void
clear
(
byte
value
)
{
for
(
int
y
=
0
;
y
<
height
;
++
y
)
{
for
(
int
x
=
0
;
x
<
width
;
++
x
)
{
bytes
[
y
][
x
]
=
value
;
}
}
}
@Override
public
String
toString
()
{
StringBuilder
result
=
new
StringBuilder
(
2
*
width
*
height
+
2
);
for
(
int
y
=
0
;
y
<
height
;
++
y
)
{
for
(
int
x
=
0
;
x
<
width
;
++
x
)
{
switch
(
bytes
[
y
][
x
])
{
case
0
:
result
.
append
(
" 0"
);
break
;
case
1
:
result
.
append
(
" 1"
);
break
;
default
:
result
.
append
(
" "
);
break
;
}
}
result
.
append
(
'\n'
);
}
return
result
.
toString
();
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/CharacterSetECI.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* Encapsulates a Character Set ECI, according to "Extended Channel Interpretations" 5.3.1.1
* of ISO 18004.
*
* @author Sean Owen
*/
public
enum
CharacterSetECI
{
// Enum name is a Java encoding valid for java.lang and java.io
Cp437
(
new
int
[]{
0
,
2
}),
ISO8859_1
(
new
int
[]{
1
,
3
},
"ISO-8859-1"
),
ISO8859_2
(
4
,
"ISO-8859-2"
),
ISO8859_3
(
5
,
"ISO-8859-3"
),
ISO8859_4
(
6
,
"ISO-8859-4"
),
ISO8859_5
(
7
,
"ISO-8859-5"
),
ISO8859_6
(
8
,
"ISO-8859-6"
),
ISO8859_7
(
9
,
"ISO-8859-7"
),
ISO8859_8
(
10
,
"ISO-8859-8"
),
ISO8859_9
(
11
,
"ISO-8859-9"
),
ISO8859_10
(
12
,
"ISO-8859-10"
),
ISO8859_11
(
13
,
"ISO-8859-11"
),
ISO8859_13
(
15
,
"ISO-8859-13"
),
ISO8859_14
(
16
,
"ISO-8859-14"
),
ISO8859_15
(
17
,
"ISO-8859-15"
),
ISO8859_16
(
18
,
"ISO-8859-16"
),
SJIS
(
20
,
"Shift_JIS"
),
Cp1250
(
21
,
"windows-1250"
),
Cp1251
(
22
,
"windows-1251"
),
Cp1252
(
23
,
"windows-1252"
),
Cp1256
(
24
,
"windows-1256"
),
UnicodeBigUnmarked
(
25
,
"UTF-16BE"
,
"UnicodeBig"
),
UTF8
(
26
,
"UTF-8"
),
ASCII
(
new
int
[]
{
27
,
170
},
"US-ASCII"
),
Big5
(
28
),
GB18030
(
29
,
"GB2312"
,
"EUC_CN"
,
"GBK"
),
EUC_KR
(
30
,
"EUC-KR"
);
private
static
final
Map
<
Integer
,
CharacterSetECI
>
VALUE_TO_ECI
=
new
HashMap
<>();
private
static
final
Map
<
String
,
CharacterSetECI
>
NAME_TO_ECI
=
new
HashMap
<>();
static
{
for
(
CharacterSetECI
eci
:
values
())
{
for
(
int
value
:
eci
.
values
)
{
VALUE_TO_ECI
.
put
(
value
,
eci
);
}
NAME_TO_ECI
.
put
(
eci
.
name
(),
eci
);
for
(
String
name
:
eci
.
otherEncodingNames
)
{
NAME_TO_ECI
.
put
(
name
,
eci
);
}
}
}
private
final
int
[]
values
;
private
final
String
[]
otherEncodingNames
;
CharacterSetECI
(
int
value
)
{
this
(
new
int
[]
{
value
});
}
CharacterSetECI
(
int
value
,
String
...
otherEncodingNames
)
{
this
.
values
=
new
int
[]
{
value
};
this
.
otherEncodingNames
=
otherEncodingNames
;
}
CharacterSetECI
(
int
[]
values
,
String
...
otherEncodingNames
)
{
this
.
values
=
values
;
this
.
otherEncodingNames
=
otherEncodingNames
;
}
public
int
getValue
()
{
return
values
[
0
];
}
/**
* @param name character set ECI encoding name
* @return CharacterSetECI representing ECI for character encoding, or null if it is legal
* but unsupported
*/
public
static
CharacterSetECI
getCharacterSetECIByName
(
String
name
)
{
return
NAME_TO_ECI
.
get
(
name
);
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/EncodeHintType.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* These are a set of hints that you may pass to Writers to specify their behavior.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public
enum
EncodeHintType
{
/**
* Specifies what degree of error correction to use, for example in QR Codes.
* Type depends on the encoder. For example for QR codes it's type
* {@link com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel}.
* For Aztec it is of type {@link Integer}, representing the minimal percentage of error correction words.
* For PDF417 it is of type {@link Integer}, valid values being 0 to 8.
* In all cases, it can also be a {@link String} representation of the desired value as well.
* Note: an Aztec symbol should have a minimum of 25% EC words.
*/
ERROR_CORRECTION
,
/**
* Specifies what character encoding to use where applicable (type {@link String})
*/
CHARACTER_SET
,
/**
* Specifies the matrix shape for Data Matrix (type {@link com.google.zxing.datamatrix.encoder.SymbolShapeHint})
*/
DATA_MATRIX_SHAPE
,
/**
* Specifies a minimum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.
*
* @deprecated use width/height params in
* {@link com.google.zxing.datamatrix.DataMatrixWriter#encode(String, BarcodeFormat, int, int)}
*/
@Deprecated
MIN_SIZE
,
/**
* Specifies a maximum barcode size (type {@link Dimension}). Only applicable to Data Matrix now.
*
* @deprecated without replacement
*/
@Deprecated
MAX_SIZE
,
/**
* Specifies margin, in pixels, to use when generating the barcode. The meaning can vary
* by format; for example it controls margin before and after the barcode horizontally for
* most 1D formats. (Type {@link Integer}, or {@link String} representation of the integer value).
*/
MARGIN
,
/**
* Specifies whether to use compact mode for PDF417 (type {@link Boolean}, or "true" or "false"
* {@link String} value).
*/
PDF417_COMPACT
,
/**
* Specifies what compaction mode to use for PDF417 (type
* {@link com.google.zxing.pdf417.encoder.Compaction Compaction} or {@link String} value of one of its
* enum values).
*/
PDF417_COMPACTION
,
/**
* Specifies the minimum and maximum number of rows and columns for PDF417 (type
* {@link com.google.zxing.pdf417.encoder.Dimensions Dimensions}).
*/
PDF417_DIMENSIONS
,
/**
* Specifies the required number of layers for an Aztec code.
* A negative number (-1, -2, -3, -4) specifies a compact Aztec code.
* 0 indicates to use the minimum number of layers (the default).
* A positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code.
* (Type {@link Integer}, or {@link String} representation of the integer value).
*/
AZTEC_LAYERS
,
/**
* Specifies the exact version of QR code to be encoded.
* (Type {@link Integer}, or {@link String} representation of the integer value).
*/
QR_VERSION
,
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/Encoder.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
import
java.io.UnsupportedEncodingException
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Map
;
/**
* @author satorux@google.com (Satoru Takabayashi) - creator
* @author dswitkin@google.com (Daniel Switkin) - ported from C++
*/
public
final
class
Encoder
{
// The original table is defined in the table 5 of JISX0510:2004 (p.19).
private
static
final
int
[]
ALPHANUMERIC_TABLE
=
{
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
// 0x00-0x0f
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
// 0x10-0x1f
36
,
-
1
,
-
1
,
-
1
,
37
,
38
,
-
1
,
-
1
,
-
1
,
-
1
,
39
,
40
,
-
1
,
41
,
42
,
43
,
// 0x20-0x2f
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
44
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
// 0x30-0x3f
-
1
,
10
,
11
,
12
,
13
,
14
,
15
,
16
,
17
,
18
,
19
,
20
,
21
,
22
,
23
,
24
,
// 0x40-0x4f
25
,
26
,
27
,
28
,
29
,
30
,
31
,
32
,
33
,
34
,
35
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
// 0x50-0x5f
};
static
final
String
DEFAULT_BYTE_MODE_ENCODING
=
"ISO-8859-1"
;
private
Encoder
()
{
}
// The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details.
// Basically it applies four rules and summate all penalties.
private
static
int
calculateMaskPenalty
(
ByteMatrix
matrix
)
{
return
MaskUtil
.
applyMaskPenaltyRule1
(
matrix
)
+
MaskUtil
.
applyMaskPenaltyRule2
(
matrix
)
+
MaskUtil
.
applyMaskPenaltyRule3
(
matrix
)
+
MaskUtil
.
applyMaskPenaltyRule4
(
matrix
);
}
/**
* @param content text to encode
* @param ecLevel error correction level to use
* @return {@link QRCode} representing the encoded QR code
* @throws WriterException if encoding can't succeed, because of for example invalid content
* or configuration
*/
public
static
QRCode
encode
(
String
content
,
ErrorCorrectionLevel
ecLevel
)
throws
WriterException
{
return
encode
(
content
,
ecLevel
,
null
);
}
public
static
QRCode
encode
(
String
content
,
ErrorCorrectionLevel
ecLevel
,
Map
<
EncodeHintType
,?>
hints
)
throws
WriterException
{
// Determine what character encoding has been specified by the caller, if any
String
encoding
=
DEFAULT_BYTE_MODE_ENCODING
;
if
(
hints
!=
null
&&
hints
.
containsKey
(
EncodeHintType
.
CHARACTER_SET
))
{
encoding
=
hints
.
get
(
EncodeHintType
.
CHARACTER_SET
).
toString
();
}
// Pick an encoding mode appropriate for the content. Note that this will not attempt to use
// multiple modes / segments even if that were more efficient. Twould be nice.
Mode
mode
=
chooseMode
(
content
,
encoding
);
// This will store the header information, like mode and
// length, as well as "header" segments like an ECI segment.
BitArray
headerBits
=
new
BitArray
();
// Append ECI segment if applicable
if
(
mode
==
Mode
.
BYTE
&&
!
DEFAULT_BYTE_MODE_ENCODING
.
equals
(
encoding
))
{
CharacterSetECI
eci
=
CharacterSetECI
.
getCharacterSetECIByName
(
encoding
);
if
(
eci
!=
null
)
{
appendECI
(
eci
,
headerBits
);
}
}
// (With ECI in place,) Write the mode marker
appendModeInfo
(
mode
,
headerBits
);
// Collect data within the main segment, separately, to count its size if needed. Don't add it to
// main payload yet.
BitArray
dataBits
=
new
BitArray
();
appendBytes
(
content
,
mode
,
dataBits
,
encoding
);
Version
version
;
if
(
hints
!=
null
&&
hints
.
containsKey
(
EncodeHintType
.
QR_VERSION
))
{
int
versionNumber
=
Integer
.
parseInt
(
hints
.
get
(
EncodeHintType
.
QR_VERSION
).
toString
());
version
=
Version
.
getVersionForNumber
(
versionNumber
);
int
bitsNeeded
=
calculateBitsNeeded
(
mode
,
headerBits
,
dataBits
,
version
);
if
(!
willFit
(
bitsNeeded
,
version
,
ecLevel
))
{
throw
new
WriterException
(
"Data too big for requested version"
);
}
}
else
{
version
=
recommendVersion
(
ecLevel
,
mode
,
headerBits
,
dataBits
);
}
BitArray
headerAndDataBits
=
new
BitArray
();
headerAndDataBits
.
appendBitArray
(
headerBits
);
// Find "length" of main segment and write it
int
numLetters
=
mode
==
Mode
.
BYTE
?
dataBits
.
getSizeInBytes
()
:
content
.
length
();
appendLengthInfo
(
numLetters
,
version
,
mode
,
headerAndDataBits
);
// Put data together into the overall payload
headerAndDataBits
.
appendBitArray
(
dataBits
);
Version
.
ECBlocks
ecBlocks
=
version
.
getECBlocksForLevel
(
ecLevel
);
int
numDataBytes
=
version
.
getTotalCodewords
()
-
ecBlocks
.
getTotalECCodewords
();
// Terminate the bits properly.
terminateBits
(
numDataBytes
,
headerAndDataBits
);
// Interleave data bits with error correction code.
BitArray
finalBits
=
interleaveWithECBytes
(
headerAndDataBits
,
version
.
getTotalCodewords
(),
numDataBytes
,
ecBlocks
.
getNumBlocks
());
QRCode
qrCode
=
new
QRCode
();
qrCode
.
setECLevel
(
ecLevel
);
qrCode
.
setMode
(
mode
);
qrCode
.
setVersion
(
version
);
// Choose the mask pattern and set to "qrCode".
int
dimension
=
version
.
getDimensionForVersion
();
ByteMatrix
matrix
=
new
ByteMatrix
(
dimension
,
dimension
);
int
maskPattern
=
chooseMaskPattern
(
finalBits
,
ecLevel
,
version
,
matrix
);
qrCode
.
setMaskPattern
(
maskPattern
);
// Build the matrix and set it to "qrCode".
MatrixUtil
.
buildMatrix
(
finalBits
,
ecLevel
,
version
,
maskPattern
,
matrix
);
qrCode
.
setMatrix
(
matrix
);
return
qrCode
;
}
/**
* Decides the smallest version of QR code that will contain all of the provided data.
*
* @throws WriterException if the data cannot fit in any version
*/
private
static
Version
recommendVersion
(
ErrorCorrectionLevel
ecLevel
,
Mode
mode
,
BitArray
headerBits
,
BitArray
dataBits
)
throws
WriterException
{
// Hard part: need to know version to know how many bits length takes. But need to know how many
// bits it takes to know version. First we take a guess at version by assuming version will be
// the minimum, 1:
int
provisionalBitsNeeded
=
calculateBitsNeeded
(
mode
,
headerBits
,
dataBits
,
Version
.
getVersionForNumber
(
1
));
Version
provisionalVersion
=
chooseVersion
(
provisionalBitsNeeded
,
ecLevel
);
// Use that guess to calculate the right version. I am still not sure this works in 100% of cases.
int
bitsNeeded
=
calculateBitsNeeded
(
mode
,
headerBits
,
dataBits
,
provisionalVersion
);
return
chooseVersion
(
bitsNeeded
,
ecLevel
);
}
private
static
int
calculateBitsNeeded
(
Mode
mode
,
BitArray
headerBits
,
BitArray
dataBits
,
Version
version
)
{
return
headerBits
.
getSize
()
+
mode
.
getCharacterCountBits
(
version
)
+
dataBits
.
getSize
();
}
/**
* @return the code point of the table used in alphanumeric mode or
* -1 if there is no corresponding code in the table.
*/
static
int
getAlphanumericCode
(
int
code
)
{
if
(
code
<
ALPHANUMERIC_TABLE
.
length
)
{
return
ALPHANUMERIC_TABLE
[
code
];
}
return
-
1
;
}
/**
* Choose the best mode by examining the content. Note that 'encoding' is used as a hint;
* if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}.
*/
private
static
Mode
chooseMode
(
String
content
,
String
encoding
)
{
if
(
"Shift_JIS"
.
equals
(
encoding
)
&&
isOnlyDoubleByteKanji
(
content
))
{
// Choose Kanji mode if all input are double-byte characters
return
Mode
.
KANJI
;
}
boolean
hasNumeric
=
false
;
boolean
hasAlphanumeric
=
false
;
for
(
int
i
=
0
;
i
<
content
.
length
();
++
i
)
{
char
c
=
content
.
charAt
(
i
);
if
(
c
>=
'0'
&&
c
<=
'9'
)
{
hasNumeric
=
true
;
}
else
if
(
getAlphanumericCode
(
c
)
!=
-
1
)
{
hasAlphanumeric
=
true
;
}
else
{
return
Mode
.
BYTE
;
}
}
if
(
hasAlphanumeric
)
{
return
Mode
.
ALPHANUMERIC
;
}
if
(
hasNumeric
)
{
return
Mode
.
NUMERIC
;
}
return
Mode
.
BYTE
;
}
private
static
boolean
isOnlyDoubleByteKanji
(
String
content
)
{
byte
[]
bytes
;
try
{
bytes
=
content
.
getBytes
(
"Shift_JIS"
);
}
catch
(
UnsupportedEncodingException
ignored
)
{
return
false
;
}
int
length
=
bytes
.
length
;
if
(
length
%
2
!=
0
)
{
return
false
;
}
for
(
int
i
=
0
;
i
<
length
;
i
+=
2
)
{
int
byte1
=
bytes
[
i
]
&
0xFF
;
if
((
byte1
<
0x81
||
byte1
>
0x9F
)
&&
(
byte1
<
0xE0
||
byte1
>
0xEB
))
{
return
false
;
}
}
return
true
;
}
private
static
int
chooseMaskPattern
(
BitArray
bits
,
ErrorCorrectionLevel
ecLevel
,
Version
version
,
ByteMatrix
matrix
)
throws
WriterException
{
int
minPenalty
=
Integer
.
MAX_VALUE
;
// Lower penalty is better.
int
bestMaskPattern
=
-
1
;
// We try all mask patterns to choose the best one.
for
(
int
maskPattern
=
0
;
maskPattern
<
QRCode
.
NUM_MASK_PATTERNS
;
maskPattern
++)
{
MatrixUtil
.
buildMatrix
(
bits
,
ecLevel
,
version
,
maskPattern
,
matrix
);
int
penalty
=
calculateMaskPenalty
(
matrix
);
if
(
penalty
<
minPenalty
)
{
minPenalty
=
penalty
;
bestMaskPattern
=
maskPattern
;
}
}
return
bestMaskPattern
;
}
private
static
Version
chooseVersion
(
int
numInputBits
,
ErrorCorrectionLevel
ecLevel
)
throws
WriterException
{
for
(
int
versionNum
=
1
;
versionNum
<=
40
;
versionNum
++)
{
Version
version
=
Version
.
getVersionForNumber
(
versionNum
);
if
(
willFit
(
numInputBits
,
version
,
ecLevel
))
{
return
version
;
}
}
throw
new
WriterException
(
"Data too big"
);
}
/**
* @return true if the number of input bits will fit in a code with the specified version and
* error correction level.
*/
private
static
boolean
willFit
(
int
numInputBits
,
Version
version
,
ErrorCorrectionLevel
ecLevel
)
{
// In the following comments, we use numbers of Version 7-H.
// numBytes = 196
int
numBytes
=
version
.
getTotalCodewords
();
// getNumECBytes = 130
Version
.
ECBlocks
ecBlocks
=
version
.
getECBlocksForLevel
(
ecLevel
);
int
numEcBytes
=
ecBlocks
.
getTotalECCodewords
();
// getNumDataBytes = 196 - 130 = 66
int
numDataBytes
=
numBytes
-
numEcBytes
;
int
totalInputBytes
=
(
numInputBits
+
7
)
/
8
;
return
numDataBytes
>=
totalInputBytes
;
}
/**
* Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24).
*/
static
void
terminateBits
(
int
numDataBytes
,
BitArray
bits
)
throws
WriterException
{
int
capacity
=
numDataBytes
*
8
;
if
(
bits
.
getSize
()
>
capacity
)
{
throw
new
WriterException
(
"data bits cannot fit in the QR Code"
+
bits
.
getSize
()
+
" > "
+
capacity
);
}
for
(
int
i
=
0
;
i
<
4
&&
bits
.
getSize
()
<
capacity
;
++
i
)
{
bits
.
appendBit
(
false
);
}
// Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details.
// If the last byte isn't 8-bit aligned, we'll add padding bits.
int
numBitsInLastByte
=
bits
.
getSize
()
&
0x07
;
if
(
numBitsInLastByte
>
0
)
{
for
(
int
i
=
numBitsInLastByte
;
i
<
8
;
i
++)
{
bits
.
appendBit
(
false
);
}
}
// If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24).
int
numPaddingBytes
=
numDataBytes
-
bits
.
getSizeInBytes
();
for
(
int
i
=
0
;
i
<
numPaddingBytes
;
++
i
)
{
bits
.
appendBits
((
i
&
0x01
)
==
0
?
0xEC
:
0x11
,
8
);
}
if
(
bits
.
getSize
()
!=
capacity
)
{
throw
new
WriterException
(
"Bits size does not equal capacity"
);
}
}
/**
* Get number of data bytes and number of error correction bytes for block id "blockID". Store
* the result in "numDataBytesInBlock", and "numECBytesInBlock". See table 12 in 8.5.1 of
* JISX0510:2004 (p.30)
*/
static
void
getNumDataBytesAndNumECBytesForBlockID
(
int
numTotalBytes
,
int
numDataBytes
,
int
numRSBlocks
,
int
blockID
,
int
[]
numDataBytesInBlock
,
int
[]
numECBytesInBlock
)
throws
WriterException
{
if
(
blockID
>=
numRSBlocks
)
{
throw
new
WriterException
(
"Block ID too large"
);
}
// numRsBlocksInGroup2 = 196 % 5 = 1
int
numRsBlocksInGroup2
=
numTotalBytes
%
numRSBlocks
;
// numRsBlocksInGroup1 = 5 - 1 = 4
int
numRsBlocksInGroup1
=
numRSBlocks
-
numRsBlocksInGroup2
;
// numTotalBytesInGroup1 = 196 / 5 = 39
int
numTotalBytesInGroup1
=
numTotalBytes
/
numRSBlocks
;
// numTotalBytesInGroup2 = 39 + 1 = 40
int
numTotalBytesInGroup2
=
numTotalBytesInGroup1
+
1
;
// numDataBytesInGroup1 = 66 / 5 = 13
int
numDataBytesInGroup1
=
numDataBytes
/
numRSBlocks
;
// numDataBytesInGroup2 = 13 + 1 = 14
int
numDataBytesInGroup2
=
numDataBytesInGroup1
+
1
;
// numEcBytesInGroup1 = 39 - 13 = 26
int
numEcBytesInGroup1
=
numTotalBytesInGroup1
-
numDataBytesInGroup1
;
// numEcBytesInGroup2 = 40 - 14 = 26
int
numEcBytesInGroup2
=
numTotalBytesInGroup2
-
numDataBytesInGroup2
;
// Sanity checks.
// 26 = 26
if
(
numEcBytesInGroup1
!=
numEcBytesInGroup2
)
{
throw
new
WriterException
(
"EC bytes mismatch"
);
}
// 5 = 4 + 1.
if
(
numRSBlocks
!=
numRsBlocksInGroup1
+
numRsBlocksInGroup2
)
{
throw
new
WriterException
(
"RS blocks mismatch"
);
}
// 196 = (13 + 26) * 4 + (14 + 26) * 1
if
(
numTotalBytes
!=
((
numDataBytesInGroup1
+
numEcBytesInGroup1
)
*
numRsBlocksInGroup1
)
+
((
numDataBytesInGroup2
+
numEcBytesInGroup2
)
*
numRsBlocksInGroup2
))
{
throw
new
WriterException
(
"Total bytes mismatch"
);
}
if
(
blockID
<
numRsBlocksInGroup1
)
{
numDataBytesInBlock
[
0
]
=
numDataBytesInGroup1
;
numECBytesInBlock
[
0
]
=
numEcBytesInGroup1
;
}
else
{
numDataBytesInBlock
[
0
]
=
numDataBytesInGroup2
;
numECBytesInBlock
[
0
]
=
numEcBytesInGroup2
;
}
}
/**
* Interleave "bits" with corresponding error correction bytes. On success, store the result in
* "result". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details.
*/
static
BitArray
interleaveWithECBytes
(
BitArray
bits
,
int
numTotalBytes
,
int
numDataBytes
,
int
numRSBlocks
)
throws
WriterException
{
// "bits" must have "getNumDataBytes" bytes of data.
if
(
bits
.
getSizeInBytes
()
!=
numDataBytes
)
{
throw
new
WriterException
(
"Number of bits and data bytes does not match"
);
}
// Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll
// store the divided data bytes blocks and error correction bytes blocks into "blocks".
int
dataBytesOffset
=
0
;
int
maxNumDataBytes
=
0
;
int
maxNumEcBytes
=
0
;
// Since, we know the number of reedsolmon blocks, we can initialize the vector with the number.
Collection
<
BlockPair
>
blocks
=
new
ArrayList
<>(
numRSBlocks
);
for
(
int
i
=
0
;
i
<
numRSBlocks
;
++
i
)
{
int
[]
numDataBytesInBlock
=
new
int
[
1
];
int
[]
numEcBytesInBlock
=
new
int
[
1
];
getNumDataBytesAndNumECBytesForBlockID
(
numTotalBytes
,
numDataBytes
,
numRSBlocks
,
i
,
numDataBytesInBlock
,
numEcBytesInBlock
);
int
size
=
numDataBytesInBlock
[
0
];
byte
[]
dataBytes
=
new
byte
[
size
];
bits
.
toBytes
(
8
*
dataBytesOffset
,
dataBytes
,
0
,
size
);
byte
[]
ecBytes
=
generateECBytes
(
dataBytes
,
numEcBytesInBlock
[
0
]);
blocks
.
add
(
new
BlockPair
(
dataBytes
,
ecBytes
));
maxNumDataBytes
=
Math
.
max
(
maxNumDataBytes
,
size
);
maxNumEcBytes
=
Math
.
max
(
maxNumEcBytes
,
ecBytes
.
length
);
dataBytesOffset
+=
numDataBytesInBlock
[
0
];
}
if
(
numDataBytes
!=
dataBytesOffset
)
{
throw
new
WriterException
(
"Data bytes does not match offset"
);
}
BitArray
result
=
new
BitArray
();
// First, place data blocks.
for
(
int
i
=
0
;
i
<
maxNumDataBytes
;
++
i
)
{
for
(
BlockPair
block
:
blocks
)
{
byte
[]
dataBytes
=
block
.
getDataBytes
();
if
(
i
<
dataBytes
.
length
)
{
result
.
appendBits
(
dataBytes
[
i
],
8
);
}
}
}
// Then, place error correction blocks.
for
(
int
i
=
0
;
i
<
maxNumEcBytes
;
++
i
)
{
for
(
BlockPair
block
:
blocks
)
{
byte
[]
ecBytes
=
block
.
getErrorCorrectionBytes
();
if
(
i
<
ecBytes
.
length
)
{
result
.
appendBits
(
ecBytes
[
i
],
8
);
}
}
}
if
(
numTotalBytes
!=
result
.
getSizeInBytes
())
{
// Should be same.
throw
new
WriterException
(
"Interleaving error: "
+
numTotalBytes
+
" and "
+
result
.
getSizeInBytes
()
+
" differ."
);
}
return
result
;
}
static
byte
[]
generateECBytes
(
byte
[]
dataBytes
,
int
numEcBytesInBlock
)
{
int
numDataBytes
=
dataBytes
.
length
;
int
[]
toEncode
=
new
int
[
numDataBytes
+
numEcBytesInBlock
];
for
(
int
i
=
0
;
i
<
numDataBytes
;
i
++)
{
toEncode
[
i
]
=
dataBytes
[
i
]
&
0xFF
;
}
new
ReedSolomonEncoder
(
GenericGF
.
QR_CODE_FIELD_256
).
encode
(
toEncode
,
numEcBytesInBlock
);
byte
[]
ecBytes
=
new
byte
[
numEcBytesInBlock
];
for
(
int
i
=
0
;
i
<
numEcBytesInBlock
;
i
++)
{
ecBytes
[
i
]
=
(
byte
)
toEncode
[
numDataBytes
+
i
];
}
return
ecBytes
;
}
/**
* Append mode info. On success, store the result in "bits".
*/
static
void
appendModeInfo
(
Mode
mode
,
BitArray
bits
)
{
bits
.
appendBits
(
mode
.
getBits
(),
4
);
}
/**
* Append length info. On success, store the result in "bits".
*/
static
void
appendLengthInfo
(
int
numLetters
,
Version
version
,
Mode
mode
,
BitArray
bits
)
throws
WriterException
{
int
numBits
=
mode
.
getCharacterCountBits
(
version
);
if
(
numLetters
>=
(
1
<<
numBits
))
{
throw
new
WriterException
(
numLetters
+
" is bigger than "
+
((
1
<<
numBits
)
-
1
));
}
bits
.
appendBits
(
numLetters
,
numBits
);
}
/**
* Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits".
*/
static
void
appendBytes
(
String
content
,
Mode
mode
,
BitArray
bits
,
String
encoding
)
throws
WriterException
{
switch
(
mode
)
{
case
NUMERIC:
appendNumericBytes
(
content
,
bits
);
break
;
case
ALPHANUMERIC:
appendAlphanumericBytes
(
content
,
bits
);
break
;
case
BYTE:
append8BitBytes
(
content
,
bits
,
encoding
);
break
;
case
KANJI:
appendKanjiBytes
(
content
,
bits
);
break
;
default
:
throw
new
WriterException
(
"Invalid mode: "
+
mode
);
}
}
static
void
appendNumericBytes
(
CharSequence
content
,
BitArray
bits
)
{
int
length
=
content
.
length
();
int
i
=
0
;
while
(
i
<
length
)
{
int
num1
=
content
.
charAt
(
i
)
-
'0'
;
if
(
i
+
2
<
length
)
{
// Encode three numeric letters in ten bits.
int
num2
=
content
.
charAt
(
i
+
1
)
-
'0'
;
int
num3
=
content
.
charAt
(
i
+
2
)
-
'0'
;
bits
.
appendBits
(
num1
*
100
+
num2
*
10
+
num3
,
10
);
i
+=
3
;
}
else
if
(
i
+
1
<
length
)
{
// Encode two numeric letters in seven bits.
int
num2
=
content
.
charAt
(
i
+
1
)
-
'0'
;
bits
.
appendBits
(
num1
*
10
+
num2
,
7
);
i
+=
2
;
}
else
{
// Encode one numeric letter in four bits.
bits
.
appendBits
(
num1
,
4
);
i
++;
}
}
}
static
void
appendAlphanumericBytes
(
CharSequence
content
,
BitArray
bits
)
throws
WriterException
{
int
length
=
content
.
length
();
int
i
=
0
;
while
(
i
<
length
)
{
int
code1
=
getAlphanumericCode
(
content
.
charAt
(
i
));
if
(
code1
==
-
1
)
{
throw
new
WriterException
();
}
if
(
i
+
1
<
length
)
{
int
code2
=
getAlphanumericCode
(
content
.
charAt
(
i
+
1
));
if
(
code2
==
-
1
)
{
throw
new
WriterException
();
}
// Encode two alphanumeric letters in 11 bits.
bits
.
appendBits
(
code1
*
45
+
code2
,
11
);
i
+=
2
;
}
else
{
// Encode one alphanumeric letter in six bits.
bits
.
appendBits
(
code1
,
6
);
i
++;
}
}
}
static
void
append8BitBytes
(
String
content
,
BitArray
bits
,
String
encoding
)
throws
WriterException
{
byte
[]
bytes
;
try
{
bytes
=
content
.
getBytes
(
encoding
);
}
catch
(
UnsupportedEncodingException
uee
)
{
throw
new
WriterException
(
uee
);
}
for
(
byte
b
:
bytes
)
{
bits
.
appendBits
(
b
,
8
);
}
}
static
void
appendKanjiBytes
(
String
content
,
BitArray
bits
)
throws
WriterException
{
byte
[]
bytes
;
try
{
bytes
=
content
.
getBytes
(
"Shift_JIS"
);
}
catch
(
UnsupportedEncodingException
uee
)
{
throw
new
WriterException
(
uee
);
}
int
length
=
bytes
.
length
;
for
(
int
i
=
0
;
i
<
length
;
i
+=
2
)
{
int
byte1
=
bytes
[
i
]
&
0xFF
;
int
byte2
=
bytes
[
i
+
1
]
&
0xFF
;
int
code
=
(
byte1
<<
8
)
|
byte2
;
int
subtracted
=
-
1
;
if
(
code
>=
0x8140
&&
code
<=
0x9ffc
)
{
subtracted
=
code
-
0x8140
;
}
else
if
(
code
>=
0xe040
&&
code
<=
0xebbf
)
{
subtracted
=
code
-
0xc140
;
}
if
(
subtracted
==
-
1
)
{
throw
new
WriterException
(
"Invalid byte sequence"
);
}
int
encoded
=
((
subtracted
>>
8
)
*
0xc0
)
+
(
subtracted
&
0xff
);
bits
.
appendBits
(
encoded
,
13
);
}
}
private
static
void
appendECI
(
CharacterSetECI
eci
,
BitArray
bits
)
{
bits
.
appendBits
(
Mode
.
ECI
.
getBits
(),
4
);
// This is correct for values up to 127, which is all we need now.
bits
.
appendBits
(
eci
.
getValue
(),
8
);
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/ErrorCorrectionLevel.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* <p>See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels
* defined by the QR code standard.</p>
*
* @author Sean Owen
*/
public
enum
ErrorCorrectionLevel
{
/** L = ~7% correction */
L
(
0x01
),
/** M = ~15% correction */
M
(
0x00
),
/** Q = ~25% correction */
Q
(
0x03
),
/** H = ~30% correction */
H
(
0x02
);
private
static
final
ErrorCorrectionLevel
[]
FOR_BITS
=
{
M
,
L
,
H
,
Q
};
private
final
int
bits
;
ErrorCorrectionLevel
(
int
bits
)
{
this
.
bits
=
bits
;
}
public
int
getBits
()
{
return
bits
;
}
/**
* @param bits int containing the two bits encoding a QR Code's error correction level
* @return ErrorCorrectionLevel representing the encoded error correction level
*/
public
static
ErrorCorrectionLevel
forBits
(
int
bits
)
{
if
(
bits
<
0
||
bits
>=
FOR_BITS
.
length
)
{
throw
new
IllegalArgumentException
();
}
return
FOR_BITS
[
bits
];
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/FormatException.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* Thrown when a barcode was successfully detected, but some aspect of
* the content did not conform to the barcode's format rules. This could have
* been due to a mis-detection.
*
* @author Sean Owen
*/
public
final
class
FormatException
extends
ReaderException
{
private
static
final
FormatException
INSTANCE
=
new
FormatException
();
static
{
INSTANCE
.
setStackTrace
(
NO_TRACE
);
// since it's meaningless
}
private
FormatException
()
{
}
}
\ No newline at end of file
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/FormatInformation.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* <p>Encapsulates a QR Code's format information, including the data mask used and
* error correction level.</p>
*
* @author Sean Owen
* @see DataMask
* @see ErrorCorrectionLevel
*/
final
class
FormatInformation
{
private
static
final
int
FORMAT_INFO_MASK_QR
=
0x5412
;
/**
* See ISO 18004:2006, Annex C, Table C.1
*/
private
static
final
int
[][]
FORMAT_INFO_DECODE_LOOKUP
=
{
{
0x5412
,
0x00
},
{
0x5125
,
0x01
},
{
0x5E7C
,
0x02
},
{
0x5B4B
,
0x03
},
{
0x45F9
,
0x04
},
{
0x40CE
,
0x05
},
{
0x4F97
,
0x06
},
{
0x4AA0
,
0x07
},
{
0x77C4
,
0x08
},
{
0x72F3
,
0x09
},
{
0x7DAA
,
0x0A
},
{
0x789D
,
0x0B
},
{
0x662F
,
0x0C
},
{
0x6318
,
0x0D
},
{
0x6C41
,
0x0E
},
{
0x6976
,
0x0F
},
{
0x1689
,
0x10
},
{
0x13BE
,
0x11
},
{
0x1CE7
,
0x12
},
{
0x19D0
,
0x13
},
{
0x0762
,
0x14
},
{
0x0255
,
0x15
},
{
0x0D0C
,
0x16
},
{
0x083B
,
0x17
},
{
0x355F
,
0x18
},
{
0x3068
,
0x19
},
{
0x3F31
,
0x1A
},
{
0x3A06
,
0x1B
},
{
0x24B4
,
0x1C
},
{
0x2183
,
0x1D
},
{
0x2EDA
,
0x1E
},
{
0x2BED
,
0x1F
},
};
private
final
ErrorCorrectionLevel
errorCorrectionLevel
;
private
final
byte
dataMask
;
private
FormatInformation
(
int
formatInfo
)
{
// Bits 3,4
errorCorrectionLevel
=
ErrorCorrectionLevel
.
forBits
((
formatInfo
>>
3
)
&
0x03
);
// Bottom 3 bits
dataMask
=
(
byte
)
(
formatInfo
&
0x07
);
}
static
int
numBitsDiffering
(
int
a
,
int
b
)
{
return
Integer
.
bitCount
(
a
^
b
);
}
/**
* @param maskedFormatInfo1 format info indicator, with mask still applied
* @param maskedFormatInfo2 second copy of same info; both are checked at the same time
* to establish best match
* @return information about the format it specifies, or {@code null}
* if doesn't seem to match any known pattern
*/
static
FormatInformation
decodeFormatInformation
(
int
maskedFormatInfo1
,
int
maskedFormatInfo2
)
{
FormatInformation
formatInfo
=
doDecodeFormatInformation
(
maskedFormatInfo1
,
maskedFormatInfo2
);
if
(
formatInfo
!=
null
)
{
return
formatInfo
;
}
// Should return null, but, some QR codes apparently
// do not mask this info. Try again by actually masking the pattern
// first
return
doDecodeFormatInformation
(
maskedFormatInfo1
^
FORMAT_INFO_MASK_QR
,
maskedFormatInfo2
^
FORMAT_INFO_MASK_QR
);
}
private
static
FormatInformation
doDecodeFormatInformation
(
int
maskedFormatInfo1
,
int
maskedFormatInfo2
)
{
// Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing
int
bestDifference
=
Integer
.
MAX_VALUE
;
int
bestFormatInfo
=
0
;
for
(
int
[]
decodeInfo
:
FORMAT_INFO_DECODE_LOOKUP
)
{
int
targetInfo
=
decodeInfo
[
0
];
if
(
targetInfo
==
maskedFormatInfo1
||
targetInfo
==
maskedFormatInfo2
)
{
// Found an exact match
return
new
FormatInformation
(
decodeInfo
[
1
]);
}
int
bitsDifference
=
numBitsDiffering
(
maskedFormatInfo1
,
targetInfo
);
if
(
bitsDifference
<
bestDifference
)
{
bestFormatInfo
=
decodeInfo
[
1
];
bestDifference
=
bitsDifference
;
}
if
(
maskedFormatInfo1
!=
maskedFormatInfo2
)
{
// also try the other option
bitsDifference
=
numBitsDiffering
(
maskedFormatInfo2
,
targetInfo
);
if
(
bitsDifference
<
bestDifference
)
{
bestFormatInfo
=
decodeInfo
[
1
];
bestDifference
=
bitsDifference
;
}
}
}
// Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits
// differing means we found a match
if
(
bestDifference
<=
3
)
{
return
new
FormatInformation
(
bestFormatInfo
);
}
return
null
;
}
ErrorCorrectionLevel
getErrorCorrectionLevel
()
{
return
errorCorrectionLevel
;
}
byte
getDataMask
()
{
return
dataMask
;
}
@Override
public
int
hashCode
()
{
return
(
errorCorrectionLevel
.
ordinal
()
<<
3
)
|
dataMask
;
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(!(
o
instanceof
FormatInformation
))
{
return
false
;
}
FormatInformation
other
=
(
FormatInformation
)
o
;
return
this
.
errorCorrectionLevel
==
other
.
errorCorrectionLevel
&&
this
.
dataMask
==
other
.
dataMask
;
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/GenericGF.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* <p>This class contains utility methods for performing mathematical operations over
* the Galois Fields. Operations use a given primitive polynomial in calculations.</p>
*
* <p>Throughout this package, elements of the GF are represented as an {@code int}
* for convenience and speed (but at the cost of memory).
* </p>
*
* @author Sean Owen
* @author David Olivier
*/
public
final
class
GenericGF
{
public
static
final
GenericGF
AZTEC_DATA_12
=
new
GenericGF
(
0x1069
,
4096
,
1
);
// x^12 + x^6 + x^5 + x^3 + 1
public
static
final
GenericGF
AZTEC_DATA_10
=
new
GenericGF
(
0x409
,
1024
,
1
);
// x^10 + x^3 + 1
public
static
final
GenericGF
AZTEC_DATA_6
=
new
GenericGF
(
0x43
,
64
,
1
);
// x^6 + x + 1
public
static
final
GenericGF
AZTEC_PARAM
=
new
GenericGF
(
0x13
,
16
,
1
);
// x^4 + x + 1
public
static
final
GenericGF
QR_CODE_FIELD_256
=
new
GenericGF
(
0x011D
,
256
,
0
);
// x^8 + x^4 + x^3 + x^2 + 1
public
static
final
GenericGF
DATA_MATRIX_FIELD_256
=
new
GenericGF
(
0x012D
,
256
,
1
);
// x^8 + x^5 + x^3 + x^2 + 1
public
static
final
GenericGF
AZTEC_DATA_8
=
DATA_MATRIX_FIELD_256
;
public
static
final
GenericGF
MAXICODE_FIELD_64
=
AZTEC_DATA_6
;
private
final
int
[]
expTable
;
private
final
int
[]
logTable
;
private
final
GenericGFPoly
zero
;
private
final
GenericGFPoly
one
;
private
final
int
size
;
private
final
int
primitive
;
private
final
int
generatorBase
;
/**
* Create a representation of GF(size) using the given primitive polynomial.
*
* @param primitive irreducible polynomial whose coefficients are represented by
* the bits of an int, where the least-significant bit represents the constant
* coefficient
* @param size the size of the field
* @param b the factor b in the generator polynomial can be 0- or 1-based
* (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).
* In most cases it should be 1, but for QR code it is 0.
*/
public
GenericGF
(
int
primitive
,
int
size
,
int
b
)
{
this
.
primitive
=
primitive
;
this
.
size
=
size
;
this
.
generatorBase
=
b
;
expTable
=
new
int
[
size
];
logTable
=
new
int
[
size
];
int
x
=
1
;
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
expTable
[
i
]
=
x
;
x
*=
2
;
// we're assuming the generator alpha is 2
if
(
x
>=
size
)
{
x
^=
primitive
;
x
&=
size
-
1
;
}
}
for
(
int
i
=
0
;
i
<
size
-
1
;
i
++)
{
logTable
[
expTable
[
i
]]
=
i
;
}
// logTable[0] == 0 but this should never be used
zero
=
new
GenericGFPoly
(
this
,
new
int
[]{
0
});
one
=
new
GenericGFPoly
(
this
,
new
int
[]{
1
});
}
GenericGFPoly
getZero
()
{
return
zero
;
}
GenericGFPoly
getOne
()
{
return
one
;
}
/**
* @return the monomial representing coefficient * x^degree
*/
GenericGFPoly
buildMonomial
(
int
degree
,
int
coefficient
)
{
if
(
degree
<
0
)
{
throw
new
IllegalArgumentException
();
}
if
(
coefficient
==
0
)
{
return
zero
;
}
int
[]
coefficients
=
new
int
[
degree
+
1
];
coefficients
[
0
]
=
coefficient
;
return
new
GenericGFPoly
(
this
,
coefficients
);
}
/**
* Implements both addition and subtraction -- they are the same in GF(size).
*
* @return sum/difference of a and b
*/
static
int
addOrSubtract
(
int
a
,
int
b
)
{
return
a
^
b
;
}
/**
* @return 2 to the power of a in GF(size)
*/
int
exp
(
int
a
)
{
return
expTable
[
a
];
}
/**
* @return base 2 log of a in GF(size)
*/
int
log
(
int
a
)
{
if
(
a
==
0
)
{
throw
new
IllegalArgumentException
();
}
return
logTable
[
a
];
}
/**
* @return multiplicative inverse of a
*/
int
inverse
(
int
a
)
{
if
(
a
==
0
)
{
throw
new
ArithmeticException
();
}
return
expTable
[
size
-
logTable
[
a
]
-
1
];
}
/**
* @return product of a and b in GF(size)
*/
int
multiply
(
int
a
,
int
b
)
{
if
(
a
==
0
||
b
==
0
)
{
return
0
;
}
return
expTable
[(
logTable
[
a
]
+
logTable
[
b
])
%
(
size
-
1
)];
}
public
int
getSize
()
{
return
size
;
}
public
int
getGeneratorBase
()
{
return
generatorBase
;
}
@Override
public
String
toString
()
{
return
"GF(0x"
+
Integer
.
toHexString
(
primitive
)
+
','
+
size
+
')'
;
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/GenericGFPoly.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* <p>Represents a polynomial whose coefficients are elements of a GF.
* Instances of this class are immutable.</p>
*
* <p>Much credit is due to William Rucklidge since portions of this code are an indirect
* port of his C++ Reed-Solomon implementation.</p>
*
* @author Sean Owen
*/
final
class
GenericGFPoly
{
private
final
GenericGF
field
;
private
final
int
[]
coefficients
;
/**
* @param field the {@link GenericGF} instance representing the field to use
* to perform computations
* @param coefficients coefficients as ints representing elements of GF(size), arranged
* from most significant (highest-power term) coefficient to least significant
* @throws IllegalArgumentException if argument is null or empty,
* or if leading coefficient is 0 and this is not a
* constant polynomial (that is, it is not the monomial "0")
*/
GenericGFPoly
(
GenericGF
field
,
int
[]
coefficients
)
{
if
(
coefficients
.
length
==
0
)
{
throw
new
IllegalArgumentException
();
}
this
.
field
=
field
;
int
coefficientsLength
=
coefficients
.
length
;
if
(
coefficientsLength
>
1
&&
coefficients
[
0
]
==
0
)
{
// Leading term must be non-zero for anything except the constant polynomial "0"
int
firstNonZero
=
1
;
while
(
firstNonZero
<
coefficientsLength
&&
coefficients
[
firstNonZero
]
==
0
)
{
firstNonZero
++;
}
if
(
firstNonZero
==
coefficientsLength
)
{
this
.
coefficients
=
new
int
[]{
0
};
}
else
{
this
.
coefficients
=
new
int
[
coefficientsLength
-
firstNonZero
];
System
.
arraycopy
(
coefficients
,
firstNonZero
,
this
.
coefficients
,
0
,
this
.
coefficients
.
length
);
}
}
else
{
this
.
coefficients
=
coefficients
;
}
}
int
[]
getCoefficients
()
{
return
coefficients
;
}
/**
* @return degree of this polynomial
*/
int
getDegree
()
{
return
coefficients
.
length
-
1
;
}
/**
* @return true iff this polynomial is the monomial "0"
*/
boolean
isZero
()
{
return
coefficients
[
0
]
==
0
;
}
/**
* @return coefficient of x^degree term in this polynomial
*/
int
getCoefficient
(
int
degree
)
{
return
coefficients
[
coefficients
.
length
-
1
-
degree
];
}
GenericGFPoly
addOrSubtract
(
GenericGFPoly
other
)
{
if
(!
field
.
equals
(
other
.
field
))
{
throw
new
IllegalArgumentException
(
"GenericGFPolys do not have same GenericGF field"
);
}
if
(
isZero
())
{
return
other
;
}
if
(
other
.
isZero
())
{
return
this
;
}
int
[]
smallerCoefficients
=
this
.
coefficients
;
int
[]
largerCoefficients
=
other
.
coefficients
;
if
(
smallerCoefficients
.
length
>
largerCoefficients
.
length
)
{
int
[]
temp
=
smallerCoefficients
;
smallerCoefficients
=
largerCoefficients
;
largerCoefficients
=
temp
;
}
int
[]
sumDiff
=
new
int
[
largerCoefficients
.
length
];
int
lengthDiff
=
largerCoefficients
.
length
-
smallerCoefficients
.
length
;
// Copy high-order terms only found in higher-degree polynomial's coefficients
System
.
arraycopy
(
largerCoefficients
,
0
,
sumDiff
,
0
,
lengthDiff
);
for
(
int
i
=
lengthDiff
;
i
<
largerCoefficients
.
length
;
i
++)
{
sumDiff
[
i
]
=
GenericGF
.
addOrSubtract
(
smallerCoefficients
[
i
-
lengthDiff
],
largerCoefficients
[
i
]);
}
return
new
GenericGFPoly
(
field
,
sumDiff
);
}
GenericGFPoly
multiply
(
GenericGFPoly
other
)
{
if
(!
field
.
equals
(
other
.
field
))
{
throw
new
IllegalArgumentException
(
"GenericGFPolys do not have same GenericGF field"
);
}
if
(
isZero
()
||
other
.
isZero
())
{
return
field
.
getZero
();
}
int
[]
aCoefficients
=
this
.
coefficients
;
int
aLength
=
aCoefficients
.
length
;
int
[]
bCoefficients
=
other
.
coefficients
;
int
bLength
=
bCoefficients
.
length
;
int
[]
product
=
new
int
[
aLength
+
bLength
-
1
];
for
(
int
i
=
0
;
i
<
aLength
;
i
++)
{
int
aCoeff
=
aCoefficients
[
i
];
for
(
int
j
=
0
;
j
<
bLength
;
j
++)
{
product
[
i
+
j
]
=
GenericGF
.
addOrSubtract
(
product
[
i
+
j
],
field
.
multiply
(
aCoeff
,
bCoefficients
[
j
]));
}
}
return
new
GenericGFPoly
(
field
,
product
);
}
GenericGFPoly
multiplyByMonomial
(
int
degree
,
int
coefficient
)
{
if
(
degree
<
0
)
{
throw
new
IllegalArgumentException
();
}
if
(
coefficient
==
0
)
{
return
field
.
getZero
();
}
int
size
=
coefficients
.
length
;
int
[]
product
=
new
int
[
size
+
degree
];
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
product
[
i
]
=
field
.
multiply
(
coefficients
[
i
],
coefficient
);
}
return
new
GenericGFPoly
(
field
,
product
);
}
GenericGFPoly
[]
divide
(
GenericGFPoly
other
)
{
if
(!
field
.
equals
(
other
.
field
))
{
throw
new
IllegalArgumentException
(
"GenericGFPolys do not have same GenericGF field"
);
}
if
(
other
.
isZero
())
{
throw
new
IllegalArgumentException
(
"Divide by 0"
);
}
GenericGFPoly
quotient
=
field
.
getZero
();
GenericGFPoly
remainder
=
this
;
int
denominatorLeadingTerm
=
other
.
getCoefficient
(
other
.
getDegree
());
int
inverseDenominatorLeadingTerm
=
field
.
inverse
(
denominatorLeadingTerm
);
while
(
remainder
.
getDegree
()
>=
other
.
getDegree
()
&&
!
remainder
.
isZero
())
{
int
degreeDifference
=
remainder
.
getDegree
()
-
other
.
getDegree
();
int
scale
=
field
.
multiply
(
remainder
.
getCoefficient
(
remainder
.
getDegree
()),
inverseDenominatorLeadingTerm
);
GenericGFPoly
term
=
other
.
multiplyByMonomial
(
degreeDifference
,
scale
);
GenericGFPoly
iterationQuotient
=
field
.
buildMonomial
(
degreeDifference
,
scale
);
quotient
=
quotient
.
addOrSubtract
(
iterationQuotient
);
remainder
=
remainder
.
addOrSubtract
(
term
);
}
return
new
GenericGFPoly
[]
{
quotient
,
remainder
};
}
@Override
public
String
toString
()
{
StringBuilder
result
=
new
StringBuilder
(
8
*
getDegree
());
for
(
int
degree
=
getDegree
();
degree
>=
0
;
degree
--)
{
int
coefficient
=
getCoefficient
(
degree
);
if
(
coefficient
!=
0
)
{
if
(
coefficient
<
0
)
{
result
.
append
(
" - "
);
coefficient
=
-
coefficient
;
}
else
{
if
(
result
.
length
()
>
0
)
{
result
.
append
(
" + "
);
}
}
if
(
degree
==
0
||
coefficient
!=
1
)
{
int
alphaPower
=
field
.
log
(
coefficient
);
if
(
alphaPower
==
0
)
{
result
.
append
(
'1'
);
}
else
if
(
alphaPower
==
1
)
{
result
.
append
(
'a'
);
}
else
{
result
.
append
(
"a^"
);
result
.
append
(
alphaPower
);
}
}
if
(
degree
!=
0
)
{
if
(
degree
==
1
)
{
result
.
append
(
'x'
);
}
else
{
result
.
append
(
"x^"
);
result
.
append
(
degree
);
}
}
}
}
return
result
.
toString
();
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/MaskUtil.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* @author Satoru Takabayashi
* @author Daniel Switkin
* @author Sean Owen
*/
final
class
MaskUtil
{
// Penalty weights from section 6.8.2.1
private
static
final
int
N1
=
3
;
private
static
final
int
N2
=
3
;
private
static
final
int
N3
=
40
;
private
static
final
int
N4
=
10
;
private
MaskUtil
()
{
// do nothing
}
/**
* Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and
* give penalty to them. Example: 00000 or 11111.
*/
static
int
applyMaskPenaltyRule1
(
ByteMatrix
matrix
)
{
return
applyMaskPenaltyRule1Internal
(
matrix
,
true
)
+
applyMaskPenaltyRule1Internal
(
matrix
,
false
);
}
/**
* Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give
* penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a
* penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block.
*/
static
int
applyMaskPenaltyRule2
(
ByteMatrix
matrix
)
{
int
penalty
=
0
;
byte
[][]
array
=
matrix
.
getArray
();
int
width
=
matrix
.
getWidth
();
int
height
=
matrix
.
getHeight
();
for
(
int
y
=
0
;
y
<
height
-
1
;
y
++)
{
for
(
int
x
=
0
;
x
<
width
-
1
;
x
++)
{
int
value
=
array
[
y
][
x
];
if
(
value
==
array
[
y
][
x
+
1
]
&&
value
==
array
[
y
+
1
][
x
]
&&
value
==
array
[
y
+
1
][
x
+
1
])
{
penalty
++;
}
}
}
return
N2
*
penalty
;
}
/**
* Apply mask penalty rule 3 and return the penalty. Find consecutive runs of 1:1:3:1:1:4
* starting with black, or 4:1:1:3:1:1 starting with white, and give penalty to them. If we
* find patterns like 000010111010000, we give penalty once.
*/
static
int
applyMaskPenaltyRule3
(
ByteMatrix
matrix
)
{
int
numPenalties
=
0
;
byte
[][]
array
=
matrix
.
getArray
();
int
width
=
matrix
.
getWidth
();
int
height
=
matrix
.
getHeight
();
for
(
int
y
=
0
;
y
<
height
;
y
++)
{
for
(
int
x
=
0
;
x
<
width
;
x
++)
{
byte
[]
arrayY
=
array
[
y
];
// We can at least optimize this access
if
(
x
+
6
<
width
&&
arrayY
[
x
]
==
1
&&
arrayY
[
x
+
1
]
==
0
&&
arrayY
[
x
+
2
]
==
1
&&
arrayY
[
x
+
3
]
==
1
&&
arrayY
[
x
+
4
]
==
1
&&
arrayY
[
x
+
5
]
==
0
&&
arrayY
[
x
+
6
]
==
1
&&
(
isWhiteHorizontal
(
arrayY
,
x
-
4
,
x
)
||
isWhiteHorizontal
(
arrayY
,
x
+
7
,
x
+
11
)))
{
numPenalties
++;
}
if
(
y
+
6
<
height
&&
array
[
y
][
x
]
==
1
&&
array
[
y
+
1
][
x
]
==
0
&&
array
[
y
+
2
][
x
]
==
1
&&
array
[
y
+
3
][
x
]
==
1
&&
array
[
y
+
4
][
x
]
==
1
&&
array
[
y
+
5
][
x
]
==
0
&&
array
[
y
+
6
][
x
]
==
1
&&
(
isWhiteVertical
(
array
,
x
,
y
-
4
,
y
)
||
isWhiteVertical
(
array
,
x
,
y
+
7
,
y
+
11
)))
{
numPenalties
++;
}
}
}
return
numPenalties
*
N3
;
}
private
static
boolean
isWhiteHorizontal
(
byte
[]
rowArray
,
int
from
,
int
to
)
{
from
=
Math
.
max
(
from
,
0
);
to
=
Math
.
min
(
to
,
rowArray
.
length
);
for
(
int
i
=
from
;
i
<
to
;
i
++)
{
if
(
rowArray
[
i
]
==
1
)
{
return
false
;
}
}
return
true
;
}
private
static
boolean
isWhiteVertical
(
byte
[][]
array
,
int
col
,
int
from
,
int
to
)
{
from
=
Math
.
max
(
from
,
0
);
to
=
Math
.
min
(
to
,
array
.
length
);
for
(
int
i
=
from
;
i
<
to
;
i
++)
{
if
(
array
[
i
][
col
]
==
1
)
{
return
false
;
}
}
return
true
;
}
/**
* Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give
* penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance.
*/
static
int
applyMaskPenaltyRule4
(
ByteMatrix
matrix
)
{
int
numDarkCells
=
0
;
byte
[][]
array
=
matrix
.
getArray
();
int
width
=
matrix
.
getWidth
();
int
height
=
matrix
.
getHeight
();
for
(
int
y
=
0
;
y
<
height
;
y
++)
{
byte
[]
arrayY
=
array
[
y
];
for
(
int
x
=
0
;
x
<
width
;
x
++)
{
if
(
arrayY
[
x
]
==
1
)
{
numDarkCells
++;
}
}
}
int
numTotalCells
=
matrix
.
getHeight
()
*
matrix
.
getWidth
();
int
fivePercentVariances
=
Math
.
abs
(
numDarkCells
*
2
-
numTotalCells
)
*
10
/
numTotalCells
;
return
fivePercentVariances
*
N4
;
}
/**
* Return the mask bit for "getMaskPattern" at "x" and "y". See 8.8 of JISX0510:2004 for mask
* pattern conditions.
*/
static
boolean
getDataMaskBit
(
int
maskPattern
,
int
x
,
int
y
)
{
int
intermediate
;
int
temp
;
switch
(
maskPattern
)
{
case
0
:
intermediate
=
(
y
+
x
)
&
0x1
;
break
;
case
1
:
intermediate
=
y
&
0x1
;
break
;
case
2
:
intermediate
=
x
%
3
;
break
;
case
3
:
intermediate
=
(
y
+
x
)
%
3
;
break
;
case
4
:
intermediate
=
((
y
/
2
)
+
(
x
/
3
))
&
0x1
;
break
;
case
5
:
temp
=
y
*
x
;
intermediate
=
(
temp
&
0x1
)
+
(
temp
%
3
);
break
;
case
6
:
temp
=
y
*
x
;
intermediate
=
((
temp
&
0x1
)
+
(
temp
%
3
))
&
0x1
;
break
;
case
7
:
temp
=
y
*
x
;
intermediate
=
((
temp
%
3
)
+
((
y
+
x
)
&
0x1
))
&
0x1
;
break
;
default
:
throw
new
IllegalArgumentException
(
"Invalid mask pattern: "
+
maskPattern
);
}
return
intermediate
==
0
;
}
/**
* Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both
* vertical and horizontal orders respectively.
*/
private
static
int
applyMaskPenaltyRule1Internal
(
ByteMatrix
matrix
,
boolean
isHorizontal
)
{
int
penalty
=
0
;
int
iLimit
=
isHorizontal
?
matrix
.
getHeight
()
:
matrix
.
getWidth
();
int
jLimit
=
isHorizontal
?
matrix
.
getWidth
()
:
matrix
.
getHeight
();
byte
[][]
array
=
matrix
.
getArray
();
for
(
int
i
=
0
;
i
<
iLimit
;
i
++)
{
int
numSameBitCells
=
0
;
int
prevBit
=
-
1
;
for
(
int
j
=
0
;
j
<
jLimit
;
j
++)
{
int
bit
=
isHorizontal
?
array
[
i
][
j
]
:
array
[
j
][
i
];
if
(
bit
==
prevBit
)
{
numSameBitCells
++;
}
else
{
if
(
numSameBitCells
>=
5
)
{
penalty
+=
N1
+
(
numSameBitCells
-
5
);
}
numSameBitCells
=
1
;
// Include the cell itself.
prevBit
=
bit
;
}
}
if
(
numSameBitCells
>=
5
)
{
penalty
+=
N1
+
(
numSameBitCells
-
5
);
}
}
return
penalty
;
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/MatrixUtil.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* @author satorux@google.com (Satoru Takabayashi) - creator
* @author dswitkin@google.com (Daniel Switkin) - ported from C++
*/
final
class
MatrixUtil
{
private
MatrixUtil
()
{
// do nothing
}
private
static
final
int
[][]
POSITION_DETECTION_PATTERN
=
{
{
1
,
1
,
1
,
1
,
1
,
1
,
1
},
{
1
,
0
,
0
,
0
,
0
,
0
,
1
},
{
1
,
0
,
1
,
1
,
1
,
0
,
1
},
{
1
,
0
,
1
,
1
,
1
,
0
,
1
},
{
1
,
0
,
1
,
1
,
1
,
0
,
1
},
{
1
,
0
,
0
,
0
,
0
,
0
,
1
},
{
1
,
1
,
1
,
1
,
1
,
1
,
1
},
};
private
static
final
int
[][]
POSITION_ADJUSTMENT_PATTERN
=
{
{
1
,
1
,
1
,
1
,
1
},
{
1
,
0
,
0
,
0
,
1
},
{
1
,
0
,
1
,
0
,
1
},
{
1
,
0
,
0
,
0
,
1
},
{
1
,
1
,
1
,
1
,
1
},
};
// From Appendix E. Table 1, JIS0510X:2004 (p 71). The table was double-checked by komatsu.
private
static
final
int
[][]
POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE
=
{
{-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 1
{
6
,
18
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 2
{
6
,
22
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 3
{
6
,
26
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 4
{
6
,
30
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 5
{
6
,
34
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 6
{
6
,
22
,
38
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 7
{
6
,
24
,
42
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 8
{
6
,
26
,
46
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 9
{
6
,
28
,
50
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 10
{
6
,
30
,
54
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 11
{
6
,
32
,
58
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 12
{
6
,
34
,
62
,
-
1
,
-
1
,
-
1
,
-
1
},
// Version 13
{
6
,
26
,
46
,
66
,
-
1
,
-
1
,
-
1
},
// Version 14
{
6
,
26
,
48
,
70
,
-
1
,
-
1
,
-
1
},
// Version 15
{
6
,
26
,
50
,
74
,
-
1
,
-
1
,
-
1
},
// Version 16
{
6
,
30
,
54
,
78
,
-
1
,
-
1
,
-
1
},
// Version 17
{
6
,
30
,
56
,
82
,
-
1
,
-
1
,
-
1
},
// Version 18
{
6
,
30
,
58
,
86
,
-
1
,
-
1
,
-
1
},
// Version 19
{
6
,
34
,
62
,
90
,
-
1
,
-
1
,
-
1
},
// Version 20
{
6
,
28
,
50
,
72
,
94
,
-
1
,
-
1
},
// Version 21
{
6
,
26
,
50
,
74
,
98
,
-
1
,
-
1
},
// Version 22
{
6
,
30
,
54
,
78
,
102
,
-
1
,
-
1
},
// Version 23
{
6
,
28
,
54
,
80
,
106
,
-
1
,
-
1
},
// Version 24
{
6
,
32
,
58
,
84
,
110
,
-
1
,
-
1
},
// Version 25
{
6
,
30
,
58
,
86
,
114
,
-
1
,
-
1
},
// Version 26
{
6
,
34
,
62
,
90
,
118
,
-
1
,
-
1
},
// Version 27
{
6
,
26
,
50
,
74
,
98
,
122
,
-
1
},
// Version 28
{
6
,
30
,
54
,
78
,
102
,
126
,
-
1
},
// Version 29
{
6
,
26
,
52
,
78
,
104
,
130
,
-
1
},
// Version 30
{
6
,
30
,
56
,
82
,
108
,
134
,
-
1
},
// Version 31
{
6
,
34
,
60
,
86
,
112
,
138
,
-
1
},
// Version 32
{
6
,
30
,
58
,
86
,
114
,
142
,
-
1
},
// Version 33
{
6
,
34
,
62
,
90
,
118
,
146
,
-
1
},
// Version 34
{
6
,
30
,
54
,
78
,
102
,
126
,
150
},
// Version 35
{
6
,
24
,
50
,
76
,
102
,
128
,
154
},
// Version 36
{
6
,
28
,
54
,
80
,
106
,
132
,
158
},
// Version 37
{
6
,
32
,
58
,
84
,
110
,
136
,
162
},
// Version 38
{
6
,
26
,
54
,
82
,
110
,
138
,
166
},
// Version 39
{
6
,
30
,
58
,
86
,
114
,
142
,
170
},
// Version 40
};
// Type info cells at the left top corner.
private
static
final
int
[][]
TYPE_INFO_COORDINATES
=
{
{
8
,
0
},
{
8
,
1
},
{
8
,
2
},
{
8
,
3
},
{
8
,
4
},
{
8
,
5
},
{
8
,
7
},
{
8
,
8
},
{
7
,
8
},
{
5
,
8
},
{
4
,
8
},
{
3
,
8
},
{
2
,
8
},
{
1
,
8
},
{
0
,
8
},
};
// From Appendix D in JISX0510:2004 (p. 67)
private
static
final
int
VERSION_INFO_POLY
=
0x1f25
;
// 1 1111 0010 0101
// From Appendix C in JISX0510:2004 (p.65).
private
static
final
int
TYPE_INFO_POLY
=
0x537
;
private
static
final
int
TYPE_INFO_MASK_PATTERN
=
0x5412
;
// Set all cells to -1. -1 means that the cell is empty (not set yet).
//
// JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding
// with the ByteMatrix initialized all to zero.
static
void
clearMatrix
(
ByteMatrix
matrix
)
{
matrix
.
clear
((
byte
)
-
1
);
}
// Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On
// success, store the result in "matrix" and return true.
static
void
buildMatrix
(
BitArray
dataBits
,
ErrorCorrectionLevel
ecLevel
,
Version
version
,
int
maskPattern
,
ByteMatrix
matrix
)
throws
WriterException
{
clearMatrix
(
matrix
);
embedBasicPatterns
(
version
,
matrix
);
// Type information appear with any version.
embedTypeInfo
(
ecLevel
,
maskPattern
,
matrix
);
// Version info appear if version >= 7.
maybeEmbedVersionInfo
(
version
,
matrix
);
// Data should be embedded at end.
embedDataBits
(
dataBits
,
maskPattern
,
matrix
);
}
// Embed basic patterns. On success, modify the matrix and return true.
// The basic patterns are:
// - Position detection patterns
// - Timing patterns
// - Dark dot at the left bottom corner
// - Position adjustment patterns, if need be
static
void
embedBasicPatterns
(
Version
version
,
ByteMatrix
matrix
)
throws
WriterException
{
// Let's get started with embedding big squares at corners.
embedPositionDetectionPatternsAndSeparators
(
matrix
);
// Then, embed the dark dot at the left bottom corner.
embedDarkDotAtLeftBottomCorner
(
matrix
);
// Position adjustment patterns appear if version >= 2.
maybeEmbedPositionAdjustmentPatterns
(
version
,
matrix
);
// Timing patterns should be embedded after position adj. patterns.
embedTimingPatterns
(
matrix
);
}
// Embed type information. On success, modify the matrix.
static
void
embedTypeInfo
(
ErrorCorrectionLevel
ecLevel
,
int
maskPattern
,
ByteMatrix
matrix
)
throws
WriterException
{
BitArray
typeInfoBits
=
new
BitArray
();
makeTypeInfoBits
(
ecLevel
,
maskPattern
,
typeInfoBits
);
for
(
int
i
=
0
;
i
<
typeInfoBits
.
getSize
();
++
i
)
{
// Place bits in LSB to MSB order. LSB (least significant bit) is the last value in
// "typeInfoBits".
boolean
bit
=
typeInfoBits
.
get
(
typeInfoBits
.
getSize
()
-
1
-
i
);
// Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46).
int
x1
=
TYPE_INFO_COORDINATES
[
i
][
0
];
int
y1
=
TYPE_INFO_COORDINATES
[
i
][
1
];
matrix
.
set
(
x1
,
y1
,
bit
);
if
(
i
<
8
)
{
// Right top corner.
int
x2
=
matrix
.
getWidth
()
-
i
-
1
;
int
y2
=
8
;
matrix
.
set
(
x2
,
y2
,
bit
);
}
else
{
// Left bottom corner.
int
x2
=
8
;
int
y2
=
matrix
.
getHeight
()
-
7
+
(
i
-
8
);
matrix
.
set
(
x2
,
y2
,
bit
);
}
}
}
// Embed version information if need be. On success, modify the matrix and return true.
// See 8.10 of JISX0510:2004 (p.47) for how to embed version information.
static
void
maybeEmbedVersionInfo
(
Version
version
,
ByteMatrix
matrix
)
throws
WriterException
{
if
(
version
.
getVersionNumber
()
<
7
)
{
// Version info is necessary if version >= 7.
return
;
// Don't need version info.
}
BitArray
versionInfoBits
=
new
BitArray
();
makeVersionInfoBits
(
version
,
versionInfoBits
);
int
bitIndex
=
6
*
3
-
1
;
// It will decrease from 17 to 0.
for
(
int
i
=
0
;
i
<
6
;
++
i
)
{
for
(
int
j
=
0
;
j
<
3
;
++
j
)
{
// Place bits in LSB (least significant bit) to MSB order.
boolean
bit
=
versionInfoBits
.
get
(
bitIndex
);
bitIndex
--;
// Left bottom corner.
matrix
.
set
(
i
,
matrix
.
getHeight
()
-
11
+
j
,
bit
);
// Right bottom corner.
matrix
.
set
(
matrix
.
getHeight
()
-
11
+
j
,
i
,
bit
);
}
}
}
// Embed "dataBits" using "getMaskPattern". On success, modify the matrix and return true.
// For debugging purposes, it skips masking process if "getMaskPattern" is -1.
// See 8.7 of JISX0510:2004 (p.38) for how to embed data bits.
static
void
embedDataBits
(
BitArray
dataBits
,
int
maskPattern
,
ByteMatrix
matrix
)
throws
WriterException
{
int
bitIndex
=
0
;
int
direction
=
-
1
;
// Start from the right bottom cell.
int
x
=
matrix
.
getWidth
()
-
1
;
int
y
=
matrix
.
getHeight
()
-
1
;
while
(
x
>
0
)
{
// Skip the vertical timing pattern.
if
(
x
==
6
)
{
x
-=
1
;
}
while
(
y
>=
0
&&
y
<
matrix
.
getHeight
())
{
for
(
int
i
=
0
;
i
<
2
;
++
i
)
{
int
xx
=
x
-
i
;
// Skip the cell if it's not empty.
if
(!
isEmpty
(
matrix
.
get
(
xx
,
y
)))
{
continue
;
}
boolean
bit
;
if
(
bitIndex
<
dataBits
.
getSize
())
{
bit
=
dataBits
.
get
(
bitIndex
);
++
bitIndex
;
}
else
{
// Padding bit. If there is no bit left, we'll fill the left cells with 0, as described
// in 8.4.9 of JISX0510:2004 (p. 24).
bit
=
false
;
}
// Skip masking if mask_pattern is -1.
if
(
maskPattern
!=
-
1
&&
MaskUtil
.
getDataMaskBit
(
maskPattern
,
xx
,
y
))
{
bit
=
!
bit
;
}
matrix
.
set
(
xx
,
y
,
bit
);
}
y
+=
direction
;
}
direction
=
-
direction
;
// Reverse the direction.
y
+=
direction
;
x
-=
2
;
// Move to the left.
}
// All bits should be consumed.
if
(
bitIndex
!=
dataBits
.
getSize
())
{
throw
new
WriterException
(
"Not all bits consumed: "
+
bitIndex
+
'/'
+
dataBits
.
getSize
());
}
}
// Return the position of the most significant bit set (to one) in the "value". The most
// significant bit is position 32. If there is no bit set, return 0. Examples:
// - findMSBSet(0) => 0
// - findMSBSet(1) => 1
// - findMSBSet(255) => 8
static
int
findMSBSet
(
int
value
)
{
return
32
-
Integer
.
numberOfLeadingZeros
(
value
);
}
// Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for "value" using polynomial "poly". The BCH
// code is used for encoding type information and version information.
// Example: Calculation of version information of 7.
// f(x) is created from 7.
// - 7 = 000111 in 6 bits
// - f(x) = x^2 + x^1 + x^0
// g(x) is given by the standard (p. 67)
// - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1
// Multiply f(x) by x^(18 - 6)
// - f'(x) = f(x) * x^(18 - 6)
// - f'(x) = x^14 + x^13 + x^12
// Calculate the remainder of f'(x) / g(x)
// x^2
// __________________________________________________
// g(x) )x^14 + x^13 + x^12
// x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2
// --------------------------------------------------
// x^11 + x^10 + x^7 + x^4 + x^2
//
// The remainder is x^11 + x^10 + x^7 + x^4 + x^2
// Encode it in binary: 110010010100
// The return value is 0xc94 (1100 1001 0100)
//
// Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit
// operations. We don't care if cofficients are positive or negative.
static
int
calculateBCHCode
(
int
value
,
int
poly
)
{
if
(
poly
==
0
)
{
throw
new
IllegalArgumentException
(
"0 polynomial"
);
}
// If poly is "1 1111 0010 0101" (version info poly), msbSetInPoly is 13. We'll subtract 1
// from 13 to make it 12.
int
msbSetInPoly
=
findMSBSet
(
poly
);
value
<<=
msbSetInPoly
-
1
;
// Do the division business using exclusive-or operations.
while
(
findMSBSet
(
value
)
>=
msbSetInPoly
)
{
value
^=
poly
<<
(
findMSBSet
(
value
)
-
msbSetInPoly
);
}
// Now the "value" is the remainder (i.e. the BCH code)
return
value
;
}
// Make bit vector of type information. On success, store the result in "bits" and return true.
// Encode error correction level and mask pattern. See 8.9 of
// JISX0510:2004 (p.45) for details.
static
void
makeTypeInfoBits
(
ErrorCorrectionLevel
ecLevel
,
int
maskPattern
,
BitArray
bits
)
throws
WriterException
{
if
(!
QRCode
.
isValidMaskPattern
(
maskPattern
))
{
throw
new
WriterException
(
"Invalid mask pattern"
);
}
int
typeInfo
=
(
ecLevel
.
getBits
()
<<
3
)
|
maskPattern
;
bits
.
appendBits
(
typeInfo
,
5
);
int
bchCode
=
calculateBCHCode
(
typeInfo
,
TYPE_INFO_POLY
);
bits
.
appendBits
(
bchCode
,
10
);
BitArray
maskBits
=
new
BitArray
();
maskBits
.
appendBits
(
TYPE_INFO_MASK_PATTERN
,
15
);
bits
.
xor
(
maskBits
);
if
(
bits
.
getSize
()
!=
15
)
{
// Just in case.
throw
new
WriterException
(
"should not happen but we got: "
+
bits
.
getSize
());
}
}
// Make bit vector of version information. On success, store the result in "bits" and return true.
// See 8.10 of JISX0510:2004 (p.45) for details.
static
void
makeVersionInfoBits
(
Version
version
,
BitArray
bits
)
throws
WriterException
{
bits
.
appendBits
(
version
.
getVersionNumber
(),
6
);
int
bchCode
=
calculateBCHCode
(
version
.
getVersionNumber
(),
VERSION_INFO_POLY
);
bits
.
appendBits
(
bchCode
,
12
);
if
(
bits
.
getSize
()
!=
18
)
{
// Just in case.
throw
new
WriterException
(
"should not happen but we got: "
+
bits
.
getSize
());
}
}
// Check if "value" is empty.
private
static
boolean
isEmpty
(
int
value
)
{
return
value
==
-
1
;
}
private
static
void
embedTimingPatterns
(
ByteMatrix
matrix
)
{
// -8 is for skipping position detection patterns (size 7), and two horizontal/vertical
// separation patterns (size 1). Thus, 8 = 7 + 1.
for
(
int
i
=
8
;
i
<
matrix
.
getWidth
()
-
8
;
++
i
)
{
int
bit
=
(
i
+
1
)
%
2
;
// Horizontal line.
if
(
isEmpty
(
matrix
.
get
(
i
,
6
)))
{
matrix
.
set
(
i
,
6
,
bit
);
}
// Vertical line.
if
(
isEmpty
(
matrix
.
get
(
6
,
i
)))
{
matrix
.
set
(
6
,
i
,
bit
);
}
}
}
// Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46)
private
static
void
embedDarkDotAtLeftBottomCorner
(
ByteMatrix
matrix
)
throws
WriterException
{
if
(
matrix
.
get
(
8
,
matrix
.
getHeight
()
-
8
)
==
0
)
{
throw
new
WriterException
();
}
matrix
.
set
(
8
,
matrix
.
getHeight
()
-
8
,
1
);
}
private
static
void
embedHorizontalSeparationPattern
(
int
xStart
,
int
yStart
,
ByteMatrix
matrix
)
throws
WriterException
{
for
(
int
x
=
0
;
x
<
8
;
++
x
)
{
if
(!
isEmpty
(
matrix
.
get
(
xStart
+
x
,
yStart
)))
{
throw
new
WriterException
();
}
matrix
.
set
(
xStart
+
x
,
yStart
,
0
);
}
}
private
static
void
embedVerticalSeparationPattern
(
int
xStart
,
int
yStart
,
ByteMatrix
matrix
)
throws
WriterException
{
for
(
int
y
=
0
;
y
<
7
;
++
y
)
{
if
(!
isEmpty
(
matrix
.
get
(
xStart
,
yStart
+
y
)))
{
throw
new
WriterException
();
}
matrix
.
set
(
xStart
,
yStart
+
y
,
0
);
}
}
// Note that we cannot unify the function with embedPositionDetectionPattern() despite they are
// almost identical, since we cannot write a function that takes 2D arrays in different sizes in
// C/C++. We should live with the fact.
private
static
void
embedPositionAdjustmentPattern
(
int
xStart
,
int
yStart
,
ByteMatrix
matrix
)
{
for
(
int
y
=
0
;
y
<
5
;
++
y
)
{
for
(
int
x
=
0
;
x
<
5
;
++
x
)
{
matrix
.
set
(
xStart
+
x
,
yStart
+
y
,
POSITION_ADJUSTMENT_PATTERN
[
y
][
x
]);
}
}
}
private
static
void
embedPositionDetectionPattern
(
int
xStart
,
int
yStart
,
ByteMatrix
matrix
)
{
for
(
int
y
=
0
;
y
<
7
;
++
y
)
{
for
(
int
x
=
0
;
x
<
7
;
++
x
)
{
matrix
.
set
(
xStart
+
x
,
yStart
+
y
,
POSITION_DETECTION_PATTERN
[
y
][
x
]);
}
}
}
// Embed position detection patterns and surrounding vertical/horizontal separators.
private
static
void
embedPositionDetectionPatternsAndSeparators
(
ByteMatrix
matrix
)
throws
WriterException
{
// Embed three big squares at corners.
int
pdpWidth
=
POSITION_DETECTION_PATTERN
[
0
].
length
;
// Left top corner.
embedPositionDetectionPattern
(
0
,
0
,
matrix
);
// Right top corner.
embedPositionDetectionPattern
(
matrix
.
getWidth
()
-
pdpWidth
,
0
,
matrix
);
// Left bottom corner.
embedPositionDetectionPattern
(
0
,
matrix
.
getWidth
()
-
pdpWidth
,
matrix
);
// Embed horizontal separation patterns around the squares.
int
hspWidth
=
8
;
// Left top corner.
embedHorizontalSeparationPattern
(
0
,
hspWidth
-
1
,
matrix
);
// Right top corner.
embedHorizontalSeparationPattern
(
matrix
.
getWidth
()
-
hspWidth
,
hspWidth
-
1
,
matrix
);
// Left bottom corner.
embedHorizontalSeparationPattern
(
0
,
matrix
.
getWidth
()
-
hspWidth
,
matrix
);
// Embed vertical separation patterns around the squares.
int
vspSize
=
7
;
// Left top corner.
embedVerticalSeparationPattern
(
vspSize
,
0
,
matrix
);
// Right top corner.
embedVerticalSeparationPattern
(
matrix
.
getHeight
()
-
vspSize
-
1
,
0
,
matrix
);
// Left bottom corner.
embedVerticalSeparationPattern
(
vspSize
,
matrix
.
getHeight
()
-
vspSize
,
matrix
);
}
// Embed position adjustment patterns if need be.
private
static
void
maybeEmbedPositionAdjustmentPatterns
(
Version
version
,
ByteMatrix
matrix
)
{
if
(
version
.
getVersionNumber
()
<
2
)
{
// The patterns appear if version >= 2
return
;
}
int
index
=
version
.
getVersionNumber
()
-
1
;
int
[]
coordinates
=
POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE
[
index
];
int
numCoordinates
=
POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE
[
index
].
length
;
for
(
int
i
=
0
;
i
<
numCoordinates
;
++
i
)
{
for
(
int
j
=
0
;
j
<
numCoordinates
;
++
j
)
{
int
y
=
coordinates
[
i
];
int
x
=
coordinates
[
j
];
if
(
x
==
-
1
||
y
==
-
1
)
{
continue
;
}
// If the cell is unset, we embed the position adjustment pattern here.
if
(
isEmpty
(
matrix
.
get
(
x
,
y
)))
{
// -2 is necessary since the x/y coordinates point to the center of the pattern, not the
// left top corner.
embedPositionAdjustmentPattern
(
x
-
2
,
y
-
2
,
matrix
);
}
}
}
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/Mode.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* <p>See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which
* data can be encoded to bits in the QR code standard.</p>
*
* @author Sean Owen
*/
public
enum
Mode
{
TERMINATOR
(
new
int
[]{
0
,
0
,
0
},
0x00
),
// Not really a mode...
NUMERIC
(
new
int
[]{
10
,
12
,
14
},
0x01
),
ALPHANUMERIC
(
new
int
[]{
9
,
11
,
13
},
0x02
),
STRUCTURED_APPEND
(
new
int
[]{
0
,
0
,
0
},
0x03
),
// Not supported
BYTE
(
new
int
[]{
8
,
16
,
16
},
0x04
),
ECI
(
new
int
[]{
0
,
0
,
0
},
0x07
),
// character counts don't apply
KANJI
(
new
int
[]{
8
,
10
,
12
},
0x08
),
FNC1_FIRST_POSITION
(
new
int
[]{
0
,
0
,
0
},
0x05
),
FNC1_SECOND_POSITION
(
new
int
[]{
0
,
0
,
0
},
0x09
),
/** See GBT 18284-2000; "Hanzi" is a transliteration of this mode name. */
HANZI
(
new
int
[]{
8
,
10
,
12
},
0x0D
);
private
final
int
[]
characterCountBitsForVersions
;
private
final
int
bits
;
Mode
(
int
[]
characterCountBitsForVersions
,
int
bits
)
{
this
.
characterCountBitsForVersions
=
characterCountBitsForVersions
;
this
.
bits
=
bits
;
}
/**
* @param bits four bits encoding a QR Code data mode
* @return Mode encoded by these bits
* @throws IllegalArgumentException if bits do not correspond to a known mode
*/
public
static
Mode
forBits
(
int
bits
)
{
switch
(
bits
)
{
case
0x0
:
return
TERMINATOR
;
case
0x1
:
return
NUMERIC
;
case
0x2
:
return
ALPHANUMERIC
;
case
0x3
:
return
STRUCTURED_APPEND
;
case
0x4
:
return
BYTE
;
case
0x5
:
return
FNC1_FIRST_POSITION
;
case
0x7
:
return
ECI
;
case
0x8
:
return
KANJI
;
case
0x9
:
return
FNC1_SECOND_POSITION
;
case
0xD
:
// 0xD is defined in GBT 18284-2000, may not be supported in foreign country
return
HANZI
;
default
:
throw
new
IllegalArgumentException
();
}
}
/**
* @param version version in question
* @return number of bits used, in this QR Code symbol {@link Version}, to encode the
* count of characters that will follow encoded in this Mode
*/
public
int
getCharacterCountBits
(
Version
version
)
{
int
number
=
version
.
getVersionNumber
();
int
offset
;
if
(
number
<=
9
)
{
offset
=
0
;
}
else
if
(
number
<=
26
)
{
offset
=
1
;
}
else
{
offset
=
2
;
}
return
characterCountBitsForVersions
[
offset
];
}
public
int
getBits
()
{
return
bits
;
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/QRCode.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* @author satorux@google.com (Satoru Takabayashi) - creator
* @author dswitkin@google.com (Daniel Switkin) - ported from C++
*/
public
final
class
QRCode
{
public
static
final
int
NUM_MASK_PATTERNS
=
8
;
private
Mode
mode
;
private
ErrorCorrectionLevel
ecLevel
;
private
Version
version
;
private
int
maskPattern
;
private
ByteMatrix
matrix
;
public
QRCode
()
{
maskPattern
=
-
1
;
}
public
Mode
getMode
()
{
return
mode
;
}
public
Version
getVersion
()
{
return
version
;
}
public
ByteMatrix
getMatrix
()
{
return
matrix
;
}
@Override
public
String
toString
()
{
StringBuilder
result
=
new
StringBuilder
(
200
);
result
.
append
(
"<<\n"
);
result
.
append
(
" mode: "
);
result
.
append
(
mode
);
result
.
append
(
"\n ecLevel: "
);
result
.
append
(
ecLevel
);
result
.
append
(
"\n version: "
);
result
.
append
(
version
);
result
.
append
(
"\n maskPattern: "
);
result
.
append
(
maskPattern
);
if
(
matrix
==
null
)
{
result
.
append
(
"\n matrix: null\n"
);
}
else
{
result
.
append
(
"\n matrix:\n"
);
result
.
append
(
matrix
);
}
result
.
append
(
">>\n"
);
return
result
.
toString
();
}
public
void
setMode
(
Mode
value
)
{
mode
=
value
;
}
public
void
setECLevel
(
ErrorCorrectionLevel
value
)
{
ecLevel
=
value
;
}
public
void
setVersion
(
Version
version
)
{
this
.
version
=
version
;
}
public
void
setMaskPattern
(
int
value
)
{
maskPattern
=
value
;
}
public
void
setMatrix
(
ByteMatrix
value
)
{
matrix
=
value
;
}
// Check if "mask_pattern" is valid.
public
static
boolean
isValidMaskPattern
(
int
maskPattern
)
{
return
maskPattern
>=
0
&&
maskPattern
<
NUM_MASK_PATTERNS
;
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/QRCodeWriter.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
import
java.util.Map
;
/**
* This object renders a QR Code as a BitMatrix 2D array of greyscale values.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public
final
class
QRCodeWriter
implements
Writer
{
private
static
final
int
QUIET_ZONE_SIZE
=
4
;
@Override
public
BitMatrix
encode
(
String
contents
,
BarcodeFormat
format
,
int
width
,
int
height
)
throws
WriterException
{
new
String
(
new
byte
[]{
12
,
12
});
return
encode
(
contents
,
format
,
width
,
height
,
null
);
}
@Override
public
BitMatrix
encode
(
String
contents
,
BarcodeFormat
format
,
int
width
,
int
height
,
Map
<
EncodeHintType
,?>
hints
)
throws
WriterException
{
if
(
contents
.
isEmpty
())
{
throw
new
IllegalArgumentException
(
"Found empty contents"
);
}
if
(
format
!=
BarcodeFormat
.
QR_CODE
)
{
throw
new
IllegalArgumentException
(
"Can only encode QR_CODE, but got "
+
format
);
}
if
(
width
<
0
||
height
<
0
)
{
throw
new
IllegalArgumentException
(
"Requested dimensions are too small: "
+
width
+
'x'
+
height
);
}
ErrorCorrectionLevel
errorCorrectionLevel
=
ErrorCorrectionLevel
.
L
;
int
quietZone
=
QUIET_ZONE_SIZE
;
if
(
hints
!=
null
)
{
if
(
hints
.
containsKey
(
EncodeHintType
.
ERROR_CORRECTION
))
{
errorCorrectionLevel
=
ErrorCorrectionLevel
.
valueOf
(
hints
.
get
(
EncodeHintType
.
ERROR_CORRECTION
).
toString
());
}
if
(
hints
.
containsKey
(
EncodeHintType
.
MARGIN
))
{
quietZone
=
Integer
.
parseInt
(
hints
.
get
(
EncodeHintType
.
MARGIN
).
toString
());
}
}
QRCode
code
=
Encoder
.
encode
(
contents
,
errorCorrectionLevel
,
hints
);
return
renderResult
(
code
,
width
,
height
,
quietZone
);
}
// Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses
// 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).
private
static
BitMatrix
renderResult
(
QRCode
code
,
int
width
,
int
height
,
int
quietZone
)
{
ByteMatrix
input
=
code
.
getMatrix
();
if
(
input
==
null
)
{
throw
new
IllegalStateException
();
}
int
inputWidth
=
input
.
getWidth
();
int
inputHeight
=
input
.
getHeight
();
int
qrWidth
=
inputWidth
+
(
quietZone
*
2
);
int
qrHeight
=
inputHeight
+
(
quietZone
*
2
);
int
outputWidth
=
Math
.
max
(
width
,
qrWidth
);
int
outputHeight
=
Math
.
max
(
height
,
qrHeight
);
int
multiple
=
Math
.
min
(
outputWidth
/
qrWidth
,
outputHeight
/
qrHeight
);
// Padding includes both the quiet zone and the extra white pixels to accommodate the requested
// dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.
// If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will
// handle all the padding from 100x100 (the actual QR) up to 200x160.
int
leftPadding
=
(
outputWidth
-
(
inputWidth
*
multiple
))
/
2
;
int
topPadding
=
(
outputHeight
-
(
inputHeight
*
multiple
))
/
2
;
BitMatrix
output
=
new
BitMatrix
(
outputWidth
,
outputHeight
);
for
(
int
inputY
=
0
,
outputY
=
topPadding
;
inputY
<
inputHeight
;
inputY
++,
outputY
+=
multiple
)
{
// Write the contents of this row of the barcode
for
(
int
inputX
=
0
,
outputX
=
leftPadding
;
inputX
<
inputWidth
;
inputX
++,
outputX
+=
multiple
)
{
if
(
input
.
get
(
inputX
,
inputY
)
==
1
)
{
output
.
setRegion
(
outputX
,
outputY
,
multiple
,
multiple
);
}
}
}
return
output
;
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/ReaderException.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* The general exception class throw when something goes wrong during decoding of a barcode.
* This includes, but is not limited to, failing checksums / error correction algorithms, being
* unable to locate finder timing patterns, and so on.
*
* @author Sean Owen
*/
public
abstract
class
ReaderException
extends
Exception
{
// disable stack traces when not running inside test units
protected
static
final
boolean
isStackTrace
=
System
.
getProperty
(
"surefire.test.class.path"
)
!=
null
;
protected
static
final
StackTraceElement
[]
NO_TRACE
=
new
StackTraceElement
[
0
];
ReaderException
()
{
// do nothing
}
// Prevent stack traces from being taken
@Override
public
final
synchronized
Throwable
fillInStackTrace
()
{
return
null
;
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/ReedSolomonEncoder.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* <p>Implements Reed-Solomon enbcoding, as the name implies.</p>
*
* @author Sean Owen
* @author William Rucklidge
*/
public
final
class
ReedSolomonEncoder
{
private
final
GenericGF
field
;
private
final
List
<
GenericGFPoly
>
cachedGenerators
;
public
ReedSolomonEncoder
(
GenericGF
field
)
{
this
.
field
=
field
;
this
.
cachedGenerators
=
new
ArrayList
<>();
cachedGenerators
.
add
(
new
GenericGFPoly
(
field
,
new
int
[]{
1
}));
}
private
GenericGFPoly
buildGenerator
(
int
degree
)
{
if
(
degree
>=
cachedGenerators
.
size
())
{
GenericGFPoly
lastGenerator
=
cachedGenerators
.
get
(
cachedGenerators
.
size
()
-
1
);
for
(
int
d
=
cachedGenerators
.
size
();
d
<=
degree
;
d
++)
{
GenericGFPoly
nextGenerator
=
lastGenerator
.
multiply
(
new
GenericGFPoly
(
field
,
new
int
[]
{
1
,
field
.
exp
(
d
-
1
+
field
.
getGeneratorBase
())
}));
cachedGenerators
.
add
(
nextGenerator
);
lastGenerator
=
nextGenerator
;
}
}
return
cachedGenerators
.
get
(
degree
);
}
public
void
encode
(
int
[]
toEncode
,
int
ecBytes
)
{
if
(
ecBytes
==
0
)
{
throw
new
IllegalArgumentException
(
"No error correction bytes"
);
}
int
dataBytes
=
toEncode
.
length
-
ecBytes
;
if
(
dataBytes
<=
0
)
{
throw
new
IllegalArgumentException
(
"No data bytes provided"
);
}
GenericGFPoly
generator
=
buildGenerator
(
ecBytes
);
int
[]
infoCoefficients
=
new
int
[
dataBytes
];
System
.
arraycopy
(
toEncode
,
0
,
infoCoefficients
,
0
,
dataBytes
);
GenericGFPoly
info
=
new
GenericGFPoly
(
field
,
infoCoefficients
);
info
=
info
.
multiplyByMonomial
(
ecBytes
,
1
);
GenericGFPoly
remainder
=
info
.
divide
(
generator
)[
1
];
int
[]
coefficients
=
remainder
.
getCoefficients
();
int
numZeroCoefficients
=
ecBytes
-
coefficients
.
length
;
for
(
int
i
=
0
;
i
<
numZeroCoefficients
;
i
++)
{
toEncode
[
dataBytes
+
i
]
=
0
;
}
System
.
arraycopy
(
coefficients
,
0
,
toEncode
,
dataBytes
+
numZeroCoefficients
,
coefficients
.
length
);
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/Version.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* See ISO 18004:2006 Annex D
*
* @author Sean Owen
*/
public
final
class
Version
{
/**
* See ISO 18004:2006 Annex D.
* Element i represents the raw version bits that specify version i + 7
*/
private
static
final
int
[]
VERSION_DECODE_INFO
=
{
0x07C94
,
0x085BC
,
0x09A99
,
0x0A4D3
,
0x0BBF6
,
0x0C762
,
0x0D847
,
0x0E60D
,
0x0F928
,
0x10B78
,
0x1145D
,
0x12A17
,
0x13532
,
0x149A6
,
0x15683
,
0x168C9
,
0x177EC
,
0x18EC4
,
0x191E1
,
0x1AFAB
,
0x1B08E
,
0x1CC1A
,
0x1D33F
,
0x1ED75
,
0x1F250
,
0x209D5
,
0x216F0
,
0x228BA
,
0x2379F
,
0x24B0B
,
0x2542E
,
0x26A64
,
0x27541
,
0x28C69
};
private
static
final
Version
[]
VERSIONS
=
buildVersions
();
private
final
int
versionNumber
;
private
final
int
[]
alignmentPatternCenters
;
private
final
ECBlocks
[]
ecBlocks
;
private
final
int
totalCodewords
;
private
Version
(
int
versionNumber
,
int
[]
alignmentPatternCenters
,
ECBlocks
...
ecBlocks
)
{
this
.
versionNumber
=
versionNumber
;
this
.
alignmentPatternCenters
=
alignmentPatternCenters
;
this
.
ecBlocks
=
ecBlocks
;
int
total
=
0
;
int
ecCodewords
=
ecBlocks
[
0
].
getECCodewordsPerBlock
();
ECB
[]
ecbArray
=
ecBlocks
[
0
].
getECBlocks
();
for
(
ECB
ecBlock
:
ecbArray
)
{
total
+=
ecBlock
.
getCount
()
*
(
ecBlock
.
getDataCodewords
()
+
ecCodewords
);
}
this
.
totalCodewords
=
total
;
}
public
int
getVersionNumber
()
{
return
versionNumber
;
}
public
int
getTotalCodewords
()
{
return
totalCodewords
;
}
public
int
getDimensionForVersion
()
{
return
17
+
4
*
versionNumber
;
}
public
ECBlocks
getECBlocksForLevel
(
ErrorCorrectionLevel
ecLevel
)
{
return
ecBlocks
[
ecLevel
.
ordinal
()];
}
public
static
Version
getVersionForNumber
(
int
versionNumber
)
{
if
(
versionNumber
<
1
||
versionNumber
>
40
)
{
throw
new
IllegalArgumentException
();
}
return
VERSIONS
[
versionNumber
-
1
];
}
/**
* <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will
* use blocks of differing sizes within one version, so, this encapsulates the parameters for
* each set of blocks. It also holds the number of error-correction codewords per block since it
* will be the same across all blocks within one version.</p>
*/
public
static
final
class
ECBlocks
{
private
final
int
ecCodewordsPerBlock
;
private
final
ECB
[]
ecBlocks
;
ECBlocks
(
int
ecCodewordsPerBlock
,
ECB
...
ecBlocks
)
{
this
.
ecCodewordsPerBlock
=
ecCodewordsPerBlock
;
this
.
ecBlocks
=
ecBlocks
;
}
public
int
getECCodewordsPerBlock
()
{
return
ecCodewordsPerBlock
;
}
public
int
getNumBlocks
()
{
int
total
=
0
;
for
(
ECB
ecBlock
:
ecBlocks
)
{
total
+=
ecBlock
.
getCount
();
}
return
total
;
}
public
int
getTotalECCodewords
()
{
return
ecCodewordsPerBlock
*
getNumBlocks
();
}
public
ECB
[]
getECBlocks
()
{
return
ecBlocks
;
}
}
/**
* <p>Encapsulates the parameters for one error-correction block in one symbol version.
* This includes the number of data codewords, and the number of times a block with these
* parameters is used consecutively in the QR code version's format.</p>
*/
public
static
final
class
ECB
{
private
final
int
count
;
private
final
int
dataCodewords
;
ECB
(
int
count
,
int
dataCodewords
)
{
this
.
count
=
count
;
this
.
dataCodewords
=
dataCodewords
;
}
public
int
getCount
()
{
return
count
;
}
public
int
getDataCodewords
()
{
return
dataCodewords
;
}
}
@Override
public
String
toString
()
{
return
String
.
valueOf
(
versionNumber
);
}
/**
* See ISO 18004:2006 6.5.1 Table 9
*/
private
static
Version
[]
buildVersions
()
{
return
new
Version
[]{
new
Version
(
1
,
new
int
[]{},
new
ECBlocks
(
7
,
new
ECB
(
1
,
19
)),
new
ECBlocks
(
10
,
new
ECB
(
1
,
16
)),
new
ECBlocks
(
13
,
new
ECB
(
1
,
13
)),
new
ECBlocks
(
17
,
new
ECB
(
1
,
9
))),
new
Version
(
2
,
new
int
[]{
6
,
18
},
new
ECBlocks
(
10
,
new
ECB
(
1
,
34
)),
new
ECBlocks
(
16
,
new
ECB
(
1
,
28
)),
new
ECBlocks
(
22
,
new
ECB
(
1
,
22
)),
new
ECBlocks
(
28
,
new
ECB
(
1
,
16
))),
new
Version
(
3
,
new
int
[]{
6
,
22
},
new
ECBlocks
(
15
,
new
ECB
(
1
,
55
)),
new
ECBlocks
(
26
,
new
ECB
(
1
,
44
)),
new
ECBlocks
(
18
,
new
ECB
(
2
,
17
)),
new
ECBlocks
(
22
,
new
ECB
(
2
,
13
))),
new
Version
(
4
,
new
int
[]{
6
,
26
},
new
ECBlocks
(
20
,
new
ECB
(
1
,
80
)),
new
ECBlocks
(
18
,
new
ECB
(
2
,
32
)),
new
ECBlocks
(
26
,
new
ECB
(
2
,
24
)),
new
ECBlocks
(
16
,
new
ECB
(
4
,
9
))),
new
Version
(
5
,
new
int
[]{
6
,
30
},
new
ECBlocks
(
26
,
new
ECB
(
1
,
108
)),
new
ECBlocks
(
24
,
new
ECB
(
2
,
43
)),
new
ECBlocks
(
18
,
new
ECB
(
2
,
15
),
new
ECB
(
2
,
16
)),
new
ECBlocks
(
22
,
new
ECB
(
2
,
11
),
new
ECB
(
2
,
12
))),
new
Version
(
6
,
new
int
[]{
6
,
34
},
new
ECBlocks
(
18
,
new
ECB
(
2
,
68
)),
new
ECBlocks
(
16
,
new
ECB
(
4
,
27
)),
new
ECBlocks
(
24
,
new
ECB
(
4
,
19
)),
new
ECBlocks
(
28
,
new
ECB
(
4
,
15
))),
new
Version
(
7
,
new
int
[]{
6
,
22
,
38
},
new
ECBlocks
(
20
,
new
ECB
(
2
,
78
)),
new
ECBlocks
(
18
,
new
ECB
(
4
,
31
)),
new
ECBlocks
(
18
,
new
ECB
(
2
,
14
),
new
ECB
(
4
,
15
)),
new
ECBlocks
(
26
,
new
ECB
(
4
,
13
),
new
ECB
(
1
,
14
))),
new
Version
(
8
,
new
int
[]{
6
,
24
,
42
},
new
ECBlocks
(
24
,
new
ECB
(
2
,
97
)),
new
ECBlocks
(
22
,
new
ECB
(
2
,
38
),
new
ECB
(
2
,
39
)),
new
ECBlocks
(
22
,
new
ECB
(
4
,
18
),
new
ECB
(
2
,
19
)),
new
ECBlocks
(
26
,
new
ECB
(
4
,
14
),
new
ECB
(
2
,
15
))),
new
Version
(
9
,
new
int
[]{
6
,
26
,
46
},
new
ECBlocks
(
30
,
new
ECB
(
2
,
116
)),
new
ECBlocks
(
22
,
new
ECB
(
3
,
36
),
new
ECB
(
2
,
37
)),
new
ECBlocks
(
20
,
new
ECB
(
4
,
16
),
new
ECB
(
4
,
17
)),
new
ECBlocks
(
24
,
new
ECB
(
4
,
12
),
new
ECB
(
4
,
13
))),
new
Version
(
10
,
new
int
[]{
6
,
28
,
50
},
new
ECBlocks
(
18
,
new
ECB
(
2
,
68
),
new
ECB
(
2
,
69
)),
new
ECBlocks
(
26
,
new
ECB
(
4
,
43
),
new
ECB
(
1
,
44
)),
new
ECBlocks
(
24
,
new
ECB
(
6
,
19
),
new
ECB
(
2
,
20
)),
new
ECBlocks
(
28
,
new
ECB
(
6
,
15
),
new
ECB
(
2
,
16
))),
new
Version
(
11
,
new
int
[]{
6
,
30
,
54
},
new
ECBlocks
(
20
,
new
ECB
(
4
,
81
)),
new
ECBlocks
(
30
,
new
ECB
(
1
,
50
),
new
ECB
(
4
,
51
)),
new
ECBlocks
(
28
,
new
ECB
(
4
,
22
),
new
ECB
(
4
,
23
)),
new
ECBlocks
(
24
,
new
ECB
(
3
,
12
),
new
ECB
(
8
,
13
))),
new
Version
(
12
,
new
int
[]{
6
,
32
,
58
},
new
ECBlocks
(
24
,
new
ECB
(
2
,
92
),
new
ECB
(
2
,
93
)),
new
ECBlocks
(
22
,
new
ECB
(
6
,
36
),
new
ECB
(
2
,
37
)),
new
ECBlocks
(
26
,
new
ECB
(
4
,
20
),
new
ECB
(
6
,
21
)),
new
ECBlocks
(
28
,
new
ECB
(
7
,
14
),
new
ECB
(
4
,
15
))),
new
Version
(
13
,
new
int
[]{
6
,
34
,
62
},
new
ECBlocks
(
26
,
new
ECB
(
4
,
107
)),
new
ECBlocks
(
22
,
new
ECB
(
8
,
37
),
new
ECB
(
1
,
38
)),
new
ECBlocks
(
24
,
new
ECB
(
8
,
20
),
new
ECB
(
4
,
21
)),
new
ECBlocks
(
22
,
new
ECB
(
12
,
11
),
new
ECB
(
4
,
12
))),
new
Version
(
14
,
new
int
[]{
6
,
26
,
46
,
66
},
new
ECBlocks
(
30
,
new
ECB
(
3
,
115
),
new
ECB
(
1
,
116
)),
new
ECBlocks
(
24
,
new
ECB
(
4
,
40
),
new
ECB
(
5
,
41
)),
new
ECBlocks
(
20
,
new
ECB
(
11
,
16
),
new
ECB
(
5
,
17
)),
new
ECBlocks
(
24
,
new
ECB
(
11
,
12
),
new
ECB
(
5
,
13
))),
new
Version
(
15
,
new
int
[]{
6
,
26
,
48
,
70
},
new
ECBlocks
(
22
,
new
ECB
(
5
,
87
),
new
ECB
(
1
,
88
)),
new
ECBlocks
(
24
,
new
ECB
(
5
,
41
),
new
ECB
(
5
,
42
)),
new
ECBlocks
(
30
,
new
ECB
(
5
,
24
),
new
ECB
(
7
,
25
)),
new
ECBlocks
(
24
,
new
ECB
(
11
,
12
),
new
ECB
(
7
,
13
))),
new
Version
(
16
,
new
int
[]{
6
,
26
,
50
,
74
},
new
ECBlocks
(
24
,
new
ECB
(
5
,
98
),
new
ECB
(
1
,
99
)),
new
ECBlocks
(
28
,
new
ECB
(
7
,
45
),
new
ECB
(
3
,
46
)),
new
ECBlocks
(
24
,
new
ECB
(
15
,
19
),
new
ECB
(
2
,
20
)),
new
ECBlocks
(
30
,
new
ECB
(
3
,
15
),
new
ECB
(
13
,
16
))),
new
Version
(
17
,
new
int
[]{
6
,
30
,
54
,
78
},
new
ECBlocks
(
28
,
new
ECB
(
1
,
107
),
new
ECB
(
5
,
108
)),
new
ECBlocks
(
28
,
new
ECB
(
10
,
46
),
new
ECB
(
1
,
47
)),
new
ECBlocks
(
28
,
new
ECB
(
1
,
22
),
new
ECB
(
15
,
23
)),
new
ECBlocks
(
28
,
new
ECB
(
2
,
14
),
new
ECB
(
17
,
15
))),
new
Version
(
18
,
new
int
[]{
6
,
30
,
56
,
82
},
new
ECBlocks
(
30
,
new
ECB
(
5
,
120
),
new
ECB
(
1
,
121
)),
new
ECBlocks
(
26
,
new
ECB
(
9
,
43
),
new
ECB
(
4
,
44
)),
new
ECBlocks
(
28
,
new
ECB
(
17
,
22
),
new
ECB
(
1
,
23
)),
new
ECBlocks
(
28
,
new
ECB
(
2
,
14
),
new
ECB
(
19
,
15
))),
new
Version
(
19
,
new
int
[]{
6
,
30
,
58
,
86
},
new
ECBlocks
(
28
,
new
ECB
(
3
,
113
),
new
ECB
(
4
,
114
)),
new
ECBlocks
(
26
,
new
ECB
(
3
,
44
),
new
ECB
(
11
,
45
)),
new
ECBlocks
(
26
,
new
ECB
(
17
,
21
),
new
ECB
(
4
,
22
)),
new
ECBlocks
(
26
,
new
ECB
(
9
,
13
),
new
ECB
(
16
,
14
))),
new
Version
(
20
,
new
int
[]{
6
,
34
,
62
,
90
},
new
ECBlocks
(
28
,
new
ECB
(
3
,
107
),
new
ECB
(
5
,
108
)),
new
ECBlocks
(
26
,
new
ECB
(
3
,
41
),
new
ECB
(
13
,
42
)),
new
ECBlocks
(
30
,
new
ECB
(
15
,
24
),
new
ECB
(
5
,
25
)),
new
ECBlocks
(
28
,
new
ECB
(
15
,
15
),
new
ECB
(
10
,
16
))),
new
Version
(
21
,
new
int
[]{
6
,
28
,
50
,
72
,
94
},
new
ECBlocks
(
28
,
new
ECB
(
4
,
116
),
new
ECB
(
4
,
117
)),
new
ECBlocks
(
26
,
new
ECB
(
17
,
42
)),
new
ECBlocks
(
28
,
new
ECB
(
17
,
22
),
new
ECB
(
6
,
23
)),
new
ECBlocks
(
30
,
new
ECB
(
19
,
16
),
new
ECB
(
6
,
17
))),
new
Version
(
22
,
new
int
[]{
6
,
26
,
50
,
74
,
98
},
new
ECBlocks
(
28
,
new
ECB
(
2
,
111
),
new
ECB
(
7
,
112
)),
new
ECBlocks
(
28
,
new
ECB
(
17
,
46
)),
new
ECBlocks
(
30
,
new
ECB
(
7
,
24
),
new
ECB
(
16
,
25
)),
new
ECBlocks
(
24
,
new
ECB
(
34
,
13
))),
new
Version
(
23
,
new
int
[]{
6
,
30
,
54
,
78
,
102
},
new
ECBlocks
(
30
,
new
ECB
(
4
,
121
),
new
ECB
(
5
,
122
)),
new
ECBlocks
(
28
,
new
ECB
(
4
,
47
),
new
ECB
(
14
,
48
)),
new
ECBlocks
(
30
,
new
ECB
(
11
,
24
),
new
ECB
(
14
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
16
,
15
),
new
ECB
(
14
,
16
))),
new
Version
(
24
,
new
int
[]{
6
,
28
,
54
,
80
,
106
},
new
ECBlocks
(
30
,
new
ECB
(
6
,
117
),
new
ECB
(
4
,
118
)),
new
ECBlocks
(
28
,
new
ECB
(
6
,
45
),
new
ECB
(
14
,
46
)),
new
ECBlocks
(
30
,
new
ECB
(
11
,
24
),
new
ECB
(
16
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
30
,
16
),
new
ECB
(
2
,
17
))),
new
Version
(
25
,
new
int
[]{
6
,
32
,
58
,
84
,
110
},
new
ECBlocks
(
26
,
new
ECB
(
8
,
106
),
new
ECB
(
4
,
107
)),
new
ECBlocks
(
28
,
new
ECB
(
8
,
47
),
new
ECB
(
13
,
48
)),
new
ECBlocks
(
30
,
new
ECB
(
7
,
24
),
new
ECB
(
22
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
22
,
15
),
new
ECB
(
13
,
16
))),
new
Version
(
26
,
new
int
[]{
6
,
30
,
58
,
86
,
114
},
new
ECBlocks
(
28
,
new
ECB
(
10
,
114
),
new
ECB
(
2
,
115
)),
new
ECBlocks
(
28
,
new
ECB
(
19
,
46
),
new
ECB
(
4
,
47
)),
new
ECBlocks
(
28
,
new
ECB
(
28
,
22
),
new
ECB
(
6
,
23
)),
new
ECBlocks
(
30
,
new
ECB
(
33
,
16
),
new
ECB
(
4
,
17
))),
new
Version
(
27
,
new
int
[]{
6
,
34
,
62
,
90
,
118
},
new
ECBlocks
(
30
,
new
ECB
(
8
,
122
),
new
ECB
(
4
,
123
)),
new
ECBlocks
(
28
,
new
ECB
(
22
,
45
),
new
ECB
(
3
,
46
)),
new
ECBlocks
(
30
,
new
ECB
(
8
,
23
),
new
ECB
(
26
,
24
)),
new
ECBlocks
(
30
,
new
ECB
(
12
,
15
),
new
ECB
(
28
,
16
))),
new
Version
(
28
,
new
int
[]{
6
,
26
,
50
,
74
,
98
,
122
},
new
ECBlocks
(
30
,
new
ECB
(
3
,
117
),
new
ECB
(
10
,
118
)),
new
ECBlocks
(
28
,
new
ECB
(
3
,
45
),
new
ECB
(
23
,
46
)),
new
ECBlocks
(
30
,
new
ECB
(
4
,
24
),
new
ECB
(
31
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
11
,
15
),
new
ECB
(
31
,
16
))),
new
Version
(
29
,
new
int
[]{
6
,
30
,
54
,
78
,
102
,
126
},
new
ECBlocks
(
30
,
new
ECB
(
7
,
116
),
new
ECB
(
7
,
117
)),
new
ECBlocks
(
28
,
new
ECB
(
21
,
45
),
new
ECB
(
7
,
46
)),
new
ECBlocks
(
30
,
new
ECB
(
1
,
23
),
new
ECB
(
37
,
24
)),
new
ECBlocks
(
30
,
new
ECB
(
19
,
15
),
new
ECB
(
26
,
16
))),
new
Version
(
30
,
new
int
[]{
6
,
26
,
52
,
78
,
104
,
130
},
new
ECBlocks
(
30
,
new
ECB
(
5
,
115
),
new
ECB
(
10
,
116
)),
new
ECBlocks
(
28
,
new
ECB
(
19
,
47
),
new
ECB
(
10
,
48
)),
new
ECBlocks
(
30
,
new
ECB
(
15
,
24
),
new
ECB
(
25
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
23
,
15
),
new
ECB
(
25
,
16
))),
new
Version
(
31
,
new
int
[]{
6
,
30
,
56
,
82
,
108
,
134
},
new
ECBlocks
(
30
,
new
ECB
(
13
,
115
),
new
ECB
(
3
,
116
)),
new
ECBlocks
(
28
,
new
ECB
(
2
,
46
),
new
ECB
(
29
,
47
)),
new
ECBlocks
(
30
,
new
ECB
(
42
,
24
),
new
ECB
(
1
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
23
,
15
),
new
ECB
(
28
,
16
))),
new
Version
(
32
,
new
int
[]{
6
,
34
,
60
,
86
,
112
,
138
},
new
ECBlocks
(
30
,
new
ECB
(
17
,
115
)),
new
ECBlocks
(
28
,
new
ECB
(
10
,
46
),
new
ECB
(
23
,
47
)),
new
ECBlocks
(
30
,
new
ECB
(
10
,
24
),
new
ECB
(
35
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
19
,
15
),
new
ECB
(
35
,
16
))),
new
Version
(
33
,
new
int
[]{
6
,
30
,
58
,
86
,
114
,
142
},
new
ECBlocks
(
30
,
new
ECB
(
17
,
115
),
new
ECB
(
1
,
116
)),
new
ECBlocks
(
28
,
new
ECB
(
14
,
46
),
new
ECB
(
21
,
47
)),
new
ECBlocks
(
30
,
new
ECB
(
29
,
24
),
new
ECB
(
19
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
11
,
15
),
new
ECB
(
46
,
16
))),
new
Version
(
34
,
new
int
[]{
6
,
34
,
62
,
90
,
118
,
146
},
new
ECBlocks
(
30
,
new
ECB
(
13
,
115
),
new
ECB
(
6
,
116
)),
new
ECBlocks
(
28
,
new
ECB
(
14
,
46
),
new
ECB
(
23
,
47
)),
new
ECBlocks
(
30
,
new
ECB
(
44
,
24
),
new
ECB
(
7
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
59
,
16
),
new
ECB
(
1
,
17
))),
new
Version
(
35
,
new
int
[]{
6
,
30
,
54
,
78
,
102
,
126
,
150
},
new
ECBlocks
(
30
,
new
ECB
(
12
,
121
),
new
ECB
(
7
,
122
)),
new
ECBlocks
(
28
,
new
ECB
(
12
,
47
),
new
ECB
(
26
,
48
)),
new
ECBlocks
(
30
,
new
ECB
(
39
,
24
),
new
ECB
(
14
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
22
,
15
),
new
ECB
(
41
,
16
))),
new
Version
(
36
,
new
int
[]{
6
,
24
,
50
,
76
,
102
,
128
,
154
},
new
ECBlocks
(
30
,
new
ECB
(
6
,
121
),
new
ECB
(
14
,
122
)),
new
ECBlocks
(
28
,
new
ECB
(
6
,
47
),
new
ECB
(
34
,
48
)),
new
ECBlocks
(
30
,
new
ECB
(
46
,
24
),
new
ECB
(
10
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
2
,
15
),
new
ECB
(
64
,
16
))),
new
Version
(
37
,
new
int
[]{
6
,
28
,
54
,
80
,
106
,
132
,
158
},
new
ECBlocks
(
30
,
new
ECB
(
17
,
122
),
new
ECB
(
4
,
123
)),
new
ECBlocks
(
28
,
new
ECB
(
29
,
46
),
new
ECB
(
14
,
47
)),
new
ECBlocks
(
30
,
new
ECB
(
49
,
24
),
new
ECB
(
10
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
24
,
15
),
new
ECB
(
46
,
16
))),
new
Version
(
38
,
new
int
[]{
6
,
32
,
58
,
84
,
110
,
136
,
162
},
new
ECBlocks
(
30
,
new
ECB
(
4
,
122
),
new
ECB
(
18
,
123
)),
new
ECBlocks
(
28
,
new
ECB
(
13
,
46
),
new
ECB
(
32
,
47
)),
new
ECBlocks
(
30
,
new
ECB
(
48
,
24
),
new
ECB
(
14
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
42
,
15
),
new
ECB
(
32
,
16
))),
new
Version
(
39
,
new
int
[]{
6
,
26
,
54
,
82
,
110
,
138
,
166
},
new
ECBlocks
(
30
,
new
ECB
(
20
,
117
),
new
ECB
(
4
,
118
)),
new
ECBlocks
(
28
,
new
ECB
(
40
,
47
),
new
ECB
(
7
,
48
)),
new
ECBlocks
(
30
,
new
ECB
(
43
,
24
),
new
ECB
(
22
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
10
,
15
),
new
ECB
(
67
,
16
))),
new
Version
(
40
,
new
int
[]{
6
,
30
,
58
,
86
,
114
,
142
,
170
},
new
ECBlocks
(
30
,
new
ECB
(
19
,
118
),
new
ECB
(
6
,
119
)),
new
ECBlocks
(
28
,
new
ECB
(
18
,
47
),
new
ECB
(
31
,
48
)),
new
ECBlocks
(
30
,
new
ECB
(
34
,
24
),
new
ECB
(
34
,
25
)),
new
ECBlocks
(
30
,
new
ECB
(
20
,
15
),
new
ECB
(
61
,
16
)))
};
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/Writer.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
import
java.util.Map
;
/**
* The base class for all objects which encode/generate a barcode image.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public
interface
Writer
{
/**
* Encode a barcode using the default settings.
*
* @param contents The contents to encode in the barcode
* @param format The barcode format to generate
* @param width The preferred width in pixels
* @param height The preferred height in pixels
* @return {@link BitMatrix} representing encoded barcode image
* @throws WriterException if contents cannot be encoded legally in a format
*/
BitMatrix
encode
(
String
contents
,
BarcodeFormat
format
,
int
width
,
int
height
)
throws
WriterException
;
/**
* @param contents The contents to encode in the barcode
* @param format The barcode format to generate
* @param width The preferred width in pixels
* @param height The preferred height in pixels
* @param hints Additional parameters to supply to the encoder
* @return {@link BitMatrix} representing encoded barcode image
* @throws WriterException if contents cannot be encoded legally in a format
*/
BitMatrix
encode
(
String
contents
,
BarcodeFormat
format
,
int
width
,
int
height
,
Map
<
EncodeHintType
,
?>
hints
)
throws
WriterException
;
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/utils/zxing/WriterException.java
0 → 100755
View file @
b6da758b
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
widget
.
imagevideobanner
.
utils
.
zxing
;
/**
* A base class which covers the range of exceptions which may occur when encoding a barcode using
* the Writer framework.
*
* @author dswitkin@google.com (Daniel Switkin)
*/
public
final
class
WriterException
extends
Exception
{
public
WriterException
()
{
}
public
WriterException
(
String
message
)
{
super
(
message
);
}
public
WriterException
(
Throwable
cause
)
{
super
(
cause
);
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/view/
VpImage
View.java
→
imageVideoBanner/src/main/java/com/widget/imagevideobanner/view/
ImageSub
View.java
View file @
b6da758b
package
com
.
widget
.
imagevideobanner
.
view
;
package
com
.
widget
.
imagevideobanner
.
view
;
import
android.content.Context
;
import
android.content.Context
;
import
android.graphics.drawable.BitmapDrawable
;
import
android.graphics.drawable.Drawable
;
import
android.os.Handler
;
import
android.os.Handler
;
import
android.
support.annotation.Nullable
;
import
android.
os.Looper
;
import
android.support.v7.widget.AppCompatImageView
;
import
android.support.v7.widget.AppCompatImageView
;
import
android.util.Log
;
import
android.util.Log
;
import
com.bumptech.glide.Glide
;
import
com.bumptech.glide.Glide
;
import
com.bumptech.glide.load.DataSource
;
import
com.bumptech.glide.load.resource.drawable.GlideDrawable
;
import
com.bumptech.glide.load.engine.GlideException
;
import
com.bumptech.glide.request.RequestListener
;
import
com.bumptech.glide.request.RequestListener
;
import
com.bumptech.glide.request.target.Target
;
import
com.bumptech.glide.request.target.Target
;
import
com.widget.imagevideobanner.R
;
import
com.widget.imagevideobanner.bean.MediaBean
;
import
com.widget.imagevideobanner.bean.MediaBean
;
import
com.widget.imagevideobanner.log.BLogUtil
;
import
com.widget.imagevideobanner.player.IPlayTarget
;
import
com.widget.imagevideobanner.player.IPlayTarget
;
import
com.widget.imagevideobanner.utils.QRCodeUtil
;
import
com.widget.imagevideobanner.utils.ThrowableUtils
;
import
com.widget.imagevideobanner.utils.ThrowableUtils
;
/**
/**
* 5秒自动切换图片
* 5秒自动切换图片
*/
*/
public
class
VpImageView
extends
AppCompatImageView
implements
IPlayTarget
{
public
class
ImageSubView
extends
AppCompatImageView
implements
IPlayTarget
,
RequestListener
<
String
,
GlideDrawable
>,
Runnable
{
private
static
final
String
TAG
=
"VpImageView"
;
private
static
final
int
DEFAULT_SWITCH_PAGE_TIME
=
5000
;
private
static
final
int
DEFAULT_SWITCH_PAGE_TIME
=
5000
;
private
OnActionFinishListener
onPageChangedListener
;
private
OnActionFinishListener
onPageChangedListener
;
private
Handler
handler
=
new
Handler
();
private
final
Handler
handler
=
new
Handler
(
Looper
.
getMainLooper
());
private
Runnable
pageChangeRunable
=
new
Runnable
()
{
@Override
public
void
run
()
{
inActive
();
if
(
null
!=
onPageChangedListener
){
onPageChangedListener
.
next
();
}
}
};
private
RequestListener
requestListener
=
new
RequestListener
()
{
@Override
public
boolean
onLoadFailed
(
@Nullable
GlideException
e
,
Object
model
,
Target
target
,
boolean
isFirstResource
)
{
Log
.
e
(
TAG
,
ThrowableUtils
.
getFullStackTrace
(
e
));
return
false
;
}
@Override
public
ImageSubView
(
Context
context
)
{
public
boolean
onResourceReady
(
Object
resource
,
Object
model
,
Target
target
,
DataSource
dataSource
,
boolean
isFirstResource
)
{
return
false
;
}
};
public
VpImageView
(
Context
context
)
{
super
(
context
);
super
(
context
);
}
}
public
VpImage
View
(
Context
context
,
final
MediaBean
mediaBean
,
final
OnActionFinishListener
onPageChangedListener
)
{
public
ImageSub
View
(
Context
context
,
final
MediaBean
mediaBean
,
final
OnActionFinishListener
onPageChangedListener
)
{
super
(
context
);
super
(
context
);
this
.
onPageChangedListener
=
onPageChangedListener
;
this
.
onPageChangedListener
=
onPageChangedListener
;
setImageUrl
(
mediaBean
.
getUrl
());
setImageUrl
(
mediaBean
.
getUrl
());
}
}
private
void
setImageUrl
(
String
url
)
{
private
void
setImageUrl
(
String
url
)
{
Log
.
e
(
TAG
,
url
);
BLogUtil
.
log
(
"设置图片链接:"
+
url
);
Drawable
err
=
new
BitmapDrawable
(
getResources
(),
QRCodeUtil
.
createQRCodeBitmap
(
url
,
100
));
Glide
.
with
(
getContext
()).
load
(
url
)
Glide
.
with
(
getContext
()).
load
(
url
)
.
error
(
R
.
drawable
.
load_fail
)
.
centerCrop
()
.
placeholder
(
R
.
drawable
.
load_fail
)
.
error
(
err
)
.
listener
(
requestListener
).
into
(
this
);
.
listener
(
this
)
.
into
(
this
);
}
}
@Override
@Override
public
void
onActive
()
{
public
void
onActive
()
{
handler
.
removeCallbacks
(
pageChangeRunable
);
BLogUtil
.
log
(
"图片开始展示"
);
handler
.
postDelayed
(
pageChangeRunable
,
DEFAULT_SWITCH_PAGE_TIME
);
handler
.
removeCallbacks
(
this
);
handler
.
postDelayed
(
this
,
DEFAULT_SWITCH_PAGE_TIME
);
}
}
@Override
@Override
public
void
inActive
()
{
public
void
inActive
()
{
handler
.
removeCallbacks
(
pageChangeRunable
);
BLogUtil
.
log
(
"图片结束展示"
);
handler
.
removeCallbacks
(
this
);
}
@Override
public
void
run
()
{
inActive
();
if
(
null
!=
onPageChangedListener
){
onPageChangedListener
.
next
();
}
}
}
@Override
public
boolean
onException
(
Exception
e
,
String
model
,
Target
<
GlideDrawable
>
target
,
boolean
isFirstResource
)
{
BLogUtil
.
log
(
"图片加载异常"
+
ThrowableUtils
.
getFullStackTrace
(
e
));
return
false
;
}
@Override
public
boolean
onResourceReady
(
GlideDrawable
resource
,
String
model
,
Target
<
GlideDrawable
>
target
,
boolean
isFromMemoryCache
,
boolean
isFirstResource
)
{
BLogUtil
.
log
(
"图片加载完成"
);
return
false
;
}
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/view/ImageVideoBanner.java
View file @
b6da758b
package
com
.
widget
.
imagevideobanner
.
view
;
package
com
.
widget
.
imagevideobanner
.
view
;
import
android.content.Context
;
import
android.content.Context
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.os.Message
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
android.support.annotation.Nullable
;
import
android.support.v4.view.PagerAdapter
;
import
android.support.v4.view.PagerAdapter
;
import
android.text.TextUtils
;
import
android.util.AttributeSet
;
import
android.util.AttributeSet
;
import
android.util.Log
;
import
android.view.LayoutInflater
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.view.ViewGroup
;
import
android.widget.FrameLayout
;
import
android.widget.FrameLayout
;
import
com.alibaba.fastjson.JSON
;
import
com.blankj.utilcode.util.FileUtils
;
import
com.widget.imagevideobanner.R
;
import
com.widget.imagevideobanner.R
;
import
com.widget.imagevideobanner.bean.MediaBean
;
import
com.widget.imagevideobanner.bean.MediaBean
;
import
com.widget.imagevideobanner.log.BLogUtil
;
import
com.widget.imagevideobanner.player.IPlayTarget
;
import
com.widget.imagevideobanner.player.IPlayTarget
;
import
com.widget.imagevideobanner.utils.ResourceUtils
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
static
com
.
widget
.
imagevideobanner
.
bean
.
MediaBean
.
TYPE_IMAGE
;
import
static
com
.
widget
.
imagevideobanner
.
bean
.
MediaBean
.
TYPE_VIDEO
;
import
static
com
.
widget
.
imagevideobanner
.
bean
.
MediaBean
.
TYPE_VIDEO
;
/**
/**
...
@@ -27,11 +35,37 @@ import static com.widget.imagevideobanner.bean.MediaBean.TYPE_VIDEO;
...
@@ -27,11 +35,37 @@ import static com.widget.imagevideobanner.bean.MediaBean.TYPE_VIDEO;
*/
*/
public
class
ImageVideoBanner
extends
FrameLayout
implements
ViewPager
.
OnPageChangeListener
,
OnActionFinishListener
{
public
class
ImageVideoBanner
extends
FrameLayout
implements
ViewPager
.
OnPageChangeListener
,
OnActionFinishListener
{
private
static
String
TAG
=
"ImageVideoBanner"
;
private
final
static
String
HTTP
=
"http"
;
private
ViewPager
mViewPager
;
private
ViewPager
viewPager
;
private
List
<
View
>
mList
=
new
ArrayList
<>();
private
final
List
<
View
>
viewArrayList
=
new
ArrayList
<>();
private
ViewsPagerAdapter
mAdapter
;
private
final
List
<
MediaBean
>
mediaBeanList
=
new
ArrayList
<>();
private
ViewsPagerAdapter
viewsPagerAdapter
;
private
int
curIndex
;
private
int
curIndex
;
private
final
ExecutorService
sExecutor
=
Executors
.
newFixedThreadPool
(
3
);
private
final
Handler
handler
=
new
Handler
(
Looper
.
getMainLooper
(),
new
Handler
.
Callback
()
{
@Override
public
boolean
handleMessage
(
Message
msg
)
{
if
(
msg
.
what
==
1
)
{
BLogUtil
.
log
(
JSON
.
toJSONString
(
mediaBeanList
));
for
(
MediaBean
mediaBean
:
mediaBeanList
)
{
if
(!
TextUtils
.
isEmpty
(
mediaBean
.
getUrl
()))
{
if
(
mediaBean
.
getType
()
==
TYPE_VIDEO
)
{
viewArrayList
.
add
(
new
VideoSubView
(
getContext
(),
mediaBean
,
ImageVideoBanner
.
this
));
}
else
{
viewArrayList
.
add
(
new
ImageSubView
(
getContext
(),
mediaBean
,
ImageVideoBanner
.
this
));
}
}
}
if
(
viewArrayList
.
size
()
>
0
)
{
viewsPagerAdapter
.
notifyDataSetChanged
();
//onAttachedToWindow 执行的比较早
((
IPlayTarget
)
viewArrayList
.
get
(
0
)).
onActive
();
}
}
return
false
;
}
});
private
ImageVideoBanner
(
@NonNull
Context
context
)
{
private
ImageVideoBanner
(
@NonNull
Context
context
)
{
super
(
context
);
super
(
context
);
...
@@ -43,74 +77,126 @@ public class ImageVideoBanner extends FrameLayout implements ViewPager.OnPageCha
...
@@ -43,74 +77,126 @@ public class ImageVideoBanner extends FrameLayout implements ViewPager.OnPageCha
initView
();
initView
();
}
}
private
void
initView
(){
private
void
initView
()
{
View
view
=
LayoutInflater
.
from
(
getContext
()).
inflate
(
R
.
layout
.
banner_imge_video
,
this
,
true
);
View
view
=
LayoutInflater
.
from
(
getContext
()).
inflate
(
R
.
layout
.
banner_imge_video
,
this
,
true
);
mV
iewPager
=
view
.
findViewById
(
R
.
id
.
view_pager
);
v
iewPager
=
view
.
findViewById
(
R
.
id
.
view_pager
);
mAdapter
=
new
ViewsPagerAdapter
(
m
List
);
viewsPagerAdapter
=
new
ViewsPagerAdapter
(
viewArray
List
);
mViewPager
.
setAdapter
(
m
Adapter
);
viewPager
.
setAdapter
(
viewsPager
Adapter
);
mV
iewPager
.
setOnPageChangeListener
(
this
);
v
iewPager
.
setOnPageChangeListener
(
this
);
}
}
public
void
bindData
(
List
<
MediaBean
>
beans
){
public
void
bindData
(
List
<
MediaBean
>
beans
)
{
if
(
beans
==
null
){
final
List
<
MediaBean
>
realMedias
=
filterNoExist
(
beans
);
if
(
null
==
realMedias
||
realMedias
.
size
()
==
0
)
{
BLogUtil
.
log
(
"bindData数据是空!!!"
);
viewArrayList
.
clear
();
viewArrayList
.
add
(
new
VideoSubView
(
getContext
(),
MediaBean
.
getDefaultMedia
(
getContext
()),
this
));
viewsPagerAdapter
.
notifyDataSetChanged
();
return
;
return
;
}
}
mList
.
clear
();
for
(
MediaBean
mediaBean
:
beans
){
if
(!
mediaBean
.
isNull
()){
if
(
mediaBean
.
getResType
()
==
TYPE_IMAGE
){
mList
.
add
(
new
VpImageView
(
getContext
(),
mediaBean
,
this
));
}
if
(
mediaBean
.
getResType
()
==
TYPE_VIDEO
){
BLogUtil
.
log
(
"bindData轮播数据:"
+
JSON
.
toJSONString
(
realMedias
));
mList
.
add
(
new
VpVideoView
(
getContext
(),
mediaBean
,
this
));
}
sExecutor
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
resolveMedia
(
realMedias
);
handler
.
sendEmptyMessage
(
1
);
}
}
});
}
/**
* 资源有更新
*/
public
void
reflesh
(
List
<
MediaBean
>
beans
)
{
List
<
MediaBean
>
realMedias
=
filterNoExist
(
beans
);
if
(
null
==
realMedias
||
realMedias
.
size
()
==
0
)
return
;
if
(
mediaBeanList
.
size
()
==
0
||
mediaBeanList
.
size
()
!=
realMedias
.
size
())
{
bindData
(
realMedias
);
}
}
if
(
mList
.
size
()
>
0
){
}
mAdapter
.
notifyDataSetChanged
();
/**
* 排除不存在的视频
*/
private
List
<
MediaBean
>
filterNoExist
(
List
<
MediaBean
>
beans
)
{
if
(
beans
==
null
||
beans
.
size
()
<=
0
)
return
null
;
List
<
MediaBean
>
list
=
new
ArrayList
<>();
for
(
MediaBean
mediaBean
:
beans
)
{
if
(!
TextUtils
.
isEmpty
(
mediaBean
.
getUrl
()))
{
if
(
mediaBean
.
getType
()
==
TYPE_VIDEO
)
{
if
(!
mediaBean
.
getUrl
().
startsWith
(
HTTP
)
&&
FileUtils
.
isFileExists
(
mediaBean
.
getUrl
()))
{
list
.
add
(
mediaBean
);
}
}
else
{
list
.
add
(
mediaBean
);
}
}
}
}
return
list
;
}
}
@Override
/**
protected
void
onAttachedToWindow
()
{
* 截取首帧 宽高【耗时】
super
.
onAttachedToWindow
();
*/
IPlayTarget
iPlayTarget
=
(
IPlayTarget
)
mList
.
get
(
curIndex
);
private
void
resolveMedia
(
List
<
MediaBean
>
beans
)
{
iPlayTarget
.
onActive
();
mediaBeanList
.
clear
();
mediaBeanList
.
addAll
(
beans
);
for
(
MediaBean
mediaBean
:
mediaBeanList
)
{
if
(!
TextUtils
.
isEmpty
(
mediaBean
.
getUrl
())
&&
mediaBean
.
getType
()
==
TYPE_VIDEO
)
{
ResourceUtils
.
resolveVideo
(
mediaBean
);
}
}
}
}
@Override
@Override
protected
void
onDetachedFromWindow
()
{
protected
void
onWindowVisibilityChanged
(
int
visibility
)
{
super
.
onDetachedFromWindow
();
super
.
onWindowVisibilityChanged
(
visibility
);
IPlayTarget
iPlayTarget
=
(
IPlayTarget
)
mList
.
get
(
curIndex
);
if
(
viewArrayList
.
size
()
>
0
)
{
iPlayTarget
.
inActive
();
if
(
visibility
==
VISIBLE
){
BLogUtil
.
log
(
"onWindowVisibilityChanged 视图可见,开启广告"
);
IPlayTarget
iPlayTarget
=
(
IPlayTarget
)
viewArrayList
.
get
(
curIndex
);
iPlayTarget
.
onActive
();
}
else
{
BLogUtil
.
log
(
"onWindowVisibilityChanged 视图隐藏,暂停广告"
);
IPlayTarget
iPlayTarget
=
(
IPlayTarget
)
viewArrayList
.
get
(
curIndex
);
iPlayTarget
.
inActive
();
}
}
}
}
@Override
@Override
public
void
onPageScrolled
(
int
position
,
float
positionOffset
,
int
positionOffsetPixels
)
{}
public
void
onPageScrolled
(
int
position
,
float
positionOffset
,
int
positionOffsetPixels
)
{
}
@Override
@Override
public
void
onPageSelected
(
int
position
)
{
public
void
onPageSelected
(
int
position
)
{
IPlayTarget
iPlayTarget
=
(
IPlayTarget
)
m
List
.
get
(
curIndex
);
IPlayTarget
iPlayTarget
=
(
IPlayTarget
)
viewArray
List
.
get
(
curIndex
);
iPlayTarget
.
onActive
();
iPlayTarget
.
onActive
();
}
}
@Override
@Override
public
void
next
()
{
public
void
next
()
{
curIndex
=
curIndex
+
1
;
curIndex
=
curIndex
+
1
;
if
(
curIndex
>=
m
List
.
size
())
{
if
(
curIndex
>=
viewArray
List
.
size
())
{
curIndex
=
0
;
curIndex
=
0
;
}
}
Log
.
e
(
TAG
,
"curIndex = "
+
curIndex
);
viewPager
.
setCurrentItem
(
curIndex
);
mViewPager
.
setCurrentItem
(
curIndex
);
}
}
@Override
@Override
public
void
onPageScrollStateChanged
(
int
state
)
{
}
public
void
onPageScrollStateChanged
(
int
state
)
{
}
private
static
final
class
ViewsPagerAdapter
extends
PagerAdapter
{
private
static
final
class
ViewsPagerAdapter
extends
PagerAdapter
{
private
List
<
View
>
mList
;
private
final
List
<
View
>
mList
;
public
ViewsPagerAdapter
(
List
<
View
>
list
)
{
public
ViewsPagerAdapter
(
List
<
View
>
list
)
{
this
.
mList
=
list
;
this
.
mList
=
list
;
...
@@ -132,11 +218,12 @@ public class ImageVideoBanner extends FrameLayout implements ViewPager.OnPageCha
...
@@ -132,11 +218,12 @@ public class ImageVideoBanner extends FrameLayout implements ViewPager.OnPageCha
container
.
addView
(
mList
.
get
(
position
));
container
.
addView
(
mList
.
get
(
position
));
return
mList
.
get
(
position
);
return
mList
.
get
(
position
);
}
}
@Override
@Override
public
void
destroyItem
(
ViewGroup
container
,
int
position
,
@NonNull
Object
object
)
{
public
void
destroyItem
(
ViewGroup
container
,
int
position
,
@NonNull
Object
object
)
{
container
.
removeView
(
mList
.
get
(
position
));
container
.
removeView
(
mList
.
get
(
position
));
}
}
}
}
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/view/SampleCoverVideo.java
0 → 100644
View file @
b6da758b
package
com
.
widget
.
imagevideobanner
.
view
;
import
android.content.Context
;
import
android.graphics.Point
;
import
android.text.TextUtils
;
import
android.util.AttributeSet
;
import
android.view.MotionEvent
;
import
android.view.Surface
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.view.Window
;
import
android.widget.ImageView
;
import
android.widget.SeekBar
;
import
com.bumptech.glide.GenericRequestBuilder
;
import
com.bumptech.glide.Glide
;
import
com.bumptech.glide.RequestManager
;
import
com.bumptech.glide.load.engine.DiskCacheStrategy
;
import
com.shuyu.gsyvideoplayer.utils.CommonUtil
;
import
com.shuyu.gsyvideoplayer.utils.Debuger
;
import
com.shuyu.gsyvideoplayer.utils.GSYVideoType
;
import
com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
;
import
com.shuyu.gsyvideoplayer.video.base.GSYBaseVideoPlayer
;
import
com.widget.imagevideobanner.R
;
import
com.widget.imagevideobanner.log.BLogUtil
;
public
class
SampleCoverVideo
extends
StandardGSYVideoPlayer
{
ImageView
mCoverImage
;
String
mCoverOriginUrl
;
int
mCoverOriginId
=
0
;
int
mDefaultRes
;
public
SampleCoverVideo
(
Context
context
,
Boolean
fullFlag
)
{
super
(
context
,
fullFlag
);
}
public
SampleCoverVideo
(
Context
context
)
{
super
(
context
);
}
public
SampleCoverVideo
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
}
@Override
protected
void
init
(
Context
context
)
{
super
.
init
(
context
);
mCoverImage
=
(
ImageView
)
findViewById
(
R
.
id
.
thumbImage
);
if
(
mThumbImageViewLayout
!=
null
&&
(
mCurrentState
==
-
1
||
mCurrentState
==
CURRENT_STATE_NORMAL
||
mCurrentState
==
CURRENT_STATE_ERROR
))
{
mThumbImageViewLayout
.
setVisibility
(
VISIBLE
);
}
Debuger
.
enable
();
}
@Override
public
int
getLayoutId
()
{
return
R
.
layout
.
video_layout_cover
;
}
public
void
loadCoverImage
(
String
url
,
int
res
)
{
if
(
TextUtils
.
isEmpty
(
url
))
return
;
BLogUtil
.
log
(
"加载视频封面"
+
url
);
mCoverOriginUrl
=
url
;
mDefaultRes
=
res
;
Glide
.
with
(
getContext
().
getApplicationContext
())
.
load
(
url
)
.
diskCacheStrategy
(
DiskCacheStrategy
.
ALL
)
.
error
(
res
)
.
placeholder
(
res
)
.
into
(
mCoverImage
);
}
public
void
loadCoverImageBy
(
int
id
,
int
res
)
{
mCoverOriginId
=
id
;
mDefaultRes
=
res
;
mCoverImage
.
setImageResource
(
id
);
}
@Override
public
GSYBaseVideoPlayer
startWindowFullscreen
(
Context
context
,
boolean
actionBar
,
boolean
statusBar
)
{
GSYBaseVideoPlayer
gsyBaseVideoPlayer
=
super
.
startWindowFullscreen
(
context
,
actionBar
,
statusBar
);
SampleCoverVideo
sampleCoverVideo
=
(
SampleCoverVideo
)
gsyBaseVideoPlayer
;
if
(
mCoverOriginUrl
!=
null
)
{
sampleCoverVideo
.
loadCoverImage
(
mCoverOriginUrl
,
mDefaultRes
);
}
else
if
(
mCoverOriginId
!=
0
)
{
sampleCoverVideo
.
loadCoverImageBy
(
mCoverOriginId
,
mDefaultRes
);
}
return
gsyBaseVideoPlayer
;
}
@Override
public
GSYBaseVideoPlayer
showSmallVideo
(
Point
size
,
boolean
actionBar
,
boolean
statusBar
)
{
//下面这里替换成你自己的强制转化
SampleCoverVideo
sampleCoverVideo
=
(
SampleCoverVideo
)
super
.
showSmallVideo
(
size
,
actionBar
,
statusBar
);
sampleCoverVideo
.
mStartButton
.
setVisibility
(
GONE
);
sampleCoverVideo
.
mStartButton
=
null
;
return
sampleCoverVideo
;
}
@Override
protected
void
cloneParams
(
GSYBaseVideoPlayer
from
,
GSYBaseVideoPlayer
to
)
{
super
.
cloneParams
(
from
,
to
);
SampleCoverVideo
sf
=
(
SampleCoverVideo
)
from
;
SampleCoverVideo
st
=
(
SampleCoverVideo
)
to
;
st
.
mShowFullAnimation
=
sf
.
mShowFullAnimation
;
}
/**
* 退出window层播放全屏效果
*/
@SuppressWarnings
(
"ResourceType"
)
@Override
protected
void
clearFullscreenLayout
()
{
mIfCurrentIsFullscreen
=
false
;
int
delay
=
0
;
// ------- !!!如果不需要旋转屏幕,可以不调用!!!-------
// 不需要屏幕旋转,还需要设置 setNeedOrientationUtils(false)
if
(
mOrientationUtils
!=
null
)
{
delay
=
mOrientationUtils
.
backToProtVideo
();
mOrientationUtils
.
setEnable
(
false
);
if
(
mOrientationUtils
!=
null
)
{
mOrientationUtils
.
releaseListener
();
mOrientationUtils
=
null
;
}
}
if
(!
mShowFullAnimation
)
{
delay
=
0
;
}
final
ViewGroup
vp
=
(
CommonUtil
.
scanForActivity
(
getContext
())).
findViewById
(
Window
.
ID_ANDROID_CONTENT
);
final
View
oldF
=
vp
.
findViewById
(
getFullId
());
if
(
oldF
!=
null
)
{
//此处fix bug#265,推出全屏的时候,虚拟按键问题
SampleCoverVideo
gsyVideoPlayer
=
(
SampleCoverVideo
)
oldF
;
gsyVideoPlayer
.
mIfCurrentIsFullscreen
=
false
;
}
if
(
delay
==
0
)
{
backToNormal
();
}
else
{
postDelayed
(
new
Runnable
()
{
@Override
public
void
run
()
{
backToNormal
();
}
},
delay
);
}
}
/******************* 下方两个重载方法,在播放开始前不屏蔽封面,不需要可屏蔽 ********************/
@Override
public
void
onSurfaceUpdated
(
Surface
surface
)
{
super
.
onSurfaceUpdated
(
surface
);
if
(
mThumbImageViewLayout
!=
null
&&
mThumbImageViewLayout
.
getVisibility
()
==
VISIBLE
)
{
mThumbImageViewLayout
.
setVisibility
(
INVISIBLE
);
}
}
@Override
protected
void
setViewShowState
(
View
view
,
int
visibility
)
{
if
(
view
==
mThumbImageViewLayout
&&
visibility
!=
VISIBLE
)
{
return
;
}
super
.
setViewShowState
(
view
,
visibility
);
}
@Override
public
void
onSurfaceAvailable
(
Surface
surface
)
{
super
.
onSurfaceAvailable
(
surface
);
if
(
GSYVideoType
.
getRenderType
()
!=
GSYVideoType
.
TEXTURE
)
{
if
(
mThumbImageViewLayout
!=
null
&&
mThumbImageViewLayout
.
getVisibility
()
==
VISIBLE
)
{
mThumbImageViewLayout
.
setVisibility
(
INVISIBLE
);
}
}
}
/******************* 下方重载方法,在播放开始不显示底部进度和按键,不需要可屏蔽 ********************/
protected
boolean
byStartedClick
;
@Override
protected
void
onClickUiToggle
()
{
if
(
mIfCurrentIsFullscreen
&&
mLockCurScreen
&&
mNeedLockFull
)
{
setViewShowState
(
mLockScreen
,
VISIBLE
);
return
;
}
byStartedClick
=
true
;
super
.
onClickUiToggle
();
}
@Override
protected
void
changeUiToNormal
()
{
super
.
changeUiToNormal
();
Debuger
.
printfLog
(
"Sample changeUiToNormal"
);
byStartedClick
=
false
;
}
@Override
protected
void
changeUiToPreparingShow
()
{
super
.
changeUiToPreparingShow
();
Debuger
.
printfLog
(
"Sample changeUiToPreparingShow"
);
hideAllWidget
();
}
@Override
protected
void
changeUiToPlayingBufferingShow
()
{
super
.
changeUiToPlayingBufferingShow
();
Debuger
.
printfLog
(
"Sample changeUiToPlayingBufferingShow"
);
if
(!
byStartedClick
)
{
hideAllWidget
();
}
}
@Override
protected
void
changeUiToCompleteShow
()
{
Debuger
.
printfLog
(
"Sample changeUiToPlayingBufferingShow"
);
super
.
changeUiToCompleteShow
();
hideAllWidget
();
}
@Override
protected
void
changeUiToPlayingShow
()
{
super
.
changeUiToPlayingShow
();
Debuger
.
printfLog
(
"Sample changeUiToPlayingShow"
);
if
(!
byStartedClick
)
{
hideAllWidget
();
}
}
@Override
public
void
startAfterPrepared
()
{
super
.
startAfterPrepared
();
Debuger
.
printfLog
(
"Sample startAfterPrepared"
);
hideAllWidget
();
}
@Override
public
void
onStartTrackingTouch
(
SeekBar
seekBar
)
{
Debuger
.
printfLog
(
"Sample onStartTrackingTouch"
);
byStartedClick
=
true
;
super
.
onStartTrackingTouch
(
seekBar
);
}
protected
void
setTextAndProgress
(
int
secProgress
)
{
Debuger
.
printfLog
(
"Sample setTextAndProgress"
);
mBottomProgressBar
.
setVisibility
(
INVISIBLE
);
}
@Override
public
void
setIsTouchWiget
(
boolean
isTouchWiget
)
{
super
.
setIsTouchWiget
(
true
);
}
@Override
public
void
setIsTouchWigetFull
(
boolean
isTouchWigetFull
)
{
super
.
setIsTouchWigetFull
(
true
);
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/view/VideoSubView.java
0 → 100644
View file @
b6da758b
package
com
.
widget
.
imagevideobanner
.
view
;
import
android.content.Context
;
import
android.support.annotation.NonNull
;
import
android.util.Log
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.widget.FrameLayout
;
import
android.widget.ImageView
;
import
com.bumptech.glide.Glide
;
import
com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
;
import
com.shuyu.gsyvideoplayer.video.GSYSampleADVideoPlayer
;
import
com.widget.imagevideobanner.R
;
import
com.widget.imagevideobanner.bean.MediaBean
;
import
com.widget.imagevideobanner.log.BLogUtil
;
import
com.widget.imagevideobanner.player.IPlayTarget
;
public
class
VideoSubView
extends
FrameLayout
implements
IPlayTarget
{
private
OnActionFinishListener
mOnPageChangedListener
;
private
SampleCoverVideo
player
;
private
final
GSYSampleCallBack
sampleCallBack
=
new
GSYSampleCallBack
(){
@Override
public
void
onAutoComplete
(
String
url
,
Object
...
objects
)
{
super
.
onAutoComplete
(
url
,
objects
);
BLogUtil
.
log
(
"当前视频播放完毕,切换下一帧"
);
if
(
null
!=
mOnPageChangedListener
){
mOnPageChangedListener
.
next
();
}
}
};
public
VideoSubView
(
@NonNull
Context
context
)
{
super
(
context
);
}
public
VideoSubView
(
@NonNull
Context
context
,
MediaBean
mediaBean
,
final
OnActionFinishListener
onPageChangedListener
)
{
super
(
context
);
mOnPageChangedListener
=
onPageChangedListener
;
View
parent
=
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
layout_player_view
,
this
,
true
);
player
=
parent
.
findViewById
(
R
.
id
.
player
);
player
.
getBackButton
().
setVisibility
(
View
.
GONE
);
player
.
setAutoFullWithSize
(
true
);
player
.
setVideoAllCallBack
(
sampleCallBack
);
player
.
loadCoverImage
(
mediaBean
.
getCover
(),
0
);
player
.
setUp
(
mediaBean
.
getUrl
(),
true
,
null
);
player
.
setLooping
(
mediaBean
.
isLooping
());
}
@Override
public
void
onActive
()
{
BLogUtil
.
log
(
"视频开始播放"
);
player
.
startPlayLogic
();
}
@Override
public
void
inActive
()
{
BLogUtil
.
log
(
"视频暂停播放"
);
try
{
player
.
onVideoReset
();
}
catch
(
Throwable
e
){
BLogUtil
.
log
(
"停止视频播放出错 "
+
e
.
getLocalizedMessage
());
}
}
}
imageVideoBanner/src/main/java/com/widget/imagevideobanner/view/ViewPager.java
View file @
b6da758b
...
@@ -88,7 +88,7 @@ public class ViewPager extends ViewGroup {
...
@@ -88,7 +88,7 @@ public class ViewPager extends ViewGroup {
private
static
final
boolean
USE_CACHE
=
false
;
private
static
final
boolean
USE_CACHE
=
false
;
private
static
final
int
DEFAULT_OFFSCREEN_PAGES
=
5
;
//默认是1,这里直接改为0
private
static
final
int
DEFAULT_OFFSCREEN_PAGES
=
0
;
//默认是1,这里直接改为0
private
static
final
int
MAX_SETTLE_DURATION
=
600
;
// ms
private
static
final
int
MAX_SETTLE_DURATION
=
600
;
// ms
private
static
final
int
MIN_DISTANCE_FOR_FLING
=
25
;
// dips
private
static
final
int
MIN_DISTANCE_FOR_FLING
=
25
;
// dips
...
...
imageVideoBanner/src/main/java/com/widget/imagevideobanner/view/VpVideoView.java
deleted
100644 → 0
View file @
8552baff
package
com
.
widget
.
imagevideobanner
.
view
;
import
android.content.Context
;
import
android.graphics.drawable.Drawable
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
android.text.TextUtils
;
import
android.util.Log
;
import
android.view.Gravity
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.view.ViewParent
;
import
android.widget.FrameLayout
;
import
android.widget.ImageView
;
import
com.bumptech.glide.Glide
;
import
com.bumptech.glide.load.DataSource
;
import
com.bumptech.glide.load.engine.GlideException
;
import
com.bumptech.glide.request.RequestListener
;
import
com.bumptech.glide.request.target.Target
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
import
com.google.android.exoplayer2.PlaybackParameters
;
import
com.google.android.exoplayer2.Player
;
import
com.google.android.exoplayer2.SimpleExoPlayer
;
import
com.google.android.exoplayer2.Timeline
;
import
com.google.android.exoplayer2.source.MediaSource
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.trackselection.TrackSelectionArray
;
import
com.google.android.exoplayer2.ui.PlayerControlView
;
import
com.google.android.exoplayer2.ui.PlayerView
;
import
com.widget.imagevideobanner.R
;
import
com.widget.imagevideobanner.bean.MediaBean
;
import
com.widget.imagevideobanner.player.IPlayTarget
;
import
com.widget.imagevideobanner.player.PlayerManager
;
import
com.widget.imagevideobanner.utils.ThrowableUtils
;
import
java.math.BigDecimal
;
import
jp.wasabeef.glide.transformations.BlurTransformation
;
public
class
VpVideoView
extends
FrameLayout
implements
IPlayTarget
,
PlayerControlView
.
VisibilityListener
,
Player
.
EventListener
{
private
static
final
String
TAG
=
"VpVideoView"
;
private
ImageView
cover
,
blur
;
private
String
mVideoUrl
;
private
int
mWidthPx
;
private
int
mHeightPx
;
private
View
bufferView
;
private
OnActionFinishListener
mOnPageChangedListener
;
private
MediaBean
mediaBean
;
private
boolean
isVideoEnded
=
false
;
public
VpVideoView
(
@NonNull
Context
context
)
{
super
(
context
);
}
public
VpVideoView
(
@NonNull
Context
context
,
MediaBean
bean
,
final
OnActionFinishListener
onPageChangedListener
)
{
super
(
context
);
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
layout_player_view
,
this
,
true
);
//封面view
cover
=
findViewById
(
R
.
id
.
cover
);
//高斯模糊背景图,防止出现两边留嘿
blur
=
findViewById
(
R
.
id
.
blur_background
);
//缓冲转圈圈的view
bufferView
=
findViewById
(
R
.
id
.
buffer_view
);
//播放完成监听
mOnPageChangedListener
=
onPageChangedListener
;
this
.
mediaBean
=
bean
;
bindData
(
mediaBean
.
getWidth
(),
mediaBean
.
getHeight
(),
mediaBean
.
getCover
(),
mediaBean
.
getUrl
());
}
public
void
bindData
(
int
widthPx
,
int
heightPx
,
String
coverUrl
,
String
videoUrl
)
{
mVideoUrl
=
videoUrl
;
mWidthPx
=
widthPx
;
mHeightPx
=
heightPx
;
setCoverImageUrl
(
coverUrl
,
cover
);
setBlurImageUrl
(
coverUrl
,
blur
);
}
private
void
setBlurImageUrl
(
String
blurUrl
,
ImageView
blur
){
Glide
.
with
(
getContext
())
.
load
(
blurUrl
)
.
transform
(
new
BlurTransformation
())
.
dontAnimate
()
.
listener
(
new
RequestListener
<
Drawable
>()
{
@Override
public
boolean
onLoadFailed
(
@Nullable
GlideException
e
,
Object
model
,
Target
<
Drawable
>
target
,
boolean
isFirstResource
)
{
Log
.
e
(
TAG
,
ThrowableUtils
.
getFullStackTrace
(
e
));
return
false
;
}
@Override
public
boolean
onResourceReady
(
Drawable
resource
,
Object
model
,
Target
<
Drawable
>
target
,
DataSource
dataSource
,
boolean
isFirstResource
)
{
return
false
;
}
}).
into
(
blur
);
}
//todo 缓存固定尺寸
private
void
setCoverImageUrl
(
String
coverUrl
,
ImageView
cover
){
Glide
.
with
(
getContext
())
.
load
(
coverUrl
)
.
dontAnimate
()
.
listener
(
new
RequestListener
<
Drawable
>()
{
@Override
public
boolean
onLoadFailed
(
@Nullable
GlideException
e
,
Object
model
,
Target
<
Drawable
>
target
,
boolean
isFirstResource
)
{
Log
.
e
(
TAG
,
ThrowableUtils
.
getFullStackTrace
(
e
));
return
false
;
}
@Override
public
boolean
onResourceReady
(
Drawable
resource
,
Object
model
,
Target
<
Drawable
>
target
,
DataSource
dataSource
,
boolean
isFirstResource
)
{
return
false
;
}
}).
into
(
cover
);
}
@Override
protected
void
onSizeChanged
(
int
w
,
int
h
,
int
oldw
,
int
oldh
)
{
super
.
onSizeChanged
(
w
,
h
,
oldw
,
oldh
);
Log
.
e
(
TAG
,
"onSizeChanged"
);
reSize
();
}
private
void
reSize
(){
//动态设置
int
mHeight
=
getHeight
();
int
mWidth
=
getWidth
();
BigDecimal
viewScale
=
new
BigDecimal
(
mWidth
+
""
)
.
divide
(
new
BigDecimal
(
mHeight
+
""
),
2
,
BigDecimal
.
ROUND_HALF_UP
);
BigDecimal
videoScale
=
new
BigDecimal
(
mWidthPx
+
""
)
.
divide
(
new
BigDecimal
(
mHeightPx
+
""
),
2
,
BigDecimal
.
ROUND_HALF_UP
);
if
(
viewScale
.
compareTo
(
videoScale
)
>=
0
){
//按照高度缩放
BigDecimal
heightScale
=
new
BigDecimal
(
mHeight
+
""
)
.
divide
(
new
BigDecimal
(
mHeightPx
+
""
),
2
,
BigDecimal
.
ROUND_HALF_UP
);
mHeightPx
=
mHeight
;
mWidthPx
=
new
BigDecimal
(
mWidthPx
+
""
).
multiply
(
heightScale
).
intValue
();
}
else
{
//按照宽度缩放
BigDecimal
widthScale
=
new
BigDecimal
(
mWidth
+
""
)
.
divide
(
new
BigDecimal
(
mWidthPx
+
""
),
2
,
BigDecimal
.
ROUND_HALF_UP
);
mWidthPx
=
mWidth
;
mHeightPx
=
new
BigDecimal
(
mHeightPx
+
""
).
multiply
(
widthScale
).
intValue
();
}
FrameLayout
.
LayoutParams
coverParams
=
(
LayoutParams
)
cover
.
getLayoutParams
();
coverParams
.
width
=
mWidthPx
;
coverParams
.
height
=
mHeightPx
;
coverParams
.
gravity
=
Gravity
.
CENTER
;
cover
.
setLayoutParams
(
coverParams
);
Log
.
e
(
TAG
,
"onSizeChanged"
+
mWidthPx
+
" "
+
mHeightPx
);
}
@Override
public
void
onTimelineChanged
(
Timeline
timeline
,
Object
manifest
,
int
reason
)
{
}
@Override
public
void
onTracksChanged
(
TrackGroupArray
trackGroups
,
TrackSelectionArray
trackSelections
)
{
}
@Override
public
void
onLoadingChanged
(
boolean
isLoading
)
{
}
@Override
public
void
onPlayerStateChanged
(
boolean
playWhenReady
,
int
playbackState
)
{
Log
.
e
(
TAG
,
"onPlayerStateChanged playbackState"
+
playbackState
);
SimpleExoPlayer
exoPlayer
=
PlayerManager
.
getInstance
().
exoPlayer
;
if
(
playbackState
==
Player
.
STATE_READY
&&
exoPlayer
.
getBufferedPosition
()
!=
0
&&
playWhenReady
)
{
cover
.
setVisibility
(
GONE
);
bufferView
.
setVisibility
(
GONE
);
}
else
if
(
playbackState
==
Player
.
STATE_BUFFERING
)
{
cover
.
setVisibility
(
VISIBLE
);
bufferView
.
setVisibility
(
VISIBLE
);
}
//执行2次 bugfxied
if
(
playbackState
==
Player
.
STATE_ENDED
){
if
(!
isVideoEnded
){
isVideoEnded
=
true
;
playNextVideo
();
}
}
}
private
void
playNextVideo
(){
Log
.
e
(
TAG
,
"playNextVideo"
);
inActive
();
if
(
null
!=
mOnPageChangedListener
){
mOnPageChangedListener
.
next
();
}
}
@Override
public
void
onRepeatModeChanged
(
int
repeatMode
)
{
}
@Override
public
void
onShuffleModeEnabledChanged
(
boolean
shuffleModeEnabled
)
{
}
@Override
public
void
onPlayerError
(
ExoPlaybackException
error
)
{
Log
.
e
(
TAG
,
ThrowableUtils
.
getFullStackTrace
(
error
));
playNextVideo
();
}
@Override
public
void
onPositionDiscontinuity
(
int
reason
)
{
}
@Override
public
void
onPlaybackParametersChanged
(
PlaybackParameters
playbackParameters
)
{
}
@Override
public
void
onSeekProcessed
()
{
}
@Override
public
void
onVisibilityChange
(
int
visibility
)
{
}
@Override
public
void
onActive
()
{
isVideoEnded
=
false
;
bufferView
.
setVisibility
(
GONE
);
cover
.
setVisibility
(
VISIBLE
);
//todo 这个地方能否得到具体尺寸
//视频播放,或恢复播放
//通过该View所在页面的mCategory(比如首页列表tab_all,沙发tab的tab_video,标签帖子聚合的tag_feed) 字段,
//取出管理该页面的Exoplayer播放器,ExoplayerView播放View,控制器对象PageListPlay
PlayerManager
playerManager
=
PlayerManager
.
getInstance
();
SimpleExoPlayer
exoPlayer
=
playerManager
.
exoPlayer
;
PlayerView
playerView
=
playerManager
.
playerView
;
//此处我们需要主动调用一次 switchPlayerView,把播放器Exoplayer和展示视频画面的View ExoplayerView相关联
//为什么呢?因为在列表页点击视频Item跳转到视频详情页的时候,详情页会复用列表页的播放器Exoplayer,然后和新创建的展示视频画面的View ExoplayerView相关联,达到视频无缝续播的效果
//如果 我们再次返回列表页,则需要再次把播放器和ExoplayerView相关联
playerManager
.
switchPlayerView
(
playerView
,
true
);
ViewParent
parent
=
playerView
.
getParent
();
if
(
parent
!=
this
)
{
//把展示视频画面的View添加到ItemView的容器上
if
(
parent
!=
null
)
{
((
ViewGroup
)
parent
).
removeView
(
playerView
);
}
//视频尺寸参数共用cover
ViewGroup
.
LayoutParams
coverParams
=
cover
.
getLayoutParams
();
this
.
addView
(
playerView
,
1
,
coverParams
);
}
//如果是同一个视频资源,则不需要从重新创建mediaSource。
//但需要onPlayerStateChanged 否则不会触发onPlayerStateChanged()
if
(
TextUtils
.
equals
(
playerManager
.
playUrl
,
mVideoUrl
))
{
onPlayerStateChanged
(
true
,
Player
.
STATE_READY
);
}
else
{
MediaSource
mediaSource
=
playerManager
.
createMediaSource
(
mVideoUrl
);
exoPlayer
.
prepare
(
mediaSource
);
//TODO 如果只有一个视频 模式改为循环播放
exoPlayer
.
setRepeatMode
(
Player
.
REPEAT_MODE_OFF
);
playerManager
.
playUrl
=
mVideoUrl
;
}
exoPlayer
.
addListener
(
this
);
exoPlayer
.
setPlayWhenReady
(
true
);
}
@Override
public
void
inActive
()
{
Log
.
e
(
TAG
,
"inActive"
);
PlayerManager
playerManager
=
PlayerManager
.
getInstance
();
playerManager
.
exoPlayer
.
setPlayWhenReady
(
false
);
playerManager
.
exoPlayer
.
removeListener
(
this
);
View
child
=
getChildAt
(
1
);
if
(
child
instanceof
PlayerView
){
PlayerView
playerView
=
(
PlayerView
)
child
;
playerView
.
setPlayer
(
null
);
playerManager
.
playerView
.
setPlayer
(
null
);
this
.
removeViewInLayout
(
child
);
}
}
}
imageVideoBanner/src/main/res/drawable-mdpi/guide_defaut.png
View replaced file @
8552baff
View file @
b6da758b
276 Bytes
|
W:
|
H:
202 KB
|
W:
|
H:
2-up
Swipe
Onion skin
imageVideoBanner/src/main/res/layout/layout_exo_player_view.xml
deleted
100755 → 0
View file @
8552baff
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.exoplayer2.ui.PlayerView
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:id=
"@+id/player_view"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:keepScreenOn=
"true"
app:use_controller=
"false"
app:show_timeout=
"1000"
app:surface_type=
"texture_view"
app:resize_mode=
"zoom"
app:player_layout_id=
"@layout/layout_simple_exo_player_view"
android:orientation=
"vertical"
>
</com.google.android.exoplayer2.ui.PlayerView>
\ No newline at end of file
imageVideoBanner/src/main/res/layout/layout_player_view.xml
View file @
b6da758b
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android=
"http://schemas.android.com/apk/res/android"
<FrameLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_height=
"match_parent"
>
android:orientation=
"vertical"
>
<
ImageView
<
com.widget.imagevideobanner.view.SampleCoverVideo
android:id=
"@+id/
blur_background
"
android:id=
"@+id/
player
"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_height=
"match_parent"
/>
android:transitionName=
"blur_image"
android:scaleType=
"centerCrop"
tools:background=
"@drawable/guide_defaut"
/>
<!-- 真正能够播放展示视频画面的view 会动态的添加到这里-->
</FrameLayout>
\ No newline at end of file
<ImageView
android:id=
"@+id/cover"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:scaleType=
"centerInside"
android:transitionName=
"cover"
/>
<ProgressBar
android:id=
"@+id/buffer_view"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:indeterminate=
"true"
android:indeterminateTint=
"#CAE7DF"
android:transitionName=
"buffer_view"
android:visibility=
"visible"
/>
</merge>
\ No newline at end of file
imageVideoBanner/src/main/res/layout/video_layout_cover.xml
0 → 100644
View file @
b6da758b
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@android:color/black"
>
<FrameLayout
android:id=
"@+id/surface_container"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:gravity=
"center"
>
</FrameLayout>
<RelativeLayout
android:id=
"@+id/thumb"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_alignParentStart=
"true"
android:layout_alignParentLeft=
"true"
android:layout_alignParentTop=
"true"
android:layout_alignParentEnd=
"true"
android:layout_alignParentRight=
"true"
android:layout_alignParentBottom=
"true"
android:background=
"#000000"
>
<ImageView
android:id=
"@+id/thumbImage"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:scaleType=
"centerInside"
/>
</RelativeLayout>
<LinearLayout
android:id=
"@+id/layout_bottom"
android:layout_width=
"match_parent"
android:layout_height=
"40dp"
android:layout_alignParentBottom=
"true"
android:background=
"#99000000"
android:gravity=
"center_vertical"
android:orientation=
"horizontal"
android:visibility=
"invisible"
>
<TextView
android:id=
"@+id/current"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"16dp"
android:text=
"00:00"
android:textColor=
"#ffffff"
/>
<SeekBar
android:id=
"@+id/progress"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
android:layout_weight=
"1.0"
android:background=
"@null"
android:max=
"100"
android:maxHeight=
"4dp"
android:minHeight=
"4dp"
android:paddingTop=
"8dp"
android:paddingBottom=
"8dp"
android:progressDrawable=
"@drawable/video_seek_progress"
android:thumb=
"@drawable/video_seek_thumb"
/>
<TextView
android:id=
"@+id/total"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginRight=
"16dp"
android:text=
"00:00"
android:textColor=
"#ffffff"
/>
<ImageView
android:id=
"@+id/fullscreen"
android:layout_width=
"wrap_content"
android:layout_height=
"fill_parent"
android:paddingRight=
"16dp"
android:scaleType=
"center"
android:src=
"@drawable/video_enlarge"
/>
</LinearLayout>
<ProgressBar
android:id=
"@+id/bottom_progressbar"
style=
"?android:attr/progressBarStyleHorizontal"
android:layout_width=
"match_parent"
android:layout_height=
"1.5dp"
android:layout_alignParentBottom=
"true"
android:max=
"100"
android:progressDrawable=
"@drawable/video_progress"
/>
<ImageView
android:id=
"@+id/back_tiny"
android:layout_width=
"24dp"
android:layout_height=
"24dp"
android:layout_marginLeft=
"6dp"
android:layout_marginTop=
"6dp"
android:visibility=
"gone"
/>
<LinearLayout
android:id=
"@+id/layout_top"
android:layout_width=
"match_parent"
android:layout_height=
"48dp"
android:background=
"@drawable/video_title_bg"
android:gravity=
"center_vertical"
>
<ImageView
android:id=
"@+id/back"
android:layout_width=
"48dp"
android:layout_height=
"48dp"
android:paddingLeft=
"10dp"
android:scaleType=
"centerInside"
android:src=
"@drawable/video_back"
/>
<TextView
android:id=
"@+id/title"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:paddingLeft=
"10dp"
android:textColor=
"@android:color/white"
android:textSize=
"18sp"
/>
</LinearLayout>
<moe.codeest.enviews.ENDownloadView
android:id=
"@+id/loading"
android:layout_width=
"28dp"
android:layout_height=
"28dp"
android:layout_centerHorizontal=
"true"
android:layout_centerVertical=
"true"
android:visibility=
"invisible"
/>
<moe.codeest.enviews.ENPlayView
android:id=
"@+id/start"
android:layout_width=
"60dp"
android:layout_height=
"60dp"
android:layout_centerHorizontal=
"true"
android:layout_centerVertical=
"true"
android:layout_gravity=
"center_vertical"
/>
<ImageView
android:id=
"@+id/small_close"
android:layout_width=
"30dp"
android:layout_height=
"30dp"
android:paddingLeft=
"10dp"
android:paddingTop=
"10dp"
android:scaleType=
"centerInside"
android:src=
"@drawable/video_small_close"
android:visibility=
"gone"
/>
<ImageView
android:id=
"@+id/lock_screen"
android:layout_width=
"30dp"
android:layout_height=
"30dp"
android:layout_alignParentRight=
"true"
android:layout_centerVertical=
"true"
android:layout_marginRight=
"50dp"
android:scaleType=
"centerInside"
android:src=
"@drawable/unlock"
android:visibility=
"gone"
/>
</RelativeLayout>
imageVideoBanner/src/main/res/raw/default_guide.mp4
deleted
100644 → 0
View file @
8552baff
File deleted
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