Author Topic: Stripping icons from Windows .EXE files  (Read 1898 times)

Clippy

  • Hero Member
  • *****
  • Posts: 16446
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #30 on: November 01, 2011, 04:57:47 PM »
OK, I saw the header being copied, but I thought siz was the header size. That's pretty slick doing it that way. So 54 is copied instead of 40 then. That might create a problem if somebody looks for it to find the BMPheader. That offset is misleading as the actual start of header and image data is one more. I ran into that problem so I looked for 40 and adjusted accordingly in icons that had more than one image, LOL.

I did it the hard way to convert icons back to bitmaps. I'll have to try it your way. Would be easier just replacing the icon header with 14 bytes of junk...but some icons don't have good or complete information in the BMP header.

You could also use TYPE information to get stuff faster:

http://qb64.net/wiki/index.php?title=Icons_and_Cursors

I'll tell you, I have been searching for a way to do this for quite some time now and YOU finally did it!
You have no reason to be ashamed of your code! GREAT JOB! Galleon should add this to QB64 immediately if not sooner! We could use icons for real and save a LOT of headaches! Then the _ICON function will really shine!

QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 DLL files in a ZIP: Program64.zip

Clippy

  • Hero Member
  • *****
  • Posts: 16446
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #31 on: November 01, 2011, 05:33:14 PM »
Only problem is that it doesn't run...
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 DLL files in a ZIP: Program64.zip

mcalkins

  • Hero Member
  • *****
  • Posts: 1302
    • qbasicmichael.com
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #32 on: November 01, 2011, 05:39:21 PM »
What doesn't run. mgi.exe?

Regards, Michael
The QBASIC Forum Community: http://www.network54.com/index/10167 Includes off-topic subforums.
QB64 Off-topic subforum: http://qb64offtopic.freeforums.org/

Clippy

  • Hero Member
  • *****
  • Posts: 16446
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #33 on: November 01, 2011, 05:49:56 PM »
Nope. I did everything like you said only I used batch files. The first batch had this:

Code: [Select]
@ECHO OFF
internal\c\bin\windres -i mgi.rc -o mgi.o

qb64 -c samples\thebob\minigolf\mg.bas

Echo Wait for program to be compiled
pause

cd internal\c
dir qbx*.cpp /O:-D

pause

I found QBX2.cpp and ran the other batch file code in internal\c folder. It placed the MGI.EXE in the QB64 folder. The MG.EXE file runs, but the other one doesn't. Had same problem with another icon adder.

Wonder if I can remove those old QBX files? They are old...I don't have ANY dated for today...

http://i301.photobucket.com/albums/nn53/burger2227/WriteTimes.jpg

They were all accessed today:

http://i301.photobucket.com/albums/nn53/burger2227/AcessTimes.jpg
« Last Edit: November 01, 2011, 06:14:08 PM by Clippy »
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 DLL files in a ZIP: Program64.zip

mcalkins

  • Hero Member
  • *****
  • Posts: 1302
    • qbasicmichael.com
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #34 on: November 01, 2011, 06:07:31 PM »
Did you verify which is the latest recompile.bat to refer to "mg.exe"?

Most of those are from last year. The most recent is from 2 days ago.

It seems that QB64 doesn't always generate a new one. I guess it's smart enough to know when you are compiling something you've already compiled. You might have to search your internal\tempn\recompile.bat files to see which one outputs "mg.exe". I can't guarantee that it would be the most recent one.

Also, in an automated process, the g command line would probably need to be copied out of the recompile.bat file (inserting the name of the object containing the icon), since the command line changes based on the program. For example, in the case of minigolf, there is that extra object file for the data, which isn't normally present.

I guess I was wrong about the "one tricky part"... :-P

The solution to this is probably up to Galleon. He is the one in the best position to automate the inclusion of icons.

Regards, Michael

P.S.

The qbxn.cpp file includes numerous .txt files from the internal\tempn folder, I think most notably main.txt. I think what is happening is that, since the program itself is in internal\tempn\main.txt (I think), qbxn doesn't need to change each time (I think it is rather generic).

Perhaps which internal\tempn\recompile.bat file is most recent would be a better indicator.

Unfortunately, dir recompile.bat /s /o:d is unsuitable, since it sorts within each subfolder, not the whole. So the order of results displayed by it is meaningless.

In other words, I was wrong about needing to find the latest qbxn.cpp. I think you need to figure out which internal\tempn\recompile.bat is the latest one that refers to -o "..\..\mg.exe". That tells you which n you need.

