Skip to content

Commit

Permalink
Support converting PNG files to GZip
Browse files Browse the repository at this point in the history
  • Loading branch information
NeRdTheNed committed Aug 16, 2023
1 parent ba16b25 commit 0ed7077
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@
import java.util.List;
import java.util.concurrent.Callable;

import com.github.NeRdTheNed.deft4j.container.ContainerUtil;
import com.github.NeRdTheNed.deft4j.container.DeflateFilesContainer;
import com.github.NeRdTheNed.deft4j.container.GZFile;
import com.github.NeRdTheNed.deft4j.container.ZipFile;
import com.github.NeRdTheNed.deft4j.container.ToGZipConvertible;

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;

@Command(name = "convert-zip", description = "Converts a given zip file to GZip files")
class ConvertZip implements Callable<Integer> {
@Command(name = "convert-to-gzip", aliases = { "convert-png", "convert-zip" }, description = "Converts a given file to GZip files")
class ConvertToGZip implements Callable<Integer> {

@Parameters(index = "0", description = "The input zip file")
@Parameters(index = "0", description = "The input file")
private Path inputFile;

@Parameters(index = "1", description = "The directory to output files to")
Expand All @@ -44,14 +46,19 @@ public Integer call() throws Exception {

try
(final InputStream is = new BufferedInputStream(Files.newInputStream(inputFile));
final ZipFile zip = new ZipFile()) {
if (!zip.read(is)) {
final DeflateFilesContainer container = ContainerUtil.getContainerForPath(inputFile)) {
if (!container.read(is)) {
System.err.println("Failed to read input file");
}

System.out.println("Read input file " + inputFile);
converted = zip.asGZipFiles();
System.out.println("Converted to GZip, writing files...");

if (container instanceof ToGZipConvertible) {
converted = ((ToGZipConvertible) container).asGZipFiles();
System.out.println("Converted to GZip, writing files...");
} else {
System.out.println("Could not convert input file " + inputFile + " to GZip");
}
} catch (final IOException e) {
System.err.println("IOException thrown when reading file " + inputFile);
e.printStackTrace();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import picocli.CommandLine;
import picocli.CommandLine.Command;

@Command(name = "deft4j", version = "deft4j v1.0.0-beta-5", subcommands = { Optimise.class, OptimiseFolder.class, ConvertZip.class })
@Command(name = "deft4j", version = "deft4j v1.0.0-beta-5", subcommands = { Optimise.class, OptimiseFolder.class, ConvertToGZip.class })
public class Main {
public static void main(String[] args) {
final int exitCode = new CommandLine(new Main()).execute(args);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.CRC32;

import com.github.NeRdTheNed.deft4j.deflate.DeflateStream;
import com.github.NeRdTheNed.deft4j.util.Util;

public class PNGFile implements DeflateFilesContainer {
public class PNGFile implements DeflateFilesContainer, ToGZipConvertible {
class PNGChunk {
final byte[] type = new byte[4];
byte[] data;
Expand Down Expand Up @@ -178,6 +179,35 @@ boolean read(InputStream is) throws IOException {
/** Cached CRC32 calculator */
private final CRC32 crc32Calc = new CRC32();

@Override
public List<GZFile> asGZipFiles() throws IOException {
final List<GZFile> converted = new ArrayList<>();
final GZFile idatGZ = new GZFile();
idatGZ.setData(idat.deflateStream);
idatGZ.setFilename("IDAT");
converted.add(idatGZ);
final Map<String, Integer> seenChunks = new HashMap<>();

for (final Entry<PNGChunk, DeflateFilesContainer> entry : deflateStreamMapNonIDAT.entrySet()) {
final PNGChunk chunk = entry.getKey();
final DeflateFilesContainer container = entry.getValue();
final String type = chunk.type();
final int seen = seenChunks.merge(type, 1, Integer::sum);
final List<DeflateStream> streams = container.getDeflateStreams();
final int streamsSize = streams.size();

for (int i = 0; i < streamsSize; i++) {
final String name = type + "-num-" + seen + "-stream-" + i;
final GZFile chunkGZ = new GZFile();
chunkGZ.setData(streams.get(i));
chunkGZ.setFilename(name);
converted.add(chunkGZ);
}
}

return converted;
}

private void syncStreams() throws IOException {
// Find the first IDAT chunk, and store the index
final PNGChunk firstIDAT = pngChunks.stream().filter(PNGChunk::isIDAT).findFirst().orElseThrow(() -> new IOException("No IDAT chunk found in PNG"));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.github.NeRdTheNed.deft4j.container;

import java.io.IOException;
import java.util.List;

public interface ToGZipConvertible {
List<GZFile> asGZipFiles() throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@
import software.coley.lljzip.util.BufferData;
import software.coley.lljzip.util.ByteDataUtil;

public class ZipFile implements DeflateFilesContainer {
public class ZipFile implements DeflateFilesContainer, ToGZipConvertible {
private Map<LocalFileHeader, DeflateStream> deflateStreamMap;
private ZipArchive archive;

@Override
public List<GZFile> asGZipFiles() throws IOException {
final List<GZFile> converted = new ArrayList<>();

Expand Down

0 comments on commit 0ed7077

Please sign in to comment.