Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XMPや信ぴょう性チェック対応 #29

Merged
merged 46 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
fd1d1fc
xmpテスト
JangSungChul May 26, 2023
2c9f9c3
source-file情報追加
JangSungChul Jun 7, 2023
3f2c097
信ぴょう性チェック用フレームワークを追加:JACICHashLib
JangSungChul Jun 13, 2023
be64169
jcomsiaPhoto情報のパラメータ追加
JangSungChul Jun 14, 2023
be15d3e
ビルドエラーなので、JACICHashLib.frameworkを外す
JangSungChul Jun 15, 2023
a0e1cc4
タイポ修正
JangSungChul Jun 15, 2023
13d635d
XMP情報取得&出力
JangSungChul Jun 16, 2023
8188288
nullチェック
JangSungChul Jun 20, 2023
e6e6490
JCOMSIAHashLib.frameworkの差し替え
JangSungChul Jun 21, 2023
5fabfaf
信ぴょう性チェック対応
JangSungChul Jun 21, 2023
5a66a3c
embed情報を追加
JangSungChul Jun 21, 2023
3e34eba
softwareとのimageDescription変更
JangSungChul Jun 29, 2023
67f7071
nullチェック追加
JangSungChul Jun 29, 2023
0fc3fc9
null対応
JangSungChul Jun 29, 2023
e025e64
現場名と受注者を追加
karuru6225 Jul 12, 2023
4e12c81
規格に通る綴りに修正
karuru6225 Jul 12, 2023
b8afdd2
Boolean系の表記を規格に合わせて修正
karuru6225 Jul 12, 2023
f3362e7
XMPの構造を修正
karuru6225 Jul 12, 2023
8e2fcb9
enumにないunitも入力できるように修正
karuru6225 Jul 18, 2023
ef921dc
Unitタグ名修正
karuru6225 Jul 18, 2023
7e2247c
写真説明をjcomsia用に修正
karuru6225 Jul 19, 2023
3d09aae
exifにsubsecとexifバージョンを追加。
karuru6225 Jul 31, 2023
a86fbad
オリジナルのExifを引き継ぐように修正。Exifバージョンも追加
karuru6225 Jul 31, 2023
243c1a4
ComponentsConfigurationとFlashpixVersionを追加
JangSungChul Aug 8, 2023
340f634
buildエラーの修正
JangSungChul Aug 21, 2023
f126c48
XMPのversion情報を追加
JangSungChul Sep 5, 2023
14c6216
version情報の追加
JangSungChul Sep 8, 2023
61bd48b
XMP情報の追加
JangSungChul Sep 20, 2023
d2f87d6
ファイル設定の追加
JangSungChul Sep 22, 2023
d977c40
gson不要
JangSungChul Sep 22, 2023
5dfe31d
Kotlinの有効設定
JangSungChul Sep 25, 2023
740f68e
Kotlin設定
JangSungChul Sep 25, 2023
ca41f89
Merge pull request #31 from ncdcdev/feature/xmp_info_kotlin
JangSungChul Sep 25, 2023
0ddb738
cppライブラリ追加
JangSungChul Sep 25, 2023
e321571
ファイルコピー
JangSungChul Sep 25, 2023
1fea606
コード修正
JangSungChul Sep 25, 2023
4182583
jcomsiaPhotoのnull対応
JangSungChul Sep 26, 2023
6d8b2fd
信ぴょう性対応
JangSungChul Sep 26, 2023
eed9f88
XMPデータなしの対応
JangSungChul Sep 26, 2023
7b9817d
hooks名の修正
JangSungChul Sep 26, 2023
0ee80f7
pathの修正
JangSungChul Sep 26, 2023
4575bae
PhotoInfoがない場合の対応
JangSungChul Sep 27, 2023
94dadd3
photoInfoのnull対応
JangSungChul Sep 28, 2023
5bdd59b
isNeedBlackBoardとblackboardViewPriorityのnull対応
JangSungChul Oct 10, 2023
85c73aa
Merge pull request #33 from ncdcdev/feature/xmp_info_fix_isNeedBlackB…
JangSungChul Oct 27, 2023
eefd41b
Merge pull request #32 from ncdcdev/feature/xmp_info_cpp
JangSungChul Oct 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions hooks/copy_native_files.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
var fs = require("fs-extra");
var path = require("path");

module.exports = function (context) {
var srcDir = path.join(
context.opts.projectRoot,
"plugins",
"cordova-plugin-blackboard-camera",
"src",
"android",
"cpp"
);
var destDir = path.join(
context.opts.projectRoot,
"platforms",
"android",
"app",
"src",
"main",
"cpp"
);

fs.copySync(srcDir, destDir);
};
35 changes: 35 additions & 0 deletions hooks/modify-root-build-gradle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
var fs = require("fs");
var path = require("path");

