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

336 lines
7.9 KiB
Java
Raw Normal View History

2016-12-31 09:34:15 +00:00
package com.bytezone.diskbrowser.applefile;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.io.ByteArrayInputStream;
import java.io.IOException;
2017-01-14 01:40:58 +00:00
import java.util.List;
2016-12-31 09:34:15 +00:00
import javax.imageio.ImageIO;
import com.bytezone.diskbrowser.prodos.ProdosConstants;
public abstract class HiResImage extends AbstractFile
{
2017-01-14 01:40:58 +00:00
protected static PaletteFactory paletteFactory = new PaletteFactory ();
2017-01-12 22:11:05 +00:00
2016-12-31 09:34:15 +00:00
private static final byte[] pngHeader =
{ (byte) 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };
protected static boolean colourQuirks;
protected static boolean monochrome;
protected int fileType;
protected int auxType;
protected byte[] unpackedBuffer;
2017-01-14 20:58:07 +00:00
protected int paletteIndex;
2016-12-31 09:34:15 +00:00
public HiResImage (String name, byte[] buffer)
{
super (name, buffer);
}
public HiResImage (String name, byte[] buffer, int loadAddress)
{
this (name, buffer, loadAddress, false);
}
public HiResImage (String name, byte[] buffer, int loadAddress, boolean scrunched)
{
super (name, buffer);
this.loadAddress = loadAddress; // for the disassembly listing
if (scrunched)
this.buffer = unscrunch (buffer);
}
public HiResImage (String name, byte[] buffer, int fileType, int auxType)
{
super (name, buffer);
this.fileType = fileType;
this.auxType = auxType;
}
protected void createImage ()
{
2017-01-25 05:26:37 +00:00
if (isGif (buffer) || isPng (buffer) || isBmp (buffer))
2016-12-31 09:34:15 +00:00
makeImage ();
else if (monochrome)
createMonochromeImage ();
else
createColourImage ();
}
protected abstract void createMonochromeImage ();
protected abstract void createColourImage ();
2017-01-14 20:58:07 +00:00
public void checkPalette ()
{
if (!monochrome && paletteIndex != paletteFactory.getCurrentPaletteIndex ())
createImage ();
}
2017-01-14 11:11:07 +00:00
public void setPalette ()
2017-01-11 21:26:28 +00:00
{
if (!monochrome)
createImage ();
}
2016-12-31 09:34:15 +00:00
public void setColourQuirks (boolean value)
{
if (colourQuirks == value)
return;
colourQuirks = value;
if (!monochrome)
createImage ();
}
public void setMonochrome (boolean value)
{
if (monochrome == value)
return;
monochrome = value;
createImage ();
}
public static void setDefaultColourQuirks (boolean value)
{
colourQuirks = value;
}
public static void setDefaultMonochrome (boolean value)
{
monochrome = value;
}
/*-
Mode Page 1 Page 2
280 x 192 Black & White 0 4
280 x 192 Limited Color 1 5
560 x 192 Black & White 2 6
140 x 192 Full Color 3 7
*/
// SHR see - http://noboot.com/charlie/cb2e_p3.htm
@Override
public String getText ()
{
String auxText = "";
StringBuilder text = new StringBuilder ("Image File : " + name);
text.append (String.format ("%nFile type : $%02X", fileType));
switch (fileType)
{
case ProdosConstants.FILE_TYPE_PICT:
if (auxType < 0x4000)
{
auxText = "Graphics File";
byte mode = buffer[0x78]; // 0-7
System.out.println ("Prodos PICT, mode=" + mode);
}
else if (auxType == 0x4000)
auxText = "Packed Hi-Res File";
else if (auxType == 0x4001)
auxText = "Packed Double Hi-Res File";
break;
case ProdosConstants.FILE_TYPE_PNT:
if (auxType == 1)
auxText = "Packed Super Hi-Res Image";
else if (auxType == 2)
2017-01-25 01:38:00 +00:00
auxText = "Super Hi-Res Image (Apple Preferred)";
2016-12-31 09:34:15 +00:00
else if (auxType == 3)
auxText = "Packed QuickDraw II PICT File";
break;
case ProdosConstants.FILE_TYPE_PIC:
if (auxType == 0)
auxText = "Super Hi-res Screen Image";
else if (auxType == 1)
auxText = "QuickDraw PICT File";
else if (auxType == 2)
auxText = "Super Hi-Res 3200 color image";
}
if (!auxText.isEmpty ())
text.append (String.format ("%nAux type : $%04X %s", auxType, auxText));
text.append (String.format ("%nFile size : %,d", buffer.length));
if (unpackedBuffer != null)
{
text.append (String.format ("%nUnpacked : %,d%n%n", unpackedBuffer.length));
2017-01-25 01:38:00 +00:00
// text.append (HexFormatter.format (unpackedBuffer));
2016-12-31 09:34:15 +00:00
}
return text.toString ();
}
2017-01-15 11:29:11 +00:00
protected void makeScreen (byte[] buffer)
2016-12-31 09:34:15 +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 = (buffer[ptr] & 0xF0) >> 4;
int pix2 = buffer[ptr] & 0x0F;
if (pix1 > 0)
db.setElem (element, 255);
if (pix2 > 0)
db.setElem (element + 1, 255);
element += 2;
ptr++;
}
}
2017-01-25 04:40:15 +00:00
/*
* Unpack the Apple PackBytes format.
*
* Format is:
* <flag><data> ...
*
* Flag values (first 6 bits of flag byte):
* 00xxxxxx: (0-63) 1 to 64 bytes follow, all different
* 01xxxxxx: (0-63) 1 to 64 repeats of next byte
* 10xxxxxx: (0-63) 1 to 64 repeats of next 4 bytes
* 11xxxxxx: (0-63) 1 to 64 repeats of next byte taken as 4 bytes
* (as in 10xxxxxx case)
*/
2016-12-31 09:34:15 +00:00
// Super Hi-res IIGS
protected byte[] unpackBytes (byte[] buffer)
{
// routine found here - http://kpreid.livejournal.com/4319.html
byte[] newBuf = new byte[32768];
byte[] fourBuf = new byte[4];
int ptr = 0, newPtr = 0;
while (ptr < buffer.length)
{
2017-01-24 08:59:40 +00:00
int type = (buffer[ptr] & 0xC0) >> 6; // 0-3
int count = (buffer[ptr++] & 0x3F) + 1; // 1-64
2016-12-31 09:34:15 +00:00
switch (type)
{
case 0:
while (count-- != 0)
newBuf[newPtr++] = buffer[ptr++];
break;
case 1:
byte b = buffer[ptr++];
while (count-- != 0)
newBuf[newPtr++] = b;
break;
case 2:
for (int i = 0; i < 4; i++)
fourBuf[i] = buffer[ptr++];
while (count-- != 0)
for (int i = 0; i < 4; i++)
newBuf[newPtr++] = fourBuf[i];
break;
case 3:
b = buffer[ptr++];
count *= 4;
while (count-- != 0)
newBuf[newPtr++] = b;
break;
}
}
return newBuf;
}
// Beagle Bros routine to expand a hi-res screen
private byte[] unscrunch (byte[] src)
{
byte[] dst = new byte[0x2000];
int p1 = 0;
int p2 = 0;
while (p1 < dst.length)
{
byte b = src[p2++];
if ((b == (byte) 0x80) || (b == (byte) 0xFF))
{
b &= 0x7F;
int rpt = src[p2++];
for (int i = 0; i < rpt; i++)
dst[p1++] = b;
}
else
dst[p1++] = b;
}
return dst;
}
protected void makeImage ()
{
try
{
image = ImageIO.read (new ByteArrayInputStream (buffer));
}
catch (IOException e)
{
e.printStackTrace ();
}
2017-01-25 05:26:37 +00:00
catch (IndexOutOfBoundsException e) // some BMP files cause this
{
System.out.println ("Error in makeImage()");
System.out.println (e.getMessage ());
}
2016-12-31 09:34:15 +00:00
}
public static boolean isGif (byte[] buffer)
{
if (buffer.length < 6)
return false;
String text = new String (buffer, 0, 6);
return text.equals ("GIF89a") || text.equals ("GIF87a");
}
public static boolean isPng (byte[] buffer)
{
if (buffer.length < pngHeader.length)
return false;
for (int i = 0; i < pngHeader.length; i++)
if (pngHeader[i] != buffer[i])
return false;
return true;
}
2017-01-12 22:11:05 +00:00
2017-01-25 05:26:37 +00:00
public static boolean isBmp (byte[] buffer)
{
if (buffer.length < 2)
return false;
String text = new String (buffer, 0, 2);
return text.equals ("BM");
}
2017-01-14 01:40:58 +00:00
public static PaletteFactory getPaletteFactory ()
2017-01-12 22:11:05 +00:00
{
2017-01-14 01:40:58 +00:00
return paletteFactory;
2017-01-12 22:11:05 +00:00
}
2017-01-14 01:40:58 +00:00
public static List<Palette> getPalettes ()
2017-01-12 22:11:05 +00:00
{
2017-01-14 01:40:58 +00:00
return paletteFactory.getPalettes ();
2017-01-12 22:11:05 +00:00
}
2015-06-01 09:35:51 +00:00
}