How can I get a pixel color?

Anything QL Software or Programming Related.
User avatar
pjw
QL Wafer Drive
Posts: 1626
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: How can I get a pixel color?

Post by pjw »

BSJR wrote: Sun Nov 06, 2022 1:45 pm <>This is not entirely true.
When in mode 32: COLOUR_NATIVE: PAPER $1F: CLS: gives bleu, :PAPER $F800: then gives red as in rrrrrggg.gggbbbbb.
Only in PIC and SPR files are the bytes reversed as in a 16-bit BMP.
I think its the other way, Bob. Did you actually try PIXEL32%? Add the following few lines to have a go:

Code: Select all

10 CLS: CLS#2
12 FOR c = 0 TO 7
14  COLOUR_QL: BLOCK#2; 50, 50, 0, 0, c
16  c% = PIXEL32%(2, 1)
18  COLOUR_NATIVE: BLOCK 50, 50, 0, 0, c%
20  PAUSE
22 END FOR c
24 :
Try the same with the not-byte-swapped PIXEL33%


Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
User avatar
BSJR
Trump Card
Posts: 222
Joined: Sun Oct 18, 2015 12:53 pm
Location: Amsterdam
Contact:

Re: How can I get a pixel color?

Post by BSJR »

pjw wrote: Sun Nov 06, 2022 2:54 pm
BSJR wrote: Sun Nov 06, 2022 1:45 pm <>This is not entirely true.
When in mode 32: COLOUR_NATIVE: PAPER $1F: CLS: gives bleu, :PAPER $F800: then gives red as in rrrrrggg.gggbbbbb.
Only in PIC and SPR files are the bytes reversed as in a 16-bit BMP.
I think its the other way, Bob. Did you actually try PIXEL32%? Add the following few lines to have a go:
I have not tried Dilwyn's S*Basic function but your own RPIX% which confirms what QCP also told me.
: COLOUR_QL: PAPER #1,4: CLS
: PRINT HEX$(RPIX%(#1,2,2),16)
This gets me a green window on my m32 QPC2 and returns $07C0, as in 'rrrrrGGG.GGGbbbbb'.
'GGGbbbbb.rrrrrGGG' would have returned $C007, a dark red.

BSJR


User avatar
dilwyn
Mr QL
Posts: 3114
Joined: Wed Dec 01, 2010 10:39 pm

Re: How can I get a pixel color?

Post by dilwyn »

Basically, what we need is to sort out whether the byte-reversed Pixel32% is correct, or that the original one (similar to the Mode 33 version) is correct.

I haven't got a mode 33 display system to compare the results, I'm afraid (although I could probably try to persuade QemuLator to use its Q60 display, I don't know how it handles the endian on Intel systems for display purposes). Equally, I don't know if SMSQ/E on mode 32 systems detects the byte order and transparently reverses them so that byte reversal is unnecessary (ironically this would make both Per and Bob's answers correct in a way!).

It's be interesting, for example, to compare a PEEK_W of a colour word with two PEEKs of the consecutive addresses to see what's going on, might do that when I'm back later.

This gets more and more interesting the more we look at it (enters geek mode) :ugeek:

Once we get a definitive answer, I'll ensure that the Pixelxx% are amended accordingly and make them available from my website for all to use.


User avatar
pjw
QL Wafer Drive
Posts: 1626
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: How can I get a pixel color?

Post by pjw »

I dont know if I have the proper vocabulary for this, but heres how I
understand it:

In mode 32 the formal colour designation is of the form

1. rrrrrggggggbbbbb

in other words, 5 bits red, 6 bits green and 5 bits blue. See Tony Tebby's
GD2-V2.doc rev. 28.05.2001. So this is how you present the colours to the
driver in NATIVE mode.

COLOUR_NATIVE: CLS#2
BLOCK#2; 60, 10, 10, 0, %1111100000000000
BLOCK#2; 60, 10, 10, 10, %0000111111000000
BLOCK#2; 60, 10, 10, 20, %0000000000011111

would produce red, green and blue stripes, as expected.

However, presumably for technical reasons, as Intel-like machines operate
internally with Little-endian numbers, the system switches the bytes
around. For the same reason the sprite and PICture format maintain the
colour information in this internal format, ie:

2. gggbbbbbrrrrrggg

See the SMSQ/E documentation dev8_extras_doc_display_txt.

So values fetched from within the system, eg off the screen as PIXEL32%
and RPIX% do or from the driver as my GETCOL% does, get the Little-endian
(2) version of the colour code, and so to be able to give that back to the
system in the form of INK, PAPER, BLOCK, etc colours they must be switched
to Big-endian (1). However, to use those colour codes to produce sprites or
PICtures, they have to be switched back again! - Or simply left in their
internal, Little-endian state, as you do when you create a screen dump
or a PICture.

It MIGHT have been simpler (at least for us punters) to have just
designated (2) as the formal colour code format, but we are where we are.
I presume the implementers had their reasons.

Mode 33 has quirks too - nothing quite like this, though, but thats another
story.


Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
User avatar
dilwyn
Mr QL
Posts: 3114
Joined: Wed Dec 01, 2010 10:39 pm

Re: How can I get a pixel color?

Post by dilwyn »

So in relaity it doesn't matter too much as long as you manage to remember and work out where the red, green and blue bits of the colours are! I remember this causing me brain aches when it came to working out the mode conversions in programs like BMP! Luckily, Bob sorted out any bugs in that one.

Going through this step by step to see the results in practice for mode 32:

RED. Write a red pixel (INK 2) to the screen. The colour word reads as follows:
PEEK_W the address of this pixel gives 248, binary 0000 0000 1111 1000. PEEK the lower address gives 0 (half the nil green plus the nil blue component GGGBBBBB) and PEEK the higher address gives 0, the red component and the other half of the green RRRRRGGG.

GREEN. Write a green pixel (INK 4) to the screen. The colour word reads back as follows:
PEEK_W the address of this pixel gives -16377, binary 1100 0000 0000 0111. PEEK the lower address gives 192 (half the green and the nil blue component GGGBBBBB) and PEEK the higher address gives 7, the nil red component and the other half of the green RRRRRGGG.

BLUE. Write a blue pixel (INK 1) to the screen. The colour word reads back as follows:
PEEK_W the address of this pixel gives 7936, binary 0001 1111 0000 0000. PEEK the lower address gives 31 (nil green and the 5 blue bits) and PEEK the higher address gives 0, nil red and nil green in the RRRRRGGG bits.

So as long as you know where the red, green and blue bits are, you can work out where and how do your own calculations when you want to manipulate the colours.

If you PEEK_W a mode 32 display you get GGGBBBBB RRRRRGGG which is byte reversed according to the docs. Byte reversing this gives you RRRRRGGGGGGBBBBB as Per says, and this makes it a bit easier to handle since the 6 green bits are now together and easier to handle and do calculations with.

So both approaches can be correct, it becomes a question of whether we want to end up with bits in order, or in the form they are stored. Maybe the answer as far as my functions are concerned is to simply PEEK_W the value in mode 32 (like PIXEL33%) but provide a byte-reversal routine for where the order of the two bytes is important. I think I'll do that and document with the functions why the byte reversal may or may not be important, depending on what you want to do.

My brain hurts.


User avatar
dilwyn
Mr QL
Posts: 3114
Joined: Wed Dec 01, 2010 10:39 pm

Re: How can I get a pixel color?

Post by dilwyn »

So, through an international collaboration between Norway, The Netherlands and Wales, we seem to have got to here, where I have the "compromise" solution to reading colours from the screen.

For Mode 32 (QPC2, QXL, etc) we have two functions. PIXEL32% just reads the colour word for a pixel from the screen memory, while PIXEL32_REV% returns the colour word value byte reversed as Per has explained.

If we're OK with this now, I'll write a very short text to go with this and put it on my website.

Thanks everyone.

Code: Select all

1000 DEFine PROCedure ScreenDetails
1010   REMark QDOS ROM defaults
1020   screenbase = 131072 : REMark base address of screen
1030   screenllen = 128    : REMark screen line width in bytes
1040   IF VER$ = 'HBA' THEN
1050     REMark use SBASIC functions on hires systems
1060     screenbase = SCR_BASE
1070     screenllen = SCR_LLEN
1080   END IF
1090 END DEFine ScreenDetails
1100 :
1110 DEFine FuNction PIXEL4%(x,y)
1120   LOCal screenbase,screenllen,pixel,word,green,red,addr
1130   ScreenDetails
1140   pixel = 7-(x MOD 8) : REMark pixel number across colour byte
1150   word  = 2*(x DIV 8)
1160   addr  = screenbase+(y*screenllen)+word
1170   green = 4*((PEEK(addr)&&(2^pixel))<>0)
1180   red   = 2*((PEEK(addr+1)&&(2^pixel))<>0)
1190   RETurn green+red+(green<>0 AND red<>0) : REMark 4+2->7 for white
1200 END DEFine PIXEL4%
1210 :
1220 DEFine FuNction PIXEL8%(x,y)
1230   LOCal screenbase,screenllen,pixel,word,green,red,blue,addr
1240   ScreenDetails
1250   pixel = 7-((x&&254) MOD 8) : REMark pixel number across colour byte
1260   word  = 2*(x DIV 8)
1270   addr  = screenbase+(y*screenllen)+word
1280   green = 4*((PEEK(addr)&&(2^pixel))<>0)
1290   red   = 2*((PEEK(addr+1)&&(2^pixel))<>0)
1300   blue  = (PEEK(addr+1)&&(2^(pixel-1)))<>0
1310   RETurn green+red+blue
1320 END DEFine PIXEL8%
1330 :
1340 DEFine FuNction PIXEL16%(x,y)
1350   REMark returns value of MODE 16 (256 colour) pixel from screen
1360   ScreenDetails
1370   RETurn PEEK(screenbase+(y*screenllen)+x)
1380 END DEFine PIXEL16%
1390 :
1400 DEFine FuNction PIXEL32%(x,y)
1410   ScreenDetails
1420   REMark returns MODE 32 colour as GGGBBBBB RRRRRGGG as stored in memory
1430   RETurn PEEK_W(screenbase+(y*screenllen)+(2*x))
1440 END DEFine PIXEL32%
1450 :
1460 DEFine FuNction PIXEL32_REV%(x,y)
1470   LOCal addr,word
1480   ScreenDetails
1490   addr = screenbase+(y*screenllen)+(2*x)
1500   REMark byte reverse MODE 32 systems
1510   REMark to get RRRRRGGG GGGBBBBB
1520   word = PEEK(addr+1)*256 + PEEK(addr)
1530   IF word > 32767 THEN word = word-65536
1540   RETurn word
1550 END DEFine PIXEL32_REV%
1560 :
1570 DEFine FuNction PIXEL33%(x,y)
1580   REMark return value of mode 33 pixel
1590   ScreenDetails
1600   REMark colour is GGGGGRRR RRBBBBBW
1610   RETurn PEEK_W(screenbase+(y*screenllen)+(2*x))
1620 END DEFine PIXEL33%


User avatar
pjw
QL Wafer Drive
Posts: 1626
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: How can I get a pixel color?

Post by pjw »

Not sure I agree with the premise, Dilwyn. The reversed values are the Little-endian, internal ones. The "design format" is rrrrrggggggbbbbb! It is this format to use for setting colour values in INK, PAPER, BLOCK and the like, so that is the value Id expect to get when I use PIXEL32%.. I think doing it the other way will just propagate the confusion.

The Endian issue is one of the reasons I love 68 and hate 86! Little-endian is designed by engineers for machines, not for people. People like 1234 (one thousand two hundred and thirty four). Why should we write it, or even have to think of it as 3412?

Anyway, do as you please.

BTW the 3 last functions in the code above are all missing the x, y parameters.


Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
User avatar
dilwyn
Mr QL
Posts: 3114
Joined: Wed Dec 01, 2010 10:39 pm

Re: How can I get a pixel color?

Post by dilwyn »

FFS, why did I get into opening this can of worms in the first place? :cry:

(I'm sure there's a variation of Murphy's Law in there somewhere, about the only way of closing a can of worms is to use a larger can?)

Anyway, fixed, thanks Per. That'll teach me not to be lazy and do an actual file transfer or copy and paste rather than just retyping something :?

As Per says, use the byte reversed function unless you really need to work with the straight PEEK_W value in MODE 32 for some unknown reason.


User avatar
pjw
QL Wafer Drive
Posts: 1626
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: How can I get a pixel color?

Post by pjw »

dilwyn wrote: Mon Nov 07, 2022 11:06 pm FFS, why did I get into opening this can of worms in the first place? :cry: <>
No good deed goes unpunished ;)


Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
User avatar
dilwyn
Mr QL
Posts: 3114
Joined: Wed Dec 01, 2010 10:39 pm

Re: How can I get a pixel color?

Post by dilwyn »

pjw wrote: Tue Nov 08, 2022 1:06 pm
dilwyn wrote: Mon Nov 07, 2022 11:06 pm FFS, why did I get into opening this can of worms in the first place? :cry: <>
No good deed goes unpunished ;)
He he, good job Per Witte was around to clear up my mess :oops:


Post Reply