Many JPG images in project

Hi All,
My project needs to use about 120 JPEG (!) images of varying sizes that need to be compiled into the project. I dont want users to be able to change these images (as complicated as possible for them to edit so no simple .RES file)

What is the best solution as well as how do I read the image (whatever format you suggest) into a TImage (or similar) component?

Thank you!
maxbAsked:
Who is Participating?
 
Slick812Connect With a Mentor Commented:
 I guess that I should say, that as far as I have seen , , having Reources in a DLL does  NOT  make them any harder to get to and get them or change them, , , ,  resources are treated about the same in programs and DLLs.

OK, you will need to make a   .RES  resource file, You need to make a resource Creation file ( .RC ) and for Jpegs  Gifs and other "Non-Standard" files you can use a resource type name like "JPG" or "JPEG" or "MyJunk", this does NOT singify any  TYPE of file it's just an Identifier. .
you can give them ID names of whatever is your ideas, I use aJPEG but it has no meaning. .
the following three lines of code is for the DllJpgs.RC  file -


Error1 aJPEG "errorG1.jpg"
taNotes aJPEG "notes.jpg"
backGround aJPEG "light water.jpg"

now compile this DllJpegs.RC file with the Delphi resource compiler  brcc32.exe and you will get the DllJpgs.RES  file, move this res file to your DLL folder.


fire up delphi and on the file menu pick "New" then pick "Dll", here are the 4 lines of code for the JpgDll.dpr  library program -


library JpgDll;
{$R DllJpgs.RES}
begin
end.


now compile this  library JpgDll;  and get your resource  Dll, named   JpgDll.dll . . .


now open a program in Delphi and add a button and for the button click have this code -


procedure TForm1.sbut_JpgFromDllClick(Sender: TObject);
var
Jpg1: TJPEGImage;
ResStm : TResourceStream;
hLibJpg: THandle;
begin
hLibJpg := LoadLibrary('JpgDll.dll');

if hLibJpg = 0 then
  begin
  ShowMessage('ERROR - Could NOT load library');
  Exit;
  end;
Jpg1 := TJPEGImage.Create;
ResStm := TResourceStream.Create(hLibJpg, 'backGround', 'aJPEG');
// use TResourceStream to find and load your resource
try
  Jpg1.LoadFromStream(ResStm);
  // load Jpg from Res Stream
  Canvas.Draw(656,70, Jpg1);

  finally
  FreeLibrary(hLibJpg);
  FreeAndNil(Jpg1);
  FreeAndNil(ResStm);
  end;
end;

 - - - - - - - - - - - - - - -  - - - - - - - -  - - - - - -  - --

to get another Jpg
ResStm := TResourceStream.Create(hLibJpg, 'taNotes', 'aJPEG');

ask questions if you need more
0
 
-Karamja-Commented:
>I dont want users to be able to change these images.

Dont think you can, The only thing I could think of is using a exe packer (UPX, ASPack)
0
 
maxbAuthor Commented:
I guess anything harder than just changing the .RES or images in a directory would suffice as "not easy to change images easily". Maybe compile into a DLL? I have no experience working with DLLs at all...
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
pritaeasSoftware EngineerCommented:
http://www.greatis.com/delphicb/tips/lib/resource-bmpfromdll.html

Above link shows an example. Related links at the bottom shows how to include JPEG in DLL.
0
 
maxbAuthor Commented:
The DLL idea is just something I threw out, is that really the best solution for my problem?
0
 
maxbAuthor Commented:
Ok, even if DLL is the best solution... That link doesnt provide a way to put the JPGs inside the DLL. It simply shows an example of how to have the DLL as a loader... Need more help
0
 
Slick812Commented:
hello maxb , , I am not really clear about what it is that you are trying to do? ? I am wondering why you say that you want to prevent -
"I dont want users to be able to change these images"

why do you care about someone running a Resource Editor and changing your images to something they might prefer?, , , I will have to guess, since you mention change Image, that you do not want someone to Get the special images out of your executable?

I would stick to a RES resource, and just remove the first several standard bytes of the JPEG file header, and then add those back when I got the image data from the resource, ,

