Page 1 of 1

_PIC Format

Posted: Wed Feb 19, 2014 10:23 am
by RWAP
Hmm - does anyone have a quick précis of the format for a QL picture stored in the _PIC format ?

I know there is a header which basically stores the height and width of the saved area, and the top left x and y co-ordinate (possibly). But I can't find the information anywhere!

Has this ever been updated to take account of the higher resolution / higher colour drivers?

Re: _PIC Format

Posted: Wed Feb 19, 2014 2:05 pm
by Mr_Navigator
I'd be happy with the original QL, something that converts 256x256 8 colour BMP/PNG etc in to a format I can load in to a standard QL screen as a loading screen or graphic, much like the Spectrum did and also how Talent did. I want to create the graphics off QL and then load in to QL.

I have tried many off Dilwyn's site to no avail.

Re: _PIC Format

Posted: Wed Feb 19, 2014 3:22 pm
by dilwyn
PIC File Format - slightly modified version from my website at http://www.dilwyn.me.uk/docs/formats/index.html. It's a few years old and so if you spot anything out of date in it, let me know so I can update what's on my website!

This article is best viewed in a fixed pitch font.

Dilwyn

Code: Select all

PARTIAL AREA SAVES, OR PIC FILES

This article uses information kindly supplied by George Gwilt, and information from Tony Tebby's GD2 documents. Note that this applies to Tony Tebby-style PIC files. A variation used by George Gwilt, PSA files, has an extra 4 bytes flag at the start of the file, before the header block, making the header area 14 bytes long instead of 10 for conventional PIC files.

The format of a Partial Save Area file is shown in the table below:

+--------+-----------+--------+-----------------------------+
| OFFSET | FUNCTION  | LENGTH | DESCRIPTION                 |
+--------+-----------+--------+-----------------------------+
| 0      | Flag      | Word   | $4AFC - identification flag |
| 2      | X_size    | Word   | Width in pixels             |
| 4      | Y_size    | Word   | Height in pixels            |
| 6      | Increment | Word   | Length of one line in bytes |
| 8      | Mode      | Byte   | Mode of saved image         |
| 9      | Spare     | Byte   | zero                        |
|        |           |                                      |
| 10     | Image     | Increment*Y_size bytes               |
+--------+--------------------------------------------------+

The "Image" is simply the exact copy of the part of the screen which is saved. If the mode is 33 (as for the Q40/60 extended colours) each pixel is a word or 32 (QXL/QPC2/SMSQmulator) each pixel is also a word. If the mode is 16 (256 colour mode on Aurora or QPC2 mode 16) each pixel is a byte value. For mode 4 each word contains 8 pixels. For mode 8, each word contains 4 actual pixels, or the equivalent of 8 pixel co-ordinates if using the 512-pixel across co-ordinate system across. See the Concepts section of the QL user guide for further details of mode 4 and 8.

The image part is preceded by the 10 byte header or preamble as shown in the table above.

The extension _pic is often used for filenames for these partial area saves. In fact, if you look in the Easyptr manual, under the WSAIN and related commands (L_WSA, S_WSA, WSASV, WSARS) it documents this file format and provides a set of BASIC extensions to handle these in memory (save and restore areas) and to save and load to/from file.

To construct a buffer in the common heap to hold an area ready to save as a file you need to define the size of the area to hold the image and add the 10 byte header described above.

For mode 4 and 8, each line of graphics will require the number of pixels divided by 4 and rounded up to the nearest word, but beware of a potential trap in that 4 pixels neeeds two bytes, not one, to hold them! (Round up the width in mode 4 or 8 to a multiple of eight pixels to ensure that you get the right number of bytes, the graphics work in multiples of two bytes across, e.g. one odd pixel needs a full word)

saved_line_width=((pixel_width+7) DIV 8)*2

Obviously, these files are easier to handle if they are saved from a word aligned origin, in other words a multiple of 8 pixels across, to avoid the need to either round down to such a location or rotate the pixels to such locations. In truth, you are best advised to use operating facilities provided in pointer environment systems to save areas and so on, this would (in theory) ensure your programs work on all systems current and future. In practice, this may not be possible if you are working in BASIC and no access to suitable routines for example.

I've been using these routines for a while. Assuming no typos during writing this article, these routines go by the theory concerned, so stand a good chance of working on most systems at least. Even if they don't work on a given platform, the theory is still provided so should provide a theory base for you to work from at the very least.

