Image writing

General discussion relating to the library modules supplied with the compiler

Moderators: David Barker, Jerry Messina

Francis
Registered User
Registered User
Posts: 314
Joined: Sun Mar 25, 2007 9:40 am
Location: Devon

Image writing

Post by Francis » Sun Jul 15, 2007 7:54 pm

Hi,

I've had a run through the forum and was unable to get any help/hints with my query. It's not urgent by the way.

I am using an 18F2520 + 20MHz xtal with a KS0108 (128x64) type GLCD.
I've got it to read in a bitmap and display.

But, I'm using a bit of a clunky method to do it i.e. I've aliased a byte into bits and then sequentially use SetPixel to write each dot. Good news it works fine , but, using a bit-at-a-time it takes almost a second to display the image.

So, I was wondering if there was a method of writing a byte at a time and setting 8 dots in a single hit - if you see what I mean.

I had a look at the SetImage library but couldn't follow it and I don't know how fast it would show the image, assuming I could modify it to suit.
I appreciate a bog-standard GLCD isn't going to be superfast but I'd appreciate a pointer (or a command).

Thanks.

TimB
Posts: 262
Joined: Wed Oct 04, 2006 7:25 am
Location: London UK

Post by TimB » Mon Jul 16, 2007 7:34 am

I had a look at the SetImage library but couldn't follow it and I don't know how fast it would show the image
I would look in the samples folder for GLCD then GLCDImage and try it!

If you have any more questions come back

Francis
Registered User
Registered User
Posts: 314
Joined: Sun Mar 25, 2007 9:40 am
Location: Devon

Post by Francis » Mon Jul 16, 2007 8:32 am

Thanks Tim, I'll check it out.

Francis
Registered User
Registered User
Posts: 314
Joined: Sun Mar 25, 2007 9:40 am
Location: Devon

Post by Francis » Mon Jul 16, 2007 11:18 am

I'm afraid I couldn't get to grips with it this morning.

My data is in a 1024 byte array and I couldn't see how to translate that using SetImage or WriteImage byte.

I was just hoping to replace 8 setpixels with a write image byte * 16 across the screen, increment Y and repeat until EOD.

I'm sure the libraries do that but sadly my brain couldn't follow it.
Thanks anyway, I need an aspirin now.

TimB
Posts: 262
Joined: Wed Oct 04, 2006 7:25 am
Location: London UK

Post by TimB » Mon Jul 16, 2007 11:35 am

Can you post your data?

I will look at the conversion.

Idealy you let SF do the conversion from a bitmap or at worst you just need to add 4 bytes by hand to the header of the array so the compiler knows hey type and size of the image.

Francis
Registered User
Registered User
Posts: 314
Joined: Sun Mar 25, 2007 9:40 am
Location: Devon

Post by Francis » Mon Jul 16, 2007 12:38 pm

Thanks Tim.

Its a standard 1-bit 128x64 .bmp image.
I get one PIC to read it from a file and strip off the first 60 bytes.
Bytes 0 and 1 should be B and M. Then bytes 18 and 22 should be 128 and 64 resp for checking. The other bytes I don't want to look at.
The header lasts for 60 bytes (if I remember correctly) then its onto the actual image data.

In my app my first PIC reads the header and then sends the remaining 1024 bitmap bytes to the second PIC which is where I'm getting it to display the image. So the data it works on is simply 1024 imag bytes.

I only mention this as it may be quicker for you to make a picture in Corel Photopaint or simlar - I will send the data if it's more convenient.

At the moment my code is a clunky:-

Code: Select all

Sub PlotPicture()
   XPos = 0
   YPos = 63
   GWord = 2                                     ' Set general Byte counter to zero
   GCommand = DByte(1)
   If GCommand = 67 Then                         ' User wishes to clear GLCD first
      GLCD.Cls
      DelayMS(100)
   EndIf
   For  J = 0 To 1024 Step 16
     For I = 0 To 15      
        GBlock = DByte(GWord)             ' Read each byte into Gblock
        If Pix8 = 0 Then                         '  translate to a pixel
          GLCD.SetPixel( XPos,YPos)
          Inc (XPos)
        Else
          Inc (XPos)
        EndIf      
        If Pix7 = 0 Then                         
          GLCD.SetPixel( XPos,YPos)
          Inc (XPos)
        Else
          Inc (XPos)
        EndIf
        If Pix6 = 0 Then
          GLCD.SetPixel( XPos,YPos)
          Inc (XPos)
        Else
          Inc (XPos)
        EndIf
        If Pix5 = 0 Then
          GLCD.SetPixel( XPos,YPos)
          Inc (XPos)
        Else
          Inc (XPos)
        EndIf
        If Pix4 = 0 Then
          GLCD.SetPixel( XPos,YPos)
          Inc (XPos)
        Else
          Inc (XPos)
        EndIf
        If Pix3 = 0 Then
          GLCD.SetPixel( XPos,YPos)
          Inc (XPos)
        Else
          Inc (XPos)
        EndIf
        If Pix2 = 0 Then
          GLCD.SetPixel( XPos,YPos )
          Inc (XPos)
        Else
          Inc (XPos)
        EndIf
        If Pix1 = 0 Then
          GLCD.SetPixel( XPos,YPos)
          Inc (XPos)
        Else
          Inc (XPos)
        EndIf     
      Inc(GWord)                                            ' Increment G byte counter
     Next ' I 
     Dec (YPos)
     XPos = 0                                               ' Set X position back to zero
   Next

