/* Ċ Ġ* ĠCopyright Ġ( c ) Ġ 2 0 2 1 ĠSer el ay ĠLtd . ĠAll Ġrights Ġreserved . Ċ Ġ*/ Ċ Ċ package Ġcom . ser el ay . c 2 pa Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroid . graphics . Bitmap Factory Ċ import Ġandroid . util . Base 6 4 Ċ import Ġandroidx . ex if interface . media . Ex if Interface Ċ import Ġcom . ser el ay . c 2 pa . pro venance . ByteArray Helper Ċ import Ġjava . io .* Ċ import Ġjava . security . Message Digest Ċ import Ġkotlin . math . max Ċ import Ġkotlin . math . round ToInt Ċ Ċ object ĠThumb nail Helper Ġ{ ĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ ĠSystem . load Library (" ser el ay - j pe gt ur bo ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠUse Ġa Ġnative Ġlibrary Ġto Ġcreate Ġa Ġreproducible Ġthumbnail . ĠBuilt Ġin Ġthumbnail Ġmethods Ġon Ġthe ĠOS Ġare Ġsus cept ible Ġto ĠOS Ġchanges Ġand ĊĠĠĠĠ Ġ* Ġhardware Ġdifferences . ĠUsing Ġthis Ġapproach Ġmeans Ġwe Ġare Ġsure Ġthat Ġfor Ġthe Ġsame Ġinput ĠJPEG Ġthe Ġsame Ġoutput Ġthumbnail ĠJPEG Ġis Ġoutput ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThis Ġversion Ġis Ġused Ġin Ġfavour Ġof Ġminim izing Ġthe Ġmemory Ġfoot print Ġ- Ġby Ġre - using Ġthe Ġalready Ġexisting Ġbyte Ġarray Ġof Ġthe Ġimage . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠUSE D ĠAT ĠC 2 PA Ġ_ PROCESS ING _ ĠTIME ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġbytes ĠByte Ġarray Ġof Ġthe Ġoriginal ĠJPEG Ġfile ĊĠĠĠĠ Ġ* Ġ@ return ĠJPEG Ġrepresentation Ġof Ġthumbnail ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġget Re pro duc ible JPEG Thumbnail ( context : ĠContext , Ġbytes : ĠByteArray ): ĠByteArray Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġval ĠinputStream Ġ= ĠBuffered InputStream ( FileInputStream ( file )) ĊĠĠĠĠĠĠĠ Ġval ĠinputStream Ġ= ĠByteArrayInputStream ( bytes ) ĊĊĠĠĠĠĠĠĠ Ġval Ġopts Ġ= ĠBitmap Factory . Options (). apply Ġ{ Ġin Just Decode Bounds Ġ= Ġtrue Ġ} ĊĠĠĠĠĠĠĠ Ġ// ĠDecode Ġjust Ġthe Ġinfo , Ġnot Ġbitmap Ġitself . ĠCannot Ġuse Ġsame ĠinputStream Ġas Ġwe Ġcan 't Ġre wind / reset ĊĠĠĠĠĠĠĠ ĠBitmap Factory . decode Stream ( inputStream , Ġnull , Ġopts ) ĊĠĠĠĠĠĠĠ ĠinputStream . close () ĊĊĠĠĠĠĠĠĠ Ġval Ġinput Ġ= ĠByteArrayInputStream ( bytes ) ĊĠĠĠĠĠĠĠ Ġval Ġrotation Ġ= ĠEx if Interface ( input ). rotation Degrees ĊĠĠĠĠĠĠĠ Ġinput . close () ĊĊĠĠĠĠĠĠĠ Ġval Ġoriginal Width Ġ= Ġopts . out Width ĊĠĠĠĠĠĠĠ Ġval Ġoriginal Height Ġ= Ġopts . out Height ĊĊĠĠĠĠĠĠĠ Ġ// ĠCalculate Ġres ample / scale ĊĠĠĠĠĠĠĠ Ġ// ĠWe Ġassume Ġit 's Ġalready Ġover Ġ 1 0 2 4 Ġso Ġmust Ġscale Ġdown Ġat Ġleast Ġonce ĊĠĠĠĠĠĠĠ Ġval Ġmax Ġ= Ġmax ( original Width , Ġoriginal Height ) ĊĊĠĠĠĠĠĠĠ Ġvar Ġscale Ġ= Ġ 8 ĊĠĠĠĠĠĠĠ Ġval Ġdenom Ġ= Ġ 8 ĊĠĠĠĠĠĠĠ Ġvar Ġscaled Max : ĠInt ĊĠĠĠĠĠĠĠ Ġdo Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġscale -- ĊĠĠĠĠĠĠĠĠĠĠĠ Ġscaled Max Ġ= Ġ( max Ġ* Ġ( scale . toFloat () Ġ/ Ġdenom . toFloat ())). toInt () ĊĠĠĠĠĠĠĠ Ġ} Ġwhile Ġ( scaled Max Ġ> Ġ 1 0 2 4 ) ĊĠĠĠĠĠĠĠ Ġ// Ġhttps :// sourceforge . net / p / lib jpeg - tur bo / mail man / message / 3 2 8 0 6 5 8 1 / ĊĠĠĠĠĠĠĠ Ġ// Ġ Ġround ToInt : ĠRound s Ġthis Ġ[ Float ] Ġvalue Ġto Ġthe Ġnearest Ġinteger Ġand Ġconverts Ġthe Ġresult Ġto Ġ[ Int ]. ĊĠĠĠĠĠĠĠ Ġ// Ġ Ġ* ĠT ies Ġare Ġrounded Ġtowards Ġpositive Ġinfinity . ĊĠĠĠĠĠĠĠ Ġval Ġwidth Ġ= Ġ( original Width . toFloat () Ġ* Ġ( scale . toFloat () Ġ/ Ġdenom . toFloat ())). round ToInt () ĊĠĠĠĠĠĠĠ Ġval Ġheight Ġ= Ġ( original Height . toFloat () Ġ* Ġ( scale . toFloat () Ġ/ Ġdenom . toFloat ())). round ToInt () ĊĠĠĠĠĠĠĠ Ġval Ġun rot ated Thumbnail Ġ= Ġget Thumbnail ( bytes , Ġbytes . size , Ġwidth , Ġheight ) ĊĠĠĠĠĠĠĠ Ġreturn Ġrotate Thumbnail ( context , Ġun rot ated Thumbnail , Ġrotation ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠUse Ġa Ġnative Ġlibrary Ġto Ġcreate Ġa Ġreproducible Ġthumbnail . ĊĠĠĠĠ Ġ* ĠBuilt Ġin Ġthumbnail Ġmethods Ġon Ġthe ĠOS Ġare Ġsus cept ible Ġto ĠOS Ġversion / software Ġchanges Ġand ĊĠĠĠĠ Ġ* Ġhardware Ġdifferences . ĊĠĠĠĠ Ġ* ĠUsing Ġthis Ġapproach Ġmeans Ġwe Ġare Ġsure Ġthat Ġfor Ġthe Ġsame Ġinput ĠJPEG Ġgives ĊĠĠĠĠ Ġ* Ġthe Ġsame Ġoutput Ġthumbnail ĠJPEG Ġis Ġoutput . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThis Ġis Ġpossible Ġwith Ġa Ġfull ĠByteArray Ġof Ġan Ġimage Ġtoo . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġfile ĠAn Ġoriginal ĠJPEG Ġfile ĊĠĠĠĠ Ġ* Ġ@ return ĠJPEG Ġrepresentation Ġof Ġthumbnail ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġget Re pro duc ible JPEG Thumbnail ( context : ĠContext , Ġfile : ĠFile ): ĠByteArray Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠinputStream Ġ= ĠBuffered InputStream ( FileInputStream ( file )) ĊĠĠĠĠĠĠĠ Ġval Ġopts Ġ= ĠBitmap Factory . Options (). apply Ġ{ Ġin Just Decode Bounds Ġ= Ġtrue Ġ} ĊĠĠĠĠĠĠĠ Ġ// ĠDecode Ġjust Ġthe Ġinfo , Ġnot Ġbitmap Ġitself . ĠCannot Ġuse Ġsame ĠinputStream Ġas Ġwe Ġcan 't Ġre wind / reset ĊĠĠĠĠĠĠĠ ĠBitmap Factory . decode Stream ( inputStream , Ġnull , Ġopts ) ĊĠĠĠĠĠĠĠ ĠinputStream . close () ĊĊĠĠĠĠĠĠĠ Ġval Ġrotation Ġ= ĠEx if Interface ( file ). rotation Degrees ĊĊĠĠĠĠĠĠĠ Ġval Ġoriginal Width Ġ= Ġopts . out Width ĊĠĠĠĠĠĠĠ Ġval Ġoriginal Height Ġ= Ġopts . out Height ĊĊĠĠĠĠĠĠĠ Ġ// ĠCalculate Ġres ample / scale ĊĠĠĠĠĠĠĠ Ġ// ĠWe Ġassume Ġit 's Ġalready Ġover Ġ 1 0 2 4 Ġso Ġmust Ġscale Ġdown Ġat Ġleast Ġonce ĊĠĠĠĠĠĠĠ Ġval Ġmax Ġ= Ġmax ( original Width , Ġoriginal Height ) ĊĊĠĠĠĠĠĠĠ Ġvar Ġscale Ġ= Ġ 8 ĊĠĠĠĠĠĠĠ Ġval Ġdenom Ġ= Ġ 8 ĊĠĠĠĠĠĠĠ Ġvar Ġscaled Max : ĠInt ĊĠĠĠĠĠĠĠ Ġdo Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġscale -- ĊĠĠĠĠĠĠĠĠĠĠĠ Ġscaled Max Ġ= Ġ( max Ġ* Ġ( scale . toFloat () Ġ/ Ġdenom . toFloat ())). toInt () ĊĠĠĠĠĠĠĠ Ġ} Ġwhile Ġ( scaled Max Ġ> Ġ 1 0 2 4 ) ĊĠĠĠĠĠĠĠ Ġval Ġwidth Ġ= Ġ( original Width . toFloat () Ġ* Ġ( scale . toFloat () Ġ/ Ġdenom . toFloat ())). round ToInt () ĊĠĠĠĠĠĠĠ Ġval Ġheight Ġ= Ġ( original Height . toFloat () Ġ* Ġ( scale . toFloat () Ġ/ Ġdenom . toFloat ())). round ToInt () ĊĊĠĠĠĠĠĠĠ Ġval Ġbyte ArrayOf Image Ġ= ĠByteArray Helper . toByteArray ( file ) !! ĊĊĠĠĠĠĠĠĠ Ġval Ġun rot ated Thumbnail Ġ= Ġget Thumbnail ( byte ArrayOf Image , Ġbyte ArrayOf Image . size , Ġwidth , Ġheight ) ĊĠĠĠĠĠĠĠ Ġreturn Ġrotate Thumbnail ( context , Ġun rot ated Thumbnail , Ġrotation ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠApply ĠEx if Ġrotation Ġto Ġthe Ġnew Ġthumbnail , Ġso Ġthat Ġit Ġrenders Ġcorrectly . ĠRot ating Ġin ĠLib JPEG Ġtur bo Ġis Ġnot Ġperfect Ġfor ĠM CU Ġsize ĊĠĠĠĠ Ġ* Ġso Ġleads Ġto Ġsome Ġartifact ing Ġwhere Ġthe Ġincomplete ĠM CU Ġis Ġleft Ġon Ġthe Ġedges Ġof Ġthe Ġimage Ġ( right Ġor Ġbottom ) ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġcontext ĠThe Ġapplication Ġcontext ĊĠĠĠĠ Ġ* Ġ@ param Ġoriginal ĠThe Ġthumbnail ĠJPEG Ġbytes , Ġun rot ated ĊĠĠĠĠ Ġ* Ġ@ param Ġrotation ĠThe Ġrotation Ġdegrees Ġto Ġapply Ġin ĠEX IF ĊĠĠĠĠ Ġ* Ġ@ return ĠThe Ġfinal ĠJPEG Ġbytes Ġwhich Ġincludes Ġthe Ġrotation ĠEX IF Ġinformation ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġrotate Thumbnail ( context : ĠContext , Ġoriginal : ĠByteArray , Ġrotation : ĠInt ): ĠByteArray Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfile Ġ= ĠFile ( context . cacheDir , Ġ"${ System . nano Time ()}. jpg ") Ġ// Ġwe Ġassume Ġnone Ġcan Ġhappen Ġat Ġthe Ġsame Ġnan ose cond Ġhere ĊĠĠĠĠĠĠĠ Ġfile . write Bytes ( original ) ĊĠĠĠĠĠĠĠ Ġval Ġex if Ġ= ĠEx if Interface ( file ) ĊĠĠĠĠĠĠĠ Ġwhen Ġ( rotation ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠ 9 0 Ġ-> Ġex if . setAttribute ( Ex if Interface . TAG _ OR IENTATION , ĠEx if Interface . OR IENTATION _ ROT ATE _ 9 0 . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠ 1 8 0 Ġ-> Ġex if . setAttribute ( Ex if Interface . TAG _ OR IENTATION , ĠEx if Interface . OR IENTATION _ ROT ATE _ 1 8 0 . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠ 2 7 0 Ġ-> Ġex if . setAttribute ( Ex if Interface . TAG _ OR IENTATION , ĠEx if Interface . OR IENTATION _ ROT ATE _ 2 7 0 . toString ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġex if . save Attributes () ĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġfile . read Bytes () ĊĠĠĠĠĠĠĠ Ġfile . delete () ĊĠĠĠĠĠĠĠ Ġreturn Ġresult ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠGenerate Ġa Ġthumbnail Ġfrom Ġa Ġsource Ġimage Ġusing Ġa Ġscaled Ġdown Ġrepresentation Ġin Ġa Ġpower Ġof Ġ 2 . ĊĠĠĠĠ Ġ* ĠThe Ġdimensions Ġshould Ġbe Ġprovided Ġwith Ġpre - rotation Ġand Ġscaled Ġdown Ġby Ġthe Ġsame Ġfactor . ĊĠĠĠĠ Ġ* Ġe . g . Ġ 2 Ġwould Ġbe Ġhalf Ġthe Ġsize , Ġ 4 Ġwould Ġbe Ġa Ġquarter Ġof Ġthe Ġsize . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ param Ġsource Ġthe Ġbyte Ġbuffer Ġof Ġthe Ġoriginal ĠJPEG Ġfile Ġitself ĊĠĠĠĠ Ġ* Ġ@ param Ġlength Ġthe Ġlength Ġof Ġthe Ġbyte Ġbuffer ĊĠĠĠĠ Ġ* Ġ@ param Ġwidth Ġthe Ġpre - rot ated Ġwidth Ġ( non ĠEX IF Ġapplication ) ĊĠĠĠĠ Ġ* Ġ@ param Ġheight Ġthe Ġpre - rot ated Ġheight Ġ( non ĠEX IF Ġapplication ) ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return ĠThe ĠJPEG Ġrepresentation Ġof Ġthe Ġthumbnail Ġin Ġbyte Ġarray Ġwith ĠEX IF Ġand Ġother Ġmetadata . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġexternal Ġfun Ġget Thumbnail ( ĊĠĠĠĠĠĠĠ Ġsource : ĠByteArray , ĊĠĠĠĠĠĠĠ Ġlength : ĠInt , ĊĠĠĠĠĠĠĠ Ġwidth : ĠInt , ĊĠĠĠĠĠĠĠ Ġheight : ĠInt ĊĠĠĠ Ġ): ĠByteArray Ċ Ċ }