For mode 16 (256 colour mode, simply one byte per pixel across.

For mode 32 and 33 and any other future modes where a word holds the pixel colour value, the line width will be 2*pixel_width bytes

So, this formula will calculate the area needed:

10+(((pixel_width+7) DIV 8)*2)*pixel_height

To copy screen memory into this area you'll need to know the line increment value of the video screen on your system (a number of toolkits provide such a function, e.g. the display_cde functions published in QL Today and in the DISPLAY directory) extract it from the screen channel defintiion block if using assembler or a BASIC extension able to read the channel definition block values) and how to calculate the address of the origin of the saved area on the screen:

sd_linel on on version JS or later machines provides the line length in bytes. On version JM, AH or earlier ROMs you'll have to assume it's 128 bytes.

I'll assume in this case you're using DISPLAY_CDE to save an area w pixels wide, h pixels high, with the origin (top left) of the area to be saved at x pixels across and y pixels down.

LET line_length = BYTES(#0)
LET screen_base = ADDRESS(#0)
LET screen_mode = DMODE(#0)
IF screen_mode = 0 OR screen_mode = 4 OR screen_mode = 8 THEN
  LET origin = screen_base+(y*line_length)+((x DIV 8)*2)
  save_width = ((w+7)DIV 8)*2
ELSE
  LET origin = screen_base+(y*line_length)+2*x
  save_width = 2*w
END IF
base = ALCHP(10+save_width*h)
POKE_W base,HEX('4AFC')
POKE_W base+2,w
POKE_W base+4,h
REMark IMPORTANT: width contains width of area saved, not screen line width!
POKE_W base+6,save_width
POKE base+8,screen_mode
POKE base+9,0
adr_heap = base+10
adr_scrn = origin
FOR a = 0 TO h-1
  MOVEMEM adr_scrn TO adr_heap,save_width
  adr_scrn = adr_scrn + line_length
  adr_heap = adr_heap + save_width
END FOR a
REMark screen area copied to heap, now save it
SBYTES 'filename_pic',base,10+(save_width*h)
REMark release heap area used
RECHP base

Loading an area back to the screen involves the opposite of this - allocate a heap area of the same size as the pic file, LBYTES it there, calculate the origin of the screen area where it's to be 'pasted' back, set up pointers to this origin and to the image part of the file (i.e. just past the 10 byte header) and a loop FOR a = 0 TO h-1 to copy each line back to the screen, incrementing the screen address pointer by the line width between each MOVEMEM and the heap pointer address by the line width of the saved file.

For modes not described above, the number of bits per pixel is as follows (information source: GD2 docs). Not all modes actually exist in working form at the time of writing, e.g. although the Aurora is capable of working in a 16-colour mode, I have never seen drivers for that mode.

0        mono displays                 1

4        4 colour                      2
7        4 colour palette mapped       2

8        16 colour                     4
15       16 colour palette mapped      4

16       256 colour                    8
31       256 colour palette mapped     8

32       64K colour 6 bit green        16
33       64K colour 5 bit green        16

64       16m colour, 8 bit RGB         24 of 32

Re: _PIC Format

Posted: Wed Feb 19, 2014 3:23 pm
by dilwyn
Mr_Navigator wrote:I'd be happy with the original QL, something that converts 256x256 8 colour BMP/PNG etc in to a format I can load in to a standard QL screen as a loading screen or graphic, much like the Spectrum did and also how Talent did. I want to create the graphics off QL and then load in to QL.

I have tried many off Dilwyn's site to no avail.
A decent graphics program for modern systems is on my to do list for sometime in the next decade :roll:

Re: _PIC Format

Posted: Wed Feb 19, 2014 6:39 pm
by RWAP
In the meantime, you did convert a PNG image for me :) (thank you)

I had searched using Google and looking at your site, but missed that _PIC definition - maybe because it is called:

PIC Files - Some information about Area Save files.

Might be better as :

PIC Files - File information about QL screen area save files...

Re: _PIC Format

Posted: Thu Feb 20, 2014 3:54 am
by dilwyn
RWAP wrote:I had searched using Google and looking at your site, but missed that _PIC definition - maybe because it is called:
PIC Files - Some information about Area Save files.
Might be better as :
PIC Files - File information about QL screen area save files...
OK, done. I updated the file on the website to include the small amount of extra information about PIC and PSA files in my posting, and I've also added separate articles to the same page about the new sprite graphics formats in SMSQ/E version 3 and above.
http://www.dilwyn.me.uk/docs/formats/index.html