End Sub
//
So, you can see its not very efficient, its my first bash at this. The Pix1, Pix2 variables etc are simply bit aliased from GBlock.
Ideally, I'd like it to superimpose (which is what the above does).

TimB
Posts: 262
Joined: Wed Oct 04, 2006 7:25 am
Location: London UK

Post by TimB » Mon Jul 16, 2007 9:37 pm

Hello Francis

Sorry I do not follow exactly what your trying to achieve.

Do you have a data table your looking to put on the screen?

If so then can you post the data table, not your code. As you said it's not doing what you want. I was just looking to convert the data table so you could use the writeimage sub or a derivative of it.

User avatar
Steven
BETA Tester
Posts: 406
Joined: Tue Oct 03, 2006 8:32 pm
Location: Cumbria, UK

Post by Steven » Tue Jul 17, 2007 6:32 am

Francis - where is the image coming from? Is it being read from a bitmap file and being displayed? Is the file being sent over RS232 or from SD, or some other way? Do you need to display lots of images, or could a small number of them be converted and saved in data tables first?

Steve

Francis
Registered User
Registered User
Posts: 314
Joined: Sun Mar 25, 2007 9:40 am
Location: Devon

Post by Francis » Tue Jul 17, 2007 8:21 am

Sorry for delay Gentlmen. I appreciate hints and tips.

PIC-1 is used for SD work.
... connected serially to ...
PIC-2 which is just for graphics display.
Both are 18F2520.

So, PIC1 reads standard 128x64 1-bit mono .bmp file from SD, checks header to make sure its a 128x64 bitmap . it then strips off the rest of the header (60 bytes-ish) and sends the remaining 1kb of actual image data serially to PIC2.
PIC2 reads the 1024 bytes into an array and then displays.
There would only be one image-at-a-time.
Then a few seconds later another image would be stripped/sent/displayed.
And repeated at unknown intervals.

So, I need an unknown quantity displayed (maybe dozens) under user control rather than just a few converted as in examples.

My code currently works but is a bit slow and clunky. I just wanted to improve it, to reduce the image plotting time.(And learn a bit too).

I probably wasn't very clear in my enthusiasm to post, but what I wanted to do was replace my (Setpixel x 8 for each byte) x16 for each line with 'WriteByte' x16 for each line where the 'WriteByte' sets 8 pixels in one go.
I'm just stuck on how to write a byte which does the above and I couldn't follow the library routines.


I can't really post my data here as it would only be the 'dectostr' representation of it, and would be difficult for you to pick out unless I did it line by line.
Last edited by Francis on Tue Jul 17, 2007 8:32 am, edited 1 time in total.

TimB
Posts: 262
Joined: Wed Oct 04, 2006 7:25 am
Location: London UK

Post by TimB » Tue Jul 17, 2007 8:27 am

Ok we understand


Just for starters is there any reason you need 2 pics I see it being done in one.

But now we understand what you want we can help.

Be back later.

TimB
Posts: 262
Joined: Wed Oct 04, 2006 7:25 am
Location: London UK

Post by TimB » Tue Jul 17, 2007 9:03 am

I have another question? What format is the data stored on the SD card. Is it saved with the bytes made up of pixels on the Y axis or the X axis

Francis
Registered User
Registered User
Posts: 314
Joined: Sun Mar 25, 2007 9:40 am
Location: Devon

Post by Francis » Tue Jul 17, 2007 9:30 am

Why 2 PICs? Well, PIC1 is a permanent fixture and PIC2 pcb+GLCD is a 'plugin'. And space too.

Standard bitmap file on SD. Created by Photopaint.
PIC1 reads/checks/strips header which is 60 bytes long.
You'll see below in the notes that it should only be 51 bytes of header but there is 10 bytes of gash from somewhere.