Use Explorer to search your qb64 folder and subfolders for all files named "recompile.bat" containing text "mg.exe" (without quotes). If there is more than one, sort them by date.

The resulting mgi.exe on my computer is 854,528 bytes. SHA1 sums wouldn't be useful, because the file should contain timestamps.

I wouldn't delete any of those qbxn.cpp files, unless Galleon says it's okay. When I upgrade to a new version of QB64, I delete everything except my own files, and extract the new .zip.

Regards,
Michael
The QBASIC Forum Community: http://www.network54.com/index/10167 Includes off-topic subforums.
QB64 Off-topic subforum: http://qb64offtopic.freeforums.org/

Clippy

  • Hero Member
  • *****
  • Posts: 16446
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #35 on: November 01, 2011, 06:28:12 PM »
I got it to work! I had to move all of the QBX files out except QBX.CPP so I only had ONE file to contend with. Apparently QB64 looks through all of them until it finds the right one.  ;D

It would NOT compile without at least one of them! But it uses it over and over apparently.

Galleon SHOULD be the one to add this capability if only to make QB64 easier to find! I can still use the icon maker too though. You will be in the WIKI again kiddo!
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 DLL files in a ZIP: Program64.zip

Clippy

  • Hero Member
  • *****
  • Posts: 16446
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #36 on: November 01, 2011, 10:06:45 PM »
One thing of note is that the icons created say they are 32 bit in the properties summary.

I tried an 8 bit one and it is 32 now too. The MiniGolf one was 4 bit.

I looked at the bytes of the Entry Header and the first 3 are all &H20 or 32. The third byte should be 16 and I cannot duplicate the difference. 2 ^ Word should be 16...

I had to zero the Byte value b to get it to put &H10 for the 4 bit one and 0 for the 8 bit ones. They still say 32 bits in the Properties. Why is the Byte value holding the previous value from the height?

Code: [Select]
PUT 2, , Byte 'height
Byte = 0
GET 1, 1 + dat + 14, Word 'number of colors from BPP
IF Word < 8 THEN Byte = 2 ^ Word ELSE Byte = 0 '256 colors = 0, 4BPP = 16
PUT 2, , Byte 'num of colors

The QB64icon.ico bitmap is 8 BPP or:
The Long value for the byte size is 1024 + 1024 palette + 40 header + 22 entry + 32 * 4 bytes wide = 2238
« Last Edit: November 02, 2011, 01:17:40 AM by Clippy »
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 DLL files in a ZIP: Program64.zip

mcalkins

  • Hero Member
  • *****
  • Posts: 1302
    • qbasicmichael.com
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #37 on: November 02, 2011, 02:17:51 AM »
I don't know. The code I posted seems to work correctly, at least for minigolf. For mgi.ico, it produces 32, 32, 16 (dec) for the first three bytes of the ICONENTRY.

PRINT w
IF w < 8 THEN b = 2 ^ w ELSE b = 0
PRINT b
SLEEP

prints:
4
16

I'd say put PRINT statements in it and see where the value is wrong.

You've clearly modified it, at least the variable names. The problems you're having are just on the modification, and not my version, right?

I'd double check to make sure Word is the right data type. Also, make sure the dat const is the correct value (14).

Regards, Michael
The QBASIC Forum Community: http://www.network54.com/index/10167 Includes off-topic subforums.
QB64 Off-topic subforum: http://qb64offtopic.freeforums.org/

Clippy

  • Hero Member
  • *****
  • Posts: 16446
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #38 on: November 02, 2011, 02:56:00 AM »
What does the file properties say? Mine says 32 BPP for a four bit and an 8 bit one.

Code: [Select]
'public domain, november 2011, michael calkins
CONST dat = 14~&
DIM Dword AS _UNSIGNED LONG
DIM siz AS _UNSIGNED LONG
DIM wid AS _UNSIGNED LONG
DIM hei AS _UNSIGNED LONG
DIM Word AS _UNSIGNED INTEGER
DIM Byte AS _UNSIGNED _BYTE
DO
  LINE INPUT "Enter existing BMP file name to convert to icon: ", BMP$
LOOP UNTIL _FILEEXISTS(BMP$)
DO
  LINE INPUT "Enter ICO file name to create (must not exist): ", ICO$
LOOP UNTIL _FILEEXISTS(ICO$) = 0

OPEN BMP$ FOR BINARY ACCESS READ AS 1 'BITMAP name
OPEN ICO$ FOR OUTPUT AS 2 'destination icon name
CLOSE 2
OPEN ICO$ FOR BINARY AS 2
GET 1, 1 + 2, siz 'skip "BM" in bitmap
siz = siz - 14 '14 bytes not used

