-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcga_remap.bas
More file actions
367 lines (301 loc) · 11.8 KB
/
cga_remap.bas
File metadata and controls
367 lines (301 loc) · 11.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
''
' CGA REMAP - Remap PNG files to 16-color CGA palette (like PowerShell remap-cga.ps1)
'
' This program takes an input directory and output directory,
' processes all PNG files in the input directory, and converts them to
' indexed PNG format using the exact 16-color CGA palette.
'
' Usage: cga_remap.exe <input_dir> <output_dir>
'
' @author grymmjack
' @version 2.0
' @description Remap PNG files to CGA 16-color palette
''
$CONSOLE
'$INCLUDE:'IMGADJ/IMGADJ.BI'
'$INCLUDE:'DUMP/DUMP.BI'
'$INCLUDE:'SYS/SYS.BI'
'$INCLUDE:'STRINGS/STRINGS.BI'
' CGA 16-color palette (exact order 0..15)
TYPE CGA_COLOR
r AS INTEGER
g AS INTEGER
b AS INTEGER
END TYPE
DIM SHARED CGA_PALETTE(0 TO 15) AS CGA_COLOR
DECLARE SUB InitCGAPalette
DECLARE FUNCTION GetCGAColor% (rval AS INTEGER, gval AS INTEGER, bval AS INTEGER)
DECLARE FUNCTION ConvertToCGA& (sourceImg AS LONG)
DECLARE SUB ProcessDirectory (inputDir AS STRING, outputDir AS STRING)
DECLARE FUNCTION GetFileExtension$ (filename AS STRING)
' Main program variables
DIM inputDir AS STRING
DIM outputDir AS STRING
' Initialize CGA palette
InitCGAPalette
' Get command line arguments
IF COMMAND$ = "" THEN
_ECHO "=== CGA REMAP - Convert PNG files to 16-color CGA palette ==="
_ECHO ""
_ECHO "Usage: " + COMMAND$(0) + " <input_directory> <output_directory>"
_ECHO ""
_ECHO "This program processes all PNG files in the input directory"
_ECHO "and converts them to indexed PNG format using the exact 16-color CGA palette."
_ECHO ""
_ECHO "Example: cga_remap.exe input_images output_images"
_ECHO ""
SYSTEM
END IF
' Parse command line arguments
DIM args AS STRING
DIM parsedInputDir AS STRING
DIM parsedOutputDir AS STRING
DIM lastBackslash AS INTEGER
DIM i AS INTEGER
DIM testPos AS INTEGER
args = LTRIM$(RTRIM$(COMMAND$))
IF LEN(args) = 0 THEN
_ECHO "ERROR: Both input and output directories must be specified!"
_ECHO "Usage: " + COMMAND$(0) + " " + CHR$(34) + "<input_directory>" + CHR$(34) + " " + CHR$(34) + "<output_directory>" + CHR$(34)
_ECHO "Note: Use quotes around paths with spaces"
SYSTEM
END IF
' Strategy: Find the last backslash in the string, then look for the space after it
' This assumes the input path ends with a directory name followed by a space
' and then the output directory starts
' Find all spaces in the command line and test each one
DIM spacePositions(1 TO 50) AS INTEGER
DIM spaceCount AS INTEGER
spaceCount = 0
FOR i = 1 TO LEN(args)
IF MID$(args, i, 1) = " " THEN
spaceCount = spaceCount + 1
IF spaceCount <= 50 THEN spacePositions(spaceCount) = i
END IF
NEXT i
' Try each space position to see which gives us valid directories
DIM found AS INTEGER
found = 0
FOR i = spaceCount TO 1 STEP -1 ' Start from the last space and work backwards
testPos = spacePositions(i)
parsedInputDir = LTRIM$(RTRIM$(LEFT$(args, testPos - 1)))
parsedOutputDir = LTRIM$(RTRIM$(MID$(args, testPos + 1)))
' Check if this gives us a valid input directory
IF _DIREXISTS(parsedInputDir) THEN
found = 1
EXIT FOR
END IF
NEXT i
IF found = 0 THEN
_ECHO "ERROR: Could not parse command line arguments correctly!"
_ECHO "Raw command line: [" + args + "]"
_ECHO ""
_ECHO "Make sure the input directory exists and use quotes around paths with spaces:"
_ECHO "Usage: " + COMMAND$(0) + " " + CHR$(34) + "<input_directory>" + CHR$(34) + " " + CHR$(34) + "<output_directory>" + CHR$(34)
' Show what we tried
_ECHO ""
_ECHO "Tried these splits:"
FOR i = 1 TO spaceCount
testPos = spacePositions(i)
DIM tryInput AS STRING, tryOutput AS STRING
tryInput = LEFT$(args, testPos - 1)
tryOutput = MID$(args, testPos + 1)
_ECHO " Input: [" + tryInput + "] Output: [" + tryOutput + "]"
NEXT i
SYSTEM
END IF
inputDir = parsedInputDir
outputDir = parsedOutputDir
_ECHO "=== CGA REMAP - Convert PNG files to 16-color CGA palette ==="
_ECHO ""
_ECHO "Input directory: " + inputDir
_ECHO "Output directory: " + outputDir
_ECHO ""
' Validate input directory
IF NOT _DIREXISTS(inputDir) THEN
_ECHO "ERROR: Input directory '" + inputDir + "' does not exist!"
SYSTEM
END IF
' Create output directory if it doesn't exist
IF NOT _DIREXISTS(outputDir) THEN
MKDIR outputDir
IF NOT _DIREXISTS(outputDir) THEN
_ECHO "ERROR: Could not create output directory '" + outputDir + "'!"
SYSTEM
END IF
_ECHO "Created output directory: " + outputDir
END IF
' Process all PNG files in the input directory
ProcessDirectory inputDir, outputDir
_ECHO ""
_ECHO "CGA remapping complete!"
SYSTEM
' Initialize CGA palette (exact 16-color CGA palette in order 0..15)
SUB InitCGAPalette
' CGA palette in desired index order (0..15) - matching PowerShell script
CGA_PALETTE(0).r = 0: CGA_PALETTE(0).g = 0: CGA_PALETTE(0).b = 0 ' Black
CGA_PALETTE(1).r = 0: CGA_PALETTE(1).g = 0: CGA_PALETTE(1).b = 170 ' Blue
CGA_PALETTE(2).r = 0: CGA_PALETTE(2).g = 170: CGA_PALETTE(2).b = 0 ' Green
CGA_PALETTE(3).r = 0: CGA_PALETTE(3).g = 170: CGA_PALETTE(3).b = 170 ' Cyan
CGA_PALETTE(4).r = 170: CGA_PALETTE(4).g = 0: CGA_PALETTE(4).b = 0 ' Red
CGA_PALETTE(5).r = 170: CGA_PALETTE(5).g = 0: CGA_PALETTE(5).b = 170 ' Magenta
CGA_PALETTE(6).r = 170: CGA_PALETTE(6).g = 85: CGA_PALETTE(6).b = 0 ' Brown
CGA_PALETTE(7).r = 170: CGA_PALETTE(7).g = 170: CGA_PALETTE(7).b = 170 ' Light Gray
CGA_PALETTE(8).r = 85: CGA_PALETTE(8).g = 85: CGA_PALETTE(8).b = 85 ' Dark Gray
CGA_PALETTE(9).r = 85: CGA_PALETTE(9).g = 85: CGA_PALETTE(9).b = 255 ' Light Blue
CGA_PALETTE(10).r = 85: CGA_PALETTE(10).g = 255: CGA_PALETTE(10).b = 85 ' Light Green
CGA_PALETTE(11).r = 85: CGA_PALETTE(11).g = 255: CGA_PALETTE(11).b = 255 ' Light Cyan
CGA_PALETTE(12).r = 255: CGA_PALETTE(12).g = 85: CGA_PALETTE(12).b = 85 ' Light Red
CGA_PALETTE(13).r = 255: CGA_PALETTE(13).g = 85: CGA_PALETTE(13).b = 255 ' Light Magenta
CGA_PALETTE(14).r = 255: CGA_PALETTE(14).g = 255: CGA_PALETTE(14).b = 85 ' Yellow
CGA_PALETTE(15).r = 255: CGA_PALETTE(15).g = 255: CGA_PALETTE(15).b = 255 ' White
END SUB
' Find closest CGA color for given RGB values (no dithering - exact match)
FUNCTION GetCGAColor% (rval AS INTEGER, gval AS INTEGER, bval AS INTEGER)
DIM bestIndex AS INTEGER
DIM bestDistance AS LONG
DIM distance AS LONG
DIM i AS INTEGER
bestDistance = 999999
bestIndex = 0
' Find closest color in the 16-color CGA palette
FOR i = 0 TO 15
' Calculate Euclidean distance in RGB space
distance = (rval - CGA_PALETTE(i).r) ^ 2 + (gval - CGA_PALETTE(i).g) ^ 2 + (bval - CGA_PALETTE(i).b) ^ 2
IF distance < bestDistance THEN
bestDistance = distance
bestIndex = i
END IF
NEXT i
GetCGAColor% = bestIndex
END FUNCTION
' Convert image to CGA 16-color palette (indexed PNG)
FUNCTION ConvertToCGA& (sourceImg AS LONG)
DIM newImg AS LONG
DIM w AS INTEGER, h AS INTEGER
DIM x AS INTEGER, y AS INTEGER
DIM pixel AS _UNSIGNED LONG
DIM r AS INTEGER, g AS INTEGER, b AS INTEGER
DIM cgaIndex AS INTEGER
DIM oldDest AS LONG
DIM i AS INTEGER
w = _WIDTH(sourceImg)
h = _HEIGHT(sourceImg)
' Create a 256-color image and set up EXACTLY the 16 CGA colors
newImg = _NEWIMAGE(w, h, 256)
oldDest = _DEST
' Set the destination and configure the 16-color CGA palette
_DEST newImg
FOR i = 0 TO 15
_PALETTECOLOR i, _RGB32(CGA_PALETTE(i).r, CGA_PALETTE(i).g, CGA_PALETTE(i).b)
NEXT i
' Set all remaining palette entries to BLACK to force 16-color usage
FOR i = 16 TO 255
_PALETTECOLOR i, _RGB32(0, 0, 0)
NEXT i
_SOURCE sourceImg
' Process each pixel and force it to use ONLY CGA palette indexes 0-15
FOR y = 0 TO h - 1
FOR x = 0 TO w - 1
pixel = POINT(x, y)
' Extract RGB components
r = _RED32(pixel)
g = _GREEN32(pixel)
b = _BLUE32(pixel)
' Find closest color index (0-15 only)
cgaIndex = GetCGAColor%(r, g, b)
' Set pixel using ONLY the 16-color palette index (0-15)
' This ensures the saved image uses exactly these 16 colors
PSET (x, y), cgaIndex
NEXT x
NEXT y
_DEST oldDest
ConvertToCGA& = newImg
END FUNCTION
' Process all PNG files in a directory
SUB ProcessDirectory (inputDir AS STRING, outputDir AS STRING)
DIM currentFile AS STRING
DIM sourceImg AS LONG
DIM cgaImg AS LONG
DIM inputPath AS STRING
DIM outputPath AS STRING
DIM filesProcessed AS INTEGER
filesProcessed = 0
' Get list of files in the directory
' Note: This is a simplified version - QB64PE doesn't have built-in directory listing
' In a real implementation, you might need to use SHELL commands or external tools
_ECHO "Scanning directory for PNG files..."
' For now, let's process files by trying common names or asking user
' This is where you'd implement proper directory scanning
' Example implementation - you would replace this with actual directory scanning
DIM testFiles() AS STRING
DIM fileCount AS INTEGER
DIM i AS INTEGER
' Dynamic array for file list
REDIM testFiles(1 TO 16) AS STRING
fileCount = 0
' Since QB64PE doesn't have built-in directory listing, we'll use a SHELL command
' to get the file list and parse it
SHELL _HIDE "dir /B " + CHR$(34) + inputDir + "\*.png" + CHR$(34) + " > temp_filelist.txt"
IF _FILEEXISTS("temp_filelist.txt") THEN
OPEN "temp_filelist.txt" FOR INPUT AS #1
DO UNTIL EOF(1)
LINE INPUT #1, currentFile
IF RTRIM$(LTRIM$(currentFile)) <> "" THEN
fileCount = fileCount + 1
IF fileCount > UBOUND(testFiles) THEN
REDIM _PRESERVE testFiles(1 TO UBOUND(testFiles) * 2) AS STRING
END IF
testFiles(fileCount) = RTRIM$(LTRIM$(currentFile))
END IF
LOOP
CLOSE #1
KILL "temp_filelist.txt"
END IF
IF fileCount = 0 THEN
_ECHO "No PNG files found in input directory."
EXIT SUB
END IF
_ECHO "Found " + STR$(fileCount) + " PNG files to process:"
_ECHO ""
' Process each file
FOR i = 1 TO fileCount
currentFile = testFiles(i)
inputPath = inputDir + "\" + currentFile
outputPath = outputDir + "\" + currentFile
_ECHO "Processing: " + currentFile
' Load source image
sourceImg = _LOADIMAGE(inputPath, 32)
IF sourceImg = -1 THEN
_ECHO " ERROR: Could not load " + currentFile
ELSE
' Convert to CGA format
cgaImg = ConvertToCGA&(sourceImg)
' Save as PNG with CGA palette
_SAVEIMAGE outputPath, cgaImg, "PNG"
_ECHO " Saved: " + outputPath + " (" + STR$(_WIDTH(cgaImg)) + "x" + STR$(_HEIGHT(cgaImg)) + ")"
' Clean up
_FREEIMAGE sourceImg
_FREEIMAGE cgaImg
filesProcessed = filesProcessed + 1
END IF
NEXT i
_ECHO ""
_ECHO "Processed " + STR$(filesProcessed) + " files successfully."
END SUB
' Get file extension from filename
FUNCTION GetFileExtension$ (filename AS STRING)
DIM i AS INTEGER
DIM ext AS STRING
FOR i = LEN(filename) TO 1 STEP -1
IF MID$(filename, i, 1) = "." THEN
ext = MID$(filename, i + 1)
EXIT FOR
END IF
NEXT i
GetFileExtension$ = UCASE$(ext)
END FUNCTION
'$INCLUDE:'IMGADJ/IMGADJ.BM'
'$INCLUDE:'DUMP/DUMP.BM'
'$INCLUDE:'SYS/SYS.BM'
'$INCLUDE:'STRINGS/STRINGS.BM'