Git Product home page Git Product logo

Comments (7)

ben-manes avatar ben-manes commented on July 20, 2024 1

and just like that I got it working πŸ™‚

IIOMetadata metadata = new TIFFImageMetadata(List.of(
    new TIFFEntry(TIFF.TAG_X_RESOLUTION, 200),
    new TIFFEntry(TIFF.TAG_Y_RESOLUTION, 200)));
var type = ImageTypeSpecifier.createFromBufferedImageType(TYPE_INT_RGB);
metadata = writer.convertImageMetadata(metadata, type, null);

from twelvemonkeys.

ben-manes avatar ben-manes commented on July 20, 2024 1

okay, so I lied πŸ˜„

I'm not sure exactly why, but I have it now working with both writers. I believe somewhere I must have passed in the wrong property, e.g. the write params, and caused some corrupted output. I'll stop spamming you, hopefully.

from twelvemonkeys.

haraldk avatar haraldk commented on July 20, 2024 1

No worries!

I've been away on summer holiday, so not been able to comment. But glad you figured it out! πŸ˜€

from twelvemonkeys.

ben-manes avatar ben-manes commented on July 20, 2024

haha, given it was very late I immediately went to bed and I completely missed that the output came out purple 😞

I tried some of the other color spaces without any luck. Hopefully I have some time today to dig into it, but any hints would be appreciated.

Java
import static java.awt.AlphaComposite.Src;
import static java.awt.RenderingHints.KEY_DITHERING;
import static java.awt.RenderingHints.VALUE_DITHER_DISABLE;
import static java.awt.image.BufferedImage.TYPE_BYTE_BINARY;
import static java.nio.ByteOrder.BIG_ENDIAN;
import static javax.imageio.ImageWriteParam.MODE_EXPLICIT;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.IntStream;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.twelvemonkeys.image.MonochromeColorModel;
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
import com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadata;

import net.autobuilder.AutoBuilder;

public class TiffTest {

  public static void main(String[] args) {
//    create(TiffSettings.group4()
//        .addToImages(Path.of("/Users/ben/Downloads/original.jpg"))
//        .destination(Path.of("/Users/ben/Downloads/java_g4.tif"))
//        .build());
//    create(TiffSettings.lzwColor()
//        .addToImages(Path.of("/Users/ben/Downloads/original.jpg"))
//        .destination(Path.of("/Users/ben/Downloads/java_lzw.tif"))
//        .build());
    create(TiffSettings.jpegColor()
        .addToImages(Path.of("/Users/ben/Downloads/original.jpg"))
        .destination(Path.of("/Users/ben/Downloads/java_jpg.tif"))
        .build());
    System.out.println("done");
  }

  public static void create(TiffSettings settings) {
    var images = new BufferedImage[settings.images().size()];
    ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next();
    try (var fileOutput = Files.newOutputStream(settings.destination());
         var output = ImageIO.createImageOutputStream(fileOutput)) {
      for (int i = 0; i < settings.images().size(); i++) {
        images[i] = ImageIO.read(settings.images().get(i).toFile());
        if (settings.monochrome()) {
          images[i] = convertMonochrome(images[i]);
        }
      }

      output.setByteOrder(BIG_ENDIAN);
      writer.setOutput(output);

      var params = writer.getDefaultWriteParam();
      params.setCompressionMode(MODE_EXPLICIT);
      params.setCompressionType(settings.compression());
      var tiffMetadata = new TIFFImageMetadata(List.of(
          new TIFFEntry(TIFF.TAG_X_RESOLUTION, 200),
          new TIFFEntry(TIFF.TAG_Y_RESOLUTION, 200)));
      var type = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
      var metadata = writer.convertImageMetadata(tiffMetadata, type, /* write param */ null);

      writer.prepareWriteSequence(/* stream metadata */ null);
      for (var image : images) {
        writer.writeToSequence(new IIOImage(image, /* thumbnails */ null, metadata), params);
      }
      writer.endWriteSequence();
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    } finally {
      writer.dispose();
    }
  }

  private static BufferedImage convertMonochrome(BufferedImage source) {
    if (IntStream.of(source.getSampleModel().getSampleSize()).sum() == 1) {
      return source;
    }

    var destination = new BufferedImage(source.getWidth(), source.getHeight(),
        TYPE_BYTE_BINARY, MonochromeColorModel.getInstance());
    var graphics = destination.createGraphics();
    try {
      graphics.setComposite(Src);
      graphics.setRenderingHint(KEY_DITHERING, VALUE_DITHER_DISABLE);
      graphics.drawImage(source, 0, 0, null);
      return destination;
    } finally {
      graphics.dispose();
    }
  }

  @AutoValue @AutoBuilder
  public static abstract class TiffSettings {
    public abstract ImmutableList<Path> images();
    public abstract ByteOrder byteOrder();
    public abstract String compression();
    public abstract boolean monochrome();
    public abstract Path destination();
    public abstract int xResolution();
    public abstract int yResolution();

    public static TiffTest_TiffSettings_Builder group4() {
      return builder()
          .compression("CCITT T.6")
          .monochrome(true)
          .xResolution(200)
          .yResolution(200);
    }

    public static TiffTest_TiffSettings_Builder jpegColor() {
      return builder()
          .compression("JPEG")
          .xResolution(200)
          .yResolution(200);
    }

    public static TiffTest_TiffSettings_Builder lzwColor() {
      return builder()
          .compression("LZW")
          .xResolution(72)
          .yResolution(72);
    }

    public static TiffTest_TiffSettings_Builder builder() {
      return TiffTest_TiffSettings_Builder.builder()
          .byteOrder(BIG_ENDIAN);
    }
  }
}

from twelvemonkeys.

haraldk avatar haraldk commented on July 20, 2024

Hi Ben,

I don’t have a computer nearby at the moment, sorry. I type this on my phone.

But keep in mind that image metadata is per image/IFD in the TIFF. So you should probably create the metadata object inside the loop where you write images. Also, the type var should be created from the actual image you write (use ITS.createFromRenderedImag(image)).

from twelvemonkeys.

ben-manes avatar ben-manes commented on July 20, 2024

thanks! I appreciate the response and please don't bother yourself when not available or it is a hassle.

I actually did that in a refactoring between meetings. I think the issue is something to do with the alpha channel or in some "transparency" mode, where I read index 0 is r=255,g=0,b=255 which is pink. If I convert the original jpg with ImageMagick, it turns from sRGB 3-channel to Grayscale 2-channel and the tiff (jpeg compressed) is perfect. This could be from downloading a sample from the CDN which would do some mozjpeg-style optimization to the jpeg. That might not happen on the source image in the pipeline and that I should download a better sample.

from twelvemonkeys.

ben-manes avatar ben-manes commented on July 20, 2024

oh oh oh! This is actually a bug in TwelveMonkeys.

If I select the com.sun.imageio.plugins.tiff.TIFFImageWriter then the jpeg-encoded tiff is rendered correctly. It has a white background. The com.twelvemonkeys.imageio.plugins.tiff.TIFFImageWriter implementation has a pink background.

The DPI metadata did not get applied where it defaults to 78. So I would need to handle that xml nonsense, which looked very messy when I was searching yesterday.

Unfortunately it does seem that I found a bug here. Attached is a zip containing my test sample and outputs.

images.zip

from twelvemonkeys.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.