module.exports = function (context) {
var gradlePath = path.join(
context.opts.projectRoot,
"platforms",
"android",
"app",
"build.gradle"
);

if (fs.existsSync(gradlePath)) {
var gradleContent = fs.readFileSync(gradlePath, "utf-8");

// C++とKotlinの連携の設定を追加
var settingsToAdd = `
android {
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
}
`;

if (!gradleContent.includes("externalNativeBuild")) {
gradleContent = gradleContent.replace(
"android {",
"android {" + settingsToAdd
);
fs.writeFileSync(gradlePath, gradleContent, "utf-8");
}
}
};
3 changes: 3 additions & 0 deletions plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@
<hook type="before_plugin_rm" src="hooks/on-uninstall.js" />
<hook type="before_plugin_uninstall" src="hooks/on-uninstall.js" />

<hook type="after_platform_add" src="hooks/modify-root-build-gradle.js" />
<hook type="after_platform_add" src="hooks/copy_native_files.js" />

<config-file target="config.xml" parent="/*">
<preference name="GradlePluginKotlinEnabled" value="true" />
<feature name="BlackboardCamera">
Expand Down
12 changes: 7 additions & 5 deletions src/android/BlackboardCamera.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,26 @@ class BlackboardCamera : CordovaPlugin() {
var applicationContext = cordova.activity.applicationContext
val intent = Intent(applicationContext, CameraActivity::class.java)
val base64: String = data[0] as String
Log.d("TAG", "data[1]=" + data[1])
val isNeedBlackBoard: Boolean = try {
(data[1] as Boolean)
} catch (e: ClassCastException) {
(data[1] as Int) == 1
}
val blackboardViewPriority: String = data[2] as String
var jcomsiaPhoto: String = data[3] as String
val photoInfoJson = JSONObject(jcomsiaPhoto)
val photoInfo = PhotoInfo(photoInfoJson)
var jcomsiaPhoto: String? = data[3] as? String

var version: String = data[4] as String
val filePath = "${cordova.activity.applicationContext.filesDir}/board.png"
decoder(base64, filePath)
if (File(filePath).exists()) {
intent.putExtra("boardPath", filePath)
intent.putExtra("isNeedBlackBoard", isNeedBlackBoard)
intent.putExtra("blackboardViewPriority", blackboardViewPriority)
intent.putExtra("photoInfo", photoInfo)
if (jcomsiaPhoto != null) {
val photoInfoJson = JSONObject(jcomsiaPhoto)
val photoInfo = PhotoInfo(photoInfoJson)
intent.putExtra("photoInfo", photoInfo)
}
intent.putExtra("version", version)
}
cordova.startActivityForResult(this, intent, 1)
Expand Down
137 changes: 74 additions & 63 deletions src/android/Camera2Fragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
*/
private lateinit var mFile: File

private lateinit var mPhotoInfo: PhotoInfo
var mPhotoInfo: PhotoInfo? = null

private lateinit var mVersion: String

Expand Down Expand Up @@ -257,8 +257,8 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
// CONTROL_AE_STATE can be null on some devices
val aeState = result.get(CaptureResult.CONTROL_AE_STATE)
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
mState = STATE_WAITING_NON_PRECAPTURE
}
}
Expand Down Expand Up @@ -437,17 +437,17 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
}

val map = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) ?: continue
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) ?: continue

// For still image captures, we use the largest available size.
val sizeList = listOf(*map.getOutputSizes(ImageFormat.JPEG)).sortedByDescending { it.width }
val largest = sizeList[sizeList.indexOfFirst { it.width <= 1280 }]
Log.d(TAG, "test:setUpCameraOutputs:width=${largest.width} x height=${largest.height}")
val aspectSize = Size((largest.height.toFloat() * VIEW_ASPECT).toInt(), largest.height)
mImageReader = ImageReader.newInstance(aspectSize.width, aspectSize.height,
ImageFormat.JPEG, 2)
ImageFormat.JPEG, 2)
mImageReader!!.setOnImageAvailableListener(
mOnImageAvailableListener, mBackgroundHandler)
mOnImageAvailableListener, mBackgroundHandler)

// Find out if we need to swap dimension to get the preview size relative to sensor
// coordinate.
Expand Down Expand Up @@ -483,8 +483,8 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
// bus' bandwidth limitation, resulting in gorgeous previews but the storage of
// garbage capture data.
val previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture::class.java),
rotatedPreviewWidth, rotatedPreviewHeight, maxPreviewWidth,
maxPreviewHeight, aspectSize)
rotatedPreviewWidth, rotatedPreviewHeight, maxPreviewWidth,
maxPreviewHeight, aspectSize)

mPreviewSize = Size((previewSize!!.height.toFloat() * VIEW_ASPECT).toInt(), previewSize!!.height)

Expand Down Expand Up @@ -643,38 +643,38 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {

// Here, we create a CameraCaptureSession for camera preview.
mCameraDevice!!.createCaptureSession(listOf(mImageReader!!.surface, surface),
object : CameraCaptureSession.StateCallback() {

override fun onConfigured(cameraCaptureSession: CameraCaptureSession) {
// The camera is already closed
if (null == mCameraDevice) {
return
}

// When the session is ready, we start displaying the preview.
mCaptureSession = cameraCaptureSession
try {
// Auto focus should be continuous for camera preview.
mPreviewRequestBuilder!!.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
// Flash is automatically enabled when necessary.
setAutoFlash(mPreviewRequestBuilder!!)

// Finally, we start displaying the camera preview.
mPreviewRequest = mPreviewRequestBuilder!!.build()
mCaptureSession!!.setRepeatingRequest(mPreviewRequest!!,
mCaptureCallback, mBackgroundHandler)
} catch (e: CameraAccessException) {
e.printStackTrace()
}
object : CameraCaptureSession.StateCallback() {

override fun onConfigured(cameraCaptureSession: CameraCaptureSession) {
// The camera is already closed
if (null == mCameraDevice) {
return
}

override fun onConfigureFailed(
cameraCaptureSession: CameraCaptureSession) {
showToast("Failed")
// When the session is ready, we start displaying the preview.
mCaptureSession = cameraCaptureSession
try {
// Auto focus should be continuous for camera preview.
mPreviewRequestBuilder!!.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
// Flash is automatically enabled when necessary.
setAutoFlash(mPreviewRequestBuilder!!)

// Finally, we start displaying the camera preview.
mPreviewRequest = mPreviewRequestBuilder!!.build()
mCaptureSession!!.setRepeatingRequest(mPreviewRequest!!,
mCaptureCallback, mBackgroundHandler)
} catch (e: CameraAccessException) {
e.printStackTrace()
}
}, null

}

override fun onConfigureFailed(
cameraCaptureSession: CameraCaptureSession) {
showToast("Failed")
}
}, null
)
} catch (e: CameraAccessException) {
e.printStackTrace()
Expand All @@ -701,8 +701,8 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY())
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL)
val scale = max(
viewHeight.toFloat() / mPreviewSize!!.height,
viewWidth.toFloat() / mPreviewSize!!.width)
viewHeight.toFloat() / mPreviewSize!!.height,
viewWidth.toFloat() / mPreviewSize!!.width)
matrix.postScale(scale, scale, centerX, centerY)
matrix.postRotate((90 * (rotation - 2)).toFloat(), centerX, centerY)
} else if (Surface.ROTATION_180 == rotation) {
Expand Down Expand Up @@ -734,11 +734,11 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
val captureSession = mCaptureSession ?: return
// This is how to tell the camera to lock focus.
previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
CameraMetadata.CONTROL_AF_TRIGGER_START)
CameraMetadata.CONTROL_AF_TRIGGER_START)
// Tell #mCaptureCallback to wait for the lock.
mState = STATE_WAITING_LOCK
captureSession.capture(previewRequestBuilder.build(), mCaptureCallback,
mBackgroundHandler)
mBackgroundHandler)
Log.d(TAG, "test:lockFocus:end")
} catch (e: CameraAccessException) {
e.printStackTrace()
Expand All @@ -755,11 +755,11 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
Log.d(TAG, "test:runPrecaptureSequence")
// This is how to tell the camera to trigger.
mPreviewRequestBuilder!!.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START)
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START)
// Tell #mCaptureCallback to wait for the precapture sequence to be set.
mState = STATE_WAITING_PRECAPTURE
mCaptureSession!!.capture(mPreviewRequestBuilder!!.build(), mCaptureCallback,
mBackgroundHandler)
mBackgroundHandler)
} catch (e: CameraAccessException) {
e.printStackTrace()
}
Expand All @@ -784,7 +784,7 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
val rotation = activity.windowManager.defaultDisplay.rotation
// This is the CaptureRequest.Builder that we use to take a picture.
val captureBuilder = mCameraDevice!!.createCaptureRequest(
CameraDevice.TEMPLATE_STILL_CAPTURE)?.apply {
CameraDevice.TEMPLATE_STILL_CAPTURE)?.apply {
addTarget(mImageReader!!.surface)

// Sensor orientation is 90 for most devices, or 270 for some devices (eg. Nexus 5X)
Expand All @@ -798,7 +798,7 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {

// Use the same AE and AF modes as the preview.
set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
}?.also { setAutoFlash(it) }

// Use the same AE and AF modes as the preview.
Expand Down Expand Up @@ -852,18 +852,18 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
try {
// Reset the auto-focus trigger
mPreviewRequestBuilder!!.set(CaptureRequest.CONTROL_AF_TRIGGER,
CameraMetadata.CONTROL_AF_TRIGGER_CANCEL)
CameraMetadata.CONTROL_AF_TRIGGER_CANCEL)
setAutoFlash(mPreviewRequestBuilder!!)
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
mCaptureSession!!.stopRepeating()
mCaptureSession!!.abortCaptures()
}
mCaptureSession!!.capture(mPreviewRequestBuilder!!.build(), mCaptureCallback,
mBackgroundHandler)
mBackgroundHandler)
// After this, the camera will go back to the normal state of preview.
mState = STATE_PREVIEW
mCaptureSession!!.setRepeatingRequest(mPreviewRequest!!, mCaptureCallback,
mBackgroundHandler)
mBackgroundHandler)
} catch (e: CameraAccessException) {
e.printStackTrace()
} catch (e: java.lang.NullPointerException) {
Expand Down Expand Up @@ -1170,24 +1170,24 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
* Saves a JPEG [Image] into the specified [File].
*/
private class ImageSaver internal constructor(
/**
* The JPEG image
*/
private val image: Image,
/**
* The JPEG image
*/
private val image: Image,

private val file: File,
private val file: File,

private val board: BitmapDrawable?,
private val board: BitmapDrawable?,

private val boardRect: Rect,
private val boardRect: Rect,

private val minSize: Float,
private val minSize: Float,

private val activity: CameraActivity?,
private val activity: CameraActivity?,

private val photoInfo: PhotoInfo,
private val photoInfo: PhotoInfo?,

private val version: String?
private val version: String?

) : Runnable {

Expand Down Expand Up @@ -1246,17 +1246,25 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
}
val scaled: Bitmap = Bitmap.createScaledBitmap(rotated, sWidth, sHeight, true)
scaled.compress(Bitmap.CompressFormat.JPEG, 100, output)

// XMPのMeta情報がある場合
ElectronicBlackBoardManager.createImageEmbeddedMetaData(file.absolutePath, photoInfo, "DCP PHOTO", "Android", version ?: "TPR2 3.1.1")

val checkedFilePath = "${file.parent}/_${file.name}"
val result = writeHash(file.absolutePath, checkedFilePath)
if (result == 0) {
// 信ぴょう性チェック情報作成前のデータは削除する
file.delete()
Log.i(TAG, "🔵[success]checkedFilename=$checkedFilePath")
} else {
Log.e(TAG, "🔴[fail★★]checkedFilename=$checkedFilePath, result=$result")
}
Log.i(TAG, "exifOrientation=$exifOrientation, rotation=$rotation")
// activity.runOnUiThread {
// Toast.makeText(activity, "exifOrientation=$exifOrientation, rotation=$rotation", Toast.LENGTH_LONG).show()
// }

addImageToGallery(file.absolutePath)
addImageToGallery(checkedFilePath)
val intent = Intent()
intent.putExtra("filePath", file.absolutePath)
intent.putExtra("filePath", checkedFilePath)
intent.putExtra("mode", activity.blackboardViewPriority)
activity.setResult(1, intent)
activity.finish()
Expand Down Expand Up @@ -1346,11 +1354,14 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
private val ORIENTATIONS = SparseIntArray()

init {
System.loadLibrary("native-lib")
ORIENTATIONS.append(Surface.ROTATION_0, 90)
ORIENTATIONS.append(Surface.ROTATION_90, 0)
ORIENTATIONS.append(Surface.ROTATION_180, 270)
ORIENTATIONS.append(Surface.ROTATION_270, 180)
}
// 改ざん検知情報埋め込みメソッド
external fun writeHash(srcFilePath: String, outputFilePath: String): Int

/**
* Tag for the [Log].
Expand Down Expand Up @@ -1426,7 +1437,7 @@ class Camera2Fragment : Fragment(), View.OnClickListener, View.OnTouchListener {
val h = aspectRatio.height
for (option in choices) {
if (option.width <= maxWidth && option.height <= maxHeight &&
option.height == option.width * h / w) {
option.height == option.width * h / w) {
if (option.width >= textureViewWidth && option.height >= textureViewHeight) {
bigEnough.add(option)
} else {
Expand Down
Loading