Primer commit

This commit is contained in:
Mongar28
2024-02-03 21:52:43 -05:00
commit b5c17f85f1
3325 changed files with 855400 additions and 0 deletions

247
venv/bin/Activate.ps1 Normal file
View File

@@ -0,0 +1,247 @@
<#
.Synopsis
Activate a Python virtual environment for the current PowerShell session.
.Description
Pushes the python executable for a virtual environment to the front of the
$Env:PATH environment variable and sets the prompt to signify that you are
in a Python virtual environment. Makes use of the command line switches as
well as the `pyvenv.cfg` file values present in the virtual environment.
.Parameter VenvDir
Path to the directory that contains the virtual environment to activate. The
default value for this is the parent of the directory that the Activate.ps1
script is located within.
.Parameter Prompt
The prompt prefix to display when this virtual environment is activated. By
default, this prompt is the name of the virtual environment folder (VenvDir)
surrounded by parentheses and followed by a single space (ie. '(.venv) ').
.Example
Activate.ps1
Activates the Python virtual environment that contains the Activate.ps1 script.
.Example
Activate.ps1 -Verbose
Activates the Python virtual environment that contains the Activate.ps1 script,
and shows extra information about the activation as it executes.
.Example
Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
Activates the Python virtual environment located in the specified location.
.Example
Activate.ps1 -Prompt "MyPython"
Activates the Python virtual environment that contains the Activate.ps1 script,
and prefixes the current prompt with the specified string (surrounded in
parentheses) while the virtual environment is active.
.Notes
On Windows, it may be required to enable this Activate.ps1 script by setting the
execution policy for the user. You can do this by issuing the following PowerShell
command:
PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
For more information on Execution Policies:
https://go.microsoft.com/fwlink/?LinkID=135170
#>
Param(
[Parameter(Mandatory = $false)]
[String]
$VenvDir,
[Parameter(Mandatory = $false)]
[String]
$Prompt
)
<# Function declarations --------------------------------------------------- #>
<#
.Synopsis
Remove all shell session elements added by the Activate script, including the
addition of the virtual environment's Python executable from the beginning of
the PATH variable.
.Parameter NonDestructive
If present, do not remove this function from the global namespace for the
session.
#>
function global:deactivate ([switch]$NonDestructive) {
# Revert to original values
# The prior prompt:
if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
}
# The prior PYTHONHOME:
if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
}
# The prior PATH:
if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
Remove-Item -Path Env:_OLD_VIRTUAL_PATH
}
# Just remove the VIRTUAL_ENV altogether:
if (Test-Path -Path Env:VIRTUAL_ENV) {
Remove-Item -Path env:VIRTUAL_ENV
}
# Just remove VIRTUAL_ENV_PROMPT altogether.
if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
Remove-Item -Path env:VIRTUAL_ENV_PROMPT
}
# Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
}
# Leave deactivate function in the global namespace if requested:
if (-not $NonDestructive) {
Remove-Item -Path function:deactivate
}
}
<#
.Description
Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
given folder, and returns them in a map.
For each line in the pyvenv.cfg file, if that line can be parsed into exactly
two strings separated by `=` (with any amount of whitespace surrounding the =)
then it is considered a `key = value` line. The left hand string is the key,
the right hand is the value.
If the value starts with a `'` or a `"` then the first and last character is
stripped from the value before being captured.
.Parameter ConfigDir
Path to the directory that contains the `pyvenv.cfg` file.
#>
function Get-PyVenvConfig(
[String]
$ConfigDir
) {
Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
# Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
$pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
# An empty map will be returned if no config file is found.
$pyvenvConfig = @{ }
if ($pyvenvConfigPath) {
Write-Verbose "File exists, parse `key = value` lines"
$pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
$pyvenvConfigContent | ForEach-Object {
$keyval = $PSItem -split "\s*=\s*", 2
if ($keyval[0] -and $keyval[1]) {
$val = $keyval[1]
# Remove extraneous quotations around a string value.
if ("'""".Contains($val.Substring(0, 1))) {
$val = $val.Substring(1, $val.Length - 2)
}
$pyvenvConfig[$keyval[0]] = $val
Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
}
}
}
return $pyvenvConfig
}
<# Begin Activate script --------------------------------------------------- #>
# Determine the containing directory of this script
$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
$VenvExecDir = Get-Item -Path $VenvExecPath
Write-Verbose "Activation script is located in path: '$VenvExecPath'"
Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
# Set values required in priority: CmdLine, ConfigFile, Default
# First, get the location of the virtual environment, it might not be
# VenvExecDir if specified on the command line.
if ($VenvDir) {
Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
}
else {
Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
$VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
Write-Verbose "VenvDir=$VenvDir"
}
# Next, read the `pyvenv.cfg` file to determine any required value such
# as `prompt`.
$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
# Next, set the prompt from the command line, or the config file, or
# just use the name of the virtual environment folder.
if ($Prompt) {
Write-Verbose "Prompt specified as argument, using '$Prompt'"
}
else {
Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
$Prompt = $pyvenvCfg['prompt'];
}
else {
Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
$Prompt = Split-Path -Path $venvDir -Leaf
}
}
Write-Verbose "Prompt = '$Prompt'"
Write-Verbose "VenvDir='$VenvDir'"
# Deactivate any currently active virtual environment, but leave the
# deactivate function in place.
deactivate -nondestructive
# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
# that there is an activated venv.
$env:VIRTUAL_ENV = $VenvDir
if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
Write-Verbose "Setting prompt to '$Prompt'"
# Set the prompt to include the env name
# Make sure _OLD_VIRTUAL_PROMPT is global
function global:_OLD_VIRTUAL_PROMPT { "" }
Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
function global:prompt {
Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
_OLD_VIRTUAL_PROMPT
}
$env:VIRTUAL_ENV_PROMPT = $Prompt
}
# Clear PYTHONHOME
if (Test-Path -Path Env:PYTHONHOME) {
Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
Remove-Item -Path Env:PYTHONHOME
}
# Add the venv to the PATH
Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"

69
venv/bin/activate Normal file
View File

