diff --git a/.gitignore b/.gitignore index 6cd93c71..4461492c 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ sync.ffs_db /build/ /libs/**/build/ /modules/**/build/ +/plugin-api/**/build/ /captures/ /release/ /releases/ diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b1155d1d..aa7dcb72 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -166,9 +166,6 @@ dependencies /* Unclassified */ { // OpenCV implementation(project(":libs:org-opencv-4_8_0")) - // PaddleOCR - implementation(project(":libs:paddleocr")) - // RapidOCR implementation(project(":libs:rapidocr")) @@ -252,6 +249,9 @@ dependencies /* Unclassified */ { // ICU4J implementation(libs.icu4j) + + // Plugin API: Paddle OCR + implementation(project(":plugin-api:paddle-ocr")) } dependencies /* MIME */ { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 044786ea..adb1d02e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -126,6 +126,10 @@ android:protectionLevel="signature" tools:ignore="ProtectedPermissions" /> + + diff --git a/app/src/main/java/org/autojs/autojs/core/plugin/ocr/PaddleOcrPluginHost.kt b/app/src/main/java/org/autojs/autojs/core/plugin/ocr/PaddleOcrPluginHost.kt new file mode 100644 index 00000000..871eabd5 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/core/plugin/ocr/PaddleOcrPluginHost.kt @@ -0,0 +1,217 @@ +package org.autojs.autojs.core.plugin.ocr + +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.content.pm.PackageManager +import android.content.pm.ServiceInfo +import android.graphics.Bitmap +import android.graphics.Bitmap.CompressFormat +import android.os.Build +import android.os.Handler +import android.os.IBinder +import android.os.ParcelFileDescriptor +import android.os.SystemClock.uptimeMillis +import android.util.Log +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.withContext +import org.autojs.plugin.paddle.ocr.IOcrPlugin +import org.autojs.plugin.paddle.ocr.OcrOptions +import org.autojs.plugin.paddle.ocr.OcrResult +import org.autojs.plugin.paddle.ocr.PluginInfo +import java.io.File +import java.io.FileOutputStream + +object PaddleOcrPluginHost { + + private const val TAG = "PaddleOcrPluginHost" + + const val ACTION_OCR = "org.autojs.plugin.PADDLE_OCR" + + private const val DEFAULT_BIND_TIMEOUT_MS = 60_000L + private const val DEFAULT_CALL_TIMEOUT_MS = 60_000L + + data class Discovered( + val serviceInfo: ServiceInfo, + val pluginInfo: PluginInfo?, + ) + + suspend fun discover(context: Context): List { + val pm = context.packageManager + val resolveList = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + pm.queryIntentServices(Intent(ACTION_OCR), PackageManager.ResolveInfoFlags.of(0)) + } else { + pm.queryIntentServices(Intent(ACTION_OCR), 0) + } + val services = resolveList.mapNotNull { it.serviceInfo } + Log.i(TAG, "discover: services=${services.size}") + return services.map { svc -> + Log.i(TAG, "discover: ${svc.packageName}/${svc.name}") + val info = runCatching { withService(context, svc, DEFAULT_BIND_TIMEOUT_MS) { it.getInfo() } } + .onFailure { e -> Log.w(TAG, "getInfo failed: ${e.message}") } + .getOrNull() + Discovered(svc, info) + } + } + + suspend fun recognizeText( + context: Context, + target: Discovered, + bitmap: Bitmap, + options: OcrOptions = OcrOptions(), + callTimeoutMs: Long = DEFAULT_CALL_TIMEOUT_MS, + ): List { + val start = uptimeMillis() + return createTempPfd(context, bitmap).use { pfd -> + withService(context, target.serviceInfo, DEFAULT_BIND_TIMEOUT_MS) { proxy -> + val remain = callTimeoutMs - (uptimeMillis() - start) + if (remain <= 0) error("AIDL call timeout in ${callTimeoutMs / 1000} seconds") + val lines = proxy.recognizeText(pfd, options) + Log.i(TAG, "recognizeTextAidl: got ${lines.size} lines") + lines + } + } + } + + suspend fun detect( + context: Context, + target: Discovered, + bitmap: Bitmap, + options: OcrOptions = OcrOptions(), + callTimeoutMs: Long = DEFAULT_CALL_TIMEOUT_MS, + ): List { + val start = uptimeMillis() + return createTempPfd(context, bitmap).use { pfd -> + withService(context, target.serviceInfo, DEFAULT_BIND_TIMEOUT_MS) { proxy -> + val remain = callTimeoutMs - (uptimeMillis() - start) + if (remain <= 0) error("AIDL call timeout") + val results = proxy.detect(pfd, options) + Log.i(TAG, "detectAidl: got ${results.size} items") + results + } + } + } + + suspend fun select( + context: Context, + // e.g. "paddle-ocr-v5" + engineId: String? = null, + // e.g. "paddle-ocr" + engine: String? = null, + // e.g. "v5" + variant: String? = null, + ): Discovered? { + val list = discover(context).filter { it.pluginInfo != null } + if (list.isEmpty()) return null + if (engineId != null) { + list.firstOrNull { d -> d.pluginInfo?.id == engineId }?.let { return it } + } + if (engine != null && variant != null) { + list.firstOrNull { d -> d.pluginInfo?.engine == engine && d.pluginInfo.variant == variant }?.let { return it } + } + if (engine != null) { + list.firstOrNull { d -> d.pluginInfo?.engine == engine }?.let { return it } + } + return list.first() + } + + // Convert temporary file to read-only FD. + // zh-CN: 临时文件转换为只读 FD. + private fun createTempPfd(context: Context, bmp: Bitmap): ParcelFileDescriptor { + val dir = File(context.cacheDir, "ocr_ipc").apply { if (!exists()) mkdirs() } + val f = File.createTempFile("img_", ".bin", dir) + FileOutputStream(f).use { fos -> + val format = when { + bmp.hasAlpha() -> CompressFormat.PNG + else -> CompressFormat.JPEG + } + require(bmp.compress(format, 100, fos)) { "Failed to encode bitmap" } + } + return ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY) + } + + private suspend fun withService( + context: Context, + serviceInfo: ServiceInfo, + bindTimeoutMs: Long = DEFAULT_BIND_TIMEOUT_MS, + block: suspend (IOcrPlugin) -> T, + ): T = suspendCancellableCoroutine { cont -> + val cn = ComponentName(serviceInfo.packageName, serviceInfo.name) + val intent = Intent().setComponent(cn) + val appCtx = context.applicationContext + + var resolved = false + var jobRef: Job? = null + + val conn = object : ServiceConnection { + override fun onServiceConnected(name: ComponentName, binder: IBinder) { + Log.i(TAG, "onServiceConnected: $name") + val proxy = IOcrPlugin.Stub.asInterface(binder) + val self = this + + jobRef = CoroutineScope(cont.context + Dispatchers.IO).launch { + val result = runCatching { block(proxy) } + try { + resolved = true + if (!cont.isCompleted) cont.resumeWith(result) + Log.i(TAG, "resume continuation: success=${result.isSuccess}") + } finally { + withContext(Dispatchers.Main) { + runCatching { appCtx.unbindService(self) } + Log.i(TAG, "unbindService: $name") + } + } + } + } + + override fun onServiceDisconnected(name: ComponentName) { + Log.w(TAG, "onServiceDisconnected: $name") + } + } + + val ok = try { + Log.i(TAG, "bindService: $cn") + appCtx.bindService(intent, conn, Context.BIND_AUTO_CREATE) + } catch (se: SecurityException) { + Log.e(TAG, "bindService SecurityException: $cn | ${se.message}") + cont.resumeWith( + Result.failure( + IllegalStateException( + "bindService SecurityException: $cn. Please make sure the plugin declares and the Service uses this permission.", se + ) + ) + ) + return@suspendCancellableCoroutine + } + if (!ok) { + Log.e(TAG, "bindService failed: $cn") + cont.resumeWith(Result.failure(IllegalStateException("bindService failed: $cn"))) + return@suspendCancellableCoroutine + } + + val cancel = Runnable { + if (!resolved && !cont.isCompleted) { + Log.e(TAG, "bindService timeout: $cn") + cont.resumeWith(Result.failure(TimeoutException("bindService timeout: $cn"))) + runCatching { appCtx.unbindService(conn) } + } + } + val h = Handler(appCtx.mainLooper) + h.postDelayed(cancel, bindTimeoutMs) + + cont.invokeOnCancellation { + Log.w(TAG, "continuation cancelled: $cn") + h.removeCallbacks(cancel) + jobRef?.cancel() + runCatching { appCtx.unbindService(conn) } + } + } + + private class TimeoutException(msg: String) : RuntimeException(msg) + +} diff --git a/app/src/main/java/org/autojs/autojs/runtime/ScriptRuntime.kt b/app/src/main/java/org/autojs/autojs/runtime/ScriptRuntime.kt index 62d0201c..2460ea5b 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/ScriptRuntime.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/ScriptRuntime.kt @@ -3,6 +3,9 @@ package org.autojs.autojs.runtime import android.content.Context import android.os.Build import android.util.Log +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob import org.autojs.autojs.AutoJs import org.autojs.autojs.annotation.ScriptInterface import org.autojs.autojs.annotation.ScriptVariable @@ -128,6 +131,7 @@ import java.io.PrintWriter import java.io.StringWriter import java.lang.ref.WeakReference import java.util.concurrent.ConcurrentHashMap +import kotlin.coroutines.cancellation.CancellationException import org.autojs.autojs.core.accessibility.UiSelector as CoreUiSelector import org.autojs.autojs.core.crypto.Crypto as CoreCrypto import org.autojs.autojs.core.image.Colors as CoreColors @@ -149,7 +153,6 @@ import org.autojs.autojs.runtime.api.Mime as ApiMime import org.autojs.autojs.runtime.api.Notice as ApiNotice import org.autojs.autojs.runtime.api.Ocr as ApiOcr import org.autojs.autojs.runtime.api.OcrMLKit as ApiOcrMLKit -import org.autojs.autojs.runtime.api.OcrPaddle as ApiOcrPaddle import org.autojs.autojs.runtime.api.OcrRapid as ApiOcrRapid import org.autojs.autojs.runtime.api.Plugins as ApiPlugins import org.autojs.autojs.runtime.api.Recorder as ApiRecorder @@ -180,6 +183,10 @@ import org.autojs.autojs.runtime.api.augment.util.VersionCodes as UtilVersionCod @Suppress("unused", "PropertyName", "PrivatePropertyName") class ScriptRuntime private constructor(builder: Builder) { + private val mJob = SupervisorJob() + val coroutineScope = CoroutineScope(Dispatchers.Default + mJob) + val coroutineContext = coroutineScope.coroutineContext + private var mUiHandlerAppContext: Context private var mRootShell: AbstractShell? = null private val mProperties = ConcurrentHashMap() @@ -335,10 +342,6 @@ class ScriptRuntime private constructor(builder: Builder) { @ScriptVariable val ocrMLKit: ApiOcrMLKit - @JvmField - @ScriptVariable - val ocrPaddle: ApiOcrPaddle - @JvmField @ScriptVariable val ocrRapid: ApiOcrRapid @@ -474,7 +477,6 @@ class ScriptRuntime private constructor(builder: Builder) { http = ApiHttp() ocrMLKit = ApiOcrMLKit() - ocrPaddle = ApiOcrPaddle() ocrRapid = ApiOcrRapid() barcode = ApiBarcode() @@ -579,6 +581,10 @@ class ScriptRuntime private constructor(builder: Builder) { @Deprecated("ScriptRuntime#stop is deprecated", ReplaceWith("exit()")) fun stop() = exit() + fun cancelScriptJobs() { + mJob.cancel(CancellationException(mUiHandlerAppContext.getString(R.string.error_script_is_on_exiting))) + } + fun onExit() { Log.d(TAG, "on exit") this.isExiting = true @@ -620,7 +626,6 @@ class ScriptRuntime private constructor(builder: Builder) { ignoresException({ images.releaseScreenCapturer() }) ignoresException({ images.stopScreenCapturerForegroundService() }) ignoresException({ ocrMLKit.release() }) - ignoresException({ ocrPaddle.release() }) ignoresException({ sensors.unregisterAll() }) ignoresException({ timers.recycle() }) ignoresException({ ui.recycle() }) diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/OcrPaddle.java b/app/src/main/java/org/autojs/autojs/runtime/api/OcrPaddle.java deleted file mode 100644 index ae880228..00000000 --- a/app/src/main/java/org/autojs/autojs/runtime/api/OcrPaddle.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.autojs.autojs.runtime.api; - -import android.graphics.Bitmap; -import android.os.Looper; -import android.util.Log; - -import com.baidu.paddle.lite.ocr.OcrResult; -import com.baidu.paddle.lite.ocr.Predictor; - -import org.autojs.autojs.app.GlobalAppContext; -import org.autojs.autojs.concurrent.VolatileDispose; -import org.autojs.autojs.core.image.ImageWrapper; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * @author TonyJiangWJ - * @since 2023-08-06 - */ -public class OcrPaddle { - - private final Predictor mPredictor = new Predictor(); - - public synchronized boolean init(boolean useSlim) { - if (!mPredictor.isLoaded || useSlim != mPredictor.isUseSlim()) { - if (Looper.getMainLooper() == Looper.myLooper()) { - VolatileDispose result = new VolatileDispose<>(); - new Thread(() -> result.setAndNotify(mPredictor.init(GlobalAppContext.get(), useSlim))).start(); - return Boolean.TRUE.equals(result.blockedGet(60_000)); - } else { - return mPredictor.init(GlobalAppContext.get(), useSlim); - } - } - return mPredictor.isLoaded; - } - - public void release() { - mPredictor.releaseModel(); - } - - public List detect(ImageWrapper image, int cpuThreadNum, boolean useSlim) { - if (image == null) { - return Collections.emptyList(); - } - Bitmap bitmap = image.getBitmap(); - if (bitmap.isRecycled()) { - return Collections.emptyList(); - } - if (mPredictor.cpuThreadNum != cpuThreadNum) { - mPredictor.releaseModel(); - mPredictor.cpuThreadNum = cpuThreadNum; - } - init(useSlim); - return mPredictor.runOcr(bitmap); - } - - public List detect(ImageWrapper image, int cpuThreadNum) { - return detect(image, cpuThreadNum, true); - } - - public List detect(ImageWrapper image) { - return detect(image, 4, true); - } - - public List recognizeText(ImageWrapper image, int cpuThreadNum, boolean useSlim) { - List words_result = detect(image, cpuThreadNum, useSlim); - Collections.sort(words_result); - List outputResult = Arrays.asList(new String[words_result.size()]); - for (int i = 0; i < words_result.size(); i++) { - outputResult.set(i, words_result.get(i).getLabel()); - // show LOG in Logcat panel - Log.i("outputResult", outputResult.get(i)); - } - return outputResult; - } - - public List recognizeText(ImageWrapper image, int cpuThreadNum) { - return recognizeText(image, cpuThreadNum, true); - } - - public List recognizeText(ImageWrapper image) { - return recognizeText(image, 4, true); - } - -} diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/ocr/OcrPaddle.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/ocr/OcrPaddle.kt index a84e0117..bef01a7f 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/ocr/OcrPaddle.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/ocr/OcrPaddle.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.runBlocking import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface import org.autojs.autojs.apkbuilder.ApkBuilder import org.autojs.autojs.core.image.ImageWrapper -import org.autojs.autojs.core.plugin.ocr.OcrPluginHost +import org.autojs.autojs.core.plugin.ocr.PaddleOcrPluginHost import org.autojs.autojs.extension.ScriptableObjectExtensions.inquire import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.api.OcrResult @@ -14,6 +14,7 @@ import org.autojs.autojs.runtime.api.augment.ocr.Ocr.Companion.OcrMode import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException import org.autojs.autojs.util.RhinoUtils.coerceBoolean import org.autojs.autojs.util.RhinoUtils.coerceIntNumber +import org.autojs.plugin.paddle.ocr.OcrOptions import org.mozilla.javascript.NativeArray import org.mozilla.javascript.NativeObject @@ -48,32 +49,35 @@ class OcrPaddle(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRu } fun recognizeTextImpl(scriptRuntime: ScriptRuntime, image: ImageWrapper, options: NativeObject): List { - return performOcr(scriptRuntime, image, options).map { - it.text - } - } - - fun detectImpl(scriptRuntime: ScriptRuntime, image: ImageWrapper, options: NativeObject): List { - return performOcr(scriptRuntime, image, options).map { - OcrResult(it.text, it.confidence, it.bounds) - } - } - - private fun performOcr(scriptRuntime: ScriptRuntime, image: ImageWrapper, options: NativeObject): List { ApkBuilder.Libs.PADDLE_OCR.ensureLibFiles(OcrMode.PADDLE.value) val (cpuThreadNum, useSlim, useOpenCL) = getOcrOptions(options) - val ocrOptions = org.autojs.plugin.ocr.OcrOptions().apply { - this.threads = cpuThreadNum + val ocrOptions = OcrOptions().apply { + this.cpuThreadNum = cpuThreadNum this.useSlim = useSlim this.useOpenCL = useOpenCL } return runBlocking(scriptRuntime.coroutineContext) { - val target = OcrPluginHost.select(globalContext) + val target = PaddleOcrPluginHost.select(globalContext) ?: throw WrappedIllegalArgumentException("No Paddle OCR plugin matched") - OcrPluginHost.detect(globalContext, target, image.bitmap, ocrOptions) + PaddleOcrPluginHost.recognizeText(globalContext, target, image.bitmap, ocrOptions) } } + fun detectImpl(scriptRuntime: ScriptRuntime, image: ImageWrapper, options: NativeObject): List { + ApkBuilder.Libs.PADDLE_OCR.ensureLibFiles(OcrMode.PADDLE.value) + val (cpuThreadNum, useSlim, useOpenCL) = getOcrOptions(options) + val ocrOptions = OcrOptions().apply { + this.cpuThreadNum = cpuThreadNum + this.useSlim = useSlim + this.useOpenCL = useOpenCL + } + return runBlocking(scriptRuntime.coroutineContext) { + val target = PaddleOcrPluginHost.select(globalContext) + ?: throw WrappedIllegalArgumentException("No Paddle OCR plugin matched") + PaddleOcrPluginHost.detect(globalContext, target, image.bitmap, ocrOptions) + }.map { OcrResult(it.text, it.confidence, it.bounds) } + } + private fun getOcrOptions(options: NativeObject): OcrOptions { val cpuThreadNum = options.inquire("cpuThreadNum", ::coerceIntNumber, DEFAULT_CPU_THREAD_NUM) val useSlim = options.inquire("useSlim", ::coerceBoolean, DEFAULT_USE_SLIM) diff --git a/libs/paddleocr/.gitignore b/libs/paddleocr/.gitignore deleted file mode 100644 index d6443fc1..00000000 --- a/libs/paddleocr/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -/build/ -/.cxx/ -/.idea/ -/cache/ - -/src/sdk/native/ - -*.skip -**/temp-extracted/ diff --git a/libs/paddleocr/PaddleLite/cxx/include/paddle_api.h b/libs/paddleocr/PaddleLite/cxx/include/paddle_api.h deleted file mode 100644 index 07a23d77..00000000 --- a/libs/paddleocr/PaddleLite/cxx/include/paddle_api.h +++ /dev/null @@ -1,611 +0,0 @@ -// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. -// -// 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. - -/* - * This file defines PaddlePredictor, the api for lite. It supports multiple - * hardware including ARM, X86, OpenCL, CUDA and so on. - */ - -#ifndef PADDLE_LITE_API_H_ // NOLINT -#define PADDLE_LITE_API_H_ -#include -#include -#include -#include -#include -#include -#include "paddle_place.h" // NOLINT - -namespace paddle { -namespace lite_api { - -using shape_t = std::vector; -using lod_t = std::vector>; - -enum class LiteModelType { kProtobuf = 0, kNaiveBuffer, UNK }; -// Methods for allocating L3Cache on Arm platform -enum class L3CacheSetMethod { - kDeviceL3Cache = 0, // Use the system L3 Cache size, best performance. - kDeviceL2Cache = 1, // Use the system L2 Cache size, trade off performance - // with less memory consumption. - kAbsolute = 2, // Use the external setting. - // kAutoGrow = 3, // Not supported yet, least memory consumption. -}; - -// return true if current device supports OpenCL model -LITE_API bool IsOpenCLBackendValid(bool check_fp16_valid = false); - -// return current opencl device type, -// if opencl not enabled or IsOpenCLBackendValid return false, it will return -1 -// UNKNOWN:0, QUALCOMM_ADRENO:1, ARM_MALI:2, IMAGINATION_POWERVR:3, OTHERS:4, -LITE_API int GetOpenCLDeviceType(); - -struct LITE_API Tensor { - explicit Tensor(void* raw); - explicit Tensor(const void* raw); - - void Resize(const shape_t& shape); - - /// Readonly data. - template - const T* data() const; - - template - T* mutable_data(TargetType type = TargetType::kHost) const; - - void* mutable_metal_data(void* ptr) const; - - // Share external memory. Note: ensure that the data pointer is in a valid - // state - // during the prediction process. - void ShareExternalMemory(void* data, size_t memory_size, TargetType target); - - template - void CopyFromCpu(const T* data); - - template - void CopyToCpu(T* data) const; - /// Shape of the tensor. - shape_t shape() const; - TargetType target() const; - PrecisionType precision() const; - void SetPrecision(PrecisionType precision); - - // LoD of the tensor - lod_t lod() const; - - // Set LoD of the tensor - void SetLoD(const lod_t& lod); - bool IsInitialized() const; - - private: - void* raw_tensor_; -}; - -/// The PaddlePredictor defines the basic interfaces for different kinds of -/// predictors. -class LITE_API PaddlePredictor { - public: - PaddlePredictor() = default; - - /// Get i-th input. - virtual std::unique_ptr GetInput(int i) = 0; - - /// Get i-th output. - virtual std::unique_ptr GetOutput(int i) const = 0; - - virtual void Run() = 0; - virtual std::shared_ptr Clone() = 0; - virtual std::shared_ptr Clone( - const std::vector& var_names) = 0; - - virtual std::string GetVersion() const = 0; - - // Get input names - virtual std::vector GetInputNames() = 0; - // Get output names - virtual std::vector GetOutputNames() = 0; - // Get output names - virtual std::vector GetParamNames(); - - /// Release all tmp tensor to compress the size of the memory pool. - virtual bool TryShrinkMemory() = 0; - - // Get Input by name - virtual std::unique_ptr GetInputByName(const std::string& name) = 0; - - /// Get a readonly tensor, return null if no one called `name` exists. - virtual std::unique_ptr GetTensor( - const std::string& name) const = 0; - /// Get a mutable tensor, return null if on one called `name` exists - /// internal infereces API, not recommanded. - virtual std::unique_ptr GetMutableTensor(const std::string& name); - - /// Persist the optimized model to disk. This API is only supported by - /// CxxConfig, and the persisted model can be reused for MobileConfig. - virtual void SaveOptimizedModel( - const std::string& model_dir, - LiteModelType model_type = LiteModelType::kProtobuf, - bool record_info = false); - - virtual ~PaddlePredictor() = default; - - protected: - int threads_{1}; - lite_api::PowerMode mode_{lite_api::LITE_POWER_NO_BIND}; -}; - -/// Base class for all the configs. -class LITE_API ConfigBase { - std::string model_dir_; - int threads_{1}; - PowerMode mode_{LITE_POWER_NO_BIND}; - // gpu opencl - CLTuneMode opencl_tune_mode_{CL_TUNE_NONE}; - std::string opencl_bin_path_{""}; - std::string opencl_bin_name_{""}; - CLPrecisionType opencl_precision_{CL_PRECISION_AUTO}; - // Where to cache the npu/xpu/rknpu/apu offline model to the binary files - std::string subgraph_model_cache_dir_{""}; - // Set the cached npu/xpu/rknpu/apu offline model from the buffers - std::map, std::vector>> - subgraph_model_cache_buffers_{}; - // The selected NNAdapter devices to build and run the model. - std::vector nnadapter_device_names_{}; - // The NNAdapter context properties for device configuration, model - // compilation and execution - std::string nnadapter_context_properties_{}; - int (*nnadapter_context_callback_)(int event_id, - void* user_data){nullptr}; // NOLINT - // The directory to find and store the compiled NNAdapter models. - std::string nnadapter_model_cache_dir_{""}; - // Dynamic shapes of the NNAdapter model - std::map>> - nnadapter_dynamic_shape_info_; - // The buffers for loading the compiled NNAdapter models from memory. - std::map> nnadapter_model_cache_buffers_{}; - int device_id_{0}; - int x86_math_num_threads_ = 1; - - std::string metal_path_; - bool metal_use_mps_{false}; - bool metal_use_aggressive_{false}; - void* metal_device_{nullptr}; - bool metal_use_memory_reuse_{false}; - - std::vector discarded_passes_{}; - - public: - explicit ConfigBase(PowerMode mode = LITE_POWER_NO_BIND, int threads = 1); - // set Model_dir - void set_model_dir(const std::string& x) { model_dir_ = x; } - const std::string& model_dir() const { return model_dir_; } - // set Thread - void set_threads(int threads); - int threads() const { return threads_; } - // set Power_mode - void set_power_mode(PowerMode mode); - PowerMode power_mode() const { return mode_; } - - /// \brief Set path and file name of generated OpenCL compiled kernel binary. - /// - /// If you use GPU of specific soc, using OpenCL binary will speed up the - /// initialization. - /// - /// \param path Path that OpenCL compiled kernel binay file stores in. Make - /// sure the path exist and you have Read&Write permission. - /// \param name File name of OpenCL compiled kernel binay. - /// \return void - void set_opencl_binary_path_name(const std::string& path, - const std::string& name); - - /// \brief Set path and file name of generated OpenCL algorithm selecting - /// file. - /// - /// If you use GPU of specific soc, using OpenCL binary will speed up the - /// running time in most cases. But the first running for algorithm selecting - /// is timg-costing. - /// - /// \param tune_mode Set a tune mode: - /// CL_TUNE_NONE: turn off - /// CL_TUNE_RAPID: find the optimal algorithm in a rapid way(less - /// time-cost) - /// CL_TUNE_NORMAL: find the optimal algorithm in a noraml - /// way(suggestion) - /// CL_TUNE_EXHAUSTIVE: find the optimal algorithm in a exhaustive - /// way(most time-costing) - /// \param path Path that OpenCL algorithm selecting file stores in. Make - /// sure the path exist and you have Read&Write permission. - /// \param name File name of OpenCL algorithm selecting file. - /// \param lws_repeats Repeat number for find the optimal local work size . - /// \return void - void set_opencl_tune(CLTuneMode tune_mode = CL_TUNE_NONE, - const std::string& path = "", - const std::string& name = "", - size_t lws_repeats = 4); - - /// \brief Set runtime precision on GPU using OpenCL backend. - /// - /// \param p - /// CL_PRECISION_AUTO: first fp16 if valid, default - /// CL_PRECISION_FP32: force fp32 - /// CL_PRECISION_FP16: force fp16 - /// \return void - void set_opencl_precision(CLPrecisionType p = CL_PRECISION_AUTO); - - // set subgraph_model_dir - void set_subgraph_model_cache_dir(std::string subgraph_model_cache_dir) { - subgraph_model_cache_dir_ = subgraph_model_cache_dir; - } - const std::string& subgraph_model_cache_dir() const { - return subgraph_model_cache_dir_; - } - void set_subgraph_model_cache_buffers(const std::string& key, - const std::vector& cfg, - const std::vector& bin); - const std::map, std::vector>>& - subgraph_model_cache_buffers() const { - return subgraph_model_cache_buffers_; - } - // Check if the NNAdapter device is valid. - bool check_nnadapter_device_name(const std::string& device_name); - // Choose the NNAdapter devices to build and run the model. - void set_nnadapter_device_names( - const std::vector& device_names) { - nnadapter_device_names_ = device_names; - } - const std::vector& nnadapter_device_names() const { - return nnadapter_device_names_; - } - // Set the context properties by key-value map for NNAdapter device - // configuration, model compilation and execution - // Such as "HUAWEI_ASCEND_NPU_SELECTED_DEVICE_IDS=0;" - void set_nnadapter_context_properties(const std::string& context_properties) { - nnadapter_context_properties_ = context_properties; - } - const std::string& nnadapter_context_properties() const { - return nnadapter_context_properties_; - } - // Set nnadapter_context_callback for NNAdapter device to get runtime - // parameters. - // For example: - // cudaStream_t cuda_stream; - // cudaStreamCreate(&cuda_stream); - // int nnadapter_context_callback(int event_id, void* user_data) { - // if (event_id == 0x0100) { - // *(std::reinterpret_cast(user_data)) = cuda_stream; - // } - // return 0; - // } - void set_nnadapter_context_callback( - int (*nnadapter_context_callback)(int event_id, void* user_data)) { - nnadapter_context_callback_ = nnadapter_context_callback; - } - int (*nnadapter_context_callback() const)(int event_id, // NOLINT - void* user_data) { - return nnadapter_context_callback_; - } - - // Enable caching and set the directory to search and store the compiled - // NNAdapter models in the file system. - void set_nnadapter_model_cache_dir(const std::string& model_cache_dir) { - nnadapter_model_cache_dir_ = model_cache_dir; - } - const std::string& nnadapter_model_cache_dir() const { - return nnadapter_model_cache_dir_; - } - // Set dynamic shapes for building models - void set_nnadapter_dynamic_shape_info( - const std::map>>& - nnadapter_dynamic_shape_info) { - nnadapter_dynamic_shape_info_ = nnadapter_dynamic_shape_info; - } - const std::map>>& - nnadapter_dynamic_shape_info() const { - return nnadapter_dynamic_shape_info_; - } - // Set the buffers for loading the compiled NNAdapter models from memory. - void set_nnadapter_model_cache_buffers( - const std::string& model_cache_token, - const std::vector& model_cache_buffer); - const std::map>& - nnadapter_model_cache_buffers() const { - return nnadapter_model_cache_buffers_; - } - // set Device ID - void set_device_id(int device_id) { device_id_ = device_id; } - int get_device_id() const { return device_id_; } - // set x86_math_num_threads - void set_x86_math_num_threads(int threads); - int x86_math_num_threads() const; - - void set_metal_lib_path(const std::string& path); - void set_metal_use_mps(bool flag); - void set_metal_use_aggressive(bool flag); - void set_metal_device(void* device); - void set_metal_use_memory_reuse(bool flag); - - std::string metal_lib_path() const { return metal_path_; } - bool metal_use_mps() const { return metal_use_mps_; } - bool metal_use_aggressive() const { return metal_use_aggressive_; } - void* metal_device() const { return metal_device_; } - bool metal_use_memory_reuse() const { return metal_use_memory_reuse_; } - - void add_discarded_pass(const std::string pass); - const std::vector get_discarded_passes() const { - return discarded_passes_; - } -}; - -class LITE_API CxxModelBuffer { - public: - CxxModelBuffer(const char* program_buffer, - size_t program_buffer_size, - const char* params_buffer, - size_t params_buffer_size); - CxxModelBuffer(std::string&& program_buffer, std::string&& params_buffer); - const std::string& get_program() const; - const std::string& get_params() const; - bool is_empty() const; - - CxxModelBuffer() = default; - CxxModelBuffer(const CxxModelBuffer&) = delete; - - private: - std::string program_; - std::string params_; -}; - -/// CxxConfig is the config for the Full feature predictor. -class LITE_API CxxConfig : public ConfigBase { - std::vector valid_places_; - std::string model_file_; - std::string param_file_; - std::shared_ptr model_buffer_{nullptr}; - std::vector passes_internal_{}; - bool quant_model_{false}; // Enable post_quant_dynamic in opt - QuantType quant_type_{QuantType::QUANT_INT16}; - bool sparse_model_{false}; // Enable sparse_conv_detect_pass in opt - float sparse_threshold_{0.6f}; - std::map>> - preferred_inputs_for_warmup_; -#ifdef LITE_WITH_CUDA - bool multi_stream_{false}; -#endif -#ifdef LITE_WITH_MLU - lite_api::MLUCoreVersion mlu_core_version_{lite_api::MLUCoreVersion::MLU_270}; - int mlu_core_number_{1}; - DataLayoutType mlu_input_layout_{DATALAYOUT(kNCHW)}; - std::vector mlu_first_conv_mean_{}; - std::vector mlu_first_conv_std_{}; -#endif - // The custom configuration file or buffer for the NNAdapter subgraph - // partition, here is an example: - // op_type:in_var_name_0,in_var_name1:out_var_name_0,out_var_name1 - // op_type::out_var_name_0 - // op_type:in_var_name_0 - // op_type - std::string nnadapter_subgraph_partition_config_path_; - std::string nnadapter_subgraph_partition_config_buffer_; - std::string mixed_precision_quantization_config_path_; - std::string mixed_precision_quantization_config_buffer_; - - public: - void set_valid_places(const std::vector& x) { valid_places_ = x; } - void set_model_file(const std::string& path) { model_file_ = path; } - void set_param_file(const std::string& path) { param_file_ = path; } - void set_model_buffer(const char* model_buffer, - size_t model_buffer_size, - const char* param_buffer, - size_t param_buffer_size) { - model_buffer_.reset(new CxxModelBuffer( - model_buffer, model_buffer_size, param_buffer, param_buffer_size)); - } - void set_model_buffer(std::shared_ptr model_buffer) { - model_buffer_ = model_buffer; - } - const CxxModelBuffer& get_model_buffer() const; - // internal inference to choose passes for model optimizing, - // it's designed for internal developer and not recommanded - // for comman users. - void set_passes_internal( - const std::vector& passes_internal = {}) { - passes_internal_ = passes_internal; - } - const std::vector& get_passes_internal() const { - return passes_internal_; - } - const std::vector& valid_places() const { return valid_places_; } - std::string model_file() const { return model_file_; } - std::string param_file() const { return param_file_; } - bool is_model_from_memory() const { return static_cast(model_buffer_); } - // note: `model_from_memory` has the same effect as `is_model_from_memory`, - // but is_model_from_memory is recommended and `model_from_memory` will be - // abandoned in v3.0. - bool model_from_memory() const { return static_cast(model_buffer_); } - -#ifdef LITE_WITH_CUDA - void set_multi_stream(bool multi_stream) { multi_stream_ = multi_stream; } - bool multi_stream() const { return multi_stream_; } -#endif - -#ifdef LITE_WITH_MLU - // set MLU core version, which is used when compiling MLU kernels - void set_mlu_core_version(lite_api::MLUCoreVersion core_version); - // set MLU core number, which is used when compiling MLU kernels - void set_mlu_core_number(int core_number); - // whether use MLU's first conv kernel. First conv is a special kernel - // provided by MLU, its input is uint8, and also needs two 3-dimentional - // vectors which save all inputs' mean and std values - // set the 3-dimentional mean vector and 3-dimentional std vector used by - // MLU's first conv - void set_mlu_firstconv_param(const std::vector& mean, - const std::vector& std); - // set MLU input layout. User can specify layout of input data to be NHWC, - // default is NCHW - void set_mlu_input_layout(DataLayoutType layout); - - lite_api::MLUCoreVersion mlu_core_version() const; - int mlu_core_number() const; - DataLayoutType mlu_input_layout() const; - // std::pair - std::pair, std::vector> mlu_firstconv_param() const; -#endif - - // XPU only, set the size of the workspace memory from L3 cache for the - // current thread. - // **DEPRECATED**, use set_xpu_l3_cache_method() in the future - void set_xpu_workspace_l3_size_per_thread(int l3_size = 0x4000000); - void set_xpu_l3_cache_method(size_t l3_size, bool locked = false); - - void set_xpu_gm_workspace_method(size_t gm_size); - - void set_xpu_conv_autotune(bool autotune = true, - const std::string& autotune_file = ""); - - // XPU only, specify the target device ID for the current thread. - // **DEPRECATED**, use xpu_set_device() at the very beginning of each worker - // thread - void set_xpu_dev_per_thread(int dev_no = 0); - - // XPU set multi_stream - void enable_xpu_multi_stream(); - - // **DEPRECATED**, use set_xpu_multi_encoder_method() in the future - void set_xpu_multi_encoder_precision(const std::string& precision = "int16"); - void set_xpu_multi_encoder_method(const std::string& precision = "int16", - bool adaptive_seqlen = false); - - // set input tensor for warmup. - // It is optional. If you set prefered_inputs, model wil run immediately when - // predictor is created - template - void set_preferred_inputs_for_warmup(const int group_idx, - const int tensor_idx, - const shape_t& shape, - const lod_t& lod = {}, - const T fill_value = 0, - const void* data = nullptr); - const std::map>>& - preferred_inputs_for_warmup() const { - return preferred_inputs_for_warmup_; - } - - void set_quant_model(bool quant_model) { quant_model_ = quant_model; } - bool quant_model() const { return quant_model_; } - void set_quant_type(QuantType quant_type) { quant_type_ = quant_type; } - QuantType quant_type() const { return quant_type_; } - - void set_sparse_model(bool sparse_model) { sparse_model_ = sparse_model; } - bool sparse_model() const { return sparse_model_; } - void set_sparse_threshold(float sparse_threshold) { - sparse_threshold_ = sparse_threshold; - } - float sparse_threshold() const { return sparse_threshold_; } - - // Enable the custom subgraph partition for NNAdapter by providing the - // configuration file or buffer - void set_nnadapter_subgraph_partition_config_path( - const std::string& subgraph_partition_config_path) { - nnadapter_subgraph_partition_config_path_ = subgraph_partition_config_path; - } - const std::string& nnadapter_subgraph_partition_config_path() const { - return nnadapter_subgraph_partition_config_path_; - } - void set_nnadapter_subgraph_partition_config_buffer( - const std::string& subgraph_partition_config_buffer) { - nnadapter_subgraph_partition_config_buffer_ = - subgraph_partition_config_buffer; - } - const std::string& nnadapter_subgraph_partition_config_buffer() const { - return nnadapter_subgraph_partition_config_buffer_; - } - // Clear some ops' quant information to support mixed precision compute by - // configuration file or buffer - void set_nnadapter_mixed_precision_quantization_config_path( - const std::string& mixed_precision_quantization_config_path) { - mixed_precision_quantization_config_path_ = - mixed_precision_quantization_config_path; - } - const std::string& nnadapter_mixed_precision_quantization_config_path() - const { - return mixed_precision_quantization_config_path_; - } - void set_nnadapter_mixed_precision_quantization_config_buffer( - const std::string& mixed_precision_quantization_config_buffer) { - mixed_precision_quantization_config_buffer_ = - mixed_precision_quantization_config_buffer; - } - const std::string& nnadapter_mixed_precision_quantization_config_buffer() - const { - return mixed_precision_quantization_config_buffer_; - } -}; - -/// MobileConfig is the config for the light weight predictor, it will skip -/// IR optimization or other unnecessary stages. -class LITE_API MobileConfig : public ConfigBase { - // whether to load data from memory. Model data will be loaded from memory - // buffer if model_from_memory_ is true. - bool model_from_memory_{false}; - - // model data readed from file or memory buffer in combined format. - std::string lite_model_file_; - - // NOTE: This is a deprecated variable and will be removed in latter release. - std::string model_buffer_; - std::string param_buffer_; - - public: - // set model data in combined format, `set_model_from_file` refers to loading - // model from file, set_model_from_buffer refers to loading model from memory - // buffer - void set_model_from_file(const std::string& x); - void set_model_from_buffer(const std::string& x); - // return model data in lite_model_file_, which is in combined format. - const std::string& lite_model_file() const { return lite_model_file_; } - - // return model_from_memory_, which indicates whether to load model from - // memory buffer. - bool is_model_from_memory() const { return model_from_memory_; } - // note: `model_from_memory` has the same effect as `is_model_from_memory`, - // but is_model_from_memory is recommended and `model_from_memory` will be - // abandoned in v3.0. - bool model_from_memory() const { return model_from_memory_; } - - // NOTE: This is a deprecated API and will be removed in latter release. - void set_model_buffer(const char* model_buffer, - size_t model_buffer_size, - const char* param_buffer, - size_t param_buffer_size); - - // NOTE: This is a deprecated API and will be removed in latter release. - const std::string& model_buffer() const { return model_buffer_; } - - // NOTE: This is a deprecated API and will be removed in latter release. - const std::string& param_buffer() const { return param_buffer_; } - - // This is the method for allocating workspace_size according to L3Cache size - void SetArmL3CacheSize( - L3CacheSetMethod method = L3CacheSetMethod::kDeviceL3Cache, - int absolute_val = -1); -}; - -template -LITE_API std::shared_ptr CreatePaddlePredictor(const ConfigT&); - -} // namespace lite_api -} // namespace paddle - -#endif // NOLINT diff --git a/libs/paddleocr/PaddleLite/cxx/include/paddle_image_preprocess.h b/libs/paddleocr/PaddleLite/cxx/include/paddle_image_preprocess.h deleted file mode 100644 index 49138f5f..00000000 --- a/libs/paddleocr/PaddleLite/cxx/include/paddle_image_preprocess.h +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. -// -// 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. - -#pragma once - -#include -#include -#include -#include "lite/api/paddle_api.h" -#include "lite/api/paddle_place.h" - -namespace paddle { -namespace lite { -namespace utils { -namespace cv { -typedef paddle::lite_api::Tensor Tensor; -typedef paddle::lite_api::DataLayoutType LayoutType; -// color enum -enum ImageFormat { - RGBA = 0, - BGRA, - RGB, - BGR, - GRAY, - NV21 = 11, - NV12, - YUV420SP, - YUV420P, - YUV422, - YUV444 -}; -// flip enum -enum FlipParam { - XY = -1, // flip along the XY axis - X = 0, // flip along the X axis - Y // flip along the Y axis -}; -// transform param -typedef struct { - int ih; // input height - int iw; // input width - int oh; // outpu theight - int ow; // output width - FlipParam flip_param; // flip, support x, y, xy - float rotate_param; // rotate, support 90, 180, 270 -} TransParam; - -class ImagePreprocess { - public: - /* - * init - * param srcFormat: input image color - * param dstFormat: output image color - * param param: input image parameter, egs: input size - */ - ImagePreprocess(ImageFormat srcFormat, - ImageFormat dstFormat, - TransParam param); - - /* - * image color convert - * support NV12/NV21_to_BGR(RGB), NV12/NV21_to_BGRA(RGBA), - * BGR(RGB)and BGRA(RGBA) transform, - * BGR(RGB)and RGB(BGR) transform, - * BGR(RGB)and RGBA(BGRA) transform, - * BGR(RGB) and GRAY transform, - * BGRA(RGBA) and GRAY transform, - * param src: input image data - * param dst: output image data - */ - void image_convert(const uint8_t* src, uint8_t* dst); - - /* - * image color convert - * support NV12/NV21_to_BGR(RGB), NV12/NV21_to_BGRA(RGBA), - * BGR(RGB)and BGRA(RGBA) transform, - * BGR(RGB)and RGB(BGR) transform, - * BGR(RGB)and RGBA(BGRA) transform, - * BGR(RGB)and GRAY transform, - * BGRA(RGBA) and GRAY transform, - * param src: input image data - * param dst: output image data - * param srcFormat: input image image format support: GRAY, NV12(NV21), - * BGR(RGB) and BGRA(RGBA) - * param dstFormat: output image image format, support GRAY, BGR(RGB) and - * BGRA(RGBA) - */ - void image_convert(const uint8_t* src, - uint8_t* dst, - ImageFormat srcFormat, - ImageFormat dstFormat); - - /* - * image color convert - * support NV12/NV21_to_BGR(RGB), NV12/NV21_to_BGRA(RGBA), - * BGR(RGB)and BGRA(RGBA) transform, - * BGR(RGB)and RGB(BGR) transform, - * BGR(RGB)and RGBA(BGRA) transform, - * BGR(RGB)and GRAY transform, - * BGRA(RGBA) and GRAY transform, - * param src: input image data - * param dst: output image data - * param srcFormat: input image image format support: GRAY, NV12(NV21), - * BGR(RGB) and BGRA(RGBA) - * param dstFormat: output image image format, support GRAY, BGR(RGB) and - * BGRA(RGBA) - * param srcw: input image width - * param srch: input image height - */ - void image_convert(const uint8_t* src, - uint8_t* dst, - ImageFormat srcFormat, - ImageFormat dstFormat, - int srcw, - int srch); - - /* - * image resize, use bilinear method - * support image format: 1-channel image (egs: GRAY, 2-channel image (egs: - * NV12, NV21), 3-channel(egs: BGR), 4-channel(egs: BGRA) - * param src: input image data - * param dst: output image data - */ - void image_resize(const uint8_t* src, uint8_t* dst); - - /* - image resize, use bilinear method - * support image format: 1-channel image (egs: GRAY, 2-channel image (egs: - NV12, NV21), 3-channel image(egs: BGR), 4-channel image(egs: BGRA) - * param src: input image data - * param dst: output image data - * param srcw: input image width - * param srch: input image height - * param dstw: output image width - * param dsth: output image height - */ - void image_resize(const uint8_t* src, - uint8_t* dst, - ImageFormat srcFormat, - int srcw, - int srch, - int dstw, - int dsth); - - /* - * image Rotate - * support 90, 180 and 270 Rotate process - * color format support 1-channel image, 3-channel image and 4-channel image - * param src: input image data - * param dst: output image data - */ - void image_rotate(const uint8_t* src, uint8_t* dst); - - /* - * image Rotate - * support 90, 180 and 270 Rotate process - * color format support 1-channel image, 3-channel image and 4-channel image - * param src: input image data - * param dst: output image data - * param srcFormat: input image format, support GRAY, BGR(RGB) and BGRA(RGBA) - * param srcw: input image width - * param srch: input image height - * param degree: Rotate degree, support 90, 180 and 270 - */ - void image_rotate(const uint8_t* src, - uint8_t* dst, - ImageFormat srcFormat, - int srcw, - int srch, - float degree); - - /* - * image Flip - * support X, Y and XY flip process - * color format support 1-channel image, 3-channel image and 4-channel image - * param src: input image data - * param dst: output image data - */ - void image_flip(const uint8_t* src, uint8_t* dst); - - /* - * image Flip - * support X, Y and XY flip process - * color format support 1-channel image, 3-channel image and 4-channel image - * param src: input image data - * param dst: output image data - * param srcFormat: input image format, support GRAY, BGR(RGB) and BGRA(RGBA) - * param srcw: input image width - * param srch: input image height - * param flip_param: flip parameter, support X, Y and XY - */ - void image_flip(const uint8_t* src, - uint8_t* dst, - ImageFormat srcFormat, - int srcw, - int srch, - FlipParam flip_param); - - /* - * change image data to tensor data - * support image format is GRAY, BGR(RGB) and BGRA(RGBA), Data layout is NHWC - * and - * NCHW - * param src: input image data - * param dstTensor: output tensor data - * param layout: output tensor layout,support NHWC and NCHW - * param means: means of image - * param scales: scales of image - */ - void image_to_tensor(const uint8_t* src, - Tensor* dstTensor, - LayoutType layout, - float* means, - float* scales); - - /* - * change image data to tensor data - * support image format is GRAY, BGR(RGB) and BGRA(RGBA), Data layout is NHWC - * and - * NCHW - * param src: input image data - * param dstTensor: output tensor data - * param srcFormat: input image format, support BGR(RGB) and BGRA(RGBA) - * param srcw: input image width - * param srch: input image height - * param layout: output tensor layout,support NHWC and NCHW - * param means: means of image - * param scales: scales of image - */ - void image_to_tensor(const uint8_t* src, - Tensor* dstTensor, - ImageFormat srcFormat, - int srcw, - int srch, - LayoutType layout, - float* means, - float* scales); - - /* - * image crop process - * color format support 1-channel image, 3-channel image and 4-channel image - * param src: input image data - * param dst: output image data - */ - void image_crop(const uint8_t* src, - uint8_t* dst, - ImageFormat srcFormat, - int srcw, - int srch, - int left_x, - int left_y, - int dstw, - int dsth); - - private: - ImageFormat srcFormat_; - ImageFormat dstFormat_; - TransParam transParam_; -}; -} // namespace cv -} // namespace utils -} // namespace lite -} // namespace paddle diff --git a/libs/paddleocr/PaddleLite/cxx/include/paddle_lite_factory_helper.h b/libs/paddleocr/PaddleLite/cxx/include/paddle_lite_factory_helper.h deleted file mode 100644 index 5ce6a9ac..00000000 --- a/libs/paddleocr/PaddleLite/cxx/include/paddle_lite_factory_helper.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. -// -// 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. - -/* - * This file defines some MACROS that explicitly determine the op, kernel, mir - * passes used in the inference lib. - */ -#pragma once - -// some platform-independent defintion - -#if defined(_WIN32) -#define UNUSED -#define __builtin_expect(EXP, C) (EXP) -#else -#define UNUSED __attribute__((unused)) -#endif - -#define USE_LITE_OP(op_type__) \ - extern int touch_op_##op_type__(); \ - int LITE_OP_REGISTER_FAKE(op_type__) UNUSED = touch_op_##op_type__(); - -#define USE_LITE_KERNEL(op_type__, target__, precision__, layout__, alias__) \ - extern int touch_##op_type__##target__##precision__##layout__##alias__(); \ - int op_type__##target__##precision__##layout__##alias__##__use_lite_kernel \ - UNUSED = touch_##op_type__##target__##precision__##layout__##alias__(); - -#define USE_MIR_PASS(name__) \ - extern bool mir_pass_registry##name__##_fake(); \ - static bool mir_pass_usage##name__ UNUSED = \ - mir_pass_registry##name__##_fake(); - -#define LITE_OP_REGISTER_FAKE(op_type__) op_type__##__registry__ diff --git a/libs/paddleocr/PaddleLite/cxx/include/paddle_place.h b/libs/paddleocr/PaddleLite/cxx/include/paddle_place.h deleted file mode 100644 index 691c251c..00000000 --- a/libs/paddleocr/PaddleLite/cxx/include/paddle_place.h +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. -// -// 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. - -#pragma once -#include -#include - -// Generic helper definitions for shared library support -#if defined _WIN32 || defined __CYGWIN__ -#define PADDLE_LITE_HELPER_DLL_IMPORT __declspec(dllimport) -#define PADDLE_LITE_HELPER_DLL_EXPORT __declspec(dllexport) -#define PADDLE_LITE_HELPER_DLL_LOCAL -#else -#if __GNUC__ >= 4 -#define PADDLE_LITE_HELPER_DLL_IMPORT __attribute__((visibility("default"))) -#define PADDLE_LITE_HELPER_DLL_EXPORT __attribute__((visibility("default"))) -#else -#define PADDLE_LITE_HELPER_DLL_IMPORT -#define PADDLE_LITE_HELPER_DLL_EXPORT -#endif -#endif - -#ifdef LITE_ON_TINY_PUBLISH -#define LITE_API PADDLE_LITE_HELPER_DLL_EXPORT -#define LITE_API_IMPORT PADDLE_LITE_HELPER_DLL_IMPORT -#else -#define LITE_API -#define LITE_API_IMPORT -#endif - -namespace paddle { -namespace lite_api { - -enum class TargetType : int { - kUnk = 0, - kHost = 1, - kX86 = 2, - kCUDA = 3, - kARM = 4, - kOpenCL = 5, - kAny = 6, // any target - kFPGA = 7, - kNPU = 8, - kXPU = 9, - kBM = 10, - kMLU = 11, - kRKNPU = 12, - kAPU = 13, - kHuaweiAscendNPU = 14, - kImaginationNNA = 15, - kIntelFPGA = 16, - kMetal = 17, - kNNAdapter = 18, - NUM = 19, // number of fields. -}; -enum class PrecisionType : int { - kUnk = 0, - kFloat = 1, - kInt8 = 2, - kInt32 = 3, - kAny = 4, // any precision - kFP16 = 5, - kBool = 6, - kInt64 = 7, - kInt16 = 8, - kUInt8 = 9, - kFP64 = 10, - NUM = 11, // number of fields. -}; -enum class DataLayoutType : int { - kUnk = 0, - kNCHW = 1, - kNHWC = 3, - kImageDefault = 4, // for opencl image2d - kImageFolder = 5, // for opencl image2d - kImageNW = 6, // for opencl image2d - kAny = 2, // any data layout - kMetalTexture2DArray = 7, - kMetalTexture2D = 8, - NUM = 9, // number of fields. -}; - -typedef enum { - LITE_POWER_HIGH = 0, - LITE_POWER_LOW = 1, - LITE_POWER_FULL = 2, - LITE_POWER_NO_BIND = 3, - LITE_POWER_RAND_HIGH = 4, - LITE_POWER_RAND_LOW = 5 -} PowerMode; - -typedef enum { - CL_TUNE_NONE = 0, - CL_TUNE_RAPID = 1, - CL_TUNE_NORMAL = 2, - CL_TUNE_EXHAUSTIVE = 3 -} CLTuneMode; - -typedef enum { - CL_PRECISION_AUTO = 0, - CL_PRECISION_FP32 = 1, - CL_PRECISION_FP16 = 2 -} CLPrecisionType; - -typedef enum { MLU_220 = 0, MLU_270 = 1 } MLUCoreVersion; - -enum class ActivationType : int { - kIndentity = 0, - kRelu = 1, - kRelu6 = 2, - kPRelu = 3, - kLeakyRelu = 4, - kSigmoid = 5, - kTanh = 6, - kSwish = 7, - kExp = 8, - kAbs = 9, - kHardSwish = 10, - kReciprocal = 11, - kThresholdedRelu = 12, - kElu = 13, - kHardSigmoid = 14, - kLog = 15, - kSigmoid_v2 = 16, - kTanh_v2 = 17, - kGelu = 18, - kErf = 19, - kSign = 20, - kSoftPlus = 21, - kMish = 22, - NUM = 23, -}; - -static size_t PrecisionTypeLength(PrecisionType type) { - switch (type) { - case PrecisionType::kFloat: - return 4; - case PrecisionType::kFP64: - return 8; - case PrecisionType::kUInt8: - return 1; - case PrecisionType::kInt8: - return 1; - case PrecisionType::kInt32: - return 4; - case PrecisionType::kInt64: - return 8; - case PrecisionType::kFP16: - return 2; - case PrecisionType::kInt16: - return 2; - default: - return 0; - } -} - -enum class QuantType : int { - QUANT_INT8, - QUANT_INT16, -}; - -template -struct PrecisionTypeTrait { - constexpr static PrecisionType Type() { return PrecisionType::kUnk; } -}; - -#define _ForEachPrecisionTypeHelper(callback, cpp_type, precision_type) \ - callback(cpp_type, ::paddle::lite_api::PrecisionType::precision_type); - -#define _ForEachPrecisionType(callback) \ - _ForEachPrecisionTypeHelper(callback, bool, kBool); \ - _ForEachPrecisionTypeHelper(callback, float, kFloat); \ - _ForEachPrecisionTypeHelper(callback, double, kFP64); \ - _ForEachPrecisionTypeHelper(callback, uint8_t, kUInt8); \ - _ForEachPrecisionTypeHelper(callback, int8_t, kInt8); \ - _ForEachPrecisionTypeHelper(callback, int16_t, kInt16); \ - _ForEachPrecisionTypeHelper(callback, int, kInt32); \ - _ForEachPrecisionTypeHelper(callback, int64_t, kInt64); - -#define DefinePrecisionTypeTrait(cpp_type, precision_type) \ - template <> \ - struct PrecisionTypeTrait { \ - constexpr static PrecisionType Type() { return precision_type; } \ - } - -_ForEachPrecisionType(DefinePrecisionTypeTrait); - -#ifdef ENABLE_ARM_FP16 -typedef __fp16 float16_t; -_ForEachPrecisionTypeHelper(DefinePrecisionTypeTrait, float16_t, kFP16); -#endif - -#undef _ForEachPrecisionTypeHelper -#undef _ForEachPrecisionType -#undef DefinePrecisionTypeTrait - -#define TARGET(item__) paddle::lite_api::TargetType::item__ -#define PRECISION(item__) paddle::lite_api::PrecisionType::item__ -#define DATALAYOUT(item__) paddle::lite_api::DataLayoutType::item__ - -const std::string& ActivationTypeToStr(ActivationType act); - -const std::string& TargetToStr(TargetType target); - -const std::string& PrecisionToStr(PrecisionType precision); - -const std::string& DataLayoutToStr(DataLayoutType layout); - -const std::string& TargetRepr(TargetType target); - -const std::string& PrecisionRepr(PrecisionType precision); - -const std::string& DataLayoutRepr(DataLayoutType layout); - -const std::string& CLTuneModeToStr(CLTuneMode mode); - -const std::string& CLPrecisionTypeToStr(CLPrecisionType type); - -// Get a set of all the elements represented by the target. -std::set ExpandValidTargets(TargetType target = TARGET(kAny)); - -// Get a set of all the elements represented by the precision. -std::set ExpandValidPrecisions( - PrecisionType precision = PRECISION(kAny)); - -// Get a set of all the elements represented by the layout. -std::set ExpandValidLayouts( - DataLayoutType layout = DATALAYOUT(kAny)); - -/* - * Place specifies the execution context of a Kernel or input/output for a - * kernel. It is used to make the analysis of the MIR more clear and accurate. - */ -struct LITE_API Place { - TargetType target{TARGET(kUnk)}; - PrecisionType precision{PRECISION(kUnk)}; - DataLayoutType layout{DATALAYOUT(kUnk)}; - int16_t device{0}; // device ID - - Place() = default; - Place(TargetType target, - PrecisionType precision = PRECISION(kFloat), - DataLayoutType layout = DATALAYOUT(kNCHW), - int16_t device = 0) - : target(target), precision(precision), layout(layout), device(device) {} - - bool is_valid() const { - return target != TARGET(kUnk) && precision != PRECISION(kUnk) && - layout != DATALAYOUT(kUnk); - } - - size_t hash() const; - - bool operator==(const Place& other) const { - return target == other.target && precision == other.precision && - layout == other.layout && device == other.device; - } - - bool operator!=(const Place& other) const { return !(*this == other); } - - friend bool operator<(const Place& a, const Place& b); - - std::string DebugString() const; -}; - -} // namespace lite_api -} // namespace paddle diff --git a/libs/paddleocr/PaddleLite/cxx/include/paddle_use_kernels.h b/libs/paddleocr/PaddleLite/cxx/include/paddle_use_kernels.h deleted file mode 100644 index ac097ac6..00000000 --- a/libs/paddleocr/PaddleLite/cxx/include/paddle_use_kernels.h +++ /dev/null @@ -1,408 +0,0 @@ -#pragma once -#include "paddle_lite_factory_helper.h" - -USE_LITE_KERNEL(gather_nd, kHost, kAny, kAny, def); -USE_LITE_KERNEL(relu_clipped, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(swish, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(log, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(exp, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(floor, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(hard_sigmoid, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(sqrt, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(rsqrt, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(square, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(hard_swish, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(reciprocal, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(abs, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(gelu, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(erf, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(sign, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(softplus, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(mish, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(pow, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(where, kHost, kAny, kAny, def); -USE_LITE_KERNEL(assign_value, kHost, kAny, kNCHW, def); -USE_LITE_KERNEL(tril_triu, kHost, kAny, kNCHW, float32); -USE_LITE_KERNEL(lstm, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(lstm, kARM, kInt8, kNCHW, def); -USE_LITE_KERNEL(split, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(split, kHost, kFloat, kNCHW, int32); -USE_LITE_KERNEL(split, kHost, kFloat, kNCHW, int64); -USE_LITE_KERNEL(split, kHost, kInt64, kNCHW, def); -USE_LITE_KERNEL(gaussian_random, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(feed, kHost, kAny, kAny, def); -USE_LITE_KERNEL(cos, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(conditional_block, kHost, kAny, kAny, def); -USE_LITE_KERNEL(read_from_array, kHost, kAny, kAny, def); -USE_LITE_KERNEL(deformable_conv, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(distribute_fpn_proposals, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(roi_align, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(one_hot, kHost, kAny, kAny, def); -USE_LITE_KERNEL(one_hot_v2, kHost, kAny, kAny, def); -USE_LITE_KERNEL(one_hot_v2, kHost, kAny, kAny, one_hot_v2_int32); -USE_LITE_KERNEL(unique_with_counts, kHost, kAny, kAny, def); -USE_LITE_KERNEL(arg_max, kARM, kAny, kNCHW, fp32); -USE_LITE_KERNEL(arg_max, kARM, kAny, kNCHW, int64); -USE_LITE_KERNEL(arg_max, kARM, kAny, kNCHW, int32); -USE_LITE_KERNEL(arg_max, kARM, kAny, kNCHW, int16); -USE_LITE_KERNEL(arg_max, kARM, kAny, kNCHW, uint8); -USE_LITE_KERNEL(lod_array_length, kHost, kAny, kAny, def); -USE_LITE_KERNEL(flip, kHost, kAny, kNCHW, flip_fp32); -USE_LITE_KERNEL(flip, kHost, kAny, kNCHW, flip_i64); -USE_LITE_KERNEL(reduce_all, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(reduce_any, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(stack, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(stack, kHost, kFloat, kAny, int32_def); -USE_LITE_KERNEL(stack, kHost, kFloat, kAny, int64_def); -USE_LITE_KERNEL(elementwise_add, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(elementwise_add, kARM, kInt32, kNCHW, def); -USE_LITE_KERNEL(elementwise_add, kARM, kInt64, kNCHW, def); -USE_LITE_KERNEL(elementwise_add, kARM, kFloat, kNCHW, int32); -USE_LITE_KERNEL(elementwise_add, kARM, kFloat, kNCHW, int64); -USE_LITE_KERNEL(fusion_elementwise_add_activation, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(elementwise_sub, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(elementwise_sub, kARM, kInt32, kNCHW, def); -USE_LITE_KERNEL(elementwise_sub, kARM, kFloat, kNCHW, int32); -USE_LITE_KERNEL(elementwise_sub, kARM, kFloat, kNCHW, int64); -USE_LITE_KERNEL(fusion_elementwise_sub_activation, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(elementwise_mul, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(elementwise_mul, kARM, kInt32, kNCHW, def); -USE_LITE_KERNEL(elementwise_mul, kARM, kInt64, kNCHW, def); -USE_LITE_KERNEL(elementwise_mul, kARM, kFloat, kNCHW, int32); -USE_LITE_KERNEL(elementwise_mul, kARM, kFloat, kNCHW, int64); -USE_LITE_KERNEL(fusion_elementwise_mul_activation, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(fusion_elementwise_mul_activation, kARM, kInt64, kNCHW, def); -USE_LITE_KERNEL(elementwise_max, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(fusion_elementwise_max_activation, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(elementwise_min, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(fusion_elementwise_min_activation, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(elementwise_div, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(elementwise_div, kARM, kInt32, kNCHW, def); -USE_LITE_KERNEL(elementwise_div, kARM, kInt64, kNCHW, def); -USE_LITE_KERNEL(fusion_elementwise_div_activation, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(elementwise_mod, kARM, kInt64, kNCHW, def); -USE_LITE_KERNEL(elementwise_mod, kARM, kFloat, kNCHW, int64); -USE_LITE_KERNEL(elementwise_mod, kARM, kFloat, kNCHW, int32_mod); -USE_LITE_KERNEL(elementwise_pow, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(elementwise_pow, kARM, kInt32, kNCHW, def); -USE_LITE_KERNEL(elementwise_floordiv, kARM, kInt32, kNCHW, def); -USE_LITE_KERNEL(elementwise_floordiv, kARM, kInt64, kNCHW, def); -USE_LITE_KERNEL(elementwise_floordiv, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(elementwise_floordiv, kARM, kFloat, kNCHW, int64); -USE_LITE_KERNEL(softmax, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(prior_box, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(gru, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(gru, kARM, kInt8, kNCHW, def); -USE_LITE_KERNEL(is_empty, kHost, kAny, kAny, def); -USE_LITE_KERNEL(unsqueeze, kHost, kAny, kAny, def); -USE_LITE_KERNEL(unsqueeze2, kHost, kAny, kAny, def); -USE_LITE_KERNEL(sequence_expand_as, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(sequence_expand_as, kARM, kFloat, kNCHW, int32); -USE_LITE_KERNEL(sequence_expand_as, kARM, kFloat, kNCHW, int64); -USE_LITE_KERNEL(fill_constant_batch_size_like, kHost, kAny, kNCHW, def); -USE_LITE_KERNEL(fill_zeros_like, kHost, kFloat, kNCHW, float32); -USE_LITE_KERNEL(fill_zeros_like, kHost, kFloat, kNCHW, int32); -USE_LITE_KERNEL(fill_zeros_like, kHost, kFloat, kNCHW, int64); -USE_LITE_KERNEL(sum, kARM, kFloat, kNCHW, sum_i32); -USE_LITE_KERNEL(sum, kARM, kFloat, kNCHW, sum_i64); -USE_LITE_KERNEL(sum, kARM, kFloat, kNCHW, sum_fp32); -USE_LITE_KERNEL(relu, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(leaky_relu, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(relu_clipped, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(prelu, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(sigmoid, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(tanh, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(swish, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(relu6, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(log, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(exp, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(floor, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(hard_sigmoid, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(rsqrt, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(square, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(hard_swish, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(reciprocal, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(abs, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(thresholded_relu, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(elu, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(softplus, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(reduce_mean, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(range, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(range, kHost, kInt64, kAny, def); -USE_LITE_KERNEL(range, kHost, kInt32, kAny, def); -USE_LITE_KERNEL(range, kHost, kFloat, kAny, int32); -USE_LITE_KERNEL(range, kHost, kFloat, kAny, int64); -USE_LITE_KERNEL(beam_search_decode, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(squeeze, kHost, kAny, kAny, def); -USE_LITE_KERNEL(squeeze2, kHost, kAny, kAny, def); -USE_LITE_KERNEL(group_norm, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(sequence_conv, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(write_to_array, kHost, kAny, kAny, def); -USE_LITE_KERNEL(unstack, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(unstack, kHost, kFloat, kAny, unstack_int32); -USE_LITE_KERNEL(generate_proposals_v2, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(layer_norm, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(crop_tensor, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(crop_tensor, kHost, kFloat, kAny, int32_precision); -USE_LITE_KERNEL(sequence_mask, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(sequence_mask, kHost, kFloat, kNCHW, int32); -USE_LITE_KERNEL(sequence_mask, kHost, kFloat, kNCHW, int64); -USE_LITE_KERNEL(matrix_nms, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(reverse, kHost, kAny, kNCHW, fp32); -USE_LITE_KERNEL(sequence_expand, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(sequence_expand, kHost, kFloat, kNCHW, int32); -USE_LITE_KERNEL(sequence_expand, kHost, kFloat, kNCHW, int64); -USE_LITE_KERNEL(reduce_prod, kARM, kInt32, kNCHW, def); -USE_LITE_KERNEL(reduce_prod, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(reduce_prod, kARM, kFloat, kNCHW, reduce_prod_i64); -USE_LITE_KERNEL(reduce_prod, kARM, kFloat, kNCHW, int32); -USE_LITE_KERNEL(pad3d, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(cos_sim, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(relu, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(leaky_relu, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(prelu, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(sigmoid, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(tanh, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(relu6, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(thresholded_relu, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(elu, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(polygon_box_transform, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(unfold, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(unfold, kHost, kFloat, kNCHW, def_int32); -USE_LITE_KERNEL(unfold, kHost, kFloat, kNCHW, def_int64); -USE_LITE_KERNEL(unfold, kHost, kInt8, kNCHW, def_int8); -USE_LITE_KERNEL(pixel_shuffle, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(increment, kHost, kAny, kNCHW, def); -USE_LITE_KERNEL(ctc_align, kHost, kInt64, kNCHW, def); -USE_LITE_KERNEL(ctc_align, kHost, kInt32, kNCHW, def); -USE_LITE_KERNEL(instance_norm, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(linspace, kHost, kFloat, kAny, float32); -USE_LITE_KERNEL(linspace, kHost, kInt32, kAny, int32); -USE_LITE_KERNEL(print, kHost, kAny, kAny, def); -USE_LITE_KERNEL(expand, kHost, kAny, kAny, def); -USE_LITE_KERNEL(assign, kHost, kAny, kAny, def); -USE_LITE_KERNEL(assign, kHost, kAny, kAny, def_tensor_array); -USE_LITE_KERNEL(generate_proposals, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(lrn, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(cast, kHost, kAny, kNCHW, def); -USE_LITE_KERNEL(log_softmax, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(beam_search, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(concat, kARM, kAny, kNCHW, def); -USE_LITE_KERNEL(scatter, kARM, kFloat, kNCHW, ids_int64); -USE_LITE_KERNEL(scatter, kARM, kFloat, kNCHW, ids_int32); -USE_LITE_KERNEL(shuffle_channel, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(meshgrid, kHost, kFloat, kAny, float32); -USE_LITE_KERNEL(meshgrid, kHost, kFloat, kAny, int32); -USE_LITE_KERNEL(split_lod_tensor, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(pool2d, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(scale, kARM, kFloat, kNCHW, int32); -USE_LITE_KERNEL(scale, kARM, kFloat, kNCHW, int64); -USE_LITE_KERNEL(scale, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(scale, kARM, kInt32, kNCHW, def); -USE_LITE_KERNEL(scale, kARM, kInt64, kNCHW, def); -USE_LITE_KERNEL(transpose, kARM, kAny, kNCHW, def); -USE_LITE_KERNEL(transpose2, kARM, kAny, kNCHW, def); -USE_LITE_KERNEL(depthwise_conv2d_transpose, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(depthwise_conv2d_transpose, kARM, kInt8, kNCHW, fp32_out); -USE_LITE_KERNEL(depthwise_conv2d_transpose, kARM, kInt8, kNCHW, int8_out); -USE_LITE_KERNEL(grid_sampler, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(axpy, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(tensor_array_to_tensor, kHost, kAny, kNCHW, def); -USE_LITE_KERNEL(merge_lod_tensor, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(reshape, kHost, kAny, kAny, def); -USE_LITE_KERNEL(reshape2, kHost, kAny, kAny, def); -USE_LITE_KERNEL(flatten, kHost, kAny, kAny, def); -USE_LITE_KERNEL(flatten2, kHost, kAny, kAny, def); -USE_LITE_KERNEL(sparse_conv2d, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(sparse_conv2d, kARM, kInt8, kNCHW, int8_fp32_out); -USE_LITE_KERNEL(sparse_conv2d, kARM, kInt8, kNCHW, int8_int8_out); -USE_LITE_KERNEL(lod_reset, kHost, kAny, kNCHW, def); -USE_LITE_KERNEL(expand_as, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(expand_as, kHost, kFloat, kAny, int64); -USE_LITE_KERNEL(calib, kARM, kInt8, kNCHW, fp32_to_int8); -USE_LITE_KERNEL(calib, kARM, kInt32, kNCHW, int32_to_fp32); -USE_LITE_KERNEL(calib, kARM, kInt32, kNCHW, int32_to_int64); -USE_LITE_KERNEL(calib, kARM, kInt32, kNCHW, fp32_to_int32); -USE_LITE_KERNEL(calib, kARM, kInt64, kNCHW, int64_to_fp32); -USE_LITE_KERNEL(calib, kARM, kInt64, kNCHW, fp32_to_int64); -USE_LITE_KERNEL(calib, kARM, kInt8, kNCHW, int8_to_fp32); -USE_LITE_KERNEL(calib, kARM, kInt64, kNCHW, int64_to_int32); -USE_LITE_KERNEL(calib_once, kARM, kInt8, kNCHW, fp32_to_int8); -USE_LITE_KERNEL(calib_once, kARM, kInt8, kNCHW, int8_to_fp32); -USE_LITE_KERNEL(calib_once, kARM, kInt64, kNCHW, int64_to_int32); -USE_LITE_KERNEL(clip, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(select_input, kHost, kAny, kNCHW, def); -USE_LITE_KERNEL(reduce_min, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(reduce_min, kARM, kFloat, kNCHW, def_int64); -USE_LITE_KERNEL(sequence_pad, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(sequence_pad, kHost, kFloat, kNCHW, int32); -USE_LITE_KERNEL(sequence_pad, kHost, kFloat, kNCHW, int64); -USE_LITE_KERNEL(logical_xor, kHost, kAny, kAny, def); -USE_LITE_KERNEL(logical_and, kHost, kAny, kAny, def); -USE_LITE_KERNEL(logical_or, kHost, kAny, kAny, def); -USE_LITE_KERNEL(logical_not, kHost, kAny, kAny, def); -USE_LITE_KERNEL(fill_constant, kHost, kAny, kNCHW, def); -USE_LITE_KERNEL(yolo_box, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(mean, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(collect_fpn_proposals, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(matmul_v2, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(matmul_v2, kARM, kInt8, kNCHW, def); -USE_LITE_KERNEL(inverse, kHost, kFloat, kNCHW, fp32); -USE_LITE_KERNEL(top_k, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(uniform_random, kHost, kAny, kAny, def); -USE_LITE_KERNEL(matmul, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(matmul, kARM, kInt8, kNCHW, def); -USE_LITE_KERNEL(norm, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(p_norm, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(sequence_unpad, kHost, kFloat, kAny, float32); -USE_LITE_KERNEL(sequence_unpad, kHost, kFloat, kAny, int64); -USE_LITE_KERNEL(where_index, kHost, kAny, kAny, def); -USE_LITE_KERNEL(layout, kARM, kFloat, kNCHW, nchw2nhwc); -USE_LITE_KERNEL(layout, kARM, kFloat, kNCHW, nhwc2nchw); -USE_LITE_KERNEL(layout, kARM, kInt8, kNCHW, int8_nchw2nhwc); -USE_LITE_KERNEL(layout, kARM, kInt8, kNCHW, int8_nhwc2nchw); -USE_LITE_KERNEL(layout_once, kARM, kFloat, kNCHW, nchw2nhwc); -USE_LITE_KERNEL(layout_once, kARM, kFloat, kNCHW, nhwc2nchw); -USE_LITE_KERNEL(layout_once, kARM, kInt8, kNCHW, int8_nchw2nhwc); -USE_LITE_KERNEL(layout_once, kARM, kInt8, kNCHW, int8_nhwc2nchw); -USE_LITE_KERNEL(crop, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(crop, kHost, kInt32, kAny, def); -USE_LITE_KERNEL(pad2d, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(argsort, kHost, kFloat, kAny, argsort_fp32); -USE_LITE_KERNEL(argsort, kHost, kFloat, kAny, argsort_int32); -USE_LITE_KERNEL(argsort, kHost, kFloat, kAny, argsort_int64); -USE_LITE_KERNEL(equal, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(equal, kHost, kInt64, kAny, def); -USE_LITE_KERNEL(equal, kHost, kFloat, kAny, int64); -USE_LITE_KERNEL(equal, kHost, kInt32, kAny, def); -USE_LITE_KERNEL(equal, kHost, kFloat, kAny, int32); -USE_LITE_KERNEL(not_equal, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(not_equal, kHost, kFloat, kAny, int32); -USE_LITE_KERNEL(not_equal, kHost, kFloat, kAny, int64); -USE_LITE_KERNEL(less_than, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(less_than, kHost, kInt32, kAny, def); -USE_LITE_KERNEL(less_than, kHost, kFloat, kAny, int32); -USE_LITE_KERNEL(less_than, kHost, kInt64, kAny, def); -USE_LITE_KERNEL(less_than, kHost, kFloat, kAny, int64); -USE_LITE_KERNEL(less_equal, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(less_equal, kHost, kInt64, kAny, def); -USE_LITE_KERNEL(less_equal, kHost, kFloat, kAny, int64); -USE_LITE_KERNEL(less_equal, kHost, kFloat, kAny, int32); -USE_LITE_KERNEL(greater_than, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(greater_than, kHost, kFloat, kAny, def_bool); -USE_LITE_KERNEL(greater_than, kHost, kFloat, kAny, def_int32); -USE_LITE_KERNEL(greater_than, kHost, kInt64, kAny, def); -USE_LITE_KERNEL(greater_than, kHost, kFloat, kAny, def_int64); -USE_LITE_KERNEL(greater_equal, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(greater_equal, kHost, kFloat, kAny, def_int64); -USE_LITE_KERNEL(greater_equal, kHost, kFloat, kAny, def_int32); -USE_LITE_KERNEL(sampling_id, kHost, kAny, kAny, float32); -USE_LITE_KERNEL(pixel_shuffle, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(arg_max, kHost, kAny, kNCHW, fp32); -USE_LITE_KERNEL(arg_max, kHost, kAny, kNCHW, int64); -USE_LITE_KERNEL(arg_max, kHost, kAny, kNCHW, int32); -USE_LITE_KERNEL(arg_max, kHost, kAny, kNCHW, int16); -USE_LITE_KERNEL(arg_max, kHost, kAny, kNCHW, uint8); -USE_LITE_KERNEL(anchor_generator, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(write_back, kHost, kAny, kAny, write_back); -USE_LITE_KERNEL(correlation, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(im2sequence, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(batch_norm, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(sync_batch_norm, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(gather_tree, kHost, kFloat, kAny, int32); -USE_LITE_KERNEL(gather_tree, kHost, kFloat, kAny, int64); -USE_LITE_KERNEL(flatten_contiguous_range, kHost, kAny, kAny, def); -USE_LITE_KERNEL(lookup_table, kARM, kAny, kNCHW, def); -USE_LITE_KERNEL(lookup_table_v2, kARM, kAny, kNCHW, def); -USE_LITE_KERNEL(top_k_v2, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(box_clip, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(box_coder, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(conv2d_transpose, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(conv2d_transpose, kARM, kInt8, kNCHW, fp32_out); -USE_LITE_KERNEL(conv2d_transpose, kARM, kInt8, kNCHW, int8_out); -USE_LITE_KERNEL(unbind, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(unbind, kHost, kFloat, kNCHW, def_int64); -USE_LITE_KERNEL(shape, kHost, kAny, kAny, def); -USE_LITE_KERNEL(bilinear_interp, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(nearest_interp, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(bilinear_interp_v2, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(nearest_interp_v2, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(conv2d, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(depthwise_conv2d, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(conv2d, kARM, kInt8, kNCHW, int8_out); -USE_LITE_KERNEL(conv2d, kARM, kInt8, kNCHW, fp32_out); -USE_LITE_KERNEL(depthwise_conv2d, kARM, kInt8, kNCHW, int8_out); -USE_LITE_KERNEL(depthwise_conv2d, kARM, kInt8, kNCHW, fp32_out); -USE_LITE_KERNEL(reduce_max, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(reduce_max, kARM, kFloat, kNCHW, i64); -USE_LITE_KERNEL(index_select, kHost, kAny, kNCHW, fp32); -USE_LITE_KERNEL(index_select, kHost, kAny, kNCHW, int32); -USE_LITE_KERNEL(index_select, kHost, kAny, kNCHW, int16); -USE_LITE_KERNEL(index_select, kHost, kAny, kNCHW, int8); -USE_LITE_KERNEL(affine_grid, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(sequence_pool, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(rnn, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(negative, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(gru_unit, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(fetch, kHost, kAny, kAny, def); -USE_LITE_KERNEL(density_prior_box, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(scatter_nd_add, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(scatter_nd_add, kHost, kFloat, kNCHW, float32_int64); -USE_LITE_KERNEL(scatter_nd_add, kHost, kFloat, kNCHW, int32_int32); -USE_LITE_KERNEL(scatter_nd_add, kHost, kFloat, kNCHW, int32_int64); -USE_LITE_KERNEL(scatter_nd_add, kHost, kFloat, kNCHW, int64_int32); -USE_LITE_KERNEL(scatter_nd_add, kHost, kFloat, kNCHW, int64_int64); -USE_LITE_KERNEL(roi_perspective_transform, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(while, kHost, kAny, kAny, def); -USE_LITE_KERNEL(strided_slice, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(strided_slice, kHost, kFloat, kNCHW, def_int32); -USE_LITE_KERNEL(strided_slice, kHost, kFloat, kNCHW, def_int64); -USE_LITE_KERNEL(multiclass_nms, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(multiclass_nms2, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(multiclass_nms3, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(mul, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(mul, kARM, kInt8, kNCHW, def); -USE_LITE_KERNEL(gather, kHost, kFloat, kNCHW, int32int32); -USE_LITE_KERNEL(gather, kHost, kFloat, kNCHW, int64int64); -USE_LITE_KERNEL(gather, kHost, kFloat, kNCHW, int64int32); -USE_LITE_KERNEL(gather, kHost, kFloat, kNCHW, int32int64); -USE_LITE_KERNEL(sequence_softmax, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(tile, kHost, kFloat, kNCHW, def_float); -USE_LITE_KERNEL(tile, kHost, kFloat, kNCHW, def_int32); -USE_LITE_KERNEL(tile, kHost, kFloat, kNCHW, def_int64); -USE_LITE_KERNEL(tile, kHost, kFloat, kNCHW, def_int8); -USE_LITE_KERNEL(tile, kHost, kFloat, kNCHW, def_bool); -USE_LITE_KERNEL(decode_bboxes, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(slice, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(slice, kARM, kFloat, kNCHW, array_def); -USE_LITE_KERNEL(slice, kARM, kFloat, kNCHW, float_i64_starts_ends); -USE_LITE_KERNEL(slice, kARM, kFloat, kNCHW, array_float_i64_starts_ends); -USE_LITE_KERNEL(slice, kARM, kFloat, kNCHW, bool_slice); -USE_LITE_KERNEL(slice, kARM, kFloat, kNCHW, array_bool_slice); -USE_LITE_KERNEL(slice, kARM, kFloat, kNCHW, int32_slice); -USE_LITE_KERNEL(slice, kARM, kFloat, kNCHW, array_int32_slice); -USE_LITE_KERNEL(slice, kARM, kFloat, kNCHW, def_int64); -USE_LITE_KERNEL(slice, kARM, kFloat, kNCHW, array_def_int64); -USE_LITE_KERNEL(dropout, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(fill_any_like, kHost, kAny, kNCHW, def); -USE_LITE_KERNEL(fill_zeros_like, kHost, kAny, kNCHW, def); -USE_LITE_KERNEL(max_pool2d_with_index, kHost, kFloat, kNCHW, fp32); -USE_LITE_KERNEL(pad2d, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(deformable_conv, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(reduce_sum, kARM, kFloat, kNCHW, def_int32); -USE_LITE_KERNEL(reduce_sum, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(expand_v2, kHost, kFloat, kAny, def); -USE_LITE_KERNEL(expand_v2, kHost, kFloat, kAny, def_int32); -USE_LITE_KERNEL(expand_v2, kHost, kFloat, kAny, def_int64); -USE_LITE_KERNEL(affine_channel, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(crf_decoding, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(cumsum, kHost, kFloat, kAny, float32); -USE_LITE_KERNEL(cumsum, kHost, kFloat, kAny, int32); -USE_LITE_KERNEL(cumsum, kHost, kFloat, kAny, int64); -USE_LITE_KERNEL(lookup_table_dequant, kARM, kAny, kNCHW, def); -USE_LITE_KERNEL(box_coder, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(sin, kHost, kFloat, kNCHW, def); -USE_LITE_KERNEL(fc, kARM, kFloat, kNCHW, def); -USE_LITE_KERNEL(fc, kARM, kInt8, kNCHW, int8out); -USE_LITE_KERNEL(fc, kARM, kInt8, kNCHW, fp32out); -USE_LITE_KERNEL(retinanet_detection_output, kHost, kFloat, kNCHW, def); \ No newline at end of file diff --git a/libs/paddleocr/PaddleLite/cxx/include/paddle_use_ops.h b/libs/paddleocr/PaddleLite/cxx/include/paddle_use_ops.h deleted file mode 100644 index fcd79024..00000000 --- a/libs/paddleocr/PaddleLite/cxx/include/paddle_use_ops.h +++ /dev/null @@ -1,284 +0,0 @@ -#pragma once -#include "paddle_lite_factory_helper.h" - -USE_LITE_OP(__xpu__logit); -USE_LITE_OP(mean); -USE_LITE_OP(uniform_random); -USE_LITE_OP(equal); -USE_LITE_OP(not_equal); -USE_LITE_OP(less_than); -USE_LITE_OP(less_equal); -USE_LITE_OP(greater_than); -USE_LITE_OP(greater_equal); -USE_LITE_OP(fake_quantize_moving_average_abs_max); -USE_LITE_OP(matrix_nms); -USE_LITE_OP(lrn); -USE_LITE_OP(axpy); -USE_LITE_OP(inverse); -USE_LITE_OP(scatter); -USE_LITE_OP(__xpu__multi_encoder); -USE_LITE_OP(gaussian_random); -USE_LITE_OP(affine_grid); -USE_LITE_OP(roi_align); -USE_LITE_OP(range); -USE_LITE_OP(sequence_topk_avg_pooling); -USE_LITE_OP(search_group_padding); -USE_LITE_OP(__xpu__embedding_with_eltwise_add); -USE_LITE_OP(fake_dequantize_max_abs); -USE_LITE_OP(strided_slice); -USE_LITE_OP(lookup_table_dequant); -USE_LITE_OP(sum); -USE_LITE_OP(tile); -USE_LITE_OP(fake_quantize_dequantize_moving_average_abs_max); -USE_LITE_OP(search_grnn); -USE_LITE_OP(density_prior_box); -USE_LITE_OP(atan); -USE_LITE_OP(lstm); -USE_LITE_OP(fc); -USE_LITE_OP(im2sequence); -USE_LITE_OP(__xpu__softmax_topk); -USE_LITE_OP(multiclass_nms); -USE_LITE_OP(multiclass_nms2); -USE_LITE_OP(multiclass_nms3); -USE_LITE_OP(box_coder); -USE_LITE_OP(sequence_reshape); -USE_LITE_OP(sequence_conv); -USE_LITE_OP(deformable_conv); -USE_LITE_OP(search_aligned_mat_mul); -USE_LITE_OP(search_fc); -USE_LITE_OP(pad3d); -USE_LITE_OP(dropout); -USE_LITE_OP(calib); -USE_LITE_OP(instance_norm); -USE_LITE_OP(nearest_interp); -USE_LITE_OP(bilinear_interp); -USE_LITE_OP(stack); -USE_LITE_OP(search_seq_depadding); -USE_LITE_OP(cumsum); -USE_LITE_OP(gather); -USE_LITE_OP(sequence_unpad); -USE_LITE_OP(pool2d); -USE_LITE_OP(search_seq_softmax); -USE_LITE_OP(feed); -USE_LITE_OP(generate_proposals_v2); -USE_LITE_OP(calib_once); -USE_LITE_OP(pow); -USE_LITE_OP(unstack); -USE_LITE_OP(flip); -USE_LITE_OP(lod_reset); -USE_LITE_OP(beam_search_decode); -USE_LITE_OP(io_copy_once); -USE_LITE_OP(negative); -USE_LITE_OP(tan); -USE_LITE_OP(beam_search); -USE_LITE_OP(scatter_nd_add); -USE_LITE_OP(expand); -USE_LITE_OP(affine_channel); -USE_LITE_OP(sequence_mask); -USE_LITE_OP(argsort); -USE_LITE_OP(top_k); -USE_LITE_OP(__xpu__fc); -USE_LITE_OP(fill_constant_batch_size_like); -USE_LITE_OP(unsqueeze); -USE_LITE_OP(unsqueeze2); -USE_LITE_OP(split); -USE_LITE_OP(attention_padding_mask); -USE_LITE_OP(search_attention_padding_mask); -USE_LITE_OP(fake_quantize_range_abs_max); -USE_LITE_OP(fake_quantize_abs_max); -USE_LITE_OP(__xpu__multi_softmax); -USE_LITE_OP(one_hot); -USE_LITE_OP(max_pool2d_with_index); -USE_LITE_OP(sin); -USE_LITE_OP(while); -USE_LITE_OP(ctc_align); -USE_LITE_OP(reshape); -USE_LITE_OP(reshape2); -USE_LITE_OP(sequence_concat); -USE_LITE_OP(fill_constant); -USE_LITE_OP(flatten); -USE_LITE_OP(flatten2); -USE_LITE_OP(flatten_contiguous_range); -USE_LITE_OP(is_empty); -USE_LITE_OP(retinanet_detection_output); -USE_LITE_OP(elementwise_sub); -USE_LITE_OP(elementwise_add); -USE_LITE_OP(elementwise_mul); -USE_LITE_OP(elementwise_max); -USE_LITE_OP(elementwise_min); -USE_LITE_OP(elementwise_div); -USE_LITE_OP(elementwise_floordiv); -USE_LITE_OP(elementwise_mod); -USE_LITE_OP(elementwise_pow); -USE_LITE_OP(sequence_softmax); -USE_LITE_OP(reduce_sum); -USE_LITE_OP(reduce_prod); -USE_LITE_OP(reduce_max); -USE_LITE_OP(reduce_min); -USE_LITE_OP(reduce_all); -USE_LITE_OP(reduce_any); -USE_LITE_OP(reduce_mean); -USE_LITE_OP(__xpu__conv2d); -USE_LITE_OP(lod_array_length); -USE_LITE_OP(var_conv_2d); -USE_LITE_OP(print); -USE_LITE_OP(shuffle_channel); -USE_LITE_OP(square); -USE_LITE_OP(relu_clipped); -USE_LITE_OP(swish); -USE_LITE_OP(log); -USE_LITE_OP(exp); -USE_LITE_OP(abs); -USE_LITE_OP(floor); -USE_LITE_OP(hard_sigmoid); -USE_LITE_OP(sqrt); -USE_LITE_OP(rsqrt); -USE_LITE_OP(softsign); -USE_LITE_OP(gelu); -USE_LITE_OP(hard_swish); -USE_LITE_OP(reciprocal); -USE_LITE_OP(mish); -USE_LITE_OP(sigmoid); -USE_LITE_OP(tanh); -USE_LITE_OP(relu); -USE_LITE_OP(leaky_relu); -USE_LITE_OP(relu6); -USE_LITE_OP(prelu); -USE_LITE_OP(thresholded_relu); -USE_LITE_OP(elu); -USE_LITE_OP(erf); -USE_LITE_OP(softplus); -USE_LITE_OP(fusion_elementwise_sub_activation); -USE_LITE_OP(fusion_elementwise_add_activation); -USE_LITE_OP(fusion_elementwise_mul_activation); -USE_LITE_OP(fusion_elementwise_max_activation); -USE_LITE_OP(fusion_elementwise_min_activation); -USE_LITE_OP(fusion_elementwise_div_activation); -USE_LITE_OP(assign); -USE_LITE_OP(correlation); -USE_LITE_OP(arg_max); -USE_LITE_OP(sign); -USE_LITE_OP(read_from_array); -USE_LITE_OP(logical_xor); -USE_LITE_OP(logical_and); -USE_LITE_OP(logical_or); -USE_LITE_OP(logical_not); -USE_LITE_OP(box_clip); -USE_LITE_OP(dequantize_linear); -USE_LITE_OP(softmax); -USE_LITE_OP(__xpu__resnet50); -USE_LITE_OP(transpose); -USE_LITE_OP(transpose2); -USE_LITE_OP(tensor_array_to_tensor); -USE_LITE_OP(io_copy); -USE_LITE_OP(sparse_conv2d); -USE_LITE_OP(gather_tree); -USE_LITE_OP(fake_channel_wise_quantize_dequantize_abs_max); -USE_LITE_OP(increment); -USE_LITE_OP(batch_norm); -USE_LITE_OP(sync_batch_norm); -USE_LITE_OP(pad2d); -USE_LITE_OP(lookup_table_v2); -USE_LITE_OP(unbind); -USE_LITE_OP(distribute_fpn_proposals); -USE_LITE_OP(fake_quantize_dequantize_abs_max); -USE_LITE_OP(sampling_id); -USE_LITE_OP(fpga_conv2d); -USE_LITE_OP(index_select); -USE_LITE_OP(match_matrix_tensor); -USE_LITE_OP(where_index); -USE_LITE_OP(sequence_expand_as); -USE_LITE_OP(acos); -USE_LITE_OP(one_hot_v2); -USE_LITE_OP(search_seq_fc); -USE_LITE_OP(expand_v2); -USE_LITE_OP(topk_pooling); -USE_LITE_OP(squeeze); -USE_LITE_OP(squeeze2); -USE_LITE_OP(sequence_reverse_embedding); -USE_LITE_OP(assign_value); -USE_LITE_OP(log_softmax); -USE_LITE_OP(reverse); -USE_LITE_OP(grid_sampler); -USE_LITE_OP(bilinear_interp_v2); -USE_LITE_OP(nearest_interp_v2); -USE_LITE_OP(fill_zeros_like); -USE_LITE_OP(sequence_pad); -USE_LITE_OP(cos_sim); -USE_LITE_OP(layout_once); -USE_LITE_OP(subgraph); -USE_LITE_OP(gru_unit); -USE_LITE_OP(unfold); -USE_LITE_OP(slice); -USE_LITE_OP(split_lod_tensor); -USE_LITE_OP(concat); -USE_LITE_OP(anchor_generator); -USE_LITE_OP(tril_triu); -USE_LITE_OP(conditional_block); -USE_LITE_OP(sequence_arithmetic); -USE_LITE_OP(search_seq_arithmetic); -USE_LITE_OP(unique_with_counts); -USE_LITE_OP(group_norm); -USE_LITE_OP(yolo_box); -USE_LITE_OP(shape); -USE_LITE_OP(matmul_v2); -USE_LITE_OP(sequence_expand); -USE_LITE_OP(cos); -USE_LITE_OP(crop); -USE_LITE_OP(layer_norm); -USE_LITE_OP(asin); -USE_LITE_OP(sequence_reverse); -USE_LITE_OP(fetch); -USE_LITE_OP(linspace); -USE_LITE_OP(fake_channel_wise_dequantize_max_abs); -USE_LITE_OP(rnn); -USE_LITE_OP(__xpu__mmdnn_bid_emb_grnn_att); -USE_LITE_OP(__xpu__mmdnn_bid_emb_grnn_att2); -USE_LITE_OP(__xpu__mmdnn_bid_emb_att); -USE_LITE_OP(__xpu__mmdnn_match_conv_topk); -USE_LITE_OP(__xpu__mmdnn_merge_all); -USE_LITE_OP(write_to_array); -USE_LITE_OP(write_back); -USE_LITE_OP(__xpu__sfa_head); -USE_LITE_OP(collect_fpn_proposals); -USE_LITE_OP(pixel_shuffle); -USE_LITE_OP(generate_proposals); -USE_LITE_OP(where); -USE_LITE_OP(lookup_table); -USE_LITE_OP(prior_box); -USE_LITE_OP(sequence_pool_concat); -USE_LITE_OP(conv2d); -USE_LITE_OP(conv3d); -USE_LITE_OP(depthwise_conv2d); -USE_LITE_OP(polygon_box_transform); -USE_LITE_OP(scale); -USE_LITE_OP(roi_perspective_transform); -USE_LITE_OP(crop_tensor); -USE_LITE_OP(gather_nd); -USE_LITE_OP(fill_any_like); -USE_LITE_OP(cast); -USE_LITE_OP(mul); -USE_LITE_OP(quantize_linear); -USE_LITE_OP(gru); -USE_LITE_OP(meshgrid); -USE_LITE_OP(__xpu__mmdnn_search_attention); -USE_LITE_OP(__xpu__mmdnn_search_attention2); -USE_LITE_OP(__xpu__generate_sequence); -USE_LITE_OP(__xpu__squeeze_excitation_block); -USE_LITE_OP(decode_bboxes); -USE_LITE_OP(matmul); -USE_LITE_OP(__xpu__resnet_cbam); -USE_LITE_OP(clip); -USE_LITE_OP(top_k_v2); -USE_LITE_OP(__xpu__dynamic_lstm_fuse_op); -USE_LITE_OP(norm); -USE_LITE_OP(p_norm); -USE_LITE_OP(crf_decoding); -USE_LITE_OP(layout); -USE_LITE_OP(sequence_pool); -USE_LITE_OP(__xpu__bigru); -USE_LITE_OP(select_input); -USE_LITE_OP(conv2d_transpose); -USE_LITE_OP(depthwise_conv2d_transpose); -USE_LITE_OP(merge_lod_tensor); -USE_LITE_OP(expand_as); \ No newline at end of file diff --git a/libs/paddleocr/PaddleLite/cxx/include/paddle_use_passes.h b/libs/paddleocr/PaddleLite/cxx/include/paddle_use_passes.h deleted file mode 100644 index 26457cc3..00000000 --- a/libs/paddleocr/PaddleLite/cxx/include/paddle_use_passes.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. -// -// 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. - -#pragma once -#include "paddle_lite_factory_helper.h" // NOLINT - -USE_MIR_PASS(demo); -USE_MIR_PASS(static_kernel_pick_pass); -USE_MIR_PASS(lite_unsqueeze2_pad3d_squeeze2_fuse_pass); -USE_MIR_PASS(op_transformation_pass); -USE_MIR_PASS(variable_place_inference_pass); -USE_MIR_PASS(type_target_cast_pass); -USE_MIR_PASS(__fpga_kernel_place_correct_pass); -USE_MIR_PASS(opencl_kernel_place_correct_pass); -USE_MIR_PASS(generate_program_pass); - -USE_MIR_PASS(io_copy_kernel_pick_pass); -USE_MIR_PASS(argument_type_display_pass); -USE_MIR_PASS(runtime_context_assign_pass); -USE_MIR_PASS(graph_visualize_pass); - -USE_MIR_PASS(sparse_conv_detect_pass); -USE_MIR_PASS(adaptive_1x1_pool2d_convert_global_pass); -USE_MIR_PASS(remove_scale1_pass); -USE_MIR_PASS(remove_tf_redundant_ops_pass); -USE_MIR_PASS(lite_conv_bn_fuse_pass); -USE_MIR_PASS(lite_conv_conv_fuse_pass); -USE_MIR_PASS(lite_squeeze2_matmul_fuse_pass); -USE_MIR_PASS(lite_reshape2_matmul_fuse_pass); -USE_MIR_PASS(lite_matmul_fuse_pass); -USE_MIR_PASS(lite_fc_fuse_pass); -USE_MIR_PASS(lite_matmul_element_add_fuse_pass); -USE_MIR_PASS(lite_shuffle_channel_fuse_pass); -USE_MIR_PASS(lite_transpose_softmax_transpose_fuse_pass); -USE_MIR_PASS(lite_interpolate_fuse_pass); -USE_MIR_PASS(lite_sequence_pool_concat_fuse_pass); -USE_MIR_PASS(identity_scale_eliminate_pass); -USE_MIR_PASS(identity_dropout_eliminate_pass); -USE_MIR_PASS(lite_conv_elementwise_fuse_pass); -USE_MIR_PASS(lite_conv_activation_fuse_pass); -USE_MIR_PASS(lite_var_conv_2d_activation_fuse_pass); -USE_MIR_PASS(lite_match_matrix_activation_fuse_pass); -USE_MIR_PASS(lite_scales_fuse_pass); -USE_MIR_PASS(lite_scaleacts_fuse_pass); -USE_MIR_PASS(lite_sequence_reverse_embedding_fuse_pass); -USE_MIR_PASS(lite_elementwise_activation_fuse_pass); -USE_MIR_PASS(lite_elementwise_scale_fuse_pass); -USE_MIR_PASS(lite_conv_scale_fuse_pass); -USE_MIR_PASS(lite_conv_elementwise_tree_fuse_pass); -USE_MIR_PASS(lite_quant_dequant_fuse_pass); -USE_MIR_PASS(type_precision_cast_pass); -USE_MIR_PASS(type_layout_cast_pass); -USE_MIR_PASS(type_layout_cast_preprocess_pass); -USE_MIR_PASS(memory_optimize_pass); -USE_MIR_PASS(xpu_memory_optimize_pass); -USE_MIR_PASS(lite_inplace_fuse_pass); -USE_MIR_PASS(multi_stream_analysis_pass); -USE_MIR_PASS(elementwise_mul_constant_eliminate_pass); -USE_MIR_PASS(npu_subgraph_pass); -USE_MIR_PASS(nnadapter_subgraph_pass); -USE_MIR_PASS(mlu_subgraph_pass); -USE_MIR_PASS(mlu_postprocess_pass); -USE_MIR_PASS(weight_quantization_preprocess_pass); -USE_MIR_PASS(post_quant_dynamic_pass); -USE_MIR_PASS(fp16_attribute_pass); -USE_MIR_PASS(fpga_concat_fuse_pass); -USE_MIR_PASS(quantization_parameters_propagation_pass); -USE_MIR_PASS(quantization_parameters_removal_pass); -USE_MIR_PASS(restrict_quantized_op_with_same_input_output_scale_pass); -USE_MIR_PASS(control_flow_op_unused_inputs_and_outputs_eliminate_pass); -USE_MIR_PASS(control_flow_op_shared_inputs_and_outputs_place_sync_pass); -USE_MIR_PASS(lite_scale_activation_fuse_pass); -USE_MIR_PASS(lite_instance_norm_activation_fuse_pass); -USE_MIR_PASS(ssd_boxes_calc_offline_pass); -USE_MIR_PASS(fix_mismatched_precision_pass); -USE_MIR_PASS(lite_flatten_fc_fuse_pass); -USE_MIR_PASS(lite_fc_prelu_fuse_pass); -USE_MIR_PASS(lite_greater_than_cast_fuse_pass); -USE_MIR_PASS(assign_value_calc_offline_pass); -USE_MIR_PASS(__xpu__graph_dedup_pass); -USE_MIR_PASS(__xpu__resnet_fuse_pass); -USE_MIR_PASS(__xpu__resnet_cbam_fuse_pass); -USE_MIR_PASS(__xpu__multi_encoder_fuse_pass); -USE_MIR_PASS(__xpu__embedding_with_eltwise_add_fuse_pass); -USE_MIR_PASS(__xpu__fc_fuse_pass); -USE_MIR_PASS(__xpu__mmdnn_fuse_pass); -USE_MIR_PASS(__xpu__conv2d_affine_channel_fuse_pass); -USE_MIR_PASS(__xpu__conv2d_fuse_pass); -USE_MIR_PASS(__xpu__sfa_head_meanstd_fuse_pass); -USE_MIR_PASS(__xpu__sfa_head_moment_fuse_pass); -USE_MIR_PASS(__xpu__softmax_topk_fuse_pass); -USE_MIR_PASS(__xpu__multi_encoder_adaptive_seqlen_fuse_pass); -USE_MIR_PASS(__xpu__multi_encoder_slice_link_fuse_pass); -USE_MIR_PASS(__xpu__generate_sequence_fuse_pass); -USE_MIR_PASS(__xpu__logit_fuse_pass); -USE_MIR_PASS(__xpu__link_previous_out_max_pass); -USE_MIR_PASS(__xpu__squeeze_excitation_fuse_pass); -USE_MIR_PASS(__xpu__bigru_fuse_pass); -USE_MIR_PASS(__xpu__dynamic_lstm_fuse_pass); -USE_MIR_PASS(__xpu__multi_softmax_fuse_pass); -USE_MIR_PASS(__xpu__max_pooling_pad_zero_detect_fuse_pass); -USE_MIR_PASS(x86_int8_attribute_pass); -USE_MIR_PASS(fill_range_fuse_pass); -USE_MIR_PASS(range_calc_offline_pass); -USE_MIR_PASS(p_norm_fill_constant_max_div_fuse_pass); -USE_MIR_PASS(fill_constant_calc_offline_pass); -USE_MIR_PASS(unsqueeze_calc_offline_pass); -USE_MIR_PASS(scale_calc_offline_pass); -USE_MIR_PASS(keepdims_convert_pass); diff --git a/libs/paddleocr/PaddleLite/cxx/libs/arm64-v8a/libc++_shared.so b/libs/paddleocr/PaddleLite/cxx/libs/arm64-v8a/libc++_shared.so deleted file mode 100644 index 5b9a9cff..00000000 Binary files a/libs/paddleocr/PaddleLite/cxx/libs/arm64-v8a/libc++_shared.so and /dev/null differ diff --git a/libs/paddleocr/PaddleLite/cxx/libs/arm64-v8a/libpaddle_api_light_bundled.a b/libs/paddleocr/PaddleLite/cxx/libs/arm64-v8a/libpaddle_api_light_bundled.a deleted file mode 100644 index 7246fbda..00000000 Binary files a/libs/paddleocr/PaddleLite/cxx/libs/arm64-v8a/libpaddle_api_light_bundled.a and /dev/null differ diff --git a/libs/paddleocr/PaddleLite/cxx/libs/arm64-v8a/libpaddle_light_api_shared.so b/libs/paddleocr/PaddleLite/cxx/libs/arm64-v8a/libpaddle_light_api_shared.so deleted file mode 100644 index aa47ede6..00000000 Binary files a/libs/paddleocr/PaddleLite/cxx/libs/arm64-v8a/libpaddle_light_api_shared.so and /dev/null differ diff --git a/libs/paddleocr/PaddleLite/cxx/libs/armeabi-v7a/libc++_shared.so b/libs/paddleocr/PaddleLite/cxx/libs/armeabi-v7a/libc++_shared.so deleted file mode 100644 index 4cedc793..00000000 Binary files a/libs/paddleocr/PaddleLite/cxx/libs/armeabi-v7a/libc++_shared.so and /dev/null differ diff --git a/libs/paddleocr/PaddleLite/cxx/libs/armeabi-v7a/libpaddle_api_light_bundled.a b/libs/paddleocr/PaddleLite/cxx/libs/armeabi-v7a/libpaddle_api_light_bundled.a deleted file mode 100644 index bfa3f1e8..00000000 Binary files a/libs/paddleocr/PaddleLite/cxx/libs/armeabi-v7a/libpaddle_api_light_bundled.a and /dev/null differ diff --git a/libs/paddleocr/PaddleLite/cxx/libs/armeabi-v7a/libpaddle_light_api_shared.so b/libs/paddleocr/PaddleLite/cxx/libs/armeabi-v7a/libpaddle_light_api_shared.so deleted file mode 100644 index 9f25eeed..00000000 Binary files a/libs/paddleocr/PaddleLite/cxx/libs/armeabi-v7a/libpaddle_light_api_shared.so and /dev/null differ diff --git a/libs/paddleocr/PaddleLite/java/libs/arm64-v8a/libpaddle_lite_jni.so b/libs/paddleocr/PaddleLite/java/libs/arm64-v8a/libpaddle_lite_jni.so deleted file mode 100644 index 81fff120..00000000 Binary files a/libs/paddleocr/PaddleLite/java/libs/arm64-v8a/libpaddle_lite_jni.so and /dev/null differ diff --git a/libs/paddleocr/PaddleLite/java/libs/armeabi-v7a/libpaddle_lite_jni.so b/libs/paddleocr/PaddleLite/java/libs/armeabi-v7a/libpaddle_lite_jni.so deleted file mode 100644 index feb37582..00000000 Binary files a/libs/paddleocr/PaddleLite/java/libs/armeabi-v7a/libpaddle_lite_jni.so and /dev/null differ diff --git a/libs/paddleocr/build.gradle.kts b/libs/paddleocr/build.gradle.kts deleted file mode 100644 index 0c65a918..00000000 --- a/libs/paddleocr/build.gradle.kts +++ /dev/null @@ -1,169 +0,0 @@ -/** - * Paddle OCR (https://github.com/PaddlePaddle/PaddleOCR) build script (Kotlin DSL). - * - * Created by TonyJiangWJ (https://github.com/TonyJiangWJ) on Aug 7, 2023. - * Modified by TonyJiangWJ (https://github.com/TonyJiangWJ) as of Aug 11, 2023. - * Modified by SuperMonster003 as of Sep 4, 2023. - * Transformed by SuperMonster003 on Sep 30, 2025. - */ - -plugins { - id("org.autojs.build.utils") - id("org.autojs.build.properties") - id("org.autojs.build.jvm-convention") - id("com.android.library") - id("org.jetbrains.kotlin.android") -} - -ext { - set("projectName", "Paddle OCR") -} - -val versionMap = mapOf( - "MIN_SDK" to props["MIN_SDK"].toInt(), - "COMPILE_SDK" to props["COMPILE_SDK"].toInt(), - "TARGET_SDK" to props["TARGET_SDK"].toInt(), - "NDK" to props["PADDLE_OCR/NDK"], - "CMAKE" to props["PADDLE_OCR/CMAKE"], - "OPENCV" to props["PADDLE_OCR/OPENCV"], -) - -val nameMap = mapOf( - "PROJECT" to extensions.extraProperties.get("projectName") as String, - "OPENCV" to "OpenCV", - "NDK" to "NDK", - "CMAKE" to "Cmake", -) - -val libsToDeploy = listOf( - // @Hint by TonyJiangWJ (https://github.com/TonyJiangWJ) on Aug 7, 2023. - // ! 下载 OpenCV 源码包 (默认为 4.2.0). - // ! 和 Auto.js 中的版本 (如 4.8.0) 不匹配会产生冲突, - // ! 可按需修改 version.properties 中对应内容. - // ! en-US (translated by SuperMonster003 on Oct 22, 2024): - // ! Download the archive for source code of OpenCV (defaults to 4.2.0). - // ! Not matching the version in Auto.js (e.g., 4.8.0) will cause conflicts. - // ! Adjust the corresponding content in version.properties as needed. - utils.newLibDeployer( - project, - nameMap["OPENCV"] as String, - "https://github.com/opencv/opencv/releases/download/${versionMap["OPENCV"]}/opencv-${versionMap["OPENCV"]}-android-sdk.zip", - ).apply { - setSourceDir("/OpenCV-android-sdk/sdk/native/") - setDestDir("/src/sdk/native/") - } -) - -val argsMap = mapOf( - // @Hint by LZX284 (https://github.com/LZX284) on Sep 30, 2023. - // ! "ANDROID_PLATFORM" 默认为 "android-23", 这里修改为与 AutoJs6 最低 SDK 版本一致的 `versionMap.MIN_SDK`. - // ! en-US (translated by SuperMonster003 on Oct 22, 2024): - // ! "ANDROID_PLATFORM" with default value "android-23" was changed to `versionMap.MIN_SDK` - // ! to align with the min SDK version of AutoJs6. - "ANDROID_PLATFORM" to "android-${versionMap["MIN_SDK"]}", - "ANDROID_STL" to "c++_shared", - "ANDROID_ARM_NEON" to "TRUE", -) - -// @Hint by SuperMonster003 on Nov 12, 2023. -// ! Do not add a space (nbsp) after "-D". -// ! Reference: https://stackoverflow.com/questions/14887438/spacing-in-d-option-in-cmake -// ! zh-CN: -// ! 在 "-D" 后不要添加空格 (不间断空格). -// ! 参阅: https://stackoverflow.com/questions/14887438/spacing-in-d-option-in-cmake -val args = argsMap.entries.map { (k, v) -> "-D$k=$v" } - -utils.configureLibraryLifecycleHooks( - project, - nameMap["PROJECT"] as String, - listOf("OPENCV", "NDK", "CMAKE").map { "${nameMap[it]}: ${versionMap[it]}" }, - libsToDeploy, - "isCleanupPaddleOcr", - listOf(".cxx") -) - -android { - namespace = "com.baidu.paddle.lite.ocr" - - ndkVersion = versionMap["NDK"] as String - compileSdk = versionMap["COMPILE_SDK"] as Int - - defaultConfig { - minSdk = versionMap["MIN_SDK"] as Int - - externalNativeBuild { - cmake { - val cppFlagsMap = mapOf( - "-std" to "c++11" - ) - val cppListFlags = mapOf( - "-f" to listOf("rtti", "exceptions"), - "-W" to "no-format" - ) - - // 组装等价于 Groovy 脚本中的拼接逻辑 - val cppFlagsJoined = buildString { - append( - cppFlagsMap.entries.joinToString(" ") { (k, v) -> "$k=$v" } - ) - append(" ") - append( - cppListFlags.entries.joinToString(" ") { (k, v) -> - when (v) { - is List<*> -> v.joinToString(" ") { opt -> k + opt } - else -> "$k$v" - } - } - ) - }.trim() - - cppFlags += cppFlagsJoined - arguments += args - } - } - - ndk { - // @Hint by SuperMonster003 on Jan 2, 2024. - // ! Supported architectures: arm-v7, arm-v8. - // ! References: - // ! https://github.com/PaddlePaddle/Paddle-Lite/blob/develop/lite/tools/build_android.sh#L7 - // ! https://github.com/PaddlePaddle/Paddle-Lite/issues/80 - // ! zh-CN: - // ! 支持的架构: arm-v7, arm-v8. - // ! 参阅: - // ! https://github.com/PaddlePaddle/Paddle-Lite/blob/develop/lite/tools/build_android.sh#L7 - // ! https://github.com/PaddlePaddle/Paddle-Lite/issues/80 - // noinspection ChromeOsAbiSupport - abiFilters += listOf("arm64-v8a", "armeabi-v7a") - @Suppress("DEPRECATION") - ldLibs?.add("jnigraphics") - } - } - - buildTypes { - release { - isMinifyEnabled = false - } - debug { - isMinifyEnabled = false - } - } - - externalNativeBuild { - cmake { - path = file("src/main/cpp/CMakeLists.txt") - version = versionMap["CMAKE"] as String - } - } - - lint { - targetSdk = versionMap["TARGET_SDK"] as Int - } -} - -dependencies { - implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs"))) - implementation(project(mapOf("path" to ":libs:org-opencv-${versionMap["OPENCV"]}".replace(".", "_")))) - implementation(libs.core.ktx) - implementation(libs.preference.ktx) -} \ No newline at end of file diff --git a/libs/paddleocr/proguard-rules.pro b/libs/paddleocr/proguard-rules.pro deleted file mode 100644 index ff59496d..00000000 --- a/libs/paddleocr/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/libs/paddleocr/src/main/AndroidManifest.xml b/libs/paddleocr/src/main/AndroidManifest.xml deleted file mode 100644 index 568741e5..00000000 --- a/libs/paddleocr/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/libs/paddleocr/src/main/assets/labels/ppocr_keys_v1.txt b/libs/paddleocr/src/main/assets/labels/ppocr_keys_v1.txt deleted file mode 100644 index 84b885d8..00000000 --- a/libs/paddleocr/src/main/assets/labels/ppocr_keys_v1.txt +++ /dev/null @@ -1,6623 +0,0 @@ -' -疗 -绚 -诚 -娇 -溜 -题 -贿 -者 -廖 -更 -纳 -加 -奉 -公 -一 -就 -汴 -计 -与 -路 -房 -原 -妇 -2 -0 -8 -- -7 -其 -> -: -] -, -, -骑 -刈 -全 -消 -昏 -傈 -安 -久 -钟 -嗅 -不 -影 -处 -驽 -蜿 -资 -关 -椤 -地 -瘸 -专 -问 -忖 -票 -嫉 -炎 -韵 -要 -月 -田 -节 -陂 -鄙 -捌 -备 -拳 -伺 -眼 -网 -盎 -大 -傍 -心 -东 -愉 -汇 -蹿 -科 -每 -业 -里 -航 -晏 -字 -平 -录 -先 -1 -3 -彤 -鲶 -产 -稍 -督 -腴 -有 -象 -岳 -注 -绍 -在 -泺 -文 -定 -核 -名 -水 -过 -理 -让 -偷 -率 -等 -这 -发 -” -为 -含 -肥 -酉 -相 -鄱 -七 -编 -猥 -锛 -日 -镀 -蒂 -掰 -倒 -辆 -栾 -栗 -综 -涩 -州 -雌 -滑 -馀 -了 -机 -块 -司 -宰 -甙 -兴 -矽 -抚 -保 -用 -沧 -秩 -如 -收 -息 -滥 -页 -疑 -埠 -! -! -姥 -异 -橹 -钇 -向 -下 -跄 -的 -椴 -沫 -国 -绥 -獠 -报 -开 -民 -蜇 -何 -分 -凇 -长 -讥 -藏 -掏 -施 -羽 -中 -讲 -派 -嘟 -人 -提 -浼 -间 -世 -而 -古 -多 -倪 -唇 -饯 -控 -庚 -首 -赛 -蜓 -味 -断 -制 -觉 -技 -替 -艰 -溢 -潮 -夕 -钺 -外 -摘 -枋 -动 -双 -单 -啮 -户 -枇 -确 -锦 -曜 -杜 -或 -能 -效 -霜 -盒 -然 -侗 -电 -晁 -放 -步 -鹃 -新 -杖 -蜂 -吒 -濂 -瞬 -评 -总 -隍 -对 -独 -合 -也 -是 -府 -青 -天 -诲 -墙 -组 -滴 -级 -邀 -帘 -示 -已 -时 -骸 -仄 -泅 -和 -遨 -店 -雇 -疫 -持 -巍 -踮 -境 -只 -亨 -目 -鉴 -崤 -闲 -体 -泄 -杂 -作 -般 -轰 -化 -解 -迂 -诿 -蛭 -璀 -腾 -告 -版 -服 -省 -师 -小 -规 -程 -线 -海 -办 -引 -二 -桧 -牌 -砺 -洄 -裴 -修 -图 -痫 -胡 -许 -犊 -事 -郛 -基 -柴 -呼 -食 -研 -奶 -律 -蛋 -因 -葆 -察 -戏 -褒 -戒 -再 -李 -骁 -工 -貂 -油 -鹅 -章 -啄 -休 -场 -给 -睡 -纷 -豆 -器 -捎 -说 -敏 -学 -会 -浒 -设 -诊 -格 -廓 -查 -来 -霓 -室 -溆 -¢ -诡 -寥 -焕 -舜 -柒 -狐 -回 -戟 -砾 -厄 -实 -翩 -尿 -五 -入 -径 -惭 -喹 -股 -宇 -篝 -| -; -美 -期 -云 -九 -祺 -扮 -靠 -锝 -槌 -系 -企 -酰 -阊 -暂 -蚕 -忻 -豁 -本 -羹 -执 -条 -钦 -H -獒 -限 -进 -季 -楦 -于 -芘 -玖 -铋 -茯 -未 -答 -粘 -括 -样 -精 -欠 -矢 -甥 -帷 -嵩 -扣 -令 -仔 -风 -皈 -行 -支 -部 -蓉 -刮 -站 -蜡 -救 -钊 -汗 -松 -嫌 -成 -可 -. -鹤 -院 -从 -交 -政 -怕 -活 -调 -球 -局 -验 -髌 -第 -韫 -谗 -串 -到 -圆 -年 -米 -/ -* -友 -忿 -检 -区 -看 -自 -敢 -刃 -个 -兹 -弄 -流 -留 -同 -没 -齿 -星 -聆 -轼 -湖 -什 -三 -建 -蛔 -儿 -椋 -汕 -震 -颧 -鲤 -跟 -力 -情 -璺 -铨 -陪 -务 -指 -族 -训 -滦 -鄣 -濮 -扒 -商 -箱 -十 -召 -慷 -辗 -所 -莞 -管 -护 -臭 -横 -硒 -嗓 -接 -侦 -六 -露 -党 -馋 -驾 -剖 -高 -侬 -妪 -幂 -猗 -绺 -骐 -央 -酐 -孝 -筝 -课 -徇 -缰 -门 -男 -西 -项 -句 -谙 -瞒 -秃 -篇 -教 -碲 -罚 -声 -呐 -景 -前 -富 -嘴 -鳌 -稀 -免 -朋 -啬 -睐 -去 -赈 -鱼 -住 -肩 -愕 -速 -旁 -波 -厅 -健 -茼 -厥 -鲟 -谅 -投 -攸 -炔 -数 -方 -击 -呋 -谈 -绩 -别 -愫 -僚 -躬 -鹧 -胪 -炳 -招 -喇 -膨 -泵 -蹦 -毛 -结 -5 -4 -谱 -识 -陕 -粽 -婚 -拟 -构 -且 -搜 -任 -潘 -比 -郢 -妨 -醪 -陀 -桔 -碘 -扎 -选 -哈 -骷 -楷 -亿 -明 -缆 -脯 -监 -睫 -逻 -婵 -共 -赴 -淝 -凡 -惦 -及 -达 -揖 -谩 -澹 -减 -焰 -蛹 -番 -祁 -柏 -员 -禄 -怡 -峤 -龙 -白 -叽 -生 -闯 -起 -细 -装 -谕 -竟 -聚 -钙 -上 -导 -渊 -按 -艾 -辘 -挡 -耒 -盹 -饪 -臀 -记 -邮 -蕙 -受 -各 -医 -搂 -普 -滇 -朗 -茸 -带 -翻 -酚 -( -光 -堤 -墟 -蔷 -万 -幻 -〓 -瑙 -辈 -昧 -盏 -亘 -蛀 -吉 -铰 -请 -子 -假 -闻 -税 -井 -诩 -哨 -嫂 -好 -面 -琐 -校 -馊 -鬣 -缂 -营 -访 -炖 -占 -农 -缀 -否 -经 -钚 -棵 -趟 -张 -亟 -吏 -茶 -谨 -捻 -论 -迸 -堂 -玉 -信 -吧 -瞠 -乡 -姬 -寺 -咬 -溏 -苄 -皿 -意 -赉 -宝 -尔 -钰 -艺 -特 -唳 -踉 -都 -荣 -倚 -登 -荐 -丧 -奇 -涵 -批 -炭 -近 -符 -傩 -感 -道 -着 -菊 -虹 -仲 -众 -懈 -濯 -颞 -眺 -南 -释 -北 -缝 -标 -既 -茗 -整 -撼 -迤 -贲 -挎 -耱 -拒 -某 -妍 -卫 -哇 -英 -矶 -藩 -治 -他 -元 -领 -膜 -遮 -穗 -蛾 -飞 -荒 -棺 -劫 -么 -市 -火 -温 -拈 -棚 -洼 -转 -果 -奕 -卸 -迪 -伸 -泳 -斗 -邡 -侄 -涨 -屯 -萋 -胭 -氡 -崮 -枞 -惧 -冒 -彩 -斜 -手 -豚 -随 -旭 -淑 -妞 -形 -菌 -吲 -沱 -争 -驯 -歹 -挟 -兆 -柱 -传 -至 -包 -内 -响 -临 -红 -功 -弩 -衡 -寂 -禁 -老 -棍 -耆 -渍 -织 -害 -氵 -渑 -布 -载 -靥 -嗬 -虽 -苹 -咨 -娄 -库 -雉 -榜 -帜 -嘲 -套 -瑚 -亲 -簸 -欧 -边 -6 -腿 -旮 -抛 -吹 -瞳 -得 -镓 -梗 -厨 -继 -漾 -愣 -憨 -士 -策 -窑 -抑 -躯 -襟 -脏 -参 -贸 -言 -干 -绸 -鳄 -穷 -藜 -音 -折 -详 -) -举 -悍 -甸 -癌 -黎 -谴 -死 -罩 -迁 -寒 -驷 -袖 -媒 -蒋 -掘 -模 -纠 -恣 -观 -祖 -蛆 -碍 -位 -稿 -主 -澧 -跌 -筏 -京 -锏 -帝 -贴 -证 -糠 -才 -黄 -鲸 -略 -炯 -饱 -四 -出 -园 -犀 -牧 -容 -汉 -杆 -浈 -汰 -瑷 -造 -虫 -瘩 -怪 -驴 -济 -应 -花 -沣 -谔 -夙 -旅 -价 -矿 -以 -考 -s -u -呦 -晒 -巡 -茅 -准 -肟 -瓴 -詹 -仟 -褂 -译 -桌 -混 -宁 -怦 -郑 -抿 -些 -余 -鄂 -饴 -攒 -珑 -群 -阖 -岔 -琨 -藓 -预 -环 -洮 -岌 -宀 -杲 -瀵 -最 -常 -囡 -周 -踊 -女 -鼓 -袭 -喉 -简 -范 -薯 -遐 -疏 -粱 -黜 -禧 -法 -箔 -斤 -遥 -汝 -奥 -直 -贞 -撑 -置 -绱 -集 -她 -馅 -逗 -钧 -橱 -魉 -[ -恙 -躁 -唤 -9 -旺 -膘 -待 -脾 -惫 -购 -吗 -依 -盲 -度 -瘿 -蠖 -俾 -之 -镗 -拇 -鲵 -厝 -簧 -续 -款 -展 -啃 -表 -剔 -品 -钻 -腭 -损 -清 -锶 -统 -涌 -寸 -滨 -贪 -链 -吠 -冈 -伎 -迥 -咏 -吁 -览 -防 -迅 -失 -汾 -阔 -逵 -绀 -蔑 -列 -川 -凭 -努 -熨 -揪 -利 -俱 -绉 -抢 -鸨 -我 -即 -责 -膦 -易 -毓 -鹊 -刹 -玷 -岿 -空 -嘞 -绊 -排 -术 -估 -锷 -违 -们 -苟 -铜 -播 -肘 -件 -烫 -审 -鲂 -广 -像 -铌 -惰 -铟 -巳 -胍 -鲍 -康 -憧 -色 -恢 -想 -拷 -尤 -疳 -知 -S -Y -F -D -A -峄 -裕 -帮 -握 -搔 -氐 -氘 -难 -墒 -沮 -雨 -叁 -缥 -悴 -藐 -湫 -娟 -苑 -稠 -颛 -簇 -后 -阕 -闭 -蕤 -缚 -怎 -佞 -码 -嘤 -蔡 -痊 -舱 -螯 -帕 -赫 -昵 -升 -烬 -岫 -、 -疵 -蜻 -髁 -蕨 -隶 -烛 -械 -丑 -盂 -梁 -强 -鲛 -由 -拘 -揉 -劭 -龟 -撤 -钩 -呕 -孛 -费 -妻 -漂 -求 -阑 -崖 -秤 -甘 -通 -深 -补 -赃 -坎 -床 -啪 -承 -吼 -量 -暇 -钼 -烨 -阂 -擎 -脱 -逮 -称 -P -神 -属 -矗 -华 -届 -狍 -葑 -汹 -育 -患 -窒 -蛰 -佼 -静 -槎 -运 -鳗 -庆 -逝 -曼 -疱 -克 -代 -官 -此 -麸 -耧 -蚌 -晟 -例 -础 -榛 -副 -测 -唰 -缢 -迹 -灬 -霁 -身 -岁 -赭 -扛 -又 -菡 -乜 -雾 -板 -读 -陷 -徉 -贯 -郁 -虑 -变 -钓 -菜 -圾 -现 -琢 -式 -乐 -维 -渔 -浜 -左 -吾 -脑 -钡 -警 -T -啵 -拴 -偌 -漱 -湿 -硕 -止 -骼 -魄 -积 -燥 -联 -踢 -玛 -则 -窿 -见 -振 -畿 -送 -班 -钽 -您 -赵 -刨 -印 -讨 -踝 -籍 -谡 -舌 -崧 -汽 -蔽 -沪 -酥 -绒 -怖 -财 -帖 -肱 -私 -莎 -勋 -羔 -霸 -励 -哼 -帐 -将 -帅 -渠 -纪 -婴 -娩 -岭 -厘 -滕 -吻 -伤 -坝 -冠 -戊 -隆 -瘁 -介 -涧 -物 -黍 -并 -姗 -奢 -蹑 -掣 -垸 -锴 -命 -箍 -捉 -病 -辖 -琰 -眭 -迩 -艘 -绌 -繁 -寅 -若 -毋 -思 -诉 -类 -诈 -燮 -轲 -酮 -狂 -重 -反 -职 -筱 -县 -委 -磕 -绣 -奖 -晋 -濉 -志 -徽 -肠 -呈 -獐 -坻 -口 -片 -碰 -几 -村 -柿 -劳 -料 -获 -亩 -惕 -晕 -厌 -号 -罢 -池 -正 -鏖 -煨 -家 -棕 -复 -尝 -懋 -蜥 -锅 -岛 -扰 -队 -坠 -瘾 -钬 -@ -卧 -疣 -镇 -譬 -冰 -彷 -频 -黯 -据 -垄 -采 -八 -缪 -瘫 -型 -熹 -砰 -楠 -襁 -箐 -但 -嘶 -绳 -啤 -拍 -盥 -穆 -傲 -洗 -盯 -塘 -怔 -筛 -丿 -台 -恒 -喂 -葛 -永 -¥ -烟 -酒 -桦 -书 -砂 -蚝 -缉 -态 -瀚 -袄 -圳 -轻 -蛛 -超 -榧 -遛 -姒 -奘 -铮 -右 -荽 -望 -偻 -卡 -丶 -氰 -附 -做 -革 -索 -戚 -坨 -桷 -唁 -垅 -榻 -岐 -偎 -坛 -莨 -山 -殊 -微 -骇 -陈 -爨 -推 -嗝 -驹 -澡 -藁 -呤 -卤 -嘻 -糅 -逛 -侵 -郓 -酌 -德 -摇 -※ -鬃 -被 -慨 -殡 -羸 -昌 -泡 -戛 -鞋 -河 -宪 -沿 -玲 -鲨 -翅 -哽 -源 -铅 -语 -照 -邯 -址 -荃 -佬 -顺 -鸳 -町 -霭 -睾 -瓢 -夸 -椁 -晓 -酿 -痈 -咔 -侏 -券 -噎 -湍 -签 -嚷 -离 -午 -尚 -社 -锤 -背 -孟 -使 -浪 -缦 -潍 -鞅 -军 -姹 -驶 -笑 -鳟 -鲁 -》 -孽 -钜 -绿 -洱 -礴 -焯 -椰 -颖 -囔 -乌 -孔 -巴 -互 -性 -椽 -哞 -聘 -昨 -早 -暮 -胶 -炀 -隧 -低 -彗 -昝 -铁 -呓 -氽 -藉 -喔 -癖 -瑗 -姨 -权 -胱 -韦 -堑 -蜜 -酋 -楝 -砝 -毁 -靓 -歙 -锲 -究 -屋 -喳 -骨 -辨 -碑 -武 -鸠 -宫 -辜 -烊 -适 -坡 -殃 -培 -佩 -供 -走 -蜈 -迟 -翼 -况 -姣 -凛 -浔 -吃 -飘 -债 -犟 -金 -促 -苛 -崇 -坂 -莳 -畔 -绂 -兵 -蠕 -斋 -根 -砍 -亢 -欢 -恬 -崔 -剁 -餐 -榫 -快 -扶 -‖ -濒 -缠 -鳜 -当 -彭 -驭 -浦 -篮 -昀 -锆 -秸 -钳 -弋 -娣 -瞑 -夷 -龛 -苫 -拱 -致 -% -嵊 -障 -隐 -弑 -初 -娓 -抉 -汩 -累 -蓖 -" -唬 -助 -苓 -昙 -押 -毙 -破 -城 -郧 -逢 -嚏 -獭 -瞻 -溱 -婿 -赊 -跨 -恼 -璧 -萃 -姻 -貉 -灵 -炉 -密 -氛 -陶 -砸 -谬 -衔 -点 -琛 -沛 -枳 -层 -岱 -诺 -脍 -榈 -埂 -征 -冷 -裁 -打 -蹴 -素 -瘘 -逞 -蛐 -聊 -激 -腱 -萘 -踵 -飒 -蓟 -吆 -取 -咙 -簋 -涓 -矩 -曝 -挺 -揣 -座 -你 -史 -舵 -焱 -尘 -苏 -笈 -脚 -溉 -榨 -诵 -樊 -邓 -焊 -义 -庶 -儋 -蟋 -蒲 -赦 -呷 -杞 -诠 -豪 -还 -试 -颓 -茉 -太 -除 -紫 -逃 -痴 -草 -充 -鳕 -珉 -祗 -墨 -渭 -烩 -蘸 -慕 -璇 -镶 -穴 -嵘 -恶 -骂 -险 -绋 -幕 -碉 -肺 -戳 -刘 -潞 -秣 -纾 -潜 -銮 -洛 -须 -罘 -销 -瘪 -汞 -兮 -屉 -r -林 -厕 -质 -探 -划 -狸 -殚 -善 -煊 -烹 -〒 -锈 -逯 -宸 -辍 -泱 -柚 -袍 -远 -蹋 -嶙 -绝 -峥 -娥 -缍 -雀 -徵 -认 -镱 -谷 -= -贩 -勉 -撩 -鄯 -斐 -洋 -非 -祚 -泾 -诒 -饿 -撬 -威 -晷 -搭 -芍 -锥 -笺 -蓦 -候 -琊 -档 -礁 -沼 -卵 -荠 -忑 -朝 -凹 -瑞 -头 -仪 -弧 -孵 -畏 -铆 -突 -衲 -车 -浩 -气 -茂 -悖 -厢 -枕 -酝 -戴 -湾 -邹 -飚 -攘 -锂 -写 -宵 -翁 -岷 -无 -喜 -丈 -挑 -嗟 -绛 -殉 -议 -槽 -具 -醇 -淞 -笃 -郴 -阅 -饼 -底 -壕 -砚 -弈 -询 -缕 -庹 -翟 -零 -筷 -暨 -舟 -闺 -甯 -撞 -麂 -茌 -蔼 -很 -珲 -捕 -棠 -角 -阉 -媛 -娲 -诽 -剿 -尉 -爵 -睬 -韩 -诰 -匣 -危 -糍 -镯 -立 -浏 -阳 -少 -盆 -舔 -擘 -匪 -申 -尬 -铣 -旯 -抖 -赘 -瓯 -居 -ˇ -哮 -游 -锭 -茏 -歌 -坏 -甚 -秒 -舞 -沙 -仗 -劲 -潺 -阿 -燧 -郭 -嗖 -霏 -忠 -材 -奂 -耐 -跺 -砀 -输 -岖 -媳 -氟 -极 -摆 -灿 -今 -扔 -腻 -枝 -奎 -药 -熄 -吨 -话 -q -额 -慑 -嘌 -协 -喀 -壳 -埭 -视 -著 -於 -愧 -陲 -翌 -峁 -颅 -佛 -腹 -聋 -侯 -咎 -叟 -秀 -颇 -存 -较 -罪 -哄 -岗 -扫 -栏 -钾 -羌 -己 -璨 -枭 -霉 -煌 -涸 -衿 -键 -镝 -益 -岢 -奏 -连 -夯 -睿 -冥 -均 -糖 -狞 -蹊 -稻 -爸 -刿 -胥 -煜 -丽 -肿 -璃 -掸 -跚 -灾 -垂 -樾 -濑 -乎 -莲 -窄 -犹 -撮 -战 -馄 -软 -络 -显 -鸢 -胸 -宾 -妲 -恕 -埔 -蝌 -份 -遇 -巧 -瞟 -粒 -恰 -剥 -桡 -博 -讯 -凯 -堇 -阶 -滤 -卖 -斌 -骚 -彬 -兑 -磺 -樱 -舷 -两 -娱 -福 -仃 -差 -找 -桁 -÷ -净 -把 -阴 -污 -戬 -雷 -碓 -蕲 -楚 -罡 -焖 -抽 -妫 -咒 -仑 -闱 -尽 -邑 -菁 -爱 -贷 -沥 -鞑 -牡 -嗉 -崴 -骤 -塌 -嗦 -订 -拮 -滓 -捡 -锻 -次 -坪 -杩 -臃 -箬 -融 -珂 -鹗 -宗 -枚 -降 -鸬 -妯 -阄 -堰 -盐 -毅 -必 -杨 -崃 -俺 -甬 -状 -莘 -货 -耸 -菱 -腼 -铸 -唏 -痤 -孚 -澳 -懒 -溅 -翘 -疙 -杷 -淼 -缙 -骰 -喊 -悉 -砻 -坷 -艇 -赁 -界 -谤 -纣 -宴 -晃 -茹 -归 -饭 -梢 -铡 -街 -抄 -肼 -鬟 -苯 -颂 -撷 -戈 -炒 -咆 -茭 -瘙 -负 -仰 -客 -琉 -铢 -封 -卑 -珥 -椿 -镧 -窨 -鬲 -寿 -御 -袤 -铃 -萎 -砖 -餮 -脒 -裳 -肪 -孕 -嫣 -馗 -嵇 -恳 -氯 -江 -石 -褶 -冢 -祸 -阻 -狈 -羞 -银 -靳 -透 -咳 -叼 -敷 -芷 -啥 -它 -瓤 -兰 -痘 -懊 -逑 -肌 -往 -捺 -坊 -甩 -呻 -〃 -沦 -忘 -膻 -祟 -菅 -剧 -崆 -智 -坯 -臧 -霍 -墅 -攻 -眯 -倘 -拢 -骠 -铐 -庭 -岙 -瓠 -′ -缺 -泥 -迢 -捶 -? -? -郏 -喙 -掷 -沌 -纯 -秘 -种 -听 -绘 -固 -螨 -团 -香 -盗 -妒 -埚 -蓝 -拖 -旱 -荞 -铀 -血 -遏 -汲 -辰 -叩 -拽 -幅 -硬 -惶 -桀 -漠 -措 -泼 -唑 -齐 -肾 -念 -酱 -虚 -屁 -耶 -旗 -砦 -闵 -婉 -馆 -拭 -绅 -韧 -忏 -窝 -醋 -葺 -顾 -辞 -倜 -堆 -辋 -逆 -玟 -贱 -疾 -董 -惘 -倌 -锕 -淘 -嘀 -莽 -俭 -笏 -绑 -鲷 -杈 -择 -蟀 -粥 -嗯 -驰 -逾 -案 -谪 -褓 -胫 -哩 -昕 -颚 -鲢 -绠 -躺 -鹄 -崂 -儒 -俨 -丝 -尕 -泌 -啊 -萸 -彰 -幺 -吟 -骄 -苣 -弦 -脊 -瑰 -〈 -诛 -镁 -析 -闪 -剪 -侧 -哟 -框 -螃 -守 -嬗 -燕 -狭 -铈 -缮 -概 -迳 -痧 -鲲 -俯 -售 -笼 -痣 -扉 -挖 -满 -咋 -援 -邱 -扇 -歪 -便 -玑 -绦 -峡 -蛇 -叨 -〖 -泽 -胃 -斓 -喋 -怂 -坟 -猪 -该 -蚬 -炕 -弥 -赞 -棣 -晔 -娠 -挲 -狡 -创 -疖 -铕 -镭 -稷 -挫 -弭 -啾 -翔 -粉 -履 -苘 -哦 -楼 -秕 -铂 -土 -锣 -瘟 -挣 -栉 -习 -享 -桢 -袅 -磨 -桂 -谦 -延 -坚 -蔚 -噗 -署 -谟 -猬 -钎 -恐 -嬉 -雒 -倦 -衅 -亏 -璩 -睹 -刻 -殿 -王 -算 -雕 -麻 -丘 -柯 -骆 -丸 -塍 -谚 -添 -鲈 -垓 -桎 -蚯 -芥 -予 -飕 -镦 -谌 -窗 -醚 -菀 -亮 -搪 -莺 -蒿 -羁 -足 -J -真 -轶 -悬 -衷 -靛 -翊 -掩 -哒 -炅 -掐 -冼 -妮 -l -谐 -稚 -荆 -擒 -犯 -陵 -虏 -浓 -崽 -刍 -陌 -傻 -孜 -千 -靖 -演 -矜 -钕 -煽 -杰 -酗 -渗 -伞 -栋 -俗 -泫 -戍 -罕 -沾 -疽 -灏 -煦 -芬 -磴 -叱 -阱 -榉 -湃 -蜀 -叉 -醒 -彪 -租 -郡 -篷 -屎 -良 -垢 -隗 -弱 -陨 -峪 -砷 -掴 -颁 -胎 -雯 -绵 -贬 -沐 -撵 -隘 -篙 -暖 -曹 -陡 -栓 -填 -臼 -彦 -瓶 -琪 -潼 -哪 -鸡 -摩 -啦 -俟 -锋 -域 -耻 -蔫 -疯 -纹 -撇 -毒 -绶 -痛 -酯 -忍 -爪 -赳 -歆 -嘹 -辕 -烈 -册 -朴 -钱 -吮 -毯 -癜 -娃 -谀 -邵 -厮 -炽 -璞 -邃 -丐 -追 -词 -瓒 -忆 -轧 -芫 -谯 -喷 -弟 -半 -冕 -裙 -掖 -墉 -绮 -寝 -苔 -势 -顷 -褥 -切 -衮 -君 -佳 -嫒 -蚩 -霞 -佚 -洙 -逊 -镖 -暹 -唛 -& -殒 -顶 -碗 -獗 -轭 -铺 -蛊 -废 -恹 -汨 -崩 -珍 -那 -杵 -曲 -纺 -夏 -薰 -傀 -闳 -淬 -姘 -舀 -拧 -卷 -楂 -恍 -讪 -厩 -寮 -篪 -赓 -乘 -灭 -盅 -鞣 -沟 -慎 -挂 -饺 -鼾 -杳 -树 -缨 -丛 -絮 -娌 -臻 -嗳 -篡 -侩 -述 -衰 -矛 -圈 -蚜 -匕 -筹 -匿 -濞 -晨 -叶 -骋 -郝 -挚 -蚴 -滞 -增 -侍 -描 -瓣 -吖 -嫦 -蟒 -匾 -圣 -赌 -毡 -癞 -恺 -百 -曳 -需 -篓 -肮 -庖 -帏 -卿 -驿 -遗 -蹬 -鬓 -骡 -歉 -芎 -胳 -屐 -禽 -烦 -晌 -寄 -媾 -狄 -翡 -苒 -船 -廉 -终 -痞 -殇 -々 -畦 -饶 -改 -拆 -悻 -萄 -£ -瓿 -乃 -訾 -桅 -匮 -溧 -拥 -纱 -铍 -骗 -蕃 -龋 -缬 -父 -佐 -疚 -栎 -醍 -掳 -蓄 -x -惆 -颜 -鲆 -榆 -〔 -猎 -敌 -暴 -谥 -鲫 -贾 -罗 -玻 -缄 -扦 -芪 -癣 -落 -徒 -臾 -恿 -猩 -托 -邴 -肄 -牵 -春 -陛 -耀 -刊 -拓 -蓓 -邳 -堕 -寇 -枉 -淌 -啡 -湄 -兽 -酷 -萼 -碚 -濠 -萤 -夹 -旬 -戮 -梭 -琥 -椭 -昔 -勺 -蜊 -绐 -晚 -孺 -僵 -宣 -摄 -冽 -旨 -萌 -忙 -蚤 -眉 -噼 -蟑 -付 -契 -瓜 -悼 -颡 -壁 -曾 -窕 -颢 -澎 -仿 -俑 -浑 -嵌 -浣 -乍 -碌 -褪 -乱 -蔟 -隙 -玩 -剐 -葫 -箫 -纲 -围 -伐 -决 -伙 -漩 -瑟 -刑 -肓 -镳 -缓 -蹭 -氨 -皓 -典 -畲 -坍 -铑 -檐 -塑 -洞 -倬 -储 -胴 -淳 -戾 -吐 -灼 -惺 -妙 -毕 -珐 -缈 -虱 -盖 -羰 -鸿 -磅 -谓 -髅 -娴 -苴 -唷 -蚣 -霹 -抨 -贤 -唠 -犬 -誓 -逍 -庠 -逼 -麓 -籼 -釉 -呜 -碧 -秧 -氩 -摔 -霄 -穸 -纨 -辟 -妈 -映 -完 -牛 -缴 -嗷 -炊 -恩 -荔 -茆 -掉 -紊 -慌 -莓 -羟 -阙 -萁 -磐 -另 -蕹 -辱 -鳐 -湮 -吡 -吩 -唐 -睦 -垠 -舒 -圜 -冗 -瞿 -溺 -芾 -囱 -匠 -僳 -汐 -菩 -饬 -漓 -黑 -霰 -浸 -濡 -窥 -毂 -蒡 -兢 -驻 -鹉 -芮 -诙 -迫 -雳 -厂 -忐 -臆 -猴 -鸣 -蚪 -栈 -箕 -羡 -渐 -莆 -捍 -眈 -哓 -趴 -蹼 -埕 -嚣 -骛 -宏 -淄 -斑 -噜 -严 -瑛 -垃 -椎 -诱 -压 -庾 -绞 -焘 -廿 -抡 -迄 -棘 -夫 -纬 -锹 -眨 -瞌 -侠 -脐 -竞 -瀑 -孳 -骧 -遁 -姜 -颦 -荪 -滚 -萦 -伪 -逸 -粳 -爬 -锁 -矣 -役 -趣 -洒 -颔 -诏 -逐 -奸 -甭 -惠 -攀 -蹄 -泛 -尼 -拼 -阮 -鹰 -亚 -颈 -惑 -勒 -〉 -际 -肛 -爷 -刚 -钨 -丰 -养 -冶 -鲽 -辉 -蔻 -画 -覆 -皴 -妊 -麦 -返 -醉 -皂 -擀 -〗 -酶 -凑 -粹 -悟 -诀 -硖 -港 -卜 -z -杀 -涕 -± -舍 -铠 -抵 -弛 -段 -敝 -镐 -奠 -拂 -轴 -跛 -袱 -e -t -沉 -菇 -俎 -薪 -峦 -秭 -蟹 -历 -盟 -菠 -寡 -液 -肢 -喻 -染 -裱 -悱 -抱 -氙 -赤 -捅 -猛 -跑 -氮 -谣 -仁 -尺 -辊 -窍 -烙 -衍 -架 -擦 -倏 -璐 -瑁 -币 -楞 -胖 -夔 -趸 -邛 -惴 -饕 -虔 -蝎 -§ -哉 -贝 -宽 -辫 -炮 -扩 -饲 -籽 -魏 -菟 -锰 -伍 -猝 -末 -琳 -哚 -蛎 -邂 -呀 -姿 -鄞 -却 -歧 -仙 -恸 -椐 -森 -牒 -寤 -袒 -婆 -虢 -雅 -钉 -朵 -贼 -欲 -苞 -寰 -故 -龚 -坭 -嘘 -咫 -礼 -硷 -兀 -睢 -汶 -’ -铲 -烧 -绕 -诃 -浃 -钿 -哺 -柜 -讼 -颊 -璁 -腔 -洽 -咐 -脲 -簌 -筠 -镣 -玮 -鞠 -谁 -兼 -姆 -挥 -梯 -蝴 -谘 -漕 -刷 -躏 -宦 -弼 -b -垌 -劈 -麟 -莉 -揭 -笙 -渎 -仕 -嗤 -仓 -配 -怏 -抬 -错 -泯 -镊 -孰 -猿 -邪 -仍 -秋 -鼬 -壹 -歇 -吵 -炼 -< -尧 -射 -柬 -廷 -胧 -霾 -凳 -隋 -肚 -浮 -梦 -祥 -株 -堵 -退 -L -鹫 -跎 -凶 -毽 -荟 -炫 -栩 -玳 -甜 -沂 -鹿 -顽 -伯 -爹 -赔 -蛴 -徐 -匡 -欣 -狰 -缸 -雹 -蟆 -疤 -默 -沤 -啜 -痂 -衣 -禅 -w -i -h -辽 -葳 -黝 -钗 -停 -沽 -棒 -馨 -颌 -肉 -吴 -硫 -悯 -劾 -娈 -马 -啧 -吊 -悌 -镑 -峭 -帆 -瀣 -涉 -咸 -疸 -滋 -泣 -翦 -拙 -癸 -钥 -蜒 -+ -尾 -庄 -凝 -泉 -婢 -渴 -谊 -乞 -陆 -锉 -糊 -鸦 -淮 -I -B -N -晦 -弗 -乔 -庥 -葡 -尻 -席 -橡 -傣 -渣 -拿 -惩 -麋 -斛 -缃 -矮 -蛏 -岘 -鸽 -姐 -膏 -催 -奔 -镒 -喱 -蠡 -摧 -钯 -胤 -柠 -拐 -璋 -鸥 -卢 -荡 -倾 -^ -_ -珀 -逄 -萧 -塾 -掇 -贮 -笆 -聂 -圃 -冲 -嵬 -M -滔 -笕 -值 -炙 -偶 -蜱 -搐 -梆 -汪 -蔬 -腑 -鸯 -蹇 -敞 -绯 -仨 -祯 -谆 -梧 -糗 -鑫 -啸 -豺 -囹 -猾 -巢 -柄 -瀛 -筑 -踌 -沭 -暗 -苁 -鱿 -蹉 -脂 -蘖 -牢 -热 -木 -吸 -溃 -宠 -序 -泞 -偿 -拜 -檩 -厚 -朐 -毗 -螳 -吞 -媚 -朽 -担 -蝗 -橘 -畴 -祈 -糟 -盱 -隼 -郜 -惜 -珠 -裨 -铵 -焙 -琚 -唯 -咚 -噪 -骊 -丫 -滢 -勤 -棉 -呸 -咣 -淀 -隔 -蕾 -窈 -饨 -挨 -煅 -短 -匙 -粕 -镜 -赣 -撕 -墩 -酬 -馁 -豌 -颐 -抗 -酣 -氓 -佑 -搁 -哭 -递 -耷 -涡 -桃 -贻 -碣 -截 -瘦 -昭 -镌 -蔓 -氚 -甲 -猕 -蕴 -蓬 -散 -拾 -纛 -狼 -猷 -铎 -埋 -旖 -矾 -讳 -囊 -糜 -迈 -粟 -蚂 -紧 -鲳 -瘢 -栽 -稼 -羊 -锄 -斟 -睁 -桥 -瓮 -蹙 -祉 -醺 -鼻 -昱 -剃 -跳 -篱 -跷 -蒜 -翎 -宅 -晖 -嗑 -壑 -峻 -癫 -屏 -狠 -陋 -袜 -途 -憎 -祀 -莹 -滟 -佶 -溥 -臣 -约 -盛 -峰 -磁 -慵 -婪 -拦 -莅 -朕 -鹦 -粲 -裤 -哎 -疡 -嫖 -琵 -窟 -堪 -谛 -嘉 -儡 -鳝 -斩 -郾 -驸 -酊 -妄 -胜 -贺 -徙 -傅 -噌 -钢 -栅 -庇 -恋 -匝 -巯 -邈 -尸 -锚 -粗 -佟 -蛟 -薹 -纵 -蚊 -郅 -绢 -锐 -苗 -俞 -篆 -淆 -膀 -鲜 -煎 -诶 -秽 -寻 -涮 -刺 -怀 -噶 -巨 -褰 -魅 -灶 -灌 -桉 -藕 -谜 -舸 -薄 -搀 -恽 -借 -牯 -痉 -渥 -愿 -亓 -耘 -杠 -柩 -锔 -蚶 -钣 -珈 -喘 -蹒 -幽 -赐 -稗 -晤 -莱 -泔 -扯 -肯 -菪 -裆 -腩 -豉 -疆 -骜 -腐 -倭 -珏 -唔 -粮 -亡 -润 -慰 -伽 -橄 -玄 -誉 -醐 -胆 -龊 -粼 -塬 -陇 -彼 -削 -嗣 -绾 -芽 -妗 -垭 -瘴 -爽 -薏 -寨 -龈 -泠 -弹 -赢 -漪 -猫 -嘧 -涂 -恤 -圭 -茧 -烽 -屑 -痕 -巾 -赖 -荸 -凰 -腮 -畈 -亵 -蹲 -偃 -苇 -澜 -艮 -换 -骺 -烘 -苕 -梓 -颉 -肇 -哗 -悄 -氤 -涠 -葬 -屠 -鹭 -植 -竺 -佯 -诣 -鲇 -瘀 -鲅 -邦 -移 -滁 -冯 -耕 -癔 -戌 -茬 -沁 -巩 -悠 -湘 -洪 -痹 -锟 -循 -谋 -腕 -鳃 -钠 -捞 -焉 -迎 -碱 -伫 -急 -榷 -奈 -邝 -卯 -辄 -皲 -卟 -醛 -畹 -忧 -稳 -雄 -昼 -缩 -阈 -睑 -扌 -耗 -曦 -涅 -捏 -瞧 -邕 -淖 -漉 -铝 -耦 -禹 -湛 -喽 -莼 -琅 -诸 -苎 -纂 -硅 -始 -嗨 -傥 -燃 -臂 -赅 -嘈 -呆 -贵 -屹 -壮 -肋 -亍 -蚀 -卅 -豹 -腆 -邬 -迭 -浊 -} -童 -螂 -捐 -圩 -勐 -触 -寞 -汊 -壤 -荫 -膺 -渌 -芳 -懿 -遴 -螈 -泰 -蓼 -蛤 -茜 -舅 -枫 -朔 -膝 -眙 -避 -梅 -判 -鹜 -璜 -牍 -缅 -垫 -藻 -黔 -侥 -惚 -懂 -踩 -腰 -腈 -札 -丞 -唾 -慈 -顿 -摹 -荻 -琬 -~ -斧 -沈 -滂 -胁 -胀 -幄 -莜 -Z -匀 -鄄 -掌 -绰 -茎 -焚 -赋 -萱 -谑 -汁 -铒 -瞎 -夺 -蜗 -野 -娆 -冀 -弯 -篁 -懵 -灞 -隽 -芡 -脘 -俐 -辩 -芯 -掺 -喏 -膈 -蝈 -觐 -悚 -踹 -蔗 -熠 -鼠 -呵 -抓 -橼 -峨 -畜 -缔 -禾 -崭 -弃 -熊 -摒 -凸 -拗 -穹 -蒙 -抒 -祛 -劝 -闫 -扳 -阵 -醌 -踪 -喵 -侣 -搬 -仅 -荧 -赎 -蝾 -琦 -买 -婧 -瞄 -寓 -皎 -冻 -赝 -箩 -莫 -瞰 -郊 -笫 -姝 -筒 -枪 -遣 -煸 -袋 -舆 -痱 -涛 -母 -〇 -启 -践 -耙 -绲 -盘 -遂 -昊 -搞 -槿 -诬 -纰 -泓 -惨 -檬 -亻 -越 -C -o -憩 -熵 -祷 -钒 -暧 -塔 -阗 -胰 -咄 -娶 -魔 -琶 -钞 -邻 -扬 -杉 -殴 -咽 -弓 -〆 -髻 -】 -吭 -揽 -霆 -拄 -殖 -脆 -彻 -岩 -芝 -勃 -辣 -剌 -钝 -嘎 -甄 -佘 -皖 -伦 -授 -徕 -憔 -挪 -皇 -庞 -稔 -芜 -踏 -溴 -兖 -卒 -擢 -饥 -鳞 -煲 -‰ -账 -颗 -叻 -斯 -捧 -鳍 -琮 -讹 -蛙 -纽 -谭 -酸 -兔 -莒 -睇 -伟 -觑 -羲 -嗜 -宜 -褐 -旎 -辛 -卦 -诘 -筋 -鎏 -溪 -挛 -熔 -阜 -晰 -鳅 -丢 -奚 -灸 -呱 -献 -陉 -黛 -鸪 -甾 -萨 -疮 -拯 -洲 -疹 -辑 -叙 -恻 -谒 -允 -柔 -烂 -氏 -逅 -漆 -拎 -惋 -扈 -湟 -纭 -啕 -掬 -擞 -哥 -忽 -涤 -鸵 -靡 -郗 -瓷 -扁 -廊 -怨 -雏 -钮 -敦 -E -懦 -憋 -汀 -拚 -啉 -腌 -岸 -f -痼 -瞅 -尊 -咀 -眩 -飙 -忌 -仝 -迦 -熬 -毫 -胯 -篑 -茄 -腺 -凄 -舛 -碴 -锵 -诧 -羯 -後 -漏 -汤 -宓 -仞 -蚁 -壶 -谰 -皑 -铄 -棰 -罔 -辅 -晶 -苦 -牟 -闽 -\ -烃 -饮 -聿 -丙 -蛳 -朱 -煤 -涔 -鳖 -犁 -罐 -荼 -砒 -淦 -妤 -黏 -戎 -孑 -婕 -瑾 -戢 -钵 -枣 -捋 -砥 -衩 -狙 -桠 -稣 -阎 -肃 -梏 -诫 -孪 -昶 -婊 -衫 -嗔 -侃 -塞 -蜃 -樵 -峒 -貌 -屿 -欺 -缫 -阐 -栖 -诟 -珞 -荭 -吝 -萍 -嗽 -恂 -啻 -蜴 -磬 -峋 -俸 -豫 -谎 -徊 -镍 -韬 -魇 -晴 -U -囟 -猜 -蛮 -坐 -囿 -伴 -亭 -肝 -佗 -蝠 -妃 -胞 -滩 -榴 -氖 -垩 -苋 -砣 -扪 -馏 -姓 -轩 -厉 -夥 -侈 -禀 -垒 -岑 -赏 -钛 -辐 -痔 -披 -纸 -碳 -“ -坞 -蠓 -挤 -荥 -沅 -悔 -铧 -帼 -蒌 -蝇 -a -p -y -n -g -哀 -浆 -瑶 -凿 -桶 -馈 -皮 -奴 -苜 -佤 -伶 -晗 -铱 -炬 -优 -弊 -氢 -恃 -甫 -攥 -端 -锌 -灰 -稹 -炝 -曙 -邋 -亥 -眶 -碾 -拉 -萝 -绔 -捷 -浍 -腋 -姑 -菖 -凌 -涞 -麽 -锢 -桨 -潢 -绎 -镰 -殆 -锑 -渝 -铬 -困 -绽 -觎 -匈 -糙 -暑 -裹 -鸟 -盔 -肽 -迷 -綦 -『 -亳 -佝 -俘 -钴 -觇 -骥 -仆 -疝 -跪 -婶 -郯 -瀹 -唉 -脖 -踞 -针 -晾 -忒 -扼 -瞩 -叛 -椒 -疟 -嗡 -邗 -肆 -跆 -玫 -忡 -捣 -咧 -唆 -艄 -蘑 -潦 -笛 -阚 -沸 -泻 -掊 -菽 -贫 -斥 -髂 -孢 -镂 -赂 -麝 -鸾 -屡 -衬 -苷 -恪 -叠 -希 -粤 -爻 -喝 -茫 -惬 -郸 -绻 -庸 -撅 -碟 -宄 -妹 -膛 -叮 -饵 -崛 -嗲 -椅 -冤 -搅 -咕 -敛 -尹 -垦 -闷 -蝉 -霎 -勰 -败 -蓑 -泸 -肤 -鹌 -幌 -焦 -浠 -鞍 -刁 -舰 -乙 -竿 -裔 -。 -茵 -函 -伊 -兄 -丨 -娜 -匍 -謇 -莪 -宥 -似 -蝽 -翳 -酪 -翠 -粑 -薇 -祢 -骏 -赠 -叫 -Q -噤 -噻 -竖 -芗 -莠 -潭 -俊 -羿 -耜 -O -郫 -趁 -嗪 -囚 -蹶 -芒 -洁 -笋 -鹑 -敲 -硝 -啶 -堡 -渲 -揩 -』 -携 -宿 -遒 -颍 -扭 -棱 -割 -萜 -蔸 -葵 -琴 -捂 -饰 -衙 -耿 -掠 -募 -岂 -窖 -涟 -蔺 -瘤 -柞 -瞪 -怜 -匹 -距 -楔 -炜 -哆 -秦 -缎 -幼 -茁 -绪 -痨 -恨 -楸 -娅 -瓦 -桩 -雪 -嬴 -伏 -榔 -妥 -铿 -拌 -眠 -雍 -缇 -‘ -卓 -搓 -哌 -觞 -噩 -屈 -哧 -髓 -咦 -巅 -娑 -侑 -淫 -膳 -祝 -勾 -姊 -莴 -胄 -疃 -薛 -蜷 -胛 -巷 -芙 -芋 -熙 -闰 -勿 -窃 -狱 -剩 -钏 -幢 -陟 -铛 -慧 -靴 -耍 -k -浙 -浇 -飨 -惟 -绗 -祜 -澈 -啼 -咪 -磷 -摞 -诅 -郦 -抹 -跃 -壬 -吕 -肖 -琏 -颤 -尴 -剡 -抠 -凋 -赚 -泊 -津 -宕 -殷 -倔 -氲 -漫 -邺 -涎 -怠 -$ -垮 -荬 -遵 -俏 -叹 -噢 -饽 -蜘 -孙 -筵 -疼 -鞭 -羧 -牦 -箭 -潴 -c -眸 -祭 -髯 -啖 -坳 -愁 -芩 -驮 -倡 -巽 -穰 -沃 -胚 -怒 -凤 -槛 -剂 -趵 -嫁 -v -邢 -灯 -鄢 -桐 -睽 -檗 -锯 -槟 -婷 -嵋 -圻 -诗 -蕈 -颠 -遭 -痢 -芸 -怯 -馥 -竭 -锗 -徜 -恭 -遍 -籁 -剑 -嘱 -苡 -龄 -僧 -桑 -潸 -弘 -澶 -楹 -悲 -讫 -愤 -腥 -悸 -谍 -椹 -呢 -桓 -葭 -攫 -阀 -翰 -躲 -敖 -柑 -郎 -笨 -橇 -呃 -魁 -燎 -脓 -葩 -磋 -垛 -玺 -狮 -沓 -砜 -蕊 -锺 -罹 -蕉 -翱 -虐 -闾 -巫 -旦 -茱 -嬷 -枯 -鹏 -贡 -芹 -汛 -矫 -绁 -拣 -禺 -佃 -讣 -舫 -惯 -乳 -趋 -疲 -挽 -岚 -虾 -衾 -蠹 -蹂 -飓 -氦 -铖 -孩 -稞 -瑜 -壅 -掀 -勘 -妓 -畅 -髋 -W -庐 -牲 -蓿 -榕 -练 -垣 -唱 -邸 -菲 -昆 -婺 -穿 -绡 -麒 -蚱 -掂 -愚 -泷 -涪 -漳 -妩 -娉 -榄 -讷 -觅 -旧 -藤 -煮 -呛 -柳 -腓 -叭 -庵 -烷 -阡 -罂 -蜕 -擂 -猖 -咿 -媲 -脉 -【 -沏 -貅 -黠 -熏 -哲 -烁 -坦 -酵 -兜 -× -潇 -撒 -剽 -珩 -圹 -乾 -摸 -樟 -帽 -嗒 -襄 -魂 -轿 -憬 -锡 -〕 -喃 -皆 -咖 -隅 -脸 -残 -泮 -袂 -鹂 -珊 -囤 -捆 -咤 -误 -徨 -闹 -淙 -芊 -淋 -怆 -囗 -拨 -梳 -渤 -R -G -绨 -蚓 -婀 -幡 -狩 -麾 -谢 -唢 -裸 -旌 -伉 -纶 -裂 -驳 -砼 -咛 -澄 -樨 -蹈 -宙 -澍 -倍 -貔 -操 -勇 -蟠 -摈 -砧 -虬 -够 -缁 -悦 -藿 -撸 -艹 -摁 -淹 -豇 -虎 -榭 -ˉ -吱 -d -° -喧 -荀 -踱 -侮 -奋 -偕 -饷 -犍 -惮 -坑 -璎 -徘 -宛 -妆 -袈 -倩 -窦 -昂 -荏 -乖 -K -怅 -撰 -鳙 -牙 -袁 -酞 -X -痿 -琼 -闸 -雁 -趾 -荚 -虻 -涝 -《 -杏 -韭 -偈 -烤 -绫 -鞘 -卉 -症 -遢 -蓥 -诋 -杭 -荨 -匆 -竣 -簪 -辙 -敕 -虞 -丹 -缭 -咩 -黟 -m -淤 -瑕 -咂 -铉 -硼 -茨 -嶂 -痒 -畸 -敬 -涿 -粪 -窘 -熟 -叔 -嫔 -盾 -忱 -裘 -憾 -梵 -赡 -珙 -咯 -娘 -庙 -溯 -胺 -葱 -痪 -摊 -荷 -卞 -乒 -髦 -寐 -铭 -坩 -胗 -枷 -爆 -溟 -嚼 -羚 -砬 -轨 -惊 -挠 -罄 -竽 -菏 -氧 -浅 -楣 -盼 -枢 -炸 -阆 -杯 -谏 -噬 -淇 -渺 -俪 -秆 -墓 -泪 -跻 -砌 -痰 -垡 -渡 -耽 -釜 -讶 -鳎 -煞 -呗 -韶 -舶 -绷 -鹳 -缜 -旷 -铊 -皱 -龌 -檀 -霖 -奄 -槐 -艳 -蝶 -旋 -哝 -赶 -骞 -蚧 -腊 -盈 -丁 -` -蜚 -矸 -蝙 -睨 -嚓 -僻 -鬼 -醴 -夜 -彝 -磊 -笔 -拔 -栀 -糕 -厦 -邰 -纫 -逭 -纤 -眦 -膊 -馍 -躇 -烯 -蘼 -冬 -诤 -暄 -骶 -哑 -瘠 -」 -臊 -丕 -愈 -咱 -螺 -擅 -跋 -搏 -硪 -谄 -笠 -淡 -嘿 -骅 -谧 -鼎 -皋 -姚 -歼 -蠢 -驼 -耳 -胬 -挝 -涯 -狗 -蒽 -孓 -犷 -凉 -芦 -箴 -铤 -孤 -嘛 -坤 -V -茴 -朦 -挞 -尖 -橙 -诞 -搴 -碇 -洵 -浚 -帚 -蜍 -漯 -柘 -嚎 -讽 -芭 -荤 -咻 -祠 -秉 -跖 -埃 -吓 -糯 -眷 -馒 -惹 -娼 -鲑 -嫩 -讴 -轮 -瞥 -靶 -褚 -乏 -缤 -宋 -帧 -删 -驱 -碎 -扑 -俩 -俄 -偏 -涣 -竹 -噱 -皙 -佰 -渚 -唧 -斡 -# -镉 -刀 -崎 -筐 -佣 -夭 -贰 -肴 -峙 -哔 -艿 -匐 -牺 -镛 -缘 -仡 -嫡 -劣 -枸 -堀 -梨 -簿 -鸭 -蒸 -亦 -稽 -浴 -{ -衢 -束 -槲 -j -阁 -揍 -疥 -棋 -潋 -聪 -窜 -乓 -睛 -插 -冉 -阪 -苍 -搽 -「 -蟾 -螟 -幸 -仇 -樽 -撂 -慢 -跤 -幔 -俚 -淅 -覃 -觊 -溶 -妖 -帛 -侨 -曰 -妾 -泗 -· -: -瀘 -風 -Ë -( -) -∶ -紅 -紗 -瑭 -雲 -頭 -鶏 -財 -許 -• -¥ -樂 -焗 -麗 -— -; -滙 -東 -榮 -繪 -興 -… -門 -業 -π -楊 -國 -顧 -é -盤 -寳 -Λ -龍 -鳳 -島 -誌 -緣 -結 -銭 -萬 -勝 -祎 -璟 -優 -歡 -臨 -時 -購 -= -★ -藍 -昇 -鐵 -觀 -勅 -農 -聲 -畫 -兿 -術 -發 -劉 -記 -專 -耑 -園 -書 -壴 -種 -Ο -● -褀 -號 -銀 -匯 -敟 -锘 -葉 -橪 -廣 -進 -蒄 -鑽 -阝 -祙 -貢 -鍋 -豊 -夬 -喆 -團 -閣 -開 -燁 -賓 -館 -酡 -沔 -順 -+ -硚 -劵 -饸 -陽 -車 -湓 -復 -萊 -氣 -軒 -華 -堃 -迮 -纟 -戶 -馬 -學 -裡 -電 -嶽 -獨 -マ -シ -サ -ジ -燘 -袪 -環 -❤ -臺 -灣 -専 -賣 -孖 -聖 -攝 -線 -▪ -α -傢 -俬 -夢 -達 -莊 -喬 -貝 -薩 -劍 -羅 -壓 -棛 -饦 -尃 -璈 -囍 -醫 -G -I -A -# -N -鷄 -髙 -嬰 -啓 -約 -隹 -潔 -賴 -藝 -~ -寶 -籣 -麺 -  -嶺 -√ -義 -網 -峩 -長 -∧ -魚 -機 -構 -② -鳯 -偉 -L -B -㙟 -畵 -鴿 -' -詩 -溝 -嚞 -屌 -藔 -佧 -玥 -蘭 -織 -1 -3 -9 -0 -7 -點 -砭 -鴨 -鋪 -銘 -廳 -弍 -‧ -創 -湯 -坶 -℃ -卩 -骝 -& -烜 -荘 -當 -潤 -扞 -係 -懷 -碶 -钅 -蚨 -讠 -☆ -叢 -爲 -埗 -涫 -塗 -→ -楽 -現 -鯨 -愛 -瑪 -鈺 -忄 -悶 -藥 -飾 -樓 -視 -孬 -ㆍ -燚 -苪 -師 -① -丼 -锽 -│ -韓 -標 -è -兒 -閏 -匋 -張 -漢 -Ü -髪 -會 -閑 -檔 -習 -裝 -の -峯 -菘 -輝 -И -雞 -釣 -億 -浐 -K -O -R -8 -H -E -P -T -W -D -S -C -M -F -姌 -饹 -» -晞 -廰 -ä -嵯 -鷹 -負 -飲 -絲 -冚 -楗 -澤 -綫 -區 -❋ -← -質 -靑 -揚 -③ -滬 -統 -産 -協 -﹑ -乸 -畐 -經 -運 -際 -洺 -岽 -為 -粵 -諾 -崋 -豐 -碁 -ɔ -V -2 -6 -齋 -誠 -訂 -´ -勑 -雙 -陳 -無 -í -泩 -媄 -夌 -刂 -i -c -t -o -r -a -嘢 -耄 -燴 -暃 -壽 -媽 -靈 -抻 -體 -唻 -É -冮 -甹 -鎮 -錦 -ʌ -蜛 -蠄 -尓 -駕 -戀 -飬 -逹 -倫 -貴 -極 -Я -Й -寬 -磚 -嶪 -郎 -職 -| -間 -n -d -剎 -伈 -課 -飛 -橋 -瘊 -№ -譜 -骓 -圗 -滘 -縣 -粿 -咅 -養 -濤 -彳 -® -% -Ⅱ -啰 -㴪 -見 -矞 -薬 -糁 -邨 -鲮 -顔 -罱 -З -選 -話 -贏 -氪 -俵 -競 -瑩 -繡 -枱 -β -綉 -á -獅 -爾 -™ -麵 -戋 -淩 -徳 -個 -劇 -場 -務 -簡 -寵 -h -實 -膠 -轱 -圖 -築 -嘣 -樹 -㸃 -營 -耵 -孫 -饃 -鄺 -飯 -麯 -遠 -輸 -坫 -孃 -乚 -閃 -鏢 -㎡ -題 -廠 -關 -↑ -爺 -將 -軍 -連 -篦 -覌 -參 -箸 -- -窠 -棽 -寕 -夀 -爰 -歐 -呙 -閥 -頡 -熱 -雎 -垟 -裟 -凬 -勁 -帑 -馕 -夆 -疌 -枼 -馮 -貨 -蒤 -樸 -彧 -旸 -靜 -龢 -暢 -㐱 -鳥 -珺 -鏡 -灡 -爭 -堷 -廚 -Ó -騰 -診 -┅ -蘇 -褔 -凱 -頂 -豕 -亞 -帥 -嘬 -⊥ -仺 -桖 -複 -饣 -絡 -穂 -顏 -棟 -納 -▏ -濟 -親 -設 -計 -攵 -埌 -烺 -ò -頤 -燦 -蓮 -撻 -節 -講 -濱 -濃 -娽 -洳 -朿 -燈 -鈴 -護 -膚 -铔 -過 -補 -Z -U -5 -4 -坋 -闿 -䖝 -餘 -缐 -铞 -貿 -铪 -桼 -趙 -鍊 -[ -㐂 -垚 -菓 -揸 -捲 -鐘 -滏 -𣇉 -爍 -輪 -燜 -鴻 -鮮 -動 -鹞 -鷗 -丄 -慶 -鉌 -翥 -飮 -腸 -⇋ -漁 -覺 -來 -熘 -昴 -翏 -鲱 -圧 -鄉 -萭 -頔 -爐 -嫚 -г -貭 -類 -聯 -幛 -輕 -訓 -鑒 -夋 -锨 -芃 -珣 -䝉 -扙 -嵐 -銷 -處 -ㄱ -語 -誘 -苝 -歸 -儀 -燒 -楿 -內 -粢 -葒 -奧 -麥 -礻 -滿 -蠔 -穵 -瞭 -態 -鱬 -榞 -硂 -鄭 -黃 -煙 -祐 -奓 -逺 -* -瑄 -獲 -聞 -薦 -讀 -這 -樣 -決 -問 -啟 -們 -執 -説 -轉 -單 -隨 -唘 -帶 -倉 -庫 -還 -贈 -尙 -皺 -■ -餅 -產 -○ -∈ -報 -狀 -楓 -賠 -琯 -嗮 -禮 -` -傳 -> -≤ -嗞 -Φ -≥ -換 -咭 -∣ -↓ -曬 -ε -応 -寫 -″ -終 -様 -純 -費 -療 -聨 -凍 -壐 -郵 -ü -黒 -∫ -製 -塊 -調 -軽 -確 -撃 -級 -馴 -Ⅲ -涇 -繹 -數 -碼 -證 -狒 -処 -劑 -< -晧 -賀 -衆 -] -櫥 -兩 -陰 -絶 -對 -鯉 -憶 -◎ -p -e -Y -蕒 -煖 -頓 -測 -試 -鼽 -僑 -碩 -妝 -帯 -≈ -鐡 -舖 -權 -喫 -倆 -ˋ -該 -悅 -ā -俫 -. -f -s -b -m -k -g -u -j -貼 -淨 -濕 -針 -適 -備 -l -/ -給 -謢 -強 -觸 -衛 -與 -⊙ -$ -緯 -變 -⑴ -⑵ -⑶ -㎏ -殺 -∩ -幚 -─ -價 -▲ -離 -ú -ó -飄 -烏 -関 -閟 -﹝ -﹞ -邏 -輯 -鍵 -驗 -訣 -導 -歷 -屆 -層 -▼ -儱 -錄 -熳 -ē -艦 -吋 -錶 -辧 -飼 -顯 -④ -禦 -販 -気 -対 -枰 -閩 -紀 -幹 -瞓 -貊 -淚 -△ -眞 -墊 -Ω -獻 -褲 -縫 -緑 -亜 -鉅 -餠 -{ -} -◆ -蘆 -薈 -█ -◇ -溫 -彈 -晳 -粧 -犸 -穩 -訊 -崬 -凖 -熥 -П -舊 -條 -紋 -圍 -Ⅳ -筆 -尷 -難 -雜 -錯 -綁 -識 -頰 -鎖 -艶 -□ -殁 -殼 -⑧ -├ -▕ -鵬 -ǐ -ō -ǒ -糝 -綱 -▎ -μ -盜 -饅 -醬 -籤 -蓋 -釀 -鹽 -據 -à -ɡ -辦 -◥ -彐 -┌ -婦 -獸 -鲩 -伱 -ī -蒟 -蒻 -齊 -袆 -腦 -寧 -凈 -妳 -煥 -詢 -偽 -謹 -啫 -鯽 -騷 -鱸 -損 -傷 -鎻 -髮 -買 -冏 -儥 -両 -﹢ -∞ -載 -喰 -z -羙 -悵 -燙 -曉 -員 -組 -徹 -艷 -痠 -鋼 -鼙 -縮 -細 -嚒 -爯 -≠ -維 -" -鱻 -壇 -厍 -帰 -浥 -犇 -薡 -軎 -² -應 -醜 -刪 -緻 -鶴 -賜 -噁 -軌 -尨 -镔 -鷺 -槗 -彌 -葚 -濛 -請 -溇 -緹 -賢 -訪 -獴 -瑅 -資 -縤 -陣 -蕟 -栢 -韻 -祼 -恁 -伢 -謝 -劃 -涑 -總 -衖 -踺 -砋 -凉 -籃 -駿 -苼 -瘋 -昽 -紡 -驊 -腎 -﹗ -響 -杋 -剛 -嚴 -禪 -歓 -槍 -傘 -檸 -檫 -炣 -勢 -鏜 -鎢 -銑 -尐 -減 -奪 -惡 -θ -僮 -婭 -臘 -ū -ì -殻 -鉄 -∑ -蛲 -焼 -緖 -續 -紹 -懮 \ No newline at end of file diff --git a/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu(slim)/cls_opt.nb b/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu(slim)/cls_opt.nb deleted file mode 100644 index 1bfd0ef2..00000000 Binary files a/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu(slim)/cls_opt.nb and /dev/null differ diff --git a/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu(slim)/det_opt.nb b/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu(slim)/det_opt.nb deleted file mode 100644 index 74e021f8..00000000 Binary files a/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu(slim)/det_opt.nb and /dev/null differ diff --git a/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu(slim)/rec_opt.nb b/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu(slim)/rec_opt.nb deleted file mode 100644 index f0b726ec..00000000 Binary files a/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu(slim)/rec_opt.nb and /dev/null differ diff --git a/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu/cls_opt.nb b/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu/cls_opt.nb deleted file mode 100644 index 6dc3c397..00000000 Binary files a/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu/cls_opt.nb and /dev/null differ diff --git a/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu/det_opt.nb b/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu/det_opt.nb deleted file mode 100644 index 43fdd7f7..00000000 Binary files a/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu/det_opt.nb and /dev/null differ diff --git a/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu/rec_opt.nb b/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu/rec_opt.nb deleted file mode 100644 index 00fee114..00000000 Binary files a/libs/paddleocr/src/main/assets/models/ocr_v3_for_cpu/rec_opt.nb and /dev/null differ diff --git a/libs/paddleocr/src/main/cpp/CMakeLists.txt b/libs/paddleocr/src/main/cpp/CMakeLists.txt deleted file mode 100644 index 8d26f7f2..00000000 --- a/libs/paddleocr/src/main/cpp/CMakeLists.txt +++ /dev/null @@ -1,94 +0,0 @@ -# For more information about using CMake with Android Studio, read the -# documentation: https://d.android.com/studio/projects/add-native-code.html - -# Sets the minimum version of CMake required to build the native library. - -cmake_minimum_required(VERSION 3.4.1) - -# Creates and names a library, sets it as either STATIC or SHARED, and provides -# the relative paths to its source code. You can define multiple libraries, and -# CMake builds them for you. Gradle automatically packages shared libraries with -# your APK. - -get_filename_component(MODULE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../.." ABSOLUTE) -set(PaddleLite_DIR "${MODULE_DIR}/PaddleLite") -include_directories(${PaddleLite_DIR}/cxx/include) - -set(OpenCV_DIR "${MODULE_DIR}/src/sdk/native/jni") -message(STATUS "opencv dir: ${OpenCV_DIR}") -find_package(OpenCV REQUIRED) -message(STATUS "OpenCV libraries: ${OpenCV_LIBS}") -include_directories(${OpenCV_INCLUDE_DIRS}) -aux_source_directory(. SOURCES) -set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -ffast-math -Ofast -Os" - ) -set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -fdata-sections -ffunction-sections" - ) -set(CMAKE_SHARED_LINKER_FLAGS - "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections -Wl,-z,nocopyreloc") - -add_library( - # Sets the name of the library. - Native - # Sets the library as a shared library. - SHARED - # Provides a relative path to your source file(s). - ${SOURCES}) - -find_library( - # Sets the name of the path variable. - log-lib - # Specifies the name of the NDK library that you want CMake to locate. - log) - -add_library( - # Sets the name of the library. - paddle_light_api_shared - # Sets the library as a shared library. - SHARED - # Provides a relative path to your source file(s). - IMPORTED) - -set_target_properties( - # Specifies the target library. - paddle_light_api_shared - # Specifies the parameter you want to define. - PROPERTIES - IMPORTED_LOCATION - ${PaddleLite_DIR}/cxx/libs/${ANDROID_ABI}/libpaddle_light_api_shared.so - # Provides the path to the library you want to import. -) - - -# Specifies libraries CMake should link to your target library. You can link -# multiple libraries, such as libraries you define in this build script, -# prebuilt third-party libraries, or system libraries. - -target_link_libraries( - # Specifies the target library. - Native - paddle_light_api_shared - ${OpenCV_LIBS} - GLESv2 - EGL - jnigraphics - ${log-lib} -) - -add_custom_command( - TARGET Native - POST_BUILD - COMMAND - ${CMAKE_COMMAND} -E copy - ${PaddleLite_DIR}/cxx/libs/${ANDROID_ABI}/libc++_shared.so - ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libc++_shared.so) - -add_custom_command( - TARGET Native - POST_BUILD - COMMAND - ${CMAKE_COMMAND} -E copy - ${PaddleLite_DIR}/cxx/libs/${ANDROID_ABI}/libpaddle_light_api_shared.so - ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libpaddle_light_api_shared.so) diff --git a/libs/paddleocr/src/main/cpp/common.h b/libs/paddleocr/src/main/cpp/common.h deleted file mode 100644 index fc474078..00000000 --- a/libs/paddleocr/src/main/cpp/common.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Created by fu on 4/25/18. -// - -#pragma once -#import -#import - -#ifdef __ANDROID__ - -#include - -#define LOG_TAG "OCR_NDK" - -#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) -#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) -#else -#include -#define LOGI(format, ...) \ - fprintf(stdout, "[" LOG_TAG "]" format "\n", ##__VA_ARGS__) -#define LOGW(format, ...) \ - fprintf(stdout, "[" LOG_TAG "]" format "\n", ##__VA_ARGS__) -#define LOGE(format, ...) \ - fprintf(stderr, "[" LOG_TAG "]Error: " format "\n", ##__VA_ARGS__) -#endif - -enum RETURN_CODE { RETURN_OK = 0 }; - -enum NET_TYPE { NET_OCR = 900100, NET_OCR_INTERNAL = 991008 }; - -template inline T product(const std::vector &vec) { - if (vec.empty()) { - return 0; - } - return std::accumulate(vec.begin(), vec.end(), 1, std::multiplies()); -} diff --git a/libs/paddleocr/src/main/cpp/native.cpp b/libs/paddleocr/src/main/cpp/native.cpp deleted file mode 100644 index b7a34e59..00000000 --- a/libs/paddleocr/src/main/cpp/native.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// Created by fujiayi on 2020/7/5. -// - -#include "native.h" -#include "ocr_ppredictor.h" -#include -#include -#include - -static paddle::lite_api::PowerMode str_to_cpu_mode(const std::string &cpu_mode); - -extern "C" JNIEXPORT jlong JNICALL -Java_com_baidu_paddle_lite_ocr_OCRPredictorNative_init( - JNIEnv *env, jobject thiz, jstring j_det_model_path, - jstring j_rec_model_path, jstring j_cls_model_path, jint j_use_opencl, jint j_thread_num, - jstring j_cpu_mode) { - std::string det_model_path = jstring_to_cpp_string(env, j_det_model_path); - std::string rec_model_path = jstring_to_cpp_string(env, j_rec_model_path); - std::string cls_model_path = jstring_to_cpp_string(env, j_cls_model_path); - int thread_num = j_thread_num; - std::string cpu_mode = jstring_to_cpp_string(env, j_cpu_mode); - ppredictor::OCR_Config conf; - conf.use_opencl = j_use_opencl; - conf.thread_num = thread_num; - conf.mode = str_to_cpu_mode(cpu_mode); - ppredictor::OCR_PPredictor *orc_predictor = - new ppredictor::OCR_PPredictor{conf}; - orc_predictor->init_from_file(det_model_path, rec_model_path, cls_model_path); - return reinterpret_cast(orc_predictor); -} - -/** - * "LITE_POWER_HIGH" convert to paddle::lite_api::LITE_POWER_HIGH - * @param cpu_mode - * @return - */ -static paddle::lite_api::PowerMode -str_to_cpu_mode(const std::string &cpu_mode) { - static std::map cpu_mode_map{ - {"LITE_POWER_HIGH", paddle::lite_api::LITE_POWER_HIGH}, - {"LITE_POWER_LOW", paddle::lite_api::LITE_POWER_HIGH}, - {"LITE_POWER_FULL", paddle::lite_api::LITE_POWER_FULL}, - {"LITE_POWER_NO_BIND", paddle::lite_api::LITE_POWER_NO_BIND}, - {"LITE_POWER_RAND_HIGH", paddle::lite_api::LITE_POWER_RAND_HIGH}, - {"LITE_POWER_RAND_LOW", paddle::lite_api::LITE_POWER_RAND_LOW}}; - std::string upper_key; - std::transform(cpu_mode.cbegin(), cpu_mode.cend(), upper_key.begin(), - ::toupper); - auto index = cpu_mode_map.find(upper_key.c_str()); - if (index == cpu_mode_map.end()) { - // 可能因为大小写转换后找不到 直接通过入参查找 - index = cpu_mode_map.find(cpu_mode); - if (index != cpu_mode_map.end()) { - LOGI("find cpu_mode by &cpu_mode %s", cpu_mode.c_str()); - return index->second; - } - LOGE("cpu_mode not found %s", upper_key.c_str()); - return paddle::lite_api::LITE_POWER_HIGH; - } else { - return index->second; - } -} - -extern "C" JNIEXPORT jfloatArray JNICALL -Java_com_baidu_paddle_lite_ocr_OCRPredictorNative_forward( - JNIEnv *env, jobject thiz, jlong java_pointer, - jobject original_image,jint j_max_size_len, jint j_run_det, jint j_run_cls, - jint j_run_rec) { - LOGI("begin to run native forward"); - if (java_pointer == 0) { - LOGE("JAVA pointer is NULL"); - return cpp_array_to_jfloatarray(env, nullptr, 0); - } - - cv::Mat origin = bitmap_to_cv_mat(env, original_image); - if (origin.size == nullptr) { - LOGE("origin bitmap cannot convert to CV Mat"); - return cpp_array_to_jfloatarray(env, nullptr, 0); - } - - int max_size_len = j_max_size_len; - int run_det = j_run_det; - int run_cls = j_run_cls; - int run_rec = j_run_rec; - - ppredictor::OCR_PPredictor *ppredictor = - (ppredictor::OCR_PPredictor *)java_pointer; - std::vector dims_arr; - std::vector results = - ppredictor->infer_ocr(origin, max_size_len, run_det, run_cls, run_rec); - LOGI("infer_ocr finished with boxes %ld", results.size()); - - // 这里将std::vector 序列化成 - // float数组,传输到java层再反序列化 - std::vector float_arr; - for (const ppredictor::OCRPredictResult &r : results) { - float_arr.push_back(r.points.size()); - float_arr.push_back(r.word_index.size()); - float_arr.push_back(r.score); - // add det point - for (const std::vector &point : r.points) { - float_arr.push_back(point.at(0)); - float_arr.push_back(point.at(1)); - } - // add rec word idx - for (int index : r.word_index) { - float_arr.push_back(index); - } - // add cls result - float_arr.push_back(r.cls_label); - float_arr.push_back(r.cls_score); - } - return cpp_array_to_jfloatarray(env, float_arr.data(), float_arr.size()); -} - -extern "C" JNIEXPORT void JNICALL -Java_com_baidu_paddle_lite_ocr_OCRPredictorNative_release( - JNIEnv *env, jobject thiz, jlong java_pointer) { - if (java_pointer == 0) { - LOGE("JAVA pointer is NULL"); - return; - } - ppredictor::OCR_PPredictor *ppredictor = - (ppredictor::OCR_PPredictor *)java_pointer; - delete ppredictor; -} \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/native.h b/libs/paddleocr/src/main/cpp/native.h deleted file mode 100644 index 9b8e4e40..00000000 --- a/libs/paddleocr/src/main/cpp/native.h +++ /dev/null @@ -1,137 +0,0 @@ -// -// Created by fujiayi on 2020/7/5. -// - -#pragma once - -#include "common.h" -#include -#include -#include -#include -#include - -inline std::string jstring_to_cpp_string(JNIEnv *env, jstring jstr) { - // In java, a unicode char will be encoded using 2 bytes (utf16). - // so jstring will contain characters utf16. std::string in c++ is - // essentially a string of bytes, not characters, so if we want to - // pass jstring from JNI to c++, we have convert utf16 to bytes. - if (!jstr) { - return ""; - } - const jclass stringClass = env->GetObjectClass(jstr); - const jmethodID getBytes = - env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B"); - const jbyteArray stringJbytes = (jbyteArray)env->CallObjectMethod( - jstr, getBytes, env->NewStringUTF("UTF-8")); - - size_t length = (size_t)env->GetArrayLength(stringJbytes); - jbyte *pBytes = env->GetByteArrayElements(stringJbytes, NULL); - - std::string ret = std::string(reinterpret_cast(pBytes), length); - env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT); - - env->DeleteLocalRef(stringJbytes); - env->DeleteLocalRef(stringClass); - return ret; -} - -inline jstring cpp_string_to_jstring(JNIEnv *env, std::string str) { - auto *data = str.c_str(); - jclass strClass = env->FindClass("java/lang/String"); - jmethodID strClassInitMethodID = - env->GetMethodID(strClass, "", "([BLjava/lang/String;)V"); - - jbyteArray bytes = env->NewByteArray(strlen(data)); - env->SetByteArrayRegion(bytes, 0, strlen(data), - reinterpret_cast(data)); - - jstring encoding = env->NewStringUTF("UTF-8"); - jstring res = (jstring)( - env->NewObject(strClass, strClassInitMethodID, bytes, encoding)); - - env->DeleteLocalRef(strClass); - env->DeleteLocalRef(encoding); - env->DeleteLocalRef(bytes); - - return res; -} - -inline jfloatArray cpp_array_to_jfloatarray(JNIEnv *env, const float *buf, - int64_t len) { - if (len == 0) { - return env->NewFloatArray(0); - } - jfloatArray result = env->NewFloatArray(len); - env->SetFloatArrayRegion(result, 0, len, buf); - return result; -} - -inline jintArray cpp_array_to_jintarray(JNIEnv *env, const int *buf, - int64_t len) { - jintArray result = env->NewIntArray(len); - env->SetIntArrayRegion(result, 0, len, buf); - return result; -} - -inline jbyteArray cpp_array_to_jbytearray(JNIEnv *env, const int8_t *buf, - int64_t len) { - jbyteArray result = env->NewByteArray(len); - env->SetByteArrayRegion(result, 0, len, buf); - return result; -} - -inline jlongArray int64_vector_to_jlongarray(JNIEnv *env, - const std::vector &vec) { - jlongArray result = env->NewLongArray(vec.size()); - jlong *buf = new jlong[vec.size()]; - for (size_t i = 0; i < vec.size(); ++i) { - buf[i] = (jlong)vec[i]; - } - env->SetLongArrayRegion(result, 0, vec.size(), buf); - delete[] buf; - return result; -} - -inline std::vector jlongarray_to_int64_vector(JNIEnv *env, - jlongArray data) { - int data_size = env->GetArrayLength(data); - jlong *data_ptr = env->GetLongArrayElements(data, nullptr); - std::vector data_vec(data_ptr, data_ptr + data_size); - env->ReleaseLongArrayElements(data, data_ptr, 0); - return data_vec; -} - -inline std::vector jfloatarray_to_float_vector(JNIEnv *env, - jfloatArray data) { - int data_size = env->GetArrayLength(data); - jfloat *data_ptr = env->GetFloatArrayElements(data, nullptr); - std::vector data_vec(data_ptr, data_ptr + data_size); - env->ReleaseFloatArrayElements(data, data_ptr, 0); - return data_vec; -} - -inline cv::Mat bitmap_to_cv_mat(JNIEnv *env, jobject bitmap) { - AndroidBitmapInfo info; - int result = AndroidBitmap_getInfo(env, bitmap, &info); - if (result != ANDROID_BITMAP_RESULT_SUCCESS) { - LOGE("AndroidBitmap_getInfo failed, result: %d", result); - return cv::Mat{}; - } - if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { - LOGE("Bitmap format is not RGBA_8888 !"); - return cv::Mat{}; - } - unsigned char *srcData = NULL; - AndroidBitmap_lockPixels(env, bitmap, (void **)&srcData); - cv::Mat mat = cv::Mat::zeros(info.height, info.width, CV_8UC4); - memcpy(mat.data, srcData, info.height * info.width * 4); - AndroidBitmap_unlockPixels(env, bitmap); - cv::cvtColor(mat, mat, cv::COLOR_RGBA2BGR); - /** - if (!cv::imwrite("/sdcard/1/copy.jpg", mat)){ - LOGE("Write image failed " ); - } - */ - return mat; -} diff --git a/libs/paddleocr/src/main/cpp/ocr_clipper.cpp b/libs/paddleocr/src/main/cpp/ocr_clipper.cpp deleted file mode 100644 index 4a531fcf..00000000 --- a/libs/paddleocr/src/main/cpp/ocr_clipper.cpp +++ /dev/null @@ -1,4380 +0,0 @@ -/******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 6.4.2 * -* Date : 27 February 2017 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2017 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -* Attributions: * -* The code in this library is an extension of Bala Vatti's clipping algorithm: * -* "A generic solution to polygon clipping" * -* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * -* http://portal.acm.org/citation.cfm?id=129906 * -* * -* Computer graphics and geometric modeling: implementation and algorithms * -* By Max K. Agoston * -* Springer; 1 edition (January 4, 2005) * -* http://books.google.com/books?q=vatti+clipping+agoston * -* * -* See also: * -* "Polygon Offsetting by Computing Winding Numbers" * -* Paper no. DETC2005-85513 pp. 565-575 * -* ASME 2005 International Design Engineering Technical Conferences * -* and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24-28, 2005 , Long Beach, California, USA * -* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * -* * -*******************************************************************************/ - -/******************************************************************************* -* * -* This is a translation of the Delphi Clipper library and the naming style * -* used has retained a Delphi flavour. * -* * -*******************************************************************************/ - -#include "ocr_clipper.hpp" -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ClipperLib { - -static double const pi = 3.141592653589793238; -static double const two_pi = pi * 2; -static double const def_arc_tolerance = 0.25; - -enum Direction { dRightToLeft, dLeftToRight }; - -static int const Unassigned = -1; // edge not currently 'owning' a solution -static int const Skip = -2; // edge that would otherwise close a path - -#define HORIZONTAL (-1.0E+40) -#define TOLERANCE (1.0e-20) -#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) - -struct TEdge { - IntPoint Bot; - IntPoint Curr; // current (updated for every new scanbeam) - IntPoint Top; - double Dx; - PolyType PolyTyp; - EdgeSide Side; // side only refers to current side of solution poly - int WindDelta; // 1 or -1 depending on winding direction - int WindCnt; - int WindCnt2; // winding count of the opposite polytype - int OutIdx; - TEdge *Next; - TEdge *Prev; - TEdge *NextInLML; - TEdge *NextInAEL; - TEdge *PrevInAEL; - TEdge *NextInSEL; - TEdge *PrevInSEL; -}; - -struct IntersectNode { - TEdge *Edge1; - TEdge *Edge2; - IntPoint Pt; -}; - -struct LocalMinimum { - cInt Y; - TEdge *LeftBound; - TEdge *RightBound; -}; - -struct OutPt; - -// OutRec: contains a path in the clipping solution. Edges in the AEL will -// carry a pointer to an OutRec when they are part of the clipping solution. -struct OutRec { - int Idx; - bool IsHole; - bool IsOpen; - OutRec *FirstLeft; // see comments in clipper.pas - PolyNode *PolyNd; - OutPt *Pts; - OutPt *BottomPt; -}; - -struct OutPt { - int Idx; - IntPoint Pt; - OutPt *Next; - OutPt *Prev; -}; - -struct Join { - OutPt *OutPt1; - OutPt *OutPt2; - IntPoint OffPt; -}; - -struct LocMinSorter { - inline bool operator()(const LocalMinimum &locMin1, - const LocalMinimum &locMin2) { - return locMin2.Y < locMin1.Y; - } -}; - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -inline cInt Round(double val) { - if ((val < 0)) - return static_cast(val - 0.5); - else - return static_cast(val + 0.5); -} -//------------------------------------------------------------------------------ - -inline cInt Abs(cInt val) { return val < 0 ? -val : val; } - -//------------------------------------------------------------------------------ -// PolyTree methods ... -//------------------------------------------------------------------------------ - -void PolyTree::Clear() { - for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i) - delete AllNodes[i]; - AllNodes.resize(0); - Childs.resize(0); -} -//------------------------------------------------------------------------------ - -PolyNode *PolyTree::GetFirst() const { - if (!Childs.empty()) - return Childs[0]; - else - return 0; -} -//------------------------------------------------------------------------------ - -int PolyTree::Total() const { - int result = (int)AllNodes.size(); - // with negative offsets, ignore the hidden outer polygon ... - if (result > 0 && Childs[0] != AllNodes[0]) - result--; - return result; -} - -//------------------------------------------------------------------------------ -// PolyNode methods ... -//------------------------------------------------------------------------------ - -PolyNode::PolyNode() : Parent(0), Index(0), m_IsOpen(false) {} -//------------------------------------------------------------------------------ - -int PolyNode::ChildCount() const { return (int)Childs.size(); } -//------------------------------------------------------------------------------ - -void PolyNode::AddChild(PolyNode &child) { - unsigned cnt = (unsigned)Childs.size(); - Childs.push_back(&child); - child.Parent = this; - child.Index = cnt; -} -//------------------------------------------------------------------------------ - -PolyNode *PolyNode::GetNext() const { - if (!Childs.empty()) - return Childs[0]; - else - return GetNextSiblingUp(); -} -//------------------------------------------------------------------------------ - -PolyNode *PolyNode::GetNextSiblingUp() const { - if (!Parent) // protects against PolyTree.GetNextSiblingUp() - return 0; - else if (Index == Parent->Childs.size() - 1) - return Parent->GetNextSiblingUp(); - else - return Parent->Childs[Index + 1]; -} -//------------------------------------------------------------------------------ - -bool PolyNode::IsHole() const { - bool result = true; - PolyNode *node = Parent; - while (node) { - result = !result; - node = node->Parent; - } - return result; -} -//------------------------------------------------------------------------------ - -bool PolyNode::IsOpen() const { return m_IsOpen; } -//------------------------------------------------------------------------------ - -#ifndef use_int32 - -//------------------------------------------------------------------------------ -// Int128 class (enables safe math on signed 64bit integers) -// eg Int128 val1((long64)9223372036854775807); //ie 2^63 -1 -// Int128 val2((long64)9223372036854775807); -// Int128 val3 = val1 * val2; -// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37) -//------------------------------------------------------------------------------ - -class Int128 { -public: - ulong64 lo; - long64 hi; - - Int128(long64 _lo = 0) { - lo = (ulong64)_lo; - if (_lo < 0) - hi = -1; - else - hi = 0; - } - - Int128(const Int128 &val) : lo(val.lo), hi(val.hi) {} - - Int128(const long64 &_hi, const ulong64 &_lo) : lo(_lo), hi(_hi) {} - - Int128 &operator=(const long64 &val) { - lo = (ulong64)val; - if (val < 0) - hi = -1; - else - hi = 0; - return *this; - } - - bool operator==(const Int128 &val) const { - return (hi == val.hi && lo == val.lo); - } - - bool operator!=(const Int128 &val) const { return !(*this == val); } - - bool operator>(const Int128 &val) const { - if (hi != val.hi) - return hi > val.hi; - else - return lo > val.lo; - } - - bool operator<(const Int128 &val) const { - if (hi != val.hi) - return hi < val.hi; - else - return lo < val.lo; - } - - bool operator>=(const Int128 &val) const { return !(*this < val); } - - bool operator<=(const Int128 &val) const { return !(*this > val); } - - Int128 &operator+=(const Int128 &rhs) { - hi += rhs.hi; - lo += rhs.lo; - if (lo < rhs.lo) - hi++; - return *this; - } - - Int128 operator+(const Int128 &rhs) const { - Int128 result(*this); - result += rhs; - return result; - } - - Int128 &operator-=(const Int128 &rhs) { - *this += -rhs; - return *this; - } - - Int128 operator-(const Int128 &rhs) const { - Int128 result(*this); - result -= rhs; - return result; - } - - Int128 operator-() const // unary negation - { - if (lo == 0) - return Int128(-hi, 0); - else - return Int128(~hi, ~lo + 1); - } - - operator double() const { - const double shift64 = 18446744073709551616.0; // 2^64 - if (hi < 0) { - if (lo == 0) - return (double)hi * shift64; - else - return -(double)(~lo + ~hi * shift64); - } else - return (double)(lo + hi * shift64); - } -}; -//------------------------------------------------------------------------------ - -Int128 Int128Mul(long64 lhs, long64 rhs) { - bool negate = (lhs < 0) != (rhs < 0); - - if (lhs < 0) - lhs = -lhs; - ulong64 int1Hi = ulong64(lhs) >> 32; - ulong64 int1Lo = ulong64(lhs & 0xFFFFFFFF); - - if (rhs < 0) - rhs = -rhs; - ulong64 int2Hi = ulong64(rhs) >> 32; - ulong64 int2Lo = ulong64(rhs & 0xFFFFFFFF); - - // nb: see comments in clipper.pas - ulong64 a = int1Hi * int2Hi; - ulong64 b = int1Lo * int2Lo; - ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; - - Int128 tmp; - tmp.hi = long64(a + (c >> 32)); - tmp.lo = long64(c << 32); - tmp.lo += long64(b); - if (tmp.lo < b) - tmp.hi++; - if (negate) - tmp = -tmp; - return tmp; -}; -#endif - -//------------------------------------------------------------------------------ -// Miscellaneous global functions -//------------------------------------------------------------------------------ - -bool Orientation(const Path &poly) { return Area(poly) >= 0; } -//------------------------------------------------------------------------------ - -double Area(const Path &poly) { - int size = (int)poly.size(); - if (size < 3) - return 0; - - double a = 0; - for (int i = 0, j = size - 1; i < size; ++i) { - a += ((double)poly[j].X + poly[i].X) * ((double)poly[j].Y - poly[i].Y); - j = i; - } - return -a * 0.5; -} -//------------------------------------------------------------------------------ - -double Area(const OutPt *op) { - const OutPt *startOp = op; - if (!op) - return 0; - double a = 0; - do { - a += (double)(op->Prev->Pt.X + op->Pt.X) * - (double)(op->Prev->Pt.Y - op->Pt.Y); - op = op->Next; - } while (op != startOp); - return a * 0.5; -} -//------------------------------------------------------------------------------ - -double Area(const OutRec &outRec) { return Area(outRec.Pts); } -//------------------------------------------------------------------------------ - -bool PointIsVertex(const IntPoint &Pt, OutPt *pp) { - OutPt *pp2 = pp; - do { - if (pp2->Pt == Pt) - return true; - pp2 = pp2->Next; - } while (pp2 != pp); - return false; -} -//------------------------------------------------------------------------------ - -// See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & -// Agathos -// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf -int PointInPolygon(const IntPoint &pt, const Path &path) { - // returns 0 if false, +1 if true, -1 if pt ON polygon boundary - int result = 0; - size_t cnt = path.size(); - if (cnt < 3) - return 0; - IntPoint ip = path[0]; - for (size_t i = 1; i <= cnt; ++i) { - IntPoint ipNext = (i == cnt ? path[0] : path[i]); - if (ipNext.Y == pt.Y) { - if ((ipNext.X == pt.X) || - (ip.Y == pt.Y && ((ipNext.X > pt.X) == (ip.X < pt.X)))) - return -1; - } - if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y)) { - if (ip.X >= pt.X) { - if (ipNext.X > pt.X) - result = 1 - result; - else { - double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); - if (!d) - return -1; - if ((d > 0) == (ipNext.Y > ip.Y)) - result = 1 - result; - } - } else { - if (ipNext.X > pt.X) { - double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); - if (!d) - return -1; - if ((d > 0) == (ipNext.Y > ip.Y)) - result = 1 - result; - } - } - } - ip = ipNext; - } - return result; -} -//------------------------------------------------------------------------------ - -int PointInPolygon(const IntPoint &pt, OutPt *op) { - // returns 0 if false, +1 if true, -1 if pt ON polygon boundary - int result = 0; - OutPt *startOp = op; - for (;;) { - if (op->Next->Pt.Y == pt.Y) { - if ((op->Next->Pt.X == pt.X) || - (op->Pt.Y == pt.Y && ((op->Next->Pt.X > pt.X) == (op->Pt.X < pt.X)))) - return -1; - } - if ((op->Pt.Y < pt.Y) != (op->Next->Pt.Y < pt.Y)) { - if (op->Pt.X >= pt.X) { - if (op->Next->Pt.X > pt.X) - result = 1 - result; - else { - double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); - if (!d) - return -1; - if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) - result = 1 - result; - } - } else { - if (op->Next->Pt.X > pt.X) { - double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); - if (!d) - return -1; - if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) - result = 1 - result; - } - } - } - op = op->Next; - if (startOp == op) - break; - } - return result; -} -//------------------------------------------------------------------------------ - -bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2) { - OutPt *op = OutPt1; - do { - // nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon - int res = PointInPolygon(op->Pt, OutPt2); - if (res >= 0) - return res > 0; - op = op->Next; - } while (op != OutPt1); - return true; -} -//---------------------------------------------------------------------- - -bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range) { -#ifndef use_int32 - if (UseFullInt64Range) - return Int128Mul(e1.Top.Y - e1.Bot.Y, e2.Top.X - e2.Bot.X) == - Int128Mul(e1.Top.X - e1.Bot.X, e2.Top.Y - e2.Bot.Y); - else -#endif - return (e1.Top.Y - e1.Bot.Y) * (e2.Top.X - e2.Bot.X) == - (e1.Top.X - e1.Bot.X) * (e2.Top.Y - e2.Bot.Y); -} -//------------------------------------------------------------------------------ - -bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, const IntPoint pt3, - bool UseFullInt64Range) { -#ifndef use_int32 - if (UseFullInt64Range) - return Int128Mul(pt1.Y - pt2.Y, pt2.X - pt3.X) == - Int128Mul(pt1.X - pt2.X, pt2.Y - pt3.Y); - else -#endif - return (pt1.Y - pt2.Y) * (pt2.X - pt3.X) == - (pt1.X - pt2.X) * (pt2.Y - pt3.Y); -} -//------------------------------------------------------------------------------ - -bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, const IntPoint pt3, - const IntPoint pt4, bool UseFullInt64Range) { -#ifndef use_int32 - if (UseFullInt64Range) - return Int128Mul(pt1.Y - pt2.Y, pt3.X - pt4.X) == - Int128Mul(pt1.X - pt2.X, pt3.Y - pt4.Y); - else -#endif - return (pt1.Y - pt2.Y) * (pt3.X - pt4.X) == - (pt1.X - pt2.X) * (pt3.Y - pt4.Y); -} -//------------------------------------------------------------------------------ - -inline bool IsHorizontal(TEdge &e) { return e.Dx == HORIZONTAL; } -//------------------------------------------------------------------------------ - -inline double GetDx(const IntPoint pt1, const IntPoint pt2) { - return (pt1.Y == pt2.Y) ? HORIZONTAL - : (double)(pt2.X - pt1.X) / (pt2.Y - pt1.Y); -} -//--------------------------------------------------------------------------- - -inline void SetDx(TEdge &e) { - cInt dy = (e.Top.Y - e.Bot.Y); - if (dy == 0) - e.Dx = HORIZONTAL; - else - e.Dx = (double)(e.Top.X - e.Bot.X) / dy; -} -//--------------------------------------------------------------------------- - -inline void SwapSides(TEdge &Edge1, TEdge &Edge2) { - EdgeSide Side = Edge1.Side; - Edge1.Side = Edge2.Side; - Edge2.Side = Side; -} -//------------------------------------------------------------------------------ - -inline void SwapPolyIndexes(TEdge &Edge1, TEdge &Edge2) { - int OutIdx = Edge1.OutIdx; - Edge1.OutIdx = Edge2.OutIdx; - Edge2.OutIdx = OutIdx; -} -//------------------------------------------------------------------------------ - -inline cInt TopX(TEdge &edge, const cInt currentY) { - return (currentY == edge.Top.Y) - ? edge.Top.X - : edge.Bot.X + Round(edge.Dx * (currentY - edge.Bot.Y)); -} -//------------------------------------------------------------------------------ - -void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip) { -#ifdef use_xyz - ip.Z = 0; -#endif - - double b1, b2; - if (Edge1.Dx == Edge2.Dx) { - ip.Y = Edge1.Curr.Y; - ip.X = TopX(Edge1, ip.Y); - return; - } else if (Edge1.Dx == 0) { - ip.X = Edge1.Bot.X; - if (IsHorizontal(Edge2)) - ip.Y = Edge2.Bot.Y; - else { - b2 = Edge2.Bot.Y - (Edge2.Bot.X / Edge2.Dx); - ip.Y = Round(ip.X / Edge2.Dx + b2); - } - } else if (Edge2.Dx == 0) { - ip.X = Edge2.Bot.X; - if (IsHorizontal(Edge1)) - ip.Y = Edge1.Bot.Y; - else { - b1 = Edge1.Bot.Y - (Edge1.Bot.X / Edge1.Dx); - ip.Y = Round(ip.X / Edge1.Dx + b1); - } - } else { - b1 = Edge1.Bot.X - Edge1.Bot.Y * Edge1.Dx; - b2 = Edge2.Bot.X - Edge2.Bot.Y * Edge2.Dx; - double q = (b2 - b1) / (Edge1.Dx - Edge2.Dx); - ip.Y = Round(q); - if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) - ip.X = Round(Edge1.Dx * q + b1); - else - ip.X = Round(Edge2.Dx * q + b2); - } - - if (ip.Y < Edge1.Top.Y || ip.Y < Edge2.Top.Y) { - if (Edge1.Top.Y > Edge2.Top.Y) - ip.Y = Edge1.Top.Y; - else - ip.Y = Edge2.Top.Y; - if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) - ip.X = TopX(Edge1, ip.Y); - else - ip.X = TopX(Edge2, ip.Y); - } - // finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ... - if (ip.Y > Edge1.Curr.Y) { - ip.Y = Edge1.Curr.Y; - // use the more vertical edge to derive X ... - if (std::fabs(Edge1.Dx) > std::fabs(Edge2.Dx)) - ip.X = TopX(Edge2, ip.Y); - else - ip.X = TopX(Edge1, ip.Y); - } -} -//------------------------------------------------------------------------------ - -void ReversePolyPtLinks(OutPt *pp) { - if (!pp) - return; - OutPt *pp1, *pp2; - pp1 = pp; - do { - pp2 = pp1->Next; - pp1->Next = pp1->Prev; - pp1->Prev = pp2; - pp1 = pp2; - } while (pp1 != pp); -} -//------------------------------------------------------------------------------ - -void DisposeOutPts(OutPt *&pp) { - if (pp == 0) - return; - pp->Prev->Next = 0; - while (pp) { - OutPt *tmpPp = pp; - pp = pp->Next; - delete tmpPp; - } -} -//------------------------------------------------------------------------------ - -inline void InitEdge(TEdge *e, TEdge *eNext, TEdge *ePrev, const IntPoint &Pt) { - std::memset(e, 0, sizeof(TEdge)); - e->Next = eNext; - e->Prev = ePrev; - e->Curr = Pt; - e->OutIdx = Unassigned; -} -//------------------------------------------------------------------------------ - -void InitEdge2(TEdge &e, PolyType Pt) { - if (e.Curr.Y >= e.Next->Curr.Y) { - e.Bot = e.Curr; - e.Top = e.Next->Curr; - } else { - e.Top = e.Curr; - e.Bot = e.Next->Curr; - } - SetDx(e); - e.PolyTyp = Pt; -} -//------------------------------------------------------------------------------ - -TEdge *RemoveEdge(TEdge *e) { - // removes e from double_linked_list (but without removing from memory) - e->Prev->Next = e->Next; - e->Next->Prev = e->Prev; - TEdge *result = e->Next; - e->Prev = 0; // flag as removed (see ClipperBase.Clear) - return result; -} -//------------------------------------------------------------------------------ - -inline void ReverseHorizontal(TEdge &e) { - // swap horizontal edges' Top and Bottom x's so they follow the natural - // progression of the bounds - ie so their xbots will align with the - // adjoining lower edge. [Helpful in the ProcessHorizontal() method.] - std::swap(e.Top.X, e.Bot.X); -#ifdef use_xyz - std::swap(e.Top.Z, e.Bot.Z); -#endif -} -//------------------------------------------------------------------------------ - -void SwapPoints(IntPoint &pt1, IntPoint &pt2) { - IntPoint tmp = pt1; - pt1 = pt2; - pt2 = tmp; -} -//------------------------------------------------------------------------------ - -bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, - IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) { - // precondition: segments are Collinear. - if (Abs(pt1a.X - pt1b.X) > Abs(pt1a.Y - pt1b.Y)) { - if (pt1a.X > pt1b.X) - SwapPoints(pt1a, pt1b); - if (pt2a.X > pt2b.X) - SwapPoints(pt2a, pt2b); - if (pt1a.X > pt2a.X) - pt1 = pt1a; - else - pt1 = pt2a; - if (pt1b.X < pt2b.X) - pt2 = pt1b; - else - pt2 = pt2b; - return pt1.X < pt2.X; - } else { - if (pt1a.Y < pt1b.Y) - SwapPoints(pt1a, pt1b); - if (pt2a.Y < pt2b.Y) - SwapPoints(pt2a, pt2b); - if (pt1a.Y < pt2a.Y) - pt1 = pt1a; - else - pt1 = pt2a; - if (pt1b.Y > pt2b.Y) - pt2 = pt1b; - else - pt2 = pt2b; - return pt1.Y > pt2.Y; - } -} -//------------------------------------------------------------------------------ - -bool FirstIsBottomPt(const OutPt *btmPt1, const OutPt *btmPt2) { - OutPt *p = btmPt1->Prev; - while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) - p = p->Prev; - double dx1p = std::fabs(GetDx(btmPt1->Pt, p->Pt)); - p = btmPt1->Next; - while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) - p = p->Next; - double dx1n = std::fabs(GetDx(btmPt1->Pt, p->Pt)); - - p = btmPt2->Prev; - while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) - p = p->Prev; - double dx2p = std::fabs(GetDx(btmPt2->Pt, p->Pt)); - p = btmPt2->Next; - while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) - p = p->Next; - double dx2n = std::fabs(GetDx(btmPt2->Pt, p->Pt)); - - if (std::max(dx1p, dx1n) == std::max(dx2p, dx2n) && - std::min(dx1p, dx1n) == std::min(dx2p, dx2n)) - return Area(btmPt1) > 0; // if otherwise identical use orientation - else - return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); -} -//------------------------------------------------------------------------------ - -OutPt *GetBottomPt(OutPt *pp) { - OutPt *dups = 0; - OutPt *p = pp->Next; - while (p != pp) { - if (p->Pt.Y > pp->Pt.Y) { - pp = p; - dups = 0; - } else if (p->Pt.Y == pp->Pt.Y && p->Pt.X <= pp->Pt.X) { - if (p->Pt.X < pp->Pt.X) { - dups = 0; - pp = p; - } else { - if (p->Next != pp && p->Prev != pp) - dups = p; - } - } - p = p->Next; - } - if (dups) { - // there appears to be at least 2 vertices at BottomPt so ... - while (dups != p) { - if (!FirstIsBottomPt(p, dups)) - pp = dups; - dups = dups->Next; - while (dups->Pt != pp->Pt) - dups = dups->Next; - } - } - return pp; -} -//------------------------------------------------------------------------------ - -bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1, const IntPoint pt2, - const IntPoint pt3) { - if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2)) - return false; - else if (pt1.X != pt3.X) - return (pt2.X > pt1.X) == (pt2.X < pt3.X); - else - return (pt2.Y > pt1.Y) == (pt2.Y < pt3.Y); -} -//------------------------------------------------------------------------------ - -bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b) { - if (seg1a > seg1b) - std::swap(seg1a, seg1b); - if (seg2a > seg2b) - std::swap(seg2a, seg2b); - return (seg1a < seg2b) && (seg2a < seg1b); -} - -//------------------------------------------------------------------------------ -// ClipperBase class methods ... -//------------------------------------------------------------------------------ - -ClipperBase::ClipperBase() // constructor -{ - m_CurrentLM = m_MinimaList.begin(); // begin() == end() here - m_UseFullRange = false; -} -//------------------------------------------------------------------------------ - -ClipperBase::~ClipperBase() // destructor -{ - Clear(); -} -//------------------------------------------------------------------------------ - -void RangeTest(const IntPoint &Pt, bool &useFullRange) { - if (useFullRange) { - if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange) - throw clipperException("Coordinate outside allowed range"); - } else if (Pt.X > loRange || Pt.Y > loRange || -Pt.X > loRange || - -Pt.Y > loRange) { - useFullRange = true; - RangeTest(Pt, useFullRange); - } -} -//------------------------------------------------------------------------------ - -TEdge *FindNextLocMin(TEdge *E) { - for (;;) { - while (E->Bot != E->Prev->Bot || E->Curr == E->Top) - E = E->Next; - if (!IsHorizontal(*E) && !IsHorizontal(*E->Prev)) - break; - while (IsHorizontal(*E->Prev)) - E = E->Prev; - TEdge *E2 = E; - while (IsHorizontal(*E)) - E = E->Next; - if (E->Top.Y == E->Prev->Bot.Y) - continue; // ie just an intermediate horz. - if (E2->Prev->Bot.X < E->Bot.X) - E = E2; - break; - } - return E; -} -//------------------------------------------------------------------------------ - -TEdge *ClipperBase::ProcessBound(TEdge *E, bool NextIsForward) { - TEdge *Result = E; - TEdge *Horz = 0; - - if (E->OutIdx == Skip) { - // if edges still remain in the current bound beyond the skip edge then - // create another LocMin and call ProcessBound once more - if (NextIsForward) { - while (E->Top.Y == E->Next->Bot.Y) - E = E->Next; - // don't include top horizontals when parsing a bound a second time, - // they will be contained in the opposite bound ... - while (E != Result && IsHorizontal(*E)) - E = E->Prev; - } else { - while (E->Top.Y == E->Prev->Bot.Y) - E = E->Prev; - while (E != Result && IsHorizontal(*E)) - E = E->Next; - } - - if (E == Result) { - if (NextIsForward) - Result = E->Next; - else - Result = E->Prev; - } else { - // there are more edges in the bound beyond result starting with E - if (NextIsForward) - E = Result->Next; - else - E = Result->Prev; - MinimaList::value_type locMin; - locMin.Y = E->Bot.Y; - locMin.LeftBound = 0; - locMin.RightBound = E; - E->WindDelta = 0; - Result = ProcessBound(E, NextIsForward); - m_MinimaList.push_back(locMin); - } - return Result; - } - - TEdge *EStart; - - if (IsHorizontal(*E)) { - // We need to be careful with open paths because this may not be a - // true local minima (ie E may be following a skip edge). - // Also, consecutive horz. edges may start heading left before going right. - if (NextIsForward) - EStart = E->Prev; - else - EStart = E->Next; - if (IsHorizontal(*EStart)) // ie an adjoining horizontal skip edge - { - if (EStart->Bot.X != E->Bot.X && EStart->Top.X != E->Bot.X) - ReverseHorizontal(*E); - } else if (EStart->Bot.X != E->Bot.X) - ReverseHorizontal(*E); - } - - EStart = E; - if (NextIsForward) { - while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip) - Result = Result->Next; - if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip) { - // nb: at the top of a bound, horizontals are added to the bound - // only when the preceding edge attaches to the horizontal's left vertex - // unless a Skip edge is encountered when that becomes the top divide - Horz = Result; - while (IsHorizontal(*Horz->Prev)) - Horz = Horz->Prev; - if (Horz->Prev->Top.X > Result->Next->Top.X) - Result = Horz->Prev; - } - while (E != Result) { - E->NextInLML = E->Next; - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) - ReverseHorizontal(*E); - E = E->Next; - } - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) - ReverseHorizontal(*E); - Result = Result->Next; // move to the edge just beyond current bound - } else { - while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip) - Result = Result->Prev; - if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip) { - Horz = Result; - while (IsHorizontal(*Horz->Next)) - Horz = Horz->Next; - if (Horz->Next->Top.X == Result->Prev->Top.X || - Horz->Next->Top.X > Result->Prev->Top.X) - Result = Horz->Next; - } - - while (E != Result) { - E->NextInLML = E->Prev; - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) - ReverseHorizontal(*E); - E = E->Prev; - } - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) - ReverseHorizontal(*E); - Result = Result->Prev; // move to the edge just beyond current bound - } - - return Result; -} -//------------------------------------------------------------------------------ - -bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) { -#ifdef use_lines - if (!Closed && PolyTyp == ptClip) - throw clipperException("AddPath: Open paths must be subject."); -#else - if (!Closed) - throw clipperException("AddPath: Open paths have been disabled."); -#endif - - int highI = (int)pg.size() - 1; - if (Closed) - while (highI > 0 && (pg[highI] == pg[0])) - --highI; - while (highI > 0 && (pg[highI] == pg[highI - 1])) - --highI; - if ((Closed && highI < 2) || (!Closed && highI < 1)) - return false; - - // create a new edge array ... - TEdge *edges = new TEdge[highI + 1]; - - bool IsFlat = true; - // 1. Basic (first) edge initialization ... - try { - edges[1].Curr = pg[1]; - RangeTest(pg[0], m_UseFullRange); - RangeTest(pg[highI], m_UseFullRange); - InitEdge(&edges[0], &edges[1], &edges[highI], pg[0]); - InitEdge(&edges[highI], &edges[0], &edges[highI - 1], pg[highI]); - for (int i = highI - 1; i >= 1; --i) { - RangeTest(pg[i], m_UseFullRange); - InitEdge(&edges[i], &edges[i + 1], &edges[i - 1], pg[i]); - } - } catch (...) { - delete[] edges; - throw; // range test fails - } - TEdge *eStart = &edges[0]; - - // 2. Remove duplicate vertices, and (when closed) collinear edges ... - TEdge *E = eStart, *eLoopStop = eStart; - for (;;) { - // nb: allows matching start and end points when not Closed ... - if (E->Curr == E->Next->Curr && (Closed || E->Next != eStart)) { - if (E == E->Next) - break; - if (E == eStart) - eStart = E->Next; - E = RemoveEdge(E); - eLoopStop = E; - continue; - } - if (E->Prev == E->Next) - break; // only two vertices - else if (Closed && SlopesEqual(E->Prev->Curr, E->Curr, E->Next->Curr, - m_UseFullRange) && - (!m_PreserveCollinear || - !Pt2IsBetweenPt1AndPt3(E->Prev->Curr, E->Curr, E->Next->Curr))) { - // Collinear edges are allowed for open paths but in closed paths - // the default is to merge adjacent collinear edges into a single edge. - // However, if the PreserveCollinear property is enabled, only overlapping - // collinear edges (ie spikes) will be removed from closed paths. - if (E == eStart) - eStart = E->Next; - E = RemoveEdge(E); - E = E->Prev; - eLoopStop = E; - continue; - } - E = E->Next; - if ((E == eLoopStop) || (!Closed && E->Next == eStart)) - break; - } - - if ((!Closed && (E == E->Next)) || (Closed && (E->Prev == E->Next))) { - delete[] edges; - return false; - } - - if (!Closed) { - m_HasOpenPaths = true; - eStart->Prev->OutIdx = Skip; - } - - // 3. Do second stage of edge initialization ... - E = eStart; - do { - InitEdge2(*E, PolyTyp); - E = E->Next; - if (IsFlat && E->Curr.Y != eStart->Curr.Y) - IsFlat = false; - } while (E != eStart); - - // 4. Finally, add edge bounds to LocalMinima list ... - - // Totally flat paths must be handled differently when adding them - // to LocalMinima list to avoid endless loops etc ... - if (IsFlat) { - if (Closed) { - delete[] edges; - return false; - } - E->Prev->OutIdx = Skip; - MinimaList::value_type locMin; - locMin.Y = E->Bot.Y; - locMin.LeftBound = 0; - locMin.RightBound = E; - locMin.RightBound->Side = esRight; - locMin.RightBound->WindDelta = 0; - for (;;) { - if (E->Bot.X != E->Prev->Top.X) - ReverseHorizontal(*E); - if (E->Next->OutIdx == Skip) - break; - E->NextInLML = E->Next; - E = E->Next; - } - m_MinimaList.push_back(locMin); - m_edges.push_back(edges); - return true; - } - - m_edges.push_back(edges); - bool leftBoundIsForward; - TEdge *EMin = 0; - - // workaround to avoid an endless loop in the while loop below when - // open paths have matching start and end points ... - if (E->Prev->Bot == E->Prev->Top) - E = E->Next; - - for (;;) { - E = FindNextLocMin(E); - if (E == EMin) - break; - else if (!EMin) - EMin = E; - - // E and E.Prev now share a local minima (left aligned if horizontal). - // Compare their slopes to find which starts which bound ... - MinimaList::value_type locMin; - locMin.Y = E->Bot.Y; - if (E->Dx < E->Prev->Dx) { - locMin.LeftBound = E->Prev; - locMin.RightBound = E; - leftBoundIsForward = false; // Q.nextInLML = Q.prev - } else { - locMin.LeftBound = E; - locMin.RightBound = E->Prev; - leftBoundIsForward = true; // Q.nextInLML = Q.next - } - - if (!Closed) - locMin.LeftBound->WindDelta = 0; - else if (locMin.LeftBound->Next == locMin.RightBound) - locMin.LeftBound->WindDelta = -1; - else - locMin.LeftBound->WindDelta = 1; - locMin.RightBound->WindDelta = -locMin.LeftBound->WindDelta; - - E = ProcessBound(locMin.LeftBound, leftBoundIsForward); - if (E->OutIdx == Skip) - E = ProcessBound(E, leftBoundIsForward); - - TEdge *E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward); - if (E2->OutIdx == Skip) - E2 = ProcessBound(E2, !leftBoundIsForward); - - if (locMin.LeftBound->OutIdx == Skip) - locMin.LeftBound = 0; - else if (locMin.RightBound->OutIdx == Skip) - locMin.RightBound = 0; - m_MinimaList.push_back(locMin); - if (!leftBoundIsForward) - E = E2; - } - return true; -} -//------------------------------------------------------------------------------ - -bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed) { - bool result = false; - for (Paths::size_type i = 0; i < ppg.size(); ++i) - if (AddPath(ppg[i], PolyTyp, Closed)) - result = true; - return result; -} -//------------------------------------------------------------------------------ - -void ClipperBase::Clear() { - DisposeLocalMinimaList(); - for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) { - TEdge *edges = m_edges[i]; - delete[] edges; - } - m_edges.clear(); - m_UseFullRange = false; - m_HasOpenPaths = false; -} -//------------------------------------------------------------------------------ - -void ClipperBase::Reset() { - m_CurrentLM = m_MinimaList.begin(); - if (m_CurrentLM == m_MinimaList.end()) - return; // ie nothing to process - std::sort(m_MinimaList.begin(), m_MinimaList.end(), LocMinSorter()); - - m_Scanbeam = ScanbeamList(); // clears/resets priority_queue - // reset all edges ... - for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); - ++lm) { - InsertScanbeam(lm->Y); - TEdge *e = lm->LeftBound; - if (e) { - e->Curr = e->Bot; - e->Side = esLeft; - e->OutIdx = Unassigned; - } - - e = lm->RightBound; - if (e) { - e->Curr = e->Bot; - e->Side = esRight; - e->OutIdx = Unassigned; - } - } - m_ActiveEdges = 0; - m_CurrentLM = m_MinimaList.begin(); -} -//------------------------------------------------------------------------------ - -void ClipperBase::DisposeLocalMinimaList() { - m_MinimaList.clear(); - m_CurrentLM = m_MinimaList.begin(); -} -//------------------------------------------------------------------------------ - -bool ClipperBase::PopLocalMinima(cInt Y, const LocalMinimum *&locMin) { - if (m_CurrentLM == m_MinimaList.end() || (*m_CurrentLM).Y != Y) - return false; - locMin = &(*m_CurrentLM); - ++m_CurrentLM; - return true; -} -//------------------------------------------------------------------------------ - -IntRect ClipperBase::GetBounds() { - IntRect result; - MinimaList::iterator lm = m_MinimaList.begin(); - if (lm == m_MinimaList.end()) { - result.left = result.top = result.right = result.bottom = 0; - return result; - } - result.left = lm->LeftBound->Bot.X; - result.top = lm->LeftBound->Bot.Y; - result.right = lm->LeftBound->Bot.X; - result.bottom = lm->LeftBound->Bot.Y; - while (lm != m_MinimaList.end()) { - // todo - needs fixing for open paths - result.bottom = std::max(result.bottom, lm->LeftBound->Bot.Y); - TEdge *e = lm->LeftBound; - for (;;) { - TEdge *bottomE = e; - while (e->NextInLML) { - if (e->Bot.X < result.left) - result.left = e->Bot.X; - if (e->Bot.X > result.right) - result.right = e->Bot.X; - e = e->NextInLML; - } - result.left = std::min(result.left, e->Bot.X); - result.right = std::max(result.right, e->Bot.X); - result.left = std::min(result.left, e->Top.X); - result.right = std::max(result.right, e->Top.X); - result.top = std::min(result.top, e->Top.Y); - if (bottomE == lm->LeftBound) - e = lm->RightBound; - else - break; - } - ++lm; - } - return result; -} -//------------------------------------------------------------------------------ - -void ClipperBase::InsertScanbeam(const cInt Y) { m_Scanbeam.push(Y); } -//------------------------------------------------------------------------------ - -bool ClipperBase::PopScanbeam(cInt &Y) { - if (m_Scanbeam.empty()) - return false; - Y = m_Scanbeam.top(); - m_Scanbeam.pop(); - while (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) { - m_Scanbeam.pop(); - } // Pop duplicates. - return true; -} -//------------------------------------------------------------------------------ - -void ClipperBase::DisposeAllOutRecs() { - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - DisposeOutRec(i); - m_PolyOuts.clear(); -} -//------------------------------------------------------------------------------ - -void ClipperBase::DisposeOutRec(PolyOutList::size_type index) { - OutRec *outRec = m_PolyOuts[index]; - if (outRec->Pts) - DisposeOutPts(outRec->Pts); - delete outRec; - m_PolyOuts[index] = 0; -} -//------------------------------------------------------------------------------ - -void ClipperBase::DeleteFromAEL(TEdge *e) { - TEdge *AelPrev = e->PrevInAEL; - TEdge *AelNext = e->NextInAEL; - if (!AelPrev && !AelNext && (e != m_ActiveEdges)) - return; // already deleted - if (AelPrev) - AelPrev->NextInAEL = AelNext; - else - m_ActiveEdges = AelNext; - if (AelNext) - AelNext->PrevInAEL = AelPrev; - e->NextInAEL = 0; - e->PrevInAEL = 0; -} -//------------------------------------------------------------------------------ - -OutRec *ClipperBase::CreateOutRec() { - OutRec *result = new OutRec; - result->IsHole = false; - result->IsOpen = false; - result->FirstLeft = 0; - result->Pts = 0; - result->BottomPt = 0; - result->PolyNd = 0; - m_PolyOuts.push_back(result); - result->Idx = (int)m_PolyOuts.size() - 1; - return result; -} -//------------------------------------------------------------------------------ - -void ClipperBase::SwapPositionsInAEL(TEdge *Edge1, TEdge *Edge2) { - // check that one or other edge hasn't already been removed from AEL ... - if (Edge1->NextInAEL == Edge1->PrevInAEL || - Edge2->NextInAEL == Edge2->PrevInAEL) - return; - - if (Edge1->NextInAEL == Edge2) { - TEdge *Next = Edge2->NextInAEL; - if (Next) - Next->PrevInAEL = Edge1; - TEdge *Prev = Edge1->PrevInAEL; - if (Prev) - Prev->NextInAEL = Edge2; - Edge2->PrevInAEL = Prev; - Edge2->NextInAEL = Edge1; - Edge1->PrevInAEL = Edge2; - Edge1->NextInAEL = Next; - } else if (Edge2->NextInAEL == Edge1) { - TEdge *Next = Edge1->NextInAEL; - if (Next) - Next->PrevInAEL = Edge2; - TEdge *Prev = Edge2->PrevInAEL; - if (Prev) - Prev->NextInAEL = Edge1; - Edge1->PrevInAEL = Prev; - Edge1->NextInAEL = Edge2; - Edge2->PrevInAEL = Edge1; - Edge2->NextInAEL = Next; - } else { - TEdge *Next = Edge1->NextInAEL; - TEdge *Prev = Edge1->PrevInAEL; - Edge1->NextInAEL = Edge2->NextInAEL; - if (Edge1->NextInAEL) - Edge1->NextInAEL->PrevInAEL = Edge1; - Edge1->PrevInAEL = Edge2->PrevInAEL; - if (Edge1->PrevInAEL) - Edge1->PrevInAEL->NextInAEL = Edge1; - Edge2->NextInAEL = Next; - if (Edge2->NextInAEL) - Edge2->NextInAEL->PrevInAEL = Edge2; - Edge2->PrevInAEL = Prev; - if (Edge2->PrevInAEL) - Edge2->PrevInAEL->NextInAEL = Edge2; - } - - if (!Edge1->PrevInAEL) - m_ActiveEdges = Edge1; - else if (!Edge2->PrevInAEL) - m_ActiveEdges = Edge2; -} -//------------------------------------------------------------------------------ - -void ClipperBase::UpdateEdgeIntoAEL(TEdge *&e) { - if (!e->NextInLML) - throw clipperException("UpdateEdgeIntoAEL: invalid call"); - - e->NextInLML->OutIdx = e->OutIdx; - TEdge *AelPrev = e->PrevInAEL; - TEdge *AelNext = e->NextInAEL; - if (AelPrev) - AelPrev->NextInAEL = e->NextInLML; - else - m_ActiveEdges = e->NextInLML; - if (AelNext) - AelNext->PrevInAEL = e->NextInLML; - e->NextInLML->Side = e->Side; - e->NextInLML->WindDelta = e->WindDelta; - e->NextInLML->WindCnt = e->WindCnt; - e->NextInLML->WindCnt2 = e->WindCnt2; - e = e->NextInLML; - e->Curr = e->Bot; - e->PrevInAEL = AelPrev; - e->NextInAEL = AelNext; - if (!IsHorizontal(*e)) - InsertScanbeam(e->Top.Y); -} -//------------------------------------------------------------------------------ - -bool ClipperBase::LocalMinimaPending() { - return (m_CurrentLM != m_MinimaList.end()); -} - -//------------------------------------------------------------------------------ -// TClipper methods ... -//------------------------------------------------------------------------------ - -Clipper::Clipper(int initOptions) - : ClipperBase() // constructor -{ - m_ExecuteLocked = false; - m_UseFullRange = false; - m_ReverseOutput = ((initOptions & ioReverseSolution) != 0); - m_StrictSimple = ((initOptions & ioStrictlySimple) != 0); - m_PreserveCollinear = ((initOptions & ioPreserveCollinear) != 0); - m_HasOpenPaths = false; -#ifdef use_xyz - m_ZFill = 0; -#endif -} -//------------------------------------------------------------------------------ - -#ifdef use_xyz -void Clipper::ZFillFunction(ZFillCallback zFillFunc) { m_ZFill = zFillFunc; } -//------------------------------------------------------------------------------ -#endif - -bool Clipper::Execute(ClipType clipType, Paths &solution, - PolyFillType fillType) { - return Execute(clipType, solution, fillType, fillType); -} -//------------------------------------------------------------------------------ - -bool Clipper::Execute(ClipType clipType, PolyTree &polytree, - PolyFillType fillType) { - return Execute(clipType, polytree, fillType, fillType); -} -//------------------------------------------------------------------------------ - -bool Clipper::Execute(ClipType clipType, Paths &solution, - PolyFillType subjFillType, PolyFillType clipFillType) { - if (m_ExecuteLocked) - return false; - if (m_HasOpenPaths) - throw clipperException( - "Error: PolyTree struct is needed for open path clipping."); - m_ExecuteLocked = true; - solution.resize(0); - m_SubjFillType = subjFillType; - m_ClipFillType = clipFillType; - m_ClipType = clipType; - m_UsingPolyTree = false; - bool succeeded = ExecuteInternal(); - if (succeeded) - BuildResult(solution); - DisposeAllOutRecs(); - m_ExecuteLocked = false; - return succeeded; -} -//------------------------------------------------------------------------------ - -bool Clipper::Execute(ClipType clipType, PolyTree &polytree, - PolyFillType subjFillType, PolyFillType clipFillType) { - if (m_ExecuteLocked) - return false; - m_ExecuteLocked = true; - m_SubjFillType = subjFillType; - m_ClipFillType = clipFillType; - m_ClipType = clipType; - m_UsingPolyTree = true; - bool succeeded = ExecuteInternal(); - if (succeeded) - BuildResult2(polytree); - DisposeAllOutRecs(); - m_ExecuteLocked = false; - return succeeded; -} -//------------------------------------------------------------------------------ - -void Clipper::FixHoleLinkage(OutRec &outrec) { - // skip OutRecs that (a) contain outermost polygons or - //(b) already have the correct owner/child linkage ... - if (!outrec.FirstLeft || - (outrec.IsHole != outrec.FirstLeft->IsHole && outrec.FirstLeft->Pts)) - return; - - OutRec *orfl = outrec.FirstLeft; - while (orfl && ((orfl->IsHole == outrec.IsHole) || !orfl->Pts)) - orfl = orfl->FirstLeft; - outrec.FirstLeft = orfl; -} -//------------------------------------------------------------------------------ - -bool Clipper::ExecuteInternal() { - bool succeeded = true; - try { - Reset(); - m_Maxima = MaximaList(); - m_SortedEdges = 0; - - succeeded = true; - cInt botY, topY; - if (!PopScanbeam(botY)) - return false; - InsertLocalMinimaIntoAEL(botY); - while (PopScanbeam(topY) || LocalMinimaPending()) { - ProcessHorizontals(); - ClearGhostJoins(); - if (!ProcessIntersections(topY)) { - succeeded = false; - break; - } - ProcessEdgesAtTopOfScanbeam(topY); - botY = topY; - InsertLocalMinimaIntoAEL(botY); - } - } catch (...) { - succeeded = false; - } - - if (succeeded) { - // fix orientations ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { - OutRec *outRec = m_PolyOuts[i]; - if (!outRec->Pts || outRec->IsOpen) - continue; - if ((outRec->IsHole ^ m_ReverseOutput) == (Area(*outRec) > 0)) - ReversePolyPtLinks(outRec->Pts); - } - - if (!m_Joins.empty()) - JoinCommonEdges(); - - // unfortunately FixupOutPolygon() must be done after JoinCommonEdges() - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { - OutRec *outRec = m_PolyOuts[i]; - if (!outRec->Pts) - continue; - if (outRec->IsOpen) - FixupOutPolyline(*outRec); - else - FixupOutPolygon(*outRec); - } - - if (m_StrictSimple) - DoSimplePolygons(); - } - - ClearJoins(); - ClearGhostJoins(); - return succeeded; -} -//------------------------------------------------------------------------------ - -void Clipper::SetWindingCount(TEdge &edge) { - TEdge *e = edge.PrevInAEL; - // find the edge of the same polytype that immediately preceeds 'edge' in AEL - while (e && ((e->PolyTyp != edge.PolyTyp) || (e->WindDelta == 0))) - e = e->PrevInAEL; - if (!e) { - if (edge.WindDelta == 0) { - PolyFillType pft = - (edge.PolyTyp == ptSubject ? m_SubjFillType : m_ClipFillType); - edge.WindCnt = (pft == pftNegative ? -1 : 1); - } else - edge.WindCnt = edge.WindDelta; - edge.WindCnt2 = 0; - e = m_ActiveEdges; // ie get ready to calc WindCnt2 - } else if (edge.WindDelta == 0 && m_ClipType != ctUnion) { - edge.WindCnt = 1; - edge.WindCnt2 = e->WindCnt2; - e = e->NextInAEL; // ie get ready to calc WindCnt2 - } else if (IsEvenOddFillType(edge)) { - // EvenOdd filling ... - if (edge.WindDelta == 0) { - // are we inside a subj polygon ... - bool Inside = true; - TEdge *e2 = e->PrevInAEL; - while (e2) { - if (e2->PolyTyp == e->PolyTyp && e2->WindDelta != 0) - Inside = !Inside; - e2 = e2->PrevInAEL; - } - edge.WindCnt = (Inside ? 0 : 1); - } else { - edge.WindCnt = edge.WindDelta; - } - edge.WindCnt2 = e->WindCnt2; - e = e->NextInAEL; // ie get ready to calc WindCnt2 - } else { - // nonZero, Positive or Negative filling ... - if (e->WindCnt * e->WindDelta < 0) { - // prev edge is 'decreasing' WindCount (WC) toward zero - // so we're outside the previous polygon ... - if (Abs(e->WindCnt) > 1) { - // outside prev poly but still inside another. - // when reversing direction of prev poly use the same WC - if (e->WindDelta * edge.WindDelta < 0) - edge.WindCnt = e->WindCnt; - // otherwise continue to 'decrease' WC ... - else - edge.WindCnt = e->WindCnt + edge.WindDelta; - } else - // now outside all polys of same polytype so set own WC ... - edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); - } else { - // prev edge is 'increasing' WindCount (WC) away from zero - // so we're inside the previous polygon ... - if (edge.WindDelta == 0) - edge.WindCnt = (e->WindCnt < 0 ? e->WindCnt - 1 : e->WindCnt + 1); - // if wind direction is reversing prev then use same WC - else if (e->WindDelta * edge.WindDelta < 0) - edge.WindCnt = e->WindCnt; - // otherwise add to WC ... - else - edge.WindCnt = e->WindCnt + edge.WindDelta; - } - edge.WindCnt2 = e->WindCnt2; - e = e->NextInAEL; // ie get ready to calc WindCnt2 - } - - // update WindCnt2 ... - if (IsEvenOddAltFillType(edge)) { - // EvenOdd filling ... - while (e != &edge) { - if (e->WindDelta != 0) - edge.WindCnt2 = (edge.WindCnt2 == 0 ? 1 : 0); - e = e->NextInAEL; - } - } else { - // nonZero, Positive or Negative filling ... - while (e != &edge) { - edge.WindCnt2 += e->WindDelta; - e = e->NextInAEL; - } - } -} -//------------------------------------------------------------------------------ - -bool Clipper::IsEvenOddFillType(const TEdge &edge) const { - if (edge.PolyTyp == ptSubject) - return m_SubjFillType == pftEvenOdd; - else - return m_ClipFillType == pftEvenOdd; -} -//------------------------------------------------------------------------------ - -bool Clipper::IsEvenOddAltFillType(const TEdge &edge) const { - if (edge.PolyTyp == ptSubject) - return m_ClipFillType == pftEvenOdd; - else - return m_SubjFillType == pftEvenOdd; -} -//------------------------------------------------------------------------------ - -bool Clipper::IsContributing(const TEdge &edge) const { - PolyFillType pft, pft2; - if (edge.PolyTyp == ptSubject) { - pft = m_SubjFillType; - pft2 = m_ClipFillType; - } else { - pft = m_ClipFillType; - pft2 = m_SubjFillType; - } - - switch (pft) { - case pftEvenOdd: - // return false if a subj line has been flagged as inside a subj polygon - if (edge.WindDelta == 0 && edge.WindCnt != 1) - return false; - break; - case pftNonZero: - if (Abs(edge.WindCnt) != 1) - return false; - break; - case pftPositive: - if (edge.WindCnt != 1) - return false; - break; - default: // pftNegative - if (edge.WindCnt != -1) - return false; - } - - switch (m_ClipType) { - case ctIntersection: - switch (pft2) { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 != 0); - case pftPositive: - return (edge.WindCnt2 > 0); - default: - return (edge.WindCnt2 < 0); - } - break; - case ctUnion: - switch (pft2) { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 == 0); - case pftPositive: - return (edge.WindCnt2 <= 0); - default: - return (edge.WindCnt2 >= 0); - } - break; - case ctDifference: - if (edge.PolyTyp == ptSubject) - switch (pft2) { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 == 0); - case pftPositive: - return (edge.WindCnt2 <= 0); - default: - return (edge.WindCnt2 >= 0); - } - else - switch (pft2) { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 != 0); - case pftPositive: - return (edge.WindCnt2 > 0); - default: - return (edge.WindCnt2 < 0); - } - break; - case ctXor: - if (edge.WindDelta == 0) // XOr always contributing unless open - switch (pft2) { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 == 0); - case pftPositive: - return (edge.WindCnt2 <= 0); - default: - return (edge.WindCnt2 >= 0); - } - else - return true; - break; - default: - return true; - } -} -//------------------------------------------------------------------------------ - -OutPt *Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) { - OutPt *result; - TEdge *e, *prevE; - if (IsHorizontal(*e2) || (e1->Dx > e2->Dx)) { - result = AddOutPt(e1, Pt); - e2->OutIdx = e1->OutIdx; - e1->Side = esLeft; - e2->Side = esRight; - e = e1; - if (e->PrevInAEL == e2) - prevE = e2->PrevInAEL; - else - prevE = e->PrevInAEL; - } else { - result = AddOutPt(e2, Pt); - e1->OutIdx = e2->OutIdx; - e1->Side = esRight; - e2->Side = esLeft; - e = e2; - if (e->PrevInAEL == e1) - prevE = e1->PrevInAEL; - else - prevE = e->PrevInAEL; - } - - if (prevE && prevE->OutIdx >= 0 && prevE->Top.Y < Pt.Y && e->Top.Y < Pt.Y) { - cInt xPrev = TopX(*prevE, Pt.Y); - cInt xE = TopX(*e, Pt.Y); - if (xPrev == xE && (e->WindDelta != 0) && (prevE->WindDelta != 0) && - SlopesEqual(IntPoint(xPrev, Pt.Y), prevE->Top, IntPoint(xE, Pt.Y), - e->Top, m_UseFullRange)) { - OutPt *outPt = AddOutPt(prevE, Pt); - AddJoin(result, outPt, e->Top); - } - } - return result; -} -//------------------------------------------------------------------------------ - -void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) { - AddOutPt(e1, Pt); - if (e2->WindDelta == 0) - AddOutPt(e2, Pt); - if (e1->OutIdx == e2->OutIdx) { - e1->OutIdx = Unassigned; - e2->OutIdx = Unassigned; - } else if (e1->OutIdx < e2->OutIdx) - AppendPolygon(e1, e2); - else - AppendPolygon(e2, e1); -} -//------------------------------------------------------------------------------ - -void Clipper::AddEdgeToSEL(TEdge *edge) { - // SEL pointers in PEdge are reused to build a list of horizontal edges. - // However, we don't need to worry about order with horizontal edge - // processing. - if (!m_SortedEdges) { - m_SortedEdges = edge; - edge->PrevInSEL = 0; - edge->NextInSEL = 0; - } else { - edge->NextInSEL = m_SortedEdges; - edge->PrevInSEL = 0; - m_SortedEdges->PrevInSEL = edge; - m_SortedEdges = edge; - } -} -//------------------------------------------------------------------------------ - -bool Clipper::PopEdgeFromSEL(TEdge *&edge) { - if (!m_SortedEdges) - return false; - edge = m_SortedEdges; - DeleteFromSEL(m_SortedEdges); - return true; -} -//------------------------------------------------------------------------------ - -void Clipper::CopyAELToSEL() { - TEdge *e = m_ActiveEdges; - m_SortedEdges = e; - while (e) { - e->PrevInSEL = e->PrevInAEL; - e->NextInSEL = e->NextInAEL; - e = e->NextInAEL; - } -} -//------------------------------------------------------------------------------ - -void Clipper::AddJoin(OutPt *op1, OutPt *op2, const IntPoint OffPt) { - Join *j = new Join; - j->OutPt1 = op1; - j->OutPt2 = op2; - j->OffPt = OffPt; - m_Joins.push_back(j); -} -//------------------------------------------------------------------------------ - -void Clipper::ClearJoins() { - for (JoinList::size_type i = 0; i < m_Joins.size(); i++) - delete m_Joins[i]; - m_Joins.resize(0); -} -//------------------------------------------------------------------------------ - -void Clipper::ClearGhostJoins() { - for (JoinList::size_type i = 0; i < m_GhostJoins.size(); i++) - delete m_GhostJoins[i]; - m_GhostJoins.resize(0); -} -//------------------------------------------------------------------------------ - -void Clipper::AddGhostJoin(OutPt *op, const IntPoint OffPt) { - Join *j = new Join; - j->OutPt1 = op; - j->OutPt2 = 0; - j->OffPt = OffPt; - m_GhostJoins.push_back(j); -} -//------------------------------------------------------------------------------ - -void Clipper::InsertLocalMinimaIntoAEL(const cInt botY) { - const LocalMinimum *lm; - while (PopLocalMinima(botY, lm)) { - TEdge *lb = lm->LeftBound; - TEdge *rb = lm->RightBound; - - OutPt *Op1 = 0; - if (!lb) { - // nb: don't insert LB into either AEL or SEL - InsertEdgeIntoAEL(rb, 0); - SetWindingCount(*rb); - if (IsContributing(*rb)) - Op1 = AddOutPt(rb, rb->Bot); - } else if (!rb) { - InsertEdgeIntoAEL(lb, 0); - SetWindingCount(*lb); - if (IsContributing(*lb)) - Op1 = AddOutPt(lb, lb->Bot); - InsertScanbeam(lb->Top.Y); - } else { - InsertEdgeIntoAEL(lb, 0); - InsertEdgeIntoAEL(rb, lb); - SetWindingCount(*lb); - rb->WindCnt = lb->WindCnt; - rb->WindCnt2 = lb->WindCnt2; - if (IsContributing(*lb)) - Op1 = AddLocalMinPoly(lb, rb, lb->Bot); - InsertScanbeam(lb->Top.Y); - } - - if (rb) { - if (IsHorizontal(*rb)) { - AddEdgeToSEL(rb); - if (rb->NextInLML) - InsertScanbeam(rb->NextInLML->Top.Y); - } else - InsertScanbeam(rb->Top.Y); - } - - if (!lb || !rb) - continue; - - // if any output polygons share an edge, they'll need joining later ... - if (Op1 && IsHorizontal(*rb) && m_GhostJoins.size() > 0 && - (rb->WindDelta != 0)) { - for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i) { - Join *jr = m_GhostJoins[i]; - // if the horizontal Rb and a 'ghost' horizontal overlap, then convert - // the 'ghost' join to a real join ready for later ... - if (HorzSegmentsOverlap(jr->OutPt1->Pt.X, jr->OffPt.X, rb->Bot.X, - rb->Top.X)) - AddJoin(jr->OutPt1, Op1, jr->OffPt); - } - } - - if (lb->OutIdx >= 0 && lb->PrevInAEL && - lb->PrevInAEL->Curr.X == lb->Bot.X && lb->PrevInAEL->OutIdx >= 0 && - SlopesEqual(lb->PrevInAEL->Bot, lb->PrevInAEL->Top, lb->Curr, lb->Top, - m_UseFullRange) && - (lb->WindDelta != 0) && (lb->PrevInAEL->WindDelta != 0)) { - OutPt *Op2 = AddOutPt(lb->PrevInAEL, lb->Bot); - AddJoin(Op1, Op2, lb->Top); - } - - if (lb->NextInAEL != rb) { - - if (rb->OutIdx >= 0 && rb->PrevInAEL->OutIdx >= 0 && - SlopesEqual(rb->PrevInAEL->Curr, rb->PrevInAEL->Top, rb->Curr, - rb->Top, m_UseFullRange) && - (rb->WindDelta != 0) && (rb->PrevInAEL->WindDelta != 0)) { - OutPt *Op2 = AddOutPt(rb->PrevInAEL, rb->Bot); - AddJoin(Op1, Op2, rb->Top); - } - - TEdge *e = lb->NextInAEL; - if (e) { - while (e != rb) { - // nb: For calculating winding counts etc, IntersectEdges() assumes - // that param1 will be to the Right of param2 ABOVE the intersection - // ... - IntersectEdges(rb, e, lb->Curr); // order important here - e = e->NextInAEL; - } - } - } - } -} -//------------------------------------------------------------------------------ - -void Clipper::DeleteFromSEL(TEdge *e) { - TEdge *SelPrev = e->PrevInSEL; - TEdge *SelNext = e->NextInSEL; - if (!SelPrev && !SelNext && (e != m_SortedEdges)) - return; // already deleted - if (SelPrev) - SelPrev->NextInSEL = SelNext; - else - m_SortedEdges = SelNext; - if (SelNext) - SelNext->PrevInSEL = SelPrev; - e->NextInSEL = 0; - e->PrevInSEL = 0; -} -//------------------------------------------------------------------------------ - -#ifdef use_xyz -void Clipper::SetZ(IntPoint &pt, TEdge &e1, TEdge &e2) { - if (pt.Z != 0 || !m_ZFill) - return; - else if (pt == e1.Bot) - pt.Z = e1.Bot.Z; - else if (pt == e1.Top) - pt.Z = e1.Top.Z; - else if (pt == e2.Bot) - pt.Z = e2.Bot.Z; - else if (pt == e2.Top) - pt.Z = e2.Top.Z; - else - (*m_ZFill)(e1.Bot, e1.Top, e2.Bot, e2.Top, pt); -} -//------------------------------------------------------------------------------ -#endif - -void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &Pt) { - bool e1Contributing = (e1->OutIdx >= 0); - bool e2Contributing = (e2->OutIdx >= 0); - -#ifdef use_xyz - SetZ(Pt, *e1, *e2); -#endif - -#ifdef use_lines - // if either edge is on an OPEN path ... - if (e1->WindDelta == 0 || e2->WindDelta == 0) { - // ignore subject-subject open path intersections UNLESS they - // are both open paths, AND they are both 'contributing maximas' ... - if (e1->WindDelta == 0 && e2->WindDelta == 0) - return; - - // if intersecting a subj line with a subj poly ... - else if (e1->PolyTyp == e2->PolyTyp && e1->WindDelta != e2->WindDelta && - m_ClipType == ctUnion) { - if (e1->WindDelta == 0) { - if (e2Contributing) { - AddOutPt(e1, Pt); - if (e1Contributing) - e1->OutIdx = Unassigned; - } - } else { - if (e1Contributing) { - AddOutPt(e2, Pt); - if (e2Contributing) - e2->OutIdx = Unassigned; - } - } - } else if (e1->PolyTyp != e2->PolyTyp) { - // toggle subj open path OutIdx on/off when Abs(clip.WndCnt) == 1 ... - if ((e1->WindDelta == 0) && abs(e2->WindCnt) == 1 && - (m_ClipType != ctUnion || e2->WindCnt2 == 0)) { - AddOutPt(e1, Pt); - if (e1Contributing) - e1->OutIdx = Unassigned; - } else if ((e2->WindDelta == 0) && (abs(e1->WindCnt) == 1) && - (m_ClipType != ctUnion || e1->WindCnt2 == 0)) { - AddOutPt(e2, Pt); - if (e2Contributing) - e2->OutIdx = Unassigned; - } - } - return; - } -#endif - - // update winding counts... - // assumes that e1 will be to the Right of e2 ABOVE the intersection - if (e1->PolyTyp == e2->PolyTyp) { - if (IsEvenOddFillType(*e1)) { - int oldE1WindCnt = e1->WindCnt; - e1->WindCnt = e2->WindCnt; - e2->WindCnt = oldE1WindCnt; - } else { - if (e1->WindCnt + e2->WindDelta == 0) - e1->WindCnt = -e1->WindCnt; - else - e1->WindCnt += e2->WindDelta; - if (e2->WindCnt - e1->WindDelta == 0) - e2->WindCnt = -e2->WindCnt; - else - e2->WindCnt -= e1->WindDelta; - } - } else { - if (!IsEvenOddFillType(*e2)) - e1->WindCnt2 += e2->WindDelta; - else - e1->WindCnt2 = (e1->WindCnt2 == 0) ? 1 : 0; - if (!IsEvenOddFillType(*e1)) - e2->WindCnt2 -= e1->WindDelta; - else - e2->WindCnt2 = (e2->WindCnt2 == 0) ? 1 : 0; - } - - PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; - if (e1->PolyTyp == ptSubject) { - e1FillType = m_SubjFillType; - e1FillType2 = m_ClipFillType; - } else { - e1FillType = m_ClipFillType; - e1FillType2 = m_SubjFillType; - } - if (e2->PolyTyp == ptSubject) { - e2FillType = m_SubjFillType; - e2FillType2 = m_ClipFillType; - } else { - e2FillType = m_ClipFillType; - e2FillType2 = m_SubjFillType; - } - - cInt e1Wc, e2Wc; - switch (e1FillType) { - case pftPositive: - e1Wc = e1->WindCnt; - break; - case pftNegative: - e1Wc = -e1->WindCnt; - break; - default: - e1Wc = Abs(e1->WindCnt); - } - switch (e2FillType) { - case pftPositive: - e2Wc = e2->WindCnt; - break; - case pftNegative: - e2Wc = -e2->WindCnt; - break; - default: - e2Wc = Abs(e2->WindCnt); - } - - if (e1Contributing && e2Contributing) { - if ((e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || - (e1->PolyTyp != e2->PolyTyp && m_ClipType != ctXor)) { - AddLocalMaxPoly(e1, e2, Pt); - } else { - AddOutPt(e1, Pt); - AddOutPt(e2, Pt); - SwapSides(*e1, *e2); - SwapPolyIndexes(*e1, *e2); - } - } else if (e1Contributing) { - if (e2Wc == 0 || e2Wc == 1) { - AddOutPt(e1, Pt); - SwapSides(*e1, *e2); - SwapPolyIndexes(*e1, *e2); - } - } else if (e2Contributing) { - if (e1Wc == 0 || e1Wc == 1) { - AddOutPt(e2, Pt); - SwapSides(*e1, *e2); - SwapPolyIndexes(*e1, *e2); - } - } else if ((e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1)) { - // neither edge is currently contributing ... - - cInt e1Wc2, e2Wc2; - switch (e1FillType2) { - case pftPositive: - e1Wc2 = e1->WindCnt2; - break; - case pftNegative: - e1Wc2 = -e1->WindCnt2; - break; - default: - e1Wc2 = Abs(e1->WindCnt2); - } - switch (e2FillType2) { - case pftPositive: - e2Wc2 = e2->WindCnt2; - break; - case pftNegative: - e2Wc2 = -e2->WindCnt2; - break; - default: - e2Wc2 = Abs(e2->WindCnt2); - } - - if (e1->PolyTyp != e2->PolyTyp) { - AddLocalMinPoly(e1, e2, Pt); - } else if (e1Wc == 1 && e2Wc == 1) - switch (m_ClipType) { - case ctIntersection: - if (e1Wc2 > 0 && e2Wc2 > 0) - AddLocalMinPoly(e1, e2, Pt); - break; - case ctUnion: - if (e1Wc2 <= 0 && e2Wc2 <= 0) - AddLocalMinPoly(e1, e2, Pt); - break; - case ctDifference: - if (((e1->PolyTyp == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || - ((e1->PolyTyp == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) - AddLocalMinPoly(e1, e2, Pt); - break; - case ctXor: - AddLocalMinPoly(e1, e2, Pt); - } - else - SwapSides(*e1, *e2); - } -} -//------------------------------------------------------------------------------ - -void Clipper::SetHoleState(TEdge *e, OutRec *outrec) { - TEdge *e2 = e->PrevInAEL; - TEdge *eTmp = 0; - while (e2) { - if (e2->OutIdx >= 0 && e2->WindDelta != 0) { - if (!eTmp) - eTmp = e2; - else if (eTmp->OutIdx == e2->OutIdx) - eTmp = 0; - } - e2 = e2->PrevInAEL; - } - if (!eTmp) { - outrec->FirstLeft = 0; - outrec->IsHole = false; - } else { - outrec->FirstLeft = m_PolyOuts[eTmp->OutIdx]; - outrec->IsHole = !outrec->FirstLeft->IsHole; - } -} -//------------------------------------------------------------------------------ - -OutRec *GetLowermostRec(OutRec *outRec1, OutRec *outRec2) { - // work out which polygon fragment has the correct hole state ... - if (!outRec1->BottomPt) - outRec1->BottomPt = GetBottomPt(outRec1->Pts); - if (!outRec2->BottomPt) - outRec2->BottomPt = GetBottomPt(outRec2->Pts); - OutPt *OutPt1 = outRec1->BottomPt; - OutPt *OutPt2 = outRec2->BottomPt; - if (OutPt1->Pt.Y > OutPt2->Pt.Y) - return outRec1; - else if (OutPt1->Pt.Y < OutPt2->Pt.Y) - return outRec2; - else if (OutPt1->Pt.X < OutPt2->Pt.X) - return outRec1; - else if (OutPt1->Pt.X > OutPt2->Pt.X) - return outRec2; - else if (OutPt1->Next == OutPt1) - return outRec2; - else if (OutPt2->Next == OutPt2) - return outRec1; - else if (FirstIsBottomPt(OutPt1, OutPt2)) - return outRec1; - else - return outRec2; -} -//------------------------------------------------------------------------------ - -bool OutRec1RightOfOutRec2(OutRec *outRec1, OutRec *outRec2) { - do { - outRec1 = outRec1->FirstLeft; - if (outRec1 == outRec2) - return true; - } while (outRec1); - return false; -} -//------------------------------------------------------------------------------ - -OutRec *Clipper::GetOutRec(int Idx) { - OutRec *outrec = m_PolyOuts[Idx]; - while (outrec != m_PolyOuts[outrec->Idx]) - outrec = m_PolyOuts[outrec->Idx]; - return outrec; -} -//------------------------------------------------------------------------------ - -void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) { - // get the start and ends of both output polygons ... - OutRec *outRec1 = m_PolyOuts[e1->OutIdx]; - OutRec *outRec2 = m_PolyOuts[e2->OutIdx]; - - OutRec *holeStateRec; - if (OutRec1RightOfOutRec2(outRec1, outRec2)) - holeStateRec = outRec2; - else if (OutRec1RightOfOutRec2(outRec2, outRec1)) - holeStateRec = outRec1; - else - holeStateRec = GetLowermostRec(outRec1, outRec2); - - // get the start and ends of both output polygons and - // join e2 poly onto e1 poly and delete pointers to e2 ... - - OutPt *p1_lft = outRec1->Pts; - OutPt *p1_rt = p1_lft->Prev; - OutPt *p2_lft = outRec2->Pts; - OutPt *p2_rt = p2_lft->Prev; - - // join e2 poly onto e1 poly and delete pointers to e2 ... - if (e1->Side == esLeft) { - if (e2->Side == esLeft) { - // z y x a b c - ReversePolyPtLinks(p2_lft); - p2_lft->Next = p1_lft; - p1_lft->Prev = p2_lft; - p1_rt->Next = p2_rt; - p2_rt->Prev = p1_rt; - outRec1->Pts = p2_rt; - } else { - // x y z a b c - p2_rt->Next = p1_lft; - p1_lft->Prev = p2_rt; - p2_lft->Prev = p1_rt; - p1_rt->Next = p2_lft; - outRec1->Pts = p2_lft; - } - } else { - if (e2->Side == esRight) { - // a b c z y x - ReversePolyPtLinks(p2_lft); - p1_rt->Next = p2_rt; - p2_rt->Prev = p1_rt; - p2_lft->Next = p1_lft; - p1_lft->Prev = p2_lft; - } else { - // a b c x y z - p1_rt->Next = p2_lft; - p2_lft->Prev = p1_rt; - p1_lft->Prev = p2_rt; - p2_rt->Next = p1_lft; - } - } - - outRec1->BottomPt = 0; - if (holeStateRec == outRec2) { - if (outRec2->FirstLeft != outRec1) - outRec1->FirstLeft = outRec2->FirstLeft; - outRec1->IsHole = outRec2->IsHole; - } - outRec2->Pts = 0; - outRec2->BottomPt = 0; - outRec2->FirstLeft = outRec1; - - int OKIdx = e1->OutIdx; - int ObsoleteIdx = e2->OutIdx; - - e1->OutIdx = - Unassigned; // nb: safe because we only get here via AddLocalMaxPoly - e2->OutIdx = Unassigned; - - TEdge *e = m_ActiveEdges; - while (e) { - if (e->OutIdx == ObsoleteIdx) { - e->OutIdx = OKIdx; - e->Side = e1->Side; - break; - } - e = e->NextInAEL; - } - - outRec2->Idx = outRec1->Idx; -} -//------------------------------------------------------------------------------ - -OutPt *Clipper::AddOutPt(TEdge *e, const IntPoint &pt) { - if (e->OutIdx < 0) { - OutRec *outRec = CreateOutRec(); - outRec->IsOpen = (e->WindDelta == 0); - OutPt *newOp = new OutPt; - outRec->Pts = newOp; - newOp->Idx = outRec->Idx; - newOp->Pt = pt; - newOp->Next = newOp; - newOp->Prev = newOp; - if (!outRec->IsOpen) - SetHoleState(e, outRec); - e->OutIdx = outRec->Idx; - return newOp; - } else { - OutRec *outRec = m_PolyOuts[e->OutIdx]; - // OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most' - OutPt *op = outRec->Pts; - - bool ToFront = (e->Side == esLeft); - if (ToFront && (pt == op->Pt)) - return op; - else if (!ToFront && (pt == op->Prev->Pt)) - return op->Prev; - - OutPt *newOp = new OutPt; - newOp->Idx = outRec->Idx; - newOp->Pt = pt; - newOp->Next = op; - newOp->Prev = op->Prev; - newOp->Prev->Next = newOp; - op->Prev = newOp; - if (ToFront) - outRec->Pts = newOp; - return newOp; - } -} -//------------------------------------------------------------------------------ - -OutPt *Clipper::GetLastOutPt(TEdge *e) { - OutRec *outRec = m_PolyOuts[e->OutIdx]; - if (e->Side == esLeft) - return outRec->Pts; - else - return outRec->Pts->Prev; -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessHorizontals() { - TEdge *horzEdge; - while (PopEdgeFromSEL(horzEdge)) - ProcessHorizontal(horzEdge); -} -//------------------------------------------------------------------------------ - -inline bool IsMinima(TEdge *e) { - return e && (e->Prev->NextInLML != e) && (e->Next->NextInLML != e); -} -//------------------------------------------------------------------------------ - -inline bool IsMaxima(TEdge *e, const cInt Y) { - return e && e->Top.Y == Y && !e->NextInLML; -} -//------------------------------------------------------------------------------ - -inline bool IsIntermediate(TEdge *e, const cInt Y) { - return e->Top.Y == Y && e->NextInLML; -} -//------------------------------------------------------------------------------ - -TEdge *GetMaximaPair(TEdge *e) { - if ((e->Next->Top == e->Top) && !e->Next->NextInLML) - return e->Next; - else if ((e->Prev->Top == e->Top) && !e->Prev->NextInLML) - return e->Prev; - else - return 0; -} -//------------------------------------------------------------------------------ - -TEdge *GetMaximaPairEx(TEdge *e) { - // as GetMaximaPair() but returns 0 if MaxPair isn't in AEL (unless it's - // horizontal) - TEdge *result = GetMaximaPair(e); - if (result && - (result->OutIdx == Skip || - (result->NextInAEL == result->PrevInAEL && !IsHorizontal(*result)))) - return 0; - return result; -} -//------------------------------------------------------------------------------ - -void Clipper::SwapPositionsInSEL(TEdge *Edge1, TEdge *Edge2) { - if (!(Edge1->NextInSEL) && !(Edge1->PrevInSEL)) - return; - if (!(Edge2->NextInSEL) && !(Edge2->PrevInSEL)) - return; - - if (Edge1->NextInSEL == Edge2) { - TEdge *Next = Edge2->NextInSEL; - if (Next) - Next->PrevInSEL = Edge1; - TEdge *Prev = Edge1->PrevInSEL; - if (Prev) - Prev->NextInSEL = Edge2; - Edge2->PrevInSEL = Prev; - Edge2->NextInSEL = Edge1; - Edge1->PrevInSEL = Edge2; - Edge1->NextInSEL = Next; - } else if (Edge2->NextInSEL == Edge1) { - TEdge *Next = Edge1->NextInSEL; - if (Next) - Next->PrevInSEL = Edge2; - TEdge *Prev = Edge2->PrevInSEL; - if (Prev) - Prev->NextInSEL = Edge1; - Edge1->PrevInSEL = Prev; - Edge1->NextInSEL = Edge2; - Edge2->PrevInSEL = Edge1; - Edge2->NextInSEL = Next; - } else { - TEdge *Next = Edge1->NextInSEL; - TEdge *Prev = Edge1->PrevInSEL; - Edge1->NextInSEL = Edge2->NextInSEL; - if (Edge1->NextInSEL) - Edge1->NextInSEL->PrevInSEL = Edge1; - Edge1->PrevInSEL = Edge2->PrevInSEL; - if (Edge1->PrevInSEL) - Edge1->PrevInSEL->NextInSEL = Edge1; - Edge2->NextInSEL = Next; - if (Edge2->NextInSEL) - Edge2->NextInSEL->PrevInSEL = Edge2; - Edge2->PrevInSEL = Prev; - if (Edge2->PrevInSEL) - Edge2->PrevInSEL->NextInSEL = Edge2; - } - - if (!Edge1->PrevInSEL) - m_SortedEdges = Edge1; - else if (!Edge2->PrevInSEL) - m_SortedEdges = Edge2; -} -//------------------------------------------------------------------------------ - -TEdge *GetNextInAEL(TEdge *e, Direction dir) { - return dir == dLeftToRight ? e->NextInAEL : e->PrevInAEL; -} -//------------------------------------------------------------------------------ - -void GetHorzDirection(TEdge &HorzEdge, Direction &Dir, cInt &Left, - cInt &Right) { - if (HorzEdge.Bot.X < HorzEdge.Top.X) { - Left = HorzEdge.Bot.X; - Right = HorzEdge.Top.X; - Dir = dLeftToRight; - } else { - Left = HorzEdge.Top.X; - Right = HorzEdge.Bot.X; - Dir = dRightToLeft; - } -} -//------------------------------------------------------------------------ - -/******************************************************************************* -* Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or * -* Bottom of a scanbeam) are processed as if layered. The order in which HEs * -* are processed doesn't matter. HEs intersect with other HE Bot.Xs only [#] * -* (or they could intersect with Top.Xs only, ie EITHER Bot.Xs OR Top.Xs), * -* and with other non-horizontal edges [*]. Once these intersections are * -* processed, intermediate HEs then 'promote' the Edge above (NextInLML) into * -* the AEL. These 'promoted' edges may in turn intersect [%] with other HEs. * -*******************************************************************************/ - -void Clipper::ProcessHorizontal(TEdge *horzEdge) { - Direction dir; - cInt horzLeft, horzRight; - bool IsOpen = (horzEdge->WindDelta == 0); - - GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); - - TEdge *eLastHorz = horzEdge, *eMaxPair = 0; - while (eLastHorz->NextInLML && IsHorizontal(*eLastHorz->NextInLML)) - eLastHorz = eLastHorz->NextInLML; - if (!eLastHorz->NextInLML) - eMaxPair = GetMaximaPair(eLastHorz); - - MaximaList::const_iterator maxIt; - MaximaList::const_reverse_iterator maxRit; - if (m_Maxima.size() > 0) { - // get the first maxima in range (X) ... - if (dir == dLeftToRight) { - maxIt = m_Maxima.begin(); - while (maxIt != m_Maxima.end() && *maxIt <= horzEdge->Bot.X) - maxIt++; - if (maxIt != m_Maxima.end() && *maxIt >= eLastHorz->Top.X) - maxIt = m_Maxima.end(); - } else { - maxRit = m_Maxima.rbegin(); - while (maxRit != m_Maxima.rend() && *maxRit > horzEdge->Bot.X) - maxRit++; - if (maxRit != m_Maxima.rend() && *maxRit <= eLastHorz->Top.X) - maxRit = m_Maxima.rend(); - } - } - - OutPt *op1 = 0; - - for (;;) // loop through consec. horizontal edges - { - - bool IsLastHorz = (horzEdge == eLastHorz); - TEdge *e = GetNextInAEL(horzEdge, dir); - while (e) { - - // this code block inserts extra coords into horizontal edges (in output - // polygons) whereever maxima touch these horizontal edges. This helps - //'simplifying' polygons (ie if the Simplify property is set). - if (m_Maxima.size() > 0) { - if (dir == dLeftToRight) { - while (maxIt != m_Maxima.end() && *maxIt < e->Curr.X) { - if (horzEdge->OutIdx >= 0 && !IsOpen) - AddOutPt(horzEdge, IntPoint(*maxIt, horzEdge->Bot.Y)); - maxIt++; - } - } else { - while (maxRit != m_Maxima.rend() && *maxRit > e->Curr.X) { - if (horzEdge->OutIdx >= 0 && !IsOpen) - AddOutPt(horzEdge, IntPoint(*maxRit, horzEdge->Bot.Y)); - maxRit++; - } - } - }; - - if ((dir == dLeftToRight && e->Curr.X > horzRight) || - (dir == dRightToLeft && e->Curr.X < horzLeft)) - break; - - // Also break if we've got to the end of an intermediate horizontal edge - // ... - // nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal. - if (e->Curr.X == horzEdge->Top.X && horzEdge->NextInLML && - e->Dx < horzEdge->NextInLML->Dx) - break; - - if (horzEdge->OutIdx >= 0 && !IsOpen) // note: may be done multiple times - { -#ifdef use_xyz - if (dir == dLeftToRight) - SetZ(e->Curr, *horzEdge, *e); - else - SetZ(e->Curr, *e, *horzEdge); -#endif - op1 = AddOutPt(horzEdge, e->Curr); - TEdge *eNextHorz = m_SortedEdges; - while (eNextHorz) { - if (eNextHorz->OutIdx >= 0 && - HorzSegmentsOverlap(horzEdge->Bot.X, horzEdge->Top.X, - eNextHorz->Bot.X, eNextHorz->Top.X)) { - OutPt *op2 = GetLastOutPt(eNextHorz); - AddJoin(op2, op1, eNextHorz->Top); - } - eNextHorz = eNextHorz->NextInSEL; - } - AddGhostJoin(op1, horzEdge->Bot); - } - - // OK, so far we're still in range of the horizontal Edge but make sure - // we're at the last of consec. horizontals when matching with eMaxPair - if (e == eMaxPair && IsLastHorz) { - if (horzEdge->OutIdx >= 0) - AddLocalMaxPoly(horzEdge, eMaxPair, horzEdge->Top); - DeleteFromAEL(horzEdge); - DeleteFromAEL(eMaxPair); - return; - } - - if (dir == dLeftToRight) { - IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); - IntersectEdges(horzEdge, e, Pt); - } else { - IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); - IntersectEdges(e, horzEdge, Pt); - } - TEdge *eNext = GetNextInAEL(e, dir); - SwapPositionsInAEL(horzEdge, e); - e = eNext; - } // end while(e) - - // Break out of loop if HorzEdge.NextInLML is not also horizontal ... - if (!horzEdge->NextInLML || !IsHorizontal(*horzEdge->NextInLML)) - break; - - UpdateEdgeIntoAEL(horzEdge); - if (horzEdge->OutIdx >= 0) - AddOutPt(horzEdge, horzEdge->Bot); - GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); - - } // end for (;;) - - if (horzEdge->OutIdx >= 0 && !op1) { - op1 = GetLastOutPt(horzEdge); - TEdge *eNextHorz = m_SortedEdges; - while (eNextHorz) { - if (eNextHorz->OutIdx >= 0 && - HorzSegmentsOverlap(horzEdge->Bot.X, horzEdge->Top.X, - eNextHorz->Bot.X, eNextHorz->Top.X)) { - OutPt *op2 = GetLastOutPt(eNextHorz); - AddJoin(op2, op1, eNextHorz->Top); - } - eNextHorz = eNextHorz->NextInSEL; - } - AddGhostJoin(op1, horzEdge->Top); - } - - if (horzEdge->NextInLML) { - if (horzEdge->OutIdx >= 0) { - op1 = AddOutPt(horzEdge, horzEdge->Top); - UpdateEdgeIntoAEL(horzEdge); - if (horzEdge->WindDelta == 0) - return; - // nb: HorzEdge is no longer horizontal here - TEdge *ePrev = horzEdge->PrevInAEL; - TEdge *eNext = horzEdge->NextInAEL; - if (ePrev && ePrev->Curr.X == horzEdge->Bot.X && - ePrev->Curr.Y == horzEdge->Bot.Y && ePrev->WindDelta != 0 && - (ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && - SlopesEqual(*horzEdge, *ePrev, m_UseFullRange))) { - OutPt *op2 = AddOutPt(ePrev, horzEdge->Bot); - AddJoin(op1, op2, horzEdge->Top); - } else if (eNext && eNext->Curr.X == horzEdge->Bot.X && - eNext->Curr.Y == horzEdge->Bot.Y && eNext->WindDelta != 0 && - eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && - SlopesEqual(*horzEdge, *eNext, m_UseFullRange)) { - OutPt *op2 = AddOutPt(eNext, horzEdge->Bot); - AddJoin(op1, op2, horzEdge->Top); - } - } else - UpdateEdgeIntoAEL(horzEdge); - } else { - if (horzEdge->OutIdx >= 0) - AddOutPt(horzEdge, horzEdge->Top); - DeleteFromAEL(horzEdge); - } -} -//------------------------------------------------------------------------------ - -bool Clipper::ProcessIntersections(const cInt topY) { - if (!m_ActiveEdges) - return true; - try { - BuildIntersectList(topY); - size_t IlSize = m_IntersectList.size(); - if (IlSize == 0) - return true; - if (IlSize == 1 || FixupIntersectionOrder()) - ProcessIntersectList(); - else - return false; - } catch (...) { - m_SortedEdges = 0; - DisposeIntersectNodes(); - throw clipperException("ProcessIntersections error"); - } - m_SortedEdges = 0; - return true; -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeIntersectNodes() { - for (size_t i = 0; i < m_IntersectList.size(); ++i) - delete m_IntersectList[i]; - m_IntersectList.clear(); -} -//------------------------------------------------------------------------------ - -void Clipper::BuildIntersectList(const cInt topY) { - if (!m_ActiveEdges) - return; - - // prepare for sorting ... - TEdge *e = m_ActiveEdges; - m_SortedEdges = e; - while (e) { - e->PrevInSEL = e->PrevInAEL; - e->NextInSEL = e->NextInAEL; - e->Curr.X = TopX(*e, topY); - e = e->NextInAEL; - } - - // bubblesort ... - bool isModified; - do { - isModified = false; - e = m_SortedEdges; - while (e->NextInSEL) { - TEdge *eNext = e->NextInSEL; - IntPoint Pt; - if (e->Curr.X > eNext->Curr.X) { - IntersectPoint(*e, *eNext, Pt); - if (Pt.Y < topY) - Pt = IntPoint(TopX(*e, topY), topY); - IntersectNode *newNode = new IntersectNode; - newNode->Edge1 = e; - newNode->Edge2 = eNext; - newNode->Pt = Pt; - m_IntersectList.push_back(newNode); - - SwapPositionsInSEL(e, eNext); - isModified = true; - } else - e = eNext; - } - if (e->PrevInSEL) - e->PrevInSEL->NextInSEL = 0; - else - break; - } while (isModified); - m_SortedEdges = 0; // important -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessIntersectList() { - for (size_t i = 0; i < m_IntersectList.size(); ++i) { - IntersectNode *iNode = m_IntersectList[i]; - { - IntersectEdges(iNode->Edge1, iNode->Edge2, iNode->Pt); - SwapPositionsInAEL(iNode->Edge1, iNode->Edge2); - } - delete iNode; - } - m_IntersectList.clear(); -} -//------------------------------------------------------------------------------ - -bool IntersectListSort(IntersectNode *node1, IntersectNode *node2) { - return node2->Pt.Y < node1->Pt.Y; -} -//------------------------------------------------------------------------------ - -inline bool EdgesAdjacent(const IntersectNode &inode) { - return (inode.Edge1->NextInSEL == inode.Edge2) || - (inode.Edge1->PrevInSEL == inode.Edge2); -} -//------------------------------------------------------------------------------ - -bool Clipper::FixupIntersectionOrder() { - // pre-condition: intersections are sorted Bottom-most first. - // Now it's crucial that intersections are made only between adjacent edges, - // so to ensure this the order of intersections may need adjusting ... - CopyAELToSEL(); - std::sort(m_IntersectList.begin(), m_IntersectList.end(), IntersectListSort); - size_t cnt = m_IntersectList.size(); - for (size_t i = 0; i < cnt; ++i) { - if (!EdgesAdjacent(*m_IntersectList[i])) { - size_t j = i + 1; - while (j < cnt && !EdgesAdjacent(*m_IntersectList[j])) - j++; - if (j == cnt) - return false; - std::swap(m_IntersectList[i], m_IntersectList[j]); - } - SwapPositionsInSEL(m_IntersectList[i]->Edge1, m_IntersectList[i]->Edge2); - } - return true; -} -//------------------------------------------------------------------------------ - -void Clipper::DoMaxima(TEdge *e) { - TEdge *eMaxPair = GetMaximaPairEx(e); - if (!eMaxPair) { - if (e->OutIdx >= 0) - AddOutPt(e, e->Top); - DeleteFromAEL(e); - return; - } - - TEdge *eNext = e->NextInAEL; - while (eNext && eNext != eMaxPair) { - IntersectEdges(e, eNext, e->Top); - SwapPositionsInAEL(e, eNext); - eNext = e->NextInAEL; - } - - if (e->OutIdx == Unassigned && eMaxPair->OutIdx == Unassigned) { - DeleteFromAEL(e); - DeleteFromAEL(eMaxPair); - } else if (e->OutIdx >= 0 && eMaxPair->OutIdx >= 0) { - if (e->OutIdx >= 0) - AddLocalMaxPoly(e, eMaxPair, e->Top); - DeleteFromAEL(e); - DeleteFromAEL(eMaxPair); - } -#ifdef use_lines - else if (e->WindDelta == 0) { - if (e->OutIdx >= 0) { - AddOutPt(e, e->Top); - e->OutIdx = Unassigned; - } - DeleteFromAEL(e); - - if (eMaxPair->OutIdx >= 0) { - AddOutPt(eMaxPair, e->Top); - eMaxPair->OutIdx = Unassigned; - } - DeleteFromAEL(eMaxPair); - } -#endif - else - throw clipperException("DoMaxima error"); -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY) { - TEdge *e = m_ActiveEdges; - while (e) { - // 1. process maxima, treating them as if they're 'bent' horizontal edges, - // but exclude maxima with horizontal edges. nb: e can't be a horizontal. - bool IsMaximaEdge = IsMaxima(e, topY); - - if (IsMaximaEdge) { - TEdge *eMaxPair = GetMaximaPairEx(e); - IsMaximaEdge = (!eMaxPair || !IsHorizontal(*eMaxPair)); - } - - if (IsMaximaEdge) { - if (m_StrictSimple) - m_Maxima.push_back(e->Top.X); - TEdge *ePrev = e->PrevInAEL; - DoMaxima(e); - if (!ePrev) - e = m_ActiveEdges; - else - e = ePrev->NextInAEL; - } else { - // 2. promote horizontal edges, otherwise update Curr.X and Curr.Y ... - if (IsIntermediate(e, topY) && IsHorizontal(*e->NextInLML)) { - UpdateEdgeIntoAEL(e); - if (e->OutIdx >= 0) - AddOutPt(e, e->Bot); - AddEdgeToSEL(e); - } else { - e->Curr.X = TopX(*e, topY); - e->Curr.Y = topY; -#ifdef use_xyz - e->Curr.Z = - topY == e->Top.Y ? e->Top.Z : (topY == e->Bot.Y ? e->Bot.Z : 0); -#endif - } - - // When StrictlySimple and 'e' is being touched by another edge, then - // make sure both edges have a vertex here ... - if (m_StrictSimple) { - TEdge *ePrev = e->PrevInAEL; - if ((e->OutIdx >= 0) && (e->WindDelta != 0) && ePrev && - (ePrev->OutIdx >= 0) && (ePrev->Curr.X == e->Curr.X) && - (ePrev->WindDelta != 0)) { - IntPoint pt = e->Curr; -#ifdef use_xyz - SetZ(pt, *ePrev, *e); -#endif - OutPt *op = AddOutPt(ePrev, pt); - OutPt *op2 = AddOutPt(e, pt); - AddJoin(op, op2, pt); // StrictlySimple (type-3) join - } - } - - e = e->NextInAEL; - } - } - - // 3. Process horizontals at the Top of the scanbeam ... - m_Maxima.sort(); - ProcessHorizontals(); - m_Maxima.clear(); - - // 4. Promote intermediate vertices ... - e = m_ActiveEdges; - while (e) { - if (IsIntermediate(e, topY)) { - OutPt *op = 0; - if (e->OutIdx >= 0) - op = AddOutPt(e, e->Top); - UpdateEdgeIntoAEL(e); - - // if output polygons share an edge, they'll need joining later ... - TEdge *ePrev = e->PrevInAEL; - TEdge *eNext = e->NextInAEL; - if (ePrev && ePrev->Curr.X == e->Bot.X && ePrev->Curr.Y == e->Bot.Y && - op && ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && - SlopesEqual(e->Curr, e->Top, ePrev->Curr, ePrev->Top, - m_UseFullRange) && - (e->WindDelta != 0) && (ePrev->WindDelta != 0)) { - OutPt *op2 = AddOutPt(ePrev, e->Bot); - AddJoin(op, op2, e->Top); - } else if (eNext && eNext->Curr.X == e->Bot.X && - eNext->Curr.Y == e->Bot.Y && op && eNext->OutIdx >= 0 && - eNext->Curr.Y > eNext->Top.Y && - SlopesEqual(e->Curr, e->Top, eNext->Curr, eNext->Top, - m_UseFullRange) && - (e->WindDelta != 0) && (eNext->WindDelta != 0)) { - OutPt *op2 = AddOutPt(eNext, e->Bot); - AddJoin(op, op2, e->Top); - } - } - e = e->NextInAEL; - } -} -//------------------------------------------------------------------------------ - -void Clipper::FixupOutPolyline(OutRec &outrec) { - OutPt *pp = outrec.Pts; - OutPt *lastPP = pp->Prev; - while (pp != lastPP) { - pp = pp->Next; - if (pp->Pt == pp->Prev->Pt) { - if (pp == lastPP) - lastPP = pp->Prev; - OutPt *tmpPP = pp->Prev; - tmpPP->Next = pp->Next; - pp->Next->Prev = tmpPP; - delete pp; - pp = tmpPP; - } - } - - if (pp == pp->Prev) { - DisposeOutPts(pp); - outrec.Pts = 0; - return; - } -} -//------------------------------------------------------------------------------ - -void Clipper::FixupOutPolygon(OutRec &outrec) { - // FixupOutPolygon() - removes duplicate points and simplifies consecutive - // parallel edges by removing the middle vertex. - OutPt *lastOK = 0; - outrec.BottomPt = 0; - OutPt *pp = outrec.Pts; - bool preserveCol = m_PreserveCollinear || m_StrictSimple; - - for (;;) { - if (pp->Prev == pp || pp->Prev == pp->Next) { - DisposeOutPts(pp); - outrec.Pts = 0; - return; - } - - // test for duplicate points and collinear edges ... - if ((pp->Pt == pp->Next->Pt) || (pp->Pt == pp->Prev->Pt) || - (SlopesEqual(pp->Prev->Pt, pp->Pt, pp->Next->Pt, m_UseFullRange) && - (!preserveCol || - !Pt2IsBetweenPt1AndPt3(pp->Prev->Pt, pp->Pt, pp->Next->Pt)))) { - lastOK = 0; - OutPt *tmp = pp; - pp->Prev->Next = pp->Next; - pp->Next->Prev = pp->Prev; - pp = pp->Prev; - delete tmp; - } else if (pp == lastOK) - break; - else { - if (!lastOK) - lastOK = pp; - pp = pp->Next; - } - } - outrec.Pts = pp; -} -//------------------------------------------------------------------------------ - -int PointCount(OutPt *Pts) { - if (!Pts) - return 0; - int result = 0; - OutPt *p = Pts; - do { - result++; - p = p->Next; - } while (p != Pts); - return result; -} -//------------------------------------------------------------------------------ - -void Clipper::BuildResult(Paths &polys) { - polys.reserve(m_PolyOuts.size()); - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { - if (!m_PolyOuts[i]->Pts) - continue; - Path pg; - OutPt *p = m_PolyOuts[i]->Pts->Prev; - int cnt = PointCount(p); - if (cnt < 2) - continue; - pg.reserve(cnt); - for (int i = 0; i < cnt; ++i) { - pg.push_back(p->Pt); - p = p->Prev; - } - polys.push_back(pg); - } -} -//------------------------------------------------------------------------------ - -void Clipper::BuildResult2(PolyTree &polytree) { - polytree.Clear(); - polytree.AllNodes.reserve(m_PolyOuts.size()); - // add each output polygon/contour to polytree ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++) { - OutRec *outRec = m_PolyOuts[i]; - int cnt = PointCount(outRec->Pts); - if ((outRec->IsOpen && cnt < 2) || (!outRec->IsOpen && cnt < 3)) - continue; - FixHoleLinkage(*outRec); - PolyNode *pn = new PolyNode(); - // nb: polytree takes ownership of all the PolyNodes - polytree.AllNodes.push_back(pn); - outRec->PolyNd = pn; - pn->Parent = 0; - pn->Index = 0; - pn->Contour.reserve(cnt); - OutPt *op = outRec->Pts->Prev; - for (int j = 0; j < cnt; j++) { - pn->Contour.push_back(op->Pt); - op = op->Prev; - } - } - - // fixup PolyNode links etc ... - polytree.Childs.reserve(m_PolyOuts.size()); - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); i++) { - OutRec *outRec = m_PolyOuts[i]; - if (!outRec->PolyNd) - continue; - if (outRec->IsOpen) { - outRec->PolyNd->m_IsOpen = true; - polytree.AddChild(*outRec->PolyNd); - } else if (outRec->FirstLeft && outRec->FirstLeft->PolyNd) - outRec->FirstLeft->PolyNd->AddChild(*outRec->PolyNd); - else - polytree.AddChild(*outRec->PolyNd); - } -} -//------------------------------------------------------------------------------ - -void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2) { - // just swap the contents (because fIntersectNodes is a single-linked-list) - IntersectNode inode = int1; // gets a copy of Int1 - int1.Edge1 = int2.Edge1; - int1.Edge2 = int2.Edge2; - int1.Pt = int2.Pt; - int2.Edge1 = inode.Edge1; - int2.Edge2 = inode.Edge2; - int2.Pt = inode.Pt; -} -//------------------------------------------------------------------------------ - -inline bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) { - if (e2.Curr.X == e1.Curr.X) { - if (e2.Top.Y > e1.Top.Y) - return e2.Top.X < TopX(e1, e2.Top.Y); - else - return e1.Top.X > TopX(e2, e1.Top.Y); - } else - return e2.Curr.X < e1.Curr.X; -} -//------------------------------------------------------------------------------ - -bool GetOverlap(const cInt a1, const cInt a2, const cInt b1, const cInt b2, - cInt &Left, cInt &Right) { - if (a1 < a2) { - if (b1 < b2) { - Left = std::max(a1, b1); - Right = std::min(a2, b2); - } else { - Left = std::max(a1, b2); - Right = std::min(a2, b1); - } - } else { - if (b1 < b2) { - Left = std::max(a2, b1); - Right = std::min(a1, b2); - } else { - Left = std::max(a2, b2); - Right = std::min(a1, b1); - } - } - return Left < Right; -} -//------------------------------------------------------------------------------ - -inline void UpdateOutPtIdxs(OutRec &outrec) { - OutPt *op = outrec.Pts; - do { - op->Idx = outrec.Idx; - op = op->Prev; - } while (op != outrec.Pts); -} -//------------------------------------------------------------------------------ - -void Clipper::InsertEdgeIntoAEL(TEdge *edge, TEdge *startEdge) { - if (!m_ActiveEdges) { - edge->PrevInAEL = 0; - edge->NextInAEL = 0; - m_ActiveEdges = edge; - } else if (!startEdge && E2InsertsBeforeE1(*m_ActiveEdges, *edge)) { - edge->PrevInAEL = 0; - edge->NextInAEL = m_ActiveEdges; - m_ActiveEdges->PrevInAEL = edge; - m_ActiveEdges = edge; - } else { - if (!startEdge) - startEdge = m_ActiveEdges; - while (startEdge->NextInAEL && - !E2InsertsBeforeE1(*startEdge->NextInAEL, *edge)) - startEdge = startEdge->NextInAEL; - edge->NextInAEL = startEdge->NextInAEL; - if (startEdge->NextInAEL) - startEdge->NextInAEL->PrevInAEL = edge; - edge->PrevInAEL = startEdge; - startEdge->NextInAEL = edge; - } -} -//---------------------------------------------------------------------- - -OutPt *DupOutPt(OutPt *outPt, bool InsertAfter) { - OutPt *result = new OutPt; - result->Pt = outPt->Pt; - result->Idx = outPt->Idx; - if (InsertAfter) { - result->Next = outPt->Next; - result->Prev = outPt; - outPt->Next->Prev = result; - outPt->Next = result; - } else { - result->Prev = outPt->Prev; - result->Next = outPt; - outPt->Prev->Next = result; - outPt->Prev = result; - } - return result; -} -//------------------------------------------------------------------------------ - -bool JoinHorz(OutPt *op1, OutPt *op1b, OutPt *op2, OutPt *op2b, - const IntPoint Pt, bool DiscardLeft) { - Direction Dir1 = (op1->Pt.X > op1b->Pt.X ? dRightToLeft : dLeftToRight); - Direction Dir2 = (op2->Pt.X > op2b->Pt.X ? dRightToLeft : dLeftToRight); - if (Dir1 == Dir2) - return false; - - // When DiscardLeft, we want Op1b to be on the Left of Op1, otherwise we - // want Op1b to be on the Right. (And likewise with Op2 and Op2b.) - // So, to facilitate this while inserting Op1b and Op2b ... - // when DiscardLeft, make sure we're AT or RIGHT of Pt before adding Op1b, - // otherwise make sure we're AT or LEFT of Pt. (Likewise with Op2b.) - if (Dir1 == dLeftToRight) { - while (op1->Next->Pt.X <= Pt.X && op1->Next->Pt.X >= op1->Pt.X && - op1->Next->Pt.Y == Pt.Y) - op1 = op1->Next; - if (DiscardLeft && (op1->Pt.X != Pt.X)) - op1 = op1->Next; - op1b = DupOutPt(op1, !DiscardLeft); - if (op1b->Pt != Pt) { - op1 = op1b; - op1->Pt = Pt; - op1b = DupOutPt(op1, !DiscardLeft); - } - } else { - while (op1->Next->Pt.X >= Pt.X && op1->Next->Pt.X <= op1->Pt.X && - op1->Next->Pt.Y == Pt.Y) - op1 = op1->Next; - if (!DiscardLeft && (op1->Pt.X != Pt.X)) - op1 = op1->Next; - op1b = DupOutPt(op1, DiscardLeft); - if (op1b->Pt != Pt) { - op1 = op1b; - op1->Pt = Pt; - op1b = DupOutPt(op1, DiscardLeft); - } - } - - if (Dir2 == dLeftToRight) { - while (op2->Next->Pt.X <= Pt.X && op2->Next->Pt.X >= op2->Pt.X && - op2->Next->Pt.Y == Pt.Y) - op2 = op2->Next; - if (DiscardLeft && (op2->Pt.X != Pt.X)) - op2 = op2->Next; - op2b = DupOutPt(op2, !DiscardLeft); - if (op2b->Pt != Pt) { - op2 = op2b; - op2->Pt = Pt; - op2b = DupOutPt(op2, !DiscardLeft); - }; - } else { - while (op2->Next->Pt.X >= Pt.X && op2->Next->Pt.X <= op2->Pt.X && - op2->Next->Pt.Y == Pt.Y) - op2 = op2->Next; - if (!DiscardLeft && (op2->Pt.X != Pt.X)) - op2 = op2->Next; - op2b = DupOutPt(op2, DiscardLeft); - if (op2b->Pt != Pt) { - op2 = op2b; - op2->Pt = Pt; - op2b = DupOutPt(op2, DiscardLeft); - }; - }; - - if ((Dir1 == dLeftToRight) == DiscardLeft) { - op1->Prev = op2; - op2->Next = op1; - op1b->Next = op2b; - op2b->Prev = op1b; - } else { - op1->Next = op2; - op2->Prev = op1; - op1b->Prev = op2b; - op2b->Next = op1b; - } - return true; -} -//------------------------------------------------------------------------------ - -bool Clipper::JoinPoints(Join *j, OutRec *outRec1, OutRec *outRec2) { - OutPt *op1 = j->OutPt1, *op1b; - OutPt *op2 = j->OutPt2, *op2b; - - // There are 3 kinds of joins for output polygons ... - // 1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are vertices anywhere - // along (horizontal) collinear edges (& Join.OffPt is on the same - // horizontal). - // 2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same - // location at the Bottom of the overlapping segment (& Join.OffPt is above). - // 3. StrictSimple joins where edges touch but are not collinear and where - // Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point. - bool isHorizontal = (j->OutPt1->Pt.Y == j->OffPt.Y); - - if (isHorizontal && (j->OffPt == j->OutPt1->Pt) && - (j->OffPt == j->OutPt2->Pt)) { - // Strictly Simple join ... - if (outRec1 != outRec2) - return false; - op1b = j->OutPt1->Next; - while (op1b != op1 && (op1b->Pt == j->OffPt)) - op1b = op1b->Next; - bool reverse1 = (op1b->Pt.Y > j->OffPt.Y); - op2b = j->OutPt2->Next; - while (op2b != op2 && (op2b->Pt == j->OffPt)) - op2b = op2b->Next; - bool reverse2 = (op2b->Pt.Y > j->OffPt.Y); - if (reverse1 == reverse2) - return false; - if (reverse1) { - op1b = DupOutPt(op1, false); - op2b = DupOutPt(op2, true); - op1->Prev = op2; - op2->Next = op1; - op1b->Next = op2b; - op2b->Prev = op1b; - j->OutPt1 = op1; - j->OutPt2 = op1b; - return true; - } else { - op1b = DupOutPt(op1, true); - op2b = DupOutPt(op2, false); - op1->Next = op2; - op2->Prev = op1; - op1b->Prev = op2b; - op2b->Next = op1b; - j->OutPt1 = op1; - j->OutPt2 = op1b; - return true; - } - } else if (isHorizontal) { - // treat horizontal joins differently to non-horizontal joins since with - // them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt - // may be anywhere along the horizontal edge. - op1b = op1; - while (op1->Prev->Pt.Y == op1->Pt.Y && op1->Prev != op1b && - op1->Prev != op2) - op1 = op1->Prev; - while (op1b->Next->Pt.Y == op1b->Pt.Y && op1b->Next != op1 && - op1b->Next != op2) - op1b = op1b->Next; - if (op1b->Next == op1 || op1b->Next == op2) - return false; // a flat 'polygon' - - op2b = op2; - while (op2->Prev->Pt.Y == op2->Pt.Y && op2->Prev != op2b && - op2->Prev != op1b) - op2 = op2->Prev; - while (op2b->Next->Pt.Y == op2b->Pt.Y && op2b->Next != op2 && - op2b->Next != op1) - op2b = op2b->Next; - if (op2b->Next == op2 || op2b->Next == op1) - return false; // a flat 'polygon' - - cInt Left, Right; - // Op1 --> Op1b & Op2 --> Op2b are the extremites of the horizontal edges - if (!GetOverlap(op1->Pt.X, op1b->Pt.X, op2->Pt.X, op2b->Pt.X, Left, Right)) - return false; - - // DiscardLeftSide: when overlapping edges are joined, a spike will created - // which needs to be cleaned up. However, we don't want Op1 or Op2 caught up - // on the discard Side as either may still be needed for other joins ... - IntPoint Pt; - bool DiscardLeftSide; - if (op1->Pt.X >= Left && op1->Pt.X <= Right) { - Pt = op1->Pt; - DiscardLeftSide = (op1->Pt.X > op1b->Pt.X); - } else if (op2->Pt.X >= Left && op2->Pt.X <= Right) { - Pt = op2->Pt; - DiscardLeftSide = (op2->Pt.X > op2b->Pt.X); - } else if (op1b->Pt.X >= Left && op1b->Pt.X <= Right) { - Pt = op1b->Pt; - DiscardLeftSide = op1b->Pt.X > op1->Pt.X; - } else { - Pt = op2b->Pt; - DiscardLeftSide = (op2b->Pt.X > op2->Pt.X); - } - j->OutPt1 = op1; - j->OutPt2 = op2; - return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide); - } else { - // nb: For non-horizontal joins ... - // 1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y - // 2. Jr.OutPt1.Pt > Jr.OffPt.Y - - // make sure the polygons are correctly oriented ... - op1b = op1->Next; - while ((op1b->Pt == op1->Pt) && (op1b != op1)) - op1b = op1b->Next; - bool Reverse1 = ((op1b->Pt.Y > op1->Pt.Y) || - !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)); - if (Reverse1) { - op1b = op1->Prev; - while ((op1b->Pt == op1->Pt) && (op1b != op1)) - op1b = op1b->Prev; - if ((op1b->Pt.Y > op1->Pt.Y) || - !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)) - return false; - }; - op2b = op2->Next; - while ((op2b->Pt == op2->Pt) && (op2b != op2)) - op2b = op2b->Next; - bool Reverse2 = ((op2b->Pt.Y > op2->Pt.Y) || - !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)); - if (Reverse2) { - op2b = op2->Prev; - while ((op2b->Pt == op2->Pt) && (op2b != op2)) - op2b = op2b->Prev; - if ((op2b->Pt.Y > op2->Pt.Y) || - !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)) - return false; - } - - if ((op1b == op1) || (op2b == op2) || (op1b == op2b) || - ((outRec1 == outRec2) && (Reverse1 == Reverse2))) - return false; - - if (Reverse1) { - op1b = DupOutPt(op1, false); - op2b = DupOutPt(op2, true); - op1->Prev = op2; - op2->Next = op1; - op1b->Next = op2b; - op2b->Prev = op1b; - j->OutPt1 = op1; - j->OutPt2 = op1b; - return true; - } else { - op1b = DupOutPt(op1, true); - op2b = DupOutPt(op2, false); - op1->Next = op2; - op2->Prev = op1; - op1b->Prev = op2b; - op2b->Next = op1b; - j->OutPt1 = op1; - j->OutPt2 = op1b; - return true; - } - } -} -//---------------------------------------------------------------------- - -static OutRec *ParseFirstLeft(OutRec *FirstLeft) { - while (FirstLeft && !FirstLeft->Pts) - FirstLeft = FirstLeft->FirstLeft; - return FirstLeft; -} -//------------------------------------------------------------------------------ - -void Clipper::FixupFirstLefts1(OutRec *OldOutRec, OutRec *NewOutRec) { - // tests if NewOutRec contains the polygon before reassigning FirstLeft - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { - OutRec *outRec = m_PolyOuts[i]; - OutRec *firstLeft = ParseFirstLeft(outRec->FirstLeft); - if (outRec->Pts && firstLeft == OldOutRec) { - if (Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts)) - outRec->FirstLeft = NewOutRec; - } - } -} -//---------------------------------------------------------------------- - -void Clipper::FixupFirstLefts2(OutRec *InnerOutRec, OutRec *OuterOutRec) { - // A polygon has split into two such that one is now the inner of the other. - // It's possible that these polygons now wrap around other polygons, so check - // every polygon that's also contained by OuterOutRec's FirstLeft container - //(including 0) to see if they've become inner to the new inner polygon ... - OutRec *orfl = OuterOutRec->FirstLeft; - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { - OutRec *outRec = m_PolyOuts[i]; - - if (!outRec->Pts || outRec == OuterOutRec || outRec == InnerOutRec) - continue; - OutRec *firstLeft = ParseFirstLeft(outRec->FirstLeft); - if (firstLeft != orfl && firstLeft != InnerOutRec && - firstLeft != OuterOutRec) - continue; - if (Poly2ContainsPoly1(outRec->Pts, InnerOutRec->Pts)) - outRec->FirstLeft = InnerOutRec; - else if (Poly2ContainsPoly1(outRec->Pts, OuterOutRec->Pts)) - outRec->FirstLeft = OuterOutRec; - else if (outRec->FirstLeft == InnerOutRec || - outRec->FirstLeft == OuterOutRec) - outRec->FirstLeft = orfl; - } -} -//---------------------------------------------------------------------- -void Clipper::FixupFirstLefts3(OutRec *OldOutRec, OutRec *NewOutRec) { - // reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) { - OutRec *outRec = m_PolyOuts[i]; - OutRec *firstLeft = ParseFirstLeft(outRec->FirstLeft); - if (outRec->Pts && firstLeft == OldOutRec) - outRec->FirstLeft = NewOutRec; - } -} -//---------------------------------------------------------------------- - -void Clipper::JoinCommonEdges() { - for (JoinList::size_type i = 0; i < m_Joins.size(); i++) { - Join *join = m_Joins[i]; - - OutRec *outRec1 = GetOutRec(join->OutPt1->Idx); - OutRec *outRec2 = GetOutRec(join->OutPt2->Idx); - - if (!outRec1->Pts || !outRec2->Pts) - continue; - if (outRec1->IsOpen || outRec2->IsOpen) - continue; - - // get the polygon fragment with the correct hole state (FirstLeft) - // before calling JoinPoints() ... - OutRec *holeStateRec; - if (outRec1 == outRec2) - holeStateRec = outRec1; - else if (OutRec1RightOfOutRec2(outRec1, outRec2)) - holeStateRec = outRec2; - else if (OutRec1RightOfOutRec2(outRec2, outRec1)) - holeStateRec = outRec1; - else - holeStateRec = GetLowermostRec(outRec1, outRec2); - - if (!JoinPoints(join, outRec1, outRec2)) - continue; - - if (outRec1 == outRec2) { - // instead of joining two polygons, we've just created a new one by - // splitting one polygon into two. - outRec1->Pts = join->OutPt1; - outRec1->BottomPt = 0; - outRec2 = CreateOutRec(); - outRec2->Pts = join->OutPt2; - - // update all OutRec2.Pts Idx's ... - UpdateOutPtIdxs(*outRec2); - - if (Poly2ContainsPoly1(outRec2->Pts, outRec1->Pts)) { - // outRec1 contains outRec2 ... - outRec2->IsHole = !outRec1->IsHole; - outRec2->FirstLeft = outRec1; - - if (m_UsingPolyTree) - FixupFirstLefts2(outRec2, outRec1); - - if ((outRec2->IsHole ^ m_ReverseOutput) == (Area(*outRec2) > 0)) - ReversePolyPtLinks(outRec2->Pts); - - } else if (Poly2ContainsPoly1(outRec1->Pts, outRec2->Pts)) { - // outRec2 contains outRec1 ... - outRec2->IsHole = outRec1->IsHole; - outRec1->IsHole = !outRec2->IsHole; - outRec2->FirstLeft = outRec1->FirstLeft; - outRec1->FirstLeft = outRec2; - - if (m_UsingPolyTree) - FixupFirstLefts2(outRec1, outRec2); - - if ((outRec1->IsHole ^ m_ReverseOutput) == (Area(*outRec1) > 0)) - ReversePolyPtLinks(outRec1->Pts); - } else { - // the 2 polygons are completely separate ... - outRec2->IsHole = outRec1->IsHole; - outRec2->FirstLeft = outRec1->FirstLeft; - - // fixup FirstLeft pointers that may need reassigning to OutRec2 - if (m_UsingPolyTree) - FixupFirstLefts1(outRec1, outRec2); - } - - } else { - // joined 2 polygons together ... - - outRec2->Pts = 0; - outRec2->BottomPt = 0; - outRec2->Idx = outRec1->Idx; - - outRec1->IsHole = holeStateRec->IsHole; - if (holeStateRec == outRec2) - outRec1->FirstLeft = outRec2->FirstLeft; - outRec2->FirstLeft = outRec1; - - if (m_UsingPolyTree) - FixupFirstLefts3(outRec2, outRec1); - } - } -} - -//------------------------------------------------------------------------------ -// ClipperOffset support functions ... -//------------------------------------------------------------------------------ - -DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2) { - if (pt2.X == pt1.X && pt2.Y == pt1.Y) - return DoublePoint(0, 0); - - double Dx = (double)(pt2.X - pt1.X); - double dy = (double)(pt2.Y - pt1.Y); - double f = 1 * 1.0 / std::sqrt(Dx * Dx + dy * dy); - Dx *= f; - dy *= f; - return DoublePoint(dy, -Dx); -} - -//------------------------------------------------------------------------------ -// ClipperOffset class -//------------------------------------------------------------------------------ - -ClipperOffset::ClipperOffset(double miterLimit, double arcTolerance) { - this->MiterLimit = miterLimit; - this->ArcTolerance = arcTolerance; - m_lowest.X = -1; -} -//------------------------------------------------------------------------------ - -ClipperOffset::~ClipperOffset() { Clear(); } -//------------------------------------------------------------------------------ - -void ClipperOffset::Clear() { - for (int i = 0; i < m_polyNodes.ChildCount(); ++i) - delete m_polyNodes.Childs[i]; - m_polyNodes.Childs.clear(); - m_lowest.X = -1; -} -//------------------------------------------------------------------------------ - -void ClipperOffset::AddPath(const Path &path, JoinType joinType, - EndType endType) { - int highI = (int)path.size() - 1; - if (highI < 0) - return; - PolyNode *newNode = new PolyNode(); - newNode->m_jointype = joinType; - newNode->m_endtype = endType; - - // strip duplicate points from path and also get index to the lowest point ... - if (endType == etClosedLine || endType == etClosedPolygon) - while (highI > 0 && path[0] == path[highI]) - highI--; - newNode->Contour.reserve(highI + 1); - newNode->Contour.push_back(path[0]); - int j = 0, k = 0; - for (int i = 1; i <= highI; i++) - if (newNode->Contour[j] != path[i]) { - j++; - newNode->Contour.push_back(path[i]); - if (path[i].Y > newNode->Contour[k].Y || - (path[i].Y == newNode->Contour[k].Y && - path[i].X < newNode->Contour[k].X)) - k = j; - } - if (endType == etClosedPolygon && j < 2) { - delete newNode; - return; - } - m_polyNodes.AddChild(*newNode); - - // if this path's lowest pt is lower than all the others then update m_lowest - if (endType != etClosedPolygon) - return; - if (m_lowest.X < 0) - m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); - else { - IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X]->Contour[(int)m_lowest.Y]; - if (newNode->Contour[k].Y > ip.Y || - (newNode->Contour[k].Y == ip.Y && newNode->Contour[k].X < ip.X)) - m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); - } -} -//------------------------------------------------------------------------------ - -void ClipperOffset::AddPaths(const Paths &paths, JoinType joinType, - EndType endType) { - for (Paths::size_type i = 0; i < paths.size(); ++i) - AddPath(paths[i], joinType, endType); -} -//------------------------------------------------------------------------------ - -void ClipperOffset::FixOrientations() { - // fixup orientations of all closed paths if the orientation of the - // closed path with the lowermost vertex is wrong ... - if (m_lowest.X >= 0 && - !Orientation(m_polyNodes.Childs[(int)m_lowest.X]->Contour)) { - for (int i = 0; i < m_polyNodes.ChildCount(); ++i) { - PolyNode &node = *m_polyNodes.Childs[i]; - if (node.m_endtype == etClosedPolygon || - (node.m_endtype == etClosedLine && Orientation(node.Contour))) - ReversePath(node.Contour); - } - } else { - for (int i = 0; i < m_polyNodes.ChildCount(); ++i) { - PolyNode &node = *m_polyNodes.Childs[i]; - if (node.m_endtype == etClosedLine && !Orientation(node.Contour)) - ReversePath(node.Contour); - } - } -} -//------------------------------------------------------------------------------ - -void ClipperOffset::Execute(Paths &solution, double delta) { - solution.clear(); - FixOrientations(); - DoOffset(delta); - - // now clean up 'corners' ... - Clipper clpr; - clpr.AddPaths(m_destPolys, ptSubject, true); - if (delta > 0) { - clpr.Execute(ctUnion, solution, pftPositive, pftPositive); - } else { - IntRect r = clpr.GetBounds(); - Path outer(4); - outer[0] = IntPoint(r.left - 10, r.bottom + 10); - outer[1] = IntPoint(r.right + 10, r.bottom + 10); - outer[2] = IntPoint(r.right + 10, r.top - 10); - outer[3] = IntPoint(r.left - 10, r.top - 10); - - clpr.AddPath(outer, ptSubject, true); - clpr.ReverseSolution(true); - clpr.Execute(ctUnion, solution, pftNegative, pftNegative); - if (solution.size() > 0) - solution.erase(solution.begin()); - } -} -//------------------------------------------------------------------------------ - -void ClipperOffset::Execute(PolyTree &solution, double delta) { - solution.Clear(); - FixOrientations(); - DoOffset(delta); - - // now clean up 'corners' ... - Clipper clpr; - clpr.AddPaths(m_destPolys, ptSubject, true); - if (delta > 0) { - clpr.Execute(ctUnion, solution, pftPositive, pftPositive); - } else { - IntRect r = clpr.GetBounds(); - Path outer(4); - outer[0] = IntPoint(r.left - 10, r.bottom + 10); - outer[1] = IntPoint(r.right + 10, r.bottom + 10); - outer[2] = IntPoint(r.right + 10, r.top - 10); - outer[3] = IntPoint(r.left - 10, r.top - 10); - - clpr.AddPath(outer, ptSubject, true); - clpr.ReverseSolution(true); - clpr.Execute(ctUnion, solution, pftNegative, pftNegative); - // remove the outer PolyNode rectangle ... - if (solution.ChildCount() == 1 && solution.Childs[0]->ChildCount() > 0) { - PolyNode *outerNode = solution.Childs[0]; - solution.Childs.reserve(outerNode->ChildCount()); - solution.Childs[0] = outerNode->Childs[0]; - solution.Childs[0]->Parent = outerNode->Parent; - for (int i = 1; i < outerNode->ChildCount(); ++i) - solution.AddChild(*outerNode->Childs[i]); - } else - solution.Clear(); - } -} -//------------------------------------------------------------------------------ - -void ClipperOffset::DoOffset(double delta) { - m_destPolys.clear(); - m_delta = delta; - - // if Zero offset, just copy any CLOSED polygons to m_p and return ... - if (NEAR_ZERO(delta)) { - m_destPolys.reserve(m_polyNodes.ChildCount()); - for (int i = 0; i < m_polyNodes.ChildCount(); i++) { - PolyNode &node = *m_polyNodes.Childs[i]; - if (node.m_endtype == etClosedPolygon) - m_destPolys.push_back(node.Contour); - } - return; - } - - // see offset_triginometry3.svg in the documentation folder ... - if (MiterLimit > 2) - m_miterLim = 2 / (MiterLimit * MiterLimit); - else - m_miterLim = 0.5; - - double y; - if (ArcTolerance <= 0.0) - y = def_arc_tolerance; - else if (ArcTolerance > std::fabs(delta) * def_arc_tolerance) - y = std::fabs(delta) * def_arc_tolerance; - else - y = ArcTolerance; - // see offset_triginometry2.svg in the documentation folder ... - double steps = pi / std::acos(1 - y / std::fabs(delta)); - if (steps > std::fabs(delta) * pi) - steps = std::fabs(delta) * pi; // ie excessive precision check - m_sin = std::sin(two_pi / steps); - m_cos = std::cos(two_pi / steps); - m_StepsPerRad = steps / two_pi; - if (delta < 0.0) - m_sin = -m_sin; - - m_destPolys.reserve(m_polyNodes.ChildCount() * 2); - for (int i = 0; i < m_polyNodes.ChildCount(); i++) { - PolyNode &node = *m_polyNodes.Childs[i]; - m_srcPoly = node.Contour; - - int len = (int)m_srcPoly.size(); - if (len == 0 || - (delta <= 0 && (len < 3 || node.m_endtype != etClosedPolygon))) - continue; - - m_destPoly.clear(); - if (len == 1) { - if (node.m_jointype == jtRound) { - double X = 1.0, Y = 0.0; - for (cInt j = 1; j <= steps; j++) { - m_destPoly.push_back(IntPoint(Round(m_srcPoly[0].X + X * delta), - Round(m_srcPoly[0].Y + Y * delta))); - double X2 = X; - X = X * m_cos - m_sin * Y; - Y = X2 * m_sin + Y * m_cos; - } - } else { - double X = -1.0, Y = -1.0; - for (int j = 0; j < 4; ++j) { - m_destPoly.push_back(IntPoint(Round(m_srcPoly[0].X + X * delta), - Round(m_srcPoly[0].Y + Y * delta))); - if (X < 0) - X = 1; - else if (Y < 0) - Y = 1; - else - X = -1; - } - } - m_destPolys.push_back(m_destPoly); - continue; - } - // build m_normals ... - m_normals.clear(); - m_normals.reserve(len); - for (int j = 0; j < len - 1; ++j) - m_normals.push_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1])); - if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon) - m_normals.push_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0])); - else - m_normals.push_back(DoublePoint(m_normals[len - 2])); - - if (node.m_endtype == etClosedPolygon) { - int k = len - 1; - for (int j = 0; j < len; ++j) - OffsetPoint(j, k, node.m_jointype); - m_destPolys.push_back(m_destPoly); - } else if (node.m_endtype == etClosedLine) { - int k = len - 1; - for (int j = 0; j < len; ++j) - OffsetPoint(j, k, node.m_jointype); - m_destPolys.push_back(m_destPoly); - m_destPoly.clear(); - // re-build m_normals ... - DoublePoint n = m_normals[len - 1]; - for (int j = len - 1; j > 0; j--) - m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); - m_normals[0] = DoublePoint(-n.X, -n.Y); - k = 0; - for (int j = len - 1; j >= 0; j--) - OffsetPoint(j, k, node.m_jointype); - m_destPolys.push_back(m_destPoly); - } else { - int k = 0; - for (int j = 1; j < len - 1; ++j) - OffsetPoint(j, k, node.m_jointype); - - IntPoint pt1; - if (node.m_endtype == etOpenButt) { - int j = len - 1; - pt1 = IntPoint((cInt)Round(m_srcPoly[j].X + m_normals[j].X * delta), - (cInt)Round(m_srcPoly[j].Y + m_normals[j].Y * delta)); - m_destPoly.push_back(pt1); - pt1 = IntPoint((cInt)Round(m_srcPoly[j].X - m_normals[j].X * delta), - (cInt)Round(m_srcPoly[j].Y - m_normals[j].Y * delta)); - m_destPoly.push_back(pt1); - } else { - int j = len - 1; - k = len - 2; - m_sinA = 0; - m_normals[j] = DoublePoint(-m_normals[j].X, -m_normals[j].Y); - if (node.m_endtype == etOpenSquare) - DoSquare(j, k); - else - DoRound(j, k); - } - - // re-build m_normals ... - for (int j = len - 1; j > 0; j--) - m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); - m_normals[0] = DoublePoint(-m_normals[1].X, -m_normals[1].Y); - - k = len - 1; - for (int j = k - 1; j > 0; --j) - OffsetPoint(j, k, node.m_jointype); - - if (node.m_endtype == etOpenButt) { - pt1 = IntPoint((cInt)Round(m_srcPoly[0].X - m_normals[0].X * delta), - (cInt)Round(m_srcPoly[0].Y - m_normals[0].Y * delta)); - m_destPoly.push_back(pt1); - pt1 = IntPoint((cInt)Round(m_srcPoly[0].X + m_normals[0].X * delta), - (cInt)Round(m_srcPoly[0].Y + m_normals[0].Y * delta)); - m_destPoly.push_back(pt1); - } else { - k = 1; - m_sinA = 0; - if (node.m_endtype == etOpenSquare) - DoSquare(0, 1); - else - DoRound(0, 1); - } - m_destPolys.push_back(m_destPoly); - } - } -} -//------------------------------------------------------------------------------ - -void ClipperOffset::OffsetPoint(int j, int &k, JoinType jointype) { - // cross product ... - m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y); - if (std::fabs(m_sinA * m_delta) < 1.0) { - // dot product ... - double cosA = - (m_normals[k].X * m_normals[j].X + m_normals[j].Y * m_normals[k].Y); - if (cosA > 0) // angle => 0 degrees - { - m_destPoly.push_back( - IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), - Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); - return; - } - // else angle => 180 degrees - } else if (m_sinA > 1.0) - m_sinA = 1.0; - else if (m_sinA < -1.0) - m_sinA = -1.0; - - if (m_sinA * m_delta < 0) { - m_destPoly.push_back( - IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), - Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); - m_destPoly.push_back(m_srcPoly[j]); - m_destPoly.push_back( - IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta), - Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); - } else - switch (jointype) { - case jtMiter: { - double r = 1 + (m_normals[j].X * m_normals[k].X + - m_normals[j].Y * m_normals[k].Y); - if (r >= m_miterLim) - DoMiter(j, k, r); - else - DoSquare(j, k); - break; - } - case jtSquare: - DoSquare(j, k); - break; - case jtRound: - DoRound(j, k); - break; - } - k = j; -} -//------------------------------------------------------------------------------ - -void ClipperOffset::DoSquare(int j, int k) { - double dx = std::tan(std::atan2(m_sinA, m_normals[k].X * m_normals[j].X + - m_normals[k].Y * m_normals[j].Y) / - 4); - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[j].X + m_delta * (m_normals[k].X - m_normals[k].Y * dx)), - Round(m_srcPoly[j].Y + - m_delta * (m_normals[k].Y + m_normals[k].X * dx)))); - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[j].X + m_delta * (m_normals[j].X + m_normals[j].Y * dx)), - Round(m_srcPoly[j].Y + - m_delta * (m_normals[j].Y - m_normals[j].X * dx)))); -} -//------------------------------------------------------------------------------ - -void ClipperOffset::DoMiter(int j, int k, double r) { - double q = m_delta / r; - m_destPoly.push_back( - IntPoint(Round(m_srcPoly[j].X + (m_normals[k].X + m_normals[j].X) * q), - Round(m_srcPoly[j].Y + (m_normals[k].Y + m_normals[j].Y) * q))); -} -//------------------------------------------------------------------------------ - -void ClipperOffset::DoRound(int j, int k) { - double a = std::atan2(m_sinA, m_normals[k].X * m_normals[j].X + - m_normals[k].Y * m_normals[j].Y); - int steps = std::max((int)Round(m_StepsPerRad * std::fabs(a)), 1); - - double X = m_normals[k].X, Y = m_normals[k].Y, X2; - for (int i = 0; i < steps; ++i) { - m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + X * m_delta), - Round(m_srcPoly[j].Y + Y * m_delta))); - X2 = X; - X = X * m_cos - m_sin * Y; - Y = X2 * m_sin + Y * m_cos; - } - m_destPoly.push_back( - IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta), - Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); -} - -//------------------------------------------------------------------------------ -// Miscellaneous public functions -//------------------------------------------------------------------------------ - -void Clipper::DoSimplePolygons() { - PolyOutList::size_type i = 0; - while (i < m_PolyOuts.size()) { - OutRec *outrec = m_PolyOuts[i++]; - OutPt *op = outrec->Pts; - if (!op || outrec->IsOpen) - continue; - do // for each Pt in Polygon until duplicate found do ... - { - OutPt *op2 = op->Next; - while (op2 != outrec->Pts) { - if ((op->Pt == op2->Pt) && op2->Next != op && op2->Prev != op) { - // split the polygon into two ... - OutPt *op3 = op->Prev; - OutPt *op4 = op2->Prev; - op->Prev = op4; - op4->Next = op; - op2->Prev = op3; - op3->Next = op2; - - outrec->Pts = op; - OutRec *outrec2 = CreateOutRec(); - outrec2->Pts = op2; - UpdateOutPtIdxs(*outrec2); - if (Poly2ContainsPoly1(outrec2->Pts, outrec->Pts)) { - // OutRec2 is contained by OutRec1 ... - outrec2->IsHole = !outrec->IsHole; - outrec2->FirstLeft = outrec; - if (m_UsingPolyTree) - FixupFirstLefts2(outrec2, outrec); - } else if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts)) { - // OutRec1 is contained by OutRec2 ... - outrec2->IsHole = outrec->IsHole; - outrec->IsHole = !outrec2->IsHole; - outrec2->FirstLeft = outrec->FirstLeft; - outrec->FirstLeft = outrec2; - if (m_UsingPolyTree) - FixupFirstLefts2(outrec, outrec2); - } else { - // the 2 polygons are separate ... - outrec2->IsHole = outrec->IsHole; - outrec2->FirstLeft = outrec->FirstLeft; - if (m_UsingPolyTree) - FixupFirstLefts1(outrec, outrec2); - } - op2 = op; // ie get ready for the Next iteration - } - op2 = op2->Next; - } - op = op->Next; - } while (op != outrec->Pts); - } -} -//------------------------------------------------------------------------------ - -void ReversePath(Path &p) { std::reverse(p.begin(), p.end()); } -//------------------------------------------------------------------------------ - -void ReversePaths(Paths &p) { - for (Paths::size_type i = 0; i < p.size(); ++i) - ReversePath(p[i]); -} -//------------------------------------------------------------------------------ - -void SimplifyPolygon(const Path &in_poly, Paths &out_polys, - PolyFillType fillType) { - Clipper c; - c.StrictlySimple(true); - c.AddPath(in_poly, ptSubject, true); - c.Execute(ctUnion, out_polys, fillType, fillType); -} -//------------------------------------------------------------------------------ - -void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, - PolyFillType fillType) { - Clipper c; - c.StrictlySimple(true); - c.AddPaths(in_polys, ptSubject, true); - c.Execute(ctUnion, out_polys, fillType, fillType); -} -//------------------------------------------------------------------------------ - -void SimplifyPolygons(Paths &polys, PolyFillType fillType) { - SimplifyPolygons(polys, polys, fillType); -} -//------------------------------------------------------------------------------ - -inline double DistanceSqrd(const IntPoint &pt1, const IntPoint &pt2) { - double Dx = ((double)pt1.X - pt2.X); - double dy = ((double)pt1.Y - pt2.Y); - return (Dx * Dx + dy * dy); -} -//------------------------------------------------------------------------------ - -double DistanceFromLineSqrd(const IntPoint &pt, const IntPoint &ln1, - const IntPoint &ln2) { - // The equation of a line in general form (Ax + By + C = 0) - // given 2 points (x�,y�) & (x�,y�) is ... - //(y� - y�)x + (x� - x�)y + (y� - y�)x� - (x� - x�)y� = 0 - // A = (y� - y�); B = (x� - x�); C = (y� - y�)x� - (x� - x�)y� - // perpendicular distance of point (x�,y�) = (Ax� + By� + C)/Sqrt(A� + B�) - // see http://en.wikipedia.org/wiki/Perpendicular_distance - double A = double(ln1.Y - ln2.Y); - double B = double(ln2.X - ln1.X); - double C = A * ln1.X + B * ln1.Y; - C = A * pt.X + B * pt.Y - C; - return (C * C) / (A * A + B * B); -} -//--------------------------------------------------------------------------- - -bool SlopesNearCollinear(const IntPoint &pt1, const IntPoint &pt2, - const IntPoint &pt3, double distSqrd) { - // this function is more accurate when the point that's geometrically - // between the other 2 points is the one that's tested for distance. - // ie makes it more likely to pick up 'spikes' ... - if (Abs(pt1.X - pt2.X) > Abs(pt1.Y - pt2.Y)) { - if ((pt1.X > pt2.X) == (pt1.X < pt3.X)) - return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; - else if ((pt2.X > pt1.X) == (pt2.X < pt3.X)) - return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; - else - return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; - } else { - if ((pt1.Y > pt2.Y) == (pt1.Y < pt3.Y)) - return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; - else if ((pt2.Y > pt1.Y) == (pt2.Y < pt3.Y)) - return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; - else - return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; - } -} -//------------------------------------------------------------------------------ - -bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd) { - double Dx = (double)pt1.X - pt2.X; - double dy = (double)pt1.Y - pt2.Y; - return ((Dx * Dx) + (dy * dy) <= distSqrd); -} -//------------------------------------------------------------------------------ - -OutPt *ExcludeOp(OutPt *op) { - OutPt *result = op->Prev; - result->Next = op->Next; - op->Next->Prev = result; - result->Idx = 0; - return result; -} -//------------------------------------------------------------------------------ - -void CleanPolygon(const Path &in_poly, Path &out_poly, double distance) { - // distance = proximity in units/pixels below which vertices - // will be stripped. Default ~= sqrt(2). - - size_t size = in_poly.size(); - - if (size == 0) { - out_poly.clear(); - return; - } - - OutPt *outPts = new OutPt[size]; - for (size_t i = 0; i < size; ++i) { - outPts[i].Pt = in_poly[i]; - outPts[i].Next = &outPts[(i + 1) % size]; - outPts[i].Next->Prev = &outPts[i]; - outPts[i].Idx = 0; - } - - double distSqrd = distance * distance; - OutPt *op = &outPts[0]; - while (op->Idx == 0 && op->Next != op->Prev) { - if (PointsAreClose(op->Pt, op->Prev->Pt, distSqrd)) { - op = ExcludeOp(op); - size--; - } else if (PointsAreClose(op->Prev->Pt, op->Next->Pt, distSqrd)) { - ExcludeOp(op->Next); - op = ExcludeOp(op); - size -= 2; - } else if (SlopesNearCollinear(op->Prev->Pt, op->Pt, op->Next->Pt, - distSqrd)) { - op = ExcludeOp(op); - size--; - } else { - op->Idx = 1; - op = op->Next; - } - } - - if (size < 3) - size = 0; - out_poly.resize(size); - for (size_t i = 0; i < size; ++i) { - out_poly[i] = op->Pt; - op = op->Next; - } - delete[] outPts; -} -//------------------------------------------------------------------------------ - -void CleanPolygon(Path &poly, double distance) { - CleanPolygon(poly, poly, distance); -} -//------------------------------------------------------------------------------ - -void CleanPolygons(const Paths &in_polys, Paths &out_polys, double distance) { - out_polys.resize(in_polys.size()); - for (Paths::size_type i = 0; i < in_polys.size(); ++i) - CleanPolygon(in_polys[i], out_polys[i], distance); -} -//------------------------------------------------------------------------------ - -void CleanPolygons(Paths &polys, double distance) { - CleanPolygons(polys, polys, distance); -} -//------------------------------------------------------------------------------ - -void Minkowski(const Path &poly, const Path &path, Paths &solution, bool isSum, - bool isClosed) { - int delta = (isClosed ? 1 : 0); - size_t polyCnt = poly.size(); - size_t pathCnt = path.size(); - Paths pp; - pp.reserve(pathCnt); - if (isSum) - for (size_t i = 0; i < pathCnt; ++i) { - Path p; - p.reserve(polyCnt); - for (size_t j = 0; j < poly.size(); ++j) - p.push_back(IntPoint(path[i].X + poly[j].X, path[i].Y + poly[j].Y)); - pp.push_back(p); - } - else - for (size_t i = 0; i < pathCnt; ++i) { - Path p; - p.reserve(polyCnt); - for (size_t j = 0; j < poly.size(); ++j) - p.push_back(IntPoint(path[i].X - poly[j].X, path[i].Y - poly[j].Y)); - pp.push_back(p); - } - - solution.clear(); - solution.reserve((pathCnt + delta) * (polyCnt + 1)); - for (size_t i = 0; i < pathCnt - 1 + delta; ++i) - for (size_t j = 0; j < polyCnt; ++j) { - Path quad; - quad.reserve(4); - quad.push_back(pp[i % pathCnt][j % polyCnt]); - quad.push_back(pp[(i + 1) % pathCnt][j % polyCnt]); - quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]); - quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]); - if (!Orientation(quad)) - ReversePath(quad); - solution.push_back(quad); - } -} -//------------------------------------------------------------------------------ - -void MinkowskiSum(const Path &pattern, const Path &path, Paths &solution, - bool pathIsClosed) { - Minkowski(pattern, path, solution, true, pathIsClosed); - Clipper c; - c.AddPaths(solution, ptSubject, true); - c.Execute(ctUnion, solution, pftNonZero, pftNonZero); -} -//------------------------------------------------------------------------------ - -void TranslatePath(const Path &input, Path &output, const IntPoint delta) { - // precondition: input != output - output.resize(input.size()); - for (size_t i = 0; i < input.size(); ++i) - output[i] = IntPoint(input[i].X + delta.X, input[i].Y + delta.Y); -} -//------------------------------------------------------------------------------ - -void MinkowskiSum(const Path &pattern, const Paths &paths, Paths &solution, - bool pathIsClosed) { - Clipper c; - for (size_t i = 0; i < paths.size(); ++i) { - Paths tmp; - Minkowski(pattern, paths[i], tmp, true, pathIsClosed); - c.AddPaths(tmp, ptSubject, true); - if (pathIsClosed) { - Path tmp2; - TranslatePath(paths[i], tmp2, pattern[0]); - c.AddPath(tmp2, ptClip, true); - } - } - c.Execute(ctUnion, solution, pftNonZero, pftNonZero); -} -//------------------------------------------------------------------------------ - -void MinkowskiDiff(const Path &poly1, const Path &poly2, Paths &solution) { - Minkowski(poly1, poly2, solution, false, true); - Clipper c; - c.AddPaths(solution, ptSubject, true); - c.Execute(ctUnion, solution, pftNonZero, pftNonZero); -} -//------------------------------------------------------------------------------ - -enum NodeType { ntAny, ntOpen, ntClosed }; - -void AddPolyNodeToPaths(const PolyNode &polynode, NodeType nodetype, - Paths &paths) { - bool match = true; - if (nodetype == ntClosed) - match = !polynode.IsOpen(); - else if (nodetype == ntOpen) - return; - - if (!polynode.Contour.empty() && match) - paths.push_back(polynode.Contour); - for (int i = 0; i < polynode.ChildCount(); ++i) - AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths); -} -//------------------------------------------------------------------------------ - -void PolyTreeToPaths(const PolyTree &polytree, Paths &paths) { - paths.resize(0); - paths.reserve(polytree.Total()); - AddPolyNodeToPaths(polytree, ntAny, paths); -} -//------------------------------------------------------------------------------ - -void ClosedPathsFromPolyTree(const PolyTree &polytree, Paths &paths) { - paths.resize(0); - paths.reserve(polytree.Total()); - AddPolyNodeToPaths(polytree, ntClosed, paths); -} -//------------------------------------------------------------------------------ - -void OpenPathsFromPolyTree(PolyTree &polytree, Paths &paths) { - paths.resize(0); - paths.reserve(polytree.Total()); - // Open paths are top level only, so ... - for (int i = 0; i < polytree.ChildCount(); ++i) - if (polytree.Childs[i]->IsOpen()) - paths.push_back(polytree.Childs[i]->Contour); -} -//------------------------------------------------------------------------------ - -std::ostream &operator<<(std::ostream &s, const IntPoint &p) { - s << "(" << p.X << "," << p.Y << ")"; - return s; -} -//------------------------------------------------------------------------------ - -std::ostream &operator<<(std::ostream &s, const Path &p) { - if (p.empty()) - return s; - Path::size_type last = p.size() - 1; - for (Path::size_type i = 0; i < last; i++) - s << "(" << p[i].X << "," << p[i].Y << "), "; - s << "(" << p[last].X << "," << p[last].Y << ")\n"; - return s; -} -//------------------------------------------------------------------------------ - -std::ostream &operator<<(std::ostream &s, const Paths &p) { - for (Paths::size_type i = 0; i < p.size(); i++) - s << p[i]; - s << "\n"; - return s; -} -//------------------------------------------------------------------------------ - -} // ClipperLib namespace diff --git a/libs/paddleocr/src/main/cpp/ocr_clipper.hpp b/libs/paddleocr/src/main/cpp/ocr_clipper.hpp deleted file mode 100644 index 60af2bb7..00000000 --- a/libs/paddleocr/src/main/cpp/ocr_clipper.hpp +++ /dev/null @@ -1,544 +0,0 @@ -/******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 6.4.2 * -* Date : 27 February 2017 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2017 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -* Attributions: * -* The code in this library is an extension of Bala Vatti's clipping algorithm: * -* "A generic solution to polygon clipping" * -* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * -* http://portal.acm.org/citation.cfm?id=129906 * -* * -* Computer graphics and geometric modeling: implementation and algorithms * -* By Max K. Agoston * -* Springer; 1 edition (January 4, 2005) * -* http://books.google.com/books?q=vatti+clipping+agoston * -* * -* See also: * -* "Polygon Offsetting by Computing Winding Numbers" * -* Paper no. DETC2005-85513 pp. 565-575 * -* ASME 2005 International Design Engineering Technical Conferences * -* and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24-28, 2005 , Long Beach, California, USA * -* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * -* * -*******************************************************************************/ - -#ifndef clipper_hpp -#define clipper_hpp - -#define CLIPPER_VERSION "6.4.2" - -// use_int32: When enabled 32bit ints are used instead of 64bit ints. This -// improve performance but coordinate values are limited to the range +/- 46340 -//#define use_int32 - -// use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance. -//#define use_xyz - -// use_lines: Enables line clipping. Adds a very minor cost to performance. -#define use_lines - -// use_deprecated: Enables temporary support for the obsolete functions -//#define use_deprecated - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ClipperLib { - -enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; -enum PolyType { ptSubject, ptClip }; -// By far the most widely used winding rules for polygon filling are -// EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) -// Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) -// see http://glprogramming.com/red/chapter11.html -enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; - -#ifdef use_int32 -typedef int cInt; -static cInt const loRange = 0x7FFF; -static cInt const hiRange = 0x7FFF; -#else -typedef signed long long cInt; -static cInt const loRange = 0x3FFFFFFF; -static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL; -typedef signed long long long64; // used by Int128 class -typedef unsigned long long ulong64; - -#endif - -struct IntPoint { - cInt X; - cInt Y; -#ifdef use_xyz - cInt Z; - IntPoint(cInt x = 0, cInt y = 0, cInt z = 0) : X(x), Y(y), Z(z){}; -#else - - IntPoint(cInt x = 0, cInt y = 0) : X(x), Y(y){}; -#endif - - friend inline bool operator==(const IntPoint &a, const IntPoint &b) { - return a.X == b.X && a.Y == b.Y; - } - - friend inline bool operator!=(const IntPoint &a, const IntPoint &b) { - return a.X != b.X || a.Y != b.Y; - } -}; -//------------------------------------------------------------------------------ - -typedef std::vector Path; -typedef std::vector Paths; - -inline Path &operator<<(Path &poly, const IntPoint &p) { - poly.push_back(p); - return poly; -} - -inline Paths &operator<<(Paths &polys, const Path &p) { - polys.push_back(p); - return polys; -} - -std::ostream &operator<<(std::ostream &s, const IntPoint &p); - -std::ostream &operator<<(std::ostream &s, const Path &p); - -std::ostream &operator<<(std::ostream &s, const Paths &p); - -struct DoublePoint { - double X; - double Y; - - DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} - - DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {} -}; -//------------------------------------------------------------------------------ - -#ifdef use_xyz -typedef void (*ZFillCallback)(IntPoint &e1bot, IntPoint &e1top, IntPoint &e2bot, - IntPoint &e2top, IntPoint &pt); -#endif - -enum InitOptions { - ioReverseSolution = 1, - ioStrictlySimple = 2, - ioPreserveCollinear = 4 -}; -enum JoinType { jtSquare, jtRound, jtMiter }; -enum EndType { - etClosedPolygon, - etClosedLine, - etOpenButt, - etOpenSquare, - etOpenRound -}; - -class PolyNode; - -typedef std::vector PolyNodes; - -class PolyNode { -public: - PolyNode(); - - virtual ~PolyNode(){}; - Path Contour; - PolyNodes Childs; - PolyNode *Parent; - - PolyNode *GetNext() const; - - bool IsHole() const; - - bool IsOpen() const; - - int ChildCount() const; - -private: - // PolyNode& operator =(PolyNode& other); - unsigned Index; // node index in Parent.Childs - bool m_IsOpen; - JoinType m_jointype; - EndType m_endtype; - - PolyNode *GetNextSiblingUp() const; - - void AddChild(PolyNode &child); - - friend class Clipper; // to access Index - friend class ClipperOffset; -}; - -class PolyTree : public PolyNode { -public: - ~PolyTree() { Clear(); }; - - PolyNode *GetFirst() const; - - void Clear(); - - int Total() const; - -private: - // PolyTree& operator =(PolyTree& other); - PolyNodes AllNodes; - - friend class Clipper; // to access AllNodes -}; - -bool Orientation(const Path &poly); - -double Area(const Path &poly); - -int PointInPolygon(const IntPoint &pt, const Path &path); - -void SimplifyPolygon(const Path &in_poly, Paths &out_polys, - PolyFillType fillType = pftEvenOdd); - -void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, - PolyFillType fillType = pftEvenOdd); - -void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd); - -void CleanPolygon(const Path &in_poly, Path &out_poly, double distance = 1.415); - -void CleanPolygon(Path &poly, double distance = 1.415); - -void CleanPolygons(const Paths &in_polys, Paths &out_polys, - double distance = 1.415); - -void CleanPolygons(Paths &polys, double distance = 1.415); - -void MinkowskiSum(const Path &pattern, const Path &path, Paths &solution, - bool pathIsClosed); - -void MinkowskiSum(const Path &pattern, const Paths &paths, Paths &solution, - bool pathIsClosed); - -void MinkowskiDiff(const Path &poly1, const Path &poly2, Paths &solution); - -void PolyTreeToPaths(const PolyTree &polytree, Paths &paths); - -void ClosedPathsFromPolyTree(const PolyTree &polytree, Paths &paths); - -void OpenPathsFromPolyTree(PolyTree &polytree, Paths &paths); - -void ReversePath(Path &p); - -void ReversePaths(Paths &p); - -struct IntRect { - cInt left; - cInt top; - cInt right; - cInt bottom; -}; - -// enums that are used internally ... -enum EdgeSide { esLeft = 1, esRight = 2 }; - -// forward declarations (for stuff used internally) ... -struct TEdge; -struct IntersectNode; -struct LocalMinimum; -struct OutPt; -struct OutRec; -struct Join; - -typedef std::vector PolyOutList; -typedef std::vector EdgeList; -typedef std::vector JoinList; -typedef std::vector IntersectList; - -//------------------------------------------------------------------------------ - -// ClipperBase is the ancestor to the Clipper class. It should not be -// instantiated directly. This class simply abstracts the conversion of sets of -// polygon coordinates into edge objects that are stored in a LocalMinima list. -class ClipperBase { -public: - ClipperBase(); - - virtual ~ClipperBase(); - - virtual bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed); - - bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed); - - virtual void Clear(); - - IntRect GetBounds(); - - bool PreserveCollinear() { return m_PreserveCollinear; }; - - void PreserveCollinear(bool value) { m_PreserveCollinear = value; }; - -protected: - void DisposeLocalMinimaList(); - - TEdge *AddBoundsToLML(TEdge *e, bool IsClosed); - - virtual void Reset(); - - TEdge *ProcessBound(TEdge *E, bool IsClockwise); - - void InsertScanbeam(const cInt Y); - - bool PopScanbeam(cInt &Y); - - bool LocalMinimaPending(); - - bool PopLocalMinima(cInt Y, const LocalMinimum *&locMin); - - OutRec *CreateOutRec(); - - void DisposeAllOutRecs(); - - void DisposeOutRec(PolyOutList::size_type index); - - void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); - - void DeleteFromAEL(TEdge *e); - - void UpdateEdgeIntoAEL(TEdge *&e); - - typedef std::vector MinimaList; - MinimaList::iterator m_CurrentLM; - MinimaList m_MinimaList; - - bool m_UseFullRange; - EdgeList m_edges; - bool m_PreserveCollinear; - bool m_HasOpenPaths; - PolyOutList m_PolyOuts; - TEdge *m_ActiveEdges; - - typedef std::priority_queue ScanbeamList; - ScanbeamList m_Scanbeam; -}; -//------------------------------------------------------------------------------ - -class Clipper : public virtual ClipperBase { -public: - Clipper(int initOptions = 0); - - bool Execute(ClipType clipType, Paths &solution, - PolyFillType fillType = pftEvenOdd); - - bool Execute(ClipType clipType, Paths &solution, PolyFillType subjFillType, - PolyFillType clipFillType); - - bool Execute(ClipType clipType, PolyTree &polytree, - PolyFillType fillType = pftEvenOdd); - - bool Execute(ClipType clipType, PolyTree &polytree, PolyFillType subjFillType, - PolyFillType clipFillType); - - bool ReverseSolution() { return m_ReverseOutput; }; - - void ReverseSolution(bool value) { m_ReverseOutput = value; }; - - bool StrictlySimple() { return m_StrictSimple; }; - - void StrictlySimple(bool value) { m_StrictSimple = value; }; -// set the callback function for z value filling on intersections (otherwise Z -// is 0) -#ifdef use_xyz - void ZFillFunction(ZFillCallback zFillFunc); -#endif -protected: - virtual bool ExecuteInternal(); - -private: - JoinList m_Joins; - JoinList m_GhostJoins; - IntersectList m_IntersectList; - ClipType m_ClipType; - typedef std::list MaximaList; - MaximaList m_Maxima; - TEdge *m_SortedEdges; - bool m_ExecuteLocked; - PolyFillType m_ClipFillType; - PolyFillType m_SubjFillType; - bool m_ReverseOutput; - bool m_UsingPolyTree; - bool m_StrictSimple; -#ifdef use_xyz - ZFillCallback m_ZFill; // custom callback -#endif - - void SetWindingCount(TEdge &edge); - - bool IsEvenOddFillType(const TEdge &edge) const; - - bool IsEvenOddAltFillType(const TEdge &edge) const; - - void InsertLocalMinimaIntoAEL(const cInt botY); - - void InsertEdgeIntoAEL(TEdge *edge, TEdge *startEdge); - - void AddEdgeToSEL(TEdge *edge); - - bool PopEdgeFromSEL(TEdge *&edge); - - void CopyAELToSEL(); - - void DeleteFromSEL(TEdge *e); - - void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); - - bool IsContributing(const TEdge &edge) const; - - bool IsTopHorz(const cInt XPos); - - void DoMaxima(TEdge *e); - - void ProcessHorizontals(); - - void ProcessHorizontal(TEdge *horzEdge); - - void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); - - OutPt *AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); - - OutRec *GetOutRec(int idx); - - void AppendPolygon(TEdge *e1, TEdge *e2); - - void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt); - - OutPt *AddOutPt(TEdge *e, const IntPoint &pt); - - OutPt *GetLastOutPt(TEdge *e); - - bool ProcessIntersections(const cInt topY); - - void BuildIntersectList(const cInt topY); - - void ProcessIntersectList(); - - void ProcessEdgesAtTopOfScanbeam(const cInt topY); - - void BuildResult(Paths &polys); - - void BuildResult2(PolyTree &polytree); - - void SetHoleState(TEdge *e, OutRec *outrec); - - void DisposeIntersectNodes(); - - bool FixupIntersectionOrder(); - - void FixupOutPolygon(OutRec &outrec); - - void FixupOutPolyline(OutRec &outrec); - - bool IsHole(TEdge *e); - - bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl); - - void FixHoleLinkage(OutRec &outrec); - - void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt); - - void ClearJoins(); - - void ClearGhostJoins(); - - void AddGhostJoin(OutPt *op, const IntPoint offPt); - - bool JoinPoints(Join *j, OutRec *outRec1, OutRec *outRec2); - - void JoinCommonEdges(); - - void DoSimplePolygons(); - - void FixupFirstLefts1(OutRec *OldOutRec, OutRec *NewOutRec); - - void FixupFirstLefts2(OutRec *InnerOutRec, OutRec *OuterOutRec); - - void FixupFirstLefts3(OutRec *OldOutRec, OutRec *NewOutRec); - -#ifdef use_xyz - void SetZ(IntPoint &pt, TEdge &e1, TEdge &e2); -#endif -}; -//------------------------------------------------------------------------------ - -class ClipperOffset { -public: - ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25); - - ~ClipperOffset(); - - void AddPath(const Path &path, JoinType joinType, EndType endType); - - void AddPaths(const Paths &paths, JoinType joinType, EndType endType); - - void Execute(Paths &solution, double delta); - - void Execute(PolyTree &solution, double delta); - - void Clear(); - - double MiterLimit; - double ArcTolerance; - -private: - Paths m_destPolys; - Path m_srcPoly; - Path m_destPoly; - std::vector m_normals; - double m_delta, m_sinA, m_sin, m_cos; - double m_miterLim, m_StepsPerRad; - IntPoint m_lowest; - PolyNode m_polyNodes; - - void FixOrientations(); - - void DoOffset(double delta); - - void OffsetPoint(int j, int &k, JoinType jointype); - - void DoSquare(int j, int k); - - void DoMiter(int j, int k, double r); - - void DoRound(int j, int k); -}; -//------------------------------------------------------------------------------ - -class clipperException : public std::exception { -public: - clipperException(const char *description) : m_descr(description) {} - - virtual ~clipperException() throw() {} - - virtual const char *what() const throw() { return m_descr.c_str(); } - -private: - std::string m_descr; -}; -//------------------------------------------------------------------------------ - -} // ClipperLib namespace - -#endif // clipper_hpp diff --git a/libs/paddleocr/src/main/cpp/ocr_cls_process.cpp b/libs/paddleocr/src/main/cpp/ocr_cls_process.cpp deleted file mode 100644 index e7de9b0b..00000000 --- a/libs/paddleocr/src/main/cpp/ocr_cls_process.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. -// -// 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. - -#include "ocr_cls_process.h" -#include -#include -#include -#include -#include -#include - -const std::vector CLS_IMAGE_SHAPE = {3, 48, 192}; - -cv::Mat cls_resize_img(const cv::Mat &img) { - int imgC = CLS_IMAGE_SHAPE[0]; - int imgW = CLS_IMAGE_SHAPE[2]; - int imgH = CLS_IMAGE_SHAPE[1]; - - float ratio = float(img.cols) / float(img.rows); - int resize_w = 0; - if (ceilf(imgH * ratio) > imgW) - resize_w = imgW; - else - resize_w = int(ceilf(imgH * ratio)); - - cv::Mat resize_img; - cv::resize(img, resize_img, cv::Size(resize_w, imgH), 0.f, 0.f, - cv::INTER_CUBIC); - - if (resize_w < imgW) { - cv::copyMakeBorder(resize_img, resize_img, 0, 0, 0, int(imgW - resize_w), - cv::BORDER_CONSTANT, {0, 0, 0}); - } - return resize_img; -} \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/ocr_cls_process.h b/libs/paddleocr/src/main/cpp/ocr_cls_process.h deleted file mode 100644 index 1c30ee10..00000000 --- a/libs/paddleocr/src/main/cpp/ocr_cls_process.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. -// -// 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. - -#pragma once - -#include "common.h" -#include -#include - -extern const std::vector CLS_IMAGE_SHAPE; - -cv::Mat cls_resize_img(const cv::Mat &img); \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/ocr_crnn_process.cpp b/libs/paddleocr/src/main/cpp/ocr_crnn_process.cpp deleted file mode 100644 index f355be61..00000000 --- a/libs/paddleocr/src/main/cpp/ocr_crnn_process.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. -// -// 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. - -#include "ocr_crnn_process.h" -#include -#include -#include -#include -#include -#include - -const std::string CHARACTER_TYPE = "ch"; -const int MAX_DICT_LENGTH = 6624; -const std::vector REC_IMAGE_SHAPE = {3, 48, 320}; - -static cv::Mat crnn_resize_norm_img(cv::Mat img, float wh_ratio) { - int imgC = REC_IMAGE_SHAPE[0]; - int imgH = REC_IMAGE_SHAPE[1]; - int imgW = REC_IMAGE_SHAPE[2]; - - if (CHARACTER_TYPE == "ch") - imgW = int(32 * wh_ratio); - - float ratio = float(img.cols) / float(img.rows); - int resize_w = 0; - if (ceilf(imgH * ratio) > imgW) - resize_w = imgW; - else - resize_w = int(ceilf(imgH * ratio)); - cv::Mat resize_img; - cv::resize(img, resize_img, cv::Size(resize_w, imgH), 0.f, 0.f, - cv::INTER_CUBIC); - - resize_img.convertTo(resize_img, CV_32FC3, 1 / 255.f); - - for (int h = 0; h < resize_img.rows; h++) { - for (int w = 0; w < resize_img.cols; w++) { - resize_img.at(h, w)[0] = - (resize_img.at(h, w)[0] - 0.5) * 2; - resize_img.at(h, w)[1] = - (resize_img.at(h, w)[1] - 0.5) * 2; - resize_img.at(h, w)[2] = - (resize_img.at(h, w)[2] - 0.5) * 2; - } - } - - cv::Mat dist; - cv::copyMakeBorder(resize_img, dist, 0, 0, 0, int(imgW - resize_w), - cv::BORDER_CONSTANT, {0, 0, 0}); - - return dist; -} - -cv::Mat crnn_resize_img(const cv::Mat &img, float wh_ratio) { - int imgC = REC_IMAGE_SHAPE[0]; - int imgH = REC_IMAGE_SHAPE[1]; - int imgW = REC_IMAGE_SHAPE[2]; - - imgW = int(imgH * wh_ratio); - - float ratio = float(img.cols) / float(img.rows); - int resize_w = 0; - if (ceilf(imgH * ratio) > imgW) - resize_w = imgW; - else - resize_w = int(ceilf(imgH * ratio)); - cv::Mat resize_img; - cv::resize(img, resize_img, cv::Size(resize_w, imgH), 0.f, 0.f, - cv::INTER_LINEAR); - cv::copyMakeBorder(resize_img, resize_img, 0, 0, 0, - int(imgW - resize_img.cols), cv::BORDER_CONSTANT, - {127, 127, 127}); - return resize_img; -} - -cv::Mat get_rotate_crop_image(const cv::Mat &srcimage, - const std::vector> &box) { - - std::vector> points = box; - - int x_collect[4] = {box[0][0], box[1][0], box[2][0], box[3][0]}; - int y_collect[4] = {box[0][1], box[1][1], box[2][1], box[3][1]}; - int left = int(*std::min_element(x_collect, x_collect + 4)); - int right = int(*std::max_element(x_collect, x_collect + 4)); - int top = int(*std::min_element(y_collect, y_collect + 4)); - int bottom = int(*std::max_element(y_collect, y_collect + 4)); - - cv::Mat img_crop; - srcimage(cv::Rect(left, top, right - left, bottom - top)).copyTo(img_crop); - - for (int i = 0; i < points.size(); i++) { - points[i][0] -= left; - points[i][1] -= top; - } - - int img_crop_width = int(sqrt(pow(points[0][0] - points[1][0], 2) + - pow(points[0][1] - points[1][1], 2))); - int img_crop_height = int(sqrt(pow(points[0][0] - points[3][0], 2) + - pow(points[0][1] - points[3][1], 2))); - - cv::Point2f pts_std[4]; - pts_std[0] = cv::Point2f(0., 0.); - pts_std[1] = cv::Point2f(img_crop_width, 0.); - pts_std[2] = cv::Point2f(img_crop_width, img_crop_height); - pts_std[3] = cv::Point2f(0.f, img_crop_height); - - cv::Point2f pointsf[4]; - pointsf[0] = cv::Point2f(points[0][0], points[0][1]); - pointsf[1] = cv::Point2f(points[1][0], points[1][1]); - pointsf[2] = cv::Point2f(points[2][0], points[2][1]); - pointsf[3] = cv::Point2f(points[3][0], points[3][1]); - - cv::Mat M = cv::getPerspectiveTransform(pointsf, pts_std); - - cv::Mat dst_img; - cv::warpPerspective(img_crop, dst_img, M, - cv::Size(img_crop_width, img_crop_height), - cv::BORDER_REPLICATE); - - if (float(dst_img.rows) >= float(dst_img.cols) * 1.5) { - /* - cv::Mat srcCopy = cv::Mat(dst_img.rows, dst_img.cols, dst_img.depth()); - cv::transpose(dst_img, srcCopy); - cv::flip(srcCopy, srcCopy, 0); - return srcCopy; - */ - cv::transpose(dst_img, dst_img); - cv::flip(dst_img, dst_img, 0); - return dst_img; - } else { - return dst_img; - } -} diff --git a/libs/paddleocr/src/main/cpp/ocr_crnn_process.h b/libs/paddleocr/src/main/cpp/ocr_crnn_process.h deleted file mode 100644 index 0346afe4..00000000 --- a/libs/paddleocr/src/main/cpp/ocr_crnn_process.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// Created by fujiayi on 2020/7/3. -// -#pragma once - -#include "common.h" -#include -#include - -extern const std::vector REC_IMAGE_SHAPE; - -cv::Mat get_rotate_crop_image(const cv::Mat &srcimage, - const std::vector> &box); - -cv::Mat crnn_resize_img(const cv::Mat &img, float wh_ratio); - -template -inline size_t argmax(ForwardIterator first, ForwardIterator last) { - return std::distance(first, std::max_element(first, last)); -} \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/ocr_db_post_process.cpp b/libs/paddleocr/src/main/cpp/ocr_db_post_process.cpp deleted file mode 100644 index 9816ea4a..00000000 --- a/libs/paddleocr/src/main/cpp/ocr_db_post_process.cpp +++ /dev/null @@ -1,342 +0,0 @@ -// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. -// -// 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. - -#include "ocr_clipper.hpp" -#include "opencv2/core.hpp" -#include "opencv2/imgcodecs.hpp" -#include "opencv2/imgproc.hpp" -#include -#include -#include - -static void getcontourarea(float **box, float unclip_ratio, float &distance) { - int pts_num = 4; - float area = 0.0f; - float dist = 0.0f; - for (int i = 0; i < pts_num; i++) { - area += box[i][0] * box[(i + 1) % pts_num][1] - - box[i][1] * box[(i + 1) % pts_num][0]; - dist += sqrtf((box[i][0] - box[(i + 1) % pts_num][0]) * - (box[i][0] - box[(i + 1) % pts_num][0]) + - (box[i][1] - box[(i + 1) % pts_num][1]) * - (box[i][1] - box[(i + 1) % pts_num][1])); - } - area = fabs(float(area / 2.0)); - - distance = area * unclip_ratio / dist; -} - -static cv::RotatedRect unclip(float **box) { - float unclip_ratio = 2.0; - float distance = 1.0; - - getcontourarea(box, unclip_ratio, distance); - - ClipperLib::ClipperOffset offset; - ClipperLib::Path p; - p << ClipperLib::IntPoint(int(box[0][0]), int(box[0][1])) - << ClipperLib::IntPoint(int(box[1][0]), int(box[1][1])) - << ClipperLib::IntPoint(int(box[2][0]), int(box[2][1])) - << ClipperLib::IntPoint(int(box[3][0]), int(box[3][1])); - offset.AddPath(p, ClipperLib::jtRound, ClipperLib::etClosedPolygon); - - ClipperLib::Paths soln; - offset.Execute(soln, distance); - std::vector points; - - for (int j = 0; j < soln.size(); j++) { - for (int i = 0; i < soln[soln.size() - 1].size(); i++) { - points.emplace_back(soln[j][i].X, soln[j][i].Y); - } - } - cv::RotatedRect res = cv::minAreaRect(points); - - return res; -} - -static float **Mat2Vec(cv::Mat mat) { - auto **array = new float *[mat.rows]; - for (int i = 0; i < mat.rows; ++i) { - array[i] = new float[mat.cols]; - } - for (int i = 0; i < mat.rows; ++i) { - for (int j = 0; j < mat.cols; ++j) { - array[i][j] = mat.at(i, j); - } - } - - return array; -} - -static void quickSort(float **s, int l, int r) { - if (l < r) { - int i = l, j = r; - float x = s[l][0]; - float *xp = s[l]; - while (i < j) { - while (i < j && s[j][0] >= x) { - j--; - } - if (i < j) { - std::swap(s[i++], s[j]); - } - while (i < j && s[i][0] < x) { - i++; - } - if (i < j) { - std::swap(s[j--], s[i]); - } - } - s[i] = xp; - quickSort(s, l, i - 1); - quickSort(s, i + 1, r); - } -} - -static void quickSort_vector(std::vector> &box, int l, int r, - int axis) { - if (l < r) { - int i = l, j = r; - int x = box[l][axis]; - std::vector xp(box[l]); - while (i < j) { - while (i < j && box[j][axis] >= x) { - j--; - } - if (i < j) { - std::swap(box[i++], box[j]); - } - while (i < j && box[i][axis] < x) { - i++; - } - if (i < j) { - std::swap(box[j--], box[i]); - } - } - box[i] = xp; - quickSort_vector(box, l, i - 1, axis); - quickSort_vector(box, i + 1, r, axis); - } -} - -static std::vector> -order_points_clockwise(std::vector> pts) { - std::vector> box = pts; - quickSort_vector(box, 0, int(box.size() - 1), 0); - std::vector> leftmost = {box[0], box[1]}; - std::vector> rightmost = {box[2], box[3]}; - - if (leftmost[0][1] > leftmost[1][1]) { - std::swap(leftmost[0], leftmost[1]); - } - - if (rightmost[0][1] > rightmost[1][1]) { - std::swap(rightmost[0], rightmost[1]); - } - - std::vector> rect = {leftmost[0], rightmost[0], rightmost[1], - leftmost[1]}; - return rect; -} - -static float **get_mini_boxes(cv::RotatedRect box, float &ssid) { - ssid = box.size.width >= box.size.height ? box.size.height : box.size.width; - - cv::Mat points; - cv::boxPoints(box, points); - // sorted box points - auto array = Mat2Vec(points); - quickSort(array, 0, 3); - - float *idx1 = array[0], *idx2 = array[1], *idx3 = array[2], *idx4 = array[3]; - if (array[3][1] <= array[2][1]) { - idx2 = array[3]; - idx3 = array[2]; - } else { - idx2 = array[2]; - idx3 = array[3]; - } - if (array[1][1] <= array[0][1]) { - idx1 = array[1]; - idx4 = array[0]; - } else { - idx1 = array[0]; - idx4 = array[1]; - } - - array[0] = idx1; - array[1] = idx2; - array[2] = idx3; - array[3] = idx4; - - return array; -} - -template T clamp(T x, T min, T max) { - if (x > max) { - return max; - } - if (x < min) { - return min; - } - return x; -} - -static float clampf(float x, float min, float max) { - if (x > max) - return max; - if (x < min) - return min; - return x; -} - -float box_score_fast(float **box_array, cv::Mat pred) { - auto array = box_array; - int width = pred.cols; - int height = pred.rows; - - float box_x[4] = {array[0][0], array[1][0], array[2][0], array[3][0]}; - float box_y[4] = {array[0][1], array[1][1], array[2][1], array[3][1]}; - - int xmin = clamp(int(std::floorf(*(std::min_element(box_x, box_x + 4)))), 0, - width - 1); - int xmax = clamp(int(std::ceilf(*(std::max_element(box_x, box_x + 4)))), 0, - width - 1); - int ymin = clamp(int(std::floorf(*(std::min_element(box_y, box_y + 4)))), 0, - height - 1); - int ymax = clamp(int(std::ceilf(*(std::max_element(box_y, box_y + 4)))), 0, - height - 1); - - cv::Mat mask; - mask = cv::Mat::zeros(ymax - ymin + 1, xmax - xmin + 1, CV_8UC1); - - cv::Point root_point[4]; - root_point[0] = cv::Point(int(array[0][0]) - xmin, int(array[0][1]) - ymin); - root_point[1] = cv::Point(int(array[1][0]) - xmin, int(array[1][1]) - ymin); - root_point[2] = cv::Point(int(array[2][0]) - xmin, int(array[2][1]) - ymin); - root_point[3] = cv::Point(int(array[3][0]) - xmin, int(array[3][1]) - ymin); - const cv::Point *ppt[1] = {root_point}; - int npt[] = {4}; - cv::fillPoly(mask, ppt, npt, 1, cv::Scalar(1)); - - cv::Mat croppedImg; - pred(cv::Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1)) - .copyTo(croppedImg); - - auto score = cv::mean(croppedImg, mask)[0]; - return score; -} - -std::vector>> -boxes_from_bitmap(const cv::Mat &pred, const cv::Mat &bitmap) { - const int min_size = 3; - const int max_candidates = 1000; - const float box_thresh = 0.5; - - int width = bitmap.cols; - int height = bitmap.rows; - - std::vector> contours; - std::vector hierarchy; - - cv::findContours(bitmap, contours, hierarchy, cv::RETR_LIST, - cv::CHAIN_APPROX_SIMPLE); - - int num_contours = - contours.size() >= max_candidates ? max_candidates : contours.size(); - - std::vector>> boxes; - - for (int _i = 0; _i < num_contours; _i++) { - float ssid; - cv::RotatedRect box = cv::minAreaRect(contours[_i]); - auto array = get_mini_boxes(box, ssid); - - auto box_for_unclip = array; - // end get_mini_box - - if (ssid < min_size) { - continue; - } - - float score; - score = box_score_fast(array, pred); - // end box_score_fast - if (score < box_thresh) { - continue; - } - - // start for unclip - cv::RotatedRect points = unclip(box_for_unclip); - // end for unclip - - cv::RotatedRect clipbox = points; - auto cliparray = get_mini_boxes(clipbox, ssid); - - if (ssid < min_size + 2) - continue; - - int dest_width = pred.cols; - int dest_height = pred.rows; - std::vector> intcliparray; - - for (int num_pt = 0; num_pt < 4; num_pt++) { - std::vector a{int(clampf(roundf(cliparray[num_pt][0] / float(width) * - float(dest_width)), - 0, float(dest_width))), - int(clampf(roundf(cliparray[num_pt][1] / - float(height) * float(dest_height)), - 0, float(dest_height)))}; - intcliparray.emplace_back(std::move(a)); - } - boxes.emplace_back(std::move(intcliparray)); - - } // end for - return boxes; -} - -int _max(int a, int b) { return a >= b ? a : b; } - -int _min(int a, int b) { return a >= b ? b : a; } - -std::vector>> -filter_tag_det_res(const std::vector>> &o_boxes, - float ratio_h, float ratio_w, const cv::Mat &srcimg) { - int oriimg_h = srcimg.rows; - int oriimg_w = srcimg.cols; - std::vector>> boxes{o_boxes}; - std::vector>> root_points; - for (int n = 0; n < boxes.size(); n++) { - boxes[n] = order_points_clockwise(boxes[n]); - for (int m = 0; m < boxes[0].size(); m++) { - boxes[n][m][0] /= ratio_w; - boxes[n][m][1] /= ratio_h; - - boxes[n][m][0] = int(_min(_max(boxes[n][m][0], 0), oriimg_w - 1)); - boxes[n][m][1] = int(_min(_max(boxes[n][m][1], 0), oriimg_h - 1)); - } - } - - for (int n = 0; n < boxes.size(); n++) { - int rect_width, rect_height; - rect_width = int(sqrt(pow(boxes[n][0][0] - boxes[n][1][0], 2) + - pow(boxes[n][0][1] - boxes[n][1][1], 2))); - rect_height = int(sqrt(pow(boxes[n][0][0] - boxes[n][3][0], 2) + - pow(boxes[n][0][1] - boxes[n][3][1], 2))); - if (rect_width <= 10 || rect_height <= 10) - continue; - root_points.push_back(boxes[n]); - } - return root_points; -} \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/ocr_db_post_process.h b/libs/paddleocr/src/main/cpp/ocr_db_post_process.h deleted file mode 100644 index 327da36c..00000000 --- a/libs/paddleocr/src/main/cpp/ocr_db_post_process.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// Created by fujiayi on 2020/7/2. -// -#pragma once -#include -#include - -std::vector>> -boxes_from_bitmap(const cv::Mat &pred, const cv::Mat &bitmap); - -std::vector>> -filter_tag_det_res(const std::vector>> &o_boxes, - float ratio_h, float ratio_w, const cv::Mat &srcimg); \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/ocr_ppredictor.cpp b/libs/paddleocr/src/main/cpp/ocr_ppredictor.cpp deleted file mode 100644 index 83de4a53..00000000 --- a/libs/paddleocr/src/main/cpp/ocr_ppredictor.cpp +++ /dev/null @@ -1,349 +0,0 @@ -// -// Created by fujiayi on 2020/7/1. -// - -#include "ocr_ppredictor.h" -#include "common.h" -#include "ocr_cls_process.h" -#include "ocr_crnn_process.h" -#include "ocr_db_post_process.h" -#include "preprocess.h" - -namespace ppredictor { - -OCR_PPredictor::OCR_PPredictor(const OCR_Config &config) : _config(config) {} - -int OCR_PPredictor::init(const std::string &det_model_content, - const std::string &rec_model_content, - const std::string &cls_model_content) { - _det_predictor = std::unique_ptr( - new PPredictor{_config.use_opencl,_config.thread_num, NET_OCR, _config.mode}); - _det_predictor->init_nb(det_model_content); - - _rec_predictor = std::unique_ptr( - new PPredictor{_config.use_opencl,_config.thread_num, NET_OCR_INTERNAL, _config.mode}); - _rec_predictor->init_nb(rec_model_content); - - _cls_predictor = std::unique_ptr( - new PPredictor{_config.use_opencl,_config.thread_num, NET_OCR_INTERNAL, _config.mode}); - _cls_predictor->init_nb(cls_model_content); - return RETURN_OK; -} - -int OCR_PPredictor::init_from_file(const std::string &det_model_path, - const std::string &rec_model_path, - const std::string &cls_model_path) { - _det_predictor = std::unique_ptr( - new PPredictor{_config.use_opencl, _config.thread_num, NET_OCR, _config.mode}); - _det_predictor->init_from_file(det_model_path); - - _rec_predictor = std::unique_ptr( - new PPredictor{_config.use_opencl,_config.thread_num, NET_OCR_INTERNAL, _config.mode}); - _rec_predictor->init_from_file(rec_model_path); - - _cls_predictor = std::unique_ptr( - new PPredictor{_config.use_opencl,_config.thread_num, NET_OCR_INTERNAL, _config.mode}); - _cls_predictor->init_from_file(cls_model_path); - return RETURN_OK; -} -/** - * for debug use, show result of First Step - * @param filter_boxes - * @param boxes - * @param srcimg - */ -static void -visual_img(const std::vector>> &filter_boxes, - const std::vector>> &boxes, - const cv::Mat &srcimg) { - // visualization - cv::Point rook_points[filter_boxes.size()][4]; - for (int n = 0; n < filter_boxes.size(); n++) { - for (int m = 0; m < filter_boxes[0].size(); m++) { - rook_points[n][m] = - cv::Point(int(filter_boxes[n][m][0]), int(filter_boxes[n][m][1])); - } - } - - cv::Mat img_vis; - srcimg.copyTo(img_vis); - for (int n = 0; n < boxes.size(); n++) { - const cv::Point *ppt[1] = {rook_points[n]}; - int npt[] = {4}; - cv::polylines(img_vis, ppt, npt, 1, 1, CV_RGB(0, 255, 0), 2, 8, 0); - } - // 调试用,自行替换需要修改的路径 - cv::imwrite("/sdcard/1/vis.png", img_vis); -} - -std::vector -OCR_PPredictor::infer_ocr(cv::Mat &origin,int max_size_len, int run_det, int run_cls, int run_rec) { - LOGI("ocr cpp start *****************"); - LOGI("ocr cpp det: %d, cls: %d, rec: %d", run_det, run_cls, run_rec); - std::vector ocr_results; - if (run_det || run_rec) { - infer_det(origin, max_size_len, ocr_results); - } - if (run_rec) { - if (ocr_results.empty()) { - OCRPredictResult res; - ocr_results.emplace_back(std::move(res)); - } - for (auto & ocr_result : ocr_results) { - infer_rec(origin, run_cls, ocr_result); - } - } - if (run_cls) { - ClsPredictResult cls_res = infer_cls(origin); - OCRPredictResult res; - res.cls_score = cls_res.cls_score; - res.cls_label = cls_res.cls_label; - ocr_results.push_back(res); - } - - LOGI("ocr cpp end *****************"); - return ocr_results; -} - -cv::Mat DetResizeImg(const cv::Mat img, int max_size_len, - std::vector &ratio_hw) { - int w = img.cols; - int h = img.rows; - - float ratio = 1.f; - int max_wh = w >= h ? w : h; - if (max_wh > max_size_len) { - if (h > w) { - ratio = static_cast(max_size_len) / static_cast(h); - } else { - ratio = static_cast(max_size_len) / static_cast(w); - } - } - - int resize_h = static_cast(float(h) * ratio); - int resize_w = static_cast(float(w) * ratio); - int shapeSize = 32; - if (resize_h % shapeSize == 0) - resize_h = resize_h; - else if (resize_h / shapeSize < 1 + 1e-5) - resize_h = shapeSize; - else - resize_h = (resize_h / shapeSize - 1) * shapeSize; - - if (resize_w % shapeSize == 0) - resize_w = resize_w; - else if (resize_w / shapeSize < 1 + 1e-5) - resize_w = shapeSize; - else - resize_w = (resize_w / shapeSize - 1) * shapeSize; - - cv::Mat resize_img; - cv::resize(img, resize_img, cv::Size(resize_w, resize_h)); - - ratio_hw.push_back(static_cast(resize_h) / static_cast(h)); - ratio_hw.push_back(static_cast(resize_w) / static_cast(w)); - return resize_img; -} - -void OCR_PPredictor::infer_det(cv::Mat &origin, int max_size_len, std::vector &ocr_results) { - std::vector mean = {0.485f, 0.456f, 0.406f}; - std::vector scale = {1 / 0.229f, 1 / 0.224f, 1 / 0.225f}; - - PredictorInput input = _det_predictor->get_first_input(); - - std::vector ratio_hw; - cv::Mat input_image = DetResizeImg(origin, max_size_len, ratio_hw); - input_image.convertTo(input_image, CV_32FC3, 1 / 255.0f); - const float *dimg = reinterpret_cast(input_image.data); - int input_size = input_image.rows * input_image.cols; - - input.set_dims({1, 3, input_image.rows, input_image.cols}); - - neon_mean_scale(dimg, input.get_mutable_float_data(), input_size, mean, - scale); - LOGI("ocr cpp det shape %d,%d", input_image.rows,input_image.cols); - std::vector results = _det_predictor->infer(); - PredictorOutput &res = results.at(0); - std::vector>> filtered_box = calc_filtered_boxes( - res.get_float_data(), res.get_size(), input_image.rows, input_image.cols, origin); - LOGI("ocr cpp det Filter_box size %ld", filtered_box.size()); - - for(auto & i : filtered_box){ - LOGI("ocr cpp box %d,%d,%d,%d,%d,%d,%d,%d", i[0][0],i[0][1], i[1][0],i[1][1], i[2][0],i[2][1], i[3][0],i[3][1]); - OCRPredictResult res; - res.points = i; - ocr_results.push_back(res); - } -} - -void OCR_PPredictor::infer_rec(const cv::Mat &origin_img, int run_cls, OCRPredictResult& ocr_result) { - std::vector mean = {0.5f, 0.5f, 0.5f}; - std::vector scale = {1 / 0.5f, 1 / 0.5f, 1 / 0.5f}; - std::vector dims = {1, 3, 0, 0}; - - PredictorInput input = _rec_predictor->get_first_input(); - - const std::vector> &box = ocr_result.points; - cv::Mat crop_img; - if (!box.empty()) { - crop_img = get_rotate_crop_image(origin_img, box); - } else { - crop_img = origin_img; - } - - if (run_cls) { - ClsPredictResult cls_res = infer_cls(crop_img); - crop_img = cls_res.img; - ocr_result.cls_score = cls_res.cls_score; - ocr_result.cls_label = cls_res.cls_label; - } - - float wh_ratio = float(crop_img.cols) / float(crop_img.rows); - cv::Mat input_image = crnn_resize_img(crop_img, wh_ratio); - input_image.convertTo(input_image, CV_32FC3, 1 / 255.0f); - const float *dimg = reinterpret_cast(input_image.data); - int input_size = input_image.rows * input_image.cols; - - dims[2] = input_image.rows; - dims[3] = input_image.cols; - input.set_dims(dims); - - neon_mean_scale(dimg, input.get_mutable_float_data(), input_size, mean, - scale); - - std::vector results = _rec_predictor->infer(); - const float *predict_batch = results.at(0).get_float_data(); - const std::vector predict_shape = results.at(0).get_shape(); - - // ctc decode - int argmax_idx; - int last_index = 0; - float score = 0.f; - int count = 0; - float max_value = 0.0f; - - for (int n = 0; n < predict_shape[1]; n++) { - argmax_idx = int(argmax(&predict_batch[n * predict_shape[2]], - &predict_batch[(n + 1) * predict_shape[2]])); - max_value = - float(*std::max_element(&predict_batch[n * predict_shape[2]], - &predict_batch[(n + 1) * predict_shape[2]])); - if (argmax_idx > 0 && (!(n > 0 && argmax_idx == last_index))) { - score += max_value; - count += 1; - ocr_result.word_index.push_back(argmax_idx); - } - last_index = argmax_idx; - } - score /= count; - ocr_result.score = score; - LOGI("ocr cpp rec word size %ld", count); -} - -ClsPredictResult OCR_PPredictor::infer_cls(const cv::Mat &img, float thresh) { - std::vector mean = {0.5f, 0.5f, 0.5f}; - std::vector scale = {1 / 0.5f, 1 / 0.5f, 1 / 0.5f}; - std::vector dims = {1, 3, 0, 0}; - - PredictorInput input = _cls_predictor->get_first_input(); - - cv::Mat input_image = cls_resize_img(img); - input_image.convertTo(input_image, CV_32FC3, 1 / 255.0f); - const float *dimg = reinterpret_cast(input_image.data); - int input_size = input_image.rows * input_image.cols; - - dims[2] = input_image.rows; - dims[3] = input_image.cols; - input.set_dims(dims); - - neon_mean_scale(dimg, input.get_mutable_float_data(), input_size, mean, - scale); - - std::vector results = _cls_predictor->infer(); - - const float *scores = results.at(0).get_float_data(); - float score = 0; - int label = 0; - for (int64_t i = 0; i < results.at(0).get_size(); i++) { - LOGI("ocr cpp cls output scores [%f]", scores[i]); - if (scores[i] > score) { - score = scores[i]; - label = i; - } - } - cv::Mat srcimg; - img.copyTo(srcimg); - if (label % 2 == 1 && score > thresh) { - cv::rotate(srcimg, srcimg, 1); - } - ClsPredictResult res; - res.cls_label = label; - res.cls_score = score; - res.img = srcimg; - LOGI("ocr cpp cls word cls %ld, %f", label, score); - return res; -} - -std::vector>> -OCR_PPredictor::calc_filtered_boxes(const float *pred, int pred_size, - int output_height, int output_width, - const cv::Mat &origin) { - const double threshold = 0.3; - const double maxvalue = 1; - - cv::Mat pred_map = cv::Mat::zeros(output_height, output_width, CV_32F); - memcpy(pred_map.data, pred, pred_size * sizeof(float)); - cv::Mat cbuf_map; - pred_map.convertTo(cbuf_map, CV_8UC1); - - cv::Mat bit_map; - cv::threshold(cbuf_map, bit_map, threshold, maxvalue, cv::THRESH_BINARY); - - std::vector>> boxes = - boxes_from_bitmap(pred_map, bit_map); - float ratio_h = output_height * 1.0f / origin.rows; - float ratio_w = output_width * 1.0f / origin.cols; - std::vector>> filter_boxes = - filter_tag_det_res(boxes, ratio_h, ratio_w, origin); - return filter_boxes; -} - -std::vector -OCR_PPredictor::postprocess_rec_word_index(const PredictorOutput &res) { - const int *rec_idx = res.get_int_data(); - const std::vector> rec_idx_lod = res.get_lod(); - - std::vector pred_idx; - for (int n = int(rec_idx_lod[0][0]); n < int(rec_idx_lod[0][1] * 2); n += 2) { - pred_idx.emplace_back(rec_idx[n]); - } - return pred_idx; -} - -float OCR_PPredictor::postprocess_rec_score(const PredictorOutput &res) { - const float *predict_batch = res.get_float_data(); - const std::vector predict_shape = res.get_shape(); - const std::vector> predict_lod = res.get_lod(); - int blank = predict_shape[1]; - float score = 0.f; - int count = 0; - for (int n = predict_lod[0][0]; n < predict_lod[0][1] - 1; n++) { - int argmax_idx = argmax(predict_batch + n * predict_shape[1], - predict_batch + (n + 1) * predict_shape[1]); - float max_value = predict_batch[n * predict_shape[1] + argmax_idx]; - if (blank - 1 - argmax_idx > 1e-5) { - score += max_value; - count += 1; - } - } - if (count == 0) { - LOGE("calc score count 0"); - } else { - score /= count; - } - LOGI("calc score: %f", score); - return score; -} - -NET_TYPE OCR_PPredictor::get_net_flag() const { return NET_OCR; } -} \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/ocr_ppredictor.h b/libs/paddleocr/src/main/cpp/ocr_ppredictor.h deleted file mode 100644 index a1da2be3..00000000 --- a/libs/paddleocr/src/main/cpp/ocr_ppredictor.h +++ /dev/null @@ -1,130 +0,0 @@ -// -// Created by fujiayi on 2020/7/1. -// - -#pragma once - -#include "ppredictor.h" -#include -#include -#include - -namespace ppredictor { - -/** - * Config - */ -struct OCR_Config { - int use_opencl = 0; - int thread_num = 4; // Thread num - paddle::lite_api::PowerMode mode = - paddle::lite_api::LITE_POWER_HIGH; // PaddleLite Mode -}; - -/** - * PolyGone Result - */ -struct OCRPredictResult { - std::vector word_index; - std::vector> points; - float score; - float cls_score; - int cls_label=-1; -}; - -struct ClsPredictResult { - float cls_score; - int cls_label=-1; - cv::Mat img; -}; -/** - * OCR there are 2 models - * 1. First model(det),select polygones to show where are the texts - * 2. crop from the origin images, use these polygones to infer - */ -class OCR_PPredictor : public PPredictor_Interface { -public: - OCR_PPredictor(const OCR_Config &config); - - virtual ~OCR_PPredictor() {} - - /** - * 初始化二个模型的Predictor - * @param det_model_content - * @param rec_model_content - * @return - */ - int init(const std::string &det_model_content, - const std::string &rec_model_content, - const std::string &cls_model_content); - int init_from_file(const std::string &det_model_path, - const std::string &rec_model_path, - const std::string &cls_model_path); - /** - * Return OCR result - * @param dims - * @param input_data - * @param input_len - * @param net_flag - * @param origin - * @return - */ - virtual std::vector - infer_ocr(cv::Mat &origin, int max_size_len, int run_det, int run_cls, int run_rec); - - virtual NET_TYPE get_net_flag() const; - -private: - /** - * calcul Polygone from the result image of first model - * @param pred - * @param output_height - * @param output_width - * @param origin - * @return - */ - std::vector>> - calc_filtered_boxes(const float *pred, int pred_size, int output_height, - int output_width, const cv::Mat &origin); - - void - infer_det(cv::Mat &origin, int max_side_len, std::vector& ocr_results); - /** - * infer for rec model - * - * @param boxes - * @param origin - * @return - */ - void - infer_rec(const cv::Mat &origin, int run_cls, OCRPredictResult& ocr_result); - - /** - * infer for cls model - * - * @param boxes - * @param origin - * @return - */ - ClsPredictResult infer_cls(const cv::Mat &origin, float thresh = 0.9); - - /** - * Postprocess or sencod model to extract text - * @param res - * @return - */ - std::vector postprocess_rec_word_index(const PredictorOutput &res); - - /** - * calculate confidence of second model text result - * @param res - * @return - */ - float postprocess_rec_score(const PredictorOutput &res); - - std::unique_ptr _det_predictor; - std::unique_ptr _rec_predictor; - std::unique_ptr _cls_predictor; - OCR_Config _config; -}; -} \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/ppredictor.cpp b/libs/paddleocr/src/main/cpp/ppredictor.cpp deleted file mode 100644 index a40fe5e1..00000000 --- a/libs/paddleocr/src/main/cpp/ppredictor.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include "ppredictor.h" -#include "common.h" - -namespace ppredictor { -PPredictor::PPredictor(int use_opencl, int thread_num, int net_flag, - paddle::lite_api::PowerMode mode) - : _use_opencl(use_opencl), _thread_num(thread_num), _net_flag(net_flag), _mode(mode) {} - -int PPredictor::init_nb(const std::string &model_content) { - paddle::lite_api::MobileConfig config; - config.set_model_from_buffer(model_content); - return _init(config); -} - -int PPredictor::init_from_file(const std::string &model_content) { - paddle::lite_api::MobileConfig config; - config.set_model_from_file(model_content); - return _init(config); -} - -template int PPredictor::_init(ConfigT &config) { - bool is_opencl_backend_valid = paddle::lite_api::IsOpenCLBackendValid(/*check_fp16_valid = false*/); - if (is_opencl_backend_valid) { - if (_use_opencl != 0) { - // Make sure you have write permission of the binary path. - // We strongly recommend each model has a unique binary name. - const std::string bin_path = "/data/local/tmp/"; - const std::string bin_name = "lite_opencl_kernel.bin"; - config.set_opencl_binary_path_name(bin_path, bin_name); - - // opencl tune option - // CL_TUNE_NONE: 0 - // CL_TUNE_RAPID: 1 - // CL_TUNE_NORMAL: 2 - // CL_TUNE_EXHAUSTIVE: 3 - const std::string tuned_path = "/data/local/tmp/"; - const std::string tuned_name = "lite_opencl_tuned.bin"; - config.set_opencl_tune(paddle::lite_api::CL_TUNE_NORMAL, tuned_path, tuned_name); - - // opencl precision option - // CL_PRECISION_AUTO: 0, first fp16 if valid, default - // CL_PRECISION_FP32: 1, force fp32 - // CL_PRECISION_FP16: 2, force fp16 - config.set_opencl_precision(paddle::lite_api::CL_PRECISION_FP32); - LOGI("ocr cpp device: running on gpu."); - } - } else { - LOGI("ocr cpp device: running on cpu."); - // you can give backup cpu nb model instead - // config.set_model_from_file(cpu_nb_model_dir); - } - config.set_threads(_thread_num); - config.set_power_mode(_mode); - _predictor = paddle::lite_api::CreatePaddlePredictor(config); - LOGI("ocr cpp paddle instance created"); - return RETURN_OK; -} - -PredictorInput PPredictor::get_input(int index) { - PredictorInput input{_predictor->GetInput(index), index, _net_flag}; - _is_input_get = true; - return input; -} - -std::vector PPredictor::get_inputs(int num) { - std::vector results; - for (int i = 0; i < num; i++) { - results.emplace_back(get_input(i)); - } - return results; -} - -PredictorInput PPredictor::get_first_input() { return get_input(0); } - -std::vector PPredictor::infer() { - LOGI("ocr cpp infer Run start %d", _net_flag); - std::vector results; - if (!_is_input_get) { - return results; - } - _predictor->Run(); - LOGI("ocr cpp infer Run end"); - - for (int i = 0; i < _predictor->GetOutputNames().size(); i++) { - std::unique_ptr output_tensor = - _predictor->GetOutput(i); - LOGI("ocr cpp output tensor[%d] size %ld", i, product(output_tensor->shape())); - PredictorOutput result{std::move(output_tensor), i, _net_flag}; - results.emplace_back(std::move(result)); - } - return results; -} - -NET_TYPE PPredictor::get_net_flag() const { return (NET_TYPE)_net_flag; } -} \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/ppredictor.h b/libs/paddleocr/src/main/cpp/ppredictor.h deleted file mode 100644 index 7dd12d5c..00000000 --- a/libs/paddleocr/src/main/cpp/ppredictor.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include "paddle_api.h" -#include "predictor_input.h" -#include "predictor_output.h" - -namespace ppredictor { - -/** - * PaddleLite Preditor Common Interface - */ -class PPredictor_Interface { -public: - virtual ~PPredictor_Interface() {} - - virtual NET_TYPE get_net_flag() const = 0; -}; - -/** - * Common Predictor - */ -class PPredictor : public PPredictor_Interface { -public: - PPredictor( - int use_opencl, int thread_num, int net_flag = 0, - paddle::lite_api::PowerMode mode = paddle::lite_api::LITE_POWER_HIGH); - - virtual ~PPredictor() {} - - /** - * init paddlitelite opt model,nb format ,or use ini_paddle - * @param model_content - * @return 0 - */ - virtual int init_nb(const std::string &model_content); - - virtual int init_from_file(const std::string &model_content); - - std::vector infer(); - - std::shared_ptr get_predictor() { - return _predictor; - } - - virtual std::vector get_inputs(int num); - - virtual PredictorInput get_input(int index); - - virtual PredictorInput get_first_input(); - - virtual NET_TYPE get_net_flag() const; - -protected: - template int _init(ConfigT &config); - -private: - int _use_opencl; - int _thread_num; - paddle::lite_api::PowerMode _mode; - std::shared_ptr _predictor; - bool _is_input_get = false; - int _net_flag; -}; -} \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/predictor_input.cpp b/libs/paddleocr/src/main/cpp/predictor_input.cpp deleted file mode 100644 index f0b4bf8a..00000000 --- a/libs/paddleocr/src/main/cpp/predictor_input.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "predictor_input.h" - -namespace ppredictor { - -void PredictorInput::set_dims(std::vector dims) { - // yolov3 - if (_net_flag == 101 && _index == 1) { - _tensor->Resize({1, 2}); - _tensor->mutable_data()[0] = (int)dims.at(2); - _tensor->mutable_data()[1] = (int)dims.at(3); - } else { - _tensor->Resize(dims); - } - _is_dims_set = true; -} - -float *PredictorInput::get_mutable_float_data() { - if (!_is_dims_set) { - LOGE("PredictorInput::set_dims is not called"); - } - return _tensor->mutable_data(); -} - -void PredictorInput::set_data(const float *input_data, int input_float_len) { - float *input_raw_data = get_mutable_float_data(); - memcpy(input_raw_data, input_data, input_float_len * sizeof(float)); -} -} \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/predictor_input.h b/libs/paddleocr/src/main/cpp/predictor_input.h deleted file mode 100644 index f3fd6cfe..00000000 --- a/libs/paddleocr/src/main/cpp/predictor_input.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "common.h" -#include -#include - -namespace ppredictor { -class PredictorInput { -public: - PredictorInput(std::unique_ptr &&tensor, int index, - int net_flag) - : _tensor(std::move(tensor)), _index(index), _net_flag(net_flag) {} - - void set_dims(std::vector dims); - - float *get_mutable_float_data(); - - void set_data(const float *input_data, int input_float_len); - -private: - std::unique_ptr _tensor; - bool _is_dims_set = false; - int _index; - int _net_flag; -}; -} diff --git a/libs/paddleocr/src/main/cpp/predictor_output.cpp b/libs/paddleocr/src/main/cpp/predictor_output.cpp deleted file mode 100644 index e9cfdbc3..00000000 --- a/libs/paddleocr/src/main/cpp/predictor_output.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "predictor_output.h" -namespace ppredictor { -const float *PredictorOutput::get_float_data() const { - return _tensor->data(); -} - -const int *PredictorOutput::get_int_data() const { - return _tensor->data(); -} - -const std::vector> PredictorOutput::get_lod() const { - return _tensor->lod(); -} - -int64_t PredictorOutput::get_size() const { - if (_net_flag == NET_OCR) { - return _tensor->shape().at(2) * _tensor->shape().at(3); - } else { - return product(_tensor->shape()); - } -} - -const std::vector PredictorOutput::get_shape() const { - return _tensor->shape(); -} -} \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/predictor_output.h b/libs/paddleocr/src/main/cpp/predictor_output.h deleted file mode 100644 index 8e8c9ba0..00000000 --- a/libs/paddleocr/src/main/cpp/predictor_output.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "common.h" -#include -#include - -namespace ppredictor { -class PredictorOutput { -public: - PredictorOutput() {} - PredictorOutput(std::unique_ptr &&tensor, - int index, int net_flag) - : _tensor(std::move(tensor)), _index(index), _net_flag(net_flag) {} - - const float *get_float_data() const; - const int *get_int_data() const; - int64_t get_size() const; - const std::vector> get_lod() const; - const std::vector get_shape() const; - - std::vector data; // return float, or use data_int - std::vector data_int; // several layers return int ,or use data - std::vector shape; // PaddleLite output shape - std::vector> lod; // PaddleLite output lod - -private: - std::unique_ptr _tensor; - int _index; - int _net_flag; -}; -} diff --git a/libs/paddleocr/src/main/cpp/preprocess.cpp b/libs/paddleocr/src/main/cpp/preprocess.cpp deleted file mode 100644 index e99b2cd1..00000000 --- a/libs/paddleocr/src/main/cpp/preprocess.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "preprocess.h" -#include - -cv::Mat bitmap_to_cv_mat(JNIEnv *env, jobject bitmap) { - AndroidBitmapInfo info; - int result = AndroidBitmap_getInfo(env, bitmap, &info); - if (result != ANDROID_BITMAP_RESULT_SUCCESS) { - LOGE("AndroidBitmap_getInfo failed, result: %d", result); - return cv::Mat{}; - } - if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { - LOGE("Bitmap format is not RGBA_8888 !"); - return cv::Mat{}; - } - unsigned char *srcData = NULL; - AndroidBitmap_lockPixels(env, bitmap, (void **)&srcData); - cv::Mat mat = cv::Mat::zeros(info.height, info.width, CV_8UC4); - memcpy(mat.data, srcData, info.height * info.width * 4); - AndroidBitmap_unlockPixels(env, bitmap); - cv::cvtColor(mat, mat, cv::COLOR_RGBA2BGR); - /** - if (!cv::imwrite("/sdcard/1/copy.jpg", mat)){ - LOGE("Write image failed " ); - } - */ - - return mat; -} - -cv::Mat resize_img(const cv::Mat &img, int height, int width) { - if (img.rows == height && img.cols == width) { - return img; - } - cv::Mat new_img; - cv::resize(img, new_img, cv::Size(height, width)); - return new_img; -} - -// fill tensor with mean and scale and trans layout: nhwc -> nchw, neon speed up -void neon_mean_scale(const float *din, float *dout, int size, - const std::vector &mean, - const std::vector &scale) { - if (mean.size() != 3 || scale.size() != 3) { - LOGE("[ERROR] mean or scale size must equal to 3"); - return; - } - - float32x4_t vmean0 = vdupq_n_f32(mean[0]); - float32x4_t vmean1 = vdupq_n_f32(mean[1]); - float32x4_t vmean2 = vdupq_n_f32(mean[2]); - float32x4_t vscale0 = vdupq_n_f32(scale[0]); - float32x4_t vscale1 = vdupq_n_f32(scale[1]); - float32x4_t vscale2 = vdupq_n_f32(scale[2]); - - float *dout_c0 = dout; - float *dout_c1 = dout + size; - float *dout_c2 = dout + size * 2; - - int i = 0; - for (; i < size - 3; i += 4) { - float32x4x3_t vin3 = vld3q_f32(din); - float32x4_t vsub0 = vsubq_f32(vin3.val[0], vmean0); - float32x4_t vsub1 = vsubq_f32(vin3.val[1], vmean1); - float32x4_t vsub2 = vsubq_f32(vin3.val[2], vmean2); - float32x4_t vs0 = vmulq_f32(vsub0, vscale0); - float32x4_t vs1 = vmulq_f32(vsub1, vscale1); - float32x4_t vs2 = vmulq_f32(vsub2, vscale2); - vst1q_f32(dout_c0, vs0); - vst1q_f32(dout_c1, vs1); - vst1q_f32(dout_c2, vs2); - - din += 12; - dout_c0 += 4; - dout_c1 += 4; - dout_c2 += 4; - } - for (; i < size; i++) { - *(dout_c0++) = (*(din++) - mean[0]) * scale[0]; - *(dout_c1++) = (*(din++) - mean[1]) * scale[1]; - *(dout_c2++) = (*(din++) - mean[2]) * scale[2]; - } -} \ No newline at end of file diff --git a/libs/paddleocr/src/main/cpp/preprocess.h b/libs/paddleocr/src/main/cpp/preprocess.h deleted file mode 100644 index 79091527..00000000 --- a/libs/paddleocr/src/main/cpp/preprocess.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "common.h" -#include -#include -cv::Mat bitmap_to_cv_mat(JNIEnv *env, jobject bitmap); - -cv::Mat resize_img(const cv::Mat &img, int height, int width); - -void neon_mean_scale(const float *din, float *dout, int size, - const std::vector &mean, - const std::vector &scale); diff --git a/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/OCRPredictorNative.java b/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/OCRPredictorNative.java deleted file mode 100644 index 382293d5..00000000 --- a/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/OCRPredictorNative.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.baidu.paddle.lite.ocr; - -import android.graphics.Bitmap; -import android.util.Log; - -import org.opencv.android.OpenCVLoader; - -import java.util.ArrayList; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.ReentrantLock; - -/** - * @author PaddleOCR - * Modified by TonyJiangWJ - * @since 2023-08-06 - */ -public class OCRPredictorNative { - - private static final AtomicBoolean isSOLoaded = new AtomicBoolean(); - private static final ReentrantLock lock = new ReentrantLock(); - - public static void loadLibrary() throws RuntimeException { - if (!isSOLoaded.get() && isSOLoaded.compareAndSet(false, true)) { - try { - // 可能和 AJ 中的 OpenCV 冲突, 直接初始化一遍 - OpenCVLoader.initDebug(); - System.loadLibrary("Native"); - } catch (Throwable e) { - throw new RuntimeException( - "Load libNative.so failed, please check it exists in apk file.", e); - } - } - } - - private Config config; - - private long nativePointer = 0; - - public OCRPredictorNative(Config config) { - lock.lock(); - try { - this.config = config; - loadLibrary(); - nativePointer = init(config.detModelFilename, config.recModelFilename, config.clsModelFilename, config.useOpencl, - config.cpuThreadNum, config.cpuPower); - Log.i("OCRPredictorNative", "load success " + nativePointer); - } finally { - lock.unlock(); - } - } - - public ArrayList runImage(Bitmap originalImage, int max_size_len, int run_det, int run_cls, int run_rec) { - lock.lock(); - try { - Log.i("OCRPredictorNative", "begin to run image"); - float[] rawResults = forward(nativePointer, originalImage, max_size_len, run_det, run_cls, run_rec); - return postprocess(rawResults); - } finally { - lock.unlock(); - } - } - - public static class Config { - public int useOpencl; - public int cpuThreadNum; - public String cpuPower; - public String detModelFilename; - public String recModelFilename; - public String clsModelFilename; - - } - - public void destroy() { - if (nativePointer != 0) { - release(nativePointer); - nativePointer = 0; - } - } - - protected native long init(String detModelPath, String recModelPath, String clsModelPath, int useOpencl, int threadNum, String cpuMode); - - protected native float[] forward(long pointer, Bitmap originalImage, int max_size_len, int run_det, int run_cls, int run_rec); - - protected native void release(long pointer); - - private ArrayList postprocess(float[] raw) { - ArrayList results = new ArrayList(); - int begin = 0; - - while (begin < raw.length) { - int point_num = Math.round(raw[begin]); - int word_num = Math.round(raw[begin + 1]); - OcrResultModel model = parse(raw, begin + 2, point_num, word_num); - begin += 2 + 1 + point_num * 2 + word_num + 2; - results.add(model); - } - - return results; - } - - private OcrResultModel parse(float[] raw, int begin, int pointNum, int wordNum) { - int current = begin; - OcrResultModel model = new OcrResultModel(); - model.setConfidence(raw[current]); - current++; - for (int i = 0; i < pointNum; i++) { - model.addPoints(Math.round(raw[current + i * 2]), Math.round(raw[current + i * 2 + 1])); - } - current += (pointNum * 2); - for (int i = 0; i < wordNum; i++) { - int index = Math.round(raw[current + i]); - model.addWordIndex(index); - } - current += wordNum; - model.setClsIdx(raw[current]); - model.setClsConfidence(raw[current + 1]); - Log.i("OCRPredictorNative", "word finished " + wordNum); - return model; - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - destroy(); - } -} diff --git a/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/OcrResult.java b/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/OcrResult.java deleted file mode 100644 index 088a4af8..00000000 --- a/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/OcrResult.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.baidu.paddle.lite.ocr; - -import android.graphics.Point; -import android.graphics.Rect; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author PaddleOCR - * Modified by TonyJiangWJ - * @since 2023-08-06 - */ -public class OcrResult implements Comparable { - private String label; - private float confidence; - private Rect bounds; - private final List elements = new ArrayList<>(); - - public OcrResult() { - } - - public OcrResult(OcrResultModel resultModel) { - this.label = resultModel.getLabel(); - this.confidence = resultModel.getConfidence(); - int left = -1, right = -1, top = -1, bottom = -1; - for (Point point : resultModel.getPoints()) { - if (point.x < left || left == -1) { - left = point.x; - } - if (point.x > right || right == -1) { - right = point.x; - } - if (point.y < top || top == -1) { - top = point.y; - } - if (point.y > bottom || bottom == -1) { - bottom = point.y; - } - } - this.bounds = new Rect(left, top, right, bottom); - } - - public OcrResult(String label, float confidence, Rect bounds) { - this.label = label; - this.confidence = confidence; - this.bounds = bounds; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - - public float getConfidence() { - return confidence; - } - - public void setConfidence(float confidence) { - this.confidence = confidence; - } - - public Rect getBounds() { - return bounds; - } - - public void setBounds(Rect bounds) { - this.bounds = bounds; - } - - public RectLocation getLocation() { - return new RectLocation(bounds); - } - - public String getWords() { - return label.trim().replace("\r", ""); - } - - public List getElements() { - return this.elements; - } - - public void addElements(OcrResult element) { - this.elements.add(element); - } - - @Override - public int compareTo(OcrResult o) { - // 上下差距小于二分之一的高度 判定为同一行 - int deviation = Math.max(this.bounds.height(), o.bounds.height()) / 2; - // 通过垂直中心点的距离判定 - if (Math.abs((this.bounds.top + this.bounds.bottom) / 2 - (o.bounds.top + o.bounds.bottom) / 2) < deviation) { - return this.bounds.left - o.bounds.left; - } else { - return this.bounds.bottom - o.bounds.bottom; - } - } - - @Override - public String toString() { - return "OcrResult{" + "label='" + label + '\'' + - ", confidence=" + confidence + - ", bounds=" + bounds + - ", elements=" + elements + - '}'; - } - - public static class RectLocation { - public int left; - public int top; - public int width; - public int height; - - public RectLocation() { - } - - public RectLocation(int left, int top, int width, int height) { - this.left = left; - this.top = top; - this.width = width; - this.height = height; - } - - public RectLocation(Rect rect) { - left = rect.left; - top = rect.top; - width = rect.right - rect.left; - height = rect.bottom - rect.top; - } - } -} diff --git a/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/OcrResultModel.java b/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/OcrResultModel.java deleted file mode 100644 index 88d778e5..00000000 --- a/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/OcrResultModel.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.baidu.paddle.lite.ocr; - -import android.graphics.Point; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author PaddleOCR - * Modified by TonyJiangWJ - * @since 2023-08-06 - */ -public class OcrResultModel { - private final List points; - private final List wordIndex; - private String label; - private float confidence; - private float clsIdx; - private String clsLabel; - private float clsConfidence; - - public OcrResultModel() { - super(); - points = new ArrayList<>(); - wordIndex = new ArrayList<>(); - } - - public void addPoints(int x, int y) { - Point point = new Point(x, y); - points.add(point); - } - - public void addWordIndex(int index) { - wordIndex.add(index); - } - - public List getPoints() { - return points; - } - - public List getWordIndex() { - return wordIndex; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - - public float getConfidence() { - return confidence; - } - - public void setConfidence(float confidence) { - this.confidence = confidence; - } - - public float getClsIdx() { - return clsIdx; - } - - public void setClsIdx(float idx) { - this.clsIdx = idx; - } - - public String getClsLabel() { - return clsLabel; - } - - public void setClsLabel(String label) { - this.clsLabel = label; - } - - public float getClsConfidence() { - return clsConfidence; - } - - public void setClsConfidence(float confidence) { - this.clsConfidence = confidence; - } - - @Override - public String toString() { - return "OcrResultModel{" + - "points=" + points + - ", wordIndex=" + wordIndex + - ", label='" + label + '\'' + - ", confidence=" + confidence + - ", clsIdx=" + clsIdx + - ", clsLabel='" + clsLabel + '\'' + - ", clsConfidence=" + clsConfidence + - '}'; - } -} \ No newline at end of file diff --git a/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/Predictor.java b/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/Predictor.java deleted file mode 100644 index fbb58b29..00000000 --- a/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/Predictor.java +++ /dev/null @@ -1,377 +0,0 @@ -package com.baidu.paddle.lite.ocr; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.Build; -import android.util.Base64; -import android.util.Log; - -import androidx.preference.PreferenceManager; - -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.List; - -/** - * @author PaddleOCR - * @since 2023-08-06 - * @noinspection unused - * Modified by TonyJiangWJ as of Aug 7, 2023. - * Modified by SuperMonster003 as of Oct 27, 2023. - */ -public class Predictor { - private static final String TAG = Predictor.class.getSimpleName(); - public boolean isLoaded = false; - public int warmupIterNum = 1; - public int inferIterNum = 1; - public int cpuThreadNum = 4; - public String cpuPowerMode = "LITE_POWER_HIGH"; - public String modelPath = ""; - public String modelName = ""; - protected OCRPredictorNative paddlePredictor = null; - protected float inferenceTime = 0; - // Only for object detection - protected List wordLabels = new ArrayList<>(); - protected int detLongSize = 960; - public float scoreThreshold = 0.1f; - protected Bitmap inputImage = null; - protected float preprocessTime = 0; - /** - * 自定义开关 - */ - public boolean useSlim = true; - public boolean useOpencl = false; - public boolean checkModelLoaded = true; - public boolean runCls = false; - public boolean runDet = false; - public boolean runRec = true; - - /** @noinspection SpellCheckingInspection*/ - private static final String CHECK_IMG_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAAFQAAAA5CAYAAACoAQxFAAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAAAqMSURBVHic7ZtrUJTVH8c/uzyIxHpLLgUiKOM4kZYUqVM4I5lW5IsUm14x2kz2JotxhkVDMbSmbBvUmhhzAsRmEF5oeKlmGk0MzNKGmClDZfICm+AukagtsBf2+b9g9vQ87oV9lvX2n/28Ovucy3P2y9lzfpeDTpZlmQhhQ3+3J/D/RkTQMBMRNMxEBA0zEUHDTETQMBMRNMxEBA0zEUHDTETQMBMRNMxEBA0zEUHDjHS3J3CvcfPmTZxOJwDjx49HkrRJNOIKdbvdWCyW0GYXAo2NjRQUFFBQUMDZs2dHbH/x4kX++uuvsL3/448/ZuXKlaxcuZJLly6J54ODg0H1Dyi/2Wzm008/paurC5PJREpKiqr+xIkTDA0NaZpwdnY2cXFxfuvtdjt9fX0AuFwuv+2GhoZoaGigtraWxMRETCYTEyZM0DQXX+j1/60xt9uNy+Vi9+7dnD59mnfffZcpU6YE7B9Q0L1793Lu3DkAysrKMJlMTJo0SdRv374dh8OhacKff/55QEGD5dq1azQ0NOByuejq6uLDDz9ky5YtjBkzZlTjKgWVZZmmpiYOHToEgNFopLS0lMzMTP/9f/nlF7+Vb7/9NhkZGQBcvXqVLVu20N/fP6oJe3A6ndTW1lJbW8v58+c194+Pj8doNKLT6QD4448/qKioYLQJiKioKFGWZZlnn32WVatWAfDvv/+yYcMGTp486be/NG3aNL+VsbGxbNy4kaKiInp7e/nzzz8xmUxs3LhRtVnPnTuXF154we84LS0tfPPNN6pnTqeT+vp6ACZNmsTMmTMDflFfzJkzh4KCAr788ksAjh07Rnp6OsuWLdM8lgfPHwiGf/IA+fn5xMbGsnPnTlwuF1u3bmXHjh1Mnz7dq78UHx8f8AXx8fGUlpaybt067HY7LS0tfPbZZxQWFoo2SUlJPPXUU37H6O3t1fq9gmbFihW0t7fz888/A7B7927S0tJ44oknQhpPuUKV50NeXh6yLLNnzx6MRqNPMSFIOzQjI4OioiIAJkyYwLx581R/ybuJTqejsLCQ5ORkYPhnevTo0ZDHi46OFmXPCvXw0ksvUVVVFXDxBG1kzZ8/n/Xr15OZmak6mG7lxIkTDAwMIEkSubm5wQ4/KgwGA++88w4bNmygoKCA559/HoCTJ09y8OBBTWO1tbWJ8kgH0Pz58722F8loNPL6668HtYc988wzI7apqanBYrEQGxt7xwQFSE9Pp7q6mpiYGPGsr69PJVAoBOqfnp7u9Uw6d+5c0EbrvY5STABJkoiNjdU0xsDAgOpzoP6+TDQJ4OGHH/bZwWKxcObMGRYtWqRpUvcKS5YsYcmSJZr61NTUsH//fgCKi4tZsGCBpv5SdHQ0vk76o0ePsmvXLgYHB3E4HLz44ouaBr6dXLt2zeevKioqisTExFGNrTyU7Ha75v5SRkaGyjvwEBMTIya9c+dODAaD5r/W7aKyspKmpiav58nJyezatWtUYyu3jVAE1S9cuNBnxYIFC4SHIMsy5eXltLS0hDDF+wvlvqjVrQbQL1682G9lfn4+eXl5wLCR+8EHHwjf/m7yyCOPkJubS25uLk8//XRYxx47dqwoh+JmSyMFE9544w0sFgstLS04HA4qKysxmUw+t4k7xdKlS0XZarX69a2dTifff/99UGMaDAZycnJUp7rNZtM8txEN+6ioKIxGI+vWrePRRx/ltddeu6tiasFut1NRURFU29TU1DsjKEBcXBzl5eVedp4vPP6v0ie+n1CGFm/cuKG5f9CuZzBiAiJ9oDQ/7hZjx46lrKxM9Uz5+c033yQhIQH4z4A3GAyiPiRBbTZbWAK+Hjwn470gqCRJPPnkk6pnycnJdHV1AcPZg1tt8HHjxonyP//8o/md+pqamqAa/vTTT3R0dARs43a7he2q1eW7Vxg/fryIpPX29mpO8UjZ2dlBNfziiy/o6ekhLS2N7du3+1yBN27cEBHzyZMna5rIvYJerychIQGr1Yosy1y/fp0HH3ww+P7z5s0bsVF3dzc9PT3A8F7q7+fsSa7B/SsowEMPPSTKVqtVU9+g7B9lCCtQJLyzs1OUR8oO3m7cbndIZg+og0VaBQ3qlP/9999Fefbs2aK8Z88e4L8DSJlsO3XqFMuXLwdg0aJF5OTkAPDAAw9ommCoVFZWkpmZKd6rBWW63Gw2e9VbLBYSEhJ82uMjrlBZlmltbQWGT01lINpgMGAwGIiJicHlcvHDDz+Iura2Nqqrq5FlmejoaNH2TjgFdXV1HD58mIsXL4bUf+rUqaKsvOzgobq6mtWrV/PVV1951enXrFmjWoG30tXVJcyH2bNn+7VHm5ubuX79uupZQ0MDFRUVXrkZGLYC6urqqKur47nnnvP7fq18/fXX7N27FyBkQZWR+La2Nq/UtMViwWq1+ox46Ts6OryEUPLbb7+JclZWls82fX19VFdXi8+rVq0S9tx3331HeXm51y0QnU4nVu1oLyd4sFqtInwnSZII7ASL51CdPHmyiKvevHlTdTbIsizsWE9iUIkE+Awwe/j1119FWbl/enC5XGzbtk1MZu7cueTn55OVlUVJSQk2m42mpibsdjvFxcVhE8+DxzPzzAWGxSwpKfGZnVTalQcPHsThcNDZ2cnly5ex2Wzilkh2djbffvstMHyvIC0tDRgObnvSJL4yHQFTIA6HQwhqMBi8ctEul4tPPvlE7LFxcXGsXr0agOnTp/Pee+9RWlqKzWbj1KlTvP/++5SUlKhCZIEECiZVfetFsaioKCHm+fPn6e7u5sqVK1y5cgWz2ay6+HbgwAFV31svb3gEPXbsGMuWLUOn06lWq68knX7ixIl+L1mdPXtWuJJZWVmqA6W/v5+tW7dy/Phx8eWLi4tVNtyMGTPYvHmz8JpaW1vZvHlzQHPmwoULohyM+3rkyBFR1ul0GI1GsTIrKiooLy+nvr6e5uZmLl++HHAspe38+OOPM3HiRAA6Ojr48ccfAfUv1mfWM5BZ4Vl5MHztxYPZbOajjz5SuaJr1qzxaaPOnDmTsrIyNm3ahN1u58yZM7S2tpKTk8Phw4cZGBggOjqaoaEhLl26RHNzs+jrCVz4w263q+ZQWFioSnU/9thjPk/ppKQkpk2bxtSpU0lNTWXKlCmkpKSo3GVJkli+fLk4G7Zt20ZjYyOeu2Djxo3zuo0IIL388st+J3z69GlRnjVrFjAcMFi7dq3It+h0OtauXRswB5+ZmcmmTZsoKyvj1VdfFbZhe3u7WOG3MmvWrBFdvpiYGEpKSigqKuKVV17xys5mZWXR09MjhEtJSSElJSXglqMkLy+PI0eOYDabcTqdKj0WLlzo0wTU+ft/+cHBQdavX8+FCxdITEykqqpK1NXX11NbW0tcXBxGo9ErouMPs9lMamqq+Lxv3z7hHCiZM2cOb731VtAZzPb2dmbMmHFbrgd1d3dTWlqq2nvj4+PZsWOHz63Sr6DKAa9evaoymdxuN1VVVSxdutTvgRYMf//9N52dnej1eiRJYsyYMSQlJYXl4mw46e/vp7GxEbPZTGJiIosXL1aF+ZSMKGgEbdwfyaH7iIigYSYiaJiJCBpmIoKGmYigYeZ/jd/+RcTqcugAAAAASUVORK5CYII="; - private static final Bitmap checkingBitmap = BitmapFactory.decodeByteArray(Base64.decode(CHECK_IMG_BASE64, Base64.DEFAULT), 0, Base64.decode(CHECK_IMG_BASE64, Base64.DEFAULT).length); - /** - * 检测模型 - */ - public String detModelFilename = "det_opt.nb"; - /** - * 识别模型 - */ - public String recModelFilename = "rec_opt.nb"; - /** - * 文本方向检测模型 - */ - public String clsModelFilename = "cls_opt.nb"; - - private final String defaultLabelPath = "labels/ppocr_keys_v1.txt"; - private final String defaultModelPath = "models/ocr_v3_for_cpu"; - /** - * slim模型 目前使用的是2.10版的opt工具转换的2.11版本不能正常使用 - */ - private final String defaultModelPathSlim = "models/ocr_v3_for_cpu(slim)"; - - /** - * 初始化时校验模型是否加载正确 - */ - private int retryTime = 1; - /** - * 初始化尝试次数 - */ - private int initRetryTime = 1; - - public Predictor() { - } - - public boolean init(Context appCtx) { - return this.init(appCtx, defaultModelPath, defaultLabelPath); - } - - public boolean init(Context appCtx, boolean useSlim) { - if (this.isLoaded && this.useSlim == useSlim) { - return true; - } - this.useSlim = useSlim; - if (useSlim) { - return this.init(appCtx, defaultModelPathSlim, defaultLabelPath); - } else { - return this.init(appCtx, defaultModelPath, defaultLabelPath); - } - } - - public boolean init(Context appCtx, String modelPath, String labelPath) { - Log.d(TAG, "init whit model: " + modelPath + " label: " + labelPath); - isLoaded = loadModel(appCtx, modelPath, cpuThreadNum, cpuPowerMode); - if (!isLoaded) { - return false; - } - isLoaded = loadLabel(appCtx, labelPath); - if (!checkModelLoadedSuccess()) { - if (initRetryTime++ < 3) { - return init(appCtx, modelPath, labelPath); - } else { - return false; - } - } - return isLoaded; - } - - /** - * 初始化模型后通过识别预设图片校验是否初始化成功 - * 曲线救国 深层的失败原因需要后续排查 - */ - private boolean checkModelLoadedSuccess() { - if (!checkModelLoaded) { - return true; - } - if (!isLoaded) { - return false; - } - List results = runOcr(checkingBitmap); - StringBuilder sb = new StringBuilder(); - for (OcrResult result : results) { - sb.append(result.getLabel()); - } - boolean check = sb.toString().contains("测试"); - Log.d(TAG, "第" + retryTime + "次 校验是否初始化成功: " + check + " 识别结果:" + sb); - boolean result = check || retryTime++ >= 5; - if (!check && retryTime >= 5) { - Log.e(TAG, "初始化模型失败"); - } - return result; - } - - public boolean init(Context appCtx, String modelPath, String labelPath, int cpuThreadNum, String cpuPowerMode) { - isLoaded = loadModel(appCtx, modelPath, cpuThreadNum, cpuPowerMode); - if (!isLoaded) { - return false; - } - isLoaded = loadLabel(appCtx, labelPath); - return isLoaded; - } - - public boolean init(Context appCtx, String modelPath, String labelPath, int cpuThreadNum, String cpuPowerMode, - int detLongSize, float scoreThreshold) { - boolean isLoaded = init(appCtx, modelPath, labelPath, cpuThreadNum, cpuPowerMode); - if (!isLoaded) { - return false; - } - this.detLongSize = detLongSize; - this.scoreThreshold = scoreThreshold; - return true; - } - - protected boolean loadModel(Context appCtx, String modelPath, int cpuThreadNum, String cpuPowerMode) { - // Release model if exists - releaseModel(); - - // Load model - if (modelPath.isEmpty()) { - return false; - } - String realPath = modelPath; - if (modelPath.charAt(0) != '/') { - // Read model files from custom path if the first character of mode path is '/' - // otherwise copy model to cache from assets - realPath = appCtx.getCacheDir() + File.separator + modelPath; - // region add by TonyJiangWJ - String key = "PADDLE_MODEL_LOADED" + md5(modelPath); - // 进行了模型更新 需要强制覆盖旧模型 - boolean loaded = PreferenceManager.getDefaultSharedPreferences(appCtx).getBoolean(key, false); - if (loaded) { - // 没有必要每次都复制 - Utils.copyDirectoryFromAssetsIfNeeded(appCtx, modelPath, realPath); - } else { - Utils.copyDirectoryFromAssets(appCtx, modelPath, realPath); - PreferenceManager.getDefaultSharedPreferences(appCtx).edit().putBoolean(key, true).apply(); - } - // endregion - } - - OCRPredictorNative.Config config = new OCRPredictorNative.Config(); - // 是否使用GPU - config.useOpencl = useOpencl ? 1 : 0; - config.cpuThreadNum = cpuThreadNum; - config.detModelFilename = realPath + File.separator + detModelFilename; - config.recModelFilename = realPath + File.separator + recModelFilename; - config.clsModelFilename = realPath + File.separator + clsModelFilename; - Log.i("Predictor", "model path" + config.detModelFilename + " ; " + config.recModelFilename + ";" + config.clsModelFilename); - config.cpuPower = cpuPowerMode; - paddlePredictor = new OCRPredictorNative(config); - - this.cpuThreadNum = cpuThreadNum; - this.cpuPowerMode = cpuPowerMode; - this.modelPath = realPath; - this.modelName = realPath.substring(realPath.lastIndexOf(File.separator) + 1); - return true; - } - - public static String md5(String text) { - MessageDigest md; - byte[] bytesOfMessage = text.getBytes(); - try { - md = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - byte[] thedigest = md.digest(bytesOfMessage); - return Base64.encodeToString(thedigest, Base64.DEFAULT); - } - - public void releaseModel() { - if (paddlePredictor != null) { - paddlePredictor.destroy(); - paddlePredictor = null; - } - isLoaded = false; - modelPath = ""; - modelName = ""; - } - - protected boolean loadLabel(Context appCtx, String labelPath) { - wordLabels.clear(); - wordLabels.add("black"); - // Load word labels from file - try { - InputStream labelInputStream; - if (labelPath.startsWith(File.separator)) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - labelInputStream = Files.newInputStream(Paths.get(labelPath)); - } else { - // noinspection IOStreamConstructor - labelInputStream = new FileInputStream(labelPath); - } - } else { - labelInputStream = appCtx.getAssets().open(labelPath); - } - int available = labelInputStream.available(); - byte[] lines = new byte[available]; - if (labelInputStream.read(lines) <= 0) { - Log.e(TAG, "读取label失败"); - return false; - } - labelInputStream.close(); - String words = new String(lines); - // Windows下换行为\r\n 进行兼容 - String[] contents = words.split("(\r)?\n"); - wordLabels.addAll(Arrays.asList(contents)); - wordLabels.add(" "); - Log.i(TAG, "Word label size: " + wordLabels.size()); - } catch (Exception e) { - Log.e(TAG, e.getMessage(), e); - return false; - } - return true; - } - - public List runOcr(Bitmap inputImage) { - if (inputImage == null || !isLoaded()) { - return Collections.emptyList(); - } - // 检测、分类、识别 - int run_det = runDet ? 1 : 0, run_cls = runCls ? 1 : 0, run_rec = runRec ? 1 : 0; - // Warm up - for (int i = 0; i < warmupIterNum; i++) { - paddlePredictor.runImage(inputImage, detLongSize, run_det, run_cls, run_rec); - } - warmupIterNum = 0; // do not need warm - // Run inference - Date start = new Date(); - ArrayList results = paddlePredictor.runImage(inputImage, detLongSize, run_det, run_cls, run_rec); - Date end = new Date(); - inferenceTime = (end.getTime() - start.getTime()) / (float) inferIterNum; - - postProcess(results); - Log.i(TAG, "[stat] Preprocess Time: " + preprocessTime - + " ; Inference Time: " + inferenceTime + " ;Box Size " + results.size()); - List ocrResults = new ArrayList<>(); - for (OcrResultModel resultModel : results) { - Log.d(TAG, "recognize: " + resultModel.toString()); - if (resultModel.getConfidence() >= scoreThreshold) { - ocrResults.add(new OcrResult(resultModel)); - } - } - Collections.sort(ocrResults); - return ocrResults; - } - - public boolean isLoaded() { - return paddlePredictor != null && isLoaded; - } - - public String modelPath() { - return modelPath; - } - - public String modelName() { - return modelName; - } - - public int cpuThreadNum() { - return cpuThreadNum; - } - - public String cpuPowerMode() { - return cpuPowerMode; - } - - public float inferenceTime() { - return inferenceTime; - } - - public Bitmap inputImage() { - return inputImage; - } - - public float preprocessTime() { - return preprocessTime; - } - - public String getDefaultLabelPath() { - return defaultLabelPath; - } - - public String getDefaultModelPath() { - return defaultModelPath; - } - - public String getDefaultModelPathSlim() { - return defaultModelPathSlim; - } - - public boolean isUseSlim() { - return useSlim; - } - - public void setInputImage(Bitmap image) { - if (image == null) { - return; - } - this.inputImage = image.copy(Bitmap.Config.ARGB_8888, true); - } - - private void postProcess(ArrayList results) { - for (OcrResultModel r : results) { - StringBuilder word = new StringBuilder(); - for (int index : r.getWordIndex()) { - if (index >= 0 && index < wordLabels.size()) { - word.append(wordLabels.get(index)); - } else { - Log.e(TAG, "Word index is not in label list:" + index); - word.append(" "); - } - } - r.setLabel(word.toString()); - r.setClsLabel(r.getClsIdx() == 1 ? "180" : "0"); - } - } - -} diff --git a/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/Utils.java b/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/Utils.java deleted file mode 100644 index 7e78d2d0..00000000 --- a/libs/paddleocr/src/main/java/com/baidu/paddle/lite/ocr/Utils.java +++ /dev/null @@ -1,198 +0,0 @@ -package com.baidu.paddle.lite.ocr; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.media.ExifInterface; -import android.os.Environment; -import android.util.Log; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * @author PaddleOCR - * Modified by TonyJiangWJ - * @since 2023-08-06 - */ -public class Utils { - private static final String TAG = Utils.class.getSimpleName(); - - public static void copyFileFromAssets(Context appCtx, String srcPath, String dstPath) { - if (srcPath.isEmpty() || dstPath.isEmpty()) { - return; - } - InputStream is = null; - OutputStream os = null; - try { - is = new BufferedInputStream(appCtx.getAssets().open(srcPath)); - os = new BufferedOutputStream(new FileOutputStream(new File(dstPath))); - byte[] buffer = new byte[1024]; - int length = 0; - while ((length = is.read(buffer)) != -1) { - os.write(buffer, 0, length); - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - os.close(); - is.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - public static void copyDirectoryFromAssets(Context appCtx, String srcDir, String dstDir) { - if (srcDir.isEmpty() || dstDir.isEmpty()) { - return; - } - try { - if (!new File(dstDir).exists()) { - new File(dstDir).mkdirs(); - } - for (String fileName : appCtx.getAssets().list(srcDir)) { - String srcSubPath = srcDir + File.separator + fileName; - String dstSubPath = dstDir + File.separator + fileName; - if (new File(srcSubPath).isDirectory()) { - copyDirectoryFromAssets(appCtx, srcSubPath, dstSubPath); - } else { - Log.d(TAG, "复制资源文件: " + srcSubPath + " => " + dstSubPath); - copyFileFromAssets(appCtx, srcSubPath, dstSubPath); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static void copyDirectoryFromAssetsIfNeeded(Context appCtx, String srcDir, String dstDir) { - if (srcDir.isEmpty() || dstDir.isEmpty()) { - return; - } - try { - if (!new File(dstDir).exists()) { - new File(dstDir).mkdirs(); - } - for (String fileName : appCtx.getAssets().list(srcDir)) { - String srcSubPath = srcDir + File.separator + fileName; - String dstSubPath = dstDir + File.separator + fileName; - if (new File(srcSubPath).isDirectory()) { - copyDirectoryFromAssetsIfNeeded(appCtx, srcSubPath, dstSubPath); - } else { - if (new File(dstSubPath).exists()) { - return; - } - Log.d(TAG, "复制资源文件: " + srcSubPath + " => " + dstSubPath); - copyFileFromAssets(appCtx, srcSubPath, dstSubPath); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static float[] parseFloatsFromString(String string, String delimiter) { - String[] pieces = string.trim().toLowerCase().split(delimiter); - float[] floats = new float[pieces.length]; - for (int i = 0; i < pieces.length; i++) { - floats[i] = Float.parseFloat(pieces[i].trim()); - } - return floats; - } - - public static long[] parseLongsFromString(String string, String delimiter) { - String[] pieces = string.trim().toLowerCase().split(delimiter); - long[] longs = new long[pieces.length]; - for (int i = 0; i < pieces.length; i++) { - longs[i] = Long.parseLong(pieces[i].trim()); - } - return longs; - } - - public static String getSDCardDirectory() { - return Environment.getExternalStorageDirectory().getAbsolutePath(); - } - - public static boolean isSupportedNPU() { - return false; - // String hardware = android.os.Build.HARDWARE; - // return hardware.equalsIgnoreCase("kirin810") || hardware.equalsIgnoreCase("kirin990"); - } - - public static Bitmap resizeWithStep(Bitmap bitmap, int maxLength, int step) { - int width = bitmap.getWidth(); - int height = bitmap.getHeight(); - int maxWH = Math.max(width, height); - float ratio = 1; - int newWidth = width; - int newHeight = height; - if (maxWH > maxLength) { - ratio = maxLength * 1.0f / maxWH; - newWidth = (int) Math.floor(ratio * width); - newHeight = (int) Math.floor(ratio * height); - } - - newWidth = newWidth - newWidth % step; - if (newWidth == 0) { - newWidth = step; - } - newHeight = newHeight - newHeight % step; - if (newHeight == 0) { - newHeight = step; - } - return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true); - } - - public static Bitmap rotateBitmap(Bitmap bitmap, int orientation) { - - Matrix matrix = new Matrix(); - switch (orientation) { - case ExifInterface.ORIENTATION_NORMAL: - return bitmap; - case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: - matrix.setScale(-1, 1); - break; - case ExifInterface.ORIENTATION_ROTATE_180: - matrix.setRotate(180); - break; - case ExifInterface.ORIENTATION_FLIP_VERTICAL: - matrix.setRotate(180); - matrix.postScale(-1, 1); - break; - case ExifInterface.ORIENTATION_TRANSPOSE: - matrix.setRotate(90); - matrix.postScale(-1, 1); - break; - case ExifInterface.ORIENTATION_ROTATE_90: - matrix.setRotate(90); - break; - case ExifInterface.ORIENTATION_TRANSVERSE: - matrix.setRotate(-90); - matrix.postScale(-1, 1); - break; - case ExifInterface.ORIENTATION_ROTATE_270: - matrix.setRotate(-90); - break; - default: - return bitmap; - } - try { - Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); - bitmap.recycle(); - return bmRotated; - } catch (OutOfMemoryError e) { - e.printStackTrace(); - return null; - } - } -} diff --git a/plugin-api/paddle-ocr/build.gradle.kts b/plugin-api/paddle-ocr/build.gradle.kts new file mode 100644 index 00000000..5ee9c2b0 --- /dev/null +++ b/plugin-api/paddle-ocr/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + id("org.autojs.build.versions") + id("org.autojs.build.jvm-convention") + id("com.android.library") + id("org.jetbrains.kotlin.android") + kotlin("plugin.parcelize") +} + +android { + namespace = "org.autojs.plugin.paddle.ocr" + + compileSdk = versions.sdkVersionCompile + + defaultConfig { + minSdk = versions.sdkVersionMin + consumerProguardFiles("consumer-rules.pro") + } + + lint { + targetSdk = versions.sdkVersionTarget + abortOnError = false + } + + buildFeatures { + aidl = true + buildConfig = false + } +} diff --git a/libs/paddleocr/consumer-rules.pro b/plugin-api/paddle-ocr/consumer-rules.pro similarity index 100% rename from libs/paddleocr/consumer-rules.pro rename to plugin-api/paddle-ocr/consumer-rules.pro diff --git a/plugin-api/paddle-ocr/src/main/aidl/org/autojs/plugin/paddle/ocr/IOcrPlugin.aidl b/plugin-api/paddle-ocr/src/main/aidl/org/autojs/plugin/paddle/ocr/IOcrPlugin.aidl new file mode 100644 index 00000000..1b6ad567 --- /dev/null +++ b/plugin-api/paddle-ocr/src/main/aidl/org/autojs/plugin/paddle/ocr/IOcrPlugin.aidl @@ -0,0 +1,16 @@ +package org.autojs.plugin.paddle.ocr; + +import org.autojs.plugin.paddle.ocr.PluginInfo; +import org.autojs.plugin.paddle.ocr.OcrOptions; +import org.autojs.plugin.paddle.ocr.OcrResult; +import android.os.ParcelFileDescriptor; + +interface IOcrPlugin { + + PluginInfo getInfo(); + + List recognizeText(in ParcelFileDescriptor imageFd, in OcrOptions options); + + List detect(in ParcelFileDescriptor imageFd, in OcrOptions options); + +} \ No newline at end of file diff --git a/plugin-api/paddle-ocr/src/main/aidl/org/autojs/plugin/paddle/ocr/OcrOptions.aidl b/plugin-api/paddle-ocr/src/main/aidl/org/autojs/plugin/paddle/ocr/OcrOptions.aidl new file mode 100644 index 00000000..ef3f89bf --- /dev/null +++ b/plugin-api/paddle-ocr/src/main/aidl/org/autojs/plugin/paddle/ocr/OcrOptions.aidl @@ -0,0 +1,10 @@ +package org.autojs.plugin.paddle.ocr; + +parcelable OcrOptions { + int cpuThreadNum; + boolean useSlim; + boolean useOpenCL; + int detLongSize; + float scoreThreshold; + android.os.Bundle extras; +} \ No newline at end of file diff --git a/plugin-api/paddle-ocr/src/main/aidl/org/autojs/plugin/paddle/ocr/OcrResult.aidl b/plugin-api/paddle-ocr/src/main/aidl/org/autojs/plugin/paddle/ocr/OcrResult.aidl new file mode 100644 index 00000000..77dad8eb --- /dev/null +++ b/plugin-api/paddle-ocr/src/main/aidl/org/autojs/plugin/paddle/ocr/OcrResult.aidl @@ -0,0 +1,8 @@ +package org.autojs.plugin.paddle.ocr; + +parcelable OcrResult { + String text; + float confidence; + android.graphics.Rect bounds; + android.os.Bundle extras; +} \ No newline at end of file diff --git a/plugin-api/paddle-ocr/src/main/aidl/org/autojs/plugin/paddle/ocr/PluginInfo.aidl b/plugin-api/paddle-ocr/src/main/aidl/org/autojs/plugin/paddle/ocr/PluginInfo.aidl new file mode 100644 index 00000000..8ea34005 --- /dev/null +++ b/plugin-api/paddle-ocr/src/main/aidl/org/autojs/plugin/paddle/ocr/PluginInfo.aidl @@ -0,0 +1,24 @@ +package org.autojs.plugin.paddle.ocr; + +parcelable PluginInfo { + + String name; + @nullable String description; + + String author; + @nullable String[] collaborators; + + String versionName; + long versionCode; + @nullable String versionDate; + + /** @example "paddle-ocr-v5" */ + @nullable String id; + /** @sample "paddle-ocr" */ + @nullable String engine; + /** @sample "v5" */ + @nullable String variant; + + @nullable android.os.Bundle capabilities; + +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 45d8517c..aebc04ec 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,7 +20,6 @@ private val libs = listOf( "androidx-appcompat-1_0_2", "apk-parser-1_0_2", "org-opencv-4_8_0", - "paddleocr", "rapidocr", "imagequant", @@ -40,16 +39,25 @@ private val libs = listOf( "recyclerview-flexibledivider-1_4_0" ) +private val pluginApi = listOf( + "paddle-ocr", +) + include( ":app", *modules.map { ":modules:$it" }.toTypedArray(), *libs.map { ":libs:$it" }.toTypedArray(), + *pluginApi.map { ":plugin-api:$it" }.toTypedArray(), ) modules.forEach { project(":modules:$it").projectDir = File("modules", it) } +pluginApi.forEach { + project(":plugin-api:$it").projectDir = File("plugin-api", it) +} + pluginManagement { @Suppress("UNCHECKED_CAST") diff --git a/version.properties b/version.properties index 04aba8d5..2216ad59 100644 --- a/version.properties +++ b/version.properties @@ -1,5 +1,5 @@ -#Thu Nov 20 16:13:13 CST 2025 -BUILD_TIME=1763626393791 +#Fri Nov 28 14:10:00 CST 2025 +BUILD_TIME=1764310200816 COMPILE_SDK_VERSION=36 IMAGE_QUANT_CMAKE_VERSION=3.22.1 IMAGE_QUANT_NDK_VERSION=26.1.10909125 @@ -27,6 +27,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3 TARGET_SDK_VERSION=36 TARGET_SDK_VERSION_INRT=29 -VERSION_BUILD=3502 -VERSION_NAME=6.7.0 Alpha11 +VERSION_BUILD=3516 +VERSION_NAME=6.7.0 Alpha12 VSCODE_EXT_REQUIRED_VERSION=1.0.8