|
Re: How to make a copy of a bmap?
[Re: Caermundh]
#367544
04/14/11 14:40
04/14/11 14:40
|
Joined: Jan 2002
Posts: 4,225 Germany / Essen
Uhrwerk
Expert
|
Expert
Joined: Jan 2002
Posts: 4,225
Germany / Essen
|
@Uhwrek: No, the copied bitmap in his code does not create 2 bitmaps with the same handle, if you look at the testing code he posted originally, it puts a red cross on the original bmap. When i ran the code, i had two bmaps - one with and one without a red cross on it. I don't know what code you're talking about, I was talking about Mr. Guests code. Most obviously you're not believing me. As I already said, you better have a look at atypes.h
typedef struct BMAP {
C_LINK link;
long width,height; // original size of the bitmap
long bytespp; // original bytes per pixel (1..4)
void *ptr; // internal use
byte *pixels; // ptr to palettized, 565, 4444, 888 or 8888 coded original image
long flags; // see BMPF_... above
void *d3dtex; // LPDIRECT3DTEXTURE9 (usually a different format than the original image)
float u1,v1,u2,v2; // texture pixel bounds
long u,v; // cutout start size
long refcount; // for implicitely created bmaps
long finalwidth,finalheight,finalbytespp;
long pitch,finalpitch;
long miplevels;
long finalformat;
void *finalbits; // bitmap content when locked, otherwise NULL
} BMAP;
As you can see here the BMAP struct contains the C_LINK struct, which contains the handle. So using the mem_cpy approach WILL copy this handle. As you can see furthermore there are different pointers to image data, namely *pixels, *d3dtex and *finalbits. All this data does not get copied by mem_cpy, just the pointers get copied. Hence the image data does not get copied and copying the bitmap is kind of senseless. If you understand that and are willing to live with the consequences, go for it. But don't cry if this will fuck things up later on. EDIT: @JustSid: pffffffff....
Always learn from history, to be sure you make the same mistakes again...
|
|
|
Re: How to make a copy of a bmap?
[Re: Joey]
#367552
04/14/11 16:29
04/14/11 16:29
|
Joined: Aug 2005
Posts: 238
Caermundh
OP
Member
|
OP
Member
Joined: Aug 2005
Posts: 238
|
@Uhrwerk, Just Sid: I see what you are saying about C_LINK link; getting copied by mem copy, so that you effectivly have 2 bmaps with the same handle, and i also see your argument that memcpy() will copy only the pointers for *pixels, *d3dtex, & *finalbits without copying the data that they point to. Given that memcpy() will copy the pointers and not the data, if i write to one bmap, it would write to both, because each bmap is pointing to the same data. But i have run the code, and was able to write to one without affecting the other. Here is the code:
///////////////////////////////
#include <acknex.h>
#include <default.c>
///////////////////////////////
ENTITY* e1;
BMAP* bmp_original = "bmap_to_copy.bmp";
BMAP* bmp_clone;
PANEL* pnl_original = {
pos_x = 0;
flags = SHOW;
}
PANEL* pnl_clone = {
pos_x = 64;
flags = SHOW;
}
void bmap_cross(){
BMAP* tgablitz = pnl_original.bmap;
var format;
var pixel;
format = bmap_lock(tgablitz,0);
if (format >= 565) {
pixel = pixel_for_vec(vector(0,0,255),100,format); // red color
pixel_to_bmap(tgablitz,10,10,pixel);
pixel_to_bmap(tgablitz,10,11,pixel);
pixel_to_bmap(tgablitz,10,12,pixel);
pixel_to_bmap(tgablitz,10,13,pixel);
pixel_to_bmap(tgablitz,10,14,pixel);
pixel_to_bmap(tgablitz,8,12,pixel);
pixel_to_bmap(tgablitz,9,12,pixel);
pixel_to_bmap(tgablitz,11,12,pixel);
pixel_to_bmap(tgablitz,12,12,pixel);
}
bmap_unlock(tgablitz);
}
BMAP *bmap_clone(BMAP* bmp){
BMAP* bmpNew = malloc(sizeof(BMAP));
memcpy(bmpNew, bmp, sizeof(BMAP));
return(bmpNew);
}
void main(){
wait(1);
bmp_clone = bmap_clone(bmp_original);
pnl_original.bmap = bmp_original;
pnl_clone.bmap = bmp_clone;
bmap_cross();
}
(this is just a re-paste of Mr. Guests earlier code.) When I run the above code, I end up with 2 bitmaps on the screen, one with a red_cross on it and one without the red cross. So now i am just confused. I think JustSid and Uhrwerk are both correct in their statements - memcpy() will copy the pointers without copying the data they point to, so when i modify the data - it would modify both bmaps because they are the same bmap. But if that is so, than how am i getting 2 distinct bmaps?
|
|
|
Re: How to make a copy of a bmap?
[Re: Caermundh]
#367555
04/14/11 17:19
04/14/11 17:19
|
Joined: Apr 2007
Posts: 3,751 Canada
WretchedSid
Expert
|
Expert
Joined: Apr 2007
Posts: 3,751
Canada
|
Just a guess: Move the panels around, I guess there is a cache to avoid too many drawcalls.
Shitlord by trade and passion. Graphics programmer at Laminar Research. I write blog posts at feresignum.com
|
|
|
Re: How to make a copy of a bmap?
[Re: WretchedSid]
#367556
04/14/11 17:31
04/14/11 17:31
|
Joined: Jan 2002
Posts: 4,225 Germany / Essen
Uhrwerk
Expert
|
Expert
Joined: Jan 2002
Posts: 4,225
Germany / Essen
|
Now that is exactly what I meant with "fucking things up later on".
The reason for your two "distinct" bitmaps is the order you're doing your calls in. You copy the memory area while the DirectX Texture of the bitmap has not yet been allocated. Hence the engine will find NULL when inspecting the bitmaps and will hence allocate two textures for the same image data located in the BMAP.pixel member. The pixel_to_bmap instruction will now operate on the texture rather than on the original image data. As long as both bitmaps will remain in the video memory it will look as if there are two bitmaps because there are two textures. You're lucky in this case that the DirectX Texture was not yet allocated. Still don't believe it? Place a "bmap_preload(bmp_original);" right after the wait in your main function. You'll get a very "surprising" result.
Seriously: Several experienced forum members warned you not to mess up with internal engine data and you did it anyways and got results you we're not able to understand. Does that ring a bell for you?
Always learn from history, to be sure you make the same mistakes again...
|
|
|
Re: How to make a copy of a bmap?
[Re: MrGuest]
#367585
04/15/11 01:27
04/15/11 01:27
|
Joined: Aug 2005
Posts: 238
Caermundh
OP
Member
|
OP
Member
Joined: Aug 2005
Posts: 238
|
OK...so i did some testing. When I did a bmap_preload like you suggested Uhrwerk, the bitmaps both had red crosses on them. The only reason I was seeing one with and one without was because of, like you said, the way Gamestudios caches bitmaps. Thing is, Mr. Guest got my curiosity up, so i kept at it. I knew memcpy could work. Heres what I came up with:
//////////////////////////////////////////////////////////////////////
// test.c
#include <acknex.h>
#include <default.c>
#include "headers.h"
#define PRAGMA_PATH "Graphics\Item Icons"
#define PRAGMA_PATH "Models"
FONT* standard_font = "ackfont.pcx";
BMAP* bmp_original = "jug_icon.tga";
BMAP* bmp_clone = "jug_icon.tga";
PANEL* pnl_original = {
pos_x = 0;
pos_y = 40;
flags = SHOW;
}
PANEL* pnl_clone = {
pos_x = 64;
pos_y = 40;
flags = SHOW;
}
PANEL* info_panel =
{ pos_x = 20;
pos_y = 20;
flags = SHOW;
digits = 0,0,3.0,standard_font,1,test;
digits = 0,10,3.0,standard_font,1,test2;
}
void bmap_cross(){
BMAP* tgablitz = pnl_original.bmap;
var format;
var pixel;
format = bmap_lock(tgablitz,0);
if (format >= 565) {
pixel = pixel_for_vec(vector(0,0,255),100,format); // red color
pixel_to_bmap(tgablitz,10,10,pixel);
pixel_to_bmap(tgablitz,10,11,pixel);
pixel_to_bmap(tgablitz,10,12,pixel);
pixel_to_bmap(tgablitz,10,13,pixel);
pixel_to_bmap(tgablitz,10,14,pixel);
pixel_to_bmap(tgablitz,8,12,pixel);
pixel_to_bmap(tgablitz,9,12,pixel);
pixel_to_bmap(tgablitz,11,12,pixel);
pixel_to_bmap(tgablitz,12,12,pixel);
}
bmap_unlock(tgablitz);
}
BMAP *bmap_copy(BMAP* bmp)
{ BMAP* bmpNew = bmap_createblack(1,1,24);
bmpNew.width = bmp.width;
bmpNew.height = bmp.height;
bmpNew.bytespp = bmp.bytespp;
bmpNew.flags = bmp.flags;
bmpNew.u1 = bmp.u1;
bmpNew.v1 = bmp.v1;
bmpNew.u2 = bmp.u2;
bmpNew.v2 = bmp.v2;
bmpNew.u = bmp.u;
bmpNew.v = bmp.v;
bmpNew.refcount = bmp.refcount;
bmpNew.finalwidth = bmp.finalwidth;
bmpNew.finalheight = bmp.finalheight;
bmpNew.finalbytespp = bmp.finalbytespp;
bmpNew.pitch = bmp.pitch;
bmpNew.finalpitch = bmp.finalpitch;
bmpNew.miplevels = bmp.miplevels;
bmpNew.finalformat = bmp.finalformat;
bmpNew.finalbits = NULL;
bmpNew.d3dtex = NULL;
bmpNew.pixels = malloc((bmp.width*bmp.height)*bmp.bytespp);
memcpy(bmpNew.pixels, bmp.pixels, (bmp.width*bmp.height)*bmp.bytespp);
return(bmpNew);
}
void main()
{ wait(1);
bmap_preload(bmp_original);
bmp_clone = bmap_copy(bmp_original);
pnl_original.bmap = bmp_original;
pnl_clone.bmap = bmp_clone;
bmap_cross();
test = bmp_original.link.index;
test2 = bmp_clone.link.index;
}
Instead of using memcpy to copy the BMAP, i use memcpy to copy the bmap pixels. As you can see, i did a bmap_preload so im not getting any cached bmaps. I checked bmp_original.link.index and bmp_clone.link.index and they are different numbers, so the two bmaps are unique. When I ran the code, i got one bmap with a red cross and one without. the only problem the code has is that i get an "invalid pointer freed" error message when I exit the game. Seriously: Several experienced forum members warned you not to mess up with internal engine data and you did it anyways and got results you we're not able to understand. Does that ring a bell for you?
I mess with stuff im not supposed to all the time. Its how I learn. As well - when I am messing with stuff I dont fully understand - I gnerally do it in a test enviroment where I can blow things up all day long with no harm done. In the future, I will avoid asking "why didnt that work?" style questions like I did in the later posts of this thread. You should come to the boards with "How do I...?" style questions or with answers. I apologize for violating board etiquette the way i did.
|
|
|
Re: How to make a copy of a bmap?
[Re: Schubido]
#367595
04/15/11 07:02
04/15/11 07:02
|
Joined: Jul 2001
Posts: 6,904
HeelX
Senior Expert
|
Senior Expert
Joined: Jul 2001
Posts: 6,904
|
Funny, I coded some functions for the same topic yesterday. This is what I came up with:
BMAP* bmap_clone (BMAP* src)
{
// no source?
if (src == NULL)
return(NULL);
var format = bmap_lock(src, 0);
// invalid bitmap or unknown format?
if (format == 0)
return(NULL);
else
bmap_unlock(src);
BMAP* r = bmap_createblack(src->width, src->height, format);
if (r != NULL)
bmap_copy(src, r);
return(r);
}
BMAP* bmap_copy (BMAP* src, BMAP* dest)
{
if ((src == NULL) || (dest == NULL))
return(NULL);
bmap_blit(dest, src, NULL, NULL);
return(dest);
}
Using the format retrieved by bmap_lock in bmap_createblack is actually safe. The manual says about bmap_createblack: format - bitmap format (uncompressed formats only; see bmap_lock) or number of bits per pixel (8, 16, 24, 32). I'm not 100% sure, if a bmap_process approach would be faster - but from what I believe and know, it will . Maybe someone has the time to write a generic function for that?
|
|
|
Re: How to make a copy of a bmap?
[Re: HeelX]
#367602
04/15/11 09:21
04/15/11 09:21
|
Joined: Apr 2007
Posts: 3,751 Canada
WretchedSid
Expert
|
Expert
Joined: Apr 2007
Posts: 3,751
Canada
|
Using the format retrieved by bmap_lock in bmap_createblack is actually safe. The manual says about bmap_createblack: format - bitmap format (uncompressed formats only; see bmap_lock) or number of bits per pixel (8, 16, 24, 32). Ouh, I misunderstood the manual somehow. Thanks for the clarification.
Shitlord by trade and passion. Graphics programmer at Laminar Research. I write blog posts at feresignum.com
|
|
|
|