@@ -0,0 +1,69 @@
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
deactivate () {
# reset old environment variables
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
PATH="${_OLD_VIRTUAL_PATH:-}"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
hash -r 2> /dev/null
fi
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
PS1="${_OLD_VIRTUAL_PS1:-}"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
unset VIRTUAL_ENV_PROMPT
if [ ! "${1:-}" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV="/home/mongar/Escritorio/pruebas_oc/venv"
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH
# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
if [ -n "${PYTHONHOME:-}" ] ; then
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
unset PYTHONHOME
fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
_OLD_VIRTUAL_PS1="${PS1:-}"
PS1="(venv) ${PS1:-}"
export PS1
VIRTUAL_ENV_PROMPT="(venv) "
export VIRTUAL_ENV_PROMPT
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
hash -r 2> /dev/null
fi

View File

@@ -0,0 +1,154 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# PYTHON_ARGCOMPLETE_OK
# Copyright 2012-2023, Andrey Kislyuk and argcomplete contributors.
# Licensed under the Apache License. See https://github.com/kislyuk/argcomplete for more info.
"""
Activate the generic bash-completion script or zsh completion autoload function for the argcomplete module.
"""
import argparse
import os
import shutil
import site
import subprocess
import sys
import argcomplete
zsh_shellcode = """
# Begin added by argcomplete
fpath=( {zsh_fpath} "${{fpath[@]}}" )
# End added by argcomplete
"""
bash_shellcode = """
# Begin added by argcomplete
source "{activator}"
# End added by argcomplete
"""
def get_local_dir():
try:
return subprocess.check_output(["brew", "--prefix"]).decode().strip()
except (FileNotFoundError, subprocess.CalledProcessError):
return "/usr/local"
def get_zsh_system_dir():
return f"{get_local_dir()}/share/zsh/site-functions"
def get_bash_system_dir():
if "BASH_COMPLETION_COMPAT_DIR" in os.environ:
return os.environ["BASH_COMPLETION_COMPAT_DIR"]
elif sys.platform == "darwin":
return f"{get_local_dir()}/etc/bash_completion.d" # created by homebrew
else:
return "/etc/bash_completion.d" # created by bash-completion
def get_activator_dir():
return os.path.join(os.path.abspath(os.path.dirname(argcomplete.__file__)), "bash_completion.d")
def get_activator_path():
return os.path.join(get_activator_dir(), "_python-argcomplete")
def install_to_destination(dest):
activator = get_activator_path()
if dest == "-":
with open(activator) as fh:
sys.stdout.write(fh.read())
return
destdir = os.path.dirname(dest)
if not os.path.exists(destdir):
try:
os.makedirs(destdir, exist_ok=True)
except Exception as e:
parser.error(f"path {destdir} does not exist and could not be created: {e}")
try:
print(f"Installing {activator} to {dest}...", file=sys.stderr)
shutil.copy(activator, dest)
print("Installed.", file=sys.stderr)
except Exception as e:
parser.error(
f"while installing to {dest}: {e}. Please run this command using sudo, or see --help for more options."
)
def get_consent():
if args.yes is True:
return True
while True:
res = input("OK to proceed? [y/n] ")
if res.lower() not in {"y", "n", "yes", "no"}:
print('Please answer "yes" or "no".', file=sys.stderr)
elif res.lower() in {"y", "yes"}:
return True
else:
return False
def append_to_config_file(path, shellcode):
if os.path.exists(path):
with open(path, 'r') as fh:
if shellcode in fh.read():
print(f"The code already exists in the file {path}.", file=sys.stderr)
return
print(f"argcomplete needs to append to the file {path}. The following code will be appended:", file=sys.stderr)
for line in shellcode.splitlines():
print(">", line, file=sys.stderr)
if not get_consent():
print("Not added.", file=sys.stderr)
return
print(f"Adding shellcode to {path}...", file=sys.stderr)
with open(path, "a") as fh:
fh.write(shellcode)
print("Added.", file=sys.stderr)
def link_user_rcfiles():
# TODO: warn if running as superuser
zsh_rcfile = os.path.join(os.path.expanduser(os.environ.get("ZDOTDIR", "~")), ".zshenv")
append_to_config_file(zsh_rcfile, zsh_shellcode.format(zsh_fpath=get_activator_dir()))
bash_completion_user_file = os.path.expanduser("~/.bash_completion")
append_to_config_file(bash_completion_user_file, bash_shellcode.format(activator=get_activator_path()))
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("-y", "--yes", help="automatically answer yes for all questions", action="store_true")
parser.add_argument("--dest", help='Specify the shell completion modules directory to install into, or "-" for stdout')
parser.add_argument("--user", help="Install into user directory", action="store_true")
argcomplete.autocomplete(parser)
args = parser.parse_args()
destinations = []
if args.dest:
if args.dest != "-" and not os.path.exists(args.dest):
parser.error(f"directory {args.dest} was specified via --dest, but it does not exist")
destinations.append(args.dest)
elif site.ENABLE_USER_SITE and site.USER_SITE in argcomplete.__file__:
print(
"Argcomplete was installed in the user site local directory. Defaulting to user installation.", file=sys.stderr
)
link_user_rcfiles()
elif sys.prefix != sys.base_prefix:
print("Argcomplete was installed in a virtual environment. Defaulting to user installation.", file=sys.stderr)
link_user_rcfiles()
elif args.user:
link_user_rcfiles()
else:
print("Defaulting to system-wide installation.", file=sys.stderr)
destinations.append(f"{get_zsh_system_dir()}/_python-argcomplete")
destinations.append(f"{get_bash_system_dir()}/python-argcomplete")
for destination in destinations:
install_to_destination(destination)
if args.dest is None:
print("Please restart your shell or source the installed file to activate it.", file=sys.stderr)

26
venv/bin/activate.csh Normal file
View File

@@ -0,0 +1,26 @@
# This file must be used with "source bin/activate.csh" *from csh*.
# You cannot run it directly.
# Created by Davide Di Blasi <davidedb@gmail.com>.
# Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate'
# Unset irrelevant variables.
deactivate nondestructive
setenv VIRTUAL_ENV "/home/mongar/Escritorio/pruebas_oc/venv"
set _OLD_VIRTUAL_PATH="$PATH"
setenv PATH "$VIRTUAL_ENV/bin:$PATH"
set _OLD_VIRTUAL_PROMPT="$prompt"
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
set prompt = "(venv) $prompt"
setenv VIRTUAL_ENV_PROMPT "(venv) "
endif
alias pydoc python -m pydoc
rehash

69
venv/bin/activate.fish Normal file
View File

@@ -0,0 +1,69 @@
# This file must be used with "source <venv>/bin/activate.fish" *from fish*
# (https://fishshell.com/); you cannot run it directly.
function deactivate -d "Exit virtual environment and return to normal shell environment"
# reset old environment variables
if test -n "$_OLD_VIRTUAL_PATH"
set -gx PATH $_OLD_VIRTUAL_PATH
set -e _OLD_VIRTUAL_PATH
end
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
set -e _OLD_VIRTUAL_PYTHONHOME
end
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
set -e _OLD_FISH_PROMPT_OVERRIDE
# prevents error when using nested fish instances (Issue #93858)
if functions -q _old_fish_prompt
functions -e fish_prompt
functions -c _old_fish_prompt fish_prompt
functions -e _old_fish_prompt
end
end
set -e VIRTUAL_ENV
set -e VIRTUAL_ENV_PROMPT
if test "$argv[1]" != "nondestructive"
# Self-destruct!
functions -e deactivate
end
end
# Unset irrelevant variables.
deactivate nondestructive
set -gx VIRTUAL_ENV "/home/mongar/Escritorio/pruebas_oc/venv"
set -gx _OLD_VIRTUAL_PATH $PATH
set -gx PATH "$VIRTUAL_ENV/bin" $PATH
# Unset PYTHONHOME if set.
if set -q PYTHONHOME
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
set -e PYTHONHOME
end
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
# fish uses a function instead of an env var to generate the prompt.
# Save the current fish_prompt function as the function _old_fish_prompt.
functions -c fish_prompt _old_fish_prompt
# With the original prompt function renamed, we can override with our own.
function fish_prompt
# Save the return status of the last command.
set -l old_status $status
# Output the venv prompt; color taken from the blue of the Python logo.
printf "%s%s%s" (set_color 4B8BBE) "(venv) " (set_color normal)
# Restore the return status of the previous command.
echo "exit $old_status" | .
# Output the original/"old" prompt.
_old_fish_prompt
end
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
set -gx VIRTUAL_ENV_PROMPT "(venv) "
end

8
venv/bin/futurize Executable file
View File

@@ -0,0 +1,8 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from libfuturize.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
venv/bin/pasteurize Executable file
View File

@@ -0,0 +1,8 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from libpasteurize.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
venv/bin/pip Executable file
View File

@@ -0,0 +1,8 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
venv/bin/pip3 Executable file
View File

@@ -0,0 +1,8 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
venv/bin/pip3.11 Executable file
View File

@@ -0,0 +1,8 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from pip._internal.cli.main import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

266
venv/bin/prichunkpng Executable file
View File

@@ -0,0 +1,266 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# prichunkpng
# Chunk editing tool.
"""
Make a new PNG by adding, delete, or replacing particular chunks.
"""
import argparse
import collections
# https://docs.python.org/2.7/library/io.html
import io
import re
import string
import struct
import sys
import zlib
# Local module.
import png
Chunk = collections.namedtuple("Chunk", "type content")
class ArgumentError(Exception):
"""A user problem with the command arguments."""
def process(out, args):
"""Process the PNG file args.input to the output, chunk by chunk.
Chunks can be inserted, removed, replaced, or sometimes edited.
Chunks are specified by their 4 byte Chunk Type;
see https://www.w3.org/TR/2003/REC-PNG-20031110/#5Chunk-layout .
The chunks in args.delete will be removed from the stream.
The chunks in args.chunk will be inserted into the stream
with their contents taken from the named files.
Other options on the args object will create particular
ancillary chunks.
.gamma -> gAMA chunk
.sigbit -> sBIT chunk
Chunk types need not be official PNG chunks at all.
Non-standard chunks can be created.
"""
# Convert options to chunks in the args.chunk list
if args.gamma:
v = int(round(1e5 * args.gamma))
bs = io.BytesIO(struct.pack(">I", v))
args.chunk.insert(0, Chunk(b"gAMA", bs))
if args.sigbit:
v = struct.pack("%dB" % len(args.sigbit), *args.sigbit)
bs = io.BytesIO(v)
args.chunk.insert(0, Chunk(b"sBIT", bs))
if args.iccprofile:
# http://www.w3.org/TR/PNG/#11iCCP
v = b"a color profile\x00\x00" + zlib.compress(args.iccprofile.read())
bs = io.BytesIO(v)
args.chunk.insert(0, Chunk(b"iCCP", bs))
if args.transparent:
# https://www.w3.org/TR/2003/REC-PNG-20031110/#11tRNS
v = struct.pack(">%dH" % len(args.transparent), *args.transparent)
bs = io.BytesIO(v)
args.chunk.insert(0, Chunk(b"tRNS", bs))
if args.background:
# https://www.w3.org/TR/2003/REC-PNG-20031110/#11bKGD
v = struct.pack(">%dH" % len(args.background), *args.background)
bs = io.BytesIO(v)
args.chunk.insert(0, Chunk(b"bKGD", bs))
if args.physical:
# https://www.w3.org/TR/PNG/#11pHYs
numbers = re.findall(r"(\d+\.?\d*)", args.physical)
if len(numbers) not in {1, 2}:
raise ArgumentError("One or two numbers are required for --physical")
xppu = float(numbers[0])
if len(numbers) == 1:
yppu = xppu
else:
yppu = float(numbers[1])
unit_spec = 0
if args.physical.endswith("dpi"):
# Convert from DPI to Pixels Per Metre
# 1 inch is 0.0254 metres
l = 0.0254
xppu /= l
yppu /= l
unit_spec = 1
elif args.physical.endswith("ppm"):
unit_spec = 1
v = struct.pack("!LLB", round(xppu), round(yppu), unit_spec)
bs = io.BytesIO(v)
args.chunk.insert(0, Chunk(b"pHYs", bs))
# Create:
# - a set of chunks to delete
# - a dict of chunks to replace
# - a list of chunk to add
delete = set(args.delete)
# The set of chunks to replace are those where the specification says
# that there should be at most one of them.
replacing = set([b"gAMA", b"pHYs", b"sBIT", b"PLTE", b"tRNS", b"sPLT", b"IHDR"])
replace = dict()
add = []
for chunk in args.chunk:
if chunk.type in replacing:
replace[chunk.type] = chunk
else:
add.append(chunk)
input = png.Reader(file=args.input)
return png.write_chunks(out, edit_chunks(input.chunks(), delete, replace, add))
def edit_chunks(chunks, delete, replace, add):
"""
Iterate over chunks, yielding edited chunks.
Subtle: the new chunks have to have their contents .read().
"""
for type, v in chunks:
if type in delete:
continue
if type in replace:
yield type, replace[type].content.read()
del replace[type]
continue
if b"IDAT" <= type <= b"IDAT" and replace:
# If there are any chunks on the replace list by
# the time we reach IDAT, add then all now.
# put them all on the add list.
for chunk in replace.values():
yield chunk.type, chunk.content.read()
replace = dict()
if b"IDAT" <= type <= b"IDAT" and add:
# We reached IDAT; add all remaining chunks now.
for chunk in add:
yield chunk.type, chunk.content.read()
add = []
yield type, v
def chunk_name(s):
"""
Type check a chunk name option value.
"""
# See https://www.w3.org/TR/2003/REC-PNG-20031110/#table51
valid = len(s) == 4 and set(s) <= set(string.ascii_letters)
if not valid:
raise ValueError("Chunk name must be 4 ASCII letters")
return s.encode("ascii")
def comma_list(s):
"""
Convert s, a command separated list of whole numbers,
into a sequence of int.
"""
return tuple(int(v) for v in s.split(","))
def hex_color(s):
"""
Type check and convert a hex color.
"""
if s.startswith("#"):
s = s[1:]
valid = len(s) in [1, 2, 3, 4, 6, 12] and set(s) <= set(string.hexdigits)
if not valid:
raise ValueError("colour must be 1,2,3,4,6, or 12 hex-digits")
# For the 4-bit RGB, expand to 8-bit, by repeating digits.
if len(s) == 3:
s = "".join(c + c for c in s)
if len(s) in [1, 2, 4]:
# Single grey value.
return (int(s, 16),)
if len(s) in [6, 12]:
w = len(s) // 3
return tuple(int(s[i : i + w], 16) for i in range(0, len(s), w))
def main(argv=None):
if argv is None:
argv = sys.argv
argv = argv[1:]
parser = argparse.ArgumentParser()
parser.add_argument("--gamma", type=float, help="Gamma value for gAMA chunk")
parser.add_argument(
"--physical",
type=str,
metavar="x[,y][dpi|ppm]",
help="specify intended pixel size or aspect ratio",
)
parser.add_argument(
"--sigbit",
type=comma_list,
metavar="D[,D[,D[,D]]]",
help="Number of significant bits in each channel",
)
parser.add_argument(
"--iccprofile",
metavar="file.iccp",
type=argparse.FileType("rb"),
help="add an ICC Profile from a file",
)
parser.add_argument(
"--transparent",
type=hex_color,
metavar="#RRGGBB",
help="Specify the colour that is transparent (tRNS chunk)",
)
parser.add_argument(
"--background",
type=hex_color,
metavar="#RRGGBB",
help="background colour for bKGD chunk",
)
parser.add_argument(
"--delete",
action="append",
default=[],
type=chunk_name,
help="delete the chunk",
)
parser.add_argument(
"--chunk",
action="append",
nargs=2,
default=[],
type=str,
help="insert chunk, taking contents from file",
)
parser.add_argument(
"input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args(argv)
# Reprocess the chunk arguments, converting each pair into a Chunk.
args.chunk = [
Chunk(chunk_name(type), open(path, "rb")) for type, path in args.chunk
]
return process(png.binary_stdout(), args)
if __name__ == "__main__":
main()

81
venv/bin/pricolpng Executable file
View File

@@ -0,0 +1,81 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# http://www.python.org/doc/2.4.4/lib/module-itertools.html
import itertools
import sys
import png
Description = """Join PNG images in a column top-to-bottom."""
class FormatError(Exception):
"""
Some problem with the image format.
"""
def join_col(out, l):
"""
Join the list of images.
All input images must be same width and
have the same number of channels.
They are joined top-to-bottom.
`out` is the (open file) destination for the output image.
`l` should be a list of open files (the input image files).
"""
image = 0
stream = 0
# When the first image is read, this will be the reference width,
# which must be the same for all images.
width = None
# Total height (accumulated as images are read).
height = 0
# Accumulated rows.
rows = []
for f in l:
stream += 1
while True:
im = png.Reader(file=f)
try:
im.preamble()
except EOFError:
break
image += 1
if not width:
width = im.width
elif width != im.width:
raise FormatError('Image %d in stream %d has width %d; does not match %d.' %
(image, stream, im.width, width))
height += im.height
# Various bugs here because different numbers of channels and depths go wrong.
w, h, p, info = im.asDirect()
rows.extend(p)
# Alarmingly re-use the last info object.
tinfo = dict(info)
del tinfo['size']
w = png.Writer(width, height, **tinfo)
w.write(out, rows)
def main(argv):
import argparse
parser = argparse.ArgumentParser(description=Description)
parser.add_argument(
"input", nargs="*", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args()
return join_col(png.binary_stdout(), args.input)
if __name__ == '__main__':
main(sys.argv)

254
venv/bin/priditherpng Executable file
View File

@@ -0,0 +1,254 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# pipdither
# Error Diffusing image dithering.
# Now with serpentine scanning.
# See http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT
# http://www.python.org/doc/2.4.4/lib/module-bisect.html
from bisect import bisect_left
import png
def dither(
out,
input,
bitdepth=1,
linear=False,
defaultgamma=1.0,
targetgamma=None,
cutoff=0.5, # see :cutoff:default
):
"""Dither the input PNG `inp` into an image with a smaller bit depth
and write the result image onto `out`. `bitdepth` specifies the bit
depth of the new image.
Normally the source image gamma is honoured (the image is
converted into a linear light space before being dithered), but
if the `linear` argument is true then the image is treated as
being linear already: no gamma conversion is done (this is
quicker, and if you don't care much about accuracy, it won't
matter much).
Images with no gamma indication (no ``gAMA`` chunk) are normally
treated as linear (gamma = 1.0), but often it can be better
to assume a different gamma value: For example continuous tone
photographs intended for presentation on the web often carry
an implicit assumption of being encoded with a gamma of about
0.45 (because that's what you get if you just "blat the pixels"
onto a PC framebuffer), so ``defaultgamma=0.45`` might be a
good idea. `defaultgamma` does not override a gamma value
specified in the file itself: It is only used when the file
does not specify a gamma.
If you (pointlessly) specify both `linear` and `defaultgamma`,
`linear` wins.
The gamma of the output image is, by default, the same as the input
image. The `targetgamma` argument can be used to specify a
different gamma for the output image. This effectively recodes the
image to a different gamma, dithering as we go. The gamma specified
is the exponent used to encode the output file (and appears in the
output PNG's ``gAMA`` chunk); it is usually less than 1.
"""
# Encoding is what happened when the PNG was made (and also what
# happens when we output the PNG). Decoding is what we do to the
# source PNG in order to process it.
# The dithering algorithm is not completely general; it
# can only do bit depth reduction, not arbitrary palette changes.
import operator
maxval = 2 ** bitdepth - 1
r = png.Reader(file=input)
_, _, pixels, info = r.asDirect()
planes = info["planes"]
# :todo: make an Exception
assert planes == 1
width = info["size"][0]
sourcemaxval = 2 ** info["bitdepth"] - 1
if linear:
gamma = 1
else:
gamma = info.get("gamma") or defaultgamma
# Calculate an effective gamma for input and output;
# then build tables using those.
# `gamma` (whether it was obtained from the input file or an
# assumed value) is the encoding gamma.
# We need the decoding gamma, which is the reciprocal.
decode = 1.0 / gamma
# `targetdecode` is the assumed gamma that is going to be used
# to decoding the target PNG.
# Note that even though we will _encode_ the target PNG we
# still need the decoding gamma, because
# the table we use maps from PNG pixel value to linear light level.
if targetgamma is None:
targetdecode = decode
else:
targetdecode = 1.0 / targetgamma
incode = build_decode_table(sourcemaxval, decode)
# For encoding, we still build a decode table, because we
# use it inverted (searching with bisect).
outcode = build_decode_table(maxval, targetdecode)
# The table used for choosing output codes. These values represent
# the cutoff points between two adjacent output codes.
# The cutoff parameter can be varied between 0 and 1 to
# preferentially choose lighter (when cutoff > 0.5) or
# darker (when cutoff < 0.5) values.
# :cutoff:default: The default for this used to be 0.75, but
# testing by drj on 2021-07-30 showed that this produces
# banding when dithering left-to-right gradients;
# test with:
# priforgepng grl | priditherpng | kitty icat
choosecode = list(zip(outcode[1:], outcode))
p = cutoff
choosecode = [x[0] * p + x[1] * (1.0 - p) for x in choosecode]
rows = repeat_header(pixels)
dithered_rows = run_dither(incode, choosecode, outcode, width, rows)
dithered_rows = remove_header(dithered_rows)
info["bitdepth"] = bitdepth
info["gamma"] = 1.0 / targetdecode
w = png.Writer(**info)
w.write(out, dithered_rows)
def build_decode_table(maxval, gamma):
"""Build a lookup table for decoding;
table converts from pixel values to linear space.
"""
assert maxval == int(maxval)
assert maxval > 0
f = 1.0 / maxval
table = [f * v for v in range(maxval + 1)]
if gamma != 1.0:
table = [v ** gamma for v in table]
return table
def run_dither(incode, choosecode, outcode, width, rows):
"""
Run an serpentine dither.
Using the incode and choosecode tables.
"""
# Errors diffused downwards (into next row)
ed = [0.0] * width
flipped = False
for row in rows:
# Convert to linear...
row = [incode[v] for v in row]
# Add errors...
row = [e + v for e, v in zip(ed, row)]
if flipped:
row = row[::-1]
targetrow = [0] * width
for i, v in enumerate(row):
# `it` will be the index of the chosen target colour;
it = bisect_left(choosecode, v)
targetrow[i] = it
t = outcode[it]
# err is the error that needs distributing.
err = v - t
# Sierra "Filter Lite" distributes * 2
# as per this diagram. 1 1
ef = err * 0.5
# :todo: consider making rows one wider at each end and
# removing "if"s
if i + 1 < width:
row[i + 1] += ef
ef *= 0.5
ed[i] = ef
if i:
ed[i - 1] += ef
if flipped:
ed = ed[::-1]
targetrow = targetrow[::-1]
yield targetrow
flipped = not flipped
WARMUP_ROWS = 32
def repeat_header(rows):
"""Repeat the first row, to "warm up" the error register."""
for row in rows:
yield row
for _ in range(WARMUP_ROWS):
yield row
break
yield from rows
def remove_header(rows):
"""Remove the same number of rows that repeat_header added."""
for _ in range(WARMUP_ROWS):
next(rows)
yield from rows
def main(argv=None):
import sys
# https://docs.python.org/3.5/library/argparse.html
import argparse
parser = argparse.ArgumentParser()
if argv is None:
argv = sys.argv
progname, *args = argv
parser.add_argument("--bitdepth", type=int, default=1, help="bitdepth of output")
parser.add_argument(
"--cutoff",
type=float,
default=0.5,
help="cutoff to select adjacent output values",
)
parser.add_argument(
"--defaultgamma",
type=float,
default=1.0,
help="gamma value to use when no gamma in input",
)
parser.add_argument("--linear", action="store_true", help="force linear input")
parser.add_argument(
"--targetgamma",
type=float,
help="gamma to use in output (target), defaults to input gamma",
)
parser.add_argument(
"input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
)
ns = parser.parse_args(args)
return dither(png.binary_stdout(), **vars(ns))
if __name__ == "__main__":
main()

275
venv/bin/priforgepng Executable file
View File

@@ -0,0 +1,275 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# priforgepng
"""Forge PNG image from raw computation."""
from array import array
from fractions import Fraction
import argparse
import re
import sys
import png
def gen_glr(x):
"""Gradient Left to Right"""
return x
def gen_grl(x):
"""Gradient Right to Left"""
return 1 - x
def gen_gtb(x, y):
"""Gradient Top to Bottom"""
return y
def gen_gbt(x, y):
"""Gradient Bottom to Top"""
return 1.0 - y
def gen_rtl(x, y):
"""Radial gradient, centred at Top-Left"""
return max(1 - (float(x) ** 2 + float(y) ** 2) ** 0.5, 0.0)
def gen_rctr(x, y):
"""Radial gradient, centred at Centre"""
return gen_rtl(float(x) - 0.5, float(y) - 0.5)
def gen_rtr(x, y):
"""Radial gradient, centred at Top-Right"""
return gen_rtl(1.0 - float(x), y)
def gen_rbl(x, y):
"""Radial gradient, centred at Bottom-Left"""
return gen_rtl(x, 1.0 - float(y))
def gen_rbr(x, y):
"""Radial gradient, centred at Bottom-Right"""
return gen_rtl(1.0 - float(x), 1.0 - float(y))
def stripe(x, n):
return int(x * n) & 1
def gen_vs2(x):
"""2 Vertical Stripes"""
return stripe(x, 2)
def gen_vs4(x):
"""4 Vertical Stripes"""
return stripe(x, 4)
def gen_vs10(x):
"""10 Vertical Stripes"""
return stripe(x, 10)
def gen_hs2(x, y):
"""2 Horizontal Stripes"""
return stripe(float(y), 2)
def gen_hs4(x, y):
"""4 Horizontal Stripes"""
return stripe(float(y), 4)
def gen_hs10(x, y):
"""10 Horizontal Stripes"""
return stripe(float(y), 10)
def gen_slr(x, y):
"""10 diagonal stripes, rising from Left to Right"""
return stripe(x + y, 10)
def gen_srl(x, y):
"""10 diagonal stripes, rising from Right to Left"""
return stripe(1 + x - y, 10)
def checker(x, y, n):
return stripe(x, n) ^ stripe(y, n)
def gen_ck8(x, y):
"""8 by 8 checkerboard"""
return checker(x, y, 8)
def gen_ck15(x, y):
"""15 by 15 checkerboard"""
return checker(x, y, 15)
def gen_zero(x):
"""All zero (black)"""
return 0
def gen_one(x):
"""All one (white)"""
return 1
def yield_fun_rows(size, bitdepth, pattern):
"""
Create a single channel (monochrome) test pattern.
Yield each row in turn.
"""
width, height = size
maxval = 2 ** bitdepth - 1
if maxval > 255:
typecode = "H"
else:
typecode = "B"
pfun = pattern_function(pattern)
# The coordinates are an integer + 0.5,
# effectively sampling each pixel at its centre.
# This is morally better, and produces all 256 sample values
# in a 256-pixel wide gradient.
# We make a list of x coordinates here and re-use it,
# because Fraction instances are slow to allocate.
xs = [Fraction(x, 2 * width) for x in range(1, 2 * width, 2)]
# The general case is a function in x and y,
# but if the function only takes an x argument,
# it's handled in a special case that is a lot faster.
if n_args(pfun) == 2:
for y in range(height):
a = array(typecode)
fy = Fraction(Fraction(y + 0.5), height)
for fx in xs:
a.append(int(round(maxval * pfun(fx, fy))))
yield a
return
# For functions in x only, it's a _lot_ faster
# to generate a single row and repeatedly yield it
a = array(typecode)
for fx in xs:
a.append(int(round(maxval * pfun(x=fx))))
for y in range(height):
yield a
return
def generate(args):
"""
Create a PNG test image and write the file to stdout.
`args` should be an argparse Namespace instance or similar.
"""
size = args.size
bitdepth = args.depth
out = png.binary_stdout()
for pattern in args.pattern:
rows = yield_fun_rows(size, bitdepth, pattern)
writer = png.Writer(
size[0], size[1], bitdepth=bitdepth, greyscale=True, alpha=False
)
writer.write(out, rows)
def n_args(fun):
"""Number of arguments in fun's argument list."""
return fun.__code__.co_argcount
def pattern_function(pattern):
"""From `pattern`, a string,
return the function for that pattern.
"""
lpat = pattern.lower()
for name, fun in globals().items():
parts = name.split("_")
if parts[0] != "gen":
continue
if parts[1] == lpat:
return fun
def patterns():
"""
List the patterns.
"""
for name, fun in globals().items():
parts = name.split("_")
if parts[0] == "gen":
yield parts[1], fun.__doc__
def dimensions(s):
"""
Typecheck the --size option, which should be
one or two comma separated numbers.
Example: "64,40".
"""
tupl = re.findall(r"\d+", s)
if len(tupl) not in (1, 2):
raise ValueError("%r should be width or width,height" % s)
if len(tupl) == 1:
tupl *= 2
assert len(tupl) == 2
return list(map(int, tupl))
def main(argv=None):
if argv is None:
argv = sys.argv
parser = argparse.ArgumentParser(description="Forge greyscale PNG patterns")
parser.add_argument(
"-l", "--list", action="store_true", help="print list of patterns and exit"
)
parser.add_argument(
"-d", "--depth", default=8, type=int, metavar="N", help="N bits per pixel"
)
parser.add_argument(
"-s",
"--size",
default=[256, 256],
type=dimensions,
metavar="w[,h]",
help="width and height of the image in pixels",
)
parser.add_argument("pattern", nargs="*", help="name of pattern")
args = parser.parse_args(argv[1:])
if args.list:
for name, doc in sorted(patterns()):
print(name, doc, sep="\t")
return
if not args.pattern:
parser.error("--list or pattern is required")
return generate(args)
if __name__ == "__main__":
main()

72
venv/bin/prigreypng Executable file
View File

@@ -0,0 +1,72 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# prigreypng
# Convert image to grey (L, or LA), but only if that involves no colour change.
import argparse
import array
import png
def as_grey(out, inp):
"""
Convert image to greyscale, but only when no colour change.
This works by using the input G channel (green) as
the output L channel (luminance) and
checking that every pixel is grey as we go.
A non-grey pixel will raise an error.
"""
r = png.Reader(file=inp)
_, _, rows, info = r.asDirect()
if info["greyscale"]:
w = png.Writer(**info)
return w.write(out, rows)
planes = info["planes"]
targetplanes = planes - 2
alpha = info["alpha"]
width, height = info["size"]
typecode = "BH"[info["bitdepth"] > 8]
# Values per target row
vpr = width * targetplanes
def iterasgrey():
for i, row in enumerate(rows):
row = array.array(typecode, row)
targetrow = array.array(typecode, [0] * vpr)
# Copy G (and possibly A) channel.
green = row[0::planes]
if alpha:
targetrow[0::2] = green
targetrow[1::2] = row[3::4]
else:
targetrow = green
# Check R and B channel match.
if green != row[0::planes] or green != row[2::planes]:
raise ValueError("Row %i contains non-grey pixel." % i)
yield targetrow
info["greyscale"] = True
del info["planes"]
w = png.Writer(**info)
return w.write(out, iterasgrey())
def main(argv=None):
parser = argparse.ArgumentParser()
parser.add_argument(
"input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args()
return as_grey(png.binary_stdout(), args.input)
if __name__ == "__main__":
import sys
sys.exit(main())

111
venv/bin/pripalpng Executable file
View File

@@ -0,0 +1,111 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# pripalpng
"""Convert to Palette PNG (without changing colours)"""
import argparse
import collections
# https://docs.python.org/2.7/library/io.html
import io
import string
import zlib
# Local module.
import png
def make_inverse_palette(rows, channels):
"""
The inverse palette maps from tuple to palette index.
"""
palette = {}
for row in rows:
for pixel in png.group(row, channels):
if pixel in palette:
continue
palette[pixel] = len(palette)
return palette
def palette_convert(out, inp, palette_file):
"""
Convert PNG image in `inp` to use a palette, colour type 3,
and write converted image to `out`.
`palette_file` is a file descriptor for the palette to use.
If `palette_file` is None, then `inp` is used as the palette.
"""
if palette_file is None:
inp, palette_file = palette_file, inp
reader = png.Reader(file=palette_file)
w, h, rows, info = asRGBorA8(reader)
channels = info["planes"]
if not inp:
rows = list(rows)
palette_map = make_inverse_palette(rows, channels)
if inp:
reader = png.Reader(file=inp)
w, h, rows, info = asRGBorA8(reader)
channels = info["planes"]
# Default for colours not in palette is to use last entry.
last = len(palette_map) - 1
def map_pixel(p):
return palette_map.get(p, last)
def convert_rows():
for row in rows:
yield [map_pixel(p) for p in png.group(row, channels)]
# Make a palette by sorting the pixels according to their index.
palette = sorted(palette_map.keys(), key=palette_map.get)
pal_info = dict(size=info["size"], palette=palette)
w = png.Writer(**pal_info)
w.write(out, convert_rows())
def asRGBorA8(reader):
"""
Return (width, height, rows, info) converting to RGB,
or RGBA if original has an alpha channel.
"""
_, _, _, info = reader.read()
if info["alpha"]:
return reader.asRGBA8()
else:
return reader.asRGB8()
def main(argv=None):
import sys
import re
if argv is None:
argv = sys.argv
argv = argv[1:]
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--palette", type=png.cli_open)
parser.add_argument(
"input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args(argv)
palette_convert(png.binary_stdout(), args.input, args.palette)
if __name__ == "__main__":
main()

355
venv/bin/pripamtopng Executable file
View File

@@ -0,0 +1,355 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# pripamtopng
#
# Python Raster Image PAM to PNG
import array
import struct
import sys
import png
Description = """Convert NetPBM PAM/PNM format files to PNG."""
def read_pam_header(infile):
"""
Read (the rest of a) PAM header.
`infile` should be positioned immediately after the initial 'P7' line
(at the beginning of the second line).
Returns are as for `read_pnm_header`.
"""
# Unlike PBM, PGM, and PPM, we can read the header a line at a time.
header = dict()
while True:
line = infile.readline().strip()
if line == b"ENDHDR":
break
if not line:
raise EOFError("PAM ended prematurely")
if line[0] == b"#":
continue
line = line.split(None, 1)
key = line[0]
if key not in header:
header[key] = line[1]
else:
header[key] += b" " + line[1]
required = [b"WIDTH", b"HEIGHT", b"DEPTH", b"MAXVAL"]
required_str = b", ".join(required).decode("ascii")
result = []
for token in required:
if token not in header:
raise png.Error("PAM file must specify " + required_str)
try:
x = int(header[token])
except ValueError:
raise png.Error(required_str + " must all be valid integers")
if x <= 0:
raise png.Error(required_str + " must all be positive integers")
result.append(x)
return (b"P7",) + tuple(result)
def read_pnm_header(infile):
"""
Read a PNM header, returning (format,width,height,depth,maxval).
Also reads a PAM header (by using a helper function).
`width` and `height` are in pixels.
`depth` is the number of channels in the image;
for PBM and PGM it is synthesized as 1, for PPM as 3;
for PAM images it is read from the header.
`maxval` is synthesized (as 1) for PBM images.
"""
# Generally, see http://netpbm.sourceforge.net/doc/ppm.html
# and http://netpbm.sourceforge.net/doc/pam.html
# Technically 'P7' must be followed by a newline,
# so by using rstrip() we are being liberal in what we accept.
# I think this is acceptable.
magic = infile.read(3).rstrip()
if magic == b"P7":
# PAM header parsing is completely different.
return read_pam_header(infile)
# Expected number of tokens in header (3 for P4, 4 for P6)
expected = 4
pbm = (b"P1", b"P4")
if magic in pbm:
expected = 3
header = [magic]
# We must read the rest of the header byte by byte because
# the final whitespace character may not be a newline.
# Of course all PNM files in the wild use a newline at this point,
# but we are strong and so we avoid
# the temptation to use readline.
bs = bytearray()
backs = bytearray()
def next():
if backs:
c = bytes(backs[0:1])
del backs[0]
else:
c = infile.read(1)
if not c:
raise png.Error("premature EOF reading PNM header")
bs.extend(c)
return c
def backup():
"""Push last byte of token onto front of backs."""
backs.insert(0, bs[-1])
del bs[-1]
def ignore():
del bs[:]
def tokens():
ls = lexInit
while True:
token, ls = ls()
if token:
yield token
def lexInit():
c = next()
# Skip comments
if b"#" <= c <= b"#":
while c not in b"\n\r":
c = next()
ignore()
return None, lexInit
# Skip whitespace (that precedes a token)
if c.isspace():
ignore()
return None, lexInit
if not c.isdigit():
raise png.Error("unexpected byte %r found in header" % c)
return None, lexNumber
def lexNumber():
# According to the specification it is legal to have comments
# that appear in the middle of a token.
# I've never seen it; and,
# it's a bit awkward to code good lexers in Python (no goto).
# So we break on such cases.
c = next()
while c.isdigit():
c = next()
backup()
token = bs[:]
ignore()
return token, lexInit
for token in tokens():
# All "tokens" are decimal integers, so convert them here.
header.append(int(token))
if len(header) == expected:
break
final = next()
if not final.isspace():
raise png.Error("expected header to end with whitespace, not %r" % final)
if magic in pbm:
# synthesize a MAXVAL
header.append(1)
depth = (1, 3)[magic == b"P6"]
return header[0], header[1], header[2], depth, header[3]
def convert_pnm_plain(w, infile, outfile):
"""
Convert a plain PNM file containing raw pixel data into
a PNG file with the parameters set in the writer object.
Works for plain PGM formats.
"""
# See convert_pnm_binary for the corresponding function for
# binary PNM formats.
rows = scan_rows_from_file_plain(infile, w.width, w.height, w.planes)
w.write(outfile, rows)
def scan_rows_from_file_plain(infile, width, height, planes):
"""
Generate a sequence of rows from the input file `infile`.
The input file should be in a "Netpbm-like" plain format.
The input file should be positioned at the beginning of the
first value (that is, immediately after the header).
The number of pixels to read is taken from
the image dimensions (`width`, `height`, `planes`).
Each row is yielded as a single sequence of values.
"""
# Values per row
vpr = width * planes
values = []
rows_output = 0
# The core problem is that input lines (text lines) may not
# correspond with pixel rows. We use two nested loops.
# The outer loop reads the input one text line at a time;
# this will contain a whole number of values, which are
# added to the `values` list.
# The inner loop strips the first `vpr` values from the
# list, until there aren't enough.
# Note we can't tell how many iterations the inner loop will
# run for, it could be 0 (if not enough values were read to
# make a whole pixel row) or many (if the entire image were
# on one input line), or somewhere in between.
# In PNM there is in general no requirement to have
# correspondence between text lines and pixel rows.
for inp in infile:
values.extend(map(int, inp.split()))
while len(values) >= vpr:
yield values[:vpr]
del values[:vpr]
rows_output += 1
if rows_output >= height:
# Diagnostic here if there are spare values?
return
# Diagnostic here for early EOF?
def convert_pnm_binary(w, infile, outfile):
"""
Convert a PNM file containing raw pixel data into
a PNG file with the parameters set in the writer object.
Works for (binary) PGM, PPM, and PAM formats.
"""
rows = scan_rows_from_file(infile, w.width, w.height, w.planes, w.bitdepth)
w.write(outfile, rows)
def scan_rows_from_file(infile, width, height, planes, bitdepth):
"""
Generate a sequence of rows from the input file `infile`.
The input file should be in a "Netpbm-like" binary format.
The input file should be positioned at the beginning of the first pixel.
The number of pixels to read is taken from
the image dimensions (`width`, `height`, `planes`);
the number of bytes per value is implied by `bitdepth`.
Each row is yielded as a single sequence of values.
"""
# Values per row
vpr = width * planes
# Bytes per row
bpr = vpr
if bitdepth > 8:
assert bitdepth == 16
bpr *= 2
fmt = ">%dH" % vpr
def line():
return array.array("H", struct.unpack(fmt, infile.read(bpr)))
else:
def line():
return array.array("B", infile.read(bpr))
for y in range(height):
yield line()
def parse_args(args):
"""
Create a parser and parse the command line arguments.
"""
from argparse import ArgumentParser
parser = ArgumentParser(description=Description)
version = "%(prog)s " + png.__version__
parser.add_argument("--version", action="version", version=version)
parser.add_argument(
"-c",
"--compression",
type=int,
metavar="level",
help="zlib compression level (0-9)",
)
parser.add_argument(
"input",
nargs="?",
default="-",
type=png.cli_open,
metavar="PAM/PNM",
help="input PAM/PNM file to convert",
)
args = parser.parse_args(args)
return args
def main(argv=None):
if argv is None:
argv = sys.argv
args = parse_args(argv[1:])
# Prepare input and output files
infile = args.input
# Call after parsing, so that --version and --help work.
outfile = png.binary_stdout()
# Encode PNM to PNG
format, width, height, depth, maxval = read_pnm_header(infile)
ok_formats = (b"P2", b"P5", b"P6", b"P7")
if format not in ok_formats:
raise NotImplementedError("file format %s not supported" % format)
# The NetPBM depth (number of channels) completely
# determines the PNG format.
# Observe:
# - L, LA, RGB, RGBA are the 4 modes supported by PNG;
# - they correspond to 1, 2, 3, 4 channels respectively.
# We use the number of channels in the source image to
# determine which one we have.
# We ignore the NetPBM image type and the PAM TUPLTYPE.
greyscale = depth <= 2
pamalpha = depth in (2, 4)
supported = [2 ** x - 1 for x in range(1, 17)]
try:
mi = supported.index(maxval)
except ValueError:
raise NotImplementedError(
"input maxval (%s) not in supported list %s" % (maxval, str(supported))
)
bitdepth = mi + 1
writer = png.Writer(
width,
height,
greyscale=greyscale,
bitdepth=bitdepth,
alpha=pamalpha,
compression=args.compression,
)
plain = format in (b"P1", b"P2", b"P3")
if plain:
convert_pnm_plain(writer, infile, outfile)
else:
convert_pnm_binary(writer, infile, outfile)
if __name__ == "__main__":
try:
sys.exit(main())
except png.Error as e:
print(e, file=sys.stderr)
sys.exit(99)

540
venv/bin/priplan9topng Executable file
View File

@@ -0,0 +1,540 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# Imported from //depot/prj/plan9topam/master/code/plan9topam.py#4 on
# 2009-06-15.
"""Command line tool to convert from Plan 9 image format to PNG format.
Plan 9 image format description:
https://plan9.io/magic/man2html/6/image
Where possible this tool will use unbuffered read() calls,
so that when finished the file offset is exactly at the end of
the image data.
This is useful for Plan9 subfont files which place font metric
data immediately after the image.
"""
# Test materials
# asset/left.bit is a Plan 9 image file, a leftwards facing Glenda.
# Other materials have to be scrounged from the internet.
# https://plan9.io/sources/plan9/sys/games/lib/sokoban/images/cargo.bit
import array
import collections
import io
# http://www.python.org/doc/2.3.5/lib/module-itertools.html
import itertools
import os
# http://www.python.org/doc/2.3.5/lib/module-re.html
import re
import struct
# http://www.python.org/doc/2.3.5/lib/module-sys.html
import sys
# https://docs.python.org/3/library/tarfile.html
import tarfile
# https://pypi.org/project/pypng/
import png
# internal
import prix
class Error(Exception):
"""Some sort of Plan 9 image error."""
def block(s, n):
return zip(*[iter(s)] * n)
def plan9_as_image(inp):
"""Represent a Plan 9 image file as a png.Image instance, so
that it can be written as a PNG file.
Works with compressed input files and may work with uncompressed files.
"""
# Use inp.raw if available.
# This avoids buffering and means that when the image is processed,
# the resulting input stream is cued up exactly at the end
# of the image.
inp = getattr(inp, "raw", inp)
info, blocks = plan9_open_image(inp)
rows, infodict = plan9_image_rows(blocks, info)
return png.Image(rows, infodict)
def plan9_open_image(inp):
"""Open a Plan9 image file (`inp` should be an already open
file object), and return (`info`, `blocks`) pair.
`info` should be a Plan9 5-tuple;
`blocks` is the input, and it should yield (`row`, `data`)
pairs (see :meth:`pixmeta`).
"""
r = inp.read(11)
if r == b"compressed\n":
info, blocks = decompress(inp)
else:
# Since Python 3, there is a good chance that this path
# doesn't work.
info, blocks = glue(inp, r)
return info, blocks
def glue(f, r):
"""Return (info, stream) pair, given `r` the initial portion of
the metadata that has already been read from the stream `f`.
"""
r = r + f.read(60 - len(r))
return (meta(r), f)
def meta(r):
"""Convert 60 byte bytestring `r`, the metadata from an image file.
Returns a 5-tuple (*chan*,*minx*,*miny*,*limx*,*limy*).
5-tuples may settle into lists in transit.
As per https://plan9.io/magic/man2html/6/image the metadata
comprises 5 words separated by blanks.
As it happens each word starts at an index that is a multiple of 12,
but this routine does not care about that.
"""
r = r.split()
# :todo: raise FormatError
if 5 != len(r):
raise Error("Expected 5 space-separated words in metadata")
r = [r[0]] + [int(x) for x in r[1:]]
return r
def bitdepthof(chan):
"""Return the bitdepth for a Plan9 pixel format string."""
maxd = 0
for c in re.findall(rb"[a-z]\d*", chan):
if c[0] != "x":
maxd = max(maxd, int(c[1:]))
return maxd
def maxvalof(chan):
"""Return the netpbm MAXVAL for a Plan9 pixel format string."""
bitdepth = bitdepthof(chan)
return (2 ** bitdepth) - 1
def plan9_image_rows(blocks, metadata):
"""
Convert (uncompressed) Plan 9 image file to pair of (*rows*, *info*).
This is intended to be used by PyPNG format.
*info* is the image info (metadata) returned in a dictionary,
*rows* is an iterator that yields each row in
boxed row flat pixel format.
`blocks`, should be an iterator of (`row`, `data`) pairs.
"""
chan, minx, miny, limx, limy = metadata
rows = limy - miny
width = limx - minx
nchans = len(re.findall(b"[a-wyz]", chan))
alpha = b"a" in chan
# Iverson's convention for the win!
ncolour = nchans - alpha
greyscale = ncolour == 1
bitdepth = bitdepthof(chan)
maxval = maxvalof(chan)
# PNG style info dict.
meta = dict(
size=(width, rows),
bitdepth=bitdepth,
greyscale=greyscale,
alpha=alpha,
planes=nchans,
)
arraycode = "BH"[bitdepth > 8]
return (
map(
lambda x: array.array(arraycode, itertools.chain(*x)),
block(unpack(blocks, rows, width, chan, maxval), width),
),
meta,
)
def unpack(f, rows, width, chan, maxval):
"""Unpack `f` into pixels.
`chan` describes the pixel format using
the Plan9 syntax ("k8", "r8g8b8", and so on).
Assumes the pixel format has a total channel bit depth
that is either a multiple or a divisor of 8
(the Plan9 image specification requires this).
`f` should be an iterator that returns blocks of input such that
each block contains a whole number of pixels.
The return value is an iterator that yields each pixel as an n-tuple.
"""
def mask(w):
"""An integer, to be used as a mask, with bottom `w` bits set to 1."""
return (1 << w) - 1
def deblock(f, depth, width):
"""A "packer" used to convert multiple bytes into single pixels.
`depth` is the pixel depth in bits (>= 8), `width` is the row width in
pixels.
"""
w = depth // 8
i = 0
for block in f:
for i in range(len(block) // w):
p = block[w * i : w * (i + 1)]
i += w
# Convert little-endian p to integer x
x = 0
s = 1 # scale
for j in p:
x += s * j
s <<= 8
yield x
def bitfunge(f, depth, width):
"""A "packer" used to convert single bytes into multiple pixels.
Depth is the pixel depth (< 8), width is the row width in pixels.
"""
assert 8 / depth == 8 // depth
for block in f:
col = 0
for x in block:
for j in range(8 // depth):
yield x >> (8 - depth)
col += 1
if col == width:
# A row-end forces a new byte even if
# we haven't consumed all of the current byte.
# Effectively rows are bit-padded to make
# a whole number of bytes.
col = 0
break
x <<= depth
# number of bits in each channel
bits = [int(d) for d in re.findall(rb"\d+", chan)]
# colr of each channel
# (r, g, b, k for actual colours, and
# a, m, x for alpha, map-index, and unused)
colr = re.findall(b"[a-z]", chan)
depth = sum(bits)
# Select a "packer" that either:
# - gathers multiple bytes into a single pixel (for depth >= 8); or,
# - splits bytes into several pixels (for depth < 8).
if depth >= 8:
assert depth % 8 == 0
packer = deblock
else:
assert 8 % depth == 0
packer = bitfunge
for x in packer(f, depth, width):
# x is the pixel as an unsigned integer
o = []
# This is a bit yucky.
# Extract each channel from the _most_ significant part of x.
for b, col in zip(bits, colr):
v = (x >> (depth - b)) & mask(b)
x <<= b
if col != "x":
# scale to maxval
v = v * float(maxval) / mask(b)
v = int(v + 0.5)
o.append(v)
yield o
def decompress(f):
"""Decompress a Plan 9 image file.
The input `f` should be a binary file object that
is already cued past the initial 'compressed\n' string.
The return result is (`info`, `blocks`);
`info` is a 5-tuple of the Plan 9 image metadata;
`blocks` is an iterator that yields a (row, data) pair
for each block of data.
"""
r = meta(f.read(60))
return r, decomprest(f, r[4])
def decomprest(f, rows):
"""Iterator that decompresses the rest of a file once the metadata
have been consumed."""
row = 0
while row < rows:
row, o = deblock(f)
yield o
def deblock(f):
"""Decompress a single block from a compressed Plan 9 image file.
Each block starts with 2 decimal strings of 12 bytes each.
Yields a sequence of (row, data) pairs where
`row` is the total number of rows processed
(according to the file format) and
`data` is the decompressed data for this block.
"""
row = int(f.read(12))
size = int(f.read(12))
if not (0 <= size <= 6000):
raise Error("block has invalid size; not a Plan 9 image file?")
# Since each block is at most 6000 bytes we may as well read it all in
# one go.
d = f.read(size)
i = 0
o = []
while i < size:
x = d[i]
i += 1
if x & 0x80:
x = (x & 0x7F) + 1
lit = d[i : i + x]
i += x
o.extend(lit)
continue
# x's high-order bit is 0
length = (x >> 2) + 3
# Offset is made from bottom 2 bits of x and 8 bits of next byte.
# MSByte LSByte
# +---------------------+-------------------------+
# | - - - - - - | x1 x0 | d7 d6 d5 d4 d3 d2 d1 d0 |
# +-----------------------------------------------+
# Had to discover by inspection which way round the bits go,
# because https://plan9.io/magic/man2html/6/image doesn't say.
# that x's 2 bits are most significant.
offset = (x & 3) << 8
offset |= d[i]
i += 1
# Note: complement operator neatly maps (0 to 1023) to (-1 to
# -1024). Adding len(o) gives a (non-negative) offset into o from
# which to start indexing.
offset = ~offset + len(o)
if offset < 0:
raise Error(
"byte offset indexes off the begininning of "
"the output buffer; not a Plan 9 image file?"
)
for j in range(length):
o.append(o[offset + j])
return row, bytes(o)
FontChar = collections.namedtuple("FontChar", "x top bottom left width")
def font_copy(inp, image, out, control):
"""
Convert a Plan 9 font (`inp`, `image`) to a series of PNG images,
and write them out as a tar file to the file object `out`.
Write a text control file out to the file object `control`.
Each valid glyph in the font becomes a single PNG image;
the output is a tar file of all the images.
A Plan 9 font consists of a Plan 9 image immediately
followed by font data.
The image for the font should be the `image` argument,
the file containing the rest of the font data should be the
file object `inp` which should be cued up to the start of
the font data that immediately follows the image.
https://plan9.io/magic/man2html/6/font
"""
# The format is a little unusual, and isn't completely
# clearly documented.
# Each 6-byte structure (see FontChar above) defines
# a rectangular region of the image that is used for each
# glyph.
# The source image region that is used may be strictly
# smaller than the rectangle for the target glyph.
# This seems like a micro-optimisation.
# For each glyph,
# rows above `top` and below `bottom` will not be copied
# from the source (they can be assumed to be blank).
# No space is saved in the source image, since the rows must
# be present.
# `x` is always non-decreasing, so the glyphs appear strictly
# left-to-image in the source image.
# The x of the next glyph is used to
# infer the width of the source rectangle.
# `top` and `bottom` give the y-coordinate of the top- and
# bottom- sides of the rectangle in both source and targets.
# `left` is the x-coordinate of the left-side of the
# rectangle in the target glyph. (equivalently, the amount
# of padding that should be added on the left).
# `width` is the advance-width of the glyph; by convention
# it is 0 for an undefined glyph.
name = getattr(inp, "name", "*subfont*name*not*supplied*")
header = inp.read(36)
n, height, ascent = [int(x) for x in header.split()]
print("baseline", name, ascent, file=control, sep=",")
chs = []
for i in range(n + 1):
bs = inp.read(6)
ch = FontChar(*struct.unpack("<HBBBB", bs))
chs.append(ch)
tar = tarfile.open(mode="w|", fileobj=out)
# Start at 0, increment for every image output
# (recall that not every input glyph has an output image)
output_index = 0
for i in range(n):
ch = chs[i]
if ch.width == 0:
continue
print("png", "index", output_index, "glyph", name, i, file=control, sep=",")
info = dict(image.info, size=(ch.width, height))
target = new_image(info)
source_width = chs[i + 1].x - ch.x
rect = ((ch.left, ch.top), (ch.left + source_width, ch.bottom))
image_draw(target, rect, image, (ch.x, ch.top))
# :todo: add source, glyph, and baseline data here (as a
# private tag?)
o = io.BytesIO()
target.write(o)
binary_size = o.tell()
o.seek(0)
tarinfo = tar.gettarinfo(arcname="%s/glyph%d.png" % (name, i), fileobj=inp)
tarinfo.size = binary_size
tar.addfile(tarinfo, fileobj=o)
output_index += 1
tar.close()
def new_image(info):
"""Return a fresh png.Image instance."""
width, height = info["size"]
vpr = width * info["planes"]
row = lambda: [0] * vpr
rows = [row() for _ in range(height)]
return png.Image(rows, info)
def image_draw(target, rect, source, point):
"""The point `point` in the source image is aligned with the
top-left of rect in the target image, and then the rectangle
in target is replaced with the pixels from `source`.
This routine assumes that both source and target can have
their rows objects indexed (not streamed).
"""
# :todo: there is no attempt to do clipping or channel or
# colour conversion. But maybe later?
if target.info["planes"] != source.info["planes"]:
raise NotImplementedError(
"source and target must have the same number of planes"
)
if target.info["bitdepth"] != source.info["bitdepth"]:
raise NotImplementedError("source and target must have the same bitdepth")
tl, br = rect
left, top = tl
right, bottom = br
height = bottom - top
planes = source.info["planes"]
vpr = (right - left) * planes
source_left, source_top = point
source_l = source_left * planes
source_r = source_l + vpr
target_l = left * planes
target_r = target_l + vpr
for y in range(height):
row = source.rows[y + source_top]
row = row[source_l:source_r]
target.rows[top + y][target_l:target_r] = row
def main(argv=None):
import argparse
parser = argparse.ArgumentParser(description="Convert Plan9 image to PNG")
parser.add_argument(
"input",
nargs="?",
default="-",
type=png.cli_open,
metavar="image",
help="image file in Plan 9 format",
)
parser.add_argument(
"--control",
default=os.path.devnull,
type=argparse.FileType("w"),
metavar="ControlCSV",
help="(when using --font) write a control CSV file to named file",
)
parser.add_argument(
"--font",
action="store_true",
help="process as Plan 9 subfont: output a tar file of PNGs",
)
args = parser.parse_args()
image = plan9_as_image(args.input)
image.stream()
if not args.font:
image.write(png.binary_stdout())
else:
font_copy(args.input, image, png.binary_stdout(), args.control)
if __name__ == "__main__":
sys.exit(main())

33
venv/bin/pripnglsch Executable file
View File

@@ -0,0 +1,33 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# pripnglsch
# PNG List Chunks
import png
def list_chunks(out, inp):
r = png.Reader(file=inp)
for t, v in r.chunks():
add = ""
if len(v) <= 28:
add = " " + v.hex()
else:
add = " " + v[:26].hex() + "..."
t = t.decode("ascii")
print("%s %10d%s" % (t, len(v), add), file=out)
def main(argv=None):
import argparse
import sys
parser = argparse.ArgumentParser()
parser.add_argument(
"input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args()
return list_chunks(sys.stdout, args.input)
if __name__ == "__main__":
main()

101
venv/bin/pripngtopam Executable file
View File

@@ -0,0 +1,101 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
import struct
import png
def write_pnm(file, plain, rows, meta):
"""
Write a Netpbm PNM (or PAM) file.
*file* output file object;
*plain* (a bool) true if writing plain format (not possible for PAM);
*rows* an iterator for the rows;
*meta* the info dictionary.
"""
meta = dict(meta)
meta["maxval"] = 2 ** meta["bitdepth"] - 1
meta["width"], meta["height"] = meta["size"]
# Number of planes determines both image formats:
# 1 : L to PGM
# 2 : LA to PAM
# 3 : RGB to PPM
# 4 : RGBA to PAM
planes = meta["planes"]
# Assume inputs are from a PNG file.
assert planes in (1, 2, 3, 4)
if planes in (1, 3):
if 1 == planes:
# PGM
# Even if maxval is 1 we use PGM instead of PBM,
# to avoid converting data.
magic = "P5"
if plain:
magic = "P2"
else:
# PPM
magic = "P6"
if plain:
magic = "P3"
header = "{magic} {width:d} {height:d} {maxval:d}\n".format(magic=magic, **meta)
if planes in (2, 4):
# PAM
# See http://netpbm.sourceforge.net/doc/pam.html
if plain:
raise Exception("PAM (%d-plane) does not support plain format" % planes)
if 2 == planes:
tupltype = "GRAYSCALE_ALPHA"
else:
tupltype = "RGB_ALPHA"
header = (
"P7\nWIDTH {width:d}\nHEIGHT {height:d}\n"
"DEPTH {planes:d}\nMAXVAL {maxval:d}\n"
"TUPLTYPE {tupltype}\nENDHDR\n".format(tupltype=tupltype, **meta)
)
file.write(header.encode("ascii"))
# Values per row
vpr = planes * meta["width"]
if plain:
for row in rows:
row_b = b" ".join([b"%d" % v for v in row])
file.write(row_b)
file.write(b"\n")
else:
# format for struct.pack
fmt = ">%d" % vpr
if meta["maxval"] > 0xFF:
fmt = fmt + "H"
else:
fmt = fmt + "B"
for row in rows:
file.write(struct.pack(fmt, *row))
file.flush()
def main(argv=None):
import argparse
parser = argparse.ArgumentParser(description="Convert PNG to PAM")
parser.add_argument("--plain", action="store_true")
parser.add_argument(
"input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args()
# Encode PNG to PNM (or PAM)
image = png.Reader(file=args.input)
_, _, rows, info = image.asDirect()
write_pnm(png.binary_stdout(), args.plain, rows, info)
if __name__ == "__main__":
import sys
sys.exit(main())

71
venv/bin/prirowpng Executable file
View File

@@ -0,0 +1,71 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# http://www.python.org/doc/2.4.4/lib/module-itertools.html
import itertools
import sys
import png
Description = """Join PNG images in a row left-to-right."""
class FormatError(Exception):
"""
Some problem with the image format.
"""
def join_row(out, l):
"""
Concatenate the list of images.
All input images must be same height and
have the same number of channels.
They are concatenated left-to-right.
`out` is the (open file) destination for the output image.
`l` should be a list of open files (the input image files).
"""
l = [png.Reader(file=f) for f in l]
# Ewgh, side effects.
for r in l:
r.preamble()
# The reference height; from the first image.
height = l[0].height
# The total target width
width = 0
for i,r in enumerate(l):
if r.height != height:
raise FormatError('Image %d, height %d, does not match %d.' %
(i, r.height, height))
width += r.width
# Various bugs here because different numbers of channels and depths go wrong.
pixel, info = zip(*[r.asDirect()[2:4] for r in l])
tinfo = dict(info[0])
del tinfo['size']
w = png.Writer(width, height, **tinfo)
def iter_all_rows():
for row in zip(*pixel):
# `row` is a sequence that has one row from each input image.
# list() is required here to hasten the lazy row building;
# not sure if that's a bug in PyPNG or not.
yield list(itertools.chain(*row))
w.write(out, iter_all_rows())
def main(argv):
import argparse
parser = argparse.ArgumentParser(description=Description)
parser.add_argument(
"input", nargs="*", default="-", type=png.cli_open, metavar="PNG"
)
args = parser.parse_args()
return join_row(png.binary_stdout(), args.input)
if __name__ == '__main__':
main(sys.argv)

215
venv/bin/priweavepng Executable file
View File

@@ -0,0 +1,215 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# priweavepng
# Weave selected channels from input PNG files into
# a multi-channel output PNG.
import collections
import re
from array import array
import png
"""
priweavepng file1.png [file2.png ...]
The `priweavepng` tool combines channels from the input images and
weaves a selection of those channels into an output image.
Conceptually an intermediate image is formed consisting of
all channels of all input images in the order given on the command line
and in the order of each channel in its image.
Then from 1 to 4 channels are selected and
an image is output with those channels.
The limit on the number of selected channels is
imposed by the PNG image format.
The `-c n` option selects channel `n`.
Further channels can be selected either by repeating the `-c` option,
or using a comma separated list.
For example `-c 3,2,1` will select channels 3, 2, and 1 in that order;
if the input is an RGB PNG, this will swop the Red and Blue channels.
The order is significant, the order in which the options are given is
the order of the output channels.
It is permissible, and sometimes useful
(for example, grey to colour expansion, see below),
to repeat the same channel.
If no `-c` option is used the default is
to select all of the input channels, up to the first 4.
`priweavepng` does not care about the meaning of the channels
and treats them as a matrix of values.
The numer of output channels determines the colour mode of the PNG file:
L (1-channel, Grey), LA (2-channel, Grey+Alpha),
RGB (3-channel, Red+Green+Blue), RGBA (4-channel, Red+Green+Blue+Alpha).
The `priweavepng` tool can be used for a variety of
channel building, swopping, and extraction effects:
Combine 3 grayscale images into RGB colour:
priweavepng grey1.png grey2.png grey3.png
Swop Red and Blue channels in colour image:
priweavepng -c 3 -c 2 -c 1 rgb.png
Extract Green channel as a greyscale image:
priweavepng -c 2 rgb.png
Convert a greyscale image to a colour image (all grey):
priweavepng -c 1 -c 1 -c 1 grey.png
Add alpha mask from a separate (greyscale) image:
priweavepng rgb.png grey.png
Extract alpha mask into a separate (greyscale) image:
priweavepng -c 4 rgba.png
Steal alpha mask from second file and add to first.
Note that the intermediate image in this example has 7 channels:
priweavepng -c 1 -c 2 -c 3 -c 7 rgb.png rgba.png
Take Green channel from 3 successive colour images to make a new RGB image:
priweavepng -c 2 -c 5 -c 8 rgb1.png rgb2.png rgb3.png
"""
Image = collections.namedtuple("Image", "rows info")
# For each channel in the intermediate raster,
# model:
# - image: the input image (0-based);
# - i: the channel index within that image (0-based);
# - bitdepth: the bitdepth of this channel.
Channel = collections.namedtuple("Channel", "image i bitdepth")
class Error(Exception):
pass
def weave(out, args):
"""Stack the input PNG files and extract channels
into a single output PNG.
"""
paths = args.input
if len(paths) < 1:
raise Error("Required input is missing.")
# List of Image instances
images = []
# Channel map. Maps from channel number (starting from 1)
# to an (image_index, channel_index) pair.
channel_map = dict()
channel = 1
for image_index, path in enumerate(paths):
inp = png.cli_open(path)
rows, info = png.Reader(file=inp).asDirect()[2:]
rows = list(rows)
image = Image(rows, info)
images.append(image)
# A later version of PyPNG may intelligently support
# PNG files with heterogenous bitdepths.
# For now, assumes bitdepth of all channels in image
# is the same.
channel_bitdepth = (image.info["bitdepth"],) * image.info["planes"]
for i in range(image.info["planes"]):
channel_map[channel + i] = Channel(image_index, i, channel_bitdepth[i])
channel += image.info["planes"]
assert channel - 1 == sum(image.info["planes"] for image in images)
# If no channels, select up to first 4 as default.
if not args.channel:
args.channel = range(1, channel)[:4]
out_channels = len(args.channel)
if not (0 < out_channels <= 4):
raise Error("Too many channels selected (must be 1 to 4)")
alpha = out_channels in (2, 4)
greyscale = out_channels in (1, 2)
bitdepth = tuple(image.info["bitdepth"] for image in images)
arraytype = "BH"[max(bitdepth) > 8]
size = [image.info["size"] for image in images]
# Currently, fail unless all images same size.
if len(set(size)) > 1:
raise NotImplementedError("Cannot cope when sizes differ - sorry!")
size = size[0]
# Values per row, of output image
vpr = out_channels * size[0]
def weave_row_iter():
"""
Yield each woven row in turn.
"""
# The zip call creates an iterator that yields
# a tuple with each element containing the next row
# for each of the input images.
for row_tuple in zip(*(image.rows for image in images)):
# output row
row = array(arraytype, [0] * vpr)
# for each output channel select correct input channel
for out_channel_i, selection in enumerate(args.channel):
channel = channel_map[selection]
# incoming row (make it an array)
irow = array(arraytype, row_tuple[channel.image])
n = images[channel.image].info["planes"]
row[out_channel_i::out_channels] = irow[channel.i :: n]
yield row
w = png.Writer(
size[0],
size[1],
greyscale=greyscale,
alpha=alpha,
bitdepth=bitdepth,
interlace=args.interlace,
)
w.write(out, weave_row_iter())
def comma_list(s):
"""
Type and return a list of integers.
"""
return [int(c) for c in re.findall(r"\d+", s)]
def main(argv=None):
import argparse
import itertools
import sys
if argv is None:
argv = sys.argv
argv = argv[1:]
parser = argparse.ArgumentParser()
parser.add_argument(
"-c",
"--channel",
action="append",
type=comma_list,
help="list of channels to extract",
)
parser.add_argument("--interlace", action="store_true", help="write interlaced PNG")
parser.add_argument("input", nargs="+")
args = parser.parse_args(argv)
if args.channel:
args.channel = list(itertools.chain(*args.channel))
return weave(png.binary_stdout(), args)
if __name__ == "__main__":
main()

8
venv/bin/pybarcode3 Executable file
View File

@@ -0,0 +1,8 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from barcode.pybarcode import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
venv/bin/pyserial-miniterm Executable file
View File

@@ -0,0 +1,8 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from serial.tools.miniterm import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
venv/bin/pyserial-ports Executable file
View File

@@ -0,0 +1,8 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from serial.tools.list_ports import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

1
venv/bin/python Symbolic link
View File

@@ -0,0 +1 @@
python3

View File

@@ -0,0 +1,63 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# Copyright 2012-2023, Andrey Kislyuk and argcomplete contributors.
# Licensed under the Apache License. See https://github.com/kislyuk/argcomplete for more info.
"""
This script is part of the Python argcomplete package (https://github.com/kislyuk/argcomplete).
It is used to check if an EASY-INSTALL-SCRIPT wrapper redirects to a script that contains the string
"PYTHON_ARGCOMPLETE_OK". If you have enabled global completion in argcomplete, the completion hook will run it every
time you press <TAB> in your shell.
Usage:
python-argcomplete-check-easy-install-script <input executable file>
"""
import sys
if len(sys.argv) != 2:
sys.exit(__doc__)
sys.tracebacklimit = 0
with open(sys.argv[1]) as fh:
line1, head = fh.read(1024).split("\n", 1)[:2]
if line1.startswith("#") and ("py" in line1 or "Py" in line1):
import re
lines = head.split("\n", 12)
for line in lines:
if line.startswith("# EASY-INSTALL-SCRIPT"):
import pkg_resources
dist, script = re.match("# EASY-INSTALL-SCRIPT: '(.+)','(.+)'", line).groups()
if "PYTHON_ARGCOMPLETE_OK" in pkg_resources.get_distribution(dist).get_metadata("scripts/" + script):
exit(0)
elif line.startswith("# EASY-INSTALL-ENTRY-SCRIPT"):
dist, group, name = re.match("# EASY-INSTALL-ENTRY-SCRIPT: '(.+)','(.+)','(.+)'", line).groups()
import pkgutil
import pkg_resources
module_name = pkg_resources.get_distribution(dist).get_entry_info(group, name).module_name
with open(pkgutil.get_loader(module_name).get_filename()) as mod_fh:
if "PYTHON_ARGCOMPLETE_OK" in mod_fh.read(1024):
exit(0)
elif line.startswith("# EASY-INSTALL-DEV-SCRIPT"):
for line2 in lines:
if line2.startswith("__file__"):
filename = re.match("__file__ = '(.+)'", line2).group(1)
with open(filename) as mod_fh:
if "PYTHON_ARGCOMPLETE_OK" in mod_fh.read(1024):
exit(0)
elif line.startswith("# PBR Generated"):
module = re.search("from (.*) import", head).groups()[0]
import pkgutil
import pkg_resources
with open(pkgutil.get_loader(module).get_filename()) as mod_fh:
if "PYTHON_ARGCOMPLETE_OK" in mod_fh.read(1024):
exit(0)
exit(1)

8
venv/bin/python-barcode Executable file
View File

@@ -0,0 +1,8 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from barcode.pybarcode import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

8
venv/bin/python-escpos Executable file
View File

@@ -0,0 +1,8 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from escpos.cli import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

1
venv/bin/python3 Symbolic link
View File

@@ -0,0 +1 @@
/usr/bin/python3

1
venv/bin/python3.11 Symbolic link
View File

@@ -0,0 +1 @@
python3

8
venv/bin/qr Executable file
View File

@@ -0,0 +1,8 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from qrcode.console_scripts import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

View File

@@ -0,0 +1,71 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# PYTHON_ARGCOMPLETE_OK
# Copyright 2012-2023, Andrey Kislyuk and argcomplete contributors.
# Licensed under the Apache License. See https://github.com/kislyuk/argcomplete for more info.
"""
Register a Python executable for use with the argcomplete module.
To perform the registration, source the output of this script in your bash shell
(quote the output to avoid interpolation).
Example:
$ eval "$(register-python-argcomplete my-favorite-script.py)"
For Tcsh
$ eval `register-python-argcomplete --shell tcsh my-favorite-script.py`
For Fish
$ register-python-argcomplete --shell fish my-favourite-script.py > ~/.config/fish/my-favourite-script.py.fish
"""
import argparse
import sys
import argcomplete
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument(
"--no-defaults",
dest="use_defaults",
action="store_false",
default=True,
help="when no matches are generated, do not fallback to readline's default completion (affects bash only)",
)
parser.add_argument(
"--complete-arguments",
nargs=argparse.REMAINDER,
help="arguments to call complete with; use of this option discards default options (affects bash only)",
)
parser.add_argument(
"-s",
"--shell",
choices=("bash", "zsh", "tcsh", "fish", "powershell"),
default="bash",
help="output code for the specified shell",
)
parser.add_argument(
"-e", "--external-argcomplete-script", help="external argcomplete script for auto completion of the executable"
)
parser.add_argument("executable", nargs="+", help="executable to completed (when invoked by exactly this name)")
argcomplete.autocomplete(parser)
if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)
args = parser.parse_args()
sys.stdout.write(
argcomplete.shellcode(
args.executable, args.use_defaults, args.shell, args.complete_arguments, args.external_argcomplete_script
)
)

8
venv/bin/tabulate Executable file
View File

@@ -0,0 +1,8 @@
#!/home/mongar/Escritorio/pruebas_oc/venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from tabulate import _main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(_main())