Copy/Paste Texture to Clipboard
Moderator: InsideQC Admins
12 posts
• Page 1 of 1
Copy/Paste Texture to Clipboard
FitzQuake 0.85 has a dumptextures command that downloads the textures from the video card and writes them as TGA:
I plan on making it so a single texture can be copied or pasted to the clipboard Winodws, but looks like I'll have to do this incrementally.
Accessing the clipboard is easy enough ...
But looks like I'll have to dig into some Windows API stuffs to use CF_DIB. I downloaded some source codes like GIMP and such, but most of them use GTK obfuscating getting into the Windows procedure to allocatie a DIB and fill in the data.
- Code: Select all
/*
===============
TexMgr_Imagedump_f -- dump all current textures to TGA files
===============
*/
void TexMgr_Imagedump_f (void)
{
.
.
.
buffer = malloc(glt->width*glt->height*4);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
Image_WriteTGA (tganame, buffer, glt->width, glt->height, 32, true);
.
.
.
Con_Printf ("dumped %i textures to %s\n", numgltextures, dirname);
}
I plan on making it so a single texture can be copied or pasted to the clipboard Winodws, but looks like I'll have to do this incrementally.
Accessing the clipboard is easy enough ...
- Code: Select all
char *Sys_GetClipboardData (void)
{
HANDLE th;
char *clipText, *s, *t;
static char clipboard[SYS_CLIPBOARD_SIZE];
if (!OpenClipboard(NULL))
return NULL;
if (!(th = GetClipboardData(CF_TEXT)))
{
CloseClipboard ();
return NULL;
}
if (!(clipText = GlobalLock(th)))
{
CloseClipboard ();
return NULL;
}
s = clipText;
t = clipboard;
/*
\e Write an <escape> character.
\a Write a <bell> character.
\b Write a <backspace> character.
\f Write a <form-feed> character.
\n Write a <new-line> character.
\r Write a <carriage return> character.
\t Write a <tab> character.
\v Write a <vertical tab> character.
\' Write a <single quote> character.
\\ Write a backslash character.
*/
// Filter out newlines, carriage return and backspace characters
while (*s && t - clipboard < SYS_CLIPBOARD_SIZE - 1 && *s != '\n' && *s != '\r' && *s != '\b')
*t++ = *s++;
*t = 0;
GlobalUnlock (th);
CloseClipboard ();
return clipboard;
}
// copies given text to clipboard
void Sys_CopyToClipboard(const char *text)
{
char *clipText;
HGLOBAL hglbCopy;
if (!OpenClipboard(NULL))
return;
if (!EmptyClipboard())
{
CloseClipboard();
return;
}
if (!(hglbCopy = GlobalAlloc(GMEM_DDESHARE, strlen(text) + 1)))
{
CloseClipboard();
return;
}
if (!(clipText = GlobalLock(hglbCopy)))
{
CloseClipboard();
return;
}
strcpy((char *) clipText, text);
GlobalUnlock(hglbCopy);
SetClipboardData(CF_TEXT, hglbCopy);
CloseClipboard();
}
But looks like I'll have to dig into some Windows API stuffs to use CF_DIB. I downloaded some source codes like GIMP and such, but most of them use GTK obfuscating getting into the Windows procedure to allocatie a DIB and fill in the data.
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Puzzle pieces ...
- Code: Select all
HGLOBAL hData = data.GetGlobalData(CF_DIB);
BITMAPINFO* pData = (BITMAPINFO*) GlobalLock(hData);
if (pData)
{
// use it!
GlobalFree(hData);
}
- Code: Select all
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Hmmm; I've done this in .NET just using Clipboard.SetImage which seems to use CF_BITMAP behind the scenes. Might be useful info or might not! 
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
mh wrote:Hmmm; I've done this in .NET just using Clipboard.SetImage which seems to use CF_BITMAP behind the scenes. Might be useful info or might not!
I'm thinking this is gonna be a bit more "raw" than something insulated like .NET but maybe I'll be wrong. I've been rather stunned so far as to how few open source image editors are solely native Windows coded in C or C++.
Still, I'm just not gonna be deterred. Stubborness ... the heart of engine coding
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Don't worry about the DirectQ-specific bits in here, this works:
- Code: Select all
byte *bmbits = (byte *) MainHunk->Alloc (width * height * 4);
D3D_Transfer8BitTexture ((byte *) data, (unsigned *) bmbits, width * height, D3D_GetTexturePalette (d3d_QuakePalette.standard, 0));
HBITMAP hBitmap = CreateBitmap (width, height, 1, 32, bmbits);
OpenClipboard (NULL);
if ((SetClipboardData (CF_BITMAP, hBitmap)) == NULL)
Sys_Error ("SetClipboardData failed");
CloseClipboard ();
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
mh wrote:Don't worry about the DirectQ-specific bits in here, this works:
- Code: Select all
byte *bmbits = (byte *) MainHunk->Alloc (width * height * 4);
D3D_Transfer8BitTexture ((byte *) data, (unsigned *) bmbits, width * height, D3D_GetTexturePalette (d3d_QuakePalette.standard, 0));
HBITMAP hBitmap = CreateBitmap (width, height, 1, 32, bmbits);
OpenClipboard (NULL);
if ((SetClipboardData (CF_BITMAP, hBitmap)) == NULL)
Sys_Error ("SetClipboardData failed");
CloseClipboard ();
I was doing this a bit less efficiently than your example (filling in the bitmap header manually because I didn't know better).
And it would seem that GetBitmapBits does the reverse.
Thanks, MH
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Upside down fix ....
glReadPixels (...)
FlipRows (...)
ApplyGamma (...) // Optional
hBitmap= CreateBitmap (...)
glReadPixels (...)
FlipRows (...)
ApplyGamma (...) // Optional
hBitmap= CreateBitmap (...)
- Code: Select all
static qbool FlipRows (int columns, int rows, int colordepth, byte *buffer)
{
byte *tb1, *tb2;
int offset1, offset2;
int i,bufsize;
bufsize = columns * colordepth;
tb1= Q_malloc(bufsize);
tb2= Q_malloc(bufsize);
for (i=0;i<(rows+1)/2;i++)
{
offset1= i * bufsize;
offset2=((rows-1)-i) * bufsize;
memcpy(tb1, buffer+offset1, bufsize);
memcpy(tb2, buffer+offset2, bufsize);
memcpy(buffer+offset1, tb2, bufsize);
memcpy(buffer+offset2, tb1, bufsize);
}
free (tb1);
free (tb2);
return true;
}
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Also look at glGetTexImage: http://www.opengl.org/sdk/docs/man/xhtm ... xImage.xml
Hmm, I could do this in DirectQ using it's tab autocompletion on texturenames. "copytexture <tab>", etc. And also do "dumptexture" for a single texture. Also "pastetexture" to update a texture image from the clipboard - that might be really useful for experimenting with external textures (or even just different textures) without needing to rebuild or reload a map. In fact I imagine that mappers would find such a feature to be really good.
Hmm, I could do this in DirectQ using it's tab autocompletion on texturenames. "copytexture <tab>", etc. And also do "dumptexture" for a single texture. Also "pastetexture" to update a texture image from the clipboard - that might be really useful for experimenting with external textures (or even just different textures) without needing to rebuild or reload a map. In fact I imagine that mappers would find such a feature to be really good.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
mh wrote:Also look at glGetTexImage: http://www.opengl.org/sdk/docs/man/xhtm ... xImage.xml
Actually, I was testing it with the screenshot command just to fine tune things. glReadPixels in the above post was a mistake.
Hmm, I could do this in DirectQ using it's tab autocompletion on texturenames. "copytexture <tab>", etc. And also do "dumptexture" for a single texture. Also "pastetexture" to update a texture image from the clipboard - that might be really useful for experimenting with external textures (or even just different textures) without needing to rebuild or reload a map. In fact I imagine that mappers would find such a feature to be really good.
Or alter the texture of a single surface that the crosshair is pointing to
Or, in fact, you could test model skins in real-time by copy/paste. Sure the texture would have to go through the whole padding, power of 2 routine.
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Rather than start a new thread ...
I'm rewriting my engine a bit so commands can output to ...
1. The console
2. To file
3. Text to clipboard
Why? Well the edicts command is virtually useless since it dumps probably about 2MB of entity information to the console, which vastly exceeds the console buffer and any size you would ever sensibly make it.
Just take Con_Printf and modify it to have output options.
enum {PRINT_CONSOLE, PRINT_FILE, PRINT_CLIPBOARD}
I'm rewriting my engine a bit so commands can output to ...
1. The console
2. To file
3. Text to clipboard
Why? Well the edicts command is virtually useless since it dumps probably about 2MB of entity information to the console, which vastly exceeds the console buffer and any size you would ever sensibly make it.
Just take Con_Printf and modify it to have output options.
enum {PRINT_CONSOLE, PRINT_FILE, PRINT_CLIPBOARD}
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Re: Copy/Paste Texture to Clipboard
Not wanting to start a new thread ...
I wrote a function to get an image off the clipboard and convert it to RGBA. (I use RGBA instead of BGRA as MH strongly advocates because I'd have to adjust a lot of image functions I've written and I don't want to do that right now. image loaders, resample functions, color manipulation functions, etc.)
To get BGRA instead, just turn #if 1 into #if 0 in the code below.
I wrote a function to get an image off the clipboard and convert it to RGBA. (I use RGBA instead of BGRA as MH strongly advocates because I'd have to adjust a lot of image functions I've written and I don't want to do that right now. image loaders, resample functions, color manipulation functions, etc.)
To get BGRA instead, just turn #if 1 into #if 0 in the code below.
- Code: Select all
byte* Platform_Clipboard_To_RGBA_Alloc (int* outwidth, int* outheight)
{
byte* ptr = NULL;
if (OpenClipboard(NULL))
{
HBITMAP hBitmap = GetClipboardData (CF_BITMAP);
BITMAP csBitmap;
if (hBitmap && GetObject(hBitmap, sizeof(csBitmap), &csBitmap) && csBitmap.bmBitsPixel == 32)
{
// allocate buffer
int i, bufsize = csBitmap.bmWidth * csBitmap.bmHeight * (csBitmap.bmBitsPixel / 8);
csBitmap.bmBits = ptr = Memory_malloc (bufsize, "bmbits buffer");
GetBitmapBits((HBITMAP)hBitmap, bufsize, csBitmap.bmBits );
// Convert BGRA --> RGBA, set alpha full since clipboard loses it somehow
for (i = 0; i < bufsize; i += 4)
{
#if 1 // Wants RGBA. Set to 0 for BGRA
byte temp = ptr[i + 0];
ptr[i + 0] = ptr[i + 2];
ptr[i + 2] = temp;
#endif
ptr[i + 3] = 255; // Full alpha
}
*outwidth = csBitmap.bmWidth;
*outheight = csBitmap.bmHeight;
}
CloseClipboard ();
}
return ptr;
}
The night is young. How else can I annoy the world before sunsrise?
Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
-

Baker - Posts: 3666
- Joined: Tue Mar 14, 2006 5:15 am
Re: Copy/Paste Texture to Clipboard
RGBA is OK for this kinda thing; it's not as performance-critical as lightmaps. 
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
12 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest