#!/bin/sh : " -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 " # gtagallery - a shell script to extract JPEG images from the GALLERY.DAT # file in a PS2 "Grand Theft Auto: San Andreas" save on a *ix system. # # Copyright © 2009 Ben Winslow # Version 0.2, 2009-07-13 # # Released under a Creative Commons Attribution-Noncommercial- # Share Alike 3.0 United States License. # GTA:SA's GALLERY.DAT is composed of 80 KiB chunks, each starting with # JPEG image data followed by unknown data for the remainder of the chunk. # This script uses dd to pull out the the chunks, and jpegtran (part of # libjpeg) to losslessly remove the unknown data and optimize the Huffman # tables in an attempt to get a smaller image. trap 'exit 1' INT imgpos=0 imgex=0 imgok=0 INFILE="$1" OUTFMT="$2" # Default output format if [ -z "$OUTFMT" ]; then OUTFMT="gtasa-%03d.jpg" fi # Display help if no file is specified or it's unreadable if [ "$#" -lt 1 -o ! -r "$INFILE" ]; then echo "Usage: $0 [outputfmt]" >&2 echo "Parameters: " >&2 echo " : the file name of a GALLERY.DAT extracted from a" >&2 echo " Grand Theft Auto: San Andreas (PS2) save." >&2 echo " [outputfmt]: (default \`gtasa-%03d'): a printf(3) style format string" >&2 echo " for the output file names." >&2 exit 1 fi # Check for jpegtran if ! which jpegtran > /dev/null; then echo "Warning: Unable to find the \`jpegtran' utility from libjpeg/libjpeg-progs!" >&2 echo "Without this utility, all JPEG images extracted will be exactly 80KiB and" >&2 echo "contain superfluous data at the end of the file." >&2 echo >&2 HAVE_JPEGTRAN=0 else HAVE_JPEGTRAN=1 fi # Verify $OUTFMT actually has a proper format character if [ "`printf "$OUTFMT" 1`" = "`printf "$OUTFMT" 2`" ]; then echo "Warning: The specified output format ($OUTFMT) does not provide" >&2 echo "unique file names! Only the first image will be extracted." >&2 fi INFILE_SIZE="`du -k "$INFILE" | awk '{print $1}'`" imgcnt=$((INFILE_SIZE / 80)) echo "Processing file: ${INFILE} (${imgcnt} images)..." while [ $imgpos -lt $imgcnt ]; do OUTFILE="`printf "$OUTFMT" $((imgpos + 1))`" printf "\rImage %3d: extracting... " $((imgpos + 1)) if [ -e "$OUTFILE" ]; then printf "\rSkipping image %3d (output file \`%s' already exists!)\n" $((imgpos + 1)) "$OUTFILE" >&2 imgpos=$((imgpos + 1)) continue fi dd if="$INFILE" of="$OUTFILE" bs=81920 count=1 skip=$imgpos >/dev/null 2>&1 # If dd spits out a 0-byte file, assume EOF if [ -e "$OUTFILE" -a ! -s "$OUTFILE" ]; then printf "\rImage %3d: not present (end of file)\n" $((imgpos + 1)) rm -f "$OUTFILE" break fi imgex=$((imgex + 1)) # Use jpegtran to drop the extra data after the image and optimize # the image's Huffman table. if [ "x$HAVE_JPEGTRAN" = "x1" ]; then printf "\rImage %3d: extracting... optimizing..." $((imgpos + 1)) jpegtran -copy none -optimize -progressive -outfile "$OUTFILE" "$OUTFILE" 2>/dev/null if [ "x$?" != "x0" ]; then printf "\nWarning: image %3d (%s) may be corrupt!\n" $((imgpos + 1)) $OUTFILE >&2 else imgok=$((imgok + 1)) fi fi imgpos=$((imgpos + 1)) done printf "\rDone. Extracted %d of %d images (%d verified OK.)\n" $imgex $imgcnt $imgok exit 0 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iQIcBAEBAgAGBQJKW35HAAoJEG4qBP1BCi3P5AUP+QEb2mGgt/RzsWDDx8SnVeJo R5tip+hxYBqhCyZMDDhfQkI10OMeW0qVOlmuScdHalbYNAPllJ736IuMZ89tJY74 JP327wCZyn1DX7V4HcrrAut3OdzMhGVbFYoUtvvDbheNcU9dTydEKWJ4+srZ8Qkw WH4mAkwE+Va+68oI9hLEa0DSh7ughY313XItyU5OORatxgCjdYYqHGtbyQQ5WvOh HjyWnWY7Bv5hn+XGLA+fe2laTRtSKUrjfSqxI3UV82u/mZb9vHNijB9zLTUvtl8W vhH4MdXMJryrgUWPnYirwhQwdhIK1r0WpePN4vnVogrzSz9vy3pGmzX2McIS//yu zx/AbQLenbhTKEnRcLFYq1ZMPMaREkxbDtL9X9vMfB0NlPdveGw30IeygcLAwsCD aQDkJ6eBhN+LCS5JPIojpdMgg6pXfxaM5R37luOBPoG2cJsELGwe2JgFQeZ2d1MJ P96R7Ho5K9ODt1EMLHSyVSbjKRJB3ocMOXebGCFwRWzOio/o+ZTNsPZbny6WBYiU Sf1CPGI4d7rq6sX2To5mFPZ4NcNyZRgPbYXzFOQ0fdzk+4zwKuFhqib3HSMStjBe f2BwHYPozqyaXVxh/q/ZWxDdq4FBpWNWJU31sLE0JQ/kmbE2uS5ox6OnS4ietwzB crSOoPX+FgRjG3VnMQTm =PxSM -----END PGP SIGNATURE-----