dmolony-DiskBrowser/src/com/bytezone/diskbrowser/applefile/SHRPictureFile.java

310 lines
8.3 KiB
Java
Raw Normal View History

2017-01-24 08:59:40 +00:00
package com.bytezone.diskbrowser.applefile;
2017-01-25 01:38:00 +00:00
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
2017-01-24 08:59:40 +00:00
import java.util.ArrayList;
import java.util.List;
import com.bytezone.diskbrowser.utilities.HexFormatter;
2017-01-24 21:53:34 +00:00
public class SHRPictureFile extends HiResImage
2017-01-24 08:59:40 +00:00
{
2017-01-26 11:30:16 +00:00
private final List<Block> blocks = new ArrayList<Block> ();
private Main mainBlock;
private Multipal multipalBlock;
2017-01-24 08:59:40 +00:00
2017-01-26 11:30:16 +00:00
// 0xC0 aux = 2
2017-01-25 11:02:50 +00:00
public SHRPictureFile (String name, byte[] buffer, int fileType, int auxType, int eof)
2017-01-24 08:59:40 +00:00
{
2017-01-25 11:02:50 +00:00
super (name, buffer, fileType, auxType, eof);
2017-01-24 08:59:40 +00:00
int ptr = 0;
while (ptr < buffer.length)
{
int len = HexFormatter.unsignedLong (buffer, ptr);
2017-01-26 11:30:16 +00:00
// int nameLen = buffer[ptr + 4] & 0xFF;
2017-01-24 08:59:40 +00:00
String kind = HexFormatter.getPascalString (buffer, ptr + 4);
2017-01-26 11:30:16 +00:00
byte[] data = new byte[Math.min (len, buffer.length - ptr)];
2017-01-24 08:59:40 +00:00
System.arraycopy (buffer, ptr, data, 0, data.length);
if ("MAIN".equals (kind))
2017-01-25 01:38:00 +00:00
{
mainBlock = new Main (kind, data);
blocks.add (mainBlock);
}
2017-01-25 04:40:15 +00:00
else if ("MULTIPAL".equals (kind))
{
multipalBlock = new Multipal (kind, data);
blocks.add (multipalBlock);
}
2017-01-24 08:59:40 +00:00
else
2017-01-26 11:30:16 +00:00
{
2017-01-24 08:59:40 +00:00
blocks.add (new Block (kind, data));
2017-01-26 11:30:16 +00:00
System.out.println ("Unknown block type: " + kind + " in " + name);
}
2017-01-24 08:59:40 +00:00
ptr += len;
}
2017-01-25 01:38:00 +00:00
createImage ();
2017-01-24 08:59:40 +00:00
}
@Override
protected void createMonochromeImage ()
{
2017-01-26 04:19:23 +00:00
image = new BufferedImage (320, 200, BufferedImage.TYPE_BYTE_GRAY);
DataBuffer db = image.getRaster ().getDataBuffer ();
int element = 0;
int ptr = 0;
for (int row = 0; row < 200; row++)
for (int col = 0; col < 160; col++)
{
int pix1 = (unpackedBuffer[ptr] & 0xF0) >> 4;
int pix2 = unpackedBuffer[ptr] & 0x0F;
if (pix1 > 0)
db.setElem (element, 255);
if (pix2 > 0)
db.setElem (element + 1, 255);
element += 2;
ptr++;
}
2017-01-24 08:59:40 +00:00
}
@Override
protected void createColourImage ()
{
2017-01-25 11:02:50 +00:00
image = new BufferedImage (320, mainBlock.numScanLines, BufferedImage.TYPE_INT_RGB);
2017-01-25 01:38:00 +00:00
DataBuffer dataBuffer = image.getRaster ().getDataBuffer ();
int element = 0;
int ptr = 0;
2017-01-25 11:02:50 +00:00
for (int row = 0; row < mainBlock.numScanLines; row++)
2017-01-25 01:38:00 +00:00
{
DirEntry dirEntry = mainBlock.scanLineDirectory[row];
int hi = dirEntry.mode & 0xFF00;
int lo = dirEntry.mode & 0x00FF;
2017-01-25 04:40:15 +00:00
ColorTable colorTable = multipalBlock != null ? multipalBlock.colorTables[row]
: mainBlock.colorTables[lo & 0x0F];
2017-01-25 01:38:00 +00:00
2017-01-26 11:30:16 +00:00
boolean fillMode = (lo & 0x20) != 0;
2017-01-25 01:38:00 +00:00
if (fillMode)
System.out.println ("fillmode " + fillMode);
for (int col = 0; col < 160; col++)
{
int left = (unpackedBuffer[ptr] & 0xF0) >> 4;
int right = unpackedBuffer[ptr] & 0x0F;
2017-01-25 04:40:15 +00:00
2017-01-25 01:38:00 +00:00
dataBuffer.setElem (element++, colorTable.entries[left].color.getRGB ());
dataBuffer.setElem (element++, colorTable.entries[right].color.getRGB ());
2017-01-25 04:40:15 +00:00
2017-01-25 01:38:00 +00:00
ptr++;
}
}
2017-01-24 08:59:40 +00:00
}
@Override
public String getText ()
{
StringBuilder text = new StringBuilder (super.getText ());
for (Block block : blocks)
{
text.append (block);
text.append ("\n\n");
}
2017-01-25 01:38:00 +00:00
if (blocks.size () > 0)
{
text.deleteCharAt (text.length () - 1);
text.deleteCharAt (text.length () - 1);
}
2017-01-24 08:59:40 +00:00
return text.toString ();
}
2017-01-26 11:30:16 +00:00
private class Block
2017-01-24 08:59:40 +00:00
{
String kind;
byte[] data;
public Block (String kind, byte[] data)
{
this.kind = kind;
this.data = data;
}
@Override
public String toString ()
{
StringBuilder text = new StringBuilder ();
text.append (String.format ("Kind ...... %s%n%n", kind));
text.append (HexFormatter.format (data));
return text.toString ();
}
}
2017-01-26 11:30:16 +00:00
private class Multipal extends Block
2017-01-25 04:40:15 +00:00
{
int numPalettes;
ColorTable[] colorTables;
public Multipal (String kind, byte[] data)
{
super (kind, data);
int ptr = 5 + kind.length ();
numPalettes = HexFormatter.unsignedShort (data, ptr);
ptr += 2;
colorTables = new ColorTable[numPalettes];
for (int i = 0; i < numPalettes; i++)
{
if (ptr < data.length - 32)
colorTables[i] = new ColorTable (i, data, ptr);
else
colorTables[i] = new ColorTable (); // default empty table
ptr += 32;
}
}
}
2017-01-26 11:30:16 +00:00
private class Main extends Block
2017-01-24 08:59:40 +00:00
{
int masterMode;
int pixelsPerScanLine;
int numColorTables;
ColorTable[] colorTables;
int numScanLines;
DirEntry[] scanLineDirectory;
byte[][] packedScanLines;
public Main (String kind, byte[] data)
{
super (kind, data);
int ptr = 5 + kind.length ();
masterMode = HexFormatter.unsignedShort (data, ptr);
pixelsPerScanLine = HexFormatter.unsignedShort (data, ptr + 2);
numColorTables = HexFormatter.unsignedShort (data, ptr + 4);
ptr += 6;
colorTables = new ColorTable[numColorTables];
for (int i = 0; i < numColorTables; i++)
{
colorTables[i] = new ColorTable (i, data, ptr);
ptr += 32;
}
numScanLines = HexFormatter.unsignedShort (data, ptr);
scanLineDirectory = new DirEntry[numScanLines];
packedScanLines = new byte[numScanLines][];
ptr += 2;
for (int i = 0; i < numScanLines; i++)
{
DirEntry dirEntry = new DirEntry (data, ptr);
scanLineDirectory[i] = dirEntry;
packedScanLines[i] = new byte[dirEntry.numBytes];
ptr += 4;
}
for (int i = 0; i < numScanLines; i++)
{
int len = scanLineDirectory[i].numBytes;
if (ptr + len > data.length)
break;
System.arraycopy (data, ptr, packedScanLines[i], 0, len);
ptr += len;
}
2017-01-24 21:53:34 +00:00
if (true)
{
2017-01-25 11:02:50 +00:00
unpackedBuffer = new byte[numScanLines * 160];
2017-01-24 21:53:34 +00:00
ptr = 0;
for (int line = 0; line < numScanLines; line++)
{
byte[] lineBuffer = packedScanLines[line];
if (lineBuffer.length % 2 == 1 && isEmpty (lineBuffer))
{
System.out.println ("Odd number of bytes in empty buffer in " + name);
break;
}
2017-01-25 01:38:00 +00:00
ptr = unpackLine (lineBuffer, unpackedBuffer, ptr);
2017-01-24 21:53:34 +00:00
}
}
}
private boolean isEmpty (byte[] buffer)
{
for (byte b : buffer)
if (b != 0)
return false;
return true;
2017-01-24 08:59:40 +00:00
}
@Override
public String toString ()
{
StringBuilder text = new StringBuilder ();
text.append (String.format ("Kind ................. %s%n", kind));
text.append (String.format ("MasterMode ........... %04X%n", masterMode));
text.append (String.format ("PixelsPerScanLine .... %d%n", pixelsPerScanLine));
text.append (String.format ("NumColorTables ....... %d%n", numColorTables));
text.append (String.format ("NumScanLines ......... %d%n%n", numScanLines));
text.append ("Color Tables\n");
text.append ("------------\n\n");
text.append (" # ");
for (int i = 0; i < 16; i++)
text.append (String.format (" %02X ", i));
text.deleteCharAt (text.length () - 1);
text.deleteCharAt (text.length () - 1);
text.append ("\n---");
for (int i = 0; i < 16; i++)
text.append (" ---- ");
text.deleteCharAt (text.length () - 1);
text.append ("\n");
2017-01-25 11:02:50 +00:00
2017-01-24 08:59:40 +00:00
for (ColorTable colorTable : colorTables)
{
text.append (colorTable.toLine ());
text.append ("\n");
}
text.append ("\nScan Lines\n");
text.append ("----------\n\n");
2017-01-24 21:53:34 +00:00
text.append (" # Mode Len Packed Data\n");
text.append ("--- ---- --- ---------------------------------------");
2017-01-24 08:59:40 +00:00
text.append ("------------------------------------------\n");
2017-01-24 21:53:34 +00:00
int lineSize = 24;
2017-01-24 08:59:40 +00:00
for (int i = 0; i < scanLineDirectory.length; i++)
{
DirEntry dirEntry = scanLineDirectory[i];
byte[] packedScanLine = packedScanLines[i];
2017-01-25 11:02:50 +00:00
text.append (
String.format ("%3d %3d %3d ", i, dirEntry.mode, packedScanLine.length));
2017-01-24 21:53:34 +00:00
int ptr = 0;
while (true)
{
text.append (HexFormatter.getHexString (packedScanLine, ptr, lineSize));
ptr += lineSize;
if (ptr >= packedScanLine.length)
break;
text.append ("\n ");
}
2017-01-24 08:59:40 +00:00
text.append ("\n");
}
return text.toString ();
}
}
}