/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 1 2 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġit . se phi ro th . android . library . ex if 2 Ċ Ċ import Ġandroid . util . Log Ċ import Ġit . se phi ro th . android . library . ex if 2 . utils . Count ed Data InputStream Ċ import Ġjava . io . ByteArray InputStream Ċ import Ġjava . io . IOException Ċ import Ġjava . io . InputStream Ċ import Ġjava . nio . ByteBuffer Ċ import Ġjava . nio . Byte Order Ċ import Ġjava . nio . charset . Charset Ċ import Ġjava . util .* Ċ import Ġkotlin . math . min Ċ Ċ internal Ġopen Ġclass ĠEx if Parser Ċ @ Throws ( IOException :: class , ĠEx if Invalid FormatException :: class ) Ċ private Ġconstructor ( Ċ ĉ inputStream Ġ: ĠInputStream , Ċ ĉ private Ġval Ġm Options Ġ: ĠInt , Ċ ĉ private Ġval Ġm Interface Ġ: ĠEx if Interface Ċ ) Ġ{ ĊĉĊ ĉ // Ġnumber Ġof Ġtags Ġin Ġthe Ġcurrent ĠIF D Ġarea . Ċ ĉ private Ġvar Ġtag Count In Current If d Ġ= Ġ 0 ĊĉĊ ĉ /** Ċĉ Ġ* Ġthe ĠID Ġof Ġcurrent ĠIF D . Ċĉ Ġ* Ċĉ Ġ* Ġ@ see ĠIf d Data . TYPE _ IF D _ 0 Ċĉ Ġ* Ġ@ see ĠIf d Data . TYPE _ IF D _ 1 Ċĉ Ġ* Ġ@ see ĠIf d Data . TYPE _ IF D _ GPS Ċĉ Ġ* Ġ@ see ĠIf d Data . TYPE _ IF D _ INTER OPER ABILITY Ċĉ Ġ* Ġ@ see ĠIf d Data . TYPE _ IF D _ EX IF Ċĉ Ġ*/ Ċ ĉ var Ġcurrent If d Ġ: ĠInt Ġ= Ġ 0 Ċĉ ĉ private Ġset ĊĉĊ ĉ /** Ċĉ Ġ* ĠIf Ġ[. next ] Ġreturn Ġ[. EVENT _ NEW _ TAG ] Ġor Ċĉ Ġ* Ġ[. EVENT _ VALUE _ OF _ REGISTER ED _ TAG ], Ġcall Ġthis Ġfunction Ġto Ġget Ġthe Ċĉ Ġ* Ġcorresponding Ġtag . Ċĉ Ġ* Ċĉ Ġ* Ċĉ Ġ* ĠFor Ġ[. EVENT _ NEW _ TAG ], Ġthe Ġtag Ġmay Ġnot Ġcontain Ġthe Ġvalue Ġif Ġthe Ġsize Ċĉ Ġ* Ġof Ġthe Ġvalue Ġis Ġgreater Ġthan Ġ 4 Ġbytes . ĠOne Ġshould Ġcall Ċĉ Ġ* Ġ[ Ex if Tag . hasValue ] Ġto Ġcheck Ġif Ġthe Ġtag Ġcontains Ġvalue . ĠIf Ġthere Ċĉ Ġ* Ġis Ġno Ġvalue , call Ġ[. register For Tag Value ] Ġto Ġhave Ġthe Ġparser Ċĉ Ġ* Ġemit Ġ[. EVENT _ VALUE _ OF _ REGISTER ED _ TAG ] Ġwhen Ġit Ġreaches Ġthe Ġarea Ċĉ Ġ* Ġpointed Ġby Ġthe Ġoffset . Ċĉ Ġ* Ċĉ Ġ* Ċĉ Ġ* ĠWhen Ġ[. EVENT _ VALUE _ OF _ REGISTER ED _ TAG ] Ġis Ġemitted , Ġthe Ġvalue Ġof Ġthe Ċĉ Ġ* Ġtag Ġwill Ġhave Ġalready Ġbeen Ġread Ġexcept Ġfor Ġtags Ġof Ġundefined Ġtype . ĠFor Ċĉ Ġ* Ġtags Ġof Ġundefined Ġtype , Ġcall Ġone Ġof Ġthe Ġread Ġmethods Ġto Ġget Ġthe Ġvalue . Ċĉ Ġ* Ċĉ Ġ* Ġ@ see Ġ. register For Tag Value Ċĉ Ġ* Ġ@ see Ġ. read Ċĉ Ġ* Ġ@ see Ġ. read Ċĉ Ġ* Ġ@ see Ġ. read Long Ċĉ Ġ* Ġ@ see Ġ. read Rational Ċĉ Ġ* Ġ@ see Ġ. readString Ċĉ Ġ* Ġ@ see Ġ. readString Ċĉ Ġ*/ Ċ ĉ var Ġtag Ġ: ĠEx if Tag ? Ġ= Ġnull Ċĉ ĉ private Ġset ĊĉĊ ĉ private Ġvar Ġm Image Event Ġ: ĠImage Event ? Ġ= Ġnull Ċ ĉ private Ġvar Ġm Strip Size Tag Ġ: ĠEx if Tag ? Ġ= Ġnull Ċ ĉ private Ġvar Ġm J peg Size Tag Ġ: ĠEx if Tag ? Ġ= Ġnull Ċ ĉ private Ġvar Ġm Need To Parse Offsets In Current If d Ġ: ĠBoolean Ġ= Ġfalse Ċ ĉ private Ġvar Ġm Data Above If d 0 Ġ: ĠByteArray ? Ġ= Ġnull Ċ ĉ private Ġvar Ġm If d 0 Position Ġ: ĠInt Ġ= Ġ 0 ĊĉĊ ĉ var Ġquality Guess Ġ: ĠInt Ġ= Ġ 0 Ċĉ ĉ private Ġset Ċ ĉ var Ġimage Width Ġ: ĠInt Ġ= Ġ 0 Ċĉ ĉ private Ġset Ċ ĉ var Ġimage Length Ġ: ĠInt Ġ= Ġ 0 Ċĉ ĉ private Ġset Ċ ĉ var Ġj peg Process Ġ: ĠShort Ġ= Ġ 0 Ċĉ ĉ private Ġset ĊĉĊ ĉ var Ġun compressed Data Position Ġ= Ġ 0 Ċĉ ĉ private Ġset ĊĉĊ ĉ private Ġval Ġm ByteArray Ġ= ĠByteArray ( 8 ) Ċ ĉ private Ġval Ġm ByteBuffer Ġ= ĠByteBuffer . wrap ( m ByteArray ) ĊĉĊ ĉ private Ġval Ġis Thumbnail Requested Ġ: ĠBoolean Ċĉ ĉ get () Ġ= Ġm Options Ġand ĠEx if Interface . Options . OPTION _ TH UMB NA IL Ġ!= Ġ 0 ĊĉĊ ĉ /** Ċĉ Ġ* ĠWhen Ġreceiving Ġ[. EVENT _ UN COMPRESSED _ STRIP ], Ġcall Ġthis Ġfunction Ġto Ċĉ Ġ* Ġget Ġthe Ġindex Ġof Ġthis Ġstrip . Ċĉ Ġ*/ Ċ ĉ val Ġstrip Index Ġ: ĠInt Ċĉ ĉ get () Ġ= Ġm Image Event ?. strip Index Ġ?: Ġ 0 ĊĉĊ ĉ /** Ċĉ Ġ* ĠWhen Ġreceiving Ġ[. EVENT _ UN COMPRESSED _ STRIP ], Ġcall Ġthis Ġfunction Ġto Ċĉ Ġ* Ġget Ġthe Ġstrip Ġsize . Ċĉ Ġ*/ Ċ ĉ val Ġstrip Size Ġ: ĠInt Ċĉ ĉ get () Ġ= Ġm Strip Size Tag ?. getValue At ( 0 )?. toInt () Ġ?: Ġ 0 ĊĉĊ ĉ /** Ċĉ Ġ* ĠWhen Ġreceiving Ġ[. EVENT _ COMPRESSED _ IMAGE ], Ġcall Ġthis Ġfunction Ġto Ġget Ċĉ Ġ* Ġthe Ġimage Ġdata Ġsize . Ċĉ Ġ*/ Ċ ĉ val Ġcompressed Image Size Ġ: ĠInt Ċĉ ĉ get () Ġ= Ġm J peg Size Tag ?. getValue At ( 0 )?. toInt () Ġ?: Ġ 0 ĊĉĊ ĉ /** Ċĉ Ġ* ĠGets Ġthe Ġbyte Ġorder Ġof Ġthe Ġcurrent ĠInputStream . Ċĉ Ġ*/ Ċ ĉ val Ġbyte Order Ġ: ĠByte Order Ċĉ ĉ get () Ġ= Ġm T iff Stream . byte Order ĊĉĊ ĉ val Ġsections Ġ: ĠList < Section > Ċĉ ĉ get () Ġ= Ġm Sections ĊĉĊ ĉ private Ġval Ġm Corre sponding Event Ġ= ĠTreeMap < Int , ĠAny >() ĊĉĊ ĉ private Ġval Ġm Sections Ġ= ĠArrayList < Section >( 0 ) ĊĉĊ ĉ private Ġvar Ġm If d Start Offset Ġ= Ġ 0 ĊĉĊ ĉ private Ġval Ġm T iff Stream Ġ: ĠCount ed Data InputStream Ġ= Ġseek T iff Data ( inputStream ) ĊĉĊ ĉ init Ġ{ ĊĉĉĊĉ ĉ // ĠLog . d ( ĠTAG , Ġ" sections Ġsize : Ġ" Ġ+ Ġm Sections . size () Ġ); ĊĉĉĊĉ ĉ val Ġt iff Stream Ġ= Ġm T iff Stream ĊĉĉĊĉ ĉ parse T iff Header ( tiff Stream ) ĊĉĉĊĉ ĉ val Ġoffset Ġ= Ġt iff Stream . read Unsigned Int () Ċĉ ĉ if ( offset Ġ> ĠInteger . MAX _ VALUE ) Ġ{ Ċĉĉ ĉ throw ĠEx if Invalid FormatException (" Invalid Ġoffset Ġ$ offset ") Ċĉ ĉ } Ċĉ ĉ m If d 0 Position Ġ= Ġoffset . toInt () Ċĉ ĉ current If d Ġ= ĠIf d Data . TYPE _ IF D _ 0 ĊĉĉĊĉ ĉ if ( is If d Requested ( If d Data . TYPE _ IF D _ 0 ) Ġ|| Ġneed To Parse Offsets In Current If d ()) Ġ{ Ċĉĉ ĉ register If d ( If d Data . TYPE _ IF D _ 0 , Ġoffset ) Ċĉĉ ĉ if ( offset Ġ!= ĠDEFAULT _ IF D 0 _ OFFSET . to Long ()) Ġ{ Ċĉĉĉ ĉ val Ġba Ġ= ĠByteArray ( offset . toInt () Ġ- ĠDEFAULT _ IF D 0 _ OFFSET ) Ċĉĉĉ ĉ m Data Above If d 0 Ġ= Ġba Ċĉĉĉ ĉ read ( ba ) Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĉĊ ĉ private Ġfun Ġread Int ( b Ġ: ĠByteArray , Ġ@ Suppress (" Same Parameter Value ") Ġoffset Ġ: ĠInt ) Ġ: ĠInt Ġ{ Ċĉ ĉ m ByteBuffer . rewind () Ċĉ ĉ m ByteBuffer . put ( b , Ġoffset , Ġ 4 ) Ċĉ ĉ m ByteBuffer . rewind () Ċĉ ĉ return Ġm ByteBuffer . int Ċ ĉ } ĊĉĊ ĉ private Ġfun Ġread Short ( b Ġ: ĠByteArray , Ġ@ Suppress (" Same Parameter Value ") Ġoffset Ġ: ĠInt ) Ġ: ĠShort Ġ{ Ċĉ ĉ m ByteBuffer . rewind () Ċĉ ĉ m ByteBuffer . put ( b , Ġoffset , Ġ 2 ) Ċĉ ĉ m ByteBuffer . rewind () Ċĉ ĉ return Ġm ByteBuffer . short Ċ ĉ } ĊĉĊ ĉ @ Throws ( IOException :: class , ĠEx if Invalid FormatException :: class ) Ċ ĉ private Ġfun Ġseek T iff Data ( inputStream Ġ: ĠInputStream ) Ġ: ĠCount ed Data InputStream Ġ{ Ċĉ ĉ val Ġdata Stream Ġ= Ċĉĉ ĉ Count ed Data InputStream ( inputStream ) Ċĉ ĉ var Ġt iff Stream Ġ: ĠCount ed Data InputStream ? Ġ= Ġnull ĊĉĉĊĉ ĉ var Ġa Ġ= Ġdata Stream . read Unsigned Byte () Ċĉ ĉ val Ġb Ġ= Ġdata Stream . read Unsigned Byte () ĊĉĉĊĉĉĊĉ ĉ if ( a Ġ== Ġ 1 3 7 Ġ&& Ġb Ġ== Ġ 8 0 ) Ġerror (" maybe ĠPNG Ġimage ") ĊĉĉĊĉ ĉ if ( a Ġ!= Ġ 0 xFF Ġ|| Ġb Ġ!= ĠJ peg Header . TAG _ SO I ) Ġerror (" invalid Ġj peg Ġheader ") ĊĉĉĊĉ ĉ while ( true ) Ġ{ Ċĉĉ ĉ val Ġitem len Ġ: ĠInt Ċĉĉ ĉ var Ġmarker Ġ: ĠInt ĊĉĉĉĊĉĉ ĉ val Ġgot Ġ: ĠInt Ċĉĉ ĉ val Ġdata Ġ: ĠByteArray ĊĉĉĉĊĉĉ ĉ var Ġprev Ġ= Ġ 0 Ċĉĉ ĉ a Ġ= Ġ 0 Ċĉĉ ĉ while ( true ) Ġ{ Ċĉĉĉ ĉ marker Ġ= Ġdata Stream . read Unsigned Byte () Ċĉĉĉ ĉ if ( marker Ġ!= Ġ 0 xff Ġ&& Ġprev Ġ== Ġ 0 xff ) Ġbreak Ċĉĉĉ ĉ prev Ġ= Ġmarker Ċĉĉĉ ĉ a Ġ++ Ċĉĉ ĉ } ĊĉĉĉĊĉĉ ĉ if ( a Ġ> Ġ 1 0 ) Ġ{ Ċĉĉĉ ĉ Log . w ( TAG , Ġ" Extr aneous Ġ${ a Ġ- Ġ 1 } Ġpadding Ġbytes Ġbefore Ġsection Ġ$ marker ") Ċĉĉ ĉ } ĊĉĉĉĊĉĉ ĉ // ĠRead Ġthe Ġlength Ġof Ġthe Ġsection . Ċĉĉ ĉ val Ġlh Ġ= Ġdata Stream . read Byte (). toInt () Ċĉĉ ĉ val Ġll Ġ= Ġdata Stream . read Byte (). toInt () Ċĉĉ ĉ item len Ġ= Ġlh Ġand Ġ 0 xff Ġshl Ġ 8 Ġor Ġ( ll Ġand Ġ 0 xff ) ĊĉĉĉĊĉĉ ĉ if ( item len Ġ< Ġ 2 ) Ġ{ Ċĉĉĉ ĉ throw ĠEx if Invalid FormatException (" Invalid Ġmarker ") Ċĉĉ ĉ } ĊĉĉĉĊĉĉ ĉ data Ġ= ĠByteArray ( item len ) Ċĉĉ ĉ data [ 0 ] Ġ= Ġlh . to Byte () Ċĉĉ ĉ data [ 1 ] Ġ= Ġll . to Byte () ĊĉĉĉĊĉĉ ĉ // ĠLog . i ( ĠTAG , Ġ" marker : Ġ" Ġ+ ĠString . format ( Ġ" 0 x % 2 X ", Ġmarker Ġ) Ġ+ Ġ": Ġ" Ġ+ Ġitem len Ġ+ Ġ", Ġposition : Ġ" Ġ+ Ġdata Stream . get Read Byte Count () Ġ+ Ġ", Ġavailable : Ġ" Ġ+ Ġdata Stream . available () Ġ); Ċĉĉ ĉ // Ġgot Ġ= Ġdata Stream . read ( Ġdata , Ġ 2 , Ġitem len - 2 Ġ); ĊĉĉĉĊĉĉ ĉ got Ġ= Ġread Bytes ( data Stream , Ġdata , Ġ 2 , Ġitem len Ġ- Ġ 2 ) ĊĉĉĉĊĉĉ ĉ if ( got Ġ!= Ġitem len Ġ- Ġ 2 ) Ġ{ Ċĉĉĉ ĉ throw ĠEx if Invalid FormatException (" Prem ature Ġend Ġof Ġfile ? ĠExpect ing Ġ" Ġ+ Ġ( item len Ġ- Ġ 2 ) Ġ+ Ġ", Ġreceived Ġ" Ġ+ Ġgot ) Ċĉĉ ĉ } ĊĉĉĉĊĉĉ ĉ val Ġsection Ġ= ĠSection ( type Ġ= Ġmarker , Ġsize Ġ= Ġitem len , Ġdata Ġ= Ġdata ) ĊĉĉĉĊĉĉ ĉ var Ġignore Ġ= Ġfalse ĊĉĉĉĊĉĉ ĉ when ( marker ) Ġ{ Ċĉĉĉ ĉ J peg Header . TAG _ M _ S OS Ġ-> Ġ{ Ċĉĉĉĉ ĉ // Ġstop Ġbefore Ġhitting Ġcompressed Ġdata Ċĉĉĉĉ ĉ m Sections . add ( section ) Ċĉĉĉĉ ĉ un compressed Data Position Ġ= Ġdata Stream . read Byte Count Ċĉĉĉĉ ĉ return Ġt iff Stream Ġ?: Ġerror (" stop Ġbefore Ġhitting Ġcompressed Ġdata ") Ċĉĉĉ ĉ } ĊĉĉĉĉĊĉĉĉ ĉ J peg Header . TAG _ M _ D QT Ġ-> Ċĉĉĉĉ ĉ // ĠUse Ġfor Ġj peg Ġquality Ġguess ing Ċĉĉĉĉ ĉ process _ M _ D QT ( data ) ĊĉĉĉĉĊĉĉĉ ĉ J peg Header . TAG _ M _ D HT Ġ-> Ġ{ Ċĉĉĉ ĉ } ĊĉĉĉĉĊĉĉĉ ĉ // Ġin Ġcase Ġit 's Ġa Ġtables - only ĠJPEG Ġstream Ċĉĉĉ ĉ J peg Header . TAG _ M _ EO I Ġ-> Ġ{ Ċĉĉĉĉ ĉ error ("\" No Ġimage Ġin Ġj peg ! \" ") Ċĉĉĉ ĉ } ĊĉĉĉĉĊĉĉĉ ĉ J peg Header . TAG _ M _ COM Ġ-> Ċĉĉĉĉ ĉ // ĠComment Ġsection Ċĉĉĉĉ ĉ ignore Ġ= Ġtrue ĊĉĉĉĉĊĉĉĉ ĉ J peg Header . TAG _ M _ J FI F Ġ-> Ġif ( item len Ġ< Ġ 1 6 ) Ġ{ Ċĉĉĉĉ ĉ ignore Ġ= Ġtrue Ċĉĉĉ ĉ } ĊĉĉĉĉĊĉĉĉ ĉ J peg Header . TAG _ M _ IP TC Ġ-> Ġ{ Ċĉĉĉ ĉ } ĊĉĉĉĉĊĉĉĉ ĉ J peg Header . TAG _ M _ S OF 0 , ĠJ peg Header . TAG _ M _ S OF 1 , ĠJ peg Header . TAG _ M _ S OF 2 , ĠJ peg Header . TAG _ M _ S OF 3 , ĠJ peg Header . TAG _ M _ S OF 5 , ĠJ peg Header . TAG _ M _ S OF 6 , ĠJ peg Header . TAG _ M _ S OF 7 , ĠJ peg Header . TAG _ M _ S OF 9 , ĠJ peg Header . TAG _ M _ S OF 1 0 , ĠJ peg Header . TAG _ M _ S OF 1 1 , ĠJ peg Header . TAG _ M _ S OF 1 3 , ĠJ peg Header . TAG _ M _ S OF 1 4 , ĠJ peg Header . TAG _ M _ S OF 1 5 Ġ-> Ġprocess _ M _ S OF n ( Ċĉĉĉĉ ĉ data , Ċĉĉĉĉ ĉ marker Ċĉĉĉ ĉ ) ĊĉĉĉĉĊĉĉĉ ĉ J peg Header . TAG _ M _ EX IF Ġ-> Ġif ( item len Ġ>= Ġ 8 ) Ġ{ Ċĉĉĉĉ ĉ val Ġheader Ġ= Ġread Int ( data , Ġ 2 ) Ċĉĉĉĉ ĉ val Ġheader Tail Ġ= Ġread Short ( data , Ġ 6 ) Ċĉĉĉĉ ĉ // Ġheader Ġ= ĠEx if , Ġheader Tail =\ 0 \ 0 Ċĉĉĉĉ ĉ if ( header Ġ== ĠEX IF _ HEADER Ġ&& Ġheader Tail Ġ== ĠEX IF _ HEADER _ TAIL ) Ġ{ Ċĉĉĉĉĉ ĉ tiff Stream Ġ= Ċĉĉĉĉĉĉ ĉ Count ed Data InputStream ( Ċĉĉĉĉĉĉĉ ĉ ByteArray InputStream ( data , Ġ 8 , Ġitem len Ġ- Ġ 8 ) Ċĉĉĉĉĉĉ ĉ ) Ċĉĉĉĉĉ ĉ tiff Stream . end Ġ= Ġitem len Ġ- Ġ 6 Ċĉĉĉĉĉ ĉ ignore Ġ= Ġfalse Ċĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉ ĉ Log . v ( TAG , Ġ" Image Ġc ot ains ĠX MP Ġsection ") Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } ĊĉĉĉĉĊĉĉĉ ĉ else Ġ-> ĠLog . w ( Ċĉĉĉĉ ĉ TAG , Ċĉĉĉĉ ĉ " Unknown Ġmarker : Ġ" Ġ+ ĠString . format (" 0 x % 2 X ", Ġmarker ) Ġ+ Ġ", Ġlength : Ġ" Ġ+ Ġitem len Ċĉĉĉ ĉ ) Ċĉĉ ĉ } ĊĉĉĉĊĉĉ ĉ if (! Ġignore ) Ġ{ Ċĉĉĉ ĉ // ĠLog . d ( ĠTAG , Ġ" adding Ġsection Ġwith Ġsize : Ġ" Ġ+ Ġsection . size Ġ); Ċĉĉĉ ĉ m Sections . add ( section ) Ċĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉ ĉ Log . v ( Ċĉĉĉĉ ĉ TAG , Ċĉĉĉĉ ĉ " ign oring Ġmarker : Ġ" Ġ+ ĠString . format (" 0 x % 2 X ", Ġmarker ) Ġ+ Ġ", Ġlength : Ġ" Ġ+ Ġitem len Ċĉĉĉ ĉ ) Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĉĊ ĉ /** Ċĉ Ġ* ĠUsing Ġthis Ġinstead Ġof Ġthe Ġdefault Ġ[ java . io . InputStream . read ] Ġbecause Ċĉ Ġ* Ġon Ġremote Ġinput Ġstreams Ġreading Ġlarge Ġamount Ġof Ġdata Ġcan Ġfail Ċĉ Ġ* Ċĉ Ġ* Ġ@ param Ġdata Stream Ċĉ Ġ* Ġ@ param Ġdata Ċĉ Ġ* Ġ@ param Ġoffset Arg Ċĉ Ġ* Ġ@ param Ġlength Ċĉ Ġ* Ġ@ return Ċĉ Ġ* Ġ@ throws ĠIOException Ċĉ Ġ*/ Ċ ĉ @ Throws ( IOException :: class ) Ċ ĉ private Ġfun Ġread Bytes ( Ċĉ ĉ data Stream Ġ: ĠInputStream , Ċĉ ĉ data Ġ: ĠByteArray , Ċĉ ĉ @ Suppress (" Same Parameter Value ") Ġoffset Arg Ġ: ĠInt , Ċĉ ĉ length Ġ: ĠInt Ċ ĉ ) Ġ: ĠInt Ġ{ Ċĉ ĉ var Ġoffset Ġ= Ġoffset Arg Ċĉ ĉ var Ġcount Ġ= Ġ 0 Ċĉ ĉ var Ġn Ġ: ĠInt Ċĉ ĉ var Ġmax _ length Ġ= Ġmin ( 1 0 2 4 , Ġlength ) Ċĉ ĉ while ( true ) Ġ{ Ċĉĉ ĉ n Ġ= Ġdata Stream . read ( data , Ġoffset , Ġmax _ length ) Ċĉĉ ĉ if ( n Ġ<= Ġ 0 ) Ġbreak Ċĉĉ ĉ count Ġ+= Ġn Ċĉĉ ĉ offset Ġ+= Ġn Ċĉĉ ĉ max _ length Ġ= Ġmin ( max _ length , Ġlength Ġ- Ġcount ) Ċĉ ĉ } Ċĉ ĉ return Ġcount Ċ ĉ } ĊĉĊ ĉ private Ġfun Ġprocess _ M _ S OF n ( data Ġ: ĠByteArray , Ġmarker Ġ: ĠInt ) Ġ{ Ċĉ ĉ if ( data . size Ġ> Ġ 7 ) Ġ{ Ċĉĉ ĉ // int Ġdata _ precision Ġ= Ġdata [ 2 ] Ġ& Ġ 0 xff ; Ċĉĉ ĉ // int Ġnum _ components Ġ= Ġdata [ 7 ] Ġ& Ġ 0 xff ; Ċĉĉ ĉ image Length Ġ= ĠGet 1 6 m ( data , Ġ 3 ) Ċĉĉ ĉ image Width Ġ= ĠGet 1 6 m ( data , Ġ 5 ) Ċĉ ĉ } Ċĉ ĉ jpeg Process Ġ= Ġmarker . to Short () Ċ ĉ } ĊĉĊ ĉ private Ġfun Ġprocess _ M _ D QT ( data Ġ: ĠByteArray ) Ġ{ Ċĉ ĉ var Ġa Ġ= Ġ 2 Ċĉ ĉ var Ġc Ġ: ĠInt Ċĉ ĉ var Ġtable index Ġ: ĠInt Ċĉ ĉ var Ġcoef index Ġ: ĠInt Ċĉ ĉ var Ġcum sf Ġ= Ġ 0 . 0 Ċĉ ĉ var Ġre ft able Ġ: ĠInt Array ? Ġ= Ġnull Ċĉ ĉ var Ġall ones Ġ= Ġ 1 ĊĉĉĊĉ ĉ while ( a Ġ< Ġdata . size ) Ġ{ Ċĉĉ ĉ c Ġ= Ġdata [ a Ġ++ ]. toInt () Ċĉĉ ĉ table index Ġ= Ġc Ġand Ġ 0 x 0 f ĊĉĉĉĊĉĉ ĉ if ( table index Ġ< Ġ 2 ) Ġ{ Ċĉĉĉ ĉ ref table Ġ= Ġdef tabs [ table index ] Ċĉĉ ĉ } ĊĉĉĉĊĉĉ ĉ // ĠRead Ġin Ġthe Ġtable , Ġcompute Ġstatistics Ġrelative Ġto Ġreference Ġtable Ċĉĉ ĉ coef index Ġ= Ġ 0 Ċĉĉ ĉ while ( coef index Ġ< Ġ 6 4 ) Ġ{ Ċĉĉĉ ĉ val Ġ` val ` Ġ: ĠInt Ċĉĉĉ ĉ if ( c Ġshr Ġ 4 Ġ!= Ġ 0 ) Ġ{ Ċĉĉĉĉ ĉ var Ġtemp Ġ: ĠInt Ċĉĉĉĉ ĉ temp Ġ= Ġdata [ a Ġ++ ]. toInt () Ċĉĉĉĉ ĉ temp Ġ*= Ġ 2 5 6 Ċĉĉĉĉ ĉ ` val ` Ġ= Ġdata [ a Ġ++ ]. toInt () Ġ+ Ġtemp Ċĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉ ĉ ` val ` Ġ= Ġdata [ a Ġ++ ]. toInt () Ċĉĉĉ ĉ } Ċĉĉĉ ĉ if ( ref table Ġ!= Ġnull ) Ġ{ Ċĉĉĉĉ ĉ val Ġx Ġ: ĠDouble Ċĉĉĉĉ ĉ // Ġscaling Ġfactor Ġin Ġpercent Ċĉĉĉĉ ĉ x Ġ= Ġ 1 0 0 . 0 Ġ* Ġ` val `. toDouble () Ġ/ Ġre ft able [ coef index ]. toDouble () Ċĉĉĉĉ ĉ cum sf Ġ+= Ġx Ċĉĉĉĉ ĉ // Ġseparate Ġcheck Ġfor Ġall - ones Ġtable Ġ( Q Ġ 1 0 0 ) Ċĉĉĉĉ ĉ if (` val ` Ġ!= Ġ 1 ) Ġall ones Ġ= Ġ 0 Ċĉĉĉ ĉ } Ċĉĉĉ ĉ coef index Ġ++ Ċĉĉ ĉ } Ċĉĉ ĉ // ĠPrint Ġsummary Ġstats Ċĉĉ ĉ if ( ref table Ġ!= Ġnull ) Ġ{ Ġ// Ġter se Ġoutput Ġincludes Ġquality Ċĉĉĉ ĉ val Ġqual Ġ: ĠDouble Ċĉĉĉ ĉ cum sf Ġ/= Ġ 6 4 . 0 ĠĠĠ Ġ// Ġmean Ġscale Ġfactor ĊĉĉĉĉĊĉĉĉ ĉ qual Ġ= Ġwhen Ġ{ Ċĉĉĉĉ ĉ all ones Ġ!= Ġ 0 Ġ-> Ġ 1 0 0 . 0 Ġ// Ġspecial Ġcase Ġfor Ġall - ones Ġtable Ċĉĉĉĉ ĉ cum sf Ġ<= Ġ 1 0 0 . 0 Ġ-> Ġ( 2 0 0 . 0 Ġ- Ġcum sf ) Ġ/ Ġ 2 . 0 Ċĉĉĉĉ ĉ else Ġ-> Ġ 5 0 0 0 . 0 Ġ/ Ġcum sf Ċĉĉĉ ĉ } ĊĉĉĉĉĊĉĉĉ ĉ if ( table index Ġ== Ġ 0 ) Ġ{ Ċĉĉĉĉ ĉ quality Guess Ġ= Ġ( qual Ġ+ Ġ 0 . 5 ). toInt () Ċĉĉĉĉ ĉ // ĠLog . v ( ĠTAG , Ġ" quality Ġguess : Ġ" Ġ+ Ġm Quality Guess Ġ); Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĉĊ ĉ @ Throws ( IOException :: class , ĠEx if Invalid FormatException :: class ) Ċ ĉ private Ġfun Ġparse T iff Header ( stream Ġ: ĠCount ed Data InputStream ) Ġ{ ĊĉĉĊĉ ĉ stream . byte Order Ġ= Ġwhen ( stream . read Short ()) Ġ{ Ċĉĉ ĉ LIT TLE _ ENDIAN _ TAG Ġ-> ĠByte Order . LIT TLE _ ENDIAN Ċĉĉ ĉ BIG _ ENDIAN _ TAG Ġ-> ĠByte Order . BIG _ ENDIAN Ċĉĉ ĉ else Ġ-> Ġthrow ĠEx if Invalid FormatException (" Invalid ĠTI FF Ġheader ") Ċĉ ĉ } ĊĉĉĊĉ ĉ if ( stream . read Short () Ġ!= ĠTI FF _ HEADER _ TAIL ) Ġ{ Ċĉĉ ĉ throw ĠEx if Invalid FormatException (" Invalid ĠTI FF Ġheader ") Ċĉ ĉ } Ċ ĉ } ĊĉĊ ĉ private Ġfun Ġis If d Requested ( ifd Type Ġ: ĠInt ) Ġ: ĠBoolean Ġ{ Ċĉ ĉ when ( ifd Type ) Ġ{ Ċĉĉ ĉ If d Data . TYPE _ IF D _ 0 Ġ-> Ġreturn Ġm Options Ġand ĠEx if Interface . Options . OPTION _ IF D _ 0 Ġ!= Ġ 0 Ċĉĉ ĉ If d Data . TYPE _ IF D _ 1 Ġ-> Ġreturn Ġm Options Ġand ĠEx if Interface . Options . OPTION _ IF D _ 1 Ġ!= Ġ 0 Ċĉĉ ĉ If d Data . TYPE _ IF D _ EX IF Ġ-> Ġreturn Ġm Options Ġand ĠEx if Interface . Options . OPTION _ IF D _ EX IF Ġ!= Ġ 0 Ċĉĉ ĉ If d Data . TYPE _ IF D _ GPS Ġ-> Ġreturn Ġm Options Ġand ĠEx if Interface . Options . OPTION _ IF D _ GPS Ġ!= Ġ 0 Ċĉĉ ĉ If d Data . TYPE _ IF D _ INTER OPER ABILITY Ġ-> Ġreturn Ġm Options Ġand ĠEx if Interface . Options . OPTION _ IF D _ INTER OPER ABILITY Ġ!= Ġ 0 Ċĉ ĉ } Ċĉ ĉ return Ġfalse Ċ ĉ } ĊĉĊ ĉ private Ġfun Ġneed To Parse Offsets In Current If d () Ġ: ĠBoolean Ġ{ Ċĉ ĉ return Ġwhen ( current If d ) Ġ{ ĊĉĉĉĊĉĉ ĉ If d Data . TYPE _ IF D _ 0 Ġ-> Ċĉĉĉ ĉ is If d Requested ( If d Data . TYPE _ IF D _ EX IF ) Ġ|| Ċĉĉĉĉ ĉ is If d Requested ( If d Data . TYPE _ IF D _ GPS ) Ġ|| Ċĉĉĉĉ ĉ is If d Requested ( If d Data . TYPE _ IF D _ INTER OPER ABILITY ) Ġ|| Ċĉĉĉĉ ĉ is If d Requested ( If d Data . TYPE _ IF D _ 1 ) ĊĉĉĉĊĉĉ ĉ If d Data . TYPE _ IF D _ 1 Ġ-> Ġis Thumbnail Requested ĊĉĉĉĊĉĉ ĉ If d Data . TYPE _ IF D _ EX IF Ġ-> Ċĉĉĉ ĉ // ĠThe Ġoffset Ġto Ġinter oper ability ĠIF D Ġis Ġlocated Ġin ĠEx if ĠIF D Ċĉĉĉ ĉ is If d Requested ( If d Data . TYPE _ IF D _ INTER OPER ABILITY ) ĊĉĉĉĊĉĉ ĉ else Ġ-> Ġfalse Ċĉ ĉ } Ċ ĉ } ĊĉĊ ĉ private Ġfun Ġregister If d ( ifd Type Ġ: ĠInt , Ġoffset Ġ: ĠLong ) Ġ{ Ċĉ ĉ // ĠCast Ġunsigned Ġint Ġto Ġint Ġsince Ġthe Ġoffset Ġis Ġalways Ġsmaller Ċĉ ĉ // Ġthan Ġthe Ġsize Ġof ĠM _ EX IF Ġ( 6 5 5 3 6 ) Ċĉ ĉ m Corre sponding Event [ offset . toInt ()] Ġ= ĠIf d Event ( ifd Type , Ġis If d Requested ( ifd Type )) Ċ ĉ } ĊĉĊ ĉ /** Ċĉ Ġ* ĠE quivalent Ġto Ġread ( buffer , Ġ 0 , Ġbuffer . length ). Ċĉ Ġ*/ Ċ ĉ @ Throws ( IOException :: class ) Ċ ĉ fun Ġread ( buffer Ġ: ĠByteArray ) Ġ: ĠInt Ġ= Ġm T iff Stream . read ( buffer ) ĊĉĊ ĉ // Ċ ĉ // ĉ /** Ċ ĉ // ĉ Ġ* ĠParses Ġthe Ġthe Ġgiven ĠInputStream Ġwith Ġdefault Ġoptions ; Ġthat Ġis , Ġevery ĠIF D Ċ ĉ // ĉ Ġ* Ġand Ġthumbnail l Ġwill Ġbe Ġparsed . Ċ ĉ // ĉ Ġ* Ċ ĉ // ĉ Ġ* Ġ@ throws Ġjava . io . IOException Ċ ĉ // ĉ Ġ* Ġ@ throws ĠEx if Invalid FormatException Ċ ĉ // ĉ Ġ*/ Ċ ĉ // ĉ protected Ġstatic ĠEx if Parser Ġparse ( ĠInputStream ĠinputStream , Ġboolean Ġrequest Thumbnail , ĠEx if Interface Ġi Ref Ġ) Ġthrows ĠIOException , ĠEx if Invalid FormatException Ġ{ Ċ ĉ // ĉ ĉ return Ġnew ĠEx if Parser ( ĠinputStream , ĠOPTION _ IF D _ 0 Ġ| ĠOPTION _ IF D _ 1 Ġ| ĠOPTION _ IF D _ EX IF Ġ| ĠOPTION _ IF D _ GPS Ġ| ĠOPTION _ IF D _ INTER OPER ABILITY Ġ| Ġ( Ġrequest Thumbnail Ġ? ĠOPTION _ TH UMB NA IL Ġ: Ġ 0 Ġ), Ġi Ref Ġ); Ċ ĉ // ĉ } ĊĉĊ ĉ /** Ċĉ Ġ* ĠMov es Ġthe Ġparser Ġforward Ġand Ġreturns Ġthe Ġnext Ġparsing Ġevent Ċĉ Ġ* Ċĉ Ġ* Ġ@ throws Ġjava . io . IOException Ċĉ Ġ* Ġ@ throws ĠEx if Invalid FormatException Ċĉ Ġ* Ġ@ see Ġ. EVENT _ START _ OF _ IF D Ċĉ Ġ* Ġ@ see Ġ. EVENT _ NEW _ TAG Ċĉ Ġ* Ġ@ see Ġ. EVENT _ VALUE _ OF _ REGISTER ED _ TAG Ċĉ Ġ* Ġ@ see Ġ. EVENT _ COMPRESSED _ IMAGE Ċĉ Ġ* Ġ@ see Ġ. EVENT _ UN COMPRESSED _ STRIP Ċĉ Ġ* Ġ@ see Ġ. EVENT _ END Ċĉ Ġ*/ Ċ ĉ @ Throws ( IOException :: class , ĠEx if Invalid FormatException :: class ) Ċ ĉ operator Ġfun Ġnext () Ġ: ĠInt Ġ{ ĊĉĉĊĉ ĉ val Ġoffset Ġ= Ġm T iff Stream . read Byte Count Ċĉ ĉ val Ġend Of Tags Ġ= Ġm If d Start Offset Ġ+ ĠOFFSET _ SIZE Ġ+ ĠTAG _ SIZE Ġ* Ġtag Count In Current If d Ċĉ ĉ if ( offset Ġ< Ġend Of Tags ) Ġ{ Ċĉĉ ĉ val Ġtag Ġ= Ġread Tag () Ċĉĉ ĉ this . tag Ġ= Ġtag Ċĉĉ ĉ if ( tag Ġ== Ġnull ) Ġ{ Ċĉĉĉ ĉ return Ġnext () Ċĉĉ ĉ } Ġelse Ġif ( m Need To Parse Offsets In Current If d ) Ġ{ Ċĉĉĉ ĉ check Offset Or Image Tag ( tag ) Ċĉĉ ĉ } Ċĉĉ ĉ return ĠEVENT _ NEW _ TAG Ċĉ ĉ } Ġelse Ġif ( offset Ġ== Ġend Of Tags ) Ġ{ Ċĉĉ ĉ // ĠThere Ġis Ġa Ġlink Ġto Ġif d 1 Ġat Ġthe Ġend Ġof Ġif d 0 Ċĉĉ ĉ if ( current If d Ġ== ĠIf d Data . TYPE _ IF D _ 0 ) Ġ{ Ċĉĉĉ ĉ val Ġif d Offset Ġ= Ġread Unsigned Long () Ċĉĉĉ ĉ if ( is If d Requested ( If d Data . TYPE _ IF D _ 1 ) Ġ|| Ġis Thumbnail Requested ) Ġ{ Ċĉĉĉĉ ĉ if ( ifd Offset Ġ!= Ġ 0 L ) Ġ{ Ċĉĉĉĉĉ ĉ register If d ( If d Data . TYPE _ IF D _ 1 , Ġif d Offset ) Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉ ĉ var Ġoffset Size Ġ= Ġ 4 Ċĉĉĉ ĉ // ĠSome Ġcamera Ġmodels Ġuse Ġinvalid Ġlength Ġof Ġthe Ġoffset Ċĉĉĉ ĉ if ( m Corre sponding Event . size Ġ> Ġ 0 ) Ġ{ Ċĉĉĉĉ ĉ val Ġfirst Entry Ġ= Ġm Corre sponding Event . first Entry () Ġ!! Ċĉĉĉĉ ĉ offset Size Ġ= Ġfirst Entry . key Ġ- Ġm T iff Stream . read Byte Count Ċĉĉĉ ĉ } Ċĉĉĉ ĉ if ( offset Size Ġ< Ġ 4 ) Ġ{ Ċĉĉĉĉ ĉ Log . w ( TAG , Ġ" Invalid Ġsize Ġof Ġlink Ġto Ġnext ĠIF D : Ġ$ offset Size ") Ċĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉ ĉ val Ġif d Offset Ġ= Ġread Unsigned Long () Ċĉĉĉĉ ĉ if ( ifd Offset Ġ!= Ġ 0 L ) Ġ{ Ċĉĉĉĉĉ ĉ Log . w ( TAG , Ġ" Invalid Ġlink Ġto Ġnext ĠIF D : Ġ$ ifd Offset ") Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ while ( m Corre sponding Event . size Ġ!= Ġ 0 ) Ġ{ Ċĉĉ ĉ val Ġentry Ġ= Ġm Corre sponding Event . poll First Entry () Ġ!! Ċĉĉ ĉ val Ġevent Ġ= Ġentry . value Ċĉĉ ĉ try Ġ{ Ċĉĉĉ ĉ // ĠLog . v ( TAG , Ġ" skip To : Ġ" Ġ+ Ġentry . getKey ()); Ċĉĉĉ ĉ skip To ( entry . key ) Ċĉĉ ĉ } Ġcatch ( e Ġ: ĠIOException ) Ġ{ Ċĉĉĉ ĉ Log . w ( Ċĉĉĉĉ ĉ TAG , Ċĉĉĉĉ ĉ " Failed Ġto Ġskip Ġto Ġdata Ġat : Ġ${ entry . key } Ġfor Ġ${ event . java Class . name }, Ġthe Ġfile Ġmay Ġbe Ġbroken ." Ċĉĉĉ ĉ ) Ċĉĉĉ ĉ continue Ċĉĉ ĉ } ĊĉĉĉĊĉĉ ĉ if ( event Ġis ĠIf d Event ) Ġ{ Ċĉĉĉ ĉ current If d Ġ= Ġevent . ifd Ċĉĉĉ ĉ tag Count In Current If d Ġ= Ġm T iff Stream . read Unsigned Short () Ċĉĉĉ ĉ m If d Start Offset Ġ= Ġentry . key ĊĉĉĉĉĊĉĉĉ ĉ if ( tag Count In Current If d Ġ* ĠTAG _ SIZE Ġ+ Ġm If d Start Offset Ġ+ ĠOFFSET _ SIZE Ġ> Ġm T iff Stream . end ) Ġ{ Ċĉĉĉĉ ĉ Log . w ( TAG , Ġ" Invalid Ġsize Ġof ĠIF D Ġ$ current If d ") Ċĉĉĉĉ ĉ return ĠEVENT _ END Ċĉĉĉ ĉ } ĊĉĉĉĉĊĉĉĉ ĉ m Need To Parse Offsets In Current If d Ġ= Ġneed To Parse Offsets In Current If d () Ċĉĉĉ ĉ if ( event . is Requested ) Ġ{ Ċĉĉĉĉ ĉ return ĠEVENT _ START _ OF _ IF D Ċĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉ ĉ skip Remaining Tags In Current If d () Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ġelse Ġif ( event Ġis ĠImage Event ) Ġ{ Ċĉĉĉ ĉ m Image Event Ġ= Ġevent Ċĉĉĉ ĉ return Ġevent . type Ċĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉ ĉ val Ġtag Event Ġ= Ġevent Ġas ĠEx if Tag Event Ċĉĉĉ ĉ val Ġtag Ġ= Ġtag Event . tag Ċĉĉĉ ĉ this . tag Ġ= Ġtag Ċĉĉĉ ĉ if ( tag . dataType Ġ!= ĠEx if Tag . TYPE _ UNDEFINED ) Ġ{ Ċĉĉĉĉ ĉ read Full Tag Value ( tag ) Ċĉĉĉĉ ĉ check Offset Or Image Tag ( tag ) Ċĉĉĉ ĉ } Ċĉĉĉ ĉ if ( tag Event . is Requested ) Ġ{ Ċĉĉĉĉ ĉ return ĠEVENT _ VALUE _ OF _ REGISTER ED _ TAG Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ return ĠEVENT _ END Ċ ĉ } ĊĉĊ ĉ /** Ċĉ Ġ* ĠSk ips Ġthe Ġtags Ġarea Ġof Ġcurrent ĠIF D , Ġif Ġthe Ġparser Ġis Ġnot Ġin Ġthe Ġtag Ġarea , Ċĉ Ġ* Ġnothing Ġwill Ġhappen . Ċĉ Ġ* Ċĉ Ġ* Ġ@ throws Ġjava . io . IOException Ċĉ Ġ* Ġ@ throws ĠEx if Invalid FormatException Ċĉ Ġ*/ Ċ ĉ @ Throws ( IOException :: class , ĠEx if Invalid FormatException :: class ) Ċ ĉ protected Ġfun Ġskip Remaining Tags In Current If d () Ġ{ ĊĉĉĊĉ ĉ val Ġend Of Tags Ġ= Ġm If d Start Offset Ġ+ ĠOFFSET _ SIZE Ġ+ ĠTAG _ SIZE Ġ* Ġtag Count In Current If d Ċĉ ĉ var Ġoffset Ġ= Ġm T iff Stream . read Byte Count Ċĉ ĉ if ( offset Ġ> Ġend Of Tags ) Ġreturn ĊĉĉĊĉ ĉ if ( m Need To Parse Offsets In Current If d ) Ġ{ Ċĉĉ ĉ while ( offset Ġ< Ġend Of Tags ) Ġ{ Ċĉĉĉ ĉ val Ġtag Ġ= Ġread Tag () Ċĉĉĉ ĉ this . tag Ġ= Ġtag Ċĉĉĉ ĉ offset Ġ+= ĠTAG _ SIZE Ċĉĉĉ ĉ if ( tag Ġ== Ġnull ) Ġ{ Ċĉĉĉĉ ĉ continue Ċĉĉĉ ĉ } Ċĉĉĉ ĉ check Offset Or Image Tag ( tag ) Ċĉĉ ĉ } Ċĉ ĉ } Ġelse Ġ{ Ċĉĉ ĉ skip To ( end Of Tags ) Ċĉ ĉ } Ċĉ ĉ val Ġif d Offset Ġ= Ġread Unsigned Long () Ċĉ ĉ // ĠFor Ġif d 0 , Ġthere Ġis Ġa Ġlink Ġto Ġif d 1 Ġin Ġthe Ġend Ġof Ġall Ġtags Ċĉ ĉ if ( current If d Ġ== ĠIf d Data . TYPE _ IF D _ 0 Ġ&& Ġ( is If d Requested ( If d Data . TYPE _ IF D _ 1 ) Ġ|| Ġis Thumbnail Requested )) Ġ{ Ċĉĉ ĉ if ( ifd Offset Ġ> Ġ 0 ) Ġ{ Ċĉĉĉ ĉ register If d ( If d Data . TYPE _ IF D _ 1 , Ġif d Offset ) Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĉĊ ĉ @ Throws ( IOException :: class ) Ċ ĉ private Ġfun Ġskip To ( offset Ġ: ĠInt ) Ġ{ Ċĉ ĉ m T iff Stream . skip To ( offset . to Long ()) ĊĉĉĊĉ ĉ // ĠLog . v ( TAG , Ġ" available : Ġ" Ġ+ Ġm T iff Stream . available () Ġ); Ċĉ ĉ while (! Ġm Corre sponding Event . isEmpty () Ġ&& Ġm Corre sponding Event . first Key () Ġ< Ġoffset ) Ġ{ Ċĉĉ ĉ m Corre sponding Event . poll First Entry () Ċĉ ĉ } Ċ ĉ } ĊĉĊ ĉ /** Ċĉ Ġ* ĠWhen Ġgetting Ġ[. EVENT _ NEW _ TAG ] Ġin Ġthe Ġtag Ġarea Ġof ĠIF D , Ġthe Ġtag Ġmay Ċĉ Ġ* Ġnot Ġcontain Ġthe Ġvalue Ġif Ġthe Ġsize Ġof Ġthe Ġvalue Ġis Ġgreater Ġthan Ġ 4 Ġbytes . Ċĉ Ġ* ĠWhen Ġthe Ġvalue Ġis Ġnot Ġavailable Ġhere , Ġcall Ġthis Ġmethod Ġso Ġthat Ġthe Ġparser Ċĉ Ġ* Ġwill Ġemit Ġ[. EVENT _ VALUE _ OF _ REGISTER ED _ TAG ] Ġwhen Ġit Ġreaches Ġthe Ġarea Ċĉ Ġ* Ġwhere Ġthe Ġvalue Ġis Ġlocated . Ċĉ Ġ* Ċĉ Ġ* Ġ@ see Ġ. EVENT _ VALUE _ OF _ REGISTER ED _ TAG Ċĉ Ġ*/ Ċ ĉ fun Ġregister For Tag Value ( tag Ġ: ĠEx if Tag ) Ġ{ Ċĉ ĉ if ( tag . offset Ġ>= Ġm T iff Stream . read Byte Count ) Ġ{ Ċĉĉ ĉ m Corre sponding Event [ tag . offset ] Ġ= ĠEx if Tag Event ( tag , Ġtrue ) Ċĉ ĉ } Ċ ĉ } ĊĉĊ ĉ private Ġfun Ġregister Compressed Image ( offset Ġ: ĠLong ) Ġ{ Ċĉ ĉ m Corre sponding Event [ offset . toInt ()] Ġ= ĠImage Event ( EVENT _ COMPRESSED _ IMAGE ) Ċ ĉ } ĊĉĊ ĉ private Ġfun Ġregister Un compressed Strip ( strip Index Ġ: ĠInt , Ġoffset Ġ: ĠLong ) Ġ{ Ċĉ ĉ m Corre sponding Event [ offset . toInt ()] Ġ= ĠImage Event ( EVENT _ UN COMPRESSED _ STRIP , Ġstrip Index ) Ċ ĉ } ĊĉĊ ĉ @ Throws ( IOException :: class , ĠEx if Invalid FormatException :: class ) Ċ ĉ private Ġfun Ġread Tag () Ġ: ĠEx if Tag ? Ġ{ ĊĉĉĊĉ ĉ val Ġtag Id Ġ= Ġm T iff Stream . read Short () Ċĉ ĉ val Ġdata Format Ġ= Ġm T iff Stream . read Short () Ċĉ ĉ val ĠnumOf Comp Ġ= Ġm T iff Stream . read Unsigned Int () Ċĉ ĉ if ( num Of Comp Ġ> ĠInteger . MAX _ VALUE ) Ġ{ Ċĉĉ ĉ throw ĠEx if Invalid FormatException (" Number Ġof Ġcomponent Ġis Ġlarger Ġthen ĠInteger . MAX _ VALUE ") Ċĉ ĉ } Ċĉ ĉ // ĠSome Ġinvalid Ġimage Ġfile Ġcontains Ġinvalid Ġdata Ġtype . ĠIgnore Ġthose Ġtags Ċĉ ĉ if (! ĠEx if Tag . isValid Type ( data Format )) Ġ{ Ċĉĉ ĉ Log . w ( TAG , ĠString . format (" Tag Ġ% 0 4 x : ĠInvalid Ġdata Ġtype Ġ% d ", Ġtag Id , Ġdata Format )) Ċĉĉ ĉ m T iff Stream . skip ( 4 ) Ċĉĉ ĉ return Ġnull Ċĉ ĉ } Ċĉ ĉ // ĠTODO : Ġhandle ĠnumOf Comp Ġoverflow Ċĉ ĉ val Ġtag Ġ= ĠEx if Tag ( Ċĉĉ ĉ tag Id , Ċĉĉ ĉ data Format , Ċĉĉ ĉ num Of Comp . toInt (), Ċĉĉ ĉ current If d , Ċĉĉ ĉ num Of Comp . toInt () Ġ!= ĠEx if Tag . SIZE _ UNDEFINED Ċĉ ĉ ) Ċĉ ĉ val Ġdata Size Ġ= Ġtag . data Size Ċĉ ĉ if ( data Size Ġ> Ġ 4 ) Ġ{ Ċĉĉ ĉ val Ġoffset Ġ= Ġm T iff Stream . read Unsigned Int () Ċĉĉ ĉ if ( offset Ġ> ĠInteger . MAX _ VALUE ) Ġ{ Ċĉĉĉ ĉ throw ĠEx if Invalid FormatException (" offset Ġis Ġlarger Ġthen ĠInteger . MAX _ VALUE ") Ċĉĉ ĉ } Ċĉĉ ĉ // ĠSome Ġinvalid Ġimages Ġput Ġsome Ġundefined Ġdata Ġbefore ĠIF D 0 . Ċĉĉ ĉ // ĠRead Ġthe Ġdata Ġhere . Ċĉĉ ĉ if ( offset Ġ< Ġm If d 0 Position Ġ&& Ġdata Format Ġ== ĠEx if Tag . TYPE _ UNDEFINED ) Ġ{ Ċĉĉĉ ĉ val Ġbuf Ġ= ĠByteArray ( num Of Comp . toInt ()) Ċĉĉĉ ĉ System . arraycopy ( Ċĉĉĉĉ ĉ m Data Above If d 0 Ġ!! , Ċĉĉĉĉ ĉ offset . toInt () Ġ- ĠDEFAULT _ IF D 0 _ OFFSET , Ċĉĉĉĉ ĉ buf , Ċĉĉĉĉĉ 0 , Ċĉĉĉĉ ĉ num Of Comp . toInt () Ċĉĉĉ ĉ ) Ċĉĉĉ ĉ tag . setValue ( buf ) Ċĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉ ĉ tag . offset Ġ= Ġoffset . toInt () Ċĉĉ ĉ } Ċĉ ĉ } Ġelse Ġ{ Ċĉĉ ĉ val Ġdef Count Ġ= Ġtag . has Defined Count Ċĉĉ ĉ // ĠSet Ġdefined Ġcount Ġto Ġ 0 Ġso Ġwe Ġcan Ġadd Ġ\ 0 Ġto Ġnon - terminated Ġstrings Ċĉĉ ĉ tag . has Defined Count Ġ= Ġfalse Ċĉĉ ĉ // ĠRead Ġvalue Ċĉĉ ĉ read Full Tag Value ( tag ) Ċĉĉ ĉ tag . has Defined Count Ġ= Ġdef Count Ċĉĉ ĉ m T iff Stream . skip (( 4 Ġ- Ġdata Size ). to Long ()) Ċĉĉ ĉ // ĠSet Ġthe Ġoffset Ġto Ġthe Ġposition Ġof Ġvalue . Ċĉĉ ĉ tag . offset Ġ= Ġm T iff Stream . read Byte Count Ġ- Ġ 4 Ċĉ ĉ } Ċĉ ĉ return Ġtag Ċ ĉ } ĊĉĊ ĉ /** Ċĉ Ġ* ĠCheck Ġthe Ġtag , Ġif Ġthe Ġtag Ġis Ġone Ġof Ġthe Ġoffset Ġtag Ġthat Ġpoints Ġto Ġthe ĠIF D Ċĉ Ġ* Ġor Ġimage Ġthe Ġcaller Ġis Ġinterested Ġin , Ġregister Ġthe ĠIF D Ġor Ġimage . Ċĉ Ġ*/ Ċ ĉ private Ġfun Ġcheck Offset Or Image Tag ( tag Ġ: ĠEx if Tag ) Ġ{ Ċĉ ĉ // ĠSome Ġinvalid Ġformat td Ġimage Ġcontains Ġtag Ġwith Ġ 0 Ġsize . Ċĉ ĉ if ( tag . component Count Ġ== Ġ 0 ) Ġ{ Ċĉĉ ĉ return Ċĉ ĉ } Ċĉ ĉ val Ġtid Ġ= Ġtag . tag Id Ċĉ ĉ val Ġif d Ġ= Ġtag . ifd Ċĉ ĉ if ( tid Ġ== ĠTAG _ EX IF _ IF D Ġ&& Ġcheck Allowed ( ifd , ĠEx if Interface . TAG _ EX IF _ IF D )) Ġ{ Ċĉĉ ĉ if ( is If d Requested ( If d Data . TYPE _ IF D _ EX IF ) Ġ|| Ġis If d Requested ( If d Data . TYPE _ IF D _ INTER OPER ABILITY )) Ġ{ Ċĉĉĉ ĉ register If d ( If d Data . TYPE _ IF D _ EX IF , Ġtag . getValue At ( 0 )) Ċĉĉ ĉ } Ċĉ ĉ } Ġelse Ġif ( tid Ġ== ĠTAG _ GPS _ IF D Ġ&& Ġcheck Allowed ( ifd , ĠEx if Interface . TAG _ GPS _ IF D )) Ġ{ Ċĉĉ ĉ if ( is If d Requested ( If d Data . TYPE _ IF D _ GPS )) Ġ{ Ċĉĉĉ ĉ register If d ( If d Data . TYPE _ IF D _ GPS , Ġtag . getValue At ( 0 )) Ċĉĉ ĉ } Ċĉ ĉ } Ġelse Ġif ( tid Ġ== ĠTAG _ INTER OPER ABILITY _ IF D Ġ&& Ġcheck Allowed ( Ċĉĉĉ ĉ ifd , Ċĉĉĉ ĉ Ex if Interface . TAG _ INTER OPER ABILITY _ IF D Ċĉĉ ĉ )) Ġ{ Ċĉĉ ĉ if ( is If d Requested ( If d Data . TYPE _ IF D _ INTER OPER ABILITY )) Ġ{ Ċĉĉĉ ĉ register If d ( If d Data . TYPE _ IF D _ INTER OPER ABILITY , Ġtag . getValue At ( 0 )) Ċĉĉ ĉ } Ċĉ ĉ } Ġelse Ġif ( tid Ġ== ĠTAG _ JPEG _ INTER CHANGE _ FORMAT Ġ&& Ġcheck Allowed ( Ċĉĉĉ ĉ ifd , Ċĉĉĉ ĉ Ex if Interface . TAG _ JPEG _ INTER CHANGE _ FORMAT Ċĉĉ ĉ )) Ġ{ Ċĉĉ ĉ if ( is Thumbnail Requested ) Ġ{ Ċĉĉĉ ĉ register Compressed Image ( tag . getValue At ( 0 )) Ċĉĉ ĉ } Ċĉ ĉ } Ġelse Ġif ( tid Ġ== ĠTAG _ JPEG _ INTER CHANGE _ FORMAT _ LENGTH Ġ&& Ġcheck Allowed ( Ċĉĉĉ ĉ ifd , Ċĉĉĉ ĉ Ex if Interface . TAG _ JPEG _ INTER CHANGE _ FORMAT _ LENGTH Ċĉĉ ĉ )) Ġ{ Ċĉĉ ĉ if ( is Thumbnail Requested ) Ġ{ Ċĉĉĉ ĉ mJ peg Size Tag Ġ= Ġtag Ċĉĉ ĉ } Ċĉ ĉ } Ġelse Ġif ( tid Ġ== ĠTAG _ STRIP _ OFFSET S Ġ&& Ġcheck Allowed ( ifd , ĠEx if Interface . TAG _ STRIP _ OFFSET S )) Ġ{ Ċĉĉ ĉ if ( is Thumbnail Requested ) Ġ{ Ċĉĉĉ ĉ if ( tag . hasValue ) Ġ{ Ċĉĉĉĉ ĉ for ( i Ġin Ġ 0 Ġuntil Ġtag . component Count ) Ġ{ Ċĉĉĉĉĉ ĉ if ( tag . dataType Ġ== ĠEx if Tag . TYPE _ UNSIGNED _ SHORT ) Ġ{ Ċĉĉĉĉĉĉ ĉ register Un compressed Strip ( i , Ġtag . getValue At ( i )) Ċĉĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉĉ ĉ register Un compressed Strip ( i , Ġtag . getValue At ( i )) Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉ ĉ m Corre sponding Event [ tag . offset ] Ġ= ĠEx if Tag Event ( tag , Ġfalse ) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ġelse Ġif ( tid Ġ== ĠTAG _ STRIP _ BYTE _ COUNT S Ġ&& Ġcheck Allowed ( Ċĉĉĉ ĉ ifd , Ċĉĉĉ ĉ Ex if Interface . TAG _ STRIP _ BYTE _ COUNT S Ċĉĉ ĉ ) Ġ&& Ġis Thumbnail Requested Ġ&& Ġtag . hasValue ) Ġ{ Ċĉĉ ĉ m Strip Size Tag Ġ= Ġtag Ċĉ ĉ } Ċ ĉ } ĊĉĊ ĉ fun Ġis Defined Tag ( ifd Id Ġ: ĠInt , Ġtag Id Ġ: ĠShort ) Ġ: ĠBoolean Ġ{ Ċĉ ĉ return Ġm Interface . tag Info . get ( Ċĉĉ ĉ Ex if Interface . define Tag ( Ċĉĉĉ ĉ ifd Id , Ċĉĉĉ ĉ tag Id Ċĉĉ ĉ ) Ċĉ ĉ ) Ġ!= ĠEx if Interface . DEFINITION _ NULL Ċ ĉ } ĊĉĊ ĉ private Ġfun Ġcheck Allowed ( ifd Ġ: ĠInt , Ġtag Id Ġ: ĠInt ) Ġ: ĠBoolean Ġ{ Ċĉ ĉ val Ġinfo Ġ= Ġm Interface . tag Info . get ( tag Id ) Ċĉ ĉ return Ġif ( info Ġ== ĠEx if Interface . DEFINITION _ NULL ) Ġ{ Ċĉĉ ĉ false Ċĉ ĉ } Ġelse ĠEx if Interface . is If d Allowed ( info , Ġif d ) Ċ ĉ } ĊĉĊ ĉ @ Throws ( IOException :: class ) Ċ ĉ fun Ġread Full Tag Value ( tag Ġ: ĠEx if Tag ) Ġ{ ĊĉĉĊĉ ĉ // ĠSome Ġinvalid Ġimages Ġcontains Ġtags Ġwith Ġwrong Ġsize , Ġcheck Ġit Ġhere Ċĉ ĉ val Ġtype Ġ= Ġtag . dataType Ċĉ ĉ val Ġcomponent Count Ġ= Ġtag . component Count ĊĉĉĊĉ ĉ // Ġsanity Ġcheck Ċĉ ĉ if ( component Count Ġ>= Ġ 0 x 6 6 0 0 0 0 0 0 ) Ġthrow ĠIOException (" size Ġout Ġof Ġbounds ") ĊĉĉĊĉ ĉ if ( type Ġ== ĠEx if Tag . TYPE _ ASCII Ġ|| Ġtype Ġ== ĠEx if Tag . TYPE _ UNDEFINED Ġ|| Ċĉĉ ĉ type Ġ== ĠEx if Tag . TYPE _ UNSIGNED _ BYTE ) Ġ{ Ċĉĉ ĉ var Ġsize Ġ= Ġtag . component Count Ċĉĉ ĉ if ( m Corre sponding Event . size Ġ> Ġ 0 ) Ġ{ Ċĉĉĉ ĉ val Ġfirst Entry Ġ= Ġm Corre sponding Event . first Entry () Ġ!! Ċĉĉĉ ĉ if ( first Entry . key Ġ< Ġm T iff Stream . read Byte Count Ġ+ Ġsize ) Ġ{ Ċĉĉĉĉ ĉ val Ġevent Ġ= Ġfirst Entry . value Ċĉĉĉĉ ĉ if ( event Ġis ĠImage Event ) Ġ{ Ċĉĉĉĉĉ ĉ // ĠTag Ġvalue Ġoverlap s Ġthumbnail , Ġignore Ġthumbnail . Ċĉĉĉĉĉ ĉ Log . w ( TAG , Ġ" Thumbnail Ġoverlap s Ġvalue Ġfor Ġtag : Ġ\ n $ tag ") Ċĉĉĉĉĉ ĉ val Ġentry Ġ= Ġm Corre sponding Event . poll First Entry () Ġ!! Ċĉĉĉĉĉ ĉ Log . w ( TAG , Ġ" Invalid Ġthumbnail Ġoffset : Ġ" Ġ+ Ġentry . key ) Ċĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉ ĉ // ĠTag Ġvalue Ġoverlap s Ġanother Ġtag , Ġshort en Ġcount Ċĉĉĉĉĉ ĉ if ( event Ġis ĠIf d Event ) Ġ{ Ċĉĉĉĉĉĉ ĉ Log . w ( TAG , Ġ" If d Ġ${ event . ifd } Ġoverlap s Ġvalue Ġfor Ġtag : Ġ\ n $ tag ") Ċĉĉĉĉĉ ĉ } Ġelse Ġif ( event Ġis ĠEx if Tag Event ) Ġ{ Ċĉĉĉĉĉĉ ĉ Log . w ( Ċĉĉĉĉĉĉĉ ĉ TAG , Ċĉĉĉĉĉĉĉ ĉ " Tag Ġvalue Ġfor Ġtag : Ġ\ n ${ event . tag } Ġoverlap s Ġvalue Ġfor Ġtag : Ġ\ n $ tag " Ċĉĉĉĉĉĉ ĉ ) Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉĉ ĉ size Ġ= Ġfirst Entry . key Ġ- Ġm T iff Stream . read Byte Count Ċĉĉĉĉĉ ĉ Log . w ( TAG , Ġ" Invalid Ġsize Ġof Ġtag : Ġ\ n $ tag Ġsetting Ġcount Ġto : Ġ$ size ") Ċĉĉĉĉĉ ĉ tag . force Set Component Count ( size ) Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ when ( tag . dataType ) Ġ{ Ċĉĉ ĉ Ex if Tag . TYPE _ UNSIGNED _ BYTE , ĠEx if Tag . TYPE _ UNDEFINED Ġ-> Ċĉĉĉ ĉ tag . setValue ( ByteArray ( component Count ). also Ġ{ Ġread ( it ) Ġ}) ĊĉĉĉĊĉĉ ĉ Ex if Tag . TYPE _ ASCII Ġ-> Ċĉĉĉ ĉ tag . setValue ( readString ( component Count )) ĊĉĉĉĊĉĉ ĉ Ex if Tag . TYPE _ UNSIGNED _ SHORT Ġ-> Ċĉĉĉ ĉ tag . setValue ( IntArray ( component Count ) Ġ{ Ġread Unsigned Short () Ġ}) ĊĉĉĉĊĉĉ ĉ Ex if Tag . TYPE _ LONG Ġ-> Ċĉĉĉ ĉ tag . setValue ( IntArray ( component Count ) Ġ{ Ġread Long (). toInt () Ġ}) Ċĉĉ ĉ Ex if Tag . TYPE _ UNSIGNED _ LONG Ġ-> Ċĉĉĉ ĉ tag . setValue ( Long Array ( component Count ) Ġ{ Ġread Unsigned Long () Ġ}) ĊĉĉĉĊĉĉ ĉ Ex if Tag . TYPE _ RATION AL Ġ-> Ċĉĉĉ ĉ tag . setValue ( Array ( component Count ) Ġ{ Ġread Rational () Ġ}) Ċĉĉ ĉ Ex if Tag . TYPE _ UNSIGNED _ RATION AL Ġ-> Ċĉĉĉ ĉ tag . setValue ( Array ( component Count ) Ġ{ Ġread Unsigned Rational () Ġ}) ĊĉĉĉĊĉ ĉ } ĊĉĉĊĉ ĉ // ĠLog . v ( ĠTAG , Ġ"\ n " Ġ+ Ġtag . toString () Ġ); Ċ ĉ } ĊĉĊ ĉ /** Ċĉ Ġ* ĠReads Ġbytes Ġfrom Ġthe ĠInputStream . Ċĉ Ġ*/ Ċ ĉ @ Throws ( IOException :: class ) Ċ ĉ protected Ġfun Ġread ( buffer Ġ: ĠByteArray , Ġoffset Ġ: ĠInt , Ġlength Ġ: ĠInt ) Ġ: ĠInt Ġ= Ċĉ ĉ m T iff Stream . read ( buffer , Ġoffset , Ġlength ) ĊĉĊ ĉ /** Ċĉ Ġ* ĠReads Ġa ĠString Ġfrom Ġthe ĠInputStream Ġwith ĠUS - ASCII Ġcharset . ĠThe Ġparser Ċĉ Ġ* Ġwill Ġread Ġn Ġbytes Ġand Ġconvert Ġit Ġto Ġascii Ġstring . ĠThis Ġis Ġused Ġfor Ċĉ Ġ* Ġreading Ġvalues Ġof Ġtype Ġ[ Ex if Tag . TYPE _ ASCII ]. Ċĉ Ġ*/ ĊĉĊ ĉ /** Ċĉ Ġ* ĠReads Ġa ĠString Ġfrom Ġthe ĠInputStream Ġwith Ġthe Ġgiven Ġcharset . ĠThe Ġparser Ċĉ Ġ* Ġwill Ġread Ġn Ġbytes Ġand Ġconvert Ġit Ġto Ġstring . ĠThis Ġis Ġused Ġfor Ġreading Ċĉ Ġ* Ġvalues Ġof Ġtype Ġ[ Ex if Tag . TYPE _ ASCII ]. Ċĉ Ġ*/ Ċ ĉ @ Throws ( IOException :: class ) Ċ ĉ @ Jvm Over loads Ċ ĉ protected Ġfun Ġread String ( n Ġ: ĠInt , Ġcharset Ġ: ĠCharset Ġ= ĠUS _ ASCII ) Ġ: ĠString Ġ= Ċĉ ĉ when Ġ{ Ċĉĉ ĉ n Ġ<= Ġ 0 Ġ-> Ġ"" Ċĉĉ ĉ else Ġ-> Ġm T iff Stream . readString ( n , Ġcharset ) Ċĉ ĉ } ĊĉĊ ĉ /** Ċĉ Ġ* ĠReads Ġvalue Ġof Ġtype Ġ[ Ex if Tag . TYPE _ UNSIGNED _ SHORT ] Ġfrom Ġthe Ċĉ Ġ* ĠInputStream . Ċĉ Ġ*/ Ċ ĉ @ Throws ( IOException :: class ) Ċ ĉ protected Ġfun Ġread Unsigned Short () Ġ: ĠInt Ġ= Ċĉ ĉ m T iff Stream . read Short (). toInt () Ġand Ġ 0 xffff ĊĉĊ ĉ /** Ċĉ Ġ* ĠReads Ġvalue Ġof Ġtype Ġ[ Ex if Tag . TYPE _ UNSIGNED _ LONG ] Ġfrom Ġthe Ċĉ Ġ* ĠInputStream . Ċĉ Ġ*/ Ċ ĉ @ Throws ( IOException :: class ) Ċ ĉ protected Ġfun Ġread Unsigned Long () Ġ: ĠLong Ġ{ Ċĉ ĉ return Ġread Long () Ġand Ġ 0 xffffffff L Ċ ĉ } ĊĉĊ ĉ /** Ċĉ Ġ* ĠReads Ġvalue Ġof Ġtype Ġ[ Ex if Tag . TYPE _ UNSIGNED _ RATION AL ] Ġfrom Ġthe Ċĉ Ġ* ĠInputStream . Ċĉ Ġ*/ Ċ ĉ @ Throws ( IOException :: class ) Ċ ĉ protected Ġfun Ġread Unsigned Rational () Ġ: ĠRational Ġ{ Ċĉ ĉ val Ġnom i Ġ= Ġread Unsigned Long () Ċĉ ĉ val Ġden omi Ġ= Ġread Unsigned Long () Ċĉ ĉ return ĠRational ( nom i , Ġden omi ) Ċ ĉ } ĊĉĊ ĉ /** Ċĉ Ġ* ĠReads Ġvalue Ġof Ġtype Ġ[ Ex if Tag . TYPE _ LONG ] Ġfrom Ġthe ĠInputStream . Ċĉ Ġ*/ Ċ ĉ @ Throws ( IOException :: class ) Ċ ĉ protected Ġfun Ġread Long () Ġ: ĠLong Ġ= Ċĉ ĉ m T iff Stream . readInt (). to Long () ĊĉĊ ĉ /** Ċĉ Ġ* ĠReads Ġvalue Ġof Ġtype Ġ[ Ex if Tag . TYPE _ RATION AL ] Ġfrom Ġthe ĠInputStream . Ċĉ Ġ*/ Ċ ĉ @ Throws ( IOException :: class ) Ċ ĉ protected Ġfun Ġread Rational () Ġ: ĠRational Ġ{ Ċĉ ĉ val Ġnom i Ġ= Ġread Long () Ċĉ ĉ val Ġden omi Ġ= Ġread Long () Ċĉ ĉ return ĠRational ( nom i , Ġden omi ) Ċ ĉ } ĊĉĊ ĉ private Ġclass ĠImage Event Ġ{ Ċĉ ĉ internal Ġvar Ġstrip Index Ġ: ĠInt Ġ= Ġ 0 Ċĉ ĉ internal Ġvar Ġtype Ġ: ĠInt Ġ= Ġ 0 ĊĉĉĊĉ ĉ internal Ġconstructor ( type Ġ: ĠInt ) Ġ{ Ċĉĉ ĉ this . strip Index Ġ= Ġ 0 Ċĉĉ ĉ this . type Ġ= Ġtype Ċĉ ĉ } ĊĉĉĊĉ ĉ internal Ġconstructor ( type Ġ: ĠInt , Ġstrip Index Ġ: ĠInt ) Ġ{ Ċĉĉ ĉ this . type Ġ= Ġtype Ċĉĉ ĉ this . strip Index Ġ= Ġstrip Index Ċĉ ĉ } Ċ ĉ } ĊĉĊ ĉ private Ġclass ĠIf d Event Ġinternal Ġconstructor ( Ċĉ ĉ internal Ġvar Ġif d Ġ: ĠInt , Ċĉ ĉ internal Ġvar Ġis Requested Ġ: ĠBoolean Ċ ĉ ) ĊĉĊ ĉ private Ġclass ĠEx if Tag Event Ġinternal Ġconstructor ( Ċĉ ĉ internal Ġvar Ġtag Ġ: ĠEx if Tag , Ċĉ ĉ internal Ġvar Ġis Requested Ġ: ĠBoolean Ċ ĉ ) ĊĉĊ ĉ class ĠSection ( var Ġsize Ġ: ĠInt , Ġvar Ġtype Ġ: ĠInt , Ġvar Ġdata Ġ: ĠByteArray ) ĊĊ ĉ comp anion Ġobject Ġ{ Ċĉ ĉ private Ġconst Ġval ĠTAG Ġ= Ġ" Ex if Parser " ĊĉĉĊĉ ĉ /** Ċĉĉ Ġ* ĠWhen Ġthe Ġparser Ġreaches Ġa Ġnew ĠIF D Ġarea . ĠCall Ġ[. getCurrent If d ] Ġto Ċĉĉ Ġ* Ġknow Ġwhich ĠIF D Ġwe Ġare Ġin . Ċĉĉ Ġ*/ Ċĉ ĉ const Ġval ĠEVENT _ START _ OF _ IF D Ġ= Ġ 0 Ċĉ ĉ /** Ċĉĉ Ġ* ĠWhen Ġthe Ġparser Ġreaches Ġa Ġnew Ġtag . ĠCall Ġ[. getTag ] to Ġget Ġthe Ċĉĉ Ġ* Ġcorresponding Ġtag . Ċĉĉ Ġ*/ Ċĉ ĉ const Ġval ĠEVENT _ NEW _ TAG Ġ= Ġ 1 Ċĉ ĉ /** Ċĉĉ Ġ* ĠWhen Ġthe Ġparser Ġreaches Ġthe Ġvalue Ġarea Ġof Ġtag Ġthat Ġis Ġregistered Ġby Ċĉĉ Ġ* Ġ[. register For Tag Value ] Ġpreviously . ĠCall Ġ[. getTag ] Ċĉĉ Ġ* Ġto Ġget Ġthe Ġcorresponding Ġtag . Ċĉĉ Ġ*/ Ċĉ ĉ const Ġval ĠEVENT _ VALUE _ OF _ REGISTER ED _ TAG Ġ= Ġ 2 Ċĉ ĉ /** Ċĉĉ Ġ* ĠWhen Ġthe Ġparser Ġreaches Ġthe Ġcompressed Ġimage Ġarea . Ċĉĉ Ġ*/ Ċĉ ĉ const Ġval ĠEVENT _ COMPRESSED _ IMAGE Ġ= Ġ 3 Ċĉ ĉ /** Ċĉĉ Ġ* ĠWhen Ġthe Ġparser Ġreaches Ġthe Ġun compressed Ġimage Ġstrip . ĠCall Ċĉĉ Ġ* Ġ[. get Strip Index ] Ġto Ġget Ġthe Ġindex Ġof Ġthe Ġstrip . Ċĉĉ Ġ* Ċĉĉ Ġ* Ġ@ see Ġ. get Strip Index Ċĉĉ Ġ*/ Ċĉ ĉ const Ġval ĠEVENT _ UN COMPRESSED _ STRIP Ġ= Ġ 4 Ċĉ ĉ /** Ċĉĉ Ġ* ĠWhen Ġthere Ġis Ġnothing Ġmore Ġto Ġparse . Ċĉĉ Ġ*/ Ċĉ ĉ const Ġval ĠEVENT _ END Ġ= Ġ 5 ĊĉĉĊĉ ĉ protected Ġconst Ġval ĠEX IF _ HEADER Ġ= Ġ 0 x 4 5 7 8 6 9 6 6 Ġ// ĠEX IF Ġheader Ġ" Ex if " Ċĉ ĉ protected Ġconst Ġval ĠEX IF _ HEADER _ TAIL Ġ= Ġ 0 x 0 0 0 0 . to Short () Ġ// ĠEX IF Ġheader Ġin ĠM _ EX IF Ċĉ ĉ // ĠTI FF Ġheader Ċĉ ĉ protected Ġconst Ġval ĠL IT TLE _ ENDIAN _ TAG Ġ= Ġ 0 x 4 9 4 9 . to Short () Ġ// Ġ" II " Ċĉ ĉ protected Ġconst Ġval ĠBIG _ ENDIAN _ TAG Ġ= Ġ 0 x 4 d 4 d . to Short () Ġ// Ġ" MM " Ċĉ ĉ protected Ġconst Ġval ĠTI FF _ HEADER _ TAIL Ġ: ĠShort Ġ= Ġ 0 x 0 0 2 A Ċĉ ĉ protected Ġconst Ġval ĠTAG _ SIZE Ġ= Ġ 1 2 Ċĉ ĉ protected Ġconst Ġval ĠOFFSET _ SIZE Ġ= Ġ 2 Ċĉ ĉ protected Ġconst Ġval ĠDEFAULT _ IF D 0 _ OFFSET Ġ= Ġ 8 Ċĉ ĉ private Ġval ĠUS _ ASCII Ġ= ĠCharset . forName (" US - ASCII ") Ċĉ ĉ private Ġval ĠTAG _ EX IF _ IF D Ġ= ĠEx if Interface . get True Tag Key ( Ex if Interface . TAG _ EX IF _ IF D ) Ċĉ ĉ private Ġval ĠTAG _ GPS _ IF D Ġ= ĠEx if Interface . get True Tag Key ( Ex if Interface . TAG _ GPS _ IF D ) Ċĉ ĉ private Ġval ĠTAG _ INTER OPER ABILITY _ IF D Ġ= Ċĉĉ ĉ Ex if Interface . get True Tag Key ( Ex if Interface . TAG _ INTER OPER ABILITY _ IF D ) Ċĉ ĉ private Ġval ĠTAG _ JPEG _ INTER CHANGE _ FORMAT Ġ= Ċĉĉ ĉ Ex if Interface . get True Tag Key ( Ex if Interface . TAG _ JPEG _ INTER CHANGE _ FORMAT ) Ċĉ ĉ private Ġval ĠTAG _ JPEG _ INTER CHANGE _ FORMAT _ LENGTH Ġ= Ċĉĉ ĉ Ex if Interface . get True Tag Key ( Ex if Interface . TAG _ JPEG _ INTER CHANGE _ FORMAT _ LENGTH ) Ċĉ ĉ private Ġval ĠTAG _ STRIP _ OFFSET S Ġ= ĠEx if Interface . get True Tag Key ( Ex if Interface . TAG _ STRIP _ OFFSET S ) Ċĉ ĉ private Ġval ĠTAG _ STRIP _ BYTE _ COUNT S Ġ= Ċĉĉ ĉ Ex if Interface . get True Tag Key ( Ex if Interface . TAG _ STRIP _ BYTE _ COUNT S ) ĊĉĉĊĉ ĉ private Ġval Ġstd _ l uminance _ quant _ tbl Ġ: ĠInt Array Ċĉ ĉ private Ġval Ġstd _ chrom in ance _ quant _ tbl Ġ: ĠInt Array Ċĉ ĉ val Ġdef tabs Ġ: ĠArray < IntArray > ĊĉĉĊĉ ĉ init Ġ{ Ċĉĉ ĉ std _ l uminance _ quant _ tbl Ġ= Ġint ArrayOf ( Ċĉĉĉĉ 1 6 , Ċĉĉĉĉ 1 1 , Ċĉĉĉĉ 1 2 , Ċĉĉĉĉ 1 4 , Ċĉĉĉĉ 1 2 , Ċĉĉĉĉ 1 0 , Ċĉĉĉĉ 1 6 , Ċĉĉĉĉ 1 4 , Ċĉĉĉĉ 1 3 , Ċĉĉĉĉ 1 4 , Ċĉĉĉĉ 1 8 , Ċĉĉĉĉ 1 7 , Ċĉĉĉĉ 1 6 , Ċĉĉĉĉ 1 9 , Ċĉĉĉĉ 2 4 , Ċĉĉĉĉ 4 0 , Ċĉĉĉĉ 2 6 , Ċĉĉĉĉ 2 4 , Ċĉĉĉĉ 2 2 , Ċĉĉĉĉ 2 2 , Ċĉĉĉĉ 2 4 , Ċĉĉĉĉ 4 9 , Ċĉĉĉĉ 3 5 , Ċĉĉĉĉ 3 7 , Ċĉĉĉĉ 2 9 , Ċĉĉĉĉ 4 0 , Ċĉĉĉĉ 5 8 , Ċĉĉĉĉ 5 1 , Ċĉĉĉĉ 6 1 , Ċĉĉĉĉ 6 0 , Ċĉĉĉĉ 5 7 , Ċĉĉĉĉ 5 1 , Ċĉĉĉĉ 5 6 , Ċĉĉĉĉ 5 5 , Ċĉĉĉĉ 6 4 , Ċĉĉĉĉ 7 2 , Ċĉĉĉĉ 9 2 , Ċĉĉĉĉ 7 8 , Ċĉĉĉĉ 6 4 , Ċĉĉĉĉ 6 8 , Ċĉĉĉĉ 8 7 , Ċĉĉĉĉ 6 9 , Ċĉĉĉĉ 5 5 , Ċĉĉĉĉ 5 6 , Ċĉĉĉĉ 8 0 , Ċĉĉĉĉ 1 0 9 , Ċĉĉĉĉ 8 1 , Ċĉĉĉĉ 8 7 , Ċĉĉĉĉ 9 5 , Ċĉĉĉĉ 9 8 , Ċĉĉĉĉ 1 0 3 , Ċĉĉĉĉ 1 0 4 , Ċĉĉĉĉ 1 0 3 , Ċĉĉĉĉ 6 2 , Ċĉĉĉĉ 7 7 , Ċĉĉĉĉ 1 1 3 , Ċĉĉĉĉ 1 2 1 , Ċĉĉĉĉ 1 1 2 , Ċĉĉĉĉ 1 0 0 , Ċĉĉĉĉ 1 2 0 , Ċĉĉĉĉ 9 2 , Ċĉĉĉĉ 1 0 1 , Ċĉĉĉĉ 1 0 3 , Ċĉĉĉĉ 9 9 Ċĉĉ ĉ ) ĊĉĉĉĊĉĉ ĉ std _ chrom in ance _ quant _ tbl Ġ= Ġint ArrayOf ( Ċĉĉĉĉ 1 7 , Ċĉĉĉĉ 1 8 , Ċĉĉĉĉ 1 8 , Ċĉĉĉĉ 2 4 , Ċĉĉĉĉ 2 1 , Ċĉĉĉĉ 2 4 , Ċĉĉĉĉ 4 7 , Ċĉĉĉĉ 2 6 , Ċĉĉĉĉ 2 6 , Ċĉĉĉĉ 4 7 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 6 6 , Ċĉĉĉĉ 5 6 , Ċĉĉĉĉ 6 6 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 , Ċĉĉĉĉ 9 9 Ċĉĉ ĉ ) ĊĉĉĉĊĉĉ ĉ def tabs Ġ= ĠarrayOf ( std _ l uminance _ quant _ tbl , Ġstd _ chrom in ance _ quant _ tbl ) Ċĉ ĉ } ĊĉĉĊĉ ĉ fun ĠGet 1 6 m ( data Ġ: ĠByteArray , Ġposition Ġ: ĠInt ) Ġ: ĠInt Ġ{ Ċĉĉ ĉ val Ġb 1 Ġ= Ġdata [ position ]. toInt () Ġand Ġ 0 xFF Ġshl Ġ 8 Ċĉĉ ĉ val Ġb 2 Ġ= Ġdata [ position Ġ+ Ġ 1 ]. toInt () Ġand Ġ 0 xFF Ċĉĉ ĉ return Ġb 1 Ġor Ġb 2 Ċĉ ĉ } ĊĉĉĊĉ ĉ /** Ċĉĉ Ġ* ĠParses Ġthe Ġthe Ġgiven ĠInputStream Ġwith Ġthe Ġgiven Ġoptions Ċĉĉ Ġ* Ċĉĉ Ġ* Ġ@ throws Ġjava . io . IOException Ċĉĉ Ġ* Ġ@ throws ĠEx if Invalid FormatException Ċĉĉ Ġ*/ Ċĉ ĉ @ Throws ( IOException :: class , ĠEx if Invalid FormatException :: class ) Ċĉ ĉ fun Ġparse ( inputStream Ġ: ĠInputStream , Ġoptions Ġ: ĠInt , Ġi Ref Ġ: ĠEx if Interface ) Ġ: ĠEx if Parser Ġ= Ċĉĉ ĉ Ex if Parser ( inputStream , Ġoptions , Ġi Ref ) Ċ ĉ } Ċ }