Image buffer without ImageCreate

New to FreeBASIC? Post your questions here.
[ACC]
Posts: 6
Joined: Sep 21, 2012 11:40

Image buffer without ImageCreate

Post by [ACC] »

Hi there.

Basically, I'm writting a DLL that needs to create a freebasic image buffer. Because imagecreate will return a NULL pointer if there's no screen set, I'm trying to mimic the buffer using allocate (the destination picture is always 4 bytes per pixel). But it's... well, buggy and random to say the least.

Anyone got any idea on how to recreate the fb.image buffer or force imagecreate from a dll (without graphic window)?

Code: Select all

function ImgCreate (byval PicWidth as uinteger = 0, byval PicHeight as uinteger = 0) as any ptr
  dim as uinteger ptr Pic
  dim as uinteger     PicEmpty   = 0
  dim as integer       PicBpp     = 4
  dim as uinteger     PicVersion = 7
  dim as uinteger     PicPitch   = ((PicWidth*PicBpp) + &hF) and not &hF
  dim as uinteger     PicSize    = PicPitch*PicHeight
  Pic = allocate((32+PicSize)*sizeof(ubyte))
  Pic[0] = PicVersion:  Pic[1] = PicBpp
  Pic[2] = PicWidth:    Pic[3] = PicHeight
  Pic[4] = PicPitch:    Pic[5] = PicEmpty
  Pic[6] = PicEmpty:    Pic[7] = PicEmpty
  for k as uinteger = 1 to PicSize\4
    Pic[7+k] = rgba(255,0,255,0)
  next k 
  return Pic
end function
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: Image buffer without ImageCreate

Post by TJF »

Did you check Internal graphics formats part Buffer formats.

It should be possible to create such a buffer (without graphic window).
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Re: Image buffer without ImageCreate

Post by Richard »

I would try a temporary graphics screen.

Code: Select all

Dim As Integer ix = 800, iy = 600

Screenres 1, 1, 32
Dim As Uinteger Ptr uip = Imagecreate(ix, iy, 0, 32)
Screen 0

Print uip
Imagedestroy uip
uip = 0

Print "done"
Sleep
If that did not solve it I would look for the FB image structures and dependencies in source files such as;
fb_gfx.h
libfb_gfx_image.c

Do you want your image buffer to work with ImageInfo, Point and Pset ?
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Image buffer without ImageCreate

Post by counting_pine »

TJF wrote:It should be possible to create such a buffer (without graphic window).
Yeah, if you pass the GFX_NULL flag to Screen/ScreenRes, that should give you an image without needing a graphics window. See the info at KeyPgScreengraphics.
[ACC]
Posts: 6
Joined: Sep 21, 2012 11:40

Re: Image buffer without ImageCreate

Post by [ACC] »

TJF wrote:Did you check Internal graphics formats part Buffer formats.
It should be possible to create such a buffer (without graphic window).
This is where I looked first, but I just have no idea how I'm supposed to handle header types and such (that's why I used a uinterger ptr); I get weird artefacts with the current method (and random crashes), so I suppose I can't just stuff a memory segment and expect it to work fine...
counting_pine wrote:
TJF wrote:It should be possible to create such a buffer (without graphic window).
Yeah, if you pass the GFX_NULL flag to Screen/ScreenRes, that should give you an image without needing a graphics window. See the info at KeyPgScreengraphics.
I'm not a huge fan of the idea, but I'll give it a try. Thanks.
fxm
Moderator
Posts: 12576
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Image buffer without ImageCreate

Post by fxm »

[ACC] wrote:
counting_pine wrote:
TJF wrote:It should be possible to create such a buffer (without graphic window).
Yeah, if you pass the GFX_NULL flag to Screen/ScreenRes, that should give you an image without needing a graphics window. See the info at KeyPgScreengraphics.
I'm not a huge fan of the idea, but I'll give it a try. Thanks.
I think instead that it is a very good idea!