The only other way I have heard of to stick data into an executable, is to Tack it on to the End of the program file, but you will need a separate program to stick the data onto it, but the program can read the data whenever it is running
0
 
maxbAuthor Commented:
Exactly, I want to make it difficult for them to get the images out and replace them with something else. Isn't there a way to compile a res into a DLL (makes it more difficult to extract the images)?

I have no idea on how to remove the JPG header... although that sounds like a great option...

Also, how do I even get a JPG into a RES? It'll only take BMP and ICO
0
 
DragonSlayerCommented:
Gwena has a component that allows you to 'embed' your files to your EXE and retrieve/update it during runtime http://www.geocities.com/gacarpenter386
0
 
maxbAuthor Commented:
Thank you but I dont think that would work because I will have to compare the hash of the exe every time they connect to my server to ensure it has not been tampred with. Also, it would bring the EXE size to 5 or 6mb, isn't there some sort of memory problem with an EXE that size? I have to admit I don't know much about the topic.
0
 
DragonSlayerCommented:
well, I guess you could always encrypt the jpg before appending it to your EXE, that way, your users won't know what to temper anyway ;-)

by the way, if you add the JPGs into a DLL, isn't the DLL file size going to be 5-6MB too? Never had problems with .exe of 5-6MBs yet, heh. Photoshop's exe is more than 15MB, by the way :-)
0
 
pritaeasSoftware EngineerCommented:
http://cc.borland.com/ccweb.exe/listing?id=12708

I'll see if I can put together a code sample for you. Creating a resource is like: create a data.rc file, put data in it, link it into a dll project using {$R *.RC} or {$R *.RES}, compile it, done.

Then use the code I gave you to extract the data. You can do it with any file: JPG, HTML, AVI even EXE if you like.

code for the .rc file

1 JPEG "test1.jpg"
2 JPEG "test2.jpg"
3 JPEG "test3.jpg"
0
 
maxbAuthor Commented:
DragonSlayer,
So from what you're saying, I can just put a bunch of TImage components on a "resource" form inside my project. Select the JPG for each (at design time). Then just use Image.Picture as a source throughout the app? Is there a downside to doing this? What's a point in using resource DLLs (other than sharing between apps) if you can just compile the images into the exe?

Piraeas,
I would love to see what that code looks like. Thank you.
0
 
DragonSlayerCommented:
Well, the downside is, everytime you update/patch your software, you will have to redistribute the whole chunk of 5-6MB file.
0
 
maxbAuthor Commented:
Good point :) I don't know why I didn't think of that. So is the DLL approach the best?
0
 
DragonSlayerCommented:
well, it's either the DLL, or the Database, or you can come up with your own "storage format"...
0
 
DragonSlayerCommented:
Here is a storage component (with encryption and compression) that I've used in some projects quite a while ago... http://www.xarka.com/download/hkstrm17.zip (THKStream)

To quote from the Author's readme:

"HKStreams is a component that enables you to easily save and load many streams into one file. The streams can be stored with LHA compression if wanted, and can also be encrypted with blowfish. THKStreams is also smart, if you load afterwards an encrypted or compressed (or both) file, it will know how to read it, and can also call your event that asks the user for a password if needed.Can also handle wrong passwords or corrupt files.

This program works by saving the streams in a file with a 10 byte header that contains information whether encryption and/or compression exists, and also a series of bytes that are used for a test if the correct password was entered, in the case of encryption (of course only those 8 bytes are known).

With this you can implement with little code the ability for users to protect their files if they want it, and also compress their data. However you will have to warn them that if they forget the password, there will be no way to regain the data (well except maybe if they work in CIA)"



DragonSlayer.
0
 
DragonSlayerCommented:
And here's another of the file storage alternative, but this one's not free: http://www.aidaim.com/products/sfs/sfs_spec.php
0
 