Word = 0
PUT 2, 1, Word 'reserved
Word = 1
PUT 2, , Word 'resource id 1 as icon, 2 as cursor
PUT 2, , Word 'icon count in resource
GET 1, 1 + dat + 4, wid 'skip header size in BMP
SELECT CASE wid
  CASE IS < &H100: Byte = wid '< 256
  CASE &H100: Byte = 0
  CASE ELSE: PRINT "bitmap is larger than 256 pixels.": END
END SELECT
PUT 2, , Byte 'width
GET 1, , hei
SELECT CASE hei
  CASE IS < &H100: Byte = hei '< 256
  CASE &H100: Byte = 0 '256 = 0
  CASE ELSE: PRINT "bitmap is larger than 256 pixels.": END
END SELECT
PUT 2, , Byte 'height
Byte = 0
GET 1, 1 + dat + 14, Word 'number of colors from BPP
IF Word < 8 THEN Byte = 2 ^ Word ELSE Byte = 0 '256 colors = 0, 4BPP = 16
PUT 2, , Byte 'num of colors
Byte = 0
Dword = 0
PUT 2, , Byte 'reserved as byte
PUT 2, , Dword 'reserved 2 hotspots = 0
Dword = siz + (((wid * hei) + 7) \ 8)
PUT 2, , Dword 'size of data
Dword = 22 '6 byte header + 16
PUT 2, , Dword 'offset

'copy bitmap header down 14 bytes, palette and image info, but double height
SEEK 1, 1 + dat 'BMP info header size
FOR Dword = 1 TO siz 'actual size of data - 14 header bytes not used
  GET 1, , Byte
  IF Dword = 1 + 8 THEN
    Word = hei * 2 ' 2 times height
    PUT 2, , Word
    Dword = Dword + 1
    GET 1, , Byte
  ELSE
    PUT 2, , Byte
  END IF
NEXT

'add null AND bitmask for full square image
Byte = 0
FOR Dword = 1 TO ((hei * wid) + 7) \ 8
  PUT 2, , Byte
NEXT
CLOSE
SYSTEM

There is something else to consider. 16 and 48 wide icons pad the AND mask 2 bytes

BitsOver = Width& MOD 32

Code: [Select]
wid& = 32
hei& = 32
BitsOver = wid& MOD 32
n& = hei& * (wid& + BitsOver) \ 8
PRINT n&
« Last Edit: November 02, 2011, 03:32:00 AM by Clippy »
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 DLL files in a ZIP: Program64.zip

mcalkins

  • Hero Member
  • *****
  • Posts: 1302
    • qbasicmichael.com
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #39 on: November 02, 2011, 03:29:29 AM »
Same here. But when I save the 16 color Notepad icon with resource hacker, it says bit depth 32 for that also.

Regards,
Michael
The QBASIC Forum Community: http://www.network54.com/index/10167 Includes off-topic subforums.
QB64 Off-topic subforum: http://qb64offtopic.freeforums.org/

Clippy

  • Hero Member
  • *****
  • Posts: 16446
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #40 on: November 02, 2011, 05:19:43 AM »
This works:
Code: [Select]
'add null AND bitmask for full square image
Byte = 0
BitsOver& = wide MOD 32
IF BitsOver& THEN ANDpad& = (32 - BitsOver&) ELSE ANDpad& = 0
FOR Dword = 1 TO high * (wide + ANDpad&) \ 8
  PUT 2, , Byte
NEXT

In the picture you can see what happened to 16 X 16 icons when I used the original code. Black halfway.

http://i301.photobucket.com/albums/nn53/burger2227/16X16icons.jpg
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 DLL files in a ZIP: Program64.zip

Clippy

  • Hero Member
  • *****
  • Posts: 16446
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #41 on: November 02, 2011, 02:03:44 PM »
Here is my Icon embedding program thanks to Michael. It will create the latest program compiled!

Code: [Select]
_TITLE "QB64 Icon Embedding Program"
DO
  LINE INPUT "Enter name of icon to use without .ICO extension: ", icon$
LOOP UNTIL _FILEEXISTS(icon$ + ".ico")

Q$ = CHR$(34)
PRINT "Creating RC resource file..."
OPEN icon$ + "A.rc" FOR OUTPUT AS #1
PRINT #1, "0 ICON " + Q$ + icon$ + ".ico" + Q$
CLOSE #1
_DELAY 5
IF _FILEEXISTS(icon$ + "A.rc") THEN
  PRINT icon$ + "A.rc resource file created! Creating Object file..."
  SHELL _HIDE "internal\c\bin\windres -i " + icon$ + "A.rc -o " + icon$ + "A.o"
  DO: _LIMIT 100
  LOOP UNTIL _FILEEXISTS(icon$ + "A.o")
  PRINT icon$ + "A.o Object file created in QB64 folder!"
