2009-09-30 23:50:03 +00:00
/ *
* CVS identifier :
*
* $ Id : CodestreamManipulator . java , v 1.17 2001 / 05 / 16 13 : 58 : 09 qtxjoas Exp $
*
* Class : CodestreamManipulator
*
* Description : Manipulates codestream to create tile - parts etc
*
*
*
* COPYRIGHT :
*
* This software module was originally developed by Rapha <EFBFBD> l Grosbois and
* Diego Santa Cruz ( Swiss Federal Institute of Technology - EPFL ) ; Joel
* Askel <EFBFBD> f ( Ericsson Radio Systems AB ) ; and Bertrand Berthelot , David
* Bouchard , F <EFBFBD> lix Henry , Gerard Mozelle and Patrice Onno ( Canon Research
* Centre France S . A ) in the course of development of the JPEG2000
* standard as specified by ISO / IEC 15444 ( JPEG 2000 Standard ) . This
* software module is an implementation of a part of the JPEG 2000
* Standard . Swiss Federal Institute of Technology - EPFL , Ericsson Radio
* Systems AB and Canon Research Centre France S . A ( collectively JJ2000
* Partners ) agree not to assert against ISO / IEC and users of the JPEG
* 2000 Standard ( Users ) any of their rights under the copyright , not
* including other intellectual property rights , for this software module
* with respect to the usage by ISO / IEC and Users of this software module
* or modifications thereof for use in hardware or software products
* claiming conformance to the JPEG 2000 Standard . Those intending to use
* this software module in hardware or software products are advised that
* their use may infringe existing patents . The original developers of
* this software module , JJ2000 Partners and ISO / IEC assume no liability
* for use of this software module or modifications thereof . No license
* or right to this software module is granted for non JPEG 2000 Standard
* conforming products . JJ2000 Partners have full right to use this
* software module for his / her own purpose , assign or donate this
* software module to any third party and to inhibit third parties from
* using this software module for non JPEG 2000 Standard conforming
* products . This copyright notice must be included in all copies or
* derivative works of this software module .
*
* Copyright ( c ) 1999 / 2000 JJ2000 Partners .
* * /
namespace CSJ2K.j2k.util
{
2017-05-16 19:41:03 -05:00
using System.Collections.Generic ;
using System.IO ;
using CSJ2K.j2k.io ;
2009-09-30 23:50:03 +00:00
/// <summary> This class takes a legal JPEG 2000 codestream and performs some
/// manipulation on it. Currently the manipulations supported are: Tile-parts
///
/// </summary>
public class CodestreamManipulator
{
private void InitBlock ( )
{
ppt = new int [ nt ] ;
}
/// <summary>Flag indicating whether packed packet headers in main header is used
///
/// </summary>
2017-05-16 19:41:03 -05:00
private readonly bool ppmUsed ;
2009-09-30 23:50:03 +00:00
/// <summary>Flag indicating whether packed packet headers in tile headers is used
///
/// </summary>
2017-05-16 19:41:03 -05:00
private readonly bool pptUsed ;
2009-09-30 23:50:03 +00:00
/// <summary>Flag indicating whether SOP marker was only intended for parsing in
/// This class and should be removed
/// </summary>
2017-05-16 19:41:03 -05:00
private readonly bool tempSop ;
2009-09-30 23:50:03 +00:00
/// <summary>Flag indicating whether EPH marker was only intended for parsing in
/// This class and should be removed
/// </summary>
2017-05-16 19:41:03 -05:00
private readonly bool tempEph ;
2009-09-30 23:50:03 +00:00
/// <summary>The number of tiles in the image </summary>
2017-05-16 19:41:03 -05:00
private readonly int nt ;
2009-09-30 23:50:03 +00:00
/// <summary>The number of packets per tile-part </summary>
private int pptp ;
/// <summary>The name of the outfile </summary>
2017-05-16 19:41:03 -05:00
private readonly Stream stream ;
2009-09-30 23:50:03 +00:00
/// <summary>The length of a SOT plus a SOD marker </summary>
2017-05-16 19:41:03 -05:00
private const int TP_HEAD_LEN = 14 ;
2009-09-30 23:50:03 +00:00
/// <summary>The maximum number of a tile part index (TPsot) </summary>
//private static int MAX_TPSOT = 16;
/// <summary>The maximum number of tile parts in any tile </summary>
private int maxtp ;
/// <summary>The number of packets per tile </summary>
//UPGRADE_NOTE: The initialization of 'ppt' was moved to method 'InitBlock'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1005'"
private int [ ] ppt ;
/// <summary>The positions of the SOT, SOP and EPH markers </summary>
private System . Int32 [ ] positions ;
/// <summary>The main header </summary>
private byte [ ] mainHeader ;
/// <summary>Buffers containing the tile parts </summary>
private byte [ ] [ ] [ ] tileParts ;
/// <summary>Buffers containing the original tile headers </summary>
private byte [ ] [ ] tileHeaders ;
/// <summary>Buffers contaning the packet headers </summary>
private byte [ ] [ ] [ ] packetHeaders ;
/// <summary>Buffers containing the packet data </summary>
private byte [ ] [ ] [ ] packetData ;
/// <summary>Buffers containing the SOP marker segments </summary>
private byte [ ] [ ] [ ] sopMarkSeg ;
/// <summary> Instantiates a codestream manipulator..
///
/// </summary>
2017-05-16 19:41:03 -05:00
/// <param name="stream">The output stream
2009-09-30 23:50:03 +00:00
///
/// </param>
/// <param name="nt">The number of tiles in the image
///
/// </param>
/// <param name="pptp">Packets per tile-part. If zero, no division into tileparts
/// is performed
///
/// </param>
/// <param name="ppm">Flag indicating that PPM marker is used
///
/// </param>
/// <param name="ppt">Flag indicating that PPT marker is used
///
/// </param>
/// <param name="tempSop">Flag indicating whether SOP merker should be removed
///
/// </param>
/// <param name="tempEph">Flag indicating whether EPH merker should be removed
///
/// </param>
2017-05-16 19:41:03 -05:00
public CodestreamManipulator ( Stream stream , int nt , int pptp , bool ppm , bool ppt , bool tempSop , bool tempEph )
2009-09-30 23:50:03 +00:00
{
InitBlock ( ) ;
2017-05-16 19:41:03 -05:00
this . stream = stream ;
2009-09-30 23:50:03 +00:00
this . nt = nt ;
this . pptp = pptp ;
this . ppmUsed = ppm ;
this . pptUsed = ppt ;
this . tempSop = tempSop ;
this . tempEph = tempEph ;
}
/// <summary> This method performs the actual manipulation of the codestream which is
/// the reparsing for tile parts and packed packet headers
///
/// </summary>
/// <returns> The number of bytes that the file has increased by
///
/// </returns>
2017-05-16 19:41:03 -05:00
/// <exception cref="IOException">If an I/O error ocurred.
2009-09-30 23:50:03 +00:00
///
/// </exception>
public virtual int doCodestreamManipulation ( )
{
BEBufferedRandomAccessFile fi ;
int addedHeaderBytes = 0 ;
ppt = new int [ nt ] ;
tileParts = new byte [ nt ] [ ] [ ] ;
tileHeaders = new byte [ nt ] [ ] ;
packetHeaders = new byte [ nt ] [ ] [ ] ;
packetData = new byte [ nt ] [ ] [ ] ;
sopMarkSeg = new byte [ nt ] [ ] [ ] ;
// If neither packed packet header nor tile parts are used, return 0
if ( ppmUsed = = false & & pptUsed = = false & & pptp = = 0 )
return 0 ;
// Open file for reading and writing
2017-05-16 19:41:03 -05:00
fi = new BEBufferedRandomAccessFile ( stream , false ) ;
2009-09-30 23:50:03 +00:00
addedHeaderBytes - = fi . length ( ) ;
// Parse the codestream for SOT, SOP and EPH markers
parseAndFind ( fi ) ;
// Read and buffer the tile headers, packet headers and packet data
readAndBuffer ( fi ) ;
2017-05-16 19:41:03 -05:00
// Rewind and overwrite with new contents
fi . seek ( 0 ) ;
2009-09-30 23:50:03 +00:00
// Create tile-parts
createTileParts ( ) ;
// Write new codestream
writeNewCodestream ( fi ) ;
// Close file
fi . flush ( ) ;
addedHeaderBytes + = fi . length ( ) ;
fi . close ( ) ;
return addedHeaderBytes ;
}
/// <summary> This method parses the codestream for SOT, SOP and EPH markers and
/// removes header header bits signalling SOP and EPH markers if packed
/// packet headers are used
///
/// </summary>
/// <param name="fi">The file to parse the markers from
///
/// </param>
2017-05-16 19:41:03 -05:00
/// <exception cref="IOException">If an I/O error ocurred.
2009-09-30 23:50:03 +00:00
///
/// </exception>
private void parseAndFind ( BufferedRandomAccessFile fi )
{
int length , pos , i , t , sop = 0 , eph = 0 ;
short marker ;
int halfMarker ;
int tileEnd ;
2017-05-16 19:41:03 -05:00
System . Collections . Generic . List < System . Int32 > markPos = new List < int > ( 10 ) ;
2009-09-30 23:50:03 +00:00
// Find position of first SOT marker
marker = ( short ) fi . readUnsignedShort ( ) ; // read SOC marker
marker = ( short ) fi . readUnsignedShort ( ) ;
while ( marker ! = CSJ2K . j2k . codestream . Markers . SOT )
{
pos = fi . Pos ;
length = fi . readUnsignedShort ( ) ;
// If SOP and EPH markers were only used for parsing in this
// class remove SOP and EPH markers from Scod field
if ( marker = = CSJ2K . j2k . codestream . Markers . COD )
{
int scod = fi . readUnsignedByte ( ) ;
if ( tempSop )
scod & = 0xfd ; // Remove bits indicating SOP
if ( tempEph )
scod & = 0xfb ; // Remove bits indicating SOP
fi . seek ( pos + 2 ) ;
fi . write ( scod ) ;
}
fi . seek ( pos + length ) ;
marker = ( short ) fi . readUnsignedShort ( ) ;
}
pos = fi . Pos ;
fi . seek ( pos - 2 ) ;
// Find all packet headers, packed data and tile headers
for ( t = 0 ; t < nt ; t + + )
{
// Read SOT marker
fi . readUnsignedShort ( ) ; // Skip SOT
pos = fi . Pos ;
markPos . Add ( ( System . Int32 ) fi . Pos ) ;
fi . readInt ( ) ; // Skip Lsot and Isot
length = fi . readInt ( ) ; // Read Psot
fi . readUnsignedShort ( ) ; // Skip TPsot & TNsot
tileEnd = pos + length - 2 ; // Last byte of tile
// Find position of SOD marker
marker = ( short ) fi . readUnsignedShort ( ) ;
while ( marker ! = CSJ2K . j2k . codestream . Markers . SOD )
{
pos = fi . Pos ;
length = fi . readUnsignedShort ( ) ;
// If SOP and EPH markers were only used for parsing in this
// class remove SOP and EPH markers from Scod field
if ( marker = = CSJ2K . j2k . codestream . Markers . COD )
{
int scod = fi . readUnsignedByte ( ) ;
if ( tempSop )
scod & = 0xfd ; // Remove bits indicating SOP
if ( tempEph )
scod & = 0xfb ; // Remove bits indicating SOP
fi . seek ( pos + 2 ) ;
fi . write ( scod ) ;
}
fi . seek ( pos + length ) ;
marker = ( short ) fi . readUnsignedShort ( ) ;
}
// Find all SOP and EPH markers in tile
sop = 0 ;
eph = 0 ;
i = fi . Pos ;
while ( i < tileEnd )
{
halfMarker = ( short ) fi . readUnsignedByte ( ) ;
if ( halfMarker = = ( short ) 0xff )
{
marker = ( short ) ( ( halfMarker < < 8 ) + fi . readUnsignedByte ( ) ) ;
i + + ;
if ( marker = = CSJ2K . j2k . codestream . Markers . SOP )
{
markPos . Add ( ( System . Int32 ) fi . Pos ) ;
ppt [ t ] + + ;
sop + + ;
fi . skipBytes ( 4 ) ;
i + = 4 ;
}
if ( marker = = CSJ2K . j2k . codestream . Markers . EPH )
{
markPos . Add ( ( System . Int32 ) fi . Pos ) ;
eph + + ;
}
}
i + + ;
}
}
markPos . Add ( ( System . Int32 ) ( fi . Pos + 2 ) ) ;
positions = new System . Int32 [ markPos . Count ] ;
markPos . CopyTo ( positions ) ;
}
/// <summary> This method reads and buffers the tile headers, packet headers and
/// packet data.
///
/// </summary>
/// <param name="fi">The file to read the headers and data from
///
/// </param>
2017-05-16 19:41:03 -05:00
/// <exception cref="IOException">If an I/O error ocurred.
2009-09-30 23:50:03 +00:00
///
/// </exception>
private void readAndBuffer ( BufferedRandomAccessFile fi )
{
int p , prem , length , t , markIndex ;
// Buffer main header
fi . seek ( 0 ) ;
length = ( ( System . Int32 ) positions [ 0 ] ) - 2 ;
mainHeader = new byte [ length ] ;
fi . readFully ( mainHeader , 0 , length ) ;
markIndex = 0 ;
for ( t = 0 ; t < nt ; t + + )
{
prem = ppt [ t ] ;
packetHeaders [ t ] = new byte [ prem ] [ ] ;
packetData [ t ] = new byte [ prem ] [ ] ;
sopMarkSeg [ t ] = new byte [ prem ] [ ] ;
// Read tile header
length = positions [ markIndex + 1 ] - positions [ markIndex ] ;
tileHeaders [ t ] = new byte [ length ] ;
fi . readFully ( tileHeaders [ t ] , 0 , length ) ;
markIndex + + ;
for ( p = 0 ; p < prem ; p + + )
{
// Read packet header
length = positions [ markIndex + 1 ] - positions [ markIndex ] ;
if ( tempSop )
{
// SOP marker is skipped
length - = CSJ2K . j2k . codestream . Markers . SOP_LENGTH ;
fi . skipBytes ( CSJ2K . j2k . codestream . Markers . SOP_LENGTH ) ;
}
else
{
// SOP marker is read and buffered
length - = CSJ2K . j2k . codestream . Markers . SOP_LENGTH ;
sopMarkSeg [ t ] [ p ] = new byte [ CSJ2K . j2k . codestream . Markers . SOP_LENGTH ] ;
fi . readFully ( sopMarkSeg [ t ] [ p ] , 0 , CSJ2K . j2k . codestream . Markers . SOP_LENGTH ) ;
}
if ( ! tempEph )
{
// EPH marker is kept in header
length + = CSJ2K . j2k . codestream . Markers . EPH_LENGTH ;
}
packetHeaders [ t ] [ p ] = new byte [ length ] ;
fi . readFully ( packetHeaders [ t ] [ p ] , 0 , length ) ;
markIndex + + ;
// Read packet data
length = positions [ markIndex + 1 ] - positions [ markIndex ] ;
length - = CSJ2K . j2k . codestream . Markers . EPH_LENGTH ;
if ( tempEph )
{
// EPH marker is used and is skipped
fi . skipBytes ( CSJ2K . j2k . codestream . Markers . EPH_LENGTH ) ;
}
packetData [ t ] [ p ] = new byte [ length ] ;
fi . readFully ( packetData [ t ] [ p ] , 0 , length ) ;
markIndex + + ;
}
}
}
/// <summary> This method creates the tileparts from the buffered tile headers,
/// packet headers and packet data
///
/// </summary>
2017-05-16 19:41:03 -05:00
/// <exception cref="IOException">If an I/O error ocurred.
2009-09-30 23:50:03 +00:00
///
/// </exception>
private void createTileParts ( )
{
int i , prem , t , length ;
2017-05-16 19:41:03 -05:00
int pIndex ; // phIndex removed
2009-09-30 23:50:03 +00:00
int tppStart ;
int tilePart ;
int p , np , nomnp ;
int numTileParts ;
int numPackets ;
System . IO . MemoryStream temp = new System . IO . MemoryStream ( ) ;
byte [ ] tempByteArr ;
// Create tile parts
tileParts = new byte [ nt ] [ ] [ ] ;
maxtp = 0 ;
for ( t = 0 ; t < nt ; t + + )
{
// Calculate number of tile parts. If tileparts are not used,
// put all packets in the first tilepart
if ( pptp = = 0 )
pptp = ppt [ t ] ;
prem = ppt [ t ] ;
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
numTileParts = ( int ) System . Math . Ceiling ( ( ( double ) prem ) / pptp ) ;
numPackets = packetHeaders [ t ] . Length ;
maxtp = ( numTileParts > maxtp ) ? numTileParts : maxtp ;
tileParts [ t ] = new byte [ numTileParts ] [ ] ;
// Create all the tile parts for tile t
tppStart = 0 ;
pIndex = 0 ;
p = 0 ;
//phIndex = 0;
for ( tilePart = 0 ; tilePart < numTileParts ; tilePart + + )
{
// Calculate number of packets in this tilepart
nomnp = ( pptp > prem ) ? prem : pptp ;
np = nomnp ;
// Write tile part header
if ( tilePart = = 0 )
{
// Write original tile part header up to SOD marker
temp . Write ( tileHeaders [ t ] , 0 , tileHeaders [ t ] . Length - 2 ) ;
}
else
{
// Write empty header of length TP_HEAD_LEN-2
temp . Write ( new byte [ TP_HEAD_LEN - 2 ] , 0 , TP_HEAD_LEN - 2 ) ;
}
// Write PPT marker segments if PPT used
if ( pptUsed )
{
int pptLength = 3 ; // Zppt and Lppt
int pptIndex = 0 ;
int phLength ;
p = pIndex ;
while ( np > 0 )
{
phLength = packetHeaders [ t ] [ p ] . Length ;
// If the total legth of the packet headers is greater
// than MAX_LPPT, several PPT markers are needed
if ( pptLength + phLength > CSJ2K . j2k . codestream . Markers . MAX_LPPT )
{
temp . WriteByte ( ( System . Byte ) SupportClass . URShift ( CSJ2K . j2k . codestream . Markers . PPT , 8 ) ) ;
temp . WriteByte ( ( System . Byte ) ( CSJ2K . j2k . codestream . Markers . PPT & 0x00FF ) ) ;
temp . WriteByte ( ( System . Byte ) SupportClass . URShift ( pptLength , 8 ) ) ;
temp . WriteByte ( ( System . Byte ) pptLength ) ;
temp . WriteByte ( ( System . Byte ) pptIndex + + ) ;
for ( i = pIndex ; i < p ; i + + )
{
temp . Write ( packetHeaders [ t ] [ i ] , 0 , packetHeaders [ t ] [ i ] . Length ) ;
}
pptLength = 3 ; // Zppt and Lppt
pIndex = p ;
}
pptLength + = phLength ;
p + + ;
np - - ;
}
// Write last PPT marker
temp . WriteByte ( ( System . Byte ) SupportClass . URShift ( CSJ2K . j2k . codestream . Markers . PPT , 8 ) ) ;
temp . WriteByte ( ( System . Byte ) ( CSJ2K . j2k . codestream . Markers . PPT & 0x00FF ) ) ;
temp . WriteByte ( ( System . Byte ) SupportClass . URShift ( pptLength , 8 ) ) ;
temp . WriteByte ( ( System . Byte ) pptLength ) ;
temp . WriteByte ( ( System . Byte ) pptIndex ) ;
for ( i = pIndex ; i < p ; i + + )
{
temp . Write ( packetHeaders [ t ] [ i ] , 0 , packetHeaders [ t ] [ i ] . Length ) ;
}
}
pIndex = p ;
np = nomnp ;
// Write SOD marker
temp . WriteByte ( ( System . Byte ) SupportClass . URShift ( CSJ2K . j2k . codestream . Markers . SOD , 8 ) ) ;
temp . WriteByte ( ( System . Byte ) ( CSJ2K . j2k . codestream . Markers . SOD & 0x00FF ) ) ;
// Write packet data and packet headers if PPT and PPM not used
for ( p = tppStart ; p < tppStart + np ; p + + )
{
if ( ! tempSop )
{
temp . Write ( sopMarkSeg [ t ] [ p ] , 0 , CSJ2K . j2k . codestream . Markers . SOP_LENGTH ) ;
}
if ( ! ( ppmUsed | | pptUsed ) )
{
temp . Write ( packetHeaders [ t ] [ p ] , 0 , packetHeaders [ t ] [ p ] . Length ) ;
}
temp . Write ( packetData [ t ] [ p ] , 0 , packetData [ t ] [ p ] . Length ) ;
}
tppStart + = np ;
// Edit tile part header
tempByteArr = temp . ToArray ( ) ;
tileParts [ t ] [ tilePart ] = tempByteArr ;
length = ( int ) temp . Length ;
if ( tilePart = = 0 )
{
// Edit first tile part header
tempByteArr [ 6 ] = ( byte ) ( SupportClass . URShift ( length , 24 ) ) ; // Psot
tempByteArr [ 7 ] = ( byte ) ( SupportClass . URShift ( length , 16 ) ) ;
tempByteArr [ 8 ] = ( byte ) ( SupportClass . URShift ( length , 8 ) ) ;
tempByteArr [ 9 ] = ( byte ) ( length ) ;
tempByteArr [ 10 ] = ( byte ) SupportClass . Identity ( ( 0 ) ) ; // TPsot
tempByteArr [ 11 ] = ( byte ) ( numTileParts ) ; // TNsot
}
else
{
// Edit tile part header
tempByteArr [ 0 ] = ( byte ) ( SupportClass . URShift ( CSJ2K . j2k . codestream . Markers . SOT , 8 ) ) ; // SOT
tempByteArr [ 1 ] = ( byte ) ( CSJ2K . j2k . codestream . Markers . SOT & 0x00FF ) ;
tempByteArr [ 2 ] = ( byte ) SupportClass . Identity ( ( 0 ) ) ; // Lsot
tempByteArr [ 3 ] = ( byte ) SupportClass . Identity ( ( 10 ) ) ;
tempByteArr [ 4 ] = ( byte ) ( SupportClass . URShift ( t , 8 ) ) ; // Isot
tempByteArr [ 5 ] = ( byte ) ( t ) ; //
tempByteArr [ 6 ] = ( byte ) ( SupportClass . URShift ( length , 24 ) ) ; // Psot
tempByteArr [ 7 ] = ( byte ) ( SupportClass . URShift ( length , 16 ) ) ;
tempByteArr [ 8 ] = ( byte ) ( SupportClass . URShift ( length , 8 ) ) ;
tempByteArr [ 9 ] = ( byte ) ( length ) ;
tempByteArr [ 10 ] = ( byte ) ( tilePart ) ; //TPsot
tempByteArr [ 11 ] = ( byte ) ( numTileParts ) ; // TNsot
}
//UPGRADE_ISSUE: Method 'java.io.ByteArrayOutputStream.reset' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javaioByteArrayOutputStreamreset'"
//temp.reset();
2017-05-16 19:41:03 -05:00
temp . SetLength ( 0 ) ;
2009-09-30 23:50:03 +00:00
prem - = np ;
}
}
2017-05-16 19:41:03 -05:00
temp . Dispose ( ) ;
2009-09-30 23:50:03 +00:00
}
/// <summary> This method writes the new codestream to the file.
///
/// </summary>
/// <param name="fi">The file to write the new codestream to
///
/// </param>
2017-05-16 19:41:03 -05:00
/// <exception cref="IOException">If an I/O error ocurred.
2009-09-30 23:50:03 +00:00
///
/// </exception>
private void writeNewCodestream ( BufferedRandomAccessFile fi )
{
int t , p , tp ; // i removed
int numTiles = tileParts . Length ;
int [ ] [ ] packetHeaderLengths = new int [ numTiles ] [ ] ;
for ( int i2 = 0 ; i2 < numTiles ; i2 + + )
{
packetHeaderLengths [ i2 ] = new int [ maxtp ] ;
}
byte [ ] temp ;
int length ;
// Write main header up to SOT marker
fi . write ( mainHeader , 0 , mainHeader . Length ) ;
// If PPM used write all packet headers in PPM markers
if ( ppmUsed )
{
System . IO . MemoryStream ppmMarkerSegment = new System . IO . MemoryStream ( ) ;
int numPackets ;
int totNumPackets ;
int ppmIndex = 0 ;
int ppmLength ;
int pStart , pStop ;
int [ ] prem = new int [ numTiles ] ;
// Set number of remaining packets
for ( t = 0 ; t < numTiles ; t + + )
{
prem [ t ] = packetHeaders [ t ] . Length ;
}
// Calculate Nppm values
for ( tp = 0 ; tp < maxtp ; tp + + )
{
for ( t = 0 ; t < numTiles ; t + + )
{
if ( tileParts [ t ] . Length > tp )
{
totNumPackets = packetHeaders [ t ] . Length ;
// Calculate number of packets in this tilepart
numPackets = ( tp = = tileParts [ t ] . Length - 1 ) ? prem [ t ] : pptp ;
pStart = totNumPackets - prem [ t ] ;
pStop = pStart + numPackets ;
// Calculate number of packet header bytes for this
// tile part
for ( p = pStart ; p < pStop ; p + + )
packetHeaderLengths [ t ] [ tp ] + = packetHeaders [ t ] [ p ] . Length ;
prem [ t ] - = numPackets ;
}
}
}
// Write first PPM marker
ppmMarkerSegment . WriteByte ( ( System . Byte ) SupportClass . URShift ( CSJ2K . j2k . codestream . Markers . PPM , 8 ) ) ;
ppmMarkerSegment . WriteByte ( ( System . Byte ) ( CSJ2K . j2k . codestream . Markers . PPM & 0x00FF ) ) ;
ppmMarkerSegment . WriteByte ( ( System . Byte ) 0 ) ; // Temporary Lppm value
ppmMarkerSegment . WriteByte ( ( System . Byte ) 0 ) ; // Temporary Lppm value
ppmMarkerSegment . WriteByte ( ( System . Byte ) 0 ) ; // zppm
ppmLength = 3 ;
ppmIndex + + ;
// Set number of remaining packets
for ( t = 0 ; t < numTiles ; t + + )
prem [ t ] = packetHeaders [ t ] . Length ;
// Write all PPM markers and information
for ( tp = 0 ; tp < maxtp ; tp + + )
{
for ( t = 0 ; t < numTiles ; t + + )
{
if ( tileParts [ t ] . Length > tp )
{
totNumPackets = packetHeaders [ t ] . Length ;
// Calculate number of packets in this tilepart
numPackets = ( tp = = tileParts [ t ] . Length - 1 ) ? prem [ t ] : pptp ;
pStart = totNumPackets - prem [ t ] ;
pStop = pStart + numPackets ;
// If Nppm value wont fit in current PPM marker segment
// write current PPM marker segment and start new
if ( ppmLength + 4 > CSJ2K . j2k . codestream . Markers . MAX_LPPM )
{
// Write current PPM marker
temp = ppmMarkerSegment . ToArray ( ) ;
length = temp . Length - 2 ;
temp [ 2 ] = ( byte ) ( SupportClass . URShift ( length , 8 ) ) ;
temp [ 3 ] = ( byte ) length ;
fi . write ( temp , 0 , length + 2 ) ;
// Start new PPM marker segment
//UPGRADE_ISSUE: Method 'java.io.ByteArrayOutputStream.reset' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javaioByteArrayOutputStreamreset'"
//ppmMarkerSegment.reset();
2017-05-16 19:41:03 -05:00
ppmMarkerSegment . SetLength ( 0 ) ;
2009-09-30 23:50:03 +00:00
ppmMarkerSegment . WriteByte ( ( System . Byte ) SupportClass . URShift ( CSJ2K . j2k . codestream . Markers . PPM , 8 ) ) ;
ppmMarkerSegment . WriteByte ( ( System . Byte ) ( CSJ2K . j2k . codestream . Markers . PPM & 0x00FF ) ) ;
ppmMarkerSegment . WriteByte ( ( System . Byte ) 0 ) ; // Temporary Lppm value
ppmMarkerSegment . WriteByte ( ( System . Byte ) 0 ) ; // Temporary Lppm value
ppmMarkerSegment . WriteByte ( ( System . Byte ) ppmIndex + + ) ; // zppm
ppmLength = 3 ;
}
// Write Nppm value
length = packetHeaderLengths [ t ] [ tp ] ;
ppmMarkerSegment . WriteByte ( ( System . Byte ) SupportClass . URShift ( length , 24 ) ) ;
ppmMarkerSegment . WriteByte ( ( System . Byte ) SupportClass . URShift ( length , 16 ) ) ;
ppmMarkerSegment . WriteByte ( ( System . Byte ) SupportClass . URShift ( length , 8 ) ) ;
ppmMarkerSegment . WriteByte ( ( System . Byte ) length ) ;
ppmLength + = 4 ;
// Write packet headers
for ( p = pStart ; p < pStop ; p + + )
{
length = packetHeaders [ t ] [ p ] . Length ;
// If next packet header value wont fit in
// current PPM marker segment write current PPM
// marker segment and start new
if ( ppmLength + length > CSJ2K . j2k . codestream . Markers . MAX_LPPM )
{
// Write current PPM marker
temp = ppmMarkerSegment . ToArray ( ) ;
length = temp . Length - 2 ;
temp [ 2 ] = ( byte ) ( SupportClass . URShift ( length , 8 ) ) ;
temp [ 3 ] = ( byte ) length ;
fi . write ( temp , 0 , length + 2 ) ;
// Start new PPM marker segment
//UPGRADE_ISSUE: Method 'java.io.ByteArrayOutputStream.reset' was not converted. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1000_javaioByteArrayOutputStreamreset'"
//ppmMarkerSegment.reset();
2017-05-16 19:41:03 -05:00
ppmMarkerSegment . SetLength ( 0 ) ;
2009-09-30 23:50:03 +00:00
ppmMarkerSegment . WriteByte ( ( System . Byte ) SupportClass . URShift ( CSJ2K . j2k . codestream . Markers . PPM , 8 ) ) ;
ppmMarkerSegment . WriteByte ( ( System . Byte ) ( CSJ2K . j2k . codestream . Markers . PPM & 0x00FF ) ) ;
ppmMarkerSegment . WriteByte ( ( System . Byte ) 0 ) ; // Temp Lppm value
ppmMarkerSegment . WriteByte ( ( System . Byte ) 0 ) ; // Temp Lppm value
ppmMarkerSegment . WriteByte ( ( System . Byte ) ppmIndex + + ) ; // zppm
ppmLength = 3 ;
}
// write packet header
ppmMarkerSegment . Write ( packetHeaders [ t ] [ p ] , 0 , packetHeaders [ t ] [ p ] . Length ) ;
ppmLength + = packetHeaders [ t ] [ p ] . Length ;
}
prem [ t ] - = numPackets ;
}
}
}
// Write last PPM marker segment
temp = ppmMarkerSegment . ToArray ( ) ;
length = temp . Length - 2 ;
temp [ 2 ] = ( byte ) ( SupportClass . URShift ( length , 8 ) ) ;
temp [ 3 ] = ( byte ) length ;
fi . write ( temp , 0 , length + 2 ) ;
}
// Write tile parts interleaved
for ( tp = 0 ; tp < maxtp ; tp + + )
{
for ( t = 0 ; t < nt ; t + + )
{
if ( tileParts [ t ] . Length > tp )
{
temp = tileParts [ t ] [ tp ] ;
length = temp . Length ;
fi . write ( temp , 0 , length ) ;
}
}
}
fi . writeShort ( CSJ2K . j2k . codestream . Markers . EOC ) ;
}
}
}