Save as type?

Just wondering, is there a way to save files with Lua in a format other than .txt? For example, this from the wiki:



concommand.Add( "jpegexporttest", function()

local RCD = {}

RCD.format = "jpeg"
RCD.h = ScrH()
RCD.w = ScrW()
RCD.quality = 100 //Max quality
RCD.x = 0
RCD.y = 0

local data = render.Capture( RCD )

file.Write( "Image.txt", data )

end )


Produces a file called ‘Image.txt’, which you have to MANUALLY RENAME to ‘Image.jpeg’. Surely we’re past the stone age by now?
There has to be a way to write a file of a certain format, right?

There is a reason you can only save something as a text file, you could exploit it otherwise. Viruses and worms could be downloaded to the client.

Well, surely there are other allowed formats? A PNG wouldn’t download/inflict a virus, right?

You’d be surprised. I’ve heard loomenadi rumors of arbitrary code execution while an image is being read.
That said, I agree that a white-list of extensions should be in order. For now, you can always grab those images in lua by doing “imagename.txt
.png”! (Most filesystems ignore everything after a newline)

-snip-

Wait, what? Do I do file.Write( “imagename.txt
.png”, data ) or something?

Or do I save imagename.txt and use “imagename.txt
.png” to convert it to a PNG, if it’s an opertation?

What do you mean by ‘grab those images’? Just read them? I don’t care about reading the images, I just want to write them for now.



function MaterialData(mat, param)
	local ret = Material("../data/" .. mat .. "
.jpg", param)
	LocalPlayer():ConCommand("mat_reloadmaterial ../data/" .. mat .. "*")
	return ret
end
----------------------------------
local tex = MaterialData("muh_file.txt")
----------------------------------
surface.SetMaterial(tex)


[editline]3rd May 2015[/editline]

^ That would be how to read a .txt (jpg) image in lua

I guess I’m going to have to save the file as something like Untitled.jpg.txt and just expect the 9 year old addon complainers to figure out how to remove the file association so it gets replaced with .jpg instead (which will probably never happen).

There’s another much more simple way : C++ DLL, already made that, that’s so easy to do, just use Windows registry to get Desktop path, and use ofstream, and you can save your files at whatever location/extension you want.

Example



int WriteFile(lua_State* state)
{
	if (LUA->IsType(1, GarrysMod::Lua::Type::STRING) && LUA->IsType(2, GarrysMod::Lua::Type::STRING))
	{
		const char* path = LUA->GetString(1);
		const char* stringData = LUA->GetString(2);

		ofstream file;
		file.open(path);	

		file << stringData;
		
		file.close();
	}
	else
	{
		VC2HelperError("Given arguments are invalid !");
	}
	return 0;
}


EDIT : don’t forget to #include <iostream> and fstream !
EDIT2 : printf and cout are blocked by Garry’s Mod so you can’t write anything from your C++ dll.

So you can’t use the script you provided at all? Great…

No, you can use it, it’s just that it will not popup anything in Source Engine console, it’s like if printf/cout were not bound to any code…

[editline]6th May 2015[/editline]

I myself use my own C++ module to generate .lua file and save them in Windows 7 x64 desktop (dll only compatible windows 7 x64, but should work on windows 7 x86, not tested as i’m not using x86 anymore).

If you want I can compile you a DLL however it’s platform dependent, so no ways to get Mac/Linux otherwise you buy me 1 other computer (Mac), I think I can compile on Linux using VMWare Player, but I’m not sure it will work, because sometimes Linux guest is crashing my host with a bluescreen driver problem…

I don’t want to use C++ though… just Lua if possible (I’m 99% sure .gma files wouldn’t be able to include .dlls)

No. It’s not possible to save as anything other than .txt. Don’t you think that if there was it would have been terribly exploited by now? (not that it hasn’t, cough cough :v:).

If you can tell us what you’re trying to do by setting a different file type maybe we could help you find an alternative.

The only alternative is to save files with the “.dat” extension.

I gave the best example I could before-



concommand.Add( "jpegexporttest", function()

local RCD = {}

RCD.format = "jpeg"
RCD.h = ScrH()
RCD.w = ScrW()
RCD.quality = 100 //Max quality
RCD.x = 0
RCD.y = 0

local data = render.Capture( RCD )

file.Write( "Image.txt", data )

end )


All I want to do is capture a certain region of the screen (or do some sort of operation that produces a jpeg or any other available image file type) and then export it. To be more specific, I’m making a Microsoft Paint addon which will be a replica of MS Paint. It works by using Panel.Paint() to draw a bunch of decals (for every paint splotch) onto a canvas (which is actually a DButton, and pressing down this button triggers the drawing of the splotches). With the way I’m currently doing it, the only format I can export as is a .txt file, even though I am able to export .JPG data into this .txt. Is there an alternative to render.Capture that not only captures the screen but exports it (this wouldn’t make the JPEG possible to contain a virus, right)?

So then it’s realy simple, if your user has got the DLL then allow export to png/jpg/whatever you want.

If the user has not the DLL block file export to .txt/.dat in the data directory.

Use a code like that to know if use has downloaded your DLL :



//For Linux/Mac I don't know because like I said I have no ways to compile for these systems, and no ways to run GMod on them...
local files, folders = file.Find("lua/bin/*.dll", "GAME")
if (system.IsWindows() && table.HasValue(files, "gmcl_vc2helper_win32.dll")) then
//DO CODE USING C++ DLL HERE !
end


I don’t want to force the user to download some backstreet-looking DLL for a simple exporting function.

[editline]9th May 2015[/editline]

By ‘backstreet’ I mean many users would be highly suspicious about downloading an external file for such an unimportant part.

One method I can think of would be to draw the created image to the screen, with black borders etc and then executing the screenshot command.

The thing I’m capturing is already drawn to the screen, but the screenshot command only does one format, and I probably can’t rename it(?)

I suppose I could use a bunch of different console commands until I can support every format, but for the thing I’m doing, I need only a certain region of the screen, not all of it, which render.Capture can capture.

I’m sorry, but like it has already been said, this is impossible without a DLL. You can however export it as basic dat/txt, but if you want real png/jpg this is impossible, I’m sorry.
I already searched something like that. Indeed, maybe you know I managed to send a client Screenshot to the server, directly using net messages. However when came the time to save some PNG files server side in data/realistic_rp/screenshots/your_steam_id/screen_date.png, I did not find anything to make it working. I even tried some workarrounds in Lua, but nothing works. The file library seams to be completely locked.

EDIT : You can maybe use a PHP server behind your code. Maybe POST library of GMod would be able to send the screen shot by packet to a PHP page, that will add and add data to a real PNG/JPG file. However it will not download it…