That's why I wrote the following tool today - which worked fine here with a lot of images - hopefully it will do the right job also for you:
Code: Select all
EnableExplicit
#QR="QR.png"
; Define
#W=500
#Max=100
#Scan=20
#NoiseFilter=$F8F8F8
UsePNGImageDecoder()
UseJPEGImageDecoder()
Procedure.i iMin(val1.i,val2.i)
EnableASM
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
MOV eax, val1
CMP eax, val2
CMOVG eax, val2
CompilerElse
MOV rax, val1
CMP rax, val2
CMOVG rax, val2
CompilerEndIf
DisableASM
ProcedureReturn
EndProcedure
Procedure.i iMax(val1.i,val2.i)
EnableASM
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
MOV eax, val1
CMP eax, val2
CMOVNG eax, val2
CompilerElse
MOV rax, val1
CMP rax, val2
CMOVNG rax, val2
CompilerEndIf
DisableASM
ProcedureReturn
EndProcedure
; EndDefine
Procedure CheckQR(log=#Null)
Protected Dim l(#Scan)
Protected Dim z(#Scan)
Protected Dim b(#Scan,#Max)
Protected Dim w(#Scan,#Max)
Protected Dim c(#Max,#Max)
Protected Dim d(#Max)
Protected w,h
Protected x,y,z
Protected box
Protected i,j,pi,pj
Protected c,d,s
Protected xmin,xmax
Protected ymin,ymax
Protected scan
If FileSize(#QR) And LoadImage(0,#QR)
w=ImageWidth(0)
h=ImageHeight(0)
; Path I - detecting black/white areas
StartDrawing(ImageOutput(0))
scan=iMin(#Scan,h/3)
s=h/scan
For i=1 To scan-1
y=s*i
c=0
z=0
For x=0 To w-1
Select Point(x,y)&#NoiseFilter
Case #Black
If c<>1; c=0
If z<#Max
z+1
b(i,z)=x
EndIf
;Box(x-2,y-5,3,10,#Magenta)
c=1
EndIf
Case #NoiseFilter
If c
If c=1
w(i,z)=x
EndIf
;Box(x,y-10,1,20,#Green)
c=0
EndIf
Default
If c=1
w(i,z)=x
EndIf
;Debug Hex(Point(x,y))
;Box(x,y-20,1,40,#Red)
c=2
EndSelect
Next x
If z
l(i)=y
z(i)=z
EndIf
Next i
StopDrawing()
; Path II - find nice start point
box=w
For i=2 To scan-2
If z(i)>1 And z(i-1)>1 And z(i+1)>1
For j=2 To z(i)
d=b(i,j)-b(i,j-1)
If d<box
box=d
pi=i
pj=j
EndIf
Next j
EndIf
Next i
If pi*pj=#Null Or box<3 Or w(pi,pj)-b(pi,pj)<box/2
Debug "No start point for QR pattern detected."
ProcedureReturn #False
EndIf
; Path III - find square center and pattern
StartDrawing(ImageOutput(0))
x=b(pi,pj)+box/7
y=l(pi)
While y And Point(x+i,y)&#NoiseFilter=#Black
y-1
Wend
x=b(pi,pj)+box/4
y+box/4
ymin=#Max
ymax=0
xmin=#Max
xmax=0
c=#Max/2
d=box/2
For i=0 To #Max
pi=x+(i-c)*box/2
For j=0 To #Max
pj=y+(j-c)*box/2
If pi>=0 And pj>=0 And pi<w And pj<h
Select Point(pi,pj)&#NoiseFilter
Case #Black
c(i,j)=1
xmin=iMin(xmin,i)
ymin=iMin(ymin,j)
xmax=iMax(xmax,i)
ymax=iMax(ymax,j)
Box(pi-d/2,pj-d/2,d,d,#Green)
Case #NoiseFilter
c(i,j)=0
Default
c(i,j)=2
EndSelect
Else
c(i,j)=2
EndIf
Next j
Next i
; Repeat
; z=0
; For i=0 To 3
; dx=i>>1-i&1
; dy=i!3>>1-i&1
; Debug Str(dx)+" "+Str(dy)
; Next i
; Until z=0
StopDrawing()
; Path IV - reduce surrounding border
Repeat
z=0
j=ymin
While j<ymax
c=0
d=0
For i=xmin To xmax
c+Bool(c(i,j)=1)
d+Bool(c(i,j)=2)
Next i
If c=0 Or d
If ymax-j<j-ymin
ymax=j-1
z=1
Else
ymin=j+1
z=2
EndIf
EndIf
j+1
Wend
i=xmin
While i<xmax
c=0
d=0
For j=ymin To ymax
c+Bool(c(i,j)=1)
d+Bool(c(i,j)=2)
Next j
If c=0 Or d
If xmax-i<i-xmin
xmax=i-1
z=3
Else
xmin=i+1
z=4
EndIf
EndIf
i+1
Wend
Until z=0
If ymax-ymin<>xmax-xmin
Debug "QR not squared."
EndIf
; Path V - draw image
c=xmax-xmin+1
CreateImage(0,c,ymax-ymin+1)
StartDrawing(ImageOutput(0))
For j=ymin To ymax
Protected t.s=""
For i=xmin To xmax
Plot(i-xmin,j-ymin,#White*(c(i,j)!1))
t+Mid(" #.",c(i,j)+1,1)
Next i
If log
Debug t
EndIf
Next j
StopDrawing()
ProcedureReturn c
Else
Debug "Could not load image "+#QR+"."
ProcedureReturn #False
EndIf
EndProcedure
#Zoom=16
Define c=CheckQR()
If c
c*#Zoom
OpenWindow(0,0,0,c,c,"QR",#PB_Window_ScreenCentered)
CanvasGadget(0,0,0,c,c)
StartDrawing(CanvasOutput(0))
ResizeImage(0,c,c,#PB_Image_Raw)
DrawImage(ImageID(0),0,0)
StopDrawing()
Repeat
Select WaitWindowEvent()
Case #WM_CHAR, #PB_Event_CloseWindow
End
EndSelect
ForEver
EndIf