Extract of documentation:
GFX_NULL: Starts a QB-on-GUI graphics mode. It creates a graphics buffer but not a window.

Remark: the proposal of Richard (temporary graphics screen) is always applicable (Imagedestroy works even after return to screen 0).
Richard
Posts: 3096
Joined: Jan 15, 2007 20:44
Location: Australia

Re: Image buffer without ImageCreate

Post by Richard »

IIRC, I have encountered a weird problem with Imagecreate when the graphics screen mode selected at the time had a lower bit depth than the image buffer being created. I thought at the time that it was a bug triggered by a difference in pallet type. This possible bug may reappear when creating images without an open graphics screen.
fxm
Moderator
Posts: 12576
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Image buffer without ImageCreate

Post by fxm »

Use "GFX_NULL" does not preclude defining "depth".
yetifoot
Posts: 1710
Joined: Sep 11, 2005 7:08
Location: England
Contact:

Re: Image buffer without ImageCreate

Post by yetifoot »

Hi all, something to note here. If you create your own image buffer, you should be aware of something that will cause imagedestroy to fail hard if you don't match the behaviour.

FB's imagecreate aims to be paragraph aligned (aligned to 16 bytes). This is for people who wish to use fast SSE commands on their buffer. So what FB does, is it allocates a bit more than needed. It stores the original pointer as a temporary. It then returns to the user the next address within the buffer that is correctly aligned. It stores the real pointer taken from malloc just before this aligned address.

So, if you try and pass a custom buffer to imagedestroy that is not aware of this, it will try to do dellocate(cast(any ptr ptr, p)[-1]) and probably crash, and not free the memory. You could just use your own version of imagedestroy too if you liked, that would probably be fine.

Here's an attempt I made, using the details from the gfx_image.c

Code: Select all


/'
function ImgCreate (byval PicWidth as uinteger = 0, byval PicHeight as uinteger = 0) as any ptr
  dim as uinteger ptr Pic
  dim as uinteger     PicEmpty   = 0
  dim as integer       PicBpp     = 4
  dim as uinteger     PicVersion = 7
  dim as uinteger     PicPitch   = ((PicWidth*PicBpp) + &hF) and not &hF
  dim as uinteger     PicSize    = PicPitch*PicHeight
  Pic = allocate((32+PicSize)*sizeof(ubyte))
  Pic[0] = PicVersion:  Pic[1] = PicBpp
  Pic[2] = PicWidth:    Pic[3] = PicHeight
  Pic[4] = PicPitch:    Pic[5] = PicEmpty
  Pic[6] = PicEmpty:    Pic[7] = PicEmpty
  for k as uinteger = 1 to PicSize\4
    Pic[7+k] = rgba(255,0,255,0)
  next k 
  return Pic
end function
'/

function ImgCreate (byval PicWidth as uinteger = 0, byval PicHeight as uinteger = 0) as any ptr

	dim as any ptr  Pic
	dim as uinteger PicEmpty   = 0
	dim as integer  PicBpp     = 4
	dim as uinteger PicVersion = 7
	dim as uinteger PicPitch = ((PicWidth*PicBpp) + &hF) and not &hF
	dim as uinteger PicSize  = PicPitch*PicHeight

	' Here are some smelly lines to do the alignment of the buffer and
        ' the top secret hidden original pointer magic.  I hope I got them
        ' correct

	' 0xF for the para alignment, p_size is sizeof(void *) rounded up to % 16 for the storage for the original pointer
	dim as integer p_size = (sizeof(any ptr) + &HF) and &HF
	dim as any ptr tmp = allocate(PicSize + 32 + p_size + &HF)

	' Awooga, Awooga, sound the alarms, I just cast this to a uinteger
        ' to do the pointer math, this will cause a 64 bit system to LITERALLY EXPLODE
        ' and maybe even worse.  But FBC isn't on 64 bit yet anyway.
	Pic = cast(any ptr, (cast(uinteger, tmp) + p_size + &HF) and not &HF)
	cast(any ptr ptr, Pic)[-1] = tmp

	' Phew, I'm glad that's over

	dim as uinteger ptr hdr = cast(uinteger ptr, Pic)
	
	hdr[0] = PicVersion : hdr[1] = PicBpp
	hdr[2] = PicWidth   : hdr[3] = PicHeight
	hdr[4] = PicPitch   : hdr[5] = PicEmpty
	hdr[6] = PicEmpty   : hdr[7] = PicEmpty

	return Pic

