From: Karl E. Peterson on
It happens that argusy formulated :
> I'm trying to open a jpg file, find the position of "FF C0 00 01 08" and get
> the next four bytes of info. (width and height of said jpg)
>
> That data never stays in one fixed spot, so I have to find it.
>
> Anyone interested in giving me a hand with the code?

Mike Sutton might. Grab the JPG Info sample here:

http://edais.mvps.org/Files/Demo/Page3.html

It's got all this stuff, and a lot more, in it. (As interesting as the
InstrB thing is, and it is certainly a technique to be aware of, why
pound sand when you can actually pick through the header as it was
designed to be picked through?)

--
..NET: It's About Trust!
http://vfred.mvps.org


From: Karl E. Peterson on
argusy pretended :
> I'm trying to open a jpg file, find the position of "FF C0 00 01 08" and get
> the next four bytes of info. (width and height of said jpg)

I've opened a couple of JPGs, and none of them seem to have that
signature in them. Are you sure that's what you want to look for?

At any rate, I was pretty surprised about how little known the InstrB
functionality was for scanning byte arrays, so I thought this would be
a good thing to throw out in a column sometime. I haven't seen anyone
else post a working snippet for the thread, so here's a very simple and
quick preview of what may show up at VSM Online one of these days...

Public Sub Main()
Dim Buffer() As Byte
Dim Search() As Byte
Dim Found As Long
Const jpg As String = "D:\Images\Projects\freeways\city01.jpg"

If ReadFileB(jpg, Buffer()) Then
If ReadHexBytes("4A464946", Search) Then
Found = InStrB(Buffer, Search)
' This is a one-based offset, so we need to correct
' for using zero-based arrays.
Found = Found - 1
If Found >= 0 Then
Debug.Print "Found byte pattern at offset:"; Found
Else
Debug.Print "Byte pattern not found."
End If
End If
End If
End Sub

