-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathextrae_pics_v3.py
executable file
·199 lines (171 loc) · 7.51 KB
/
extrae_pics_v3.py
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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# NAPS: The New Age PAW-like System - Herramientas para sistemas PAW-like
#
# Extrae gráficos de bases de datos gráficas de DAAD, en el formato de las versiones más recientes de DAAD
# Copyright (C) 2008, 2018-2023 José Manuel Ferrer Ortiz
#
# *****************************************************************************
# * *
# * This program is free software; you can redistribute it and/or modify it *
# * under the terms of the GNU General Public License version 2, as *
# * published by the Free Software Foundation. *
# * *
# * This program is distributed in the hope that it will be useful, but *
# * WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
# * General Public License version 2 for more details. *
# * *
# * You should have received a copy of the GNU General Public License *
# * version 2 along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
# * *
# *****************************************************************************
import os
import sys
from bajo_nivel import *
from prn_func import prn
try:
import png
except:
try:
import pygame.display
import pygame.image
prn ('Si quieres guardar las imágenes en formato de paleta indexada (necesario para crea_bd_pics), instala la librería PyPNG')
except:
prn ('Se necesita o bien la librería PyPNG (preferiblemente), o la librería pygame')
sys.exit()
if len (sys.argv) < 3:
prn ('Uso:', sys.argv[0], 'base_de_datos_imágenes carpeta_destino')
sys.exit()
try:
import progressbar
hayProgreso = True
except:
hayProgreso = False
bbddimg = sys.argv[1] # Ruta a base de datos DAAD de imágenes
destino = sys.argv[2] # Ruta de destino de las imágenes extraídas
# Paletas CGA (1 y 2 con brillo) en el orden necesario
paleta1b = ((0, 0, 0), (85, 255, 255), (255, 85, 255), (254, 255, 255))
paleta2b = ((0, 0, 0), (85, 255, 85), (255, 85, 85), (255, 255, 85))
# Paleta EGA en el orden necesario
paletaEGA = (( 0, 0, 0), ( 0, 0, 170), ( 0, 170, 0), ( 0, 170, 170),
(170, 0, 0), (170, 0, 170), (170, 85, 0), (170, 170, 170),
( 85, 85, 85), ( 85, 85, 255), ( 85, 255, 85), ( 85, 255, 255),
(255, 85, 85), (255, 85, 255), (255, 255, 85), (255, 255, 255))
if 'pygame' in sys.modules:
pygame.display.init() # Necesario para poner la paleta de la imagen
fichero = open (bbddimg, 'rb') # Fichero de base de datos DAAD de imágenes
bajo_nivel_cambia_ent (fichero)
longCabeceraImg = 48 # Longitud de la cabecera de imagen
modo = fichero.read (4)
if modo not in ('\x03\x00\x00\x00', '\xff\xff\x00\x00'):
prn ('El fichero de entrada no es una base de datos de imágenes de DAAD de formato conocido')
sys.exit()
if modo == '\x03\x00\x00\x00': # Amiga/Atari ST
carga_int2 = carga_int2_be
carga_int4 = carga_int4_be
le = False
else:
carga_int2 = carga_int2_le
carga_int4 = carga_int4_le
le = True
try:
os.mkdir (destino)
except:
pass # Asumimos que ese directorio ya existe
rango = range (256) # Recorremos todas las imágenes posibles
if hayProgreso:
progreso = progressbar.ProgressBar()
rango = progreso (range (256))
for numImg in rango:
fichero.seek (10 + (longCabeceraImg * numImg)) # Parte de cabecera de la imagen
posicion = carga_int4()
if not posicion:
continue # Ninguna imagen con ese número
# Obtenemos la paleta de la imagen
fichero.seek (8, 1) # El segundo parámetro indica posición relativa
paleta = []
# FIXME: soporte de 4 bits por componente de color
for color in range (16):
# TODO: calcular valores exactos
rojo = carga_int1()
rojo = (rojo & 7) << 5
# rojo = rojo & 4 + ((rojo & 3) << 4)
veaz = carga_int1()
verde = ((veaz >> 4) & 7) << 5
azul = (veaz & 7) << 5
paleta.append ((rojo, verde, azul))
fichero.seek (posicion) # Saltamos a donde está la imagen
if le:
ancho = carga_int1() # LSB de la anchura de la imagen
valor = carga_int1()
else:
valor = carga_int1()
ancho = carga_int1() # LSB de la anchura de la imagen
ancho += (valor & 127) * 256
if ancho == 0 or ancho % 4:
prn ('El ancho de la imagen', numImg, 'no es mayor que 0 y múltiplo de 4, vale', ancho)
ancho /= 4 # Anchura de la imagen (en bloques de 4 píxeles)
rle = valor & 128
alto = carga_int2() # Altura de la imagen (en número de filas)
if alto == 0 or alto % 8:
prn ('El alto de la imagen', numImg, 'no es mayor que 0 y múltiplo de 8, vale', alto)
if 0 in (ancho, alto):
continue
repetir = []
fichero.seek (2, 1) # Saltamos valor de longitud de la imagen
if rle:
bits = carga_int2() # Máscara de colores que se repetirán
for indiceBit in range (16):
if bits & (2 ** indiceBit):
repetir.append (indiceBit)
strImg = '' # Cadena que representa toda la imagen
tamFila = ancho * 4 # Tamaño en píxeles (y bytes) que tendrá cada fila
tamImg = tamFila * alto # Tamaño en píxeles (y bytes) que tendrá la imagen
if le or rle: # Formato de DOS o comprimido
cargar = 1 if le else 4 # Cuántos bytes de valores cargar cada vez, tomando primero el último cargado
color = None # Índice de color del píxel actual
valores = [] # Valores (índices de color y contador de repeticiones) pendientes de procesar, en orden
while len (strImg) < tamImg: # Mientras quede imagen por procesar
if not valores:
try:
for i in range (cargar):
b = carga_int1() # Byte actual
valores = [b & 15, b >> 4] + valores # Los 4 bits más bajos primero, y luego los 4 más altos
except:
prn ('Imagen', numImg, 'incompleta. ¿Formato incorrecto?')
break
if color == None:
color = valores.pop (0)
continue # Por si hay que cargar un nuevo byte
if rle and color in repetir:
repeticiones = valores.pop (0) + 1
else:
repeticiones = 1
strImg += chr (color) * repeticiones
color = None
else: # Formato de Amiga/Atari ST sin comprimir
numPlanos = 4
while len (strImg) < tamImg: # Mientras quede imagen por procesar
colores = ([0] * 8)
for plano in range (numPlanos):
b = carga_int1() # Byte actual
for indiceBit in range (8):
bit = b & (2 ** indiceBit)
colores[7 - indiceBit] += (2 ** plano) if bit else 0
for pixel in range (8): # Cada píxel en el grupo
strImg += chr (colores[pixel])
bpp = 4
if 'png' in sys.modules:
listaImg = []
for numFila in range (alto):
listaImg.append (strImg[numFila * ancho * 4 : (numFila + 1) * ancho * 4])
escritor = png.Writer (ancho * 4, alto, palette = paleta, bitdepth = bpp)
salida = open ('%s/pic%03d.png' % (destino, numImg), 'wb')
escritor.write (salida, listaImg)
else:
# OJO: pygame no guarda las imágenes como paleta indexada
imagen = pygame.image.fromstring (strImg, (ancho * 4, alto), 'P')
imagen.set_palette (paleta)
pygame.image.save (imagen, '%s/pic%03d.png' % (destino, numImg))