New setting to control the quality of exported PDFs (#70)

This commit is contained in:
Pierre-Yves Nicolas
2026-01-10 15:06:01 +01:00
parent fcdcea1891
commit 5c5b6e921e
14 changed files with 295 additions and 64 deletions

View File

@@ -25,7 +25,6 @@ import org.opencv.core.Size
import org.opencv.imgproc.Imgproc
import org.opencv.imgproc.Imgproc.fillConvexPoly
import kotlin.math.roundToInt
import kotlin.math.sqrt
fun isColoredDocument(
img: Mat,
@@ -97,18 +96,6 @@ fun isColoredDocument(
return proportion > proportionThreshold
}
private fun resizeForMaxPixels(img: Mat, maxPixels: Double): Mat {
val origPixels = img.width() * img.height()
if (origPixels <= maxPixels) {
return img.clone()
}
val scale = sqrt(maxPixels / origPixels)
val size = Size(img.width() * scale, img.height() * scale)
val resizedImg = Mat()
Imgproc.resize(img, resizedImg, size, 0.0, 0.0, Imgproc.INTER_AREA)
return resizedImg
}
private fun chroma(a: Mat, b: Mat): Mat {
val aFloat = Mat()
val bFloat = Mat()

View File

@@ -32,15 +32,6 @@ interface Mask {
fun toMat(): Mat
}
data class PageAnalysis(
val isColored: Boolean,
)
data class ExtractedDocument(
val image: Mat,
val pageAnalysis: PageAnalysis,
)
fun detectDocumentQuad(mask: Mask, isLiveAnalysis: Boolean, minQuadAreaRatio: Double = 0.02): Quad? {
val mat = mask.toMat()
val (biggest: MatOfPoint2f?, area) = biggestContour(mat)
@@ -125,8 +116,9 @@ fun extractDocument(
inputMat: Mat,
quad: Quad,
rotationDegrees: Int,
mask: Mask,
): ExtractedDocument {
isColored: Boolean,
maxPixels: Long,
): Mat {
val widthTop = norm(quad.topLeft, quad.topRight)
val widthBottom = norm(quad.bottomLeft, quad.bottomRight)
val targetWidth = (widthTop + widthBottom) / 2
@@ -153,27 +145,11 @@ fun extractDocument(
val outputSize = Size(targetWidth, targetHeight)
Imgproc.warpPerspective(inputMat, outputMat, transform, outputSize)
val resized = resize(outputMat, 1500.0)
val isColored = isColoredDocument(inputMat, mask, quad)
val resized = resizeForMaxPixels(outputMat, maxPixels.toDouble())
val enhanced = enhanceCapturedImage(resized, isColored)
val rotated = rotate(enhanced, rotationDegrees)
return ExtractedDocument(rotated, PageAnalysis(isColored))
}
fun resize(original: Mat, targetMax: Double): Mat {
val origSize = original.size()
if (max(origSize.width, origSize.height) < targetMax)
return original;
var targetWidth = targetMax
var targetHeight = origSize.height * targetWidth / origSize.width
if (origSize.width < origSize.height) {
targetHeight = targetMax
targetWidth = origSize.width * targetHeight / origSize.height
}
val result = Mat()
Imgproc.resize(original, result, Size(targetWidth, targetHeight), 0.0, 0.0, Imgproc.INTER_AREA)
return result
return rotated
}
fun rotate(input: Mat, degrees: Int): Mat {

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2025 Pierre-Yves Nicolas
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.fairscan.imageprocessing
import org.opencv.core.Mat
import org.opencv.core.Size
import org.opencv.imgproc.Imgproc
import kotlin.math.sqrt
fun resizeForMaxPixels(img: Mat, maxPixels: Double): Mat {
val origPixels = img.width() * img.height()
if (origPixels <= maxPixels) {
return img.clone()
}
val scale = sqrt(maxPixels / origPixels)
val size = Size(img.width() * scale, img.height() * scale)
val resizedImg = Mat()
Imgproc.resize(img, resizedImg, size, 0.0, 0.0, Imgproc.INTER_AREA)
return resizedImg
}