binary string question

D

Dan Jones

Hello,

I'm trying to figure out how to get bit operators to work on a binary
string. This is what I'm trying to do:

list(frame) #where frame is a binary string
y = frame[x] << 8

It gives me a TypeError. Whats the best way to get around that? I think
the struct module may be what I'm looking for, if so could someone give
me an example? Also, is there a better way to be able to access
individual bytes than converting the string to a list?

Thanks,

Dan Jones
 
B

Ben Finney

You can access an individual byte simply by indexing the string

It's possible the original poster is asking (ambiguously) about treating
a string consisting of '0' and '1' digits, as a binary number.
 
A

Alex Martelli

Dan said:
Hello,

I'm trying to figure out how to get bit operators to work on a binary
string. This is what I'm trying to do:

list(frame) #where frame is a binary string
y = frame[x] << 8

It gives me a TypeError. Whats the best way to get around that? I think
the struct module may be what I'm looking for, if so could someone give
me an example? Also, is there a better way to be able to access
individual bytes than converting the string to a list?

You can access an individual byte simply by indexing the string -- for
any string x, x[0] is the first byte, x[1] the second one, and so on. As
to what you mean by "shifting by 8 bits", I dunno -- just slice with
x[1:] is what you perhaps may mean...? For N bits where N is not a
multiple of 8 you have a serious problem, probably best met with
extension module gmpy if performance is important.


Alex
 
P

Peter Hansen

Dan said:
I'm trying to figure out how to get bit operators to work on a binary
string. This is what I'm trying to do:

list(frame) #where frame is a binary string
y = frame[x] << 8

You don't describe what you want this to do. How about an example, showing
input and desired output?
It gives me a TypeError. Whats the best way to get around that? I think
the struct module may be what I'm looking for, if so could someone give
me an example? Also, is there a better way to be able to access
individual bytes than converting the string to a list?

Yes, use an array (see the module by that name).

On the other hand, depending on what you really want, the answer might
be as simple as taking your string and skipping the first element.
After all, shifting each byte in a long sequence to the left by 8 bits
is pretty much synonymous with that approach:

out = in[1:] + '\x00'

But I suspect that's not really what you meant. Please explain.

-Peter
 
A

Alexander Schmolck

Dan Jones said:
Hello,

I'm trying to figure out how to get bit operators to work on a binary
string.

More below, but are you sure you really need to do this?
This is what I'm trying to do:

list(frame) #where frame is a binary string

This has no effect (apart from wasting ressources). You create a new list from
the string frame, but don't use it any further. You presumably intended

frame = list(frame)
y = frame[x] << 8

It gives me a TypeError. Whats the best way to get around that?

Well see below (not that I can see how rightshifting by 8 is going to make
much sense if you want to treat a string as collection of bytes).
I think the struct module may be what I'm looking for,

You want to treat each item in the string the same, right? In that case use
array.
if so could someone give me an example?

Here you go:
import array
frame = "abcde"
frameAsArray = array.array('b', frame)
frameAsArray[0] >>= 1
frameAsArray.tostring()
'0bcde'

Also, is there a better way to be able to access individual bytes than
converting the string to a list?

see above

'as
 
A

Alex Martelli

Ben said:
It's possible the original poster is asking (ambiguously) about treating
a string consisting of '0' and '1' digits, as a binary number.

oh, then:

x = long(thestringof0sand1s, 2)

might work, but to access individual bits, bytes, etc, you need masks and
shifts.


Alex
 
D

Dan Jones

Dan said:
I'm trying to figure out how to get bit operators to work on a binary
string. This is what I'm trying to do:

list(frame) #where frame is a binary string
y = frame[x] << 8

You don't describe what you want this to do. How about an example, showing
input and desired output?
It gives me a TypeError. Whats the best way to get around that? I think
the struct module may be what I'm looking for, if so could someone give
me an example? Also, is there a better way to be able to access
individual bytes than converting the string to a list?

Yes, use an array (see the module by that name).

On the other hand, depending on what you really want, the answer might
be as simple as taking your string and skipping the first element.
After all, shifting each byte in a long sequence to the left by 8 bits
is pretty much synonymous with that approach:

out = in[1:] + '\x00'

But I suspect that's not really what you meant. Please explain.

-Peter

Sorry, I should have included more information. I'm trying to write a
webcam app to grab and display images off a Philips (pwc) camera in
Linux. What I have so far is based on the mini-tv.py demo in the pyv4l
module. It will work with RGB output such as from a tv tuner card but
the Philips cameras use a different color palette. I found a C function
that converts the YUV420P color palette to RGB, and I'm trying to
convert it to python. The binary string in question is the image data
for one frame of video. To display it, I'm using PIL's
Image.fromstring() and tkinter.

I don't know much C at all and am fairly new to python as well, but I'll
post what I have so far.


Here's the C version:

static void ccvt_420p(int width, int height, const unsigned char *src,
unsigned char *dst, int push)
{
int line, col, linewidth;
int y, u, v, yy, vr, ug, vg, ub;
int r, g, b;
const unsigned char *py, *pu, *pv;

linewidth = width >> 1;
py = src;
pu = py + (width * height);
pv = pu + (width * height) / 4;

y = *py++;
yy = y << 8;
u = *pu - 128;
ug = 88 * u;
ub = 454 * u;
v = *pv - 128;
vg = 183 * v;
vr = 359 * v;

for (line = 0; line < height; line++) {
for (col = 0; col < width; col++) {
r = (yy + vr) >> 8;
g = (yy - ug - vg) >> 8;
b = (yy + ub ) >> 8;

if (r < 0) r = 0;
if (r > 255) r = 255;
if (g < 0) g = 0;
if (g > 255) g = 255;
if (b < 0) b = 0;
if (b > 255) b = 255;

switch(push) {
case PUSH_RGB24:
*dst++ = r;
*dst++ = g;
*dst++ = b;
break;

case PUSH_BGR24:
*dst++ = b;
*dst++ = g;
*dst++ = r;
break;

case PUSH_RGB32:
*dst++ = r;
*dst++ = g;
*dst++ = b;
*dst++ = 0;
break;

case PUSH_BGR32:
*dst++ = b;
*dst++ = g;
*dst++ = r;
*dst++ = 0;
break;
}

y = *py++;
yy = y << 8;
if (col & 1) {
pu++;
pv++;

u = *pu - 128;
ug = 88 * u;
ub = 454 * u;
v = *pv - 128;
vg = 183 * v;
vr = 359 * v;
}
} /* ..for col */
if ((line & 1) == 0) { // even line: rewind
pu -= linewidth;
pv -= linewidth;
}
} /* ..for line */
}

void ccvt_420p_rgb24(int width, int height, const void *src, void *dst)
{
ccvt_420p(width, height, (const unsigned char *)src, (unsigned
char *)dst, PUSH_RGB24);
}

#########################

And here's what I have so far:


def yuv420p_to_rgb24(WIDTH, HEIGHT, source):
line, col, linewidth = 0,0,0
y,u,v,yy,vr,ug,vg,ub = 0,0,0,0,0,0,0,0
r,g,b = 0,0,0
linewidth = WIDTH >> 1
sourceframe = list(source)
py = 0
pu = py + (WIDTH * HEIGHT)
pv = pu + (WIDTH * HEIGHT) / 4
destination = []
destindex = 0

y = sourceframe[py]
py += 1
int(y)
yy = y << 8 # This is where it blows up
u = sourceframe[pu] - 128
ug = 88 * u
ub = 454 * u
v = sourceframe[pv] - 128
vg = 183 * v
vr = 359 * v

line = 0
while (line < HEIGHT):
col = 0
while (col < WIDTH):
r = (yy + vr) >> 8
g = (yy - ug - vg) >> 8
b = (yy + ub ) >> 8

if (r < 0):
r = 0
if (r > 255):
r = 255
if (g < 0):
g = 0
if (g > 255):
g = 255
if (b < 0):
b = 0
if (b > 255):
b = 255

destination[destindex] = r
destindex += 1
destination[destindex] = g
destindex += 1
destination[destindex] = b
destindex += 1

y = sourceframe[py]
py += 1
yy = y << 8
if (col & 1):
pu += 1
pv += 1
u = sourceframe[pu] - 128
ug = 88 * u
ub = 454 * u
v = sourceframe[pv] - 128
vg = 183 * v
vr = 359 * v

col += 1
#end while col

if ((line % 1) == 0): # even line: rewind
pu -= linewidth
pv -= linewidth

line += 1
#end while line
return destination
 
A

Andrew Henshaw

Dan said:
Hello,

I'm trying to figure out how to get bit operators to work on a binary
string. This is what I'm trying to do:

list(frame) #where frame is a binary string
y = frame[x] << 8

It gives me a TypeError. Whats the best way to get around that? I think
the struct module may be what I'm looking for, if so could someone give
me an example? Also, is there a better way to be able to access
individual bytes than converting the string to a list?

Thanks,

Dan Jones

The other responses address your overall requirements (e.g. use the array
module); but, it looks like you may also need a pointer on this specific
question. It appears that you have a string of octets (perhaps from
reading a "binary" file) and you want to be able to perform arithmetic
operations on an individual octet. To do so, use 'ord'. For example,
130
 
P

Peter Abel

....
....
....
static void ccvt_420p(int width, int height, const unsigned char *src,
unsigned char *dst, int push)
{
int line, col, linewidth;
int y, u, v, yy, vr, ug, vg, ub;
int r, g, b;
const unsigned char *py, *pu, *pv;

linewidth = width >> 1;
py = src;
pu = py + (width * height);
pv = pu + (width * height) / 4;

y = *py++;

I guess here you're using char as int.
yy = y << 8;
u = *pu - 128; ....
....
....
for (line = 0; line < height; line++) {
for (col = 0; col < width; col++) {
r = (yy + vr) >> 8;
g = (yy - ug - vg) >> 8;
b = (yy + ub ) >> 8;
....
....
....
And here's what I have so far:


def yuv420p_to_rgb24(WIDTH, HEIGHT, source):
line, col, linewidth = 0,0,0
y,u,v,yy,vr,ug,vg,ub = 0,0,0,0,0,0,0,0
r,g,b = 0,0,0
linewidth = WIDTH >> 1

To do the same in pyhton ...
sourceframe = list(source)
... use sourceframe = map(ord,source) instead !!


py = 0
pu = py + (WIDTH * HEIGHT)
pv = pu + (WIDTH * HEIGHT) / 4
destination = []
destindex = 0
!!!! *y* becomes an int because *sourceframe* is a list of ints !!!!
y = sourceframe[py]
py += 1

*********The following line has no effect**********************
***************************************************************

!!!! Now *y* is an int and can be shifted !!!!
yy = y << 8 # This is where it blows up

....
....
....

Regards
Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,169
Messages
2,570,920
Members
47,464
Latest member
Bobbylenly

Latest Threads

Top