| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597 |
- //
- // JPEG Decoder
- //
- // written by Larry Bank
- // bitbank@pobox.com
- // Arduino port started 8/2/2020
- // Original JPEG code written 26+ years ago :)
- // The goal of this code is to decode baseline JPEG images
- // using no more than 18K of RAM (if sent directly to an LCD display)
- //
- // Copyright 2020 BitBank Software, Inc. All Rights Reserved.
- // 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.
- //===========================================================================
- //
- #include "ImC/decoder.h"
- #if defined(ARM_MATH_CM4) || defined(ARM_MATH_CM7)
- #define HAS_SIMD
- #endif
- // forward references
- static int JPEGInit(JPEGIMAGE *pJPEG);
- static int JPEGParseInfo(JPEGIMAGE *pPage, int bExtractThumb);
- static void JPEGGetMoreData(JPEGIMAGE *pPage);
- static int DecodeJPEG(JPEGIMAGE *pImage);
- static int32_t readRAM(JPEGFILE *pFile, uint8_t *pBuf, int32_t iLen);
- static int32_t seekMem(JPEGFILE *pFile, int32_t iPosition);
- //static int32_t readFile(JPEGFILE *pFile, uint8_t *pBuf, int32_t iLen);
- //static int32_t seekFile(JPEGFILE *pFile, int32_t iPosition);
- //static void closeFile(void *handle);
- static void JPEGDither(JPEGIMAGE *pJPEG, int iWidth, int iHeight);
- /* JPEG tables */
- // zigzag ordering of DCT coefficients
- static const unsigned char cZigZag[64] = {0,1,5,6,14,15,27,28,
- 2,4,7,13,16,26,29,42,
- 3,8,12,17,25,30,41,43,
- 9,11,18,24,31,40,44,53,
- 10,19,23,32,39,45,52,54,
- 20,22,33,38,46,51,55,60,
- 21,34,37,47,50,56,59,61,
- 35,36,48,49,57,58,62,63};
- // un-zigzag ordering
- static const unsigned char cZigZag2[64] = {0,1,8,16,9,2,3,10,
- 17,24,32,25,18,11,4,5,
- 12,19,26,33,40,48,41,34,
- 27,20,13,6,7,14,21,28,
- 35,42,49,56,57,50,43,36,
- 29,22,15,23,30,37,44,51,
- 58,59,52,45,38,31,39,46,
- 53,60,61,54,47,55,62,63};
- // For AA&N IDCT method, multipliers are equal to quantization
- // coefficients scaled by scalefactor[row]*scalefactor[col], where
- // scalefactor[0] = 1
- // scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
- // For integer operation, the multiplier table is to be scaled by
- // IFAST_SCALE_BITS.
- static const int iScaleBits[64] = {16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
- 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
- 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
- 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
- 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
- 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
- 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
- 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247};
- uint8_t (*dst_image)[120][160][3];
- float scale;
- int32_t zero_point;
- /////////////////////////////////////BILINEAR INTERPOLATION////////////////////////////////////////////////
- //#define floor(x) (int)x
- //#define ceil(x) (int)(x+0.995)
- //void resize_image(uint32_t* src, uint32_t* dst, int image_width, int image_height, int new_width, int new_height){
- //
- //
- //
- // float ratio_x = (float) (image_width - 1) / (new_width -1);
- // float ratio_y = (float) (image_height -1) / (new_height-1);
- //
- // for(int i = 0; i < new_height; i++){
- // for(int j = 0; j < new_width; j++){
- // int xl = floor(ratio_x * j);
- // int yl = floor(ratio_y * i);
- // int xh = ceil(ratio_x * j);
- // int yh = ceil(ratio_y * i);
- //
- // float x_weight = (ratio_x * j) - xl;
- // float y_weight = (ratio_y * i) - yl;
- //
- // uint32_t a = src[yl * image_width + xl];
- // uint32_t b = src[yl * image_width + xh];
- // uint32_t c = src[yh * image_width + xl];
- // uint32_t d = src[yh * image_width + xh];
- //
- // uint32_t pixel = a * (1 - x_weight) * (1 - y_weight) +
- // b * x_weight * ( 1- y_weight) +
- // c * y_weight * ( 1 - x_weight) +
- // d * x_weight * y_weight;
- //
- //
- // dst[i * new_width + j] = pixel;
- //
- // }
- // }
- //
- //}
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////
- int getImage(JPEGDRAW *pdraw){
- // printf("Being called for drawing\r\n");
- // int iCount;
- // iCount = pdraw->iWidth * pdraw->iHeight;
- // printf("Depth of the pixel %d \r\n", pdraw->iBpp);
- for(int i = 0, ii=pdraw->y; i < pdraw->iHeight; i++,ii++){
- for(int j = 0; j < pdraw->iWidth; j++){
- uint32_t rgb = (uint32_t)pdraw->pPixels[i * pdraw->iWidth + j];
- uint32_t R5 = ((((rgb >> 11) & 0x1F) * 527) + 23) >> 6;
- uint32_t G6 = ((((rgb >> 5) & 0x3F) * 259) + 33) >> 6;
- uint32_t B5 = (((rgb & 0x1F) * 527) + 23) >> 6;
- (*dst_image)[ii][j][0] = (int8_t) ( (R5 / 255.0) / scale + zero_point);
- (*dst_image)[ii][j][1] = (int8_t) ( (G6 / 255.0) / scale + zero_point);
- (*dst_image)[ii][j][2] = (int8_t) ( (B5 / 255.0) / scale + zero_point);
- }
- }
- return 1;
- }
- //void decodeMyImage(uint8_t* _pdata, int iDataSize, int x, int y, int iOptions, JPEG_DRAW_CALLBACK *pfnDraw, int convert_to_grayscale){
- int32_t decodeMyImage(uint8_t* _pdata, int iDataSize, int x, int y, int iOptions, JPEG_DRAW_CALLBACK *pfnDraw, int convert_to_grayscale){
- // printf("[DEC] init ...\r\n");
- JPEGIMAGE _jpeg;
- memset(&_jpeg, 0, sizeof(JPEGIMAGE));
- _jpeg.ucMemType = JPEG_MEM_RAM;
- _jpeg.pfnRead = readRAM;
- _jpeg.pfnSeek = seekMem;
- _jpeg.pfnDraw = getImage;
- _jpeg.pfnOpen = NULL;
- _jpeg.pfnClose = NULL;
- _jpeg.JPEGFile.iSize = iDataSize;
- _jpeg.JPEGFile.pData = _pdata;
- _jpeg.iMaxMCUs = 1000; // set to an unnaturally high value to start
- if(JPEGInit(&_jpeg))
- printf("[DEC] OK init\r\n");
- else {
- printf("[DEC] FAILED init\r\n");
- return DEC_EINI;
- }
- // printf("Image size: %d x %d, orientation: %d, bpp: %d\r\n", _jpeg.iWidth,
- // _jpeg.iHeight, (int)_jpeg.ucOrientation, (int)_jpeg.ucBpp);
- _jpeg.iXOffset = x;
- _jpeg.iYOffset = y;
- _jpeg.iOptions = iOptions;
- //START_AGAIN:
- if(DecodeJPEG(&_jpeg)){
- printf("[DEC] OK decode\r\n");
- return DEC_ENON;
- }
- else{
- printf("[DEC] FAILED decode\r\n");
- // goto START_AGAIN;
- return DEC_EDEC;
- }
- // printf("dump memory D:\\temp %p %p \r\n", dst_image, (uint8_t*)dst_image + (120*160*3));
- // resize_image(dst_image, resized_image, 160, 120, 50, 50);
- // printf("%p\r\n", resized_image);
- // printf("Done\r\n");
- }
- //
- // Range clip and shift for RGB565 output
- // input value is 0 to 255, then another 256 for overflow to FF, then 512 more for negative values wrapping around
- // Trims a few instructions off the final output stage
- //
- static const uint8_t ucRangeTable[] = {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
- 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
- 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
- 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
- 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
- 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
- 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
- 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
- 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
- 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
- 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
- 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
- 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
- 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f};
- //
- // Convert 8-bit grayscale into RGB565
- //
- static const uint16_t usGrayTo565[] = {0x0000,0x0000,0x0000,0x0000,0x0020,0x0020,0x0020,0x0020, // 0
- 0x0841,0x0841,0x0841,0x0841,0x0861,0x0861,0x0861,0x0861,
- 0x1082,0x1082,0x1082,0x1082,0x10a2,0x10a2,0x10a2,0x10a2,
- 0x18c3,0x18c3,0x18c3,0x18c3,0x18e3,0x18e3,0x18e3,0x18e3,
- 0x2104,0x2104,0x2104,0x2104,0x2124,0x2124,0x2124,0x2124,
- 0x2945,0x2945,0x2945,0x2945,0x2965,0x2965,0x2965,0x2965,
- 0x3186,0x3186,0x3186,0x3186,0x31a6,0x31a6,0x31a6,0x31a6,
- 0x39c7,0x39c7,0x39c7,0x39c7,0x39e7,0x39e7,0x39e7,0x39e7,
- 0x4208,0x4208,0x4208,0x4208,0x4228,0x4228,0x4228,0x4228,
- 0x4a49,0x4a49,0x4a49,0x4a49,0x4a69,0x4a69,0x4a69,0x4a69,
- 0x528a,0x528a,0x528a,0x528a,0x52aa,0x52aa,0x52aa,0x52aa,
- 0x5acb,0x5acb,0x5acb,0x5acb,0x5aeb,0x5aeb,0x5aeb,0x5aeb,
- 0x630c,0x630c,0x630c,0x630c,0x632c,0x632c,0x632c,0x632c,
- 0x6b4d,0x6b4d,0x6b4d,0x6b4d,0x6b6d,0x6b6d,0x6b6d,0x6b6d,
- 0x738e,0x738e,0x738e,0x738e,0x73ae,0x73ae,0x73ae,0x73ae,
- 0x7bcf,0x7bcf,0x7bcf,0x7bcf,0x7bef,0x7bef,0x7bef,0x7bef,
- 0x8410,0x8410,0x8410,0x8410,0x8430,0x8430,0x8430,0x8430,
- 0x8c51,0x8c51,0x8c51,0x8c51,0x8c71,0x8c71,0x8c71,0x8c71,
- 0x9492,0x9492,0x9492,0x9492,0x94b2,0x94b2,0x94b2,0x94b2,
- 0x9cd3,0x9cd3,0x9cd3,0x9cd3,0x9cf3,0x9cf3,0x9cf3,0x9cf3,
- 0xa514,0xa514,0xa514,0xa514,0xa534,0xa534,0xa534,0xa534,
- 0xad55,0xad55,0xad55,0xad55,0xad75,0xad75,0xad75,0xad75,
- 0xb596,0xb596,0xb596,0xb596,0xb5b6,0xb5b6,0xb5b6,0xb5b6,
- 0xbdd7,0xbdd7,0xbdd7,0xbdd7,0xbdf7,0xbdf7,0xbdf7,0xbdf7,
- 0xc618,0xc618,0xc618,0xc618,0xc638,0xc638,0xc638,0xc638,
- 0xce59,0xce59,0xce59,0xce59,0xce79,0xce79,0xce79,0xce79,
- 0xd69a,0xd69a,0xd69a,0xd69a,0xd6ba,0xd6ba,0xd6ba,0xd6ba,
- 0xdedb,0xdedb,0xdedb,0xdedb,0xdefb,0xdefb,0xdefb,0xdefb,
- 0xe71c,0xe71c,0xe71c,0xe71c,0xe73c,0xe73c,0xe73c,0xe73c,
- 0xef5d,0xef5d,0xef5d,0xef5d,0xef7d,0xef7d,0xef7d,0xef7d,
- 0xf79e,0xf79e,0xf79e,0xf79e,0xf7be,0xf7be,0xf7be,0xf7be,
- 0xffdf,0xffdf,0xffdf,0xffdf,0xffff,0xffff,0xffff,0xffff};
- //
- // Clip and convert red value into 5-bits for RGB565
- //
- static const uint16_t usRangeTableR[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 0
- 0x0800,0x0800,0x0800,0x0800,0x0800,0x0800,0x0800,0x0800,
- 0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,0x1000,
- 0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,0x1800,
- 0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,
- 0x2800,0x2800,0x2800,0x2800,0x2800,0x2800,0x2800,0x2800,
- 0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,
- 0x3800,0x3800,0x3800,0x3800,0x3800,0x3800,0x3800,0x3800,
- 0x4000,0x4000,0x4000,0x4000,0x4000,0x4000,0x4000,0x4000,
- 0x4800,0x4800,0x4800,0x4800,0x4800,0x4800,0x4800,0x4800,
- 0x5000,0x5000,0x5000,0x5000,0x5000,0x5000,0x5000,0x5000,
- 0x5800,0x5800,0x5800,0x5800,0x5800,0x5800,0x5800,0x5800,
- 0x6000,0x6000,0x6000,0x6000,0x6000,0x6000,0x6000,0x6000,
- 0x6800,0x6800,0x6800,0x6800,0x6800,0x6800,0x6800,0x6800,
- 0x7000,0x7000,0x7000,0x7000,0x7000,0x7000,0x7000,0x7000,
- 0x7800,0x7800,0x7800,0x7800,0x7800,0x7800,0x7800,0x7800,
- 0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,
- 0x8800,0x8800,0x8800,0x8800,0x8800,0x8800,0x8800,0x8800,
- 0x9000,0x9000,0x9000,0x9000,0x9000,0x9000,0x9000,0x9000,
- 0x9800,0x9800,0x9800,0x9800,0x9800,0x9800,0x9800,0x9800,
- 0xa000,0xa000,0xa000,0xa000,0xa000,0xa000,0xa000,0xa000,
- 0xa800,0xa800,0xa800,0xa800,0xa800,0xa800,0xa800,0xa800,
- 0xb000,0xb000,0xb000,0xb000,0xb000,0xb000,0xb000,0xb000,
- 0xb800,0xb800,0xb800,0xb800,0xb800,0xb800,0xb800,0xb800,
- 0xc000,0xc000,0xc000,0xc000,0xc000,0xc000,0xc000,0xc000,
- 0xc800,0xc800,0xc800,0xc800,0xc800,0xc800,0xc800,0xc800,
- 0xd000,0xd000,0xd000,0xd000,0xd000,0xd000,0xd000,0xd000,
- 0xd800,0xd800,0xd800,0xd800,0xd800,0xd800,0xd800,0xd800,
- 0xe000,0xe000,0xe000,0xe000,0xe000,0xe000,0xe000,0xe000,
- 0xe800,0xe800,0xe800,0xe800,0xe800,0xe800,0xe800,0xe800,
- 0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,0xf000,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800, // 256
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 512
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 768
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- //
- // Clip and convert green value into 5-bits for RGB565
- //
- static const uint16_t usRangeTableG[] = {0x0000,0x0000,0x0000,0x0000,0x0020,0x0020,0x0020,0x0020, // 0
- 0x0040,0x0040,0x0040,0x0040,0x0060,0x0060,0x0060,0x0060,
- 0x0080,0x0080,0x0080,0x0080,0x00a0,0x00a0,0x00a0,0x00a0,
- 0x00c0,0x00c0,0x00c0,0x00c0,0x00e0,0x00e0,0x00e0,0x00e0,
- 0x0100,0x0100,0x0100,0x0100,0x0120,0x0120,0x0120,0x0120,
- 0x0140,0x0140,0x0140,0x0140,0x0160,0x0160,0x0160,0x0160,
- 0x0180,0x0180,0x0180,0x0180,0x01a0,0x01a0,0x01a0,0x01a0,
- 0x01c0,0x01c0,0x01c0,0x01c0,0x01e0,0x01e0,0x01e0,0x01e0,
- 0x0200,0x0200,0x0200,0x0200,0x0220,0x0220,0x0220,0x0220,
- 0x0240,0x0240,0x0240,0x0240,0x0260,0x0260,0x0260,0x0260,
- 0x0280,0x0280,0x0280,0x0280,0x02a0,0x02a0,0x02a0,0x02a0,
- 0x02c0,0x02c0,0x02c0,0x02c0,0x02e0,0x02e0,0x02e0,0x02e0,
- 0x0300,0x0300,0x0300,0x0300,0x0320,0x0320,0x0320,0x0320,
- 0x0340,0x0340,0x0340,0x0340,0x0360,0x0360,0x0360,0x0360,
- 0x0380,0x0380,0x0380,0x0380,0x03a0,0x03a0,0x03a0,0x03a0,
- 0x03c0,0x03c0,0x03c0,0x03c0,0x03e0,0x03e0,0x03e0,0x03e0,
- 0x0400,0x0400,0x0400,0x0400,0x0420,0x0420,0x0420,0x0420,
- 0x0440,0x0440,0x0440,0x0440,0x0460,0x0460,0x0460,0x0460,
- 0x0480,0x0480,0x0480,0x0480,0x04a0,0x04a0,0x04a0,0x04a0,
- 0x04c0,0x04c0,0x04c0,0x04c0,0x04e0,0x04e0,0x04e0,0x04e0,
- 0x0500,0x0500,0x0500,0x0500,0x0520,0x0520,0x0520,0x0520,
- 0x0540,0x0540,0x0540,0x0540,0x0560,0x0560,0x0560,0x0560,
- 0x0580,0x0580,0x0580,0x0580,0x05a0,0x05a0,0x05a0,0x05a0,
- 0x05c0,0x05c0,0x05c0,0x05c0,0x05e0,0x05e0,0x05e0,0x05e0,
- 0x0600,0x0600,0x0600,0x0600,0x0620,0x0620,0x0620,0x0620,
- 0x0640,0x0640,0x0640,0x0640,0x0660,0x0660,0x0660,0x0660,
- 0x0680,0x0680,0x0680,0x0680,0x06a0,0x06a0,0x06a0,0x06a0,
- 0x06c0,0x06c0,0x06c0,0x06c0,0x06e0,0x06e0,0x06e0,0x06e0,
- 0x0700,0x0700,0x0700,0x0700,0x0720,0x0720,0x0720,0x0720,
- 0x0740,0x0740,0x0740,0x0740,0x0760,0x0760,0x0760,0x0760,
- 0x0780,0x0780,0x0780,0x0780,0x07a0,0x07a0,0x07a0,0x07a0,
- 0x07c0,0x07c0,0x07c0,0x07c0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0, // 256
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,0x07e0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 512
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 768
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- //
- // Clip and convert blue value into 5-bits for RGB565
- //
- static const uint16_t usRangeTableB[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // 0
- 0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
- 0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
- 0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,
- 0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,
- 0x0005,0x0005,0x0005,0x0005,0x0005,0x0005,0x0005,0x0005,
- 0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,
- 0x0007,0x0007,0x0007,0x0007,0x0007,0x0007,0x0007,0x0007,
- 0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,
- 0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,
- 0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,
- 0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,
- 0x000c,0x000c,0x000c,0x000c,0x000c,0x000c,0x000c,0x000c,
- 0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,0x000d,
- 0x000e,0x000e,0x000e,0x000e,0x000e,0x000e,0x000e,0x000e,
- 0x000f,0x000f,0x000f,0x000f,0x000f,0x000f,0x000f,0x000f,
- 0x0010,0x0010,0x0010,0x0010,0x0010,0x0010,0x0010,0x0010,
- 0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,0x0011,
- 0x0012,0x0012,0x0012,0x0012,0x0012,0x0012,0x0012,0x0012,
- 0x0013,0x0013,0x0013,0x0013,0x0013,0x0013,0x0013,0x0013,
- 0x0014,0x0014,0x0014,0x0014,0x0014,0x0014,0x0014,0x0014,
- 0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,0x0015,
- 0x0016,0x0016,0x0016,0x0016,0x0016,0x0016,0x0016,0x0016,
- 0x0017,0x0017,0x0017,0x0017,0x0017,0x0017,0x0017,0x0017,
- 0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,0x0018,
- 0x0019,0x0019,0x0019,0x0019,0x0019,0x0019,0x0019,0x0019,
- 0x001a,0x001a,0x001a,0x001a,0x001a,0x001a,0x001a,0x001a,
- 0x001b,0x001b,0x001b,0x001b,0x001b,0x001b,0x001b,0x001b,
- 0x001c,0x001c,0x001c,0x001c,0x001c,0x001c,0x001c,0x001c,
- 0x001d,0x001d,0x001d,0x001d,0x001d,0x001d,0x001d,0x001d,
- 0x001e,0x001e,0x001e,0x001e,0x001e,0x001e,0x001e,0x001e,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f, // 256
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,0x001f,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 512
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 768
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- #if defined (__MACH__) || defined( __LINUX__ ) || defined( __MCUXPRESSO )
- //
- // API for C
- //
- //
- // Memory initialization
- //
- int JPEG_openRAM(JPEGIMAGE *pJPEG, uint8_t *pData, int iDataSize, JPEG_DRAW_CALLBACK *pfnDraw)
- {
- memset(pJPEG, 0, sizeof(JPEGIMAGE));
- pJPEG->ucMemType = JPEG_MEM_RAM;
- pJPEG->pfnRead = readRAM;
- pJPEG->pfnSeek = seekMem;
- pJPEG->pfnDraw = pfnDraw;
- pJPEG->pfnOpen = NULL;
- pJPEG->pfnClose = NULL;
- pJPEG->JPEGFile.iSize = iDataSize;
- pJPEG->JPEGFile.pData = pData;
- pJPEG->iMaxMCUs = 1000; // set to an unnaturally high value to start
- return JPEGInit(pJPEG);
- } /* JPEG_openRAM() */
- //
- // File initialization
- //
- int JPEG_openFile(JPEGIMAGE *pJPEG, const char *szFilename, JPEG_DRAW_CALLBACK *pfnDraw)
- {
- memset(pJPEG, 0, sizeof(JPEGIMAGE));
- pJPEG->ucMemType = JPEG_MEM_RAM;
- pJPEG->pfnRead = readFile;
- pJPEG->pfnSeek = seekFile;
- pJPEG->pfnDraw = pfnDraw;
- pJPEG->pfnOpen = NULL;
- pJPEG->pfnClose = closeFile;
- pJPEG->iMaxMCUs = 1000; // set to an unnaturally high value to start
- pJPEG->JPEGFile.fHandle = fopen(szFilename, "r+b");
- if (pJPEG->JPEGFile.fHandle == NULL)
- return 0;
- fseek((FILE *)pJPEG->JPEGFile.fHandle, 0, SEEK_END);
- pJPEG->JPEGFile.iSize = (int)ftell((FILE *)pJPEG->JPEGFile.fHandle);
- fseek((FILE *)pJPEG->JPEGFile.fHandle, 0, SEEK_SET);
- return JPEGInit(pJPEG);
- } /* JPEG_openFile() */
- int JPEG_getLastError(JPEGIMAGE *pJPEG)
- {
- return pJPEG->iError;
- } /* JPEG_getLastError() */
- int JPEG_getWidth(JPEGIMAGE *pJPEG)
- {
- return pJPEG->iWidth;
- } /* JPEG_getWidth() */
- int JPEG_getHeight(JPEGIMAGE *pJPEG)
- {
- return pJPEG->iHeight;
- } /* JPEG_getHeight() */
- int JPEG_getOrientation(JPEGIMAGE *pJPEG)
- {
- return (int)pJPEG->ucOrientation;
- } /* JPEG_getOrientation() */
- int JPEG_getBpp(JPEGIMAGE *pJPEG)
- {
- return (int)pJPEG->ucBpp;
- } /* JPEG_getBpp() */
- int JPEG_getSubSample(JPEGIMAGE *pJPEG)
- {
- return (int)pJPEG->ucSubSample;
- } /* JPEG_getSubSample() */
- int JPEG_hasThumb(JPEGIMAGE *pJPEG)
- {
- return (int)pJPEG->ucHasThumb;
- } /* JPEG_hasThumb() */
- int JPEG_getThumbWidth(JPEGIMAGE *pJPEG)
- {
- return pJPEG->iThumbWidth;
- } /* JPEG_getThumbWidth() */
- int JPEG_getThumbHeight(JPEGIMAGE *pJPEG)
- {
- return pJPEG->iThumbHeight;
- } /* JPEG_getThumbHeight() */
- void JPEG_setPixelType(JPEGIMAGE *pJPEG, int iType)
- {
- pJPEG->ucPixelType = (uint8_t)iType;
- } /* JPEG_setPixelType() */
- void JPEG_setMaxOutputSize(JPEGIMAGE *pJPEG, int iMaxMCUs)
- {
- if (iMaxMCUs < 1)
- iMaxMCUs = 1; // don't allow invalid value
- pJPEG->iMaxMCUs = iMaxMCUs;
- } /* JPEG_setMaxOutputSize() */
- int JPEG_decode(JPEGIMAGE *pJPEG, int x, int y, int iOptions)
- {
- pJPEG->iXOffset = x;
- pJPEG->iYOffset = y;
- pJPEG->iOptions = iOptions;
- return DecodeJPEG(pJPEG);
- } /* JPEG_decode() */
- int JPEG_decodeDither(JPEGIMAGE *pJPEG, uint8_t *pDither, int iOptions)
- {
- pJPEG->iOptions = iOptions;
- pJPEG->pDitherBuffer = pDither;
- return DecodeJPEG(pJPEG);
- } /* JPEG_decodeDither() */
- void JPEG_close(JPEGIMAGE *pJPEG)
- {
- if (pJPEG->pfnClose)
- (*pJPEG->pfnClose)(pJPEG->JPEGFile.fHandle);
- } /* JPEG_close() */
- #endif // !__cplusplus
- //
- // Helper functions for memory based images
- //
- static int32_t readRAM(JPEGFILE *pFile, uint8_t *pBuf, int32_t iLen)
- {
- int32_t iBytesRead;
- iBytesRead = iLen;
- if ((pFile->iSize - pFile->iPos) < iLen)
- iBytesRead = pFile->iSize - pFile->iPos;
- if (iBytesRead <= 0)
- return 0;
- memcpy(pBuf, &pFile->pData[pFile->iPos], iBytesRead);
- pFile->iPos += iBytesRead;
- return iBytesRead;
- } /* readRAM() */
- static int32_t seekMem(JPEGFILE *pFile, int32_t iPosition)
- {
- if (iPosition < 0) iPosition = 0;
- else if (iPosition >= pFile->iSize) iPosition = pFile->iSize-1;
- pFile->iPos = iPosition;
- return iPosition;
- } /* seekMem() */
- #if defined (__MACH__) || defined( __LINUX__ ) || defined( __MCUXPRESSO )
- static void closeFile(void *handle)
- {
- fclose((FILE *)handle);
- } /* closeFile() */
- static int32_t seekFile(JPEGFILE *pFile, int32_t iPosition)
- {
- if (iPosition < 0) iPosition = 0;
- else if (iPosition >= pFile->iSize) iPosition = pFile->iSize-1;
- pFile->iPos = iPosition;
- fseek((FILE *)pFile->fHandle, iPosition, SEEK_SET);
- return iPosition;
- } /* seekFile() */
- static int32_t readFile(JPEGFILE *pFile, uint8_t *pBuf, int32_t iLen)
- {
- int32_t iBytesRead;
- iBytesRead = iLen;
- if ((pFile->iSize - pFile->iPos) < iLen)
- iBytesRead = pFile->iSize - pFile->iPos;
- if (iBytesRead <= 0)
- return 0;
- iBytesRead = (int)fread(pBuf, 1, iBytesRead, (FILE *)pFile->fHandle);
- pFile->iPos += iBytesRead;
- return iBytesRead;
- } /* readFile() */
- #endif // __LINUX__
- //
- // The following functions are written in plain C and have no
- // 3rd party dependencies, not even the C runtime library
- //
- //
- // Initialize a JPEG file and callback access from a file on SD or memory
- // returns 1 for success, 0 for failure
- // Fills in the basic image info fields of the JPEGIMAGE structure
- //
- static int JPEGInit(JPEGIMAGE *pJPEG)
- {
- return JPEGParseInfo(pJPEG, 0); // gather info for image
- } /* JPEGInit() */
- //
- // Unpack the Huffman tables
- //
- static int JPEGGetHuffTables(uint8_t *pBuf, int iLen, JPEGIMAGE *pJPEG)
- {
- int i, j, iOffset, iTableOffset;
- uint8_t ucTable, *pHuffVals;
- iOffset = 0;
- pHuffVals = (uint8_t *)pJPEG->usPixels; // temp holding area to save RAM
- while (iLen > 17) // while there are tables to copy (we may have combined more than 1 table together)
- {
- ucTable = pBuf[iOffset++]; // get table index
- if (ucTable & 0x10) // convert AC offset of 0x10 into offset of 4
- ucTable ^= 0x14;
- pJPEG->ucHuffTableUsed |= (1 << ucTable); // mark this table as being defined
- if (ucTable <= 7) // tables are 0-3, AC+DC
- {
- iTableOffset = ucTable * HUFF_TABLEN;
- j = 0; // total bits
- for (i=0; i<16; i++)
- {
- j += pBuf[iOffset];
- pHuffVals[iTableOffset+i] = pBuf[iOffset++];
- }
- iLen -= 17; // subtract length of bit lengths
- if (j == 0 || j > 256 || j > iLen) // bogus bit lengths
- {
- return -1;
- }
- iTableOffset += 16;
- for (i=0; i<j; i++)
- { // copy huffman table
- pHuffVals[iTableOffset+i] = pBuf[iOffset++];
- }
- iLen -= j;
- }
- }
- return 0;
- } /* JPEGGetHuffTables() */
- #ifdef FUTURE
- //
- // Create 11-bit lookup tables for some images where it doesn't work
- // for 10-bit tables
- //
- static int JPEGMakeHuffTables_Slow(JPEGIMAGE *pJPEG, int bThumbnail)
- {
- int code, repeat, count, codestart;
- int j;
- int iLen, iTable;
- unsigned short *pTable, *pShort, *pLong;
- unsigned char *pucTable, *pucShort, *pucLong;
- uint32_t ul, *pLongTable;
- int iBitNum; // current code bit length
- int cc; // code
- unsigned char *p, *pBits, ucCode;
- int iMaxLength, iMaxMask;
- pJPEG->b11Bit = 1; // indicate we're using the bigger A/C decode tables
- // first do DC components (up to 4 tables of 12-bit codes)
- // we can save time and memory for the DC codes by knowing that there exist short codes (<= 6 bits)
- // and long codes (>6 bits, but the first 5 bits are 1's). This allows us to create 2 tables: a 6-bit and 7 or 8-bit
- // to handle any DC codes
- iMaxLength = 12; // assume DC codes can be 12-bits
- iMaxMask = 0x7f; // lower 7 bits after truncate 5 leading 1's
- if (pJPEG->ucMode == 0xc3) // create 13-bit tables for lossless mode
- {
- iMaxLength = 13;
- iMaxMask = 0xff;
- }
- for (iTable = 0; iTable < 2; iTable++)
- {
- if (pJPEG->ucHuffTableUsed & (1<<iTable))
- {
- // pJPEG->huffdcFast[iTable] = (int *)PILIOAlloc(0x180); // short table = 128 bytes, long table = 256 bytes
- pucShort = (unsigned char *)&pJPEG->ucHuffDC[iTable*DC_TABLE_SIZE];
- // pJPEG->huffdc[iTable] = pJPEG->huffdcFast[iTable] + 0x20; // 0x20 longs = 128 bytes
- pucLong = (unsigned char *)&pJPEG->ucHuffDC[iTable*DC_TABLE_SIZE + 128];
- pBits = &pJPEG->ucHuffVals[iTable * HUFF_TABLEN];
- p = pBits;
- p += 16; // point to bit data
- cc = 0; // start with a code of 0
- for (iBitNum = 1; iBitNum <= 16; iBitNum++)
- {
- iLen = *pBits++; // get number of codes for this bit length
- if (iBitNum > iMaxLength && iLen > 0) // we can't handle codes longer a certain length
- {
- return -1;
- }
- while (iLen)
- {
- // if (iBitNum > 6) // do long table
- if ((cc >> (iBitNum-5)) == 0x1f) // first 5 bits are 1 - use long table
- {
- count = iMaxLength - iBitNum;
- codestart = cc << count;
- pucTable = &pucLong[codestart & iMaxMask]; // use lower 7/8 bits of code
- }
- else // do short table
- {
- count = 6 - iBitNum;
- if (count < 0)
- return -1; // DEBUG - something went wrong
- codestart = cc << count;
- pucTable = &pucShort[codestart];
- }
- ucCode = *p++; // get actual huffman code
- if (ucCode == 16 && pJPEG->ucMode == 0xc3) // lossless mode
- {
- // in lossless mode, this code won't fit in 4 bits, so save it's length in the next slot
- ucCode = 255;
- pucLong[256] = (unsigned char)iBitNum;
- }
- // does precalculating the DC value save time on ARM?
- #ifndef USE_ARM_ASM
- if (ucCode != 0 && (ucCode + iBitNum) <= 6 && pJPEG->ucMode != 0xc2) // we can fit the magnitude value in the code lookup (not for progressive)
- {
- int k, iLoop;
- unsigned char ucCoeff;
- unsigned char *d = &pucTable[512];
- unsigned char ucMag = ucCode;
- ucCode |= ((iBitNum+ucCode) << 4); // add magnitude bits to length
- repeat = 1<<ucMag;
- iLoop = 1<<(count-ucMag);
- for (j=0; j<repeat; j++)
- { // calcuate the magnitude coeff already
- if (j & 1<<(ucMag-1)) // positive number
- ucCoeff = (unsigned char)j;
- else // negative number
- ucCoeff = (unsigned char)(j - ((1<<ucMag)-1));
- for (k=0; k<iLoop; k++)
- {
- *d++ = ucCoeff;
- } // for k
- } // for j
- }
- #endif
- else
- {
- ucCode |= (iBitNum << 4);
- }
- if (count) // do it as dwords to save time
- {
- repeat = (1<<count);
- memset(pucTable, ucCode, repeat);
- // pLongTable = (uint32_t *)pTable;
- // repeat = 1 << (count-2); // store as dwords (/4)
- // ul = code | (code << 16);
- // for (j=0; j<repeat; j++)
- // *pLongTable++ = ul;
- }
- else
- {
- pucTable[0] = ucCode;
- }
- cc++;
- iLen--;
- }
- cc <<= 1;
- }
- } // if table defined
- }
- // now do AC components (up to 2 tables of 16-bit codes)
- // We split the codes into a short table (9 bits or less) and a long table (first 5 bits are 1)
- for (iTable = 0; iTable < 2; iTable++)
- {
- if (pJPEG->ucHuffTableUsed & (1<<(iTable+4))) // if this table is defined
- {
- pBits = &pJPEG->ucHuffVals[(iTable+4) * HUFF_TABLEN];
- p = pBits;
- p += 16; // point to bit data
- pShort = &pJPEG->usHuffAC[iTable*HUFF11SIZE];
- pLong = &pJPEG->usHuffAC[iTable*HUFF11SIZE + 1024]; // long codes start here
- cc = 0; // start with a code of 0
- // construct the decode table
- for (iBitNum = 1; iBitNum <= 16; iBitNum++)
- {
- iLen = *pBits++; // get number of codes for this bit length
- while (iLen)
- {
- if ((cc >> (iBitNum-4)) == 0xf) // first 4 bits are 1 - use long table
- {
- count = 16 - iBitNum;
- codestart = cc << count;
- pTable = &pLong[codestart & 0xfff]; // use lower 12 bits of code
- }
- else
- {
- count = 12 - iBitNum;
- if (count < 0) // a 13-bit? code - that doesn't fit our optimized scheme, see if we can do a bigger table version
- {
- return -1; // DEBUG - fatal error, we currently don't support it
- }
- codestart = cc << count;
- pTable = &pShort[codestart]; // 11 bits or shorter
- }
- code = *p++; // get actual huffman code
- if (bThumbnail && code != 0) // add "extra" bits to code length since we skip these codes
- {
- // get rid of extra bits in code and add increment (1) for AC index
- code = ((iBitNum+(code & 0xf)) << 8) | ((code >> 4)+1);
- }
- else
- {
- code |= (iBitNum << 8);
- }
- if (count) // do it as dwords to save time
- {
- repeat = 1 << (count-1); // store as dwords (/2)
- ul = code | (code << 16);
- pLongTable = (uint32_t *)pTable;
- for (j=0; j<repeat; j++)
- *pLongTable++ = ul;
- }
- else
- {
- pTable[0] = (unsigned short)code;
- }
- cc++;
- iLen--;
- }
- cc <<= 1;
- } // for each bit length
- } // if table defined
- }
- return 0;
- } /* JPEGMakeHuffTables_Slow() */
- #endif // FUTURE
- //
- // Expand the Huffman tables for fast decoding
- // returns 1 for success, 0 for failure
- //
- static int JPEGMakeHuffTables(JPEGIMAGE *pJPEG, int bThumbnail)
- {
- int code, repeat, count, codestart;
- int j;
- int iLen, iTable;
- uint16_t *pTable, *pShort, *pLong;
- uint8_t *pHuffVals, *pucTable, *pucShort, *pucLong;
- uint32_t ul, *pLongTable;
- int iBitNum; // current code bit length
- int cc; // code
- uint8_t *p, *pBits, ucCode;
- int iMaxLength, iMaxMask;
- int iTablesUsed;
- iTablesUsed = 0;
- pHuffVals = (uint8_t *)pJPEG->usPixels;
- for (j=0; j<4; j++)
- {
- if (pJPEG->ucHuffTableUsed & (1 << j))
- iTablesUsed++;
- }
- // first do DC components (up to 4 tables of 12-bit codes)
- // we can save time and memory for the DC codes by knowing that there exist short codes (<= 6 bits)
- // and long codes (>6 bits, but the first 5 bits are 1's). This allows us to create 2 tables: a 6-bit and 7 or 8-bit
- // to handle any DC codes
- iMaxLength = 12; // assume DC codes can be 12-bits
- iMaxMask = 0x7f; // lower 7 bits after truncate 5 leading 1's
- for (iTable = 0; iTable < 4; iTable++)
- {
- if (pJPEG->ucHuffTableUsed & (1 << iTable))
- {
- // pJPEG->huffdcFast[iTable] = (int *)PILIOAlloc(0x180); // short table = 128 bytes, long table = 256 bytes
- pucShort = &pJPEG->ucHuffDC[iTable*DC_TABLE_SIZE];
- // pJPEG->huffdc[iTable] = pJPEG->huffdcFast[iTable] + 0x20; // 0x20 longs = 128 bytes
- pucLong = &pJPEG->ucHuffDC[iTable*DC_TABLE_SIZE + 128];
- pBits = &pHuffVals[iTable * HUFF_TABLEN];
- p = pBits;
- p += 16; // point to bit data
- cc = 0; // start with a code of 0
- for (iBitNum = 1; iBitNum <= 16; iBitNum++)
- {
- iLen = *pBits++; // get number of codes for this bit length
- if (iBitNum > iMaxLength && iLen > 0) // we can't handle codes longer a certain length
- {
- return 0;
- }
- while (iLen)
- {
- // if (iBitNum > 6) // do long table
- if ((cc >> (iBitNum-5)) == 0x1f) // first 5 bits are 1 - use long table
- {
- count = iMaxLength - iBitNum;
- codestart = cc << count;
- pucTable = &pucLong[codestart & iMaxMask]; // use lower 7/8 bits of code
- }
- else // do short table
- {
- count = 6 - iBitNum;
- if (count < 0)
- return 0; // DEBUG - something went wrong
- codestart = cc << count;
- pucTable = &pucShort[codestart];
- }
- ucCode = *p++; // get actual huffman code
- // does precalculating the DC value save time on ARM?
- #ifndef USE_ARM_ASM
- if (ucCode != 0 && (ucCode + iBitNum) <= 6 && pJPEG->ucMode != 0xc2) // we can fit the magnitude value in the code lookup (not for progressive)
- {
- int k, iLoop;
- unsigned char ucCoeff;
- unsigned char *d = &pucTable[512];
- unsigned char ucMag = ucCode;
- ucCode |= ((iBitNum+ucCode) << 4); // add magnitude bits to length
- repeat = 1<<ucMag;
- iLoop = 1<<(count-ucMag);
- for (j=0; j<repeat; j++)
- { // calcuate the magnitude coeff already
- if (j & 1<<(ucMag-1)) // positive number
- ucCoeff = (unsigned char)j;
- else // negative number
- ucCoeff = (unsigned char)(j - ((1<<ucMag)-1));
- for (k=0; k<iLoop; k++)
- {
- *d++ = ucCoeff;
- } // for k
- } // for j
- }
- #endif
- else
- {
- ucCode |= (iBitNum << 4);
- }
- if (count) // do it as dwords to save time
- {
- repeat = (1<<count);
- memset(pucTable, ucCode, repeat);
- // pLongTable = (uint32_t *)pTable;
- // repeat = 1 << (count-2); // store as dwords (/4)
- // ul = code | (code << 16);
- // for (j=0; j<repeat; j++)
- // *pLongTable++ = ul;
- }
- else
- {
- pucTable[0] = ucCode;
- }
- cc++;
- iLen--;
- }
- cc <<= 1;
- }
- } // if table defined
- }
- // now do AC components (up to 4 tables of 16-bit codes)
- // We split the codes into a short table (9 bits or less) and a long table (first 5 bits are 1)
- for (iTable = 0; iTable < 4; iTable++)
- {
- if (pJPEG->ucHuffTableUsed & (1 << (iTable+4))) // if this table is defined
- {
- pBits = &pHuffVals[(iTable+4) * HUFF_TABLEN];
- p = pBits;
- p += 16; // point to bit data
- pShort = &pJPEG->usHuffAC[iTable*HUFF11SIZE];
- pLong = &pJPEG->usHuffAC[iTable*HUFF11SIZE + 1024];
- cc = 0; // start with a code of 0
- // construct the decode table
- for (iBitNum = 1; iBitNum <= 16; iBitNum++)
- {
- iLen = *pBits++; // get number of codes for this bit length
- while (iLen)
- {
- if ((cc >> (iBitNum-6)) == 0x3f) // first 6 bits are 1 - use long table
- {
- count = 16 - iBitNum;
- codestart = cc << count;
- pTable = &pLong[codestart & 0x3ff]; // use lower 10 bits of code
- }
- else
- {
- count = 10 - iBitNum;
- if (count < 0) // an 11/12-bit? code - that doesn't fit our optimized scheme, see if we can do a bigger table version
- {
- if (count == -1 && iTablesUsed <= 4) // we need to create "slow" tables
- { // DEBUG
- // j = JPEGMakeHuffTables_Slow(pJPEG, bThumbnail);
- return 0;
- }
- else
- return 0; // DEBUG - fatal error, more than 2 big tables we currently don't support
- }
- codestart = cc << count;
- pTable = &pShort[codestart]; // 10 bits or shorter
- }
- code = *p++; // get actual huffman code
- if (bThumbnail && code != 0) // add "extra" bits to code length since we skip these codes
- {
- // get rid of extra bits in code and add increment (1) for AC index
- code = ((iBitNum+(code & 0xf)) << 8) | ((code >> 4)+1);
- }
- #ifdef BOGUS // precalculating the AC coeff makes it run slightly slower
- else if ((code & 0xf) != 0 && (code + iBitNum) <= 10) // we can fit the magnitude value + huffman code in a single read
- {
- int k, iLoop;
- unsigned short usCoeff;
- unsigned short *d = &pTable[4096]; // use unused table slots 2+3 for extra coeff data
- unsigned char ucMag = (unsigned char)(code & 0xf);
- code |= ((iBitNum + (code & 0xf)) << 8); // add magnitude bits to length
- repeat = 1<<ucMag;
- iLoop = 1<<(count-ucMag);
- for (j=0; j<repeat; j++)
- { // calcuate the magnitude coeff already
- if (j & 1<<(ucMag-1)) // positive number
- usCoeff = (unsigned short)j;
- else // negative number
- usCoeff = (unsigned short)(j - ((1<<ucMag)-1));
- for (k=0; k<iLoop; k++)
- {
- *d++ = usCoeff;
- } // for k
- } // for j
- }
- #endif
- else
- {
- code |= (iBitNum << 8);
- }
- if (count) // do it as dwords to save time
- {
- repeat = 1 << (count-1); // store as dwords (/2)
- ul = code | (code << 16);
- pLongTable = (uint32_t *)pTable;
- for (j=0; j<repeat; j++)
- *pLongTable++ = ul;
- }
- else
- {
- pTable[0] = (unsigned short)code;
- }
- cc++;
- iLen--;
- }
- cc <<= 1;
- } // for each bit length
- } // if table defined
- }
- return 1;
- } /* JPEGMakeHuffTables() */
- //
- // TIFFSHORT
- // read a 16-bit unsigned integer from the given pointer
- // and interpret the data as big endian (Motorola) or little endian (Intel)
- //
- static uint16_t TIFFSHORT(unsigned char *p, int bMotorola)
- {
- unsigned short s;
- if (bMotorola)
- s = *p * 0x100 + *(p+1); // big endian (AKA Motorola byte order)
- else
- s = *p + *(p+1)*0x100; // little endian (AKA Intel byte order)
- return s;
- } /* TIFFSHORT() */
- //
- // TIFFLONG
- // read a 32-bit unsigned integer from the given pointer
- // and interpret the data as big endian (Motorola) or little endian (Intel)
- //
- static uint32_t TIFFLONG(unsigned char *p, int bMotorola)
- {
- uint32_t l;
- if (bMotorola)
- l = *p * 0x1000000 + *(p+1) * 0x10000 + *(p+2) * 0x100 + *(p+3); // big endian
- else
- l = *p + *(p+1) * 0x100 + *(p+2) * 0x10000 + *(p+3) * 0x1000000; // little endian
- return l;
- } /* TIFFLONG() */
- //
- // TIFFVALUE
- // read an integer value encoded in a TIFF TAG (12-byte structure)
- // and interpret the data as big endian (Motorola) or little endian (Intel)
- //
- static int TIFFVALUE(unsigned char *p, int bMotorola)
- {
- int i, iType;
- iType = TIFFSHORT(p+2, bMotorola);
- /* If pointer to a list of items, must be a long */
- if (TIFFSHORT(p+4, bMotorola) > 1)
- {
- iType = 4;
- }
- switch (iType)
- {
- case 3: /* Short */
- i = TIFFSHORT(p+8, bMotorola);
- break;
- case 4: /* Long */
- case 7: // undefined (treat it as a long since it's usually a multibyte buffer)
- i = TIFFLONG(p+8, bMotorola);
- break;
- case 6: // signed byte
- i = (signed char)p[8];
- break;
- case 2: /* ASCII */
- case 5: /* Unsigned Rational */
- case 10: /* Signed Rational */
- i = TIFFLONG(p+8, bMotorola);
- break;
- default: /* to suppress compiler warning */
- i = 0;
- break;
- }
- return i;
- } /* TIFFVALUE() */
- static void GetTIFFInfo(JPEGIMAGE *pPage, int bMotorola, int iOffset)
- {
- int iTag, iTagCount, i;
- uint8_t *cBuf = pPage->ucFileBuf;
- iTagCount = TIFFSHORT(&cBuf[iOffset], bMotorola); /* Number of tags in this dir */
- if (iTagCount < 1 || iTagCount > 256) // invalid tag count
- return; /* Bad header info */
- /*--- Search the TIFF tags ---*/
- for (i=0; i<iTagCount; i++)
- {
- unsigned char *p = &cBuf[iOffset + (i*12) +2];
- iTag = TIFFSHORT(p, bMotorola); /* current tag value */
- if (iTag == 274) // orientation tag
- {
- pPage->ucOrientation = TIFFVALUE(p, bMotorola);
- }
- else if (iTag == 256) // width of thumbnail
- {
- pPage->iThumbWidth = TIFFVALUE(p, bMotorola);
- }
- else if (iTag == 257) // height of thumbnail
- {
- pPage->iThumbHeight = TIFFVALUE(p, bMotorola);
- }
- else if (iTag == 513) // offset to JPEG data
- {
- pPage->iThumbData = TIFFVALUE(p, bMotorola);
- }
- }
- } /* GetTIFFInfo() */
- static int JPEGGetSOS(JPEGIMAGE *pJPEG, int *iOff)
- {
- int16_t sLen;
- int iOffset = *iOff;
- int i, j;
- uint8_t uc,c,cc;
- uint8_t *buf = pJPEG->ucFileBuf;
- sLen = MOTOSHORT(&buf[iOffset]);
- iOffset += 2;
- // Assume no components in this scan
- for (i=0; i<4; i++)
- pJPEG->JPCI[i].component_needed = 0;
- uc = buf[iOffset++]; // get number of components
- pJPEG->ucComponentsInScan = uc;
- sLen -= 3;
- if (uc < 1 || uc > MAX_COMPS_IN_SCAN || sLen != (uc*2+3)) // check length of data packet
- return 1; // error
- for (i=0; i<uc; i++)
- {
- cc = buf[iOffset++];
- c = buf[iOffset++];
- sLen -= 2;
- for (j=0; j<4; j++) // search for component id
- {
- if (pJPEG->JPCI[j].component_id == cc)
- break;
- }
- if (j == 4) // error, not found
- return 1;
- if ((c & 0xf) > 3 || (c & 0xf0) > 0x30)
- return 1; // bogus table numbers
- pJPEG->JPCI[j].dc_tbl_no = c >> 4;
- pJPEG->JPCI[j].ac_tbl_no = c & 0xf;
- pJPEG->JPCI[j].component_needed = 1; // mark this component as being included in the scan
- }
- pJPEG->iScanStart = buf[iOffset++]; // Get the scan start (or lossless predictor) for this scan
- pJPEG->iScanEnd = buf[iOffset++]; // Get the scan end for this scan
- c = buf[iOffset++]; // successive approximation bits
- pJPEG->cApproxBitsLow = c & 0xf; // also point transform in lossless mode
- pJPEG->cApproxBitsHigh = c >> 4;
- *iOff = iOffset;
- return 0;
- } /* JPEGGetSOS() */
- //
- // Remove markers from the data stream to allow faster decode
- // Stuffed zeros and restart interval markers aren't needed to properly decode
- // the data, but they make reading VLC data slower, so I pull them out first
- //
- static int JPEGFilter(uint8_t *pBuf, uint8_t *d, int iLen, uint8_t *bFF)
- {
- // since we have the entire jpeg buffer in memory already, we can just change it in place
- unsigned char c, *s, *pEnd, *pStart;
- pStart = d;
- s = pBuf;
- pEnd = &s[iLen-1]; // stop just shy of the end to not miss a final marker/stuffed 0
- if (*bFF) // last byte was a FF, check the next one
- {
- if (s[0] == 0) // stuffed 0, keep the FF
- *d++ = 0xff;
- s++;
- *bFF = 0;
- }
- while (s < pEnd)
- {
- c = *d++ = *s++;
- if (c == 0xff) // marker or stuffed zeros?
- {
- if (s[0] != 0) // it's a marker, skip both
- {
- d--;
- }
- s++; // for stuffed 0's, store the FF, skip the 00
- }
- }
- if (s == pEnd) // need to test the last byte
- {
- c = s[0];
- if (c == 0xff) // last byte is FF, take care of it next time through
- *bFF = 1; // take care of it next time through
- else
- *d++ = c; // nope, just store it
- }
- return (int)(d-pStart); // filtered output length
- } /* JPEGFilter() */
- //
- // Read and filter more VLC data for decoding
- //
- static void JPEGGetMoreData(JPEGIMAGE *pPage)
- {
- int iDelta = pPage->iVLCSize - pPage->iVLCOff;
- // printf("Getting more data...size=%d, off=%d\n", pPage->iVLCSize, pPage->iVLCOff);
- // move any existing data down
- if (iDelta >= (JPEG_FILE_BUF_SIZE-64) || iDelta < 0)
- return; // buffer is already full; no need to read more data
- if (pPage->iVLCOff != 0)
- {
- memcpy(pPage->ucFileBuf, &pPage->ucFileBuf[pPage->iVLCOff], pPage->iVLCSize - pPage->iVLCOff);
- pPage->iVLCSize -= pPage->iVLCOff;
- pPage->iVLCOff = 0;
- pPage->bb.pBuf = pPage->ucFileBuf; // reset VLC source pointer too
- }
- if (pPage->JPEGFile.iPos < pPage->JPEGFile.iSize && pPage->iVLCSize < JPEG_FILE_BUF_SIZE-64)
- {
- int i;
- // Try to read enough to fill the buffer
- i = (*pPage->pfnRead)(&pPage->JPEGFile, &pPage->ucFileBuf[pPage->iVLCSize], JPEG_FILE_BUF_SIZE - pPage->iVLCSize); // max length we can read
- // Filter out the markers
- pPage->iVLCSize += JPEGFilter(&pPage->ucFileBuf[pPage->iVLCSize], &pPage->ucFileBuf[pPage->iVLCSize], i, &pPage->ucFF);
- }
- } /* JPEGGetMoreData() */
- //
- // Parse the JPEG header, gather necessary info to decode the image
- // Returns 1 for success, 0 for failure
- //
- static int JPEGParseInfo(JPEGIMAGE *pPage, int bExtractThumb)
- {
- int iBytesRead;
- int i, iOffset, iTableOffset;
- uint8_t ucTable, *s = pPage->ucFileBuf;
- uint16_t usMarker, usLen = 0;
- int iFilePos = 0;
- if (bExtractThumb) // seek to the start of the thumbnail image
- {
- iFilePos = pPage->iThumbData;
- (*pPage->pfnSeek)(&pPage->JPEGFile, iFilePos);
- }
- iBytesRead = (*pPage->pfnRead)(&pPage->JPEGFile, s, JPEG_FILE_BUF_SIZE);
- if (iBytesRead < 256) // a JPEG file this tiny? probably bad
- {
- pPage->iError = JPEG_INVALID_FILE;
- return 0;
- }
- iFilePos += iBytesRead;
- if (MOTOSHORT(pPage->ucFileBuf) != 0xffd8)
- {
- pPage->iError = JPEG_INVALID_FILE;
- return 0; // not a JPEG file
- }
- iOffset = 2; /* Start at offset of first marker */
- usMarker = 0; /* Search for SOFx (start of frame) marker */
- while (usMarker != 0xffda && iOffset < pPage->JPEGFile.iSize)
- {
- if (iOffset >= JPEG_FILE_BUF_SIZE/2) // too close to the end, read more data
- {
- // Do we need to seek first?
- if (iOffset >= JPEG_FILE_BUF_SIZE)
- {
- iFilePos += (iOffset - iBytesRead);
- iOffset = 0;
- (*pPage->pfnSeek)(&pPage->JPEGFile, iFilePos);
- iBytesRead = 0; // throw away any old data
- }
- // move existing bytes down
- if (iOffset)
- {
- memcpy(pPage->ucFileBuf, &pPage->ucFileBuf[iOffset], iBytesRead - iOffset);
- iBytesRead -= iOffset;
- iOffset = 0;
- }
- i = (*pPage->pfnRead)(&pPage->JPEGFile, &pPage->ucFileBuf[iBytesRead], JPEG_FILE_BUF_SIZE-iBytesRead);
- iFilePos += i;
- iBytesRead += i;
- }
- usMarker = MOTOSHORT(&s[iOffset]);
- iOffset += 2;
- usLen = MOTOSHORT(&s[iOffset]); // marker length
- if (usMarker < 0xffc0 || usMarker == 0xffff) // invalid marker, could be generated by "Arles Image Web Page Creator" or Accusoft
- {
- iOffset++;
- continue; // skip 1 byte and try to resync
- }
- switch (usMarker)
- {
- case 0xffc1:
- case 0xffc2:
- case 0xffc3:
- pPage->iError = JPEG_UNSUPPORTED_FEATURE;
- return 0; // currently unsupported modes
- case 0xffe1: // App1 (EXIF?)
- if (s[iOffset+2] == 'E' && s[iOffset+3] == 'x' && (s[iOffset+8] == 'M' || s[iOffset+8] == 'I')) // the EXIF data we want
- {
- int bMotorola, IFD, iTagCount;
- pPage->iEXIF = iFilePos - iBytesRead + iOffset + 8; // start of TIFF file
- // Get the orientation value (if present)
- bMotorola = (s[iOffset+8] == 'M');
- IFD = TIFFLONG(&s[iOffset+12], bMotorola);
- iTagCount = TIFFSHORT(&s[iOffset+16], bMotorola);
- GetTIFFInfo(pPage, bMotorola, IFD+iOffset+8);
- // The second IFD defines the thumbnail (if present)
- if (iTagCount >= 1 && iTagCount < 32) // valid number of tags for EXIF data 'page'
- {
- // point to next IFD
- IFD += (12 * iTagCount) + 2;
- IFD = TIFFLONG(&s[IFD + iOffset + 8], bMotorola);
- if (IFD != 0) // Thumbnail present?
- {
- pPage->ucHasThumb = 1;
- GetTIFFInfo(pPage, bMotorola, IFD+iOffset+8); // info for second 'page' of TIFF
- pPage->iThumbData += iOffset + 8; // absolute offset in the file
- }
- }
- }
- break;
- case 0xffc0: // SOFx - start of frame
- pPage->ucMode = (uint8_t)usMarker;
- pPage->ucBpp = s[iOffset+2]; // bits per sample
- pPage->iHeight = MOTOSHORT(&s[iOffset+3]);
- pPage->iWidth = MOTOSHORT(&s[iOffset+5]);
- pPage->ucNumComponents = s[iOffset+7];
- pPage->ucBpp = pPage->ucBpp * pPage->ucNumComponents; /* Bpp = number of components * bits per sample */
- if (pPage->ucNumComponents == 1)
- pPage->ucSubSample = 0; // use this to differentiate from color 1:1
- else
- {
- usLen -= 8;
- iOffset += 8;
- // pPage->ucSubSample = s[iOffset+9]; // subsampling option for the second color component
- for (i=0; i<pPage->ucNumComponents; i++)
- {
- uint8_t ucSamp;
- pPage->JPCI[i].component_id = s[iOffset++];
- pPage->JPCI[i].component_index = (unsigned char)i;
- ucSamp = s[iOffset++]; // get the h+v sampling factor
- if (i == 0) // Y component?
- pPage->ucSubSample = ucSamp;
- // pPage->JPCI[i].h_samp_factor = ucSamp >> 4;
- // pPage->JPCI[i].v_samp_factor = ucSamp & 0xf;
- pPage->JPCI[i].quant_tbl_no = s[iOffset++]; // quantization table number
- usLen -= 3;
- }
- }
- break;
- case 0xffdd: // Restart Interval
- if (usLen == 4)
- pPage->iResInterval = MOTOSHORT(&s[iOffset+2]);
- break;
- case 0xffc4: /* M_DHT */ // get Huffman tables
- iOffset += 2; // skip length
- usLen -= 2; // subtract length length
- if (JPEGGetHuffTables(&s[iOffset], usLen, pPage) != 0) // bad tables?
- {
- pPage->iError = JPEG_DECODE_ERROR;
- return 0; // error
- }
- break;
- case 0xffdb: /* M_DQT */
- /* Get the quantization tables */
- /* first byte has PPPPNNNN where P = precision and N = table number 0-3 */
- iOffset += 2; // skip length
- usLen -= 2; // subtract length length
- while (usLen > 0)
- {
- ucTable = s[iOffset++]; // table number
- if ((ucTable & 0xf) > 3) // invalid table number
- {
- pPage->iError = JPEG_DECODE_ERROR;
- return 0;
- }
- iTableOffset = (ucTable & 0xf) * DCTSIZE;
- if (ucTable & 0xf0) // if word precision
- {
- for (i=0; i<DCTSIZE; i++)
- {
- pPage->sQuantTable[i+iTableOffset] = MOTOSHORT(&s[iOffset]);
- iOffset += 2;
- }
- usLen -= (DCTSIZE*2 + 1);
- }
- else // byte precision
- {
- for (i=0; i<DCTSIZE; i++)
- {
- pPage->sQuantTable[i+iTableOffset] = (unsigned short)s[iOffset++];
- }
- usLen -= (DCTSIZE + 1);
- }
- }
- break;
- } // switch on JPEG marker
- iOffset += usLen;
- } // while
- if (usMarker == 0xffda) // start of image
- {
- if (pPage->ucBpp != 8) // need to match up table IDs
- {
- iOffset -= usLen;
- JPEGGetSOS(pPage, &iOffset); // get Start-Of-Scan info for decoding
- }
- if (!JPEGMakeHuffTables(pPage, 0)) //int bThumbnail) DEBUG
- {
- pPage->iError = JPEG_UNSUPPORTED_FEATURE;
- return 0;
- }
- // Now the offset points to the start of compressed data
- i = JPEGFilter(&pPage->ucFileBuf[iOffset], pPage->ucFileBuf, iBytesRead-iOffset, &pPage->ucFF);
- pPage->iVLCOff = 0;
- pPage->iVLCSize = i;
- JPEGGetMoreData(pPage); // read more VLC data
- return 1;
- }
- pPage->iError = JPEG_DECODE_ERROR;
- return 0;
- } /* JPEGParseInfo() */
- //
- // Fix and reorder the quantization table for faster decoding.*
- //
- static void JPEGFixQuantD(JPEGIMAGE *pJPEG)
- {
- int iTable, iTableOffset;
- signed short sTemp[DCTSIZE];
- int i;
- uint16_t *p;
- for (iTable=0; iTable<pJPEG->ucNumComponents; iTable++)
- {
- iTableOffset = iTable * DCTSIZE;
- p = (uint16_t *)&pJPEG->sQuantTable[iTableOffset];
- for (i=0; i<DCTSIZE; i++)
- sTemp[i] = p[cZigZag[i]];
- memcpy(&pJPEG->sQuantTable[iTableOffset], sTemp, DCTSIZE*sizeof(short)); // copy back to original spot
- // Prescale for DCT multiplication
- p = (uint16_t *)&pJPEG->sQuantTable[iTableOffset];
- for (i=0; i<DCTSIZE; i++)
- {
- p[i] = (uint16_t)((p[i] * iScaleBits[i]) >> 12);
- }
- }
- } /* JPEGFixQuantD() */
- //
- // Decode the 64 coefficients of the current DCT block
- //
- static int JPEGDecodeMCU(JPEGIMAGE *pJPEG, int iMCU, int *iDCPredictor)
- {
- uint32_t ulCode, ulTemp;
- uint8_t *pZig;
- signed char cCoeff;
- unsigned short *pFast;
- unsigned char ucHuff, *pucFast;
- uint32_t usHuff; // this prevents an unnecessary & 65535 for shorts
- uint32_t ulBitOff, ulBits; // local copies to allow compiler to use register vars
- uint8_t *pBuf, *pEnd, *pEnd2;
- signed short *pMCU = &pJPEG->sMCUs[iMCU];
- uint8_t ucMaxACCol, ucMaxACRow;
- #define MIN_DCT_THRESHOLD 8
- ulBitOff = pJPEG->bb.ulBitOff;
- ulBits = pJPEG->bb.ulBits;
- pBuf = pJPEG->bb.pBuf;
- pZig = (unsigned char *)&cZigZag2[1];
- pEnd = (unsigned char *)&cZigZag2[64];
- if (ulBitOff > (REGISTER_WIDTH-17)) // need to get more data
- {
- pBuf += (ulBitOff >> 3);
- ulBitOff &= 7;
- ulBits = MOTOLONG(pBuf);
- }
- if (pJPEG->iOptions & (JPEG_SCALE_QUARTER | JPEG_SCALE_EIGHTH)) // reduced size DCT
- {
- pMCU[1] = pMCU[8] = pMCU[9] = 0;
- pEnd2 = (uint8_t *)&cZigZag2[5]; // we only need to store the 4 elements we care about
- }
- else
- {
- memset(pMCU, 0, 64*sizeof(short)); // pre-fill with zero since we may skip coefficients
- pEnd2 = (uint8_t *)&cZigZag2[64];
- }
- ucMaxACCol = ucMaxACRow = 0;
- pZig = (unsigned char *)&cZigZag2[1];
- pEnd = (unsigned char *)&cZigZag2[64];
- // get the DC component
- pucFast = &pJPEG->ucHuffDC[pJPEG->ucDCTable * DC_TABLE_SIZE];
- ulCode = (ulBits >> (REGISTER_WIDTH - 12 - ulBitOff)) & 0xfff; // get as lower 12 bits
- if (ulCode >= 0xf80) // it's a long code
- ulCode = (ulCode & 0xff); // point to long table and trim to 7-bits + 0x80 offset into long table
- else
- ulCode >>= 6; // it's a short code, use first 6 bits only
- ucHuff = pucFast[ulCode];
- cCoeff = (signed char)pucFast[ulCode+512]; // get pre-calculated extra bits for "small" values
- if (ucHuff == 0) // invalid code
- return -1;
- ulBitOff += (ucHuff >> 4); // add the Huffman length
- ucHuff &= 0xf; // get the actual code (SSSS)
- if (ucHuff) // if there is a change to the DC value
- { // get the 'extra' bits
- if (cCoeff)
- {
- (*iDCPredictor) += cCoeff;
- }
- else
- {
- if (ulBitOff > (REGISTER_WIDTH - 17)) // need to get more data
- {
- pBuf += (ulBitOff >> 3);
- ulBitOff &= 7;
- ulBits = MOTOLONG(pBuf);
- }
- ulCode = ulBits << ulBitOff;
- ulTemp = ~(uint32_t)(((int32_t)ulCode)>>31); // slide sign bit across other 31 bits
- ulCode >>= (REGISTER_WIDTH - ucHuff);
- ulCode -= ulTemp>>(REGISTER_WIDTH-ucHuff);
- ulBitOff += ucHuff; // add bit length
- (*iDCPredictor) += (int)ulCode;
- }
- }
- pMCU[0] = (short)*iDCPredictor; // store in MCU[0]
- // Now get the other 63 AC coefficients
- pFast = &pJPEG->usHuffAC[pJPEG->ucACTable * HUFF11SIZE];
- if (pJPEG->b11Bit) // 11-bit "slow" tables used
- {
- // if (pJPEG->pHuffACFast == pJPEG->huffacFast[1]) // second table
- // pFast = &pJPEG->ucAltHuff[0];
- while (pZig < pEnd)
- {
- if (ulBitOff >(REGISTER_WIDTH - 17)) // need to get more data
- {
- pBuf += (ulBitOff >> 3);
- ulBitOff &= 7;
- ulBits = MOTOLONG(pBuf);
- }
- ulCode = (ulBits >> (REGISTER_WIDTH - 16 - ulBitOff)) & 0xffff; // get as lower 16 bits
- if (ulCode >= 0xf000) // first 4 bits = 1, use long table
- ulCode = (ulCode & 0x1fff);
- else
- ulCode >>= 4; // use lower 12 bits (short table)
- usHuff = pFast[ulCode];
- if (usHuff == 0) // invalid code
- return -1;
- ulBitOff += (usHuff >> 8); // add length
- usHuff &= 0xff; // get code (RRRR/SSSS)
- if (usHuff == 0) // no more AC components
- {
- goto mcu_done;
- }
- if (ulBitOff > (REGISTER_WIDTH - 17)) // need to get more data
- {
- pBuf += (ulBitOff >> 3);
- ulBitOff &= 7;
- ulBits = MOTOLONG(pBuf);
- }
- pZig += (usHuff >> 4); // get the skip amount (RRRR)
- usHuff &= 0xf; // get (SSSS) - extra length
- if (pZig < pEnd && usHuff) // && piHisto)
- {
- ulCode = ulBits << ulBitOff;
- ulTemp = ~(uint32_t) (((int32_t) ulCode) >> (REGISTER_WIDTH-1)); // slide sign bit across other 63 bits
- ulCode >>= (REGISTER_WIDTH - usHuff);
- ulCode -= ulTemp >> (REGISTER_WIDTH - usHuff);
- ucMaxACCol |= 1<<(*pZig & 7); // keep track of occupied columns
- if (*pZig >= 0x20) // if more than 4 rows used in a col, mark it
- ucMaxACRow |= 1<<(*pZig & 7); // keep track of the max AC term row
- pMCU[*pZig] = (signed short)ulCode; // store AC coefficient (already reordered)
- }
- ulBitOff += usHuff; // add (SSSS) extra length
- pZig++;
- } // while
- }
- else // 10-bit "fast" tables used
- {
- while (pZig < pEnd)
- {
- if (ulBitOff >(REGISTER_WIDTH - 17)) // need to get more data
- {
- pBuf += (ulBitOff >> 3);
- ulBitOff &= 7;
- ulBits = MOTOLONG(pBuf);
- }
- ulCode = (ulBits >> (REGISTER_WIDTH - 16 - ulBitOff)) & 0xffff; // get as lower 16 bits
- if (ulCode >= 0xfc00) // first 6 bits = 1, use long table
- ulCode = (ulCode & 0x7ff); // (ulCode & 0x3ff) + 0x400;
- else
- ulCode >>= 6; // use lower 10 bits (short table)
- usHuff = pFast[ulCode];
- if (usHuff == 0) // invalid code
- return -1;
- ulBitOff += (usHuff >> 8); // add length
- usHuff &= 0xff; // get code (RRRR/SSSS)
- if (usHuff == 0) // no more AC components
- {
- goto mcu_done;
- }
- if (ulBitOff >(REGISTER_WIDTH - 17)) // need to get more data
- {
- pBuf += (ulBitOff >> 3);
- ulBitOff &= 7;
- ulBits = MOTOLONG(pBuf);
- }
- pZig += (usHuff >> 4); // get the skip amount (RRRR)
- usHuff &= 0xf; // get (SSSS) - extra length
- if (pZig < pEnd2 && usHuff)
- {
- ulCode = ulBits << ulBitOff;
- ulTemp = ~(uint32_t) (((int32_t) ulCode) >> (REGISTER_WIDTH-1)); // slide sign bit across other 63 bits
- ulCode >>= (REGISTER_WIDTH - usHuff);
- ulCode -= ulTemp >> (REGISTER_WIDTH - usHuff);
- ucMaxACCol |= 1<<(*pZig & 7); // keep track of occupied columns
- if (*pZig >= 0x20) // if more than 4 rows used in a col, mark it
- ucMaxACRow |= 1<<(*pZig & 7); // keep track of the max AC term row
- pMCU[*pZig] = (signed short)ulCode; // store AC coefficient (already reordered)
- }
- ulBitOff += usHuff; // add (SSSS) extra length
- pZig++;
- } // while
- } // 10-bit tables
- mcu_done:
- pJPEG->bb.pBuf = pBuf;
- pJPEG->iVLCOff = (int)(pBuf - pJPEG->ucFileBuf);
- pJPEG->bb.ulBitOff = ulBitOff;
- pJPEG->bb.ulBits = ulBits;
- pJPEG->ucMaxACCol = ucMaxACCol;
- pJPEG->ucMaxACRow = ucMaxACRow; // DEBUG
- return 0;
- } /* JPEGDecodeMCU() */
- //
- // Inverse DCT
- //
- static void JPEGIDCT(JPEGIMAGE *pJPEG, int iMCUOffset, int iQuantTable, int iACFlags)
- {
- int iRow;
- unsigned char ucColMask;
- int iCol;
- signed int tmp6,tmp7,tmp10,tmp11,tmp12,tmp13;
- signed int z5,z10,z11,z12,z13;
- signed int tmp0,tmp1,tmp2,tmp3,tmp4,tmp5;
- signed short *pQuant;
- unsigned char *pOutput;
- unsigned char ucMaxACRow, ucMaxACCol;
- int16_t *pMCUSrc = &pJPEG->sMCUs[iMCUOffset];
- ucMaxACRow = (unsigned char)(iACFlags >> 8);
- ucMaxACCol = iACFlags & 0xff;
- // my shortcut method appears to violate patent 20020080052
- // but the patent is invalidated by prior art:
- // http://netilium.org/~mad/dtj/DTJ/DTJK04/
- pQuant = &pJPEG->sQuantTable[iQuantTable * DCTSIZE];
- if (pJPEG->iOptions & JPEG_SCALE_QUARTER) // special case
- {
- /* Column 0 */
- tmp4 = pMCUSrc[0] * pQuant[0];
- tmp5 = pMCUSrc[8] * pQuant[8];
- tmp0 = tmp4 + tmp5;
- tmp2 = tmp4 - tmp5;
- /* Column 1 */
- tmp4 = pMCUSrc[1] * pQuant[1];
- tmp5 = pMCUSrc[9] * pQuant[9];
- tmp1 = tmp4 + tmp5;
- tmp3 = tmp4 - tmp5;
- /* Pass 2: process 2 rows, store into output array. */
- /* Row 0 */
- pOutput = (unsigned char *)pMCUSrc; // store output pixels back into MCU
- pOutput[0] = ucRangeTable[(((tmp0 + tmp1)>>5) & 0x3ff)];
- pOutput[1] = ucRangeTable[(((tmp0 - tmp1)>>5) & 0x3ff)];
- /* Row 1 */
- pOutput[2] = ucRangeTable[(((tmp2 + tmp3)>>5) & 0x3ff)];
- pOutput[3] = ucRangeTable[(((tmp2 - tmp3)>>5) & 0x3ff)];
- return;
- }
- // do columns first
- ucColMask = ucMaxACCol | 1; // column 0 must always be calculated
- for (iCol = 0; iCol < 8 && ucColMask; iCol++)
- {
- if (ucColMask & (1<<iCol)) // column has data in it
- {
- ucColMask &= ~(1<<iCol); // unmark this col after use
- if (!(ucMaxACRow & (1<<iCol))) // simpler calculations if only half populated
- {
- // even part
- tmp10 = pMCUSrc[iCol] * pQuant[iCol];
- tmp1 = pMCUSrc[iCol+16] * pQuant[iCol+16]; // get 2nd row
- tmp12 = ((tmp1*106)>>8); // used to be 362 - 1 (256)
- tmp0 = tmp10 + tmp1;
- tmp3 = tmp10 - tmp1;
- tmp1 = tmp10 + tmp12;
- tmp2 = tmp10 - tmp12;
- // odd part
- tmp4 = pMCUSrc[iCol+8] * pQuant[iCol+8]; // get 1st row
- tmp5 = pMCUSrc[iCol+24];
- if (tmp5) // this value is usually 0
- {
- tmp5 *= pQuant[iCol+24]; // get 3rd row
- tmp7 = tmp4 + tmp5;
- tmp11 = (((tmp4 - tmp5) * 362) >> 8); // 362>>8 = 1.414213562
- z5 = (((tmp4-tmp5) * 473) >> 8); // 473>>8 = 1.8477
- tmp12 = ((-tmp5 * -669)>>8) + z5; // -669>>8 = -2.6131259
- tmp6 = tmp12 - tmp7;
- tmp5 = tmp11 - tmp6;
- tmp10 = ((tmp4 * 277)>>8) - z5; // 277>>8 = 1.08239
- tmp4 = tmp10 + tmp5;
- }
- else // simpler case when we only have 1 odd row to calculate
- {
- tmp7 = tmp4;
- tmp5 = (145*tmp4) >> 8;
- tmp6 = (217*tmp4) >> 8;
- tmp4 = (-51*tmp4) >> 8;
- }
- pMCUSrc[iCol] = (short)(tmp0 + tmp7); // row0
- pMCUSrc[iCol+8] = (short)(tmp1 + tmp6); // row 1
- pMCUSrc[iCol+16] = (short)(tmp2 + tmp5); // row 2
- pMCUSrc[iCol+24] = (short)(tmp3 - tmp4); // row 3
- pMCUSrc[iCol+32] = (short)(tmp3 + tmp4); // row 4
- pMCUSrc[iCol+40] = (short)(tmp2 - tmp5); // row 5
- pMCUSrc[iCol+48] = (short)(tmp1 - tmp6); // row 6
- pMCUSrc[iCol+56] = (short)(tmp0 - tmp7); // row 7
- }
- else // need to do full column calculation
- {
- // even part
- tmp0 = pMCUSrc[iCol] * pQuant[iCol];
- tmp2 = pMCUSrc[iCol+32]; // get 4th row
- if (tmp2) // 4th row is most likely 0
- {
- tmp2 = tmp2 * pQuant[iCol+32];
- tmp10 = tmp0 + tmp2;
- tmp11 = tmp0 - tmp2;
- }
- else
- {
- tmp10 = tmp11 = tmp0;
- }
- tmp1 = pMCUSrc[iCol+16] * pQuant[iCol+16]; // get 2nd row
- tmp3 = pMCUSrc[iCol+48]; // get 6th row
- if (tmp3) // 6th row is most likely 0
- {
- tmp3 = tmp3 * pQuant[iCol+48];
- tmp13 = tmp1 + tmp3;
- tmp12 = (((tmp1 - tmp3) * 362) >> 8) - tmp13; // 362>>8 = 1.414213562
- }
- else
- {
- tmp13 = tmp1;
- tmp12 = ((tmp1*362)>>8) - tmp1;
- }
- tmp0 = tmp10 + tmp13;
- tmp3 = tmp10 - tmp13;
- tmp1 = tmp11 + tmp12;
- tmp2 = tmp11 - tmp12;
- // odd part
- tmp5 = pMCUSrc[iCol+24] * pQuant[iCol+24]; // get 3rd row
- tmp6 = pMCUSrc[iCol+40]; // get 5th row
- if (tmp6) // very likely that row 5 = 0
- {
- tmp6 = tmp6 * pQuant[iCol+40];
- z13 = tmp6 + tmp5;
- z10 = tmp6 - tmp5;
- }
- else
- {
- z13 = tmp5;
- z10 = -tmp5;
- }
- tmp4 = pMCUSrc[iCol+8] * pQuant[iCol+8]; // get 1st row
- tmp7 = pMCUSrc[iCol+56]; // get 7th row
- if (tmp7) // very likely that row 7 = 0
- {
- tmp7 = tmp7 * pQuant[iCol+56];
- z11 = tmp4 + tmp7;
- z12 = tmp4 - tmp7;
- }
- else
- {
- z11 = z12 = tmp4;
- }
- tmp7 = z11 + z13;
- tmp11 = (((z11 - z13) * 362) >> 8); // 362>>8 = 1.414213562
- z5 = (((z10 + z12) * 473) >> 8); // 473>>8 = 1.8477
- tmp12 = ((z10 * -669)>>8) + z5; // -669>>8 = -2.6131259
- tmp6 = tmp12 - tmp7;
- tmp5 = tmp11 - tmp6;
- tmp10 = ((z12 * 277)>>8) - z5; // 277>>8 = 1.08239
- tmp4 = tmp10 + tmp5;
- pMCUSrc[iCol] = (short)(tmp0 + tmp7); // row0
- pMCUSrc[iCol+8] = (short)(tmp1 + tmp6); // row 1
- pMCUSrc[iCol+16] = (short)(tmp2 + tmp5); // row 2
- pMCUSrc[iCol+24] = (short)(tmp3 - tmp4); // row 3
- pMCUSrc[iCol+32] = (short)(tmp3 + tmp4); // row 4
- pMCUSrc[iCol+40] = (short)(tmp2 - tmp5); // row 5
- pMCUSrc[iCol+48] = (short)(tmp1 - tmp6); // row 6
- pMCUSrc[iCol+56] = (short)(tmp0 - tmp7); // row 7
- } // full calculation needed
- } // if column has data in it
- } // for each column
- // now do rows
- pOutput = (unsigned char *)pMCUSrc; // store output pixels back into MCU
- for (iRow=0; iRow<64; iRow+=8) // all rows must be calculated
- {
- // even part
- if (ucMaxACCol < 0x10) // quick and dirty calculation (right 4 columns are all 0's)
- {
- if (ucMaxACCol < 0x04) // very likely case (1 or 2 columns occupied)
- {
- // even part
- tmp0 = tmp1 = tmp2 = tmp3 = pMCUSrc[iRow+0];
- // odd part
- tmp7 = pMCUSrc[iRow+1];
- tmp6 = (tmp7 * 217)>>8; // * 0.8477
- tmp5 = (tmp7 * 145)>>8; // * 0.5663
- tmp4 = -((tmp7 * 51)>>8); // * -0.199
- }
- else
- {
- tmp10 = pMCUSrc[iRow+0];
- tmp13 = pMCUSrc[iRow+2];
- tmp12 = ((tmp13 * 106)>>8); // 2-6 * 1.414
- tmp0 = tmp10 + tmp13;
- tmp3 = tmp10 - tmp13;
- tmp1 = tmp10 + tmp12;
- tmp2 = tmp10 - tmp12;
- // odd part
- z13 = pMCUSrc[iRow+3];
- z11 = pMCUSrc[iRow+1];
- tmp7 = z11 + z13;
- tmp11 = ((z11 - z13)*362)>>8; // * 1.414
- z5 = ((z11 - z13)*473)>>8; // * 1.8477
- tmp10 = ((z11*277)>>8) - z5; // * 1.08239
- tmp12 = ((z13*669)>>8) + z5; // * 2.61312
- tmp6 = tmp12 - tmp7;
- tmp5 = tmp11 - tmp6;
- tmp4 = tmp10 + tmp5;
- }
- }
- else // need to do the full calculation
- {
- tmp10 = pMCUSrc[iRow+0] + pMCUSrc[iRow+4];
- tmp11 = pMCUSrc[iRow+0] - pMCUSrc[iRow+4];
- tmp13 = pMCUSrc[iRow+2] + pMCUSrc[iRow+6];
- tmp12 = (((pMCUSrc[iRow+2] - pMCUSrc[iRow+6]) * 362)>>8) - tmp13; // 2-6 * 1.414
- tmp0 = tmp10 + tmp13;
- tmp3 = tmp10 - tmp13;
- tmp1 = tmp11 + tmp12;
- tmp2 = tmp11 - tmp12;
- // odd part
- z13 = pMCUSrc[iRow+5] + pMCUSrc[iRow+3];
- z10 = pMCUSrc[iRow+5] - pMCUSrc[iRow+3];
- z11 = pMCUSrc[iRow+1] + pMCUSrc[iRow+7];
- z12 = pMCUSrc[iRow+1] - pMCUSrc[iRow+7];
- tmp7 = z11 + z13;
- tmp11 = ((z11 - z13)*362)>>8; // * 1.414
- z5 = ((z10 + z12)*473)>>8; // * 1.8477
- tmp10 = ((z12*277)>>8) - z5; // * 1.08239
- tmp12 = ((z10*-669)>>8) + z5; // * 2.61312
- tmp6 = tmp12 - tmp7;
- tmp5 = tmp11 - tmp6;
- tmp4 = tmp10 + tmp5;
- }
- // final output stage - scale down and range limit
- pOutput[0] = ucRangeTable[(((tmp0 + tmp7)>>5) & 0x3ff)];
- pOutput[1] = ucRangeTable[(((tmp1 + tmp6)>>5) & 0x3ff)];
- pOutput[2] = ucRangeTable[(((tmp2 + tmp5)>>5) & 0x3ff)];
- pOutput[3] = ucRangeTable[(((tmp3 - tmp4)>>5) & 0x3ff)];
- pOutput[4] = ucRangeTable[(((tmp3 + tmp4)>>5) & 0x3ff)];
- pOutput[5] = ucRangeTable[(((tmp2 - tmp5)>>5) & 0x3ff)];
- pOutput[6] = ucRangeTable[(((tmp1 - tmp6)>>5) & 0x3ff)];
- pOutput[7] = ucRangeTable[(((tmp0 - tmp7)>>5) & 0x3ff)];
- pOutput += 8;
- } // for each row
- } /* JPEGIDCT() */
- static void JPEGPutMCU8BitGray(JPEGIMAGE *pJPEG, int x, int iPitch)
- {
- int i, j, xcount, ycount;
- uint8_t *pDest, *pSrc = (uint8_t *)&pJPEG->sMCUs[0];
- if (pJPEG->pDitherBuffer)
- pDest = &pJPEG->pDitherBuffer[x];
- else
- pDest = (uint8_t *)&pJPEG->usPixels[x/2];
- if (pJPEG->ucSubSample <= 0x11) // single Y
- {
- if (pJPEG->iOptions & JPEG_SCALE_HALF) // special handling of 1/2 size (pixel averaging)
- {
- int pix;
- for (i=0; i<4; i++)
- {
- for (j=0; j<4; j++)
- {
- pix = (pSrc[0] + pSrc[1] + pSrc[8] + pSrc[9] + 2) >> 2; // average 2x2 block
- pDest[j] = (uint8_t)pix;
- pSrc += 2;
- }
- pSrc += 8; // skip extra line
- pDest += iPitch;
- }
- return;
- }
- xcount = ycount = 8; // debug
- if (pJPEG->iOptions & JPEG_SCALE_QUARTER)
- xcount = ycount = 2;
- else if (pJPEG->iOptions & JPEG_SCALE_EIGHTH)
- xcount = ycount = 1;
- for (i=0; i<ycount; i++) // do up to 8 rows
- {
- for (j=0; j<xcount; j++)
- *pDest++ = *pSrc++;
- pDest -= xcount;
- pDest += iPitch; // next line
- }
- return;
- } // single Y source
- if (pJPEG->ucSubSample == 0x21) // stacked horizontally
- {
- if (pJPEG->iOptions & JPEG_SCALE_EIGHTH)
- {
- // only 2 pixels emitted
- pDest[0] = pSrc[0];
- pDest[1] = pSrc[128];
- return;
- } /* 1/8 */
- if (pJPEG->iOptions & JPEG_SCALE_HALF)
- {
- for (i=0; i<4; i++)
- {
- for (j=0; j<4; j++)
- {
- int pix;
- pix = (pSrc[j*2] + pSrc[j*2+1] + pSrc[j*2 + 8] + pSrc[j*2 + 9] + 2) >> 2;
- pDest[j] = (uint8_t)pix;
- pix = (pSrc[j*2 + 128] + pSrc[j*2+129] + pSrc[j*2 + 136] + pSrc[j*2 + 137] + 2) >> 2;
- pDest[j+4] = (uint8_t)pix;
- }
- pSrc += 16;
- pDest += iPitch;
- }
- return;
- }
- if (pJPEG->iOptions & JPEG_SCALE_QUARTER)
- {
- // each MCU contributes a 2x2 block
- pDest[0] = pSrc[0]; // Y0
- pDest[1] = pSrc[1];
- pDest[iPitch] = pSrc[2];
- pDest[iPitch+1] = pSrc[3];
- pDest[2] = pSrc[128]; // Y`
- pDest[3] = pSrc[129];
- pDest[iPitch+2] = pSrc[130];
- pDest[iPitch+3] = pSrc[131];
- return;
- }
- for (i=0; i<8; i++)
- {
- for (j=0; j<8; j++)
- {
- pDest[j] = pSrc[j];
- pDest[j+8] = pSrc[128 + j];
- }
- pSrc += 8;
- pDest += iPitch;
- }
- } // 0x21
- if (pJPEG->ucSubSample == 0x12) // stacked vertically
- {
- if (pJPEG->iOptions & JPEG_SCALE_EIGHTH)
- {
- // only 2 pixels emitted
- pDest[0] = pSrc[0];
- pDest[iPitch] = pSrc[128];
- return;
- } /* 1/8 */
- if (pJPEG->iOptions & JPEG_SCALE_HALF)
- {
- for (i=0; i<4; i++)
- {
- for (j=0; j<4; j++)
- {
- int pix;
- pix = (pSrc[j*2] + pSrc[j*2+1] + pSrc[j*2 + 8] + pSrc[j*2 + 9] + 2) >> 2;
- pDest[j] = (uint8_t)pix;
- pix = (pSrc[j*2 + 128] + pSrc[j*2+129] + pSrc[j*2 + 136] + pSrc[j*2 + 137] + 2) >> 2;
- pDest[4*iPitch+j] = (uint8_t)pix;
- }
- pSrc += 16;
- pDest += iPitch;
- }
- return;
- }
- if (pJPEG->iOptions & JPEG_SCALE_QUARTER)
- {
- // each MCU contributes a 2x2 block
- pDest[0] = pSrc[0]; // Y0
- pDest[1] = pSrc[1];
- pDest[iPitch] = pSrc[2];
- pDest[iPitch+1] = pSrc[3];
- pDest[iPitch*2] = pSrc[128]; // Y`
- pDest[iPitch*2+1] = pSrc[129];
- pDest[iPitch*3] = pSrc[130];
- pDest[iPitch*3+1] = pSrc[131];
- return;
- }
- for (i=0; i<8; i++)
- {
- for (j=0; j<8; j++)
- {
- pDest[j] = pSrc[j];
- pDest[8*iPitch + j] = pSrc[128 + j];
- }
- pSrc += 8;
- pDest += iPitch;
- }
- } // 0x12
- if (pJPEG->ucSubSample == 0x22)
- {
- if (pJPEG->iOptions & JPEG_SCALE_EIGHTH)
- {
- // each MCU contributes 1 pixel
- pDest[0] = pSrc[0]; // Y0
- pDest[1] = pSrc[128]; // Y1
- pDest[iPitch] = pSrc[256]; // Y2
- pDest[iPitch + 1] = pSrc[384]; // Y3
- return;
- }
- if (pJPEG->iOptions & JPEG_SCALE_QUARTER)
- {
- // each MCU contributes 2x2 pixels
- pDest[0] = pSrc[0]; // Y0
- pDest[1] = pSrc[1];
- pDest[iPitch] = pSrc[2];
- pDest[iPitch+1] = pSrc[3];
- pDest[2] = pSrc[128]; // Y1
- pDest[3] = pSrc[129];
- pDest[iPitch+2] = pSrc[130];
- pDest[iPitch+3] = pSrc[131];
- pDest[iPitch*2] = pSrc[256]; // Y2
- pDest[iPitch*2+1] = pSrc[257];
- pDest[iPitch*3] = pSrc[258];
- pDest[iPitch*3+1] = pSrc[259];
- pDest[iPitch*2+2] = pSrc[384]; // Y3
- pDest[iPitch*2+3] = pSrc[385];
- pDest[iPitch*3+2] = pSrc[386];
- pDest[iPitch*3+3] = pSrc[387];
- return;
- }
- if (pJPEG->iOptions & JPEG_SCALE_HALF)
- {
- for (i=0; i<4; i++)
- {
- for (j=0; j<4; j++)
- {
- int pix;
- pix = (pSrc[j*2] + pSrc[j*2+1] + pSrc[j*2 + 8] + pSrc[j*2 + 9] + 2) >> 2;
- pDest[j] = (uint8_t)pix; // Y0
- pix = (pSrc[j*2+128] + pSrc[j*2+129] + pSrc[j*2 + 136] + pSrc[j*2 + 137] + 2) >> 2;
- pDest[j+4] = (uint8_t)pix; // Y1
- pix = (pSrc[j*2+256] + pSrc[j*2+257] + pSrc[j*2 + 264] + pSrc[j*2 + 265] + 2) >> 2;
- pDest[iPitch*4 + j] = (uint8_t)pix; // Y2
- pix = (pSrc[j*2+384] + pSrc[j*2+385] + pSrc[j*2 + 392] + pSrc[j*2 + 393] + 2) >> 2;
- pDest[iPitch*4 + j + 4] = (uint8_t)pix; // Y3
- }
- pSrc += 16;
- pDest += iPitch;
- }
- return;
- }
- for (i=0; i<8; i++)
- {
- for (j=0; j<8; j++)
- {
- pDest[j] = pSrc[j]; // Y0
- pDest[j+8] = pSrc[j+128]; // Y1
- pDest[iPitch*8 + j] = pSrc[j+256]; // Y2
- pDest[iPitch*8 + j + 8] = pSrc[j + 384]; // Y3
- }
- pSrc += 8;
- pDest += iPitch;
- }
- } // 0x22
- } /* JPEGMPutMCU8BitGray() */
- static void JPEGPutMCUGray(JPEGIMAGE *pJPEG, int x, int iPitch)
- {
- uint16_t *usDest = (uint16_t *)&pJPEG->usPixels[x];
- int i, j, xcount, ycount;
- uint8_t *pSrc = (uint8_t *)&pJPEG->sMCUs[0];
- if (pJPEG->iOptions & JPEG_SCALE_HALF) // special handling of 1/2 size (pixel averaging)
- {
- int pix;
- for (i=0; i<4; i++)
- {
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- for (j=0; j<4; j++)
- {
- pix = (pSrc[0] + pSrc[1] + pSrc[8] + pSrc[9] + 2) >> 2; // average 2x2 block
- usDest[j] = usGrayTo565[pix];
- pSrc += 2;
- }
- }
- else
- {
- for (j=0; j<4; j++)
- {
- pix = (pSrc[0] + pSrc[1] + pSrc[8] + pSrc[9] + 2) >> 2; // average 2x2 block
- usDest[j] = __builtin_bswap16(usGrayTo565[pix]);
- pSrc += 2;
- }
- }
- pSrc += 8; // skip extra line
- usDest += iPitch;
- }
- return;
- }
- xcount = ycount = 8; // debug
- if (pJPEG->iOptions & JPEG_SCALE_QUARTER)
- xcount = ycount = 2;
- else if (pJPEG->iOptions & JPEG_SCALE_EIGHTH)
- xcount = ycount = 1;
- for (i=0; i<ycount; i++) // do up to 8 rows
- {
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- for (j=0; j<xcount; j++)
- *usDest++ = usGrayTo565[*pSrc++];
- }
- else
- {
- for (j=0; j<xcount; j++)
- *usDest++ = __builtin_bswap16(usGrayTo565[*pSrc++]);
- }
- usDest -= xcount;
- usDest += iPitch; // next line
- }
- } /* JPEGPutMCUGray() */
- static void JPEGPixelLE(uint16_t *pDest, int iY, int iCb, int iCr)
- {
- //
- // Cortex-M4/M7 has some SIMD instructions which can shave a few cycles
- // off of this function (e.g. Teensy, Arduino Nano 33 BLE, Portenta, etc)
- //
- #ifdef HAS_SIMD
- uint32_t ulPixel;
- uint32_t ulCbCr = (iCb | (iCr << 16));
- uint32_t ulTmp = -1409 | (-2925 << 16); // for green calc
- ulCbCr = __SSUB16(ulCbCr, 0x00800080); // dual 16-bit subtraction
- ulPixel = __SMLAD(ulCbCr, ulTmp, iY) >> 14; // G
- ulPixel = __USAT16(ulPixel, 6) << 5; // range limit to 6 bits
- ulTmp = __SMLAD(7258, ulCbCr, iY) >> 15; // Blue
- ulTmp = __USAT16(ulTmp, 5); // range limit to 5 bits
- ulPixel |= ulTmp; // now we have G + B
- ulTmp = __SMLAD(5742, ulCbCr >> 16, iY) >> 15; // Red
- ulTmp = __USAT16(ulTmp, 5); // range limit to 5 bits
- ulPixel |= (ulTmp << 11); // now we have R + G + B
- pDest[0] = (uint16_t)ulPixel;
- #else
- int iCBB, iCBG, iCRG, iCRR;
- unsigned short usPixel;
- iCBB = 7258 * (iCb-0x80);
- iCBG = -1409 * (iCb-0x80);
- iCRG = -2925 * (iCr-0x80);
- iCRR = 5742 * (iCr-0x80);
- usPixel = usRangeTableB[((iCBB + iY) >> 12) & 0x3ff]; // blue pixel
- usPixel |= usRangeTableG[((iCBG + iCRG + iY) >> 12) & 0x3ff]; // green pixel
- usPixel |= usRangeTableR[((iCRR + iY) >> 12) & 0x3ff]; // red pixel
- pDest[0] = usPixel;
- #endif
- } /* JPEGPixelLE() */
- static void JPEGPixelBE(uint16_t *pDest, int iY, int iCb, int iCr)
- {
- int iCBB, iCBG, iCRG, iCRR;
- unsigned short usPixel;
- iCBB = 7258 * (iCb-0x80);
- iCBG = -1409 * (iCb-0x80);
- iCRG = -2925 * (iCr-0x80);
- iCRR = 5742 * (iCr-0x80);
- usPixel = usRangeTableB[((iCBB + iY) >> 12) & 0x3ff]; // blue pixel
- usPixel |= usRangeTableG[((iCBG + iCRG + iY) >> 12) & 0x3ff]; // green pixel
- usPixel |= usRangeTableR[((iCRR + iY) >> 12) & 0x3ff]; // red pixel
- pDest[0] = __builtin_bswap16(usPixel);
- } /* JPEGPixelBE() */
- static void JPEGPixel2LE(uint16_t *pDest, int iY1, int iY2, int iCb, int iCr)
- {
- uint32_t ulPixel1, ulPixel2;
- //
- // Cortex-M4/M7 has some SIMD instructions which can shave a few cycles
- // off of this function (e.g. Teensy, Arduino Nano 33 BLE, Portenta, etc)
- //
- #ifdef HAS_SIMD
- uint32_t ulCbCr = (iCb | (iCr << 16));
- uint32_t ulTmp2, ulTmp = -1409 | (-2925 << 16); // for green calc
- ulCbCr = __SSUB16(ulCbCr, 0x00800080); // dual 16-bit subtraction
- ulPixel1 = __SMLAD(ulCbCr, ulTmp, iY1) >> 14; // G for pixel 1
- ulPixel2 = __SMLAD(ulCbCr, ulTmp, iY2) >> 14; // G for pixel 2
- ulPixel1 |= (ulPixel2 << 16);
- ulPixel1 = __USAT16(ulPixel1, 6) << 5; // range limit both to 6 bits
- ulTmp = __SMLAD(7258, ulCbCr, iY1) >> 15; // Blue 1
- ulTmp2 = __SMLAD(7258, ulCbCr, iY2) >> 15; // Blue 2
- ulTmp = __USAT16(ulTmp | (ulTmp2 << 16), 5); // range limit both to 5 bits
- ulPixel1 |= ulTmp; // now we have G + B
- ulTmp = __SMLAD(5742, ulCbCr >> 16, iY1) >> 15; // Red 1
- ulTmp2 = __SMLAD(5742, ulCbCr >> 16, iY2) >> 15; // Red 2
- ulTmp = __USAT16(ulTmp | (ulTmp2 << 16), 5); // range limit both to 5 bits
- ulPixel1 |= (ulTmp << 11); // now we have R + G + B
- *(uint32_t *)&pDest[0] = ulPixel1;
- #else
- int iCBB, iCBG, iCRG, iCRR;
- iCBB = 7258 * (iCb-0x80);
- iCBG = -1409 * (iCb-0x80);
- iCRG = -2925 * (iCr-0x80);
- iCRR = 5742 * (iCr-0x80);
- ulPixel1 = usRangeTableB[((iCBB + iY1) >> 12) & 0x3ff]; // blue pixel
- ulPixel1 |= usRangeTableG[((iCBG + iCRG + iY1) >> 12) & 0x3ff]; // green pixel
- ulPixel1 |= usRangeTableR[((iCRR + iY1) >> 12) & 0x3ff]; // red pixel
- ulPixel2 = usRangeTableB[((iCBB + iY2) >> 12) & 0x3ff]; // blue pixel
- ulPixel2 |= usRangeTableG[((iCBG + iCRG + iY2) >> 12) & 0x3ff]; // green pixel
- ulPixel2 |= usRangeTableR[((iCRR + iY2) >> 12) & 0x3ff]; // red pixel
- *(uint32_t *)&pDest[0] = (ulPixel1 | (ulPixel2<<16));
- #endif
- } /* JPEGPixel2LE() */
- static void JPEGPixel2BE(uint16_t *pDest, int32_t iY1, int32_t iY2, int32_t iCb, int32_t iCr)
- {
- int32_t iCBB, iCBG, iCRG, iCRR;
- uint32_t ulPixel1, ulPixel2;
- iCBB = 7258L * (iCb-0x80);
- iCBG = -1409L * (iCb-0x80);
- iCRG = -2925L * (iCr-0x80);
- iCRR = 5742L * (iCr-0x80);
- ulPixel1 = usRangeTableB[((iCBB + iY1) >> 12) & 0x3ff]; // blue pixel
- ulPixel1 |= usRangeTableG[((iCBG + iCRG + iY1) >> 12) & 0x3ff]; // green pixel
- ulPixel1 |= usRangeTableR[((iCRR + iY1) >> 12) & 0x3ff]; // red pixel
- ulPixel2 = usRangeTableB[((iCBB + iY2) >> 12) & 0x3ff]; // blue pixel
- ulPixel2 |= usRangeTableG[((iCBG + iCRG + iY2) >> 12) & 0x3ff]; // green pixel
- ulPixel2 |= usRangeTableR[((iCRR + iY2) >> 12) & 0x3ff]; // red pixel
- *(uint32_t *)&pDest[0] = __builtin_bswap16(ulPixel1) | ((uint32_t)__builtin_bswap16(ulPixel2)<<16);
- } /* JPEGPixel2BE() */
- static void JPEGPutMCU11(JPEGIMAGE *pJPEG, int x, int iPitch)
- {
- int iCr, iCb;
- signed int Y;
- int iCol;
- int iRow;
- uint8_t *pY, *pCr, *pCb;
- uint16_t *pOutput = &pJPEG->usPixels[x];
- pY = (unsigned char *)&pJPEG->sMCUs[0*DCTSIZE];
- pCb = (unsigned char *)&pJPEG->sMCUs[1*DCTSIZE];
- pCr = (unsigned char *)&pJPEG->sMCUs[2*DCTSIZE];
- if (pJPEG->iOptions & JPEG_SCALE_HALF)
- {
- for (iRow=0; iRow<4; iRow++) // up to 8 rows to do
- {
- for (iCol=0; iCol<4; iCol++) // up to 4x2 cols to do
- {
- iCr = (pCr[0] + pCr[1] + pCr[8] + pCr[9] + 2) >> 2;
- iCb = (pCb[0] + pCb[1] + pCb[8] + pCb[9] + 2) >> 2;
- Y = (pY[0] + pY[1] + pY[8] + pY[9]) << 10;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput+iCol, Y, iCb, iCr);
- else
- JPEGPixelBE(pOutput+iCol, Y, iCb, iCr);
- pCr += 2;
- pCb += 2;
- pY += 2;
- } // for col
- pCr += 8;
- pCb += 8;
- pY += 8;
- pOutput += iPitch;
- } // for row
- return;
- }
- if (pJPEG->iOptions & JPEG_SCALE_EIGHTH) // special case for 1/8 scaling
- {
- // only 4 pixels to draw, so no looping needed
- iCr = pCr[0];
- iCb = pCb[0];
- Y = (int)(pY[0]) << 12;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput, Y, iCb, iCr);
- else
- JPEGPixelBE(pOutput, Y, iCb, iCr);
- return;
- }
- if (pJPEG->iOptions & JPEG_SCALE_QUARTER) // special case for 1/4 scaling
- {
- // only 4 pixels to draw, so no looping needed
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- iCr = *pCr++;
- iCb = *pCb++;
- Y = (int)(*pY++) << 12;
- JPEGPixelLE(pOutput, Y, iCb, iCr);
- iCr = *pCr++;
- iCb = *pCb++;
- Y = (int)(*pY++) << 12;
- JPEGPixelLE(pOutput+1, Y, iCb, iCr);
- iCr = *pCr++;
- iCb = *pCb++;
- Y = (int)(*pY++) << 12;
- JPEGPixelLE(pOutput+iPitch, Y, iCb, iCr);
- iCr = *pCr++;
- iCb = *pCb++;
- Y = (int)(*pY++) << 12;
- JPEGPixelLE(pOutput+1+iPitch, Y, iCb, iCr);
- }
- else
- {
- iCr = *pCr++;
- iCb = *pCb++;
- Y = (int)(*pY++) << 12;
- JPEGPixelBE(pOutput, Y, iCb, iCr);
- iCr = *pCr++;
- iCb = *pCb++;
- Y = (int)(*pY++) << 12;
- JPEGPixelBE(pOutput+1, Y, iCb, iCr);
- iCr = *pCr++;
- iCb = *pCb++;
- Y = (int)(*pY++) << 12;
- JPEGPixelBE(pOutput+iPitch, Y, iCb, iCr);
- iCr = *pCr++;
- iCb = *pCb++;
- Y = (int)(*pY++) << 12;
- JPEGPixelBE(pOutput+1+iPitch, Y, iCb, iCr);
- }
- return;
- }
- for (iRow=0; iRow<8; iRow++) // up to 8 rows to do
- {
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- for (iCol=0; iCol<8; iCol++) // up to 4x2 cols to do
- {
- iCr = *pCr++;
- iCb = *pCb++;
- Y = (int)(*pY++) << 12;
- JPEGPixelLE(pOutput+iCol, Y, iCb, iCr);
- } // for col
- }
- else
- {
- for (iCol=0; iCol<8; iCol++) // up to 4x2 cols to do
- {
- iCr = *pCr++;
- iCb = *pCb++;
- Y = (int)(*pY++) << 12;
- JPEGPixelBE(pOutput+iCol, Y, iCb, iCr);
- } // for col
- }
- pOutput += iPitch;
- } // for row
- } /* JPEGPutMCU11() */
- static void JPEGPutMCU22(JPEGIMAGE *pJPEG, int x, int iPitch)
- {
- uint32_t Cr,Cb;
- signed int Y1, Y2, Y3, Y4;
- int iRow, iCol, iXCount1, iXCount2, iYCount;
- unsigned char *pY, *pCr, *pCb;
- int bUseOdd1, bUseOdd2; // special case where 24bpp odd sized image can clobber first column
- uint16_t *pOutput = &pJPEG->usPixels[x];
- pY = (unsigned char *)&pJPEG->sMCUs[0*DCTSIZE];
- pCb = (unsigned char *)&pJPEG->sMCUs[4*DCTSIZE];
- pCr = (unsigned char *)&pJPEG->sMCUs[5*DCTSIZE];
- if (pJPEG->iOptions & JPEG_SCALE_HALF) // special handling of 1/2 size (pixel averaging)
- {
- for (iRow=0; iRow<4; iRow++) // 16x16 becomes 8x8 of 2x2 pixels
- {
- for (iCol=0; iCol<4; iCol++)
- {
- Y1 = (pY[iCol*2] + pY[iCol*2+1] + pY[iCol*2+8] + pY[iCol*2+9]) << 10;
- Cb = pCb[iCol];
- Cr = pCr[iCol];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput+iCol, Y1, Cb, Cr); // top left
- else
- JPEGPixelBE(pOutput+iCol, Y1, Cb, Cr);
- Y1 = (pY[iCol*2+(DCTSIZE*2)] + pY[iCol*2+1+(DCTSIZE*2)] + pY[iCol*2+8+(DCTSIZE*2)] + pY[iCol*2+9+(DCTSIZE*2)]) << 10;
- Cb = pCb[iCol+4];
- Cr = pCr[iCol+4];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput+iCol+4, Y1, Cb, Cr); // top right
- else
- JPEGPixelBE(pOutput+iCol+4, Y1, Cb, Cr);
- Y1 = (pY[iCol*2+(DCTSIZE*4)] + pY[iCol*2+1+(DCTSIZE*4)] + pY[iCol*2+8+(DCTSIZE*4)] + pY[iCol*2+9+(DCTSIZE*4)]) << 10;
- Cb = pCb[iCol+32];
- Cr = pCr[iCol+32];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput+iCol+iPitch*4, Y1, Cb, Cr); // bottom left
- else
- JPEGPixelBE(pOutput+iCol+iPitch*4, Y1, Cb, Cr);
- Y1 = (pY[iCol*2+(DCTSIZE*6)] + pY[iCol*2+1+(DCTSIZE*6)] + pY[iCol*2+8+(DCTSIZE*6)] + pY[iCol*2+9+(DCTSIZE*6)]) << 10;
- Cb = pCb[iCol+32+4];
- Cr = pCr[iCol+32+4];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput+iCol+4+iPitch*4, Y1, Cb, Cr); // bottom right
- else
- JPEGPixelBE(pOutput+iCol+4+iPitch*4, Y1, Cb, Cr);
- }
- pY += 16;
- pCb += 8;
- pCr += 8;
- pOutput += iPitch;
- }
- return;
- }
- if (pJPEG->iOptions & JPEG_SCALE_EIGHTH)
- {
- Y1 = pY[0] << 12; // scale to level of conversion table
- Cb = pCb[0];
- Cr = pCr[0];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput, Y1, Cb, Cr);
- else
- JPEGPixelBE(pOutput, Y1, Cb, Cr);
- // top right block
- Y1 = pY[DCTSIZE*2] << 12; // scale to level of conversion table
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput + 1, Y1, Cb, Cr);
- else
- JPEGPixelBE(pOutput + 1, Y1, Cb, Cr);
- // bottom left block
- Y1 = pY[DCTSIZE*4] << 12; // scale to level of conversion table
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput+iPitch, Y1, Cb, Cr);
- else
- JPEGPixelBE(pOutput+iPitch, Y1, Cb, Cr);
- // bottom right block
- Y1 = pY[DCTSIZE*6] << 12; // scale to level of conversion table
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput+ 1 + iPitch, Y1, Cb, Cr);
- else
- JPEGPixelBE(pOutput+ 1 + iPitch, Y1, Cb, Cr);
- return;
- }
- if (pJPEG->iOptions & JPEG_SCALE_QUARTER) // special case of 1/4
- {
- for (iRow=0; iRow<2; iRow++)
- {
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- for (iCol=0; iCol<2; iCol++)
- {
- // top left block
- Y1 = pY[iCol] << 12; // scale to level of conversion table
- Cb = pCb[0];
- Cr = pCr[0];
- JPEGPixelLE(pOutput + iCol, Y1, Cb, Cr);
- // top right block
- Y1 = pY[iCol+(DCTSIZE*2)] << 12; // scale to level of conversion table
- Cb = pCb[1];
- Cr = pCr[1];
- JPEGPixelLE(pOutput + 2+iCol, Y1, Cb, Cr);
- // bottom left block
- Y1 = pY[iCol+DCTSIZE*4] << 12; // scale to level of conversion table
- Cb = pCb[2];
- Cr = pCr[2];
- JPEGPixelLE(pOutput+iPitch*2 + iCol, Y1, Cb, Cr);
- // bottom right block
- Y1 = pY[iCol+DCTSIZE*6] << 12; // scale to level of conversion table
- Cb = pCb[3];
- Cr = pCr[3];
- JPEGPixelLE(pOutput+iPitch*2 + 2+iCol, Y1, Cb, Cr);
- } // for each column
- }
- else
- {
- for (iCol=0; iCol<2; iCol++)
- {
- // top left block
- Y1 = pY[iCol] << 12; // scale to level of conversion table
- Cb = pCb[0];
- Cr = pCr[0];
- JPEGPixelBE(pOutput + iCol, Y1, Cb, Cr);
- // top right block
- Y1 = pY[iCol+(DCTSIZE*2)] << 12; // scale to level of conversion table
- Cb = pCb[1];
- Cr = pCr[1];
- JPEGPixelBE(pOutput + 2+iCol, Y1, Cb, Cr);
- // bottom left block
- Y1 = pY[iCol+DCTSIZE*4] << 12; // scale to level of conversion table
- Cb = pCb[2];
- Cr = pCr[2];
- JPEGPixelBE(pOutput+iPitch*2 + iCol, Y1, Cb, Cr);
- // bottom right block
- Y1 = pY[iCol+DCTSIZE*6] << 12; // scale to level of conversion table
- Cb = pCb[3];
- Cr = pCr[3];
- JPEGPixelBE(pOutput+iPitch*2 + 2+iCol, Y1, Cb, Cr);
- } // for each column
- }
- pY += 2; // skip 1 line of source pixels
- pOutput += iPitch;
- }
- return;
- }
- /* Convert YCC pixels into RGB pixels and store in output image */
- iYCount = 4;
- bUseOdd1 = bUseOdd2 = 1; // assume odd column can be used
- if ((x+15) >= pJPEG->iWidth)
- {
- iCol = (((pJPEG->iWidth & 15)+1) >> 1);
- if (iCol >= 4)
- {
- iXCount1 = 4;
- iXCount2 = iCol-4;
- if (pJPEG->iWidth & 1 && (iXCount2 * 2) + 8 + (x * 16) > pJPEG->iWidth)
- bUseOdd2 = 0;
- }
- else
- {
- iXCount1 = iCol;
- iXCount2 = 0;
- if (pJPEG->iWidth & 1 && (iXCount1 * 2) + (x * 16) > pJPEG->iWidth)
- bUseOdd1 = 0;
- }
- }
- else
- iXCount1 = iXCount2 = 4;
- for (iRow=0; iRow<iYCount; iRow++) // up to 4 rows to do
- {
- for (iCol=0; iCol<iXCount1; iCol++) // up to 4 cols to do
- {
- // for top left block
- Y1 = pY[iCol*2];
- Y2 = pY[iCol*2+1];
- Y3 = pY[iCol*2+8];
- Y4 = pY[iCol*2+9];
- Y1 <<= 12; // scale to level of conversion table
- Y2 <<= 12;
- Y3 <<= 12;
- Y4 <<= 12;
- Cb = pCb[iCol];
- Cr = pCr[iCol];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- if (bUseOdd1 || iCol != (iXCount1-1)) // only render if it won't go off the right edge
- {
- JPEGPixel2LE(pOutput + (iCol<<1), Y1, Y2, Cb, Cr);
- JPEGPixel2LE(pOutput+iPitch + (iCol<<1), Y3, Y4, Cb, Cr);
- }
- else
- {
- JPEGPixelLE(pOutput + (iCol<<1), Y1, Cb, Cr);
- JPEGPixelLE(pOutput+iPitch + (iCol<<1), Y3, Cb, Cr);
- }
- }
- else
- {
- if (bUseOdd1 || iCol != (iXCount1-1)) // only render if it won't go off the right edge
- {
- JPEGPixel2BE(pOutput + (iCol<<1), Y1, Y2, Cb, Cr);
- JPEGPixel2BE(pOutput+iPitch + (iCol<<1), Y3, Y4, Cb, Cr);
- }
- else
- {
- JPEGPixelBE(pOutput + (iCol<<1), Y1, Cb, Cr);
- JPEGPixelBE(pOutput+iPitch + (iCol<<1), Y3, Cb, Cr);
- }
- }
- // for top right block
- if (iCol < iXCount2)
- {
- Y1 = pY[iCol*2+DCTSIZE*2];
- Y2 = pY[iCol*2+1+DCTSIZE*2];
- Y3 = pY[iCol*2+8+DCTSIZE*2];
- Y4 = pY[iCol*2+9+DCTSIZE*2];
- Y1 <<= 12; // scale to level of conversion table
- Y2 <<= 12;
- Y3 <<= 12;
- Y4 <<= 12;
- Cb = pCb[iCol+4];
- Cr = pCr[iCol+4];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- if (bUseOdd2 || iCol != (iXCount2-1)) // only render if it won't go off the right edge
- {
- JPEGPixel2LE(pOutput + 8+(iCol<<1), Y1, Y2, Cb, Cr);
- JPEGPixel2LE(pOutput+iPitch + 8+(iCol<<1), Y3, Y4, Cb, Cr);
- }
- else
- {
- JPEGPixelLE(pOutput+ 8+(iCol<<1), Y1, Cb, Cr);
- JPEGPixelLE(pOutput+iPitch+ 8+(iCol<<1), Y3, Cb, Cr);
- }
- }
- else
- {
- if (bUseOdd2 || iCol != (iXCount2-1)) // only render if it won't go off the right edge
- {
- JPEGPixel2BE(pOutput + 8+(iCol<<1), Y1, Y2, Cb, Cr);
- JPEGPixel2BE(pOutput+iPitch + 8+(iCol<<1), Y3, Y4, Cb, Cr);
- }
- else
- {
- JPEGPixelBE(pOutput+ 8+(iCol<<1), Y1, Cb, Cr);
- JPEGPixelBE(pOutput+iPitch+ 8+(iCol<<1), Y3, Cb, Cr);
- }
- }
- }
- // for bottom left block
- Y1 = pY[iCol*2+DCTSIZE*4];
- Y2 = pY[iCol*2+1+DCTSIZE*4];
- Y3 = pY[iCol*2+8+DCTSIZE*4];
- Y4 = pY[iCol*2+9+DCTSIZE*4];
- Y1 <<= 12; // scale to level of conversion table
- Y2 <<= 12;
- Y3 <<= 12;
- Y4 <<= 12;
- Cb = pCb[iCol+32];
- Cr = pCr[iCol+32];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- if (bUseOdd1 || iCol != (iXCount1-1)) // only render if it won't go off the right edge
- {
- JPEGPixel2LE(pOutput+iPitch*8+ (iCol<<1), Y1, Y2, Cb, Cr);
- JPEGPixel2LE(pOutput+iPitch*9+ (iCol<<1), Y3, Y4, Cb, Cr);
- }
- else
- {
- JPEGPixelLE(pOutput+iPitch*8+ (iCol<<1), Y1, Cb, Cr);
- JPEGPixelLE(pOutput+iPitch*9+ (iCol<<1), Y3, Cb, Cr);
- }
- }
- else
- {
- if (bUseOdd1 || iCol != (iXCount1-1)) // only render if it won't go off the right edge
- {
- JPEGPixel2BE(pOutput+iPitch*8+ (iCol<<1), Y1, Y2, Cb, Cr);
- JPEGPixel2BE(pOutput+iPitch*9+ (iCol<<1), Y3, Y4, Cb, Cr);
- }
- else
- {
- JPEGPixelBE(pOutput+iPitch*8+ (iCol<<1), Y1, Cb, Cr);
- JPEGPixelBE(pOutput+iPitch*9+ (iCol<<1), Y3, Cb, Cr);
- }
- }
- // for bottom right block
- if (iCol < iXCount2)
- {
- Y1 = pY[iCol*2+DCTSIZE*6];
- Y2 = pY[iCol*2+1+DCTSIZE*6];
- Y3 = pY[iCol*2+8+DCTSIZE*6];
- Y4 = pY[iCol*2+9+DCTSIZE*6];
- Y1 <<= 12; // scale to level of conversion table
- Y2 <<= 12;
- Y3 <<= 12;
- Y4 <<= 12;
- Cb = pCb[iCol+36];
- Cr = pCr[iCol+36];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- if (bUseOdd2 || iCol != (iXCount2-1)) // only render if it won't go off the right edge
- {
- JPEGPixel2LE(pOutput+iPitch*8+ 8+(iCol<<1), Y1, Y2, Cb, Cr);
- JPEGPixel2LE(pOutput+iPitch*9+ 8+(iCol<<1), Y3, Y4, Cb, Cr);
- }
- else
- {
- JPEGPixelLE(pOutput+iPitch*8+ 8+(iCol<<1), Y1, Cb, Cr);
- JPEGPixelLE(pOutput+iPitch*9+ 8+(iCol<<1), Y3, Cb, Cr);
- }
- }
- else
- {
- if (bUseOdd2 || iCol != (iXCount2-1)) // only render if it won't go off the right edge
- {
- JPEGPixel2BE(pOutput+iPitch*8+ 8+(iCol<<1), Y1, Y2, Cb, Cr);
- JPEGPixel2BE(pOutput+iPitch*9+ 8+(iCol<<1), Y3, Y4, Cb, Cr);
- }
- else
- {
- JPEGPixelBE(pOutput+iPitch*8+ 8+(iCol<<1), Y1, Cb, Cr);
- JPEGPixelBE(pOutput+iPitch*9+ 8+(iCol<<1), Y3, Cb, Cr);
- }
- }
- }
- } // for each column
- pY += 16; // skip to next line of source pixels
- pCb += 8;
- pCr += 8;
- pOutput += iPitch*2;
- }
- } /* JPEGPutMCU22() */
- static void JPEGPutMCU12(JPEGIMAGE *pJPEG, int x, int iPitch)
- {
- uint32_t Cr,Cb;
- signed int Y1, Y2;
- int iRow, iCol, iXCount, iYCount;
- uint8_t *pY, *pCr, *pCb;
- uint16_t *pOutput = &pJPEG->usPixels[x];
- pY = (uint8_t *)&pJPEG->sMCUs[0*DCTSIZE];
- pCb = (uint8_t *)&pJPEG->sMCUs[2*DCTSIZE];
- pCr = (uint8_t *)&pJPEG->sMCUs[3*DCTSIZE];
- if (pJPEG->iOptions & JPEG_SCALE_HALF)
- {
- for (iRow=0; iRow<4; iRow++)
- {
- for (iCol=0; iCol<4; iCol++)
- {
- Y1 = (pY[0] + pY[1] + pY[8] + pY[9]) << 10;
- Cb = (pCb[0] + pCb[1] + 1) >> 1;
- Cr = (pCr[0] + pCr[1] + 1) >> 1;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput+iCol, Y1, Cb, Cr);
- else
- JPEGPixelBE(pOutput+iCol, Y1, Cb, Cr);
- Y1 = (pY[DCTSIZE*2] + pY[DCTSIZE*2+1] + pY[DCTSIZE*2+8] + pY[DCTSIZE*2+9]) << 10;
- Cb = (pCb[32] + pCb[33] + 1) >> 1;
- Cr = (pCr[32] + pCr[33] + 1) >> 1;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput+iCol+iPitch, Y1, Cb, Cr);
- else
- JPEGPixelBE(pOutput+iCol+iPitch, Y1, Cb, Cr);
- pCb += 2;
- pCr += 2;
- pY += 2;
- }
- pY += 8;
- pOutput += iPitch*2;
- }
- return;
- }
- if (pJPEG->iOptions & JPEG_SCALE_EIGHTH)
- {
- Y1 = pY[0] << 12;
- Y2 = pY[DCTSIZE*2] << 12;
- Cb = pCb[0];
- Cr = pCr[0];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- JPEGPixelLE(pOutput, Y1, Cb, Cr);
- JPEGPixelLE(pOutput + iPitch, Y2, Cb, Cr);
- }
- else
- {
- JPEGPixelBE(pOutput, Y1, Cb, Cr);
- JPEGPixelBE(pOutput + iPitch, Y2, Cb, Cr);
- }
- return;
- }
- if (pJPEG->iOptions & JPEG_SCALE_QUARTER)
- { // draw a 2x4 block
- Y1 = pY[0] << 12;
- Y2 = pY[2] << 12;
- Cb = pCb[0];
- Cr = pCr[0];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- JPEGPixelLE(pOutput, Y1, Cb, Cr);
- JPEGPixelLE(pOutput + iPitch, Y2, Cb, Cr);
- }
- else
- {
- JPEGPixelBE(pOutput, Y1, Cb, Cr);
- JPEGPixelBE(pOutput + iPitch, Y2, Cb, Cr);
- }
- Y1 = pY[1] << 12;
- Y2 = pY[3] << 12;
- Cb = pCb[1];
- Cr = pCr[1];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- JPEGPixelLE(pOutput + 1, Y1, Cb, Cr);
- JPEGPixelLE(pOutput + 1 + iPitch, Y2, Cb, Cr);
- }
- else
- {
- JPEGPixelBE(pOutput + 1, Y1, Cb, Cr);
- JPEGPixelBE(pOutput + 1 + iPitch, Y2, Cb, Cr);
- }
- pY += DCTSIZE*2; // next Y block below
- Y1 = pY[0] << 12;
- Y2 = pY[2] << 12;
- Cb = pCb[2];
- Cr = pCr[2];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- JPEGPixelLE(pOutput + iPitch*2, Y1, Cb, Cr);
- JPEGPixelLE(pOutput + iPitch*3, Y2, Cb, Cr);
- }
- else
- {
- JPEGPixelBE(pOutput + iPitch*2, Y1, Cb, Cr);
- JPEGPixelBE(pOutput + iPitch*3, Y2, Cb, Cr);
- }
- Y1 = pY[1] << 12;
- Y2 = pY[3] << 12;
- Cb = pCb[3];
- Cr = pCr[3];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- JPEGPixelLE(pOutput + 1 + iPitch*2, Y1, Cb, Cr);
- JPEGPixelLE(pOutput + 1 + iPitch*3, Y2, Cb, Cr);
- }
- else
- {
- JPEGPixelBE(pOutput + 1 + iPitch*2, Y1, Cb, Cr);
- JPEGPixelBE(pOutput + 1 + iPitch*3, Y2, Cb, Cr);
- }
- return;
- }
- /* Convert YCC pixels into RGB pixels and store in output image */
- iYCount = 16;
- iXCount = 8;
- for (iRow=0; iRow<iYCount; iRow+=2) // up to 16 rows to do
- {
- for (iCol=0; iCol<iXCount; iCol++) // up to 8 cols to do
- {
- Y1 = pY[iCol];
- Y2 = pY[iCol+8];
- Y1 <<= 12; // scale to level of conversion table
- Y2 <<= 12;
- Cb = pCb[iCol];
- Cr = pCr[iCol];
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- {
- JPEGPixelLE(pOutput + iCol, Y1, Cb, Cr);
- JPEGPixelLE(pOutput + iPitch + iCol, Y2, Cb, Cr);
- }
- else
- {
- JPEGPixelBE(pOutput + iCol, Y1, Cb, Cr);
- JPEGPixelBE(pOutput + iPitch + iCol, Y2, Cb, Cr);
- }
- }
- pY += 16; // skip to next 2 lines of source pixels
- if (iRow == 6) // next MCU block, skip ahead to correct spot
- pY += (128-64);
- pCb += 8;
- pCr += 8;
- pOutput += iPitch*2; // next 2 lines of dest pixels
- }
- } /* JPEGPutMCU12() */
- static void JPEGPutMCU21(JPEGIMAGE *pJPEG, int x, int iPitch)
- {
- int iCr, iCb;
- signed int Y1, Y2;
- int iCol;
- int iRow;
- uint8_t *pY, *pCr, *pCb;
- uint16_t *pOutput = &pJPEG->usPixels[x];
- pY = (uint8_t *)&pJPEG->sMCUs[0*DCTSIZE];
- pCb = (uint8_t *)&pJPEG->sMCUs[2*DCTSIZE];
- pCr = (uint8_t *)&pJPEG->sMCUs[3*DCTSIZE];
- if (pJPEG->iOptions & JPEG_SCALE_HALF)
- {
- for (iRow=0; iRow<4; iRow++)
- {
- for (iCol=0; iCol<4; iCol++)
- { // left block
- iCr = (pCr[0] + pCr[8] + 1) >> 1;
- iCb = (pCb[0] + pCb[8] + 1) >> 1;
- Y1 = (signed int)(pY[0] + pY[1] + pY[8] + pY[9]) << 10;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput+iCol, Y1, iCb, iCr);
- else
- JPEGPixelBE(pOutput+iCol, Y1, iCb, iCr);
- // right block
- iCr = (pCr[4] + pCr[12] + 1) >> 1;
- iCb = (pCb[4] + pCb[12] + 1) >> 1;
- Y1 = (signed int)(pY[128] + pY[129] + pY[136] + pY[137]) << 10;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixelLE(pOutput+iCol+4, Y1, iCb, iCr);
- else
- JPEGPixelBE(pOutput+iCol+4, Y1, iCb, iCr);
- pCb++;
- pCr++;
- pY += 2;
- }
- pCb += 12;
- pCr += 12;
- pY += 8;
- pOutput += iPitch;
- }
- return;
- }
- if (pJPEG->iOptions & JPEG_SCALE_EIGHTH)
- { // draw 2 pixels
- iCr = pCr[0];
- iCb = pCb[0];
- Y1 = (signed int)(pY[0]) << 12;
- Y2 = (signed int)(pY[DCTSIZE*2]) << 12;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixel2LE(pOutput, Y1, Y2, iCb, iCr);
- else
- JPEGPixel2BE(pOutput, Y1, Y2, iCb, iCr);
- return;
- }
- if (pJPEG->iOptions & JPEG_SCALE_QUARTER)
- { // draw 4x2 pixels
- // top left
- iCr = pCr[0];
- iCb = pCb[0];
- Y1 = (signed int)(pY[0]) << 12;
- Y2 = (signed int)(pY[1]) << 12;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixel2LE(pOutput, Y1, Y2, iCb, iCr);
- else
- JPEGPixel2BE(pOutput, Y1, Y2, iCb, iCr);
- // top right
- iCr = pCr[1];
- iCb = pCb[1];
- Y1 = (signed int)pY[DCTSIZE*2] << 12;
- Y2 = (signed int)pY[DCTSIZE*2+1] << 12;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixel2LE(pOutput + 2, Y1, Y2, iCb, iCr);
- else
- JPEGPixel2BE(pOutput + 2, Y1, Y2, iCb, iCr);
- // bottom left
- iCr = pCr[2];
- iCb = pCb[2];
- Y1 = (signed int)(pY[2]) << 12;
- Y2 = (signed int)(pY[3]) << 12;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixel2LE(pOutput + iPitch, Y1, Y2, iCb, iCr);
- else
- JPEGPixel2BE(pOutput + iPitch, Y1, Y2, iCb, iCr);
- // bottom right
- iCr = pCr[3];
- iCb = pCb[3];
- Y1 = (signed int)pY[DCTSIZE*2+2] << 12;
- Y2 = (signed int)pY[DCTSIZE*2+3] << 12;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixel2LE(pOutput + iPitch + 2, Y1, Y2, iCb, iCr);
- else
- JPEGPixel2BE(pOutput + iPitch + 2, Y1, Y2, iCb, iCr);
- return;
- }
- /* Convert YCC pixels into RGB pixels and store in output image */
- for (iRow=0; iRow<8; iRow++) // up to 8 rows to do
- {
- for (iCol=0; iCol<4; iCol++) // up to 4x2 cols to do
- { // left block
- iCr = *pCr++;
- iCb = *pCb++;
- Y1 = (signed int)(*pY++) << 12;
- Y2 = (signed int)(*pY++) << 12;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixel2LE(pOutput + iCol*2, Y1, Y2, iCb, iCr);
- else
- JPEGPixel2BE(pOutput + iCol*2, Y1, Y2, iCb, iCr);
- // right block
- iCr = pCr[3];
- iCb = pCb[3];
- Y1 = (signed int)pY[126] << 12;
- Y2 = (signed int)pY[127] << 12;
- if (pJPEG->ucPixelType == RGB565_LITTLE_ENDIAN)
- JPEGPixel2LE(pOutput + 8 + iCol*2, Y1, Y2, iCb, iCr);
- else
- JPEGPixel2BE(pOutput + 8 + iCol*2, Y1, Y2, iCb, iCr);
- } // for col
- pCb += 4;
- pCr += 4;
- pOutput += iPitch;
- } // for row
- } /* JPEGPutMCU21() */
- // Dither the 8-bit gray pixels into 1, 2, or 4-bit gray
- static void JPEGDither(JPEGIMAGE *pJPEG, int iWidth, int iHeight)
- {
- int x, y, xmask=0, iDestPitch=0;
- int32_t cNew, lFErr, v=0, h;
- int32_t e1,e2,e3,e4;
- uint8_t cOut, ucPixelType; // forward errors for gray
- uint8_t *pSrc, *pDest, *errors, *pErrors=NULL, *d, *pPixels; // destination 8bpp image
- uint8_t pixelmask=0, shift=0;
- ucPixelType = pJPEG->ucPixelType;
- errors = (uint8_t *)pJPEG->usPixels; // plenty of space here
- errors[0] = errors[1] = errors[2] = 0;
- pDest = pSrc = pJPEG->pDitherBuffer; // write the new pixels over the original
- switch (ucPixelType)
- {
- case FOUR_BIT_DITHERED:
- iDestPitch = (iWidth+1)/2;
- pixelmask = 0xf0;
- shift = 4;
- xmask = 1;
- break;
- case TWO_BIT_DITHERED:
- iDestPitch = (iWidth+3)/4;
- pixelmask = 0xc0;
- shift = 2;
- xmask = 3;
- break;
- case ONE_BIT_DITHERED:
- iDestPitch = (iWidth+7)/8;
- pixelmask = 0x80;
- shift = 1;
- xmask = 7;
- break;
- }
- for (y=0; y<iHeight; y++)
- {
- pPixels = &pSrc[y * iWidth];
- d = &pDest[y * iDestPitch];
- pErrors = &errors[1]; // point to second pixel to avoid boundary check
- lFErr = 0;
- cOut = 0;
- for (x=0; x<iWidth; x++)
- {
- cNew = *pPixels++; // get grayscale uint8_t pixel
- // add forward error
- cNew += lFErr;
- if (cNew > 255) cNew = 255; // clip to uint8_t
- cOut <<= shift; // pack new pixels into a byte
- cOut |= (cNew >> (8-shift)); // keep top N bits
- if ((x & xmask) == xmask) // store it when the byte is full
- {
- *d++ = cOut;
- cOut = 0;
- }
- // calculate the Floyd-Steinberg error for this pixel
- v = cNew - (cNew & pixelmask); // new error for N-bit gray output (always positive)
- h = v >> 1;
- e1 = (7*h)>>3; // 7/16
- e2 = h - e1; // 1/16
- e3 = (5*h) >> 3; // 5/16
- e4 = h - e3; // 3/16
- // distribute error to neighbors
- lFErr = e1 + pErrors[1];
- pErrors[1] = (uint8_t)e2;
- pErrors[0] += e3;
- pErrors[-1] += e4;
- pErrors++;
- } // for x
- } // for y
- } /* JPEGDither() */
- //
- // Decode the image
- // returns 0 for error, 1 for success
- //
- static int DecodeJPEG(JPEGIMAGE *pJPEG)
- {
- int cx, cy, x, y, mcuCX, mcuCY;
- int iLum0, iLum1, iLum2, iLum3, iCr, iCb;
- signed int iDCPred0, iDCPred1, iDCPred2;
- int i, iQuant1, iQuant2, iQuant3, iErr;
- uint8_t c;
- int iMCUCount, xoff, iPitch, bThumbnail = 0;
- int bContinue = 1; // early exit if the DRAW callback wants to stop
- uint32_t l, *pl;
- unsigned char cDCTable0, cACTable0, cDCTable1, cACTable1, cDCTable2, cACTable2;
- JPEGDRAW jd;
- int iMaxFill = 16, iScaleShift = 0;
- // Requested the Exif thumbnail
- if (pJPEG->iOptions & JPEG_EXIF_THUMBNAIL)
- {
- if (pJPEG->iThumbData == 0 || pJPEG->iThumbWidth == 0) // doesn't exist
- {
- pJPEG->iError = JPEG_INVALID_PARAMETER;
- return 0;
- }
- if (!JPEGParseInfo(pJPEG, 1)) // parse the embedded thumbnail file header
- return 0; // something went wrong
- }
- // Fast downscaling options
- if (pJPEG->iOptions & JPEG_SCALE_HALF)
- iScaleShift = 1;
- else if (pJPEG->iOptions & JPEG_SCALE_QUARTER)
- {
- iScaleShift = 2;
- iMaxFill = 1;
- }
- else if (pJPEG->iOptions & JPEG_SCALE_EIGHTH)
- {
- iScaleShift = 3;
- iMaxFill = 1;
- bThumbnail = 1;
- }
- // reorder and fix the quantization table for decoding
- JPEGFixQuantD(pJPEG);
- pJPEG->bb.ulBits = MOTOLONG(&pJPEG->ucFileBuf[0]); // preload first 4 bytes
- pJPEG->bb.pBuf = pJPEG->ucFileBuf;
- pJPEG->bb.ulBitOff = 0;
- cDCTable0 = pJPEG->JPCI[0].dc_tbl_no;
- cACTable0 = pJPEG->JPCI[0].ac_tbl_no;
- cDCTable1 = pJPEG->JPCI[1].dc_tbl_no;
- cACTable1 = pJPEG->JPCI[1].ac_tbl_no;
- cDCTable2 = pJPEG->JPCI[2].dc_tbl_no;
- cACTable2 = pJPEG->JPCI[2].ac_tbl_no;
- iDCPred0 = iDCPred1 = iDCPred2 = mcuCX = mcuCY = 0;
- switch (pJPEG->ucSubSample) // set up the parameters for the different subsampling options
- {
- case 0x00: // fake value to handle grayscale
- case 0x01: // fake value to handle sRGB/CMYK
- case 0x11:
- cx = (pJPEG->iWidth + 7) >> 3; // number of MCU blocks
- cy = (pJPEG->iHeight + 7) >> 3;
- iCr = MCU1;
- iCb = MCU2;
- mcuCX = mcuCY = 8;
- break;
- case 0x12:
- cx = (pJPEG->iWidth + 7) >> 3; // number of MCU blocks
- cy = (pJPEG->iHeight + 15) >> 4;
- iCr = MCU2;
- iCb = MCU3;
- mcuCX = 8;
- mcuCY = 16;
- break;
- case 0x21:
- cx = (pJPEG->iWidth + 15) >> 4; // number of MCU blocks
- cy = (pJPEG->iHeight + 7) >> 3;
- iCr = MCU2;
- iCb = MCU3;
- mcuCX = 16;
- mcuCY = 8;
- break;
- case 0x22:
- cx = (pJPEG->iWidth + 15) >> 4; // number of MCU blocks
- cy = (pJPEG->iHeight + 15) >> 4;
- iCr = MCU4;
- iCb = MCU5;
- mcuCX = mcuCY = 16;
- break;
- default: // to suppress compiler warning
- cx = cy = 0;
- iCr = iCb = 0;
- break;
- }
- // Scale down the MCUs by the requested amount
- mcuCX >>= iScaleShift;
- mcuCY >>= iScaleShift;
- iQuant1 = pJPEG->sQuantTable[pJPEG->JPCI[0].quant_tbl_no*DCTSIZE]; // DC quant values
- iQuant2 = pJPEG->sQuantTable[pJPEG->JPCI[1].quant_tbl_no*DCTSIZE];
- iQuant3 = pJPEG->sQuantTable[pJPEG->JPCI[2].quant_tbl_no*DCTSIZE];
- // luminance values are always in these positions
- iLum0 = MCU0;
- iLum1 = MCU1;
- iLum2 = MCU2;
- iLum3 = MCU3;
- iErr = 0;
- pJPEG->iResCount = pJPEG->iResInterval;
- // Calculate how many MCUs we can fit in the pixel buffer to maximize LCD drawing speed
- iMCUCount = MAX_BUFFERED_PIXELS / (mcuCX * mcuCY);
- if (pJPEG->ucPixelType == EIGHT_BIT_GRAYSCALE)
- iMCUCount *= 2; // each pixel is only 1 byte
- if (iMCUCount > cx)
- iMCUCount = cx; // don't go wider than the image
- if (iMCUCount > pJPEG->iMaxMCUs) // did the user set an upper bound on how many pixels per JPEGDraw callback?
- iMCUCount = pJPEG->iMaxMCUs;
- if (pJPEG->ucPixelType > EIGHT_BIT_GRAYSCALE) // dithered, override the max MCU count
- iMCUCount = cx; // do the whole row
- jd.iBpp = 16;
- switch (pJPEG->ucPixelType)
- {
- case EIGHT_BIT_GRAYSCALE:
- jd.iBpp = 8;
- break;
- case FOUR_BIT_DITHERED:
- jd.iBpp = 4;
- break;
- case TWO_BIT_DITHERED:
- jd.iBpp = 2;
- break;
- case ONE_BIT_DITHERED:
- jd.iBpp = 1;
- break;
- }
- if (pJPEG->ucPixelType > EIGHT_BIT_GRAYSCALE)
- jd.pPixels = (uint16_t *)pJPEG->pDitherBuffer;
- else
- jd.pPixels = pJPEG->usPixels;
- jd.iHeight = mcuCY;
- jd.y = pJPEG->iYOffset;
- for (y = 0; y < cy && bContinue && iErr == 0; y++, jd.y += mcuCY)
- {
- jd.x = pJPEG->iXOffset;
- xoff = 0; // start of new LCD output group
- iPitch = iMCUCount * mcuCX; // pixels per line of LCD buffer
- for (x = 0; x < cx && bContinue && iErr == 0; x++)
- {
- pJPEG->ucACTable = cACTable0;
- pJPEG->ucDCTable = cDCTable0;
- // do the first luminance component
- iErr = JPEGDecodeMCU(pJPEG, iLum0, &iDCPred0);
- if (pJPEG->ucMaxACCol == 0 || bThumbnail) // no AC components, save some time
- {
- pl = (uint32_t *)&pJPEG->sMCUs[iLum0];
- c = ucRangeTable[((iDCPred0 * iQuant1) >> 5) & 0x3ff];
- l = c | ((uint32_t) c << 8) | ((uint32_t) c << 16) | ((uint32_t) c << 24);
- // dct stores byte values
- for (i = 0; i<iMaxFill; i++) // 8x8 bytes = 16 longs
- pl[i] = l;
- }
- else
- {
- JPEGIDCT(pJPEG, iLum0, pJPEG->JPCI[0].quant_tbl_no, (pJPEG->ucMaxACCol | (pJPEG->ucMaxACRow << 8))); // first quantization table
- }
- // do the second luminance component
- if (pJPEG->ucSubSample > 0x11) // subsampling
- {
- iErr |= JPEGDecodeMCU(pJPEG, iLum1, &iDCPred0);
- if (pJPEG->ucMaxACCol == 0 || bThumbnail) // no AC components, save some time
- {
- c = ucRangeTable[((iDCPred0 * iQuant1) >> 5) & 0x3ff];
- l = c | ((uint32_t) c << 8) | ((uint32_t) c << 16) | ((uint32_t) c << 24);
- // dct stores byte values
- pl = (uint32_t *)&pJPEG->sMCUs[iLum1];
- for (i = 0; i<iMaxFill; i++) // 8x8 bytes = 16 longs
- pl[i] = l;
- }
- else
- {
- JPEGIDCT(pJPEG, iLum1, pJPEG->JPCI[0].quant_tbl_no, (pJPEG->ucMaxACCol | (pJPEG->ucMaxACRow << 8))); // first quantization table
- }
- if (pJPEG->ucSubSample == 0x22)
- {
- iErr |= JPEGDecodeMCU(pJPEG, iLum2, &iDCPred0);
- if (pJPEG->ucMaxACCol == 0 || bThumbnail) // no AC components, save some time
- {
- c = ucRangeTable[((iDCPred0 * iQuant1) >> 5) & 0x3ff];
- l = c | ((uint32_t) c << 8) | ((uint32_t) c << 16) | ((uint32_t) c << 24);
- // dct stores byte values
- pl = (uint32_t *)&pJPEG->sMCUs[iLum2];
- for (i = 0; i<iMaxFill; i++) // 8x8 bytes = 16 longs
- pl[i] = l;
- }
- else
- {
- JPEGIDCT(pJPEG, iLum2, pJPEG->JPCI[0].quant_tbl_no, (pJPEG->ucMaxACCol | (pJPEG->ucMaxACRow << 8))); // first quantization table
- }
- iErr |= JPEGDecodeMCU(pJPEG, iLum3, &iDCPred0);
- if (pJPEG->ucMaxACCol == 0 || bThumbnail) // no AC components, save some time
- {
- c = ucRangeTable[((iDCPred0 * iQuant1) >> 5) & 0x3ff];
- l = c | ((uint32_t) c << 8) | ((uint32_t) c << 16) | ((uint32_t) c << 24);
- // dct stores byte values
- pl = (uint32_t *)&pJPEG->sMCUs[iLum3];
- for (i = 0; i<iMaxFill; i++) // 8x8 bytes = 16 longs
- pl[i] = l;
- }
- else
- {
- JPEGIDCT(pJPEG, iLum3, pJPEG->JPCI[0].quant_tbl_no, (pJPEG->ucMaxACCol | (pJPEG->ucMaxACRow << 8))); // first quantization table
- }
- } // if 2:2 subsampling
- } // if subsampling used
- if (pJPEG->ucSubSample && pJPEG->ucNumComponents == 3) // if color (not CMYK)
- {
- // first chroma
- pJPEG->ucACTable = cACTable1;
- pJPEG->ucDCTable = cDCTable1;
- iErr |= JPEGDecodeMCU(pJPEG, iCr, &iDCPred1);
- if (pJPEG->ucMaxACCol == 0 || bThumbnail) // no AC components, save some time
- {
- c = ucRangeTable[((iDCPred1 * iQuant2) >> 5) & 0x3ff];
- l = c | ((uint32_t) c << 8) | ((uint32_t) c << 16) | ((uint32_t) c << 24);
- // dct stores byte values
- pl = (uint32_t *)&pJPEG->sMCUs[iCr];
- for (i = 0; i<iMaxFill; i++) // 8x8 bytes = 16 longs
- pl[i] = l;
- }
- else
- {
- JPEGIDCT(pJPEG, iCr, pJPEG->JPCI[1].quant_tbl_no, (pJPEG->ucMaxACCol | (pJPEG->ucMaxACRow << 8))); // second quantization table
- }
- // second chroma
- pJPEG->ucACTable = cACTable2;
- pJPEG->ucDCTable = cDCTable2;
- iErr |= JPEGDecodeMCU(pJPEG, iCb, &iDCPred2);
- if (pJPEG->ucMaxACCol == 0 || bThumbnail) // no AC components, save some time
- {
- c = ucRangeTable[((iDCPred2 * iQuant3) >> 5) & 0x3ff];
- l = c | ((uint32_t) c << 8) | ((uint32_t) c << 16) | ((uint32_t) c << 24);
- // dct stores byte values
- pl = (uint32_t *)&pJPEG->sMCUs[iCb];
- for (i = 0; i<iMaxFill; i++) // 8x8 bytes = 16 longs
- pl[i] = l;
- }
- else
- {
- JPEGIDCT(pJPEG, iCb, pJPEG->JPCI[2].quant_tbl_no, (pJPEG->ucMaxACCol | (pJPEG->ucMaxACRow << 8)));
- }
- } // if color components present
- if (pJPEG->ucPixelType >= EIGHT_BIT_GRAYSCALE)
- {
- JPEGPutMCU8BitGray(pJPEG, xoff, iPitch);
- }
- else
- {
- switch (pJPEG->ucSubSample)
- {
- case 0x00: // grayscale
- JPEGPutMCUGray(pJPEG, xoff, iPitch);
- break;
- case 0x11:
- JPEGPutMCU11(pJPEG, xoff, iPitch);
- break;
- case 0x12:
- JPEGPutMCU12(pJPEG, xoff, iPitch);
- break;
- case 0x21:
- JPEGPutMCU21(pJPEG, xoff, iPitch);
- break;
- case 0x22:
- JPEGPutMCU22(pJPEG, xoff, iPitch);
- break;
- } // switch on color option
- }
- xoff += mcuCX;
- if (xoff == iPitch || x == cx-1) // time to draw
- {
- xoff = 0;
- jd.iWidth = iPitch; // width of each LCD block group
- jd.pUser = pJPEG->pUser;
- if (pJPEG->ucPixelType > EIGHT_BIT_GRAYSCALE) // dither to 4/2/1 bits
- JPEGDither(pJPEG, cx * mcuCX, mcuCY);
- if ((jd.y - pJPEG->iYOffset + mcuCY) > (pJPEG->iHeight>>iScaleShift)) { // last row needs to be trimmed
- jd.iHeight = (pJPEG->iHeight>>iScaleShift) - (jd.y - pJPEG->iYOffset);
- }
- bContinue = (*pJPEG->pfnDraw)(&jd);
- jd.x += iPitch;
- if ((cx - 1 - x) < iMCUCount) // change pitch for the last set of MCUs on this row
- iPitch = (cx - 1 - x) * mcuCX;
- }
- if (pJPEG->iResInterval)
- {
- if (--pJPEG->iResCount == 0)
- {
- pJPEG->iResCount = pJPEG->iResInterval;
- iDCPred0 = iDCPred1 = iDCPred2 = 0; // reset DC predictors
- if (pJPEG->bb.ulBitOff & 7) // need to start at the next even byte
- {
- pJPEG->bb.ulBitOff += (8 - (pJPEG->bb.ulBitOff & 7)); // new restart interval starts on byte boundary
- }
- } // if restart interval needs to reset
- } // if there is a restart interval
- // See if we need to feed it more data
- if (pJPEG->iVLCOff >= FILE_HIGHWATER)
- JPEGGetMoreData(pJPEG); // need more 'filtered' VLC data
- } // for x
- } // for y
- if (iErr != 0)
- pJPEG->iError = JPEG_DECODE_ERROR;
- return (iErr == 0);
- } /* DecodeJPEG() */
|