ELSE PRINT "Resource file not found!": END
END IF
qbx$ = "QBX64.LST"
PRINT
PRINT "List of recent program QBX files:"
CHDIR "internal\c"
SHELL _HIDE "dir qbx*.cpp /O /T:A > " + qbx$
OPEN qbx$ FOR INPUT AS #2
DO UNTIL EOF(2)
  LINE INPUT #2, text$
  PRINT text$
LOOP
CLOSE #2
DO
  LINE INPUT "Select the most recent QBX file number to use(Hit Enter if QBX.cpp!): ", qbxnum$
LOOP UNTIL _FILEEXISTS("QBX" + qbxnum$ + ".cpp")
PRINT
DO
  LINE INPUT "Enter a name for the most recent program EXE file(program adds .EXE): ", exefile$
LOOP UNTIL _FILEEXISTS(exefile$ + ".EXE") = 0

SHELL _HIDE ".\bin\g -w -Wall -I.\i -I..\..\ -L.\l ..\\temp" + qbxnum$ + "\\data.o qbx" + qbxnum$ + ".cpp libqbx.o ..\..\" + icon$ + "A.o -mwindows .\i686-w64-mingw32\lib\libimm32.a -lwinspool -lmingw32 -ln -lmix -limg -lttf -lmn -lSDL -s -o ..\..\" + exefile$ + ".exe"
'
'

This is GREAT! Thanks again Michael! You are the best!

PS: My computer don't like small icons. I re-booted and they all turned ugly...
« Last Edit: November 06, 2011, 12:00:40 PM by Clippy »
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 DLL files in a ZIP: Program64.zip

OlDosLover

  • Hero Member
  • *****
  • Posts: 4136
  • OlDosLover
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #42 on: November 03, 2011, 07:42:52 AM »
Hi all,
    I take my hat off to you Ted for that great program and the wonderful praise for mcalkins.
OlDosLover.

Clippy

  • Hero Member
  • *****
  • Posts: 16446
  • I LOVE π = 4 * ATN(1)    Use the QB64 WIKI >>>
    • Pete's Qbasic Site
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #43 on: November 03, 2011, 01:42:14 PM »
Yeah, I'm gonna dress it up so that it checks for the resource and object files when they have already been created. I may add an Open dialog box to find the icon. I'll put it in the WIKI when it is done.

Ted
QB64 WIKI: Main Page
Download Q-Basics Code Demo: Q-Basics.zip
Download QB64 BAT, IconAdder and VBS shortcuts: QB64BAT.zip
Download QB64 DLL files in a ZIP: Program64.zip

mcalkins

  • Hero Member
  • *****
  • Posts: 1302
    • qbasicmichael.com
    • Email
Re: Stripping icons from Windows .EXE files
« Reply #44 on: November 03, 2011, 03:20:05 PM »
Thanks guys. :-)

I hate raining on the parade, but there are two issues, both of which I've previously mentioned.

The first is that, I think, the search needs to be for the most recent internal\tempn\recompile.bat, not the most recent qbxn.cpp. I'll need to double check whether qb64 even regenerates that each time. If not, it'll be the most recent one that contains the name of the output file.

The second thing is that the g command line differs from program to program. It would be more reliable to copy the g command line out of the recompile.bat file, inserting the reference to the new .o file. For example, the data.o file isn't always needed. I'm guessing qb64 only creates it when the program contains DATA statements.

I'll probably contribute code to search for recompile.bat and get the g command line out of it, but it might take me a day or two to get around to it.

Regarding your second question in the developer blog, I'm guessing qb64 uses qbx.cpp (without any number) as a template when creating the numbered ones.

I think all of this will probably become much more straight forward next year when Galleon modularizes qb64. I'm thinking (hoping) he will be making it more like a traditional compiler.

My family is changing the home phone line from a Verizon land line to a Sprint mobile line. This means I can't get on the internet using dial up from home anymore. It will reduce the time and frequency of my forum access. I can still get on the internet from my dad's shop, and from the library in town.

Regards, Michael

EDIT: I was wrong. The unnumbered is basically 1.
« Last Edit: November 04, 2011, 04:37:38 PM by mcalkins »
The QBASIC Forum Community: http://www.network54.com/index/10167 Includes off-topic subforums.
QB64 Off-topic subforum: http://qb64offtopic.freeforums.org/