Skip to content

Commit

Permalink
Test out CPS writer - still no good
Browse files Browse the repository at this point in the history
  • Loading branch information
ultraq committed May 5, 2024
1 parent a685451 commit c0ab3a4
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 51 deletions.
24 changes: 13 additions & 11 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@
/libraries
/mix
/mods
/*.aud
/*.cps
/*.ini
/*.log
/*.mix
/*.pcx
/*.shp
/*.v00
/*.vqa
/*.wsa
build

build/

*.aud
*.cps
*.ini
*.log
*.mix
*.pcx
*.shp
*.v00
*.vqa
*.wsa
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,27 @@ class CpsFileWriter extends FileWriter<ImageFile, Void> {
@Override
void write(OutputStream outputStream, Void options) {

def output = new NativeDataOutputStream(outputStream)
def lcw = new LCW()
def palette = source instanceof InternalPalette ? source.palette : null
var output = new NativeDataOutputStream(outputStream)
var lcw = new LCW()
var palette = source instanceof InternalPalette ? source.palette : null

// Encode image
def encodedImage = lcw.encode(source.imageData, ByteBuffer.allocateNative(source.imageData.capacity()))
var encodedImage = lcw.encode(source.imageData, ByteBuffer.allocateNative(source.imageData.capacity()))

// Write header
output.writeShort(8 + encodedImage.limit()) // (Header - this value) + image
output.writeShort(COMPRESSION_LCW)
output.writeShort(IMAGE_SIZE)
output.writeShort(0)
output.writeInt(IMAGE_SIZE)
output.writeShort(palette ? PALETTE_SIZE : 0)

// Write optional palette and image data
// Write optional palette
if (palette) {
palette.size.times { i ->
output.write(palette[i])
}
}

// Write image data
output.write(encodedImage.array(), 0, encodedImage.limit())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ class ShpFile implements ImagesFile {
static final byte FORMAT_LCW = (byte)0x80
static final byte FORMAT_XOR_BASE = (byte)0x40
static final byte FORMAT_XOR_CHAIN = (byte)0x20
private static final byte[] FORMATS = [FORMAT_LCW, FORMAT_XOR_BASE, FORMAT_XOR_CHAIN]
// @formatter:on

private final NativeDataInputStream input
Expand Down Expand Up @@ -98,7 +97,7 @@ class ShpFile implements ImagesFile {
imageOffsets = new ShpImageInfo[numImages + 2]
imageOffsets.length.times { i ->
var imageInfo = new ShpImageInfo(input)
assert imageInfo.offsetFormat == 0 || imageInfo.offsetFormat in FORMATS
assert imageInfo.offsetFormat == 0 || imageInfo.offsetFormat in [FORMAT_LCW, FORMAT_XOR_BASE, FORMAT_XOR_CHAIN]
imageOffsets[i] = imageInfo
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class Pcx2CpsConverterCli implements Callable<Integer> {
if (!destFile.exists()) {
sourceFile.withInputStream { inputStream ->
destFile.withOutputStream { outputStream ->
def pcxFile = new PcxFile(inputStream)
var pcxFile = new PcxFile(inputStream)
new CpsFileWriter(pcxFile).write(outputStream)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ class Pcx2CpsConverterCliTests extends Specification {
@Ignore("CPS conversion got busted somewhere along the way 😢")
def "Converts a PCX file to a CPS file"() {
given:
var pcxPath = 'nz/net/ultraq/redhorizon/cli/converter/alipaper.pcx'
var cpsPath = 'nz/net/ultraq/redhorizon/cli/converter/alipaper.cps'
var pcxPath = 'alipaper.pcx'
var cpsPath = 'alipaper.cps'
var converter = new Pcx2CpsConverterCli(
sourceFile: getResourceAsFile(pcxPath),
destFile: new File("${System.getProperty('user.dir')}/build/classes/test/${cpsPath}"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
/*
* Copyright 2007 Emanuel Rabina (http://www.ultraq.net.nz/)
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -18,7 +18,7 @@ package nz.net.ultraq.redhorizon.filetypes

import nz.net.ultraq.redhorizon.filetypes.codecs.RunLengthEncoding
import nz.net.ultraq.redhorizon.filetypes.io.NativeDataInputStream
import static nz.net.ultraq.redhorizon.filetypes.ColourFormat.*
import static nz.net.ultraq.redhorizon.filetypes.ColourFormat.FORMAT_RGB

import java.nio.ByteBuffer

Expand All @@ -30,14 +30,15 @@ import java.nio.ByteBuffer
* but for the purpose of Red Horizon, PCX files will be of the type used in the
* Command & Conquer games: a 256-colour file with an internal palette located
* at the tail of the file.
*
*
* @author Emanuel Rabina.
*/
@FileExtensions('pcx')
@SuppressWarnings('GrFinalVariableAccess')
class PcxFile implements ImageFile, InternalPalette {

// Header constants
// @formatter:off
static final int HEADER_PALETTE_SIZE = 48
static final byte MANUFACTURER_ZSOFT = 0x0a // 10 = ZSoft .pcx
static final byte VERSION_PCP25 = 0 // PC Paintbrush 2.5
Expand All @@ -51,6 +52,7 @@ class PcxFile implements ImageFile, InternalPalette {
static final int PALETTE_COLOURS = 256
static final int PALETTE_SIZE = PALETTE_COLOURS * FORMAT_RGB.value
static final int PALETTE_PADDING_SIZE = 1
// @formatter:on

// Header data
final byte manufacturer
Expand Down Expand Up @@ -80,23 +82,19 @@ class PcxFile implements ImageFile, InternalPalette {

/**
* Constructor, creates a new PCX file from data in the given input stream.
*
*
* @param inputStream Input stream of the PCX file data.
*/
PcxFile(InputStream inputStream) {

def input = new NativeDataInputStream(inputStream)
var input = new NativeDataInputStream(inputStream)

// File header
manufacturer = input.readByte()
assert manufacturer == MANUFACTURER_ZSOFT

version = input.readByte()
assert version == VERSION_PCP25 ||
version == VERSION_PCP28_PAL ||
version == VERSION_PCP28_NO_PAL ||
version == VERSION_PCP4WIN ||
version == VERSION_PCPPLUS
assert version in [VERSION_PCP25, VERSION_PCP28_PAL, VERSION_PCP28_NO_PAL, VERSION_PCP4WIN, VERSION_PCPPLUS]

encoding = input.readByte()
assert encoding == ENCODING_RLE
Expand All @@ -111,41 +109,41 @@ class PcxFile implements ImageFile, InternalPalette {
hdpi = input.readShort()
vdpi = input.readShort()

egaPalette = input.readNBytes(HEADER_PALETTE_SIZE)
reserved = input.readByte()
planes = input.readByte()
egaPalette = input.readNBytes(HEADER_PALETTE_SIZE)
reserved = input.readByte()
planes = input.readByte()
bytesPerLine = input.readShort()
paletteInfo = input.readShort()
hScreenSize = input.readShort()
vScreenSize = input.readShort()
filler = input.readNBytes(54)
paletteInfo = input.readShort()
hScreenSize = input.readShort()
vScreenSize = input.readShort()
filler = input.readNBytes(54)

width = xMax - xMin + 1
height = yMax - yMin + 1

// Read the rest of the stream
def imageAndPalette = input.readAllBytes()
def encodedImage = ByteBuffer.wrapNative(imageAndPalette, 0, imageAndPalette.length - PALETTE_SIZE - PALETTE_PADDING_SIZE)
var imageAndPalette = input.readAllBytes()
var encodedImage = ByteBuffer.wrapNative(imageAndPalette, 0, imageAndPalette.length - PALETTE_SIZE - PALETTE_PADDING_SIZE)

// Build up the raw image data for use with a palette later
// NOTE: The below is for the case when the scanline data exceeds the
// width/height data, but have I ever encountered that? Otherwise
// this is double-handling the same data.
def scanLines = new ArrayList<ByteBuffer>()
def runLengthEncoding = new RunLengthEncoding((byte)0xc0)
var scanLines = new ArrayList<ByteBuffer>()
var runLengthEncoding = new RunLengthEncoding((byte)0xc0)
while (encodedImage.hasRemaining()) {
scanLines << runLengthEncoding.decode(encodedImage, ByteBuffer.allocateNative(planes * bytesPerLine))
}
def indexedData = ByteBuffer.allocateNative(width * height)
var indexedData = ByteBuffer.allocateNative(width * height)
(yMin..yMax).each { y ->
def scanLine = scanLines[y]
var scanLine = scanLines[y]
(xMin..xMax).each { x ->
indexedData.put(scanLine.get(x))
}
}
indexedData.flip()

def paletteData = ByteBuffer.wrapNative(imageAndPalette, imageAndPalette.length - PALETTE_SIZE, PALETTE_SIZE)
var paletteData = ByteBuffer.wrapNative(imageAndPalette, imageAndPalette.length - PALETTE_SIZE, PALETTE_SIZE)
palette = new Palette(PALETTE_COLOURS, FORMAT_RGB, paletteData)

// Apply palette to raw image data to create the final image
Expand All @@ -154,7 +152,7 @@ class PcxFile implements ImageFile, InternalPalette {

/**
* Returns some information on this PCX file.
*
*
* @return PCX file info.
*/
@Override
Expand Down

0 comments on commit c0ab3a4

Please sign in to comment.