I am looking at examples of icafe library https://github.com/dragon66/icafe to see how to manipulate the image metadata but I can't find any examples.
I am trying to add a field to the exif metadata like Description and add some sample text to that field.
Also, from what I have found I can't seem to tell whether icafe will work on image input stream or does it need an absolute path to a file stored on the disk?
Although there is no example on the wiki page, there is actually a detailed example on how to manipulate metadata which can be found in the source code package com.icafe4j.test. The name for the class is TestMetadata which shows you how to insert different metadata like EXIF, IPTC, XMP, Comment, Thumbnail etc.
ICAFE works with InputStream and OutputStream. So it doesn't matter if it comes from a local file or not as long as it is an InputStream. If you only want to add some comments, you can simply do something like this:
FileInputStream fin = new FileInputStream("input.png");
FileOutputStream fout = new FileOutputStream("comment-inserted.png");
Metadata.insertComments(fin, fout, Arrays.asList("Comment1", "Comment2"));
The above code works for common image formats like JPEG, TIFF, PNG, GIF etc equally as long as the format supports certain metadata.
If you want to work with Exif, you can use:
Metadata.insertExif(InputStream fin, OutputStream fout, Exif exif, boolean upate);
which also has a parameter "update" to control whether or not you want to keep the original Exif data if present. Details on how to create Exif instance can be found from the same example.
Related
I found a java code that converts a jpg and a Dicom(it takes the metadata friĀ”om that one) files to a final Dicom one. What I want to do is convert the jpg image into a Dicom one, generating the metadata with java code.
BufferedImage jpg = ImageIO.read(new File("myjpg.jpg"));
// Convert the image to a byte array
DataBuffer buff = jpg.getData().getDataBuffer();
DataBufferUShort buffer = new DataBufferUShort(buff.getSize());
for (int i = 0; i < buffer.getSize(); ++i)
buffer.setElem(i, buff.getElem(i));
short[] data = buffer.getData();
ByteBuffer byteBuf = ByteBuffer.allocate(2 * data.length);
int i = 0;
while (data.length > i) {
byteBuf.putShort(data[i]);
i++;
}
// Copy a header
DicomInputStream dis = new DicomInputStream(new File("fileToCopyheaderFrom.dcm"));
Attributes meta = dis.readFileMetaInformation();
Attributes attribs = dis.readDataset(-1, Tag.PixelData);
dis.close();
// Change the rows and columns
attribs.setInt(Tag.Rows, VR.US, jpg.getHeight());
attribs.setInt(Tag.Columns, VR.US, jpg.getWidth());
System.out.println(byteBuf.array().length);
// Write the file
attribs.setBytes(Tag.PixelData, VR.OW, byteBuf.array());
DicomOutputStream dcmo = new DicomOutputStream(new File("myDicom.dcm"));
dcmo.writeFileMetaInformation(meta);
attribs.writeTo(dcmo);
dcmo.close();
I am not expert in toolkit (and of-course Java as well).
Your "// Copy a header" section reads the source DICOM file and holds all the attributes in Attributes attribs variable.
Then, your "// Change the rows and columns" section modifies few attributes as per need.
Then, your "// Write the file" section simply add the attributes read from source file to destination file.
Now, you want to bypass the source DICOM file and convert plain JPEG to DICOM with adding attributes yourself.
Replace your "// Copy a header" section to build the instance of Attributes.
Attributes attribs = new Attributes();
attribs.setString(Tag.StudyDate, VR.DA, "20110404");
attribs.setString(Tag.StudyTime, VR.TM, "15");
The tags mentioned in above example are for example only. You have to decide yourself which tags you want to include. Note that specifications have defined Types 1, 1C, 2, 2C and 3 for tags depending on the SOP class you are dealing with.
While adding the tags, you have to take care of correct VR as well. Specifications talk about that thing as well.
I cannot explain all this here; too broad.
I cannot help about dcm4che, but if using another Java DICOM library is an option for you, this task is quite simple using DeCaMino (http://dicomplugin.com) :
BufferedImage jpg = ImageIO.read(new File("myjpg.jpg"));
DicomWriter dw = new DicomWriter();
dw.setOutput(new File("myjpg.dcm"));
DicomMetadata dmd = new DicomMetadata();
dw.write(dmd, new IIOImage(jpg, null, null), null);
This will write a DICOM conform file with SOP class "secondary capture" and default metadata.
To customize the metadata, add data elements to dmd before writing, e.g. :
DataSet ds = dmd.getDataSet();
ds.set(Tag.StudyDate, LocalDate.of(2011, 4, 4));
ds.set(Tag.StudyTime, LocalTime.of(15, 0, 0));
You can also change the transfer syntax (thus controlling the pixel data encoding) :
dw.setTransferSyntax(UID.JPEG2000TS);
Disclaimer: I'm the author of DeCaMino.
EDIT: As kritzel_sw says, I'll strongly advice against modifying and existing DICOM object by changing pixel data and some data element, you'll mostly end with a non-conform object. Better is to write an object from scratch, and the simplest objects are from the secondary capture class. DeCaMino helps you by generating a conform secondary capture object with mandatory data elements, but it won't help you to generate a modality (like a CT acquisition) object.
Just a side note:
attribs.setBytes(Tag.PixelData, VR.OW, byteBuf.array());
VR.OW means 16 bits per pixel/channel. Since you are replacing the pixel data with pixel data read from a JPEG image, and you named the buffer "byteBuf", I suspect that this is inconsistent. VR.OB is the value representation for 8 bits per pixel/channel image.
Talking about channels, I understand that you want to make construction of a DICOM object easy by modifying an existing DICOM image rather than creating a new one from scratch. However, color pixel data is not appropriate for all types of DICOM images. E.g. if your fileToCopyheaderFrom.dcm is a Radiography, CT or MRI image (or many other radiology types), it is not allowed to add color pixel data to it.
Furthermore, each image contains identifying information (Study-, Series-, SOP Instance UID are the most important ones) which should be replaced by newly generated values.
I understand that it appears appealing to modify an existing DICOM object with new pixel data, but this process is probably much more complicated than you would expect it to be. In both cases, it is inevitable to learn basic DICOM concepts.
I have a photoshop file that I want to be able to change 2 text values with a java program. Opening the PSD with a text editor I can find the text that I want to change. LayerText Eighty, LayerText Nine
I hid some content with blue for privacy reasons. If I use exiftool gui i see [this][2]. So I assumed it was under TextLayerText. In photoshop they are [text layers.][3] I did some research and heard about Sanselan in apache commons. I can find the same code that I found in my [text editor][4].
File imageFile = new File(fileField.getText());
File outputFile = new File(fileField.getText().split("\\.")[0] + ".png");
BufferedImage image = Sanselan.getBufferedImage(imageFile);
logArea.append("--- XMP Metadata ----\n");
logArea.append(Sanselan.getXmpXml(imageFile));
Map params = new HashMap();
params.put("TextLayerText", "");
Sanselan.writeImage(image, outputFile, ImageFormat.IMAGE_FORMAT_PNG, params);
This is the code I currently have. It declares 2 files first is input and 2nd is output. It gets the XMP and prints it out. I create a params Map but my error is.
org.apache.sanselan.ImageWriteException: Unknown parameter: TextLayerText
The goal of this program is to modify the 2 text layers and render the png from this. It renders the png file if i leave the params blank, and i can read the params with Sanselan.getXmpXml. I am struggling to find a way to change them though. I put all pictures in one because of my reputation I can't post more than 2 links.
I'm using JAudioTagger to fetch the metadata from music files, getting the title, year etc is working fine but I am having a problem with getting the cover art. I have not been able to find any examples searching online, any help would be great!
Here is my current code, which the coverArt BufferedImage is showing up as null when debugging. I have checked and the mp3 file has a cover image.
ID3v23Tag id3v23Tag = (ID3v23Tag)tag;
TagField coverArtField =
id3v23Tag.getFirstField(org.jaudiotagger.tag.id3.ID3v23FieldKey.COVER_ART.getFieldName());
FrameBodyAPIC body = (FrameBodyAPIC)((ID3v23Frame)coverArtField).getBody();
byte[] imageRawData = (byte[])body.getObjectValue(DataTypes.OBJ_PICTURE_DATA);
coverArt = ImageIO.read(ImageIO.createImageInputStream(new ByteArrayInputStream(imageRawData)));
In my application I use
MP3File mp3;
mp3.getTag().getFirstArtwork();
which returns the firstArtwork of the MP3 (which is in most cases the cover you are looking for). This can be cast to a BufferedImage if necessary.
Anyone still looking for an answer can do this..
AudioFile f = AudioFileIO.read(new File(path));
Tag tag = f.getTag();
if(tag.hasField("Cover Art")){
byte[] b = tag.getFirstArtwork().getBinaryData();
}
Now you have your image in binary data. you can easily use it with glide or picasso if you want..
Glide.with(this).load(b).into(ImageView);
Normally, the easiest way is simply:
List<Artwork> existingArtworkList = tag.getArtworkList();
You don't have to perform any casting nor work at the frame body level. Is there are reason you are doing this?
Take a look at the imageRawData - is that being read correctly? Maybe the problem is at the imageio level. If it's a JPEG it should begin 0xFF, 0xD8 for example.
I have a solution that inserts strings into an XHTML document and prints the results as Reports. My employer has asked if we could pull images off their SQL database (stored as byte arrays) to insert into the Reports.
I am using FlyingSaucer as the XHTML interpreter and I've been using Java DOM to modify pre-stored reports that I have stored in the Report Generator's package.
The only solution I can think of at the moment is to construct the images, save them as a file, link the file in an img tag (or background-image) in a constructed report, print the report and then delete the file. This seems really sloppy and I imagine it will be very time consuming.
I can't help but feel there must be a more elegant solution. Any suggestions for inserting a byte array into html?
Read the image and convert it into it's Base64-encoded form:
InputStream image = getClass().getClassLoader().getResourceAsStream("image.png");
String encodedImage = BaseEncoding.base64().encode(ByteStreams.toByteArray(image));
I've used BaseEncoding and ByteStreams from Google Guava.
Change src attribute of img element within your Document object.
Document doc = ...; // get Document from XHTMLPanel.getDocument() or create
// new one using DocumentBuilderFactory
doc.getElementById("myImage").getAttributes().getNamedItem("src").setNodeValue("data:image/png;base64," + encodedImage);
Unfortunatley FlyingSaucer does not support DataURIs out-of-the-box so you'll have to create your own ReplacedElementFactory. Read Using Data URLs for embedding images in Flying Saucer generated PDFs article - it contains a complete solution.
I have been reading a gif Image as an ImageInputStream using java.mageio.stream api. Is there a way I can parser that stream "manually" , in order to find the index position of the beginning of the image descriptor block? According to the Gif documentation, the Image Separator - which identifies the beginning of an Image Descriptor, the fixed value 0x2C. I have been reading each byte of the stream and matched it with the "0x2c" value, but obviously this is incorrect, as there are "attributes" that are more than one byte values.
I am trying to do this manually, as I am trying to avoid loading the whole image at this point.
Any ideas would be more than welcomed.
Thanks in advance
Just to provide an answer, so we can mark it as answered:
Instead of manually parsing the GIF structure, the easiest way of getting the data from the GIF image descriptor in Java is using ImageIO.
For simple values like image width and height, you can use the corresponding methods on ImageReader like this:
ImageInputStream stream = ImageIO.createImageInputStream(gif); // gif is File or InputStream
ImageReader reader = ImageIO.getImageReaders(stream).next();
reader.setInput(stream);
int w = reader.getWidth(0);
int h = reader.getHeight(0);
For more information on the GIF, you can use:
IIOMetadata metadata = reader.getImageMetadata(0);
For native metadata format, see GIF metadata, for standard (format neutral) metadata format, see standard metadata.