/*
Java?Media?APIs:?Cross-Platform?Imaging,?Media?and?Visualization
Alejandro?Terrazas
Sams,?Published?November?2002,?
ISBN?0672320940
*/
import?
java.awt.Rectangle;
import?
java.awt.image.Raster;
import?
java.io.IOException;
import?
javax.imageio.IIOImage;
import?
javax.imageio.ImageTypeSpecifier;
import?
javax.imageio.ImageWriteParam;
import?
javax.imageio.ImageWriter;
import?
javax.imageio.metadata.IIOMetadata;
import?
javax.imageio.metadata.IIOMetadataFormat;
import?
javax.imageio.metadata.IIOMetadataNode;
import?
javax.imageio.spi.ImageWriterSpi;
import?
javax.imageio.stream.ImageOutputStream;
import?
org.w3c.dom.Node;
/**
?
*?ch5ImageWriter.java?--?this?class?provides?the?functionality?to?write?an
?
*?image?of?format?ch5.
?
*/
public?class?
ch5ImageWriter?
extends?
ImageWriter?
{
??
public?
ch5ImageWriter
(
ImageWriterSpi?originatingProvider
)?{
????
super
(
originatingProvider
)
;
????
streamMetadataWritten?=?
false
;
??
}
??
/**
???
*?this?method?is?used?to?convert?an?ImageReader's?image?metadata?which?is
???
*?in?a?particular?format?into?image?metadata?that?can?be?used?for?this
???
*?ImageWriter.?Primarily?this?is?used?for?transcoding?(format?conversion).
???
*?This?ImageWriter?does?not?support?such?conversions
???
*/
??
public?
IIOMetadata?convertImageMetadata
(
IIOMetadata?metadata,
??????
ImageTypeSpecifier?specifier,?ImageWriteParam?param
)?{
????
return?null
;
??
}
??
/**
???
*?this?method?is?used?to?convert?an?ImageReader's?stream?metadata?which?is
???
*?in?a?particular?format?into?stream?metadata?that?can?be?used?for?this
???
*?ImageWriter.?Primarily?this?is?used?for?transcoding?(format?conversion).
???
*?This?ImageWriter?does?not?support?such?conversions
???
*/
??
public?
IIOMetadata?convertStreamMetadata
(
IIOMetadata?metadata,
??????
ImageWriteParam?param
)?{
????
return?null
;
??
}
??
/**
???
*?provide?default?values?for?the?image?metadata
???
*/
??
public?
IIOMetadata?getDefaultImageMetadata
(
ImageTypeSpecifier?specifier,
??????
ImageWriteParam?param
)?{
????
ch5ImageMetadata?imagemd?=?
new?
ch5ImageMetadata
()
;
????
int?
width?=?raster.getWidth
()
;
????
int?
height?=?raster.getHeight
()
;
????
imagemd.initialize
(
width,?height
)
;?
//?default?image?size
????
return?
imagemd;
??
}
??
/**
???
*?provide?default?values?for?the?stream?metadata
???
*/
??
public?
IIOMetadata?getDefaultStreamMetadata
(
ImageWriteParam?param
)?{
????
ch5StreamMetadata?streammd?=?
new?
ch5StreamMetadata
()
;
????
streammd.initialize
(
1
)
;?
//?default?number?of?images
????
return?
streammd;
??
}
??
/**
???
*?write?out?the?output?image?specified?by?index?imageIndex?using?the
???
*?parameters?specified?by?the?ImageWriteParam?object?param
???
*/
??
public?
void?
write
(
IIOMetadata?metadata,?IIOImage?iioimage,
??????
ImageWriteParam?param
)?{
????
Node?root?=?
null
;
????
Node?dimensionsElementNode?=?
null
;
????
if?
(
iioimage.getRenderedImage
()?
!=?
null
)
??????
raster?=?iioimage.getRenderedImage
()
.getData
()
;
????
else
??????
raster?=?iioimage.getRaster
()
;
????
/*
?????
*?since?this?format?allows?you?to?write?multiple?images,?the
?????
*?streamMetadataWritten?variable?makes?sure?the?stream?metadata?is
?????
*?written?only?once
?????
*/
????
if?
(
streamMetadataWritten?==?
false
)?{
??????
if?
(
metadata?==?
null
)
????????
metadata?=?getDefaultStreamMetadata
(
param
)
;
??????
root?=?metadata.getAsTree
(
"ch5.imageio.ch5stream_1.00"
)
;
??????
dimensionsElementNode?=?root.getFirstChild
()
;
??????
Node?numberImagesAttributeNode?=?dimensionsElementNode
??????????
.getAttributes
()
.getNamedItem
(
"numberImages"
)
;
??????
String?numberImages?=?numberImagesAttributeNode.getNodeValue
()
;
??????
try?
{
????????
ios.writeBytes
(
"5\n"
)
;
????????
ios.writeBytes
(
numberImages
)
;
????????
ios.flush
()
;
??????
}?
catch?
(
IOException?ioe
)?{
????????
System.err.println
(
"IOException?"?
+?ioe.getMessage
())
;
??????
}
??????
streamMetadataWritten?=?
true
;
????
}
????
String?widthString;
????
String?heightString;
????
IIOMetadata?imageMetadata?=?
(
ch5ImageMetadata
)?
iioimage.getMetadata
()
;
????
/*
?????
*?don't?really?need?image?metadata?object?here?since?raster?knows
?????
*?necessary?information
?????
*/
????
if?
(
imageMetadata?==?
null
)
??????
imageMetadata?=?getDefaultImageMetadata
(
null,?param
)
;
????
root?=?imageMetadata.getAsTree
(
"ch5.imageio.ch5image_1.00"
)
;
????
dimensionsElementNode?=?root.getFirstChild
()
;
????
Node?widthAttributeNode?=?dimensionsElementNode.getAttributes
()
????????
.getNamedItem
(
"imageWidth"
)
;
????
widthString?=?widthAttributeNode.getNodeValue
()
;
????
Node?heightAttributeNode?=?dimensionsElementNode.getAttributes
()
????????
.getNamedItem
(
"imageHeight"
)
;
????
heightString?=?heightAttributeNode.getNodeValue
()
;
????
int?
sourceWidth?=?Integer.parseInt
(
widthString
)
;
????
int?
sourceHeight?=?Integer.parseInt
(
heightString
)
;
????
int?
destinationWidth?=?-
1
;
????
int?
destinationHeight?=?-
1
;
????
int?
sourceRegionWidth?=?-
1
;
????
int?
sourceRegionHeight?=?-
1
;
????
int?
sourceRegionXOffset?=?-
1
;
????
int?
sourceRegionYOffset?=?-
1
;
????
int?
xSubsamplingFactor?=?-
1
;
????
int?
ySubsamplingFactor?=?-
1
;
????
if?
(
param?==?
null
)
??????
param?=?getDefaultWriteParam
()
;
????
/*
?????
*?get?Rectangle?object?which?will?be?used?to?clip?the?source?image's
?????
*?dimensions.
?????
*/
????
Rectangle?sourceRegion?=?param.getSourceRegion
()
;
????
if?
(
sourceRegion?!=?
null
)?{
??????
sourceRegionWidth?=?
(
int
)?
sourceRegion.getWidth
()
;
??????
sourceRegionHeight?=?
(
int
)?
sourceRegion.getHeight
()
;
??????
sourceRegionXOffset?=?
(
int
)?
sourceRegion.getX
()
;
??????
sourceRegionYOffset?=?
(
int
)?
sourceRegion.getY
()
;
??????
/*
???????
*?correct?for?overextended?source?regions
???????
*/
??????
if?
(
sourceRegionXOffset?+?sourceRegionWidth?>?sourceWidth
)
????????
destinationWidth?=?sourceWidth?-?sourceRegionXOffset;
??????
else
????????
destinationWidth?=?sourceRegionWidth;
??????
if?
(
sourceRegionYOffset?+?sourceRegionHeight?>?sourceHeight
)
????????
destinationHeight?=?sourceHeight?-?sourceRegionYOffset;
??????
else
????????
destinationHeight?=?sourceRegionHeight;
????
}?
else?
{
??????
destinationWidth?=?sourceWidth;
??????
destinationHeight?=?sourceHeight;
??????
sourceRegionXOffset?=?sourceRegionYOffset?=?
0
;
????
}
????
/*
?????
*?get?subsampling?factors
?????
*/
????
xSubsamplingFactor?=?param.getSourceXSubsampling
()
;
????
ySubsamplingFactor?=?param.getSourceYSubsampling
()
;
????
destinationWidth?=?
(
destinationWidth?-?
1
)?
/?xSubsamplingFactor?+?
1
;
????
destinationHeight?=?
(
destinationHeight?-?
1
)?
/?ySubsamplingFactor?+?
1
;
????
byte
[]?
sourceBuffer;
????
byte
[]?
destinationBuffer?=?
new?
byte
[
destinationWidth
]
;
????
try?
{
??????
ios.writeBytes
(
new?
String
(
"\n"
))
;
??????
ios.writeBytes
(
new?
String
(
destinationWidth?+?
"\n"
))
;
??????
ios.writeBytes
(
new?
String
(
destinationHeight?+?
"\n"
))
;
??????
int?
jj;
??????
int?
index;
??????
for?
(
int?
j?=?
0
;?j?<?sourceWidth;?j++
)?{
????????
sourceBuffer?=?
(
byte
[])?
raster.getDataElements
(
0
,?j,
????????????
sourceWidth,?
1
,?
null
)
;
????????
jj?=?j?-?sourceRegionYOffset;
????????
if?
(
jj?%?ySubsamplingFactor?==?
0
)?{
??????????
jj?/=?ySubsamplingFactor;
??????????
if?
((
jj?>=?
0
)?
&&?
(
jj?<?destinationHeight
))?{
????????????
for?
(
int?
i?=?
0
;?i?<?destinationWidth;?i++
)?{
??????????????
index?=?sourceRegionXOffset?+?i
??????????????????
*?xSubsamplingFactor;
??????????????
destinationBuffer
[
i
]?
=?sourceBuffer
[
index
]
;
????????????
}
????????????
ios.write
(
destinationBuffer,?
0
,?destinationWidth
)
;
????????????
ios.flush
()
;
??????????
}
????????
}
??????
}
????
}?
catch?
(
IOException?e
)?{
??????
System.err.println
(
"IOException:?"?
+?e.getMessage
())
;
????
}
??
}
??
public?
void?
setOutput
(
Object?output
)?{
????
super
.setOutput
(
output
)
;
????
if?
(
output?==?
null
)
??????
throw?new?
IllegalArgumentException
(
"output?is?null"
)
;
????
if?
(
!
(
output?
instanceof?
ImageOutputStream
))
??????
throw?new?
IllegalArgumentException
(
??????????
"output?not?an?ImageOutputStream"
)
;
????
ios?=?
(
ImageOutputStream
)?
output;
????
streamMetadataWritten?=?
false
;
??
}
??
private?
ImageOutputStream?ios;
??
private?
boolean?
streamMetadataWritten;
??
private?
Raster?raster;
}
/**
?
*?ch5StreamMetadata.java?--?holds?stream?metadata?for?the?ch5?format.?The
?
*?internal?tree?for?holding?this?metadata?is?read?only
?
*/
class?
ch5StreamMetadata?
extends?
IIOMetadata?
{
??
static?final?
String?nativeMetadataFormatName?=?
"ch5.imageio.ch5stream_1.00"
;
??
static?final?
String?nativeMetadataFormatClassName?=?
"ch5.imageio.ch5stream"
;
??
static?final?
String
[]?
extraMetadataFormatNames?=?
null
;
??
static?final?
String
[]?
extraMetadataFormatClassNames?=?
null
;
??
static?final?
boolean?
standardMetadataFormatSupported?=?
false
;
??
public?
int?
numberImages;
??
public?
ch5StreamMetadata
()?{
????
super
(
standardMetadataFormatSupported,?nativeMetadataFormatName,
????????
nativeMetadataFormatClassName,?extraMetadataFormatNames,
????????
extraMetadataFormatClassNames
)
;
????
numberImages?=?-
1
;
??
}
??
public?
boolean?
isReadOnly
()?{
????
return?true
;
??
}
??
/**
???
*?IIOMetadataFormat?objects?are?meant?to?describe?the?structure?of?metadata
???
*?returned?from?the?getAsTree?method.?In?this?case,?no?such?description?is
???
*?available
???
*/
??
public?
IIOMetadataFormat?getMetadataFormat
(
String?formatName
)?{
????
if?
(
formatName.equals
(
nativeMetadataFormatName
))?{
??????
return?null
;
????
}?
else?
{
??????
throw?new?
IllegalArgumentException
(
"Unrecognized?format!"
)
;
????
}
??
}
??
/**
???
*?returns?the?stream?metadata?in?a?tree?corresponding?to?the?provided
???
*?formatName
???
*/
??
public?
Node?getAsTree
(
String?formatName
)?{
????
if?
(
formatName.equals
(
nativeMetadataFormatName
))?{
??????
return?
getNativeTree
()
;
????
}?
else?
{
??????
throw?new?
IllegalArgumentException
(
"Unrecognized?format!"
)
;
????
}
??
}
??
/**
???
*?returns?the?stream?metadata?in?a?tree?using?the?following?format
???
*?
<!ELEMENT?ch5.imageio.ch5stream_1.00?(imageDimensions)>?
<!ATTLIST
???
*?imageDimensions?numberImages?CDATA?#REQUIRED
???
*/
??
private?
Node?getNativeTree
()?{
????
IIOMetadataNode?node;?
//?scratch?node
????
IIOMetadataNode?root?=?
new?
IIOMetadataNode
(
nativeMetadataFormatName
)
;
????
//?Image?descriptor
????
node?=?
new?
IIOMetadataNode
(
"imageDimensions"
)
;
????
node.setAttribute
(
"numberImages"
,?Integer.toString
(
numberImages
))
;
????
root.appendChild
(
node
)
;
????
return?
root;
??
}
??
public?
void?
setFromTree
(
String?formatName,?Node?root
)?{
????
throw?new?
IllegalStateException
(
"Metadata?is?read-only!"
)
;
??
}
??
public?
void?
mergeTree
(
String?formatName,?Node?root
)?{
????
throw?new?
IllegalStateException
(
"Metadata?is?read-only!"
)
;
??
}
??
public?
void?
reset
()?{
????
throw?new?
IllegalStateException
(
"Metadata?is?read-only!"
)
;
??
}
??
/**
???
*?initialize?the?stream?metadata?element?numberImages
???
*/
??
public?
void?
initialize
(
int?
numberImages
)?{
????
this
.numberImages?=?numberImages;
??
}
}
/**
?
*?ch5ImageMetadata.java?--?holds?image?metadata?for?the?ch5?format.
?
*?The?internal?tree?for?holding?this?metadata?is?read?only
?
*/
class?
ch5ImageMetadata?
extends?
IIOMetadata?
{
????
static?final?
String
????????
nativeMetadataFormatName?=?
"ch5.imageio.ch5image_1.00"
;
????
static?final?
String
????????
nativeMetadataFormatClassName?=?
"ch5.imageio.ch5image"
;
????
static?final?
String
[]?
extraMetadataFormatNames?=?
null
;
????
static?final?
String
[]?
extraMetadataFormatClassNames?=?
null
;
????
static?final?
boolean?
standardMetadataFormatSupported?=?
false
;
????
public?
int?
imageWidth;
????
public?
int?
imageHeight;
????
public?
ch5ImageMetadata
()?{
??
super
(
standardMetadataFormatSupported,
????????
nativeMetadataFormatName,?
????????
nativeMetadataFormatClassName,
????????
extraMetadataFormatNames,
????????
extraMetadataFormatClassNames
????????
)
;
??
imageWidth?=?-
1
;
??
imageHeight?=?-
1
;
????
}
????
public?
boolean?
isReadOnly
()?{
????????
return?true
;
????
}
????
/**
?????
*?IIOMetadataFormat?objects?are?meant?to?describe?the?structure?of
?????
*?metadata?returned?from?the?getAsTree?method.??In?this?case,
?????
*?no?such?description?is?available
?????
*/
????
public?
IIOMetadataFormat?getMetadataFormat
(
String?formatName
)?{
????????
if?
(
formatName.equals
(
nativeMetadataFormatName
))?{
????????????
return?null
;
????????
}?
else?
{
????????????
throw?new?
IllegalArgumentException
(
"Unrecognized?format!"
)
;
????????
}
????
}
????
/**
?????
*?returns?the?image?metadata?in?a?tree?corresponding?to?the
?????
*?provided?formatName
?????
*/
????
public?
Node?getAsTree
(
String?formatName
)?{
????????
if?
(
formatName.equals
(
nativeMetadataFormatName
))?{
????????????
return?
getNativeTree
()
;
????????
}?
else?
{
????????????
throw?new?
IllegalArgumentException
(
"Unrecognized?format!"
)
;
????????
}
????
}
????
/**
?????
*?returns?the?image?metadata?in?a?tree?using?the?following?format
?????
*?
<!ELEMENT?ch5.imageio.ch5image_1.00?(imageDimensions)>
?????
*?<!ATTLIST?imageDimensions
?????
*??????imageWidth???CDATA??#REQUIRED
?????
*??????imageHeight??CDATA??#REQUIRED
?????
*/
????
private?
Node?getNativeTree
()?{
????????
IIOMetadataNode?root?=
????????????
new?
IIOMetadataNode
(
nativeMetadataFormatName
)
;
????????
IIOMetadataNode?node?=?
new?
IIOMetadataNode
(
"imageDimensions"
)
;
????????
node.setAttribute
(
"imageWidth"
,?Integer.toString
(
imageWidth
))
;
????????
node.setAttribute
(
"imageHeight"
,?Integer.toString
(
imageHeight
))
;
????????
root.appendChild
(
node
)
;
????????
return?
root;
????
}
????
public?
void?
setFromTree
(
String?formatName,?Node?root
)?{
????????
throw?new?
IllegalStateException
(
"Metadata?is?read-only!"
)
;
????
}
????
public?
void?
mergeTree
(
String?formatName,?Node?root
)?{
????????
throw?new?
IllegalStateException
(
"Metadata?is?read-only!"
)
;
????
}
????
public?
void?
reset
()?{
????????
throw?new?
IllegalStateException
(
"Metadata?is?read-only!"
)
;
????
}
????
/**
?????
*?initialize?the?image?metadata?elements?width?and?height
?????
*/
????
public?
void?
initialize
(
int?
width,?
int?
height
)?{
??
imageWidth?=?width;
??
imageHeight?=?height;
????
}
}
|