TheRealLokiSenior DeveloperCommented:
I think I'd just have the jpg's as files, but keep a crc checksum in the application. run a quick checksum when the app starts (equiv time to loading the app with the jpg's embedded anyway) but the files are then only loaded into memory when they are needed. Saves resources
0
 
GwenaCommented:
You can use my ExeMod.pas unit to add the jpg files to the end of the exe.

You will not have any problems with the exe size... and the images are easily
scrambled to make them hard for users to alter.

The images are read from the exe file on disk at runtime..much the same as
working with simple jpg files on disk.... you call the images by name...it's easy.

ExeMod.pas gives you an easy way to keep everything in the exe instead
of in seperates files...and it replaces the utility of res files and gives you
the ability to change the stored data at runtime...something that is really
hard to do with a res file.

There are some demos on my site that will help you
or I can make a small custom demo if you need it.  :-)
0
 
DragonSlayerCommented:
PS: Gwena, I myself can't seem to access your geocities site anymore... did you move your site?
0
 
GwenaCommented:
no..the site is still up..
I just checked to make sure :-)

http://www.geocities.com/gacarpenter386
0
 
DragonSlayerCommented:
strange... maybe my ISP is having problems with geocities? heh...
0
 
TheRealLokiSenior DeveloperCommented:
geocities has ads and/or popups. If you use a popup or ad blocker, it is likely the site will not work.
0
 
maxbAuthor Commented:
Still waiting for the DLL help... unless the streams are a better approach?

Just to finalize this up, can you guys just tell me how I create a RES file that contains JPGs, compile it into a DLL, view the image in my app?

Thank you!!
0
 
Slick812Commented:
If you can have a separate file with your images, , ,  just my opinion  , , , you might should consider using Gwena's ExeMod for a sparate file, seems like if you can do a "compare the hash of the exe" for a DLL, seems like you could on a ExeMod file.. . or do a program with a ExeMod jpg tack on, , , and  then do a hash compare on your  program with ExeMod? I would think the ExeMod would give you some more protection than a resource.

oh as far as "protection", you might use some meaning less resource types and names
instead of  "aJPEG", , use "BVOYD" or "KXRSY"

and instead of "backGround"  use  "najybfok" or "kijsr4d"
0
 
maxbAuthor Commented:
var
ResStm : TResourceStream;
hLibJpg: THandle;
Jpg1: TJPEGImage;
begin
Application.CreateForm(TMain, Main);
hLibJpg := LoadLibrary('max1.dll');
if hLibJpg = 0 then begin
  ShowMessage('ERROR - Could NOT load library');
  Exit;
end;

ResStm := TResourceStream.Create(hLibJpg, 'pic1', 'aCategory');
try
  Jpg1.LoadFromStream(ResStm);   <-- Access Violation
 // Main.drgpic.
  Main.Drg2.Canvas.Draw(199,14, Jpg1);
  ShowMessage('Loaded');
finally
  FreeLibrary(hLibJpg);
  FreeAndNil(ResStm);
  FreeAndNil(Jpg1);
end;


I keep getting an Access Violation error on the line above. Main.Drg2 is a TPaintBox
0
 
Slick812Commented:
???

how can you access something that does not exist?
In your code you do NOT create a  Jpg1, so you can not access it . . . .


Jpg1 := TJPEGImage.Create;  // you need this line
ResStm := TResourceStream.Create(hLibJpg, 'backGround', 'aJPEG');
0
 
maxbAuthor Commented:
Ok, I don't get it.

No more access errors (dumb mistake).. but even though the DLL loads (looks like fine), there is no image visible on the canvas...

However, if I draw on the current form (login), the image shows. What I really need is the image to be visible on "main" and the action launched by "login". Please help
0
 
Slick812Commented:
I can not understand what you are asking, and do not see what you are having a problem?
If you get a JPG image, that is all that loading a resource DLL and getting a resource (a JPG file in this case) form a DLL is suppose to do, onec you have the JPG , you can do anything you want to do with it, in my example, I was only doing a simple show the JPG, but you can make the

Jpg1: TJPEGImage;

a class or unit global variable, and not free it at the end of your DLL load procedurethen use it in the Main (whatever that may be), once you have the JPG, do whatever you want to with it. . . if you want to have it in your main then put the

Jpg1: TJPEGImage;

variable in your main and use it there
0
 
Slick812Commented:
if you want a persistant image then put the jpg in a TImage
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.