Then the remaining 1024 bytes (i.e. the actual nitty-gritty data) is sent to PIC2 serially, where my clunky routine above writes it to GLCD.

The bitmap format is simple line-by-line.
Bytes 0 - 15 = Line1
Bytes 16 - 31 = Line 2
etc.
- starting bottom left of GLCD (Y=63)

e.g. Byte 0 :
Y=63 X=0
Pix8,Pix7,Pix6,Pix5,Pix4,Pix3,Pix2,Pix1
i.e. first 8 dots of bottom line from left to right, though it's inverted.
Bits: 76543210 76543210 - first 2 bytes starting bottom left.


So, if I could write a byte to the GLCD 'illuminating' the dots instead of pixel at a time it would make things a lot neater.

Sorry, I haven't meant to take up loads of your time here, I was just hoping there was a simple command-set to replace my long-winded method.

Notes: This may have use elsewhere so I've chucked this in.

BITMAP Header info:-

start size name stdvalue purpose
'1 2 bfType 19778 must always be set to 'BM' to declare that this is a .bmp-file.
'3 4 bfSize ?? specifies the size of the file in bytes.
'7 2 bfReserved1 0 must always be set to zero.
'9 2 bfReserved2 0 must always be set to zero.
'11 4 bfOffBits 1078 specifies the offset from the beginning of the file to the bitmap data.


'The BITMAPINFOHEADER:
'start size name stdvalue purpose
'15 4 biSize 40 specifies the size of the BITMAPINFOHEADER structure, in bytes.
'19 4 biWidth 100 specifies the width of the image, in pixels.
'23 4 biHeight 100 specifies the height of the image, in pixels.
'27 2 biPlanes 1 specifies the number of planes of the target device, must be set to zero.
'29 2 biBitCount 8 specifies the number of bits per pixel.
'31 4 biCompression 0 Specifies the type of compression, usually set to zero (no compression).
'35 4 biSizeImage 0 specifies the size of the image data, in bytes. If there is no compression, it is valid to set this member to zero.
'39 4 biXPelsPerMeter 0 specifies the the horizontal pixels per meter on the designated targer device, usually set to zero.
'43 4 biYPelsPerMeter 0 specifies the the vertical pixels per meter on the designated targer device, usually set to zero.
'47 4 biClrUsed 0 specifies the number of colors used in the bitmap, if set to zero the number of colors is calculated using the biBitCount member.
'51 4 biClrImportant 0 specifies the number of color that are 'important' for the bitmap, if set to zero, all colors are important.

TimB
Posts: 262
Joined: Wed Oct 04, 2006 7:25 am
Location: London UK

Post by TimB » Tue Jul 17, 2007 9:38 am

So by the looks of it the issue is that the data is in the wrong format so you need to do data extraction from the array to arrange it into the format that the GLCD likes.

I will look at that.

Francis
Registered User
Registered User
Posts: 314
Joined: Sun Mar 25, 2007 9:40 am
Location: Devon

Post by Francis » Tue Jul 17, 2007 10:00 am

Thanks Tim.

I certainly have to re-arrange.
The bitmap files are just standard bitmaps as would be created by Photopaint / Paintshop-Pro / etc. , not really 'wrong'(?).

I seem to remember with the good old T6963 you write a byte-at-a-time to plot/unplot 8 bits in a single go in a character cell, instead of having to writepixel x 8.
I couldn't see whether this was available with the KS0108, that was my real query.

If .bmp bytes have the pixels back-to-front I can sort that.
It was just saving space / increasing speed of plot I was thinking of.
Thank you.

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Tue Jul 17, 2007 1:06 pm

You can access the KS0108 module directly if you want to create your own render routines. Here is the complete code needed to fill the whole KS0108 display will horizontal lines

Code: Select all

// device and clock...
device = 18F452
clock = 20

// import driver...
include "KS0108.bas"
dim x,y as byte
   
// program start...
ADCON1 = $07    
Cls  
x = 0
while x < 128
   y = 0
   while y < 8
      Pos.x = x              // GLCD x pos
      Pos.y = y              // GLCD y pos
      WriteByte(%10101010)   // write a byte to KS0108
      inc(y)
   wend
   inc(x)
wend
If you run the above, you can see than the image is displayed in the blink of an eye. You would just need to replace '%10101010' with a bytes worth of data from your bitmap.

When you write a byte to the KS0108, it is along the y. You will see this by running the above code. Just in case you didn't already know, the KS0108 aspect ratio will make you image look 'stretched' along the y axis, so expect some distortion when comparing against your original image.

Post Reply