end function

screenres 640, 480, 32

dim as any ptr img = ImgCreate(640, 480)

for i as integer = 0 to 9999
	pset img, (int(rnd() * 640), int(rnd() * 480)), int(rnd()*16777216)
next i

put(0, 0), img, PSET

imagedestroy(img)

sleep
[ACC]
Posts: 6
Joined: Sep 21, 2012 11:40

Re: Image buffer without ImageCreate

Post by [ACC] »

yetifoot wrote:Here's an attempt I made, using the details from the gfx_image.c
Eh eh! Nice.

I tried the screenres with no window (thought it would be dirty like "there's a window, but it's invisible" I was wrong). Everything works now; Just one thing: "Screenres 1, 1, 32"... I changed a few things as I tried this method, so it might be something totally unrelated that caused the problem, but tiny dimensions in screenres tend to provide wrong pointers or no pointers at all.

Anyway, everything's fine now. Thanks everyone!
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Image buffer without ImageCreate

Post by counting_pine »

[ACC] wrote:"Screenres 1, 1, 32"... I changed a few things as I tried this method, so it might be something totally unrelated that caused the problem, but tiny dimensions in screenres tend to provide wrong pointers or no pointers all.
Interesting, do you mean ImageCreate was returning null pointers, or ScreenPtr was, or something..? I don't suppose anyone can confirm anything like that?
[ACC]
Posts: 6
Joined: Sep 21, 2012 11:40

Re: Image buffer without ImageCreate

Post by [ACC] »

counting_pine wrote:Interesting, do you mean ImageCreate was returning null pointers, or ScreenPtr was, or something..? I don't suppose anyone can confirm anything like that?
I know I spent some time swearing then solved it and kinda forgot about the stuff... From what I recall, ImageInfo would return weird values when using a true freebasic image pointer; dimensions were too big or negatives, the pointer existed, I had no error when working in the buffer or using ImageDestroy, but Put wouldn't show anything... The problem was coming from a sub that converts the freeimage buffer to freebasic image. First I defined the buffer as:

Code: Select all

DIM AS ANY PTR
instead of:

Code: Select all

DIM AS FB.Image PTR
I don't have the problem anymore (I use FB.Image PTR now) and once again, it might be something else I changed somewhere in the code...
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Image buffer without ImageCreate

Post by counting_pine »

The type of pointer shouldn't make a difference, unless of course you're actually accessing fb.image members.
What sort of weird values is ImageInfo returning?
[ACC]
Posts: 6
Joined: Sep 21, 2012 11:40

Re: Image buffer without ImageCreate

Post by [ACC] »

counting_pine wrote:The type of pointer shouldn't make a difference, unless of course you're actually accessing fb.image members.
What sort of weird values is ImageInfo returning?
The member access wouldn't compile at all I guess.
ImageInfo would return negative values or huge ones (like 3446x84554 -not an actual value, but you get the idea- for a 16x16 sprite). I wish I made a save point with the bug, but didn't (plus it's hard to tell what the problem is: it could be the EXE or the DLL -just encountered the temporary string stack full bug- )... When I get that kind of issues, I just rewrite huge chunks of code because the mistake is certainly on my end...
Gonzo
Posts: 722
Joined: Dec 11, 2005 22:46

Re: Image buffer without ImageCreate

Post by Gonzo »

stack overflows are detected by the OS and in windows your program is silently stopped :)
its one of those things that are worth to know, since you'll likely encounter it at some point, so if you have any kind of recursion and the program just disappears, the stack was becoming too big
Post Reply