Does anyone have a more elegant way to bust a string of hex bytes down
into a byte array? Putting together the following routine was actually
half the purpose of going through this exercise of me. It seems I
routinely want to do something like this, but never took the time to
make it a standalone function. (Waiting for Rick's won-liner. <g>)

Private Function ReadHexBytes(ByVal HexValues As String, Data() As
Byte) As Boolean
Dim i As Long, n As Long
n = Len(HexValues)
' Input string must be a multiple of two chars.
If (n > 0) And (n Mod 2 = 0) Then
ReDim Data(0 To n \ 2 - 1) As Byte
For i = 0 To UBound(Data)
Data(i) = Val("&h" & Mid$(HexValues, i * 2 + 1, 2))
Next i
ReadHexBytes = True
End If
End Function

And then there's just the standard slurp of an entire file into a JPG.
Actually, taking Larry's idea, it might be kind of fun to modify this
so that it would (optionally) return a segment of the file starting at
a given offset?

Private Function ReadFileB(ByVal FileName As String, Data() As Byte)
As Boolean
Dim hFile As Long
On Error GoTo Hell
hFile = FreeFile
Open FileName For Binary As #hFile
ReDim Data(0 To LOF(hFile) - 1) As Byte
Get #hFile, , Data
Close #hFile
Hell:
ReadFileB = Not CBool(Err.Number)
End Function

There ya go...

--
..NET: It's About Trust!
http://vfred.mvps.org


From: Larry Serflaten on

"Karl E. Peterson" <karl(a)exmvps.org> wrote
> argusy pretended :
> > I'm trying to open a jpg file, find the position of "FF C0 00 01 08" and get
> > the next four bytes of info. (width and height of said jpg)
>
> I've opened a couple of JPGs, and none of them seem to have that
> signature in them. Are you sure that's what you want to look for?

I think he just wanted the first occurance of "FF C0"
(maybe not, but that's what worked for me....)


> At any rate, I was pretty surprised about how little known the InstrB
> functionality was for scanning byte arrays, so I thought this would be
> a good thing to throw out in a column sometime. I haven't seen anyone
> else post a working snippet for the thread, so here's a very simple and
> quick preview of what may show up at VSM Online one of these days...
<snipped>

I understood it as being something like this:

Private Sub Form_Load()
Dim buf() As Byte
Dim fnd() As Byte
Dim rst() As Byte
Dim pos As Long
Const FILE = "D:\temp\testimage.jpg"

' Get file data
ReDim buf(0 To 4095)
Open FILE For Binary As 1
Get #1, , buf
Close 1

' Find marker
fnd = ChrW(&HC0FF)
pos = InStrB(1, buf, fnd, vbBinaryCompare)

If pos > 0 Then
' Print size
rst = MidB(buf, pos + 5, 4)
Debug.Print "File:", FILE
Debug.Print "Size: ", rst(2) * 256& + rst(3); "x"; rst(0) * 256& + rst(1)
End If

End Sub



> Does anyone have a more elegant way to bust a string of hex bytes down
> into a byte array?

For me, it depends on the number of bytes desired. For a predetermined
constant value you can use the Chr, ChrW, or if you stuff them all into some
longer string; StrConv. But for a general purpose routine, I'd go with something
like this:

Function ByteArray(ParamArray Data()) As Variant
Dim D() As Byte
Dim ub As Long, i As Long

ub = UBound(Data)
If ub >= 0 Then
ReDim D(0 To ub)
For i = 0 To ub
D(i) = Data(i) And 255
Next
End If
ByteArray = D

End Function


Mind you that will choke if you send it string data, but you get the idea....

Note that the returned array will also work in the search routine above,
specifically, the line to assign the search argument could be:

fnd = ByteArray(&HFF, &HC0)

FWIW...
LFS


From: Schmidt on

"Schmidt" <sss(a)online.de> schrieb im Newsbeitrag
news:ewQDQxnoKHA.3948(a)TK2MSFTNGP06.phx.gbl...

Sorry, the code needs a small change with regards to
"LBound-Awareness" of the passed BFind()-Array:

Please serach for this sequence in the Class...

'**** brute-force loops for very short find-sequences (<= 2Chars)
If FndLen <= 2 Then
If Comp = vbBinaryCompare Then
Char = BFind(0)
If FndLen = 2 Then Char2 = BFind(1)
Else
Char = LCaseLUT(BFind(0))
If FndLen = 2 Then Char2 = LCaseLUT(BFind(1))
End If

And change it to:

'**** brute-force loops for very short find-sequences (<= 2Chars)
If FndLen <= 2 Then
Char = BFind(LBound(BFind))
If FndLen = 2 Then Char2 = BFind(LBound(BFind) + 1)

If Comp <> vbBinaryCompare Then
Char = LCaseLUT(Char)
Char2 = LCaseLUT(Char2)
End If

That will ensure, that the BFind-Array-Param can be used
with LBounds, different from Zero - this patch is relevant only
for BFind-Length' <=2 (in the BruteForce-Scanning-part
of the Function).

The Boyer-Moore-Section is already correctly covered
regarding the "BFind-LBounds", since in this section an
appropriate copy-over from BFind into a ZeroBound-Array
(BF) is done beforehand.


Olaf


From: Karl E. Peterson on
Larry Serflaten explained :
> "Karl E. Peterson" <karl(a)exmvps.org> wrote
>> argusy pretended :
>>> I'm trying to open a jpg file, find the position of "FF C0 00 01 08" and
>>> get the next four bytes of info. (width and height of said jpg)
>>
>> I've opened a couple of JPGs, and none of them seem to have that
>> signature in them. Are you sure that's what you want to look for?
>
> I think he just wanted the first occurance of "FF C0"
> (maybe not, but that's what worked for me....)

I dunno. I trusted Mike's implementation of JpgInfo when I needed to
pick those headers apart. Worked like a charm. This problem just
interested me from a more generic perspective, as I realized how few
folks were aware of the byte array scanning available with InstrB.

>> At any rate, I was pretty surprised about how little known the InstrB
>> functionality was for scanning byte arrays, so I thought this would be
>> a good thing to throw out in a column sometime. I haven't seen anyone
>> else post a working snippet for the thread, so here's a very simple and
>> quick preview of what may show up at VSM Online one of these days...
> <snipped>
>
> I understood it as being something like this:
>
> Private Sub Form_Load()
> Dim buf() As Byte
> Dim fnd() As Byte
> Dim rst() As Byte
> Dim pos As Long
> Const FILE = "D:\temp\testimage.jpg"
>
> ' Get file data
> ReDim buf(0 To 4095)
> Open FILE For Binary As 1
> Get #1, , buf
> Close 1
>
> ' Find marker
> fnd = ChrW(&HC0FF)
> pos = InStrB(1, buf, fnd, vbBinaryCompare)
>
> If pos > 0 Then
> ' Print size
> rst = MidB(buf, pos + 5, 4)
> Debug.Print "File:", FILE
> Debug.Print "Size: ", rst(2) * 256& + rst(3); "x"; rst(0) * 256& +
> rst(1) End If
>
> End Sub

Yeah, that's a specific implmentation.

>> Does anyone have a more elegant way to bust a string of hex bytes down
>> into a byte array?
>
> For me, it depends on the number of bytes desired. For a predetermined
> constant value you can use the Chr, ChrW, or if you stuff them all into some
> longer string; StrConv. But for a general purpose routine, I'd go with
> something like this:
>
> Function ByteArray(ParamArray Data()) As Variant
> Dim D() As Byte
> Dim ub As Long, i As Long
>
> ub = UBound(Data)
> If ub >= 0 Then
> ReDim D(0 To ub)
> For i = 0 To ub
> D(i) = Data(i) And 255
> Next
> End If
> ByteArray = D
>
> End Function
>
>
> Mind you that will choke if you send it string data, but you get the idea....

Not a bad idea! It's more typing, which folks always seem to want to
avoid <g>, of course. Certainly more efficient, but that's unlikely to
be a concern for something of this nature. I dunno why, but so often I
overlook the ParamArray solutions. I'll have to think about that as
another option. One nice thing about it is, the inputs wouldn't *have*
to be hex. Yeah, a lot to recommend that.

> Note that the returned array will also work in the search routine above,
> specifically, the line to assign the search argument could be:
>
> fnd = ByteArray(&HFF, &HC0)

I like! :-)

--
..NET: It's About Trust!
http://vfred.mvps.org


First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5
Prev: Linux
Next: The BIG Picture (VB vs the OS)